From 9cd0d5fb5e1d0507e3c3bc48227baa01ab74dbf8 Mon Sep 17 00:00:00 2001 From: Sirttas Date: Tue, 9 Jun 2026 23:44:16 +0200 Subject: [PATCH] rule book dup/delete --- docs/mammon-api.yml | 24 +++++++++-- src/App.vue | 2 + src/confirm/ConfirmModal.vue | 45 +++++++++++++++++++++ src/confirm/index.ts | 3 ++ src/confirm/useConfirm.ts | 37 +++++++++++++++++ src/generated/mammon/api.ts | 67 +++++++++++++++++++++++++++++++ src/pages/rules/ListRuleBooks.vue | 23 +++++++++-- src/rules/rules.ts | 12 +++++- 8 files changed, 205 insertions(+), 8 deletions(-) create mode 100644 src/confirm/ConfirmModal.vue create mode 100644 src/confirm/index.ts create mode 100644 src/confirm/useConfirm.ts diff --git a/docs/mammon-api.yml b/docs/mammon-api.yml index 87217ed..406ff22 100644 --- a/docs/mammon-api.yml +++ b/docs/mammon-api.yml @@ -58,6 +58,24 @@ paths: $ref: "#/components/schemas/RuleBookResponse" "400": description: Invalid request (e.g. blank name) + delete: + tags: + - rule-book + summary: Delete a rule book + operationId: deleteRuleBook + parameters: + - name: ruleBookId + in: path + description: Id of the rule book + required: true + schema: + type: string + format: uuid + responses: + "204": + description: The rule book was deleted + "400": + description: The rule book is associated to a character /ledgers/main/{ledgerId}: put: tags: @@ -439,7 +457,7 @@ components: type: array items: type: string - pattern: "[a-z]+(-[a-z]+)*" + pattern: "[a-z][a-zA-Z0-9]*" script: type: string required: @@ -461,7 +479,7 @@ components: type: array items: type: string - pattern: "[a-z]+(-[a-z]+)*" + pattern: "[a-z][a-zA-Z0-9]*" script: type: string required: @@ -571,7 +589,7 @@ components: type: array items: type: string - pattern: "[a-z]+(-[a-z]+)*" + pattern: "[a-z][a-zA-Z0-9]*" script: type: string required: diff --git a/src/App.vue b/src/App.vue index 773444b..c3670ec 100644 --- a/src/App.vue +++ b/src/App.vue @@ -2,6 +2,7 @@ import {computed} from 'vue'; import {RouterView, useRoute} from 'vue-router'; import {Sidebar} from './sidebar'; +import {ConfirmModal} from '@/confirm'; import {routeNames} from '@/routes'; const route = useRoute(); @@ -21,6 +22,7 @@ const hideSidebar = computed(() => { + \ No newline at end of file diff --git a/src/confirm/index.ts b/src/confirm/index.ts new file mode 100644 index 0000000..ad55037 --- /dev/null +++ b/src/confirm/index.ts @@ -0,0 +1,3 @@ +export { default as ConfirmModal } from './ConfirmModal.vue'; +export { confirm, useConfirmStore } from './useConfirm'; +export type { ConfirmOptions } from './useConfirm'; \ No newline at end of file diff --git a/src/confirm/useConfirm.ts b/src/confirm/useConfirm.ts new file mode 100644 index 0000000..5bbe1a8 --- /dev/null +++ b/src/confirm/useConfirm.ts @@ -0,0 +1,37 @@ +import {defineStore} from "pinia"; +import {ref} from "vue"; + +export interface ConfirmOptions { + title?: string; + message: string; + confirmLabel?: string; + cancelLabel?: string; + danger?: boolean; +} + +export const useConfirmStore = defineStore('confirm', () => { + const open = ref(false); + const options = ref({message: ""}); + let resolver: ((value: boolean) => void) | undefined; + + const settle = (value: boolean) => { + open.value = false; + resolver?.(value); + resolver = undefined; + }; + + const confirm = (opts: ConfirmOptions | string): Promise => { + options.value = typeof opts === "string" ? {message: opts} : opts; + open.value = true; + return new Promise(resolve => { + resolver = resolve; + }); + }; + + const accept = () => settle(true); + const cancel = () => settle(false); + + return {open, options, confirm, accept, cancel}; +}); + +export const confirm = (opts: ConfirmOptions | string): Promise => useConfirmStore().confirm(opts); \ No newline at end of file diff --git a/src/generated/mammon/api.ts b/src/generated/mammon/api.ts index 38c479c..df4b63f 100644 --- a/src/generated/mammon/api.ts +++ b/src/generated/mammon/api.ts @@ -1313,6 +1313,39 @@ export const RuleBookApiAxiosParamCreator = function (configuration?: Configurat options: localVarRequestOptions, }; }, + /** + * + * @summary Delete a rule book + * @param {string} ruleBookId Id of the rule book + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + deleteRuleBook: async (ruleBookId: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'ruleBookId' is not null or undefined + assertParamExists('deleteRuleBook', 'ruleBookId', ruleBookId) + const localVarPath = `/rule-books/{ruleBookId}` + .replace('{ruleBookId}', encodeURIComponent(String(ruleBookId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'DELETE', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * * @summary Find all rule books @@ -1468,6 +1501,19 @@ export const RuleBookApiFp = function(configuration?: Configuration) { const localVarOperationServerBasePath = operationServerMap['RuleBookApi.createRuleBook']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, + /** + * + * @summary Delete a rule book + * @param {string} ruleBookId Id of the rule book + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async deleteRuleBook(ruleBookId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.deleteRuleBook(ruleBookId, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['RuleBookApi.deleteRuleBook']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, /** * * @summary Find all rule books @@ -1538,6 +1584,16 @@ export const RuleBookApiFactory = function (configuration?: Configuration, baseP createRuleBook(createRuleBookRequest: CreateRuleBookRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.createRuleBook(createRuleBookRequest, options).then((request) => request(axios, basePath)); }, + /** + * + * @summary Delete a rule book + * @param {string} ruleBookId Id of the rule book + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + deleteRuleBook(ruleBookId: string, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.deleteRuleBook(ruleBookId, options).then((request) => request(axios, basePath)); + }, /** * * @summary Find all rule books @@ -1595,6 +1651,17 @@ export class RuleBookApi extends BaseAPI { return RuleBookApiFp(this.configuration).createRuleBook(createRuleBookRequest, options).then((request) => request(this.axios, this.basePath)); } + /** + * + * @summary Delete a rule book + * @param {string} ruleBookId Id of the rule book + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + public deleteRuleBook(ruleBookId: string, options?: RawAxiosRequestConfig) { + return RuleBookApiFp(this.configuration).deleteRuleBook(ruleBookId, options).then((request) => request(this.axios, this.basePath)); + } + /** * * @summary Find all rule books diff --git a/src/pages/rules/ListRuleBooks.vue b/src/pages/rules/ListRuleBooks.vue index b90056a..1fe39cd 100644 --- a/src/pages/rules/ListRuleBooks.vue +++ b/src/pages/rules/ListRuleBooks.vue @@ -1,10 +1,24 @@ @@ -16,7 +30,8 @@ const {ruleBooks} = storeToRefs(useRuleBooksStore());
{{ruleBook.name}} - + +
\ No newline at end of file diff --git a/src/rules/rules.ts b/src/rules/rules.ts index 558e1cc..13ed86a 100644 --- a/src/rules/rules.ts +++ b/src/rules/rules.ts @@ -32,12 +32,22 @@ export const useRuleBooksStore = defineStore('rule-books', () => { const findById = (ruleBookId: string): RuleBook | undefined => ruleBooks.value.find(rb => rb.ruleBookId === ruleBookId); const create = (ruleBook: CreateRuleBookRequest) => ruleBookApi.createRuleBook(ruleBook).then(response => addRuleBook(response.data)); const update = (ruleBookId: string, ruleBook: CreateRuleBookRequest) => ruleBookApi.updateRuleBook(ruleBookId, ruleBook).then(response => replaceRuleBook(response.data)); + const duplicate = (ruleBook: RuleBook) => create({ + name: `${ruleBook.name} (copy)`, + usedForAcquisitions: ruleBook.usedForAcquisitions, + ledgerRefs: [...ruleBook.ledgerRefs], + script: ruleBook.script, + }); + + const remove = (ruleBookId: string) => ruleBookApi.deleteRuleBook(ruleBookId).then(() => { + ruleBooks.value = ruleBooks.value.filter(rb => rb.ruleBookId !== ruleBookId); + }); const refresh = () => ruleBookApi.findAllRuleBooks().then(response => ruleBooks.value = response.data); refresh(); - return {ruleBooks, findById, create, update, refresh}; + return {ruleBooks, findById, create, update, duplicate, remove, refresh}; }) export const findCharacterRuleBookByCharacterId = (characterId: number): Promise => characterRuleBookApi.findCharacterRuleBookByCharacterId(characterId)