adminforth 2.25.0-test.9 → 2.25.1

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 (71) hide show
  1. package/commands/createApp/templates/Dockerfile.hbs +5 -5
  2. package/commands/createApp/templates/custom/package.json.hbs +12 -0
  3. package/commands/createApp/templates/package.json.hbs +6 -6
  4. package/commands/createApp/templates/readme.md.hbs +5 -5
  5. package/commands/createApp/utils.js +10 -10
  6. package/commands/createPlugin/utils.js +6 -5
  7. package/commands/postinstall.js +1 -1
  8. package/dist/dataConnectors/baseConnector.d.ts +2 -2
  9. package/dist/dataConnectors/baseConnector.d.ts.map +1 -1
  10. package/dist/dataConnectors/baseConnector.js +1 -1
  11. package/dist/dataConnectors/baseConnector.js.map +1 -1
  12. package/dist/dataConnectors/mysql.d.ts +3 -2
  13. package/dist/dataConnectors/mysql.d.ts.map +1 -1
  14. package/dist/dataConnectors/mysql.js +26 -1
  15. package/dist/dataConnectors/mysql.js.map +1 -1
  16. package/dist/dataConnectors/postgres.d.ts +3 -2
  17. package/dist/dataConnectors/postgres.d.ts.map +1 -1
  18. package/dist/dataConnectors/postgres.js +25 -1
  19. package/dist/dataConnectors/postgres.js.map +1 -1
  20. package/dist/dataConnectors/sqlite.d.ts +3 -2
  21. package/dist/dataConnectors/sqlite.d.ts.map +1 -1
  22. package/dist/dataConnectors/sqlite.js +21 -1
  23. package/dist/dataConnectors/sqlite.js.map +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/modules/codeInjector.d.ts +2 -2
  27. package/dist/modules/codeInjector.d.ts.map +1 -1
  28. package/dist/modules/codeInjector.js +48 -76
  29. package/dist/modules/codeInjector.js.map +1 -1
  30. package/dist/modules/configValidator.d.ts.map +1 -1
  31. package/dist/modules/configValidator.js +8 -1
  32. package/dist/modules/configValidator.js.map +1 -1
  33. package/dist/modules/restApi.d.ts.map +1 -1
  34. package/dist/modules/restApi.js +5 -0
  35. package/dist/modules/restApi.js.map +1 -1
  36. package/dist/modules/styles.d.ts +0 -4
  37. package/dist/modules/styles.d.ts.map +1 -1
  38. package/dist/modules/styles.js +0 -4
  39. package/dist/modules/styles.js.map +1 -1
  40. package/dist/modules/utils.d.ts +7 -0
  41. package/dist/modules/utils.d.ts.map +1 -1
  42. package/dist/modules/utils.js +34 -0
  43. package/dist/modules/utils.js.map +1 -1
  44. package/dist/servers/express.d.ts +1 -0
  45. package/dist/servers/express.d.ts.map +1 -1
  46. package/dist/spa/README.md +4 -4
  47. package/dist/spa/package-lock.json +1420 -1882
  48. package/dist/spa/package.json +3 -3
  49. package/dist/spa/src/afcl/Button.vue +5 -12
  50. package/dist/spa/src/afcl/Dialog.vue +126 -155
  51. package/dist/spa/src/afcl/Modal.vue +6 -25
  52. package/dist/spa/src/afcl/Select.vue +1 -1
  53. package/dist/spa/src/components/Sidebar.vue +1 -1
  54. package/dist/spa/src/components/ThreeDotsMenu.vue +1 -1
  55. package/dist/spa/src/components/ValueRenderer.vue +1 -1
  56. package/dist/spa/src/stores/core.ts +2 -1
  57. package/dist/spa/src/types/Back.ts +4 -3
  58. package/dist/spa/src/types/Common.ts +0 -6
  59. package/dist/spa/src/types/FrontendAPI.ts +3 -0
  60. package/dist/spa/src/utils/utils.ts +2 -57
  61. package/dist/spa/src/views/CreateView.vue +11 -12
  62. package/dist/spa/src/views/EditView.vue +13 -9
  63. package/dist/spa/vite.config.ts +40 -27
  64. package/dist/types/Back.d.ts +5 -3
  65. package/dist/types/Back.d.ts.map +1 -1
  66. package/dist/types/Common.d.ts +0 -5
  67. package/dist/types/Common.d.ts.map +1 -1
  68. package/dist/types/Common.js.map +1 -1
  69. package/package.json +6 -13
  70. package/commands/createApp/templates/pnpm-workspace.yaml.hbs +0 -2
  71. package/dist/spa/pnpm-lock.yaml +0 -3546
@@ -30,8 +30,7 @@
30
30
  "vue-diff": "^1.2.4",
31
31
  "vue-i18n": "^10.0.5",
32
32
  "vue-router": "^4.3.0",
33
- "vue-slider-component": "^4.1.0-beta.7",
34
- "vue3-json-viewer": "^2.2.2"
33
+ "vue-slider-component": "^4.1.0-beta.7"
35
34
  },
36
35
  "devDependencies": {
37
36
  "@rushstack/eslint-patch": "^1.8.0",
@@ -55,6 +54,7 @@
55
54
  "typescript": "~5.4.0",
56
55
  "vite": "^5.2.13",
57
56
  "vue-i18n-extract": "^2.0.7",
58
- "vue-tsc": "^2.0.11"
57
+ "vue-tsc": "^2.0.11",
58
+ "vue3-json-viewer": "^2.2.2"
59
59
  }
60
60
  }
@@ -6,8 +6,7 @@
6
6
  focus:ring-4 focus:outline-none focus:ring-lightButtonFocusRing focus:ring-opacity-50 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:focus:ring-darkButtonFocusRing dark:text-darkButtonsText dark:border-darkButtonsBorder dark:hover:bg-darkButtonsHover dark:hover:border-darkButtonsBorderHover"
7
7
  :class="{
8
8
  'cursor-default opacity-50 pointer-events-none': props.disabled,
9
- 'active brightness-200 hover:brightness-150' : props.active,
10
- 'text-lightSecondaryContrast/70 bg-lightSecondary border-lightSecondaryContrast/30 dark:bg-darkSecondary hover:bg-lightSecondary/60 hover:border-lightSecondaryContrast/60 focus:ring-lightSecondary dark:focus:ring-darkSecondary/40 dark:text-darkSecondaryContrast dark:border-darkSecondaryContrast/40 dark:hover:bg-darkSecondary/60 dark:hover:border-darkSecondary/60': props.mode === 'secondary',
9
+ 'active brightness-200 hover:brightness-150' : props.active
11
10
  }"
12
11
  >
13
12
  <svg v-if="props.loader"
@@ -19,16 +18,10 @@
19
18
 
20
19
  <script setup lang="ts">
21
20
 
22
- const props = withDefaults(defineProps<{
23
- loader?: boolean;
24
- disabled?: boolean;
25
- active?: boolean;
26
- mode?: 'primary' | 'secondary';
27
- }>(), {
28
- loader: false,
29
- disabled: false,
30
- active: false,
31
- mode: 'primary'
21
+ const props = defineProps({
22
+ loader: Boolean,
23
+ disabled: Boolean,
24
+ active: Boolean,
32
25
  });
33
26
 
34
27
  </script>
@@ -1,188 +1,124 @@
1
1
  <template>
2
- <Modal
3
- ref="modalRef"
4
- v-bind="$attrs"
5
- :closeByClickOutside="clickToCloseOutside || closeByClickOutside"
6
- :closeByEsc="closeByEsc || closable"
7
- :beforeCloseFunction="beforeCloseFunction"
8
- :beforeOpenFunction="beforeOpenFunction"
9
- :askForCloseConfirmation="askForCloseConfirmation"
10
- :closeConfirmationText="closeConfirmationText"
11
- :removeFromDomOnClose="removeFromDomOnClose"
2
+ <div
3
+ v-if="$slots.trigger"
4
+ @click="modal?.show()" class="inline-flex items-center cursor-pointer"
12
5
  >
13
- <template v-if="$slots.trigger" #trigger>
14
- <slot name="trigger"></slot>
15
- </template>
16
-
17
- <!-- Modal header -->
18
- <div
19
- v-if="header"
20
- class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-darkDialogBreakLine border-lightDialogBreakLine"
21
- >
22
- <h3 class="text-xl font-semibold text-lightDialogHeaderText dark:text-darkDialogHeaderText">
23
- {{ header }}
24
- </h3>
25
- <button
26
- v-if="headerCloseButton"
27
- type="button"
28
- class="text-lightDialogCloseButton bg-transparent hover:bg-lightDialogCloseButtonHoverBackground hover:text-lightDialogCloseButtonHover rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:text-darkDialogCloseButton dark:hover:bg-darkDialogCloseButtonHoverBackground dark:hover:text-darkDialogCloseButtonHover"
29
- @click="tryToHideModal"
30
- >
31
- <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
32
- <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"/>
33
- </svg>
34
- <span class="sr-only">{{ t('Close Modal') }}</span>
35
- </button>
36
- </div>
37
- <!-- Modal body -->
38
- <div class="p-4 md:p-5 text-lightDialogBodyText dark:text-darkDialogBodyText">
39
- <slot></slot>
40
- </div>
41
- <!-- Modal footer -->
42
- <div
43
- v-if="buttons.length"
44
- class="flex items-center p-4 md:p-5 border-t border-lightDialogBreakLine rounded-b dark:border-darkDialogBreakLine"
45
- >
46
- <Button
47
- v-for="(button, buttonIndex) in buttons"
48
- :key="buttonIndex"
49
- v-bind="button.options"
50
- :class="{ 'ms-3': buttonIndex > 0 }"
51
- @click="button.onclick(dialog)"
52
- >
53
- {{ button.label }}
54
- </Button>
6
+ <slot name="trigger"></slot>
7
+ </div>
8
+ <Teleport to="body">
9
+ <div ref="modalEl" tabindex="-1" aria-hidden="true" class="[scrollbar-gutter:stable] hidden 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-full max-h-full">
10
+ <div v-bind="$attrs" class="relative p-4 max-w-2xl max-h-full" :class="($attrs.class as string)?.includes('w-') ? '' : 'w-full'">
11
+ <!-- Modal content -->
12
+ <div class="relative bg-lightDialogBackgorund rounded-lg shadow-sm dark:bg-darkDialogBackgorund">
13
+ <!-- Modal header -->
14
+ <div
15
+ v-if="header"
16
+ class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-darkDialogBreakLine border-lightDialogBreakLine"
17
+ >
18
+ <h3 class="text-xl font-semibold text-lightDialogHeaderText dark:text-darkDialogHeaderText">
19
+ {{ header }}
20
+ </h3>
21
+ <button
22
+ v-if="headerCloseButton"
23
+ type="button"
24
+ class="text-lightDialogCloseButton bg-transparent hover:bg-lightDialogCloseButtonHoverBackground hover:text-lightDialogCloseButtonHover rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:text-darkDialogCloseButton dark:hover:bg-darkDialogCloseButtonHoverBackground dark:hover:text-darkDialogCloseButtonHover"
25
+ @click="tryToHideModal"
26
+ >
27
+ <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
28
+ <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"/>
29
+ </svg>
30
+ <span class="sr-only">Close modal</span>
31
+ </button>
32
+ </div>
33
+ <!-- Modal body -->
34
+ <div class="p-4 md:p-5 space-y-4 text-lightDialogBodyText dark:text-darkDialogBodyText">
35
+ <slot></slot>
36
+ </div>
37
+ <!-- Modal footer -->
38
+ <div
39
+ v-if="buttons.length"
40
+ class="flex items-center p-4 md:p-5 border-t border-lightDialogBreakLine rounded-b dark:border-darkDialogBreakLine"
41
+ >
42
+ <Button
43
+ v-for="(button, buttonIndex) in buttons"
44
+ :key="buttonIndex"
45
+ v-bind="button.options"
46
+ :class="{ 'ms-3': buttonIndex > 0 }"
47
+ @click="button.onclick(modal)"
48
+ >
49
+ {{ button.label }}
50
+ </Button>
51
+ </div>
52
+ </div>
53
+ </div>
54
+ <div>
55
+ <!-- Confirmation Modal -->
56
+ <div
57
+ v-if="showConfirmationOnClose"
58
+ class="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-[60]"
59
+ >
60
+ <div class="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-lg max-w-sm w-full">
61
+ <h2 class="text-lg font-semibold mb-4 text-lightDialogHeaderText dark:text-darkDialogHeaderText">Confirm Close</h2>
62
+ <p class="mb-6 text-lightDialogBodyText dark:text-darkDialogBodyText">{{ props.closeConfirmationText }}</p>
63
+ <div class="flex justify-end">
64
+ <Button
65
+ class="me-3 !bg-gray-50 dark:!bg-gray-700 !text-lightDialogBodyText dark:!text-darkDialogBodyText hover:!bg-gray-100 dark:hover:!bg-gray-600 !border-gray-200 dark:!border-gray-600"
66
+ @click="showConfirmationOnClose = false"
67
+ >
68
+ Cancel
69
+ </Button>
70
+ <Button
71
+ @click="
72
+ showConfirmationOnClose = false;
73
+ modal?.hide();
74
+ "
75
+ >
76
+ Confirm
77
+ </Button>
78
+ </div>
79
+ </div>
80
+ </div>
81
+ </div>
55
82
  </div>
56
- </Modal>
83
+ </Teleport>
57
84
  </template>
58
85
 
59
86
  <script setup lang="ts">
60
87
  import Button from "./Button.vue";
61
- import { ref, computed, type Ref } from 'vue';
62
- import { Modal } from '@/afcl'
63
- import { useI18n } from "vue-i18n";
64
-
65
- const { t } = useI18n();
66
-
67
-
68
- interface IDialogInsideButtonClickHandler {
69
- hide: () => void
70
- }
88
+ import { ref, onMounted, nextTick, onUnmounted, computed, type Ref } from 'vue';
89
+ import { Modal } from 'flowbite';
71
90
 
91
+ const modalEl = ref(null);
92
+ const modal: Ref<Modal|null> = ref(null);
72
93
 
73
94
  interface DialogButton {
74
95
  label: string
75
- onclick: (dialog: IDialogInsideButtonClickHandler) => void
96
+ onclick: (dialog: any) => void
76
97
  options?: Record<string, any>
77
98
  }
78
99
 
79
-
80
100
  interface DialogProps {
81
- /**
82
- * The header text to display in the dialog. If not provided, no header will be displayed.
83
- */
84
101
  header?: string
85
-
86
- /**
87
- * If true, a close button will be displayed in the dialog header. Default is true.
88
- */
89
102
  headerCloseButton?: boolean
90
-
91
- /**
92
- * An array of buttons to display in the dialog footer.
93
- */
94
103
  buttons?: DialogButton[]
95
-
96
- /**
97
- * If true, clicking outside the dialog will close it. Default is true.
98
- *
99
- * @deprecated Use `closeByClickOutside` instead
100
- */
101
104
  clickToCloseOutside?: boolean
102
-
103
- /**
104
- * If true, pressing the Esc key will close the dialog. Default is true.
105
- */
106
- closeByEsc?: boolean
107
-
108
- /**
109
- * If true, clicking outside the dialog will close it. Default is true.
110
- */
111
- closeByClickOutside?: boolean
112
-
113
- /**
114
- * Function that will be called before the dialog is closed.
115
- */
116
105
  beforeCloseFunction?: (() => void | Promise<void>) | null
117
-
118
- /**
119
- * Function that will be called before the dialog is opened.
120
- */
121
106
  beforeOpenFunction?: (() => void | Promise<void>) | null
122
-
123
- /**
124
- * Disables close on Ecs button
125
- *
126
- * @deprecated Use `closeByEsc` or instead
127
- */
128
107
  closable?: boolean
129
-
130
- /**
131
- * If true, the dialog will ask for confirmation before closing. Default is false.
132
- */
133
108
  askForCloseConfirmation?: boolean
134
-
135
- /**
136
- * The text to display in the close confirmation dialog. Default is "Are you sure you want to close this dialog?".
137
- */
138
109
  closeConfirmationText?: string
139
-
140
- /**
141
- * If true, the dialog will be removed from the DOM when closed. Default is false.
142
- */
143
- removeFromDomOnClose?: boolean
144
110
  }
145
111
 
146
-
147
-
148
-
149
-
150
-
151
- /********** for the backward compatibility ***************/
152
- class Dialog implements IDialogInsideButtonClickHandler {
153
- hide: () => void
154
- constructor( hide: () => void ) {
155
- this.hide = hide;
156
- }
157
- }
158
- const dialog: Ref<Dialog> = ref(
159
- new Dialog(
160
- () => {
161
- if (dialog.value) {
162
- tryToHideModal();
163
- }
164
- }
165
- )
166
- );
167
- /*************************************************************/
168
-
169
-
170
-
171
- const modalRef = ref();
172
-
173
112
  const props = withDefaults(defineProps<DialogProps>(), {
174
113
  header: '',
175
114
  headerCloseButton: true,
176
115
  buttons: () => [],
177
- clickToCloseOutside: false,
178
- closeByEsc: true,
179
- closeByClickOutside: true,
116
+ clickToCloseOutside: true,
180
117
  beforeCloseFunction: null,
181
118
  beforeOpenFunction: null,
182
- closable: false,
119
+ closable: true,
183
120
  askForCloseConfirmation: false,
184
121
  closeConfirmationText: 'Are you sure you want to close this dialog?',
185
- removeFromDomOnClose: false,
186
122
  })
187
123
 
188
124
  const buttons = computed<DialogButton[]>(() => {
@@ -193,20 +129,51 @@ const buttons = computed<DialogButton[]>(() => {
193
129
  {
194
130
  label: 'Close',
195
131
  onclick: (dialog: any) => {
196
- tryToHideModal();
132
+ if (!props.askForCloseConfirmation) {
133
+ dialog.hide();
134
+ } else {
135
+ showConfirmationOnClose.value = true;
136
+ }
197
137
  },
198
138
  options: {}
199
139
  }
200
140
  ];
201
141
  });
202
142
 
143
+ const showConfirmationOnClose = ref(false);
144
+ onMounted(async () => {
145
+ //await one tick when all is mounted
146
+ await nextTick();
147
+ modal.value = new Modal(
148
+ modalEl.value,
149
+ {
150
+ closable: props.closable,
151
+ backdrop: props.clickToCloseOutside ? 'dynamic' : 'static',
152
+ onHide: async () => {
153
+ if (props.beforeCloseFunction) {
154
+ await props.beforeCloseFunction();
155
+ }
156
+ },
157
+ onShow: async () => {
158
+ if (props.beforeOpenFunction) {
159
+ await props.beforeOpenFunction();
160
+ }
161
+ },
162
+ }
163
+ );
164
+ })
165
+
166
+ onUnmounted(() => {
167
+ //destroy tooltip
168
+ modal.value?.destroy();
169
+ })
203
170
 
204
171
  function open() {
205
- modalRef.value.open();
172
+ modal.value?.show();
206
173
  }
207
174
 
208
175
  function close() {
209
- modalRef.value.hide();
176
+ modal.value?.hide();
210
177
  }
211
178
 
212
179
  defineExpose({
@@ -216,7 +183,11 @@ defineExpose({
216
183
  })
217
184
 
218
185
  function tryToHideModal() {
219
- modalRef.value?.tryToHideModal();
186
+ if (!props.askForCloseConfirmation ) {
187
+ modal.value?.hide();
188
+ } else {
189
+ showConfirmationOnClose.value = true;
190
+ }
220
191
  }
221
192
 
222
193
 
@@ -6,12 +6,12 @@
6
6
  <slot name="trigger"></slot>
7
7
  </div>
8
8
  <Teleport to="body">
9
- <div v-show="isModalOpen" v-if="!removeFromDom" @click="backdropClick" class="bg-black/50 overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full h-full md:inset-0 h-1rem max-h-full flex" >
9
+ <div v-show="isModalOpen" v-if="!removeFromDom" @click="backdropClick" v-bind="$attrs" class="bg-black/50 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-1rem max-h-full flex" >
10
10
  <!-- Modal content -->
11
- <div v-bind="$attrs" class="relative bg-lightDialogBackgorund rounded-lg shadow-sm dark:bg-darkDialogBackgorund">
11
+ <div class="relative bg-lightDialogBackgorund rounded-lg shadow-sm dark:bg-darkDialogBackgorund">
12
12
 
13
13
  <!-- Modal body -->
14
- <div class="text-lightDialogBodyText dark:text-darkDialogBodyText">
14
+ <div class="p-4 md:p-5 space-y-4 text-lightDialogBodyText dark:text-darkDialogBodyText">
15
15
  <slot ></slot>
16
16
  </div>
17
17
 
@@ -57,8 +57,7 @@ const removeFromDom = computed(() => {
57
57
  })
58
58
 
59
59
  interface DialogProps {
60
- closeByClickOutside?: boolean
61
- closeByEsc?: boolean
60
+ clickToCloseOutside?: boolean
62
61
  beforeCloseFunction?: (() => void | Promise<void>) | null
63
62
  beforeOpenFunction?: (() => void | Promise<void>) | null
64
63
  askForCloseConfirmation?: boolean
@@ -67,8 +66,7 @@ interface DialogProps {
67
66
  }
68
67
 
69
68
  const props = withDefaults(defineProps<DialogProps>(), {
70
- closeByClickOutside: true,
71
- closeByEsc: true,
69
+ clickToCloseOutside: true,
72
70
  beforeCloseFunction: null,
73
71
  beforeOpenFunction: null,
74
72
  askForCloseConfirmation: false,
@@ -111,25 +109,8 @@ function toggleModal() {
111
109
  }
112
110
  }
113
111
 
114
- function onEsc(event: KeyboardEvent) {
115
- if (event.key === 'Escape') {
116
- if (props.closeByEsc) {
117
- tryToHideModal();
118
- }
119
- }
120
- }
121
-
122
- onMounted(() => {
123
- document.addEventListener('keydown', onEsc)
124
- })
125
-
126
- onUnmounted(() => {
127
- document.removeEventListener('keydown', onEsc)
128
- })
129
-
130
-
131
112
  function backdropClick(e: MouseEvent) {
132
- if (props.closeByClickOutside && e.target === e.currentTarget) {
113
+ if (props.clickToCloseOutside && e.target === e.currentTarget) {
133
114
  tryToHideModal();
134
115
  }
135
116
  }
@@ -122,7 +122,7 @@ import { useElementSize } from '@vueuse/core'
122
122
  const props = defineProps({
123
123
  options: Array,
124
124
  modelValue: {
125
- type: Array as PropType<(string | number)[] | (string | number)>,
125
+ type: Array as PropType<(string | number)[]>,
126
126
  default: () => [],
127
127
  },
128
128
  multiple: {
@@ -28,7 +28,7 @@
28
28
  :class="{
29
29
  'hidden': !(coreStore.config?.showBrandLogoInSidebar !== false && (!iconOnlySidebarEnabled || !isSidebarIconOnly || (isSidebarIconOnly && isSidebarHovering))) }"
30
30
  />
31
- <img v-if="coreStore.config?.iconOnlySidebar?.logo" :src="loadFile(coreStore.config?.iconOnlySidebar?.logo || '')" :alt="`${ coreStore.config?.brandName } Logo`" class="af-sidebar-icon-only-logo h-8" :class="{ 'hidden': !(coreStore.config?.showBrandLogoInSidebar !== false && coreStore.config?.iconOnlySidebar?.logo && iconOnlySidebarEnabled && isSidebarIconOnly && !isSidebarHovering) }" />
31
+ <img :src="loadFile(coreStore.config?.iconOnlySidebar?.logo || '')" :alt="`${ coreStore.config?.brandName } Logo`" class="af-sidebar-icon-only-logo h-8" :class="{ 'hidden': !(coreStore.config?.showBrandLogoInSidebar !== false && coreStore.config?.iconOnlySidebar?.logo && iconOnlySidebarEnabled && isSidebarIconOnly && !isSidebarHovering) }" />
32
32
  <span
33
33
  v-if="coreStore.config?.showBrandNameInSidebar && (!iconOnlySidebarEnabled || !isSidebarIconOnly || (isSidebarIconOnly && isSidebarHovering))"
34
34
  class="af-title self-center text-lightNavbarText-size font-semibold sm:text-lightNavbarText-size whitespace-nowrap dark:text-darkSidebarText text-lightSidebarText"
@@ -18,7 +18,7 @@
18
18
  'hidden': !showDropdown,
19
19
  'left-0 md:left-auto': checkboxes && checkboxes.length > 0
20
20
  }"
21
- class="absolute z-30 mt-3 bg-lightThreeDotsMenuBodyBackground divide-y divide-gray-100 rounded-lg shadow w-max max-w-64 dark:bg-darkThreeDotsMenuBodyBackground dark:divide-gray-600 right-0">
21
+ class="absolute z-30 mt-3 bg-lightThreeDotsMenuBodyBackground divide-y divide-gray-100 rounded-lg shadow w-auto max-w-64 dark:bg-darkThreeDotsMenuBodyBackground dark:divide-gray-600 right-0">
22
22
  <ul class="py-2 text-sm text-lightThreeDotsMenuBodyText dark:text-darkThreeDotsMenuBodyText" aria-labelledby="dropdownMenuIconButton">
23
23
  <li v-for="(item, i) in threeDotsDropdownItems" :key="`dropdown-item-${i}`">
24
24
  <div
@@ -117,7 +117,7 @@ import timezone from 'dayjs/plugin/timezone';
117
117
  import {checkEmptyValues} from '@/utils';
118
118
  import { useRoute, useRouter } from 'vue-router';
119
119
  import { JsonViewer } from "vue3-json-viewer";
120
- import "vue3-json-viewer/dist/vue3-json-viewer.css";
120
+ import "vue3-json-viewer/dist/index.css";
121
121
  import type { AdminForthResourceColumnCommon } from '@/types/Common';
122
122
 
123
123
  import { useCoreStore } from '@/stores/core';
@@ -92,7 +92,6 @@ export const useCoreStore = defineStore('core', () => {
92
92
 
93
93
  // console.log('🔔 subscribeToMenuBadges', mi.badge, JSON.stringify(mi));
94
94
  if (mi.badge !== undefined) {
95
- websocket.unsubscribe(`/opentopic/update-menu-badge/${mi.itemId}`);
96
95
  websocket.subscribe(`/opentopic/update-menu-badge/${mi.itemId}`, ({ badge }) => {
97
96
  mi.badge = badge;
98
97
  });
@@ -122,6 +121,8 @@ export const useCoreStore = defineStore('core', () => {
122
121
  item.badge = badge;
123
122
  }
124
123
  });
124
+ // TODO: This thing was created for something. Find out why
125
+ // websocket.unsubscribeAll();
125
126
  subscribeToMenuBadges();
126
127
 
127
128
  }
@@ -192,7 +192,7 @@ export interface IAdminForthDataSourceConnector {
192
192
  *
193
193
  * @param resource
194
194
  */
195
- discoverFields(resource: AdminForthResource): Promise<{[key: string]: AdminForthResourceColumn}>;
195
+ discoverFields(resource: AdminForthResource, config: AdminForthConfig): Promise<{[key: string]: AdminForthResourceColumn}>;
196
196
 
197
197
 
198
198
  /**
@@ -1206,8 +1206,8 @@ interface AdminForthInputConfigCustomization {
1206
1206
  *
1207
1207
  * ```bashcreating rec
1208
1208
  * cd custom
1209
- * pnpm init -y
1210
- * pnpm install highcharts highcharts-vue
1209
+ * npm init -y
1210
+ * npm install highcharts highcharts-vue
1211
1211
  * ```
1212
1212
  *
1213
1213
  * And specify vueUsesFile in AdminForth config:
@@ -2056,6 +2056,7 @@ export interface AdminForthForeignResource extends AdminForthForeignResourceComm
2056
2056
  afterDatasourceResponse?: AfterDataSourceResponseFunction | Array<AfterDataSourceResponseFunction>,
2057
2057
  },
2058
2058
  },
2059
+ onDelete?: 'cascade' | 'setNull'
2059
2060
  }
2060
2061
 
2061
2062
  export type ShowInModernInput = {
@@ -361,12 +361,6 @@ export interface AdminForthResourceInputCommon {
361
361
  recordLabel?: (item: any) => string,
362
362
 
363
363
 
364
- /**
365
- * If true, user will not see warning about unsaved changes when tries to leave edit or create page with unsaved changes.
366
- * default is false
367
- */
368
- dontShowWarningAboutUnsavedChanges?: boolean,
369
-
370
364
  /**
371
365
  * General options for resource.
372
366
  */
@@ -213,3 +213,6 @@ export enum AlertVariant {
213
213
  }
214
214
 
215
215
 
216
+
217
+
218
+
@@ -5,13 +5,13 @@ import router from "../router";
5
5
  import { useCoreStore } from '../stores/core';
6
6
  import { useUserStore } from '../stores/user';
7
7
  import { Dropdown } from 'flowbite';
8
- import adminforth, { useAdminforth } from '../adminforth';
8
+ import adminforth from '../adminforth';
9
9
  import sanitizeHtml from 'sanitize-html'
10
10
  import debounce from 'debounce';
11
11
  import type { AdminForthResourceColumnInputCommon, Predicate } from '@/types/Common';
12
12
  import { i18nInstance } from '../i18n'
13
13
  import { useI18n } from 'vue-i18n';
14
- import { onBeforeRouteLeave } from 'vue-router';
14
+
15
15
 
16
16
 
17
17
 
@@ -616,59 +616,4 @@ export function getTimeAgoString(date: Date): string {
616
616
  const days = Math.floor(diffInSeconds / 86400);
617
617
  return `${days} ${days === 1 ? 'day' : 'days'} ago`;
618
618
  }
619
- }
620
-
621
- export class leaveGuardActiveClass {
622
- private active = false;
623
-
624
- isActive() {
625
- return this.active;
626
- }
627
-
628
- setActive(value: boolean) {
629
- this.active = value;
630
- }
631
- }
632
-
633
- export async function onBeforeRouteLeaveCreateEditViewGuard(initialValues: any, record: any, checkIfWeCanLeavePage: () => boolean, leaveGuardActive: leaveGuardActiveClass, isActive: { value: boolean }): Promise<void> {
634
-
635
- const { confirm } = useAdminforth();
636
- const { t } = useI18n();
637
-
638
- onBeforeRouteLeave(async (to, from) => {
639
- if (!isActive.value) {
640
- return true;
641
- }
642
-
643
-
644
- if (leaveGuardActive.isActive()) {
645
- return false;
646
- }
647
-
648
- if (checkIfWeCanLeavePage()) {
649
- return true;
650
- }
651
-
652
- leaveGuardActive.setActive(true);
653
-
654
- try {
655
- const { changedFields } = compareOldAndNewRecord(
656
- initialValues.value,
657
- record.value
658
- );
659
-
660
- const messageHtml =
661
- generateMessageHtmlForRecordChange(changedFields, t);
662
-
663
- const answer = await confirm({
664
- messageHtml,
665
- yes: t('Yes'),
666
- no: t('No'),
667
- });
668
-
669
- return answer;
670
- } finally {
671
- leaveGuardActive.setActive(false);
672
- }
673
- });
674
619
  }