adminforth 1.0.30 → 1.0.31

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/dist/index.js CHANGED
@@ -455,10 +455,73 @@ class AdminForth {
455
455
  return Object.assign(Object.assign({}, data), { options: resource === null || resource === void 0 ? void 0 : resource.options });
456
456
  }),
457
457
  });
458
+ server.endpoint({
459
+ method: 'POST',
460
+ path: '/get_resource_foreign_data',
461
+ handler: (_h) => __awaiter(this, [_h], void 0, function* ({ body, adminUser }) {
462
+ var _j, _k, _l, _m;
463
+ const { resourceId, column } = body;
464
+ if (!this.statuses.dbDiscover) {
465
+ return { error: 'Database discovery not started' };
466
+ }
467
+ if (this.statuses.dbDiscover !== 'done') {
468
+ return { error: 'Database discovery is still in progress, please try later' };
469
+ }
470
+ const resource = this.config.resources.find((res) => res.resourceId == resourceId);
471
+ if (!resource) {
472
+ return { error: `Resource ${resourceId} not found` };
473
+ }
474
+ const columnConfig = resource.columns.find((col) => col.name == column);
475
+ if (!columnConfig.foreignResource) {
476
+ return { error: `Column ${column} in resource ${resourceId} is not a foreign key` };
477
+ }
478
+ const targetResourceId = columnConfig.foreignResource.resourceId;
479
+ const targetResource = this.config.resources.find((res) => res.resourceId == targetResourceId);
480
+ if ((_j = columnConfig.foreignResource.hooks) === null || _j === void 0 ? void 0 : _j.beforeDatasourceRequest) {
481
+ const resp = yield ((_k = column.foreignResource.hooks) === null || _k === void 0 ? void 0 : _k.beforeDatasourceRequest({ query: body, adminUser }));
482
+ if (!resp || (!resp.ok && !resp.error)) {
483
+ throw new Error(`Hook must return object with {ok: true} or { error: 'Error' } `);
484
+ }
485
+ if (resp.error) {
486
+ return { error: resp.error };
487
+ }
488
+ }
489
+ const { limit, offset, filters, sort } = body;
490
+ const dbDataItems = yield this.connectors[targetResource.dataSource].getData({
491
+ resource: targetResource,
492
+ limit,
493
+ offset,
494
+ filters: filters || [],
495
+ sort: sort || [],
496
+ });
497
+ const items = dbDataItems.data.map((item) => {
498
+ const pk = item[targetResource.columns.find((col) => col.primaryKey).name];
499
+ const labler = targetResource.itemLabel || ((record) => `${targetResource.label} ${pk}`);
500
+ return {
501
+ value: pk,
502
+ label: labler(item),
503
+ _item: item, // user might need it in hook to form new label
504
+ };
505
+ });
506
+ const response = {
507
+ items
508
+ };
509
+ if ((_l = columnConfig.foreignResource.hooks) === null || _l === void 0 ? void 0 : _l.afterDatasourceRequest) {
510
+ const resp = yield ((_m = column.foreignResource.hooks) === null || _m === void 0 ? void 0 : _m.afterDatasourceRequest({ response, adminUser }));
511
+ if (!resp || (!resp.ok && !resp.error)) {
512
+ throw new Error(`Hook must return object with {ok: true} or { error: 'Error' } `);
513
+ }
514
+ if (resp.error) {
515
+ return { error: resp.error };
516
+ }
517
+ }
518
+ return response;
519
+ }),
520
+ });
458
521
  server.endpoint({
459
522
  method: 'POST',
460
523
  path: '/get_min_max_for_columns',
461
- handler: (_h) => __awaiter(this, [_h], void 0, function* ({ body }) {
524
+ handler: (_o) => __awaiter(this, [_o], void 0, function* ({ body }) {
462
525
  const { resourceId } = body;
463
526
  if (!this.statuses.dbDiscover) {
464
527
  return { error: 'Database discovery not started' };
@@ -487,8 +550,8 @@ class AdminForth {
487
550
  server.endpoint({
488
551
  method: 'POST',
489
552
  path: '/get_record',
490
- handler: (_j) => __awaiter(this, [_j], void 0, function* ({ body, adminUser }) {
491
- var _k, _l;
553
+ handler: (_p) => __awaiter(this, [_p], void 0, function* ({ body, adminUser }) {
554
+ var _q, _r;
492
555
  const { resourceId, primaryKey } = body;
493
556
  const resource = this.config.resources.find((res) => res.resourceId == resourceId);
494
557
  const primaryKeyColumn = resource.columns.find((col) => col.primaryKey);
@@ -498,8 +561,8 @@ class AdminForth {
498
561
  return { error: `Record with ${primaryKeyColumn.name} ${primaryKey} not found` };
499
562
  }
500
563
  // execute hook if needed
501
- if ((_k = resource.hooks) === null || _k === void 0 ? void 0 : _k.show) {
502
- const resp = yield ((_l = resource.hooks) === null || _l === void 0 ? void 0 : _l.show({ resource, record, adminUser }));
564
+ if ((_q = resource.hooks) === null || _q === void 0 ? void 0 : _q.show) {
565
+ const resp = yield ((_r = resource.hooks) === null || _r === void 0 ? void 0 : _r.show({ resource, record, adminUser }));
503
566
  if (!resp || (!resp.ok && !resp.error)) {
504
567
  throw new Error(`Hook must return object with {ok: true} or { error: 'Error' } `);
505
568
  }
@@ -516,8 +579,8 @@ class AdminForth {
516
579
  noAuth: true, // TODO
517
580
  method: 'POST',
518
581
  path: '/create_record',
519
- handler: (_m) => __awaiter(this, [_m], void 0, function* ({ body, adminUser }) {
520
- var _o, _p, _q, _r, _s, _t, _u, _v, _w;
582
+ handler: (_s) => __awaiter(this, [_s], void 0, function* ({ body, adminUser }) {
583
+ var _t, _u, _v, _w, _x, _y, _z, _0, _1;
521
584
  console.log('create_record', body, this.config.resources);
522
585
  const resource = this.config.resources.find((res) => res.resourceId == body['resourceId']);
523
586
  if (!resource) {
@@ -525,8 +588,8 @@ class AdminForth {
525
588
  }
526
589
  const record = body['record'];
527
590
  // execute hook if needed
528
- if ((_p = (_o = resource.hooks) === null || _o === void 0 ? void 0 : _o.create) === null || _p === void 0 ? void 0 : _p.beforeSave) {
529
- const resp = yield ((_r = (_q = resource.hooks) === null || _q === void 0 ? void 0 : _q.create) === null || _r === void 0 ? void 0 : _r.beforeSave({ resource, record, adminUser }));
591
+ if ((_u = (_t = resource.hooks) === null || _t === void 0 ? void 0 : _t.create) === null || _u === void 0 ? void 0 : _u.beforeSave) {
592
+ const resp = yield ((_w = (_v = resource.hooks) === null || _v === void 0 ? void 0 : _v.create) === null || _w === void 0 ? void 0 : _w.beforeSave({ resource, record, adminUser }));
530
593
  if (!resp || (!resp.ok && !resp.error)) {
531
594
  throw new Error(`Hook beforeSave must return object with {ok: true} or { error: 'Error' } `);
532
595
  }
@@ -542,7 +605,7 @@ class AdminForth {
542
605
  });
543
606
  }
544
607
  }
545
- if (((_s = column.required) === null || _s === void 0 ? void 0 : _s.create) && body['record'][column.name] === undefined) {
608
+ if (((_x = column.required) === null || _x === void 0 ? void 0 : _x.create) && body['record'][column.name] === undefined) {
546
609
  return { error: `Column '${column.name}' is required` };
547
610
  }
548
611
  if (column.isUnique) {
@@ -567,8 +630,8 @@ class AdminForth {
567
630
  const connector = this.connectors[resource.dataSource];
568
631
  yield connector.createRecord({ resource, record });
569
632
  // execute hook if needed
570
- if ((_u = (_t = resource.hooks) === null || _t === void 0 ? void 0 : _t.create) === null || _u === void 0 ? void 0 : _u.afterSave) {
571
- const resp = yield ((_w = (_v = resource.hooks) === null || _v === void 0 ? void 0 : _v.create) === null || _w === void 0 ? void 0 : _w.afterSave({ resource, record, adminUser }));
633
+ if ((_z = (_y = resource.hooks) === null || _y === void 0 ? void 0 : _y.create) === null || _z === void 0 ? void 0 : _z.afterSave) {
634
+ const resp = yield ((_1 = (_0 = resource.hooks) === null || _0 === void 0 ? void 0 : _0.create) === null || _1 === void 0 ? void 0 : _1.afterSave({ resource, record, adminUser }));
572
635
  if (!resp || (!resp.ok && !resp.error)) {
573
636
  throw new Error(`Hook afterSave must return object with {ok: true} or { error: 'Error' } `);
574
637
  }
@@ -585,8 +648,8 @@ class AdminForth {
585
648
  noAuth: true, // TODO
586
649
  method: 'POST',
587
650
  path: '/update_record',
588
- handler: (_x) => __awaiter(this, [_x], void 0, function* ({ body, adminUser }) {
589
- var _y, _z, _0, _1, _2, _3, _4, _5;
651
+ handler: (_2) => __awaiter(this, [_2], void 0, function* ({ body, adminUser }) {
652
+ var _3, _4, _5, _6, _7, _8, _9, _10;
590
653
  console.log('update_record', body);
591
654
  const resource = this.config.resources.find((res) => res.resourceId == body['resourceId']);
592
655
  if (!resource) {
@@ -601,8 +664,8 @@ class AdminForth {
601
664
  }
602
665
  const record = body['record'];
603
666
  // execute hook if needed
604
- if ((_z = (_y = resource.hooks) === null || _y === void 0 ? void 0 : _y.edit) === null || _z === void 0 ? void 0 : _z.beforeSave) {
605
- const resp = yield ((_1 = (_0 = resource.hooks) === null || _0 === void 0 ? void 0 : _0.edit) === null || _1 === void 0 ? void 0 : _1.beforeSave({ resource, record, adminUser }));
667
+ if ((_4 = (_3 = resource.hooks) === null || _3 === void 0 ? void 0 : _3.edit) === null || _4 === void 0 ? void 0 : _4.beforeSave) {
668
+ const resp = yield ((_6 = (_5 = resource.hooks) === null || _5 === void 0 ? void 0 : _5.edit) === null || _6 === void 0 ? void 0 : _6.beforeSave({ resource, record, adminUser }));
606
669
  if (!resp || (!resp.ok && !resp.error)) {
607
670
  throw new Error(`Hook beforeSave must return object with {ok: true} or { error: 'Error' } `);
608
671
  }
@@ -620,8 +683,8 @@ class AdminForth {
620
683
  yield connector.updateRecord({ resource, recordId, record, newValues });
621
684
  }
622
685
  // execute hook if needed
623
- if ((_3 = (_2 = resource.hooks) === null || _2 === void 0 ? void 0 : _2.edit) === null || _3 === void 0 ? void 0 : _3.afterSave) {
624
- const resp = yield ((_5 = (_4 = resource.hooks) === null || _4 === void 0 ? void 0 : _4.edit) === null || _5 === void 0 ? void 0 : _5.afterSave({ resource, record, adminUser }));
686
+ if ((_8 = (_7 = resource.hooks) === null || _7 === void 0 ? void 0 : _7.edit) === null || _8 === void 0 ? void 0 : _8.afterSave) {
687
+ const resp = yield ((_10 = (_9 = resource.hooks) === null || _9 === void 0 ? void 0 : _9.edit) === null || _10 === void 0 ? void 0 : _10.afterSave({ resource, record, adminUser }));
625
688
  if (!resp || (!resp.ok && !resp.error)) {
626
689
  throw new Error(`Hook afterSave must return object with {ok: true} or { error: 'Error' } `);
627
690
  }
@@ -638,16 +701,16 @@ class AdminForth {
638
701
  noAuth: true, // TODO
639
702
  method: 'POST',
640
703
  path: '/delete_record',
641
- handler: (_6) => __awaiter(this, [_6], void 0, function* ({ body, adminUser }) {
642
- var _7, _8, _9, _10, _11, _12, _13, _14;
704
+ handler: (_11) => __awaiter(this, [_11], void 0, function* ({ body, adminUser }) {
705
+ var _12, _13, _14, _15, _16, _17, _18, _19;
643
706
  const resource = this.config.resources.find((res) => res.resourceId == body['resourceId']);
644
707
  const record = yield this.connectors[resource.dataSource].getRecordByPrimaryKey(resource, body['primaryKey']);
645
708
  if (!resource) {
646
709
  return { error: `Resource '${body['resourceId']}' not found` };
647
710
  }
648
711
  // execute hook if needed
649
- if ((_8 = (_7 = resource.hooks) === null || _7 === void 0 ? void 0 : _7.delete) === null || _8 === void 0 ? void 0 : _8.beforeSave) {
650
- const resp = yield ((_10 = (_9 = resource.hooks) === null || _9 === void 0 ? void 0 : _9.delete) === null || _10 === void 0 ? void 0 : _10.beforeSave({ resource, record, adminUser }));
712
+ if ((_13 = (_12 = resource.hooks) === null || _12 === void 0 ? void 0 : _12.delete) === null || _13 === void 0 ? void 0 : _13.beforeSave) {
713
+ const resp = yield ((_15 = (_14 = resource.hooks) === null || _14 === void 0 ? void 0 : _14.delete) === null || _15 === void 0 ? void 0 : _15.beforeSave({ resource, record, adminUser }));
651
714
  if (!resp || (!resp.ok && !resp.error)) {
652
715
  throw new Error(`Hook beforeSave must return object with {ok: true} or { error: 'Error' } `);
653
716
  }
@@ -658,8 +721,8 @@ class AdminForth {
658
721
  const connector = this.connectors[resource.dataSource];
659
722
  yield connector.deleteRecord({ resource, recordId: body['primaryKey'] });
660
723
  // execute hook if needed
661
- if ((_12 = (_11 = resource.hooks) === null || _11 === void 0 ? void 0 : _11.delete) === null || _12 === void 0 ? void 0 : _12.afterSave) {
662
- const resp = yield ((_14 = (_13 = resource.hooks) === null || _13 === void 0 ? void 0 : _13.delete) === null || _14 === void 0 ? void 0 : _14.afterSave({ resource, record, adminUser }));
724
+ if ((_17 = (_16 = resource.hooks) === null || _16 === void 0 ? void 0 : _16.delete) === null || _17 === void 0 ? void 0 : _17.afterSave) {
725
+ const resp = yield ((_19 = (_18 = resource.hooks) === null || _18 === void 0 ? void 0 : _18.delete) === null || _19 === void 0 ? void 0 : _19.afterSave({ resource, record, adminUser }));
663
726
  if (!resp || (!resp.ok && !resp.error)) {
664
727
  throw new Error(`Hook afterSave must return object with {ok: true} or { error: 'Error' } `);
665
728
  }
@@ -676,7 +739,7 @@ class AdminForth {
676
739
  noAuth: true, // TODO
677
740
  method: 'POST',
678
741
  path: '/start_bulk_action',
679
- handler: (_15) => __awaiter(this, [_15], void 0, function* ({ body }) {
742
+ handler: (_20) => __awaiter(this, [_20], void 0, function* ({ body }) {
680
743
  const { resourceId, actionId, recordIds } = body;
681
744
  const resource = this.config.resources.find((res) => res.resourceId == resourceId);
682
745
  if (!resource) {
@@ -63,9 +63,8 @@ class CodeInjector {
63
63
  rmTmpDir() {
64
64
  return __awaiter(this, void 0, void 0, function* () {
65
65
  // remove spa_tmp folder if it is exists
66
- const spaTmpPath = CodeInjector.SPA_TMP_PATH;
67
66
  try {
68
- yield fs.promises.rm(spaTmpPath, { recursive: true });
67
+ yield fs.promises.rm(CodeInjector.SPA_TMP_PATH, { recursive: true });
69
68
  }
70
69
  catch (e) {
71
70
  // ignore
@@ -74,7 +73,7 @@ class CodeInjector {
74
73
  }
75
74
  prepareSources(_a) {
76
75
  return __awaiter(this, arguments, void 0, function* ({ filesUpdated, verbose = false }) {
77
- var _b, _c, _d;
76
+ var _b, _c, _d, _e, _f, _g;
78
77
  const spaTmpPath = CodeInjector.SPA_TMP_PATH;
79
78
  // check SPA_TMP_PATH exists and create if not
80
79
  try {
@@ -186,23 +185,35 @@ class CodeInjector {
186
185
  }
187
186
  yield fs.promises.writeFile(appVuePath, appVueContent);
188
187
  /* generate custom rotes */
188
+ const homepageMenuItem = this.adminforth.config.menu.find((mi) => mi.homepage);
189
+ let childrenHomePageMenuItem = this.adminforth.config.menu.find((mi) => { var _a; return mi.children && ((_a = mi.children) === null || _a === void 0 ? void 0 : _a.find((mi) => mi.homepage)); });
190
+ let childrenHomepage = (_e = childrenHomePageMenuItem === null || childrenHomePageMenuItem === void 0 ? void 0 : childrenHomePageMenuItem.children) === null || _e === void 0 ? void 0 : _e.find((mi) => mi.homepage);
191
+ let homePagePath = (homepageMenuItem === null || homepageMenuItem === void 0 ? void 0 : homepageMenuItem.path) || `resource/${childrenHomepage === null || childrenHomepage === void 0 ? void 0 : childrenHomepage.resourceId}`;
192
+ if (!homePagePath) {
193
+ homePagePath = ((_f = this.adminforth.config.menu.filter((mi) => mi.path)[0]) === null || _f === void 0 ? void 0 : _f.path) || `resource/${(_g = this.adminforth.config.menu.filter((mi) => mi.children)[0]) === null || _g === void 0 ? void 0 : _g.resourceId}`;
194
+ }
195
+ routes += `{
196
+ path: '/',
197
+ name: 'home',
198
+ //redirect to login
199
+ redirect: '/${homePagePath}'
200
+ },\n`;
189
201
  const routerVuePath = path.join(spaTmpPath, 'src', 'router', 'index.ts');
190
202
  let routerVueContent = yield fs.promises.readFile(routerVuePath, 'utf-8');
191
203
  routerVueContent = routerVueContent.replace('/* IMPORTANT:ADMINFORTH ROUTES */', routes);
192
204
  yield fs.promises.writeFile(routerVuePath, routerVueContent);
193
205
  /* hash checking */
194
- const packageLockPath = path.join(spaTmpPath, 'package-lock.json');
195
- const packageLock = JSON.parse(yield fs.promises.readFile(packageLockPath, 'utf-8'));
196
- const lockHash = hashify(packageLock);
206
+ const spaPackageLockPath = path.join(spaTmpPath, 'package-lock.json');
207
+ const spaPackageLock = JSON.parse(yield fs.promises.readFile(spaPackageLockPath, 'utf-8'));
208
+ const spaLockHash = hashify(spaPackageLock);
197
209
  /* customPackageLock */
198
- const customPackagePath = path.join('./package.json');
199
- const customPackage = JSON.parse(yield fs.promises.readFile(customPackagePath, 'utf-8'));
200
- const customPackageHash = hashify(customPackage);
201
- const customLockPath = path.join('./package-lock.json');
202
- const customLock = JSON.parse(yield fs.promises.readFile(customLockPath, 'utf-8'));
203
- const customLockHash = hashify(customLock);
210
+ const usersPackagePath = path.join('./package.json');
211
+ const usersPackage = JSON.parse(yield fs.promises.readFile(usersPackagePath, 'utf-8'));
212
+ const usersLockPath = path.join('./package-lock.json');
213
+ const usersLock = JSON.parse(yield fs.promises.readFile(usersLockPath, 'utf-8'));
214
+ const usersLockHash = hashify(usersLock);
204
215
  const packagesNamesHash = hashify(packageNames);
205
- const fullHash = hashify([lockHash, packagesNamesHash, customLockHash]);
216
+ const fullHash = `${spaLockHash}::${packagesNamesHash}::${usersLockHash}`;
206
217
  const hashPath = path.join(spaTmpPath, 'node_modules', '.adminforth_hash');
207
218
  try {
208
219
  const existingHash = yield fs.promises.readFile(hashPath, 'utf-8');
@@ -210,14 +221,25 @@ class CodeInjector {
210
221
  console.log('Hashes match, skipping npm ci/install');
211
222
  return;
212
223
  }
224
+ else {
225
+ if (verbose) {
226
+ console.log(`Hashes do not match: existing ${existingHash} new ${fullHash}, proceeding with npm ci/install`);
227
+ }
228
+ }
213
229
  }
214
230
  catch (e) {
215
231
  // ignore
232
+ if (verbose) {
233
+ console.log('Hash file does not exist, proceeding with npm ci/install');
234
+ }
216
235
  }
217
236
  yield this.runNpmShell({ command: 'ci', verbose, cwd: spaTmpPath });
218
237
  // get packages with version from customPackage
219
- const customPackgeNames = [...Object.keys(customPackage.dependencies), ...Object.keys(customPackage.devDependencies || [])].reduce((acc, packageName) => {
220
- const version = customLock.packages[`node_modules/${packageName}`].version;
238
+ const IGNORE_PACKAGES = ['tsx', 'typescript', 'express', 'nodemon'];
239
+ const customPackgeNames = [...Object.keys(usersPackage.dependencies), ...Object.keys(usersPackage.devDependencies || [])]
240
+ .filter((packageName) => !IGNORE_PACKAGES.includes(packageName))
241
+ .reduce((acc, packageName) => {
242
+ const version = usersLock.packages[`node_modules/${packageName}`].version;
221
243
  acc.push(`${packageName}@${version}`);
222
244
  return acc;
223
245
  }, []);
@@ -9,12 +9,15 @@
9
9
  "version": "0.0.0",
10
10
  "dependencies": {
11
11
  "@iconify-prerendered/vue-flowbite": "^0.23.1714023977",
12
+ "@vueuse/core": "^10.10.0",
12
13
  "dayjs": "^1.11.11",
14
+ "debounce": "^2.1.0",
13
15
  "flowbite": "^2.3.0",
14
16
  "flowbite-datepicker": "^1.2.6",
15
17
  "pinia": "^2.1.7",
16
18
  "vue": "^3.4.21",
17
- "vue-router": "^4.3.0"
19
+ "vue-router": "^4.3.0",
20
+ "vue-slider-component": "^4.1.0-beta.7"
18
21
  },
19
22
  "devDependencies": {
20
23
  "@rushstack/eslint-patch": "^1.8.0",
@@ -950,6 +953,11 @@
950
953
  "undici-types": "~5.26.4"
951
954
  }
952
955
  },
956
+ "node_modules/@types/web-bluetooth": {
957
+ "version": "0.0.20",
958
+ "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
959
+ "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
960
+ },
953
961
  "node_modules/@typescript-eslint/eslint-plugin": {
954
962
  "version": "7.9.0",
955
963
  "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.9.0.tgz",
@@ -1330,6 +1338,89 @@
1330
1338
  "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==",
1331
1339
  "dev": true
1332
1340
  },
1341
+ "node_modules/@vueuse/core": {
1342
+ "version": "10.10.0",
1343
+ "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.10.0.tgz",
1344
+ "integrity": "sha512-vexJ/YXYs2S42B783rI95lMt3GzEwkxzC8Hb0Ndpd8rD+p+Lk/Za4bd797Ym7yq4jXqdSyj3JLChunF/vyYjUw==",
1345
+ "dependencies": {
1346
+ "@types/web-bluetooth": "^0.0.20",
1347
+ "@vueuse/metadata": "10.10.0",
1348
+ "@vueuse/shared": "10.10.0",
1349
+ "vue-demi": ">=0.14.7"
1350
+ },
1351
+ "funding": {
1352
+ "url": "https://github.com/sponsors/antfu"
1353
+ }
1354
+ },
1355
+ "node_modules/@vueuse/core/node_modules/vue-demi": {
1356
+ "version": "0.14.8",
1357
+ "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz",
1358
+ "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==",
1359
+ "hasInstallScript": true,
1360
+ "bin": {
1361
+ "vue-demi-fix": "bin/vue-demi-fix.js",
1362
+ "vue-demi-switch": "bin/vue-demi-switch.js"
1363
+ },
1364
+ "engines": {
1365
+ "node": ">=12"
1366
+ },
1367
+ "funding": {
1368
+ "url": "https://github.com/sponsors/antfu"
1369
+ },
1370
+ "peerDependencies": {
1371
+ "@vue/composition-api": "^1.0.0-rc.1",
1372
+ "vue": "^3.0.0-0 || ^2.6.0"
1373
+ },
1374
+ "peerDependenciesMeta": {
1375
+ "@vue/composition-api": {
1376
+ "optional": true
1377
+ }
1378
+ }
1379
+ },
1380
+ "node_modules/@vueuse/metadata": {
1381
+ "version": "10.10.0",
1382
+ "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.10.0.tgz",
1383
+ "integrity": "sha512-UNAo2sTCAW5ge6OErPEHb5z7NEAg3XcO9Cj7OK45aZXfLLH1QkexDcZD77HBi5zvEiLOm1An+p/4b5K3Worpug==",
1384
+ "funding": {
1385
+ "url": "https://github.com/sponsors/antfu"
1386
+ }
1387
+ },
1388
+ "node_modules/@vueuse/shared": {
1389
+ "version": "10.10.0",
1390
+ "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.10.0.tgz",
1391
+ "integrity": "sha512-2aW33Ac0Uk0U+9yo3Ypg9s5KcR42cuehRWl7vnUHadQyFvCktseyxxEPBi1Eiq4D2yBGACOnqLZpx1eMc7g5Og==",
1392
+ "dependencies": {
1393
+ "vue-demi": ">=0.14.7"
1394
+ },
1395
+ "funding": {
1396
+ "url": "https://github.com/sponsors/antfu"
1397
+ }
1398
+ },
1399
+ "node_modules/@vueuse/shared/node_modules/vue-demi": {
1400
+ "version": "0.14.8",
1401
+ "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz",
1402
+ "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==",
1403
+ "hasInstallScript": true,
1404
+ "bin": {
1405
+ "vue-demi-fix": "bin/vue-demi-fix.js",
1406
+ "vue-demi-switch": "bin/vue-demi-switch.js"
1407
+ },
1408
+ "engines": {
1409
+ "node": ">=12"
1410
+ },
1411
+ "funding": {
1412
+ "url": "https://github.com/sponsors/antfu"
1413
+ },
1414
+ "peerDependencies": {
1415
+ "@vue/composition-api": "^1.0.0-rc.1",
1416
+ "vue": "^3.0.0-0 || ^2.6.0"
1417
+ },
1418
+ "peerDependenciesMeta": {
1419
+ "@vue/composition-api": {
1420
+ "optional": true
1421
+ }
1422
+ }
1423
+ },
1333
1424
  "node_modules/acorn": {
1334
1425
  "version": "8.11.3",
1335
1426
  "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
@@ -1716,6 +1807,17 @@
1716
1807
  "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
1717
1808
  "dev": true
1718
1809
  },
1810
+ "node_modules/debounce": {
1811
+ "version": "2.1.0",
1812
+ "resolved": "https://registry.npmjs.org/debounce/-/debounce-2.1.0.tgz",
1813
+ "integrity": "sha512-OkL3+0pPWCqoBc/nhO9u6TIQNTK44fnBnzuVtJAbp13Naxw9R6u21x+8tVTka87AhDZ3htqZ2pSSsZl9fqL2Wg==",
1814
+ "engines": {
1815
+ "node": ">=18"
1816
+ },
1817
+ "funding": {
1818
+ "url": "https://github.com/sponsors/sindresorhus"
1819
+ }
1820
+ },
1719
1821
  "node_modules/debug": {
1720
1822
  "version": "4.3.4",
1721
1823
  "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -3970,6 +4072,11 @@
3970
4072
  "vue": "^3.2.0"
3971
4073
  }
3972
4074
  },
4075
+ "node_modules/vue-slider-component": {
4076
+ "version": "4.1.0-beta.7",
4077
+ "resolved": "https://registry.npmjs.org/vue-slider-component/-/vue-slider-component-4.1.0-beta.7.tgz",
4078
+ "integrity": "sha512-Qb7K920ZG7PoQswoF6Ias+i3W2rd3k4fpk04JUl82kEUcN86Yg6et7bVSKWt/7VpQe8a5IT3BqCKSCOZ7AJgCA=="
4079
+ },
3973
4080
  "node_modules/vue-template-compiler": {
3974
4081
  "version": "2.7.16",
3975
4082
  "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz",
@@ -13,12 +13,15 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "@iconify-prerendered/vue-flowbite": "^0.23.1714023977",
16
+ "@vueuse/core": "^10.10.0",
16
17
  "dayjs": "^1.11.11",
18
+ "debounce": "^2.1.0",
17
19
  "flowbite": "^2.3.0",
18
20
  "flowbite-datepicker": "^1.2.6",
19
21
  "pinia": "^2.1.7",
20
22
  "vue": "^3.4.21",
21
- "vue-router": "^4.3.0"
23
+ "vue-router": "^4.3.0",
24
+ "vue-slider-component": "^4.1.0-beta.7"
22
25
  },
23
26
  "devDependencies": {
24
27
  "@rushstack/eslint-patch": "^1.8.0",
@@ -32,7 +32,7 @@
32
32
 
33
33
  </button>
34
34
  </div>
35
- <div class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded shadow dark:bg-gray-700 dark:divide-gray-600 dark:shadow-xl" id="dropdown-user">
35
+ <div class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded shadow dark:shadow-black dark:bg-gray-700 dark:divide-gray-600 dark:shadow-black" id="dropdown-user">
36
36
  <div class="px-4 py-3" role="none">
37
37
  <p class="text-sm text-gray-900 dark:text-white" role="none" v-if="coreStore.userFullname">
38
38
  {{ coreStore.userFullname }}
@@ -112,7 +112,7 @@
112
112
  </div>
113
113
  </div>
114
114
 
115
- <div v-else>
115
+ <div v-else-if="routerIsReady">
116
116
  <RouterView/>
117
117
  </div>
118
118
  <AcceptModal />
@@ -141,6 +141,10 @@ const routerIsReady = ref(false);
141
141
 
142
142
  const loggedIn = computed(() => route.name !== 'login' && routerIsReady.value);
143
143
 
144
+ watch(loggedIn, (value) => {
145
+ console.log('🔻🔻🔻 loggedIn', value);
146
+ });
147
+
144
148
  const theme = ref('light');
145
149
 
146
150
  function toggleTheme() {
@@ -16,7 +16,7 @@ const modalStore = useModalStore();
16
16
  <Teleport to="body">
17
17
  <div v-if="modalStore.isOpened" class="bg-gray-900/50 dark:bg-gray-900/80 overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
18
18
  <div class="relative p-4 w-full max-w-md max-h-full top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 " >
19
- <div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
19
+ <div class="relative bg-white rounded-lg shadow dark:bg-gray-700 dark:shadow-black">
20
20
  <button type="button"@click="modalStore.togleModal" class="absolute top-3 end-2.5 text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white" >
21
21
  <svg class="w-3 h-3" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
22
22
  <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
@@ -0,0 +1,143 @@
1
+ <template>
2
+ <div class="flex flex-wrap gap-2">
3
+ <input
4
+ type="number" aria-describedby="helper-text-explanation"
5
+ class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-20 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
6
+ placeholder="From"
7
+ v-model="start"
8
+ >
9
+
10
+ <input
11
+ type="number" aria-describedby="helper-text-explanation"
12
+ class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-20 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
13
+ placeholder="To"
14
+ v-model="end"
15
+ >
16
+
17
+ <button
18
+ v-if="isChanged"
19
+ type="button"
20
+ class="flex items-center p-0.5 ml-auto px-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
21
+ @click="clear">Clear
22
+ </button>
23
+
24
+ <div class="w-full">
25
+ <vue-slider
26
+ class="custom-slider"
27
+ :dot-size="20"
28
+ height="7.99px"
29
+ :min="minFormatted"
30
+ :max="maxFormatted"
31
+ v-model="sliderValue"
32
+ @update:model-value="updateFromSlider($event)"
33
+ />
34
+ </div>
35
+ </div>
36
+ </template>
37
+ <script setup lang="ts">
38
+ import VueSlider from 'vue-slider-component';
39
+ import 'vue-slider-component/theme/antd.css'
40
+ import {computed, onMounted, ref, watch} from "vue";
41
+ import debounce from 'debounce'
42
+
43
+ const props = defineProps({
44
+ valueStart: {
45
+ default: 0,
46
+ },
47
+ valueEnd: {
48
+ default: 10,
49
+ },
50
+ min: {
51
+ default: 0,
52
+ },
53
+ max: {
54
+ default: 10,
55
+ },
56
+ });
57
+
58
+ const emit = defineEmits(['update:valueStart', 'update:valueEnd']);
59
+
60
+ const minFormatted = computed(() => Math.floor(props.min));
61
+ const maxFormatted = computed(() => Math.ceil(props.max));
62
+
63
+ const isChanged = computed(() => {
64
+ return start.value !== minFormatted.value || end.value !== maxFormatted.value;
65
+ });
66
+
67
+ const start = ref(minFormatted.value);
68
+ const end = ref(maxFormatted.value);
69
+
70
+ const sliderValue = ref([start.value, end.value]);
71
+
72
+ const updateFromSlider =
73
+ debounce((value: [number, number]) => {
74
+ start.value = value[0];
75
+ end.value = value[1];
76
+ }, 500);
77
+
78
+ function updateFromProps() {
79
+ if (props.valueStart || props.valueEnd) {
80
+ setFromProps(props.valueStart, props.valueEnd)
81
+ } else {
82
+ clear();
83
+ }
84
+ }
85
+
86
+ onMounted(() => {
87
+ updateFromProps();
88
+
89
+ watch(() => [props.valueStart, props.valueEnd], (value) => {
90
+ updateFromProps();
91
+ });
92
+ })
93
+
94
+ watch(start, () => {
95
+ //console.log('⚡ emit', start.value)
96
+ emit('update:valueStart', start.value)
97
+ })
98
+
99
+ watch(end, () => {
100
+ //console.log('⚡ emit', end.value)
101
+ emit('update:valueEnd', end.value);
102
+ })
103
+
104
+ const clear = () => {
105
+ start.value = minFormatted.value;
106
+ end.value = maxFormatted.value;
107
+ sliderValue.value = [start.value, end.value]
108
+ }
109
+
110
+ function setFromProps(startValue: number, endValue: number) {
111
+ start.value = startValue ? startValue : minFormatted.value
112
+ end.value = endValue ? endValue : maxFormatted.value
113
+ sliderValue.value = [start.value, end.value]
114
+ }
115
+ </script>
116
+
117
+ <style lang="scss" scoped>
118
+ .custom-slider {
119
+ &:deep(.vue-slider-rail) {
120
+ background-color: rgb(229 231 235);
121
+ }
122
+
123
+ &:deep(.vue-slider-dot-handle) {
124
+ background-color: #1c64f2;
125
+ border: none;
126
+ box-shadow: none;
127
+ }
128
+
129
+ &:deep(.vue-slider-dot-handle:hover) {
130
+ background-color: #1c64f2;
131
+ border: none;
132
+ box-shadow: none;
133
+ }
134
+
135
+ &:deep(.vue-slider-process) {
136
+ background-color: rgb(225 239 254);
137
+ }
138
+
139
+ &:deep(.vue-slider-process:hover) {
140
+ background-color: rgb(225 239 254);
141
+ }
142
+ }
143
+ </style>