@ramathibodi/nuxt-commons 0.1.46 → 0.1.48

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/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^3.0.0"
6
6
  },
7
- "version": "0.1.46",
7
+ "version": "0.1.48",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.4",
10
10
  "unbuild": "2.0.0"
@@ -9,12 +9,14 @@ interface ExportButtonProps extends /* @vue-ignore */ InstanceType<typeof VBtn['
9
9
  sheetName?: string
10
10
  modelValue?: object[]
11
11
  stringFields?: Array<string>
12
+ tooltip?: string | Record<string,any> | undefined
12
13
  }
13
14
 
14
15
  const props = withDefaults(defineProps<ExportButtonProps>(), {
15
16
  fileName: 'download',
16
17
  sheetName: 'Sheet1',
17
18
  stringFields: ()=>[],
19
+ tooltip: ()=>({text: 'Export', location: 'bottom'}),
18
20
  })
19
21
 
20
22
  const alert = useAlert()
@@ -84,6 +86,7 @@ function flattenObject(obj: any, parentKey = '', separator = '.') {
84
86
  :disabled="loading"
85
87
  text="Export CSV"
86
88
  @click="exportFile"
89
+ v-tooltip="props.tooltip"
87
90
  >
88
91
  <template
89
92
  v-for="(_, name, index) in ($slots as {})"
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import {ref, watch} from 'vue'
2
+ import {ref} from 'vue'
3
3
  import {VBtn} from 'vuetify/components/VBtn'
4
4
 
5
5
  interface Props extends /* @vue-ignore */ InstanceType<typeof VBtn['$props']> {
@@ -7,11 +7,13 @@ interface Props extends /* @vue-ignore */ InstanceType<typeof VBtn['$props']> {
7
7
  multiple?: boolean
8
8
  iconOnly?: boolean
9
9
  modelValue?: File | File[] | undefined
10
+ tooltip?: string | Record<string,any> | undefined
10
11
  }
11
12
 
12
13
  const props = withDefaults(defineProps<Props>(), {
13
14
  multiple: false,
14
15
  accept: '*',
16
+ tooltip: 'Upload File',
15
17
  })
16
18
 
17
19
  const emit = defineEmits<{
@@ -41,6 +43,7 @@ defineExpose({ reset })
41
43
  <v-btn
42
44
  v-bind="$attrs"
43
45
  @click="openFileInput"
46
+ v-tooltip="tooltip"
44
47
  >
45
48
  <template
46
49
  v-for="(_, name, index) in ($slots as {})"
@@ -6,10 +6,12 @@ import { VBtn } from 'vuetify/components/VBtn'
6
6
 
7
7
  interface ImportButtonProps extends /* @vue-ignore */ InstanceType<typeof VBtn['$props']> {
8
8
  stringFields?: Array<string>
9
+ tooltip?: string | Record<string,any> | undefined
9
10
  }
10
11
 
11
12
  const props = withDefaults(defineProps<ImportButtonProps>(), {
12
13
  stringFields: ()=>[],
14
+ tooltip: ()=>({text: 'Import', location: 'bottom'}),
13
15
  })
14
16
 
15
17
  const alert = useAlert()
@@ -120,6 +122,7 @@ const parseIfJson = (value: any) => {
120
122
  accept=".csv, .xlsx"
121
123
  :multiple="false"
122
124
  @update:model-value="uploadedFile"
125
+ :tooltip="props.tooltip"
123
126
  >
124
127
  <template
125
128
  v-for="(_, name, index) in ($slots as {})"
@@ -112,13 +112,27 @@ export function escapeObjectForInlineBinding(obj) {
112
112
  export function buildValidationRules(validationString) {
113
113
  validationString = validationString.replace(/^\[|]$/g, "").trim();
114
114
  if (!validationRulesRegex.test(validationString)) return "";
115
- const rules = validationString.split(",").map((rule) => {
115
+ const rules = [];
116
+ let current = "";
117
+ let depth = 0;
118
+ for (let char of validationString) {
119
+ if (char === "," && depth === 0) {
120
+ if (current.trim()) rules.push(current.trim());
121
+ current = "";
122
+ } else {
123
+ if (char === "(") depth++;
124
+ if (char === ")") depth--;
125
+ current += char;
126
+ }
127
+ }
128
+ if (current.trim()) rules.push(current.trim());
129
+ const formatted = rules.map((rule) => {
116
130
  rule = rule.trim();
117
131
  if (!rule.startsWith("rules.")) rule = `rules.${rule}`;
118
132
  if (!/\(.+\)$/.test(rule)) rule += "()";
119
133
  return rule.replace(/"/g, "'");
120
134
  });
121
- return `:rules="[${rules.join(",")}]"`;
135
+ return `:rules="[${formatted.join(",")}]"`;
122
136
  }
123
137
  export function processDefaultTemplate(item, insideTemplate, optionString, validationRules) {
124
138
  if (!validationRules) validationRules = item.validationRules ? buildValidationRules(item.validationRules) || "" : "";
@@ -5,5 +5,7 @@ import {
5
5
  } from "./template.js";
6
6
  export function processTemplateFormTable(item, parentTemplates) {
7
7
  let tableOptions = Object.assign({ title: item.inputLabel || "", formTemplate: "" }, item.inputOptions);
8
- return processDefaultTemplate(item, `<template #form="{data,rules}">${useDocumentTemplate(tableOptions.formTemplate)}</template>`, `title="${tableOptions.title}" :headers='${escapeObjectForInlineBinding(tableOptions.headers || {})}'`);
8
+ let tableHeader = tableOptions.headers || [];
9
+ if (!tableHeader.some((h) => h.key === "action")) tableHeader.push({ title: "Action", key: "action", width: "100px" });
10
+ return processDefaultTemplate(item, `<template #form="{data,rules}">${useDocumentTemplate(tableOptions.formTemplate)}</template>`, `title="${tableOptions.title}" :headers='${escapeObjectForInlineBinding(tableHeader)}'`);
9
11
  }
@@ -1,3 +1,4 @@
1
+ import { cloneDeep } from "lodash-es";
1
2
  import { classAttributes, isClassConstructor } from "../utils/object.js";
2
3
  import { useGraphQl } from "./graphql.js";
3
4
  import { graphqlInputType, graphqlOperation, graphqlType, scalarType } from "#imports";
@@ -36,8 +37,9 @@ export function buildFields(operationFields, fields, depth = 0) {
36
37
  }
37
38
  export function buildVariables(outputVariables, inputVariables, reject, isRoot = true) {
38
39
  if (!outputVariables) return void 0;
40
+ let localOutputVariables = cloneDeep(outputVariables);
39
41
  if (inputVariables) {
40
- outputVariables.map((variable) => {
42
+ localOutputVariables.map((variable) => {
41
43
  if (variable.type && !scalarType.includes(variable.type)) {
42
44
  if (variable.list) {
43
45
  if (inputVariables[variable.name] && Array.isArray(inputVariables[variable.name])) {
@@ -58,7 +60,7 @@ export function buildVariables(outputVariables, inputVariables, reject, isRoot =
58
60
  return variable;
59
61
  });
60
62
  }
61
- outputVariables.forEach((variable) => {
63
+ localOutputVariables.forEach((variable) => {
62
64
  if (variable.required && variable.value === void 0) {
63
65
  console.warn("Required variable " + variable.name + " is not found, operation abort");
64
66
  if (reject) {
@@ -67,10 +69,10 @@ export function buildVariables(outputVariables, inputVariables, reject, isRoot =
67
69
  }
68
70
  }
69
71
  });
70
- const usedVariables = outputVariables.map((variable) => variable.name);
72
+ const usedVariables = localOutputVariables.map((variable) => variable.name);
71
73
  const droppedVariable = Object.keys(inputVariables || {}).filter((key) => !usedVariables.includes(key));
72
74
  if (droppedVariable.length > 0) console.debug("There is data not appeared in schema and dropped before operation.", droppedVariable);
73
- return outputVariables.reduce((acc, item) => {
75
+ return localOutputVariables.reduce((acc, item) => {
74
76
  acc[item.name] = isRoot ? item : item.value;
75
77
  return acc;
76
78
  }, {});
@@ -20,7 +20,7 @@ export function routeToMenuItem(route) {
20
20
  };
21
21
  if (route.children) {
22
22
  const menuItems = new Array();
23
- for (const children of route.children.sort((a, b) => (a.path?.toString() ?? "").localeCompare(b.path?.toString() ?? ""))) {
23
+ for (const children of route.children.sort((a, b) => (a.name?.toString() ?? "").localeCompare(b.name?.toString() ?? ""))) {
24
24
  const childMenuItem = routeToMenuItem(children);
25
25
  if (childMenuItem) menuItems.push(childMenuItem);
26
26
  menuItem.menuItems = menuItems;
@@ -31,7 +31,7 @@ export function routeToMenuItem(route) {
31
31
  }
32
32
  export function createMenu() {
33
33
  const menuAll = ref([]);
34
- const routes = useRouter().getRoutes().sort((a, b) => (a.path?.toString() ?? "").localeCompare(b.path?.toString() ?? ""));
34
+ const routes = useRouter().getRoutes().sort((a, b) => (a.name?.toString() ?? "").localeCompare(b.name?.toString() ?? ""));
35
35
  for (const route of routes) {
36
36
  const paths = route.path.split("/");
37
37
  if (paths.length == 2) {
@@ -7,7 +7,7 @@ export function useRules() {
7
7
  const requireIf = (conditionIf, customError = "This field is required") => (value) => condition(!!value || value === false || value === 0 || !conditionIf, customError);
8
8
  const requireTrue = (customError = "This field must be true") => (value) => condition(!!value, customError);
9
9
  const requireTrueIf = (conditionIf, customError = "This field must be true") => (value) => condition(!!value || !conditionIf, customError);
10
- const numeric = (customError = "This field must be a number") => (value) => condition(!value || !Number.isNaN(value), customError);
10
+ const numeric = (customError = "This field must be a number") => (value) => condition(!value || !isNaN(Number(value)), customError);
11
11
  const range = (minValue, maxValue, customError = `Value is out of range (${minValue}-${maxValue})`) => (value) => condition(!value || value >= minValue && value <= maxValue, customError);
12
12
  const integer = (customError = "This field must be an integer") => (value) => condition(!value || isInteger(value) || /^\+?-?\d+$/.test(value), customError);
13
13
  const unique = (data, fieldName, customError = "This field must be unique") => (value) => condition(!value || !data || !find(data, [fieldName, value]), customError);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ramathibodi/nuxt-commons",
3
- "version": "0.1.46",
3
+ "version": "0.1.48",
4
4
  "description": "Ramathibodi Nuxt modules for common components",
5
5
  "repository": {
6
6
  "type": "git",