adminforth 1.3.54-next.3 → 1.3.54-next.30

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 (135) hide show
  1. package/dist/auth.js +42 -56
  2. package/dist/auth.js.map +1 -0
  3. package/dist/basePlugin.js +1 -0
  4. package/dist/basePlugin.js.map +1 -0
  5. package/dist/dataConnectors/baseConnector.js +108 -122
  6. package/dist/dataConnectors/baseConnector.js.map +1 -0
  7. package/dist/dataConnectors/clickhouse.js +132 -150
  8. package/dist/dataConnectors/clickhouse.js.map +1 -0
  9. package/dist/dataConnectors/mongo.js +75 -101
  10. package/dist/dataConnectors/mongo.js.map +1 -0
  11. package/dist/dataConnectors/postgres.js +124 -143
  12. package/dist/dataConnectors/postgres.js.map +1 -0
  13. package/dist/dataConnectors/sqlite.js +113 -130
  14. package/dist/dataConnectors/sqlite.js.map +1 -0
  15. package/dist/index.js +197 -217
  16. package/dist/index.js.map +1 -0
  17. package/dist/modules/codeInjector.js +480 -486
  18. package/dist/modules/codeInjector.js.map +1 -0
  19. package/dist/modules/configValidator.js +31 -22
  20. package/dist/modules/configValidator.js.map +1 -0
  21. package/dist/modules/operationalResource.js +50 -70
  22. package/dist/modules/operationalResource.js.map +1 -0
  23. package/dist/modules/restApi.js +104 -116
  24. package/dist/modules/restApi.js.map +1 -0
  25. package/dist/modules/styleGenerator.js +1 -0
  26. package/dist/modules/styleGenerator.js.map +1 -0
  27. package/dist/modules/styles.js +1 -0
  28. package/dist/modules/styles.js.map +1 -0
  29. package/dist/modules/utils.js +1 -0
  30. package/dist/modules/utils.js.map +1 -0
  31. package/dist/plugins/audit-log/types.js +2 -0
  32. package/dist/plugins/audit-log/types.js.map +1 -0
  33. package/dist/plugins/chat-gpt/types.js +2 -0
  34. package/dist/plugins/chat-gpt/types.js.map +1 -0
  35. package/dist/plugins/email-password-reset/types.js +2 -0
  36. package/dist/plugins/email-password-reset/types.js.map +1 -0
  37. package/dist/plugins/foreign-inline-list/types.js +2 -0
  38. package/dist/plugins/foreign-inline-list/types.js.map +1 -0
  39. package/dist/plugins/import-export/types.js +2 -0
  40. package/dist/plugins/import-export/types.js.map +1 -0
  41. package/dist/plugins/rich-editor/custom/async-queue.js +29 -0
  42. package/dist/plugins/rich-editor/custom/async-queue.js.map +1 -0
  43. package/dist/plugins/rich-editor/dist/async-queue.js +41 -0
  44. package/dist/plugins/rich-editor/dist/custom/async-queue.js +29 -0
  45. package/dist/plugins/rich-editor/dist/custom/async-queue.js.map +1 -0
  46. package/dist/plugins/rich-editor/types.js +16 -0
  47. package/dist/plugins/rich-editor/types.js.map +1 -0
  48. package/dist/plugins/two-factors-auth/types.js +2 -0
  49. package/dist/plugins/two-factors-auth/types.js.map +1 -0
  50. package/dist/plugins/upload/types.js +2 -0
  51. package/dist/plugins/upload/types.js.map +1 -0
  52. package/dist/servers/express.js +30 -42
  53. package/dist/servers/express.js.map +1 -0
  54. package/dist/types/AdminForthConfig.js +1 -0
  55. package/dist/types/AdminForthConfig.js.map +1 -0
  56. package/dist/types/FrontendAPI.js +1 -0
  57. package/dist/types/FrontendAPI.js.map +1 -0
  58. package/package.json +7 -4
  59. package/auth.ts +0 -140
  60. package/basePlugin.ts +0 -70
  61. package/dataConnectors/baseConnector.ts +0 -216
  62. package/dataConnectors/clickhouse.ts +0 -341
  63. package/dataConnectors/mongo.ts +0 -202
  64. package/dataConnectors/postgres.ts +0 -306
  65. package/dataConnectors/sqlite.ts +0 -254
  66. package/index.ts +0 -428
  67. package/modules/codeInjector.ts +0 -736
  68. package/modules/configValidator.ts +0 -571
  69. package/modules/operationalResource.ts +0 -98
  70. package/modules/restApi.ts +0 -718
  71. package/modules/styleGenerator.ts +0 -55
  72. package/modules/styles.ts +0 -126
  73. package/modules/utils.ts +0 -472
  74. package/servers/express.ts +0 -259
  75. package/spa/.eslintrc.cjs +0 -14
  76. package/spa/README.md +0 -39
  77. package/spa/env.d.ts +0 -1
  78. package/spa/index.html +0 -23
  79. package/spa/package-lock.json +0 -4573
  80. package/spa/package.json +0 -49
  81. package/spa/postcss.config.js +0 -6
  82. package/spa/public/assets/favicon.png +0 -0
  83. package/spa/src/App.vue +0 -418
  84. package/spa/src/assets/base.css +0 -2
  85. package/spa/src/assets/logo.svg +0 -19
  86. package/spa/src/components/AcceptModal.vue +0 -45
  87. package/spa/src/components/Breadcrumbs.vue +0 -41
  88. package/spa/src/components/BreadcrumbsWithButtons.vue +0 -26
  89. package/spa/src/components/CustomDatePicker.vue +0 -176
  90. package/spa/src/components/CustomDateRangePicker.vue +0 -218
  91. package/spa/src/components/CustomRangePicker.vue +0 -156
  92. package/spa/src/components/Dropdown.vue +0 -168
  93. package/spa/src/components/Filters.vue +0 -222
  94. package/spa/src/components/HelloWorld.vue +0 -17
  95. package/spa/src/components/MenuLink.vue +0 -27
  96. package/spa/src/components/ResourceForm.vue +0 -290
  97. package/spa/src/components/ResourceListTable.vue +0 -460
  98. package/spa/src/components/SingleSkeletLoader.vue +0 -13
  99. package/spa/src/components/SkeleteLoader.vue +0 -23
  100. package/spa/src/components/ThreeDotsMenu.vue +0 -43
  101. package/spa/src/components/Toast.vue +0 -78
  102. package/spa/src/components/ValueRenderer.vue +0 -114
  103. package/spa/src/components/icons/IconCalendar.vue +0 -5
  104. package/spa/src/components/icons/IconCommunity.vue +0 -7
  105. package/spa/src/components/icons/IconDocumentation.vue +0 -7
  106. package/spa/src/components/icons/IconEcosystem.vue +0 -7
  107. package/spa/src/components/icons/IconSupport.vue +0 -7
  108. package/spa/src/components/icons/IconTime.vue +0 -5
  109. package/spa/src/components/icons/IconTooling.vue +0 -19
  110. package/spa/src/composables/useFrontendApi.ts +0 -26
  111. package/spa/src/composables/useStores.ts +0 -131
  112. package/spa/src/index.scss +0 -31
  113. package/spa/src/main.ts +0 -18
  114. package/spa/src/router/index.ts +0 -59
  115. package/spa/src/spa_types/core.ts +0 -53
  116. package/spa/src/stores/core.ts +0 -148
  117. package/spa/src/stores/filters.ts +0 -27
  118. package/spa/src/stores/modal.ts +0 -48
  119. package/spa/src/stores/toast.ts +0 -31
  120. package/spa/src/stores/user.ts +0 -72
  121. package/spa/src/utils.ts +0 -149
  122. package/spa/src/views/CreateView.vue +0 -167
  123. package/spa/src/views/EditView.vue +0 -170
  124. package/spa/src/views/ListView.vue +0 -279
  125. package/spa/src/views/LoginView.vue +0 -192
  126. package/spa/src/views/ResourceParent.vue +0 -17
  127. package/spa/src/views/ShowView.vue +0 -186
  128. package/spa/tailwind.config.js +0 -17
  129. package/spa/tsconfig.app.json +0 -14
  130. package/spa/tsconfig.json +0 -11
  131. package/spa/tsconfig.node.json +0 -19
  132. package/spa/vite.config.ts +0 -56
  133. package/tsconfig.json +0 -112
  134. package/types/AdminForthConfig.ts +0 -1762
  135. package/types/FrontendAPI.ts +0 -143
@@ -1,114 +0,0 @@
1
- <template>
2
- <div>
3
- <span @click="(e)=>{e.stopPropagation()}" v-if="column.foreignResource">
4
- <RouterLink v-if="record[column.name]" class="font-medium text-lightPrimary dark:text-darkPrimary hover:brightness-110 whitespace-nowrap"
5
- :to="{ name: 'resource-show', params: { resourceId: column.foreignResource.resourceId, primaryKey: record[column.name].pk } }">
6
- {{ record[column.name].label }}
7
- </RouterLink>
8
- <div v-else>
9
- <span class="text-gray-400">-</span>
10
- </div>
11
- </span>
12
-
13
- <span v-else-if="column.type === 'boolean'">
14
- <span v-if="record[column.name]" class="bg-green-100 text-green-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-green-400 border border-green-400">Yes</span>
15
- <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
- </span>
17
- <span v-else-if="column.enum">
18
- {{ checkEmptyValues(column.enum.find(e => e.value === record[column.name])?.label || record[column.name], route.meta.type) }}
19
- </span>
20
- <span v-else-if="column.type === 'datetime'" class="whitespace-nowrap">
21
- {{ checkEmptyValues(formatDateTime(record[column.name]),route.meta.type) }}
22
- </span>
23
- <span v-else-if="column.type === 'date'" class="whitespace-nowrap">
24
- {{ checkEmptyValues(formatDate(record[column.name]),route.meta.type) }}
25
- </span>
26
- <span v-else-if="column.type === 'time'" class="whitespace-nowrap">
27
- {{ checkEmptyValues(formatTime(record[column.name]),route.meta.type) }}
28
- </span>
29
- <span v-else-if="column.type === 'richtext'">
30
- <div v-html="protectAgainstXSS(record[column.name])" class="allow-lists"></div>
31
- </span>
32
- <span v-else>
33
- {{ checkEmptyValues(record[column.name],route.meta.type) }}
34
- </span>
35
- </div>
36
- </template>
37
-
38
-
39
- <script setup>
40
-
41
- import dayjs from 'dayjs';
42
- import utc from 'dayjs/plugin/utc';
43
- import timezone from 'dayjs/plugin/timezone';
44
- import {checkEmptyValues} from '@/utils';
45
- import { useRoute, useRouter } from 'vue-router';
46
- import sanitizeHtml from 'sanitize-html';
47
-
48
-
49
- import { useCoreStore } from '@/stores/core';
50
-
51
- const coreStore = useCoreStore();
52
- const route = useRoute();
53
-
54
-
55
- dayjs.extend(utc);
56
- dayjs.extend(timezone);
57
-
58
- const props = defineProps({
59
- column: Object,
60
- record: Object
61
- });
62
-
63
- function protectAgainstXSS(value) {
64
- return sanitizeHtml(value, {
65
- allowedTags: [
66
- "address", "article", "aside", "footer", "header", "h1", "h2", "h3", "h4",
67
- "h5", "h6", "hgroup", "main", "nav", "section", "blockquote", "dd", "div",
68
- "dl", "dt", "figcaption", "figure", "hr", "li", "main", "ol", "p", "pre",
69
- "ul", "a", "abbr", "b", "bdi", "bdo", "br", "cite", "code", "data", "dfn",
70
- "em", "i", "kbd", "mark", "q", "rb", "rp", "rt", "rtc", "ruby", "s", "samp",
71
- "small", "span", "strong", "sub", "sup", "time", "u", "var", "wbr", "caption",
72
- "col", "colgroup", "table", "tbody", "td", "tfoot", "th", "thead", "tr", 'img'
73
- ],
74
- allowedAttributes: {
75
- 'li': [ 'data-list' ],
76
- 'img': [ 'src', 'srcset', 'alt', 'title', 'width', 'height', 'loading' ]
77
- }
78
- });
79
- }
80
-
81
-
82
- function formatDateTime(date) {
83
- if (!date) return '';
84
- return dayjs.utc(date).local().format(`${coreStore.config?.datesFormat} ${coreStore.config?.timeFormat}` || 'YYYY-MM-DD HH:mm:ss');
85
- }
86
-
87
- function formatDate(date) {
88
- if (!date) return '';
89
- return dayjs.utc(date).local().format(coreStore.config?.datesFormat || 'YYYY-MM-DD');
90
- }
91
-
92
- function formatTime(time) {
93
- if (!time) return '';
94
- return dayjs(`0000-00-00 ${time}`).format(coreStore.config?.timeFormat || 'HH:mm:ss');
95
- }
96
- </script>
97
-
98
- <style lang="scss">
99
-
100
- .allow-lists {
101
- ol {
102
- list-style-type: decimal;
103
- padding-left: 1.5em;
104
-
105
- li[data-list="bullet"] {
106
- list-style-type: disc;
107
- }
108
- li[data-list="ordered"] {
109
- list-style-type: decimal;
110
- }
111
- }
112
-
113
- }
114
- </style>
@@ -1,5 +0,0 @@
1
- <template>
2
- <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
3
- <path d="M20 4a2 2 0 0 0-2-2h-2V1a1 1 0 0 0-2 0v1h-3V1a1 1 0 0 0-2 0v1H6V1a1 1 0 0 0-2 0v1H2a2 2 0 0 0-2 2v2h20V4ZM0 18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8H0v10Zm5-8h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2Z"/>
4
- </svg>
5
- </template>
@@ -1,7 +0,0 @@
1
- <template>
2
- <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
3
- <path
4
- d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
5
- />
6
- </svg>
7
- </template>
@@ -1,7 +0,0 @@
1
- <template>
2
- <svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
3
- <path
4
- d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
5
- />
6
- </svg>
7
- </template>
@@ -1,7 +0,0 @@
1
- <template>
2
- <svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
3
- <path
4
- d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
5
- />
6
- </svg>
7
- </template>
@@ -1,7 +0,0 @@
1
- <template>
2
- <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
3
- <path
4
- d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
5
- />
6
- </svg>
7
- </template>
@@ -1,5 +0,0 @@
1
- <template>
2
- <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24">
3
- <path fill-rule="evenodd" d="M2 12C2 6.477 6.477 2 12 2s10 4.477 10 10-4.477 10-10 10S2 17.523 2 12Zm11-4a1 1 0 1 0-2 0v4a1 1 0 0 0 .293.707l3 3a1 1 0 0 0 1.414-1.414L13 11.586V8Z" clip-rule="evenodd"></path>
4
- </svg>
5
- </template>
@@ -1,19 +0,0 @@
1
- <!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
2
- <template>
3
- <svg
4
- xmlns="http://www.w3.org/2000/svg"
5
- xmlns:xlink="http://www.w3.org/1999/xlink"
6
- aria-hidden="true"
7
- role="img"
8
- class="iconify iconify--mdi"
9
- width="24"
10
- height="24"
11
- preserveAspectRatio="xMidYMid meet"
12
- viewBox="0 0 24 24"
13
- >
14
- <path
15
- d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
16
- fill="currentColor"
17
- ></path>
18
- </svg>
19
- </template>
@@ -1,26 +0,0 @@
1
- export function showSuccesTost(message: string) {
2
- window.adminforth.alert({ message, variant: 'success' });
3
- return message;
4
- }
5
-
6
- export function showWarningTost(message: string) {
7
- window.adminforth.alert({ message, variant: 'warning' });
8
- return message;
9
- }
10
-
11
- export function showErrorTost(message: string, timeout?: number) {
12
- window.adminforth.alert({ message, variant: 'danger', timeout: timeout || 30});
13
- return message;
14
- }
15
-
16
-
17
- const useFrontendApi = () => {
18
- return {
19
- showSuccesTost,
20
- showWarningTost,
21
- showErrorTost
22
- }
23
- }
24
-
25
-
26
- export default useFrontendApi;
@@ -1,131 +0,0 @@
1
- import type { FrontendAPIInterface, ConfirmParams, AlertParams, } from '../types/FrontendAPI';
2
- import type { AdminForthFilterOperators } from '@/types/AdminForthConfig';
3
- import { useToastStore } from '../stores/toast';
4
- import { useModalStore } from '../stores/modal';
5
- import { useCoreStore } from '@/stores/core';
6
- import { useFiltersStore } from '@/stores/filters';
7
- import router from '@/router'
8
- import type { AdminForthResourceColumn } from '@/types/AdminForthConfig';
9
-
10
- type FilterParams = {
11
- /**
12
- * Field of resource to filter
13
- */
14
- field: string;
15
- /**
16
- * Operator of filter
17
- */
18
- operator: AdminForthFilterOperators;
19
- /**
20
- * Value of filter
21
- */
22
- value: string | number | boolean ;
23
- }
24
-
25
- declare global {
26
- interface Window {
27
- adminforth: FrontendAPIInterface;
28
- }
29
- }
30
-
31
- export class FrontendAPI {
32
- private toastStore:any
33
- private modalStore:any
34
- private filtersStore:any
35
- private coreStore:any
36
- init() {
37
- if (window.adminforth) {
38
- throw new Error('adminforth already initialized');
39
- }
40
- this.toastStore = useToastStore();
41
- this.modalStore = useModalStore();
42
-
43
- window.adminforth = {
44
- confirm: this.confirm.bind(this),
45
- alert: this.alert.bind(this),
46
-
47
- list: {
48
- refresh: () => {/* will be redefined in list*/},
49
- closeThreeDotsDropdown: () => {/* will be redefined in list*/},
50
- closeUserMenuDropdown: () => {/* will be redefined in list*/},
51
- setFilter: () => this.setListFilter.bind(this),
52
- updateFilter: () => this.updateListFilter.bind(this),
53
- clearFilters: () => this.clearListFilters.bind(this),
54
- }
55
- };
56
- }
57
-
58
- confirm(params: ConfirmParams): Promise<void> {
59
- return new Promise((resolve, reject) => {
60
- this.modalStore.setModalContent({
61
- content: params.message,
62
- acceptText: params.yes || 'Yes',
63
- cancelText: params.no || 'Cancel'
64
- })
65
- this.modalStore.onAcceptFunction = resolve
66
- this.modalStore.onCancelFunction = reject
67
- this.modalStore.togleModal()
68
- })
69
- }
70
-
71
- alert(params: AlertParams): void {
72
- this.toastStore.addToast({
73
- message: params.message,
74
- messageHtml: params.messageHtml,
75
- variant: params.variant,
76
- timeout: params.timeout
77
- })
78
- }
79
-
80
- listFilterValidation(filter: FilterParams): boolean {
81
- if(router.currentRoute.value.meta.type !== 'list'){
82
- throw new Error(`Cannot use ${this.setListFilter.name} filter on a list page`)
83
- } else {
84
- if(!this.coreStore) this.coreStore = useCoreStore()
85
- console.log(this.coreStore.resourceColumnsWithFilters,'core store')
86
- const filterField = this.coreStore.resourceColumnsWithFilters.find((col: AdminForthResourceColumn) => col.name === filter.field)
87
- if(!filterField){
88
- throw new Error(`Field ${filter.field} is not available for filtering`)
89
- }
90
-
91
- }
92
- return true
93
- }
94
-
95
- setListFilter(filter: FilterParams): void {
96
- if(this.listFilterValidation(filter)){
97
- this.filtersStore = useFiltersStore()
98
- if(this.filtersStore.filters.some((f) => {return f.field === filter.field && f.operator === filter.operator})){
99
- throw new Error(`Filter ${filter.field} with operator ${filter.operator} already exists`)
100
- } else {
101
- this.filtersStore.setFilter(filter)
102
- }
103
- }
104
- }
105
-
106
- clearListFilters(): void {
107
- this.filtersStore = useFiltersStore()
108
- this.filtersStore.clearFilters()
109
- }
110
-
111
- updateListFilter(filter: FilterParams): void {
112
- if(this.listFilterValidation(filter)){
113
- this.filtersStore = useFiltersStore()
114
- const index = this.filtersStore.filters.findIndex((f: FilterParams) => f.field === filter.field)
115
- if(index === -1) {
116
- this.filtersStore.setFilter(filter)
117
- } else {
118
- const filters = [...this.filtersStore.filters];
119
- if (filter.value === undefined) {
120
- filters.splice(index, 1);
121
- } else {
122
- filters[index] = filter;
123
- }
124
- this.filtersStore.setFilters(filters);
125
- }
126
- }
127
- }
128
-
129
-
130
-
131
- }
@@ -1,31 +0,0 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
-
5
-
6
- // @layer base {
7
- // /* width */
8
- // ::-webkit-scrollbar {
9
- // @apply w-2 p-2
10
- // }
11
-
12
- // /* Track */
13
- // ::-webkit-scrollbar-track {
14
- // @apply bg-inherit
15
- // }
16
-
17
- // /* Handle */
18
- // ::-webkit-scrollbar-thumb {
19
- // @apply bg-gray-200 dark:bg-gray-600 rounded-xl
20
- // }
21
-
22
- // /* Handle on hover */
23
- // ::-webkit-scrollbar-thumb:hover {
24
- // @apply bg-gray-700
25
- // }
26
- // }
27
-
28
-
29
- *{
30
- -moz-user-select: none;
31
- }
package/spa/src/main.ts DELETED
@@ -1,18 +0,0 @@
1
- import { createApp } from 'vue'
2
- import { createPinia } from 'pinia'
3
- /* IMPORTANT:ADMINFORTH IMPORTS */
4
-
5
-
6
- import App from './App.vue'
7
- import router from './router'
8
-
9
- export const app = createApp(App)
10
- /* IMPORTANT:ADMINFORTH COMPONENT REGISTRATIONS */
11
-
12
-
13
- app.use(createPinia())
14
- app.use(router)
15
-
16
- /* IMPORTANT:ADMINFORTH CUSTOM USES */
17
-
18
- app.mount('#app')
@@ -1,59 +0,0 @@
1
- import { createRouter, createWebHistory } from 'vue-router';
2
- import ResourceParent from '@/views/ResourceParent.vue';
3
-
4
- /* IMPORTANT:ADMINFORTH ROUTES IMPORTS */
5
-
6
- const router = createRouter({
7
- history: createWebHistory(import.meta.env.BASE_URL),
8
- routes: [
9
- {
10
- path: '/login',
11
- name: 'login',
12
- component: () => import('@/views/LoginView.vue'),
13
- meta: { title: 'login' },
14
- beforeEnter: async (to, from, next) => {
15
- if(localStorage.getItem('isAuthorized') === 'true'){
16
- next({name: 'home'})
17
- } else {
18
- next()
19
- }
20
- }
21
- },
22
- {
23
- path: '/resource/:resourceId',
24
- component: ResourceParent,
25
- name: 'resource',
26
- children: [
27
- {
28
- path: '',
29
- component: () => import('@/views/ListView.vue'),
30
- name: 'resource-list',
31
- meta: { title: 'list',type: 'list' }
32
- },
33
- {
34
- path: 'show/:primaryKey',
35
- component: () => import('@/views/ShowView.vue'),
36
- name: 'resource-show',
37
- meta: { title: 'show', type: 'show'}
38
-
39
- },
40
- {
41
- path: 'edit/:primaryKey',
42
- component: () => import('@/views/EditView.vue'),
43
- name: 'resource-edit',
44
- meta: { title: 'edit', type: 'edit'}
45
- },
46
- {
47
- path: 'create',
48
- component: () => import('@/views/CreateView.vue'),
49
- name: 'resource-create',
50
- meta: { title: 'create', type: 'create'}
51
-
52
- },
53
- ]
54
- },
55
- /* IMPORTANT:ADMINFORTH ROUTES */
56
- ]
57
- })
58
-
59
- export default router
@@ -1,53 +0,0 @@
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
- timeFormat: string,
28
- usernameField: string,
29
- usernameFieldName?: string,
30
- deleteConfirmation?: boolean,
31
- auth?: {
32
- resourceId: string,
33
- usernameField: string,
34
- passwordHashField: string,
35
- loginBackgroundImage: string,
36
- loginBackgroundPosition: string,
37
- userFullnameField: string,
38
- },
39
- emptyFieldPlaceholder?: {
40
- show: string,
41
- list: string,
42
-
43
- } | string,
44
- }
45
-
46
-
47
- export type AllowedActions = {
48
- show: boolean,
49
- create: boolean,
50
- edit: boolean,
51
- delete: boolean,
52
- }
53
-
@@ -1,148 +0,0 @@
1
- import { ref, computed } from 'vue'
2
- import { defineStore } from 'pinia'
3
- import { callAdminForthApi } from '@/utils';
4
- import type { AdminForthResource, AdminForthResourceColumn } from '@/types/AdminForthConfig';
5
- import type { Ref } from 'vue'
6
-
7
- export const useCoreStore = defineStore('core', () => {
8
- const resourceById: Ref<Object> = ref({});
9
- const menu = ref([]);
10
- const config = ref({});
11
- const record: Ref<any | null> = ref({});
12
- const resource: Ref<AdminForthResource | null> = ref(null);
13
-
14
- const resourceColumnsWithFilters = computed(() => {
15
- if (!resource.value) {
16
- return [];
17
- }
18
- return resource.value.columns.filter((col: AdminForthResourceColumn) => col.showIn?.includes('filter'));
19
- })
20
-
21
- const resourceOptions = ref(null);
22
- const resourceColumnsError = ref('');
23
- const resourceColumnsId = ref(null);
24
- const adminUser = ref(null);
25
-
26
- async function fetchMenuAndResource() {
27
- const resp = await callAdminForthApi({
28
- path: '/get_base_config',
29
- method: 'GET',
30
- });
31
- if(!resp){
32
- return
33
- }
34
- menu.value = resp.menu;
35
- resourceById.value = resp.resources.reduce((acc: Object, resource: AdminForthResource) => {
36
- acc[resource.resourceId] = resource;
37
- return acc;
38
- }, {});
39
- config.value = resp.config;
40
- adminUser.value = resp.user;
41
- console.log('🌍 AdminForth v', resp.version);
42
- }
43
-
44
- async function fetchRecord({ resourceId, primaryKey }) {
45
- record.value = null;
46
-
47
- if (!resource.value) {
48
- throw new Error('Columns not fetched yet');
49
- }
50
- const col = resource.value.columns.find((col: AdminForthResourceColumn) => col.primaryKey);
51
- if (!col) {
52
- throw new Error(`Primary key not found in resource ${resourceId}`);
53
- }
54
-
55
- const respData = await callAdminForthApi({
56
- path: '/get_resource_data',
57
- method: 'POST',
58
- body: {
59
- source: 'show',
60
- resourceId: resourceId,
61
- filters: [
62
- {
63
- field: col.name,
64
- operator: 'eq',
65
- value: primaryKey
66
- }
67
- ],
68
- sort: [],
69
- limit: 1,
70
- offset: 0
71
- }
72
- });
73
-
74
- if (respData.error) {
75
- window.adminforth.alert({
76
- message: respData.error,
77
- variant: 'danger',
78
- timeout: 30,
79
- });
80
- record.value = {};
81
- } else {
82
- record.value = respData.data[0];
83
- }
84
-
85
- }
86
-
87
- async function fetchResourceFull({ resourceId }: { resourceId: string }) {
88
- if (resourceColumnsId.value === resourceId && resource.value) {
89
- // already fetched
90
- return;
91
- }
92
- resourceColumnsId.value = resourceId;
93
- resourceColumnsError.value = '';
94
- const res = await callAdminForthApi({
95
- path: '/get_resource',
96
- method: 'POST',
97
- body: {
98
- resourceId,
99
- }
100
- });
101
- if (res.error) {
102
- resourceColumnsError.value = res.error;
103
- } else {
104
- resourceById.value[resourceId] = res.resource;
105
- resource.value = res.resource;
106
- resourceOptions.value = res.resource.options;
107
- }
108
- }
109
-
110
- async function getPublicConfig() {
111
- const res = await callAdminForthApi({
112
- path: '/get_public_config',
113
- method: 'GET',
114
- });
115
- config.value = {...config.value, ...res};
116
- }
117
-
118
-
119
-
120
- const username = computed(() => {
121
- const usernameField = config.value.usernameField;
122
- return adminUser.value && adminUser.value[usernameField];
123
- });
124
-
125
- const userFullname = computed(() => {
126
- const userFullnameField = config.value.userFullnameField;
127
- return adminUser.value && adminUser.value[userFullnameField];
128
- })
129
-
130
-
131
- return {
132
- config,
133
- resourceById,
134
- menu,
135
- username,
136
- userFullname,
137
- getPublicConfig,
138
- fetchMenuAndResource,
139
- fetchRecord,
140
- record,
141
- fetchResourceFull,
142
- resourceColumnsError,
143
- resourceOptions,
144
- resource,
145
- adminUser,
146
- resourceColumnsWithFilters
147
- }
148
- })