adminforth 1.0.76 → 1.0.78

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
@@ -73,6 +73,9 @@ class AdminForth {
73
73
  }
74
74
  console.log('\n ⚠️⚠️⚠️ [INSECURE ALERT] config.rootUser is set, please create a new user and remove config.rootUser from config before going to production\n');
75
75
  }
76
+ if (!this.config.customization.customComponentsDir) {
77
+ this.config.customization.customComponentsDir = './custom';
78
+ }
76
79
  if (this.config.auth) {
77
80
  if (!this.config.auth.resourceId) {
78
81
  throw new Error('No config.auth.resourceId defined');
@@ -94,9 +97,6 @@ class AdminForth {
94
97
  if (!this.config.customization) {
95
98
  this.config.customization = {};
96
99
  }
97
- if (!this.config.customization.customComponentsDir) {
98
- this.config.customization.customComponentsDir = './custom';
99
- }
100
100
  if (!this.config.baseUrl) {
101
101
  this.config.baseUrl = '';
102
102
  }
@@ -484,7 +484,7 @@ class AdminForth {
484
484
  auth: this.config.auth,
485
485
  usernameField: this.config.auth.usernameField,
486
486
  title: (_h = this.config.customization) === null || _h === void 0 ? void 0 : _h.title,
487
- emtyFieldPlaceholder: (_j = this.config.customization) === null || _j === void 0 ? void 0 : _j.emtyFieldPlaceholder,
487
+ emptyFieldPlaceholder: (_j = this.config.customization) === null || _j === void 0 ? void 0 : _j.emptyFieldPlaceholder,
488
488
  },
489
489
  adminUser,
490
490
  version: ADMINFORTH_VERSION,
@@ -394,6 +394,9 @@ class CodeInjector {
394
394
  watchCustomComponentsForCopy(_a) {
395
395
  return __awaiter(this, arguments, void 0, function* ({ verbose }) {
396
396
  const customComponentsDir = this.adminforth.config.customization.customComponentsDir;
397
+ if (!customComponentsDir) {
398
+ return;
399
+ }
397
400
  // check if folder exists
398
401
  try {
399
402
  yield fs.promises.access(customComponentsDir, fs.constants.F_OK);
@@ -1,5 +1,6 @@
1
1
  <template>
2
2
  <div>
3
+
3
4
  <span v-if="column.foreignResource">
4
5
  <RouterLink v-if="row[column.name]" class="font-medium text-blue-600 dark:text-blue-500 hover:brightness-110"
5
6
  :to="{ name: 'resource-show', params: { resourceId: column.foreignResource.resourceId, primaryKey: row[column.name].pk } }">
@@ -15,14 +16,14 @@
15
16
  <span v-else class="bg-red-100 text-red-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-red-400 border border-red-400">No</span>
16
17
  </span>
17
18
  <span v-else-if="column.enum">
18
- {{ column.enum.find(e => e.value === row[column.name])?.label }}
19
+ {{ checkEmptyValues(column.enum.find(e => e.value === row[column.name])?.label,route.meta.type) }}
19
20
  </span>
20
21
  <span v-else-if="column.type === 'datetime'">
21
- {{ formatDate(row[column.name]) }}
22
+ {{ checkEmptyValues(formatDate(row[column.name]),route.meta.type) }}
22
23
 
23
24
  </span>
24
25
  <span v-else>
25
- {{ row[column.name] }}
26
+ {{ checkEmptyValues(row[column.name],route.meta.type) }}
26
27
  </span>
27
28
  </div>
28
29
  </template>
@@ -33,10 +34,15 @@
33
34
  import dayjs from 'dayjs';
34
35
  import utc from 'dayjs/plugin/utc';
35
36
  import timezone from 'dayjs/plugin/timezone';
37
+ import {checkEmptyValues} from '@/utils';
38
+ import { useRoute, useRouter } from 'vue-router';
39
+
36
40
 
37
41
  import { useCoreStore } from '@/stores/core';
38
42
 
39
43
  const coreStore = useCoreStore();
44
+ const route = useRoute();
45
+
40
46
 
41
47
  dayjs.extend(utc);
42
48
  dayjs.extend(timezone);
@@ -20,26 +20,26 @@ const router = createRouter({
20
20
  path: '',
21
21
  component: () => import('@/views/ListView.vue'),
22
22
  name: 'resource-list',
23
- meta: { title: 'list' }
23
+ meta: { title: 'list',type: 'list' }
24
24
  },
25
25
  {
26
26
  path: 'show/:primaryKey',
27
27
  component: () => import('@/views/ShowView.vue'),
28
28
  name: 'resource-show',
29
- meta: { title: 'show' }
29
+ meta: { title: 'show', type: 'show'}
30
30
 
31
31
  },
32
32
  {
33
33
  path: 'edit/:primaryKey',
34
34
  component: () => import('@/views/EditView.vue'),
35
35
  name: 'resource-edit',
36
- meta: { title: 'edit' }
36
+ meta: { title: 'edit', type: 'edit'}
37
37
  },
38
38
  {
39
39
  path: 'create',
40
40
  component: () => import('@/views/CreateView.vue'),
41
41
  name: 'resource-create',
42
- meta: { title: 'create' }
42
+ meta: { title: 'create', type: 'create'}
43
43
 
44
44
  },
45
45
  ]
@@ -0,0 +1,51 @@
1
+ import type { AdminForthResource, AdminForthResourceColumn } from '../types/AdminForthConfig';
2
+
3
+ export type resourceById = {
4
+ [key: string]: AdminForthResource;
5
+ }
6
+
7
+ export type Menu = {
8
+ label: string,
9
+ icon: string,
10
+ resourceId: string,
11
+ children?: Array<Menu>,
12
+ }
13
+
14
+ export type Record = {
15
+ [key: string]: any;
16
+ }
17
+
18
+ export type ResourceColumns = {
19
+ [key: string]: Array<AdminForthResourceColumn>;
20
+ }
21
+
22
+ export type CoreConfig = {
23
+ brandName: string,
24
+ brandLogo: string,
25
+ title: string,
26
+ datesFormat: string,
27
+ usernameField: string,
28
+ usernameFieldName?: string,
29
+ deleteConfirmation?: boolean,
30
+ auth?: {
31
+ resourceId: string,
32
+ usernameField: string,
33
+ passwordHashField: string,
34
+ loginBackgroundImage: string,
35
+ userFullnameField: string,
36
+ },
37
+ emptyFieldPlaceholder?: {
38
+ show: string,
39
+ list: string,
40
+
41
+ } | string,
42
+ }
43
+
44
+
45
+ export type AllowedActions = {
46
+ show: boolean,
47
+ create: boolean,
48
+ edit: boolean,
49
+ delete: boolean,
50
+ }
51
+
@@ -30,8 +30,7 @@ export const useCoreStore = defineStore('core', () => {
30
30
  user.value = resp.user;
31
31
  console.log('🌍 AdminForth v', resp.version);
32
32
 
33
- // find homepage:true in menu recuresively
34
-
33
+
35
34
  }
36
35
 
37
36
  async function fetchRecord({ resourceId, primaryKey }) {
@@ -1,4 +1,5 @@
1
1
  import { onMounted, ref, resolveComponent } from 'vue';
2
+ import type { CoreConfig } from './spa_types/core';
2
3
 
3
4
  import router from "./router";
4
5
  import { useCoreStore } from './stores/core';
@@ -64,12 +65,18 @@ export const loadFile = (file: string) => {
64
65
  return baseUrl;
65
66
  }
66
67
 
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
- // }
68
+ export function checkEmptyValues(value: any, viewType:'show' | 'list' ) {
69
+ const config: CoreConfig | {} = useCoreStore().config;
70
+ let emptyFieldPlaceholder = '';
71
+ if (config.emptyFieldPlaceholder) {
72
+ if(typeof config.emptyFieldPlaceholder === 'string') {
73
+ emptyFieldPlaceholder = config.emptyFieldPlaceholder;
74
+ } else {
75
+ emptyFieldPlaceholder = config.emptyFieldPlaceholder?.[viewType] || '';
76
+ }
77
+ if (value === null || value === undefined || value === '') {
78
+ return emptyFieldPlaceholder;
79
+ }
80
+ }
81
+ return value;
82
+ }
@@ -5,7 +5,7 @@ import type * as Preset from '@docusaurus/preset-classic';
5
5
  const config: Config = {
6
6
  title: 'AdminForth',
7
7
  tagline: 'AdminForth Open-Source Vue-driven Next-Gen Admin Panel',
8
- favicon: 'img/favicon.ico',
8
+ favicon: 'img/favicon.png',
9
9
 
10
10
  // Set the production url of your site here
11
11
  url: 'https://adminforth.devforth.io',
@@ -1 +1,19 @@
1
- <svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path fill="#FFF" d="M99 52h84v34H99z"/><path d="M23 163c-7.398 0-13.843-4.027-17.303-10A19.886 19.886 0 0 0 3 163c0 11.046 8.954 20 20 20h20v-20H23z" fill="#3ECC5F"/><path d="M112.98 57.376L183 53V43c0-11.046-8.954-20-20-20H73l-2.5-4.33c-1.112-1.925-3.889-1.925-5 0L63 23l-2.5-4.33c-1.111-1.925-3.889-1.925-5 0L53 23l-2.5-4.33c-1.111-1.925-3.889-1.925-5 0L43 23c-.022 0-.042.003-.065.003l-4.142-4.141c-1.57-1.571-4.252-.853-4.828 1.294l-1.369 5.104-5.192-1.392c-2.148-.575-4.111 1.389-3.535 3.536l1.39 5.193-5.102 1.367c-2.148.576-2.867 3.259-1.296 4.83l4.142 4.142c0 .021-.003.042-.003.064l-4.33 2.5c-1.925 1.111-1.925 3.889 0 5L23 53l-4.33 2.5c-1.925 1.111-1.925 3.889 0 5L23 63l-4.33 2.5c-1.925 1.111-1.925 3.889 0 5L23 73l-4.33 2.5c-1.925 1.111-1.925 3.889 0 5L23 83l-4.33 2.5c-1.925 1.111-1.925 3.889 0 5L23 93l-4.33 2.5c-1.925 1.111-1.925 3.889 0 5L23 103l-4.33 2.5c-1.925 1.111-1.925 3.889 0 5L23 113l-4.33 2.5c-1.925 1.111-1.925 3.889 0 5L23 123l-4.33 2.5c-1.925 1.111-1.925 3.889 0 5L23 133l-4.33 2.5c-1.925 1.111-1.925 3.889 0 5L23 143l-4.33 2.5c-1.925 1.111-1.925 3.889 0 5L23 153l-4.33 2.5c-1.925 1.111-1.925 3.889 0 5L23 163c0 11.046 8.954 20 20 20h120c11.046 0 20-8.954 20-20V83l-70.02-4.376A10.645 10.645 0 0 1 103 68c0-5.621 4.37-10.273 9.98-10.624" fill="#3ECC5F"/><path fill="#3ECC5F" d="M143 183h30v-40h-30z"/><path d="M193 158c-.219 0-.428.037-.639.064-.038-.15-.074-.301-.116-.451A5 5 0 0 0 190.32 148a4.96 4.96 0 0 0-3.016 1.036 26.531 26.531 0 0 0-.335-.336 4.955 4.955 0 0 0 1.011-2.987 5 5 0 0 0-9.599-1.959c-.148-.042-.297-.077-.445-.115.027-.211.064-.42.064-.639a5 5 0 0 0-5-5 5 5 0 0 0-5 5c0 .219.037.428.064.639-.148.038-.297.073-.445.115a4.998 4.998 0 0 0-9.599 1.959c0 1.125.384 2.151 1.011 2.987-3.717 3.632-6.031 8.693-6.031 14.3 0 11.046 8.954 20 20 20 9.339 0 17.16-6.41 19.361-15.064.211.027.42.064.639.064a5 5 0 0 0 5-5 5 5 0 0 0-5-5" fill="#44D860"/><path fill="#3ECC5F" d="M153 123h30v-20h-30z"/><path d="M193 115.5a2.5 2.5 0 1 0 0-5c-.109 0-.214.019-.319.032-.02-.075-.037-.15-.058-.225a2.501 2.501 0 0 0-.963-4.807c-.569 0-1.088.197-1.508.518a6.653 6.653 0 0 0-.168-.168c.314-.417.506-.931.506-1.494a2.5 2.5 0 0 0-4.8-.979A9.987 9.987 0 0 0 183 103c-5.522 0-10 4.478-10 10s4.478 10 10 10c.934 0 1.833-.138 2.69-.377a2.5 2.5 0 0 0 4.8-.979c0-.563-.192-1.077-.506-1.494.057-.055.113-.111.168-.168.42.321.939.518 1.508.518a2.5 2.5 0 0 0 .963-4.807c.021-.074.038-.15.058-.225.105.013.21.032.319.032" fill="#44D860"/><path d="M63 55.5a2.5 2.5 0 0 1-2.5-2.5c0-4.136-3.364-7.5-7.5-7.5s-7.5 3.364-7.5 7.5a2.5 2.5 0 1 1-5 0c0-6.893 5.607-12.5 12.5-12.5S65.5 46.107 65.5 53a2.5 2.5 0 0 1-2.5 2.5" fill="#000"/><path d="M103 183h60c11.046 0 20-8.954 20-20V93h-60c-11.046 0-20 8.954-20 20v70z" fill="#FFFF50"/><path d="M168.02 124h-50.04a1 1 0 1 1 0-2h50.04a1 1 0 1 1 0 2m0 20h-50.04a1 1 0 1 1 0-2h50.04a1 1 0 1 1 0 2m0 20h-50.04a1 1 0 1 1 0-2h50.04a1 1 0 1 1 0 2m0-49.814h-50.04a1 1 0 1 1 0-2h50.04a1 1 0 1 1 0 2m0 19.814h-50.04a1 1 0 1 1 0-2h50.04a1 1 0 1 1 0 2m0 20h-50.04a1 1 0 1 1 0-2h50.04a1 1 0 1 1 0 2M183 61.611c-.012 0-.022-.006-.034-.005-3.09.105-4.552 3.196-5.842 5.923-1.346 2.85-2.387 4.703-4.093 4.647-1.889-.068-2.969-2.202-4.113-4.46-1.314-2.594-2.814-5.536-5.963-5.426-3.046.104-4.513 2.794-5.807 5.167-1.377 2.528-2.314 4.065-4.121 3.994-1.927-.07-2.951-1.805-4.136-3.813-1.321-2.236-2.848-4.75-5.936-4.664-2.994.103-4.465 2.385-5.763 4.4-1.373 2.13-2.335 3.428-4.165 3.351-1.973-.07-2.992-1.51-4.171-3.177-1.324-1.873-2.816-3.993-5.895-3.89-2.928.1-4.399 1.97-5.696 3.618-1.232 1.564-2.194 2.802-4.229 2.724a1 1 0 0 0-.072 2c3.017.101 4.545-1.8 5.872-3.487 1.177-1.496 2.193-2.787 4.193-2.855 1.926-.082 2.829 1.115 4.195 3.045 1.297 1.834 2.769 3.914 5.731 4.021 3.103.104 4.596-2.215 5.918-4.267 1.182-1.834 2.202-3.417 4.15-3.484 1.793-.067 2.769 1.35 4.145 3.681 1.297 2.197 2.766 4.686 5.787 4.796 3.125.108 4.634-2.62 5.949-5.035 1.139-2.088 2.214-4.06 4.119-4.126 1.793-.042 2.728 1.595 4.111 4.33 1.292 2.553 2.757 5.445 5.825 5.556l.169.003c3.064 0 4.518-3.075 5.805-5.794 1.139-2.41 2.217-4.68 4.067-4.773v-2z" fill="#000"/><path fill="#3ECC5F" d="M83 183h40v-40H83z"/><path d="M143 158c-.219 0-.428.037-.639.064-.038-.15-.074-.301-.116-.451A5 5 0 0 0 140.32 148a4.96 4.96 0 0 0-3.016 1.036 26.531 26.531 0 0 0-.335-.336 4.955 4.955 0 0 0 1.011-2.987 5 5 0 0 0-9.599-1.959c-.148-.042-.297-.077-.445-.115.027-.211.064-.42.064-.639a5 5 0 0 0-5-5 5 5 0 0 0-5 5c0 .219.037.428.064.639-.148.038-.297.073-.445.115a4.998 4.998 0 0 0-9.599 1.959c0 1.125.384 2.151 1.011 2.987-3.717 3.632-6.031 8.693-6.031 14.3 0 11.046 8.954 20 20 20 9.339 0 17.16-6.41 19.361-15.064.211.027.42.064.639.064a5 5 0 0 0 5-5 5 5 0 0 0-5-5" fill="#44D860"/><path fill="#3ECC5F" d="M83 123h40v-20H83z"/><path d="M133 115.5a2.5 2.5 0 1 0 0-5c-.109 0-.214.019-.319.032-.02-.075-.037-.15-.058-.225a2.501 2.501 0 0 0-.963-4.807c-.569 0-1.088.197-1.508.518a6.653 6.653 0 0 0-.168-.168c.314-.417.506-.931.506-1.494a2.5 2.5 0 0 0-4.8-.979A9.987 9.987 0 0 0 123 103c-5.522 0-10 4.478-10 10s4.478 10 10 10c.934 0 1.833-.138 2.69-.377a2.5 2.5 0 0 0 4.8-.979c0-.563-.192-1.077-.506-1.494.057-.055.113-.111.168-.168.42.321.939.518 1.508.518a2.5 2.5 0 0 0 .963-4.807c.021-.074.038-.15.058-.225.105.013.21.032.319.032" fill="#44D860"/><path d="M143 41.75c-.16 0-.33-.02-.49-.05a2.52 2.52 0 0 1-.47-.14c-.15-.06-.29-.14-.431-.23-.13-.09-.259-.2-.38-.31-.109-.12-.219-.24-.309-.38s-.17-.28-.231-.43a2.619 2.619 0 0 1-.189-.96c0-.16.02-.33.05-.49.03-.16.08-.31.139-.47.061-.15.141-.29.231-.43.09-.13.2-.26.309-.38.121-.11.25-.22.38-.31.141-.09.281-.17.431-.23.149-.06.31-.11.47-.14.32-.07.65-.07.98 0 .159.03.32.08.47.14.149.06.29.14.43.23.13.09.259.2.38.31.11.12.22.25.31.38.09.14.17.28.23.43.06.16.11.31.14.47.029.16.05.33.05.49 0 .66-.271 1.31-.73 1.77-.121.11-.25.22-.38.31-.14.09-.281.17-.43.23a2.565 2.565 0 0 1-.96.19m20-1.25c-.66 0-1.3-.27-1.771-.73a3.802 3.802 0 0 1-.309-.38c-.09-.14-.17-.28-.231-.43a2.619 2.619 0 0 1-.189-.96c0-.66.27-1.3.729-1.77.121-.11.25-.22.38-.31.141-.09.281-.17.431-.23.149-.06.31-.11.47-.14.32-.07.66-.07.98 0 .159.03.32.08.47.14.149.06.29.14.43.23.13.09.259.2.38.31.459.47.73 1.11.73 1.77 0 .16-.021.33-.05.49-.03.16-.08.32-.14.47-.07.15-.14.29-.23.43-.09.13-.2.26-.31.38-.121.11-.25.22-.38.31-.14.09-.281.17-.43.23a2.565 2.565 0 0 1-.96.19" fill="#000"/></g></svg>
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g clip-path="url(#clip0_1_8)">
3
+ <path d="M8.034 6.006V13H6.097V12.194C5.59433 12.8007 4.86633 13.104 3.913 13.104C3.25433 13.104 2.65633 12.9567 2.119 12.662C1.59033 12.3673 1.17433 11.947 0.871 11.401C0.567667 10.855 0.416 10.2223 0.416 9.503C0.416 8.78367 0.567667 8.151 0.871 7.605C1.17433 7.059 1.59033 6.63867 2.119 6.344C2.65633 6.04933 3.25433 5.902 3.913 5.902C4.80567 5.902 5.50333 6.18367 6.006 6.747V6.006H8.034ZM4.264 11.44C4.77533 11.44 5.2 11.2667 5.538 10.92C5.876 10.5647 6.045 10.0923 6.045 9.503C6.045 8.91367 5.876 8.44567 5.538 8.099C5.2 7.74367 4.77533 7.566 4.264 7.566C3.744 7.566 3.315 7.74367 2.977 8.099C2.639 8.44567 2.47 8.91367 2.47 9.503C2.47 10.0923 2.639 10.5647 2.977 10.92C3.315 11.2667 3.744 11.44 4.264 11.44Z" fill="url(#paint0_linear_1_8)"/>
4
+ <path d="M13.317 5.538C12.589 5.538 12.0387 5.69833 11.666 6.019C11.2933 6.331 11.107 6.80333 11.107 7.436V7.995H14.851V9.685H11.107V13H9.001V7.449C9.001 6.279 9.365 5.369 10.093 4.719C10.8297 4.069 11.8567 3.744 13.174 3.744C13.694 3.744 14.1837 3.80033 14.643 3.913C15.1023 4.017 15.501 4.173 15.839 4.381L15.189 6.045C14.669 5.707 14.045 5.538 13.317 5.538Z" fill="url(#paint1_linear_1_8)"/>
5
+ </g>
6
+ <defs>
7
+ <linearGradient id="paint0_linear_1_8" x1="1.5" y1="6.93333" x2="7.31883" y2="11.8926" gradientUnits="userSpaceOnUse">
8
+ <stop stop-color="#656E7A"/>
9
+ <stop offset="1" stop-color="#99A6B8"/>
10
+ </linearGradient>
11
+ <linearGradient id="paint1_linear_1_8" x1="12.5" y1="3.73333" x2="9.68642" y2="12.7016" gradientUnits="userSpaceOnUse">
12
+ <stop stop-color="#48C5FF"/>
13
+ <stop offset="1" stop-color="#A1E1FF"/>
14
+ </linearGradient>
15
+ <clipPath id="clip0_1_8">
16
+ <rect width="16" height="16" fill="white"/>
17
+ </clipPath>
18
+ </defs>
19
+ </svg>
package/index.ts CHANGED
@@ -93,6 +93,10 @@ class AdminForth implements AdminForthClass {
93
93
 
94
94
  console.log('\n ⚠️⚠️⚠️ [INSECURE ALERT] config.rootUser is set, please create a new user and remove config.rootUser from config before going to production\n');
95
95
  }
96
+
97
+ if (!this.config.customization.customComponentsDir) {
98
+ this.config.customization.customComponentsDir = './custom';
99
+ }
96
100
 
97
101
  if (this.config.auth) {
98
102
  if (!this.config.auth.resourceId) {
@@ -117,10 +121,6 @@ class AdminForth implements AdminForthClass {
117
121
  this.config.customization = {};
118
122
  }
119
123
 
120
- if (!this.config.customization.customComponentsDir) {
121
- this.config.customization.customComponentsDir = './custom';
122
- }
123
-
124
124
 
125
125
  if (!this.config.baseUrl) {
126
126
  this.config.baseUrl = '';
@@ -557,7 +557,7 @@ class AdminForth implements AdminForthClass {
557
557
  auth: this.config.auth,
558
558
  usernameField: this.config.auth.usernameField,
559
559
  title: this.config.customization?.title,
560
- emtyFieldPlaceholder: this.config.customization?.emtyFieldPlaceholder,
560
+ emptyFieldPlaceholder: this.config.customization?.emptyFieldPlaceholder,
561
561
  },
562
562
  adminUser,
563
563
  version: ADMINFORTH_VERSION,
@@ -456,7 +456,9 @@ async watchForReprepare({ verbose }) {
456
456
 
457
457
  async watchCustomComponentsForCopy({ verbose }) {
458
458
  const customComponentsDir = this.adminforth.config.customization.customComponentsDir;
459
-
459
+ if (!customComponentsDir) {
460
+ return;
461
+ }
460
462
  // check if folder exists
461
463
  try {
462
464
  await fs.promises.access(customComponentsDir, fs.constants.F_OK);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "1.0.76",
3
+ "version": "1.0.78",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,5 +1,6 @@
1
1
  <template>
2
2
  <div>
3
+
3
4
  <span v-if="column.foreignResource">
4
5
  <RouterLink v-if="row[column.name]" class="font-medium text-blue-600 dark:text-blue-500 hover:brightness-110"
5
6
  :to="{ name: 'resource-show', params: { resourceId: column.foreignResource.resourceId, primaryKey: row[column.name].pk } }">
@@ -15,14 +16,14 @@
15
16
  <span v-else class="bg-red-100 text-red-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-red-400 border border-red-400">No</span>
16
17
  </span>
17
18
  <span v-else-if="column.enum">
18
- {{ column.enum.find(e => e.value === row[column.name])?.label }}
19
+ {{ checkEmptyValues(column.enum.find(e => e.value === row[column.name])?.label,route.meta.type) }}
19
20
  </span>
20
21
  <span v-else-if="column.type === 'datetime'">
21
- {{ formatDate(row[column.name]) }}
22
+ {{ checkEmptyValues(formatDate(row[column.name]),route.meta.type) }}
22
23
 
23
24
  </span>
24
25
  <span v-else>
25
- {{ row[column.name] }}
26
+ {{ checkEmptyValues(row[column.name],route.meta.type) }}
26
27
  </span>
27
28
  </div>
28
29
  </template>
@@ -33,10 +34,15 @@
33
34
  import dayjs from 'dayjs';
34
35
  import utc from 'dayjs/plugin/utc';
35
36
  import timezone from 'dayjs/plugin/timezone';
37
+ import {checkEmptyValues} from '@/utils';
38
+ import { useRoute, useRouter } from 'vue-router';
39
+
36
40
 
37
41
  import { useCoreStore } from '@/stores/core';
38
42
 
39
43
  const coreStore = useCoreStore();
44
+ const route = useRoute();
45
+
40
46
 
41
47
  dayjs.extend(utc);
42
48
  dayjs.extend(timezone);
@@ -20,26 +20,26 @@ const router = createRouter({
20
20
  path: '',
21
21
  component: () => import('@/views/ListView.vue'),
22
22
  name: 'resource-list',
23
- meta: { title: 'list' }
23
+ meta: { title: 'list',type: 'list' }
24
24
  },
25
25
  {
26
26
  path: 'show/:primaryKey',
27
27
  component: () => import('@/views/ShowView.vue'),
28
28
  name: 'resource-show',
29
- meta: { title: 'show' }
29
+ meta: { title: 'show', type: 'show'}
30
30
 
31
31
  },
32
32
  {
33
33
  path: 'edit/:primaryKey',
34
34
  component: () => import('@/views/EditView.vue'),
35
35
  name: 'resource-edit',
36
- meta: { title: 'edit' }
36
+ meta: { title: 'edit', type: 'edit'}
37
37
  },
38
38
  {
39
39
  path: 'create',
40
40
  component: () => import('@/views/CreateView.vue'),
41
41
  name: 'resource-create',
42
- meta: { title: 'create' }
42
+ meta: { title: 'create', type: 'create'}
43
43
 
44
44
  },
45
45
  ]
@@ -0,0 +1,51 @@
1
+ import type { AdminForthResource, AdminForthResourceColumn } from '../types/AdminForthConfig';
2
+
3
+ export type resourceById = {
4
+ [key: string]: AdminForthResource;
5
+ }
6
+
7
+ export type Menu = {
8
+ label: string,
9
+ icon: string,
10
+ resourceId: string,
11
+ children?: Array<Menu>,
12
+ }
13
+
14
+ export type Record = {
15
+ [key: string]: any;
16
+ }
17
+
18
+ export type ResourceColumns = {
19
+ [key: string]: Array<AdminForthResourceColumn>;
20
+ }
21
+
22
+ export type CoreConfig = {
23
+ brandName: string,
24
+ brandLogo: string,
25
+ title: string,
26
+ datesFormat: string,
27
+ usernameField: string,
28
+ usernameFieldName?: string,
29
+ deleteConfirmation?: boolean,
30
+ auth?: {
31
+ resourceId: string,
32
+ usernameField: string,
33
+ passwordHashField: string,
34
+ loginBackgroundImage: string,
35
+ userFullnameField: string,
36
+ },
37
+ emptyFieldPlaceholder?: {
38
+ show: string,
39
+ list: string,
40
+
41
+ } | string,
42
+ }
43
+
44
+
45
+ export type AllowedActions = {
46
+ show: boolean,
47
+ create: boolean,
48
+ edit: boolean,
49
+ delete: boolean,
50
+ }
51
+
@@ -30,8 +30,7 @@ export const useCoreStore = defineStore('core', () => {
30
30
  user.value = resp.user;
31
31
  console.log('🌍 AdminForth v', resp.version);
32
32
 
33
- // find homepage:true in menu recuresively
34
-
33
+
35
34
  }
36
35
 
37
36
  async function fetchRecord({ resourceId, primaryKey }) {
package/spa/src/utils.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { onMounted, ref, resolveComponent } from 'vue';
2
+ import type { CoreConfig } from './spa_types/core';
2
3
 
3
4
  import router from "./router";
4
5
  import { useCoreStore } from './stores/core';
@@ -64,12 +65,18 @@ export const loadFile = (file: string) => {
64
65
  return baseUrl;
65
66
  }
66
67
 
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
- // }
68
+ export function checkEmptyValues(value: any, viewType:'show' | 'list' ) {
69
+ const config: CoreConfig | {} = useCoreStore().config;
70
+ let emptyFieldPlaceholder = '';
71
+ if (config.emptyFieldPlaceholder) {
72
+ if(typeof config.emptyFieldPlaceholder === 'string') {
73
+ emptyFieldPlaceholder = config.emptyFieldPlaceholder;
74
+ } else {
75
+ emptyFieldPlaceholder = config.emptyFieldPlaceholder?.[viewType] || '';
76
+ }
77
+ if (value === null || value === undefined || value === '') {
78
+ return emptyFieldPlaceholder;
79
+ }
80
+ }
81
+ return value;
82
+ }
@@ -134,12 +134,11 @@ export type AdminForthConfig = {
134
134
  datesFormat?: string,
135
135
  title?: string,
136
136
  brandLogo?: string,
137
- emtyFieldPlaceholder?: {
137
+ emptyFieldPlaceholder?: {
138
138
  show?: string,
139
139
  list?: string,
140
- create?: string,
141
- edit?: string,
142
- },
140
+
141
+ } | string,
143
142
  },
144
143
  baseUrl?: string,
145
144