@simitgroup/simpleapp-generator 1.6.0-alpha → 1.6.2-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/README.md +8 -1
- package/dist/framework.d.ts.map +1 -1
- package/dist/framework.js +2 -1
- package/dist/framework.js.map +1 -1
- package/package.json +1 -1
- package/src/framework.ts +2 -1
- package/templates/basic/nest/processor.ts.eta +2 -1
- package/templates/basic/nuxt/component.select.vue.eta +5 -1
- package/templates/basic/nuxt/simpleapp.generate.client.ts.eta +11 -13
- package/templates/nest/src/app.module.ts.eta +12 -4
- package/templates/nest/src/cloudapi/cloudapi.module.ts._eta +1 -1
- package/templates/nest/src/printapi/printapi.module.ts.eta +1 -1
- package/templates/nest/src/simpleapp/generate/commons/robotuser.service.ts.eta +5 -4
- package/templates/nest/src/simpleapp/generate/commons/user.context.ts.eta +1 -0
- package/templates/nest/src/simpleapp/generate/processors/perm.processor.ts.eta +1 -1
- package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +51 -7
- package/templates/nest/src/simpleapp/generate/types/simpleapp.type.ts.eta +2 -2
- package/templates/nest/src/simpleapp/profile/profile.apischema.ts.eta +15 -0
- package/templates/nest/src/simpleapp/profile/profile.controller.ts.eta +3 -1
- package/templates/nest/src/simpleapp/profile/profile.service.ts.eta +20 -3
- package/templates/nest/src/simpleapp/services/userresolver.service.ts._eta +22 -25
- package/templates/nest/src/simpleapp/simpleapp.module.ts.eta +4 -4
- package/templates/nuxt/assets/css/listview.css._eta +2 -2
- package/templates/nuxt/components/calendar/CalendarInput.vue.eta +24 -0
- package/templates/nuxt/components/calendar/CalendarSmall.vue.eta +11 -2
- package/templates/nuxt/components/debug/DebugDocumentData.vue.eta +1 -1
- package/templates/nuxt/components/list/ListView.vue.eta +66 -28
- package/templates/nuxt/components/renderer/RendererMoney.vue.eta +11 -12
- package/templates/nuxt/components/select/SelectTemplate.vue.eta +49 -20
- package/templates/nuxt/components/simpleApp/SimpleAppAutocomplete.vue.eta +1 -1
- package/templates/nuxt/components/simpleApp/SimpleAppChildrenList.vue.eta +16 -15
- package/templates/nuxt/components/simpleApp/SimpleAppFormToolBar.vue._eta +18 -20
- package/templates/nuxt/components/simpleApp/SimpleAppInput.vue.eta +29 -6
- package/templates/nuxt/components/user/UserButtonCreateTenant.vue._eta +18 -2
- package/templates/nuxt/composables/date.generate.ts.eta +1 -0
- package/templates/nuxt/composables/getUserStore.generate.ts.eta +1 -1
- package/templates/nuxt/simpleapp/generate/clients/SimpleAppClient.ts.eta +4 -1
- package/templates/project/jsonschemas/invoice.json._eta +15 -7
- package/templates/project/lang/default._json +1 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex flex-col ">
|
|
3
|
+
<label v-if="label" :for="inputid">{{ label }}</label>
|
|
4
|
+
<Calendar
|
|
5
|
+
v-model="modelValue"
|
|
6
|
+
class="w-full"
|
|
7
|
+
:inputid="inputid"
|
|
8
|
+
:date-format="getPrimevueCalendarDateFormat()"
|
|
9
|
+
/>
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
<script setup lang="ts">
|
|
13
|
+
/**
|
|
14
|
+
* This file was automatically generated by simpleapp generator during initialization.
|
|
15
|
+
* IT IS NOT CHANGABLE
|
|
16
|
+
* last change 2024-04-16
|
|
17
|
+
* author: Ks Tan
|
|
18
|
+
*/
|
|
19
|
+
const modelValue = defineModel<Date>({required:true})
|
|
20
|
+
const inputid=randomUUID()
|
|
21
|
+
const props = defineProps<{
|
|
22
|
+
label?:string
|
|
23
|
+
}>()
|
|
24
|
+
</script>
|
|
@@ -13,11 +13,13 @@
|
|
|
13
13
|
@view-change="viewChange"
|
|
14
14
|
:events="allevents"
|
|
15
15
|
@cell-focus="chooseDate"
|
|
16
|
+
|
|
16
17
|
xsmall
|
|
17
18
|
>
|
|
18
19
|
<template #today-button>
|
|
19
20
|
<!-- Using Vuetify (but we prefer Wave UI 🤘) -->
|
|
20
|
-
<div
|
|
21
|
+
<div
|
|
22
|
+
@click="chooseDate(new Date(), true)">{{ t("today") }}</div>
|
|
21
23
|
</template>
|
|
22
24
|
<template #cell-content="{ cell, events }">
|
|
23
25
|
<div>
|
|
@@ -31,7 +33,7 @@
|
|
|
31
33
|
<span v-else>{{ cell.content }} </span>
|
|
32
34
|
</div>
|
|
33
35
|
<div>
|
|
34
|
-
<slot name="default" :cell="cell" events="events">
|
|
36
|
+
<slot name="default" :cell="cell" :events="events">
|
|
35
37
|
<Badge
|
|
36
38
|
v-if="events.length > 0"
|
|
37
39
|
@contextmenu="(mouseevent) => onRightClickDate(mouseevent, cell)"
|
|
@@ -75,8 +77,14 @@ const allevents = computed(() => {
|
|
|
75
77
|
const list = props.items.map((item) => {
|
|
76
78
|
if (item.start instanceof Date)
|
|
77
79
|
item.start = item.start.format("YYYY-MM-DD HH:mm");
|
|
80
|
+
else if (typeof item.start == 'string' ){
|
|
81
|
+
item.start = item.start.substring(0,16).replace('T',' ');
|
|
82
|
+
}
|
|
78
83
|
if (item.end instanceof Date)
|
|
79
84
|
item.end = item.end.format("YYYY-MM-DD HH:mm");
|
|
85
|
+
else if (typeof item.end == 'string' ){
|
|
86
|
+
item.end = item.end.substring(0,16).replace('T',' ');
|
|
87
|
+
}
|
|
80
88
|
return item;
|
|
81
89
|
});
|
|
82
90
|
return list;
|
|
@@ -84,6 +92,7 @@ const allevents = computed(() => {
|
|
|
84
92
|
const viewChange = (event: CalViewChange) => {
|
|
85
93
|
viewStatus.value = event;
|
|
86
94
|
};
|
|
95
|
+
|
|
87
96
|
const chooseDate = (date1: Date, force?: boolean) => {
|
|
88
97
|
if (force || !viewStatus.value || viewStatus.value.view == "month") {
|
|
89
98
|
selectedDate.value = date1;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div :class="`p-0 absolute bg-yellow-200 bottom-
|
|
2
|
+
<div :class="`p-0 absolute bg-yellow-200 bottom-100 right-0`" v-if="isdebug=='1'">
|
|
3
3
|
<button @click="visible=true" class=" text-white text-xs bg-warning-800 p-0 m-0">
|
|
4
4
|
<i class="pi pi-code"></i>{{ label }}</button>
|
|
5
5
|
<Sidebar v-model:visible="visible" class="text-red-100">
|
|
@@ -1,21 +1,29 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="relative">
|
|
3
|
-
<div v-if="withFilter" class="flex flex-row">
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
3
|
+
<div v-if="withFilter" class="flex flex-row p-2">
|
|
4
|
+
<InputGroup>
|
|
5
|
+
<InputGroupAddon v-if="filter">
|
|
6
|
+
|
|
7
|
+
<ButtonDefault @click="showMoreFilter" v-if="Object.keys(filter)==0">
|
|
8
|
+
<i class="pi pi-filter"></i>
|
|
9
|
+
</ButtonDefault>
|
|
10
|
+
<ButtonWarning @click="showMoreFilter" v-else>
|
|
11
|
+
<i class="pi pi-filter"></i>
|
|
12
|
+
</ButtonWarning>
|
|
13
|
+
</InputGroupAddon>
|
|
14
|
+
<InputText
|
|
15
|
+
:placeholder="t('searchKeyword')"
|
|
16
|
+
v-model="searchvalue"
|
|
17
|
+
class="w-full dark:text-white text-sm "
|
|
18
|
+
type="search"
|
|
19
|
+
ref="listviewfilter"
|
|
20
|
+
/>
|
|
21
|
+
<InputGroupAddon v-if="withAddNew">
|
|
22
|
+
<ButtonPrimary @click="emits('add')">
|
|
23
|
+
<i class="pi pi-plus"></i>
|
|
24
|
+
</ButtonPrimary>
|
|
25
|
+
</InputGroupAddon>
|
|
26
|
+
</InputGroup>
|
|
19
27
|
</div>
|
|
20
28
|
|
|
21
29
|
<div
|
|
@@ -51,9 +59,9 @@
|
|
|
51
59
|
index > 0 ? 'border-t-2' : ''
|
|
52
60
|
}`"
|
|
53
61
|
>
|
|
54
|
-
<NuxtLink
|
|
55
|
-
|
|
56
|
-
class="p-2"
|
|
62
|
+
<NuxtLink
|
|
63
|
+
:to="getUrl(item)"
|
|
64
|
+
:class="`p-2 ${showClickEffect ? 'listlink' : ''}`"
|
|
57
65
|
>
|
|
58
66
|
<slot name="default" :item="item" :index="index">
|
|
59
67
|
<div class="flex flex-row">
|
|
@@ -79,6 +87,23 @@
|
|
|
79
87
|
</slot>
|
|
80
88
|
</div>
|
|
81
89
|
</div>
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
<Dialog v-model:visible="visibleMoreFilter" :header="t('filter')">
|
|
93
|
+
<slot name="filter">
|
|
94
|
+
define filter in #filter
|
|
95
|
+
</slot>
|
|
96
|
+
<template #footer>
|
|
97
|
+
<div class="flex flex-row">
|
|
98
|
+
<ButtonDefault @click="clearFilter" class="flex flex-row p-2">
|
|
99
|
+
<i class="pi pi-times mr-1"/> <span class="mr-1">{{t('clear')}}</span>
|
|
100
|
+
</ButtonDefault>
|
|
101
|
+
<ButtonPrimary @click="runFilter" class="flex flex-row p-2">
|
|
102
|
+
<i class="pi pi-filter mr-1"/> <span class="mr-1">{{t('ok')}}</span>
|
|
103
|
+
</ButtonPrimary>
|
|
104
|
+
</div>
|
|
105
|
+
</template>
|
|
106
|
+
</Dialog>
|
|
82
107
|
</div>
|
|
83
108
|
</template>
|
|
84
109
|
<script setup lang="ts" generic="T extends { [key: string]: any }">
|
|
@@ -90,7 +115,8 @@
|
|
|
90
115
|
*/
|
|
91
116
|
import { ref } from "vue";
|
|
92
117
|
import { ListItem } from "~/types/listview";
|
|
93
|
-
import _ from
|
|
118
|
+
import _ from "lodash";
|
|
119
|
+
const visibleMoreFilter = ref(false)
|
|
94
120
|
const listviewfilter = ref();
|
|
95
121
|
const props = withDefaults(
|
|
96
122
|
defineProps<{
|
|
@@ -100,8 +126,10 @@ const props = withDefaults(
|
|
|
100
126
|
idField?: string;
|
|
101
127
|
subTitleField?: string;
|
|
102
128
|
withFilter?: boolean;
|
|
129
|
+
filter?:Object;
|
|
103
130
|
withAddNew?: boolean;
|
|
104
131
|
showIndex?: boolean;
|
|
132
|
+
showClickEffect?: boolean;
|
|
105
133
|
}>(),
|
|
106
134
|
{
|
|
107
135
|
idField: "_id",
|
|
@@ -110,21 +138,20 @@ const props = withDefaults(
|
|
|
110
138
|
const letters = ref<string[]>([]);
|
|
111
139
|
let lastchar = "";
|
|
112
140
|
|
|
113
|
-
const emits = defineEmits(["add", "click"]);
|
|
141
|
+
const emits = defineEmits(["add", "runFilter", "clearFilter","click"]);
|
|
114
142
|
const searchvalue = ref("");
|
|
115
143
|
const selecteditem = ref("");
|
|
116
144
|
const clickRow = (item: ListItem) => {
|
|
117
145
|
// emit('clickitem',item)
|
|
118
146
|
// selecteditem.value = item.code
|
|
119
147
|
};
|
|
120
|
-
const getUrl = (item:any)=>{
|
|
121
|
-
if(props.url && props.idField) {
|
|
122
|
-
if(_.last(props.url)==
|
|
123
|
-
else return `${props.url}/${item[props.idField]}
|
|
124
|
-
}
|
|
125
|
-
else return undefined
|
|
148
|
+
const getUrl = (item: any) => {
|
|
149
|
+
if (props.url && props.idField) {
|
|
150
|
+
if (_.last(props.url) == "/") return `${props.url}${item[props.idField]}`;
|
|
151
|
+
else return `${props.url}/${item[props.idField]}`;
|
|
152
|
+
} else return undefined;
|
|
126
153
|
// :to="url ? `${url}/${item[idField]}` : undefined"
|
|
127
|
-
}
|
|
154
|
+
};
|
|
128
155
|
const filterlist = computed(() => {
|
|
129
156
|
let newlist: T[] = [];
|
|
130
157
|
if (!Array.isArray(props.list)) {
|
|
@@ -175,6 +202,17 @@ const onClick = (index: number, data: T) => {
|
|
|
175
202
|
emits("click", index, data);
|
|
176
203
|
};
|
|
177
204
|
|
|
205
|
+
const showMoreFilter = ()=>{
|
|
206
|
+
visibleMoreFilter.value=true
|
|
207
|
+
}
|
|
208
|
+
const clearFilter = () =>{
|
|
209
|
+
visibleMoreFilter.value = false
|
|
210
|
+
emits('clearFilter')
|
|
211
|
+
}
|
|
212
|
+
const runFilter = () => {
|
|
213
|
+
visibleMoreFilter.value = false
|
|
214
|
+
emits('runFilter')
|
|
215
|
+
}
|
|
178
216
|
onMounted(() => {
|
|
179
217
|
// if(props.withFilter) listviewfilter.value.$el.focus()
|
|
180
218
|
});
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<span v-if="typeof modelValue=='undefined' || typeof modelValue=='string'
|
|
3
|
-
|
|
4
|
-
{{
|
|
5
|
-
currenyValue
|
|
6
|
-
}}</span
|
|
2
|
+
<span v-if="typeof modelValue == 'undefined' || typeof modelValue == 'string'"
|
|
3
|
+
>-</span
|
|
7
4
|
>
|
|
5
|
+
<span v-else-if="showCurrency"> {{ currenyValue }}</span>
|
|
8
6
|
<span v-else>
|
|
9
7
|
{{ modelValue.toLocaleString(useI18n().defaultLocale, options) }}</span
|
|
10
8
|
>
|
|
@@ -16,14 +14,14 @@
|
|
|
16
14
|
* last change 2024-02-04
|
|
17
15
|
* author: Ks Tan
|
|
18
16
|
*/
|
|
19
|
-
const currenyValue = computed(()=>{
|
|
20
|
-
if(modelValue.value === undefined) return
|
|
17
|
+
const currenyValue = computed(() => {
|
|
18
|
+
if (modelValue.value === undefined) return "-";
|
|
21
19
|
return Intl.NumberFormat(useI18n().defaultLocale, {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
})
|
|
20
|
+
// style: "currency",
|
|
21
|
+
// currency: getUserProfile()?.currency ?? '',
|
|
22
|
+
// currencyDisplay: "symbol",
|
|
23
|
+
}).format(modelValue.value);
|
|
24
|
+
});
|
|
27
25
|
const options = {
|
|
28
26
|
style: "decimal", // Other options: 'currency', 'percent', etc.
|
|
29
27
|
minimumFractionDigits: 2,
|
|
@@ -31,4 +29,5 @@ const options = {
|
|
|
31
29
|
};
|
|
32
30
|
const modelValue = defineModel<number>({ required: true });
|
|
33
31
|
const props = defineProps<{ showCurrency?: boolean }>();
|
|
32
|
+
|
|
34
33
|
</script>
|
|
@@ -1,12 +1,36 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
<div>
|
|
3
|
+
<div class="flex flex-row ">
|
|
4
|
+
<label v-if="!hideLabel" :for="fieldid" class="pt-2">
|
|
5
|
+
{{t(documentName)}}
|
|
6
|
+
</label>
|
|
7
|
+
<ButtonText v-if="allowAddNew" @click="addnew" class="text-xs text-blue-600">
|
|
8
|
+
<span>{{t('new')}}</span>
|
|
9
|
+
</ButtonText>
|
|
10
|
+
</div>
|
|
11
|
+
<MultiSelect
|
|
12
|
+
:input-id="fieldid"
|
|
13
|
+
v-if="multiple"
|
|
14
|
+
display="chip"
|
|
15
|
+
@update:modelValue="change"
|
|
16
|
+
v-model="modelValue"
|
|
17
|
+
:options="options"
|
|
18
|
+
optionLabel="label"
|
|
19
|
+
optionValue="value"
|
|
20
|
+
:placeholder="placeholder"
|
|
21
|
+
/>
|
|
22
|
+
<Dropdown
|
|
23
|
+
|
|
24
|
+
:input-id="fieldid"
|
|
25
|
+
v-else
|
|
26
|
+
@update:modelValue="change"
|
|
27
|
+
v-model="modelValue"
|
|
28
|
+
:options="options"
|
|
29
|
+
optionLabel="label"
|
|
30
|
+
optionValue="value"
|
|
31
|
+
:placeholder="placeholder"
|
|
32
|
+
/>
|
|
33
|
+
</div>
|
|
10
34
|
</template>
|
|
11
35
|
<script setup lang="ts">
|
|
12
36
|
/**
|
|
@@ -18,15 +42,17 @@
|
|
|
18
42
|
import Dropdown from "primevue/dropdown";
|
|
19
43
|
import { ForeignKey, FormCrudEvent } from "~/types";
|
|
20
44
|
const emits = defineEmits(["change"]);
|
|
21
|
-
const modelValue = defineModel<string>();
|
|
45
|
+
const modelValue = defineModel<string | string[]>();
|
|
22
46
|
const list = ref<ForeignKey[]>([]);
|
|
23
|
-
|
|
47
|
+
const fieldid = randomUUID()
|
|
24
48
|
const props = defineProps<{
|
|
25
49
|
documentName: string;
|
|
26
50
|
placeholder?: string;
|
|
27
51
|
showNull?: boolean;
|
|
28
52
|
allowAddNew?: boolean;
|
|
29
|
-
filter?: any
|
|
53
|
+
filter?: any;
|
|
54
|
+
multiple?: boolean;
|
|
55
|
+
hideLabel?:boolean
|
|
30
56
|
}>();
|
|
31
57
|
const options = ref<
|
|
32
58
|
{
|
|
@@ -35,12 +61,12 @@ const options = ref<
|
|
|
35
61
|
}[]
|
|
36
62
|
>([]);
|
|
37
63
|
const getListOptions = async () => {
|
|
38
|
-
const filter = props.filter ?? {}
|
|
64
|
+
const filter = props.filter ?? {};
|
|
39
65
|
const res = await getDocumentApi(props.documentName).autoComplete("", filter);
|
|
40
66
|
list.value = res.data as ForeignKey[];
|
|
41
|
-
if (props.allowAddNew)
|
|
42
|
-
|
|
43
|
-
if (props.showNull)
|
|
67
|
+
// if (!props.multiple && props.allowAddNew)
|
|
68
|
+
// list.value.unshift({ _id: "new", code: "", label: t("addNew") });
|
|
69
|
+
if (!props.multiple && props.showNull)
|
|
44
70
|
list.value.unshift({ _id: "", code: "", label: t("null") });
|
|
45
71
|
options.value = list.value.map((item) => ({
|
|
46
72
|
value: item._id,
|
|
@@ -55,7 +81,12 @@ const getItem = (id: string) => list.value?.find((item) => item._id == id);
|
|
|
55
81
|
|
|
56
82
|
const change = (id: string) => {
|
|
57
83
|
const selectedItem = getItem(id);
|
|
58
|
-
|
|
84
|
+
emits("change", id, selectedItem);
|
|
85
|
+
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const addnew=()=>{
|
|
89
|
+
|
|
59
90
|
const doc = getDocument(props.documentName)?.docClass;
|
|
60
91
|
if (doc) {
|
|
61
92
|
const tmpdata = doc?.getReactiveData();
|
|
@@ -71,9 +102,7 @@ const change = (id: string) => {
|
|
|
71
102
|
}
|
|
72
103
|
},
|
|
73
104
|
);
|
|
74
|
-
|
|
75
|
-
} else {
|
|
76
|
-
emits("change", id, selectedItem);
|
|
105
|
+
|
|
77
106
|
}
|
|
78
|
-
}
|
|
107
|
+
}
|
|
79
108
|
</script>
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="flex flex-col">
|
|
3
|
-
<div class="flex flex-row">
|
|
4
|
-
|
|
5
|
-
<TextTitle v-if="title">{{ title }}</TextTitle>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
<div class="flex flex-row gap-2">
|
|
4
|
+
|
|
5
|
+
<TextTitle v-if="title" class="flex-1">{{ title }}</TextTitle>
|
|
6
|
+
|
|
7
|
+
<div class="flex flex-row"><slot name="buttons"></slot></div>
|
|
8
|
+
|
|
9
|
+
<div>
|
|
10
|
+
<ButtonDefault v-if="!readOnly" @click="addRow">
|
|
11
|
+
<i class="pi pi-plus"></i>
|
|
12
|
+
</ButtonDefault>
|
|
13
|
+
</div>
|
|
12
14
|
</div>
|
|
13
15
|
<ListView
|
|
14
16
|
class="p-2 dark:bg-slate-900 bg-slate-200 rounded-lg"
|
|
@@ -61,10 +63,9 @@ const updateItem = () => {
|
|
|
61
63
|
showDialog.value = false;
|
|
62
64
|
emits("itemupdated", rowIndex.value);
|
|
63
65
|
};
|
|
64
|
-
const addRow = (event:MouseEvent) =>{
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
66
|
+
const addRow = (event: MouseEvent) => {
|
|
67
|
+
emits("addrow", MouseEvent);
|
|
68
|
+
const lineno = props.list.length - 1;
|
|
69
|
+
showRow(lineno, props.list[lineno]);
|
|
70
|
+
};
|
|
70
71
|
</script>
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
<ConfirmPopup></ConfirmPopup>
|
|
67
67
|
</div>
|
|
68
68
|
<Dialog v-model:visible="visiblePrintFormats" :header="t('printFormats')">
|
|
69
|
-
<div>
|
|
69
|
+
<div>
|
|
70
70
|
<ListView
|
|
71
71
|
:list="printformats"
|
|
72
72
|
#default="{ item, index }"
|
|
@@ -84,16 +84,16 @@
|
|
|
84
84
|
:header="t('printPreview')"
|
|
85
85
|
position="bottom"
|
|
86
86
|
>
|
|
87
|
-
|
|
88
87
|
<TextDanger v-if="printservererror || !printstr">
|
|
89
88
|
{{ t("printServerError") }}
|
|
90
89
|
</TextDanger>
|
|
91
|
-
<vue-pdf-embed
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
<vue-pdf-embed
|
|
91
|
+
class="w-11/12"
|
|
92
|
+
v-else-if="isMobile()"
|
|
93
|
+
:source="printstr"
|
|
94
|
+
:disableTextLayer="true"
|
|
95
|
+
/>
|
|
95
96
|
<iframe v-else width="100%" height="100%" :src="printstr"></iframe>
|
|
96
|
-
|
|
97
97
|
</Sidebar>
|
|
98
98
|
</template>
|
|
99
99
|
<script setup lang="ts">
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
* last change 2024-04-02
|
|
104
104
|
* author: Ks Tan
|
|
105
105
|
*/
|
|
106
|
-
|
|
106
|
+
import VuePdfEmbed from "vue-pdf-embed";
|
|
107
107
|
|
|
108
108
|
// import VuePdfKit from 'vue-pdf-kit'
|
|
109
109
|
// import 'vue-pdf-kit/dist/style.css'
|
|
@@ -190,9 +190,7 @@ const printPdf = async (index: number, format: any) => {
|
|
|
190
190
|
const tmp: any = await doc
|
|
191
191
|
.getApi()
|
|
192
192
|
.runPrint(data.value._id ?? "", formatid);
|
|
193
|
-
printstr.value =
|
|
194
|
-
"data:application/pdf;base64," +
|
|
195
|
-
tmp.data;
|
|
193
|
+
printstr.value = "data:application/pdf;base64," + tmp.data;
|
|
196
194
|
} catch (e) {
|
|
197
195
|
printservererror.value = true;
|
|
198
196
|
printstr.value = "";
|
|
@@ -245,7 +243,7 @@ const emitEvent = async (menu: FormMenu, clickEvent: Event | MouseEvent) => {
|
|
|
245
243
|
message: `${t("deleteThisRecord?")}`,
|
|
246
244
|
|
|
247
245
|
// icon: "pi pi-exclamation-triangle gap-4",
|
|
248
|
-
acceptClass: "
|
|
246
|
+
acceptClass: "bg-danger-600 text-white",
|
|
249
247
|
accept: async () => {
|
|
250
248
|
if (await deleteData()) emits("on", FormCrudEvent.delete);
|
|
251
249
|
},
|
|
@@ -339,12 +337,12 @@ const getActionIcon = (actionName: string) => {
|
|
|
339
337
|
};
|
|
340
338
|
</script>
|
|
341
339
|
<style>
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
340
|
+
.vue-pdf-embed {
|
|
341
|
+
@apply p-4;
|
|
342
|
+
}
|
|
343
|
+
.vue-pdf-embed > div {
|
|
344
|
+
@apply mb-4;
|
|
345
|
+
/* margin-bottom: 8px;
|
|
348
346
|
box-shadow: 0 2px 8px 4px rgba(0, 0, 0, 0.1); */
|
|
349
|
-
|
|
350
|
-
</style>
|
|
347
|
+
}
|
|
348
|
+
</style>
|
|
@@ -134,6 +134,23 @@
|
|
|
134
134
|
@change="onChange"
|
|
135
135
|
/>
|
|
136
136
|
|
|
137
|
+
|
|
138
|
+
<MultiSelect
|
|
139
|
+
v-model="modelValue"
|
|
140
|
+
:pt="pt"
|
|
141
|
+
v-else-if="SimpleAppInputType.selectmultiple == inputType"
|
|
142
|
+
:inputId="slotprops.uuid"
|
|
143
|
+
:path="setting.instancepath"
|
|
144
|
+
:readonly="isReadonly"
|
|
145
|
+
class="w w-full lg:w-full"
|
|
146
|
+
:disabled="isReadonly"
|
|
147
|
+
:options="getListOptions()"
|
|
148
|
+
optionLabel="label"
|
|
149
|
+
optionValue="value"
|
|
150
|
+
:placeholder="placeholder"
|
|
151
|
+
v-bind="componentProps"
|
|
152
|
+
@change="onChange"
|
|
153
|
+
/>
|
|
137
154
|
<!-- radio component -->
|
|
138
155
|
<div v-else-if="inputType == SimpleAppInputType.radio">
|
|
139
156
|
<div v-for="(item, index) in getListOptions()">
|
|
@@ -236,7 +253,6 @@
|
|
|
236
253
|
:class="!pt ? 'w-full flex flex-col' : ''"
|
|
237
254
|
:inputId="slotprops.uuid"
|
|
238
255
|
@update:modelValue="onChange"
|
|
239
|
-
|
|
240
256
|
:path="setting.instancepath"
|
|
241
257
|
v-bind="componentProps as InputNumber"
|
|
242
258
|
:placeholder="placeholder"
|
|
@@ -288,6 +304,8 @@
|
|
|
288
304
|
v-bind="componentProps as InputTextProps"
|
|
289
305
|
/>
|
|
290
306
|
<!-- component require special treatment -->
|
|
307
|
+
|
|
308
|
+
<slot name="footer"></slot>
|
|
291
309
|
</SimpleAppFieldContainer>
|
|
292
310
|
</template>
|
|
293
311
|
|
|
@@ -443,10 +461,16 @@ const setFocus = (ev: any) => {
|
|
|
443
461
|
};
|
|
444
462
|
|
|
445
463
|
const getListOptions = () => {
|
|
446
|
-
const options = [];
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
464
|
+
const options = [];
|
|
465
|
+
const enumlist = props.setting.fieldsetting.type == 'array'
|
|
466
|
+
? props.setting.fieldsetting.items.enum
|
|
467
|
+
: props.setting.fieldsetting.enum
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
if (enumlist) {
|
|
472
|
+
for (let i = 0; i < enumlist.length; i++) {
|
|
473
|
+
const v = enumlist[i];
|
|
450
474
|
if (typeof v == "string") {
|
|
451
475
|
options.push({ value: v, label: t(v) });
|
|
452
476
|
} else {
|
|
@@ -523,7 +547,6 @@ onMounted(() => {
|
|
|
523
547
|
});
|
|
524
548
|
|
|
525
549
|
const onChange = () => {
|
|
526
|
-
console.log("On change ", props.inputType)
|
|
527
550
|
pt.value = undefined;
|
|
528
551
|
resetcount.value++;
|
|
529
552
|
emits("change", modelValue.value);
|
|
@@ -33,8 +33,15 @@
|
|
|
33
33
|
*/
|
|
34
34
|
import { ref } from "vue";
|
|
35
35
|
import { AxiosResponse } from "axios";
|
|
36
|
+
import {EventType,NotificationStatus} from "~/types"
|
|
36
37
|
const visible = ref(false);
|
|
37
|
-
const data = ref({
|
|
38
|
+
const data = ref({
|
|
39
|
+
tenantName: "",
|
|
40
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
41
|
+
utcOffset: new Date().getTimezoneOffset()
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
|
|
38
45
|
|
|
39
46
|
const createtitle = ref("Create My Company");
|
|
40
47
|
const errCreateTenant = ref();
|
|
@@ -55,7 +62,16 @@ const createTenant = async () => {
|
|
|
55
62
|
})
|
|
56
63
|
.catch((err) => {
|
|
57
64
|
errCreateTenant.value = err["message"];
|
|
58
|
-
console.error("errCreateTenant", err);
|
|
65
|
+
console.error("errCreateTenant", err.response.data.data);
|
|
66
|
+
|
|
67
|
+
useNuxtApp().$event('Notification',{
|
|
68
|
+
documentName:'tenant',
|
|
69
|
+
status: NotificationStatus.error,
|
|
70
|
+
summary:t('createError'),
|
|
71
|
+
data:err.response?.data?.data
|
|
72
|
+
|
|
73
|
+
})
|
|
74
|
+
|
|
59
75
|
})
|
|
60
76
|
.finally(() => {
|
|
61
77
|
onhold.value = false;
|
|
@@ -21,6 +21,7 @@ export const dateToISOString = (date:Date) => useDayjs()(date).toISOString()
|
|
|
21
21
|
export const dateToTimeString = (date:Date) => useDayjs()(date).format('HH:mm:ss')
|
|
22
22
|
export const stringToDate = (datestr:string) => new Date(datestr)
|
|
23
23
|
export const dateToDateTimeString = (date:Date)=> useDayjs().utc(date).format('YYYY-MM-DD HH:mm:ss')
|
|
24
|
+
export const toLocalDate = (date:string | Date)=> useDayjs().utc(date).format(getDateFormat())
|
|
24
25
|
export const toUTCDate = (date:string | Date)=> useDayjs().utc(date).format(getDateFormat())
|
|
25
26
|
export const toUTCDateTime = (date:string | Date)=> useDayjs().utc(date).format(getDateTimeFormat())
|
|
26
27
|
export const toUTCTime = (date:string | Date)=> useDayjs().utc(date).format('HH:mm')
|
|
@@ -14,7 +14,7 @@ export const reloadUserStore = async () =>{
|
|
|
14
14
|
const {$userstore} = useNuxtApp()
|
|
15
15
|
await $userstore.loadRemoteUserInfo()
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
export const getCurrency = () =>getUserStore()?.currency ?? '$$'
|
|
18
18
|
export const getUserProfile = () =>{
|
|
19
19
|
const userstore = getUserStore()
|
|
20
20
|
|
|
@@ -30,6 +30,7 @@ export class SimpleAppClient<
|
|
|
30
30
|
TApi extends crudType,
|
|
31
31
|
> {
|
|
32
32
|
// protected defaultTimeOut=5000
|
|
33
|
+
protected unwantchobj;
|
|
33
34
|
protected docapi;
|
|
34
35
|
public event:Function|null=null;
|
|
35
36
|
public listen:Function|null=null;
|
|
@@ -66,18 +67,20 @@ export class SimpleAppClient<
|
|
|
66
67
|
};
|
|
67
68
|
|
|
68
69
|
async getById(id?: string) {
|
|
70
|
+
if(this.unwantchobj)this.unwantchobj()
|
|
69
71
|
return await this.docapi.runFindOne(id,this.axios)
|
|
70
72
|
.then((res: AxiosResponse) => {
|
|
71
73
|
// if(this.event){this.event('info:getById',res.data)}
|
|
72
74
|
this.data.value={} as TData
|
|
73
75
|
Object.assign(this.data.value, res.data);
|
|
76
|
+
this.setWatchChange()
|
|
74
77
|
return res;
|
|
75
78
|
}).catch((res:any)=>{
|
|
76
79
|
// if(this.event){this.event('error:getById',res)}
|
|
77
80
|
return Promise.reject(res)
|
|
78
81
|
});
|
|
79
82
|
}
|
|
80
|
-
|
|
83
|
+
setWatchChange(){}
|
|
81
84
|
|
|
82
85
|
async runDefault(){
|
|
83
86
|
const res = await this.docapi.runDefault()
|