adminforth 1.5.4-next.9 → 1.5.4

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.
Files changed (55) hide show
  1. package/dist/auth.js +4 -4
  2. package/dist/auth.js.map +1 -1
  3. package/dist/dataConnectors/clickhouse.d.ts.map +1 -1
  4. package/dist/dataConnectors/clickhouse.js +0 -1
  5. package/dist/dataConnectors/clickhouse.js.map +1 -1
  6. package/dist/index.d.ts +0 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +3 -13
  9. package/dist/index.js.map +1 -1
  10. package/dist/modules/codeInjector.d.ts.map +1 -1
  11. package/dist/modules/codeInjector.js +7 -5
  12. package/dist/modules/codeInjector.js.map +1 -1
  13. package/dist/modules/configValidator.d.ts +11 -5
  14. package/dist/modules/configValidator.d.ts.map +1 -1
  15. package/dist/modules/configValidator.js +387 -379
  16. package/dist/modules/configValidator.js.map +1 -1
  17. package/dist/modules/restApi.d.ts.map +1 -1
  18. package/dist/modules/restApi.js +32 -13
  19. package/dist/modules/restApi.js.map +1 -1
  20. package/dist/modules/socketBroker.d.ts.map +1 -1
  21. package/dist/modules/socketBroker.js +0 -1
  22. package/dist/modules/socketBroker.js.map +1 -1
  23. package/dist/servers/express.d.ts.map +1 -1
  24. package/dist/servers/express.js +2 -3
  25. package/dist/servers/express.js.map +1 -1
  26. package/dist/spa/src/App.vue +8 -6
  27. package/dist/spa/src/afcl/Input.vue +1 -1
  28. package/dist/spa/src/afcl/Link.vue +9 -1
  29. package/dist/spa/src/afcl/LinkButton.vue +5 -3
  30. package/dist/spa/src/afcl/VerticalTabs.vue +1 -1
  31. package/dist/spa/src/components/AcceptModal.vue +1 -2
  32. package/dist/spa/src/components/ResourceListTable.vue +4 -3
  33. package/dist/spa/src/components/SkeleteLoader.vue +5 -10
  34. package/dist/spa/src/components/ValueRenderer.vue +13 -14
  35. package/dist/spa/src/spa_types/core.ts +2 -4
  36. package/dist/spa/src/stores/core.ts +15 -16
  37. package/dist/spa/src/stores/user.ts +0 -7
  38. package/dist/spa/src/types/Back.ts +310 -327
  39. package/dist/spa/src/types/Common.ts +220 -10
  40. package/dist/spa/src/types/FrontendAPI.ts +5 -4
  41. package/dist/spa/src/utils.ts +5 -1
  42. package/dist/spa/src/views/LoginView.vue +6 -1
  43. package/dist/spa/src/websocket.ts +3 -2
  44. package/dist/types/Back.d.ts +262 -287
  45. package/dist/types/Back.d.ts.map +1 -1
  46. package/dist/types/Back.js +1 -46
  47. package/dist/types/Back.js.map +1 -1
  48. package/dist/types/Common.d.ts +194 -9
  49. package/dist/types/Common.d.ts.map +1 -1
  50. package/dist/types/Common.js +47 -0
  51. package/dist/types/Common.js.map +1 -1
  52. package/dist/types/FrontendAPI.d.ts +4 -4
  53. package/dist/types/FrontendAPI.d.ts.map +1 -1
  54. package/dist/types/FrontendAPI.js.map +1 -1
  55. package/package.json +4 -4
@@ -45,6 +45,7 @@ export enum ActionCheckSource {
45
45
  DisplayButtons = 'displayButtons',
46
46
  ListRequest = 'listRequest',
47
47
  ShowRequest = 'showRequest',
48
+ EditLoadRequest = 'editLoadRequest', // when data for edit page is loaded
48
49
  EditRequest = 'editRequest',
49
50
  CreateRequest = 'createRequest',
50
51
  DeleteRequest = 'deleteRequest',
@@ -62,7 +63,7 @@ export enum AllowedActionsEnum {
62
63
 
63
64
 
64
65
  export type AllowedActionsResolved = {
65
- [key in AllowedActionsEnum]?: boolean
66
+ [key in AllowedActionsEnum]: boolean
66
67
  }
67
68
 
68
69
  export interface AdminUser {
@@ -235,7 +236,7 @@ export type AdminForthComponentDeclaration = AdminForthComponentDeclarationFull
235
236
  * Resource describes one table or collection in database.
236
237
  * AdminForth generates set of pages for 'list', 'show', 'edit', 'create', 'filter' operations for each resource.
237
238
  */
238
- export interface AdminForthResourceCommon {
239
+ export interface AdminForthResourceInputCommon {
239
240
  /**
240
241
  * Unique identifier of resource. By default it equals to table name in database.
241
242
  * If you wish you can explicitly set it to any string.
@@ -263,12 +264,7 @@ export interface AdminForthResourceCommon {
263
264
  * Array of columns which will be displayed in the admin panel.
264
265
  * Each column has its own configuration.
265
266
  */
266
- columns: Array<AdminForthResourceColumnCommon>,
267
-
268
- /**
269
- * Internal array of columns which are not virtual. You should not edit it.
270
- */
271
- dataSourceColumns?: Array<AdminForthResourceColumnCommon>, // TODO, mark as private
267
+ columns: Array<AdminForthResourceColumnInputCommon>,
272
268
 
273
269
  /**
274
270
  * Hook which allow you to modify record label
@@ -280,7 +276,7 @@ export interface AdminForthResourceCommon {
280
276
  * ```
281
277
  *
282
278
  */
283
- recordLabel?: Function,
279
+ recordLabel?: (item: any) => string,
284
280
 
285
281
 
286
282
  /**
@@ -459,6 +455,13 @@ export interface AdminForthResourceCommon {
459
455
  },
460
456
  }
461
457
 
458
+ export interface AdminForthResourceCommon extends AdminForthResourceInputCommon {
459
+ resourceId: string,
460
+ label: string,
461
+
462
+ columns: Array<AdminForthResourceColumnCommon>,
463
+ }
464
+
462
465
 
463
466
  export type ValidationObject = {
464
467
  /**
@@ -516,7 +519,7 @@ export interface AdminForthForeignResourceCommon {
516
519
  /**
517
520
  * Column describes one field in the table or collection in database.
518
521
  */
519
- export type AdminForthResourceColumnCommon = {
522
+ export interface AdminForthResourceColumnInputCommon {
520
523
  /**
521
524
  * Column name in database.
522
525
  */
@@ -699,9 +702,216 @@ export type AdminForthResourceColumnCommon = {
699
702
  */
700
703
  masked?: boolean,
701
704
 
705
+ }
706
+
707
+ export interface AdminForthResourceColumnCommon extends AdminForthResourceColumnInputCommon {
702
708
 
703
709
  /**
704
710
  * Internal type which indicates original type of column in database.
705
711
  */
706
712
  _underlineType?: string,
713
+
714
+ }
715
+
716
+ export enum AdminForthMenuTypes {
717
+ /**
718
+ * HEADING is just a label in the menu.
719
+ * Respect `label` and `icon` property in {@link AdminForthConfigMenuItem}
720
+ */
721
+ heading = 'heading',
722
+
723
+ /**
724
+ * GROUP is a group of menu items.
725
+ * Respects `label`, `icon` and `children` properties in {@link AdminForthConfigMenuItem}
726
+ * use @AdminForthMenuTypes.open to set if group is open by default
727
+ */
728
+ group = 'group',
729
+
730
+ /**
731
+ * RESOURCE is a link to a resource.
732
+ * Respects `label`, `icon`, `resourceId`, `homepage`, `isStaticRoute` properties in {@link AdminForthConfigMenuItem}
733
+ */
734
+ resource = 'resource',
735
+
736
+ /**
737
+ * PAGE is a link to a custom page.
738
+ * Respects `label`, `icon`, `path`, `component`, `homepage`, `isStaticRoute`, properties in {@link AdminForthConfigMenuItem}
739
+ *
740
+ * Example:
741
+ *
742
+ * ```ts
743
+ * \{
744
+ * type: AdminForthMenuTypes.PAGE,
745
+ * label: 'Custom Page',
746
+ * icon: 'home',
747
+ * path: '/dash',
748
+ * component: '@@/Dashboard.vue',
749
+ * homepage: true,
750
+ * \}
751
+ * ```
752
+ *
753
+ */
754
+ page = 'page',
755
+
756
+ /**
757
+ * GAP ads some space between menu items.
758
+ */
759
+ gap = 'gap',
760
+
761
+ /**
762
+ * DIVIDER is a divider between menu items.
763
+ */
764
+ divider = 'divider',
765
+ }
766
+
767
+
768
+ /**
769
+ * Menu item which displayed in the left sidebar of the admin panel.
770
+ */
771
+ export interface AdminForthConfigMenuItem {
772
+ type?: AdminForthMenuTypes | keyof typeof AdminForthMenuTypes,
773
+
774
+ /**
775
+ * Label for menu item which will be displayed in the admin panel.
776
+ */
777
+ label?: string,
778
+
779
+ /**
780
+ * Icon for menu item which will be displayed in the admin panel.
781
+ * Supports iconify icons in format `<icon set name>:<icon name>`
782
+ * Browse available icons here: https://icon-sets.iconify.design/
783
+ *
784
+ * Example:
785
+ *
786
+ * ```ts
787
+ * icon: 'flowbite:brain-solid',
788
+ * ```
789
+ *
790
+ */
791
+ icon?: string,
792
+
793
+ /**
794
+ * Path to custom component which will be displayed in the admin panel.
795
+ *
796
+ */
797
+ path?: string,
798
+
799
+ /**
800
+ * Component to be used for this menu item. Component should be placed in custom folder and referenced with `@@/` prefix.
801
+ * Supported for AdminForthMenuTypes.PAGE only!
802
+ * Example:
803
+ *
804
+ * ```ts
805
+ * component: '@@/Dashboard.vue',
806
+ * ```
807
+ *
808
+ */
809
+ component?: string,
810
+
811
+ /**
812
+ * Resource ID which will be used to fetch data from.
813
+ * Supported for AdminForthMenuTypes.RESOURCE only!
814
+ *
815
+ */
816
+ resourceId?: string,
817
+
818
+ /**
819
+ * If true, group will be open by default after user login to the admin panel.
820
+ * Also will be used to redirect from root path.
821
+ */
822
+ homepage?: boolean,
823
+
824
+ /**
825
+ * Where Group is open by default
826
+ * Supported for AdminForthMenuTypes.GROUP only!
827
+ *
828
+ */
829
+ open?: boolean,
830
+
831
+ /**
832
+ * Children menu items which will be displayed in this group.
833
+ * Supported for AdminForthMenuTypes.GROUP only!
834
+ */
835
+ children?: Array<AdminForthConfigMenuItem>,
836
+
837
+ /**
838
+ * By default all pages are imported dynamically with lazy import().
839
+ * If you wish to import page statically, set this option to true.
840
+ * Homepage will be imported statically by default. but you can override it with this option.
841
+ */
842
+ isStaticRoute?: boolean,
843
+
844
+ meta?: {
845
+ title?: string,
846
+ },
847
+
848
+ /**
849
+ * Optional callback which will be called before rendering the menu for each item.
850
+ * You can use it to hide menu items depending on some user
851
+ */
852
+ visible?: (user: AdminUser) => boolean,
853
+
854
+ /**
855
+ * Optional callback which will be called before rendering the menu for each item.
856
+ * Result of callback if not null will be used as a small badge near the menu item.
857
+ */
858
+ badge?: string | ((user: AdminUser) => Promise<string>),
859
+
860
+ /**
861
+ * Item id will be automatically generated from hashed resourceId+Path+label
862
+ */
863
+ _itemId?: string,
864
+ }
865
+
866
+
867
+ export interface ResourceVeryShort {
868
+ resourceId: string,
869
+ label: string,
707
870
  }
871
+
872
+ export interface UserData {
873
+ pk: string,
874
+ [key: string]: any,
875
+ }
876
+
877
+ export type AnnouncementBadgeResponse = { text?: string, html?: string, closable?: boolean, title?: string };
878
+
879
+ export interface AdminForthConfigForFrontend {
880
+ brandName: string,
881
+ usernameFieldName: string,
882
+ loginBackgroundImage: string,
883
+ loginBackgroundPosition: string,
884
+ title?: string,
885
+ demoCredentials?: string,
886
+ loginPromptHTML?: string,
887
+ loginPageInjections: {
888
+ underInputs: Array<AdminForthComponentDeclaration>,
889
+ },
890
+ rememberMeDays: number,
891
+ showBrandNameInSidebar: boolean,
892
+ brandLogo?: string,
893
+ datesFormat: string,
894
+ timeFormat: string,
895
+ auth: any,
896
+ userFullnameField: string,
897
+ usernameField: string,
898
+ emptyFieldPlaceholder?: string | {
899
+ show?: string,
900
+ list?: string,
901
+ },
902
+ announcementBadge?: AnnouncementBadgeResponse | null,
903
+ globalInjections: {
904
+ userMenu: Array<AdminForthComponentDeclarationFull>,
905
+ header: Array<AdminForthComponentDeclarationFull>,
906
+ sidebar: Array<AdminForthComponentDeclarationFull>,
907
+ }
908
+ }
909
+
910
+ export interface GetBaseConfigResponse {
911
+ user: UserData,
912
+ resources: ResourceVeryShort[],
913
+ menu: AdminForthConfigMenuItem[],
914
+ config: AdminForthConfigForFrontend,
915
+ adminUser: AdminUser,
916
+ version: string,
917
+ }
@@ -60,10 +60,6 @@ export interface FrontendAPIInterface {
60
60
  */
61
61
  closeThreeDotsDropdown(): void;
62
62
 
63
- /**
64
- * Close the user menu dropdown
65
- */
66
- closeUserMenuDropdown(): void;
67
63
 
68
64
  /**
69
65
  * Set a filter in the list
@@ -105,6 +101,11 @@ export interface FrontendAPIInterface {
105
101
  */
106
102
  refreshMenuBadges(): void;
107
103
  }
104
+
105
+ /**
106
+ * Close the user menu dropdown
107
+ */
108
+ closeUserMenuDropdown(): void;
108
109
  }
109
110
 
110
111
  export type ConfirmParams = {
@@ -43,7 +43,7 @@ export async function callAdminForthApi({ path, method, body=undefined }: {
43
43
  }
44
44
  }
45
45
 
46
- export function getCustomComponent({ file, meta }: { file: string, meta: any }) {
46
+ export function getCustomComponent({ file, meta }: { file: string, meta?: any }) {
47
47
  const name = file.replace(/@/g, '').replace(/\./g, '').replace(/\//g, '');
48
48
  return resolveComponent(name);
49
49
  }
@@ -157,4 +157,8 @@ export function setQuery(query: any) {
157
157
  router.replace({
158
158
  query: currentQuery,
159
159
  });
160
+ }
161
+
162
+ export function verySimpleHash(str: string): string {
163
+ return `${str.split('').reduce((a, b)=>{a=((a<<5)-a)+b.charCodeAt(0);return a&a},0)}`;
160
164
  }
@@ -155,12 +155,16 @@ onMounted(async () => {
155
155
 
156
156
 
157
157
  async function login() {
158
+
158
159
  const username = usernameInput.value.value;
159
160
  const password = passwordInput.value.value;
160
161
 
161
162
  if (!username || !password) {
162
163
  return;
163
164
  }
165
+ if (inProgress.value) {
166
+ return;
167
+ }
164
168
  inProgress.value = true;
165
169
  const resp = await callAdminForthApi({
166
170
  path: '/login',
@@ -171,7 +175,6 @@ async function login() {
171
175
  rememberMe: rememberInput.value?.checked,
172
176
  }
173
177
  });
174
- inProgress.value = false;
175
178
  if (resp.error) {
176
179
  error.value = resp.error;
177
180
  } else if (resp.redirectTo) {
@@ -180,6 +183,8 @@ async function login() {
180
183
  error.value = null;
181
184
  await user.finishLogin();
182
185
  }
186
+ inProgress.value = false;
187
+
183
188
  }
184
189
 
185
190
 
@@ -62,11 +62,12 @@ async function connect () {
62
62
  });
63
63
  state.ws.addEventListener('close', () => {
64
64
  console.log('🔌 AFWS disconnected');
65
- state.status = 'disconnected';
66
65
  setTimeout(() => {
67
66
  console.log('🔌 AFWS reconnecting after close');
68
67
  connect();
69
- }, 2_000);
68
+ // if it is first time, reconnect instantly
69
+ }, state.status === 'connected' ? 0 : 2_000);
70
+ state.status = 'disconnected';
70
71
  });
71
72
  }
72
73