diff --git a/app/models/design-layer/design-layer.create.server.ts b/app/models/design-layer/design-layer.create.server.ts new file mode 100644 index 00000000..5af26063 --- /dev/null +++ b/app/models/design-layer/design-layer.create.server.ts @@ -0,0 +1,18 @@ +import { type IntentActionArgs } from '#app/definitions/intent-action-args' +import { NewLayerDesignSchema } from '#app/schema/design-layer' +import { ValidateLayerParentSubmissionStrategy } from '#app/strategies/validate-submission.strategy' +import { validateEntitySubmission } from '#app/utils/conform-utils' + +export const validateLayerNewDesignSubmission = async ({ + userId, + formData, +}: IntentActionArgs) => { + const strategy = new ValidateLayerParentSubmissionStrategy() + + return await validateEntitySubmission({ + userId, + formData, + schema: NewLayerDesignSchema, + strategy, + }) +} diff --git a/app/models/design-layer/design-layer.delete.server.ts b/app/models/design-layer/design-layer.delete.server.ts new file mode 100644 index 00000000..e43a09c6 --- /dev/null +++ b/app/models/design-layer/design-layer.delete.server.ts @@ -0,0 +1,18 @@ +import { type IntentActionArgs } from '#app/definitions/intent-action-args' +import { DeleteLayerDesignSchema } from '#app/schema/design-layer' +import { ValidateLayerParentSubmissionStrategy } from '#app/strategies/validate-submission.strategy' +import { validateEntitySubmission } from '#app/utils/conform-utils' + +export const validateLayerDeleteDesignSubmission = async ({ + userId, + formData, +}: IntentActionArgs) => { + const strategy = new ValidateLayerParentSubmissionStrategy() + + return await validateEntitySubmission({ + userId, + formData, + schema: DeleteLayerDesignSchema, + strategy, + }) +} diff --git a/app/models/design-layer/design-layer.update.server.ts b/app/models/design-layer/design-layer.update.server.ts new file mode 100644 index 00000000..7040d4a2 --- /dev/null +++ b/app/models/design-layer/design-layer.update.server.ts @@ -0,0 +1,35 @@ +import { type IntentActionArgs } from '#app/definitions/intent-action-args' +import { + ReorderLayerDesignSchema, + ToggleVisibleLayerDesignSchema, +} from '#app/schema/design-layer' +import { ValidateLayerParentSubmissionStrategy } from '#app/strategies/validate-submission.strategy' +import { validateEntitySubmission } from '#app/utils/conform-utils' + +export const validateLayerToggleVisibeDesignSubmission = async ({ + userId, + formData, +}: IntentActionArgs) => { + const strategy = new ValidateLayerParentSubmissionStrategy() + + return await validateEntitySubmission({ + userId, + formData, + schema: ToggleVisibleLayerDesignSchema, + strategy, + }) +} + +export const validateLayerReorderDesignSubmission = async ({ + userId, + formData, +}: IntentActionArgs) => { + const strategy = new ValidateLayerParentSubmissionStrategy() + + return await validateEntitySubmission({ + userId, + formData, + schema: ReorderLayerDesignSchema, + strategy, + }) +} diff --git a/app/routes/resources+/api.v1+/artboard-version.design.update.visible.tsx b/app/routes/resources+/api.v1+/artboard-version.design.update.visible.tsx index 436d79b1..9eaec5c5 100644 --- a/app/routes/resources+/api.v1+/artboard-version.design.update.visible.tsx +++ b/app/routes/resources+/api.v1+/artboard-version.design.update.visible.tsx @@ -6,7 +6,7 @@ import { import { redirectBack } from 'remix-utils/redirect-back' import { validateArtboardVersionToggleVisibeDesignSubmission } from '#app/models/design-artboard-version/design-artboard-version.update.server' import { validateNoJS } from '#app/schema/form-data' -import { artboardDesignToggleVisibleService } from '#app/services/artboard/design/toggle-visible.service' +import { artboardVersionDesignToggleVisibleService } from '#app/services/artboard/version/design/toggle-visible.service' import { requireUserId } from '#app/utils/auth.server' // https://www.epicweb.dev/full-stack-components @@ -29,7 +29,7 @@ export async function action({ request }: DataFunctionArgs) { }) if (status === 'success') { - const { success } = await artboardDesignToggleVisibleService({ + const { success } = await artboardVersionDesignToggleVisibleService({ userId, ...submission.value, }) diff --git a/app/routes/resources+/api.v1+/layer.design.create.tsx b/app/routes/resources+/api.v1+/layer.design.create.tsx new file mode 100644 index 00000000..1f6e9767 --- /dev/null +++ b/app/routes/resources+/api.v1+/layer.design.create.tsx @@ -0,0 +1,50 @@ +import { + type LoaderFunctionArgs, + json, + type DataFunctionArgs, +} from '@remix-run/node' +import { redirectBack } from 'remix-utils/redirect-back' +import { validateLayerNewDesignSubmission } from '#app/models/design-layer/design-layer.create.server' +import { validateNoJS } from '#app/schema/form-data' +import { layerDesignCreateService } from '#app/services/layer/design/create.service' +import { requireUserId } from '#app/utils/auth.server' + +// https://www.epicweb.dev/full-stack-components + +export async function loader({ request }: LoaderFunctionArgs) { + await requireUserId(request) + return json({}) +} + +export async function action({ request }: DataFunctionArgs) { + const userId = await requireUserId(request) + const formData = await request.formData() + const noJS = validateNoJS({ formData }) + + let createSuccess = false + const { status, submission } = await validateLayerNewDesignSubmission({ + userId, + formData, + }) + + if (status === 'success') { + const { success } = await layerDesignCreateService({ + userId, + ...submission.value, + }) + createSuccess = success + } + + if (noJS) { + throw redirectBack(request, { + fallback: '/', + }) + } + + return json( + { status, submission }, + { + status: status === 'error' || !createSuccess ? 422 : 201, + }, + ) +} diff --git a/app/routes/resources+/api.v1+/layer.design.delete.tsx b/app/routes/resources+/api.v1+/layer.design.delete.tsx new file mode 100644 index 00000000..b948a0d8 --- /dev/null +++ b/app/routes/resources+/api.v1+/layer.design.delete.tsx @@ -0,0 +1,50 @@ +import { + type LoaderFunctionArgs, + json, + type DataFunctionArgs, +} from '@remix-run/node' +import { redirectBack } from 'remix-utils/redirect-back' +import { validateLayerDeleteDesignSubmission } from '#app/models/design-layer/design-layer.delete.server' +import { validateNoJS } from '#app/schema/form-data' +import { layerDesignDeleteService } from '#app/services/layer/design/delete.service' +import { requireUserId } from '#app/utils/auth.server' + +// https://www.epicweb.dev/full-stack-components + +export async function loader({ request }: LoaderFunctionArgs) { + await requireUserId(request) + return json({}) +} + +export async function action({ request }: DataFunctionArgs) { + const userId = await requireUserId(request) + const formData = await request.formData() + const noJS = validateNoJS({ formData }) + + let deleteSuccess = false + const { status, submission } = await validateLayerDeleteDesignSubmission({ + userId, + formData, + }) + + if (status === 'success') { + const { success } = await layerDesignDeleteService({ + userId, + ...submission.value, + }) + deleteSuccess = success + } + + if (noJS) { + throw redirectBack(request, { + fallback: '/', + }) + } + + return json( + { status, submission }, + { + status: status === 'error' || !deleteSuccess ? 404 : 200, + }, + ) +} diff --git a/app/routes/resources+/api.v1+/layer.design.update.order.tsx b/app/routes/resources+/api.v1+/layer.design.update.order.tsx new file mode 100644 index 00000000..d5b0f41a --- /dev/null +++ b/app/routes/resources+/api.v1+/layer.design.update.order.tsx @@ -0,0 +1,58 @@ +import { + type LoaderFunctionArgs, + json, + type DataFunctionArgs, +} from '@remix-run/node' +import { redirectBack } from 'remix-utils/redirect-back' +import { validateLayerReorderDesignSubmission } from '#app/models/design-layer/design-layer.update.server' +import { validateNoJS } from '#app/schema/form-data' +import { layerDesignMoveDownService } from '#app/services/layer/design/move-down.service' +import { layerDesignMoveUpService } from '#app/services/layer/design/move-up.service' +import { requireUserId } from '#app/utils/auth.server' + +// https://www.epicweb.dev/full-stack-components + +export async function loader({ request }: LoaderFunctionArgs) { + await requireUserId(request) + return json({}) +} + +export async function action({ request }: DataFunctionArgs) { + const userId = await requireUserId(request) + const formData = await request.formData() + const noJS = validateNoJS({ formData }) + + let updateSuccess = false + const { status, submission } = await validateLayerReorderDesignSubmission({ + userId, + formData, + }) + + if (status === 'success') { + const { direction } = submission.value + const { success } = + direction === 'up' + ? await layerDesignMoveUpService({ + userId, + ...submission.value, + }) + : await layerDesignMoveDownService({ + userId, + ...submission.value, + }) + updateSuccess = success + } + + if (noJS) { + throw redirectBack(request, { + fallback: '/', + }) + } + + return json( + { status, submission }, + { + status: status === 'error' || !updateSuccess ? 404 : 200, + }, + ) +} diff --git a/app/routes/resources+/api.v1+/layer.design.update.visible.tsx b/app/routes/resources+/api.v1+/layer.design.update.visible.tsx new file mode 100644 index 00000000..4e650ad6 --- /dev/null +++ b/app/routes/resources+/api.v1+/layer.design.update.visible.tsx @@ -0,0 +1,51 @@ +import { + type LoaderFunctionArgs, + json, + type DataFunctionArgs, +} from '@remix-run/node' +import { redirectBack } from 'remix-utils/redirect-back' +import { validateLayerToggleVisibeDesignSubmission } from '#app/models/design-layer/design-layer.update.server' +import { validateNoJS } from '#app/schema/form-data' +import { layerDesignToggleVisibleService } from '#app/services/layer/design/toggle-visible.service' +import { requireUserId } from '#app/utils/auth.server' + +// https://www.epicweb.dev/full-stack-components + +export async function loader({ request }: LoaderFunctionArgs) { + await requireUserId(request) + return json({}) +} + +export async function action({ request }: DataFunctionArgs) { + const userId = await requireUserId(request) + const formData = await request.formData() + const noJS = validateNoJS({ formData }) + + let updateSuccess = false + const { status, submission } = + await validateLayerToggleVisibeDesignSubmission({ + userId, + formData, + }) + + if (status === 'success') { + const { success } = await layerDesignToggleVisibleService({ + userId, + ...submission.value, + }) + updateSuccess = success + } + + if (noJS) { + throw redirectBack(request, { + fallback: '/', + }) + } + + return json( + { status, submission }, + { + status: status === 'error' || !updateSuccess ? 404 : 200, + }, + ) +} diff --git a/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.panel.artboard-version.tsx b/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.panel.artboard-version.tsx index 53900c3f..d827d0cb 100644 --- a/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.panel.artboard-version.tsx +++ b/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.panel.artboard-version.tsx @@ -1,7 +1,7 @@ import { type IArtboardVersionWithDesignsAndLayers } from '#app/models/artboard-version/artboard-version.server' import { PanelArtboardVersionBackground } from './sidebars.panel.artboard-version.background' -import { PanelArtboardVersionDesigns } from './sidebars.panel.artboard-version.designs' import { PanelArtboardVersionFrame } from './sidebars.panel.artboard-version.frame' +import { PanelArtboardVersionDesigns } from './sidebars.panel.designs.artboard-version' export const PanelArtboardVersion = ({ version, diff --git a/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.panel.artboard-version.designs.tsx b/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.panel.designs.artboard-version.tsx similarity index 100% rename from app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.panel.artboard-version.designs.tsx rename to app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.panel.designs.artboard-version.tsx diff --git a/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.panel.designs.layer.tsx b/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.panel.designs.layer.tsx new file mode 100644 index 00000000..ed03b762 --- /dev/null +++ b/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.panel.designs.layer.tsx @@ -0,0 +1,20 @@ +import { type ILayerWithDesigns } from '#app/models/layer.server' +import { DashboardPanelCreateLayerDesignTypeStrategy } from '#app/strategies/component/dashboard-panel/create-entity.strategy' +import { DashboardPanelLayerDesignActionStrategy } from '#app/strategies/component/dashboard-panel/entity-action/entity-action' +import { DashboardPanelUpdateLayerDesignTypeOrderStrategy } from '#app/strategies/component/dashboard-panel/update-entity-order.strategy' +import { PanelDesigns } from './sidebars.panel.designs' + +export const PanelLayerDesigns = ({ layer }: { layer: ILayerWithDesigns }) => { + const strategyEntityNew = new DashboardPanelCreateLayerDesignTypeStrategy() + const strategyReorder = new DashboardPanelUpdateLayerDesignTypeOrderStrategy() + const strategyActions = new DashboardPanelLayerDesignActionStrategy() + + return ( + + ) +} diff --git a/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.panel.layer.tsx b/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.panel.layer.tsx new file mode 100644 index 00000000..20da035e --- /dev/null +++ b/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.panel.layer.tsx @@ -0,0 +1,10 @@ +import { type ILayerWithDesigns } from '#app/models/layer.server' +import { PanelLayerDesigns } from './sidebars.panel.designs.layer' + +export const PanelLayer = ({ layer }: { layer: ILayerWithDesigns }) => { + return ( +
+ +
+ ) +} diff --git a/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.tsx b/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.tsx index 81961d85..54e3b355 100644 --- a/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.tsx +++ b/app/routes/sketch+/projects+/$projectSlug_+/artboards+/$artboardSlug+/__components/sidebars.tsx @@ -4,6 +4,7 @@ import { type IArtboardVersionWithDesignsAndLayers } from '#app/models/artboard- import { type ILayerWithDesigns } from '#app/models/layer.server' import { PanelArtboardVersion } from './sidebars.panel.artboard-version' import { PanelArtboardVersionLayers } from './sidebars.panel.artboard-version.layers' +import { PanelLayer } from './sidebars.panel.layer' export const SidebarLeft = ({ version, @@ -35,8 +36,11 @@ export const SidebarRight = ({ - {selectedLayer &&

yo

} - + {selectedLayer ? ( + + ) : ( + + )}
Actions here
diff --git a/app/schema/design-layer.ts b/app/schema/design-layer.ts index 11705076..89b4843e 100644 --- a/app/schema/design-layer.ts +++ b/app/schema/design-layer.ts @@ -20,7 +20,7 @@ export const LayerDesignDataCreateSchema = z.object({ export const NewLayerDesignSchema = z.object({ layerId: z.string(), type: z.nativeEnum(DesignTypeEnum), - visibleDesignsCount: z.number(), + visibleDesignsCount: z.number().optional(), }) export const DeleteLayerDesignSchema = z.object({ diff --git a/app/strategies/component/dashboard-panel/create-entity.strategy.ts b/app/strategies/component/dashboard-panel/create-entity.strategy.ts index 02bd1042..5ec152a7 100644 --- a/app/strategies/component/dashboard-panel/create-entity.strategy.ts +++ b/app/strategies/component/dashboard-panel/create-entity.strategy.ts @@ -3,6 +3,7 @@ import { type NewDesignSchemaType, } from '#app/schema/design' import { NewArtboardVersionDesignSchema } from '#app/schema/design-artboard-version' +import { NewLayerDesignSchema } from '#app/schema/design-layer' import { type entityParentIdTypeEnum, type NewEntitySchemaType, @@ -40,3 +41,13 @@ export class DashboardPanelCreateArtboardVersionLayerStrategy schema: NewLayerSchemaType = NewArtboardVersionLayerSchema iconText = 'Add New Layer' } + +export class DashboardPanelCreateLayerDesignTypeStrategy + implements IDashboardPanelCreateEntityStrategy +{ + route: RoutePath = Routes.RESOURCES.API.V1.LAYER.DESIGN.CREATE + parentTypeId: entityParentIdTypeEnum = DesignParentTypeIdEnum.LAYER_ID + formId: string = 'layer-design-create' + schema: NewDesignSchemaType = NewLayerDesignSchema + iconText = 'Add New Design' +} diff --git a/app/strategies/component/dashboard-panel/delete-entity.strategy.ts b/app/strategies/component/dashboard-panel/delete-entity.strategy.ts index ac3baa7e..223502ee 100644 --- a/app/strategies/component/dashboard-panel/delete-entity.strategy.ts +++ b/app/strategies/component/dashboard-panel/delete-entity.strategy.ts @@ -3,6 +3,7 @@ import { DesignParentTypeIdEnum, } from '#app/schema/design' import { DeleteArtboardVersionDesignSchema } from '#app/schema/design-artboard-version' +import { DeleteLayerDesignSchema } from '#app/schema/design-layer' import { type entityParentIdTypeEnum, type DeleteEntitySchemaType, @@ -45,3 +46,14 @@ export class DashboardPanelDeleteArtboardVersionLayerStrategy schema: DeleteLayerSchemaType = DeleteArtboardVersionLayerSchema iconText = 'Delete Layer' } + +export class DashboardPanelDeleteLayerDesignStrategy + implements IDashboardPanelDeleteEntityStrategy +{ + actionType: entityActionTypeEnum = EntityActionType.DELETE + route: RoutePath = Routes.RESOURCES.API.V1.LAYER.DESIGN.DELETE + parentTypeId: entityParentIdTypeEnum = DesignParentTypeIdEnum.LAYER_ID + formId: string = 'layer-design-delete' + schema: DeleteDesignSchemaType = DeleteLayerDesignSchema + iconText = 'Delete Design' +} diff --git a/app/strategies/component/dashboard-panel/entity-action/entity-action.ts b/app/strategies/component/dashboard-panel/entity-action/entity-action.ts index 605bdc3a..394bd893 100644 --- a/app/strategies/component/dashboard-panel/entity-action/entity-action.ts +++ b/app/strategies/component/dashboard-panel/entity-action/entity-action.ts @@ -1,11 +1,13 @@ import { DashboardPanelDeleteArtboardVersionDesignStrategy, + DashboardPanelDeleteLayerDesignStrategy, type IDashboardPanelDeleteEntityStrategy, } from '../delete-entity.strategy' import { DashboardPanelSelectArtboardVersionLayerStrategy } from '../select-entity.strategy' import { DashboardPanelUpdateArtboardVersionDesignVisibleStrategy, DashboardPanelUpdateArtboardVersionLayerVisibleStrategy, + DashboardPanelUpdateLayerDesignVisibleStrategy, type IDashboardPanelUpdateEntityVisibleStrategy, } from '../update-entity-visible.strategy' @@ -47,3 +49,15 @@ export class DashboardPanelArtboardVersionLayerActionStrategy return [strategyToggleVisible, strategySelect] } } + +export class DashboardPanelLayerDesignActionStrategy + implements IDashboardPanelEntityActionStrategy +{ + getPanelActions(): IPanelEntityActionStrategy[] { + const strategyToggleVisible = + new DashboardPanelUpdateLayerDesignVisibleStrategy() + const strategyDelete = new DashboardPanelDeleteLayerDesignStrategy() + + return [strategyToggleVisible, strategyDelete] + } +} diff --git a/app/strategies/component/dashboard-panel/update-entity-order.strategy.ts b/app/strategies/component/dashboard-panel/update-entity-order.strategy.ts index e51b0b29..3cdff8e5 100644 --- a/app/strategies/component/dashboard-panel/update-entity-order.strategy.ts +++ b/app/strategies/component/dashboard-panel/update-entity-order.strategy.ts @@ -3,6 +3,7 @@ import { type ReorderDesignSchemaType, } from '#app/schema/design' import { ReorderArtboardVersionDesignSchema } from '#app/schema/design-artboard-version' +import { ReorderLayerDesignSchema } from '#app/schema/design-layer' import { type ReorderEntitySchemaType, type entityParentIdTypeEnum, @@ -41,3 +42,13 @@ export class DashboardPanelUpdateArtboardVersionLayerTypeOrderStrategy schema: ReorderLayerSchemaType = ReorderArtboardVersionLayerSchema iconText = 'Move' } + +export class DashboardPanelUpdateLayerDesignTypeOrderStrategy + implements IDashboardPanelUpdateEntityOrderStrategy +{ + route: RoutePath = Routes.RESOURCES.API.V1.LAYER.DESIGN.UPDATE.ORDER + parentTypeId: entityParentIdTypeEnum = DesignParentTypeIdEnum.LAYER_ID + formId: string = 'layer-design-update-order' + schema: ReorderDesignSchemaType = ReorderLayerDesignSchema + iconText = 'Move' +} diff --git a/app/strategies/component/dashboard-panel/update-entity-visible.strategy.ts b/app/strategies/component/dashboard-panel/update-entity-visible.strategy.ts index feff0d0d..0ff4fa26 100644 --- a/app/strategies/component/dashboard-panel/update-entity-visible.strategy.ts +++ b/app/strategies/component/dashboard-panel/update-entity-visible.strategy.ts @@ -3,6 +3,7 @@ import { type ToggleVisibleDesignSchemaType, } from '#app/schema/design' import { ToggleVisibleArtboardVersionDesignSchema } from '#app/schema/design-artboard-version' +import { ToggleVisibleLayerDesignSchema } from '#app/schema/design-layer' import { type entityActionTypeEnum, type ToggleVisibleEntitySchemaType, @@ -48,3 +49,14 @@ export class DashboardPanelUpdateArtboardVersionLayerVisibleStrategy schema: ToggleVisibleLayerSchemaType = ToggleVisibleArtboardVersionLayerSchema iconText = 'Design' } + +export class DashboardPanelUpdateLayerDesignVisibleStrategy + implements IDashboardPanelUpdateEntityVisibleStrategy +{ + actionType: entityActionTypeEnum = EntityActionType.TOGGLE_VISIBLE + route: RoutePath = Routes.RESOURCES.API.V1.LAYER.DESIGN.UPDATE.VISIBLE + parentTypeId: entityParentIdTypeEnum = DesignParentTypeIdEnum.LAYER_ID + formId: string = 'layer-design-update-visible' + schema: ToggleVisibleDesignSchemaType = ToggleVisibleLayerDesignSchema + iconText = 'Design' +} diff --git a/app/strategies/validate-submission.strategy.ts b/app/strategies/validate-submission.strategy.ts index 5e84e9ad..dd4a3fbb 100644 --- a/app/strategies/validate-submission.strategy.ts +++ b/app/strategies/validate-submission.strategy.ts @@ -29,7 +29,7 @@ export class ValidateArtboardVersionSubmissionStrategy const artboardVersion = await getArtboardVersion({ where: { id, ownerId: userId }, }) - if (!artboardVersion) ctx.addIssue(addNotFoundIssue('Artboard')) + if (!artboardVersion) ctx.addIssue(addNotFoundIssue('ArtboardVersion')) } } @@ -49,7 +49,7 @@ export class ValidateArtboardVersionParentSubmissionStrategy const artboardVersion = await getArtboardVersion({ where: { id: artboardVersionId, ownerId: userId }, }) - if (!artboardVersion) ctx.addIssue(addNotFoundIssue('Artboard')) + if (!artboardVersion) ctx.addIssue(addNotFoundIssue('ArtboardVersion')) } } @@ -89,6 +89,26 @@ export class ValidateLayerSubmissionStrategy const layer = await getLayer({ where: { id, ownerId: userId }, }) - if (!layer) ctx.addIssue(addNotFoundIssue('Artboard')) + if (!layer) ctx.addIssue(addNotFoundIssue('Layer')) + } +} + +export class ValidateLayerParentSubmissionStrategy + implements IValidateSubmissionStrategy +{ + async validateFormDataEntity({ + userId, + data, + ctx, + }: { + userId: User['id'] + data: any + ctx: any + }): Promise { + const { layerId } = data + const layer = await getLayer({ + where: { id: layerId, ownerId: userId }, + }) + if (!layer) ctx.addIssue(addNotFoundIssue('Layer')) } } diff --git a/app/utils/routes.utils.ts b/app/utils/routes.utils.ts index b5b06d57..7f250f8f 100644 --- a/app/utils/routes.utils.ts +++ b/app/utils/routes.utils.ts @@ -127,6 +127,22 @@ import { loader as apiV1DesignTypeTemplateStyleLoader, action as apiV1DesignTypeTemplateStyleAction, } from '#app/routes/resources+/api.v1+/design.type.template.update.style' +import { + loader as apiV1LayerDesignCreateLoader, + action as apiV1LayerDesignCreateAction, +} from '#app/routes/resources+/api.v1+/layer.design.create' +import { + loader as apiV1LayerDesignDeleteLoader, + action as apiV1LayerDesignDeleteAction, +} from '#app/routes/resources+/api.v1+/layer.design.delete' +import { + loader as apiV1LayerDesignUpdateOrderLoader, + action as apiV1LayerDesignUpdateOrderAction, +} from '#app/routes/resources+/api.v1+/layer.design.update.order' +import { + loader as apiV1LayerDesignUpdateVisibleLoader, + action as apiV1LayerDesignUpdateVisibleAction, +} from '#app/routes/resources+/api.v1+/layer.design.update.visible' import { loader as apiV1LayerUpdateDescriptionLoader, action as apiV1LayerUpdateDescriptionAction, @@ -229,6 +245,14 @@ export const Routes = { DESCRIPTION: `${pathBase}/layer/update/description`, NAME: `${pathBase}/layer/update/name`, }, + DESIGN: { + CREATE: `${pathBase}/layer/design/create`, + DELETE: `${pathBase}/layer/design/delete`, + UPDATE: { + VISIBLE: `${pathBase}/layer/design/update/visible`, + ORDER: `${pathBase}/layer/design/update/order`, + }, + }, }, }, }, @@ -260,9 +284,6 @@ export interface ApiRouteLoaders { .ORDER]: typeof apiV1ArtboardVersionLayerUpdateOrderLoader [Routes.RESOURCES.API.V1.ARTBOARD_VERSION.LAYER.UPDATE .SELECTED]: typeof apiV1ArtboardVersionLayerUpdateSelectedLoader - [Routes.RESOURCES.API.V1.LAYER.UPDATE - .DESCRIPTION]: typeof apiV1LayerUpdateDescriptionLoader - [Routes.RESOURCES.API.V1.LAYER.UPDATE.NAME]: typeof apiV1LayerUpdateNameLoader [Routes.RESOURCES.API.V1.DESIGN.TYPE.LAYOUT.UPDATE .COUNT]: typeof apiV1DesignTypeLayoutCountLoader [Routes.RESOURCES.API.V1.DESIGN.TYPE.LAYOUT.UPDATE @@ -303,6 +324,17 @@ export interface ApiRouteLoaders { .BASIS]: typeof apiV1DesignTypeRotateBasisLoader [Routes.RESOURCES.API.V1.DESIGN.TYPE.TEMPLATE.UPDATE .STYLE]: typeof apiV1DesignTypeTemplateStyleLoader + [Routes.RESOURCES.API.V1.LAYER.UPDATE + .DESCRIPTION]: typeof apiV1LayerUpdateDescriptionLoader + [Routes.RESOURCES.API.V1.LAYER.UPDATE.NAME]: typeof apiV1LayerUpdateNameLoader + [Routes.RESOURCES.API.V1.LAYER.DESIGN + .CREATE]: typeof apiV1LayerDesignCreateLoader + [Routes.RESOURCES.API.V1.LAYER.DESIGN + .DELETE]: typeof apiV1LayerDesignDeleteLoader + [Routes.RESOURCES.API.V1.LAYER.DESIGN.UPDATE + .VISIBLE]: typeof apiV1LayerDesignUpdateVisibleLoader + [Routes.RESOURCES.API.V1.LAYER.DESIGN.UPDATE + .ORDER]: typeof apiV1LayerDesignUpdateOrderLoader } export const loaders: ApiRouteLoaders = { @@ -330,9 +362,6 @@ export const loaders: ApiRouteLoaders = { apiV1ArtboardVersionLayerUpdateOrderLoader, [Routes.RESOURCES.API.V1.ARTBOARD_VERSION.LAYER.UPDATE.SELECTED]: apiV1ArtboardVersionLayerUpdateSelectedLoader, - [Routes.RESOURCES.API.V1.LAYER.UPDATE.DESCRIPTION]: - apiV1LayerUpdateDescriptionLoader, - [Routes.RESOURCES.API.V1.LAYER.UPDATE.NAME]: apiV1LayerUpdateNameLoader, [Routes.RESOURCES.API.V1.DESIGN.TYPE.LAYOUT.UPDATE.COUNT]: apiV1DesignTypeLayoutCountLoader, [Routes.RESOURCES.API.V1.DESIGN.TYPE.LAYOUT.UPDATE.ROWS]: @@ -373,6 +402,15 @@ export const loaders: ApiRouteLoaders = { apiV1DesignTypeRotateBasisLoader, [Routes.RESOURCES.API.V1.DESIGN.TYPE.TEMPLATE.UPDATE.STYLE]: apiV1DesignTypeTemplateStyleLoader, + [Routes.RESOURCES.API.V1.LAYER.UPDATE.DESCRIPTION]: + apiV1LayerUpdateDescriptionLoader, + [Routes.RESOURCES.API.V1.LAYER.UPDATE.NAME]: apiV1LayerUpdateNameLoader, + [Routes.RESOURCES.API.V1.LAYER.DESIGN.CREATE]: apiV1LayerDesignCreateLoader, + [Routes.RESOURCES.API.V1.LAYER.DESIGN.DELETE]: apiV1LayerDesignDeleteLoader, + [Routes.RESOURCES.API.V1.LAYER.DESIGN.UPDATE.VISIBLE]: + apiV1LayerDesignUpdateVisibleLoader, + [Routes.RESOURCES.API.V1.LAYER.DESIGN.UPDATE.ORDER]: + apiV1LayerDesignUpdateOrderLoader, } export function getLoaderType( @@ -408,9 +446,6 @@ export interface ApiRouteActions { .ORDER]: typeof apiV1ArtboardVersionLayerUpdateOrderAction [Routes.RESOURCES.API.V1.ARTBOARD_VERSION.LAYER.UPDATE .SELECTED]: typeof apiV1ArtboardVersionLayerUpdateSelectedAction - [Routes.RESOURCES.API.V1.LAYER.UPDATE - .DESCRIPTION]: typeof apiV1LayerUpdateDescriptionAction - [Routes.RESOURCES.API.V1.LAYER.UPDATE.NAME]: typeof apiV1LayerUpdateNameAction [Routes.RESOURCES.API.V1.DESIGN.TYPE.LAYOUT.UPDATE .COUNT]: typeof apiV1DesignTypeLayoutCountAction [Routes.RESOURCES.API.V1.DESIGN.TYPE.LAYOUT.UPDATE @@ -451,6 +486,17 @@ export interface ApiRouteActions { .BASIS]: typeof apiV1DesignTypeRotateBasisAction [Routes.RESOURCES.API.V1.DESIGN.TYPE.TEMPLATE.UPDATE .STYLE]: typeof apiV1DesignTypeTemplateStyleAction + [Routes.RESOURCES.API.V1.LAYER.UPDATE + .DESCRIPTION]: typeof apiV1LayerUpdateDescriptionAction + [Routes.RESOURCES.API.V1.LAYER.UPDATE.NAME]: typeof apiV1LayerUpdateNameAction + [Routes.RESOURCES.API.V1.LAYER.DESIGN + .CREATE]: typeof apiV1LayerDesignCreateAction + [Routes.RESOURCES.API.V1.LAYER.DESIGN + .DELETE]: typeof apiV1LayerDesignDeleteAction + [Routes.RESOURCES.API.V1.LAYER.DESIGN.UPDATE + .VISIBLE]: typeof apiV1LayerDesignUpdateVisibleAction + [Routes.RESOURCES.API.V1.LAYER.DESIGN.UPDATE + .ORDER]: typeof apiV1LayerDesignUpdateOrderAction } export const actions: ApiRouteActions = { @@ -478,9 +524,6 @@ export const actions: ApiRouteActions = { apiV1ArtboardVersionLayerUpdateOrderAction, [Routes.RESOURCES.API.V1.ARTBOARD_VERSION.LAYER.UPDATE.SELECTED]: apiV1ArtboardVersionLayerUpdateSelectedAction, - [Routes.RESOURCES.API.V1.LAYER.UPDATE.DESCRIPTION]: - apiV1LayerUpdateDescriptionAction, - [Routes.RESOURCES.API.V1.LAYER.UPDATE.NAME]: apiV1LayerUpdateNameAction, [Routes.RESOURCES.API.V1.DESIGN.TYPE.LAYOUT.UPDATE.COUNT]: apiV1DesignTypeLayoutCountAction, [Routes.RESOURCES.API.V1.DESIGN.TYPE.LAYOUT.UPDATE.ROWS]: @@ -521,6 +564,15 @@ export const actions: ApiRouteActions = { apiV1DesignTypeRotateBasisAction, [Routes.RESOURCES.API.V1.DESIGN.TYPE.TEMPLATE.UPDATE.STYLE]: apiV1DesignTypeTemplateStyleAction, + [Routes.RESOURCES.API.V1.LAYER.UPDATE.DESCRIPTION]: + apiV1LayerUpdateDescriptionAction, + [Routes.RESOURCES.API.V1.LAYER.UPDATE.NAME]: apiV1LayerUpdateNameAction, + [Routes.RESOURCES.API.V1.LAYER.DESIGN.CREATE]: apiV1LayerDesignCreateAction, + [Routes.RESOURCES.API.V1.LAYER.DESIGN.DELETE]: apiV1LayerDesignDeleteAction, + [Routes.RESOURCES.API.V1.LAYER.DESIGN.UPDATE.VISIBLE]: + apiV1LayerDesignUpdateVisibleAction, + [Routes.RESOURCES.API.V1.LAYER.DESIGN.UPDATE.ORDER]: + apiV1LayerDesignUpdateOrderAction, } export function getActionType(