forked from mirrors/homebox
feat: asset tags/ids (#142)
* add schema * run db migration * bulk seed asset IDs * breaking: update runtime options * conditionally increment asset IDs * update API endpoints * fix import asset id assignment * refactor display + marshal/unmarshal * add docs page * add to form field * hide 000-000 values * update ENV vars
This commit is contained in:
parent
976f68252d
commit
6dc2ae1bea
32 changed files with 905 additions and 72 deletions
10
frontend/lib/api/classes/actions.ts
Normal file
10
frontend/lib/api/classes/actions.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { BaseAPI, route } from "../base";
|
||||
import { EnsureAssetIDResult } from "../types/data-contracts";
|
||||
|
||||
export class ActionsAPI extends BaseAPI {
|
||||
ensureAssetIDs() {
|
||||
return this.http.post<void, EnsureAssetIDResult>({
|
||||
url: route("/actions/ensure-asset-ids"),
|
||||
});
|
||||
}
|
||||
}
|
|
@ -71,6 +71,9 @@ export interface ItemField {
|
|||
|
||||
export interface ItemOut {
|
||||
archived: boolean;
|
||||
|
||||
/** @example 0 */
|
||||
assetId: string;
|
||||
attachments: ItemAttachment[];
|
||||
children: ItemSummary[];
|
||||
createdAt: Date;
|
||||
|
@ -131,6 +134,7 @@ export interface ItemSummary {
|
|||
|
||||
export interface ItemUpdate {
|
||||
archived: boolean;
|
||||
assetId: string;
|
||||
description: string;
|
||||
fields: ItemField[];
|
||||
id: string;
|
||||
|
@ -300,6 +304,10 @@ export interface ChangePassword {
|
|||
new: string;
|
||||
}
|
||||
|
||||
export interface EnsureAssetIDResult {
|
||||
completed: number;
|
||||
}
|
||||
|
||||
export interface GroupInvitation {
|
||||
expiresAt: Date;
|
||||
token: string;
|
||||
|
|
|
@ -4,6 +4,7 @@ import { LabelsApi } from "./classes/labels";
|
|||
import { LocationsApi } from "./classes/locations";
|
||||
import { GroupApi } from "./classes/group";
|
||||
import { UserApi } from "./classes/users";
|
||||
import { ActionsAPI } from "./classes/actions";
|
||||
import { Requests } from "~~/lib/requests";
|
||||
|
||||
export class UserClient extends BaseAPI {
|
||||
|
@ -12,6 +13,7 @@ export class UserClient extends BaseAPI {
|
|||
items: ItemsApi;
|
||||
group: GroupApi;
|
||||
user: UserApi;
|
||||
actions: ActionsAPI;
|
||||
|
||||
constructor(requests: Requests) {
|
||||
super(requests);
|
||||
|
@ -21,6 +23,7 @@ export class UserClient extends BaseAPI {
|
|||
this.items = new ItemsApi(requests);
|
||||
this.group = new GroupApi(requests);
|
||||
this.user = new UserApi(requests);
|
||||
this.actions = new ActionsAPI(requests);
|
||||
|
||||
Object.freeze(this);
|
||||
}
|
||||
|
|
|
@ -120,6 +120,11 @@
|
|||
label: "Archived",
|
||||
ref: "archived",
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
label: "Asset ID",
|
||||
ref: "assetId",
|
||||
},
|
||||
];
|
||||
|
||||
const purchaseFields: FormField[] = [
|
||||
|
|
|
@ -70,6 +70,19 @@
|
|||
);
|
||||
});
|
||||
|
||||
const assetID = computed<Details>(() => {
|
||||
if (item.value?.assetId === "000-000") {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
name: "Asset ID",
|
||||
text: item.value?.assetId,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const itemDetails = computed<Details>(() => {
|
||||
return [
|
||||
{
|
||||
|
@ -100,6 +113,7 @@
|
|||
name: "Notes",
|
||||
text: item.value?.notes,
|
||||
},
|
||||
...assetID.value,
|
||||
...item.value.fields.map(field => {
|
||||
/**
|
||||
* Support Special URL Syntax
|
||||
|
|
|
@ -163,6 +163,25 @@
|
|||
passwordChange.current = "";
|
||||
passwordChange.loading = false;
|
||||
}
|
||||
|
||||
async function ensureAssetIDs() {
|
||||
const { isCanceled } = await confirm.open(
|
||||
"Are you sure you want to ensure all assets have an ID? This will take a while and cannot be undone."
|
||||
);
|
||||
|
||||
if (isCanceled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await api.actions.ensureAssetIDs();
|
||||
|
||||
if (result.error) {
|
||||
notify.error("Failed to ensure asset IDs.");
|
||||
return;
|
||||
}
|
||||
|
||||
notify.success(`${result.data.completed} assets have been updated.`);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -286,6 +305,32 @@
|
|||
</div>
|
||||
</BaseCard>
|
||||
|
||||
<BaseCard>
|
||||
<template #title>
|
||||
<BaseSectionHeader>
|
||||
<Icon name="mdi-warning" class="mr-2 -mt-1 text-base-600" />
|
||||
<span class="text-base-600"> Actions </span>
|
||||
<template #description>
|
||||
Apply Actions to your inventory in bulk. These are irreversible actions. Be careful.
|
||||
</template>
|
||||
</BaseSectionHeader>
|
||||
|
||||
<div class="py-4 border-t-2 border-gray-300">
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-10">
|
||||
<div class="col-span-3">
|
||||
<h4>Manage Asset IDs</h4>
|
||||
<p class="text-sm">
|
||||
Ensures that all items in your inventory have a valid asset_id field. This is done by finding the
|
||||
highest current asset_id field in the database and applying the next value to each item that has an
|
||||
unset asset_id field. This is done in order of the created_at field.
|
||||
</p>
|
||||
</div>
|
||||
<BaseButton class="btn-primary mt-auto" @click="ensureAssetIDs"> Ensure Asset IDs </BaseButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</BaseCard>
|
||||
|
||||
<BaseCard>
|
||||
<template #title>
|
||||
<BaseSectionHeader>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue