@simitgroup/simpleapp-generator 1.6.4-c-alpha → 1.6.4-e-alpha
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/buildinschemas/documentevent.d.ts +3 -0
- package/dist/buildinschemas/documentevent.d.ts.map +1 -0
- package/dist/buildinschemas/documentevent.js +38 -0
- package/dist/buildinschemas/documentevent.js.map +1 -0
- package/dist/buildinschemas/index.d.ts +2 -0
- package/dist/buildinschemas/index.d.ts.map +1 -1
- package/dist/buildinschemas/index.js +5 -1
- package/dist/buildinschemas/index.js.map +1 -1
- package/dist/buildinschemas/tenant.d.ts.map +1 -1
- package/dist/buildinschemas/tenant.js +9 -0
- package/dist/buildinschemas/tenant.js.map +1 -1
- package/dist/buildinschemas/webhook.d.ts.map +1 -1
- package/dist/buildinschemas/webhook.js +21 -3
- package/dist/buildinschemas/webhook.js.map +1 -1
- package/dist/buildinschemas/webhookhistory.d.ts +3 -0
- package/dist/buildinschemas/webhookhistory.d.ts.map +1 -0
- package/dist/buildinschemas/webhookhistory.js +44 -0
- package/dist/buildinschemas/webhookhistory.js.map +1 -0
- package/dist/framework.js +1 -1
- package/dist/framework.js.map +1 -1
- package/dist/generate.js +1 -1
- package/dist/generate.js.map +1 -1
- package/package.json +1 -1
- package/src/buildinschemas/documentevent.ts +36 -0
- package/src/buildinschemas/index.ts +3 -1
- package/src/buildinschemas/tenant.ts +9 -0
- package/src/buildinschemas/webhook.ts +22 -3
- package/src/buildinschemas/webhookhistory.ts +42 -0
- package/src/framework.ts +1 -1
- package/src/generate.ts +1 -1
- package/templates/basic/nest/apischema.ts.eta +6 -2
- package/templates/basic/nest/controller.ts.eta +4 -3
- package/templates/basic/nest/default.ts.eta +6 -5
- package/templates/basic/nuxt/default.ts.eta +2 -0
- package/templates/basic/nuxt/simpleapp.generate.client.ts.eta +1 -6
- package/templates/nest/src/simpleapp/apischemas/index.ts._eta +17 -0
- package/templates/nest/src/simpleapp/generate/commons/audittrail.service.ts.eta +37 -7
- package/templates/nest/src/simpleapp/generate/commons/runwebhook.service.ts.eta +39 -20
- package/templates/nest/src/simpleapp/generate/commons/user.context.ts.eta +60 -41
- package/templates/nest/src/simpleapp/generate/controllers/simpleapp.controller.ts.eta +3 -3
- package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +100 -34
- package/templates/nest/src/simpleapp/profile/profile.controller.ts.eta +16 -8
- package/templates/nest/src/simpleapp/profile/profile.service.ts.eta +7 -0
- package/templates/nest/src/simpleapp/simpleapp.module.ts.eta +3 -3
- package/templates/nest/src/simpleapp/types/index.ts._eta +14 -0
- package/templates/nuxt/app.vue.eta +9 -7
- package/templates/nuxt/components/image/ImageAvatar.vue.eta._vue +7 -14
- package/templates/nuxt/components/list/ListView.vue.eta +97 -111
- package/templates/nuxt/components/renderer/RendererDocHistories.vue.eta +102 -42
- package/templates/nuxt/components/search/SearchBox.vue._eta +371 -0
- package/templates/nuxt/components/search/SearchBoxBefore.vue._eta +11 -0
- package/templates/nuxt/components/search/SearchBoxProduct.vue._eta +26 -0
- package/templates/nuxt/components/simpleApp/SimpleAppAutocomplete.vue.eta +24 -3
- package/templates/nuxt/components/simpleApp/SimpleAppCalendarInput.vue.eta +1 -0
- package/templates/nuxt/components/simpleApp/SimpleAppChildrenList.vue.eta +10 -5
- package/templates/nuxt/components/simpleApp/SimpleAppFormToolBar.vue._eta +4 -3
- package/templates/nuxt/components/user/UserTenantPicker.vue.eta +18 -16
- package/templates/nuxt/composables/getOpenApi.generate.ts.eta +6 -49
- package/templates/nuxt/composables/stringHelper.generate.ts.eta +2 -2
- package/templates/nuxt/middleware/30.acl.global.ts.eta +6 -5
- package/templates/nuxt/pages/[xorg]/pickgroup.vue._eta +28 -27
- package/templates/nuxt/pages/picktenant.vue._eta +3 -3
- package/templates/nuxt/plugins/20.simpleapp-userstore.ts.eta +49 -29
- package/templates/nuxt/simpleapp/generate/clients/SimpleAppClient.ts.eta +7 -1
- package/templates/nuxt/types/others.ts.eta +7 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-if="getCurrentXorg() && canPerform('student', 'search')"
|
|
4
|
+
class="w-full border p-2 rounded-lg flex flex-row gap-1 cursor-pointer justify-between"
|
|
5
|
+
@click="showDialog"
|
|
6
|
+
>
|
|
7
|
+
<i class="pi pi-search p-1" />
|
|
8
|
+
|
|
9
|
+
<span>{{ t("search") }}</span>
|
|
10
|
+
<span
|
|
11
|
+
v-if="isMacOS"
|
|
12
|
+
class="bg-green-800 text-white pl-2 pr-2 text-sm rounded border"
|
|
13
|
+
>
|
|
14
|
+
⌘+k
|
|
15
|
+
</span>
|
|
16
|
+
<span
|
|
17
|
+
v-else
|
|
18
|
+
class="bg-green-800 text-white pl-2 pr-2 text-sm rounded border"
|
|
19
|
+
>
|
|
20
|
+
cmd+k
|
|
21
|
+
</span>
|
|
22
|
+
|
|
23
|
+
<Dialog
|
|
24
|
+
v-model:visible="visiblesearch"
|
|
25
|
+
:closable="false"
|
|
26
|
+
dismissable-mask
|
|
27
|
+
position="top"
|
|
28
|
+
modal
|
|
29
|
+
:pt="{ root: { class: 'mt-0 w-1/2 max-h-screen' } }"
|
|
30
|
+
>
|
|
31
|
+
<template #header>
|
|
32
|
+
<div class="flex flex-col w-full">
|
|
33
|
+
<SearchInput
|
|
34
|
+
ref="searchbox"
|
|
35
|
+
id="searchbox"
|
|
36
|
+
v-model="searchVal"
|
|
37
|
+
:searchIcon="false"
|
|
38
|
+
:shortcutIcon="true"
|
|
39
|
+
:clearIcon="false"
|
|
40
|
+
:hideShortcutIconOnBlur="false"
|
|
41
|
+
:selectOnFocus="true"
|
|
42
|
+
:placeholder="t('searchKeyword')"
|
|
43
|
+
@update:modelValue="onchange"
|
|
44
|
+
@keydown="onKeyDown"
|
|
45
|
+
></SearchInput>
|
|
46
|
+
</div>
|
|
47
|
+
</template>
|
|
48
|
+
<template #default :tabIndex="tabIndex">
|
|
49
|
+
<div v-if="searchVal == ''"><SearchBoxBefore /></div>
|
|
50
|
+
<div v-else-if="searchVal != keyword"><ProgressSpinner /></div>
|
|
51
|
+
<TabView v-else-if="list.length > 0 || menulist.length > 0" lazy>
|
|
52
|
+
<TabPanel :header="t('all')">
|
|
53
|
+
<Listbox
|
|
54
|
+
ref="alllist"
|
|
55
|
+
@update:model-value="selectItem"
|
|
56
|
+
v-model="selecteddata"
|
|
57
|
+
:options="groupedData"
|
|
58
|
+
optionGroupLabel="label"
|
|
59
|
+
optionGroupChildren="items"
|
|
60
|
+
>
|
|
61
|
+
<template #optiongroup="{ option, index }">
|
|
62
|
+
<div class="flex align-items-center font-semibold">
|
|
63
|
+
<div>{{ option.label }}</div>
|
|
64
|
+
</div>
|
|
65
|
+
</template>
|
|
66
|
+
<template #option="{ option, index }">
|
|
67
|
+
<div v-if="option.documentName == 'menu'">
|
|
68
|
+
<SearchBoxMenu :item="option.data" />
|
|
69
|
+
</div>
|
|
70
|
+
<div v-else>
|
|
71
|
+
<SearchBoxStudent
|
|
72
|
+
v-if="option.documentName == 'student'"
|
|
73
|
+
:item="option.data"
|
|
74
|
+
/>
|
|
75
|
+
<SearchBoxTeacher
|
|
76
|
+
v-else-if="option.documentName == 'teacher'"
|
|
77
|
+
:item="option.data"
|
|
78
|
+
/>
|
|
79
|
+
<SearchBoxAccTrans
|
|
80
|
+
v-else-if="option.documentName == 'accounttransaction'"
|
|
81
|
+
:item="option.data"
|
|
82
|
+
/>
|
|
83
|
+
<SearchBoxProduct
|
|
84
|
+
v-else-if="option.documentName == 'product'"
|
|
85
|
+
:item="option.data"
|
|
86
|
+
/>
|
|
87
|
+
<TextSubsubtitle class="italic"
|
|
88
|
+
>{{ option.documentName }}
|
|
89
|
+
{{ option.data.score }}</TextSubsubtitle
|
|
90
|
+
>
|
|
91
|
+
</div>
|
|
92
|
+
</template>
|
|
93
|
+
</Listbox>
|
|
94
|
+
|
|
95
|
+
<!-- <ListView ref="searchlistel" :list="list" idField="_id" @click="selectItem" #default="{item,index}">
|
|
96
|
+
<SearchBoxMenu v-if="item.documentName=='menu'" :item="item.data"/>
|
|
97
|
+
<SearchBoxStudent v-else-if="item.documentName=='student'" :item="item.data"/>
|
|
98
|
+
<SearchBoxTeacher v-else-if="item.documentName=='teacher'" :item="item.data"/>
|
|
99
|
+
<SearchBoxAccTrans v-else-if="item.documentName=='accounttransaction'" :item="item.data"/>
|
|
100
|
+
</ListView> -->
|
|
101
|
+
</TabPanel>
|
|
102
|
+
<TabPanel :header="t('students')" v-if="students.length > 0">
|
|
103
|
+
<ListView
|
|
104
|
+
ref="searchstudentlistel"
|
|
105
|
+
:list="students"
|
|
106
|
+
idField="_id"
|
|
107
|
+
#default="{ item, index }"
|
|
108
|
+
>
|
|
109
|
+
<SearchBoxStudent :item="item.data" />
|
|
110
|
+
</ListView>
|
|
111
|
+
</TabPanel>
|
|
112
|
+
<TabPanel :header="t('transactions')" v-if="acctrans.length > 0">
|
|
113
|
+
<ListView
|
|
114
|
+
ref="searchstudentlistel"
|
|
115
|
+
:list="acctrans"
|
|
116
|
+
idField="_id"
|
|
117
|
+
#default="{ item, index }"
|
|
118
|
+
>
|
|
119
|
+
<SearchBoxAccTrans :item="item.data" />
|
|
120
|
+
</ListView>
|
|
121
|
+
</TabPanel>
|
|
122
|
+
<TabPanel :header="t('teacher')" v-if="teachers.length > 0">
|
|
123
|
+
<ListView
|
|
124
|
+
ref="searchteacherlistel"
|
|
125
|
+
:list="teachers"
|
|
126
|
+
idField="_id"
|
|
127
|
+
#default="{ item, index }"
|
|
128
|
+
>
|
|
129
|
+
<SearchBoxTeacher :item="item.data" />
|
|
130
|
+
</ListView>
|
|
131
|
+
</TabPanel>
|
|
132
|
+
</TabView>
|
|
133
|
+
<div v-else><NodataLarge /></div>
|
|
134
|
+
</template>
|
|
135
|
+
</Dialog>
|
|
136
|
+
</div>
|
|
137
|
+
</template>
|
|
138
|
+
<script setup lang="ts">
|
|
139
|
+
/**
|
|
140
|
+
* This file was automatically generated by simpleapp generator during initialization. It is changable.
|
|
141
|
+
* last change 2024-02-22
|
|
142
|
+
* author: Ks Tan
|
|
143
|
+
*/
|
|
144
|
+
import SearchInput from "vue-search-input";
|
|
145
|
+
import { getAllDocuments } from "~/simpleapp/generate/commons/documents";
|
|
146
|
+
import "vue-search-input/dist/styles.css";
|
|
147
|
+
import { debounce } from "lodash"; // Assuming you have Lodash installed
|
|
148
|
+
import {
|
|
149
|
+
Accounttransaction,
|
|
150
|
+
Student,
|
|
151
|
+
Teacher,
|
|
152
|
+
} from "~/simpleapp/generate/openapi";
|
|
153
|
+
import { SimpleAppDocuments, MenuData, ForeignKey } from "~/types";
|
|
154
|
+
import TextSubsubtitle from "../text/TextSubsubtitle.vue";
|
|
155
|
+
const alllist = ref();
|
|
156
|
+
const selecteddata = ref();
|
|
157
|
+
const students = computed(() =>
|
|
158
|
+
list.value.filter((item) => item.documentName == "student"),
|
|
159
|
+
);
|
|
160
|
+
const parents = computed(() =>
|
|
161
|
+
list.value.filter((item) => item.documentName == "parent"),
|
|
162
|
+
);
|
|
163
|
+
const teachers = computed(() =>
|
|
164
|
+
list.value.filter((item) => item.documentName == "teacher"),
|
|
165
|
+
);
|
|
166
|
+
const acctrans = computed(() =>
|
|
167
|
+
list.value.filter((item) => item.documentName == "accounttransaction"),
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
type ResultDataType = { _id: string; documentName: string; data: any };
|
|
171
|
+
const list = ref<ResultDataType[]>([]);
|
|
172
|
+
const menulist = ref<ResultDataType[]>([]);
|
|
173
|
+
|
|
174
|
+
const groupedData = computed(() => [
|
|
175
|
+
{
|
|
176
|
+
label: t("menus"),
|
|
177
|
+
items: menulist.value,
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
label: t("results"),
|
|
181
|
+
items: list.value.sort((a, b) => {
|
|
182
|
+
const vA = a.data.score;
|
|
183
|
+
const vB = b.data.score;
|
|
184
|
+
if (vA < vB) {
|
|
185
|
+
return 1;
|
|
186
|
+
}
|
|
187
|
+
if (vA > vB) {
|
|
188
|
+
return -1;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return 0;
|
|
192
|
+
}),
|
|
193
|
+
},
|
|
194
|
+
]);
|
|
195
|
+
|
|
196
|
+
const searchlistel = ref(null);
|
|
197
|
+
const deviceType: any = useNuxtApp().$device;
|
|
198
|
+
type SearchDoc = {
|
|
199
|
+
[key: string]: {
|
|
200
|
+
fields: string[];
|
|
201
|
+
// search:string[]
|
|
202
|
+
// sort:string
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
const documents: SearchDoc = {
|
|
206
|
+
student: {
|
|
207
|
+
fields: [
|
|
208
|
+
"studentName",
|
|
209
|
+
"studentCode",
|
|
210
|
+
"alternateName",
|
|
211
|
+
"level",
|
|
212
|
+
"studentGroup",
|
|
213
|
+
"status",
|
|
214
|
+
"updated",
|
|
215
|
+
],
|
|
216
|
+
},
|
|
217
|
+
parent: {
|
|
218
|
+
fields: ["parentName", "active", "updated"],
|
|
219
|
+
},
|
|
220
|
+
product: {
|
|
221
|
+
fields: [
|
|
222
|
+
"productCode",
|
|
223
|
+
"productName",
|
|
224
|
+
"defaultPrice",
|
|
225
|
+
"billingMethod",
|
|
226
|
+
"category",
|
|
227
|
+
"categoryType",
|
|
228
|
+
"active",
|
|
229
|
+
"updated",
|
|
230
|
+
],
|
|
231
|
+
},
|
|
232
|
+
teacher: {
|
|
233
|
+
fields: [
|
|
234
|
+
"teacherNo",
|
|
235
|
+
"teacherName",
|
|
236
|
+
"alternateName",
|
|
237
|
+
"teacherGroup",
|
|
238
|
+
"active",
|
|
239
|
+
"updated",
|
|
240
|
+
],
|
|
241
|
+
},
|
|
242
|
+
accounttransaction: {
|
|
243
|
+
fields: [
|
|
244
|
+
"date",
|
|
245
|
+
"document",
|
|
246
|
+
"documentNo",
|
|
247
|
+
"documentName",
|
|
248
|
+
"amount",
|
|
249
|
+
"updated",
|
|
250
|
+
"student",
|
|
251
|
+
],
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const isMacOS = computed(() => deviceType.isMacOS);
|
|
256
|
+
const havedata = ref(false);
|
|
257
|
+
const searchbox = ref();
|
|
258
|
+
const visiblesearch = ref(false);
|
|
259
|
+
const searchVal = ref("");
|
|
260
|
+
const keyword = ref("");
|
|
261
|
+
const tabIndex = ref(0);
|
|
262
|
+
const selectedIndex = ref(0);
|
|
263
|
+
const isloading = ref(false);
|
|
264
|
+
|
|
265
|
+
const showDialog = () => {
|
|
266
|
+
searchVal.value = "";
|
|
267
|
+
keyword.value = "";
|
|
268
|
+
visiblesearch.value = true;
|
|
269
|
+
setTimeout(() => {
|
|
270
|
+
const el = document.querySelector("#searchbox") as HTMLInputElement;
|
|
271
|
+
if (el !== undefined) el.focus();
|
|
272
|
+
}, 500);
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
onMounted(() => {
|
|
276
|
+
document.onkeydown = function (e) {
|
|
277
|
+
if (e.key === "k" && (e.ctrlKey || e.metaKey)) {
|
|
278
|
+
e.preventDefault(); // present "Save Page" from getting triggered.
|
|
279
|
+
showDialog();
|
|
280
|
+
} else if (e.key == "Escape") {
|
|
281
|
+
visiblesearch.value = false;
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
});
|
|
285
|
+
const onchange = debounce((str: string) => {
|
|
286
|
+
havedata.value = false;
|
|
287
|
+
if (searchVal.value == "") return false;
|
|
288
|
+
keyword.value = searchVal.value;
|
|
289
|
+
search();
|
|
290
|
+
havedata.value = true;
|
|
291
|
+
}, 800);
|
|
292
|
+
|
|
293
|
+
const search = () => {
|
|
294
|
+
list.value = [];
|
|
295
|
+
isloading.value = true;
|
|
296
|
+
searchdocument();
|
|
297
|
+
for (const key in documents) {
|
|
298
|
+
const searchdoc = documents[key];
|
|
299
|
+
if (canPerform(key, "search")) {
|
|
300
|
+
let doc;
|
|
301
|
+
if (key == "student") doc = useNuxtApp().$StudentDoc();
|
|
302
|
+
else if (key == "teacher") doc = useNuxtApp().$TeacherDoc();
|
|
303
|
+
else if (key == "accounttransaction")
|
|
304
|
+
doc = useNuxtApp().$AccounttransactionDoc();
|
|
305
|
+
else if (key == "product") doc = useNuxtApp().$ProductDoc();
|
|
306
|
+
else if (key == "parent") doc = useNuxtApp().$ParentDoc();
|
|
307
|
+
else {
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
doc
|
|
311
|
+
.runFullTextSearh({
|
|
312
|
+
keyword: keyword.value,
|
|
313
|
+
})
|
|
314
|
+
.then((data: any[]) => {
|
|
315
|
+
if (data.length > 0) {
|
|
316
|
+
list.value = list.value.concat(
|
|
317
|
+
data.map((item) => {
|
|
318
|
+
const tmp: ResultDataType = {
|
|
319
|
+
_id: <string>item._id,
|
|
320
|
+
documentName: doc.getDocName(),
|
|
321
|
+
data: item,
|
|
322
|
+
};
|
|
323
|
+
return tmp;
|
|
324
|
+
}),
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
isloading.value = false;
|
|
331
|
+
// setTimeout(() => setFocus(), 200);
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
function onKeyDown(event:KeyboardEvent){
|
|
335
|
+
if(['ArrowDown','ArrowUp'].includes(event.code)){
|
|
336
|
+
setFocus()
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const searchdocument = () => {
|
|
340
|
+
menulist.value = getAllDocuments()
|
|
341
|
+
.filter(
|
|
342
|
+
(item) =>
|
|
343
|
+
item.page != "" && item.docName.includes(keyword.value.toLowerCase()),
|
|
344
|
+
)
|
|
345
|
+
.map((item) => {
|
|
346
|
+
const tmp: ResultDataType = {
|
|
347
|
+
_id: item.docName,
|
|
348
|
+
documentName: "menu",
|
|
349
|
+
data: item,
|
|
350
|
+
};
|
|
351
|
+
return tmp;
|
|
352
|
+
})
|
|
353
|
+
.sort();
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
const selectItem = (item: ResultDataType) => {
|
|
357
|
+
if (item.documentName == "menu") {
|
|
358
|
+
goTo(item._id);
|
|
359
|
+
} else if (item.documentName == "student") {
|
|
360
|
+
goTo("managestudents", item._id);
|
|
361
|
+
} else {
|
|
362
|
+
goTo(item.documentName, item._id);
|
|
363
|
+
}
|
|
364
|
+
visiblesearch.value = false;
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
function setFocus() {
|
|
368
|
+
const listbodyid = alllist.value?.$el?.id;
|
|
369
|
+
document.querySelector(`#${listbodyid} .p-listbox-list`)?.focus();
|
|
370
|
+
}
|
|
371
|
+
</script>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
|
|
3
|
+
</template>
|
|
4
|
+
<script setup lang="ts">
|
|
5
|
+
/**
|
|
6
|
+
* This file was automatically generated by simpleapp generator during initialization. It is changable.
|
|
7
|
+
* --remove-this-line-to-prevent-override--
|
|
8
|
+
* last change 2024-02-22
|
|
9
|
+
* author: Ks Tan
|
|
10
|
+
*/
|
|
11
|
+
</script>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
|
|
3
|
+
<div class="flex flex-row justify-between cursor-pointer">
|
|
4
|
+
<div>
|
|
5
|
+
<div class="font-semibold">
|
|
6
|
+
{{ item.productCode }} - {{ item.productName }}
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
<div class="flex flex-col text-right">
|
|
10
|
+
<RendererMoney class="font-semibold" :value="item.defaultPrice" />
|
|
11
|
+
<div>{{ item.billingMethod }}</div>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
</template>
|
|
15
|
+
<script setup lang="ts">
|
|
16
|
+
/**
|
|
17
|
+
* This file was automatically generated by simpleapp generator during initialization. It is changable.
|
|
18
|
+
* --remove-this-line-to-prevent-override--
|
|
19
|
+
* last change 2024-02-22
|
|
20
|
+
* author: Ks Tan
|
|
21
|
+
*/
|
|
22
|
+
import { Product } from "~/simpleapp/generate/openapi";
|
|
23
|
+
import {SimpleAppDocuments} from "~/types"
|
|
24
|
+
const props = defineProps<{item:Product}>()
|
|
25
|
+
|
|
26
|
+
</script>
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
class="p-2 border rounded-lg border-gray-300 dark:border-blue-900/40"
|
|
5
5
|
>
|
|
6
6
|
<button
|
|
7
|
+
type="button"
|
|
7
8
|
:readonly="readonly"
|
|
8
9
|
class="cursor-pointer text-primary-600 dark:text-primary-400"
|
|
9
10
|
tabindex="0"
|
|
@@ -16,9 +17,12 @@
|
|
|
16
17
|
v-else-if="modelValue !== undefined"
|
|
17
18
|
class="p-2 border rounded-lg border-gray-300 dark:border-blue-900/40 relative"
|
|
18
19
|
>
|
|
20
|
+
<!-- readonly -->
|
|
19
21
|
<button
|
|
20
22
|
ref="autocompleteinput"
|
|
21
|
-
|
|
23
|
+
type="button"
|
|
24
|
+
:id="inputId"
|
|
25
|
+
|
|
22
26
|
class="cursor-pointer text-primary-600 dark:text-primary-400"
|
|
23
27
|
@click="openViewer(true)"
|
|
24
28
|
>
|
|
@@ -29,6 +33,7 @@
|
|
|
29
33
|
class="absolute h-full top-0 right-0 text-right text-white z-10 align-middle p-3"
|
|
30
34
|
>
|
|
31
35
|
<button
|
|
36
|
+
type="button"
|
|
32
37
|
class="pi pi-times rounded-full bg-slate-500 p-1 cursor-pointer text-xs"
|
|
33
38
|
@click="clear"
|
|
34
39
|
tabindex="0"
|
|
@@ -189,7 +194,7 @@ import {
|
|
|
189
194
|
SchemaType,
|
|
190
195
|
} from "~/types";
|
|
191
196
|
const mobileVisible = ref(false);
|
|
192
|
-
const autocompleteinput = ref
|
|
197
|
+
const autocompleteinput = ref();
|
|
193
198
|
const { $event } = useNuxtApp();
|
|
194
199
|
const list = ref<any[]>([]);
|
|
195
200
|
const props = withDefaults(
|
|
@@ -237,6 +242,13 @@ if (modelValue.value && modelValue.value._id) {
|
|
|
237
242
|
const clear = () => {
|
|
238
243
|
autocompleteitem.value = undefined;
|
|
239
244
|
modelValue.value = undefined;
|
|
245
|
+
if(!isMobile()){
|
|
246
|
+
setTimeout(()=>{
|
|
247
|
+
const autoel = autocompleteinput.value.$el
|
|
248
|
+
autoel?.firstElementChild?.focus()
|
|
249
|
+
},100)
|
|
250
|
+
}
|
|
251
|
+
|
|
240
252
|
};
|
|
241
253
|
|
|
242
254
|
//if record picked, click button show record info instead
|
|
@@ -285,7 +297,10 @@ const getListFromAutocompleteApi = (event: any) => {
|
|
|
285
297
|
console.log("Run autocomplete?");
|
|
286
298
|
list.value = res.data;
|
|
287
299
|
|
|
288
|
-
if (
|
|
300
|
+
if (
|
|
301
|
+
props.allowAddNew &&
|
|
302
|
+
canPerform(upperFirst(targetDocument), "create")
|
|
303
|
+
) {
|
|
289
304
|
list.value = list.value.concat({
|
|
290
305
|
_id: "new",
|
|
291
306
|
label: "<" + t("new") + ">",
|
|
@@ -323,6 +338,12 @@ watch(modelValue, (newvalue: any) => {
|
|
|
323
338
|
});
|
|
324
339
|
const emitChanges = () => {
|
|
325
340
|
emits("change", modelValue.value);
|
|
341
|
+
if(!isMobile()){
|
|
342
|
+
setTimeout(()=>{
|
|
343
|
+
const autoel = autocompleteinput.value
|
|
344
|
+
autoel?.focus()
|
|
345
|
+
},100)}
|
|
346
|
+
|
|
326
347
|
};
|
|
327
348
|
|
|
328
349
|
const setFocus = (ev: any) => {
|
|
@@ -11,19 +11,23 @@
|
|
|
11
11
|
</ButtonDefault>
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
14
|
-
<
|
|
14
|
+
<ListContainer
|
|
15
15
|
class="p-2 dark:bg-slate-900 bg-slate-200 rounded-lg"
|
|
16
16
|
:list="list"
|
|
17
|
-
#default="{
|
|
17
|
+
#default="{item,index }"
|
|
18
18
|
@click="showRow"
|
|
19
19
|
>
|
|
20
20
|
<slot name="listbody" :item="item" :index="index">
|
|
21
21
|
<div class="flex flex-row">item {{ item._id }}</div>
|
|
22
22
|
</slot>
|
|
23
|
-
</
|
|
23
|
+
</ListContainer>
|
|
24
24
|
|
|
25
|
-
<Dialog
|
|
26
|
-
|
|
25
|
+
<Dialog
|
|
26
|
+
v-model:visible="showDialog"
|
|
27
|
+
modal
|
|
28
|
+
:header="t('editDetails')"
|
|
29
|
+
:pt="{ root: { class: 'w-1/2' } }"
|
|
30
|
+
>
|
|
27
31
|
<div class="flex flex-col p-2 gap-4">
|
|
28
32
|
<slot name="popupbody" :index="rowIndex" :item="list[rowIndex]">
|
|
29
33
|
row {{ rowIndex }} define SimpleAppInputs here
|
|
@@ -40,6 +44,7 @@
|
|
|
40
44
|
</template>
|
|
41
45
|
<script setup lang="ts" generic="T extends { [key: string]: any }">
|
|
42
46
|
import { SimpleAppClient } from "~/simpleapp/generate/clients/SimpleAppClient";
|
|
47
|
+
import ListContainer from "../list/ListContainer.vue";
|
|
43
48
|
/**
|
|
44
49
|
* This file was automatically generated by simpleapp generator. Every
|
|
45
50
|
* MODIFICATION OVERRIDE BY GENERATEOR
|
|
@@ -51,7 +51,8 @@
|
|
|
51
51
|
:disabled="!canPerform(doc.getDocName(true), 'access')"
|
|
52
52
|
@click="emitEvent(menu, $event)"
|
|
53
53
|
:action-name="menu.action"
|
|
54
|
-
>{{ menu.label }}</ButtonAction
|
|
54
|
+
>{{ menu.label }}</ButtonAction
|
|
55
|
+
>
|
|
55
56
|
<ButtonAction
|
|
56
57
|
v-else
|
|
57
58
|
:disabled="!canPerform(doc.getDocName(true), menu.action)"
|
|
@@ -68,8 +69,8 @@
|
|
|
68
69
|
<!-- right -->
|
|
69
70
|
<div class="flex flex-row gap-2">
|
|
70
71
|
<DebugDocumentData v-model="data" :label="t(doc.getDocName())" />
|
|
71
|
-
<div
|
|
72
|
-
<RendererDocHistories :data="data" />
|
|
72
|
+
<div>
|
|
73
|
+
<RendererDocHistories :data="data" :documentName="doc.getDocName()" />
|
|
73
74
|
</div>
|
|
74
75
|
<div v-for="(menu, index) in menus" :key="index">
|
|
75
76
|
<div v-if="menu.label && menu.type == 'docstatus'">
|
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="w-full">
|
|
2
|
+
<div class="w-full p-4">
|
|
3
|
+
<LazyTenantCreator v-model:model-value="visibleCreateTenant"></LazyTenantCreator>
|
|
4
|
+
<ButtonPrimary @click="visibleCreateTenant=true">{{ t('newBusiness') }}</ButtonPrimary>
|
|
3
5
|
<div v-if="waiting" class="p-4 w-full">waiting..</div>
|
|
4
|
-
<div
|
|
6
|
+
<div
|
|
7
|
+
v-else
|
|
8
|
+
class="w-full p-2 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
|
|
9
|
+
>
|
|
5
10
|
<div v-for="tenant in alltenants" class="border rounded-lg p-2 m-2">
|
|
6
|
-
|
|
7
11
|
<TextTitle>{{ tenant.tenantName }}</TextTitle>
|
|
8
|
-
<div v-for="
|
|
12
|
+
<div v-for="item in tenant.permissions">
|
|
9
13
|
<NuxtLink :to="`/${item.xOrg}`" external>
|
|
10
|
-
<div class="flex flex-row gap-2 hover:bg-primary-100">
|
|
14
|
+
<div class="flex flex-row gap-2 hover:bg-primary-100">
|
|
11
15
|
<div class="min-w-14 p=2">
|
|
12
|
-
<ImageOrganization :orgRecordId="item.orgRecordId" :size="12"/>
|
|
13
|
-
</div>
|
|
14
|
-
<div class="flex flex-col w-full justify-end gap-2">
|
|
16
|
+
<ImageOrganization :orgRecordId="item.orgRecordId" :size="12" />
|
|
17
|
+
</div>
|
|
18
|
+
<div class="flex flex-col w-full justify-end gap-2">
|
|
15
19
|
<div class="flex flex-row gap-2">
|
|
16
20
|
<TextMain>{{ item.branchCode }}</TextMain>
|
|
17
21
|
<Tag v-for="groupname in item.groups">{{ t(groupname) }}</Tag>
|
|
18
22
|
</div>
|
|
19
23
|
<TextSubsubtitle>{{ item.orgName }}</TextSubsubtitle>
|
|
20
|
-
|
|
21
|
-
|
|
22
24
|
</div>
|
|
23
|
-
|
|
25
|
+
</div>
|
|
24
26
|
</NuxtLink>
|
|
25
27
|
</div>
|
|
26
28
|
</div>
|
|
@@ -39,7 +41,7 @@ import TextPrimary from "../text/TextPrimary.vue";
|
|
|
39
41
|
import ImageOrganization from "../image/ImageOrganization.vue";
|
|
40
42
|
const waiting = ref(true);
|
|
41
43
|
const alltenants = ref();
|
|
42
|
-
|
|
44
|
+
const visibleCreateTenant = ref(false)
|
|
43
45
|
const loadAllTenants = async () => {
|
|
44
46
|
waiting.value = false;
|
|
45
47
|
alltenants.value = (await getProfileApi().getAllTenants()).data;
|
|
@@ -53,10 +55,10 @@ const getBranchlist = (tenant: any) => tenant.permissions;
|
|
|
53
55
|
// const getOrglist = (tenant: any) =>
|
|
54
56
|
// _.uniqBy(getBranchlist(tenant), "orgId").map((item: any) => ({
|
|
55
57
|
// orgId: item.orgId,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
// orgRecordId:'aaa',// item.orgRecordId,
|
|
59
|
+
// orgCode: item.orgCode,
|
|
60
|
+
// orgName: item.orgName,
|
|
61
|
+
// }));
|
|
60
62
|
|
|
61
63
|
onNuxtReady(() => {
|
|
62
64
|
loadAllTenants();
|
|
@@ -38,51 +38,9 @@ export const getDocumentApi = (documentName: string): any => {
|
|
|
38
38
|
|
|
39
39
|
const config = getAxiosConfig()
|
|
40
40
|
const docsOpenapi: any = {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
'permission': new o.PERMApi(config),
|
|
45
|
-
'autoincreament': new o.AUTOINCApi(config),
|
|
46
|
-
'docnoformat': new o.DOCNOApi(config),
|
|
47
|
-
'systemmessage': new o.SYSMSGApi(config),
|
|
48
|
-
'keyvaluepair': new o.KVPAIRApi(config),
|
|
49
|
-
'webhook': new o.WEBHOOKApi(config),
|
|
50
|
-
'academysession': new o.ACADEMYSESSIONApi(config),
|
|
51
|
-
'accounttransaction': new o.ACCTRANSApi(config),
|
|
52
|
-
'agent': new o.AGENTApi(config),
|
|
53
|
-
'area': new o.AREAApi(config),
|
|
54
|
-
'attendance': new o.ATTApi(config),
|
|
55
|
-
'category': new o.CATApi(config),
|
|
56
|
-
'creditnote': new o.CNApi(config),
|
|
57
|
-
'enrollment': new o.ENROLLApi(config),
|
|
58
|
-
'enrollmenttransaction': new o.ENROLLTRANSApi(config),
|
|
59
|
-
'holiday': new o.HOLIDAYApi(config),
|
|
60
|
-
'invoice': new o.INVApi(config),
|
|
61
|
-
'level': new o.LVLApi(config),
|
|
62
|
-
'parent': new o.PARENTApi(config),
|
|
63
|
-
'payment': new o.PAYApi(config),
|
|
64
|
-
'paymentmethod': new o.PAYMETHODApi(config),
|
|
65
|
-
'product': new o.PRDApi(config),
|
|
66
|
-
'productpackage': new o.PRDPKGApi(config),
|
|
67
|
-
'race': new o.RACEApi(config),
|
|
68
|
-
'refund': new o.REFUNDApi(config),
|
|
69
|
-
'refundtype': new o.REFUNDTYPEApi(config),
|
|
70
|
-
'religion': new o.RELIGIONApi(config),
|
|
71
|
-
'room': new o.ROOMApi(config),
|
|
72
|
-
'roomtype': new o.ROOMTYPEApi(config),
|
|
73
|
-
'schedule': new o.SCHEDULEApi(config),
|
|
74
|
-
'school': new o.SCHOOLApi(config),
|
|
75
|
-
'stopenrollment': new o.STOPENROLLApi(config),
|
|
76
|
-
'stopreason': new o.STOPREASONApi(config),
|
|
77
|
-
'student': new o.STUApi(config),
|
|
78
|
-
'studentgroup': new o.STUGROUPApi(config),
|
|
79
|
-
'studentsource': new o.STUDENTSRCApi(config),
|
|
80
|
-
'studentsummary': new o.STUSUMApi(config),
|
|
81
|
-
'teacher': new o.TEACHERApi(config),
|
|
82
|
-
'teachergroup': new o.TEACHERGROUPApi(config),
|
|
83
|
-
'tuitionclass': new o.TUITIONApi(config),
|
|
84
|
-
'user': new o.USERApi(config),
|
|
85
|
-
|
|
41
|
+
<% for(let i=0;i<it.modules.length; i++){ %>
|
|
42
|
+
'<%=it.modules[i].docname.toLowerCase()%>': new o.<%=it.modules[i].doctype.toUpperCase()%>Api(config),
|
|
43
|
+
<%}%>
|
|
86
44
|
};
|
|
87
45
|
|
|
88
46
|
if (!docsOpenapi[documentName]) {
|
|
@@ -100,10 +58,9 @@ export const getAllApi=()=>{
|
|
|
100
58
|
return o
|
|
101
59
|
}
|
|
102
60
|
|
|
103
|
-
export const getWorkflowApi = () => {
|
|
104
|
-
return new o.WorkflowApi(getAxiosConfig())
|
|
105
|
-
|
|
106
|
-
}
|
|
61
|
+
//export const getWorkflowApi = () => {
|
|
62
|
+
//return new o.WorkflowApi(getAxiosConfig())
|
|
63
|
+
//}
|
|
107
64
|
|
|
108
65
|
export const getProfileApi = () => {
|
|
109
66
|
return new o.PROFILEApi(getAxiosConfig())
|