adminforth 1.0.73 → 1.0.75

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.
@@ -29,10 +29,29 @@ function hashify(obj) {
29
29
  return crypto.createHash('sha256').update(JSON.stringify(obj)).digest('hex');
30
30
  }
31
31
  class CodeInjector {
32
+ cleanup() {
33
+ console.log('Cleaning up...');
34
+ this.allWatchers.forEach((watcher) => {
35
+ watcher.removeAll();
36
+ });
37
+ }
32
38
  constructor(adminforth) {
39
+ this.allWatchers = [];
33
40
  this.allComponentNames = {};
34
41
  this.srcFoldersToSync = {};
35
42
  this.adminforth = adminforth;
43
+ process.on('SIGINT', () => {
44
+ console.log('Received SIGINT.');
45
+ this.cleanup();
46
+ });
47
+ process.on('SIGTERM', () => {
48
+ console.log('Received SIGTERM.');
49
+ this.cleanup();
50
+ });
51
+ process.on('exit', () => {
52
+ console.log('Exiting.');
53
+ this.cleanup();
54
+ });
36
55
  }
37
56
  // async runShell({command, verbose = false}) {
38
57
  // console.log(`⚙️ Running shell ${command}...`);
@@ -144,7 +163,10 @@ class CodeInjector {
144
163
  yield Promise.all(filesUpdated.map((file) => __awaiter(this, void 0, void 0, function* () {
145
164
  const src = path.join(ADMIN_FORTH_ABSOLUTE_PATH, 'spa', file);
146
165
  const dest = path.join(CodeInjector.SPA_TMP_PATH, file);
147
- yield fsExtra.copy(src, dest);
166
+ yield fsExtra.copy(src, dest, {
167
+ overwrite: true,
168
+ dereference: true, // needed to dereference types
169
+ });
148
170
  if (process.env.HEAVY_DEBUG) {
149
171
  console.log('🪲 await fsExtra.copy filtering', src, dest);
150
172
  }
@@ -154,6 +176,13 @@ class CodeInjector {
154
176
  if (process.env.HEAVY_DEBUG) {
155
177
  console.log(`🪲 await fsExtra.copy from ${path.join(ADMIN_FORTH_ABSOLUTE_PATH, 'spa')}, ${CodeInjector.SPA_TMP_PATH}`);
156
178
  }
179
+ // try to rm SPA_TMP_PATH/src/types directory
180
+ try {
181
+ yield fs.promises.rm(path.join(CodeInjector.SPA_TMP_PATH, 'src', 'types'), { recursive: true });
182
+ }
183
+ catch (e) {
184
+ // ignore
185
+ }
157
186
  yield fsExtra.copy(path.join(ADMIN_FORTH_ABSOLUTE_PATH, 'spa'), CodeInjector.SPA_TMP_PATH, {
158
187
  filter: (src) => {
159
188
  if (process.env.HEAVY_DEBUG) {
@@ -162,6 +191,7 @@ class CodeInjector {
162
191
  return !src.includes('/adminforth/spa/node_modules') && !src.includes('/adminforth/spa/dist');
163
192
  },
164
193
  overwrite: true,
194
+ dereference: true, // needed to dereference types
165
195
  });
166
196
  // copy whole custom directory
167
197
  if ((_b = this.adminforth.config.customization) === null || _b === void 0 ? void 0 : _b.customComponentsDir) {
@@ -358,9 +388,7 @@ class CodeInjector {
358
388
  console.log(`File ${file} changed, preparing sources...`);
359
389
  yield this.prepareSources({ filesUpdated: [file.replace(spaPath + '/', '')] });
360
390
  }));
361
- process.on('exit', () => {
362
- watcher.removeAll();
363
- });
391
+ this.allWatchers.push(watcher);
364
392
  });
365
393
  }
366
394
  watchCustomComponentsForCopy(_a) {
@@ -405,9 +433,7 @@ class CodeInjector {
405
433
  recursive: true,
406
434
  });
407
435
  }));
408
- process.on('exit', () => {
409
- watcher.removeAll();
410
- });
436
+ this.allWatchers.push(watcher);
411
437
  });
412
438
  }
413
439
  bundleNow(_a) {
@@ -11,6 +11,7 @@ import path from 'path';
11
11
  import { fileURLToPath } from 'url';
12
12
  import fs from 'fs';
13
13
  import CodeInjector from '../modules/codeInjector.js';
14
+ import fetch from 'node-fetch';
14
15
  const __filename = fileURLToPath(import.meta.url);
15
16
  const __dirname = path.dirname(__filename);
16
17
  function replaceAtStart(string, substring) {
@@ -21,13 +22,9 @@ function replaceAtStart(string, substring) {
21
22
  }
22
23
  function proxyTo(url, res) {
23
24
  return __awaiter(this, void 0, void 0, function* () {
24
- const r = yield fetch(url);
25
- const body = yield r.text();
26
- res.status(r.status);
27
- r.headers.forEach((value, name) => {
28
- res.setHeader(name, value);
29
- });
30
- res.send(body);
25
+ const actual = yield fetch(url);
26
+ actual.headers.forEach((v, n) => res.setHeader(n, v));
27
+ actual.body.pipe(res);
31
28
  });
32
29
  }
33
30
  function parseExpressCookie(req) {
@@ -93,11 +90,12 @@ class ExpressServer {
93
90
  const slashedPrefix = prefix.endsWith('/') ? prefix : `${prefix}/`;
94
91
  if (this.adminforth.runningHotReload) {
95
92
  const handler = (req, res) => __awaiter(this, void 0, void 0, function* () {
96
- // proxy using fetch to webpack dev server
93
+ // proxy using fetch to webpack dev server
97
94
  try {
98
95
  yield proxyTo(`http://localhost:5173${req.url}`, res);
99
96
  }
100
97
  catch (e) {
98
+ // console.log('Failed to proxy', e);
101
99
  res.status(500).send(respondNoServer('AdminForth SPA is not ready yet', 'Vite is still starting up. Please wait a moment...'));
102
100
  return;
103
101
  }
@@ -9,7 +9,7 @@ import router from './router'
9
9
  const app = createApp(App)
10
10
  /* IMPORTANT:ADMINFORTH COMPONENT REGISTRATIONS */
11
11
 
12
-
12
+
13
13
  app.use(createPinia())
14
14
  app.use(router)
15
15
 
@@ -1,6 +1,7 @@
1
1
  import { onMounted, ref, resolveComponent } from 'vue';
2
2
 
3
3
  import router from "./router";
4
+ import { useCoreStore } from './stores/core';
4
5
 
5
6
  export async function callApi({path, method, body=undefined} ) {
6
7
  const options = {
@@ -62,3 +63,13 @@ export const loadFile = (file: string) => {
62
63
  }
63
64
  return baseUrl;
64
65
  }
66
+
67
+ // export function checkEmptyValues(value: any, viewType:'show' | 'list' | 'create' | 'edit') {
68
+ // const config: = useCoreStore().config;
69
+ // const emptyFieldPlaceholder = config.emptyFieldPlaceholder?.[viewType] || '---';
70
+
71
+ // if (value === null || value === undefined || value === '') {
72
+ // return emptyFieldPlaceholder;
73
+ // }
74
+ // return value;
75
+ // }
@@ -7,7 +7,8 @@
7
7
  'background-blend-mode': 'darken'
8
8
  }: {}"
9
9
  >
10
- <!-- Main modal -->
10
+
11
+ <!-- Main modal -->
11
12
  <div id="authentication-modal" tabindex="-1" class=" overflow-y-auto overflow-x-hidden z-50 min-w-[400px] justify-center items-center md:inset-0 h-[calc(100%-1rem)] max-h-full">
12
13
  <div class="relative p-4 w-full max-w-md max-h-full">
13
14
  <!-- Modal content -->
@@ -78,13 +79,14 @@
78
79
 
79
80
  <script setup>
80
81
 
81
- import { onMounted, ref } from 'vue';
82
+ import { onMounted, ref, watchEffect } from 'vue';
82
83
  import { useCoreStore } from '@/stores/core';
83
84
  import { IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbite';
84
85
  import { callAdminForthApi, loadFile } from '@/utils';
85
86
  import { useRouter } from 'vue-router';
86
87
  import { initFlowbite } from 'flowbite'
87
88
 
89
+
88
90
  const router = useRouter();
89
91
  const inProgress = ref(false);
90
92
 
@@ -114,6 +116,7 @@ async function login() {
114
116
  } else {
115
117
  error.value = null;
116
118
  router.push('/');
119
+ await router.isReady();
117
120
  await coreStore.fetchMenuAndResource();
118
121
  setTimeout(() => {
119
122
  initFlowbite();
@@ -1 +1,33 @@
1
- export {};
1
+ export var AdminForthDataTypes;
2
+ (function (AdminForthDataTypes) {
3
+ AdminForthDataTypes["STRING"] = "string";
4
+ AdminForthDataTypes["INTEGER"] = "integer";
5
+ AdminForthDataTypes["FLOAT"] = "float";
6
+ AdminForthDataTypes["DECIMAL"] = "decimal";
7
+ AdminForthDataTypes["BOOLEAN"] = "boolean";
8
+ AdminForthDataTypes["DATE"] = "date";
9
+ AdminForthDataTypes["DATETIME"] = "datetime";
10
+ AdminForthDataTypes["TIME"] = "time";
11
+ AdminForthDataTypes["TEXT"] = "text";
12
+ AdminForthDataTypes["JSON"] = "json";
13
+ })(AdminForthDataTypes || (AdminForthDataTypes = {}));
14
+ export var AdminForthFilterOperators;
15
+ (function (AdminForthFilterOperators) {
16
+ AdminForthFilterOperators["EQ"] = "eq";
17
+ AdminForthFilterOperators["NE"] = "ne";
18
+ AdminForthFilterOperators["GT"] = "gt";
19
+ AdminForthFilterOperators["LT"] = "lt";
20
+ AdminForthFilterOperators["GTE"] = "gte";
21
+ AdminForthFilterOperators["LTE"] = "lte";
22
+ AdminForthFilterOperators["LIKE"] = "like";
23
+ AdminForthFilterOperators["ILIKE"] = "ilike";
24
+ AdminForthFilterOperators["IN"] = "in";
25
+ AdminForthFilterOperators["NIN"] = "nin";
26
+ })(AdminForthFilterOperators || (AdminForthFilterOperators = {}));
27
+ ;
28
+ export var AdminForthSortDirections;
29
+ (function (AdminForthSortDirections) {
30
+ AdminForthSortDirections["ASC"] = "asc";
31
+ AdminForthSortDirections["DESC"] = "desc";
32
+ })(AdminForthSortDirections || (AdminForthSortDirections = {}));
33
+ ;
package/index.ts CHANGED
@@ -9,9 +9,9 @@ import ExpressServer from './servers/express.js';
9
9
  import {v1 as uuid} from 'uuid';
10
10
  import fs from 'fs';
11
11
  import { ADMINFORTH_VERSION } from './modules/utils.js';
12
- import { AdminForthFilterOperators, AdminForthTypes, AdminForthTypesValues } from './types.js';
13
- import { AdminForthConfig } from './types/AdminForthConfig.js';
12
+ import { AdminForthConfig, AdminForthClass, AdminForthFilterOperators, AdminForthDataTypes } from './types/AdminForthConfig.js';
14
13
  import { getFunctionList } from './modules/utils.js';
14
+ import path from 'path';
15
15
 
16
16
  const AVAILABLE_SHOW_IN = ['list', 'edit', 'create', 'filter', 'show'];
17
17
  const DEFAULT_ALLOWED_ACTIONS = {create: true, edit: true, show: true, delete: true};
@@ -22,9 +22,8 @@ type ValidationObject = {
22
22
  message: string,
23
23
  }
24
24
 
25
- class AdminForth {
26
- static Types = AdminForthTypes;
27
-
25
+ class AdminForth implements AdminForthClass {
26
+ static Types = AdminForthDataTypes;
28
27
 
29
28
  static Utils = {
30
29
  generatePasswordHash: async (password) => {
@@ -48,7 +47,6 @@ class AdminForth {
48
47
  dbDiscover?: 'running' | 'done',
49
48
  }
50
49
 
51
-
52
50
  constructor(config: AdminForthConfig) {
53
51
  this.config = {...this.#defaultConfig,...config};
54
52
  this.codeInjector = new CodeInjector(this);
@@ -72,7 +70,19 @@ class AdminForth {
72
70
  };
73
71
  }
74
72
 
73
+ checkCustomFileExists(filePath: string): Array<string> {
74
+ if (filePath.startsWith('@@/')) {
75
+ const checkPath = path.join(this.config.customization.customComponentsDir, filePath.replace('@@/', ''));
76
+ if (!fs.existsSync(checkPath)) {
77
+ return [`File file ${filePath} does not exist in ${this.config.customization.customComponentsDir}`];
78
+ }
79
+ }
80
+ return [];
81
+ }
82
+
75
83
  validateConfig() {
84
+ const errors = [];
85
+
76
86
  if (this.config.rootUser) {
77
87
  if (!this.config.rootUser.username) {
78
88
  throw new Error('rootUser.username is required');
@@ -91,6 +101,12 @@ class AdminForth {
91
101
  if (!this.config.auth.passwordHashField) {
92
102
  throw new Error('No config.auth.passwordHashField defined');
93
103
  }
104
+ if (!this.config.auth.usernameField) {
105
+ throw new Error('No config.auth.usernameField defined');
106
+ }
107
+ if (this.config.auth.loginBackgroundImage) {
108
+ errors.push(...this.checkCustomFileExists(this.config.auth.loginBackgroundImage));
109
+ }
94
110
  const userResource = this.config.resources.find((res) => res.resourceId === this.config.auth.resourceId);
95
111
  if (!userResource) {
96
112
  throw new Error(`Resource with id "${this.config.auth.resourceId}" not found`);
@@ -106,7 +122,6 @@ class AdminForth {
106
122
  }
107
123
 
108
124
 
109
- const errors = [];
110
125
  if (!this.config.baseUrl) {
111
126
  this.config.baseUrl = '';
112
127
  }
@@ -114,10 +129,7 @@ class AdminForth {
114
129
  this.config.customization.brandName = 'AdminForth';
115
130
  }
116
131
  if (this.config.customization.brandLogo) {
117
- if (!this.config.customization.brandLogo.startsWith('@@/')) {
118
- errors.push(`Brand logo must start with @@ and be placed in custom directory`);
119
- }
120
- // todo check file exist
132
+ errors.push(...this.checkCustomFileExists(this.config.customization.brandLogo));
121
133
  }
122
134
 
123
135
 
@@ -422,6 +434,17 @@ class AdminForth {
422
434
  throw new Error('No config.auth defined');
423
435
  }
424
436
  const userResource = this.config.resources.find((res) => res.resourceId === this.config.auth.resourceId);
437
+ // if there is no passwordHashField, in columns, add it, with backendOnly and showIn: []
438
+ if (!userResource.dataSourceColumns.find((col) => col.name === this.config.auth.passwordHashField)) {
439
+ userResource.dataSourceColumns.push({
440
+ name: this.config.auth.passwordHashField,
441
+ backendOnly: true,
442
+ showIn: [],
443
+ type: AdminForth.Types.STRING,
444
+ });
445
+ console.log('Adding passwordHashField to userResource', userResource)
446
+ }
447
+
425
448
  const userRecord = (
426
449
  await this.connectors[userResource.dataSource].getData({
427
450
  resource: userResource,
@@ -775,12 +798,12 @@ class AdminForth {
775
798
  const item = await this.connectors[resource.dataSource].getMinMaxForColumns({
776
799
  resource,
777
800
  columns: resource.columns.filter((col) => [
778
- AdminForthTypes.INTEGER,
779
- AdminForthTypes.FLOAT,
780
- AdminForthTypes.DATE,
781
- AdminForthTypes.DATETIME,
782
- AdminForthTypes.TIME,
783
- AdminForthTypes.DECIMAL,
801
+ AdminForthDataTypes.INTEGER,
802
+ AdminForthDataTypes.FLOAT,
803
+ AdminForthDataTypes.DATE,
804
+ AdminForthDataTypes.DATETIME,
805
+ AdminForthDataTypes.TIME,
806
+ AdminForthDataTypes.DECIMAL,
784
807
  ].includes(col.type) && col.allowMinMaxQuery === true),
785
808
  });
786
809
  return item;
@@ -11,6 +11,7 @@ import { ADMIN_FORTH_ABSOLUTE_PATH } from './utils.js';
11
11
  import { getComponentNameFromPath } from './utils.js';
12
12
 
13
13
 
14
+
14
15
  let TMP_DIR;
15
16
 
16
17
  try {
@@ -29,14 +30,36 @@ function hashify(obj) {
29
30
 
30
31
  class CodeInjector {
31
32
 
33
+ allWatchers = [];
32
34
  adminforth: AdminForth;
33
35
  allComponentNames: { [key: string]: string } = {};
34
36
  srcFoldersToSync: { [key: string]: string } = {};
35
37
 
36
38
  static SPA_TMP_PATH = path.join(TMP_DIR, 'adminforth', 'spa_tmp');
37
39
 
40
+ cleanup() {
41
+ console.log('Cleaning up...');
42
+ this.allWatchers.forEach((watcher) => {
43
+ watcher.removeAll();
44
+ });
45
+ }
38
46
  constructor(adminforth) {
39
47
  this.adminforth = adminforth;
48
+
49
+ process.on('SIGINT', () => {
50
+ console.log('Received SIGINT.');
51
+ this.cleanup();
52
+ });
53
+
54
+ process.on('SIGTERM', () => {
55
+ console.log('Received SIGTERM.');
56
+ this.cleanup();
57
+ });
58
+
59
+ process.on('exit', () => {
60
+ console.log('Exiting.');
61
+ this.cleanup();
62
+ });
40
63
  }
41
64
 
42
65
  // async runShell({command, verbose = false}) {
@@ -153,7 +176,11 @@ class CodeInjector {
153
176
  await Promise.all(filesUpdated.map(async (file) => {
154
177
  const src = path.join(ADMIN_FORTH_ABSOLUTE_PATH, 'spa', file);
155
178
  const dest = path.join(CodeInjector.SPA_TMP_PATH, file);
156
- await fsExtra.copy(src, dest);
179
+
180
+ await fsExtra.copy(src, dest, {
181
+ overwrite: true,
182
+ dereference: true, // needed to dereference types
183
+ });
157
184
  if (process.env.HEAVY_DEBUG) {
158
185
  console.log('🪲 await fsExtra.copy filtering', src, dest);
159
186
  }
@@ -164,6 +191,13 @@ class CodeInjector {
164
191
  console.log(`🪲 await fsExtra.copy from ${path.join(ADMIN_FORTH_ABSOLUTE_PATH, 'spa')}, ${CodeInjector.SPA_TMP_PATH}`);
165
192
  }
166
193
 
194
+ // try to rm SPA_TMP_PATH/src/types directory
195
+ try {
196
+ await fs.promises.rm(path.join(CodeInjector.SPA_TMP_PATH, 'src', 'types'), { recursive: true });
197
+ } catch (e) {
198
+ // ignore
199
+ }
200
+
167
201
  await fsExtra.copy(path.join(ADMIN_FORTH_ABSOLUTE_PATH, 'spa'), CodeInjector.SPA_TMP_PATH, {
168
202
  filter: (src) => {
169
203
  if (process.env.HEAVY_DEBUG) {
@@ -173,6 +207,7 @@ class CodeInjector {
173
207
  return !src.includes('/adminforth/spa/node_modules') && !src.includes('/adminforth/spa/dist');
174
208
  },
175
209
  overwrite: true,
210
+ dereference: true, // needed to dereference types
176
211
  });
177
212
 
178
213
  // copy whole custom directory
@@ -416,9 +451,7 @@ async watchForReprepare({ verbose }) {
416
451
  await this.prepareSources({ filesUpdated: [file.replace(spaPath + '/', '')] });
417
452
  }
418
453
  )
419
- process.on('exit', () => {
420
- watcher.removeAll();
421
- });
454
+ this.allWatchers.push(watcher);
422
455
  }
423
456
 
424
457
  async watchCustomComponentsForCopy({ verbose }) {
@@ -471,9 +504,7 @@ async watchForReprepare({ verbose }) {
471
504
  });
472
505
  }
473
506
  )
474
- process.on('exit', () => {
475
- watcher.removeAll();
476
- });
507
+ this.allWatchers.push(watcher);
477
508
  }
478
509
 
479
510
  async bundleNow({hotReload = false, verbose = false}: {hotReload: boolean, verbose: boolean}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "1.0.73",
3
+ "version": "1.0.75",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -23,6 +23,7 @@
23
23
  "jsonwebtoken": "^9.0.2",
24
24
  "mongodb": "6.6",
25
25
  "pg": "^8.11.5",
26
+ "request": "^2.88.2",
26
27
  "uuid": "^9.0.1"
27
28
  },
28
29
  "devDependencies": {
package/plugins/base.ts CHANGED
@@ -1,13 +1,12 @@
1
- import { AdminForthResource } from '../types/AdminForthConfig.js';
2
- import AdminForth from '../index.js';
1
+ import { AdminForthResource, AdminForthPluginType, AdminForthClass } from '../types/AdminForthConfig.js';
3
2
  import { getComponentNameFromPath } from '../modules/utils.js';
4
3
  import { currentFileDir } from '../modules/utils.js';
5
4
  import path from 'path';
6
5
  import fs from 'fs';
7
6
 
8
- export default class AdminForthPlugin {
7
+ export default class AdminForthPlugin implements AdminForthPluginType {
9
8
 
10
- adminforth: AdminForth;
9
+ adminforth: AdminForthClass;
11
10
  pluginDir: string;
12
11
  customFolderName: string = 'custom';
13
12
 
@@ -16,7 +15,7 @@ export default class AdminForthPlugin {
16
15
  this.pluginDir = currentFileDir(metaUrl);
17
16
  }
18
17
 
19
- modifyResourceConfig(adminforth: AdminForth, resourceConfig: AdminForthResource) {
18
+ modifyResourceConfig(adminforth: AdminForthClass, resourceConfig: AdminForthResource) {
20
19
  this.adminforth = adminforth;
21
20
  }
22
21
 
@@ -5,6 +5,7 @@ import fs from 'fs';
5
5
  import CodeInjector from '../modules/codeInjector.js';
6
6
  import AdminForth from '../index.js';
7
7
  import { Express } from 'express';
8
+ import fetch from 'node-fetch';
8
9
 
9
10
  const __filename = fileURLToPath(import.meta.url);
10
11
  const __dirname = path.dirname(__filename);
@@ -19,13 +20,9 @@ function replaceAtStart(string, substring) {
19
20
  }
20
21
 
21
22
  async function proxyTo(url, res) {
22
- const r = await fetch(url);
23
- const body = await r.text();
24
- res.status(r.status);
25
- r.headers.forEach((value, name) => {
26
- res.setHeader(name, value);
27
- });
28
- res.send(body);
23
+ const actual = await fetch(url);
24
+ actual.headers.forEach((v, n) => res.setHeader(n, v));
25
+ actual.body.pipe(res);
29
26
  }
30
27
 
31
28
  async function parseExpressCookie(req) {
@@ -99,13 +96,14 @@ class ExpressServer {
99
96
 
100
97
  if (this.adminforth.runningHotReload) {
101
98
  const handler = async (req, res) => {
102
- // proxy using fetch to webpack dev server
99
+ // proxy using fetch to webpack dev server
103
100
  try {
104
101
  await proxyTo(`http://localhost:5173${req.url}`, res);
105
102
  } catch (e) {
103
+ // console.log('Failed to proxy', e);
106
104
  res.status(500).send(respondNoServer('AdminForth SPA is not ready yet', 'Vite is still starting up. Please wait a moment...'));
107
105
  return;
108
- }
106
+ }
109
107
  }
110
108
  this.expressApp.get(`${slashedPrefix}assets/*`, handler);
111
109
  this.expressApp.get(`${prefix}*`, handler);
package/spa/src/main.ts CHANGED
@@ -9,7 +9,7 @@ import router from './router'
9
9
  const app = createApp(App)
10
10
  /* IMPORTANT:ADMINFORTH COMPONENT REGISTRATIONS */
11
11
 
12
-
12
+
13
13
  app.use(createPinia())
14
14
  app.use(router)
15
15
 
package/spa/src/utils.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { onMounted, ref, resolveComponent } from 'vue';
2
2
 
3
3
  import router from "./router";
4
+ import { useCoreStore } from './stores/core';
4
5
 
5
6
  export async function callApi({path, method, body=undefined} ) {
6
7
  const options = {
@@ -62,3 +63,13 @@ export const loadFile = (file: string) => {
62
63
  }
63
64
  return baseUrl;
64
65
  }
66
+
67
+ // export function checkEmptyValues(value: any, viewType:'show' | 'list' | 'create' | 'edit') {
68
+ // const config: = useCoreStore().config;
69
+ // const emptyFieldPlaceholder = config.emptyFieldPlaceholder?.[viewType] || '---';
70
+
71
+ // if (value === null || value === undefined || value === '') {
72
+ // return emptyFieldPlaceholder;
73
+ // }
74
+ // return value;
75
+ // }
@@ -7,7 +7,8 @@
7
7
  'background-blend-mode': 'darken'
8
8
  }: {}"
9
9
  >
10
- <!-- Main modal -->
10
+
11
+ <!-- Main modal -->
11
12
  <div id="authentication-modal" tabindex="-1" class=" overflow-y-auto overflow-x-hidden z-50 min-w-[400px] justify-center items-center md:inset-0 h-[calc(100%-1rem)] max-h-full">
12
13
  <div class="relative p-4 w-full max-w-md max-h-full">
13
14
  <!-- Modal content -->
@@ -78,13 +79,14 @@
78
79
 
79
80
  <script setup>
80
81
 
81
- import { onMounted, ref } from 'vue';
82
+ import { onMounted, ref, watchEffect } from 'vue';
82
83
  import { useCoreStore } from '@/stores/core';
83
84
  import { IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbite';
84
85
  import { callAdminForthApi, loadFile } from '@/utils';
85
86
  import { useRouter } from 'vue-router';
86
87
  import { initFlowbite } from 'flowbite'
87
88
 
89
+
88
90
  const router = useRouter();
89
91
  const inProgress = ref(false);
90
92
 
@@ -114,6 +116,7 @@ async function login() {
114
116
  } else {
115
117
  error.value = null;
116
118
  router.push('/');
119
+ await router.isReady();
117
120
  await coreStore.fetchMenuAndResource();
118
121
  setTimeout(() => {
119
122
  initFlowbite();