From 7d462a4dd32f6fe04f4c1956a59dee910d019d23 Mon Sep 17 00:00:00 2001 From: slid1amo2n3e4 Date: Tue, 8 Oct 2024 16:58:37 +0200 Subject: [PATCH 1/4] Fix formatting. --- backend/app/api/handlers/v1/controller.go | 20 +-- .../app/api/handlers/v1/v1_ctrl_actions.go | 56 +++--- backend/app/api/handlers/v1/v1_ctrl_assets.go | 14 +- backend/app/api/handlers/v1/v1_ctrl_auth.go | 46 ++--- backend/app/api/handlers/v1/v1_ctrl_group.go | 40 ++--- backend/app/api/handlers/v1/v1_ctrl_items.go | 164 +++++++++--------- .../handlers/v1/v1_ctrl_items_attachments.go | 68 ++++---- backend/app/api/handlers/v1/v1_ctrl_labels.go | 68 ++++---- .../app/api/handlers/v1/v1_ctrl_locations.go | 86 ++++----- .../api/handlers/v1/v1_ctrl_maint_entry.go | 28 +-- .../api/handlers/v1/v1_ctrl_maintenance.go | 40 ++--- .../app/api/handlers/v1/v1_ctrl_notifiers.go | 68 ++++---- backend/app/api/handlers/v1/v1_ctrl_qrcode.go | 14 +- .../app/api/handlers/v1/v1_ctrl_reporting.go | 12 +- .../app/api/handlers/v1/v1_ctrl_statistics.go | 52 +++--- backend/app/api/handlers/v1/v1_ctrl_user.go | 62 +++---- backend/app/api/main.go | 18 +- 17 files changed, 428 insertions(+), 428 deletions(-) diff --git a/backend/app/api/handlers/v1/controller.go b/backend/app/api/handlers/v1/controller.go index 135b1446b..436071138 100644 --- a/backend/app/api/handlers/v1/controller.go +++ b/backend/app/api/handlers/v1/controller.go @@ -111,11 +111,11 @@ func NewControllerV1(svc *services.AllServices, repos *repo.AllRepos, bus *event // HandleBase godoc // -// @Summary Application Info -// @Tags Base -// @Produce json -// @Success 200 {object} APISummary -// @Router /v1/status [GET] +// @Summary Application Info +// @Tags Base +// @Produce json +// @Success 200 {object} APISummary +// @Router /v1/status [GET] func (ctrl *V1Controller) HandleBase(ready ReadyFunc, build Build) errchain.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) error { return server.JSON(w, http.StatusOK, APISummary{ @@ -131,11 +131,11 @@ func (ctrl *V1Controller) HandleBase(ready ReadyFunc, build Build) errchain.Hand // HandleCurrency godoc // -// @Summary Currency -// @Tags Base -// @Produce json -// @Success 200 {object} currencies.Currency -// @Router /v1/currency [GET] +// @Summary Currency +// @Tags Base +// @Produce json +// @Success 200 {object} currencies.Currency +// @Router /v1/currency [GET] func (ctrl *V1Controller) HandleCurrency() errchain.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) error { // Set Cache for 10 Minutes diff --git a/backend/app/api/handlers/v1/v1_ctrl_actions.go b/backend/app/api/handlers/v1/v1_ctrl_actions.go index 2ae25f023..a134e490b 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_actions.go +++ b/backend/app/api/handlers/v1/v1_ctrl_actions.go @@ -32,52 +32,52 @@ func actionHandlerFactory(ref string, fn func(context.Context, uuid.UUID) (int, // HandleEnsureAssetID godoc // -// @Summary Ensure Asset IDs -// @Description Ensures all items in the database have an asset ID -// @Tags Actions -// @Produce json -// @Success 200 {object} ActionAmountResult -// @Router /v1/actions/ensure-asset-ids [Post] -// @Security Bearer +// @Summary Ensure Asset IDs +// @Description Ensures all items in the database have an asset ID +// @Tags Actions +// @Produce json +// @Success 200 {object} ActionAmountResult +// @Router /v1/actions/ensure-asset-ids [Post] +// @Security Bearer func (ctrl *V1Controller) HandleEnsureAssetID() errchain.HandlerFunc { return actionHandlerFactory("ensure asset IDs", ctrl.svc.Items.EnsureAssetID) } // HandleEnsureImportRefs godoc // -// @Summary Ensures Import Refs -// @Description Ensures all items in the database have an import ref -// @Tags Actions -// @Produce json -// @Success 200 {object} ActionAmountResult -// @Router /v1/actions/ensure-import-refs [Post] -// @Security Bearer +// @Summary Ensures Import Refs +// @Description Ensures all items in the database have an import ref +// @Tags Actions +// @Produce json +// @Success 200 {object} ActionAmountResult +// @Router /v1/actions/ensure-import-refs [Post] +// @Security Bearer func (ctrl *V1Controller) HandleEnsureImportRefs() errchain.HandlerFunc { return actionHandlerFactory("ensure import refs", ctrl.svc.Items.EnsureImportRef) } // HandleItemDateZeroOut godoc // -// @Summary Zero Out Time Fields -// @Description Resets all item date fields to the beginning of the day -// @Tags Actions -// @Produce json -// @Success 200 {object} ActionAmountResult -// @Router /v1/actions/zero-item-time-fields [Post] -// @Security Bearer +// @Summary Zero Out Time Fields +// @Description Resets all item date fields to the beginning of the day +// @Tags Actions +// @Produce json +// @Success 200 {object} ActionAmountResult +// @Router /v1/actions/zero-item-time-fields [Post] +// @Security Bearer func (ctrl *V1Controller) HandleItemDateZeroOut() errchain.HandlerFunc { return actionHandlerFactory("zero out date time", ctrl.repo.Items.ZeroOutTimeFields) } // HandleSetPrimaryPhotos godoc // -// @Summary Set Primary Photos -// @Description Sets the first photo of each item as the primary photo -// @Tags Actions -// @Produce json -// @Success 200 {object} ActionAmountResult -// @Router /v1/actions/set-primary-photos [Post] -// @Security Bearer +// @Summary Set Primary Photos +// @Description Sets the first photo of each item as the primary photo +// @Tags Actions +// @Produce json +// @Success 200 {object} ActionAmountResult +// @Router /v1/actions/set-primary-photos [Post] +// @Security Bearer func (ctrl *V1Controller) HandleSetPrimaryPhotos() errchain.HandlerFunc { return actionHandlerFactory("ensure asset IDs", ctrl.repo.Items.SetPrimaryPhotos) } diff --git a/backend/app/api/handlers/v1/v1_ctrl_assets.go b/backend/app/api/handlers/v1/v1_ctrl_assets.go index 4b26467c5..4699b9d1b 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_assets.go +++ b/backend/app/api/handlers/v1/v1_ctrl_assets.go @@ -17,13 +17,13 @@ import ( // HandleAssetGet godocs // -// @Summary Get Item by Asset ID -// @Tags Items -// @Produce json -// @Param id path string true "Asset ID" -// @Success 200 {object} repo.PaginationResult[repo.ItemSummary]{} -// @Router /v1/assets/{id} [GET] -// @Security Bearer +// @Summary Get Item by Asset ID +// @Tags Items +// @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() errchain.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) error { ctx := services.NewContext(r.Context()) diff --git a/backend/app/api/handlers/v1/v1_ctrl_auth.go b/backend/app/api/handlers/v1/v1_ctrl_auth.go index de5b6c2b7..945c6cfbf 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_auth.go +++ b/backend/app/api/handlers/v1/v1_ctrl_auth.go @@ -79,17 +79,17 @@ type AuthProvider interface { // HandleAuthLogin godoc // -// @Summary User Login -// @Tags Authentication -// @Accept x-www-form-urlencoded -// @Accept application/json -// @Param username formData string false "string" example(admin@admin.com) -// @Param password formData string false "string" example(admin) -// @Param payload body LoginForm true "Login Data" -// @Param provider query string false "auth provider" -// @Produce json -// @Success 200 {object} TokenResponse -// @Router /v1/users/login [POST] +// @Summary User Login +// @Tags Authentication +// @Accept x-www-form-urlencoded +// @Accept application/json +// @Param username formData string false "string" example(admin@admin.com) +// @Param password formData string false "string" example(admin) +// @Param payload body LoginForm true "Login Data" +// @Param provider query string false "auth provider" +// @Produce json +// @Success 200 {object} TokenResponse +// @Router /v1/users/login [POST] func (ctrl *V1Controller) HandleAuthLogin(ps ...AuthProvider) errchain.HandlerFunc { if len(ps) == 0 { panic("no auth providers provided") @@ -131,11 +131,11 @@ func (ctrl *V1Controller) HandleAuthLogin(ps ...AuthProvider) errchain.HandlerFu // HandleAuthLogout godoc // -// @Summary User Logout -// @Tags Authentication -// @Success 204 -// @Router /v1/users/logout [POST] -// @Security Bearer +// @Summary User Logout +// @Tags Authentication +// @Success 204 +// @Router /v1/users/logout [POST] +// @Security Bearer func (ctrl *V1Controller) HandleAuthLogout() errchain.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) error { token := services.UseTokenCtx(r.Context()) @@ -155,13 +155,13 @@ func (ctrl *V1Controller) HandleAuthLogout() errchain.HandlerFunc { // HandleAuthRefresh godoc // -// @Summary User Token Refresh -// @Description handleAuthRefresh returns a handler that will issue a new token from an existing token. -// @Description This does not validate that the user still exists within the database. -// @Tags Authentication -// @Success 200 -// @Router /v1/users/refresh [GET] -// @Security Bearer +// @Summary User Token Refresh +// @Description handleAuthRefresh returns a handler that will issue a new token from an existing token. +// @Description This does not validate that the user still exists within the database. +// @Tags Authentication +// @Success 200 +// @Router /v1/users/refresh [GET] +// @Security Bearer func (ctrl *V1Controller) HandleAuthRefresh() errchain.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) error { requestToken := services.UseTokenCtx(r.Context()) diff --git a/backend/app/api/handlers/v1/v1_ctrl_group.go b/backend/app/api/handlers/v1/v1_ctrl_group.go index 62de9165b..a29d2599c 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_group.go +++ b/backend/app/api/handlers/v1/v1_ctrl_group.go @@ -26,12 +26,12 @@ type ( // HandleGroupGet godoc // -// @Summary Get Group -// @Tags Group -// @Produce json -// @Success 200 {object} repo.Group -// @Router /v1/groups [Get] -// @Security Bearer +// @Summary Get Group +// @Tags Group +// @Produce json +// @Success 200 {object} repo.Group +// @Router /v1/groups [Get] +// @Security Bearer func (ctrl *V1Controller) HandleGroupGet() errchain.HandlerFunc { fn := func(r *http.Request) (repo.Group, error) { auth := services.NewContext(r.Context()) @@ -43,13 +43,13 @@ func (ctrl *V1Controller) HandleGroupGet() errchain.HandlerFunc { // HandleGroupUpdate godoc // -// @Summary Update Group -// @Tags Group -// @Produce json -// @Param payload body repo.GroupUpdate true "User Data" -// @Success 200 {object} repo.Group -// @Router /v1/groups [Put] -// @Security Bearer +// @Summary Update Group +// @Tags Group +// @Produce json +// @Param payload body repo.GroupUpdate true "User Data" +// @Success 200 {object} repo.Group +// @Router /v1/groups [Put] +// @Security Bearer func (ctrl *V1Controller) HandleGroupUpdate() errchain.HandlerFunc { fn := func(r *http.Request, body repo.GroupUpdate) (repo.Group, error) { auth := services.NewContext(r.Context()) @@ -69,13 +69,13 @@ func (ctrl *V1Controller) HandleGroupUpdate() errchain.HandlerFunc { // HandleGroupInvitationsCreate godoc // -// @Summary Create Group Invitation -// @Tags Group -// @Produce json -// @Param payload body GroupInvitationCreate true "User Data" -// @Success 200 {object} GroupInvitation -// @Router /v1/groups/invitations [Post] -// @Security Bearer +// @Summary Create Group Invitation +// @Tags Group +// @Produce json +// @Param payload body GroupInvitationCreate true "User Data" +// @Success 200 {object} GroupInvitation +// @Router /v1/groups/invitations [Post] +// @Security Bearer func (ctrl *V1Controller) HandleGroupInvitationsCreate() errchain.HandlerFunc { fn := func(r *http.Request, body GroupInvitationCreate) (GroupInvitation, error) { if body.ExpiresAt.IsZero() { diff --git a/backend/app/api/handlers/v1/v1_ctrl_items.go b/backend/app/api/handlers/v1/v1_ctrl_items.go index 1eddc0fc3..45790c90b 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_items.go +++ b/backend/app/api/handlers/v1/v1_ctrl_items.go @@ -21,18 +21,18 @@ import ( // HandleItemsGetAll godoc // -// @Summary Query All Items -// @Tags Items -// @Produce json -// @Param q query string false "search string" -// @Param page query int false "page number" -// @Param pageSize query int false "items per page" -// @Param labels query []string false "label Ids" collectionFormat(multi) -// @Param locations query []string false "location Ids" collectionFormat(multi) -// @Param parentIds query []string false "parent Ids" collectionFormat(multi) -// @Success 200 {object} repo.PaginationResult[repo.ItemSummary]{} -// @Router /v1/items [GET] -// @Security Bearer +// @Summary Query All Items +// @Tags Items +// @Produce json +// @Param q query string false "search string" +// @Param page query int false "page number" +// @Param pageSize query int false "items per page" +// @Param labels query []string false "label Ids" collectionFormat(multi) +// @Param locations query []string false "location Ids" collectionFormat(multi) +// @Param parentIds query []string false "parent Ids" collectionFormat(multi) +// @Success 200 {object} repo.PaginationResult[repo.ItemSummary]{} +// @Router /v1/items [GET] +// @Security Bearer func (ctrl *V1Controller) HandleItemsGetAll() errchain.HandlerFunc { extractQuery := func(r *http.Request) repo.ItemQuery { params := r.URL.Query() @@ -106,13 +106,13 @@ func (ctrl *V1Controller) HandleItemsGetAll() errchain.HandlerFunc { // HandleItemFullPath godoc // -// @Summary Get the full path of an item -// @Tags Items -// @Produce json -// @Param id path string true "Item ID" -// @Success 200 {object} []repo.ItemPath -// @Router /v1/items/{id}/path [GET] -// @Security Bearer +// @Summary Get the full path of an item +// @Tags Items +// @Produce json +// @Param id path string true "Item ID" +// @Success 200 {object} []repo.ItemPath +// @Router /v1/items/{id}/path [GET] +// @Security Bearer func (ctrl *V1Controller) HandleItemFullPath() errchain.HandlerFunc { fn := func(r *http.Request, ID uuid.UUID) ([]repo.ItemPath, error) { auth := services.NewContext(r.Context()) @@ -148,13 +148,13 @@ func (ctrl *V1Controller) HandleItemFullPath() errchain.HandlerFunc { // HandleItemsCreate godoc // -// @Summary Create Item -// @Tags Items -// @Produce json -// @Param payload body repo.ItemCreate true "Item Data" -// @Success 201 {object} repo.ItemSummary -// @Router /v1/items [POST] -// @Security Bearer +// @Summary Create Item +// @Tags Items +// @Produce json +// @Param payload body repo.ItemCreate true "Item Data" +// @Success 201 {object} repo.ItemSummary +// @Router /v1/items [POST] +// @Security Bearer func (ctrl *V1Controller) HandleItemsCreate() errchain.HandlerFunc { fn := func(r *http.Request, body repo.ItemCreate) (repo.ItemOut, error) { return ctrl.svc.Items.Create(services.NewContext(r.Context()), body) @@ -165,13 +165,13 @@ func (ctrl *V1Controller) HandleItemsCreate() errchain.HandlerFunc { // HandleItemGet godocs // -// @Summary Get Item -// @Tags Items -// @Produce json -// @Param id path string true "Item ID" -// @Success 200 {object} repo.ItemOut -// @Router /v1/items/{id} [GET] -// @Security Bearer +// @Summary Get Item +// @Tags Items +// @Produce json +// @Param id path string true "Item ID" +// @Success 200 {object} repo.ItemOut +// @Router /v1/items/{id} [GET] +// @Security Bearer func (ctrl *V1Controller) HandleItemGet() errchain.HandlerFunc { fn := func(r *http.Request, ID uuid.UUID) (repo.ItemOut, error) { auth := services.NewContext(r.Context()) @@ -184,13 +184,13 @@ func (ctrl *V1Controller) HandleItemGet() errchain.HandlerFunc { // HandleItemDelete godocs // -// @Summary Delete Item -// @Tags Items -// @Produce json -// @Param id path string true "Item ID" -// @Success 204 -// @Router /v1/items/{id} [DELETE] -// @Security Bearer +// @Summary Delete Item +// @Tags Items +// @Produce json +// @Param id path string true "Item ID" +// @Success 204 +// @Router /v1/items/{id} [DELETE] +// @Security Bearer func (ctrl *V1Controller) HandleItemDelete() errchain.HandlerFunc { fn := func(r *http.Request, ID uuid.UUID) (any, error) { auth := services.NewContext(r.Context()) @@ -203,14 +203,14 @@ func (ctrl *V1Controller) HandleItemDelete() errchain.HandlerFunc { // HandleItemUpdate godocs // -// @Summary Update Item -// @Tags Items -// @Produce json -// @Param id path string true "Item ID" -// @Param payload body repo.ItemUpdate true "Item Data" -// @Success 200 {object} repo.ItemOut -// @Router /v1/items/{id} [PUT] -// @Security Bearer +// @Summary Update Item +// @Tags Items +// @Produce json +// @Param id path string true "Item ID" +// @Param payload body repo.ItemUpdate true "Item Data" +// @Success 200 {object} repo.ItemOut +// @Router /v1/items/{id} [PUT] +// @Security Bearer func (ctrl *V1Controller) HandleItemUpdate() errchain.HandlerFunc { fn := func(r *http.Request, ID uuid.UUID, body repo.ItemUpdate) (repo.ItemOut, error) { auth := services.NewContext(r.Context()) @@ -224,14 +224,14 @@ func (ctrl *V1Controller) HandleItemUpdate() errchain.HandlerFunc { // HandleItemPatch godocs // -// @Summary Update Item -// @Tags Items -// @Produce json -// @Param id path string true "Item ID" -// @Param payload body repo.ItemPatch true "Item Data" -// @Success 200 {object} repo.ItemOut -// @Router /v1/items/{id} [Patch] -// @Security Bearer +// @Summary Update Item +// @Tags Items +// @Produce json +// @Param id path string true "Item ID" +// @Param payload body repo.ItemPatch true "Item Data" +// @Success 200 {object} repo.ItemOut +// @Router /v1/items/{id} [Patch] +// @Security Bearer func (ctrl *V1Controller) HandleItemPatch() errchain.HandlerFunc { fn := func(r *http.Request, ID uuid.UUID, body repo.ItemPatch) (repo.ItemOut, error) { auth := services.NewContext(r.Context()) @@ -250,13 +250,13 @@ func (ctrl *V1Controller) HandleItemPatch() errchain.HandlerFunc { // HandleGetAllCustomFieldNames godocs // -// @Summary Get All Custom Field Names -// @Tags Items -// @Produce json -// @Success 200 -// @Router /v1/items/fields [GET] -// @Success 200 {object} []string -// @Security Bearer +// @Summary Get All Custom Field Names +// @Tags Items +// @Produce json +// @Success 200 +// @Router /v1/items/fields [GET] +// @Success 200 {object} []string +// @Security Bearer func (ctrl *V1Controller) HandleGetAllCustomFieldNames() errchain.HandlerFunc { fn := func(r *http.Request) ([]string, error) { auth := services.NewContext(r.Context()) @@ -268,13 +268,13 @@ func (ctrl *V1Controller) HandleGetAllCustomFieldNames() errchain.HandlerFunc { // HandleGetAllCustomFieldValues godocs // -// @Summary Get All Custom Field Values -// @Tags Items -// @Produce json -// @Success 200 -// @Router /v1/items/fields/values [GET] -// @Success 200 {object} []string -// @Security Bearer +// @Summary Get All Custom Field Values +// @Tags Items +// @Produce json +// @Success 200 +// @Router /v1/items/fields/values [GET] +// @Success 200 {object} []string +// @Security Bearer func (ctrl *V1Controller) HandleGetAllCustomFieldValues() errchain.HandlerFunc { type query struct { Field string `schema:"field" validate:"required"` @@ -290,13 +290,13 @@ func (ctrl *V1Controller) HandleGetAllCustomFieldValues() errchain.HandlerFunc { // HandleItemsImport godocs // -// @Summary Import Items -// @Tags Items -// @Produce json -// @Success 204 -// @Param csv formData file true "Image to upload" -// @Router /v1/items/import [Post] -// @Security Bearer +// @Summary Import Items +// @Tags Items +// @Produce json +// @Success 204 +// @Param csv formData file true "Image to upload" +// @Router /v1/items/import [Post] +// @Security Bearer func (ctrl *V1Controller) HandleItemsImport() errchain.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) error { err := r.ParseMultipartForm(ctrl.maxUploadSize << 20) @@ -325,11 +325,11 @@ func (ctrl *V1Controller) HandleItemsImport() errchain.HandlerFunc { // HandleItemsExport godocs // -// @Summary Export Items -// @Tags Items -// @Success 200 {string} string "text/csv" -// @Router /v1/items/export [GET] -// @Security Bearer +// @Summary Export Items +// @Tags Items +// @Success 200 {string} string "text/csv" +// @Router /v1/items/export [GET] +// @Security Bearer func (ctrl *V1Controller) HandleItemsExport() errchain.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) error { ctx := services.NewContext(r.Context()) diff --git a/backend/app/api/handlers/v1/v1_ctrl_items_attachments.go b/backend/app/api/handlers/v1/v1_ctrl_items_attachments.go index 61b3b9a59..007f6dde4 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_items_attachments.go +++ b/backend/app/api/handlers/v1/v1_ctrl_items_attachments.go @@ -23,17 +23,17 @@ type ( // HandleItemAttachmentCreate godocs // -// @Summary Create Item Attachment -// @Tags Items Attachments -// @Produce json -// @Param id path string true "Item ID" -// @Param file formData file true "File attachment" -// @Param type formData string true "Type of file" -// @Param name formData string true "name of the file including extension" -// @Success 200 {object} repo.ItemOut -// @Failure 422 {object} validate.ErrorResponse -// @Router /v1/items/{id}/attachments [POST] -// @Security Bearer +// @Summary Create Item Attachment +// @Tags Items Attachments +// @Produce json +// @Param id path string true "Item ID" +// @Param file formData file true "File attachment" +// @Param type formData string true "Type of file" +// @Param name formData string true "name of the file including extension" +// @Success 200 {object} repo.ItemOut +// @Failure 422 {object} validate.ErrorResponse +// @Router /v1/items/{id}/attachments [POST] +// @Security Bearer func (ctrl *V1Controller) HandleItemAttachmentCreate() errchain.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) error { err := r.ParseMultipartForm(ctrl.maxUploadSize << 20) @@ -104,41 +104,41 @@ func (ctrl *V1Controller) HandleItemAttachmentCreate() errchain.HandlerFunc { // HandleItemAttachmentGet godocs // -// @Summary Get Item Attachment -// @Tags Items Attachments -// @Produce application/octet-stream -// @Param id path string true "Item ID" -// @Param attachment_id path string true "Attachment ID" -// @Success 200 {object} ItemAttachmentToken -// @Router /v1/items/{id}/attachments/{attachment_id} [GET] -// @Security Bearer +// @Summary Get Item Attachment +// @Tags Items Attachments +// @Produce application/octet-stream +// @Param id path string true "Item ID" +// @Param attachment_id path string true "Attachment ID" +// @Success 200 {object} ItemAttachmentToken +// @Router /v1/items/{id}/attachments/{attachment_id} [GET] +// @Security Bearer func (ctrl *V1Controller) HandleItemAttachmentGet() errchain.HandlerFunc { return ctrl.handleItemAttachmentsHandler } // HandleItemAttachmentDelete godocs // -// @Summary Delete Item Attachment -// @Tags Items Attachments -// @Param id path string true "Item ID" -// @Param attachment_id path string true "Attachment ID" -// @Success 204 -// @Router /v1/items/{id}/attachments/{attachment_id} [DELETE] -// @Security Bearer +// @Summary Delete Item Attachment +// @Tags Items Attachments +// @Param id path string true "Item ID" +// @Param attachment_id path string true "Attachment ID" +// @Success 204 +// @Router /v1/items/{id}/attachments/{attachment_id} [DELETE] +// @Security Bearer func (ctrl *V1Controller) HandleItemAttachmentDelete() errchain.HandlerFunc { return ctrl.handleItemAttachmentsHandler } // HandleItemAttachmentUpdate godocs // -// @Summary Update Item Attachment -// @Tags Items Attachments -// @Param id path string true "Item ID" -// @Param attachment_id path string true "Attachment ID" -// @Param payload body repo.ItemAttachmentUpdate true "Attachment Update" -// @Success 200 {object} repo.ItemOut -// @Router /v1/items/{id}/attachments/{attachment_id} [PUT] -// @Security Bearer +// @Summary Update Item Attachment +// @Tags Items Attachments +// @Param id path string true "Item ID" +// @Param attachment_id path string true "Attachment ID" +// @Param payload body repo.ItemAttachmentUpdate true "Attachment Update" +// @Success 200 {object} repo.ItemOut +// @Router /v1/items/{id}/attachments/{attachment_id} [PUT] +// @Security Bearer func (ctrl *V1Controller) HandleItemAttachmentUpdate() errchain.HandlerFunc { return ctrl.handleItemAttachmentsHandler } diff --git a/backend/app/api/handlers/v1/v1_ctrl_labels.go b/backend/app/api/handlers/v1/v1_ctrl_labels.go index 888be19d4..1c23adbe0 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_labels.go +++ b/backend/app/api/handlers/v1/v1_ctrl_labels.go @@ -12,12 +12,12 @@ import ( // HandleLabelsGetAll godoc // -// @Summary Get All Labels -// @Tags Labels -// @Produce json -// @Success 200 {object} []repo.LabelOut -// @Router /v1/labels [GET] -// @Security Bearer +// @Summary Get All Labels +// @Tags Labels +// @Produce json +// @Success 200 {object} []repo.LabelOut +// @Router /v1/labels [GET] +// @Security Bearer func (ctrl *V1Controller) HandleLabelsGetAll() errchain.HandlerFunc { fn := func(r *http.Request) ([]repo.LabelSummary, error) { auth := services.NewContext(r.Context()) @@ -29,13 +29,13 @@ func (ctrl *V1Controller) HandleLabelsGetAll() errchain.HandlerFunc { // HandleLabelsCreate godoc // -// @Summary Create Label -// @Tags Labels -// @Produce json -// @Param payload body repo.LabelCreate true "Label Data" -// @Success 200 {object} repo.LabelSummary -// @Router /v1/labels [POST] -// @Security Bearer +// @Summary Create Label +// @Tags Labels +// @Produce json +// @Param payload body repo.LabelCreate true "Label Data" +// @Success 200 {object} repo.LabelSummary +// @Router /v1/labels [POST] +// @Security Bearer func (ctrl *V1Controller) HandleLabelsCreate() errchain.HandlerFunc { fn := func(r *http.Request, data repo.LabelCreate) (repo.LabelOut, error) { auth := services.NewContext(r.Context()) @@ -47,13 +47,13 @@ func (ctrl *V1Controller) HandleLabelsCreate() errchain.HandlerFunc { // HandleLabelDelete godocs // -// @Summary Delete Label -// @Tags Labels -// @Produce json -// @Param id path string true "Label ID" -// @Success 204 -// @Router /v1/labels/{id} [DELETE] -// @Security Bearer +// @Summary Delete Label +// @Tags Labels +// @Produce json +// @Param id path string true "Label ID" +// @Success 204 +// @Router /v1/labels/{id} [DELETE] +// @Security Bearer func (ctrl *V1Controller) HandleLabelDelete() errchain.HandlerFunc { fn := func(r *http.Request, ID uuid.UUID) (any, error) { auth := services.NewContext(r.Context()) @@ -66,13 +66,13 @@ func (ctrl *V1Controller) HandleLabelDelete() errchain.HandlerFunc { // HandleLabelGet godocs // -// @Summary Get Label -// @Tags Labels -// @Produce json -// @Param id path string true "Label ID" -// @Success 200 {object} repo.LabelOut -// @Router /v1/labels/{id} [GET] -// @Security Bearer +// @Summary Get Label +// @Tags Labels +// @Produce json +// @Param id path string true "Label ID" +// @Success 200 {object} repo.LabelOut +// @Router /v1/labels/{id} [GET] +// @Security Bearer func (ctrl *V1Controller) HandleLabelGet() errchain.HandlerFunc { fn := func(r *http.Request, ID uuid.UUID) (repo.LabelOut, error) { auth := services.NewContext(r.Context()) @@ -84,13 +84,13 @@ func (ctrl *V1Controller) HandleLabelGet() errchain.HandlerFunc { // HandleLabelUpdate godocs // -// @Summary Update Label -// @Tags Labels -// @Produce json -// @Param id path string true "Label ID" -// @Success 200 {object} repo.LabelOut -// @Router /v1/labels/{id} [PUT] -// @Security Bearer +// @Summary Update Label +// @Tags Labels +// @Produce json +// @Param id path string true "Label ID" +// @Success 200 {object} repo.LabelOut +// @Router /v1/labels/{id} [PUT] +// @Security Bearer func (ctrl *V1Controller) HandleLabelUpdate() errchain.HandlerFunc { fn := func(r *http.Request, ID uuid.UUID, data repo.LabelUpdate) (repo.LabelOut, error) { auth := services.NewContext(r.Context()) diff --git a/backend/app/api/handlers/v1/v1_ctrl_locations.go b/backend/app/api/handlers/v1/v1_ctrl_locations.go index 3903bd928..f8099b7a7 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_locations.go +++ b/backend/app/api/handlers/v1/v1_ctrl_locations.go @@ -14,13 +14,13 @@ import ( // HandleLocationTreeQuery godoc // -// @Summary Get Locations Tree -// @Tags Locations -// @Produce json -// @Param withItems query bool false "include items in response tree" -// @Success 200 {object} []repo.TreeItem -// @Router /v1/locations/tree [GET] -// @Security Bearer +// @Summary Get Locations Tree +// @Tags Locations +// @Produce json +// @Param withItems query bool false "include items in response tree" +// @Success 200 {object} []repo.TreeItem +// @Router /v1/locations/tree [GET] +// @Security Bearer func (ctrl *V1Controller) HandleLocationTreeQuery() errchain.HandlerFunc { fn := func(r *http.Request, query repo.TreeQuery) ([]repo.TreeItem, error) { auth := services.NewContext(r.Context()) @@ -32,13 +32,13 @@ func (ctrl *V1Controller) HandleLocationTreeQuery() errchain.HandlerFunc { // HandleLocationGetAll godoc // -// @Summary Get All Locations -// @Tags Locations -// @Produce json -// @Param filterChildren query bool false "Filter locations with parents" -// @Success 200 {object} []repo.LocationOutCount -// @Router /v1/locations [GET] -// @Security Bearer +// @Summary Get All Locations +// @Tags Locations +// @Produce json +// @Param filterChildren query bool false "Filter locations with parents" +// @Success 200 {object} []repo.LocationOutCount +// @Router /v1/locations [GET] +// @Security Bearer func (ctrl *V1Controller) HandleLocationGetAll() errchain.HandlerFunc { fn := func(r *http.Request, q repo.LocationQuery) ([]repo.LocationOutCount, error) { auth := services.NewContext(r.Context()) @@ -50,13 +50,13 @@ func (ctrl *V1Controller) HandleLocationGetAll() errchain.HandlerFunc { // HandleLocationCreate godoc // -// @Summary Create Location -// @Tags Locations -// @Produce json -// @Param payload body repo.LocationCreate true "Location Data" -// @Success 200 {object} repo.LocationSummary -// @Router /v1/locations [POST] -// @Security Bearer +// @Summary Create Location +// @Tags Locations +// @Produce json +// @Param payload body repo.LocationCreate true "Location Data" +// @Success 200 {object} repo.LocationSummary +// @Router /v1/locations [POST] +// @Security Bearer func (ctrl *V1Controller) HandleLocationCreate() errchain.HandlerFunc { fn := func(r *http.Request, createData repo.LocationCreate) (repo.LocationOut, error) { auth := services.NewContext(r.Context()) @@ -68,13 +68,13 @@ func (ctrl *V1Controller) HandleLocationCreate() errchain.HandlerFunc { // HandleLocationDelete godoc // -// @Summary Delete Location -// @Tags Locations -// @Produce json -// @Param id path string true "Location ID" -// @Success 204 -// @Router /v1/locations/{id} [DELETE] -// @Security Bearer +// @Summary Delete Location +// @Tags Locations +// @Produce json +// @Param id path string true "Location ID" +// @Success 204 +// @Router /v1/locations/{id} [DELETE] +// @Security Bearer func (ctrl *V1Controller) HandleLocationDelete() errchain.HandlerFunc { fn := func(r *http.Request, ID uuid.UUID) (any, error) { auth := services.NewContext(r.Context()) @@ -124,13 +124,13 @@ func (ctrl *V1Controller) GetLocationWithPrice(auth context.Context, gid uuid.UU // HandleLocationGet godoc // -// @Summary Get Location -// @Tags Locations -// @Produce json -// @Param id path string true "Location ID" -// @Success 200 {object} repo.LocationOut -// @Router /v1/locations/{id} [GET] -// @Security Bearer +// @Summary Get Location +// @Tags Locations +// @Produce json +// @Param id path string true "Location ID" +// @Success 200 {object} repo.LocationOut +// @Router /v1/locations/{id} [GET] +// @Security Bearer func (ctrl *V1Controller) HandleLocationGet() errchain.HandlerFunc { fn := func(r *http.Request, ID uuid.UUID) (repo.LocationOut, error) { auth := services.NewContext(r.Context()) @@ -144,14 +144,14 @@ func (ctrl *V1Controller) HandleLocationGet() errchain.HandlerFunc { // HandleLocationUpdate godoc // -// @Summary Update Location -// @Tags Locations -// @Produce json -// @Param id path string true "Location ID" -// @Param payload body repo.LocationUpdate true "Location Data" -// @Success 200 {object} repo.LocationOut -// @Router /v1/locations/{id} [PUT] -// @Security Bearer +// @Summary Update Location +// @Tags Locations +// @Produce json +// @Param id path string true "Location ID" +// @Param payload body repo.LocationUpdate true "Location Data" +// @Success 200 {object} repo.LocationOut +// @Router /v1/locations/{id} [PUT] +// @Security Bearer func (ctrl *V1Controller) HandleLocationUpdate() errchain.HandlerFunc { fn := func(r *http.Request, ID uuid.UUID, body repo.LocationUpdate) (repo.LocationOut, error) { auth := services.NewContext(r.Context()) diff --git a/backend/app/api/handlers/v1/v1_ctrl_maint_entry.go b/backend/app/api/handlers/v1/v1_ctrl_maint_entry.go index e9f1f97c0..aa1f3bb55 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_maint_entry.go +++ b/backend/app/api/handlers/v1/v1_ctrl_maint_entry.go @@ -12,13 +12,13 @@ import ( // HandleMaintenanceLogGet godoc // -// @Summary Get Maintenance Log -// @Tags Item Maintenance -// @Produce json -// @Param filters query repo.MaintenanceFilters false "which maintenance to retrieve" -// @Success 200 {array} repo.MaintenanceEntryWithDetails[] -// @Router /v1/items/{id}/maintenance [GET] -// @Security Bearer +// @Summary Get Maintenance Log +// @Tags Item Maintenance +// @Produce json +// @Param filters query repo.MaintenanceFilters false "which maintenance to retrieve" +// @Success 200 {array} repo.MaintenanceEntryWithDetails[] +// @Router /v1/items/{id}/maintenance [GET] +// @Security Bearer func (ctrl *V1Controller) HandleMaintenanceLogGet() errchain.HandlerFunc { fn := func(r *http.Request, ID uuid.UUID, filters repo.MaintenanceFilters) ([]repo.MaintenanceEntryWithDetails, error) { auth := services.NewContext(r.Context()) @@ -30,13 +30,13 @@ func (ctrl *V1Controller) HandleMaintenanceLogGet() errchain.HandlerFunc { // HandleMaintenanceEntryCreate godoc // -// @Summary Create Maintenance Entry -// @Tags Item Maintenance -// @Produce json -// @Param payload body repo.MaintenanceEntryCreate true "Entry Data" -// @Success 201 {object} repo.MaintenanceEntry -// @Router /v1/items/{id}/maintenance [POST] -// @Security Bearer +// @Summary Create Maintenance Entry +// @Tags Item Maintenance +// @Produce json +// @Param payload body repo.MaintenanceEntryCreate true "Entry Data" +// @Success 201 {object} repo.MaintenanceEntry +// @Router /v1/items/{id}/maintenance [POST] +// @Security Bearer func (ctrl *V1Controller) HandleMaintenanceEntryCreate() errchain.HandlerFunc { fn := func(r *http.Request, itemID uuid.UUID, body repo.MaintenanceEntryCreate) (repo.MaintenanceEntry, error) { auth := services.NewContext(r.Context()) diff --git a/backend/app/api/handlers/v1/v1_ctrl_maintenance.go b/backend/app/api/handlers/v1/v1_ctrl_maintenance.go index 647bfa703..03145b0ac 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_maintenance.go +++ b/backend/app/api/handlers/v1/v1_ctrl_maintenance.go @@ -12,13 +12,13 @@ import ( // HandleMaintenanceGetAll godoc // -// @Summary Query All Maintenance -// @Tags Maintenance -// @Produce json -// @Param filters query repo.MaintenanceFilters false "which maintenance to retrieve" -// @Success 200 {array} repo.MaintenanceEntryWithDetails[] -// @Router /v1/maintenance [GET] -// @Security Bearer +// @Summary Query All Maintenance +// @Tags Maintenance +// @Produce json +// @Param filters query repo.MaintenanceFilters false "which maintenance to retrieve" +// @Success 200 {array} repo.MaintenanceEntryWithDetails[] +// @Router /v1/maintenance [GET] +// @Security Bearer func (ctrl *V1Controller) HandleMaintenanceGetAll() errchain.HandlerFunc { fn := func(r *http.Request, filters repo.MaintenanceFilters) ([]repo.MaintenanceEntryWithDetails, error) { auth := services.NewContext(r.Context()) @@ -30,13 +30,13 @@ func (ctrl *V1Controller) HandleMaintenanceGetAll() errchain.HandlerFunc { // HandleMaintenanceEntryUpdate godoc // -// @Summary Update Maintenance Entry -// @Tags Maintenance -// @Produce json -// @Param payload body repo.MaintenanceEntryUpdate true "Entry Data" -// @Success 200 {object} repo.MaintenanceEntry -// @Router /v1/maintenance/{id} [PUT] -// @Security Bearer +// @Summary Update Maintenance Entry +// @Tags Maintenance +// @Produce json +// @Param payload body repo.MaintenanceEntryUpdate true "Entry Data" +// @Success 200 {object} repo.MaintenanceEntry +// @Router /v1/maintenance/{id} [PUT] +// @Security Bearer func (ctrl *V1Controller) HandleMaintenanceEntryUpdate() errchain.HandlerFunc { fn := func(r *http.Request, entryID uuid.UUID, body repo.MaintenanceEntryUpdate) (repo.MaintenanceEntry, error) { auth := services.NewContext(r.Context()) @@ -48,12 +48,12 @@ func (ctrl *V1Controller) HandleMaintenanceEntryUpdate() errchain.HandlerFunc { // HandleMaintenanceEntryDelete godoc // -// @Summary Delete Maintenance Entry -// @Tags Maintenance -// @Produce json -// @Success 204 -// @Router /v1/maintenance/{id} [DELETE] -// @Security Bearer +// @Summary Delete Maintenance Entry +// @Tags Maintenance +// @Produce json +// @Success 204 +// @Router /v1/maintenance/{id} [DELETE] +// @Security Bearer func (ctrl *V1Controller) HandleMaintenanceEntryDelete() errchain.HandlerFunc { fn := func(r *http.Request, entryID uuid.UUID) (any, error) { auth := services.NewContext(r.Context()) diff --git a/backend/app/api/handlers/v1/v1_ctrl_notifiers.go b/backend/app/api/handlers/v1/v1_ctrl_notifiers.go index f46b9102c..3c48aa0c2 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_notifiers.go +++ b/backend/app/api/handlers/v1/v1_ctrl_notifiers.go @@ -13,12 +13,12 @@ import ( // HandleGetUserNotifiers godoc // -// @Summary Get Notifiers -// @Tags Notifiers -// @Produce json -// @Success 200 {object} []repo.NotifierOut -// @Router /v1/notifiers [GET] -// @Security Bearer +// @Summary Get Notifiers +// @Tags Notifiers +// @Produce json +// @Success 200 {object} []repo.NotifierOut +// @Router /v1/notifiers [GET] +// @Security Bearer func (ctrl *V1Controller) HandleGetUserNotifiers() errchain.HandlerFunc { fn := func(r *http.Request, _ struct{}) ([]repo.NotifierOut, error) { user := services.UseUserCtx(r.Context()) @@ -30,13 +30,13 @@ func (ctrl *V1Controller) HandleGetUserNotifiers() errchain.HandlerFunc { // HandleCreateNotifier godoc // -// @Summary Create Notifier -// @Tags Notifiers -// @Produce json -// @Param payload body repo.NotifierCreate true "Notifier Data" -// @Success 200 {object} repo.NotifierOut -// @Router /v1/notifiers [POST] -// @Security Bearer +// @Summary Create Notifier +// @Tags Notifiers +// @Produce json +// @Param payload body repo.NotifierCreate true "Notifier Data" +// @Success 200 {object} repo.NotifierOut +// @Router /v1/notifiers [POST] +// @Security Bearer func (ctrl *V1Controller) HandleCreateNotifier() errchain.HandlerFunc { fn := func(r *http.Request, in repo.NotifierCreate) (repo.NotifierOut, error) { auth := services.NewContext(r.Context()) @@ -48,12 +48,12 @@ func (ctrl *V1Controller) HandleCreateNotifier() errchain.HandlerFunc { // HandleDeleteNotifier godocs // -// @Summary Delete a Notifier -// @Tags Notifiers -// @Param id path string true "Notifier ID" -// @Success 204 -// @Router /v1/notifiers/{id} [DELETE] -// @Security Bearer +// @Summary Delete a Notifier +// @Tags Notifiers +// @Param id path string true "Notifier ID" +// @Success 204 +// @Router /v1/notifiers/{id} [DELETE] +// @Security Bearer func (ctrl *V1Controller) HandleDeleteNotifier() errchain.HandlerFunc { fn := func(r *http.Request, ID uuid.UUID) (any, error) { auth := services.NewContext(r.Context()) @@ -65,13 +65,13 @@ func (ctrl *V1Controller) HandleDeleteNotifier() errchain.HandlerFunc { // HandleUpdateNotifier godocs // -// @Summary Update Notifier -// @Tags Notifiers -// @Param id path string true "Notifier ID" -// @Param payload body repo.NotifierUpdate true "Notifier Data" -// @Success 200 {object} repo.NotifierOut -// @Router /v1/notifiers/{id} [PUT] -// @Security Bearer +// @Summary Update Notifier +// @Tags Notifiers +// @Param id path string true "Notifier ID" +// @Param payload body repo.NotifierUpdate true "Notifier Data" +// @Success 200 {object} repo.NotifierOut +// @Router /v1/notifiers/{id} [PUT] +// @Security Bearer func (ctrl *V1Controller) HandleUpdateNotifier() errchain.HandlerFunc { fn := func(r *http.Request, ID uuid.UUID, in repo.NotifierUpdate) (repo.NotifierOut, error) { auth := services.NewContext(r.Context()) @@ -83,14 +83,14 @@ func (ctrl *V1Controller) HandleUpdateNotifier() errchain.HandlerFunc { // HandlerNotifierTest godoc // -// @Summary Test Notifier -// @Tags Notifiers -// @Produce json -// @Param id path string true "Notifier ID" -// @Param url query string true "URL" -// @Success 204 -// @Router /v1/notifiers/test [POST] -// @Security Bearer +// @Summary Test Notifier +// @Tags Notifiers +// @Produce json +// @Param id path string true "Notifier ID" +// @Param url query string true "URL" +// @Success 204 +// @Router /v1/notifiers/test [POST] +// @Security Bearer func (ctrl *V1Controller) HandlerNotifierTest() errchain.HandlerFunc { type body struct { URL string `json:"url" validate:"required"` diff --git a/backend/app/api/handlers/v1/v1_ctrl_qrcode.go b/backend/app/api/handlers/v1/v1_ctrl_qrcode.go index b348420a1..333f8d004 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_qrcode.go +++ b/backend/app/api/handlers/v1/v1_ctrl_qrcode.go @@ -20,13 +20,13 @@ var qrcodeLogo []byte // HandleGenerateQRCode godoc // -// @Summary Create QR Code -// @Tags Items -// @Produce json -// @Param data query string false "data to be encoded into qrcode" -// @Success 200 {string} string "image/jpeg" -// @Router /v1/qrcode [GET] -// @Security Bearer +// @Summary Create QR Code +// @Tags Items +// @Produce json +// @Param data query string false "data to be encoded into qrcode" +// @Success 200 {string} string "image/jpeg" +// @Router /v1/qrcode [GET] +// @Security Bearer func (ctrl *V1Controller) HandleGenerateQRCode() errchain.HandlerFunc { type query struct { // 4,296 characters is the maximum length of a QR code diff --git a/backend/app/api/handlers/v1/v1_ctrl_reporting.go b/backend/app/api/handlers/v1/v1_ctrl_reporting.go index d3b712f8e..6df58e178 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_reporting.go +++ b/backend/app/api/handlers/v1/v1_ctrl_reporting.go @@ -8,12 +8,12 @@ import ( // HandleBillOfMaterialsExport godoc // -// @Summary Export Bill of Materials -// @Tags Reporting -// @Produce json -// @Success 200 {string} string "text/csv" -// @Router /v1/reporting/bill-of-materials [GET] -// @Security Bearer +// @Summary Export Bill of Materials +// @Tags Reporting +// @Produce json +// @Success 200 {string} string "text/csv" +// @Router /v1/reporting/bill-of-materials [GET] +// @Security Bearer func (ctrl *V1Controller) HandleBillOfMaterialsExport() errchain.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) error { actor := services.UseUserCtx(r.Context()) diff --git a/backend/app/api/handlers/v1/v1_ctrl_statistics.go b/backend/app/api/handlers/v1/v1_ctrl_statistics.go index d66bd9086..980f44b05 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_statistics.go +++ b/backend/app/api/handlers/v1/v1_ctrl_statistics.go @@ -14,12 +14,12 @@ import ( // HandleGroupStatisticsLocations godoc // -// @Summary Get Location Statistics -// @Tags Statistics -// @Produce json -// @Success 200 {object} []repo.TotalsByOrganizer -// @Router /v1/groups/statistics/locations [GET] -// @Security Bearer +// @Summary Get Location Statistics +// @Tags Statistics +// @Produce json +// @Success 200 {object} []repo.TotalsByOrganizer +// @Router /v1/groups/statistics/locations [GET] +// @Security Bearer func (ctrl *V1Controller) HandleGroupStatisticsLocations() errchain.HandlerFunc { fn := func(r *http.Request) ([]repo.TotalsByOrganizer, error) { auth := services.NewContext(r.Context()) @@ -31,12 +31,12 @@ func (ctrl *V1Controller) HandleGroupStatisticsLocations() errchain.HandlerFunc // HandleGroupStatisticsLabels godoc // -// @Summary Get Label Statistics -// @Tags Statistics -// @Produce json -// @Success 200 {object} []repo.TotalsByOrganizer -// @Router /v1/groups/statistics/labels [GET] -// @Security Bearer +// @Summary Get Label Statistics +// @Tags Statistics +// @Produce json +// @Success 200 {object} []repo.TotalsByOrganizer +// @Router /v1/groups/statistics/labels [GET] +// @Security Bearer func (ctrl *V1Controller) HandleGroupStatisticsLabels() errchain.HandlerFunc { fn := func(r *http.Request) ([]repo.TotalsByOrganizer, error) { auth := services.NewContext(r.Context()) @@ -48,12 +48,12 @@ func (ctrl *V1Controller) HandleGroupStatisticsLabels() errchain.HandlerFunc { // HandleGroupStatistics godoc // -// @Summary Get Group Statistics -// @Tags Statistics -// @Produce json -// @Success 200 {object} repo.GroupStatistics -// @Router /v1/groups/statistics [GET] -// @Security Bearer +// @Summary Get Group Statistics +// @Tags Statistics +// @Produce json +// @Success 200 {object} repo.GroupStatistics +// @Router /v1/groups/statistics [GET] +// @Security Bearer func (ctrl *V1Controller) HandleGroupStatistics() errchain.HandlerFunc { fn := func(r *http.Request) (repo.GroupStatistics, error) { auth := services.NewContext(r.Context()) @@ -65,14 +65,14 @@ func (ctrl *V1Controller) HandleGroupStatistics() errchain.HandlerFunc { // HandleGroupStatisticsPriceOverTime godoc // -// @Summary Get Purchase Price Statistics -// @Tags Statistics -// @Produce json -// @Success 200 {object} repo.ValueOverTime -// @Param start query string false "start date" -// @Param end query string false "end date" -// @Router /v1/groups/statistics/purchase-price [GET] -// @Security Bearer +// @Summary Get Purchase Price Statistics +// @Tags Statistics +// @Produce json +// @Success 200 {object} repo.ValueOverTime +// @Param start query string false "start date" +// @Param end query string false "end date" +// @Router /v1/groups/statistics/purchase-price [GET] +// @Security Bearer func (ctrl *V1Controller) HandleGroupStatisticsPriceOverTime() errchain.HandlerFunc { parseDate := func(datestr string, defaultDate time.Time) (time.Time, error) { if datestr == "" { diff --git a/backend/app/api/handlers/v1/v1_ctrl_user.go b/backend/app/api/handlers/v1/v1_ctrl_user.go index 5704fd911..a99c7b869 100644 --- a/backend/app/api/handlers/v1/v1_ctrl_user.go +++ b/backend/app/api/handlers/v1/v1_ctrl_user.go @@ -15,12 +15,12 @@ import ( // HandleUserRegistration godoc // -// @Summary Register New User -// @Tags User -// @Produce json -// @Param payload body services.UserRegistration true "User Data" -// @Success 204 -// @Router /v1/users/register [Post] +// @Summary Register New User +// @Tags User +// @Produce json +// @Param payload body services.UserRegistration true "User Data" +// @Success 204 +// @Router /v1/users/register [Post] func (ctrl *V1Controller) HandleUserRegistration() errchain.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) error { regData := services.UserRegistration{} @@ -46,12 +46,12 @@ func (ctrl *V1Controller) HandleUserRegistration() errchain.HandlerFunc { // HandleUserSelf godoc // -// @Summary Get User Self -// @Tags User -// @Produce json -// @Success 200 {object} Wrapped{item=repo.UserOut} -// @Router /v1/users/self [GET] -// @Security Bearer +// @Summary Get User Self +// @Tags User +// @Produce json +// @Success 200 {object} Wrapped{item=repo.UserOut} +// @Router /v1/users/self [GET] +// @Security Bearer func (ctrl *V1Controller) HandleUserSelf() errchain.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) error { token := services.UseTokenCtx(r.Context()) @@ -67,13 +67,13 @@ func (ctrl *V1Controller) HandleUserSelf() errchain.HandlerFunc { // HandleUserSelfUpdate godoc // -// @Summary Update Account -// @Tags User -// @Produce json -// @Param payload body repo.UserUpdate true "User Data" -// @Success 200 {object} Wrapped{item=repo.UserUpdate} -// @Router /v1/users/self [PUT] -// @Security Bearer +// @Summary Update Account +// @Tags User +// @Produce json +// @Param payload body repo.UserUpdate true "User Data" +// @Success 200 {object} Wrapped{item=repo.UserUpdate} +// @Router /v1/users/self [PUT] +// @Security Bearer func (ctrl *V1Controller) HandleUserSelfUpdate() errchain.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) error { updateData := repo.UserUpdate{} @@ -94,12 +94,12 @@ func (ctrl *V1Controller) HandleUserSelfUpdate() errchain.HandlerFunc { // HandleUserSelfDelete godoc // -// @Summary Delete Account -// @Tags User -// @Produce json -// @Success 204 -// @Router /v1/users/self [DELETE] -// @Security Bearer +// @Summary Delete Account +// @Tags User +// @Produce json +// @Success 204 +// @Router /v1/users/self [DELETE] +// @Security Bearer func (ctrl *V1Controller) HandleUserSelfDelete() errchain.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) error { if ctrl.isDemo { @@ -124,12 +124,12 @@ type ( // HandleUserSelfChangePassword godoc // -// @Summary Change Password -// @Tags User -// @Success 204 -// @Param payload body ChangePassword true "Password Payload" -// @Router /v1/users/change-password [PUT] -// @Security Bearer +// @Summary Change Password +// @Tags User +// @Success 204 +// @Param payload body ChangePassword true "Password Payload" +// @Router /v1/users/change-password [PUT] +// @Security Bearer func (ctrl *V1Controller) HandleUserSelfChangePassword() errchain.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) error { if ctrl.isDemo { diff --git a/backend/app/api/main.go b/backend/app/api/main.go index 6247fe6ad..96d0fdab9 100644 --- a/backend/app/api/main.go +++ b/backend/app/api/main.go @@ -46,15 +46,15 @@ func build() string { return fmt.Sprintf("%s, commit %s, built at %s", version, short, buildTime) } -// @title Homebox API -// @version 1.0 -// @description Track, Manage, and Organize your Things. -// @contact.name Don't -// @BasePath /api -// @securityDefinitions.apikey Bearer -// @in header -// @name Authorization -// @description "Type 'Bearer TOKEN' to correctly set the API Key" +// @title Homebox API +// @version 1.0 +// @description Track, Manage, and Organize your Things. +// @contact.name Don't +// @BasePath /api +// @securityDefinitions.apikey Bearer +// @in header +// @name Authorization +// @description "Type 'Bearer TOKEN' to correctly set the API Key" func main() { zerolog.ErrorStackMarshaler = pkgerrors.MarshalStack From 17e7e240705546f87c0ffbec0a7977be4242ee7a Mon Sep 17 00:00:00 2001 From: slid1amo2n3e4 Date: Tue, 8 Oct 2024 17:14:30 +0200 Subject: [PATCH 2/4] Implement syncing child's locations to that of parent. --- backend/app/api/static/docs/docs.go | 6 ++ backend/app/api/static/docs/swagger.json | 6 ++ backend/app/api/static/docs/swagger.yaml | 4 ++ backend/internal/data/ent/item.go | 13 +++- backend/internal/data/ent/item/item.go | 10 +++ backend/internal/data/ent/item/where.go | 15 +++++ backend/internal/data/ent/item_update.go | 34 ++++++++++ backend/internal/data/ent/migrate/schema.go | 13 ++-- backend/internal/data/ent/mutation.go | 56 +++++++++++++++- backend/internal/data/ent/runtime.go | 20 +++--- backend/internal/data/ent/schema/item.go | 2 + backend/internal/data/repo/repo_items.go | 67 +++++++++++++------ frontend/components/Form/Toggle.vue | 36 +++++++++++ frontend/lib/api/__test__/user/items.test.ts | 68 ++++++++++++++++++++ frontend/lib/api/types/data-contracts.ts | 2 + frontend/pages/item/[id]/index/edit.vue | 61 +++++++++++++++++- 16 files changed, 376 insertions(+), 37 deletions(-) create mode 100644 frontend/components/Form/Toggle.vue diff --git a/backend/app/api/static/docs/docs.go b/backend/app/api/static/docs/docs.go index 4e3a5db28..3311227d2 100644 --- a/backend/app/api/static/docs/docs.go +++ b/backend/app/api/static/docs/docs.go @@ -2242,6 +2242,9 @@ const docTemplate = `{ "soldTo": { "type": "string" }, + "syncChildItemsLocations": { + "type": "boolean" + }, "updatedAt": { "type": "string" }, @@ -2440,6 +2443,9 @@ const docTemplate = `{ "type": "string", "maxLength": 255 }, + "syncChildItemsLocations": { + "type": "boolean" + }, "warrantyDetails": { "type": "string" }, diff --git a/backend/app/api/static/docs/swagger.json b/backend/app/api/static/docs/swagger.json index 532020b81..ddec411cc 100644 --- a/backend/app/api/static/docs/swagger.json +++ b/backend/app/api/static/docs/swagger.json @@ -2235,6 +2235,9 @@ "soldTo": { "type": "string" }, + "syncChildItemsLocations": { + "type": "boolean" + }, "updatedAt": { "type": "string" }, @@ -2433,6 +2436,9 @@ "type": "string", "maxLength": 255 }, + "syncChildItemsLocations": { + "type": "boolean" + }, "warrantyDetails": { "type": "string" }, diff --git a/backend/app/api/static/docs/swagger.yaml b/backend/app/api/static/docs/swagger.yaml index 7939eb3db..fa9b7c77a 100644 --- a/backend/app/api/static/docs/swagger.yaml +++ b/backend/app/api/static/docs/swagger.yaml @@ -188,6 +188,8 @@ definitions: type: string soldTo: type: string + syncChildItemsLocations: + type: boolean updatedAt: type: string warrantyDetails: @@ -323,6 +325,8 @@ definitions: soldTo: maxLength: 255 type: string + syncChildItemsLocations: + type: boolean warrantyDetails: type: string warrantyExpires: diff --git a/backend/internal/data/ent/item.go b/backend/internal/data/ent/item.go index 682616b01..07712bd15 100644 --- a/backend/internal/data/ent/item.go +++ b/backend/internal/data/ent/item.go @@ -40,6 +40,8 @@ type Item struct { Archived bool `json:"archived,omitempty"` // AssetID holds the value of the "asset_id" field. AssetID int `json:"asset_id,omitempty"` + // SyncChildItemsLocations holds the value of the "sync_child_items_locations" field. + SyncChildItemsLocations bool `json:"sync_child_items_locations,omitempty"` // SerialNumber holds the value of the "serial_number" field. SerialNumber string `json:"serial_number,omitempty"` // ModelNumber holds the value of the "model_number" field. @@ -181,7 +183,7 @@ func (*Item) scanValues(columns []string) ([]any, error) { values := make([]any, len(columns)) for i := range columns { switch columns[i] { - case item.FieldInsured, item.FieldArchived, item.FieldLifetimeWarranty: + case item.FieldInsured, item.FieldArchived, item.FieldSyncChildItemsLocations, item.FieldLifetimeWarranty: values[i] = new(sql.NullBool) case item.FieldPurchasePrice, item.FieldSoldPrice: values[i] = new(sql.NullFloat64) @@ -280,6 +282,12 @@ func (i *Item) assignValues(columns []string, values []any) error { } else if value.Valid { i.AssetID = int(value.Int64) } + case item.FieldSyncChildItemsLocations: + if value, ok := values[j].(*sql.NullBool); !ok { + return fmt.Errorf("unexpected type %T for field sync_child_items_locations", values[j]) + } else if value.Valid { + i.SyncChildItemsLocations = value.Bool + } case item.FieldSerialNumber: if value, ok := values[j].(*sql.NullString); !ok { return fmt.Errorf("unexpected type %T for field serial_number", values[j]) @@ -485,6 +493,9 @@ func (i *Item) String() string { builder.WriteString("asset_id=") builder.WriteString(fmt.Sprintf("%v", i.AssetID)) builder.WriteString(", ") + builder.WriteString("sync_child_items_locations=") + builder.WriteString(fmt.Sprintf("%v", i.SyncChildItemsLocations)) + builder.WriteString(", ") builder.WriteString("serial_number=") builder.WriteString(i.SerialNumber) builder.WriteString(", ") diff --git a/backend/internal/data/ent/item/item.go b/backend/internal/data/ent/item/item.go index bd046791d..d3601c646 100644 --- a/backend/internal/data/ent/item/item.go +++ b/backend/internal/data/ent/item/item.go @@ -35,6 +35,8 @@ const ( FieldArchived = "archived" // FieldAssetID holds the string denoting the asset_id field in the database. FieldAssetID = "asset_id" + // FieldSyncChildItemsLocations holds the string denoting the sync_child_items_locations field in the database. + FieldSyncChildItemsLocations = "sync_child_items_locations" // FieldSerialNumber holds the string denoting the serial_number field in the database. FieldSerialNumber = "serial_number" // FieldModelNumber holds the string denoting the model_number field in the database. @@ -142,6 +144,7 @@ var Columns = []string{ FieldInsured, FieldArchived, FieldAssetID, + FieldSyncChildItemsLocations, FieldSerialNumber, FieldModelNumber, FieldManufacturer, @@ -209,6 +212,8 @@ var ( DefaultArchived bool // DefaultAssetID holds the default value on creation for the "asset_id" field. DefaultAssetID int + // DefaultSyncChildItemsLocations holds the default value on creation for the "sync_child_items_locations" field. + DefaultSyncChildItemsLocations bool // SerialNumberValidator is a validator for the "serial_number" field. It is called by the builders before save. SerialNumberValidator func(string) error // ModelNumberValidator is a validator for the "model_number" field. It is called by the builders before save. @@ -287,6 +292,11 @@ func ByAssetID(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldAssetID, opts...).ToFunc() } +// BySyncChildItemsLocations orders the results by the sync_child_items_locations field. +func BySyncChildItemsLocations(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldSyncChildItemsLocations, opts...).ToFunc() +} + // BySerialNumber orders the results by the serial_number field. func BySerialNumber(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldSerialNumber, opts...).ToFunc() diff --git a/backend/internal/data/ent/item/where.go b/backend/internal/data/ent/item/where.go index 61a8dae00..5166fa54b 100644 --- a/backend/internal/data/ent/item/where.go +++ b/backend/internal/data/ent/item/where.go @@ -106,6 +106,11 @@ func AssetID(v int) predicate.Item { return predicate.Item(sql.FieldEQ(FieldAssetID, v)) } +// SyncChildItemsLocations applies equality check predicate on the "sync_child_items_locations" field. It's identical to SyncChildItemsLocationsEQ. +func SyncChildItemsLocations(v bool) predicate.Item { + return predicate.Item(sql.FieldEQ(FieldSyncChildItemsLocations, v)) +} + // SerialNumber applies equality check predicate on the "serial_number" field. It's identical to SerialNumberEQ. func SerialNumber(v string) predicate.Item { return predicate.Item(sql.FieldEQ(FieldSerialNumber, v)) @@ -641,6 +646,16 @@ func AssetIDLTE(v int) predicate.Item { return predicate.Item(sql.FieldLTE(FieldAssetID, v)) } +// SyncChildItemsLocationsEQ applies the EQ predicate on the "sync_child_items_locations" field. +func SyncChildItemsLocationsEQ(v bool) predicate.Item { + return predicate.Item(sql.FieldEQ(FieldSyncChildItemsLocations, v)) +} + +// SyncChildItemsLocationsNEQ applies the NEQ predicate on the "sync_child_items_locations" field. +func SyncChildItemsLocationsNEQ(v bool) predicate.Item { + return predicate.Item(sql.FieldNEQ(FieldSyncChildItemsLocations, v)) +} + // SerialNumberEQ applies the EQ predicate on the "serial_number" field. func SerialNumberEQ(v string) predicate.Item { return predicate.Item(sql.FieldEQ(FieldSerialNumber, v)) diff --git a/backend/internal/data/ent/item_update.go b/backend/internal/data/ent/item_update.go index 16c3464bd..844eaf607 100644 --- a/backend/internal/data/ent/item_update.go +++ b/backend/internal/data/ent/item_update.go @@ -185,6 +185,20 @@ func (iu *ItemUpdate) AddAssetID(i int) *ItemUpdate { return iu } +// SetSyncChildItemsLocations sets the "sync_child_items_locations" field. +func (iu *ItemUpdate) SetSyncChildItemsLocations(b bool) *ItemUpdate { + iu.mutation.SetSyncChildItemsLocations(b) + return iu +} + +// SetNillableSyncChildItemsLocations sets the "sync_child_items_locations" field if the given value is not nil. +func (iu *ItemUpdate) SetNillableSyncChildItemsLocations(b *bool) *ItemUpdate { + if b != nil { + iu.SetSyncChildItemsLocations(*b) + } + return iu +} + // SetSerialNumber sets the "serial_number" field. func (iu *ItemUpdate) SetSerialNumber(s string) *ItemUpdate { iu.mutation.SetSerialNumber(s) @@ -836,6 +850,9 @@ func (iu *ItemUpdate) sqlSave(ctx context.Context) (n int, err error) { if value, ok := iu.mutation.AddedAssetID(); ok { _spec.AddField(item.FieldAssetID, field.TypeInt, value) } + if value, ok := iu.mutation.SyncChildItemsLocations(); ok { + _spec.SetField(item.FieldSyncChildItemsLocations, field.TypeBool, value) + } if value, ok := iu.mutation.SerialNumber(); ok { _spec.SetField(item.FieldSerialNumber, field.TypeString, value) } @@ -1393,6 +1410,20 @@ func (iuo *ItemUpdateOne) AddAssetID(i int) *ItemUpdateOne { return iuo } +// SetSyncChildItemsLocations sets the "sync_child_items_locations" field. +func (iuo *ItemUpdateOne) SetSyncChildItemsLocations(b bool) *ItemUpdateOne { + iuo.mutation.SetSyncChildItemsLocations(b) + return iuo +} + +// SetNillableSyncChildItemsLocations sets the "sync_child_items_locations" field if the given value is not nil. +func (iuo *ItemUpdateOne) SetNillableSyncChildItemsLocations(b *bool) *ItemUpdateOne { + if b != nil { + iuo.SetSyncChildItemsLocations(*b) + } + return iuo +} + // SetSerialNumber sets the "serial_number" field. func (iuo *ItemUpdateOne) SetSerialNumber(s string) *ItemUpdateOne { iuo.mutation.SetSerialNumber(s) @@ -2074,6 +2105,9 @@ func (iuo *ItemUpdateOne) sqlSave(ctx context.Context) (_node *Item, err error) if value, ok := iuo.mutation.AddedAssetID(); ok { _spec.AddField(item.FieldAssetID, field.TypeInt, value) } + if value, ok := iuo.mutation.SyncChildItemsLocations(); ok { + _spec.SetField(item.FieldSyncChildItemsLocations, field.TypeBool, value) + } if value, ok := iuo.mutation.SerialNumber(); ok { _spec.SetField(item.FieldSerialNumber, field.TypeString, value) } diff --git a/backend/internal/data/ent/migrate/schema.go b/backend/internal/data/ent/migrate/schema.go index 2b5883808..05fe8ec24 100644 --- a/backend/internal/data/ent/migrate/schema.go +++ b/backend/internal/data/ent/migrate/schema.go @@ -162,6 +162,7 @@ var ( {Name: "insured", Type: field.TypeBool, Default: false}, {Name: "archived", Type: field.TypeBool, Default: false}, {Name: "asset_id", Type: field.TypeInt, Default: 0}, + {Name: "sync_child_items_locations", Type: field.TypeBool, Default: false}, {Name: "serial_number", Type: field.TypeString, Nullable: true, Size: 255}, {Name: "model_number", Type: field.TypeString, Nullable: true, Size: 255}, {Name: "manufacturer", Type: field.TypeString, Nullable: true, Size: 255}, @@ -187,19 +188,19 @@ var ( ForeignKeys: []*schema.ForeignKey{ { Symbol: "items_groups_items", - Columns: []*schema.Column{ItemsColumns[24]}, + Columns: []*schema.Column{ItemsColumns[25]}, RefColumns: []*schema.Column{GroupsColumns[0]}, OnDelete: schema.Cascade, }, { Symbol: "items_items_children", - Columns: []*schema.Column{ItemsColumns[25]}, + Columns: []*schema.Column{ItemsColumns[26]}, RefColumns: []*schema.Column{ItemsColumns[0]}, OnDelete: schema.SetNull, }, { Symbol: "items_locations_items", - Columns: []*schema.Column{ItemsColumns[26]}, + Columns: []*schema.Column{ItemsColumns[27]}, RefColumns: []*schema.Column{LocationsColumns[0]}, OnDelete: schema.Cascade, }, @@ -213,17 +214,17 @@ var ( { Name: "item_manufacturer", Unique: false, - Columns: []*schema.Column{ItemsColumns[13]}, + Columns: []*schema.Column{ItemsColumns[14]}, }, { Name: "item_model_number", Unique: false, - Columns: []*schema.Column{ItemsColumns[12]}, + Columns: []*schema.Column{ItemsColumns[13]}, }, { Name: "item_serial_number", Unique: false, - Columns: []*schema.Column{ItemsColumns[11]}, + Columns: []*schema.Column{ItemsColumns[12]}, }, { Name: "item_archived", diff --git a/backend/internal/data/ent/mutation.go b/backend/internal/data/ent/mutation.go index 228de48ee..4f7e41e69 100644 --- a/backend/internal/data/ent/mutation.go +++ b/backend/internal/data/ent/mutation.go @@ -4085,6 +4085,7 @@ type ItemMutation struct { archived *bool asset_id *int addasset_id *int + sync_child_items_locations *bool serial_number *string model_number *string manufacturer *string @@ -4670,6 +4671,42 @@ func (m *ItemMutation) ResetAssetID() { m.addasset_id = nil } +// SetSyncChildItemsLocations sets the "sync_child_items_locations" field. +func (m *ItemMutation) SetSyncChildItemsLocations(b bool) { + m.sync_child_items_locations = &b +} + +// SyncChildItemsLocations returns the value of the "sync_child_items_locations" field in the mutation. +func (m *ItemMutation) SyncChildItemsLocations() (r bool, exists bool) { + v := m.sync_child_items_locations + if v == nil { + return + } + return *v, true +} + +// OldSyncChildItemsLocations returns the old "sync_child_items_locations" field's value of the Item entity. +// If the Item object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ItemMutation) OldSyncChildItemsLocations(ctx context.Context) (v bool, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldSyncChildItemsLocations is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldSyncChildItemsLocations requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldSyncChildItemsLocations: %w", err) + } + return oldValue.SyncChildItemsLocations, nil +} + +// ResetSyncChildItemsLocations resets all changes to the "sync_child_items_locations" field. +func (m *ItemMutation) ResetSyncChildItemsLocations() { + m.sync_child_items_locations = nil +} + // SetSerialNumber sets the "serial_number" field. func (m *ItemMutation) SetSerialNumber(s string) { m.serial_number = &s @@ -5729,7 +5766,7 @@ func (m *ItemMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *ItemMutation) Fields() []string { - fields := make([]string, 0, 23) + fields := make([]string, 0, 24) if m.created_at != nil { fields = append(fields, item.FieldCreatedAt) } @@ -5760,6 +5797,9 @@ func (m *ItemMutation) Fields() []string { if m.asset_id != nil { fields = append(fields, item.FieldAssetID) } + if m.sync_child_items_locations != nil { + fields = append(fields, item.FieldSyncChildItemsLocations) + } if m.serial_number != nil { fields = append(fields, item.FieldSerialNumber) } @@ -5827,6 +5867,8 @@ func (m *ItemMutation) Field(name string) (ent.Value, bool) { return m.Archived() case item.FieldAssetID: return m.AssetID() + case item.FieldSyncChildItemsLocations: + return m.SyncChildItemsLocations() case item.FieldSerialNumber: return m.SerialNumber() case item.FieldModelNumber: @@ -5882,6 +5924,8 @@ func (m *ItemMutation) OldField(ctx context.Context, name string) (ent.Value, er return m.OldArchived(ctx) case item.FieldAssetID: return m.OldAssetID(ctx) + case item.FieldSyncChildItemsLocations: + return m.OldSyncChildItemsLocations(ctx) case item.FieldSerialNumber: return m.OldSerialNumber(ctx) case item.FieldModelNumber: @@ -5987,6 +6031,13 @@ func (m *ItemMutation) SetField(name string, value ent.Value) error { } m.SetAssetID(v) return nil + case item.FieldSyncChildItemsLocations: + v, ok := value.(bool) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetSyncChildItemsLocations(v) + return nil case item.FieldSerialNumber: v, ok := value.(string) if !ok { @@ -6289,6 +6340,9 @@ func (m *ItemMutation) ResetField(name string) error { case item.FieldAssetID: m.ResetAssetID() return nil + case item.FieldSyncChildItemsLocations: + m.ResetSyncChildItemsLocations() + return nil case item.FieldSerialNumber: m.ResetSerialNumber() return nil diff --git a/backend/internal/data/ent/runtime.go b/backend/internal/data/ent/runtime.go index 12e507bd0..08aaf3f15 100644 --- a/backend/internal/data/ent/runtime.go +++ b/backend/internal/data/ent/runtime.go @@ -259,36 +259,40 @@ func init() { itemDescAssetID := itemFields[5].Descriptor() // item.DefaultAssetID holds the default value on creation for the asset_id field. item.DefaultAssetID = itemDescAssetID.Default.(int) + // itemDescSyncChildItemsLocations is the schema descriptor for sync_child_items_locations field. + itemDescSyncChildItemsLocations := itemFields[6].Descriptor() + // item.DefaultSyncChildItemsLocations holds the default value on creation for the sync_child_items_locations field. + item.DefaultSyncChildItemsLocations = itemDescSyncChildItemsLocations.Default.(bool) // itemDescSerialNumber is the schema descriptor for serial_number field. - itemDescSerialNumber := itemFields[6].Descriptor() + itemDescSerialNumber := itemFields[7].Descriptor() // item.SerialNumberValidator is a validator for the "serial_number" field. It is called by the builders before save. item.SerialNumberValidator = itemDescSerialNumber.Validators[0].(func(string) error) // itemDescModelNumber is the schema descriptor for model_number field. - itemDescModelNumber := itemFields[7].Descriptor() + itemDescModelNumber := itemFields[8].Descriptor() // item.ModelNumberValidator is a validator for the "model_number" field. It is called by the builders before save. item.ModelNumberValidator = itemDescModelNumber.Validators[0].(func(string) error) // itemDescManufacturer is the schema descriptor for manufacturer field. - itemDescManufacturer := itemFields[8].Descriptor() + itemDescManufacturer := itemFields[9].Descriptor() // item.ManufacturerValidator is a validator for the "manufacturer" field. It is called by the builders before save. item.ManufacturerValidator = itemDescManufacturer.Validators[0].(func(string) error) // itemDescLifetimeWarranty is the schema descriptor for lifetime_warranty field. - itemDescLifetimeWarranty := itemFields[9].Descriptor() + itemDescLifetimeWarranty := itemFields[10].Descriptor() // item.DefaultLifetimeWarranty holds the default value on creation for the lifetime_warranty field. item.DefaultLifetimeWarranty = itemDescLifetimeWarranty.Default.(bool) // itemDescWarrantyDetails is the schema descriptor for warranty_details field. - itemDescWarrantyDetails := itemFields[11].Descriptor() + itemDescWarrantyDetails := itemFields[12].Descriptor() // item.WarrantyDetailsValidator is a validator for the "warranty_details" field. It is called by the builders before save. item.WarrantyDetailsValidator = itemDescWarrantyDetails.Validators[0].(func(string) error) // itemDescPurchasePrice is the schema descriptor for purchase_price field. - itemDescPurchasePrice := itemFields[14].Descriptor() + itemDescPurchasePrice := itemFields[15].Descriptor() // item.DefaultPurchasePrice holds the default value on creation for the purchase_price field. item.DefaultPurchasePrice = itemDescPurchasePrice.Default.(float64) // itemDescSoldPrice is the schema descriptor for sold_price field. - itemDescSoldPrice := itemFields[17].Descriptor() + itemDescSoldPrice := itemFields[18].Descriptor() // item.DefaultSoldPrice holds the default value on creation for the sold_price field. item.DefaultSoldPrice = itemDescSoldPrice.Default.(float64) // itemDescSoldNotes is the schema descriptor for sold_notes field. - itemDescSoldNotes := itemFields[18].Descriptor() + itemDescSoldNotes := itemFields[19].Descriptor() // item.SoldNotesValidator is a validator for the "sold_notes" field. It is called by the builders before save. item.SoldNotesValidator = itemDescSoldNotes.Validators[0].(func(string) error) // itemDescID is the schema descriptor for id field. diff --git a/backend/internal/data/ent/schema/item.go b/backend/internal/data/ent/schema/item.go index 43f4859f2..b689933e4 100644 --- a/backend/internal/data/ent/schema/item.go +++ b/backend/internal/data/ent/schema/item.go @@ -51,6 +51,8 @@ func (Item) Fields() []ent.Field { Default(false), field.Int("asset_id"). Default(0), + field.Bool("sync_child_items_locations"). + Default(false), // ------------------------------------ // item identification diff --git a/backend/internal/data/repo/repo_items.go b/backend/internal/data/repo/repo_items.go index cffc910f4..a46421169 100644 --- a/backend/internal/data/repo/repo_items.go +++ b/backend/internal/data/repo/repo_items.go @@ -55,11 +55,11 @@ type ( } ItemCreate struct { - ImportRef string `json:"-"` - ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"` - Name string `json:"name" validate:"required,min=1,max=255"` - Description string `json:"description" validate:"max=1000"` - AssetID AssetID `json:"-"` + ImportRef string `json:"-"` + ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"` + Name string `json:"name" validate:"required,min=1,max=255"` + Description string `json:"description" validate:"max=1000"` + AssetID AssetID `json:"-"` // Edges LocationID uuid.UUID `json:"locationId"` @@ -67,14 +67,15 @@ type ( } ItemUpdate struct { - ParentID uuid.UUID `json:"parentId" extensions:"x-nullable,x-omitempty"` - ID uuid.UUID `json:"id"` - AssetID AssetID `json:"assetId" swaggertype:"string"` - Name string `json:"name" validate:"required,min=1,max=255"` - Description string `json:"description" validate:"max=1000"` - Quantity int `json:"quantity"` - Insured bool `json:"insured"` - Archived bool `json:"archived"` + ParentID uuid.UUID `json:"parentId" extensions:"x-nullable,x-omitempty"` + ID uuid.UUID `json:"id"` + AssetID AssetID `json:"assetId" swaggertype:"string"` + Name string `json:"name" validate:"required,min=1,max=255"` + Description string `json:"description" validate:"max=1000"` + Quantity int `json:"quantity"` + Insured bool `json:"insured"` + Archived bool `json:"archived"` + SyncChildItemsLocations bool `json:"syncChildItemsLocations"` // Edges LocationID uuid.UUID `json:"locationId"` @@ -137,6 +138,8 @@ type ( ItemSummary AssetID AssetID `json:"assetId,string"` + SyncChildItemsLocations bool `json:"syncChildItemsLocations"` + SerialNumber string `json:"serialNumber"` ModelNumber string `json:"modelNumber"` Manufacturer string `json:"manufacturer"` @@ -248,12 +251,13 @@ func mapItemOut(item *ent.Item) ItemOut { } return ItemOut{ - Parent: parent, - AssetID: AssetID(item.AssetID), - ItemSummary: mapItemSummary(item), - LifetimeWarranty: item.LifetimeWarranty, - WarrantyExpires: types.DateFromTime(item.WarrantyExpires), - WarrantyDetails: item.WarrantyDetails, + Parent: parent, + AssetID: AssetID(item.AssetID), + ItemSummary: mapItemSummary(item), + LifetimeWarranty: item.LifetimeWarranty, + WarrantyExpires: types.DateFromTime(item.WarrantyExpires), + WarrantyDetails: item.WarrantyDetails, + SyncChildItemsLocations: item.SyncChildItemsLocations, // Identification SerialNumber: item.SerialNumber, @@ -606,7 +610,8 @@ func (e *ItemsRepository) UpdateByGroup(ctx context.Context, gid uuid.UUID, data SetWarrantyExpires(data.WarrantyExpires.Time()). SetWarrantyDetails(data.WarrantyDetails). SetQuantity(data.Quantity). - SetAssetID(int(data.AssetID)) + SetAssetID(int(data.AssetID)). + SetSyncChildItemsLocations(data.SyncChildItemsLocations) currentLabels, err := e.db.Item.Query().Where(item.ID(data.ID)).QueryLabel().All(ctx) if err != nil { @@ -633,6 +638,28 @@ func (e *ItemsRepository) UpdateByGroup(ctx context.Context, gid uuid.UUID, data q.ClearParent() } + if data.SyncChildItemsLocations { + children, err := e.db.Item.Query().Where(item.ID(data.ID)).QueryChildren().All(ctx) + if err != nil { + return ItemOut{}, err + } + location := data.LocationID + + for _, child := range children { + child_location, err := child.QueryLocation().First(ctx) + if err != nil { + return ItemOut{}, err + } + + if location != child_location.ID { + err = child.Update().SetLocationID(location).Exec(ctx) + if err != nil { + return ItemOut{}, err + } + } + } + } + err = q.Exec(ctx) if err != nil { return ItemOut{}, err diff --git a/frontend/components/Form/Toggle.vue b/frontend/components/Form/Toggle.vue new file mode 100644 index 000000000..2e68d63e5 --- /dev/null +++ b/frontend/components/Form/Toggle.vue @@ -0,0 +1,36 @@ + + + + \ No newline at end of file diff --git a/frontend/lib/api/__test__/user/items.test.ts b/frontend/lib/api/__test__/user/items.test.ts index 4f8973f9a..e32a4baa3 100644 --- a/frontend/lib/api/__test__/user/items.test.ts +++ b/frontend/lib/api/__test__/user/items.test.ts @@ -193,4 +193,72 @@ describe("user should be able to create an item and add an attachment", () => { cleanup(); }); + + test("child items sync their location to their parent", async () => { + const api = await sharedUserClient(); + const [parentLocation, parentCleanup] = await useLocation(api); + const [childsLocation, childsCleanup] = await useLocation(api); + + const { response: parentResponse, data: parent } = await api.items.create({ + name: "parent-item", + labelIds: [], + description: "test-description", + locationId: parentLocation.id, + }); + expect(parentResponse.status).toBe(201); + expect(parent.id).toBeTruthy(); + + const { response: child1Response, data: child1Item } = await api.items.create({ + name: "child1-item", + labelIds: [], + description: "test-description", + locationId: childsLocation.id, + }); + expect(child1Response.status).toBe(201); + const child1ItemUpdate = { + parentId: parent.id, + ...child1Item, + locationId: child1Item.location?.id, + labelIds: [] + }; + const { response: child1UpdatedResponse, data: child1UpdatedData } = await api.items.update(child1Item.id, child1ItemUpdate as ItemUpdate); + expect(child1UpdatedResponse.status).toBe(200); + + const { response: child2Response, data: child2Item } = await api.items.create({ + name: "child2-item", + labelIds: [], + description: "test-description", + locationId: childsLocation.id, + }); + expect(child2Response.status).toBe(201); + const child2ItemUpdate = { + parentId: parent.id, + ...child2Item, + locationId: child2Item.location?.id, + labelIds: [] + } + const { response: child2UpdatedResponse, data: child2UpdatedData } = await api.items.update(child2Item.id, child2ItemUpdate as ItemUpdate); + expect(child2UpdatedResponse.status).toBe(200); + + const itemUpdate = { + parentId: null, + ...parent, + locationId: parentLocation.id, + labelIds: [], + syncChildItemsLocations: true + }; + const { response: updateResponse, data: updateData } = await api.items.update(parent.id, itemUpdate) + expect(updateResponse.status).toBe(200); + + const { response: child1FinalResponse, data: child1FinalData } = await api.items.get(child1Item.id); + expect(child1FinalResponse.status).toBe(200); + expect(child1FinalData.location?.id).toBe(parentLocation.id); + + const { response: child2FinalResponse, data: child2FinalData } = await api.items.get(child2Item.id); + expect(child2FinalResponse.status).toBe(200); + expect(child2FinalData.location?.id).toBe(parentLocation.id); + + parentCleanup(); + childsCleanup(); + }); }); diff --git a/frontend/lib/api/types/data-contracts.ts b/frontend/lib/api/types/data-contracts.ts index c664c93f5..6cfda968a 100644 --- a/frontend/lib/api/types/data-contracts.ts +++ b/frontend/lib/api/types/data-contracts.ts @@ -116,6 +116,7 @@ export interface ItemOut { /** Sold */ soldTime: Date | string; soldTo: string; + syncChildItemsLocations: boolean; updatedAt: Date | string; warrantyDetails: string; warrantyExpires: Date | string; @@ -190,6 +191,7 @@ export interface ItemUpdate { soldTime: Date | string; /** @maxLength 255 */ soldTo: string; + syncChildItemsLocations: boolean; warrantyDetails: string; warrantyExpires: Date | string; } diff --git a/frontend/pages/item/[id]/index/edit.vue b/frontend/pages/item/[id]/index/edit.vue index 1f3cd0bc0..e26acc37c 100644 --- a/frontend/pages/item/[id]/index/edit.vue +++ b/frontend/pages/item/[id]/index/edit.vue @@ -427,6 +427,63 @@ } } + async function maybeSyncWithParentLocation() { + if (parent.value && parent.value.id) { + const { data, error } = await api.items.get(parent.value.id); + + if (error) { + toast.error("Something went wrong trying to load parent data"); + } else { + if (data.syncChildItemsLocations) { + toast.info("Selected parent syncs its children's locations to its own. The location has been updated."); + item.value.location = data.location + } + } + } + } + + async function informAboutDesyncingLocationFromParent() { + if (parent.value && parent.value.id) { + const { data, error } = await api.items.get(parent.value.id); + + if (error) { + toast.error("Something went wrong trying to load parent data"); + } + + if (data.syncChildItemsLocations) { + toast.info("Changing location will de-sync it from the parent's location"); + } + } + } + + async function syncChildItemsLocations() { + if (!item.value.location?.id) { + toast.error("Failed to save item: no location selected"); + return; + } + + const payload: ItemUpdate = { + ...item.value, + locationId: item.value.location?.id, + labelIds: item.value.labels.map(l => l.id), + parentId: parent.value ? parent.value.id : null, + assetId: item.value.assetId, + }; + + const { error } = await api.items.update(itemId.value, payload); + + if (error) { + toast.error("Failed to save item"); + return; + } + + if (!item.value.syncChildItemsLocations) { + toast.success("Child items' locations will no longer be synced with this item.") + } else { + toast.success("Child items' locations have been synced with this item"); + } + } + onMounted(() => { window.addEventListener("keydown", keyboardSave); }); @@ -488,8 +545,9 @@
- + +
From f6d1f9c90d7e30bbffbe11fea75d18a9d85a8585 Mon Sep 17 00:00:00 2001 From: slid1amo2n3e4 Date: Tue, 8 Oct 2024 22:31:05 +0200 Subject: [PATCH 3/4] Fix 'should not use underscores in Go names' lint error --- backend/internal/data/repo/repo_items.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/internal/data/repo/repo_items.go b/backend/internal/data/repo/repo_items.go index a46421169..ff3562aaa 100644 --- a/backend/internal/data/repo/repo_items.go +++ b/backend/internal/data/repo/repo_items.go @@ -646,7 +646,7 @@ func (e *ItemsRepository) UpdateByGroup(ctx context.Context, gid uuid.UUID, data location := data.LocationID for _, child := range children { - child_location, err := child.QueryLocation().First(ctx) + childLocation, err := child.QueryLocation().First(ctx) if err != nil { return ItemOut{}, err } From 63eb287485edb1faa8653790f68d83d632b4d127 Mon Sep 17 00:00:00 2001 From: slid1amo2n3e4 Date: Tue, 10 Dec 2024 18:48:49 +0100 Subject: [PATCH 4/4] Make the tests pass, hopefully. --- backend/internal/data/ent/item_create.go | 25 ++++++++ backend/internal/data/repo/repo_items.go | 24 +++---- frontend/components/Form/Toggle.vue | 67 ++++++++++---------- frontend/lib/api/__test__/user/items.test.ts | 16 ++--- frontend/pages/item/[id]/index/edit.vue | 33 ++++++---- 5 files changed, 98 insertions(+), 67 deletions(-) diff --git a/backend/internal/data/ent/item_create.go b/backend/internal/data/ent/item_create.go index 97ed01ead..a9b79cdde 100644 --- a/backend/internal/data/ent/item_create.go +++ b/backend/internal/data/ent/item_create.go @@ -159,6 +159,20 @@ func (ic *ItemCreate) SetNillableAssetID(i *int) *ItemCreate { return ic } +// SetSyncChildItemsLocations sets the "sync_child_items_locations" field. +func (ic *ItemCreate) SetSyncChildItemsLocations(b bool) *ItemCreate { + ic.mutation.SetSyncChildItemsLocations(b) + return ic +} + +// SetNillableSyncChildItemsLocations sets the "sync_child_items_locations" field if the given value is not nil. +func (ic *ItemCreate) SetNillableSyncChildItemsLocations(b *bool) *ItemCreate { + if b != nil { + ic.SetSyncChildItemsLocations(*b) + } + return ic +} + // SetSerialNumber sets the "serial_number" field. func (ic *ItemCreate) SetSerialNumber(s string) *ItemCreate { ic.mutation.SetSerialNumber(s) @@ -538,6 +552,10 @@ func (ic *ItemCreate) defaults() { v := item.DefaultAssetID ic.mutation.SetAssetID(v) } + if _, ok := ic.mutation.SyncChildItemsLocations(); !ok { + v := item.DefaultSyncChildItemsLocations + ic.mutation.SetSyncChildItemsLocations(v) + } if _, ok := ic.mutation.LifetimeWarranty(); !ok { v := item.DefaultLifetimeWarranty ic.mutation.SetLifetimeWarranty(v) @@ -599,6 +617,9 @@ func (ic *ItemCreate) check() error { if _, ok := ic.mutation.AssetID(); !ok { return &ValidationError{Name: "asset_id", err: errors.New(`ent: missing required field "Item.asset_id"`)} } + if _, ok := ic.mutation.SyncChildItemsLocations(); !ok { + return &ValidationError{Name: "sync_child_items_locations", err: errors.New(`ent: missing required field "Item.sync_child_items_locations"`)} + } if v, ok := ic.mutation.SerialNumber(); ok { if err := item.SerialNumberValidator(v); err != nil { return &ValidationError{Name: "serial_number", err: fmt.Errorf(`ent: validator failed for field "Item.serial_number": %w`, err)} @@ -711,6 +732,10 @@ func (ic *ItemCreate) createSpec() (*Item, *sqlgraph.CreateSpec) { _spec.SetField(item.FieldAssetID, field.TypeInt, value) _node.AssetID = value } + if value, ok := ic.mutation.SyncChildItemsLocations(); ok { + _spec.SetField(item.FieldSyncChildItemsLocations, field.TypeBool, value) + _node.SyncChildItemsLocations = value + } if value, ok := ic.mutation.SerialNumber(); ok { _spec.SetField(item.FieldSerialNumber, field.TypeString, value) _node.SerialNumber = value diff --git a/backend/internal/data/repo/repo_items.go b/backend/internal/data/repo/repo_items.go index ff3562aaa..7cb915536 100644 --- a/backend/internal/data/repo/repo_items.go +++ b/backend/internal/data/repo/repo_items.go @@ -55,11 +55,11 @@ type ( } ItemCreate struct { - ImportRef string `json:"-"` - ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"` - Name string `json:"name" validate:"required,min=1,max=255"` - Description string `json:"description" validate:"max=1000"` - AssetID AssetID `json:"-"` + ImportRef string `json:"-"` + ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"` + Name string `json:"name" validate:"required,min=1,max=255"` + Description string `json:"description" validate:"max=1000"` + AssetID AssetID `json:"-"` // Edges LocationID uuid.UUID `json:"locationId"` @@ -67,11 +67,11 @@ type ( } 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"` - AssetID AssetID `json:"assetId" swaggertype:"string"` - Name string `json:"name" validate:"required,min=1,max=255"` - Description string `json:"description" validate:"max=1000"` + AssetID AssetID `json:"assetId" swaggertype:"string"` + Name string `json:"name" validate:"required,min=1,max=255"` + Description string `json:"description" validate:"max=1000"` Quantity int `json:"quantity"` Insured bool `json:"insured"` Archived bool `json:"archived"` @@ -93,12 +93,12 @@ type ( // Purchase PurchaseTime types.Date `json:"purchaseTime"` - PurchaseFrom string `json:"purchaseFrom" validate:"max=255"` + PurchaseFrom string `json:"purchaseFrom" validate:"max=255"` PurchasePrice float64 `json:"purchasePrice" extensions:"x-nullable,x-omitempty"` // Sold SoldTime types.Date `json:"soldTime"` - SoldTo string `json:"soldTo" validate:"max=255"` + SoldTo string `json:"soldTo" validate:"max=255"` SoldPrice float64 `json:"soldPrice" extensions:"x-nullable,x-omitempty"` SoldNotes string `json:"soldNotes"` @@ -651,7 +651,7 @@ func (e *ItemsRepository) UpdateByGroup(ctx context.Context, gid uuid.UUID, data return ItemOut{}, err } - if location != child_location.ID { + if location != childLocation.ID { err = child.Update().SetLocationID(location).Exec(ctx) if err != nil { return ItemOut{}, err diff --git a/frontend/components/Form/Toggle.vue b/frontend/components/Form/Toggle.vue index 2e68d63e5..e22decd56 100644 --- a/frontend/components/Form/Toggle.vue +++ b/frontend/components/Form/Toggle.vue @@ -1,36 +1,35 @@ - - - \ No newline at end of file + {{ label }} + + +
+ + +
+ + + diff --git a/frontend/lib/api/__test__/user/items.test.ts b/frontend/lib/api/__test__/user/items.test.ts index 83736a1b7..196c6c51a 100644 --- a/frontend/lib/api/__test__/user/items.test.ts +++ b/frontend/lib/api/__test__/user/items.test.ts @@ -205,7 +205,7 @@ describe("user should be able to create an item and add an attachment", () => { }); expect(parentResponse.status).toBe(201); expect(parent.id).toBeTruthy(); - + const { response: child1Response, data: child1Item } = await api.items.create({ name: "child1-item", labelIds: [], @@ -217,9 +217,9 @@ describe("user should be able to create an item and add an attachment", () => { parentId: parent.id, ...child1Item, locationId: child1Item.location?.id, - labelIds: [] + labelIds: [], }; - const { response: child1UpdatedResponse, data: child1UpdatedData } = await api.items.update(child1Item.id, child1ItemUpdate as ItemUpdate); + const { response: child1UpdatedResponse } = await api.items.update(child1Item.id, child1ItemUpdate as ItemUpdate); expect(child1UpdatedResponse.status).toBe(200); const { response: child2Response, data: child2Item } = await api.items.create({ @@ -233,9 +233,9 @@ describe("user should be able to create an item and add an attachment", () => { parentId: parent.id, ...child2Item, locationId: child2Item.location?.id, - labelIds: [] - } - const { response: child2UpdatedResponse, data: child2UpdatedData } = await api.items.update(child2Item.id, child2ItemUpdate as ItemUpdate); + labelIds: [], + }; + const { response: child2UpdatedResponse } = await api.items.update(child2Item.id, child2ItemUpdate as ItemUpdate); expect(child2UpdatedResponse.status).toBe(200); const itemUpdate = { @@ -243,9 +243,9 @@ describe("user should be able to create an item and add an attachment", () => { ...parent, locationId: parentLocation.id, labelIds: [], - syncChildItemsLocations: true + syncChildItemsLocations: true, }; - const { response: updateResponse, data: updateData } = await api.items.update(parent.id, itemUpdate) + const { response: updateResponse } = await api.items.update(parent.id, itemUpdate); expect(updateResponse.status).toBe(200); const { response: child1FinalResponse, data: child1FinalData } = await api.items.get(child1Item.id); diff --git a/frontend/pages/item/[id]/index/edit.vue b/frontend/pages/item/[id]/index/edit.vue index 5bda88b9c..27799fc28 100644 --- a/frontend/pages/item/[id]/index/edit.vue +++ b/frontend/pages/item/[id]/index/edit.vue @@ -468,16 +468,17 @@ async function maybeSyncWithParentLocation() { if (parent.value && parent.value.id) { - const { data, error } = await api.items.get(parent.value.id); - - if (error) { - toast.error("Something went wrong trying to load parent data"); - } else { - if (data.syncChildItemsLocations) { - toast.info("Selected parent syncs its children's locations to its own. The location has been updated."); - item.value.location = data.location - } - } + const { data, error } = await api.items.get(parent.value.id); + + if (error) { + toast.error("Something went wrong trying to load parent data"); + return; + } + + if (data.syncChildItemsLocations) { + toast.info("Selected parent syncs its children's locations to its own. The location has been updated."); + item.value.location = data.location; + } } } @@ -487,6 +488,7 @@ if (error) { toast.error("Something went wrong trying to load parent data"); + return; } if (data.syncChildItemsLocations) { @@ -500,7 +502,7 @@ toast.error("Failed to save item: no location selected"); return; } - + const payload: ItemUpdate = { ...item.value, locationId: item.value.location?.id, @@ -517,7 +519,7 @@ } if (!item.value.syncChildItemsLocations) { - toast.success("Child items' locations will no longer be synced with this item.") + toast.success("Child items' locations will no longer be synced with this item."); } else { toast.success("Child items' locations have been synced with this item"); } @@ -592,7 +594,12 @@
- +