vue-laravel-crud 2.0.5 → 2.0.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-laravel-crud",
3
- "version": "2.0.5",
3
+ "version": "2.0.7",
4
4
  "type": "module",
5
5
  "description": "",
6
6
  "homepage": "https://github.com/clonixdev/vue-laravel-crud",
package/src/ItemCard.vue CHANGED
@@ -32,6 +32,12 @@
32
32
  <span v-else-if="column.type === 'array'">
33
33
  {{ getArrayValue(itemValue(column, item), column.displayProp, column.options) }}
34
34
  </span>
35
+ <span v-else-if="column.type === 'money' || column.type === 'price'">
36
+ {{ formatMoney(itemValue(column, item), column) }}
37
+ </span>
38
+ <span v-else-if="column.type === 'number' && (column.thousandsSeparator || column.decimalSeparator || column.decimals !== undefined)">
39
+ {{ formatNumber(itemValue(column, item), column) }}
40
+ </span>
35
41
  <span v-else>
36
42
  {{ itemValue(column, item) }}
37
43
  </span>
@@ -41,11 +47,14 @@
41
47
  </slot>
42
48
  <template v-slot:footer>
43
49
  <b-button-group>
44
- <slot name="rowAction" v-bind:item="item" v-bind:index="index" v-bind:showItem="showItem"
50
+ <slot name="rowActions" v-bind:item="item" v-bind:index="index" v-bind:showItem="showItem"
45
51
  v-bind:updateItem="updateItem" v-bind:removeItem="removeItem">
46
- <b-button variant="primary" @click="showItem(item.id, index)"><b-icon-eye></b-icon-eye></b-button>
47
- <b-button variant="secondary" @click="updateItem(item.id, index)"><b-icon-pencil></b-icon-pencil></b-button>
48
- <b-button variant="danger" @click="removeItem(item.id, index)"><b-icon-trash></b-icon-trash></b-button>
52
+ <slot name="rowAction" v-bind:item="item" v-bind:index="index" v-bind:showItem="showItem"
53
+ v-bind:updateItem="updateItem" v-bind:removeItem="removeItem">
54
+ <b-button variant="primary" @click="showItem(item.id, index)"><b-icon-eye></b-icon-eye></b-button>
55
+ <b-button variant="secondary" @click="updateItem(item.id, index)"><b-icon-pencil></b-icon-pencil></b-button>
56
+ <b-button variant="danger" @click="removeItem(item.id, index)"><b-icon-trash></b-icon-trash></b-button>
57
+ </slot>
49
58
  </slot>
50
59
  </b-button-group>
51
60
  </template>
@@ -80,6 +89,38 @@
80
89
  return this.getStateOptions(this.itemValue(column, item), column.options);
81
90
  }
82
91
  return [];
92
+ },
93
+ formatNumber(value, column) {
94
+ if (value === null || value === undefined || value === '') {
95
+ return '';
96
+ }
97
+
98
+ const numValue = parseFloat(value);
99
+ if (isNaN(numValue)) {
100
+ return value;
101
+ }
102
+
103
+ const thousandsSep = column.thousandsSeparator || '.';
104
+ const decimalSep = column.decimalSeparator || ',';
105
+ const decimals = column.decimals !== undefined ? column.decimals : (numValue % 1 === 0 ? 0 : 2);
106
+
107
+ // Formatear número con separadores
108
+ const parts = numValue.toFixed(decimals).split('.');
109
+ const integerPart = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSep);
110
+ const decimalPart = parts[1] || '';
111
+
112
+ if (decimals > 0 && decimalPart) {
113
+ return `${integerPart}${decimalSep}${decimalPart}`;
114
+ }
115
+ return integerPart;
116
+ },
117
+ formatMoney(value, column) {
118
+ const formatted = this.formatNumber(value, column);
119
+ if (formatted === '') {
120
+ return '';
121
+ }
122
+ const symbol = column.symbol || '$';
123
+ return `${symbol}${formatted}`;
83
124
  }
84
125
  }
85
126
  };
@@ -1,98 +1,131 @@
1
- <template>
2
- <div v-if="displayMode == displayModes.MODE_CARDS">
3
- <draggable
4
- v-model="items"
5
- :group="draggableGroup"
6
- :draggable="orderable ? '.item' : '.none'"
7
- @start="drag = true"
8
- @end="drag = false"
9
- @sort="onSort()"
10
- @add="onDraggableAdded($event)"
11
- @change="onDraggableChange($event)"
12
- :options="draggableOptions"
13
- >
14
- <masonry
15
- :cols="{ default: 12 / colLg, 1400: 12 / colXl, 1200: 12 / colLg, 1000: 12 / colMd, 700: 12 / colSm, 400: 12 / colXs }"
16
- :gutter="{ default: '15px', 700: '15px' }"
17
- >
18
- <div v-for="(item, itemIndex) in itemsList" v-bind:key="itemIndex" class="item">
19
- <slot name="card" v-bind:item="item">
20
- <ItemCard
21
- :item="item"
22
- :columns="columns"
23
- :index="itemIndex"
24
- :cardClass="cardClass"
25
- :cardHideFooter="cardHideFooter"
26
- :itemValue="itemValue"
27
- :getStateValue="getStateValue"
28
- :getStateOptions="getStateOptions"
29
- :getStateBadgeVariant="getStateBadgeVariant"
30
- :getArrayValue="getArrayValue"
31
- :showItem="showItem"
32
- :updateItem="updateItem"
33
- :removeItem="removeItem"
34
- />
35
- </slot>
36
- </div>
37
- </masonry>
38
- </draggable>
39
-
40
- <p v-if="!loading && itemsList && itemsList.length == 0 && !infiniteScroll" class="p-3">
41
- {{ messageEmptyResults }}
42
- </p>
43
- </div>
44
- </template>
45
-
46
- <script>
47
- import Vue from 'vue';
48
- import draggable from "vuedraggable";
49
- import VueMasonry from 'vue-masonry-css';
50
- import ItemCard from '../ItemCard.vue';
51
-
52
- // Registrar el componente masonry usando el Plugin
53
- Vue.use(VueMasonry);
54
-
55
- export default {
56
- name: 'CrudCards',
57
- components: {
58
- draggable,
59
- ItemCard
60
- },
61
- inject: [
62
- 'displayMode',
63
- 'displayModes',
64
- 'items',
65
- 'draggableGroup',
66
- 'orderable',
67
- 'draggableOptions',
68
- 'itemsList',
69
- 'colLg',
70
- 'colXl',
71
- 'colMd',
72
- 'colSm',
73
- 'colXs',
74
- 'columns',
75
- 'cardClass',
76
- 'cardHideFooter',
77
- 'itemValue',
78
- 'getStateValue',
79
- 'getStateOptions',
80
- 'getStateBadgeVariant',
81
- 'getArrayValue',
82
- 'showItem',
83
- 'updateItem',
84
- 'removeItem',
85
- 'loading',
86
- 'infiniteScroll',
87
- 'messageEmptyResults',
88
- 'onSort',
89
- 'onDraggableAdded',
90
- 'onDraggableChange'
91
- ],
92
- data() {
93
- return {
94
- drag: false
95
- };
96
- }
97
- };
98
- </script>
1
+ <template>
2
+ <div v-if="currentDisplayMode == displayModes.MODE_CARDS">
3
+ <!-- Spinner durante la carga inicial -->
4
+ <div v-if="loadingValue || !firstLoadValue" class="text-center p-5">
5
+ <b-spinner variant="primary" label="Cargando..."></b-spinner>
6
+ <p class="mt-2">{{ messageLoading }}</p>
7
+ </div>
8
+
9
+ <!-- Cards con datos -->
10
+ <template v-else>
11
+ <draggable
12
+ v-model="items"
13
+ :group="draggableGroup"
14
+ :draggable="orderable ? '.item' : '.none'"
15
+ @start="drag = true"
16
+ @end="drag = false"
17
+ @sort="onSort()"
18
+ @add="onDraggableAdded($event)"
19
+ @change="onDraggableChange($event)"
20
+ :options="draggableOptions"
21
+ >
22
+ <masonry
23
+ :cols="{ default: 12 / colLg, 1400: 12 / colXl, 1200: 12 / colLg, 1000: 12 / colMd, 700: 12 / colSm, 400: 12 / colXs }"
24
+ :gutter="{ default: '15px', 700: '15px' }"
25
+ >
26
+ <div v-for="(item, itemIndex) in itemsList" v-bind:key="itemIndex" class="item">
27
+ <slot name="card" v-bind:item="item">
28
+ <ItemCard
29
+ :item="item"
30
+ :columns="columns"
31
+ :index="itemIndex"
32
+ :cardClass="cardClass"
33
+ :cardHideFooter="cardHideFooter"
34
+ :itemValue="itemValue"
35
+ :getStateValue="getStateValue"
36
+ :getStateOptions="getStateOptions"
37
+ :getStateBadgeVariant="getStateBadgeVariant"
38
+ :getArrayValue="getArrayValue"
39
+ :showItem="showItem"
40
+ :updateItem="updateItem"
41
+ :removeItem="removeItem"
42
+ >
43
+ <template v-for="(slot, name) in $scopedSlots" v-slot:[name]="slotProps">
44
+ <slot :name="name" v-bind="slotProps" />
45
+ </template>
46
+ </ItemCard>
47
+ </slot>
48
+ </div>
49
+ </masonry>
50
+ </draggable>
51
+
52
+ <p v-if="firstLoadValue && itemsList && itemsList.length == 0 && !infiniteScroll" class="p-3">
53
+ {{ messageEmptyResults }}
54
+ </p>
55
+ </template>
56
+ </div>
57
+ </template>
58
+
59
+ <script>
60
+ import Vue from 'vue';
61
+ import draggable from "vuedraggable";
62
+ import VueMasonry from 'vue-masonry-css';
63
+ import ItemCard from '../ItemCard.vue';
64
+
65
+ // Registrar el componente masonry usando el Plugin
66
+ Vue.use(VueMasonry);
67
+
68
+ export default {
69
+ name: 'CrudCards',
70
+ components: {
71
+ draggable,
72
+ ItemCard
73
+ },
74
+ inject: [
75
+ 'displayMode',
76
+ 'displayModes',
77
+ 'items',
78
+ 'draggableGroup',
79
+ 'orderable',
80
+ 'draggableOptions',
81
+ 'itemsList',
82
+ 'colLg',
83
+ 'colXl',
84
+ 'colMd',
85
+ 'colSm',
86
+ 'colXs',
87
+ 'columns',
88
+ 'cardClass',
89
+ 'cardHideFooter',
90
+ 'itemValue',
91
+ 'getStateValue',
92
+ 'getStateOptions',
93
+ 'getStateBadgeVariant',
94
+ 'getArrayValue',
95
+ 'showItem',
96
+ 'updateItem',
97
+ 'removeItem',
98
+ 'loading',
99
+ 'firstLoad',
100
+ 'infiniteScroll',
101
+ 'messageEmptyResults',
102
+ 'messageLoading',
103
+ 'onSort',
104
+ 'onDraggableAdded',
105
+ 'onDraggableChange'
106
+ ],
107
+ data() {
108
+ return {
109
+ drag: false
110
+ };
111
+ },
112
+ computed: {
113
+ currentDisplayMode() {
114
+ if (!this.displayMode) return 1;
115
+ if (this.displayMode.value !== undefined) {
116
+ return this.displayMode.value;
117
+ }
118
+ if (typeof this.displayMode === 'function') {
119
+ return this.displayMode();
120
+ }
121
+ return this.displayMode;
122
+ },
123
+ loadingValue() {
124
+ return this.loading && this.loading.value !== undefined ? this.loading.value : this.loading;
125
+ },
126
+ firstLoadValue() {
127
+ return this.firstLoad && this.firstLoad.value !== undefined ? this.firstLoad.value : this.firstLoad;
128
+ }
129
+ }
130
+ };
131
+ </script>
@@ -1,29 +1,58 @@
1
- <template>
2
- <div v-if="displayMode == displayModes.MODE_CUSTOM">
3
- <div :class="listContainerClass">
4
- <p v-if="!loading && itemsList && itemsList.length == 0 && !infiniteScroll" class="p-3">
5
- {{ messageEmptyResults }}
6
- </p>
7
- <div :class="listItemClass" v-for="(item, index) in itemsList" v-bind:key="index">
8
- <slot name="card" v-bind:item="item"> </slot>
9
- </div>
10
- </div>
11
- </div>
12
- </template>
13
-
14
- <script>
15
- export default {
16
- name: 'CrudCustom',
17
- inject: [
18
- 'displayMode',
19
- 'displayModes',
20
- 'listContainerClass',
21
- 'listItemClass',
22
- 'loading',
23
- 'items',
24
- 'infiniteScroll',
25
- 'messageEmptyResults',
26
- 'itemsList'
27
- ]
28
- };
29
- </script>
1
+ <template>
2
+ <div v-if="currentDisplayMode == displayModes.MODE_CUSTOM">
3
+ <div :class="listContainerClass">
4
+ <!-- Spinner durante la carga inicial -->
5
+ <div v-if="loadingValue || !firstLoadValue" class="text-center p-5">
6
+ <b-spinner variant="primary" label="Cargando..."></b-spinner>
7
+ <p class="mt-2">{{ messageLoading }}</p>
8
+ </div>
9
+
10
+ <!-- Contenido con datos -->
11
+ <template v-else>
12
+ <p v-if="firstLoadValue && itemsList && itemsList.length == 0 && !infiniteScroll" class="p-3">
13
+ {{ messageEmptyResults }}
14
+ </p>
15
+ <div :class="listItemClass" v-for="(item, index) in itemsList" v-bind:key="index">
16
+ <slot name="card" v-bind:item="item"> </slot>
17
+ </div>
18
+ </template>
19
+ </div>
20
+ </div>
21
+ </template>
22
+
23
+ <script>
24
+ export default {
25
+ name: 'CrudCustom',
26
+ inject: [
27
+ 'displayMode',
28
+ 'displayModes',
29
+ 'listContainerClass',
30
+ 'listItemClass',
31
+ 'loading',
32
+ 'firstLoad',
33
+ 'items',
34
+ 'infiniteScroll',
35
+ 'messageEmptyResults',
36
+ 'messageLoading',
37
+ 'itemsList'
38
+ ],
39
+ computed: {
40
+ currentDisplayMode() {
41
+ if (!this.displayMode) return 1;
42
+ if (this.displayMode.value !== undefined) {
43
+ return this.displayMode.value;
44
+ }
45
+ if (typeof this.displayMode === 'function') {
46
+ return this.displayMode();
47
+ }
48
+ return this.displayMode;
49
+ },
50
+ loadingValue() {
51
+ return this.loading && this.loading.value !== undefined ? this.loading.value : this.loading;
52
+ },
53
+ firstLoadValue() {
54
+ return this.firstLoad && this.firstLoad.value !== undefined ? this.firstLoad.value : this.firstLoad;
55
+ }
56
+ }
57
+ };
58
+ </script>