@stacksjs/defaults 0.70.57 → 0.70.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/Actions/AI/AskAction.ts +40 -0
- package/app/Actions/AI/SummaryAction.ts +40 -0
- package/app/Actions/Auth/AuthUserAction.ts +13 -0
- package/app/Actions/Auth/CreateTokenAction.ts +64 -0
- package/app/Actions/Auth/DisableTwoFactorAction.ts +37 -0
- package/app/Actions/Auth/EnableTwoFactorAction.ts +37 -0
- package/app/Actions/Auth/GenerateAuthenticationAction.ts +51 -0
- package/app/Actions/Auth/GenerateRegistrationAction.ts +53 -0
- package/app/Actions/Auth/GenerateTwoFactorSecretAction.ts +26 -0
- package/app/Actions/Auth/ListTokensAction.ts +30 -0
- package/app/Actions/Auth/LoginAction.ts +73 -0
- package/app/Actions/Auth/LogoutAction.ts +16 -0
- package/app/Actions/Auth/LogoutAllAction.ts +28 -0
- package/app/Actions/Auth/RefreshTokenAction.ts +39 -0
- package/app/Actions/Auth/RegisterAction.ts +57 -0
- package/app/Actions/Auth/ResendVerificationAction.ts +24 -0
- package/app/Actions/Auth/RevokeTokenAction.ts +43 -0
- package/app/Actions/Auth/TestAbilitiesAction.ts +61 -0
- package/app/Actions/Auth/VerifyAuthenticationAction.ts +94 -0
- package/app/Actions/Auth/VerifyEmailAction.ts +25 -0
- package/app/Actions/Auth/VerifyRegistrationAction.ts +59 -0
- package/app/Actions/Auth/VerifyTwoFactorLoginAction.ts +57 -0
- package/app/Actions/Billable/CheckoutAction.ts +25 -0
- package/app/Actions/Buddy/BuddyBrowseAction.ts +34 -0
- package/app/Actions/Buddy/BuddyCancelAction.ts +32 -0
- package/app/Actions/Buddy/BuddyCommitAction.ts +25 -0
- package/app/Actions/Buddy/BuddyGitHubConnectAction.ts +40 -0
- package/app/Actions/Buddy/BuddyGitHubDisconnectAction.ts +19 -0
- package/app/Actions/Buddy/BuddyProcessAction.ts +65 -0
- package/app/Actions/Buddy/BuddyProcessStreamAction.ts +128 -0
- package/app/Actions/Buddy/BuddyPushAction.ts +21 -0
- package/app/Actions/Buddy/BuddyRepoOpenAction.ts +44 -0
- package/app/Actions/Buddy/BuddyRepoValidateAction.ts +35 -0
- package/app/Actions/Buddy/BuddySettingsAction.ts +21 -0
- package/app/Actions/Buddy/BuddySettingsUpdateAction.ts +46 -0
- package/app/Actions/Buddy/BuddyStateAction.ts +28 -0
- package/app/Actions/Buddy/BuddyTitleAction.ts +49 -0
- package/app/Actions/Buddy/CommandsAction.ts +802 -0
- package/app/Actions/Buddy/JobCancelAction.ts +32 -0
- package/app/Actions/Buddy/JobRetryAction.ts +49 -0
- package/app/Actions/Buddy/JobsListAction.ts +141 -0
- package/app/Actions/Buddy/ScheduleListAction.ts +52 -0
- package/app/Actions/Buddy/VersionsAction.ts +12 -0
- package/app/Actions/Cms/AuthorDestroyAction.ts +21 -0
- package/app/Actions/Cms/AuthorIndexAction.ts +14 -0
- package/app/Actions/Cms/AuthorShowAction.ts +19 -0
- package/app/Actions/Cms/AuthorStoreAction.ts +20 -0
- package/app/Actions/Cms/AuthorUpdateAction.ts +24 -0
- package/app/Actions/Cms/CategorizableDestroyAction.ts +16 -0
- package/app/Actions/Cms/CategorizableIndexAction.ts +14 -0
- package/app/Actions/Cms/CategorizableShowAction.ts +16 -0
- package/app/Actions/Cms/CategorizableStoreAction.ts +42 -0
- package/app/Actions/Cms/CategorizableUpdateAction.ts +38 -0
- package/app/Actions/Cms/CommentDestroyAction.ts +16 -0
- package/app/Actions/Cms/CommentIndexAction.ts +17 -0
- package/app/Actions/Cms/CommentShowAction.ts +16 -0
- package/app/Actions/Cms/CommentStoreAction.ts +39 -0
- package/app/Actions/Cms/CommentUpdateAction.ts +37 -0
- package/app/Actions/Cms/PageDestroyAction.ts +16 -0
- package/app/Actions/Cms/PageIndexAction.ts +14 -0
- package/app/Actions/Cms/PageStoreAction.ts +31 -0
- package/app/Actions/Cms/PageUpdateAction.ts +27 -0
- package/app/Actions/Cms/PostDestroyAction.ts +17 -0
- package/app/Actions/Cms/PostIndexAction.ts +14 -0
- package/app/Actions/Cms/PostShowAction.ts +16 -0
- package/app/Actions/Cms/PostStoreAction.ts +37 -0
- package/app/Actions/Cms/PostUpdateAction.ts +32 -0
- package/app/Actions/Cms/PostViewsUpdateAction.ts +34 -0
- package/app/Actions/Cms/RssFeedAction.ts +59 -0
- package/app/Actions/Cms/SitemapAction.ts +60 -0
- package/app/Actions/Cms/TaggableDestroyAction.ts +16 -0
- package/app/Actions/Cms/TaggableIndexAction.ts +14 -0
- package/app/Actions/Cms/TaggableShowAction.ts +16 -0
- package/app/Actions/Cms/TaggableStoreAction.ts +36 -0
- package/app/Actions/Cms/TaggableUpdateAction.ts +37 -0
- package/app/Actions/Commerce/CouponDestroyAction.ts +18 -0
- package/app/Actions/Commerce/CouponIndexAction.ts +16 -0
- package/app/Actions/Commerce/CouponShowAction.ts +18 -0
- package/app/Actions/Commerce/CouponStoreAction.ts +21 -0
- package/app/Actions/Commerce/CouponUpdateAction.ts +31 -0
- package/app/Actions/Commerce/CustomerDestroyAction.ts +16 -0
- package/app/Actions/Commerce/CustomerIndexAction.ts +15 -0
- package/app/Actions/Commerce/CustomerShowAction.ts +18 -0
- package/app/Actions/Commerce/CustomerStoreAction.ts +29 -0
- package/app/Actions/Commerce/CustomerUpdateAction.ts +27 -0
- package/app/Actions/Commerce/DriverDestroyAction.ts +18 -0
- package/app/Actions/Commerce/GiftCardDestroyAction.ts +18 -0
- package/app/Actions/Commerce/GiftCardIndexAction.ts +16 -0
- package/app/Actions/Commerce/GiftCardShowAction.ts +18 -0
- package/app/Actions/Commerce/GiftCardStatsAction.ts +30 -0
- package/app/Actions/Commerce/GiftCardStoreAction.ts +35 -0
- package/app/Actions/Commerce/GiftCardUpdateAction.ts +26 -0
- package/app/Actions/Commerce/GiftCardUpdateBalanceAction.ts +36 -0
- package/app/Actions/Commerce/OrderDestroyAction.ts +18 -0
- package/app/Actions/Commerce/OrderExportAction.ts +15 -0
- package/app/Actions/Commerce/OrderIndexAction.ts +15 -0
- package/app/Actions/Commerce/OrderShowAction.ts +18 -0
- package/app/Actions/Commerce/OrderStoreAction.ts +32 -0
- package/app/Actions/Commerce/OrderUpdateAction.ts +34 -0
- package/app/Actions/Commerce/PaymentDestroyAction.ts +16 -0
- package/app/Actions/Commerce/PaymentFetchStatsAction.ts +31 -0
- package/app/Actions/Commerce/PaymentIndexAction.ts +15 -0
- package/app/Actions/Commerce/PaymentMonthlyTrendsAction.ts +21 -0
- package/app/Actions/Commerce/PaymentShowAction.ts +17 -0
- package/app/Actions/Commerce/PaymentStoreAction.ts +24 -0
- package/app/Actions/Commerce/PaymentUpdateAction.ts +35 -0
- package/app/Actions/Commerce/PrintDeviceDestroyAction.ts +18 -0
- package/app/Actions/Commerce/PrintDeviceIndexAction.ts +14 -0
- package/app/Actions/Commerce/PrintDeviceShowAction.ts +17 -0
- package/app/Actions/Commerce/PrintDeviceStoreAction.ts +27 -0
- package/app/Actions/Commerce/PrintDeviceUpdateAction.ts +27 -0
- package/app/Actions/Commerce/Product/ManufacturerDestroyAction.ts +20 -0
- package/app/Actions/Commerce/Product/ManufacturerIndexAction.ts +16 -0
- package/app/Actions/Commerce/Product/ManufacturerShowAction.ts +18 -0
- package/app/Actions/Commerce/Product/ManufacturerStoreAction.ts +14 -0
- package/app/Actions/Commerce/Product/ProductCategoryIndexAction.ts +16 -0
- package/app/Actions/Commerce/Product/ProductCategoryStoreAction.ts +16 -0
- package/app/Actions/Commerce/Product/ProductDestroyAction.ts +16 -0
- package/app/Actions/Commerce/Product/ProductIndexAction.ts +14 -0
- package/app/Actions/Commerce/Product/ProductManufacturerDestroyAction.ts +18 -0
- package/app/Actions/Commerce/Product/ProductManufacturerIndexAction.ts +14 -0
- package/app/Actions/Commerce/Product/ProductManufacturerShowAction.ts +16 -0
- package/app/Actions/Commerce/Product/ProductManufacturerStoreAction.ts +14 -0
- package/app/Actions/Commerce/Product/ProductManufacturerUpdateAction.ts +18 -0
- package/app/Actions/Commerce/Product/ProductShowAction.ts +18 -0
- package/app/Actions/Commerce/Product/ProductStoreAction.ts +17 -0
- package/app/Actions/Commerce/Product/ProductUnitDestroyAction.ts +18 -0
- package/app/Actions/Commerce/Product/ProductUnitIndexAction.ts +14 -0
- package/app/Actions/Commerce/Product/ProductUnitShowAction.ts +18 -0
- package/app/Actions/Commerce/Product/ProductUnitStoreAction.ts +15 -0
- package/app/Actions/Commerce/Product/ProductUpdateAction.ts +17 -0
- package/app/Actions/Commerce/Product/ProductVariantDestroyAction.ts +18 -0
- package/app/Actions/Commerce/Product/ProductVariantIndexAction.ts +14 -0
- package/app/Actions/Commerce/Product/ProductVariantShowAction.ts +17 -0
- package/app/Actions/Commerce/Product/ProductVariantStoreAction.ts +14 -0
- package/app/Actions/Commerce/Product/ProductVariantUpdateAction.ts +16 -0
- package/app/Actions/Commerce/ReceiptDestroyAction.ts +18 -0
- package/app/Actions/Commerce/ReceiptIndexAction.ts +14 -0
- package/app/Actions/Commerce/ReceiptShowAction.ts +18 -0
- package/app/Actions/Commerce/ReceiptStoreAction.ts +28 -0
- package/app/Actions/Commerce/ReceiptUpdateAction.ts +30 -0
- package/app/Actions/Commerce/ReviewIndexAction.ts +14 -0
- package/app/Actions/Commerce/ReviewShowAction.ts +16 -0
- package/app/Actions/Commerce/ReviewStoreAction.ts +26 -0
- package/app/Actions/Commerce/ReviewUpdateAction.ts +28 -0
- package/app/Actions/Commerce/Shipping/DeliveryRouteDestroyAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DeliveryRouteIndexAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/DeliveryRouteShowAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DeliveryRouteStoreAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/DeliveryRouteUpdateAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DigitalDeliveryDestroyAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DigitalDeliveryIndexAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/DigitalDeliveryShowAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DigitalDeliveryStoreAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DigitalDeliveryUpdateAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DriverIndexAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/DriverShowAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DriverStoreAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/DriverUpdateAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/LicenseKeyDestroyAction.ts +20 -0
- package/app/Actions/Commerce/Shipping/LicenseKeyIndexAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/LicenseKeyShowAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/LicenseKeyStoreAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/LicenseKeyUpdateAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/ShippingMethodDestroyAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingMethodIndexAction.ts +14 -0
- package/app/Actions/Commerce/Shipping/ShippingMethodShowAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingMethodStoreAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingMethodUpdateAction.ts +15 -0
- package/app/Actions/Commerce/Shipping/ShippingRateDestroyAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingRateIndexAction.ts +14 -0
- package/app/Actions/Commerce/Shipping/ShippingRateShowAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingRateStoreAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingRateUpdateAction.ts +17 -0
- package/app/Actions/Commerce/Shipping/ShippingZoneDestroyAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingZoneIndexAction.ts +14 -0
- package/app/Actions/Commerce/Shipping/ShippingZoneShowAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingZoneStoreAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingZoneUpdateAction.ts +15 -0
- package/app/Actions/Commerce/TaxRateDestroyAction.ts +16 -0
- package/app/Actions/Commerce/TaxRateIndexAction.ts +14 -0
- package/app/Actions/Commerce/TaxRateShowAction.ts +17 -0
- package/app/Actions/Commerce/TaxRateStoreAction.ts +24 -0
- package/app/Actions/Commerce/TaxRateUpdateAction.ts +24 -0
- package/app/Actions/Commerce/WaitlistProductAnalyticsAction.ts +29 -0
- package/app/Actions/Commerce/WaitlistProductDestroyAction.ts +16 -0
- package/app/Actions/Commerce/WaitlistProductIndexAction.ts +14 -0
- package/app/Actions/Commerce/WaitlistProductQuantityDistributionAction.ts +32 -0
- package/app/Actions/Commerce/WaitlistProductShowAction.ts +16 -0
- package/app/Actions/Commerce/WaitlistProductStatusAction.ts +37 -0
- package/app/Actions/Commerce/WaitlistProductStoreAction.ts +27 -0
- package/app/Actions/Commerce/WaitlistProductTimeSeriesAction.ts +25 -0
- package/app/Actions/Commerce/WaitlistProductUpdateAction.ts +29 -0
- package/app/Actions/Commerce/WaitlistRestaurantDashboardAction.ts +29 -0
- package/app/Actions/Commerce/WaitlistRestaurantDestroyAction.ts +16 -0
- package/app/Actions/Commerce/WaitlistRestaurantIndexAction.ts +14 -0
- package/app/Actions/Commerce/WaitlistRestaurantShowAction.ts +16 -0
- package/app/Actions/Commerce/WaitlistRestaurantStoreAction.ts +31 -0
- package/app/Actions/Commerce/WaitlistRestaurantUpdateAction.ts +33 -0
- package/app/Actions/ContactAction.ts +72 -0
- package/app/Actions/Dashboard/Actions/CreateAction.ts +11 -0
- package/app/Actions/Dashboard/Actions/GetActionCount.ts +12 -0
- package/app/Actions/Dashboard/Actions/GetActions.ts +19 -0
- package/app/Actions/Dashboard/Analytics/BlogAnalyticsAction.ts +58 -0
- package/app/Actions/Dashboard/Analytics/BrowserAnalyticsAction.ts +42 -0
- package/app/Actions/Dashboard/Analytics/CommerceAnalyticsAction.ts +64 -0
- package/app/Actions/Dashboard/Analytics/CountryAnalyticsAction.ts +41 -0
- package/app/Actions/Dashboard/Analytics/DeviceAnalyticsAction.ts +58 -0
- package/app/Actions/Dashboard/Analytics/EventAnalyticsAction.ts +90 -0
- package/app/Actions/Dashboard/Analytics/MarketingAnalyticsAction.ts +76 -0
- package/app/Actions/Dashboard/Analytics/PageAnalyticsAction.ts +45 -0
- package/app/Actions/Dashboard/Analytics/ReferrerAnalyticsAction.ts +72 -0
- package/app/Actions/Dashboard/Analytics/SalesAnalyticsAction.ts +73 -0
- package/app/Actions/Dashboard/Analytics/WebAnalyticsAction.ts +114 -0
- package/app/Actions/Dashboard/Auth/MeAction.ts +84 -0
- package/app/Actions/Dashboard/BuddyDashboardAction.ts +34 -0
- package/app/Actions/Dashboard/Ci/RepoRunJobsAction.ts +60 -0
- package/app/Actions/Dashboard/Ci/RepoRunsAction.ts +67 -0
- package/app/Actions/Dashboard/Ci/RunnerHistoryAction.ts +58 -0
- package/app/Actions/Dashboard/Ci/StatusAction.ts +73 -0
- package/app/Actions/Dashboard/Ci/failure-notifier.ts +214 -0
- package/app/Actions/Dashboard/Ci/runner-pressure-monitor.ts +259 -0
- package/app/Actions/Dashboard/Cloud/CloudIndexAction.ts +61 -0
- package/app/Actions/Dashboard/Commands/CreateCommand.ts +11 -0
- package/app/Actions/Dashboard/Commands/GetAverageCommandTime.ts +12 -0
- package/app/Actions/Dashboard/Commands/GetCommandCount.ts +12 -0
- package/app/Actions/Dashboard/Commands/GetCommandSuccessRate.ts +12 -0
- package/app/Actions/Dashboard/Commands/GetCommands.ts +12 -0
- package/app/Actions/Dashboard/Commerce/CommerceCouponsAction.ts +48 -0
- package/app/Actions/Dashboard/Commerce/CommerceCustomersAction.ts +48 -0
- package/app/Actions/Dashboard/Commerce/CommerceDashboardAction.ts +98 -0
- package/app/Actions/Dashboard/Commerce/CommerceDeliveryAction.ts +65 -0
- package/app/Actions/Dashboard/Commerce/CommerceGiftCardsAction.ts +48 -0
- package/app/Actions/Dashboard/Commerce/CommerceOrdersAction.ts +51 -0
- package/app/Actions/Dashboard/Commerce/CommercePaymentsAction.ts +59 -0
- package/app/Actions/Dashboard/Commerce/CommerceProductsAction.ts +50 -0
- package/app/Actions/Dashboard/Commerce/CommerceTaxesAction.ts +46 -0
- package/app/Actions/Dashboard/Commerce/PosIndexAction.ts +57 -0
- package/app/Actions/Dashboard/Commerce/ReviewIndexAction.ts +51 -0
- package/app/Actions/Dashboard/Content/AuthorIndexAction.ts +51 -0
- package/app/Actions/Dashboard/Content/CategoryIndexAction.ts +27 -0
- package/app/Actions/Dashboard/Content/CommentIndexAction.ts +41 -0
- package/app/Actions/Dashboard/Content/ContentDashboardAction.ts +54 -0
- package/app/Actions/Dashboard/Content/FileIndexAction.ts +24 -0
- package/app/Actions/Dashboard/Content/PageIndexAction.ts +25 -0
- package/app/Actions/Dashboard/Content/PostIndexAction.ts +102 -0
- package/app/Actions/Dashboard/Content/SeoIndexAction.ts +17 -0
- package/app/Actions/Dashboard/Content/TagIndexAction.ts +23 -0
- package/app/Actions/Dashboard/CreateDnsRecords.ts +11 -0
- package/app/Actions/Dashboard/CreateMailbox.ts +11 -0
- package/app/Actions/Dashboard/DashboardActivityAction.ts +58 -0
- package/app/Actions/Dashboard/DashboardHealthAction.ts +52 -0
- package/app/Actions/Dashboard/DashboardHomeAction.ts +83 -0
- package/app/Actions/Dashboard/DashboardStatsAction.ts +48 -0
- package/app/Actions/Dashboard/Data/AccessTokenIndexAction.ts +65 -0
- package/app/Actions/Dashboard/Data/ActivityIndexAction.ts +28 -0
- package/app/Actions/Dashboard/Data/DataDashboardAction.ts +67 -0
- package/app/Actions/Dashboard/Data/SubscriberIndexAction.ts +48 -0
- package/app/Actions/Dashboard/Data/TeamIndexAction.ts +43 -0
- package/app/Actions/Dashboard/Data/UserIndexAction.ts +48 -0
- package/app/Actions/Dashboard/Deployments/CreateDeployment.ts +11 -0
- package/app/Actions/Dashboard/Deployments/GetAverageDeploymentTime.ts +15 -0
- package/app/Actions/Dashboard/Deployments/GetDeployScript.ts +12 -0
- package/app/Actions/Dashboard/Deployments/GetDeploymentCount.ts +12 -0
- package/app/Actions/Dashboard/Deployments/GetDeploymentLiveTerminalOutput.ts +12 -0
- package/app/Actions/Dashboard/Deployments/GetDeployments.ts +20 -0
- package/app/Actions/Dashboard/Deployments/GetRecentDeployments.ts +12 -0
- package/app/Actions/Dashboard/Deployments/UpdateDeployScript.ts +11 -0
- package/app/Actions/Dashboard/GetDnsRecords.ts +12 -0
- package/app/Actions/Dashboard/GetEmailInboxes.ts +12 -0
- package/app/Actions/Dashboard/GetProjects.ts +13 -0
- package/app/Actions/Dashboard/GetRecentCommits.ts +13 -0
- package/app/Actions/Dashboard/Inbox/InboxIndexAction.ts +144 -0
- package/app/Actions/Dashboard/Inbox/InboxShowAction.ts +89 -0
- package/app/Actions/Dashboard/Infrastructure/CommandIndexAction.ts +18 -0
- package/app/Actions/Dashboard/Infrastructure/DnsIndexAction.ts +101 -0
- package/app/Actions/Dashboard/Infrastructure/EnvironmentIndexAction.ts +67 -0
- package/app/Actions/Dashboard/Infrastructure/InsightsAction.ts +29 -0
- package/app/Actions/Dashboard/Infrastructure/LogIndexAction.ts +50 -0
- package/app/Actions/Dashboard/Infrastructure/MailboxIndexAction.ts +85 -0
- package/app/Actions/Dashboard/Infrastructure/PermissionIndexAction.ts +54 -0
- package/app/Actions/Dashboard/Infrastructure/RequestIndexAction.ts +44 -0
- package/app/Actions/Dashboard/Infrastructure/ServerIndexAction.ts +101 -0
- package/app/Actions/Dashboard/Jobs/CreateJob.ts +11 -0
- package/app/Actions/Dashboard/Jobs/GetAverageJobTime.ts +12 -0
- package/app/Actions/Dashboard/Jobs/GetJobHistory.ts +12 -0
- package/app/Actions/Dashboard/Jobs/GetJobs.ts +11 -0
- package/app/Actions/Dashboard/Jobs/GetJobsPerMinute.ts +12 -0
- package/app/Actions/Dashboard/Jobs/JobIndexAction.ts +136 -0
- package/app/Actions/Dashboard/Jobs/JobRetryAction.ts +23 -0
- package/app/Actions/Dashboard/Jobs/JobStatsAction.ts +49 -0
- package/app/Actions/Dashboard/Kanban/BoardDestroyAction.ts +84 -0
- package/app/Actions/Dashboard/Kanban/BoardShowAction.ts +215 -0
- package/app/Actions/Dashboard/Kanban/BoardStoreAction.ts +98 -0
- package/app/Actions/Dashboard/Kanban/BoardUpdateAction.ts +96 -0
- package/app/Actions/Dashboard/Kanban/BoardsIndexAction.ts +81 -0
- package/app/Actions/Dashboard/Kanban/BoardsReorderAction.ts +80 -0
- package/app/Actions/Dashboard/Kanban/CardAssigneesSyncAction.ts +103 -0
- package/app/Actions/Dashboard/Kanban/CardCommentDestroyAction.ts +33 -0
- package/app/Actions/Dashboard/Kanban/CardCommentStoreAction.ts +82 -0
- package/app/Actions/Dashboard/Kanban/CardDestroyAction.ts +48 -0
- package/app/Actions/Dashboard/Kanban/CardLabelsSyncAction.ts +103 -0
- package/app/Actions/Dashboard/Kanban/CardShowAction.ts +122 -0
- package/app/Actions/Dashboard/Kanban/CardStoreAction.ts +112 -0
- package/app/Actions/Dashboard/Kanban/CardUpdateAction.ts +91 -0
- package/app/Actions/Dashboard/Kanban/CardsReorderAction.ts +148 -0
- package/app/Actions/Dashboard/Kanban/ColumnDestroyAction.ts +59 -0
- package/app/Actions/Dashboard/Kanban/ColumnStoreAction.ts +94 -0
- package/app/Actions/Dashboard/Kanban/ColumnUpdateAction.ts +89 -0
- package/app/Actions/Dashboard/Kanban/ColumnsReorderAction.ts +85 -0
- package/app/Actions/Dashboard/Kanban/LabelDestroyAction.ts +41 -0
- package/app/Actions/Dashboard/Kanban/LabelStoreAction.ts +70 -0
- package/app/Actions/Dashboard/Kanban/LabelUpdateAction.ts +83 -0
- package/app/Actions/Dashboard/Kanban/UsersListAction.ts +36 -0
- package/app/Actions/Dashboard/Library/CreateComponent.ts +11 -0
- package/app/Actions/Dashboard/Library/CreateFunction.ts +11 -0
- package/app/Actions/Dashboard/Library/DependencyIndexAction.ts +92 -0
- package/app/Actions/Dashboard/Library/GetAverageReleaseTime.ts +12 -0
- package/app/Actions/Dashboard/Library/GetComponents.ts +24 -0
- package/app/Actions/Dashboard/Library/GetComponentsDownloadCount.ts +12 -0
- package/app/Actions/Dashboard/Library/GetDownloadCount.ts +12 -0
- package/app/Actions/Dashboard/Library/GetFunctions.ts +22 -0
- package/app/Actions/Dashboard/Library/GetFunctionsDownloadCount.ts +12 -0
- package/app/Actions/Dashboard/Library/GetReleaseCount.ts +12 -0
- package/app/Actions/Dashboard/Library/GetReleases.ts +28 -0
- package/app/Actions/Dashboard/Library/PackageIndexAction.ts +26 -0
- package/app/Actions/Dashboard/Marketing/CampaignIndexAction.ts +45 -0
- package/app/Actions/Dashboard/Marketing/ListIndexAction.ts +43 -0
- package/app/Actions/Dashboard/Marketing/SocialPostIndexAction.ts +47 -0
- package/app/Actions/Dashboard/Models/GetModels.ts +39 -0
- package/app/Actions/Dashboard/Models/GetSubscriberCount.ts +12 -0
- package/app/Actions/Dashboard/Models/GetUserCount.ts +12 -0
- package/app/Actions/Dashboard/Models/ModelShowAction.ts +131 -0
- package/app/Actions/Dashboard/Models/ModelsIndexAction.ts +169 -0
- package/app/Actions/Dashboard/Notifications/CreateNotification.ts +11 -0
- package/app/Actions/Dashboard/Notifications/GetAverageNotificationTime.ts +12 -0
- package/app/Actions/Dashboard/Notifications/GetNotificationCount.ts +12 -0
- package/app/Actions/Dashboard/Notifications/GetNotificationDeliveryRate.ts +12 -0
- package/app/Actions/Dashboard/Notifications/GetNotificationHistory.ts +12 -0
- package/app/Actions/Dashboard/Notifications/GetNotifications.ts +12 -0
- package/app/Actions/Dashboard/Notifications/NotificationDashboardAction.ts +43 -0
- package/app/Actions/Dashboard/Queries/QueryIndexAction.ts +22 -0
- package/app/Actions/Dashboard/Queue/QueueRetryFailedAction.ts +22 -0
- package/app/Actions/Dashboard/Queue/QueueStatsAction.ts +98 -0
- package/app/Actions/Dashboard/Queue/QueueWorkersAction.ts +46 -0
- package/app/Actions/Dashboard/Rbac/PermissionDestroyAction.ts +33 -0
- package/app/Actions/Dashboard/Rbac/PermissionStoreAction.ts +53 -0
- package/app/Actions/Dashboard/Rbac/PermissionsIndexAction.ts +34 -0
- package/app/Actions/Dashboard/Rbac/RoleDestroyAction.ts +35 -0
- package/app/Actions/Dashboard/Rbac/RolePermissionsShowAction.ts +45 -0
- package/app/Actions/Dashboard/Rbac/RolePermissionsSyncAction.ts +63 -0
- package/app/Actions/Dashboard/Rbac/RoleStoreAction.ts +58 -0
- package/app/Actions/Dashboard/Rbac/RolesIndexAction.ts +36 -0
- package/app/Actions/Dashboard/Rbac/UserRolesShowAction.ts +40 -0
- package/app/Actions/Dashboard/Rbac/UserRolesSyncAction.ts +65 -0
- package/app/Actions/Dashboard/Rbac/UsersListAction.ts +39 -0
- package/app/Actions/Dashboard/Realtime/RealtimeStatsAction.ts +50 -0
- package/app/Actions/Dashboard/Releases/ReleaseIndexAction.ts +21 -0
- package/app/Actions/Dashboard/Requests/GetAverageRequestTime.ts +12 -0
- package/app/Actions/Dashboard/Requests/GetRequestCount.ts +12 -0
- package/app/Actions/Dashboard/Requests/GetRequestSuccessRate.ts +12 -0
- package/app/Actions/Dashboard/Requests/GetRequests.ts +12 -0
- package/app/Actions/Dashboard/Search/GlobalSearchAction.ts +26 -0
- package/app/Actions/Dashboard/ServiceHealthAction.ts +243 -0
- package/app/Actions/Dashboard/Settings/MailSettingsGetAction.ts +20 -0
- package/app/Actions/Dashboard/Settings/MailSettingsUpdateAction.ts +10 -0
- package/app/Actions/Dashboard/Settings/SettingsIndexAction.ts +40 -0
- package/app/Actions/Dashboard/Settings/UpdateAiConfig.ts +27 -0
- package/app/Actions/Dashboard/Settings/UpdateAnalyticsConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateAppConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateCacheConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateCliConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateCloudConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateDatabaseConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateDnsConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateDocsConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateEmailConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateEnvConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateErrorsConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateFileSystemsConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateGitConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateHashingConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateLibraryConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateLoggerConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateNotificationConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdatePaymentConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdatePortsConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateQueueConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateSearchEngineConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateSecurityConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateServicesConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateStorageConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateTeamConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateUiConfig.ts +11 -0
- package/app/Actions/HealthAction.ts +112 -0
- package/app/Actions/InstallAction.ts +83 -0
- package/app/Actions/Locale/SetLocaleAction.ts +51 -0
- package/app/Actions/LogAction.ts +42 -0
- package/app/Actions/Logs/LogFetchStatsAction.ts +50 -0
- package/app/Actions/Logs/LogIndexOrmAction.ts +13 -0
- package/app/Actions/Logs/LogShowOrmAction.ts +17 -0
- package/app/Actions/Logs/LogStoreOrmAction.ts +16 -0
- package/app/Actions/Logs/LogUpdateOrmAction.ts +20 -0
- package/app/Actions/Monitoring/ErrorDestroyAction.ts +25 -0
- package/app/Actions/Monitoring/ErrorGroupAction.ts +21 -0
- package/app/Actions/Monitoring/ErrorIgnoreAction.ts +25 -0
- package/app/Actions/Monitoring/ErrorIndexAction.ts +14 -0
- package/app/Actions/Monitoring/ErrorResolveAction.ts +25 -0
- package/app/Actions/Monitoring/ErrorShowAction.ts +19 -0
- package/app/Actions/Monitoring/ErrorStatsAction.ts +14 -0
- package/app/Actions/Monitoring/ErrorTimelineAction.ts +14 -0
- package/app/Actions/Monitoring/ErrorUnresolveAction.ts +25 -0
- package/app/Actions/NotifyUser.ts +10 -0
- package/app/Actions/Password/PasswordResetAction.ts +54 -0
- package/app/Actions/Password/SendPasswordResetEmailAction.ts +66 -0
- package/app/Actions/Password/VerifyResetTokenAction.ts +27 -0
- package/app/Actions/Payment/CancelSubscriptionAction.ts +20 -0
- package/app/Actions/Payment/CreateCheckoutAction.ts +28 -0
- package/app/Actions/Payment/CreateInvoiceSubscription.ts +18 -0
- package/app/Actions/Payment/CreatePaymentIntentAction.ts +31 -0
- package/app/Actions/Payment/CreateSetupIntentAction.ts +20 -0
- package/app/Actions/Payment/CreateSubscriptionAction.ts +23 -0
- package/app/Actions/Payment/DeleteDefaultPaymentAction.ts +18 -0
- package/app/Actions/Payment/FetchActiveSubscriptionAction.ts +18 -0
- package/app/Actions/Payment/FetchDefaultPaymentMethodAction.ts +18 -0
- package/app/Actions/Payment/FetchPaymentCustomerAction.ts +18 -0
- package/app/Actions/Payment/FetchPaymentMethodsAction.ts +18 -0
- package/app/Actions/Payment/FetchProductAction.ts +15 -0
- package/app/Actions/Payment/FetchTransactionHistoryAction.ts +18 -0
- package/app/Actions/Payment/FetchUserSubscriptionsAction.ts +18 -0
- package/app/Actions/Payment/SetDefaultPaymentAction.ts +20 -0
- package/app/Actions/Payment/SetUserDefaultPaymentAction.ts +20 -0
- package/app/Actions/Payment/StorePaymentMethodAction.ts +20 -0
- package/app/Actions/Payment/StoreTransactionAction.ts +20 -0
- package/app/Actions/Payment/UpdateCustomerAction.ts +24 -0
- package/app/Actions/Payment/UpdateDefaultPaymentMethodAction.ts +18 -0
- package/app/Actions/Payment/UpdateSubscriptionAction.ts +22 -0
- package/app/Actions/Queue/FetchQueuesAction.ts +14 -0
- package/app/Actions/README.md +61 -0
- package/app/Actions/Realtime/FetchWebsocketsAction.ts +14 -0
- package/app/Actions/RobotsAction.ts +61 -0
- package/app/Actions/SendWelcomeEmail.ts +40 -0
- package/app/Actions/SitemapAction.ts +234 -0
- package/app/Actions/Storefront/AddToCartAction.ts +153 -0
- package/app/Actions/Storefront/CheckoutContactAction.ts +50 -0
- package/app/Actions/Storefront/CheckoutShippingAction.ts +61 -0
- package/app/Actions/Storefront/GetCartAction.ts +58 -0
- package/app/Actions/Storefront/PlaceOrderAction.ts +195 -0
- package/app/Actions/Storefront/SubmitReviewAction.ts +140 -0
- package/app/Actions/Storefront/UpdateCartItemAction.ts +83 -0
- package/app/Actions/Storefront/_shipping.ts +64 -0
- package/app/Actions/SubscriberEmailAction.ts +60 -0
- package/app/Actions/TestErrorAction.ts +163 -0
- package/app/Actions/UnsubscribeAction.ts +107 -0
- package/app/Actions/UploadTestAction.ts +57 -0
- package/app/Broadcasts/OrderShipped.ts +57 -0
- package/app/Commands/Inspire.ts +57 -0
- package/app/Commands/README.md +84 -0
- package/app/Commands.ts +38 -0
- package/app/Controllers/ComingSoonController.ts +9 -0
- package/app/Controllers/QueryController.ts +373 -0
- package/app/Events.ts +14 -0
- package/app/Gates.ts +107 -0
- package/app/Jobs/ExampleJob.ts +20 -0
- package/app/Jobs/ExampleTwoJob.ts +12 -0
- package/app/Jobs/PruneModelsJob.ts +61 -0
- package/app/Jobs/PruneQueryLogsJob.ts +51 -0
- package/app/Jobs/README.md +79 -0
- package/app/Jobs/SendCampaignJob.ts +201 -0
- package/app/Jobs/SendEmailJob.ts +52 -0
- package/app/Jobs/SendPasswordResetEmailJob.ts +44 -0
- package/app/Jobs/SyncSearchIndexJob.ts +64 -0
- package/app/Listener.ts +84 -0
- package/app/Listeners/Console.ts +22 -0
- package/app/Listeners/README.md +47 -0
- package/app/Mail/OrderConfirmation.ts +60 -0
- package/app/Mail/SubscriptionConfirmation.ts +41 -0
- package/app/Middleware/Abilities.ts +53 -0
- package/app/Middleware/Api.ts +26 -0
- package/app/Middleware/Auth.ts +59 -0
- package/app/Middleware/Can.ts +68 -0
- package/app/Middleware/Compress.ts +213 -0
- package/app/Middleware/Cors.ts +320 -0
- package/app/Middleware/Csrf.ts +224 -0
- package/app/Middleware/EnsureEmailIsVerified.ts +28 -0
- package/app/Middleware/Env.ts +24 -0
- package/app/Middleware/EnvDevelopment.ts +19 -0
- package/app/Middleware/EnvLocal.ts +19 -0
- package/app/Middleware/EnvNotDevelopment.ts +19 -0
- package/app/Middleware/EnvNotLocal.ts +19 -0
- package/app/Middleware/EnvNotProduction.ts +19 -0
- package/app/Middleware/EnvNotStaging.ts +19 -0
- package/app/Middleware/EnvProduction.ts +19 -0
- package/app/Middleware/EnvStaging.ts +19 -0
- package/app/Middleware/Guest.ts +25 -0
- package/app/Middleware/Logger.ts +20 -0
- package/app/Middleware/Maintenance.ts +36 -0
- package/app/Middleware/Permission.ts +42 -0
- package/app/Middleware/README.md +48 -0
- package/app/Middleware/Role.ts +42 -0
- package/app/Middleware/Signed.ts +31 -0
- package/app/Middleware/Team.ts +36 -0
- package/app/Middleware/Throttle.ts +96 -0
- package/app/Middleware.ts +35 -0
- package/app/Models/Activity.ts +94 -0
- package/app/Models/Board.ts +103 -0
- package/app/Models/BoardColumn.ts +87 -0
- package/app/Models/Campaign.ts +239 -0
- package/app/Models/CampaignSend.ts +107 -0
- package/app/Models/Card.ts +117 -0
- package/app/Models/CardComment.ts +68 -0
- package/app/Models/Comment.ts +108 -0
- package/app/Models/Content/Author.ts +104 -0
- package/app/Models/Content/Page.ts +99 -0
- package/app/Models/Content/Post.ts +144 -0
- package/app/Models/Deployment.ts +116 -0
- package/app/Models/EmailList.ts +126 -0
- package/app/Models/EmailListSubscriber.ts +91 -0
- package/app/Models/Error.ts +70 -0
- package/app/Models/FailedJob.ts +62 -0
- package/app/Models/Job.ts +63 -0
- package/app/Models/Label.ts +66 -0
- package/app/Models/Log.ts +110 -0
- package/app/Models/Notification.ts +118 -0
- package/app/Models/PaymentMethod.ts +98 -0
- package/app/Models/PaymentProduct.ts +91 -0
- package/app/Models/PaymentTransaction.ts +78 -0
- package/app/Models/README.md +31 -0
- package/app/Models/Release.ts +89 -0
- package/app/Models/Request.ts +114 -0
- package/app/Models/SocialPost.ts +136 -0
- package/app/Models/Subscriber.ts +89 -0
- package/app/Models/SubscriberEmail.ts +55 -0
- package/app/Models/Subscription.ts +153 -0
- package/app/Models/Tag.ts +82 -0
- package/app/Models/Team.ts +72 -0
- package/app/Models/User.ts +134 -0
- package/app/Models/commerce/Cart.ts +139 -0
- package/app/Models/commerce/CartItem.ts +137 -0
- package/app/Models/commerce/Category.ts +105 -0
- package/app/Models/commerce/Coupon.ts +181 -0
- package/app/Models/commerce/Customer.ts +132 -0
- package/app/Models/commerce/DeliveryRoute.ts +93 -0
- package/app/Models/commerce/DigitalDelivery.ts +105 -0
- package/app/Models/commerce/Driver.ts +97 -0
- package/app/Models/commerce/GiftCard.ts +191 -0
- package/app/Models/commerce/LicenseKey.ts +87 -0
- package/app/Models/commerce/LoyaltyPoint.ts +107 -0
- package/app/Models/commerce/LoyaltyReward.ts +124 -0
- package/app/Models/commerce/Manufacturer.ts +84 -0
- package/app/Models/commerce/Order.ts +142 -0
- package/app/Models/commerce/OrderItem.ts +51 -0
- package/app/Models/commerce/Payment.ts +163 -0
- package/app/Models/commerce/PrintDevice.ts +117 -0
- package/app/Models/commerce/Product.ts +148 -0
- package/app/Models/commerce/ProductUnit.ts +107 -0
- package/app/Models/commerce/ProductVariant.ts +106 -0
- package/app/Models/commerce/Receipt.ts +128 -0
- package/app/Models/commerce/Review.ts +140 -0
- package/app/Models/commerce/ShippingMethod.ts +97 -0
- package/app/Models/commerce/ShippingRate.ts +74 -0
- package/app/Models/commerce/ShippingZone.ts +111 -0
- package/app/Models/commerce/TaxRate.ts +114 -0
- package/app/Models/commerce/Transaction.ts +126 -0
- package/app/Models/commerce/WaitlistProduct.ts +149 -0
- package/app/Models/commerce/WaitlistRestaurant.ts +187 -0
- package/app/Models/realtime/Websocket.ts +77 -0
- package/app/Notifications/README.md +31 -0
- package/app/Notifications/Welcome.ts +32 -0
- package/app/Policies/PostPolicy.ts +131 -0
- package/app/README.md +23 -0
- package/app/Routes.ts +47 -0
- package/app/Scheduler.ts +28 -0
- package/app/Storefront/CartCookie.ts +109 -0
- package/package.json +3 -2
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface CardInput {
|
|
5
|
+
title?: unknown
|
|
6
|
+
description?: unknown
|
|
7
|
+
dueDate?: unknown
|
|
8
|
+
archived?: unknown
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* `PATCH /api/dashboard/kanban/cards/:id` (stacksjs/stacks#1846 Phase 2).
|
|
13
|
+
*
|
|
14
|
+
* Partial update for the card body: title, description, due date,
|
|
15
|
+
* archive flag. `position` and `columnId` are NOT updatable here —
|
|
16
|
+
* card moves go through `/cards/reorder` which can rewrite multiple
|
|
17
|
+
* rows transactionally and keep the denormalised `board_id` in sync
|
|
18
|
+
* when a card crosses columns on different boards (rare but possible
|
|
19
|
+
* if the page reordered a column move pair).
|
|
20
|
+
*/
|
|
21
|
+
export default new Action({
|
|
22
|
+
name: 'Kanban Card Update',
|
|
23
|
+
description: 'Partial update of a card body (title, description, due date, archive).',
|
|
24
|
+
method: 'PATCH',
|
|
25
|
+
apiResponse: true,
|
|
26
|
+
async handle(request) {
|
|
27
|
+
const rawId = (request as any)?.params?.id ?? (request as any)?.param?.('id') ?? null
|
|
28
|
+
const id = Number(rawId)
|
|
29
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
30
|
+
return { error: 'Invalid card id', status: 400 }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const body = (request as any).jsonBody as CardInput | undefined ?? {}
|
|
34
|
+
const set: Record<string, unknown> = {}
|
|
35
|
+
|
|
36
|
+
if (typeof body.title === 'string') {
|
|
37
|
+
const title = body.title.trim()
|
|
38
|
+
if (!title || title.length > 300) {
|
|
39
|
+
return { error: '`title` must be 1-300 characters.', status: 400 }
|
|
40
|
+
}
|
|
41
|
+
set.title = title
|
|
42
|
+
}
|
|
43
|
+
if (typeof body.description === 'string' || body.description === null) {
|
|
44
|
+
set.description = typeof body.description === 'string' ? body.description.trim() : null
|
|
45
|
+
}
|
|
46
|
+
if (typeof body.dueDate === 'string' || body.dueDate === null) {
|
|
47
|
+
set.due_date = typeof body.dueDate === 'string' && body.dueDate ? body.dueDate : null
|
|
48
|
+
}
|
|
49
|
+
if (typeof body.archived === 'boolean')
|
|
50
|
+
set.archived = body.archived ? 1 : 0
|
|
51
|
+
|
|
52
|
+
if (Object.keys(set).length === 0) {
|
|
53
|
+
return { error: 'No updatable fields provided.', status: 400 }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
await db.updateTable('cards').set(set as any).where('id', '=', id).execute()
|
|
58
|
+
|
|
59
|
+
const rows = await db.unsafe(
|
|
60
|
+
`SELECT id, uuid, column_id, board_id, title, description, position,
|
|
61
|
+
created_by_user_id, due_date, archived, created_at, updated_at
|
|
62
|
+
FROM cards WHERE id = ? LIMIT 1`,
|
|
63
|
+
[id],
|
|
64
|
+
).execute() as Array<Record<string, unknown>>
|
|
65
|
+
const r = rows?.[0]
|
|
66
|
+
if (!r) {
|
|
67
|
+
return { error: 'Card not found', status: 404 }
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
card: {
|
|
71
|
+
id: Number(r.id),
|
|
72
|
+
uuid: r.uuid == null ? null : String(r.uuid),
|
|
73
|
+
columnId: Number(r.column_id),
|
|
74
|
+
boardId: Number(r.board_id),
|
|
75
|
+
title: String(r.title),
|
|
76
|
+
description: r.description == null ? null : String(r.description),
|
|
77
|
+
position: Number(r.position),
|
|
78
|
+
createdByUserId: r.created_by_user_id == null ? null : Number(r.created_by_user_id),
|
|
79
|
+
dueDate: r.due_date == null ? null : String(r.due_date),
|
|
80
|
+
archived: Number(r.archived) === 1,
|
|
81
|
+
createdAt: r.created_at == null ? null : String(r.created_at),
|
|
82
|
+
updatedAt: r.updated_at == null ? null : String(r.updated_at),
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
console.error('[dashboard/kanban] CardUpdateAction failed:', err)
|
|
88
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
})
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface ColumnReorder {
|
|
5
|
+
columnId: number
|
|
6
|
+
order: number[]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface ReorderInput {
|
|
10
|
+
/**
|
|
11
|
+
* Per-column ordered lists. Each entry rewrites every card in that
|
|
12
|
+
* column to match the supplied order, AND sets `column_id` for any
|
|
13
|
+
* card that moved in from a different column (cross-column drag).
|
|
14
|
+
*
|
|
15
|
+
* Example shape:
|
|
16
|
+
*
|
|
17
|
+
* {
|
|
18
|
+
* columns: [
|
|
19
|
+
* { columnId: 1, order: [5, 3, 7] }, // Todo
|
|
20
|
+
* { columnId: 2, order: [4, 8] }, // In Progress
|
|
21
|
+
* { columnId: 3, order: [] }, // Done — emptied
|
|
22
|
+
* ]
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* Sending the full per-column state (not just the moved card)
|
|
26
|
+
* avoids the "neighbour position drift" footgun where a card-move
|
|
27
|
+
* leaves siblings with stale positions.
|
|
28
|
+
*/
|
|
29
|
+
columns?: unknown
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* `POST /api/dashboard/kanban/cards/reorder` (stacksjs/stacks#1846 Phase 2).
|
|
34
|
+
*
|
|
35
|
+
* The drag-and-drop hot path. Rewrites card positions and column
|
|
36
|
+
* assignments across one or more columns of a single board in a single
|
|
37
|
+
* transaction. Validates that every card and every column belongs to
|
|
38
|
+
* the same board so a malformed payload can't reassign cards across
|
|
39
|
+
* boards (would break `cards.board_id` denormalisation).
|
|
40
|
+
*
|
|
41
|
+
* Returns `{ moved: <count> }` — the count is informational for
|
|
42
|
+
* client-side toast messages, not load-bearing.
|
|
43
|
+
*/
|
|
44
|
+
export default new Action({
|
|
45
|
+
name: 'Kanban Cards Reorder',
|
|
46
|
+
description: 'Bulk-rewrite cards.{column_id, position} across one or more columns of the same board.',
|
|
47
|
+
method: 'POST',
|
|
48
|
+
apiResponse: true,
|
|
49
|
+
async handle(request) {
|
|
50
|
+
const body = (request as any).jsonBody as ReorderInput | undefined ?? {}
|
|
51
|
+
|
|
52
|
+
if (!Array.isArray(body.columns) || body.columns.length === 0) {
|
|
53
|
+
return { error: '`columns` must be a non-empty array.', status: 400 }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Parse + validate. Each entry needs a positive integer columnId
|
|
57
|
+
// and a (possibly empty) array of positive integer card ids.
|
|
58
|
+
const reorders: ColumnReorder[] = []
|
|
59
|
+
const allCardIds = new Set<number>()
|
|
60
|
+
for (const raw of body.columns) {
|
|
61
|
+
if (!raw || typeof raw !== 'object')
|
|
62
|
+
return { error: '`columns[]` entry must be an object.', status: 400 }
|
|
63
|
+
const columnId = Number((raw as any).columnId)
|
|
64
|
+
if (!Number.isFinite(columnId) || columnId <= 0)
|
|
65
|
+
return { error: '`columns[].columnId` must be a positive integer.', status: 400 }
|
|
66
|
+
if (!Array.isArray((raw as any).order))
|
|
67
|
+
return { error: '`columns[].order` must be an array.', status: 400 }
|
|
68
|
+
const order: number[] = []
|
|
69
|
+
for (const v of (raw as any).order) {
|
|
70
|
+
const n = Number(v)
|
|
71
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
72
|
+
return { error: '`columns[].order` contains an invalid card id.', status: 400 }
|
|
73
|
+
if (allCardIds.has(n))
|
|
74
|
+
return { error: 'A card id appears in more than one column.', status: 400 }
|
|
75
|
+
allCardIds.add(n)
|
|
76
|
+
order.push(n)
|
|
77
|
+
}
|
|
78
|
+
reorders.push({ columnId, order })
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (reorders.length === 0) {
|
|
82
|
+
return { moved: 0 }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
// Verify all columns belong to the same board.
|
|
87
|
+
const columnIds = reorders.map(r => r.columnId)
|
|
88
|
+
const colPlaceholders = columnIds.map(() => '?').join(',')
|
|
89
|
+
const colRows = await db.unsafe(
|
|
90
|
+
`SELECT id, board_id FROM board_columns WHERE id IN (${colPlaceholders})`,
|
|
91
|
+
columnIds,
|
|
92
|
+
).execute() as Array<{ id: number, board_id: number }>
|
|
93
|
+
if (colRows.length !== columnIds.length) {
|
|
94
|
+
return { error: 'One or more column ids do not exist.', status: 400 }
|
|
95
|
+
}
|
|
96
|
+
const boardIds = new Set(colRows.map(r => r.board_id))
|
|
97
|
+
if (boardIds.size > 1) {
|
|
98
|
+
return { error: 'All columns in a reorder request must belong to the same board.', status: 400 }
|
|
99
|
+
}
|
|
100
|
+
const boardId = colRows[0].board_id
|
|
101
|
+
|
|
102
|
+
// Verify all cards belong to that board (prevents a malformed
|
|
103
|
+
// page from moving cards in from a sibling board).
|
|
104
|
+
if (allCardIds.size > 0) {
|
|
105
|
+
const cardIdList = Array.from(allCardIds)
|
|
106
|
+
const cardPlaceholders = cardIdList.map(() => '?').join(',')
|
|
107
|
+
const cardRows = await db.unsafe(
|
|
108
|
+
`SELECT id FROM cards WHERE id IN (${cardPlaceholders}) AND board_id = ?`,
|
|
109
|
+
[...cardIdList, boardId],
|
|
110
|
+
).execute() as Array<{ id: number }>
|
|
111
|
+
if (cardRows.length !== cardIdList.length) {
|
|
112
|
+
return { error: 'One or more card ids do not belong to the named board.', status: 400 }
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Single transaction: for each (columnId, order) entry, set
|
|
117
|
+
// `column_id = columnId, position = index` on each card. Cards
|
|
118
|
+
// moving across columns get both columns of their row rewritten;
|
|
119
|
+
// cards staying put still get their position rewritten (cheap,
|
|
120
|
+
// idempotent).
|
|
121
|
+
const txOps = async (qb: any) => {
|
|
122
|
+
for (const { columnId, order } of reorders) {
|
|
123
|
+
for (let i = 0; i < order.length; i++) {
|
|
124
|
+
await qb.updateTable('cards')
|
|
125
|
+
.set({ column_id: columnId, position: i, board_id: boardId })
|
|
126
|
+
.where('id', '=', order[i])
|
|
127
|
+
.execute()
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
try {
|
|
132
|
+
await (db as any).transaction(txOps)
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Driver-specific transaction shape failed — sequential is
|
|
136
|
+
// safe (each UPDATE is idempotent), but the page should
|
|
137
|
+
// refetch on failure to confirm the final state.
|
|
138
|
+
await txOps(db)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return { moved: allCardIds.size, boardId }
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
console.error('[dashboard/kanban] CardsReorderAction failed:', err)
|
|
145
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
})
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `DELETE /api/dashboard/kanban/columns/:id` (stacksjs/stacks#1846 Phase 2).
|
|
6
|
+
*
|
|
7
|
+
* Hard-deletes the column and cascade-cleans every card inside it
|
|
8
|
+
* (plus the pivot rows referencing those cards). Same convention as
|
|
9
|
+
* BoardDestroyAction — Stacks doesn't lean on DB-level FK cascade, so
|
|
10
|
+
* the cascade lives in this action.
|
|
11
|
+
*
|
|
12
|
+
* If you want to keep cards but remove the column, move the cards to
|
|
13
|
+
* a different column first via the cards/reorder endpoint, then call
|
|
14
|
+
* this on the empty column.
|
|
15
|
+
*/
|
|
16
|
+
export default new Action({
|
|
17
|
+
name: 'Kanban Column Destroy',
|
|
18
|
+
description: 'Hard-deletes a column and its cards.',
|
|
19
|
+
method: 'DELETE',
|
|
20
|
+
apiResponse: true,
|
|
21
|
+
async handle(request) {
|
|
22
|
+
const rawId = (request as any)?.params?.id ?? (request as any)?.param?.('id') ?? null
|
|
23
|
+
const id = Number(rawId)
|
|
24
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
25
|
+
return { error: 'Invalid column id', status: 400 }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const txOps = async (qb: any) => {
|
|
30
|
+
await qb.unsafe(
|
|
31
|
+
'DELETE FROM card_labels WHERE card_id IN (SELECT id FROM cards WHERE column_id = ?)',
|
|
32
|
+
[id],
|
|
33
|
+
).execute()
|
|
34
|
+
await qb.unsafe(
|
|
35
|
+
'DELETE FROM card_assignees WHERE card_id IN (SELECT id FROM cards WHERE column_id = ?)',
|
|
36
|
+
[id],
|
|
37
|
+
).execute()
|
|
38
|
+
// Card comments (Phase 3, stacksjs/stacks#1846).
|
|
39
|
+
await qb.unsafe(
|
|
40
|
+
'DELETE FROM card_comments WHERE card_id IN (SELECT id FROM cards WHERE column_id = ?)',
|
|
41
|
+
[id],
|
|
42
|
+
).execute()
|
|
43
|
+
await qb.deleteFrom('cards').where('column_id', '=', id).execute()
|
|
44
|
+
await qb.deleteFrom('board_columns').where('id', '=', id).execute()
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await (db as any).transaction(txOps)
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
await txOps(db)
|
|
51
|
+
}
|
|
52
|
+
return { deleted: true, id }
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
console.error('[dashboard/kanban] ColumnDestroyAction failed:', err)
|
|
56
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
})
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface ColumnInput {
|
|
5
|
+
boardId?: unknown
|
|
6
|
+
name?: unknown
|
|
7
|
+
color?: unknown
|
|
8
|
+
cardLimit?: unknown
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* `POST /api/dashboard/kanban/columns` (stacksjs/stacks#1846 Phase 2).
|
|
13
|
+
*
|
|
14
|
+
* Appends a new column to the end of the target board. Validates that
|
|
15
|
+
* `boardId` points at a real board so a typo doesn't silently create
|
|
16
|
+
* an orphan column row.
|
|
17
|
+
*/
|
|
18
|
+
export default new Action({
|
|
19
|
+
name: 'Kanban Column Store',
|
|
20
|
+
description: 'Creates a new column on a board.',
|
|
21
|
+
method: 'POST',
|
|
22
|
+
apiResponse: true,
|
|
23
|
+
async handle(request) {
|
|
24
|
+
const body = (request as any).jsonBody as ColumnInput | undefined ?? {}
|
|
25
|
+
|
|
26
|
+
const boardId = Number(body.boardId)
|
|
27
|
+
if (!Number.isFinite(boardId) || boardId <= 0) {
|
|
28
|
+
return { error: '`boardId` is required and must be a positive integer.', status: 400 }
|
|
29
|
+
}
|
|
30
|
+
const name = typeof body.name === 'string' ? body.name.trim() : ''
|
|
31
|
+
if (!name || name.length > 80) {
|
|
32
|
+
return { error: '`name` is required and must be 1-80 characters.', status: 400 }
|
|
33
|
+
}
|
|
34
|
+
const color = typeof body.color === 'string' && body.color ? body.color : 'slate'
|
|
35
|
+
const cardLimit = body.cardLimit == null
|
|
36
|
+
? null
|
|
37
|
+
: (Number.isFinite(Number(body.cardLimit)) && Number(body.cardLimit) >= 0
|
|
38
|
+
? Number(body.cardLimit)
|
|
39
|
+
: null)
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
// Reject orphan columns up front — a column on a deleted board
|
|
43
|
+
// would never surface in any sidebar or API, just rot in the DB.
|
|
44
|
+
const boards = await db.unsafe('SELECT id FROM boards WHERE id = ? LIMIT 1', [boardId]).execute() as Array<{ id: number }>
|
|
45
|
+
if (!boards?.length) {
|
|
46
|
+
return { error: 'Board not found.', status: 404 }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const maxRow = await db.unsafe(
|
|
50
|
+
'SELECT COALESCE(MAX(position), -1) AS m FROM board_columns WHERE board_id = ?',
|
|
51
|
+
[boardId],
|
|
52
|
+
).execute() as Array<{ m: number }>
|
|
53
|
+
const nextPosition = (Number(maxRow?.[0]?.m ?? -1) + 1) || 0
|
|
54
|
+
|
|
55
|
+
await db.insertInto('board_columns').values({
|
|
56
|
+
board_id: boardId,
|
|
57
|
+
name,
|
|
58
|
+
color,
|
|
59
|
+
card_limit: cardLimit,
|
|
60
|
+
position: nextPosition,
|
|
61
|
+
}).execute()
|
|
62
|
+
|
|
63
|
+
const rows = await db.unsafe(
|
|
64
|
+
`SELECT id, uuid, board_id, name, position, card_limit, color, created_at, updated_at
|
|
65
|
+
FROM board_columns
|
|
66
|
+
WHERE board_id = ? AND name = ? AND position = ?
|
|
67
|
+
ORDER BY id DESC
|
|
68
|
+
LIMIT 1`,
|
|
69
|
+
[boardId, name, nextPosition],
|
|
70
|
+
).execute() as Array<Record<string, unknown>>
|
|
71
|
+
const r = rows?.[0]
|
|
72
|
+
if (!r) {
|
|
73
|
+
return { error: 'Column insert succeeded but follow-up read returned nothing.', status: 500 }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
column: {
|
|
78
|
+
id: Number(r.id),
|
|
79
|
+
uuid: r.uuid == null ? null : String(r.uuid),
|
|
80
|
+
boardId: Number(r.board_id),
|
|
81
|
+
name: String(r.name),
|
|
82
|
+
position: Number(r.position),
|
|
83
|
+
cardLimit: r.card_limit == null ? null : Number(r.card_limit),
|
|
84
|
+
color: String(r.color),
|
|
85
|
+
cards: [],
|
|
86
|
+
},
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
console.error('[dashboard/kanban] ColumnStoreAction failed:', err)
|
|
91
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
})
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface ColumnInput {
|
|
5
|
+
name?: unknown
|
|
6
|
+
color?: unknown
|
|
7
|
+
cardLimit?: unknown
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* `PATCH /api/dashboard/kanban/columns/:id` (stacksjs/stacks#1846 Phase 2).
|
|
12
|
+
*
|
|
13
|
+
* Partial update for name / color / card limit. `position` and
|
|
14
|
+
* `boardId` are NOT updatable here — moving a column between boards
|
|
15
|
+
* isn't a feature (would orphan its cards' denormalised `board_id`);
|
|
16
|
+
* reordering goes through `/columns/reorder` so transactions cover
|
|
17
|
+
* the whole rewrite.
|
|
18
|
+
*/
|
|
19
|
+
export default new Action({
|
|
20
|
+
name: 'Kanban Column Update',
|
|
21
|
+
description: 'Partial update of a board column.',
|
|
22
|
+
method: 'PATCH',
|
|
23
|
+
apiResponse: true,
|
|
24
|
+
async handle(request) {
|
|
25
|
+
const rawId = (request as any)?.params?.id ?? (request as any)?.param?.('id') ?? null
|
|
26
|
+
const id = Number(rawId)
|
|
27
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
28
|
+
return { error: 'Invalid column id', status: 400 }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const body = (request as any).jsonBody as ColumnInput | undefined ?? {}
|
|
32
|
+
const set: Record<string, unknown> = {}
|
|
33
|
+
|
|
34
|
+
if (typeof body.name === 'string') {
|
|
35
|
+
const name = body.name.trim()
|
|
36
|
+
if (!name || name.length > 80) {
|
|
37
|
+
return { error: '`name` must be 1-80 characters.', status: 400 }
|
|
38
|
+
}
|
|
39
|
+
set.name = name
|
|
40
|
+
}
|
|
41
|
+
if (typeof body.color === 'string' && body.color)
|
|
42
|
+
set.color = body.color
|
|
43
|
+
if (body.cardLimit !== undefined) {
|
|
44
|
+
if (body.cardLimit === null) {
|
|
45
|
+
set.card_limit = null
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
const n = Number(body.cardLimit)
|
|
49
|
+
if (!Number.isFinite(n) || n < 0) {
|
|
50
|
+
return { error: '`cardLimit` must be a non-negative number or null.', status: 400 }
|
|
51
|
+
}
|
|
52
|
+
set.card_limit = n
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (Object.keys(set).length === 0) {
|
|
57
|
+
return { error: 'No updatable fields provided.', status: 400 }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
await db.updateTable('board_columns').set(set as any).where('id', '=', id).execute()
|
|
62
|
+
|
|
63
|
+
const rows = await db.unsafe(
|
|
64
|
+
`SELECT id, uuid, board_id, name, position, card_limit, color, created_at, updated_at
|
|
65
|
+
FROM board_columns WHERE id = ? LIMIT 1`,
|
|
66
|
+
[id],
|
|
67
|
+
).execute() as Array<Record<string, unknown>>
|
|
68
|
+
const r = rows?.[0]
|
|
69
|
+
if (!r) {
|
|
70
|
+
return { error: 'Column not found', status: 404 }
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
column: {
|
|
74
|
+
id: Number(r.id),
|
|
75
|
+
uuid: r.uuid == null ? null : String(r.uuid),
|
|
76
|
+
boardId: Number(r.board_id),
|
|
77
|
+
name: String(r.name),
|
|
78
|
+
position: Number(r.position),
|
|
79
|
+
cardLimit: r.card_limit == null ? null : Number(r.card_limit),
|
|
80
|
+
color: String(r.color),
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
console.error('[dashboard/kanban] ColumnUpdateAction failed:', err)
|
|
86
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
})
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface ReorderInput {
|
|
5
|
+
boardId?: unknown
|
|
6
|
+
order?: unknown
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* `POST /api/dashboard/kanban/columns/reorder` (stacksjs/stacks#1846 Phase 2).
|
|
11
|
+
*
|
|
12
|
+
* Bulk rewrite column positions for a board. The submitted `order`
|
|
13
|
+
* is an array of column ids in their new display order; index becomes
|
|
14
|
+
* the row's new `position`. Wrapped in a transaction so a partial
|
|
15
|
+
* failure doesn't leave the board with a half-renumbered column row.
|
|
16
|
+
*
|
|
17
|
+
* Why scoped to a board? Two reasons:
|
|
18
|
+
* 1. Validation: every id in `order` must belong to the same
|
|
19
|
+
* board — otherwise a drag in one board could accidentally
|
|
20
|
+
* renumber columns in another board sharing the same row order.
|
|
21
|
+
* 2. Index hit: the `(board_id, position)` index gives a tight
|
|
22
|
+
* lookup for the post-reorder card query.
|
|
23
|
+
*/
|
|
24
|
+
export default new Action({
|
|
25
|
+
name: 'Kanban Columns Reorder',
|
|
26
|
+
description: 'Bulk-rewrite `position` on a board\'s columns.',
|
|
27
|
+
method: 'POST',
|
|
28
|
+
apiResponse: true,
|
|
29
|
+
async handle(request) {
|
|
30
|
+
const body = (request as any).jsonBody as ReorderInput | undefined ?? {}
|
|
31
|
+
|
|
32
|
+
const boardId = Number(body.boardId)
|
|
33
|
+
if (!Number.isFinite(boardId) || boardId <= 0) {
|
|
34
|
+
return { error: '`boardId` is required.', status: 400 }
|
|
35
|
+
}
|
|
36
|
+
if (!Array.isArray(body.order) || body.order.length === 0) {
|
|
37
|
+
return { error: '`order` must be a non-empty array of column ids.', status: 400 }
|
|
38
|
+
}
|
|
39
|
+
const ids: number[] = []
|
|
40
|
+
for (const v of body.order) {
|
|
41
|
+
const n = Number(v)
|
|
42
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
43
|
+
return { error: '`order` contains an invalid id.', status: 400 }
|
|
44
|
+
}
|
|
45
|
+
ids.push(n)
|
|
46
|
+
}
|
|
47
|
+
if (new Set(ids).size !== ids.length) {
|
|
48
|
+
return { error: '`order` contains duplicate ids.', status: 400 }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
// Verify every column actually belongs to the named board.
|
|
53
|
+
// Single round-trip via a count of rows that match both criteria.
|
|
54
|
+
const placeholders = ids.map(() => '?').join(',')
|
|
55
|
+
const matchRows = await db.unsafe(
|
|
56
|
+
`SELECT COUNT(*) AS c FROM board_columns WHERE id IN (${placeholders}) AND board_id = ?`,
|
|
57
|
+
[...ids, boardId],
|
|
58
|
+
).execute() as Array<{ c: number }>
|
|
59
|
+
const matched = Number(matchRows?.[0]?.c ?? 0)
|
|
60
|
+
if (matched !== ids.length) {
|
|
61
|
+
return { error: 'One or more column ids do not belong to the named board.', status: 400 }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const txOps = async (qb: any) => {
|
|
65
|
+
for (let i = 0; i < ids.length; i++) {
|
|
66
|
+
await qb.updateTable('board_columns')
|
|
67
|
+
.set({ position: i })
|
|
68
|
+
.where('id', '=', ids[i])
|
|
69
|
+
.execute()
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
await (db as any).transaction(txOps)
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
await txOps(db)
|
|
77
|
+
}
|
|
78
|
+
return { reordered: ids.length }
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
console.error('[dashboard/kanban] ColumnsReorderAction failed:', err)
|
|
82
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `DELETE /api/dashboard/kanban/labels/:id` (stacksjs/stacks#1846 Phase 3).
|
|
6
|
+
*
|
|
7
|
+
* Removes a label and detaches it from every card that carries it.
|
|
8
|
+
* The label row goes from the `labels` table; every pivot row in
|
|
9
|
+
* `card_labels` that references it goes too. Cards themselves are
|
|
10
|
+
* untouched.
|
|
11
|
+
*/
|
|
12
|
+
export default new Action({
|
|
13
|
+
name: 'Kanban Label Destroy',
|
|
14
|
+
description: 'Hard-deletes a label and its card_labels pivot rows.',
|
|
15
|
+
method: 'DELETE',
|
|
16
|
+
apiResponse: true,
|
|
17
|
+
async handle(request) {
|
|
18
|
+
const rawId = (request as any)?.params?.id ?? (request as any)?.param?.('id') ?? null
|
|
19
|
+
const id = Number(rawId)
|
|
20
|
+
if (!Number.isFinite(id) || id <= 0)
|
|
21
|
+
return { error: 'Invalid label id', status: 400 }
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const txOps = async (qb: any) => {
|
|
25
|
+
await qb.deleteFrom('card_labels').where('label_id', '=', id).execute()
|
|
26
|
+
await qb.deleteFrom('labels').where('id', '=', id).execute()
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
await (db as any).transaction(txOps)
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
await txOps(db)
|
|
33
|
+
}
|
|
34
|
+
return { deleted: true, id }
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
console.error('[dashboard/kanban] LabelDestroyAction failed:', err)
|
|
38
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
})
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface LabelInput {
|
|
5
|
+
boardId?: unknown
|
|
6
|
+
name?: unknown
|
|
7
|
+
color?: unknown
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* `POST /api/dashboard/kanban/labels` (stacksjs/stacks#1846 Phase 3).
|
|
12
|
+
*
|
|
13
|
+
* Creates a label scoped to a board. Labels are unique per
|
|
14
|
+
* `(board_id, name)` — the migration enforces this via a unique
|
|
15
|
+
* index, and the action rejects up front with a 409 rather than
|
|
16
|
+
* letting the UNIQUE constraint fire.
|
|
17
|
+
*/
|
|
18
|
+
export default new Action({
|
|
19
|
+
name: 'Kanban Label Store',
|
|
20
|
+
description: 'Creates a label on a board.',
|
|
21
|
+
method: 'POST',
|
|
22
|
+
apiResponse: true,
|
|
23
|
+
async handle(request) {
|
|
24
|
+
const body = (request as any).jsonBody as LabelInput | undefined ?? {}
|
|
25
|
+
|
|
26
|
+
const boardId = Number(body.boardId)
|
|
27
|
+
if (!Number.isFinite(boardId) || boardId <= 0) {
|
|
28
|
+
return { error: '`boardId` is required.', status: 400 }
|
|
29
|
+
}
|
|
30
|
+
const name = typeof body.name === 'string' ? body.name.trim() : ''
|
|
31
|
+
if (!name || name.length > 60) {
|
|
32
|
+
return { error: '`name` is required and must be 1-60 characters.', status: 400 }
|
|
33
|
+
}
|
|
34
|
+
const color = typeof body.color === 'string' && body.color ? body.color : 'slate'
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
// Reject orphan labels: the board must exist.
|
|
38
|
+
const boards = await db.unsafe('SELECT id FROM boards WHERE id = ? LIMIT 1', [boardId]).execute() as Array<{ id: number }>
|
|
39
|
+
if (!boards?.length)
|
|
40
|
+
return { error: 'Board not found.', status: 404 }
|
|
41
|
+
|
|
42
|
+
// Pre-check uniqueness — clearer error than the DB's
|
|
43
|
+
// `UNIQUE constraint failed: labels.board_id, labels.name`.
|
|
44
|
+
const dup = await db.unsafe(
|
|
45
|
+
'SELECT id FROM labels WHERE board_id = ? AND name = ? LIMIT 1',
|
|
46
|
+
[boardId, name],
|
|
47
|
+
).execute() as Array<{ id: number }>
|
|
48
|
+
if (dup?.length)
|
|
49
|
+
return { error: 'A label with that name already exists on this board.', status: 409 }
|
|
50
|
+
|
|
51
|
+
await db.insertInto('labels').values({ board_id: boardId, name, color }).execute()
|
|
52
|
+
|
|
53
|
+
const inserted = await db.unsafe(
|
|
54
|
+
'SELECT id, board_id, name, color FROM labels WHERE board_id = ? AND name = ? LIMIT 1',
|
|
55
|
+
[boardId, name],
|
|
56
|
+
).execute() as Array<{ id: number, board_id: number, name: string, color: string }>
|
|
57
|
+
const r = inserted?.[0]
|
|
58
|
+
if (!r)
|
|
59
|
+
return { error: 'Label insert succeeded but follow-up read returned nothing.', status: 500 }
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
label: { id: r.id, boardId: r.board_id, name: r.name, color: r.color },
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
console.error('[dashboard/kanban] LabelStoreAction failed:', err)
|
|
67
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
})
|