@wishbone-media/spark 0.32.0 → 0.33.0
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/index.d.ts +1 -0
- package/dist/index.js +1062 -984
- package/package.json +3 -1
- package/src/composables/index.js +1 -0
- package/src/composables/useCrudResource.js +109 -0
- package/src/composables/useFormSubmission.js +20 -0
- package/src/constants/australianStates.js +14 -0
- package/src/constants/index.js +1 -0
- package/src/index.js +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wishbone-media/spark",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@vitejs/plugin-vue": "^6.0.2",
|
|
42
42
|
"vite": "^7.2.2",
|
|
43
|
+
"vite-plugin-dts": "^4.5.4",
|
|
43
44
|
"vue": "^3.5.24"
|
|
44
45
|
},
|
|
45
46
|
"packageManager": "pnpm@10.11.1",
|
|
@@ -49,6 +50,7 @@
|
|
|
49
50
|
"release:minor": "npm version minor && npm publish && git push --follow-tags",
|
|
50
51
|
"release:major": "npm version major && npm publish && git push --follow-tags"
|
|
51
52
|
},
|
|
53
|
+
"types": "./dist/index.d.ts",
|
|
52
54
|
"exports": {
|
|
53
55
|
".": "./dist/index.js",
|
|
54
56
|
"./src/*": "./src/*",
|
package/src/composables/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export { sparkOverlayService } from './sparkOverlayService.js'
|
|
|
4
4
|
export { useSparkOverlay } from './useSparkOverlay.js'
|
|
5
5
|
export { useSparkTableRouteSync } from './useSparkTableRouteSync.js'
|
|
6
6
|
export { useFormSubmission } from './useFormSubmission.js'
|
|
7
|
+
export { useCrudResource, useTableDelete } from './useCrudResource.js'
|
|
7
8
|
export { useSubNavigation } from './useSubNavigation.js'
|
|
8
9
|
export {
|
|
9
10
|
useFormDirtyGuard,
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { ref, computed, onMounted } from 'vue'
|
|
2
|
+
import { useRoute } from 'vue-router'
|
|
3
|
+
import { getAxiosInstance } from '../plugins/axios.js'
|
|
4
|
+
import { sparkNotificationService } from './sparkNotificationService.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Composable for CRUD Save views — handles resource fetching, error state, and edit mode detection.
|
|
8
|
+
*
|
|
9
|
+
* @param {string} endpoint - API endpoint name (e.g. 'tributes', 'public-holidays')
|
|
10
|
+
* @param {Object} options
|
|
11
|
+
* @param {string} options.queryParams - Optional query string for eager loading (e.g. 'with=brand.items')
|
|
12
|
+
* @param {Function} options.fetchFn - Custom fetch function. Receives { axios, resourceId, isEditMode, route }.
|
|
13
|
+
* Return value is assigned to data ref. Return undefined to skip assignment.
|
|
14
|
+
* @param {boolean} options.fetchOnCreate - Whether to call fetch() on mount in create mode (default: false)
|
|
15
|
+
* @returns {{ data, error, resourceId, isEditMode, fetch, handleSuccess }}
|
|
16
|
+
*/
|
|
17
|
+
export function useCrudResource(endpoint, options = {}) {
|
|
18
|
+
const { queryParams = '', fetchFn = null, fetchOnCreate = false } = options
|
|
19
|
+
const route = useRoute()
|
|
20
|
+
|
|
21
|
+
const data = ref(null)
|
|
22
|
+
const error = ref(null)
|
|
23
|
+
|
|
24
|
+
const resourceId = computed(() => route.params.id ?? null)
|
|
25
|
+
const isEditMode = computed(() => resourceId.value !== null)
|
|
26
|
+
|
|
27
|
+
async function fetch() {
|
|
28
|
+
if (!fetchOnCreate && !isEditMode.value) return
|
|
29
|
+
error.value = null
|
|
30
|
+
try {
|
|
31
|
+
if (fetchFn) {
|
|
32
|
+
const result = await fetchFn({
|
|
33
|
+
axios: getAxiosInstance(),
|
|
34
|
+
resourceId: resourceId.value,
|
|
35
|
+
isEditMode: isEditMode.value,
|
|
36
|
+
route,
|
|
37
|
+
})
|
|
38
|
+
if (result !== undefined) data.value = result
|
|
39
|
+
} else {
|
|
40
|
+
const axios = getAxiosInstance()
|
|
41
|
+
let url = `/${endpoint}/${resourceId.value}`
|
|
42
|
+
if (queryParams) url += `?${queryParams}`
|
|
43
|
+
const response = await axios.get(url)
|
|
44
|
+
data.value = response.data
|
|
45
|
+
}
|
|
46
|
+
} catch (err) {
|
|
47
|
+
error.value = err.response?.data?.message || err.message || 'Failed to load data.'
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function handleSuccess() {
|
|
52
|
+
if (isEditMode.value) fetch()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
onMounted(() => {
|
|
56
|
+
if (fetchOnCreate || isEditMode.value) fetch()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
return { data, error, resourceId, isEditMode, fetch, handleSuccess }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Composable for SparkTable row deletion — handles axios delete, notifications, and table refresh.
|
|
64
|
+
*
|
|
65
|
+
* @param {Ref} tableRef - Template ref to the SparkTable component (used for .refresh())
|
|
66
|
+
* @param {Object} options
|
|
67
|
+
* @param {string} options.endpoint - API endpoint name (e.g. 'public-holidays', 'invoices')
|
|
68
|
+
* @param {string} options.successMessage - Notification on success (default: 'Deleted successfully.')
|
|
69
|
+
* @param {string} options.errorMessage - Notification on error (default: API message or 'Failed to delete.')
|
|
70
|
+
* @param {Function} options.onSuccess - Callback after successful delete (receives row)
|
|
71
|
+
* @param {Function} options.onError - Callback on error (receives error, row). Return true to skip default handling.
|
|
72
|
+
* @returns {{ handleDelete }}
|
|
73
|
+
*/
|
|
74
|
+
export function useTableDelete(tableRef, options = {}) {
|
|
75
|
+
const {
|
|
76
|
+
endpoint,
|
|
77
|
+
successMessage,
|
|
78
|
+
errorMessage,
|
|
79
|
+
onSuccess,
|
|
80
|
+
onError,
|
|
81
|
+
} = options
|
|
82
|
+
|
|
83
|
+
async function handleDelete(row) {
|
|
84
|
+
try {
|
|
85
|
+
const axios = getAxiosInstance()
|
|
86
|
+
await axios.delete(`/${endpoint}/${row.id}`)
|
|
87
|
+
} catch (err) {
|
|
88
|
+
if (onError) {
|
|
89
|
+
const handled = onError(err, row)
|
|
90
|
+
if (handled) return
|
|
91
|
+
}
|
|
92
|
+
sparkNotificationService.show({
|
|
93
|
+
type: 'danger',
|
|
94
|
+
message: errorMessage || err.response?.data?.message || 'Failed to delete.',
|
|
95
|
+
})
|
|
96
|
+
console.error(err)
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
sparkNotificationService.show({
|
|
101
|
+
type: 'success',
|
|
102
|
+
message: successMessage || 'Deleted successfully.',
|
|
103
|
+
})
|
|
104
|
+
if (onSuccess) onSuccess(row)
|
|
105
|
+
if (tableRef?.value?.refresh) tableRef.value.refresh()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return { handleDelete }
|
|
109
|
+
}
|
|
@@ -24,6 +24,7 @@ import { parseLaravelErrors, getFormLevelMessage, isValidationError } from '../u
|
|
|
24
24
|
*/
|
|
25
25
|
export function useFormSubmission(options = {}) {
|
|
26
26
|
const {
|
|
27
|
+
endpoint = null,
|
|
27
28
|
successMessage = 'Saved successfully!',
|
|
28
29
|
createMessage = 'Created successfully!',
|
|
29
30
|
updateMessage = 'Updated successfully!',
|
|
@@ -152,9 +153,28 @@ export function useFormSubmission(options = {}) {
|
|
|
152
153
|
})
|
|
153
154
|
}
|
|
154
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Convenience method for standard CRUD form submissions.
|
|
158
|
+
* Automatically constructs URL and HTTP method from endpoint + resourceId.
|
|
159
|
+
* Requires `endpoint` option to be set.
|
|
160
|
+
*
|
|
161
|
+
* @param {Object} config - Submission configuration
|
|
162
|
+
* @param {Object} config.payload - Request payload
|
|
163
|
+
* @param {Object} config.node - FormKit node
|
|
164
|
+
* @param {string|number} config.resourceId - Resource ID (for edit mode)
|
|
165
|
+
* @param {boolean} config.isEditMode - Whether this is an update
|
|
166
|
+
*/
|
|
167
|
+
async function submitCrud(config) {
|
|
168
|
+
const { payload, node, resourceId, isEditMode } = config
|
|
169
|
+
const url = isEditMode ? `/${endpoint}/${resourceId}` : `/${endpoint}`
|
|
170
|
+
const method = isEditMode ? 'put' : 'post'
|
|
171
|
+
return submitToApi({ url, payload, method, node, isEditMode })
|
|
172
|
+
}
|
|
173
|
+
|
|
155
174
|
return {
|
|
156
175
|
submitting,
|
|
157
176
|
submit,
|
|
158
177
|
submitToApi,
|
|
178
|
+
...(endpoint ? { submitCrud } : {}),
|
|
159
179
|
}
|
|
160
180
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Australian state/territory options for use in select dropdowns and filter controls.
|
|
3
|
+
* Each entry has { label, value } shape compatible with FormKit selects and SparkTable filters.
|
|
4
|
+
*/
|
|
5
|
+
export const AUSTRALIAN_STATES = [
|
|
6
|
+
{ label: 'Australian Capital Territory', value: 'ACT' },
|
|
7
|
+
{ label: 'New South Wales', value: 'NSW' },
|
|
8
|
+
{ label: 'Northern Territory', value: 'NT' },
|
|
9
|
+
{ label: 'Queensland', value: 'QLD' },
|
|
10
|
+
{ label: 'South Australia', value: 'SA' },
|
|
11
|
+
{ label: 'Tasmania', value: 'TAS' },
|
|
12
|
+
{ label: 'Victoria', value: 'VIC' },
|
|
13
|
+
{ label: 'Western Australia', value: 'WA' },
|
|
14
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AUSTRALIAN_STATES } from './australianStates.js'
|