Skip to content

Commit 61b3f97

Browse files
authored
Merge pull request #106 from SafeExamBrowser/SEBSERV-898
SEBSERV-898 use new generic upload dialog with form builder
2 parents 20b2784 + 0aab7dc commit 61b3f97

12 files changed

Lines changed: 274 additions & 491 deletions

File tree

client/src/components/widgets/UploadDialog.vue

Lines changed: 0 additions & 425 deletions
This file was deleted.

client/src/i18n/locales/en.json

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -890,18 +890,24 @@
890890
"pwdMismatch": "The password and confirm password must match",
891891
"pwdSpaces": "The value must not start or end with a space.",
892892
"noNegNumber": "Cant be a negative number",
893-
"upload": {
894-
"upload": "Import SEB Settings",
895-
"selectFromFolder": "Select From File Explorer",
896-
"uploadHelp": "Drag and Drop or Search through File Explorer",
897-
"allowed": "Allowed File Types",
898-
"dropHere": "Drop a SEB Settings file here",
899-
"password": "Password",
900-
"quitPassword": "Quit Password",
901-
"onlyAllowed": "File Type not allowed",
902-
"uploadFailed": "Failed to upload SEB Settings, please contact a system administrator",
903-
"passwordIncorrect": "The password was incorrect. Please try again or contact a system administrator",
904-
"importButton": "Import"
893+
"importDialog": {
894+
"addButtonTitle": "Import",
895+
"confirmButtonTitle": "Import",
896+
"fields": {
897+
"file": {
898+
"label": "SEB Configuration File",
899+
"hint": "Drop a SEB Configuration file here or search through file explorer."
900+
},
901+
"password": {
902+
"label": "Password"
903+
},
904+
"quitPassword": {
905+
"label": "Quit Password"
906+
}
907+
},
908+
"errors": {
909+
"generic": "Failed to upload SEB Configuration, make sure you use the correct file-password. Please try again or contact a system administrator"
910+
}
905911
},
906912
"views": {
907913
"general": "General",
@@ -1824,24 +1830,19 @@
18241830
"spSearch": "Search",
18251831
"spApplications": "Applications",
18261832
"runningExams": "Running Exams",
1827-
18281833
"userAccounts": "User Accounts",
18291834
"createUserAccount": "Create User Account",
18301835
"editUserAccount": "Edit User Account",
18311836
"profileSettings": "Profile Settings",
18321837
"register": "Register",
1833-
18341838
"assessmentToolConnections": "Assessment Tool Connections",
18351839
"createAssessmentTool": "Assessment Tool Setup",
18361840
"assessmentTool": "Assessment Tool",
18371841
"assessmentToolEdit": "Edit Assessment Tool Connection",
1838-
18391842
"connectionConfigurationViewAndEdit": "Edit Connection Configuration",
18401843
"createConnectionConfiguration": "Add Connection Configuration",
18411844
"connectionConfigurations": "Connection Configurations",
1842-
18431845
"certificates": "Certificates",
1844-
18451846
"editExamTemplate": "Edit Exam Template",
18461847
"galleryView": "Gallery View"
18471848
},

client/src/models/seb-server/sebSettings.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -104,23 +104,6 @@ export type SEBSettingsView = {
104104
tableValues: Map<string, SEBSettingsTableRowValues[]>;
105105
};
106106

107-
// TODO @anhefti: this seems not to be used. Remove them if it remains so
108-
109-
// export type ApplicationView = {
110-
// configurationNodeId: number;
111-
// configurationId: number;
112-
// allowSwitchToApplications: {
113-
// id: number;
114-
// value: string;
115-
// };
116-
// allowFlashFullscreen: {
117-
// id: number;
118-
// value: string;
119-
// };
120-
// prohibitedProcesses: ProhibitedProcess[];
121-
// permittedProcesses: PermittedProcess[];
122-
// };
123-
124107
export type URLFilterRule = {
125108
index: number;
126109
active: boolean;

client/src/pages/(app)/certificate/composables/useCertificateCreateForm.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,21 @@ import i18n from "@/i18n";
44
import { FormField } from "@/components/widgets/formBuilder/types.ts";
55
import {
66
CertificateUploadItemTransient,
7+
CertKey,
78
toCertificateUploadItem,
89
} from "@/pages/(app)/certificate/types/types.ts";
910
import { useCreateCertificate } from "@/pages/(app)/certificate/composables/api/useCreateCertificate.ts";
1011

1112
export const useCertificateCreateForm = ({
1213
onSuccess,
1314
}: {
14-
onSuccess: () => void;
15+
onSuccess: (key: CertKey) => void;
1516
}) => {
16-
const { mutateData: uploadCertificate, error: uploadError } =
17-
useCreateCertificate();
17+
const {
18+
data: cert,
19+
mutateData: uploadCertificate,
20+
error: uploadError,
21+
} = useCreateCertificate();
1822

1923
const getEmptyItem = (): CertificateUploadItemTransient => ({
2024
file: undefined,
@@ -81,7 +85,11 @@ export const useCertificateCreateForm = ({
8185
);
8286
}
8387

84-
onSuccess();
88+
const createdName =
89+
cert.value?.alias || item.file.name.replace(/\.[^.]+$/i, "");
90+
const createdId = cert.value?.alias || createdName;
91+
92+
onSuccess({ id: createdId, name: createdName });
8593
};
8694

8795
return {

client/src/pages/(app)/certificate/index.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,11 @@ const {
143143
} = useDeleteCertificate(tableData);
144144
145145
const { getEmptyItem, getFormFields, handleUploadCertificate } =
146-
useCertificateCreateForm({ onSuccess: loadItems });
146+
useCertificateCreateForm({ onSuccess: onCertificateUpload });
147+
148+
function onCertificateUpload(): void {
149+
loadItems();
150+
}
147151
148152
const deleteTarget = ref<TableItem | null>(null);
149153
const deleteDialogOpen = ref(false);

client/src/pages/(app)/certificate/types/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,8 @@ export type CertificateUploadItem = z.infer<typeof certificateUploadItemSchema>;
1818
export const toCertificateUploadItem = (
1919
itemTransient: CertificateUploadItemTransient,
2020
): CertificateUploadItem => certificateUploadItemSchema.parse(itemTransient);
21+
22+
export type CertKey = {
23+
id: string;
24+
name: string;
25+
};

client/src/pages/(app)/connection-configuration/[id]/index.vue

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,35 @@
261261
.value ===
262262
'__UPLOAD__'
263263
"
264-
>mdi-upload</v-icon
265264
>
265+
<FormDialog
266+
icon-activator="mdi-plus-circle-outline"
267+
color-activator="primary"
268+
label-activator=""
269+
size-activator="large"
270+
label-activator-visible
271+
:label-cancel="
272+
$t(
273+
'general.cancelButton',
274+
)
275+
"
276+
:label-submit="
277+
$t(
278+
'certificates.createDialog.confirmButtonTitle',
279+
)
280+
"
281+
form-id="form-certificate-upload"
282+
:get-form-fields="
283+
getFormFields
284+
"
285+
:get-item="
286+
getEmptyItem
287+
"
288+
:on-submit="
289+
handleUploadCertificate
290+
"
291+
/>
292+
</v-icon>
266293
</template>
267294
</v-list-item>
268295

@@ -788,7 +815,8 @@ import {
788815
import { getConnectionConfiguration } from "@/services/seb-server/connectionConfigurationService.ts";
789816
import { getCertificates } from "@/services/seb-server/certificateService.ts";
790817
import SettingsNavigation from "@/components/widgets/navigation/SettingsNavigation.vue";
791-
import UploadDialog from "@/components/widgets/UploadDialog.vue";
818+
import { useCertificateCreateForm } from "../../certificate/composables/useCertificateCreateForm";
819+
import FormDialog from "@/components/widgets/formDialog/FormDialog.vue";
792820
793821
definePage({
794822
meta: {
@@ -855,6 +883,9 @@ const confirmQuitPwdRef = ref<InputLike | null>(null);
855883
const userToLastUpdate = ref<UserAccount | null>(null);
856884
const userNamesOfLastUserToUpdate = ref<string | undefined>(undefined);
857885
886+
const { getEmptyItem, getFormFields, handleUploadCertificate } =
887+
useCertificateCreateForm({ onSuccess: onCertImported });
888+
858889
type VuetifyFormLike = {
859890
validate: () => Promise<{ valid: boolean }>;
860891
resetValidation?: () => void;

client/src/pages/(app)/connection-configuration/create/index.vue

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,27 @@
4242
<template #prepend>
4343
<v-icon
4444
v-if="item.raw.value === '__UPLOAD__'"
45-
>mdi-upload</v-icon
4645
>
46+
<FormDialog
47+
icon-activator="mdi-plus-circle-outline"
48+
color-activator="primary"
49+
label-activator=""
50+
size-activator="large"
51+
label-activator-visible
52+
:label-cancel="
53+
$t('general.cancelButton')
54+
"
55+
:label-submit="
56+
$t(
57+
'certificates.createDialog.confirmButtonTitle',
58+
)
59+
"
60+
form-id="form-certificate-upload"
61+
:get-form-fields="getFormFields"
62+
:get-item="getEmptyItem"
63+
:on-submit="handleUploadCertificate"
64+
/>
65+
</v-icon>
4766
</template>
4867
</v-list-item>
4968
<v-divider
@@ -160,9 +179,11 @@ import type { CreateConnectionConfigurationPar } from "@/models/seb-server/conne
160179
import CancelButton from "@/components/widgets/CancelButton.vue";
161180
import ConfirmButton from "@/components/widgets/ConfirmButton.vue";
162181
import HintText from "@/components/widgets/HintText.vue";
163-
import UploadDialog from "@/components/widgets/UploadDialog.vue";
182+
import FormDialog from "@/components/widgets/formDialog/FormDialog.vue";
164183
165184
import { useRouter } from "vue-router";
185+
import { useCertificateCreateForm } from "../../certificate/composables/useCertificateCreateForm.ts";
186+
import { CertKey } from "../../certificate/types/types.ts";
166187
definePage({
167188
meta: {
168189
titleKey: "titles.createConnectionConfiguration",
@@ -215,11 +236,14 @@ function handleCertChange(val: string | undefined) {
215236
}
216237
}
217238
218-
async function onCertImported(created: { id: string; name: string }) {
239+
async function onCertImported(key: CertKey) {
219240
await loadCertificates();
220-
encryptWithCertificate.value = created.name;
241+
encryptWithCertificate.value = key.name;
221242
}
222243
244+
const { getEmptyItem, getFormFields, handleUploadCertificate } =
245+
useCertificateCreateForm({ onSuccess: onCertImported });
246+
223247
async function submit() {
224248
const mainResult = await mainFormRef.value?.validate();
225249

client/src/pages/(app)/exam-template/create/components/stepSEBSettings/components/SEBSettings.vue

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,24 @@
1010
/>
1111
</div>
1212
</v-col>
13-
<v-col cols="auto">
14-
<AddButton text="" @click="importDialog = true" />
13+
<v-col cols="auto" class="pt-8">
14+
<FormDialog
15+
icon-activator="mdi-plus-circle-outline"
16+
color-activator="primary"
17+
:label-activator="
18+
$t('sebSettings.importDialog.addButtonTitle')
19+
"
20+
size-activator="x-large"
21+
label-activator-visible
22+
:label-cancel="$t('general.cancelButton')"
23+
:label-submit="
24+
$t('sebSettings.importDialog.confirmButtonTitle')
25+
"
26+
form-id="form-certificate-upload"
27+
:get-form-fields="getFormFields"
28+
:get-item="getEmptyItem"
29+
:on-submit="handleImportSEBSettings"
30+
/>
1531
</v-col>
1632
</v-row>
1733
</v-container>
@@ -23,34 +39,17 @@
2339
</v-col>
2440
</v-row>
2541
</v-card>
26-
27-
<!-----------import dialog ---------->
28-
<UploadDialog
29-
v-model="importDialog"
30-
name-prefix="sebSettings"
31-
icon="mdi-file-upload-outline"
32-
:seb-settings-id="
33-
stepNamingStore.configurationTemplate
34-
? stepNamingStore.configurationTemplate.toString()
35-
: null
36-
"
37-
:show-quit-password="true"
38-
:default-ext-list="['.seb']"
39-
@uploaded="onConfigImported"
40-
/>
4142
</template>
4243

4344
<script setup lang="ts">
4445
import { computed, ComputedRef, ref } from "vue";
4546
import { ConfigurationTemplateKey } from "@/models/seb-server/configurationNode.ts";
4647
import { useStepNamingStore } from "@/pages/(app)/exam-template/create/components/stepNaming/composables/store/useStepNamingStore.ts";
4748
import SectionSubtitle from "@/components/widgets/SectionSubtitle.vue";
48-
import AddButton from "@/components/widgets/AddButton.vue";
4949
import SEBSettingsPanel from "@/components/widgets/sebSettings/components/SEBSettingsPanel.vue";
50-
import UploadDialog from "@/components/widgets/UploadDialog.vue";
5150
import { SEBSettingsContext } from "@/components/widgets/sebSettings/types.ts";
52-
53-
const stepNamingStore = useStepNamingStore();
51+
import { useSEBSettingsImportForm } from "../composables/useSEBSettingsImportForm";
52+
import FormDialog from "@/components/widgets/formDialog/FormDialog.vue";
5453
5554
const configKey = defineModel<ConfigurationTemplateKey | undefined>({
5655
required: true,
@@ -85,4 +84,9 @@ const seb_settings_context: ComputedRef<SEBSettingsContext> = computed(() => {
8584
ignoreSEBService: ref<boolean>(false),
8685
};
8786
});
87+
88+
const { getEmptyItem, getFormFields, handleImportSEBSettings } =
89+
useSEBSettingsImportForm(seb_settings_context.value.containerId, {
90+
onSuccess: onConfigImported,
91+
});
8892
</script>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { useMutation } from "@/composables/useMutation.ts";
2+
import { importSEBSettings } from "@/services/seb-server/configurationNodeService";
3+
import {
4+
ConfigurationKey,
5+
SEBSettingsImport,
6+
} from "@/models/seb-server/configurationNode";
7+
8+
export const useSEBSettingsImport = () =>
9+
useMutation<[SEBSettingsImport], ConfigurationKey>((params) =>
10+
importSEBSettings(params),
11+
);

0 commit comments

Comments
 (0)