forked from mirrors/homebox
feat: init tools page (#271)
This commit is contained in:
parent
ab22ea6a25
commit
6ff2d64996
7 changed files with 194 additions and 129 deletions
|
@ -53,11 +53,16 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
function setFile(e: Event) {
|
function setFile(e: Event) {
|
||||||
importCsv.value = e.target.files[0];
|
const result = e.target as HTMLInputElement;
|
||||||
|
if (!result.files || result.files.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
importCsv.value = result.files[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
function uploadCsv() {
|
function uploadCsv() {
|
||||||
importRef.value.click();
|
importRef.value?.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
const eventBus = useEventBus();
|
const eventBus = useEventBus();
|
||||||
|
@ -86,5 +91,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
eventBus.emit(EventTypes.InvalidStores);
|
eventBus.emit(EventTypes.InvalidStores);
|
||||||
|
|
||||||
|
toast.success("Import successful!");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
17
frontend/components/DetailAction.vue
Normal file
17
frontend/components/DetailAction.vue
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<template>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-10 py-6">
|
||||||
|
<div class="col-span-3">
|
||||||
|
<h4 class="mb-1 text-lg font-semibold">
|
||||||
|
<slot name="title"></slot>
|
||||||
|
</h4>
|
||||||
|
<p class="text-sm">
|
||||||
|
<slot></slot>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<BaseButton class="btn-primary mt-auto" @click="$emit('action')">
|
||||||
|
<slot name="button">
|
||||||
|
<slot name="title"></slot>
|
||||||
|
</slot>
|
||||||
|
</BaseButton>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -6,7 +6,6 @@
|
||||||
up the tree
|
up the tree
|
||||||
-->
|
-->
|
||||||
<ModalConfirm />
|
<ModalConfirm />
|
||||||
<AppImportDialog v-model="modals.import" />
|
|
||||||
<ItemCreateModal v-model="modals.item" />
|
<ItemCreateModal v-model="modals.item" />
|
||||||
<LabelCreateModal v-model="modals.label" />
|
<LabelCreateModal v-model="modals.label" />
|
||||||
<LocationCreateModal v-model="modals.location" />
|
<LocationCreateModal v-model="modals.location" />
|
||||||
|
@ -78,10 +77,6 @@
|
||||||
<Icon :name="n.icon" class="h-6 w-6 mr-4" />
|
<Icon :name="n.icon" class="h-6 w-6 mr-4" />
|
||||||
{{ n.name }}
|
{{ n.name }}
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<button v-else class="rounded-btn" @click="n.action">
|
|
||||||
<Icon :name="n.icon" class="h-6 w-6 mr-4" />
|
|
||||||
{{ n.name }}
|
|
||||||
</button>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -172,12 +167,11 @@
|
||||||
to: "/locations",
|
to: "/locations",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "mdi-database",
|
icon: "mdi-cog",
|
||||||
id: 2,
|
id: 6,
|
||||||
name: "Import",
|
active: computed(() => route.path === "/tools"),
|
||||||
action: () => {
|
name: "Tools",
|
||||||
modals.import = true;
|
to: "/tools",
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,11 @@ export interface DocumentOut {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Group {
|
export interface Group {
|
||||||
createdAt: string;
|
createdAt: Date | string;
|
||||||
currency: string;
|
currency: string;
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
updatedAt: string;
|
updatedAt: Date | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupStatistics {
|
export interface GroupStatistics {
|
||||||
|
@ -39,11 +39,11 @@ export interface GroupUpdate {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ItemAttachment {
|
export interface ItemAttachment {
|
||||||
createdAt: string;
|
createdAt: Date | string;
|
||||||
document: DocumentOut;
|
document: DocumentOut;
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
type: string;
|
||||||
updatedAt: string;
|
updatedAt: Date | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ItemAttachmentUpdate {
|
export interface ItemAttachmentUpdate {
|
||||||
|
@ -76,7 +76,7 @@ export interface ItemOut {
|
||||||
assetId: string;
|
assetId: string;
|
||||||
attachments: ItemAttachment[];
|
attachments: ItemAttachment[];
|
||||||
children: ItemSummary[];
|
children: ItemSummary[];
|
||||||
createdAt: string;
|
createdAt: Date | string;
|
||||||
description: string;
|
description: string;
|
||||||
fields: ItemField[];
|
fields: ItemField[];
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -96,23 +96,23 @@ export interface ItemOut {
|
||||||
/** @example "0" */
|
/** @example "0" */
|
||||||
purchasePrice: string;
|
purchasePrice: string;
|
||||||
/** Purchase */
|
/** Purchase */
|
||||||
purchaseTime: string;
|
purchaseTime: Date | string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
serialNumber: string;
|
serialNumber: string;
|
||||||
soldNotes: string;
|
soldNotes: string;
|
||||||
/** @example "0" */
|
/** @example "0" */
|
||||||
soldPrice: string;
|
soldPrice: string;
|
||||||
/** Sold */
|
/** Sold */
|
||||||
soldTime: string;
|
soldTime: Date | string;
|
||||||
soldTo: string;
|
soldTo: string;
|
||||||
updatedAt: string;
|
updatedAt: Date | string;
|
||||||
warrantyDetails: string;
|
warrantyDetails: string;
|
||||||
warrantyExpires: string;
|
warrantyExpires: Date | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ItemSummary {
|
export interface ItemSummary {
|
||||||
archived: boolean;
|
archived: boolean;
|
||||||
createdAt: string;
|
createdAt: Date | string;
|
||||||
description: string;
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
insured: boolean;
|
insured: boolean;
|
||||||
|
@ -123,7 +123,7 @@ export interface ItemSummary {
|
||||||
/** @example "0" */
|
/** @example "0" */
|
||||||
purchasePrice: string;
|
purchasePrice: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
updatedAt: string;
|
updatedAt: Date | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ItemUpdate {
|
export interface ItemUpdate {
|
||||||
|
@ -148,7 +148,7 @@ export interface ItemUpdate {
|
||||||
/** @example "0" */
|
/** @example "0" */
|
||||||
purchasePrice: string;
|
purchasePrice: string;
|
||||||
/** Purchase */
|
/** Purchase */
|
||||||
purchaseTime: string;
|
purchaseTime: Date | string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
/** Identifications */
|
/** Identifications */
|
||||||
serialNumber: string;
|
serialNumber: string;
|
||||||
|
@ -156,10 +156,10 @@ export interface ItemUpdate {
|
||||||
/** @example "0" */
|
/** @example "0" */
|
||||||
soldPrice: string;
|
soldPrice: string;
|
||||||
/** Sold */
|
/** Sold */
|
||||||
soldTime: string;
|
soldTime: Date | string;
|
||||||
soldTo: string;
|
soldTo: string;
|
||||||
warrantyDetails: string;
|
warrantyDetails: string;
|
||||||
warrantyExpires: string;
|
warrantyExpires: Date | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LabelCreate {
|
export interface LabelCreate {
|
||||||
|
@ -169,20 +169,20 @@ export interface LabelCreate {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LabelOut {
|
export interface LabelOut {
|
||||||
createdAt: string;
|
createdAt: Date | string;
|
||||||
description: string;
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
items: ItemSummary[];
|
items: ItemSummary[];
|
||||||
name: string;
|
name: string;
|
||||||
updatedAt: string;
|
updatedAt: Date | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LabelSummary {
|
export interface LabelSummary {
|
||||||
createdAt: string;
|
createdAt: Date | string;
|
||||||
description: string;
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
updatedAt: string;
|
updatedAt: Date | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LocationCreate {
|
export interface LocationCreate {
|
||||||
|
@ -193,30 +193,30 @@ export interface LocationCreate {
|
||||||
|
|
||||||
export interface LocationOut {
|
export interface LocationOut {
|
||||||
children: LocationSummary[];
|
children: LocationSummary[];
|
||||||
createdAt: string;
|
createdAt: Date | string;
|
||||||
description: string;
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
items: ItemSummary[];
|
items: ItemSummary[];
|
||||||
name: string;
|
name: string;
|
||||||
parent: LocationSummary;
|
parent: LocationSummary;
|
||||||
updatedAt: string;
|
updatedAt: Date | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LocationOutCount {
|
export interface LocationOutCount {
|
||||||
createdAt: string;
|
createdAt: Date | string;
|
||||||
description: string;
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
itemCount: number;
|
itemCount: number;
|
||||||
name: string;
|
name: string;
|
||||||
updatedAt: string;
|
updatedAt: Date | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LocationSummary {
|
export interface LocationSummary {
|
||||||
createdAt: string;
|
createdAt: Date | string;
|
||||||
description: string;
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
updatedAt: string;
|
updatedAt: Date | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LocationUpdate {
|
export interface LocationUpdate {
|
||||||
|
@ -229,7 +229,7 @@ export interface LocationUpdate {
|
||||||
export interface MaintenanceEntry {
|
export interface MaintenanceEntry {
|
||||||
/** @example "0" */
|
/** @example "0" */
|
||||||
cost: string;
|
cost: string;
|
||||||
date: Date;
|
date: Date | string;
|
||||||
description: string;
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -238,7 +238,7 @@ export interface MaintenanceEntry {
|
||||||
export interface MaintenanceEntryCreate {
|
export interface MaintenanceEntryCreate {
|
||||||
/** @example "0" */
|
/** @example "0" */
|
||||||
cost: string;
|
cost: string;
|
||||||
date: Date;
|
date: Date | string;
|
||||||
description: string;
|
description: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -246,7 +246,7 @@ export interface MaintenanceEntryCreate {
|
||||||
export interface MaintenanceEntryUpdate {
|
export interface MaintenanceEntryUpdate {
|
||||||
/** @example "0" */
|
/** @example "0" */
|
||||||
cost: string;
|
cost: string;
|
||||||
date: Date;
|
date: Date | string;
|
||||||
description: string;
|
description: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
@ -258,7 +258,7 @@ export interface MaintenanceLog {
|
||||||
itemId: string;
|
itemId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PaginationResultRepoItemSummary {
|
export interface PaginationResultItemSummary {
|
||||||
items: ItemSummary[];
|
items: ItemSummary[];
|
||||||
page: number;
|
page: number;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
|
@ -302,7 +302,7 @@ export interface ValueOverTime {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ValueOverTimeEntry {
|
export interface ValueOverTimeEntry {
|
||||||
date: Date;
|
date: Date | string;
|
||||||
name: string;
|
name: string;
|
||||||
value: number;
|
value: number;
|
||||||
}
|
}
|
||||||
|
@ -355,13 +355,13 @@ export interface ChangePassword {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupInvitation {
|
export interface GroupInvitation {
|
||||||
expiresAt: string;
|
expiresAt: Date | string;
|
||||||
token: string;
|
token: string;
|
||||||
uses: number;
|
uses: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupInvitationCreate {
|
export interface GroupInvitationCreate {
|
||||||
expiresAt: string;
|
expiresAt: Date | string;
|
||||||
uses: number;
|
uses: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,6 +371,6 @@ export interface ItemAttachmentToken {
|
||||||
|
|
||||||
export interface TokenResponse {
|
export interface TokenResponse {
|
||||||
attachmentToken: string;
|
attachmentToken: string;
|
||||||
expiresAt: string;
|
expiresAt: Date | string;
|
||||||
token: string;
|
token: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,15 +40,22 @@
|
||||||
|
|
||||||
// Sync Initial Currency
|
// Sync Initial Currency
|
||||||
watch(group, () => {
|
watch(group, () => {
|
||||||
if (group.value) {
|
if (!group.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error - typescript is stupid, it should know group.value is not null
|
||||||
const found = currencies.find(c => c.code === group.value.currency);
|
const found = currencies.find(c => c.code === group.value.currency);
|
||||||
if (found) {
|
if (found) {
|
||||||
currency.value = found;
|
currency.value = found;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
async function updateGroup() {
|
async function updateGroup() {
|
||||||
|
if (!group.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { data, error } = await api.group.update({
|
const { data, error } = await api.group.update({
|
||||||
name: group.value.name,
|
name: group.value.name,
|
||||||
currency: group.value.currency,
|
currency: group.value.currency,
|
||||||
|
@ -161,44 +168,6 @@
|
||||||
passwordChange.current = "";
|
passwordChange.current = "";
|
||||||
passwordChange.loading = false;
|
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.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function resetItemDateTimes() {
|
|
||||||
const { isCanceled } = await confirm.open(
|
|
||||||
"Are you sure you want to reset all date and time values? This will take a while and cannot be undone."
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isCanceled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await api.actions.resetItemDateTimes();
|
|
||||||
|
|
||||||
if (result.error) {
|
|
||||||
notify.error("Failed to reset date and time values.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
notify.success(`${result.data.completed} assets have been updated.`);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -322,46 +291,6 @@
|
||||||
</div>
|
</div>
|
||||||
</BaseCard>
|
</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 space-y-8">
|
|
||||||
<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 class="grid grid-cols-1 md:grid-cols-4 gap-10">
|
|
||||||
<div class="col-span-3">
|
|
||||||
<h4>Zero Item Date Times</h4>
|
|
||||||
<p class="text-sm">
|
|
||||||
Resets the time value for all date time fields in your inventory to the beginning of the date. This is
|
|
||||||
to fix a bug that was introduced early on in the development of the site that caused the time value to
|
|
||||||
be stored with the time which caused issues with date fields displaying accurate values.
|
|
||||||
<a class="link" href="https://github.com/hay-kot/homebox/issues/236" target="_blank">
|
|
||||||
See Github Issue #236 for more details
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<BaseButton class="btn-primary mt-auto" @click="resetItemDateTimes"> Zero Item Date Times </BaseButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</BaseCard>
|
|
||||||
|
|
||||||
<BaseCard>
|
<BaseCard>
|
||||||
<template #title>
|
<template #title>
|
||||||
<BaseSectionHeader>
|
<BaseSectionHeader>
|
||||||
|
|
118
frontend/pages/tools.vue
Normal file
118
frontend/pages/tools.vue
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<AppImportDialog v-model="modals.import" />
|
||||||
|
<BaseContainer class="flex flex-col gap-4 mb-6">
|
||||||
|
<BaseCard>
|
||||||
|
<template #title>
|
||||||
|
<BaseSectionHeader>
|
||||||
|
<Icon name="mdi-database" class="mr-2 -mt-1" />
|
||||||
|
<span> Import / Export </span>
|
||||||
|
<template #description>
|
||||||
|
Import and export your inventory to and from a CSV file. This is useful for migrating your inventory to a
|
||||||
|
new instance of Homebox.
|
||||||
|
</template>
|
||||||
|
</BaseSectionHeader>
|
||||||
|
<div class="border-t border-gray-300 divide-gray-300 divide-y">
|
||||||
|
<DetailAction @click="modals.import = true">
|
||||||
|
<template #title>Import Inventory</template>
|
||||||
|
Imports the standard CSV format for Homebox. This will <b>not</b> overwrite any existing items in your
|
||||||
|
inventory. It will only add new items.
|
||||||
|
</DetailAction>
|
||||||
|
<!-- <DetailAction>
|
||||||
|
<template #title>Export Inventory</template>
|
||||||
|
Exports the standard CSV format for Homebox. This will export all items in your inventory.
|
||||||
|
</DetailAction> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</BaseCard>
|
||||||
|
<BaseCard>
|
||||||
|
<template #title>
|
||||||
|
<BaseSectionHeader>
|
||||||
|
<Icon name="mdi-warning" class="mr-2 -mt-1" />
|
||||||
|
<span> Inventory Actions </span>
|
||||||
|
<template #description>
|
||||||
|
Apply Actions to your inventory in bulk. These are irreversible actions. <b>Be careful</b>
|
||||||
|
</template>
|
||||||
|
</BaseSectionHeader>
|
||||||
|
<div class="border-t border-gray-300 divide-gray-300 divide-y">
|
||||||
|
<DetailAction @action="ensureAssetIDs">
|
||||||
|
<template #title>Ensure Asset IDs</template>
|
||||||
|
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.
|
||||||
|
</DetailAction>
|
||||||
|
<DetailAction @click="resetItemDateTimes">
|
||||||
|
<template #title> Zero Item Date Times</template>
|
||||||
|
Resets the time value for all date time fields in your inventory to the beginning of the date. This is to
|
||||||
|
fix a bug that was introduced early on in the development of the site that caused the time value to be
|
||||||
|
stored with the time which caused issues with date fields displaying accurate values.
|
||||||
|
<a class="link" href="https://github.com/hay-kot/homebox/issues/236" target="_blank">
|
||||||
|
See Github Issue #236 for more details
|
||||||
|
</a>
|
||||||
|
</DetailAction>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</BaseCard>
|
||||||
|
</BaseContainer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
definePageMeta({
|
||||||
|
middleware: ["auth"],
|
||||||
|
});
|
||||||
|
useHead({
|
||||||
|
title: "Homebox | Profile",
|
||||||
|
});
|
||||||
|
|
||||||
|
const modals = ref({
|
||||||
|
item: false,
|
||||||
|
location: false,
|
||||||
|
label: false,
|
||||||
|
import: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const api = useUserApi();
|
||||||
|
const confirm = useConfirm();
|
||||||
|
const notify = useNotifier();
|
||||||
|
|
||||||
|
async function ensureAssetIDs() {
|
||||||
|
const { isCanceled } = await confirm.open(
|
||||||
|
"Are you sure you want to ensure all assets have an ID? This can 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.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function resetItemDateTimes() {
|
||||||
|
const { isCanceled } = await confirm.open(
|
||||||
|
"Are you sure you want to reset all date and time values? This can take a while and cannot be undone."
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isCanceled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await api.actions.resetItemDateTimes();
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
notify.error("Failed to reset date and time values.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
notify.success(`${result.data.completed} assets have been updated.`);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
|
@ -9,7 +9,7 @@ import (
|
||||||
func dateTypes(names []string) map[*regexp.Regexp]string {
|
func dateTypes(names []string) map[*regexp.Regexp]string {
|
||||||
result := make(map[*regexp.Regexp]string)
|
result := make(map[*regexp.Regexp]string)
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
result[regexp.MustCompile(fmt.Sprintf(`%s: string`, name))] = fmt.Sprintf(`%s: Date`, name)
|
result[regexp.MustCompile(fmt.Sprintf(`%s: string`, name))] = fmt.Sprintf(`%s: Date | string`, name)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue