mirror of
https://github.com/hay-kot/homebox.git
synced 2025-08-04 08:40:28 +00:00
suggested changes from PR
This commit is contained in:
parent
82a63d1ed3
commit
3f3f7d5e77
12 changed files with 162 additions and 86 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -47,5 +47,5 @@ node_modules
|
||||||
dist
|
dist
|
||||||
|
|
||||||
.pnpm-store
|
.pnpm-store
|
||||||
devData
|
backend/app/api/app
|
||||||
backend/app/api/app
|
backend/app/api/__debug_bin
|
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
@ -12,7 +12,7 @@
|
||||||
"debughandlers"
|
"debughandlers"
|
||||||
],
|
],
|
||||||
// use ESLint to format code on save
|
// use ESLint to format code on save
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": false,
|
||||||
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
|
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": true
|
"source.fixAll.eslint": true
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
package assetIds
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
|
||||||
"github.com/hay-kot/homebox/backend/internal/data/repo"
|
|
||||||
"github.com/hay-kot/homebox/backend/pkgs/server"
|
|
||||||
)
|
|
||||||
|
|
||||||
func HandleAssetRedirect(repos *repo.AllRepos) server.HandlerFunc {
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) error {
|
|
||||||
// Get the asset ID from the URL
|
|
||||||
assetIdParam := chi.URLParam(r, "id")
|
|
||||||
assetIdParam = strings.ReplaceAll(assetIdParam, "-", "") // Remove dashes
|
|
||||||
// Convert the asset ID to an int64
|
|
||||||
assetId, err := strconv.ParseInt(assetIdParam, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the asset from the database
|
|
||||||
itemIds, err := repos.Items.GetIDsByAssetID(r.Context(), repo.AssetID(assetId));
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// check if we got more than one item
|
|
||||||
if len(itemIds) > 1 {
|
|
||||||
log.Err(err).Msg("More than one item found for asset ID")
|
|
||||||
return server.Respond(w, http.StatusInternalServerError, "More than one item found for asset ID")
|
|
||||||
}
|
|
||||||
// check if we got any items
|
|
||||||
if len(itemIds) == 0 {
|
|
||||||
log.Err(err).Msg("No items found for asset ID")
|
|
||||||
return server.Respond(w, http.StatusNotFound, "No items found for asset ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
http.Redirect(w, r, "/item/" + itemIds[0].String(), http.StatusSeeOther)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
61
backend/app/api/handlers/v1/v1_ctrl_assets.go
Normal file
61
backend/app/api/handlers/v1/v1_ctrl_assets.go
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/hay-kot/homebox/backend/internal/core/services"
|
||||||
|
"github.com/hay-kot/homebox/backend/internal/data/repo"
|
||||||
|
"github.com/hay-kot/homebox/backend/internal/sys/validate"
|
||||||
|
"github.com/hay-kot/homebox/backend/pkgs/server"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandleItemGet godocs
|
||||||
|
// @Summary Gets an item by Asset ID
|
||||||
|
// @Tags Assets
|
||||||
|
// @Produce json
|
||||||
|
// @Param id path string true "Asset ID"
|
||||||
|
// @Success 200 {object} repo.PaginationResult[repo.ItemSummary]{}
|
||||||
|
// @Router /v1/assets/{id} [GET]
|
||||||
|
// @Security Bearer
|
||||||
|
func (ctrl *V1Controller) HandleAssetGet() server.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
ctx := services.NewContext(r.Context())
|
||||||
|
assetIdParam := chi.URLParam(r, "id")
|
||||||
|
assetIdParam = strings.ReplaceAll(assetIdParam, "-", "") // Remove dashes
|
||||||
|
// Convert the asset ID to an int64
|
||||||
|
assetId, err := strconv.ParseInt(assetIdParam, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pageParam := r.URL.Query().Get("page")
|
||||||
|
var page int64 = -1
|
||||||
|
if pageParam != "" {
|
||||||
|
page, err = strconv.ParseInt(pageParam, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return server.Respond(w, http.StatusBadRequest, "Invalid page number")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pageSizeParam := r.URL.Query().Get("pageSize")
|
||||||
|
var pageSize int64 = -1
|
||||||
|
if pageSizeParam != "" {
|
||||||
|
pageSize, err = strconv.ParseInt(pageSizeParam, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return server.Respond(w, http.StatusBadRequest, "Invalid page size")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
items, err := ctrl.repo.Items.QueryByAssetID(r.Context(), ctx.GID, repo.AssetID(assetId), int(page), int(pageSize))
|
||||||
|
if err != nil {
|
||||||
|
log.Err(err).Msg("failed to get item")
|
||||||
|
return validate.NewRequestError(err, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
return server.Respond(w, http.StatusOK, items)
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/hay-kot/homebox/backend/app/api/handlers/assetIds"
|
|
||||||
"github.com/hay-kot/homebox/backend/app/api/handlers/debughandlers"
|
"github.com/hay-kot/homebox/backend/app/api/handlers/debughandlers"
|
||||||
v1 "github.com/hay-kot/homebox/backend/app/api/handlers/v1"
|
v1 "github.com/hay-kot/homebox/backend/app/api/handlers/v1"
|
||||||
_ "github.com/hay-kot/homebox/backend/app/api/static/docs"
|
_ "github.com/hay-kot/homebox/backend/app/api/static/docs"
|
||||||
|
@ -118,14 +117,14 @@ func (a *app) mountRoutes(repos *repo.AllRepos) {
|
||||||
a.server.Put(v1Base("/items/{id}/maintenance/{entry_id}"), v1Ctrl.HandleMaintenanceEntryUpdate(), userMW...)
|
a.server.Put(v1Base("/items/{id}/maintenance/{entry_id}"), v1Ctrl.HandleMaintenanceEntryUpdate(), userMW...)
|
||||||
a.server.Delete(v1Base("/items/{id}/maintenance/{entry_id}"), v1Ctrl.HandleMaintenanceEntryDelete(), userMW...)
|
a.server.Delete(v1Base("/items/{id}/maintenance/{entry_id}"), v1Ctrl.HandleMaintenanceEntryDelete(), userMW...)
|
||||||
|
|
||||||
|
a.server.Get(v1Base("/asset/{id}"), v1Ctrl.HandleAssetGet(), userMW...)
|
||||||
|
|
||||||
a.server.Get(
|
a.server.Get(
|
||||||
v1Base("/items/{id}/attachments/{attachment_id}"),
|
v1Base("/items/{id}/attachments/{attachment_id}"),
|
||||||
v1Ctrl.HandleItemAttachmentGet(),
|
v1Ctrl.HandleItemAttachmentGet(),
|
||||||
a.mwAuthToken, a.mwRoles(RoleModeOr, authroles.RoleUser.String(), authroles.RoleAttachments.String()),
|
a.mwAuthToken, a.mwRoles(RoleModeOr, authroles.RoleUser.String(), authroles.RoleAttachments.String()),
|
||||||
)
|
)
|
||||||
|
|
||||||
a.server.Get("/a/{id}", assetIds.HandleAssetRedirect(a.repos))
|
|
||||||
|
|
||||||
a.server.NotFound(notFoundHandler())
|
a.server.NotFound(notFoundHandler())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,11 +72,13 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
|
||||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||||
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
|
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
@ -88,6 +90,8 @@ github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=
|
github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=
|
||||||
github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
|
github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
|
||||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||||
|
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
||||||
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
|
|
@ -283,10 +283,6 @@ func (e *ItemsRepository) GetOneByGroup(ctx context.Context, gid, id uuid.UUID)
|
||||||
return e.getOne(ctx, item.ID(id), item.HasGroupWith(group.ID(gid)))
|
return e.getOne(ctx, item.ID(id), item.HasGroupWith(group.ID(gid)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ItemsRepository) GetIDsByAssetID(ctx context.Context, assetID AssetID) ([]uuid.UUID, error) {
|
|
||||||
return e.db.Item.Query().Where(item.AssetID(int(assetID))).Order(ent.Desc(item.FieldCreatedAt)).IDs(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// QueryByGroup returns a list of items that belong to a specific group based on the provided query.
|
// QueryByGroup returns a list of items that belong to a specific group based on the provided query.
|
||||||
func (e *ItemsRepository) QueryByGroup(ctx context.Context, gid uuid.UUID, q ItemQuery) (PaginationResult[ItemSummary], error) {
|
func (e *ItemsRepository) QueryByGroup(ctx context.Context, gid uuid.UUID, q ItemQuery) (PaginationResult[ItemSummary], error) {
|
||||||
qb := e.db.Item.Query().Where(
|
qb := e.db.Item.Query().Where(
|
||||||
|
@ -360,6 +356,41 @@ func (e *ItemsRepository) QueryByGroup(ctx context.Context, gid uuid.UUID, q Ite
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// QueryByAssetID returns items by asset ID. If the item does not exist, an error is returned.
|
||||||
|
func (e *ItemsRepository) QueryByAssetID(ctx context.Context, gid uuid.UUID, assetID AssetID, page int, pageSize int) (PaginationResult[ItemSummary], error) {
|
||||||
|
qb := e.db.Item.Query().Where(
|
||||||
|
item.HasGroupWith(group.ID(gid)),
|
||||||
|
item.AssetID(int(assetID)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if page != -1 || pageSize != -1 {
|
||||||
|
qb.Offset(calculateOffset(page, pageSize)).
|
||||||
|
Limit(pageSize)
|
||||||
|
} else {
|
||||||
|
page = -1
|
||||||
|
pageSize = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
items, err := mapItemsSummaryErr(
|
||||||
|
qb.Order(ent.Asc(item.FieldName)).
|
||||||
|
WithLabel().
|
||||||
|
WithLocation().
|
||||||
|
All(ctx),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return PaginationResult[ItemSummary]{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return PaginationResult[ItemSummary]{
|
||||||
|
Page: page,
|
||||||
|
PageSize: pageSize,
|
||||||
|
Total: len(items),
|
||||||
|
Items: items,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetAll returns all the items in the database with the Labels and Locations eager loaded.
|
// GetAll returns all the items in the database with the Labels and Locations eager loaded.
|
||||||
func (e *ItemsRepository) GetAll(ctx context.Context, gid uuid.UUID) ([]ItemSummary, error) {
|
func (e *ItemsRepository) GetAll(ctx context.Context, gid uuid.UUID) ([]ItemSummary, error) {
|
||||||
return mapItemsSummaryErr(e.db.Item.Query().
|
return mapItemsSummaryErr(e.db.Item.Query().
|
||||||
|
|
|
@ -107,36 +107,6 @@ func TestItemsRepository_GetAll(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestItemsRepository_GetIDsByAssetID(t *testing.T) {
|
|
||||||
useItems(t, 4)
|
|
||||||
|
|
||||||
items, err := tRepos.Items.GetIDsByAssetID(context.Background(), 0)
|
|
||||||
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, 4, len(items), "Two items are returned when there are many with the same asset Id")
|
|
||||||
|
|
||||||
item1 := useItems(t, 1)[0]
|
|
||||||
|
|
||||||
item1Update := ItemUpdate{
|
|
||||||
ID: item1.ID,
|
|
||||||
AssetID: 1,
|
|
||||||
Name: "note-important",
|
|
||||||
Description: "This is a note",
|
|
||||||
LocationID: item1.Location.ID,
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = tRepos.Items.UpdateByGroup(context.Background(), tGroup.ID, item1Update)
|
|
||||||
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
items, err = tRepos.Items.GetIDsByAssetID(context.Background(), 1)
|
|
||||||
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, 1, len(items), "One item is returned when there is only one with the same asset Id")
|
|
||||||
assert.Equal(t, item1.ID, items[0], "The item returned is the one with the same asset Id")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func TestItemsRepository_Create(t *testing.T) {
|
func TestItemsRepository_Create(t *testing.T) {
|
||||||
location, err := tRepos.Locations.Create(context.Background(), tGroup.ID, locationFactory())
|
location, err := tRepos.Locations.Create(context.Background(), tGroup.ID, locationFactory())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
11
frontend/lib/api/classes/assets.ts
Normal file
11
frontend/lib/api/classes/assets.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { BaseAPI, route } from "../base";
|
||||||
|
import { ItemSummary } from "../types/data-contracts";
|
||||||
|
import { PaginationResult } from "../types/non-generated";
|
||||||
|
|
||||||
|
export class AssetsApi extends BaseAPI {
|
||||||
|
async get(id: string, page = 1, pageSize = 50) {
|
||||||
|
return await this.http.get<PaginationResult<ItemSummary>>({
|
||||||
|
url: route(`/asset/${id}`, { page, pageSize }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -76,7 +76,7 @@ export class ItemsApi extends BaseAPI {
|
||||||
attachments: AttachmentsAPI;
|
attachments: AttachmentsAPI;
|
||||||
maintenance: MaintenanceAPI;
|
maintenance: MaintenanceAPI;
|
||||||
|
|
||||||
constructor(http: Requests, token: string) {
|
constructor(http: Requests, token = "") {
|
||||||
super(http, token);
|
super(http, token);
|
||||||
this.attachments = new AttachmentsAPI(http);
|
this.attachments = new AttachmentsAPI(http);
|
||||||
this.maintenance = new MaintenanceAPI(http);
|
this.maintenance = new MaintenanceAPI(http);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { GroupApi } from "./classes/group";
|
||||||
import { UserApi } from "./classes/users";
|
import { UserApi } from "./classes/users";
|
||||||
import { ActionsAPI } from "./classes/actions";
|
import { ActionsAPI } from "./classes/actions";
|
||||||
import { StatsAPI } from "./classes/stats";
|
import { StatsAPI } from "./classes/stats";
|
||||||
|
import { AssetsApi } from "./classes/assets";
|
||||||
import { Requests } from "~~/lib/requests";
|
import { Requests } from "~~/lib/requests";
|
||||||
|
|
||||||
export class UserClient extends BaseAPI {
|
export class UserClient extends BaseAPI {
|
||||||
|
@ -16,6 +17,7 @@ export class UserClient extends BaseAPI {
|
||||||
user: UserApi;
|
user: UserApi;
|
||||||
actions: ActionsAPI;
|
actions: ActionsAPI;
|
||||||
stats: StatsAPI;
|
stats: StatsAPI;
|
||||||
|
assets: AssetsApi;
|
||||||
|
|
||||||
constructor(requests: Requests, attachmentToken: string) {
|
constructor(requests: Requests, attachmentToken: string) {
|
||||||
super(requests, attachmentToken);
|
super(requests, attachmentToken);
|
||||||
|
@ -27,6 +29,7 @@ export class UserClient extends BaseAPI {
|
||||||
this.user = new UserApi(requests);
|
this.user = new UserApi(requests);
|
||||||
this.actions = new ActionsAPI(requests);
|
this.actions = new ActionsAPI(requests);
|
||||||
this.stats = new StatsAPI(requests);
|
this.stats = new StatsAPI(requests);
|
||||||
|
this.assets = new AssetsApi(requests);
|
||||||
|
|
||||||
Object.freeze(this);
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
|
42
frontend/pages/a/[id].vue
Normal file
42
frontend/pages/a/[id].vue
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
definePageMeta({
|
||||||
|
middleware: ["auth"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const api = useUserApi();
|
||||||
|
const toast = useNotifier();
|
||||||
|
|
||||||
|
const assetId = computed<string>(() => route.params.id as string);
|
||||||
|
|
||||||
|
const { pending, data: items } = useLazyAsyncData(`asset/${assetId.value}`, async () => {
|
||||||
|
const { data, error } = await api.assets.get(assetId.value);
|
||||||
|
if (error) {
|
||||||
|
toast.error("Failed to load asset");
|
||||||
|
navigateTo("/home");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (data.total) {
|
||||||
|
case 0:
|
||||||
|
toast.error("Asset not found");
|
||||||
|
navigateTo("/home");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
navigateTo(`/item/${data.items[0].id}`);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return data.items;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<BaseContainer>
|
||||||
|
<section v-if="!pending">
|
||||||
|
<BaseSectionHeader class="mb-5"> This Asset Id is associated with multiple items</BaseSectionHeader>
|
||||||
|
<div class="grid gap-2 grid-cols-1 sm:grid-cols-2">
|
||||||
|
<ItemCard v-for="item in items" :key="item.id" :item="item" />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</BaseContainer>
|
||||||
|
</template>
|
Loading…
Add table
Add a link
Reference in a new issue