mirror of
https://github.com/hay-kot/homebox.git
synced 2024-12-27 09:16:30 +00:00
bulk seed asset IDs
This commit is contained in:
parent
ab406baf33
commit
567e12a1e9
13 changed files with 331 additions and 1 deletions
35
backend/app/api/handlers/v1/v1_ctrl_actions.go
Normal file
35
backend/app/api/handlers/v1/v1_ctrl_actions.go
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/hay-kot/homebox/backend/internal/core/services"
|
||||||
|
"github.com/hay-kot/homebox/backend/internal/sys/validate"
|
||||||
|
"github.com/hay-kot/homebox/backend/pkgs/server"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EnsureAssetIDResult struct {
|
||||||
|
Completed int `json:"completed"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleGroupInvitationsCreate godoc
|
||||||
|
// @Summary Get the current user
|
||||||
|
// @Tags Group
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200 {object} EnsureAssetIDResult
|
||||||
|
// @Router /v1/actions/ensure-asset-ids [Post]
|
||||||
|
// @Security Bearer
|
||||||
|
func (ctrl *V1Controller) HandleEnsureAssetID() server.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
ctx := services.NewContext(r.Context())
|
||||||
|
|
||||||
|
totalCompleted, err := ctrl.svc.Items.EnsureAssetID(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, EnsureAssetIDResult{Completed: totalCompleted})
|
||||||
|
}
|
||||||
|
}
|
|
@ -82,6 +82,8 @@ func (a *app) mountRoutes(repos *repo.AllRepos) {
|
||||||
a.server.Get(v1Base("/groups"), v1Ctrl.HandleGroupGet(), a.mwAuthToken)
|
a.server.Get(v1Base("/groups"), v1Ctrl.HandleGroupGet(), a.mwAuthToken)
|
||||||
a.server.Put(v1Base("/groups"), v1Ctrl.HandleGroupUpdate(), a.mwAuthToken)
|
a.server.Put(v1Base("/groups"), v1Ctrl.HandleGroupUpdate(), a.mwAuthToken)
|
||||||
|
|
||||||
|
a.server.Post(v1Base("/actions/ensure-asset-ids"), v1Ctrl.HandleEnsureAssetID(), a.mwAuthToken)
|
||||||
|
|
||||||
a.server.Get(v1Base("/locations"), v1Ctrl.HandleLocationGetAll(), a.mwAuthToken)
|
a.server.Get(v1Base("/locations"), v1Ctrl.HandleLocationGetAll(), a.mwAuthToken)
|
||||||
a.server.Post(v1Base("/locations"), v1Ctrl.HandleLocationCreate(), a.mwAuthToken)
|
a.server.Post(v1Base("/locations"), v1Ctrl.HandleLocationCreate(), a.mwAuthToken)
|
||||||
a.server.Get(v1Base("/locations/{id}"), v1Ctrl.HandleLocationGet(), a.mwAuthToken)
|
a.server.Get(v1Base("/locations/{id}"), v1Ctrl.HandleLocationGet(), a.mwAuthToken)
|
||||||
|
|
|
@ -21,6 +21,30 @@ const docTemplate = `{
|
||||||
"host": "{{.Host}}",
|
"host": "{{.Host}}",
|
||||||
"basePath": "{{.BasePath}}",
|
"basePath": "{{.BasePath}}",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"/v1/actions/ensure-asset-ids": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Group"
|
||||||
|
],
|
||||||
|
"summary": "Get the current user",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/v1.EnsureAssetIDResult"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/v1/groups": {
|
"/v1/groups": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
|
@ -1326,6 +1350,10 @@ const docTemplate = `{
|
||||||
"archived": {
|
"archived": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"assetId": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "0"
|
||||||
|
},
|
||||||
"attachments": {
|
"attachments": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
|
@ -1479,6 +1507,9 @@ const docTemplate = `{
|
||||||
"archived": {
|
"archived": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"assetId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@ -1891,6 +1922,14 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"v1.EnsureAssetIDResult": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"completed": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v1.GroupInvitation": {
|
"v1.GroupInvitation": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
@ -13,6 +13,30 @@
|
||||||
},
|
},
|
||||||
"basePath": "/api",
|
"basePath": "/api",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"/v1/actions/ensure-asset-ids": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Group"
|
||||||
|
],
|
||||||
|
"summary": "Get the current user",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/v1.EnsureAssetIDResult"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/v1/groups": {
|
"/v1/groups": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
|
@ -1318,6 +1342,10 @@
|
||||||
"archived": {
|
"archived": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"assetId": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "0"
|
||||||
|
},
|
||||||
"attachments": {
|
"attachments": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
|
@ -1471,6 +1499,9 @@
|
||||||
"archived": {
|
"archived": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"assetId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@ -1883,6 +1914,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"v1.EnsureAssetIDResult": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"completed": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v1.GroupInvitation": {
|
"v1.GroupInvitation": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
@ -98,6 +98,9 @@ definitions:
|
||||||
properties:
|
properties:
|
||||||
archived:
|
archived:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
assetId:
|
||||||
|
example: "0"
|
||||||
|
type: string
|
||||||
attachments:
|
attachments:
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/repo.ItemAttachment'
|
$ref: '#/definitions/repo.ItemAttachment'
|
||||||
|
@ -204,6 +207,8 @@ definitions:
|
||||||
properties:
|
properties:
|
||||||
archived:
|
archived:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
assetId:
|
||||||
|
type: string
|
||||||
description:
|
description:
|
||||||
type: string
|
type: string
|
||||||
fields:
|
fields:
|
||||||
|
@ -477,6 +482,11 @@ 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:
|
||||||
|
@ -516,6 +526,20 @@ info:
|
||||||
title: Go API Templates
|
title: Go API Templates
|
||||||
version: "1.0"
|
version: "1.0"
|
||||||
paths:
|
paths:
|
||||||
|
/v1/actions/ensure-asset-ids:
|
||||||
|
post:
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/v1.EnsureAssetIDResult'
|
||||||
|
security:
|
||||||
|
- Bearer: []
|
||||||
|
summary: Get the current user
|
||||||
|
tags:
|
||||||
|
- Group
|
||||||
/v1/groups:
|
/v1/groups:
|
||||||
get:
|
get:
|
||||||
produces:
|
produces:
|
||||||
|
|
|
@ -23,6 +23,32 @@ type ItemService struct {
|
||||||
at attachmentTokens
|
at attachmentTokens
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (svc *ItemService) EnsureAssetID(ctx context.Context, GID uuid.UUID) (int, error) {
|
||||||
|
items, err := svc.repo.Items.GetAllZeroAssetID(ctx, GID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
highest, err := svc.repo.Items.GetHighestAssetID(ctx, GID)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
finished := 0
|
||||||
|
for _, item := range items {
|
||||||
|
highest++
|
||||||
|
|
||||||
|
err = svc.repo.Items.SetAssetID(ctx, GID, item.ID, repo.AssetID(highest))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
finished++
|
||||||
|
}
|
||||||
|
|
||||||
|
return finished, nil
|
||||||
|
}
|
||||||
func (svc *ItemService) CsvImport(ctx context.Context, GID uuid.UUID, data [][]string) (int, error) {
|
func (svc *ItemService) CsvImport(ctx context.Context, GID uuid.UUID, data [][]string) (int, error) {
|
||||||
loaded := []csvRow{}
|
loaded := []csvRow{}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@ package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
@ -18,6 +21,30 @@ type ItemsRepository struct {
|
||||||
db *ent.Client
|
db *ent.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AssetID int
|
||||||
|
|
||||||
|
func (aid AssetID) MarshalJSON() ([]byte, error) {
|
||||||
|
str := fmt.Sprintf("%d", aid)
|
||||||
|
|
||||||
|
for len(str) < 6 {
|
||||||
|
str = "0" + str
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte(fmt.Sprintf(`"%s"`, str)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (aid *AssetID) UnmarshalJSON(data []byte) error {
|
||||||
|
str := string(strings.Replace(string(data), `"`, "", -1))
|
||||||
|
aidInt, err := strconv.Atoi(str)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*aid = AssetID(aidInt)
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
ItemQuery struct {
|
ItemQuery struct {
|
||||||
Page int
|
Page int
|
||||||
|
@ -52,6 +79,7 @@ type (
|
||||||
ItemUpdate struct {
|
ItemUpdate struct {
|
||||||
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable,x-omitempty"`
|
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable,x-omitempty"`
|
||||||
ID uuid.UUID `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
|
AssetID AssetID `json:"assetId"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Quantity int `json:"quantity"`
|
Quantity int `json:"quantity"`
|
||||||
|
@ -107,6 +135,7 @@ type (
|
||||||
ItemOut struct {
|
ItemOut struct {
|
||||||
Parent *ItemSummary `json:"parent,omitempty" extensions:"x-nullable,x-omitempty"`
|
Parent *ItemSummary `json:"parent,omitempty" extensions:"x-nullable,x-omitempty"`
|
||||||
ItemSummary
|
ItemSummary
|
||||||
|
AssetID AssetID `json:"assetId,string"`
|
||||||
|
|
||||||
SerialNumber string `json:"serialNumber"`
|
SerialNumber string `json:"serialNumber"`
|
||||||
ModelNumber string `json:"modelNumber"`
|
ModelNumber string `json:"modelNumber"`
|
||||||
|
@ -215,6 +244,7 @@ func mapItemOut(item *ent.Item) ItemOut {
|
||||||
|
|
||||||
return ItemOut{
|
return ItemOut{
|
||||||
Parent: parent,
|
Parent: parent,
|
||||||
|
AssetID: AssetID(item.AssetID),
|
||||||
ItemSummary: mapItemSummary(item),
|
ItemSummary: mapItemSummary(item),
|
||||||
LifetimeWarranty: item.LifetimeWarranty,
|
LifetimeWarranty: item.LifetimeWarranty,
|
||||||
WarrantyExpires: item.WarrantyExpires,
|
WarrantyExpires: item.WarrantyExpires,
|
||||||
|
@ -359,6 +389,42 @@ func (e *ItemsRepository) GetAll(ctx context.Context, gid uuid.UUID) ([]ItemSumm
|
||||||
All(ctx))
|
All(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *ItemsRepository) GetAllZeroAssetID(ctx context.Context, GID uuid.UUID) ([]ItemSummary, error) {
|
||||||
|
q := e.db.Item.Query().Where(
|
||||||
|
item.HasGroupWith(group.ID(GID)),
|
||||||
|
item.AssetID(0),
|
||||||
|
).Order(
|
||||||
|
ent.Asc(item.FieldCreatedAt),
|
||||||
|
)
|
||||||
|
|
||||||
|
return mapItemsSummaryErr(q.All(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *ItemsRepository) GetHighestAssetID(ctx context.Context, GID uuid.UUID) (AssetID, error) {
|
||||||
|
q := e.db.Item.Query().Where(
|
||||||
|
item.HasGroupWith(group.ID(GID)),
|
||||||
|
).Order(
|
||||||
|
ent.Desc(item.FieldAssetID),
|
||||||
|
).Limit(1)
|
||||||
|
|
||||||
|
result, err := q.First(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return AssetID(result.AssetID), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *ItemsRepository) SetAssetID(ctx context.Context, GID uuid.UUID, ID uuid.UUID, assetID AssetID) error {
|
||||||
|
q := e.db.Item.Update().Where(
|
||||||
|
item.HasGroupWith(group.ID(GID)),
|
||||||
|
item.ID(ID),
|
||||||
|
)
|
||||||
|
|
||||||
|
_, err := q.SetAssetID(int(assetID)).Save(ctx)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (e *ItemsRepository) Create(ctx context.Context, gid uuid.UUID, data ItemCreate) (ItemOut, error) {
|
func (e *ItemsRepository) Create(ctx context.Context, gid uuid.UUID, data ItemCreate) (ItemOut, error) {
|
||||||
q := e.db.Item.Create().
|
q := e.db.Item.Create().
|
||||||
SetImportRef(data.ImportRef).
|
SetImportRef(data.ImportRef).
|
||||||
|
@ -414,7 +480,8 @@ func (e *ItemsRepository) UpdateByGroup(ctx context.Context, gid uuid.UUID, data
|
||||||
SetInsured(data.Insured).
|
SetInsured(data.Insured).
|
||||||
SetWarrantyExpires(data.WarrantyExpires).
|
SetWarrantyExpires(data.WarrantyExpires).
|
||||||
SetWarrantyDetails(data.WarrantyDetails).
|
SetWarrantyDetails(data.WarrantyDetails).
|
||||||
SetQuantity(data.Quantity)
|
SetQuantity(data.Quantity).
|
||||||
|
SetAssetID(int(data.AssetID))
|
||||||
|
|
||||||
currentLabels, err := e.db.Item.Query().Where(item.ID(data.ID)).QueryLabel().All(ctx)
|
currentLabels, err := e.db.Item.Query().Where(item.ID(data.ID)).QueryLabel().All(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -9,6 +10,33 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestAssetID_UnmarshalJSON(t *testing.T) {
|
||||||
|
rawjson := `{"aid":"000123"}`
|
||||||
|
|
||||||
|
st := struct {
|
||||||
|
AID AssetID `json:"aid"`
|
||||||
|
}{
|
||||||
|
AID: AssetID(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal([]byte(rawjson), &st)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, AssetID(123), st.AID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAssetID_MarshalJSON(t *testing.T) {
|
||||||
|
st := struct {
|
||||||
|
AID AssetID `json:"aid"`
|
||||||
|
}{
|
||||||
|
AID: AssetID(123),
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(st)
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.JSONEq(t, `{"aid":"000123"}`, string(b))
|
||||||
|
}
|
||||||
|
|
||||||
func itemFactory() ItemCreate {
|
func itemFactory() ItemCreate {
|
||||||
return ItemCreate{
|
return ItemCreate{
|
||||||
Name: fk.Str(10),
|
Name: fk.Str(10),
|
||||||
|
|
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 {
|
export interface ItemOut {
|
||||||
archived: boolean;
|
archived: boolean;
|
||||||
|
|
||||||
|
/** @example 0 */
|
||||||
|
assetId: string;
|
||||||
attachments: ItemAttachment[];
|
attachments: ItemAttachment[];
|
||||||
children: ItemSummary[];
|
children: ItemSummary[];
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
|
@ -131,6 +134,7 @@ export interface ItemSummary {
|
||||||
|
|
||||||
export interface ItemUpdate {
|
export interface ItemUpdate {
|
||||||
archived: boolean;
|
archived: boolean;
|
||||||
|
assetId: string;
|
||||||
description: string;
|
description: string;
|
||||||
fields: ItemField[];
|
fields: ItemField[];
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -300,6 +304,10 @@ export interface ChangePassword {
|
||||||
new: string;
|
new: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface EnsureAssetIDResult {
|
||||||
|
completed: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface GroupInvitation {
|
export interface GroupInvitation {
|
||||||
expiresAt: Date;
|
expiresAt: Date;
|
||||||
token: string;
|
token: string;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { LabelsApi } from "./classes/labels";
|
||||||
import { LocationsApi } from "./classes/locations";
|
import { LocationsApi } from "./classes/locations";
|
||||||
import { GroupApi } from "./classes/group";
|
import { GroupApi } from "./classes/group";
|
||||||
import { UserApi } from "./classes/users";
|
import { UserApi } from "./classes/users";
|
||||||
|
import { ActionsAPI } from "./classes/actions";
|
||||||
import { Requests } from "~~/lib/requests";
|
import { Requests } from "~~/lib/requests";
|
||||||
|
|
||||||
export class UserClient extends BaseAPI {
|
export class UserClient extends BaseAPI {
|
||||||
|
@ -12,6 +13,7 @@ export class UserClient extends BaseAPI {
|
||||||
items: ItemsApi;
|
items: ItemsApi;
|
||||||
group: GroupApi;
|
group: GroupApi;
|
||||||
user: UserApi;
|
user: UserApi;
|
||||||
|
actions: ActionsAPI;
|
||||||
|
|
||||||
constructor(requests: Requests) {
|
constructor(requests: Requests) {
|
||||||
super(requests);
|
super(requests);
|
||||||
|
@ -21,6 +23,7 @@ export class UserClient extends BaseAPI {
|
||||||
this.items = new ItemsApi(requests);
|
this.items = new ItemsApi(requests);
|
||||||
this.group = new GroupApi(requests);
|
this.group = new GroupApi(requests);
|
||||||
this.user = new UserApi(requests);
|
this.user = new UserApi(requests);
|
||||||
|
this.actions = new ActionsAPI(requests);
|
||||||
|
|
||||||
Object.freeze(this);
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,10 @@
|
||||||
name: "Notes",
|
name: "Notes",
|
||||||
text: item.value?.notes,
|
text: item.value?.notes,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Asset ID",
|
||||||
|
text: item.value?.assetId,
|
||||||
|
},
|
||||||
...item.value.fields.map(field => {
|
...item.value.fields.map(field => {
|
||||||
/**
|
/**
|
||||||
* Support Special URL Syntax
|
* Support Special URL Syntax
|
||||||
|
|
|
@ -163,6 +163,25 @@
|
||||||
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.`);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -286,6 +305,32 @@
|
||||||
</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">
|
||||||
|
<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>
|
<BaseCard>
|
||||||
<template #title>
|
<template #title>
|
||||||
<BaseSectionHeader>
|
<BaseSectionHeader>
|
||||||
|
|
Loading…
Reference in a new issue