@stacksjs/defaults 0.70.58 → 0.70.60
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,103 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface SyncInput {
|
|
5
|
+
userIds?: unknown
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `POST /api/dashboard/kanban/cards/:id/assignees` (stacksjs/stacks#1846 Phase 3).
|
|
10
|
+
*
|
|
11
|
+
* Replaces the set of users assigned to a card. Sync semantics —
|
|
12
|
+
* pass the new full list of user ids, the action diffs against
|
|
13
|
+
* what's currently attached.
|
|
14
|
+
*
|
|
15
|
+
* Stamps `assigned_by_user_id` on each new pivot row from the
|
|
16
|
+
* request's authenticated user (when available) so the card detail
|
|
17
|
+
* modal can surface "assigned by X" attribution. Unauthenticated
|
|
18
|
+
* dev-dashboard calls leave it null.
|
|
19
|
+
*
|
|
20
|
+
* Cross-validation: each user id must exist. Doesn't validate
|
|
21
|
+
* board-scoped membership — kanban users aren't (currently) team-
|
|
22
|
+
* scoped; any platform user can be assigned to any card. Phase 4
|
|
23
|
+
* could tighten this if board-membership becomes a concept.
|
|
24
|
+
*/
|
|
25
|
+
export default new Action({
|
|
26
|
+
name: 'Kanban Card Assignees Sync',
|
|
27
|
+
description: 'Replaces the set of users assigned to a card.',
|
|
28
|
+
method: 'POST',
|
|
29
|
+
apiResponse: true,
|
|
30
|
+
async handle(request) {
|
|
31
|
+
const rawId = (request as any)?.params?.id ?? (request as any)?.param?.('id') ?? null
|
|
32
|
+
const cardId = Number(rawId)
|
|
33
|
+
if (!Number.isFinite(cardId) || cardId <= 0)
|
|
34
|
+
return { error: 'Invalid card id', status: 400 }
|
|
35
|
+
|
|
36
|
+
const body = (request as any).jsonBody as SyncInput | undefined ?? {}
|
|
37
|
+
if (!Array.isArray(body.userIds))
|
|
38
|
+
return { error: '`userIds` must be an array of user ids (possibly empty).', status: 400 }
|
|
39
|
+
|
|
40
|
+
const userIds: number[] = []
|
|
41
|
+
for (const v of body.userIds) {
|
|
42
|
+
const n = Number(v)
|
|
43
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
44
|
+
return { error: '`userIds` contains an invalid id.', status: 400 }
|
|
45
|
+
userIds.push(n)
|
|
46
|
+
}
|
|
47
|
+
const uniqueUserIds = Array.from(new Set(userIds))
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const cardRows = await db.unsafe('SELECT id FROM cards WHERE id = ? LIMIT 1', [cardId]).execute() as Array<{ id: number }>
|
|
51
|
+
if (!cardRows?.length)
|
|
52
|
+
return { error: 'Card not found.', status: 404 }
|
|
53
|
+
|
|
54
|
+
// Validate user ids exist.
|
|
55
|
+
if (uniqueUserIds.length > 0) {
|
|
56
|
+
const placeholders = uniqueUserIds.map(() => '?').join(',')
|
|
57
|
+
const userRows = await db.unsafe(
|
|
58
|
+
`SELECT id FROM users WHERE id IN (${placeholders})`,
|
|
59
|
+
uniqueUserIds,
|
|
60
|
+
).execute() as Array<{ id: number }>
|
|
61
|
+
if (userRows.length !== uniqueUserIds.length)
|
|
62
|
+
return { error: 'One or more user ids do not exist.', status: 400 }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const requester = (request as any).user ?? (request as any)._authenticatedUser ?? null
|
|
66
|
+
const assignedByUserId = requester && typeof requester.id === 'number' ? requester.id : null
|
|
67
|
+
|
|
68
|
+
const txOps = async (qb: any) => {
|
|
69
|
+
await qb.deleteFrom('card_assignees').where('card_id', '=', cardId).execute()
|
|
70
|
+
if (uniqueUserIds.length > 0) {
|
|
71
|
+
const rows = uniqueUserIds.map(userId => ({
|
|
72
|
+
card_id: cardId,
|
|
73
|
+
user_id: userId,
|
|
74
|
+
assigned_by_user_id: assignedByUserId,
|
|
75
|
+
}))
|
|
76
|
+
await qb.insertInto('card_assignees').values(rows).execute()
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
await (db as any).transaction(txOps)
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
await txOps(db)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Return the resolved user rows for the optimistic UI to confirm.
|
|
87
|
+
let assignees: Array<{ userId: number, name: string | null, email: string | null }> = []
|
|
88
|
+
if (uniqueUserIds.length > 0) {
|
|
89
|
+
const placeholders = uniqueUserIds.map(() => '?').join(',')
|
|
90
|
+
const rows = await db.unsafe(
|
|
91
|
+
`SELECT id, name, email FROM users WHERE id IN (${placeholders}) ORDER BY name ASC`,
|
|
92
|
+
uniqueUserIds,
|
|
93
|
+
).execute() as Array<{ id: number, name: string | null, email: string | null }>
|
|
94
|
+
assignees = rows.map(r => ({ userId: r.id, name: r.name, email: r.email }))
|
|
95
|
+
}
|
|
96
|
+
return { cardId, assignees }
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
console.error('[dashboard/kanban] CardAssigneesSyncAction failed:', err)
|
|
100
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `DELETE /api/dashboard/kanban/comments/:id` (stacksjs/stacks#1846 Phase 3).
|
|
6
|
+
*
|
|
7
|
+
* Hard-deletes a card comment. No authorship check yet — Phase 4
|
|
8
|
+
* could add "only the author or an admin can delete" semantics by
|
|
9
|
+
* looking at `request.user.id` vs the comment's `user_id`. For now
|
|
10
|
+
* the dashboard's role-gated visibility (only admin+dev see the
|
|
11
|
+
* surface) is the gate.
|
|
12
|
+
*/
|
|
13
|
+
export default new Action({
|
|
14
|
+
name: 'Kanban Card Comment Destroy',
|
|
15
|
+
description: 'Hard-deletes a single card comment.',
|
|
16
|
+
method: 'DELETE',
|
|
17
|
+
apiResponse: true,
|
|
18
|
+
async handle(request) {
|
|
19
|
+
const rawId = (request as any)?.params?.id ?? (request as any)?.param?.('id') ?? null
|
|
20
|
+
const id = Number(rawId)
|
|
21
|
+
if (!Number.isFinite(id) || id <= 0)
|
|
22
|
+
return { error: 'Invalid comment id', status: 400 }
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
await db.deleteFrom('card_comments').where('id', '=', id).execute()
|
|
26
|
+
return { deleted: true, id }
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
console.error('[dashboard/kanban] CardCommentDestroyAction failed:', err)
|
|
30
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
})
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface CommentInput {
|
|
5
|
+
body?: unknown
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `POST /api/dashboard/kanban/cards/:id/comments` (stacksjs/stacks#1846 Phase 3).
|
|
10
|
+
*
|
|
11
|
+
* Appends a comment to a card. Stamps `user_id` from the request's
|
|
12
|
+
* authenticated user when available; leaves it null on the no-auth
|
|
13
|
+
* dev dashboard so the surface stays usable locally.
|
|
14
|
+
*
|
|
15
|
+
* Returns the inserted row with denormalised author name/email for
|
|
16
|
+
* the optimistic UI to render without a round-trip back through
|
|
17
|
+
* `/cards/:id`.
|
|
18
|
+
*/
|
|
19
|
+
export default new Action({
|
|
20
|
+
name: 'Kanban Card Comment Store',
|
|
21
|
+
description: 'Adds a comment to a card.',
|
|
22
|
+
method: 'POST',
|
|
23
|
+
apiResponse: true,
|
|
24
|
+
async handle(request) {
|
|
25
|
+
const rawId = (request as any)?.params?.id ?? (request as any)?.param?.('id') ?? null
|
|
26
|
+
const cardId = Number(rawId)
|
|
27
|
+
if (!Number.isFinite(cardId) || cardId <= 0)
|
|
28
|
+
return { error: 'Invalid card id', status: 400 }
|
|
29
|
+
|
|
30
|
+
const body = (request as any).jsonBody as CommentInput | undefined ?? {}
|
|
31
|
+
const text = typeof body.body === 'string' ? body.body.trim() : ''
|
|
32
|
+
if (!text || text.length > 10000)
|
|
33
|
+
return { error: '`body` is required and must be 1-10000 characters.', status: 400 }
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const cardRows = await db.unsafe('SELECT id FROM cards WHERE id = ? LIMIT 1', [cardId]).execute() as Array<{ id: number }>
|
|
37
|
+
if (!cardRows?.length)
|
|
38
|
+
return { error: 'Card not found.', status: 404 }
|
|
39
|
+
|
|
40
|
+
const user = (request as any).user ?? (request as any)._authenticatedUser ?? null
|
|
41
|
+
const userId = user && typeof user.id === 'number' ? user.id : null
|
|
42
|
+
|
|
43
|
+
await db.insertInto('card_comments').values({
|
|
44
|
+
card_id: cardId,
|
|
45
|
+
user_id: userId,
|
|
46
|
+
body: text,
|
|
47
|
+
}).execute()
|
|
48
|
+
|
|
49
|
+
// Pull the inserted row + author denormalisation. Ordered by id
|
|
50
|
+
// DESC so the freshest matching row wins.
|
|
51
|
+
const rows = await db.unsafe(
|
|
52
|
+
`SELECT cc.id, cc.uuid, cc.user_id, cc.body, cc.created_at, cc.updated_at, u.name, u.email
|
|
53
|
+
FROM card_comments cc
|
|
54
|
+
LEFT JOIN users u ON u.id = cc.user_id
|
|
55
|
+
WHERE cc.card_id = ? AND cc.body = ?
|
|
56
|
+
ORDER BY cc.id DESC
|
|
57
|
+
LIMIT 1`,
|
|
58
|
+
[cardId, text],
|
|
59
|
+
).execute() as Array<{ id: number, uuid: string | null, user_id: number | null, body: string, created_at: string | null, updated_at: string | null, name: string | null, email: string | null }>
|
|
60
|
+
const r = rows?.[0]
|
|
61
|
+
if (!r)
|
|
62
|
+
return { error: 'Comment insert succeeded but follow-up read returned nothing.', status: 500 }
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
comment: {
|
|
66
|
+
id: r.id,
|
|
67
|
+
uuid: r.uuid,
|
|
68
|
+
userId: r.user_id,
|
|
69
|
+
body: r.body,
|
|
70
|
+
authorName: r.name,
|
|
71
|
+
authorEmail: r.email,
|
|
72
|
+
createdAt: r.created_at,
|
|
73
|
+
updatedAt: r.updated_at,
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
console.error('[dashboard/kanban] CardCommentStoreAction failed:', err)
|
|
79
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
})
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `DELETE /api/dashboard/kanban/cards/:id` (stacksjs/stacks#1846 Phase 2).
|
|
6
|
+
*
|
|
7
|
+
* Hard-deletes a card and clears its pivot rows in `card_labels` /
|
|
8
|
+
* `card_assignees`. The columns and board are untouched — only the
|
|
9
|
+
* single card row + its pivot dependencies go.
|
|
10
|
+
*
|
|
11
|
+
* Soft-archive (the more common ask) is a PATCH with
|
|
12
|
+
* `{ archived: true }` — the card stays in the DB but drops out of
|
|
13
|
+
* the board view. This action is the hard delete.
|
|
14
|
+
*/
|
|
15
|
+
export default new Action({
|
|
16
|
+
name: 'Kanban Card Destroy',
|
|
17
|
+
description: 'Hard-deletes a card and its pivot rows.',
|
|
18
|
+
method: 'DELETE',
|
|
19
|
+
apiResponse: true,
|
|
20
|
+
async handle(request) {
|
|
21
|
+
const rawId = (request as any)?.params?.id ?? (request as any)?.param?.('id') ?? null
|
|
22
|
+
const id = Number(rawId)
|
|
23
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
24
|
+
return { error: 'Invalid card id', status: 400 }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const txOps = async (qb: any) => {
|
|
29
|
+
await qb.deleteFrom('card_labels').where('card_id', '=', id).execute()
|
|
30
|
+
await qb.deleteFrom('card_assignees').where('card_id', '=', id).execute()
|
|
31
|
+
// Card comments (Phase 3, stacksjs/stacks#1846).
|
|
32
|
+
await qb.deleteFrom('card_comments').where('card_id', '=', id).execute()
|
|
33
|
+
await qb.deleteFrom('cards').where('id', '=', id).execute()
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
await (db as any).transaction(txOps)
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
await txOps(db)
|
|
40
|
+
}
|
|
41
|
+
return { deleted: true, id }
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
console.error('[dashboard/kanban] CardDestroyAction failed:', err)
|
|
45
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
})
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface SyncInput {
|
|
5
|
+
labelIds?: unknown
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `POST /api/dashboard/kanban/cards/:id/labels` (stacksjs/stacks#1846 Phase 3).
|
|
10
|
+
*
|
|
11
|
+
* Replaces the set of labels attached to a card. Sync semantics —
|
|
12
|
+
* pass the new full list of label ids, the action diffs against
|
|
13
|
+
* what's currently attached and attaches/detaches to match.
|
|
14
|
+
*
|
|
15
|
+
* Cross-validation: every label in `labelIds` must belong to the
|
|
16
|
+
* same board as the card. Stops a malformed page from cross-
|
|
17
|
+
* contaminating two boards' label namespaces.
|
|
18
|
+
*
|
|
19
|
+
* Wrapped in a transaction so a partial failure leaves the card
|
|
20
|
+
* with either the old set or the new set, never something in
|
|
21
|
+
* between.
|
|
22
|
+
*/
|
|
23
|
+
export default new Action({
|
|
24
|
+
name: 'Kanban Card Labels Sync',
|
|
25
|
+
description: 'Replaces the set of labels attached to a card.',
|
|
26
|
+
method: 'POST',
|
|
27
|
+
apiResponse: true,
|
|
28
|
+
async handle(request) {
|
|
29
|
+
const rawId = (request as any)?.params?.id ?? (request as any)?.param?.('id') ?? null
|
|
30
|
+
const cardId = Number(rawId)
|
|
31
|
+
if (!Number.isFinite(cardId) || cardId <= 0)
|
|
32
|
+
return { error: 'Invalid card id', status: 400 }
|
|
33
|
+
|
|
34
|
+
const body = (request as any).jsonBody as SyncInput | undefined ?? {}
|
|
35
|
+
if (!Array.isArray(body.labelIds))
|
|
36
|
+
return { error: '`labelIds` must be an array of label ids (possibly empty).', status: 400 }
|
|
37
|
+
|
|
38
|
+
const labelIds: number[] = []
|
|
39
|
+
for (const v of body.labelIds) {
|
|
40
|
+
const n = Number(v)
|
|
41
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
42
|
+
return { error: '`labelIds` contains an invalid id.', status: 400 }
|
|
43
|
+
labelIds.push(n)
|
|
44
|
+
}
|
|
45
|
+
const uniqueLabelIds = Array.from(new Set(labelIds))
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
// Resolve the card → board so we can validate label scope.
|
|
49
|
+
const cardRows = await db.unsafe(
|
|
50
|
+
'SELECT id, board_id FROM cards WHERE id = ? LIMIT 1',
|
|
51
|
+
[cardId],
|
|
52
|
+
).execute() as Array<{ id: number, board_id: number }>
|
|
53
|
+
const card = cardRows?.[0]
|
|
54
|
+
if (!card)
|
|
55
|
+
return { error: 'Card not found.', status: 404 }
|
|
56
|
+
|
|
57
|
+
// Every label must belong to the same board (labels are
|
|
58
|
+
// board-scoped per Phase 1's `labels.board_id` design).
|
|
59
|
+
if (uniqueLabelIds.length > 0) {
|
|
60
|
+
const placeholders = uniqueLabelIds.map(() => '?').join(',')
|
|
61
|
+
const labelRows = await db.unsafe(
|
|
62
|
+
`SELECT id FROM labels WHERE id IN (${placeholders}) AND board_id = ?`,
|
|
63
|
+
[...uniqueLabelIds, card.board_id],
|
|
64
|
+
).execute() as Array<{ id: number }>
|
|
65
|
+
if (labelRows.length !== uniqueLabelIds.length)
|
|
66
|
+
return { error: 'One or more label ids do not belong to this card\'s board.', status: 400 }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Sync: drop all current pivot rows for this card, insert the
|
|
70
|
+
// new set. Cheaper than diffing for the typical "user picked a
|
|
71
|
+
// few labels" use case (single-digit label counts per card).
|
|
72
|
+
const txOps = async (qb: any) => {
|
|
73
|
+
await qb.deleteFrom('card_labels').where('card_id', '=', cardId).execute()
|
|
74
|
+
if (uniqueLabelIds.length > 0) {
|
|
75
|
+
const rows = uniqueLabelIds.map(labelId => ({ card_id: cardId, label_id: labelId }))
|
|
76
|
+
await qb.insertInto('card_labels').values(rows).execute()
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
await (db as any).transaction(txOps)
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
await txOps(db)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Return the resolved label rows so the optimistic UI can
|
|
87
|
+
// confirm its in-flight state matches what the server stored.
|
|
88
|
+
let labels: Array<{ id: number, name: string, color: string }> = []
|
|
89
|
+
if (uniqueLabelIds.length > 0) {
|
|
90
|
+
const placeholders = uniqueLabelIds.map(() => '?').join(',')
|
|
91
|
+
labels = await db.unsafe(
|
|
92
|
+
`SELECT id, name, color FROM labels WHERE id IN (${placeholders}) ORDER BY name ASC`,
|
|
93
|
+
uniqueLabelIds,
|
|
94
|
+
).execute() as Array<{ id: number, name: string, color: string }>
|
|
95
|
+
}
|
|
96
|
+
return { cardId, labels }
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
console.error('[dashboard/kanban] CardLabelsSyncAction failed:', err)
|
|
100
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
})
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface CardRow {
|
|
5
|
+
id: number
|
|
6
|
+
uuid: string | null
|
|
7
|
+
column_id: number
|
|
8
|
+
board_id: number
|
|
9
|
+
title: string
|
|
10
|
+
description: string | null
|
|
11
|
+
position: number
|
|
12
|
+
created_by_user_id: number | null
|
|
13
|
+
due_date: string | null
|
|
14
|
+
archived: number
|
|
15
|
+
created_at: string | null
|
|
16
|
+
updated_at: string | null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* `GET /api/dashboard/kanban/cards/:id` (stacksjs/stacks#1846 Phase 3).
|
|
21
|
+
*
|
|
22
|
+
* Fetches a single card with everything the detail modal needs in one
|
|
23
|
+
* round-trip: labels, assignees, comments. The board view's cards
|
|
24
|
+
* already carry labels + assignees (BoardShowAction batches the
|
|
25
|
+
* pivots) — this endpoint is for the case where the user lands
|
|
26
|
+
* directly on a card URL or refreshes mid-modal.
|
|
27
|
+
*
|
|
28
|
+
* Three queries via `Promise.all`:
|
|
29
|
+
* 1. The card itself.
|
|
30
|
+
* 2. Labels via the card_labels pivot (with the label row).
|
|
31
|
+
* 3. Assignees via the card_assignees pivot (with user.name/email).
|
|
32
|
+
* 4. Comments (denormalised user name/email for display).
|
|
33
|
+
*/
|
|
34
|
+
export default new Action({
|
|
35
|
+
name: 'Kanban Card Show',
|
|
36
|
+
description: 'Returns a single card with its labels, assignees, and comments thread.',
|
|
37
|
+
method: 'GET',
|
|
38
|
+
apiResponse: true,
|
|
39
|
+
async handle(request) {
|
|
40
|
+
const rawId = (request as any)?.params?.id ?? (request as any)?.param?.('id') ?? null
|
|
41
|
+
const id = Number(rawId)
|
|
42
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
43
|
+
return { error: 'Invalid card id', status: 400 }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const cardRows = await db.unsafe(
|
|
48
|
+
'SELECT * FROM cards WHERE id = ? LIMIT 1',
|
|
49
|
+
[id],
|
|
50
|
+
).execute() as CardRow[]
|
|
51
|
+
const card = cardRows?.[0]
|
|
52
|
+
if (!card) {
|
|
53
|
+
return { error: 'Card not found', status: 404 }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const [labels, assignees, comments] = await Promise.all([
|
|
57
|
+
db.unsafe(
|
|
58
|
+
`SELECT l.id, l.name, l.color
|
|
59
|
+
FROM card_labels cl
|
|
60
|
+
JOIN labels l ON l.id = cl.label_id
|
|
61
|
+
WHERE cl.card_id = ?
|
|
62
|
+
ORDER BY l.name ASC`,
|
|
63
|
+
[id],
|
|
64
|
+
).execute() as Promise<Array<{ id: number, name: string, color: string }>>,
|
|
65
|
+
db.unsafe(
|
|
66
|
+
`SELECT ca.user_id, ca.assigned_by_user_id, ca.created_at, u.name, u.email
|
|
67
|
+
FROM card_assignees ca
|
|
68
|
+
LEFT JOIN users u ON u.id = ca.user_id
|
|
69
|
+
WHERE ca.card_id = ?`,
|
|
70
|
+
[id],
|
|
71
|
+
).execute() as Promise<Array<{ user_id: number, assigned_by_user_id: number | null, created_at: string | null, name: string | null, email: string | null }>>,
|
|
72
|
+
db.unsafe(
|
|
73
|
+
`SELECT cc.id, cc.uuid, cc.user_id, cc.body, cc.created_at, cc.updated_at, u.name, u.email
|
|
74
|
+
FROM card_comments cc
|
|
75
|
+
LEFT JOIN users u ON u.id = cc.user_id
|
|
76
|
+
WHERE cc.card_id = ?
|
|
77
|
+
ORDER BY cc.created_at ASC, cc.id ASC`,
|
|
78
|
+
[id],
|
|
79
|
+
).execute() as Promise<Array<{ id: number, uuid: string | null, user_id: number | null, body: string, created_at: string | null, updated_at: string | null, name: string | null, email: string | null }>>,
|
|
80
|
+
])
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
card: {
|
|
84
|
+
id: card.id,
|
|
85
|
+
uuid: card.uuid,
|
|
86
|
+
columnId: card.column_id,
|
|
87
|
+
boardId: card.board_id,
|
|
88
|
+
title: card.title,
|
|
89
|
+
description: card.description,
|
|
90
|
+
position: card.position,
|
|
91
|
+
createdByUserId: card.created_by_user_id,
|
|
92
|
+
dueDate: card.due_date,
|
|
93
|
+
archived: card.archived === 1,
|
|
94
|
+
createdAt: card.created_at,
|
|
95
|
+
updatedAt: card.updated_at,
|
|
96
|
+
},
|
|
97
|
+
labels: (labels ?? []).map(l => ({ id: l.id, name: l.name, color: l.color })),
|
|
98
|
+
assignees: (assignees ?? []).map(a => ({
|
|
99
|
+
userId: a.user_id,
|
|
100
|
+
name: a.name,
|
|
101
|
+
email: a.email,
|
|
102
|
+
assignedByUserId: a.assigned_by_user_id,
|
|
103
|
+
assignedAt: a.created_at,
|
|
104
|
+
})),
|
|
105
|
+
comments: (comments ?? []).map(c => ({
|
|
106
|
+
id: c.id,
|
|
107
|
+
uuid: c.uuid,
|
|
108
|
+
userId: c.user_id,
|
|
109
|
+
body: c.body,
|
|
110
|
+
authorName: c.name,
|
|
111
|
+
authorEmail: c.email,
|
|
112
|
+
createdAt: c.created_at,
|
|
113
|
+
updatedAt: c.updated_at,
|
|
114
|
+
})),
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
console.error('[dashboard/kanban] CardShowAction failed:', err)
|
|
119
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
})
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface CardInput {
|
|
5
|
+
columnId?: unknown
|
|
6
|
+
title?: unknown
|
|
7
|
+
description?: unknown
|
|
8
|
+
dueDate?: unknown
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* `POST /api/dashboard/kanban/cards` (stacksjs/stacks#1846 Phase 2).
|
|
13
|
+
*
|
|
14
|
+
* Creates a card at the end of the target column. `boardId` is
|
|
15
|
+
* resolved server-side from `column.board_id` (denormalised onto the
|
|
16
|
+
* card row) so clients don't pass it in — passing it from the page
|
|
17
|
+
* would invite drift if the column was moved between boards (which
|
|
18
|
+
* isn't a feature, but still).
|
|
19
|
+
*
|
|
20
|
+
* Stamps `created_by_user_id` from `request.user` when the request is
|
|
21
|
+
* authenticated; leaves it null for the no-auth dev dashboard so the
|
|
22
|
+
* surface still works on localhost.
|
|
23
|
+
*/
|
|
24
|
+
export default new Action({
|
|
25
|
+
name: 'Kanban Card Store',
|
|
26
|
+
description: 'Creates a new card in a column.',
|
|
27
|
+
method: 'POST',
|
|
28
|
+
apiResponse: true,
|
|
29
|
+
async handle(request) {
|
|
30
|
+
const body = (request as any).jsonBody as CardInput | undefined ?? {}
|
|
31
|
+
|
|
32
|
+
const columnId = Number(body.columnId)
|
|
33
|
+
if (!Number.isFinite(columnId) || columnId <= 0) {
|
|
34
|
+
return { error: '`columnId` is required and must be a positive integer.', status: 400 }
|
|
35
|
+
}
|
|
36
|
+
const title = typeof body.title === 'string' ? body.title.trim() : ''
|
|
37
|
+
if (!title || title.length > 300) {
|
|
38
|
+
return { error: '`title` is required and must be 1-300 characters.', status: 400 }
|
|
39
|
+
}
|
|
40
|
+
const description = typeof body.description === 'string' ? body.description.trim() : null
|
|
41
|
+
const dueDate = typeof body.dueDate === 'string' && body.dueDate ? body.dueDate : null
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
// Resolve the column → board_id so we can denormalise. Same trip
|
|
45
|
+
// also validates that the column exists; an orphan column id
|
|
46
|
+
// rejects up front rather than inserting a card with a dangling
|
|
47
|
+
// FK that no query would ever surface.
|
|
48
|
+
const cols = await db.unsafe(
|
|
49
|
+
'SELECT id, board_id FROM board_columns WHERE id = ? LIMIT 1',
|
|
50
|
+
[columnId],
|
|
51
|
+
).execute() as Array<{ id: number, board_id: number }>
|
|
52
|
+
const col = cols?.[0]
|
|
53
|
+
if (!col) {
|
|
54
|
+
return { error: 'Column not found.', status: 404 }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const maxRow = await db.unsafe(
|
|
58
|
+
'SELECT COALESCE(MAX(position), -1) AS m FROM cards WHERE column_id = ?',
|
|
59
|
+
[columnId],
|
|
60
|
+
).execute() as Array<{ m: number }>
|
|
61
|
+
const nextPosition = (Number(maxRow?.[0]?.m ?? -1) + 1) || 0
|
|
62
|
+
|
|
63
|
+
const user = (request as any).user ?? (request as any)._authenticatedUser ?? null
|
|
64
|
+
const createdByUserId = user && typeof user.id === 'number' ? user.id : null
|
|
65
|
+
|
|
66
|
+
await db.insertInto('cards').values({
|
|
67
|
+
column_id: columnId,
|
|
68
|
+
board_id: col.board_id,
|
|
69
|
+
title,
|
|
70
|
+
description,
|
|
71
|
+
position: nextPosition,
|
|
72
|
+
created_by_user_id: createdByUserId,
|
|
73
|
+
due_date: dueDate,
|
|
74
|
+
archived: 0,
|
|
75
|
+
}).execute()
|
|
76
|
+
|
|
77
|
+
const rows = await db.unsafe(
|
|
78
|
+
`SELECT id, uuid, column_id, board_id, title, description, position,
|
|
79
|
+
created_by_user_id, due_date, archived, created_at, updated_at
|
|
80
|
+
FROM cards
|
|
81
|
+
WHERE column_id = ? AND title = ? AND position = ?
|
|
82
|
+
ORDER BY id DESC LIMIT 1`,
|
|
83
|
+
[columnId, title, nextPosition],
|
|
84
|
+
).execute() as Array<Record<string, unknown>>
|
|
85
|
+
const r = rows?.[0]
|
|
86
|
+
if (!r) {
|
|
87
|
+
return { error: 'Card insert succeeded but follow-up read returned nothing.', status: 500 }
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
card: {
|
|
92
|
+
id: Number(r.id),
|
|
93
|
+
uuid: r.uuid == null ? null : String(r.uuid),
|
|
94
|
+
columnId: Number(r.column_id),
|
|
95
|
+
boardId: Number(r.board_id),
|
|
96
|
+
title: String(r.title),
|
|
97
|
+
description: r.description == null ? null : String(r.description),
|
|
98
|
+
position: Number(r.position),
|
|
99
|
+
createdByUserId: r.created_by_user_id == null ? null : Number(r.created_by_user_id),
|
|
100
|
+
dueDate: r.due_date == null ? null : String(r.due_date),
|
|
101
|
+
archived: Number(r.archived) === 1,
|
|
102
|
+
createdAt: r.created_at == null ? null : String(r.created_at),
|
|
103
|
+
updatedAt: r.updated_at == null ? null : String(r.updated_at),
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
console.error('[dashboard/kanban] CardStoreAction failed:', err)
|
|
109
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
})
|