adminforth 1.1.19 → 1.1.20
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 +33 -1
- package/dist/modules/codeInjector.js +1 -1
- package/dist/spa/index.html +2 -2
- package/dist/spa/package-lock.json +189 -1
- package/dist/spa/package.json +6 -1
- package/dist/spa/spa/src/components/ResourceListTable.vue +4 -2
- package/dist/spa/src/App.vue +76 -57
- package/dist/spa/src/components/AcceptModal.vue +1 -1
- package/dist/spa/src/components/CustomDatePicker.vue +3 -3
- package/dist/spa/src/components/CustomDateRangePicker.vue +3 -3
- package/dist/spa/src/components/CustomRangePicker.vue +148 -0
- package/dist/spa/src/components/Dropdown.vue +13 -4
- package/dist/spa/src/components/Filters.vue +55 -22
- package/dist/spa/src/components/MenuLink.vue +2 -2
- package/dist/spa/src/components/ResourceForm.vue +157 -99
- package/dist/spa/src/components/ValueRenderer.vue +11 -1
- package/dist/spa/src/router/index.ts +3 -2
- package/dist/spa/src/stores/core.ts +22 -33
- package/dist/spa/src/utils.ts +5 -3
- package/dist/spa/src/views/CreateView.vue +15 -7
- package/dist/spa/src/views/EditView.vue +36 -8
- package/dist/spa/src/views/ListView.vue +35 -23
- package/dist/spa/src/views/LoginView.vue +1 -1
- package/dist/spa/src/views/ResourceParent.vue +1 -1
- package/dist/spa/src/views/ShowView.vue +20 -9
- package/dist/spa/tailwind.config.js +5 -2
- package/index.ts +37 -1
- package/modules/codeInjector.ts +1 -1
- package/package.json +1 -1
- package/plugins/AccessControl/types.ts +2 -2
- package/spa/src/components/ResourceListTable.vue +4 -2
- package/dist/plugins/plugins/ForeignInlineListPlugin/custom/InlineList.vue +0 -248
- package/dist/spa/spa/src/components/ShowTableItem.vue +0 -14
- package/dist/spa/spa/src/views/HomeView.vue +0 -8
- package/dist/spa/src/views/HomeView.vue +0 -8
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<Teleport to="body">
|
|
3
|
-
<!-- todo exclude foreign column-->
|
|
4
|
-
<Filters
|
|
5
|
-
v-if="listResource"
|
|
6
|
-
:columns="listResource.columns.filter((c) => c.name !== listResourceRefColumn.name)"
|
|
7
|
-
v-model:filters="filters"
|
|
8
|
-
:columnsMinMax="columnsMinMax"
|
|
9
|
-
:show="filtersShow"
|
|
10
|
-
@hide="filtersShow = false"
|
|
11
|
-
/>
|
|
12
|
-
</Teleport>
|
|
13
|
-
|
|
14
|
-
<td colspan="2">
|
|
15
|
-
<div class="flex items-center gap-1">
|
|
16
|
-
<h4 v-if="listResource"
|
|
17
|
-
class="px-6 py-4"
|
|
18
|
-
>{{ listResource.label }} inline records</h4>
|
|
19
|
-
|
|
20
|
-
<button
|
|
21
|
-
@click="()=>{checkboxes = []}"
|
|
22
|
-
v-if="checkboxes.length"
|
|
23
|
-
data-tooltip-target="tooltip-remove-all"
|
|
24
|
-
data-tooltip-placement="bottom"
|
|
25
|
-
class="flex gap-1 items-center py-1 px-3 me-2 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
26
|
-
>
|
|
27
|
-
<IconBanOutline class="w-5 h-5 "/>
|
|
28
|
-
<div id="tooltip-remove-all" role="tooltip"
|
|
29
|
-
class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700">
|
|
30
|
-
Remove selection
|
|
31
|
-
<div class="tooltip-arrow" data-popper-arrow></div>
|
|
32
|
-
</div>
|
|
33
|
-
</button>
|
|
34
|
-
|
|
35
|
-
<button
|
|
36
|
-
v-if="checkboxes.length"
|
|
37
|
-
v-for="(action,i) in listResource?.options?.bulkActions"
|
|
38
|
-
:key="action.id"
|
|
39
|
-
@click="startBulkAction(action.id)"
|
|
40
|
-
class="flex gap-1 items-center py-1 px-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
41
|
-
:class="{'bg-red-100 text-red-800 border-red-400 dark:bg-red-700 dark:text-red-400 dark:border-red-400':action.state==='danger', 'bg-green-100 text-green-800 border-green-400 dark:bg-green-700 dark:text-green-400 dark:border-green-400':action.state==='success',
|
|
42
|
-
'bg-blue-100 text-blue-800 border-blue-400 dark:bg-blue-700 dark:text-blue-400 dark:border-blue-400':action.state==='active',
|
|
43
|
-
}"
|
|
44
|
-
>
|
|
45
|
-
<component
|
|
46
|
-
v-if="action.icon"
|
|
47
|
-
:is="getIcon(action.icon)"
|
|
48
|
-
class="w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"></component>
|
|
49
|
-
|
|
50
|
-
{{ `${action.label} (${checkboxes.length})` }}
|
|
51
|
-
</button>
|
|
52
|
-
|
|
53
|
-
<RouterLink v-if="listResource?.options?.allowedActions?.create"
|
|
54
|
-
:to="{
|
|
55
|
-
name: 'resource-create',
|
|
56
|
-
params: { resourceId: listResource.resourceId },
|
|
57
|
-
query: {
|
|
58
|
-
values: encodeURIComponent(JSON.stringify({[listResourceRefColumn.name]: props.record[selfPrimaryKeyColumn.name]})),
|
|
59
|
-
returnTo: $route.fullPath,
|
|
60
|
-
},
|
|
61
|
-
}"
|
|
62
|
-
class="flex items-center py-1 px-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 rounded-default"
|
|
63
|
-
>
|
|
64
|
-
<IconPlusOutline class="w-4 h-4 me-2"/>
|
|
65
|
-
Create
|
|
66
|
-
</RouterLink>
|
|
67
|
-
|
|
68
|
-
<button
|
|
69
|
-
class="flex gap-1 items-center py-1 px-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 rounded-default"
|
|
70
|
-
@click="()=>{filtersShow = !filtersShow}"
|
|
71
|
-
>
|
|
72
|
-
<IconFilterOutline class="w-4 h-4 me-2"/>
|
|
73
|
-
Filter
|
|
74
|
-
<span
|
|
75
|
-
class="bg-red-100 text-red-800 text-xs font-medium px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-red-400 border border-red-400"
|
|
76
|
-
v-if="filters.length">
|
|
77
|
-
{{ filters.length }}
|
|
78
|
-
</span>
|
|
79
|
-
</button>
|
|
80
|
-
|
|
81
|
-
</div>
|
|
82
|
-
|
|
83
|
-
<ResourceListTable
|
|
84
|
-
:resource="listResource"
|
|
85
|
-
:rows="rows"
|
|
86
|
-
@update:page="page = $event"
|
|
87
|
-
@update:sort="sort = $event"
|
|
88
|
-
@update:checkboxes="checkboxes = $event"
|
|
89
|
-
:pageSize="pageSize"
|
|
90
|
-
:totalRows="totalRows"
|
|
91
|
-
:checkboxes="checkboxes"
|
|
92
|
-
/>
|
|
93
|
-
|
|
94
|
-
</td>
|
|
95
|
-
</template>
|
|
96
|
-
|
|
97
|
-
<script setup>
|
|
98
|
-
import { callAdminForthApi } from '@/utils';
|
|
99
|
-
import { ref, onMounted, watch, computed } from 'vue';
|
|
100
|
-
import ResourceListTable from '@/components/ResourceListTable.vue';
|
|
101
|
-
import Filters from '@/components/Filters.vue';
|
|
102
|
-
import {
|
|
103
|
-
IconBanOutline,
|
|
104
|
-
IconFilterOutline,
|
|
105
|
-
IconPlusOutline,
|
|
106
|
-
} from '@iconify-prerendered/vue-flowbite';
|
|
107
|
-
|
|
108
|
-
import { getIcon } from '@/utils';
|
|
109
|
-
|
|
110
|
-
const props = defineProps(['column', 'record', 'meta', 'resource', 'adminUser']);
|
|
111
|
-
|
|
112
|
-
const listResource = ref(null);
|
|
113
|
-
const loading = ref(true);
|
|
114
|
-
|
|
115
|
-
const page = ref(1);
|
|
116
|
-
const sort = ref([]);
|
|
117
|
-
const checkboxes = ref([]);
|
|
118
|
-
const pageSize = computed(() => listResource.value?.options?.listPageSize || 10);
|
|
119
|
-
|
|
120
|
-
const rows = ref(null);
|
|
121
|
-
const totalRows = ref(0);
|
|
122
|
-
|
|
123
|
-
const filters = ref([]);
|
|
124
|
-
const filtersShow = ref(false);
|
|
125
|
-
const columnsMinMax = ref(null);
|
|
126
|
-
|
|
127
|
-
const listResourceRefColumn = computed(() => {
|
|
128
|
-
if (!listResource.value) {
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
return listResource.value.columns.find(c => c.foreignResource?.resourceId === props.resource.resourceId);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
const selfPrimaryKeyColumn = computed(() => {
|
|
135
|
-
return props.resource.columns.find(c => c.primaryKey);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
const endFilters = computed(() => {
|
|
139
|
-
if (!listResource.value) {
|
|
140
|
-
return [];
|
|
141
|
-
}
|
|
142
|
-
// get name of the column that is foreign key
|
|
143
|
-
const refColumn = listResourceRefColumn.value;
|
|
144
|
-
|
|
145
|
-
const primaryKeyColumn = selfPrimaryKeyColumn.value;
|
|
146
|
-
|
|
147
|
-
if (!refColumn) {
|
|
148
|
-
window.adminforth.alert({
|
|
149
|
-
message: `Column with foreignResource.resourceId which is equal to '${props.resource.resourceId}' not found in resource which is specified as foreighResourceId '${listResource.value.resourceId}'`,
|
|
150
|
-
variant: 'danger',
|
|
151
|
-
});
|
|
152
|
-
return [];
|
|
153
|
-
}
|
|
154
|
-
return [
|
|
155
|
-
...filters.value,
|
|
156
|
-
{
|
|
157
|
-
field: refColumn.name,
|
|
158
|
-
operator: 'eq',
|
|
159
|
-
value: props.record[primaryKeyColumn.name],
|
|
160
|
-
},
|
|
161
|
-
];
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
watch([page], async () => {
|
|
165
|
-
await getList();
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
watch([sort], async () => {
|
|
169
|
-
await getList();
|
|
170
|
-
}, {deep: true});
|
|
171
|
-
|
|
172
|
-
watch([filters], async () => {
|
|
173
|
-
page.value = 1;
|
|
174
|
-
checkboxes.value = [];
|
|
175
|
-
await getList();
|
|
176
|
-
}, {deep: true});
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
async function startBulkAction(actionId) {
|
|
180
|
-
const data = await callAdminForthApi({
|
|
181
|
-
path: '/start_bulk_action',
|
|
182
|
-
method: 'POST',
|
|
183
|
-
body: {
|
|
184
|
-
resourceId: listResource.value.resourceId,
|
|
185
|
-
actionId: actionId,
|
|
186
|
-
recordIds: checkboxes.value
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
if (data?.status === 'success') {
|
|
190
|
-
checkboxes.value = [];
|
|
191
|
-
}
|
|
192
|
-
await getList();
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
async function getList() {
|
|
196
|
-
rows.value = null;
|
|
197
|
-
console.log('getList', listResource.value)
|
|
198
|
-
const data = await callAdminForthApi({
|
|
199
|
-
path: '/get_resource_data',
|
|
200
|
-
method: 'POST',
|
|
201
|
-
body: {
|
|
202
|
-
source: 'list',
|
|
203
|
-
resourceId: listResource.value.resourceId,
|
|
204
|
-
limit: pageSize.value,
|
|
205
|
-
offset: (page.value - 1) * pageSize.value,
|
|
206
|
-
filters: endFilters.value,
|
|
207
|
-
sort: sort.value,
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
if (data.error) {
|
|
212
|
-
window.adminforth.alert({
|
|
213
|
-
message: data.error,
|
|
214
|
-
variant: 'danger',
|
|
215
|
-
timeout: 'unlimited',
|
|
216
|
-
});
|
|
217
|
-
rows.value = [];
|
|
218
|
-
totalRows.value = 0;
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
rows.value = data.data?.map(row => {
|
|
223
|
-
row._primaryKeyValue = row[listResource.value.columns.find(c => c.primaryKey).name];
|
|
224
|
-
return row;
|
|
225
|
-
});
|
|
226
|
-
totalRows.value = data.total;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
onMounted( async () => {
|
|
230
|
-
loading.value = true;
|
|
231
|
-
const foreighResourceId = props.meta.foreignResourceId;
|
|
232
|
-
listResource.value = (await callAdminForthApi({
|
|
233
|
-
path: `/plugin/${props.meta.pluginInstanceId}/get_resource`,
|
|
234
|
-
method: 'POST',
|
|
235
|
-
body: {},
|
|
236
|
-
})).resource;
|
|
237
|
-
columnsMinMax.value = await callAdminForthApi({
|
|
238
|
-
path: '/get_min_max_for_columns',
|
|
239
|
-
method: 'POST',
|
|
240
|
-
body: {
|
|
241
|
-
resourceId: foreighResourceId,
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
loading.value = false;
|
|
245
|
-
await getList();
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
</script>
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<td class="px-6 py-4 whitespace-nowrap">
|
|
3
|
-
{{ column.label }}
|
|
4
|
-
</td>
|
|
5
|
-
<td class="px-6 py-4 whitespace-nowrap whitespace-pre-wrap">
|
|
6
|
-
<ValueRenderer :column="column" :row="row" />
|
|
7
|
-
</td>
|
|
8
|
-
</template>
|
|
9
|
-
|
|
10
|
-
<script setup>
|
|
11
|
-
import ValueRenderer from '@/components/ValueRenderer.vue';
|
|
12
|
-
|
|
13
|
-
defineProps(['column', 'row']);
|
|
14
|
-
</script>
|