mirror of
https://github.com/sysadminsmedia/homebox.git
synced 2026-01-04 20:14:54 +01:00
Add maintenance records checkbox to wipe inventory dialog
- Added wipeMaintenance parameter to backend WipeInventory method - Added checkbox in WipeInventoryDialog for wiping maintenance records - Updated demo mode error message to include maintenance records - Added translation key "wipe_inventory_maintenance" to en.json - Maintenance records are linked to items via HasItemWith query - Follows same structure as labels and locations checkboxes Co-authored-by: katosdev <7927609+katosdev@users.noreply.github.com>
This commit is contained in:
@@ -98,8 +98,9 @@ func (ctrl *V1Controller) HandleCreateMissingThumbnails() errchain.HandlerFunc {
|
||||
|
||||
// WipeInventoryOptions represents the options for wiping inventory
|
||||
type WipeInventoryOptions struct {
|
||||
WipeLabels bool `json:"wipeLabels"`
|
||||
WipeLocations bool `json:"wipeLocations"`
|
||||
WipeLabels bool `json:"wipeLabels"`
|
||||
WipeLocations bool `json:"wipeLocations"`
|
||||
WipeMaintenance bool `json:"wipeMaintenance"`
|
||||
}
|
||||
|
||||
// HandleWipeInventory godoc
|
||||
@@ -128,14 +129,15 @@ func (ctrl *V1Controller) HandleWipeInventory() errchain.HandlerFunc {
|
||||
// Parse options from request body
|
||||
var options WipeInventoryOptions
|
||||
if err := server.Decode(r, &options); err != nil {
|
||||
// If no body provided, use default (false for both)
|
||||
// If no body provided, use default (false for all)
|
||||
options = WipeInventoryOptions{
|
||||
WipeLabels: false,
|
||||
WipeLocations: false,
|
||||
WipeLabels: false,
|
||||
WipeLocations: false,
|
||||
WipeMaintenance: false,
|
||||
}
|
||||
}
|
||||
|
||||
totalCompleted, err := ctrl.repo.Items.WipeInventory(ctx, ctx.GID, options.WipeLabels, options.WipeLocations)
|
||||
totalCompleted, err := ctrl.repo.Items.WipeInventory(ctx, ctx.GID, options.WipeLabels, options.WipeLocations, options.WipeMaintenance)
|
||||
if err != nil {
|
||||
log.Err(err).Str("action_ref", "wipe inventory").Msg("failed to run action")
|
||||
return validate.NewRequestError(err, http.StatusInternalServerError)
|
||||
|
||||
@@ -809,7 +809,7 @@ func (e *ItemsRepository) DeleteByGroup(ctx context.Context, gid, id uuid.UUID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *ItemsRepository) WipeInventory(ctx context.Context, gid uuid.UUID, wipeLabels bool, wipeLocations bool) (int, error) {
|
||||
func (e *ItemsRepository) WipeInventory(ctx context.Context, gid uuid.UUID, wipeLabels bool, wipeLocations bool, wipeMaintenance bool) (int, error) {
|
||||
// Get all items for the group
|
||||
items, err := e.db.Item.Query().
|
||||
Where(item.HasGroupWith(group.ID(gid))).
|
||||
@@ -872,6 +872,20 @@ func (e *ItemsRepository) WipeInventory(ctx context.Context, gid uuid.UUID, wipe
|
||||
}
|
||||
}
|
||||
|
||||
// Wipe maintenance records if requested
|
||||
if wipeMaintenance {
|
||||
// Maintenance entries are linked to items, so we query by items in the group
|
||||
maintenanceCount, err := e.db.MaintenanceEntry.Delete().
|
||||
Where(maintenanceentry.HasItemWith(item.HasGroupWith(group.ID(gid)))).
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("failed to delete maintenance entries during wipe inventory")
|
||||
} else {
|
||||
log.Info().Int("count", maintenanceCount).Msg("deleted maintenance entries during wipe inventory")
|
||||
deleted += maintenanceCount
|
||||
}
|
||||
}
|
||||
|
||||
e.publishMutationEvent(gid)
|
||||
return deleted, nil
|
||||
}
|
||||
|
||||
@@ -32,6 +32,18 @@
|
||||
{{ $t("tools.actions_set.wipe_inventory_locations") }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-2">
|
||||
<input
|
||||
id="wipe-maintenance-checkbox"
|
||||
v-model="wipeMaintenance"
|
||||
type="checkbox"
|
||||
class="h-4 w-4 rounded border-gray-300"
|
||||
/>
|
||||
<label for="wipe-maintenance-checkbox" class="text-sm font-medium cursor-pointer">
|
||||
{{ $t("tools.actions_set.wipe_inventory_maintenance") }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-sm text-gray-600">
|
||||
@@ -57,13 +69,15 @@
|
||||
const dialog = ref(false);
|
||||
const wipeLabels = ref(false);
|
||||
const wipeLocations = ref(false);
|
||||
const wipeMaintenance = ref(false);
|
||||
|
||||
let onCloseCallback: ((result?: { wipeLabels: boolean; wipeLocations: boolean } | undefined) => void) | undefined;
|
||||
let onCloseCallback: ((result?: { wipeLabels: boolean; wipeLocations: boolean; wipeMaintenance: boolean } | undefined) => void) | undefined;
|
||||
|
||||
registerOpenDialogCallback(DialogID.WipeInventory, (params?: { onClose?: (result?: { wipeLabels: boolean; wipeLocations: boolean } | undefined) => void }) => {
|
||||
registerOpenDialogCallback(DialogID.WipeInventory, (params?: { onClose?: (result?: { wipeLabels: boolean; wipeLocations: boolean; wipeMaintenance: boolean } | undefined) => void }) => {
|
||||
dialog.value = true;
|
||||
wipeLabels.value = false;
|
||||
wipeLocations.value = false;
|
||||
wipeMaintenance.value = false;
|
||||
onCloseCallback = params?.onClose;
|
||||
});
|
||||
|
||||
@@ -78,6 +92,7 @@
|
||||
const result = {
|
||||
wipeLabels: wipeLabels.value,
|
||||
wipeLocations: wipeLocations.value,
|
||||
wipeMaintenance: wipeMaintenance.value,
|
||||
};
|
||||
closeDialog(DialogID.WipeInventory, result);
|
||||
onCloseCallback?.(result);
|
||||
|
||||
@@ -72,7 +72,7 @@ export type DialogResultMap = {
|
||||
[DialogID.ItemImage]?: { action: "delete"; id: string };
|
||||
[DialogID.EditMaintenance]?: boolean;
|
||||
[DialogID.ItemChangeDetails]?: boolean;
|
||||
[DialogID.WipeInventory]?: { wipeLabels: boolean; wipeLocations: boolean };
|
||||
[DialogID.WipeInventory]?: { wipeLabels: boolean; wipeLocations: boolean; wipeMaintenance: boolean };
|
||||
};
|
||||
|
||||
/** Helpers to split IDs by requirement */
|
||||
|
||||
@@ -32,8 +32,8 @@ export class ActionsAPI extends BaseAPI {
|
||||
});
|
||||
}
|
||||
|
||||
wipeInventory(options?: { wipeLabels?: boolean; wipeLocations?: boolean }) {
|
||||
return this.http.post<{ wipeLabels?: boolean; wipeLocations?: boolean }, ActionAmountResult>({
|
||||
wipeInventory(options?: { wipeLabels?: boolean; wipeLocations?: boolean; wipeMaintenance?: boolean }) {
|
||||
return this.http.post<{ wipeLabels?: boolean; wipeLocations?: boolean; wipeMaintenance?: boolean }, ActionAmountResult>({
|
||||
url: route("/actions/wipe-inventory"),
|
||||
body: options || {},
|
||||
});
|
||||
|
||||
@@ -740,6 +740,7 @@
|
||||
"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_maintenance": "Also wipe all maintenance records",
|
||||
"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",
|
||||
@@ -749,7 +750,7 @@
|
||||
},
|
||||
"actions_sub": "Apply Actions to your inventory in bulk. These are irreversible actions. '<b>'Be careful.'</b>'",
|
||||
"demo_mode_error": {
|
||||
"wipe_inventory": "Inventory, labels and locations cannot be wiped whilst Homebox is in demo mode. Please ensure that you are not in demo mode and try again."
|
||||
"wipe_inventory": "Inventory, labels, locations and maintenance records cannot be wiped whilst Homebox is in demo mode. Please ensure that you are not in demo mode and try again."
|
||||
},
|
||||
"import_export": "Import/Export",
|
||||
"import_export_set": {
|
||||
|
||||
@@ -250,6 +250,7 @@
|
||||
const apiResult = await api.actions.wipeInventory({
|
||||
wipeLabels: result.wipeLabels,
|
||||
wipeLocations: result.wipeLocations,
|
||||
wipeMaintenance: result.wipeMaintenance,
|
||||
});
|
||||
|
||||
if (apiResult.error) {
|
||||
|
||||
Reference in New Issue
Block a user