@simitgroup/simpleapp-generator 1.3.3-alpha → 1.3.4-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.
Files changed (67) hide show
  1. package/dist/framework.js +2 -2
  2. package/dist/framework.js.map +1 -1
  3. package/dist/generate.d.ts.map +1 -1
  4. package/dist/generate.js +7 -11
  5. package/dist/generate.js.map +1 -1
  6. package/dist/processors/jsonschemabuilder.d.ts.map +1 -1
  7. package/dist/processors/jsonschemabuilder.js +8 -0
  8. package/dist/processors/jsonschemabuilder.js.map +1 -1
  9. package/package.json +1 -1
  10. package/src/framework.ts +2 -2
  11. package/src/generate.ts +15 -12
  12. package/src/processors/jsonschemabuilder.ts +12 -1
  13. package/templates/basic/nest/controller.ts.eta +16 -5
  14. package/templates/basic/nuxt/component.select.vue.eta +35 -0
  15. package/templates/basic/nuxt/pages.form.vue.eta +5 -8
  16. package/templates/basic/nuxt/simpleapp.generate.client.ts.eta +3 -1
  17. package/templates/nest/src/simpleapp/generate/commons/user.context.ts.eta +10 -9
  18. package/templates/nest/src/simpleapp/generate/controllers/simpleapp.controller.ts.eta +2 -2
  19. package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +38 -38
  20. package/templates/nest/src/simpleapp/generate/types/simpleapp.type.ts.eta +14 -9
  21. package/templates/nuxt/assets/css/style.css._eta +39 -3
  22. package/templates/nuxt/assets/primevue/passthrough.ts._eta +17 -12
  23. package/templates/nuxt/components/button/ButtonAction.vue._eta +19 -0
  24. package/templates/nuxt/components/button/ButtonDanger.vue._eta +13 -6
  25. package/templates/nuxt/components/button/ButtonDefault.vue._eta +13 -6
  26. package/templates/nuxt/components/button/ButtonMultiple.vue._eta +9 -7
  27. package/templates/nuxt/components/button/ButtonPrimary.vue._eta +13 -6
  28. package/templates/nuxt/components/button/ButtonText.vue._eta +16 -7
  29. package/templates/nuxt/components/button/ButtonWarning.vue._eta +13 -6
  30. package/templates/nuxt/components/calendar/CalendarSmall.vue.eta +83 -69
  31. package/templates/nuxt/components/chart/card.vue._eta +32 -0
  32. package/templates/nuxt/components/event/EventDocumentViewer.vue._eta +44 -21
  33. package/templates/nuxt/components/event/EventNotification.vue._eta +119 -107
  34. package/templates/nuxt/components/header/button/HeaderButtonProfile.vue.eta +129 -75
  35. package/templates/nuxt/components/list/ListView.vue.eta +44 -13
  36. package/templates/nuxt/components/mobile/MobileToolbar.vue.eta +6 -5
  37. package/templates/nuxt/components/overlay/OverlayPanelWithToolBar.vue.eta +35 -37
  38. package/templates/nuxt/components/overlay/OverlaySideBarCrud.vue.eta +3 -4
  39. package/templates/nuxt/components/renderer/RendererDate.vue.eta +3 -2
  40. package/templates/nuxt/components/renderer/RendererForeignKey.vue.eta +38 -34
  41. package/templates/nuxt/components/select/SelectTemplate.vue.eta +79 -0
  42. package/templates/nuxt/components/select/readme.md +1 -0
  43. package/templates/nuxt/components/simpleApp/SimpleAppAutocomplete.vue.eta +181 -35
  44. package/templates/nuxt/components/simpleApp/SimpleAppChildrenList.vue.eta +70 -0
  45. package/templates/nuxt/components/simpleApp/SimpleAppDocumentNo.vue.eta +77 -73
  46. package/templates/nuxt/components/simpleApp/SimpleAppForm.vue.eta +113 -111
  47. package/templates/nuxt/components/simpleApp/{SimpleAppFormToolBar.vue.eta → SimpleAppFormToolBar.vue._eta} +125 -61
  48. package/templates/nuxt/components/simpleApp/SimpleAppInput.vue.eta +116 -42
  49. package/templates/nuxt/components/text/TextPrimary.vue._eta +13 -0
  50. package/templates/nuxt/components/user/UserButtonCreateTenant.vue._eta +68 -0
  51. package/templates/nuxt/components/user/UserTenantPicker.vue.eta +81 -70
  52. package/templates/nuxt/composables/date.generate.ts.eta +2 -0
  53. package/templates/nuxt/composables/getDocument.generate.ts.eta +35 -2
  54. package/templates/nuxt/composables/getOpenApi.generate.ts.eta +5 -1
  55. package/templates/nuxt/composables/refreshDocumentList.generate.ts.eta +2 -1
  56. package/templates/nuxt/lang/en.ts.eta +3 -1
  57. package/templates/nuxt/nuxt.config.ts._eta +3 -0
  58. package/templates/nuxt/pages/index.vue._eta +10 -56
  59. package/templates/nuxt/pages/picktenant.vue._eta +19 -0
  60. package/templates/nuxt/plugins/10.simpleapp-event.ts.eta +10 -2
  61. package/templates/nuxt/server/api/[xorg]/[...].ts.eta +9 -10
  62. package/templates/nuxt/types/calendar.ts.eta +2 -0
  63. package/templates/nuxt/types/events.ts.eta +3 -1
  64. package/templates/nuxt/types/simpleappinput.ts.eta +1 -0
  65. package/templates/project/lang/default._json +5 -1
  66. package/tsconfig.tsbuildinfo +1 -1
  67. package/templates/nuxt/components/user/UserButtonCreateTenant.vue.eta +0 -103
@@ -1,131 +1,133 @@
1
1
  <template>
2
- <form class="simpleapp-form" @submit.prevent="true">
3
- <slot name="header"><h3 class="flex flex-col">{{ title }}</h3></slot>
4
- <slot name="default" :data="document.getData()" :getField="getField"></slot>
5
- </form>
2
+ <form class="simpleapp-form" @submit.prevent="true">
3
+ <slot name="default" :data="document.getData()" :getField="getField"></slot>
4
+ </form>
6
5
  </template>
7
- <script setup lang="ts" >
6
+ <script setup lang="ts">
8
7
  /**
9
8
  * This file was automatically generated by simpleapp generator. Every
10
9
  * MODIFICATION OVERRIDE BY GENERATEOR
11
10
  * last change 2023-10-28
12
11
  * Author: Ks Tan
13
12
  */
14
- import jsonpath from 'jsonpath';
15
- import { SimpleAppClient } from '~/simpleapp/generate/clients/SimpleAppClient'
16
- import type { JSONSchema7,JSONSchema7Definition } from 'json-schema';
17
- import * as alldefaults from '~/simpleapp/generate/defaults'
18
- import _, { upperFirst } from 'lodash'
19
- const props = defineProps<{
20
- title?:string,
21
- document: SimpleAppClient<any,any>
22
- readonly?:boolean
23
- }>()
24
- if(!props.document){
25
- throw "undefine SimpleAppForm property 'document'"
26
- }
13
+ import jsonpath from "jsonpath";
14
+ import { SimpleAppClient } from "~/simpleapp/generate/clients/SimpleAppClient";
15
+ import type { JSONSchema7, JSONSchema7Definition } from "json-schema";
16
+ import * as alldefaults from "~/simpleapp/generate/defaults";
17
+ import _, { upperFirst } from "lodash";
18
+ const props = defineProps<{
19
+
20
+ document: SimpleAppClient<any, any>;
21
+ readonly?: boolean;
22
+ }>();
23
+ if (!props.document) {
24
+ throw "undefine SimpleAppForm property 'document'";
25
+ }
27
26
 
28
- const isreadonly = computed(()=> props.readonly ? props.readonly: props.document.isReadOnly())
27
+ const isreadonly = computed(() =>
28
+ props.readonly ? props.readonly : props.document.isReadOnly(),
29
+ );
29
30
 
30
- // const obj = {schema:props.schema,data: props.schema}
31
- const getField = (path:string)=>{
32
- // console.log("simpleform topath",path)
33
- const data = props.document.getData()
34
- const schema = props.document.getSchema() as JSONSchema7 //force type for compatibility
35
- const fieldsetting = getPathObject(schema,path)
36
- // console.log("setting",fieldsetting)
37
-
38
- type defaulttype = typeof alldefaults
39
- type keytype = keyof defaulttype
40
-
41
- const x : keytype = 'Default'+ props.document.getDocName(true) as keytype
42
- const defaultvalue = alldefaults[x](randomUUID())
43
- return {
44
- path: path,
45
- key: _.last(path.split('/')),
46
- instancepath: getInstancePath(schema,path),
47
- fieldsetting: fieldsetting,
48
- modelObject: data,
49
- document: props.document,
50
- apiObj:props.document.getApi(),
51
- modelField: 'email',
52
- isrequired: getIsRequired(schema,path),
53
- errors: props.document.getErrors(),
54
- readonly: isreadonly.value,
55
- defaultValue: defaultvalue
56
- } //as SimpleAppFieldSetting
57
- }
31
+ // const obj = {schema:props.schema,data: props.schema}
32
+ const getField = (path: string) => {
33
+ // console.log("simpleform topath",path)
34
+ const data = props.document.getData();
35
+ const schema = props.document.getSchema() as JSONSchema7; //force type for compatibility
36
+ const fieldsetting = getPathObject(schema, path);
37
+ // console.log("setting",fieldsetting)
38
+
39
+ type defaulttype = typeof alldefaults;
40
+ type keytype = keyof defaulttype;
58
41
 
59
- // "schemaPath": "#/properties/email/format",
42
+ const x: keytype = ("Default" + props.document.getDocName(true)) as keytype;
43
+ const defaultvalue = alldefaults[x](randomUUID());
44
+ return {
45
+ path: path,
46
+ key: _.last(path.split("/")),
47
+ instancepath: getInstancePath(schema, path),
48
+ fieldsetting: fieldsetting,
49
+ modelObject: data,
50
+ document: props.document,
51
+ apiObj: props.document.getApi(),
52
+ modelField: "email",
53
+ isrequired: getIsRequired(schema, path),
54
+ errors: props.document.getErrors(),
55
+ readonly: isreadonly.value,
56
+ defaultValue: defaultvalue,
57
+ }; //as SimpleAppFieldSetting
58
+ };
60
59
 
61
- const getIsRequired=(schema:any,path:string)=>{
62
- if(!path){
63
- console.error('unknown path')
64
- return 'xx'
65
- }
60
+ // "schemaPath": "#/properties/email/format",
66
61
 
67
- try{
68
- let paths = path.replace('#/','').split('/')
69
- const fieldname = paths[paths.length-1]
70
- paths = paths.slice(0, -2);
71
- let tmp = schema
72
- for(let i=0;i<paths.length;i++){
73
- tmp = tmp[paths[i]]
74
-
75
- }
76
- if(Array.isArray(tmp['required']) ) {
77
- const arr:string[] = tmp['required']
78
- return arr.includes (fieldname)
79
- }else{
80
- return false
81
- }
62
+ const getIsRequired = (schema: any, path: string) => {
63
+ if (!path) {
64
+ console.error("unknown path");
65
+ return "xx";
66
+ }
82
67
 
83
- // console.log("get instance path",instancepath)
84
-
85
- // return tmp
86
- }catch(err:any){
87
- console.error(err.message)
88
- }
68
+ try {
69
+ let paths = path.replace("#/", "").split("/");
70
+ const fieldname = paths[paths.length - 1];
71
+ paths = paths.slice(0, -2);
72
+ let tmp = schema;
73
+ for (let i = 0; i < paths.length; i++) {
74
+ tmp = tmp[paths[i]];
89
75
  }
90
- const getInstancePath=(schema:any,path:string)=>{
91
- if(!path){
92
- console.error('unknown path')
93
- return 'yy'
76
+ if (Array.isArray(tmp["required"])) {
77
+ const arr: string[] = tmp["required"];
78
+ return arr.includes(fieldname);
79
+ } else {
80
+ return false;
94
81
  }
95
- try{
96
- let paths = path.replace('#/','').split('/')
97
- let tmp = schema
98
- let instancepath=''
99
- for(let i=0;i<paths.length;i++){
100
- tmp = tmp[paths[i]]
101
- if(tmp['type'] && paths[i] !='items'){
102
- instancepath=instancepath+'/'+paths[i]
103
- }
104
- }
105
82
 
106
- // console.log("get instance path",instancepath)
107
- return instancepath
108
- // return tmp
109
- }catch(err:any){
110
- console.error(err.message)
83
+ // console.log("get instance path",instancepath)
84
+
85
+ // return tmp
86
+ } catch (err: any) {
87
+ console.error(err.message);
88
+ }
89
+ };
90
+ const getInstancePath = (schema: any, path: string) => {
91
+ if (!path) {
92
+ console.error("unknown path");
93
+ return "yy";
94
+ }
95
+ try {
96
+ let paths = path.replace("#/", "").split("/");
97
+ let tmp = schema;
98
+ let instancepath = "";
99
+ for (let i = 0; i < paths.length; i++) {
100
+ tmp = tmp[paths[i]];
101
+ if (tmp["type"] && paths[i] != "items") {
102
+ instancepath = instancepath + "/" + paths[i];
103
+ }
111
104
  }
112
105
 
106
+ // console.log("get instance path",instancepath)
107
+ return instancepath;
108
+ // return tmp
109
+ } catch (err: any) {
110
+ console.error(err.message);
111
+ }
113
112
 
114
- // let paths = path.replace('#/','').split('/')
115
- // return '/'+paths[1]
116
- }
117
- const getPathObject=(schema:JSONSchema7,path:string):JSONSchema7|undefined=>{
118
- // console.log("path",path)
119
- if(!path || !path.includes('#/properties')){
120
- console.error('unknown path')
121
- return undefined
122
- }
123
- try{
124
- const modifiedpath = path.replace('#','$').replaceAll('/','.')
125
- const queryresult = jsonpath.query(schema,modifiedpath)[0]
126
- return queryresult
127
- }catch(err:any){
128
- console.error(err.message)
129
- }
130
- }
131
- </script>
113
+ // let paths = path.replace('#/','').split('/')
114
+ // return '/'+paths[1]
115
+ };
116
+ const getPathObject = (
117
+ schema: JSONSchema7,
118
+ path: string,
119
+ ): JSONSchema7 | undefined => {
120
+ // console.log("path",path)
121
+ if (!path || !path.includes("#/properties")) {
122
+ console.error("unknown path");
123
+ return undefined;
124
+ }
125
+ try {
126
+ const modifiedpath = path.replace("#", "$").replaceAll("/", ".");
127
+ const queryresult = jsonpath.query(schema, modifiedpath)[0];
128
+ return queryresult;
129
+ } catch (err: any) {
130
+ console.error(err.message);
131
+ }
132
+ };
133
+ </script>
@@ -1,38 +1,36 @@
1
1
  <template>
2
- <div v-if="isMobile()" class="w-full">
3
- <MobileToolbar class=" bg-gray-800 text-white">
2
+ <div v-if="isMobile()" class="w-full">
3
+ <MobileToolbar class="bg-gray-800 text-white">
4
4
  <template #start>
5
- <ButtonText class="text-xl" @click="callClose"
6
- ><i class="pi pi-times"></i
7
- ></ButtonText>
5
+ <slot name="start" :menu="menu">
6
+ <ButtonText class="text-xl" @click="callClose"
7
+ ><i class="pi pi-times"></i
8
+ ></ButtonText>
9
+ </slot>
8
10
  </template>
9
11
  <template #center>
10
- <TextTitle class="text-white ">{{ title }}</TextTitle>
12
+ <slot name="center" :menu="menu">
13
+ <TextTitle class="text-white line-clamp-2">{{ title }}</TextTitle>
14
+ </slot>
11
15
  </template>
12
16
  <template #end>
13
- <div class="flex flex-row-reverse gap-1 w-full">
14
- <ButtonText class="text-xl" @click="toggleMenu" v-if="isShow">
15
- <i class="pi pi-ellipsis-v"></i>
16
- </ButtonText>
17
-
18
- <ButtonText
19
- class="text text-xl"
20
- @click="
21
- emitEvent(
22
- {
23
- action: doc.isNew() ? 'create' : 'update',
24
- label: '',
25
- type: 'crud',
26
- },
27
- $event,
28
- )
29
- "
30
- >
31
- <i class="pi pi-save"></i>
32
- </ButtonText>
33
-
34
- <ContextMenu ref="menu" :model="menus as MenuItem[]" />
35
- </div>
17
+ <slot name="end" :menu="menu">
18
+ <div class="flex flex-row w-full">
19
+ <ButtonText
20
+ class="text-xl"
21
+ @click="emitEvent(menus[0], $event)"
22
+ v-if="isShow"
23
+ v-tooltip="menus[0].label"
24
+ >
25
+ <i :class="menus[0].icon"></i>
26
+ </ButtonText>
27
+
28
+ <ButtonText class="text-xl" @click="toggleMenu" v-if="isShow">
29
+ <i class="pi pi-ellipsis-v"></i>
30
+ </ButtonText>
31
+ </div>
32
+ </slot>
33
+ <ContextMenu ref="menu" :model="menus as MenuItem[]" />
36
34
  </template>
37
35
  </MobileToolbar>
38
36
  <div class="h-14"></div>
@@ -43,61 +41,87 @@
43
41
  <template #start>
44
42
  <div v-for="(menu, index) in menus" :key="index">
45
43
  <div v-if="menu.label && menu.type == 'crud'">
46
- <ButtonDefault @click="emitEvent(menu, $event)">{{
47
- menu.label
48
- }}</ButtonDefault>
44
+ <ButtonAction
45
+ @click="emitEvent(menu, $event)"
46
+ :action-name="menu.action"
47
+ >{{ menu.label }}</ButtonAction
48
+ >
49
49
  </div>
50
50
  </div>
51
51
  </template>
52
52
  <template #center>
53
+ <TextTitle class="text-white line-clamp-2">{{ title }}</TextTitle>
54
+ </template>
55
+ <template #end>
53
56
  <div v-for="(menu, index) in menus" :key="index">
54
57
  <div v-if="menu.label && menu.type == 'docstatus'">
55
- <ButtonDefault @click="emitEvent(menu, $event)">{{
56
- menu.label
57
- }}</ButtonDefault>
58
+ <ButtonAction
59
+ @click="emitEvent(menu, $event)"
60
+ :action-name="menu.action"
61
+ >{{ menu.label }}</ButtonAction
62
+ >
58
63
  </div>
59
64
  </div>
60
65
  </template>
61
- <template #end> </template>
62
66
  </Toolbar>
63
-
64
67
  <ConfirmPopup></ConfirmPopup>
65
68
  </div>
66
69
  </template>
67
70
  <script setup lang="ts">
68
71
  /**
69
- * This file was automatically generated by simpleapp generator. Every
70
- * MODIFICATION OVERRIDE BY GENERATEOR
71
- * last change 2023-10-28
72
- * Author: Ks Tan
72
+ * This file was automatically generated by simpleapp generator during initialization. It is changable.
73
+ * --remove-this-line-to-prevent-override--
74
+ * last change 2024-02-22
75
+ * author: Ks Tan
73
76
  */
77
+
74
78
  import { SimpleAppClient } from "~/simpleapp/generate/clients/SimpleAppClient";
75
79
  import { useConfirm } from "primevue/useconfirm";
76
80
  import { FormActions, FormCrudEvent, FormMenu } from "~/types";
77
81
  import { MenuItem } from "primevue/menuitem";
82
+ import { MenuItemCommandEvent } from "primevue/menuitem";
78
83
  const confirm = useConfirm();
79
84
  const emits = defineEmits(["on", "close"]);
80
85
  const props = defineProps<{
81
86
  document: SimpleAppClient<any, any>;
82
87
  disableaction?: string[];
83
88
  }>();
84
- const createData = async () => {try{ return await doc.create()}catch(e){console.debug('validation error:',e)}};
85
- const updateData = async () => {try{ return await doc.update()}catch(e){console.debug('validation error:',e)}};
86
- const deleteData = async () => {try{ return await doc.delete()}catch(e){console.debug('validation error:',e)}};
89
+ const createData = async () => {
90
+ try {
91
+ return await doc.create();
92
+ } catch (e) {
93
+ console.debug("validation error:", e);
94
+ }
95
+ };
96
+ const updateData = async () => {
97
+ try {
98
+ return await doc.update();
99
+ } catch (e) {
100
+ console.debug("validation error:", e);
101
+ }
102
+ };
103
+ const deleteData = async () => {
104
+ try {
105
+ return await doc.delete();
106
+ } catch (e) {
107
+ console.debug("validation error:", e);
108
+ }
109
+ };
87
110
 
88
111
  const doc = props.document;
89
112
  const data = doc.getReactiveData();
90
113
  type Datatype = keyof typeof data.value;
91
114
  const config = doc.getSchema()["x-simpleapp-config"];
92
- const titlefield = (config.documentTitle ?? config.documentTitle) as Datatype;
93
- const title = ref<string>(
115
+ const titlefield = (config.uniqueKey ?? config.documentTitle) as Datatype;
116
+ const title = computed(() =>
94
117
  data.value[titlefield as Datatype]
95
118
  ? data.value[titlefield as Datatype]
96
119
  : t(doc.getDocName()),
97
120
  );
121
+
98
122
  const menu = ref();
99
123
  const menus = computed(() =>
100
- [...getActions(), { separator: true }, ...getDocActions()].filter((item) =>
124
+ [...getActions(), ...getDocActions()].filter((item) =>
101
125
  showMenuButton(item),
102
126
  ),
103
127
  );
@@ -109,23 +133,22 @@ const toggleMenu = (event: MouseEvent) => {
109
133
  menu.value.toggle(event);
110
134
  };
111
135
 
112
- const callClose = (e: MouseEvent) => {
136
+ const callClose = (e: MouseEvent) => {
113
137
  useNuxtApp().$event("CloseDialog", doc.getDocName());
114
138
  emitEvent({ action: "exit", type: "menu", label: "" }, e);
115
139
  // async (menu: FormMenu, clickEvent: MouseEvent)
116
140
  };
117
- const emitMobileEvent = (itemevent: {
118
- item: any;
119
- originalEvent: MouseEvent;
120
- }) => {
141
+ const emitMobileEvent = (itemevent: MenuItemCommandEvent) => {
121
142
  const actionname: string = itemevent.item.action;
122
143
  const event = itemevent.originalEvent;
123
- emitEvent({ action: actionname, type: "crud", label: "" }, event);
144
+ // emitEvent({ action: actionname, type: "crud", label: "" }, event);
145
+ emitEvent(itemevent.item, event);
124
146
  };
125
147
 
126
148
  const getActions = () => {
127
149
  const actions = doc.getActions();
128
150
  const crudmenus: any[] = [];
151
+
129
152
  // Object.keys(actions).forEach((key)=>{ //crud, api, docstatus
130
153
  actions["crud"].forEach((item) => {
131
154
  if (props.disableaction && props.disableaction.includes(item)) {
@@ -135,6 +158,7 @@ const getActions = () => {
135
158
  action: item,
136
159
  label: t(item),
137
160
  type: "crud",
161
+ icon: getActionIcon(item),
138
162
  command: emitMobileEvent,
139
163
  });
140
164
  }
@@ -161,9 +185,10 @@ const emitEvent = async (menu: FormMenu, clickEvent: MouseEvent) => {
161
185
  if (await createData()) emits("on", FormCrudEvent.create);
162
186
  } else if (menu.action == "update") {
163
187
  if (await updateData()) emits("on", FormCrudEvent.update);
164
- } else if (menu.type == "setDocStatus")
188
+ } else if (menu.type == "docstatus") {
165
189
  emits("on", FormCrudEvent.setDocStatus, menu.action);
166
- else if (menu.action == FormCrudEvent.exit) emits("on", FormCrudEvent.exit);
190
+ } else if (menu.action == FormCrudEvent.exit)
191
+ emits("on", FormCrudEvent.exit);
167
192
  }
168
193
  };
169
194
 
@@ -183,21 +208,60 @@ const getDocActions = () => {
183
208
  action: item,
184
209
  label: statusNames[item],
185
210
  type: "docstatus",
211
+ icon: getActionIcon(item),
212
+ command: emitMobileEvent,
186
213
  })) ?? [];
187
214
  }
188
215
  return docactionmenus;
189
216
  };
190
217
  const showMenuButton = (menu: FormMenu) => {
191
218
  if (menu.separator) return true;
192
- if (isMobile() && ["create", "update"].includes(menu.action)) return false;
193
- if (!canPerform(doc.getDocName(), menu.action)) return false;
219
+
220
+ //all document status cannot direct apply regardless new or draft
221
+ if (menu.type == "docstatus") return true;
222
+
223
+ // afterward, new document only acces create action
194
224
  if (doc.isNew() && menu.action == "create") return true;
195
- if (!doc.isNew() && menu.action == "new") return true;
196
- if (!doc.isNew() && menu.action == "update") return true;
197
- if (!doc.isNew() && menu.action == "delete") return true;
225
+ if (doc.isNew() && menu.action != "create") return false;
226
+
227
+ //start from here, readonly document all action not allow
228
+ if (doc.isReadOnly()) return false;
198
229
 
199
- if (menu.type == "api") return false;
230
+ //edit draft document, only create not allow
231
+ if (!doc.isNew() && menu.action == "create") return false;
232
+ if (!doc.isNew() && menu.action != "create") return true;
200
233
 
201
234
  return false;
202
235
  };
236
+
237
+ const getActionIcon = (actionName: string) => {
238
+ let icon = "";
239
+ switch (actionName) {
240
+ case "create":
241
+ icon = "pi-save";
242
+ break;
243
+ case "update":
244
+ icon = "pi-save";
245
+ break;
246
+ case "delete":
247
+ icon = "pi-trash";
248
+ break;
249
+ case "confirm":
250
+ icon = "pi-check";
251
+ break;
252
+ case "void":
253
+ icon = "pi-ban";
254
+ break;
255
+ case "print":
256
+ icon = "pi-print";
257
+ break;
258
+ case "draft":
259
+ icon = "pi-pencil";
260
+ break;
261
+ default:
262
+ icon = "pi-question-circle";
263
+ break;
264
+ }
265
+ return `pi ${icon}`;
266
+ };
203
267
  </script>