forked from mirrors/homebox
fix: add custom action for fixing broken date/times (#268)
This commit is contained in:
parent
bd933af874
commit
ce2fc7712a
11 changed files with 240 additions and 59 deletions
|
@ -9,15 +9,15 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EnsureAssetIDResult struct {
|
type ActionAmountResult struct {
|
||||||
Completed int `json:"completed"`
|
Completed int `json:"completed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleGroupInvitationsCreate godoc
|
// HandleGroupInvitationsCreate godoc
|
||||||
// @Summary Get the current user
|
// @Summary Ensures all items in the database have an asset id
|
||||||
// @Tags Group
|
// @Tags Group
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} EnsureAssetIDResult
|
// @Success 200 {object} ActionAmountResult
|
||||||
// @Router /v1/actions/ensure-asset-ids [Post]
|
// @Router /v1/actions/ensure-asset-ids [Post]
|
||||||
// @Security Bearer
|
// @Security Bearer
|
||||||
func (ctrl *V1Controller) HandleEnsureAssetID() server.HandlerFunc {
|
func (ctrl *V1Controller) HandleEnsureAssetID() server.HandlerFunc {
|
||||||
|
@ -30,6 +30,27 @@ func (ctrl *V1Controller) HandleEnsureAssetID() server.HandlerFunc {
|
||||||
return validate.NewRequestError(err, http.StatusInternalServerError)
|
return validate.NewRequestError(err, http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
return server.Respond(w, http.StatusOK, EnsureAssetIDResult{Completed: totalCompleted})
|
return server.Respond(w, http.StatusOK, ActionAmountResult{Completed: totalCompleted})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleItemDateZeroOut godoc
|
||||||
|
// @Summary Resets all item date fields to the beginning of the day
|
||||||
|
// @Tags Group
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200 {object} ActionAmountResult
|
||||||
|
// @Router /v1/actions/zero-item-time-fields [Post]
|
||||||
|
// @Security Bearer
|
||||||
|
func (ctrl *V1Controller) HandleItemDateZeroOut() server.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
ctx := services.NewContext(r.Context())
|
||||||
|
|
||||||
|
totalCompleted, err := ctrl.repo.Items.ZeroOutTimeFields(ctx, ctx.GID)
|
||||||
|
if err != nil {
|
||||||
|
log.Err(err).Msg("failed to ensure asset id")
|
||||||
|
return validate.NewRequestError(err, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
return server.Respond(w, http.StatusOK, ActionAmountResult{Completed: totalCompleted})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,7 @@ func (a *app) mountRoutes(repos *repo.AllRepos) {
|
||||||
a.server.Put(v1Base("/groups"), v1Ctrl.HandleGroupUpdate(), userMW...)
|
a.server.Put(v1Base("/groups"), v1Ctrl.HandleGroupUpdate(), userMW...)
|
||||||
|
|
||||||
a.server.Post(v1Base("/actions/ensure-asset-ids"), v1Ctrl.HandleEnsureAssetID(), userMW...)
|
a.server.Post(v1Base("/actions/ensure-asset-ids"), v1Ctrl.HandleEnsureAssetID(), userMW...)
|
||||||
|
a.server.Post(v1Base("/actions/zero-item-time-fields"), v1Ctrl.HandleItemDateZeroOut(), userMW...)
|
||||||
|
|
||||||
a.server.Get(v1Base("/locations"), v1Ctrl.HandleLocationGetAll(), userMW...)
|
a.server.Get(v1Base("/locations"), v1Ctrl.HandleLocationGetAll(), userMW...)
|
||||||
a.server.Post(v1Base("/locations"), v1Ctrl.HandleLocationCreate(), userMW...)
|
a.server.Post(v1Base("/locations"), v1Ctrl.HandleLocationCreate(), userMW...)
|
||||||
|
|
|
@ -34,12 +34,36 @@ const docTemplate = `{
|
||||||
"tags": [
|
"tags": [
|
||||||
"Group"
|
"Group"
|
||||||
],
|
],
|
||||||
"summary": "Get the current user",
|
"summary": "Ensures all items in the database have an asset id",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/v1.EnsureAssetIDResult"
|
"$ref": "#/definitions/v1.ActionAmountResult"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/v1/actions/zero-item-time-fields": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Group"
|
||||||
|
],
|
||||||
|
"summary": "Resets all item date fields to the beginning of the day",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/v1.ActionAmountResult"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2365,6 +2389,14 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"v1.ActionAmountResult": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"completed": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v1.ApiSummary": {
|
"v1.ApiSummary": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -2416,14 +2448,6 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"v1.EnsureAssetIDResult": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"completed": {
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"v1.GroupInvitation": {
|
"v1.GroupInvitation": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
@ -26,12 +26,36 @@
|
||||||
"tags": [
|
"tags": [
|
||||||
"Group"
|
"Group"
|
||||||
],
|
],
|
||||||
"summary": "Get the current user",
|
"summary": "Ensures all items in the database have an asset id",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/v1.EnsureAssetIDResult"
|
"$ref": "#/definitions/v1.ActionAmountResult"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/v1/actions/zero-item-time-fields": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Group"
|
||||||
|
],
|
||||||
|
"summary": "Resets all item date fields to the beginning of the day",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/v1.ActionAmountResult"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2357,6 +2381,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"v1.ActionAmountResult": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"completed": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v1.ApiSummary": {
|
"v1.ApiSummary": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -2408,14 +2440,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"v1.EnsureAssetIDResult": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"completed": {
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"v1.GroupInvitation": {
|
"v1.GroupInvitation": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
@ -556,6 +556,11 @@ definitions:
|
||||||
token:
|
token:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
v1.ActionAmountResult:
|
||||||
|
properties:
|
||||||
|
completed:
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
v1.ApiSummary:
|
v1.ApiSummary:
|
||||||
properties:
|
properties:
|
||||||
build:
|
build:
|
||||||
|
@ -589,11 +594,6 @@ definitions:
|
||||||
new:
|
new:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
v1.EnsureAssetIDResult:
|
|
||||||
properties:
|
|
||||||
completed:
|
|
||||||
type: integer
|
|
||||||
type: object
|
|
||||||
v1.GroupInvitation:
|
v1.GroupInvitation:
|
||||||
properties:
|
properties:
|
||||||
expiresAt:
|
expiresAt:
|
||||||
|
@ -643,10 +643,24 @@ paths:
|
||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/v1.EnsureAssetIDResult'
|
$ref: '#/definitions/v1.ActionAmountResult'
|
||||||
security:
|
security:
|
||||||
- Bearer: []
|
- Bearer: []
|
||||||
summary: Get the current user
|
summary: Ensures all items in the database have an asset id
|
||||||
|
tags:
|
||||||
|
- Group
|
||||||
|
/v1/actions/zero-item-time-fields:
|
||||||
|
post:
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/v1.ActionAmountResult'
|
||||||
|
security:
|
||||||
|
- Bearer: []
|
||||||
|
summary: Resets all item date fields to the beginning of the day
|
||||||
tags:
|
tags:
|
||||||
- Group
|
- Group
|
||||||
/v1/assets/{id}:
|
/v1/assets/{id}:
|
||||||
|
|
|
@ -673,3 +673,56 @@ func (e *ItemsRepository) GetAllCustomFieldNames(ctx context.Context, GID uuid.U
|
||||||
|
|
||||||
return fieldNames, nil
|
return fieldNames, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ZeroOutTimeFields is a helper function that can be invoked via the UI by a group member which will
|
||||||
|
// set all date fields to the beginning of the day.
|
||||||
|
//
|
||||||
|
// This is designed to resolve a long-time bug that has since been fixed with the time selector on the
|
||||||
|
// frontend. This function is intended to be used as a one-time fix for existing databases and may be
|
||||||
|
// removed in the future.
|
||||||
|
func (e *ItemsRepository) ZeroOutTimeFields(ctx context.Context, GID uuid.UUID) (int, error) {
|
||||||
|
q := e.db.Item.Query().Where(
|
||||||
|
item.HasGroupWith(group.ID(GID)),
|
||||||
|
item.Or(
|
||||||
|
item.PurchaseTimeNotNil(),
|
||||||
|
item.SoldTimeNotNil(),
|
||||||
|
item.WarrantyExpiresNotNil(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
items, err := q.All(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return -1, fmt.Errorf("ZeroOutTimeFields() -> failed to get items: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
toDateOnly := func(t time.Time) time.Time {
|
||||||
|
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
|
||||||
|
}
|
||||||
|
|
||||||
|
updated := 0
|
||||||
|
|
||||||
|
for _, i := range items {
|
||||||
|
updateQ := e.db.Item.Update().Where(item.ID(i.ID))
|
||||||
|
|
||||||
|
if !i.PurchaseTime.IsZero() {
|
||||||
|
updateQ.SetPurchaseTime(toDateOnly(i.PurchaseTime))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !i.SoldTime.IsZero() {
|
||||||
|
updateQ.SetSoldTime(toDateOnly(i.SoldTime))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !i.WarrantyExpires.IsZero() {
|
||||||
|
updateQ.SetWarrantyExpires(toDateOnly(i.WarrantyExpires))
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = updateQ.Save(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return updated, fmt.Errorf("ZeroOutTimeFields() -> failed to update item: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
updated++
|
||||||
|
}
|
||||||
|
|
||||||
|
return updated, nil
|
||||||
|
}
|
||||||
|
|
|
@ -5,3 +5,4 @@
|
||||||
.btn {
|
.btn {
|
||||||
text-transform: none !important;
|
text-transform: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,11 @@
|
||||||
const selected = computed({
|
const selected = computed({
|
||||||
get() {
|
get() {
|
||||||
// return modelValue as string as YYYY-MM-DD or null
|
// return modelValue as string as YYYY-MM-DD or null
|
||||||
return props.modelValue ? props.modelValue.toISOString().split("T")[0] : null;
|
if (validDate(props.modelValue)) {
|
||||||
|
return props.modelValue ? props.modelValue.toISOString().split("T")[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
},
|
},
|
||||||
set(value: string | null) {
|
set(value: string | null) {
|
||||||
// emit update:modelValue with a Date object or null
|
// emit update:modelValue with a Date object or null
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
import { BaseAPI, route } from "../base";
|
import { BaseAPI, route } from "../base";
|
||||||
import { EnsureAssetIDResult } from "../types/data-contracts";
|
import { ActionAmountResult } from "../types/data-contracts";
|
||||||
|
|
||||||
export class ActionsAPI extends BaseAPI {
|
export class ActionsAPI extends BaseAPI {
|
||||||
ensureAssetIDs() {
|
ensureAssetIDs() {
|
||||||
return this.http.post<void, EnsureAssetIDResult>({
|
return this.http.post<void, ActionAmountResult>({
|
||||||
url: route("/actions/ensure-asset-ids"),
|
url: route("/actions/ensure-asset-ids"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetItemDateTimes() {
|
||||||
|
return this.http.post<void, ActionAmountResult>({
|
||||||
|
url: route("/actions/zero-item-time-fields"),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ export interface DocumentOut {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Group {
|
export interface Group {
|
||||||
createdAt: string;
|
createdAt: Date;
|
||||||
currency: string;
|
currency: string;
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -39,7 +39,7 @@ export interface GroupUpdate {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ItemAttachment {
|
export interface ItemAttachment {
|
||||||
createdAt: string;
|
createdAt: Date;
|
||||||
document: DocumentOut;
|
document: DocumentOut;
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
type: string;
|
||||||
|
@ -76,7 +76,7 @@ export interface ItemOut {
|
||||||
assetId: string;
|
assetId: string;
|
||||||
attachments: ItemAttachment[];
|
attachments: ItemAttachment[];
|
||||||
children: ItemSummary[];
|
children: ItemSummary[];
|
||||||
createdAt: string;
|
createdAt: Date;
|
||||||
description: string;
|
description: string;
|
||||||
fields: ItemField[];
|
fields: ItemField[];
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -96,7 +96,7 @@ export interface ItemOut {
|
||||||
/** @example "0" */
|
/** @example "0" */
|
||||||
purchasePrice: string;
|
purchasePrice: string;
|
||||||
/** Purchase */
|
/** Purchase */
|
||||||
purchaseTime: Date;
|
purchaseTime: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
serialNumber: string;
|
serialNumber: string;
|
||||||
soldNotes: string;
|
soldNotes: string;
|
||||||
|
@ -112,7 +112,7 @@ export interface ItemOut {
|
||||||
|
|
||||||
export interface ItemSummary {
|
export interface ItemSummary {
|
||||||
archived: boolean;
|
archived: boolean;
|
||||||
createdAt: string;
|
createdAt: Date;
|
||||||
description: string;
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
insured: boolean;
|
insured: boolean;
|
||||||
|
@ -148,7 +148,7 @@ export interface ItemUpdate {
|
||||||
/** @example "0" */
|
/** @example "0" */
|
||||||
purchasePrice: string;
|
purchasePrice: string;
|
||||||
/** Purchase */
|
/** Purchase */
|
||||||
purchaseTime: Date;
|
purchaseTime: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
/** Identifications */
|
/** Identifications */
|
||||||
serialNumber: string;
|
serialNumber: string;
|
||||||
|
@ -169,7 +169,7 @@ export interface LabelCreate {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LabelOut {
|
export interface LabelOut {
|
||||||
createdAt: string;
|
createdAt: Date;
|
||||||
description: string;
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
items: ItemSummary[];
|
items: ItemSummary[];
|
||||||
|
@ -178,7 +178,7 @@ export interface LabelOut {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LabelSummary {
|
export interface LabelSummary {
|
||||||
createdAt: string;
|
createdAt: Date;
|
||||||
description: string;
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -193,7 +193,7 @@ export interface LocationCreate {
|
||||||
|
|
||||||
export interface LocationOut {
|
export interface LocationOut {
|
||||||
children: LocationSummary[];
|
children: LocationSummary[];
|
||||||
createdAt: string;
|
createdAt: Date;
|
||||||
description: string;
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
items: ItemSummary[];
|
items: ItemSummary[];
|
||||||
|
@ -203,7 +203,7 @@ export interface LocationOut {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LocationOutCount {
|
export interface LocationOutCount {
|
||||||
createdAt: string;
|
createdAt: Date;
|
||||||
description: string;
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
itemCount: number;
|
itemCount: number;
|
||||||
|
@ -212,7 +212,7 @@ export interface LocationOutCount {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LocationSummary {
|
export interface LocationSummary {
|
||||||
createdAt: string;
|
createdAt: Date;
|
||||||
description: string;
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -229,7 +229,7 @@ export interface LocationUpdate {
|
||||||
export interface MaintenanceEntry {
|
export interface MaintenanceEntry {
|
||||||
/** @example "0" */
|
/** @example "0" */
|
||||||
cost: string;
|
cost: string;
|
||||||
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: 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: 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: string;
|
||||||
name: string;
|
name: string;
|
||||||
value: number;
|
value: number;
|
||||||
}
|
}
|
||||||
|
@ -330,6 +330,10 @@ export interface UserRegistration {
|
||||||
token: string;
|
token: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ActionAmountResult {
|
||||||
|
completed: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ApiSummary {
|
export interface ApiSummary {
|
||||||
build: Build;
|
build: Build;
|
||||||
demo: boolean;
|
demo: boolean;
|
||||||
|
@ -350,18 +354,14 @@ export interface ChangePassword {
|
||||||
new: string;
|
new: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EnsureAssetIDResult {
|
|
||||||
completed: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GroupInvitation {
|
export interface GroupInvitation {
|
||||||
expiresAt: Date;
|
expiresAt: string;
|
||||||
token: string;
|
token: string;
|
||||||
uses: number;
|
uses: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupInvitationCreate {
|
export interface GroupInvitationCreate {
|
||||||
expiresAt: Date;
|
expiresAt: string;
|
||||||
uses: number;
|
uses: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,6 +371,6 @@ export interface ItemAttachmentToken {
|
||||||
|
|
||||||
export interface TokenResponse {
|
export interface TokenResponse {
|
||||||
attachmentToken: string;
|
attachmentToken: string;
|
||||||
expiresAt: Date;
|
expiresAt: string;
|
||||||
token: string;
|
token: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,6 +180,25 @@
|
||||||
|
|
||||||
notify.success(`${result.data.completed} assets have been updated.`);
|
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>
|
||||||
|
@ -313,7 +332,7 @@
|
||||||
</template>
|
</template>
|
||||||
</BaseSectionHeader>
|
</BaseSectionHeader>
|
||||||
|
|
||||||
<div class="py-4 border-t-2 border-gray-300">
|
<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="grid grid-cols-1 md:grid-cols-4 gap-10">
|
||||||
<div class="col-span-3">
|
<div class="col-span-3">
|
||||||
<h4>Manage Asset IDs</h4>
|
<h4>Manage Asset IDs</h4>
|
||||||
|
@ -325,6 +344,20 @@
|
||||||
</div>
|
</div>
|
||||||
<BaseButton class="btn-primary mt-auto" @click="ensureAssetIDs"> Ensure Asset IDs </BaseButton>
|
<BaseButton class="btn-primary mt-auto" @click="ensureAssetIDs"> Ensure Asset IDs </BaseButton>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
|
|
Loading…
Reference in a new issue