@simsustech/quasar-components 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @simsustech/quasar-components
2
2
 
3
+ ## 0.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a0e1496: feat(components): add CronScheduleInput
8
+
9
+ ## 0.9.1
10
+
11
+ ### Patch Changes
12
+
13
+ - 0bb7339: fix(FilteredModelSelect): fix fetching of missing modelValue id
14
+
3
15
  ## 0.9.0
4
16
 
5
17
  ### Minor Changes
package/dist/form.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ref, defineComponent, useAttrs, withAsyncContext, watch, openBlock, createBlock, unref, mergeProps, normalizeProps, guardReactiveProps, withCtx, createVNode, createTextVNode, toDisplayString, computed, useSlots, renderSlot, createCommentVNode, toRefs, resolveDirective, createElementBlock, Fragment, renderList, resolveDynamicComponent, createElementVNode, withDirectives, onMounted, createSlots } from "vue";
1
+ import { ref, defineComponent, useAttrs, withAsyncContext, watch, openBlock, createBlock, unref, mergeProps, normalizeProps, guardReactiveProps, withCtx, createVNode, createTextVNode, toDisplayString, computed, useSlots, renderSlot, createCommentVNode, toRefs, resolveDirective, createElementBlock, Fragment, renderList, resolveDynamicComponent, createElementVNode, withDirectives, createSlots } from "vue";
2
2
  import { useQuasar, QSelect, QItem, QItemSection, QItemLabel, QInput, QDate, QIcon, QTooltip, QBtn, QPopupProxy, QField, QEditor } from "quasar";
3
3
  import { e as enUs, n as nl, u as useLang$1 } from "./en-US-BEeILC7o.js";
4
4
  const lang$1 = {
@@ -53,6 +53,24 @@ const lang$1 = {
53
53
  },
54
54
  locale: {
55
55
  locale: "Locale"
56
+ },
57
+ cron: {
58
+ name: "Repeat",
59
+ minute: "Minute",
60
+ hour: "Hour",
61
+ dayOfMonth: "Day of month",
62
+ month: "Month",
63
+ dayOfWeek: "Day of week",
64
+ every: {
65
+ minute: "Every minute",
66
+ hour: "Every hour",
67
+ dayOfMonth: "Every day",
68
+ month: "Every month",
69
+ dayOfWeek: "Every day of the week"
70
+ },
71
+ validations: {
72
+ invalidCron: "Cron rule is invalid."
73
+ }
56
74
  }
57
75
  };
58
76
  const enUS = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -63,7 +81,7 @@ var define_import_meta_env_default = { BASE_URL: "/", MODE: "production", DEV: f
63
81
  const lang = ref(lang$1);
64
82
  const locales = /* @__PURE__ */ Object.assign({
65
83
  "./en-US.ts": () => Promise.resolve().then(() => enUS),
66
- "./nl.ts": () => import("./nl-DvM_wB4u.js")
84
+ "./nl.ts": () => import("./nl-DOn8oMdw.js")
67
85
  });
68
86
  const useLang = () => {
69
87
  return lang;
@@ -87,7 +105,7 @@ const loadLang = async (isoName) => {
87
105
  loadingLanguage = false;
88
106
  }
89
107
  };
90
- const _sfc_main$d = /* @__PURE__ */ defineComponent({
108
+ const _sfc_main$e = /* @__PURE__ */ defineComponent({
91
109
  __name: "GenderSelect",
92
110
  props: {
93
111
  modelValue: {},
@@ -140,7 +158,7 @@ const _sfc_main$d = /* @__PURE__ */ defineComponent({
140
158
  };
141
159
  }
142
160
  });
143
- const _sfc_main$c = /* @__PURE__ */ defineComponent({
161
+ const _sfc_main$d = /* @__PURE__ */ defineComponent({
144
162
  __name: "GenderItem",
145
163
  props: {
146
164
  modelValue: {}
@@ -180,7 +198,7 @@ const _sfc_main$c = /* @__PURE__ */ defineComponent({
180
198
  };
181
199
  }
182
200
  });
183
- const _sfc_main$b = /* @__PURE__ */ defineComponent({
201
+ const _sfc_main$c = /* @__PURE__ */ defineComponent({
184
202
  __name: "PostalCodeInput",
185
203
  props: {
186
204
  modelValue: {},
@@ -218,7 +236,7 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
218
236
  };
219
237
  }
220
238
  });
221
- const _sfc_main$a = /* @__PURE__ */ defineComponent({
239
+ const _sfc_main$b = /* @__PURE__ */ defineComponent({
222
240
  __name: "FormItem",
223
241
  props: {
224
242
  modelValue: {},
@@ -279,7 +297,7 @@ const _sfc_main$a = /* @__PURE__ */ defineComponent({
279
297
  };
280
298
  }
281
299
  });
282
- const _sfc_main$9 = /* @__PURE__ */ defineComponent({
300
+ const _sfc_main$a = /* @__PURE__ */ defineComponent({
283
301
  __name: "FormInput",
284
302
  props: {
285
303
  modelValue: {},
@@ -312,7 +330,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
312
330
  };
313
331
  }
314
332
  });
315
- const _sfc_main$8 = /* @__PURE__ */ defineComponent({
333
+ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
316
334
  __name: "TelephoneNumberInput",
317
335
  props: {
318
336
  modelValue: {},
@@ -343,7 +361,7 @@ const _hoisted_1$1 = {
343
361
  style: { "margin-left": "-0.5em", "margin-top": "0.75em" }
344
362
  };
345
363
  const _hoisted_2$1 = { class: "row items-center justify-end" };
346
- const _sfc_main$7 = /* @__PURE__ */ defineComponent({
364
+ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
347
365
  __name: "DateInput",
348
366
  props: {
349
367
  modelValue: {},
@@ -562,7 +580,7 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
562
580
  };
563
581
  }
564
582
  });
565
- const _sfc_main$6 = /* @__PURE__ */ defineComponent({
583
+ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
566
584
  __name: "BooleanSelect",
567
585
  props: {
568
586
  modelValue: { type: [Boolean, null] },
@@ -608,7 +626,7 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
608
626
  };
609
627
  }
610
628
  });
611
- const _sfc_main$5 = /* @__PURE__ */ defineComponent({
629
+ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
612
630
  __name: "BooleanItem",
613
631
  props: {
614
632
  modelValue: { type: [Boolean, null] },
@@ -652,7 +670,7 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
652
670
  const __default__$1 = {
653
671
  name: "EmailInput"
654
672
  };
655
- const _sfc_main$4 = /* @__PURE__ */ defineComponent({
673
+ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
656
674
  ...__default__$1,
657
675
  props: {
658
676
  subject: {},
@@ -689,7 +707,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
689
707
  };
690
708
  }
691
709
  });
692
- const _sfc_main$3 = /* @__PURE__ */ defineComponent({
710
+ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
693
711
  __name: "DatePicker",
694
712
  props: {
695
713
  modelValue: {},
@@ -755,7 +773,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
755
773
  };
756
774
  }
757
775
  });
758
- const _sfc_main$2 = /* @__PURE__ */ defineComponent({
776
+ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
759
777
  __name: "CurrencySelect",
760
778
  props: {
761
779
  modelValue: {},
@@ -796,7 +814,7 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
796
814
  });
797
815
  const _hoisted_1 = { key: 0 };
798
816
  const _hoisted_2 = { key: 1 };
799
- const _sfc_main$1 = /* @__PURE__ */ defineComponent({
817
+ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
800
818
  __name: "LocaleSelect",
801
819
  props: {
802
820
  modelValue: {},
@@ -893,7 +911,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
893
911
  const __default__ = {
894
912
  name: "FilteredModelSelect"
895
913
  };
896
- const _sfc_main = /* @__PURE__ */ defineComponent({
914
+ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
897
915
  ...__default__,
898
916
  props: {
899
917
  modelValue: {},
@@ -969,16 +987,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
969
987
  };
970
988
  const selectRef = ref();
971
989
  watch(modelValue, () => {
972
- if (!options.value.length)
973
- emit("filter", {
974
- ids: selectedIds.value,
975
- searchPhrase: "",
976
- done: () => {
977
- }
978
- });
979
- });
980
- onMounted(() => {
981
- if (!options.value.length)
990
+ var _a;
991
+ if (!((_a = options.value) == null ? void 0 : _a.find((val) => val.value === modelValue.value)))
982
992
  emit("filter", {
983
993
  ids: selectedIds.value,
984
994
  searchPhrase: "",
@@ -1024,21 +1034,215 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1024
1034
  };
1025
1035
  }
1026
1036
  });
1037
+ const _sfc_main = /* @__PURE__ */ defineComponent({
1038
+ __name: "CronScheduleInput",
1039
+ props: {
1040
+ modelValue: {},
1041
+ required: { type: Boolean },
1042
+ showMinute: { type: Boolean },
1043
+ showHour: { type: Boolean },
1044
+ showDayOfWeek: { type: Boolean }
1045
+ },
1046
+ emits: ["update:modelValue"],
1047
+ setup(__props, { emit: __emit }) {
1048
+ const props = __props;
1049
+ const emit = __emit;
1050
+ const { modelValue } = toRefs(props);
1051
+ const $q = useQuasar();
1052
+ const lang2 = useLang();
1053
+ const cronregex = new RegExp(
1054
+ /(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5,7})/
1055
+ );
1056
+ const label = lang2.value.cron.name;
1057
+ const minute = ref(["0"]);
1058
+ const hour = ref(["0"]);
1059
+ const dayOfMonth = ref(["1"]);
1060
+ const month = ref([]);
1061
+ const dayOfWeek = ref([]);
1062
+ const minuteOptions = ref([...Array(59).keys()].map(String));
1063
+ const hourOptions = ref([...Array(24).keys()].map(String));
1064
+ const dayOfMonthOptions = ref(
1065
+ Array.from({ length: 31 }, (_, i) => i + 1).map(
1066
+ (dayOfMonth2) => String(dayOfMonth2)
1067
+ )
1068
+ );
1069
+ const monthOptions = ref([
1070
+ ...Array.from({ length: 12 }, (_, i) => i + 1).map((month2) => ({
1071
+ label: $q.lang.date.months[month2 - 1],
1072
+ value: String(month2)
1073
+ }))
1074
+ ]);
1075
+ const dayOfWeekOptions = ref(
1076
+ [...Array(31).keys()].map((day) => ({
1077
+ label: $q.lang.date.days[day],
1078
+ value: String(day)
1079
+ }))
1080
+ );
1081
+ const validations = ref([
1082
+ (val) => cronregex.test(val) || lang2.value.cron.validations.invalidCron
1083
+ ]);
1084
+ watch([minute, hour, dayOfMonth, month, dayOfWeek], () => {
1085
+ const cron = `${minute.value.join(",") || "*"} ${hour.value.join(",") || "*"} ${dayOfMonth.value.join(",") || "*"} ${month.value.join(",") || "*"} ${dayOfWeek.value.join(",") || "*"}`;
1086
+ if (cronregex.test(cron)) {
1087
+ emit("update:modelValue", cron);
1088
+ } else {
1089
+ emit("update:modelValue", "0 0 1 * *");
1090
+ }
1091
+ });
1092
+ function setInternalCron(cronString) {
1093
+ if (cronregex.test(cronString)) {
1094
+ const [newMinute, newHour, newDayOfMonth, newMonth, newDayOfWeek] = cronString.split(" ");
1095
+ minute.value = newMinute.split(",").filter((val) => val !== "*");
1096
+ hour.value = newHour.split(",").filter((val) => val !== "*");
1097
+ dayOfMonth.value = newDayOfMonth.split(",").filter((val) => val !== "*");
1098
+ month.value = newMonth.split(",").filter((val) => val !== "*");
1099
+ dayOfWeek.value = newDayOfWeek.split(",").filter((val) => val !== "*");
1100
+ }
1101
+ }
1102
+ watch(modelValue, (newVal) => {
1103
+ if (newVal)
1104
+ setInternalCron(newVal);
1105
+ else if (newVal === null) {
1106
+ setInternalCron("0 0 1 * *");
1107
+ }
1108
+ });
1109
+ setInternalCron(modelValue.value);
1110
+ return (_ctx, _cache) => {
1111
+ const _component_q_select = QSelect;
1112
+ const _component_q_field = QField;
1113
+ return openBlock(), createBlock(_component_q_field, {
1114
+ "model-value": unref(modelValue),
1115
+ rules: validations.value,
1116
+ label: `${unref(label)}${_ctx.required ? "*" : ""}`,
1117
+ "stack-label": "",
1118
+ borderless: ""
1119
+ }, {
1120
+ control: withCtx(() => [
1121
+ _ctx.showHour ? (openBlock(), createBlock(_component_q_select, {
1122
+ key: 0,
1123
+ modelValue: hour.value,
1124
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => hour.value = $event),
1125
+ options: hourOptions.value,
1126
+ hint: unref(lang2).cron.hour,
1127
+ "bottom-slots": "",
1128
+ style: {
1129
+ width: "10ch",
1130
+ "margin-top": "-2em",
1131
+ "margin-bottom": "-0.5em"
1132
+ },
1133
+ "map-options": "",
1134
+ "emit-value": "",
1135
+ multiple: ""
1136
+ }, {
1137
+ selected: withCtx(() => [
1138
+ createTextVNode(toDisplayString(hour.value.length ? hour.value.join(",") : unref(lang2).cron.every.hour), 1)
1139
+ ]),
1140
+ _: 1
1141
+ }, 8, ["modelValue", "options", "hint"])) : createCommentVNode("", true),
1142
+ _ctx.showMinute ? (openBlock(), createBlock(_component_q_select, {
1143
+ key: 1,
1144
+ modelValue: minute.value,
1145
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => minute.value = $event),
1146
+ options: minuteOptions.value,
1147
+ hint: unref(lang2).cron.minute,
1148
+ "bottom-slots": "",
1149
+ style: {
1150
+ width: "10ch",
1151
+ "margin-top": "-2em",
1152
+ "margin-bottom": "-0.5em"
1153
+ },
1154
+ "map-options": "",
1155
+ "emit-value": "",
1156
+ multiple: ""
1157
+ }, {
1158
+ selected: withCtx(() => [
1159
+ createTextVNode(toDisplayString(minute.value.length ? minute.value.join(",") : unref(lang2).cron.every.minute), 1)
1160
+ ]),
1161
+ _: 1
1162
+ }, 8, ["modelValue", "options", "hint"])) : createCommentVNode("", true),
1163
+ createVNode(_component_q_select, {
1164
+ modelValue: dayOfMonth.value,
1165
+ "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => dayOfMonth.value = $event),
1166
+ options: dayOfMonthOptions.value,
1167
+ hint: unref(lang2).cron.dayOfMonth,
1168
+ "bottom-slots": "",
1169
+ style: {
1170
+ width: "10ch",
1171
+ "margin-top": "-2em",
1172
+ "margin-bottom": "-0.5em"
1173
+ },
1174
+ "map-options": "",
1175
+ "emit-value": "",
1176
+ multiple: ""
1177
+ }, {
1178
+ selected: withCtx(() => [
1179
+ createTextVNode(toDisplayString(dayOfMonth.value.length ? dayOfMonth.value.join(",") : unref(lang2).cron.every.dayOfMonth), 1)
1180
+ ]),
1181
+ _: 1
1182
+ }, 8, ["modelValue", "options", "hint"]),
1183
+ createVNode(_component_q_select, {
1184
+ modelValue: month.value,
1185
+ "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => month.value = $event),
1186
+ options: monthOptions.value,
1187
+ hint: unref(lang2).cron.month,
1188
+ placeholder: unref(lang2).cron.month,
1189
+ "bottom-slots": "",
1190
+ style: {
1191
+ width: "16ch",
1192
+ "margin-top": "-2em",
1193
+ "margin-bottom": "-0.5em"
1194
+ },
1195
+ "map-options": "",
1196
+ "emit-value": "",
1197
+ multiple: ""
1198
+ }, {
1199
+ selected: withCtx(() => [
1200
+ createTextVNode(toDisplayString(month.value.length ? month.value.map((val) => unref($q).lang.date.months[Number(val) - 1]).join(",") : unref(lang2).cron.every.month), 1)
1201
+ ]),
1202
+ _: 1
1203
+ }, 8, ["modelValue", "options", "hint", "placeholder"]),
1204
+ _ctx.showDayOfWeek ? (openBlock(), createBlock(_component_q_select, {
1205
+ key: 2,
1206
+ modelValue: dayOfWeek.value,
1207
+ "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => dayOfWeek.value = $event),
1208
+ options: dayOfWeekOptions.value,
1209
+ placeholder: unref(lang2).cron.dayOfWeek,
1210
+ style: {
1211
+ width: "16ch",
1212
+ "margin-top": "-2em",
1213
+ "margin-bottom": "-0.5em"
1214
+ },
1215
+ "map-options": "",
1216
+ "emit-value": "",
1217
+ multiple: ""
1218
+ }, {
1219
+ selected: withCtx(() => [
1220
+ createTextVNode(toDisplayString(dayOfWeek.value.length ? dayOfWeek.value.map((val) => unref($q).lang.date.days[Number(val)]).join(",") : unref(lang2).cron.every.dayOfWeek), 1)
1221
+ ]),
1222
+ _: 1
1223
+ }, 8, ["modelValue", "options", "placeholder"])) : createCommentVNode("", true)
1224
+ ]),
1225
+ _: 1
1226
+ }, 8, ["model-value", "rules", "label"]);
1227
+ };
1228
+ }
1229
+ });
1027
1230
  export {
1028
- _sfc_main$5 as BooleanItem,
1029
- _sfc_main$6 as BooleanSelect,
1030
- _sfc_main$2 as CurrencySelect,
1031
- _sfc_main$7 as DateInput,
1032
- _sfc_main$3 as DatePicker,
1033
- _sfc_main$4 as EmailInput,
1034
- _sfc_main as FilteredModelSelect,
1035
- _sfc_main$9 as FormInput,
1036
- _sfc_main$a as FormItem,
1037
- _sfc_main$c as GenderItem,
1038
- _sfc_main$d as GenderSelect,
1039
- _sfc_main$1 as LocaleSelect,
1040
- _sfc_main$b as PostalCodeInput,
1041
- _sfc_main$8 as TelephoneNumberInput,
1231
+ _sfc_main$6 as BooleanItem,
1232
+ _sfc_main$7 as BooleanSelect,
1233
+ _sfc_main as CronScheduleInput,
1234
+ _sfc_main$3 as CurrencySelect,
1235
+ _sfc_main$8 as DateInput,
1236
+ _sfc_main$4 as DatePicker,
1237
+ _sfc_main$5 as EmailInput,
1238
+ _sfc_main$1 as FilteredModelSelect,
1239
+ _sfc_main$a as FormInput,
1240
+ _sfc_main$b as FormItem,
1241
+ _sfc_main$d as GenderItem,
1242
+ _sfc_main$e as GenderSelect,
1243
+ _sfc_main$2 as LocaleSelect,
1244
+ _sfc_main$c as PostalCodeInput,
1245
+ _sfc_main$9 as TelephoneNumberInput,
1042
1246
  loadLang,
1043
1247
  useLang
1044
1248
  };
@@ -50,6 +50,24 @@ const lang = {
50
50
  },
51
51
  locale: {
52
52
  locale: "Land"
53
+ },
54
+ cron: {
55
+ name: "Herhaling",
56
+ minute: "Minuut",
57
+ hour: "Uur",
58
+ dayOfMonth: "Dag van maand",
59
+ month: "Maand",
60
+ dayOfWeek: "Dag van week",
61
+ every: {
62
+ minute: "Iedere minuut",
63
+ hour: "Ieder uur",
64
+ dayOfMonth: "Iedere dag",
65
+ month: "Iedere maand",
66
+ dayOfWeek: "Iedere dag van de week"
67
+ },
68
+ validations: {
69
+ invalidCron: "Cron regel is ongeldig."
70
+ }
53
71
  }
54
72
  };
55
73
  export {
@@ -0,0 +1,22 @@
1
+ export interface Props {
2
+ modelValue: string;
3
+ required?: boolean;
4
+ showMinute?: boolean;
5
+ showHour?: boolean;
6
+ showDayOfWeek?: boolean;
7
+ }
8
+ declare const _default: import("vue").DefineComponent<__VLS_TypePropsToOption<Props>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
9
+ "update:modelValue": (val: string) => void;
10
+ }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<Props>>> & {
11
+ "onUpdate:modelValue"?: ((val: string) => any) | undefined;
12
+ }, {}, {}>;
13
+ export default _default;
14
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
15
+ type __VLS_TypePropsToOption<T> = {
16
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
17
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
18
+ } : {
19
+ type: import('vue').PropType<T[K]>;
20
+ required: true;
21
+ };
22
+ };
@@ -12,4 +12,5 @@ export { default as DatePicker } from './DatePicker.vue';
12
12
  export { default as CurrencySelect } from './CurrencySelect.vue';
13
13
  export { default as LocaleSelect } from './LocaleSelect.vue';
14
14
  export { default as FilteredModelSelect } from './FilteredModelSelect.vue';
15
+ export { default as CronScheduleInput } from './CronScheduleInput.vue';
15
16
  export { useLang, loadLang } from './lang/index.js';
@@ -51,6 +51,24 @@ export interface Language {
51
51
  locale: {
52
52
  locale: string;
53
53
  };
54
+ cron: {
55
+ name: string;
56
+ minute: string;
57
+ hour: string;
58
+ dayOfMonth: string;
59
+ month: string;
60
+ dayOfWeek: string;
61
+ every: {
62
+ minute: string;
63
+ hour: string;
64
+ dayOfMonth: string;
65
+ month: string;
66
+ dayOfWeek: string;
67
+ };
68
+ validations: {
69
+ invalidCron: string;
70
+ };
71
+ };
54
72
  }
55
73
  import type { Ref } from 'vue';
56
74
  export declare const lang: Ref<{
@@ -106,6 +124,24 @@ export declare const lang: Ref<{
106
124
  locale: {
107
125
  locale: string;
108
126
  };
127
+ cron: {
128
+ name: string;
129
+ minute: string;
130
+ hour: string;
131
+ dayOfMonth: string;
132
+ month: string;
133
+ dayOfWeek: string;
134
+ every: {
135
+ minute: string;
136
+ hour: string;
137
+ dayOfMonth: string;
138
+ month: string;
139
+ dayOfWeek: string;
140
+ };
141
+ validations: {
142
+ invalidCron: string;
143
+ };
144
+ };
109
145
  }>;
110
146
  export declare const defineLang: (lang: Language) => Language;
111
147
  export declare const useLang: () => Ref<Language>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simsustech/quasar-components",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "author": "Stefan van Herwijnen",
5
5
  "description": "High level components for Quasar Framework",
6
6
  "license": "MIT",
@@ -0,0 +1,205 @@
1
+ <template>
2
+ <q-field
3
+ :model-value="modelValue"
4
+ :rules="validations"
5
+ :label="`${label}${required ? '*' : ''}`"
6
+ stack-label
7
+ borderless
8
+ >
9
+ <template #control>
10
+ <q-select
11
+ v-if="showHour"
12
+ v-model="hour"
13
+ :options="hourOptions"
14
+ :hint="lang.cron.hour"
15
+ bottom-slots
16
+ :style="{
17
+ width: '10ch',
18
+ 'margin-top': '-2em',
19
+ 'margin-bottom': '-0.5em'
20
+ }"
21
+ map-options
22
+ emit-value
23
+ multiple
24
+ >
25
+ <template #selected>
26
+ {{ hour.length ? hour.join(',') : lang.cron.every.hour }}
27
+ </template>
28
+ </q-select>
29
+ <q-select
30
+ v-if="showMinute"
31
+ v-model="minute"
32
+ :options="minuteOptions"
33
+ :hint="lang.cron.minute"
34
+ bottom-slots
35
+ :style="{
36
+ width: '10ch',
37
+ 'margin-top': '-2em',
38
+ 'margin-bottom': '-0.5em'
39
+ }"
40
+ map-options
41
+ emit-value
42
+ multiple
43
+ >
44
+ <template #selected>
45
+ {{ minute.length ? minute.join(',') : lang.cron.every.minute }}
46
+ </template>
47
+ </q-select>
48
+ <q-select
49
+ v-model="dayOfMonth"
50
+ :options="dayOfMonthOptions"
51
+ :hint="lang.cron.dayOfMonth"
52
+ bottom-slots
53
+ :style="{
54
+ width: '10ch',
55
+ 'margin-top': '-2em',
56
+ 'margin-bottom': '-0.5em'
57
+ }"
58
+ map-options
59
+ emit-value
60
+ multiple
61
+ >
62
+ <template #selected>
63
+ {{
64
+ dayOfMonth.length
65
+ ? dayOfMonth.join(',')
66
+ : lang.cron.every.dayOfMonth
67
+ }}
68
+ </template>
69
+ </q-select>
70
+ <q-select
71
+ v-model="month"
72
+ :options="monthOptions"
73
+ :hint="lang.cron.month"
74
+ :placeholder="lang.cron.month"
75
+ bottom-slots
76
+ :style="{
77
+ width: '16ch',
78
+ 'margin-top': '-2em',
79
+ 'margin-bottom': '-0.5em'
80
+ }"
81
+ map-options
82
+ emit-value
83
+ multiple
84
+ >
85
+ <template #selected>
86
+ {{
87
+ month.length
88
+ ? month
89
+ .map((val) => $q.lang.date.months[Number(val) - 1])
90
+ .join(',')
91
+ : lang.cron.every.month
92
+ }}
93
+ </template>
94
+ </q-select>
95
+ <q-select
96
+ v-if="showDayOfWeek"
97
+ v-model="dayOfWeek"
98
+ :options="dayOfWeekOptions"
99
+ :placeholder="lang.cron.dayOfWeek"
100
+ :style="{
101
+ width: '16ch',
102
+ 'margin-top': '-2em',
103
+ 'margin-bottom': '-0.5em'
104
+ }"
105
+ map-options
106
+ emit-value
107
+ multiple
108
+ >
109
+ <template #selected>
110
+ {{
111
+ dayOfWeek.length
112
+ ? dayOfWeek.map((val) => $q.lang.date.days[Number(val)]).join(',')
113
+ : lang.cron.every.dayOfWeek
114
+ }}
115
+ </template>
116
+ </q-select>
117
+ </template>
118
+ </q-field>
119
+ </template>
120
+
121
+ <script setup lang="ts">
122
+ import { ref, toRefs, watch } from 'vue'
123
+ import { useLang } from './lang/index.js'
124
+ import { useQuasar } from 'quasar'
125
+ export interface Props {
126
+ modelValue: string
127
+ required?: boolean
128
+ showMinute?: boolean
129
+ showHour?: boolean
130
+ showDayOfWeek?: boolean
131
+ }
132
+
133
+ const props = defineProps<Props>()
134
+ const emit = defineEmits<{
135
+ (e: 'update:modelValue', val: string): void
136
+ }>()
137
+
138
+ const { modelValue } = toRefs(props)
139
+
140
+ const $q = useQuasar()
141
+ const lang = useLang()
142
+ const cronregex = new RegExp(
143
+ /(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5,7})/
144
+ )
145
+ const label = lang.value.cron.name
146
+ const minute = ref<string[]>(['0'])
147
+ const hour = ref<string[]>(['0'])
148
+ const dayOfMonth = ref<string[]>(['1'])
149
+ const month = ref<string[]>([])
150
+ const dayOfWeek = ref<string[]>([])
151
+
152
+ const minuteOptions = ref([...Array(59).keys()].map(String))
153
+ const hourOptions = ref([...Array(24).keys()].map(String))
154
+ const dayOfMonthOptions = ref(
155
+ Array.from({ length: 31 }, (_, i) => i + 1).map((dayOfMonth) =>
156
+ String(dayOfMonth)
157
+ )
158
+ )
159
+ const monthOptions = ref([
160
+ ...Array.from({ length: 12 }, (_, i) => i + 1).map((month) => ({
161
+ label: $q.lang.date.months[month - 1],
162
+ value: String(month)
163
+ }))
164
+ ])
165
+ const dayOfWeekOptions = ref(
166
+ [...Array(31).keys()].map((day) => ({
167
+ label: $q.lang.date.days[day],
168
+ value: String(day)
169
+ }))
170
+ )
171
+
172
+ const validations = ref([
173
+ (val: string) =>
174
+ cronregex.test(val) || lang.value.cron.validations.invalidCron
175
+ ])
176
+
177
+ watch([minute, hour, dayOfMonth, month, dayOfWeek], () => {
178
+ const cron = `${minute.value.join(',') || '*'} ${hour.value.join(',') || '*'} ${dayOfMonth.value.join(',') || '*'} ${month.value.join(',') || '*'} ${dayOfWeek.value.join(',') || '*'}`
179
+ if (cronregex.test(cron)) {
180
+ emit('update:modelValue', cron)
181
+ } else {
182
+ emit('update:modelValue', '0 0 1 * *')
183
+ }
184
+ })
185
+
186
+ function setInternalCron(cronString: string) {
187
+ if (cronregex.test(cronString)) {
188
+ const [newMinute, newHour, newDayOfMonth, newMonth, newDayOfWeek] =
189
+ cronString.split(' ')
190
+ minute.value = newMinute.split(',').filter((val) => val !== '*')
191
+ hour.value = newHour.split(',').filter((val) => val !== '*')
192
+ dayOfMonth.value = newDayOfMonth.split(',').filter((val) => val !== '*')
193
+ month.value = newMonth.split(',').filter((val) => val !== '*')
194
+ dayOfWeek.value = newDayOfWeek.split(',').filter((val) => val !== '*')
195
+ }
196
+ }
197
+
198
+ watch(modelValue, (newVal) => {
199
+ if (newVal) setInternalCron(newVal)
200
+ else if (newVal === null) {
201
+ setInternalCron('0 0 1 * *')
202
+ }
203
+ })
204
+ setInternalCron(modelValue.value)
205
+ </script>
@@ -37,7 +37,7 @@ export default {
37
37
  generic="T extends { id: number; [key: string]: unknown }"
38
38
  >
39
39
  import { QSelect } from 'quasar'
40
- import { computed, ref, toRefs, useAttrs, watch, onMounted } from 'vue'
40
+ import { computed, ref, toRefs, useAttrs, watch } from 'vue'
41
41
  import { useLang } from './lang/index.js'
42
42
 
43
43
  interface Props {
@@ -132,7 +132,7 @@ const filterFn: QSelect['$props']['onFilter'] = (val, update, abort) => {
132
132
  const selectRef = ref<QSelect>()
133
133
 
134
134
  watch(modelValue, () => {
135
- if (!options.value.length)
135
+ if (!options.value?.find((val) => val.value === modelValue.value))
136
136
  emit('filter', {
137
137
  ids: selectedIds.value,
138
138
  searchPhrase: '',
@@ -140,12 +140,12 @@ watch(modelValue, () => {
140
140
  })
141
141
  })
142
142
 
143
- onMounted(() => {
144
- if (!options.value.length)
145
- emit('filter', {
146
- ids: selectedIds.value,
147
- searchPhrase: '',
148
- done: () => {}
149
- })
150
- })
143
+ // onMounted(() => {
144
+ // if (!options.value?.find((val) => val.value === modelValue.value))
145
+ // emit('filter', {
146
+ // ids: selectedIds.value,
147
+ // searchPhrase: '',
148
+ // done: () => {}
149
+ // })
150
+ // })
151
151
  </script>
@@ -12,4 +12,5 @@ export { default as DatePicker } from './DatePicker.vue'
12
12
  export { default as CurrencySelect } from './CurrencySelect.vue'
13
13
  export { default as LocaleSelect } from './LocaleSelect.vue'
14
14
  export { default as FilteredModelSelect } from './FilteredModelSelect.vue'
15
+ export { default as CronScheduleInput } from './CronScheduleInput.vue'
15
16
  export { useLang, loadLang } from './lang/index.js'
@@ -52,6 +52,24 @@ const lang: Language = {
52
52
  },
53
53
  locale: {
54
54
  locale: 'Locale'
55
+ },
56
+ cron: {
57
+ name: 'Repeat',
58
+ minute: 'Minute',
59
+ hour: 'Hour',
60
+ dayOfMonth: 'Day of month',
61
+ month: 'Month',
62
+ dayOfWeek: 'Day of week',
63
+ every: {
64
+ minute: 'Every minute',
65
+ hour: 'Every hour',
66
+ dayOfMonth: 'Every day',
67
+ month: 'Every month',
68
+ dayOfWeek: 'Every day of the week'
69
+ },
70
+ validations: {
71
+ invalidCron: 'Cron rule is invalid.'
72
+ }
55
73
  }
56
74
  }
57
75
 
@@ -51,6 +51,24 @@ export interface Language {
51
51
  locale: {
52
52
  locale: string
53
53
  }
54
+ cron: {
55
+ name: string
56
+ minute: string
57
+ hour: string
58
+ dayOfMonth: string
59
+ month: string
60
+ dayOfWeek: string
61
+ every: {
62
+ minute: string
63
+ hour: string
64
+ dayOfMonth: string
65
+ month: string
66
+ dayOfWeek: string
67
+ }
68
+ validations: {
69
+ invalidCron: string
70
+ }
71
+ }
54
72
  }
55
73
 
56
74
  import type { Ref } from 'vue'
@@ -52,6 +52,24 @@ const lang: Language = {
52
52
  },
53
53
  locale: {
54
54
  locale: 'Land'
55
+ },
56
+ cron: {
57
+ name: 'Herhaling',
58
+ minute: 'Minuut',
59
+ hour: 'Uur',
60
+ dayOfMonth: 'Dag van maand',
61
+ month: 'Maand',
62
+ dayOfWeek: 'Dag van week',
63
+ every: {
64
+ minute: 'Iedere minuut',
65
+ hour: 'Ieder uur',
66
+ dayOfMonth: 'Iedere dag',
67
+ month: 'Iedere maand',
68
+ dayOfWeek: 'Iedere dag van de week'
69
+ },
70
+ validations: {
71
+ invalidCron: 'Cron regel is ongeldig.'
72
+ }
55
73
  }
56
74
  }
57
75