11<template >
22 <tr >
33 <td width =" 60%" >{{ setting.description }}
4- <q-icon v-if =" setting.doc" name =" help" class =" q-ml-md" >
5- <q-tooltip class =" text-body2" >
6- {{ setting.doc }}
7- </q-tooltip >
8- </q-icon >
4+ <q-icon v-if =" setting.doc" name =" help" size =" sm" color =" primary"
5+ class =" q-ml-md" @click =" show_help = !show_help"
6+ />
97 </td >
108 <td width =" 40%" >
119 <input-with-blur
1210 outlined dense
13- v-if =" setting?.type === 'text' || setting?.type === 'timezone'"
14- v-model =" course_setting.value"
11+ v-if =" setting?.type === 'text'"
12+ v-model =" setting_value"
13+ />
14+ <input-with-blur
15+ outlined dense
16+ v-if =" setting?.type === 'decimal'"
17+ v-model.number =" setting_value"
18+ type =" number"
1519 />
16- <q-select v-if =" setting.type === 'list'" v-model =" option" :options =" options" />
20+ <input-with-blur
21+ outlined dense
22+ v-if =" setting?.type === 'timezone'"
23+ v-model =" setting_value"
24+ :error =" !valid_timezone"
25+ error-message =" This is not a valid timezone"
26+ />
27+ <q-select v-if =" setting.type === 'list'" v-model =" option_value" :options =" options" />
28+ <q-select v-if =" setting.type === 'multilist'" multiple v-model =" multilist_value" :options =" options" />
1729 <input-with-blur
1830 v-if =" setting.type === 'time_duration'"
19- v-model =" course_setting.value"
31+ v-model =" setting_value"
32+ lazy-rules
2033 :rules =" [checkTimeDuration]"
2134 />
22- <q-toggle v-if =" setting.type === 'boolean'" v-model =" course_setting.value " />
23- <q-input v-if =" setting.type === 'integer '" v-model = " course_setting.value " :rules =" [checkInt]" />
35+ <q-toggle v-if =" setting.type === 'boolean'" v-model =" setting_value " />
36+ <q-input v-if =" setting.type === 'int '" v-model.number = " setting_value " type = " number " :rules =" [checkInt]" />
2437 </td >
2538 </tr >
39+ <tr v-if =" setting.doc && show_help" ><td class =" helptext" colspan =" 2" ><div v-html =" setting.doc" /></td ></tr >
2640</template >
2741
2842<script setup lang="ts">
2943import { defineProps , ref , watch } from ' vue' ;
3044import { useQuasar } from ' quasar' ;
31- import { CourseSetting , OptionType } from ' src/common/models/settings' ;
45+ import { CourseSetting , OptionType , SettingValueType } from ' src/common/models/settings' ;
3246
3347import InputWithBlur from ' src/components/common/InputWithBlur.vue' ;
3448import { logger } from ' src/boot/logger' ;
3549
3650import { useSettingsStore } from ' src/stores/settings' ;
3751import { isTimeDuration } from ' src/common/models/parsers' ;
52+ import { api } from ' src/boot/axios' ;
3853
3954const props = defineProps <{
4055 setting: CourseSetting
@@ -44,22 +59,43 @@ const $q = useQuasar();
4459const settings = useSettingsStore ();
4560
4661const course_setting = ref (props .setting .clone ());
62+ // used for text input/toggles
63+ const setting_value = ref <SettingValueType >();
64+ if ([' int' , ' decimal' , ' text' , ' boolean' , ' time_duration' , ' timezone' ].includes (course_setting .value .type )) {
65+ setting_value .value = course_setting .value .value ;
66+ }
67+ // Used for type list and multilist
68+ const option_value = ref <OptionType >({ value: ' ' , label: ' ' });
69+ const multilist_value = ref <OptionType []>([]);
70+ const options = ref <OptionType []>([]);
71+
72+ // Determine if the help in settings.doc is shown.
73+ const show_help = ref (false );
4774
48- const option = ref < OptionType >({ value: ' ' , label: ' ' }) ;
49- const options = ref < Array < OptionType >>([]) ;
75+ const checkInt = ( val : string ) => Number . isInteger ( val ) || ' This must be an integer. ' ;
76+ const checkTimeDuration = ( val : string ) => isTimeDuration ( val ) || ' This must be a time duration. ' ;
5077
51- const checkInt = (val : string ) => Number .isInteger (val ) ? true : ' This must be an integer.' ;
52- const checkTimeDuration = (val : string ) => isTimeDuration (val ) ? true : ' This must be a time duration.' ;
78+ const valid_timezone = ref (true );
5379
80+ // These are for type list/multilist
5481if (course_setting .value .options ) {
5582 options .value = course_setting .value .options .map ((opt : string | OptionType ) =>
5683 typeof opt === ' string' ? { label: opt , value: opt } : opt
5784 );
58- const v = options .value .find ((opt : OptionType ) => opt .value === course_setting .value .value );
59- option .value = v || { value: ' ' , label: ' ' };
85+ }
86+ // Extract the option_value for type list
87+ if (course_setting .value .type === ' list' ) {
88+ option_value .value = options .value .find ((opt : OptionType ) => opt .value === course_setting .value .value ) ||
89+ { value : ' ' , label : ' ' };
90+ }
91+
92+ // Extract the multilist_value for type list
93+ if (course_setting .value .type === ' multilist' ) {
94+ multilist_value .value = options .value
95+ .filter ((opt : OptionType ) => (course_setting .value .value as string []).includes (opt .value ));
6096}
6197
62- watch (() => course_setting . value . value , async () => {
98+ const updateCourseSetting = async () => {
6399 try {
64100 await settings .updateCourseSetting (course_setting .value as CourseSetting );
65101 const msg = ` The setting '${course_setting .value .setting_name }' was updated successfully ` ;
@@ -72,5 +108,42 @@ watch(() => course_setting.value.value, async () => {
72108 $q .notify ({ message: err as string , color: ' red' });
73109 logger .error (` [CourseSettings/updateCourseSetting]: ${err as string } ` );
74110 }
111+ };
112+
113+ watch (() => setting_value .value , async () => {
114+ if (setting_value .value ) {
115+ if (course_setting .value .type === ' timezone' ) {
116+ // Check for valid timezone on the server.
117+ const response = await api .post (' /global-settings/check-timezone' ,
118+ { timezone: setting_value .value });
119+ valid_timezone .value = (response .data as { valid_timezone: boolean }).valid_timezone ;
120+ if (! valid_timezone .value ) return ;
121+ }
122+ course_setting .value .value = setting_value .value ;
123+ await updateCourseSetting ();
124+ }
125+ });
126+
127+ watch (() => option_value .value , async () => {
128+ if (option_value .value ) {
129+ course_setting .value .value = option_value .value .value ;
130+ await updateCourseSetting ();
131+ }
132+ });
133+
134+ watch (() => multilist_value .value , async () => {
135+ if (multilist_value .value ) {
136+ course_setting .value .value = multilist_value .value .map (opt => opt .value );
137+ await updateCourseSetting ();
138+ }
75139});
76140 </script >
141+
142+ <style lang="scss" scoped>
143+ .helptext {
144+ border : 1px solid black ;
145+ border-radius : 5px ;
146+ padding : 5px 0px ;
147+ background-color : lightyellow ;
148+ }
149+ </style >
0 commit comments