Skip to content

Commit

Permalink
➕ Add types to InviteCodePanelView
Browse files Browse the repository at this point in the history
  • Loading branch information
devmount committed Jul 24, 2024
1 parent e85eb7a commit 532feb8
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 36 deletions.
8 changes: 8 additions & 0 deletions frontend/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ export const bookingStatus = {
booked: 3,
};

/**
* Status to indicate if an invite code ist still valid or no longer valid
*/
export enum InviteStatus {
Active = 1,
Revoked = 2,
};

// available appointment views
export const appointmentViews = {
booked: 1,
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/elements/AlertBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ const { t } = useI18n();
// component properties
interface Props {
title?: string; // flag showing this event as busy and non-selectable
canClose: boolean; // flag for making this alert closable
scheme: AlertSchemes; // flag, are we in month view?
canClose?: boolean; // flag for making this alert closable
scheme?: AlertSchemes; // flag, are we in month view?
};
withDefaults(defineProps<Props>(), {
canClose: true,
Expand Down
38 changes: 29 additions & 9 deletions frontend/src/models.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Dayjs } from 'dayjs';
import { UseFetchReturn } from '@vueuse/core';
import { InviteStatus } from './definitions';

export type Attendee = {
id: number;
email: string;
name: string;
timezone: string;
}
};

export type Slot = {
id: number;
Expand All @@ -22,7 +23,7 @@ export type Slot = {
subscriber_id: number;
time_updated: string;
attendee: Attendee;
}
};

export type Appointment = {
id: number;
Expand Down Expand Up @@ -133,6 +134,14 @@ export type Schedule = {
booking_confirmation: boolean;
};

export type Invite = {
subscriber_id?: number;
code: string;
status: InviteStatus;
time_created: string;
time_updated: string;
};

export type User = {
email: string;
preferredEmail: string;
Expand All @@ -145,7 +154,7 @@ export type User = {
accessToken: string;
scheduleLinks: string[];
isSetup: boolean,
}
};

export type Subscriber = {
username: string;
Expand All @@ -161,13 +170,23 @@ export type Subscriber = {

export type Signature = {
url: string;
}
};

export type Error = { error: boolean|string|null };
export type Exception = {
status_code?: number;
detail?: { msg: string }[]|ExceptionDetail;
headers?: any[];
};
export type ExceptionDetail = {
id?: string;
message?: string;
status?: number;
}
export type Token = {
access_token: string;
token_type: string;
}
};

// Types and aliases used for our custom createFetch API calls and return types
export type Fetch = (url: string) => UseFetchReturn<any> & PromiseLike<UseFetchReturn<any>>;
Expand All @@ -179,27 +198,28 @@ export type TokenResponse = UseFetchReturn<Token>;
export type AppointmentListResponse = UseFetchReturn<Appointment[]>;
export type CalendarListResponse = UseFetchReturn<Calendar[]>;
export type ScheduleListResponse = UseFetchReturn<Schedule[]>;
export type InviteListResponse = UseFetchReturn<Invite[]|Exception>;
export type ExternalConnectionCollectionResponse = UseFetchReturn<ExternalConnectionCollection>;

// Utility types
export type Time<T> = {
start: T;
end: T;
}
};
export type TimeNumeric = Time<number>;
export type TimeFormatted = Time<string>;

export type IsoWeekdayOption = {
label: string;
value: string;
}
};

export type Coloring = {
border?: string;
background?: string;
}
};

export type HTMLElementEvent = Event & {
target: HTMLElement;
currentTarget: HTMLElement;
}
};
52 changes: 27 additions & 25 deletions frontend/src/views/admin/InviteCodePanelView.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
<template>
<div class="flex w-full justify-center">
<alert-box
@close="pageNotification = ''"
v-if="pageNotification"
:scheme="AlertSchemes.success"
>
<alert-box v-if="pageNotification" @close="pageNotification = ''" :scheme="AlertSchemes.success">
{{ pageNotification }}
</alert-box>
<alert-box
@close="pageError = ''"
v-if="pageError"
>
<alert-box v-if="pageError" @close="pageError = ''">
{{ pageError }}
</alert-box>
</div>
Expand Down Expand Up @@ -63,22 +56,24 @@ import {
} from 'vue';
import { useI18n } from 'vue-i18n';
import { AlertSchemes, tableDataButtonType, tableDataType } from '@/definitions';
import DataTable from '@/components/DataTable.vue';
import { useRouter } from 'vue-router';
import { IconSend } from '@tabler/icons-vue';
import { Invite, InviteListResponse, BooleanResponse, Exception } from "@/models";
import { InviteStatus } from "@/definitions";
import { dayjsKey, callKey } from "@/keys";
import DataTable from '@/components/DataTable.vue';
import LoadingSpinner from '@/elements/LoadingSpinner.vue';
import PrimaryButton from '@/elements/PrimaryButton.vue';
import { IconSend } from '@tabler/icons-vue';
import AlertBox from '@/elements/AlertBox.vue';
import AdminNav from '@/elements/admin/AdminNav.vue';
import { dayjsKey, callKey } from "@/keys";
const router = useRouter();
const { t } = useI18n();
const call = inject(callKey);
const dj = inject(dayjsKey);
const invites = ref([]);
const invites = ref<Invite[]>([]);
const displayPage = ref(false);
const generateCodeAmount = ref(null);
const loading = ref(true);
Expand All @@ -92,7 +87,7 @@ const filteredInvites = computed(() => invites.value.map((invite) => ({
},
status: {
type: tableDataType.text,
value: invite.status === 1 ? 'Available' : 'Revoked',
value: invite.status === InviteStatus.Active ? 'Available' : 'Revoked',
},
subscriber_id: {
type: tableDataType.text,
Expand All @@ -110,7 +105,7 @@ const filteredInvites = computed(() => invites.value.map((invite) => ({
type: tableDataType.button,
buttonType: tableDataButtonType.secondary,
value: 'Revoke',
disabled: invite.subscriber_id || invite.status === 2,
disabled: invite.subscriber_id || invite.status === InviteStatus.Revoked,
},
})));
const columns = [
Expand Down Expand Up @@ -162,6 +157,7 @@ const filters = [
],
/**
* Callback function, filter the list by selectedKey and return it back to the table
* TODO: Add types when DataTable.vue is typed
* @param selectedKey
* @param mutableDataList
* @returns {*}
Expand Down Expand Up @@ -195,13 +191,20 @@ const filters = [
},
},
];
/**
* Retrieve list of all existing invites
*/
const getInvites = async () => {
const response = await call('invite/').get().json();
const response: InviteListResponse = await call('invite/').get().json();
const { data } = response;
invites.value = data.value;
invites.value = data.value as Invite[];
};
/**
* Update list of all existing invites
*/
const refresh = async () => {
loading.value = true;
await getInvites();
Expand All @@ -210,15 +213,14 @@ const refresh = async () => {
/**
* Disables an unused invite
* @param code
* @returns {Promise<void>}
* @param code Invitation identifier
*/
const revokeInvite = async (code) => {
const revokeInvite = async (code: string) => {
if (!code) {
return;
}
const response = await call(`invite/revoke/${code}`).put().json();
const response: BooleanResponse = await call(`invite/revoke/${code}`).put().json();
const { data } = response;
if (data.value) {
Expand All @@ -231,19 +233,19 @@ const generateInvites = async () => {
pageError.value = '';
pageNotification.value = '';
const response = await call(`invite/generate/${generateCodeAmount.value}`).post().json();
const response: InviteListResponse = await call(`invite/generate/${generateCodeAmount.value}`).post().json();
const { data, error } = response;
if (error.value) {
const errorObj = data.value?.detail;
const errorObj = (data.value as Exception)?.detail;
if (!errorObj) {
pageError.value = t('error.somethingWentWrong');
} else if (errorObj instanceof Array) {
pageError.value = errorObj.map((err) => err.msg).join('\n');
} else {
pageError.value = data.value?.detail?.message;
pageError.value = errorObj?.message;
}
} else {
pageNotification.value = t('info.invitationGenerated');
Expand All @@ -255,7 +257,7 @@ const generateInvites = async () => {
};
const amIAdmin = async () => {
const response = await call('permission-check').post().json();
const response: BooleanResponse = await call('permission-check').post().json();
const { error } = response;
return !error.value;
Expand Down

0 comments on commit 532feb8

Please sign in to comment.