@simitgroup/simpleapp-generator 1.2.7 → 1.3.0-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/organization.d.ts.map +1 -1
- package/dist/buildinschemas/organization.js +3 -1
- package/dist/buildinschemas/organization.js.map +1 -1
- package/dist/framework.d.ts.map +1 -1
- package/dist/framework.js +4 -9
- package/dist/framework.js.map +1 -1
- package/dist/generate.js +14 -14
- package/dist/generate.js.map +1 -1
- package/package.json +1 -1
- package/src/buildinschemas/organization.ts +3 -1
- package/src/framework.ts +5 -9
- package/src/generate.ts +17 -16
- package/templates/basic/nest/controller.ts.eta +17 -0
- package/templates/basic/nest/default.ts.eta +6 -2
- package/templates/basic/nuxt/default.ts.eta +10 -6
- package/templates/basic/nuxt/pages.[id].vue.eta +9 -7
- package/templates/basic/nuxt/pages.form.vue.eta +16 -36
- package/templates/basic/nuxt/pages.landing.vue.eta +42 -35
- package/templates/basic/nuxt/pages.viewer.vue.eta +4 -6
- package/templates/nest/.env._eta +0 -1
- package/templates/nest/src/simpleapp/generate/commons/user.context.ts.eta +14 -2
- package/templates/nest/src/simpleapp/generate/controllers/simpleapp.controller.ts.eta +32 -18
- package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +76 -13
- package/templates/nuxt/app.vue.eta +7 -3
- package/templates/nuxt/assets/css/calendar.css._eta +21 -8
- package/templates/nuxt/assets/css/style.css._eta +17 -10
- package/templates/nuxt/assets/primevue/passthrough.ts._eta +44 -22
- package/templates/nuxt/components/button/ButtonDefault.vue._eta +1 -2
- package/templates/nuxt/components/button/ButtonMultiple.vue._eta +21 -0
- package/templates/nuxt/components/calendar/CalendarByResource.vue.eta +29 -8
- package/templates/nuxt/components/debug/DebugDocumentData.vue.eta +3 -4
- package/templates/nuxt/components/event/EventDocumentViewer.vue._eta +75 -65
- package/templates/nuxt/components/event/EventNotification.vue._eta +23 -2
- package/templates/nuxt/components/form/FormBranch.vue.eta +83 -0
- package/templates/nuxt/components/form/readme.md.eta +1 -0
- package/templates/nuxt/components/header/HeaderBar.vue._eta +9 -9
- package/templates/nuxt/components/header/HeaderBreadcrumb.vue.eta +2 -2
- package/templates/nuxt/components/header/button/HeaderButtonMenuPicker.vue._eta +16 -22
- package/templates/nuxt/components/header/button/HeaderButtonProfile.vue.eta +29 -46
- package/templates/nuxt/components/list/ListDocument.vue.eta +25 -0
- package/templates/nuxt/components/list/ListDocumentTable.vue.eta +77 -0
- package/templates/nuxt/components/list/ListView.vue.eta +129 -58
- package/templates/nuxt/components/mobile/MobileToolbar.vue.eta +10 -0
- package/templates/nuxt/components/overlay/OverlaySideBarCrud.vue.eta +21 -0
- package/templates/nuxt/components/overlay/OverlayViewer.vue.eta +20 -0
- package/templates/nuxt/components/page/PageDocList.vue.eta +170 -0
- package/templates/nuxt/components/renderer/RendererBoolean.vue.eta +8 -4
- package/templates/nuxt/components/renderer/RendererDate.vue.eta +4 -4
- package/templates/nuxt/components/renderer/RendererLink.vue.eta +12 -20
- package/templates/nuxt/components/renderer/RendererMoney.vue.eta +10 -2
- package/templates/nuxt/components/renderer/RendererViewer.vue.eta +27 -21
- package/templates/nuxt/components/simpleApp/SimpleAppAutocomplete.vue.eta +202 -150
- package/templates/nuxt/components/simpleApp/SimpleAppDocumentNo.vue.eta +7 -1
- package/templates/nuxt/components/simpleApp/SimpleAppFieldContainer.vue.eta +112 -101
- package/templates/nuxt/components/simpleApp/SimpleAppFormToolBar.vue.eta +183 -91
- package/templates/nuxt/components/simpleApp/SimpleAppInput.vue.eta +383 -246
- package/templates/nuxt/components/simpleApp/SimpleAppInputTable.vue.eta +4 -3
- package/templates/nuxt/components/table/TableDocuments.vue.eta +3 -3
- package/templates/nuxt/components/text/TextDanger.vue._eta +5 -0
- package/templates/nuxt/components/text/TextSubtitle.vue._eta +5 -0
- package/templates/nuxt/components/text/TextTitle.vue._eta +5 -0
- package/templates/nuxt/components/user/UserProfileListItem.vue.eta +2 -2
- package/templates/nuxt/composables/date.generate.ts.eta +21 -0
- package/templates/nuxt/composables/goTo.generate.ts.eta +1 -0
- package/templates/nuxt/composables/stringHelper.generate.ts.eta +0 -5
- package/templates/nuxt/error.vue._eta +3 -3
- package/templates/nuxt/i18n.config.ts.eta +1 -1
- package/templates/nuxt/lang/en.ts.eta +16 -0
- package/templates/nuxt/layouts/default.vue._eta +34 -34
- package/templates/nuxt/layouts/loginlayout.vue._eta +3 -0
- package/templates/nuxt/layouts/mobile.vue._eta +52 -0
- package/templates/nuxt/nuxt.config.ts._eta +28 -22
- package/templates/nuxt/pages/[xorg]/organization/[id].vue.eta +39 -0
- package/templates/nuxt/pages/[xorg]/organization/new.vue.eta +30 -143
- package/templates/nuxt/pages/[xorg]/organization/viewer.vue.eta +3 -0
- package/templates/nuxt/pages/[xorg]/organization.vue.eta +81 -127
- package/templates/nuxt/pages/[xorg]/user/[id].vue.eta +40 -0
- package/templates/nuxt/pages/[xorg]/user/form.vue.eta +329 -0
- package/templates/nuxt/pages/[xorg]/user/index.vue.eta +37 -0
- package/templates/nuxt/pages/[xorg]/{organization/[id]/branches/[bid].vue → user/new.vue.eta} +10 -4
- package/templates/nuxt/pages/[xorg]/user/viewer.vue.eta +30 -0
- package/templates/nuxt/pages/[xorg]/{user.vue._eta → user.vue.eta} +88 -78
- package/templates/nuxt/pages/login.vue._eta +34 -0
- package/templates/nuxt/pages/profile.vue.eta +12 -3
- package/templates/nuxt/plugins/10.simpleapp-event.ts.eta +36 -35
- package/templates/nuxt/plugins/20.simpleapp-userstore.ts.eta +6 -0
- package/templates/nuxt/server/api/[xorg]/[...].ts.eta +7 -40
- package/templates/nuxt/server/api/profile/[...].ts.eta +3 -32
- package/templates/nuxt/simpleapp/generate/clients/SimpleAppClient.ts.eta +42 -3
- package/templates/nuxt/types/calendar.ts.eta +8 -1
- package/templates/nuxt/types/documentlist.ts.eta +0 -9
- package/templates/nuxt/types/events.ts.eta +1 -0
- package/templates/nuxt/types/others.ts.eta +4 -1
- package/templates/nuxt/types/simpleappinput.ts.eta +12 -2
- package/templates/nuxt/types/user.ts.eta +2 -0
- package/templates/project/lang/default._json +9 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/templates/nuxt/components/docPage/DocPageList.vue.eta +0 -125
- package/templates/nuxt/lang/en.ts._eta +0 -6
- package/templates/nuxt/pages/[xorg]/organization/[bid].vue.eta +0 -14
- package/templates/nuxt/pages/[xorg]/organization/[id]/branches/new.vue +0 -149
- package/templates/nuxt/pages/[xorg]/organization/[id]/index.vue.eta +0 -1
- package/templates/nuxt/pages/[xorg]/user/[id].vue._eta +0 -6
- package/templates/nuxt/pages/[xorg]/user/index.vue._eta +0 -302
- package/templates/nuxt/pages/login.vue.eta +0 -30
- /package/templates/nuxt/lang/{df.ts.eta → df.ts.etaxxxx} +0 -0
|
@@ -6,14 +6,13 @@ import {ref} from 'vue'
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
const { locale,setLocale,locales } = useI18n()
|
|
9
|
+
const colorMode = useColorMode()
|
|
10
|
+
const modelValue = defineModel<boolean>()
|
|
9
11
|
const mylocale = ref(locale)
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
const toggle = (event:any) => {
|
|
13
|
-
userprofileoverlay.value.toggle(event);
|
|
14
|
-
}
|
|
12
|
+
const colors = [{value:'light', name:t('light')},{value:'dark', name:t('dark')}]
|
|
13
|
+
|
|
15
14
|
const toProfile = ()=>{
|
|
16
|
-
|
|
15
|
+
modelValue.value=false
|
|
17
16
|
|
|
18
17
|
if(getCurrentXorg()){
|
|
19
18
|
navigateTo(`/${getCurrentXorg()}/profile`)
|
|
@@ -22,10 +21,6 @@ const toProfile = ()=>{
|
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
}
|
|
25
|
-
const toFrontpage = () =>{
|
|
26
|
-
userprofileoverlay.value.toggle();
|
|
27
|
-
navigateTo('/')
|
|
28
|
-
}
|
|
29
24
|
const saveLocale=async (v:string)=>{
|
|
30
25
|
await setLocale(v)
|
|
31
26
|
}
|
|
@@ -34,50 +29,40 @@ const saveLocale=async (v:string)=>{
|
|
|
34
29
|
|
|
35
30
|
</script>
|
|
36
31
|
|
|
37
|
-
<template>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
</div>
|
|
50
|
-
<OverlayPanel :pt="{root:{class:'w w-80'}}" ref="userprofileoverlay">
|
|
51
|
-
<div>
|
|
52
|
-
<div class="py-2 transition duration-150 ease-in-out z-10 absolute top-0 right-0 bottom-0 left-0" id="modal">
|
|
53
|
-
<div role="alert" class="container mx-auto w-full md:w-full max-w-lg">
|
|
54
|
-
<div class="relative p-4 md:p-8 bg-white dark:bg-gray-800 shadow-md rounded border border-gray-400">
|
|
32
|
+
<template>
|
|
33
|
+
<!-- <div class="bg-cover bg-center rounded-md p-3 cursor-pointer profile-button" @click="toggle">
|
|
34
|
+
<i class="pi pi-user dark:text-white"></i> -->
|
|
35
|
+
<!-- <img :src="getAvatarLink(<string>getProfileEmail(),32)" alt="" class="h-full w-full overflow-hidden object-cover rounded-full border-2 border-white dark:border-gray-700 shadow" /> -->
|
|
36
|
+
<!-- </div> -->
|
|
37
|
+
|
|
38
|
+
<Dialog appendTo="body" ref="userprofileoverlay" v-model:visible="modelValue" close-on-escape :header="t('profile')">
|
|
39
|
+
<!-- <div> -->
|
|
40
|
+
<!-- <div class="py-2 transition duration-150 ease-in-out z-10 absolute top-0 right-0 bottom-0 left-0" id="modal"> -->
|
|
41
|
+
<div class="p-4">
|
|
42
|
+
<!-- <div class="relative p-4 md:p-8 bg-white dark:bg-gray-800 shadow-md rounded border border-gray-400"> -->
|
|
55
43
|
<div class="w-full flex items-center justify-start text-gray-600 dark:text-gray-400 mb-5" >
|
|
56
44
|
<div class="w-12 h-12 bg-cover bg-center rounded-md">
|
|
57
|
-
<img :src="getAvatarLink(getProfileEmail(),32)" alt="" class="h-full w-full overflow-hidden object-cover rounded-full border-2 border-white dark:border-gray-700 shadow" />
|
|
45
|
+
<img :src="getAvatarLink(<string>getProfileEmail(),32)" alt="" class="h-full w-full overflow-hidden object-cover rounded-full border-2 border-white dark:border-gray-700 shadow" />
|
|
58
46
|
</div>
|
|
59
47
|
<div class="flex flex-col" >
|
|
60
|
-
<h1 class="text-left text-gray-800 dark:text-gray-100 font-lg font-bold tracking-normal leading-tight ml-2">{{ getUserProfile()
|
|
61
|
-
<p class="text-gray-400 dark:text-gray-100 font-normal text-base tracking-normal ml-2 mr-4">{{getUserProfile()
|
|
48
|
+
<h1 class="text-left text-gray-800 dark:text-gray-100 font-lg font-bold tracking-normal leading-tight ml-2">{{ getUserProfile()?.fullName }}</h1>
|
|
49
|
+
<p class="text-gray-400 dark:text-gray-100 font-normal text-base tracking-normal ml-2 mr-4">{{getUserProfile()?.group }}</p>
|
|
62
50
|
</div>
|
|
63
51
|
|
|
64
52
|
</div>
|
|
65
|
-
<!-- language -->
|
|
66
53
|
<div class="col-span-full">
|
|
67
54
|
<label for="pick-lang" class="block text-sm font-medium leading-6 text-gray-900 dark:text-gray-300">{{ t('language') }}</label>
|
|
68
55
|
<div class="mt-2">
|
|
69
56
|
<Dropdown inputId="pick-lang" @update:model-value="saveLocale" v-model="mylocale" option-value="code" option-label="name" :options="locales" >
|
|
70
|
-
</Dropdown>
|
|
71
|
-
<!-- <select v-model="$colorMode.preference" id="picklang">
|
|
72
|
-
<option value="light">Light</option>
|
|
73
|
-
<option value="dark">Dark</option>
|
|
74
|
-
</select> -->
|
|
57
|
+
</Dropdown>
|
|
75
58
|
</div>
|
|
76
59
|
</div>
|
|
77
60
|
<div class="mt-3 col-span-full">
|
|
78
61
|
<label for="pick-theme" class="block text-sm font-medium leading-6 text-gray-900 dark:text-gray-300">{{ t('theme') }}</label>
|
|
79
62
|
<div class="mt-2">
|
|
80
|
-
<
|
|
63
|
+
<h1>Color mode: {{ $colorMode.value }}</h1>
|
|
64
|
+
|
|
65
|
+
<Dropdown inputId="pick-theme" v-model="colorMode.preference" option-value="value" option-label="name" :options="colors" >
|
|
81
66
|
</Dropdown>
|
|
82
67
|
|
|
83
68
|
</div>
|
|
@@ -86,15 +71,13 @@ const saveLocale=async (v:string)=>{
|
|
|
86
71
|
|
|
87
72
|
<div class="mt-3 flex items-center justify-start w-full">
|
|
88
73
|
<button class="focus:outline-none transition duration-150 ease-in-out hover:bg-gray-600 bg-gray-700 rounded text-white px-8 py-2 text-sm" @click="toProfile">{{ t('profile') }}</button>
|
|
89
|
-
|
|
90
|
-
<button class="focus:outline-none ml-3 bg-warning-100 dark:bg-warning-700 dark:border-warning-700 dark:hover:bg-warning-600 transition duration-150 text-gray-600 dark:text-gray-400 ease-in-out hover:border-gray-400 hover:bg-gray-300 border rounded px-8 py-2 text-sm" @click="logout()">{{ t('logout') }}</button>
|
|
74
|
+
<button class="focus:outline-none ml-3 bg-warning-100 dark:bg-warning-700 dark:border-warning-700 dark:hover:bg-warning-600 transition duration-150 text-gray-600 dark:text-white ease-in-out hover:border-gray-400 hover:bg-gray-300 border rounded px-8 py-2 text-sm" @click="logout()">{{ t('logout') }}</button>
|
|
91
75
|
</div>
|
|
92
|
-
</div>
|
|
76
|
+
<!-- </div> -->
|
|
93
77
|
</div>
|
|
94
|
-
</div>
|
|
78
|
+
<!-- </div> -->
|
|
95
79
|
|
|
96
|
-
</div>
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
</div>
|
|
80
|
+
<!-- </div> -->
|
|
81
|
+
</Dialog>
|
|
82
|
+
|
|
100
83
|
</template>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ListView
|
|
3
|
+
:list="recordlist as T[]"
|
|
4
|
+
with-filter
|
|
5
|
+
:title-field="documentTitle"
|
|
6
|
+
:sub-title-field="uniqueKey"
|
|
7
|
+
#default="{ item, index }"
|
|
8
|
+
>
|
|
9
|
+
<div class="cursor-pointer flex flex-row gap-2" @click="emits('click', item)">
|
|
10
|
+
<slot name="default" :index="index" :item="item">
|
|
11
|
+
<TextTitle class="flex-1">{{ item[(documentTitle as keyof typeof item) ] }}</TextTitle>
|
|
12
|
+
<TextSubtitle >{{ item[uniqueKey as keyof typeof item] }}</TextSubtitle>
|
|
13
|
+
</slot>
|
|
14
|
+
</div>
|
|
15
|
+
</ListView>
|
|
16
|
+
</template>
|
|
17
|
+
<script setup lang="ts" generic="T extends { [key: string]: any }">
|
|
18
|
+
import { SearchBody } from "~/types";
|
|
19
|
+
const emits = defineEmits(["click"]);
|
|
20
|
+
const props = defineProps<{
|
|
21
|
+
recordlist: T[];
|
|
22
|
+
uniqueKey?: string;
|
|
23
|
+
documentTitle?: string;
|
|
24
|
+
}>();
|
|
25
|
+
</script>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<DataTable
|
|
3
|
+
v-bind="$attrs"
|
|
4
|
+
stripedRows
|
|
5
|
+
dataKey="_id"
|
|
6
|
+
:showGridlines="true"
|
|
7
|
+
size="small"
|
|
8
|
+
:pt="{
|
|
9
|
+
header: { class: '' },
|
|
10
|
+
headerRow: { class: ' bg-gray-200' },
|
|
11
|
+
}"
|
|
12
|
+
v-on:row-click="clickRow"
|
|
13
|
+
:value="value"
|
|
14
|
+
:filters="filters"
|
|
15
|
+
:paginator="true"
|
|
16
|
+
:rows="20"
|
|
17
|
+
:rowsPerPageOptions="[20, 40, 60, 100]"
|
|
18
|
+
>
|
|
19
|
+
<!-- header -->
|
|
20
|
+
<template #header>
|
|
21
|
+
<div class="flex flex-row w-full text-right justify-content-end">
|
|
22
|
+
<div class="flex-1">
|
|
23
|
+
<slot name="toolbar"></slot>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="flex-1">
|
|
26
|
+
<slot name="title">
|
|
27
|
+
<h1 class="text text-2xl pt-2 text-center dark:text-white">
|
|
28
|
+
{{ t(title) }}
|
|
29
|
+
</h1>
|
|
30
|
+
</slot>
|
|
31
|
+
</div>
|
|
32
|
+
<span class="p-input-icon-left flex-1">
|
|
33
|
+
<i class="pi pi-search mt-4 ml-2 text-gray-400 absolute" />
|
|
34
|
+
<InputText
|
|
35
|
+
type="search"
|
|
36
|
+
v-model="filters['global'].value"
|
|
37
|
+
class="text-right"
|
|
38
|
+
placeholder="Keyword Search"
|
|
39
|
+
/>
|
|
40
|
+
</span>
|
|
41
|
+
</div>
|
|
42
|
+
</template>
|
|
43
|
+
<!-- no data found -->
|
|
44
|
+
<template #empty>
|
|
45
|
+
<div class="text-center">
|
|
46
|
+
<div class="text-3xl text-gray-400 pi pi-exclamation-circle"></div>
|
|
47
|
+
<div class="text-3xl text-gray-400">{{ t("noDataFound") }}</div>
|
|
48
|
+
</div>
|
|
49
|
+
</template>
|
|
50
|
+
<slot name="default">
|
|
51
|
+
<Column header="undefineColumns"></Column>
|
|
52
|
+
</slot>
|
|
53
|
+
</DataTable>
|
|
54
|
+
</template>
|
|
55
|
+
<script setup lang="ts" generic="T">
|
|
56
|
+
// import { CellSetting } from "~/types";
|
|
57
|
+
import { FilterMatchMode } from "primevue/api";
|
|
58
|
+
import DataTable from "primevue/datatable";
|
|
59
|
+
import Column from "primevue/column";
|
|
60
|
+
import renderComponent from "~/components/renderer";
|
|
61
|
+
import { emit } from "process";
|
|
62
|
+
const props = defineProps<{
|
|
63
|
+
value: T[]
|
|
64
|
+
title: string
|
|
65
|
+
columns: string[]
|
|
66
|
+
uniqueKey: string
|
|
67
|
+
documentTitle: string
|
|
68
|
+
}>();
|
|
69
|
+
const emits = defineEmits(["selectRow"]);
|
|
70
|
+
const clickRow = (eventdata: any) => {
|
|
71
|
+
emits("selectRow", eventdata.data);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const filters = ref({
|
|
75
|
+
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
|
76
|
+
});
|
|
77
|
+
</script>
|
|
@@ -1,66 +1,137 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
2
|
+
<div class="relative ">
|
|
3
|
+
<div v-if="withFilter" class="flex flex-row ">
|
|
4
|
+
<InputText
|
|
5
|
+
placeholder="search"
|
|
6
|
+
v-model="searchvalue"
|
|
7
|
+
class="w-full dark:text-white"
|
|
8
|
+
type="search"
|
|
9
|
+
/>
|
|
10
|
+
<ButtonPrimary v-if="withAddNew" @click="emits('add')"
|
|
11
|
+
><i class="pi pi-plus"></i
|
|
12
|
+
></ButtonPrimary>
|
|
13
|
+
</div>
|
|
14
|
+
<div v-if="showIndex" class="flex flex-col text-sm fixed left-1 top-1/5 text-primary-600 dark:text-primary-400 p-1 z-10 rounded border bg-white dark:bg-black opacity-90">
|
|
15
|
+
<A :href="'#'+l" v-for="l in allLetters">{{ l }}</A>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div v-if="filterlist && filterlist.length > 0">
|
|
19
|
+
<div >
|
|
20
|
+
<div v-for="(item, index) in filterlist" :class="isMobile() ? '' : 'overflow overflow-y-scroll overflow-auto '">
|
|
21
|
+
<div class="w-full bg-gray-400 dark:bg-gray-500 p-1 pl-2 top-0 sticky opacity-90" v-if="showIndex && titleField && showCategoryBar(item[titleField][0])">
|
|
22
|
+
<a :id="item[titleField][0]">{{ item[titleField][0] }}</a></div>
|
|
23
|
+
<div :class="getSelectedCSS(item)">
|
|
24
|
+
<NuxtLink :to="url ? `${url}/${item[idField]}` : undefined">
|
|
25
|
+
|
|
26
|
+
<slot name="default" :item="item" :index="index">
|
|
27
|
+
<div class="flex flex-row">
|
|
28
|
+
<div class="flex-1 mr-2 dark:text-white">
|
|
29
|
+
{{ item[titleField ?? ""] }}
|
|
30
|
+
</div>
|
|
31
|
+
<div class="text-right dark:text-gray-400 text-gray-600">
|
|
32
|
+
{{ item[subTitleField ?? ""] }}
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</slot>
|
|
36
|
+
</NuxtLink>
|
|
37
|
+
</div>
|
|
25
38
|
</div>
|
|
39
|
+
</div>
|
|
26
40
|
</div>
|
|
41
|
+
<div v-else>
|
|
42
|
+
<div
|
|
43
|
+
class="w-full h-20 p-2 border-l-none border-r-none hover-list-primary"
|
|
44
|
+
>
|
|
45
|
+
<slot name="nodata">
|
|
46
|
+
<div class="border-round border-1 surface-border p-4 surface-card">
|
|
47
|
+
{{ t("noDataFound") }}
|
|
48
|
+
</div>
|
|
49
|
+
</slot>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
27
53
|
</template>
|
|
28
|
-
<script setup lang="ts" generic="T extends {[key:string]:any}">
|
|
29
|
-
import {ref} from
|
|
30
|
-
import {ListItem} from
|
|
31
|
-
const props = withDefaults(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
<script setup lang="ts" generic="T extends { [key: string]: any }">
|
|
55
|
+
import { ref } from "vue";
|
|
56
|
+
import { ListItem } from "~/types/listview";
|
|
57
|
+
const props = withDefaults(
|
|
58
|
+
defineProps<{
|
|
59
|
+
list: T[];
|
|
60
|
+
url?: string;
|
|
61
|
+
titleField?: string;
|
|
62
|
+
idField?: string;
|
|
63
|
+
subTitleField?: string;
|
|
64
|
+
withFilter?: boolean;
|
|
65
|
+
withAddNew?: boolean;
|
|
66
|
+
showIndex?:boolean
|
|
67
|
+
}>(),
|
|
68
|
+
{
|
|
69
|
+
idField: "_id",
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
const letters =ref<string[]> ([])
|
|
73
|
+
let lastchar=''
|
|
74
|
+
|
|
75
|
+
const emits = defineEmits(["add"]);
|
|
76
|
+
const searchvalue = ref("");
|
|
77
|
+
const selecteditem = ref("");
|
|
78
|
+
const clickRow = (item: ListItem) => {
|
|
79
|
+
// emit('clickitem',item)
|
|
80
|
+
// selecteditem.value = item.code
|
|
81
|
+
};
|
|
82
|
+
const filterlist = computed(() => {
|
|
83
|
+
let newlist: T[] = [];
|
|
84
|
+
if (!Array.isArray(props.list)) {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
if (props.list !== undefined) {
|
|
88
|
+
newlist = props.list.filter((item: T) => {
|
|
89
|
+
return (
|
|
90
|
+
String(item[props.titleField ?? ""])
|
|
91
|
+
.toLowerCase()
|
|
92
|
+
.includes(searchvalue.value.toLowerCase()) ||
|
|
93
|
+
String(item[props.subTitleField ?? ""])
|
|
94
|
+
.toLowerCase()
|
|
95
|
+
.includes(searchvalue.value.toLowerCase())
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return newlist;
|
|
101
|
+
});
|
|
102
|
+
const getSelectedCSS = (item: T) => {
|
|
103
|
+
if (selecteditem.value == item.code) {
|
|
104
|
+
return "p-2 border-l-none border-r-none bg-sky-200 border-t-2";
|
|
105
|
+
} else {
|
|
106
|
+
return "p-2 border-l-none border-r-none hover-list-primary border-t-2 dark:border-t-gray-700";
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
const allLetters = computed(()=>{
|
|
112
|
+
console.log('props.titleFieldprops.titleField',props.titleField,props.list)
|
|
113
|
+
if(props.titleField && props.list){
|
|
114
|
+
|
|
115
|
+
return props.list.filter((item)=>{
|
|
116
|
+
const titlevalue:string = item[props.titleField as keyof typeof item]
|
|
117
|
+
if(titlevalue[0]!=lastchar){
|
|
118
|
+
lastchar = item[props.titleField as keyof typeof item][0]
|
|
119
|
+
return true
|
|
120
|
+
}
|
|
121
|
+
}).map(item=>item[props.titleField as keyof typeof item][0])
|
|
122
|
+
|
|
123
|
+
}else{
|
|
124
|
+
return []
|
|
125
|
+
}
|
|
54
126
|
|
|
55
|
-
return newlist
|
|
56
127
|
})
|
|
57
|
-
const getSelectedCSS= (item:T)=>{
|
|
58
|
-
if(selecteditem.value == item.code){
|
|
59
|
-
return "p-2 border bg-sky-200"
|
|
60
|
-
}else{
|
|
61
|
-
return "p-2 border hover-list-primary"
|
|
62
|
-
}
|
|
63
128
|
|
|
129
|
+
const showCategoryBar=(letter:string)=>{
|
|
130
|
+
if(lastchar!=letter){
|
|
131
|
+
lastchar=letter
|
|
132
|
+
return true
|
|
133
|
+
}else{
|
|
134
|
+
return false
|
|
135
|
+
}
|
|
64
136
|
}
|
|
65
|
-
|
|
66
|
-
</script>
|
|
137
|
+
</script>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="w-full dark:bg-gray-800 z-20 bg-white justify justify-between absolute h h-14 flex flex-row place-items-center opacity-90 dark:text-white"
|
|
4
|
+
>
|
|
5
|
+
<div class="w-full text-left"><slot name="start"></slot></div>
|
|
6
|
+
<div class="w-full text-center"><slot name="center"></slot></div>
|
|
7
|
+
<div class="w-full text-right"><slot name="end"></slot></div>
|
|
8
|
+
</div>
|
|
9
|
+
<div class="h-14"></div>
|
|
10
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Sidebar
|
|
3
|
+
position="right"
|
|
4
|
+
v-if="showDialog"
|
|
5
|
+
v-model:visible="showDialog"
|
|
6
|
+
modal
|
|
7
|
+
:show-close-icon="false"
|
|
8
|
+
#container
|
|
9
|
+
>
|
|
10
|
+
<div class="overflow-y-scroll">
|
|
11
|
+
<slot name="default"></slot>
|
|
12
|
+
</div>
|
|
13
|
+
</Sidebar>
|
|
14
|
+
</template>
|
|
15
|
+
<script lang="ts" setup>
|
|
16
|
+
const showDialog = defineModel<boolean>({ required: true });
|
|
17
|
+
const props = defineProps<{ closeEventName: string }>();
|
|
18
|
+
useNuxtApp().$listen("CloseDialog", (closeEventName: string) => {
|
|
19
|
+
if (props.closeEventName == closeEventName) showDialog.value = false;
|
|
20
|
+
});
|
|
21
|
+
</script>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Sidebar
|
|
3
|
+
position="bottom"
|
|
4
|
+
v-if="showDialog"
|
|
5
|
+
v-model:visible="showDialog"
|
|
6
|
+
modal
|
|
7
|
+
:show-close-icon="false"
|
|
8
|
+
#container
|
|
9
|
+
>
|
|
10
|
+
<div class="overflow-y-scroll">
|
|
11
|
+
<slot name="default"></slot>
|
|
12
|
+
</div>
|
|
13
|
+
</Sidebar>
|
|
14
|
+
</template>
|
|
15
|
+
<script lang="ts" setup>
|
|
16
|
+
const showDialog = defineModel<boolean>({ required: true });
|
|
17
|
+
useNuxtApp().$listen("CloseDialog", (closeEventName: string) => {
|
|
18
|
+
if (closeEventName=='viewer') showDialog.value = false;
|
|
19
|
+
});
|
|
20
|
+
</script>
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<title v-if="!id">{{ t(doc.getDocName()) }}</title>
|
|
3
|
+
<div v-if="isMobile()" class="w-full">
|
|
4
|
+
<div class="p-2 flex flex-row justify-end place-items-center h-14">
|
|
5
|
+
<div class="flex-1">
|
|
6
|
+
<TextTitle>{{ t(doc.getDocName()) }}</TextTitle>
|
|
7
|
+
</div>
|
|
8
|
+
<div>
|
|
9
|
+
<ButtonText
|
|
10
|
+
@click="goTo(doc.getDocName(), 'new')"
|
|
11
|
+
class="pi pi-plus"
|
|
12
|
+
></ButtonText>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
<ListDocument
|
|
16
|
+
v-if="recordlist"
|
|
17
|
+
@click="showDialogForm"
|
|
18
|
+
:recordlist="recordlist as T[]"
|
|
19
|
+
:unique-key="uniqueKey"
|
|
20
|
+
:document-title="documentTitle"
|
|
21
|
+
>
|
|
22
|
+
<template #default="{ index, item }">
|
|
23
|
+
<slot name="mobileList" :index="index" :item="item as T"></slot>
|
|
24
|
+
</template>
|
|
25
|
+
</ListDocument>
|
|
26
|
+
</div>
|
|
27
|
+
<div v-else class="simpleapp-crudsimple">
|
|
28
|
+
<ListDocumentTable
|
|
29
|
+
v-if="recordlist"
|
|
30
|
+
:value="recordlist as T[]"
|
|
31
|
+
:title="doc.getDocName()"
|
|
32
|
+
:unique-key="<string>uniqueKey"
|
|
33
|
+
:document-title="<string>documentTitle"
|
|
34
|
+
:columns="columns"
|
|
35
|
+
>
|
|
36
|
+
<template #toolbar>
|
|
37
|
+
<div class="w-full text-left">
|
|
38
|
+
<ButtonPrimary
|
|
39
|
+
class="pi pi-plus"
|
|
40
|
+
@click="newData"
|
|
41
|
+
v-tooltip="t('new')"
|
|
42
|
+
v-if="canPerform(resourcename, 'create')"
|
|
43
|
+
></ButtonPrimary>
|
|
44
|
+
</div>
|
|
45
|
+
</template>
|
|
46
|
+
<template #default>
|
|
47
|
+
<slot name="dataTableColumns">
|
|
48
|
+
<Column v-for="col in columns.filter((item,index)=>index<6)" :header="t(col)" class="min-w-[5rem]" #body="{index,data}">
|
|
49
|
+
<RendererLink v-if="uniqueKey === col || documentTitle === col"
|
|
50
|
+
:value="data" :setting="{ path: resourcename.toLocaleLowerCase() }"
|
|
51
|
+
:fields="[col]" >
|
|
52
|
+
{{ data[col] }}
|
|
53
|
+
</RendererLink>
|
|
54
|
+
<span v-else-if="data[col]?.label !==undefined">{{ data[col].label }}</span>
|
|
55
|
+
<span v-else>{{ data[col] }}</span>
|
|
56
|
+
</Column>
|
|
57
|
+
|
|
58
|
+
</slot>
|
|
59
|
+
</template>
|
|
60
|
+
</ListDocumentTable>
|
|
61
|
+
</div>
|
|
62
|
+
<OverlaySideBarCrud
|
|
63
|
+
v-model="showDialog"
|
|
64
|
+
:closeEventName="doc.getDocName()"
|
|
65
|
+
#default
|
|
66
|
+
><slot name="default">
|
|
67
|
+
<NuxtPage :_id="id"></NuxtPage>
|
|
68
|
+
</slot>
|
|
69
|
+
</OverlaySideBarCrud>
|
|
70
|
+
</template>
|
|
71
|
+
|
|
72
|
+
<script setup lang="ts" generic="T extends { [key: string]: any }">
|
|
73
|
+
/**
|
|
74
|
+
* This file was automatically generated by simpleapp generator during initialization.
|
|
75
|
+
* DO NOT MODIFY IT BY HAND.
|
|
76
|
+
* last change 2024-02-04
|
|
77
|
+
* author: Ks Tan
|
|
78
|
+
*/
|
|
79
|
+
import { ref } from "vue";
|
|
80
|
+
import _ from "lodash";
|
|
81
|
+
import { SearchBody } from "~/types";
|
|
82
|
+
import { SimpleAppClient } from "~/simpleapp/generate/clients/SimpleAppClient";
|
|
83
|
+
const props = defineProps<{
|
|
84
|
+
document: SimpleAppClient<any, any>;
|
|
85
|
+
data: T;
|
|
86
|
+
columns: string[];
|
|
87
|
+
mobileColumns?: string[];
|
|
88
|
+
sorts?: string[][];
|
|
89
|
+
}>();
|
|
90
|
+
|
|
91
|
+
const emits = defineEmits(["selectRow"]);
|
|
92
|
+
const id = computed(() => getPathPara("id"));
|
|
93
|
+
const resourcename = ref(_.upperFirst(props.document.getDocName()));
|
|
94
|
+
const visible = ref(false);
|
|
95
|
+
const showDialog = ref(false);
|
|
96
|
+
const op = ref();
|
|
97
|
+
const doc = props.document;
|
|
98
|
+
const disabled = ref(false);
|
|
99
|
+
|
|
100
|
+
const router = useRouter();
|
|
101
|
+
const route = useRoute();
|
|
102
|
+
const filters = ref();
|
|
103
|
+
const popuptitle = ref(t(doc.getDocName()));
|
|
104
|
+
const systemwindows = ref(false);
|
|
105
|
+
const { $event, $listen } = useNuxtApp();
|
|
106
|
+
const recordlist = ref<T[]>();
|
|
107
|
+
const uniqueKey = doc.getSchema()["x-simpleapp-config"].uniqueKey;
|
|
108
|
+
const documentTitle = doc.getSchema()["x-simpleapp-config"].documentTitle;
|
|
109
|
+
|
|
110
|
+
const refresh = () => {
|
|
111
|
+
const searchbody: SearchBody = {
|
|
112
|
+
fields: props.columns,
|
|
113
|
+
sorts: props.sorts,
|
|
114
|
+
};
|
|
115
|
+
doc.search(searchbody).then((res: any) => {
|
|
116
|
+
recordlist.value = res;
|
|
117
|
+
disabled.value = false;
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
const newData = () => {
|
|
121
|
+
router.push({ path: getDocumentUrl(doc.getDocName(), "new") });
|
|
122
|
+
popuptitle.value = t(doc.getDocName());
|
|
123
|
+
doc.setNew();
|
|
124
|
+
visible.value = true;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
onMounted(() => {
|
|
128
|
+
refresh();
|
|
129
|
+
});
|
|
130
|
+
$listen("RefreshDocumentList", (data) => {
|
|
131
|
+
if (data.documentName == doc.getDocName()) {
|
|
132
|
+
refresh();
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
const showDialogForm = (item: T) => {
|
|
136
|
+
goTo(doc.getDocName(), item._id);
|
|
137
|
+
popuptitle.value = <string>item[documentTitle as keyof T];
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
watch(showDialog, () => {
|
|
141
|
+
if (!showDialog.value) {
|
|
142
|
+
goTo(props.document.getDocName());
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
watch(
|
|
146
|
+
() => useRoute().path,
|
|
147
|
+
async () => {
|
|
148
|
+
if (getPathPara("id")) {
|
|
149
|
+
showDialog.value = true;
|
|
150
|
+
} else {
|
|
151
|
+
showDialog.value = false;
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
onMounted(() => {
|
|
157
|
+
if (id.value) {
|
|
158
|
+
showDialog.value = true;
|
|
159
|
+
} else {
|
|
160
|
+
showDialog.value = false;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
useNuxtApp().$listen("CloseDialog", (documentName: string) => {
|
|
164
|
+
if (documentName == doc.getDocName()) {
|
|
165
|
+
goTo(resourcename.value);
|
|
166
|
+
showDialog.value = false;
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
</script>
|