mirror of
https://github.com/sysadminsmedia/homebox.git
synced 2026-01-04 20:14:54 +01:00
Add wipe inventory options for labels/locations and owner-only restriction
- Added WipeInventoryDialog component with checkboxes for wiping labels and locations - Modified backend WipeInventory method to accept wipeLabels and wipeLocations parameters - Added owner check in HandleWipeInventory to restrict action to group owners only - Updated frontend API client to send wipe options - Added new translation keys for checkbox labels and owner note - Integrated dialog into app layout and updated tools.vue to use new dialog Co-authored-by: katosdev <7927609+katosdev@users.noreply.github.com>
This commit is contained in:
85
frontend/components/WipeInventoryDialog.vue
Normal file
85
frontend/components/WipeInventoryDialog.vue
Normal file
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<BaseModal v-model="dialog" max-width="600px">
|
||||
<template #title>
|
||||
<span>{{ $t("tools.actions_set.wipe_inventory") }}</span>
|
||||
</template>
|
||||
<div class="space-y-4">
|
||||
<p class="text-base">
|
||||
{{ $t("tools.actions_set.wipe_inventory_confirm") }}
|
||||
</p>
|
||||
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center space-x-2">
|
||||
<input
|
||||
id="wipe-labels-checkbox"
|
||||
v-model="wipeLabels"
|
||||
type="checkbox"
|
||||
class="h-4 w-4 rounded border-gray-300"
|
||||
/>
|
||||
<label for="wipe-labels-checkbox" class="text-sm font-medium cursor-pointer">
|
||||
{{ $t("tools.actions_set.wipe_inventory_labels") }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-2">
|
||||
<input
|
||||
id="wipe-locations-checkbox"
|
||||
v-model="wipeLocations"
|
||||
type="checkbox"
|
||||
class="h-4 w-4 rounded border-gray-300"
|
||||
/>
|
||||
<label for="wipe-locations-checkbox" class="text-sm font-medium cursor-pointer">
|
||||
{{ $t("tools.actions_set.wipe_inventory_locations") }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-sm text-gray-600">
|
||||
{{ $t("tools.actions_set.wipe_inventory_note") }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<template #actions>
|
||||
<BaseButton @click="close"> {{ $t("global.cancel") }} </BaseButton>
|
||||
<BaseButton type="primary" @click="confirm">
|
||||
{{ $t("global.confirm") }}
|
||||
</BaseButton>
|
||||
</template>
|
||||
</BaseModal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { DialogID } from "~/components/ui/dialog-provider/utils";
|
||||
import { useDialog } from "~/components/ui/dialog-provider";
|
||||
|
||||
const { registerOpenDialogCallback, closeDialog } = useDialog();
|
||||
|
||||
const dialog = ref(false);
|
||||
const wipeLabels = ref(false);
|
||||
const wipeLocations = ref(false);
|
||||
|
||||
let onCloseCallback: ((result?: { wipeLabels: boolean; wipeLocations: boolean } | undefined) => void) | undefined;
|
||||
|
||||
registerOpenDialogCallback(DialogID.WipeInventory, (params?: { onClose?: (result?: { wipeLabels: boolean; wipeLocations: boolean } | undefined) => void }) => {
|
||||
dialog.value = true;
|
||||
wipeLabels.value = false;
|
||||
wipeLocations.value = false;
|
||||
onCloseCallback = params?.onClose;
|
||||
});
|
||||
|
||||
function close() {
|
||||
dialog.value = false;
|
||||
closeDialog(DialogID.WipeInventory, undefined);
|
||||
onCloseCallback?.(undefined);
|
||||
}
|
||||
|
||||
function confirm() {
|
||||
dialog.value = false;
|
||||
const result = {
|
||||
wipeLabels: wipeLabels.value,
|
||||
wipeLocations: wipeLocations.value,
|
||||
};
|
||||
closeDialog(DialogID.WipeInventory, result);
|
||||
onCloseCallback?.(result);
|
||||
}
|
||||
</script>
|
||||
@@ -26,6 +26,7 @@ export enum DialogID {
|
||||
UpdateLocation = "update-location",
|
||||
UpdateTemplate = "update-template",
|
||||
ItemChangeDetails = "item-table-updater",
|
||||
WipeInventory = "wipe-inventory",
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,6 +72,7 @@ export type DialogResultMap = {
|
||||
[DialogID.ItemImage]?: { action: "delete"; id: string };
|
||||
[DialogID.EditMaintenance]?: boolean;
|
||||
[DialogID.ItemChangeDetails]?: boolean;
|
||||
[DialogID.WipeInventory]?: { wipeLabels: boolean; wipeLocations: boolean };
|
||||
};
|
||||
|
||||
/** Helpers to split IDs by requirement */
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<ModalConfirm />
|
||||
<OutdatedModal v-if="status" :status="status" />
|
||||
<ItemCreateModal />
|
||||
<WipeInventoryDialog />
|
||||
<LabelCreateModal />
|
||||
<LocationCreateModal />
|
||||
<ItemBarcodeModal />
|
||||
@@ -216,6 +217,7 @@
|
||||
import ModalConfirm from "~/components/ModalConfirm.vue";
|
||||
import OutdatedModal from "~/components/App/OutdatedModal.vue";
|
||||
import ItemCreateModal from "~/components/Item/CreateModal.vue";
|
||||
import WipeInventoryDialog from "~/components/WipeInventoryDialog.vue";
|
||||
|
||||
import LabelCreateModal from "~/components/Label/CreateModal.vue";
|
||||
import LocationCreateModal from "~/components/Location/CreateModal.vue";
|
||||
|
||||
@@ -32,9 +32,10 @@ export class ActionsAPI extends BaseAPI {
|
||||
});
|
||||
}
|
||||
|
||||
wipeInventory() {
|
||||
return this.http.post<void, ActionAmountResult>({
|
||||
wipeInventory(options?: { wipeLabels?: boolean; wipeLocations?: boolean }) {
|
||||
return this.http.post<{ wipeLabels?: boolean; wipeLocations?: boolean }, ActionAmountResult>({
|
||||
url: route("/actions/wipe-inventory"),
|
||||
body: options || {},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -738,6 +738,9 @@
|
||||
"wipe_inventory": "Wipe Inventory",
|
||||
"wipe_inventory_button": "Wipe Inventory",
|
||||
"wipe_inventory_confirm": "Are you sure you want to wipe your entire inventory? This will delete all items and cannot be undone.",
|
||||
"wipe_inventory_labels": "Also wipe all labels (tags)",
|
||||
"wipe_inventory_locations": "Also wipe all locations",
|
||||
"wipe_inventory_note": "Note: Only group owners can perform this action.",
|
||||
"wipe_inventory_sub": "Permanently deletes all items in your inventory. This action is irreversible and will remove all item data including attachments and photos.",
|
||||
"zero_datetimes": "Zero Item Date Times",
|
||||
"zero_datetimes_button": "Zero Item Date Times",
|
||||
|
||||
@@ -228,20 +228,25 @@
|
||||
}
|
||||
|
||||
async function wipeInventory() {
|
||||
const { isCanceled } = await confirm.open(t("tools.actions_set.wipe_inventory_confirm"));
|
||||
|
||||
if (isCanceled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await api.actions.wipeInventory();
|
||||
|
||||
if (result.error) {
|
||||
toast.error(t("tools.toast.failed_wipe_inventory"));
|
||||
return;
|
||||
}
|
||||
|
||||
toast.success(t("tools.toast.wipe_inventory_success", { results: result.data.completed }));
|
||||
openDialog(DialogID.WipeInventory, {
|
||||
onClose: async (result) => {
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
const apiResult = await api.actions.wipeInventory({
|
||||
wipeLabels: result.wipeLabels,
|
||||
wipeLocations: result.wipeLocations,
|
||||
});
|
||||
|
||||
if (apiResult.error) {
|
||||
toast.error(t("tools.toast.failed_wipe_inventory"));
|
||||
return;
|
||||
}
|
||||
|
||||
toast.success(t("tools.toast.wipe_inventory_success", { results: apiResult.data.completed }));
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user