@happyvertical/smrt-planner 0.0.2 → 0.1.1
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/README.md +81 -8
- package/app/404.html +42 -49
- package/app/_app/immutable/assets/0.DUow1OzM.css +1 -0
- package/app/_app/immutable/assets/10.CdYxvH4G.css +1 -0
- package/app/_app/immutable/assets/11.nOT5Z4Fv.css +1 -0
- package/app/_app/immutable/assets/12.F7A7zP4J.css +1 -0
- package/app/_app/immutable/assets/13.JoySu8W5.css +1 -0
- package/app/_app/immutable/assets/14.nsp62-4b.css +1 -0
- package/app/_app/immutable/assets/2.CbPiqdz5.css +1 -0
- package/app/_app/immutable/assets/3.D518dbB5.css +1 -0
- package/app/_app/immutable/assets/4.B3vt1gMJ.css +1 -0
- package/app/_app/immutable/assets/AiSetup.4fXjMpTZ.css +1 -0
- package/app/_app/immutable/assets/AppShell.DOvXbUZo.css +1 -0
- package/app/_app/immutable/assets/ConnectTools.DTleL8YA.css +1 -0
- package/app/_app/immutable/assets/FieldMapForm.C8SZ3t4N.css +1 -0
- package/app/_app/immutable/assets/ModelPage.DbXvPbHE.css +1 -0
- package/app/_app/immutable/assets/SectionActions.BE1CPmxk.css +1 -0
- package/app/_app/immutable/assets/SectionIcons.BGFcFuOf.css +1 -0
- package/app/_app/immutable/assets/SegmentedControl.BkyuoCEJ.css +1 -0
- package/app/_app/immutable/assets/app.eM0k786r.css +1 -0
- package/app/_app/immutable/assets/currency-metadata.DDyu8_ub.css +1 -0
- package/app/_app/immutable/assets/data.bGq43K60.css +1 -0
- package/app/_app/immutable/assets/feedback.xBpOq9ef.css +1 -0
- package/app/_app/immutable/assets/forms.B3_bbIMe.css +1 -0
- package/app/_app/immutable/assets/labels.BiuUjqHs.css +1 -0
- package/app/_app/immutable/assets/percent.DbwvwMhf.css +1 -0
- package/app/_app/immutable/assets/state.CJipYvSU.css +1 -0
- package/app/_app/immutable/assets/webmcp-ui-context.BnR-DUfO.css +1 -0
- package/app/_app/immutable/assets/workspace.B5Xq-5pJ.css +1 -0
- package/app/_app/immutable/chunks/1ElZWh_R.js +10 -0
- package/app/_app/immutable/chunks/B-CpwO-j.js +1 -0
- package/app/_app/immutable/chunks/{BnRri03M.js → B7KB-rhH.js} +1 -1
- package/app/_app/immutable/chunks/BUhghcIm.js +1 -0
- package/app/_app/immutable/chunks/BV3NwM01.js +1 -0
- package/app/_app/immutable/chunks/BZVZZ6VY.js +1 -0
- package/app/_app/immutable/chunks/Ba1g71Sq.js +1 -0
- package/app/_app/immutable/chunks/BeJD7_hy.js +1 -0
- package/app/_app/immutable/chunks/BiO_bqNH.js +2 -0
- package/app/_app/immutable/chunks/{DkR8_Ws6.js → BqBuCJB_.js} +2 -2
- package/app/_app/immutable/chunks/BsJoBmTA.js +1 -0
- package/app/_app/immutable/chunks/Bxbz6_Mb.js +1 -0
- package/app/_app/immutable/chunks/Bz5uCkjV.js +2 -0
- package/app/_app/immutable/chunks/BzMfoxBk.js +1 -0
- package/app/_app/immutable/chunks/CF6zSg_o.js +2 -0
- package/app/_app/immutable/chunks/CFL0B6dk.js +1 -0
- package/app/_app/immutable/chunks/CRu55ZTy.js +4 -0
- package/app/_app/immutable/chunks/{CyUMm_Wp.js → Cv2EcCr0.js} +1 -1
- package/app/_app/immutable/chunks/D-3Ri0zJ.js +1 -0
- package/app/_app/immutable/chunks/{BWPhGFHl.js → D0FW0z6R.js} +1 -1
- package/app/_app/immutable/chunks/D7d5GssF.js +1 -0
- package/app/_app/immutable/chunks/DCsSRJsN.js +1 -0
- package/app/_app/immutable/chunks/DGqV6_5v.js +1 -0
- package/app/_app/immutable/chunks/DNSRTkf6.js +11 -0
- package/app/_app/immutable/chunks/DQNX_XPY.js +1 -0
- package/app/_app/immutable/chunks/DSyIMN4M.js +1 -0
- package/app/_app/immutable/chunks/DUTtmM1Y.js +1 -0
- package/app/_app/immutable/chunks/DYuawOB3.js +980 -0
- package/app/_app/immutable/chunks/DfCLzLZc.js +1 -0
- package/app/_app/immutable/chunks/Dh5fne6n.js +1 -0
- package/app/_app/immutable/chunks/LruoUXGC.js +1 -0
- package/app/_app/immutable/chunks/ZLqixH7j.js +9 -0
- package/app/_app/immutable/chunks/_pYwB_Eb.js +4 -0
- package/app/_app/immutable/chunks/aoU3lIZI.js +1 -0
- package/app/_app/immutable/chunks/c57ZlocB.js +24 -0
- package/app/_app/immutable/chunks/h8ppmjOm.js +1 -0
- package/app/_app/immutable/chunks/jhcy_jeO.js +1 -0
- package/app/_app/immutable/chunks/vNEnXNLV.js +3 -0
- package/app/_app/immutable/chunks/vwntRvfV.js +1 -0
- package/app/_app/immutable/entry/app.D5LoTsNA.js +2 -0
- package/app/_app/immutable/entry/start.Sb_s0NGC.js +1 -0
- package/app/_app/immutable/nodes/0.Cuo9-RQc.js +9 -0
- package/app/_app/immutable/nodes/1.BW8Ar5T3.js +1 -0
- package/app/_app/immutable/nodes/10.CpLYjN7r.js +3 -0
- package/app/_app/immutable/nodes/11.BMPKD4M3.js +1 -0
- package/app/_app/immutable/nodes/12.WYpy0AHE.js +4 -0
- package/app/_app/immutable/nodes/13.BYo05X9B.js +1 -0
- package/app/_app/immutable/nodes/14.DN0MT3KB.js +1 -0
- package/app/_app/immutable/nodes/2.DM6k_pqu.js +24 -0
- package/app/_app/immutable/nodes/3.YgEwJ-vF.js +1 -0
- package/app/_app/immutable/nodes/4.A3Y6Lax0.js +1 -0
- package/app/_app/immutable/nodes/5.D9Vd85hG.js +1 -0
- package/app/_app/immutable/nodes/6.C5c56bSW.js +1 -0
- package/app/_app/immutable/nodes/7.CDBMbYlD.js +1 -0
- package/app/_app/immutable/nodes/8.8olDkDou.js +1 -0
- package/app/_app/immutable/nodes/9.CWgx__8Z.js +1 -0
- package/app/_app/version.json +1 -1
- package/app/advanced-styles/index.html +84 -0
- package/app/ai/index.html +60 -52
- package/app/blueprint/index.html +46 -53
- package/app/cookbook/index.html +46 -53
- package/app/index.html +92 -64
- package/app/m/ads/AdDeliveryTier/index.html +52 -59
- package/app/m/ads/AdEvent/index.html +52 -59
- package/app/m/ads/AdFormat/index.html +52 -59
- package/app/m/ads/AdGroup/index.html +52 -59
- package/app/m/ads/AdVariation/index.html +52 -59
- package/app/m/analytics/AnalyticsDataStream/index.html +52 -59
- package/app/m/analytics/AnalyticsEvent/index.html +52 -59
- package/app/m/analytics/AnalyticsProperty/index.html +52 -59
- package/app/m/analytics/AnalyticsReport/index.html +52 -59
- package/app/m/approvals/ApprovalEvent/index.html +52 -59
- package/app/m/approvals/ApprovalPolicy/index.html +52 -59
- package/app/m/approvals/ApprovalRequest/index.html +52 -59
- package/app/m/assets/Asset/attachments/index.html +91 -0
- package/app/m/assets/Asset/index.html +52 -59
- package/app/m/assets/AssetAssociation/index.html +53 -60
- package/app/m/assets/AssetMetafield/index.html +52 -59
- package/app/m/assets/AssetStatus/index.html +52 -59
- package/app/m/assets/AssetType/index.html +52 -59
- package/app/m/assets/Folder/index.html +52 -59
- package/app/m/chat/AgentSession/index.html +52 -59
- package/app/m/chat/ChatMessage/index.html +53 -60
- package/app/m/chat/ChatParticipant/index.html +53 -60
- package/app/m/chat/ChatReaction/index.html +52 -59
- package/app/m/chat/ChatRoom/index.html +52 -59
- package/app/m/chat/ChatThread/index.html +53 -60
- package/app/m/chat/VoiceGatewayTurn/index.html +52 -59
- package/app/m/chat/VoiceSession/index.html +52 -59
- package/app/m/commerce/Agreement/index.html +52 -59
- package/app/m/commerce/Cart/index.html +52 -59
- package/app/m/commerce/Contract/index.html +52 -59
- package/app/m/commerce/ContractLineItem/index.html +53 -60
- package/app/m/commerce/Customer/index.html +52 -59
- package/app/m/commerce/DocumentTax/index.html +89 -0
- package/app/m/commerce/Estimate/index.html +52 -59
- package/app/m/commerce/Fulfillment/index.html +52 -59
- package/app/m/commerce/FulfillmentLineItem/index.html +53 -60
- package/app/m/commerce/Invoice/index.html +52 -59
- package/app/m/commerce/InvoiceLineItem/index.html +53 -60
- package/app/m/commerce/Lease/index.html +52 -59
- package/app/m/commerce/LicenseSale/index.html +52 -59
- package/app/m/commerce/Order/index.html +52 -59
- package/app/m/commerce/Payment/index.html +52 -59
- package/app/m/commerce/PaymentAllocation/index.html +53 -60
- package/app/m/commerce/PaymentInstrument/index.html +52 -59
- package/app/m/commerce/PaymentIntent/index.html +52 -59
- package/app/m/commerce/Payout/index.html +52 -59
- package/app/m/commerce/ProductionOrder/index.html +52 -59
- package/app/m/commerce/PurchaseContract/index.html +89 -0
- package/app/m/commerce/PurchaseOrder/index.html +52 -59
- package/app/m/commerce/SalesContract/index.html +89 -0
- package/app/m/commerce/SupplierQuote/index.html +89 -0
- package/app/m/commerce/TaxCode/index.html +89 -0
- package/app/m/commerce/TaxComponent/index.html +89 -0
- package/app/m/commerce/TaxSettings/index.html +89 -0
- package/app/m/commerce/TaxSummaryReport/index.html +89 -0
- package/app/m/commerce/Vendor/index.html +52 -59
- package/app/m/commerce/WholesaleOrder/index.html +52 -59
- package/app/m/content/Content/index.html +52 -59
- package/app/m/content/ContentContribution/index.html +52 -59
- package/app/m/content/ContentContributionAttachment/index.html +52 -59
- package/app/m/content/ContentContributionRevision/index.html +52 -59
- package/app/m/content/ContentContributionType/index.html +52 -59
- package/app/m/content/ContentContributor/index.html +52 -59
- package/app/m/content/ContentCorrection/index.html +52 -59
- package/app/m/content/ContentFeedSource/index.html +52 -59
- package/app/m/content/ContentGovernanceAssignment/index.html +52 -59
- package/app/m/content/ContentGovernancePolicy/index.html +52 -59
- package/app/m/content/ContentGovernanceProfile/index.html +52 -59
- package/app/m/content/ContentReference/index.html +52 -59
- package/app/m/content/ContentReview/index.html +52 -59
- package/app/m/content/ContentVersion/index.html +52 -59
- package/app/m/events/Event/index.html +52 -59
- package/app/m/events/EventParticipant/index.html +53 -60
- package/app/m/events/EventSeries/index.html +52 -59
- package/app/m/events/EventType/index.html +52 -59
- package/app/m/expenses/Expense/index.html +89 -0
- package/app/m/facts/Fact/index.html +52 -59
- package/app/m/facts/FactContent/index.html +52 -59
- package/app/m/facts/FactEvidence/index.html +52 -59
- package/app/m/facts/FactSource/index.html +52 -59
- package/app/m/facts/FactSubject/index.html +52 -59
- package/app/m/facts/FactTag/index.html +52 -59
- package/app/m/fields/FieldPolicy/index.html +52 -59
- package/app/m/fields/FieldPolicySuggestion/index.html +52 -59
- package/app/m/fields/FieldUsageCounter/index.html +52 -59
- package/app/m/images/Image/index.html +52 -59
- package/app/m/inventory/InventoryLocation/index.html +52 -59
- package/app/m/inventory/StockLevel/index.html +52 -59
- package/app/m/inventory/StockMovement/index.html +52 -59
- package/app/m/ledgers/Account/index.html +52 -59
- package/app/m/ledgers/Journal/index.html +52 -59
- package/app/m/ledgers/JournalEntry/index.html +53 -60
- package/app/m/manufacturing/Assembly/index.html +52 -59
- package/app/m/manufacturing/BillOfMaterials/index.html +52 -59
- package/app/m/manufacturing/BomLine/index.html +52 -59
- package/app/m/manufacturing/Operation/index.html +52 -59
- package/app/m/manufacturing/ProductionRun/index.html +52 -59
- package/app/m/manufacturing/ProductionRunCompletion/index.html +52 -59
- package/app/m/manufacturing/RoutingStep/index.html +52 -59
- package/app/m/marketing/Campaign/index.html +52 -59
- package/app/m/marketing/CampaignChannel/index.html +52 -59
- package/app/m/marketing/CampaignMetricSnapshot/index.html +52 -59
- package/app/m/messages/Account/index.html +52 -59
- package/app/m/messages/Attachment/index.html +52 -59
- package/app/m/messages/Blacklist/index.html +52 -59
- package/app/m/messages/Email/failed-sends/index.html +54 -59
- package/app/m/messages/Email/index.html +52 -59
- package/app/m/messages/Email/mailbox/index.html +54 -59
- package/app/m/messages/EmailAccount/index.html +52 -59
- package/app/m/messages/EmailAttachment/index.html +89 -0
- package/app/m/messages/EmailFolder/index.html +52 -59
- package/app/m/messages/Message/index.html +52 -59
- package/app/m/messages/MessagingEndpoint/index.html +52 -59
- package/app/m/messages/PersonaMessageRoute/index.html +52 -59
- package/app/m/messages/SlackAccount/index.html +52 -59
- package/app/m/messages/SlackMessage/index.html +52 -59
- package/app/m/messages/TelegramAccount/index.html +52 -59
- package/app/m/messages/Tweet/index.html +52 -59
- package/app/m/messages/TwitterAccount/index.html +52 -59
- package/app/m/messages/Whitelist/index.html +52 -59
- package/app/m/messages/ZulipAccount/index.html +52 -59
- package/app/m/places/Place/index.html +52 -59
- package/app/m/places/PlaceType/index.html +52 -59
- package/app/m/products/Category/index.html +52 -59
- package/app/m/products/Material/index.html +52 -59
- package/app/m/products/Product/index.html +52 -59
- package/app/m/products/Product/ingredients/index.html +54 -59
- package/app/m/products/ProductVariant/index.html +53 -60
- package/app/m/products/Sku/index.html +53 -60
- package/app/m/profiles/ApiKey/index.html +52 -59
- package/app/m/profiles/Bot/index.html +52 -59
- package/app/m/profiles/MagicLinkToken/index.html +52 -59
- package/app/m/profiles/NostrIdentity/index.html +52 -59
- package/app/m/profiles/OidcIdentity/index.html +52 -59
- package/app/m/profiles/Organization/index.html +52 -59
- package/app/m/profiles/Person/index.html +52 -59
- package/app/m/profiles/Profile/index.html +52 -59
- package/app/m/profiles/ProfileMetadata/index.html +52 -59
- package/app/m/profiles/ProfileMetafield/index.html +52 -59
- package/app/m/profiles/ProfileRelationship/index.html +52 -59
- package/app/m/profiles/ProfileRelationshipTerm/index.html +52 -59
- package/app/m/profiles/ProfileRelationshipType/index.html +52 -59
- package/app/m/profiles/ProfileType/index.html +52 -59
- package/app/m/projects/Comment/index.html +53 -60
- package/app/m/projects/Issue/index.html +52 -59
- package/app/m/projects/Label/index.html +52 -59
- package/app/m/projects/Project/index.html +52 -59
- package/app/m/projects/ProjectIntegration/index.html +52 -59
- package/app/m/projects/PullRequest/index.html +52 -59
- package/app/m/projects/Repository/index.html +52 -59
- package/app/m/properties/Property/index.html +52 -59
- package/app/m/properties/Zone/index.html +52 -59
- package/app/m/reports/RuntimeReport/index.html +52 -59
- package/app/m/reports/SmrtPrincipalReportRefreshTask/index.html +52 -59
- package/app/m/reports/SmrtReportLock/index.html +52 -59
- package/app/m/reports/SmrtReportRefreshTask/index.html +52 -59
- package/app/m/reports/SmrtReportRun/index.html +52 -59
- package/app/m/reports/SmrtReportSchedule/index.html +52 -59
- package/app/m/reports/SmrtReportWatermark/index.html +52 -59
- package/app/m/sales/AttributionException/index.html +52 -59
- package/app/m/sales/AttributionPolicy/index.html +52 -59
- package/app/m/sales/Commission/index.html +52 -59
- package/app/m/sales/CommissionAdjustment/index.html +52 -59
- package/app/m/sales/CommissionPayout/index.html +52 -59
- package/app/m/sales/CommissionPlan/index.html +52 -59
- package/app/m/sales/Earner/index.html +52 -59
- package/app/m/sales/EarnerSourceAttribution/index.html +52 -59
- package/app/m/sales/EarningEvent/index.html +52 -59
- package/app/m/sales/ExecutedAgreement/index.html +52 -59
- package/app/m/sales/Lead/index.html +52 -59
- package/app/m/sales/Opportunity/index.html +52 -59
- package/app/m/sales/OpportunityConversion/index.html +52 -59
- package/app/m/sales/PipelineDefinition/index.html +52 -59
- package/app/m/sales/PipelineStage/index.html +53 -60
- package/app/m/sales/Referral/index.html +52 -59
- package/app/m/sales/ReferralAgreement/index.html +52 -59
- package/app/m/sales/ReferralLink/index.html +52 -59
- package/app/m/sales/ReferralProgram/index.html +52 -59
- package/app/m/sales/ReferralTermSnapshot/index.html +52 -59
- package/app/m/sales/ReferralTouch/index.html +52 -59
- package/app/m/sales/Referrer/index.html +52 -59
- package/app/m/sales/SalesActivity/index.html +52 -59
- package/app/m/sales/SalesRepresentative/index.html +52 -59
- package/app/m/sites/Site/index.html +52 -59
- package/app/m/sites/SiteAgentBinding/index.html +52 -59
- package/app/m/social/OAuthState/index.html +52 -59
- package/app/m/social/SocialAccount/index.html +52 -59
- package/app/m/social/SocialPost/index.html +52 -59
- package/app/m/social/SocialPostAnalyticsSnapshot/index.html +52 -59
- package/app/m/subscriptions/BillingAdjustment/index.html +52 -59
- package/app/m/subscriptions/ClientCharge/index.html +52 -59
- package/app/m/subscriptions/CreditGrant/index.html +52 -59
- package/app/m/subscriptions/PricingRule/index.html +52 -59
- package/app/m/subscriptions/RetailCharge/index.html +52 -59
- package/app/m/subscriptions/SpendingPolicy/index.html +52 -59
- package/app/m/subscriptions/SubscriptionPlan/index.html +52 -59
- package/app/m/subscriptions/TenantSubscription/index.html +52 -59
- package/app/m/subscriptions/TenantUsageMetric/index.html +52 -59
- package/app/m/support/ServiceTimeEntry/index.html +52 -59
- package/app/m/support/SupportAiRun/index.html +52 -59
- package/app/m/support/SupportAvailability/index.html +52 -59
- package/app/m/support/SupportCase/index.html +52 -59
- package/app/m/support/SupportCaseEvent/index.html +52 -59
- package/app/m/support/SupportChannelBinding/index.html +52 -59
- package/app/m/support/SupportCharge/index.html +52 -59
- package/app/m/support/SupportCompensation/index.html +52 -59
- package/app/m/support/SupportCompensationPlan/index.html +52 -59
- package/app/m/support/SupportEscalation/index.html +52 -59
- package/app/m/support/SupportInteraction/index.html +52 -59
- package/app/m/support/SupportPlan/index.html +52 -59
- package/app/m/support/SupportPolicy/index.html +52 -59
- package/app/m/support/SupportQualification/index.html +52 -59
- package/app/m/support/SupportServiceTarget/index.html +52 -59
- package/app/m/support/SupportSpecialist/index.html +52 -59
- package/app/m/support/SupportWorkLink/index.html +52 -59
- package/app/m/tags/Tag/index.html +52 -59
- package/app/m/tags/TagAlias/index.html +52 -59
- package/app/m/timesheets/AttendanceBreak/index.html +52 -59
- package/app/m/timesheets/AttendancePunch/index.html +52 -59
- package/app/m/timesheets/AttendanceSegment/index.html +89 -0
- package/app/m/timesheets/ServiceChargeSnapshot/index.html +52 -59
- package/app/m/timesheets/ServiceCompensationSnapshot/index.html +52 -59
- package/app/m/timesheets/ServiceTimeEntry/index.html +52 -59
- package/app/m/users/Group/index.html +52 -59
- package/app/m/users/GroupMember/index.html +52 -59
- package/app/m/users/GroupRole/index.html +52 -59
- package/app/m/users/Membership/index.html +53 -60
- package/app/m/users/MembershipOverride/index.html +52 -59
- package/app/m/users/Permission/index.html +52 -59
- package/app/m/users/Role/index.html +52 -59
- package/app/m/users/RolePermission/index.html +52 -59
- package/app/m/users/Session/index.html +52 -59
- package/app/m/users/Tenant/index.html +52 -59
- package/app/m/users/TenantIntegration/index.html +52 -59
- package/app/m/users/TenantPermissionOverride/index.html +52 -59
- package/app/m/users/User/index.html +52 -59
- package/app/m/video/Character/index.html +52 -59
- package/app/m/video/CharacterAsset/index.html +52 -59
- package/app/m/video/CompositeJob/index.html +52 -59
- package/app/m/video/Performer/index.html +52 -59
- package/app/m/video/PerformerAsset/index.html +52 -59
- package/app/m/video/Scene/index.html +52 -59
- package/app/m/video/SceneAsset/index.html +52 -59
- package/app/m/video/VideoComposition/index.html +52 -59
- package/app/m/video/VideoCompositionAsset/index.html +52 -59
- package/app/m/video/VideoSequence/index.html +52 -59
- package/app/m/video/VideoSequenceAsset/index.html +52 -59
- package/app/m/video/VideoShot/index.html +52 -59
- package/app/m/video/VideoShotAsset/index.html +52 -59
- package/app/m/video/VideoShotCharacter/index.html +52 -59
- package/app/m/video/VideoWorkflow/index.html +52 -59
- package/app/m/voice/VoiceOutput/index.html +52 -59
- package/app/m/voice/VoiceProfile/index.html +52 -59
- package/app/m/voice/VoiceSample/index.html +52 -59
- package/app/packages/ads/index.html +50 -57
- package/app/packages/analytics/index.html +50 -57
- package/app/packages/approvals/index.html +50 -57
- package/app/packages/assets/index.html +50 -57
- package/app/packages/chat/index.html +50 -57
- package/app/packages/comments/index.html +50 -57
- package/app/packages/commerce/index.html +50 -57
- package/app/packages/content/index.html +50 -57
- package/app/packages/events/index.html +50 -57
- package/app/packages/expenses/index.html +50 -57
- package/app/packages/facts/index.html +50 -57
- package/app/packages/fields/index.html +50 -57
- package/app/packages/human-resources/index.html +50 -57
- package/app/packages/images/index.html +50 -57
- package/app/packages/index.html +49 -55
- package/app/packages/ingestion/index.html +85 -0
- package/app/packages/inventory/index.html +50 -57
- package/app/packages/ledgers/index.html +50 -57
- package/app/packages/manufacturing/index.html +50 -57
- package/app/packages/marketing/index.html +50 -57
- package/app/packages/messages/index.html +50 -57
- package/app/packages/places/index.html +50 -57
- package/app/packages/preferences/index.html +50 -57
- package/app/packages/products/index.html +50 -57
- package/app/packages/profiles/index.html +50 -57
- package/app/packages/projects/index.html +50 -57
- package/app/packages/properties/index.html +50 -57
- package/app/packages/reports/index.html +50 -57
- package/app/packages/sales/index.html +50 -57
- package/app/packages/sites/index.html +50 -57
- package/app/packages/social/index.html +50 -57
- package/app/packages/subscriptions/index.html +50 -57
- package/app/packages/support/index.html +50 -57
- package/app/packages/tags/index.html +50 -57
- package/app/packages/timesheets/index.html +50 -57
- package/app/packages/users/index.html +50 -57
- package/app/packages/video/index.html +50 -57
- package/app/packages/voice/index.html +50 -57
- package/app/packages/webhooks/index.html +85 -0
- package/app/recipes/account-access/help/index.html +52 -57
- package/app/recipes/account-access/index.html +57 -59
- package/app/recipes/activity/help/index.html +52 -57
- package/app/recipes/activity/index.html +57 -59
- package/app/recipes/agreements/help/index.html +52 -57
- package/app/recipes/agreements/index.html +57 -59
- package/app/recipes/analytics.reports/help/index.html +52 -57
- package/app/recipes/analytics.reports/index.html +57 -59
- package/app/recipes/assets/help/index.html +52 -57
- package/app/recipes/assets/index.html +57 -59
- package/app/recipes/billing/help/index.html +52 -57
- package/app/recipes/billing/index.html +57 -59
- package/app/recipes/chat.assistant/help/index.html +52 -57
- package/app/recipes/chat.assistant/index.html +57 -59
- package/app/recipes/comments/help/index.html +52 -57
- package/app/recipes/comments/index.html +57 -59
- package/app/recipes/commerce.customers/help/index.html +52 -57
- package/app/recipes/commerce.customers/index.html +57 -59
- package/app/recipes/commerce.estimates/help/index.html +52 -57
- package/app/recipes/commerce.estimates/index.html +57 -59
- package/app/recipes/commerce.purchases/help/index.html +52 -57
- package/app/recipes/commerce.purchases/index.html +57 -59
- package/app/recipes/commerce.sales/help/index.html +52 -57
- package/app/recipes/commerce.sales/index.html +57 -59
- package/app/recipes/commerce.vendors/help/index.html +52 -57
- package/app/recipes/commerce.vendors/index.html +57 -59
- package/app/recipes/commerce.wholesale/help/index.html +52 -57
- package/app/recipes/commerce.wholesale/index.html +57 -59
- package/app/recipes/events.calendar/help/index.html +52 -57
- package/app/recipes/events.calendar/index.html +57 -59
- package/app/recipes/expenses.tracking/help/index.html +88 -0
- package/app/recipes/expenses.tracking/index.html +92 -0
- package/app/recipes/fields.form-customization/help/index.html +52 -57
- package/app/recipes/fields.form-customization/index.html +57 -59
- package/app/recipes/ingestion/help/index.html +88 -0
- package/app/recipes/ingestion/index.html +93 -0
- package/app/recipes/integrations/help/index.html +88 -0
- package/app/recipes/integrations/index.html +92 -0
- package/app/recipes/inventory.stock/help/index.html +52 -57
- package/app/recipes/inventory.stock/index.html +57 -59
- package/app/recipes/ledgers.bookkeeping/help/index.html +52 -57
- package/app/recipes/ledgers.bookkeeping/index.html +57 -59
- package/app/recipes/messages/help/index.html +52 -57
- package/app/recipes/messages/index.html +57 -59
- package/app/recipes/products/help/index.html +52 -57
- package/app/recipes/products/index.html +57 -59
- package/app/recipes/projects.tracker/help/index.html +52 -57
- package/app/recipes/projects.tracker/index.html +57 -59
- package/app/recipes/reports.materialized/help/index.html +52 -57
- package/app/recipes/reports.materialized/index.html +57 -59
- package/app/recipes/reports.runtime/help/index.html +88 -0
- package/app/recipes/reports.runtime/index.html +92 -0
- package/app/recipes/sales.pipeline/help/index.html +52 -57
- package/app/recipes/sales.pipeline/index.html +57 -59
- package/app/recipes/tags.taxonomy/help/index.html +52 -57
- package/app/recipes/tags.taxonomy/index.html +57 -59
- package/app/recipes/team-collaboration/help/index.html +52 -57
- package/app/recipes/team-collaboration/index.html +57 -59
- package/app/recipes/timesheets.time-entries/help/index.html +88 -0
- package/app/recipes/timesheets.time-entries/index.html +92 -0
- package/app/s/custom-accounts/index.html +82 -0
- package/app/s/custom-appointments/index.html +82 -0
- package/app/s/custom-billing/index.html +47 -54
- package/app/s/custom-buying/index.html +47 -54
- package/app/s/custom-checkout/index.html +82 -0
- package/app/s/custom-classes/index.html +47 -54
- package/app/s/custom-clients/index.html +82 -0
- package/app/s/custom-events/index.html +82 -0
- package/app/s/custom-fleet/index.html +82 -0
- package/app/s/custom-giving/index.html +82 -0
- package/app/s/custom-jobs/index.html +47 -54
- package/app/s/custom-kitchen/index.html +47 -54
- package/app/s/custom-material/index.html +47 -54
- package/app/s/custom-meetings/index.html +82 -0
- package/app/s/custom-members/index.html +47 -54
- package/app/s/custom-parts/index.html +47 -54
- package/app/s/custom-rentals/index.html +82 -0
- package/app/s/custom-roastery/index.html +82 -0
- package/app/s/custom-schedule/index.html +47 -54
- package/app/s/custom-shelf/index.html +82 -0
- package/app/s/custom-shop/index.html +47 -54
- package/app/s/custom-wholesale/index.html +47 -54
- package/app/s/custom-work/index.html +82 -0
- package/app/s/custom-yard/index.html +82 -0
- package/app/s/section-access-control/index.html +47 -54
- package/app/s/section-account-security/index.html +47 -54
- package/app/s/section-accounting/index.html +47 -54
- package/app/s/section-activity/index.html +47 -54
- package/app/s/section-agreements/index.html +47 -54
- package/app/s/section-analytics/index.html +47 -54
- package/app/s/section-assets/index.html +47 -54
- package/app/s/section-billing/index.html +47 -54
- package/app/s/section-calendar/index.html +47 -54
- package/app/s/section-catalog/index.html +47 -54
- package/app/s/section-chat.assistant/index.html +47 -54
- package/app/s/section-comments/index.html +47 -54
- package/app/s/section-fields.form-customization/index.html +47 -54
- package/app/s/section-ingestion/index.html +82 -0
- package/app/s/section-integrations/index.html +82 -0
- package/app/s/section-messages/index.html +47 -54
- package/app/s/section-more/index.html +47 -54
- package/app/s/section-operations/index.html +47 -54
- package/app/s/section-projects/index.html +47 -54
- package/app/s/section-purchasing/index.html +47 -54
- package/app/s/section-reports.materialized/index.html +47 -54
- package/app/s/section-reports.runtime/index.html +82 -0
- package/app/s/section-sales/index.html +47 -54
- package/app/s/section-taxonomy/index.html +47 -54
- package/app/s/section-team/index.html +47 -54
- package/app/s/section-work/index.html +82 -0
- package/dist/ai/state.svelte.d.ts +13 -0
- package/dist/ai/state.svelte.js +33 -0
- package/dist/assistant/change.d.ts +14 -3
- package/dist/assistant/change.js +26 -3
- package/dist/assistant/engine.js +5 -1
- package/dist/assistant/prompt.js +7 -3
- package/dist/catalog/catalog.json +11263 -14455
- package/dist/catalog/generate/exclusions.d.ts +2 -0
- package/dist/catalog/generate/exclusions.js +14 -0
- package/dist/catalog/generate/extract.js +28 -7
- package/dist/catalog/types.d.ts +7 -0
- package/dist/components/AdvancedStyles.svelte +138 -0
- package/dist/components/AdvancedStyles.svelte.d.ts +6 -0
- package/dist/components/AiModelsPage.svelte +40 -0
- package/dist/components/AiModelsPage.svelte.d.ts +7 -0
- package/dist/components/AiSetup.svelte +9 -6
- package/dist/components/AiStatusIcons.svelte +8 -5
- package/dist/components/AppSettings.svelte +105 -1
- package/dist/components/BrowserAssistant.svelte +16 -17
- package/dist/components/BrowserAssistant.svelte.d.ts +2 -0
- package/dist/components/ChildRecords.svelte +61 -14
- package/dist/components/ChildRecords.svelte.d.ts +1 -0
- package/dist/components/ConnectTools.svelte +5 -2
- package/dist/components/CookbooksPanel.svelte +56 -33
- package/dist/components/CopyButton.svelte +65 -0
- package/dist/components/CopyButton.svelte.d.ts +24 -0
- package/dist/components/ExportPanel.svelte +292 -57
- package/dist/components/ExportPanel.svelte.d.ts +10 -1
- package/dist/components/FeatureCard.svelte +21 -10
- package/dist/components/FeaturesPanel.svelte +4 -1
- package/dist/components/FieldInput.svelte +6 -3
- package/dist/components/FieldMapForm.svelte +6 -10
- package/dist/components/FieldMapForm.svelte.d.ts +1 -0
- package/dist/components/FormWorkspace.svelte +80 -9
- package/dist/components/FormWorkspace.svelte.d.ts +1 -0
- package/dist/components/HeaderIconLink.svelte +86 -0
- package/dist/components/HeaderIconLink.svelte.d.ts +14 -0
- package/dist/components/HelpView.svelte +3 -0
- package/dist/components/ModelOptions.svelte +13 -2
- package/dist/components/ModelPage.svelte +33 -5
- package/dist/components/ModelPage.svelte.d.ts +4 -0
- package/dist/components/ModelWorkspace.svelte +148 -50
- package/dist/components/ModelWorkspace.svelte.d.ts +4 -0
- package/dist/components/PackagePage.svelte +96 -0
- package/dist/components/PackagePage.svelte.d.ts +9 -0
- package/dist/components/ProductMedia.svelte +95 -0
- package/dist/components/ProductMedia.svelte.d.ts +10 -0
- package/dist/components/RecipeCards.svelte +13 -1
- package/dist/components/RecipeHelp.svelte +3 -0
- package/dist/components/RecipeOptions.svelte +13 -1
- package/dist/components/RecordFeatures.svelte +22 -8
- package/dist/components/RecordView.svelte +354 -0
- package/dist/components/RecordView.svelte.d.ts +14 -0
- package/dist/components/RelationField.svelte +5 -2
- package/dist/components/SectionActions.svelte +8 -5
- package/dist/components/SectionHeading.svelte +63 -0
- package/dist/components/SectionHeading.svelte.d.ts +11 -0
- package/dist/components/SectionIcons.svelte +15 -3
- package/dist/components/SectionOverview.svelte +33 -3
- package/dist/components/SectionOverview.svelte.d.ts +4 -0
- package/dist/components/SectionPage.svelte +25 -165
- package/dist/components/SectionView.svelte +172 -0
- package/dist/components/SectionView.svelte.d.ts +18 -0
- package/dist/components/SettingsPanel.svelte +3 -9
- package/dist/components/SettingsPanel.svelte.d.ts +1 -5
- package/dist/components/ThemeBridge.svelte +80 -4
- package/dist/components/ThemeBridge.svelte.d.ts +5 -1
- package/dist/components/ThemeSection.svelte +208 -117
- package/dist/components/ThemeSection.svelte.d.ts +3 -7
- package/dist/components/VariantGridForm.svelte +9 -13
- package/dist/components/VariantGridForm.svelte.d.ts +1 -0
- package/dist/components/VoiceTyping.svelte +3 -0
- package/dist/cookbook/describe.d.ts +29 -0
- package/dist/cookbook/describe.js +164 -0
- package/dist/cookbook/file.d.ts +6 -0
- package/dist/cookbook/file.js +18 -4
- package/dist/cookbook/prompt.d.ts +49 -0
- package/dist/cookbook/prompt.js +96 -0
- package/dist/cookbook/store.svelte.d.ts +13 -0
- package/dist/cookbook/store.svelte.js +36 -8
- package/dist/core/prompt.js +10 -1
- package/dist/core/reply.d.ts +6 -1
- package/dist/data/children.d.ts +50 -6
- package/dist/data/children.js +146 -16
- package/dist/data/derived.d.ts +37 -29
- package/dist/data/derived.js +49 -30
- package/dist/data/display.d.ts +21 -8
- package/dist/data/display.js +74 -11
- package/dist/data/fakes.d.ts +48 -9
- package/dist/data/fakes.js +146 -22
- package/dist/data/labels.d.ts +7 -2
- package/dist/data/labels.js +12 -2
- package/dist/data/list-sort.d.ts +8 -0
- package/dist/data/list-sort.js +45 -0
- package/dist/data/money.d.ts +225 -0
- package/dist/data/money.js +411 -0
- package/dist/data/packs.d.ts +13 -0
- package/dist/data/packs.js +1224 -0
- package/dist/data/planner-source.js +120 -3
- package/dist/data/source.d.ts +13 -2
- package/dist/data/source.js +274 -40
- package/dist/features/palette.d.ts +2 -0
- package/dist/features/palette.js +1 -1
- package/dist/forms/stock.d.ts +1 -1
- package/dist/forms/stock.js +3 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.js +6 -1
- package/dist/kitchen/LiveKitchenBridge.svelte +73 -0
- package/dist/kitchen/LiveKitchenBridge.svelte.d.ts +8 -0
- package/dist/kitchen/live.d.ts +7 -0
- package/dist/kitchen/live.js +51 -0
- package/dist/library/icons.js +34 -0
- package/dist/library/library.json +1546 -15
- package/dist/library/pending.json +5 -0
- package/dist/library/types.d.ts +4 -0
- package/dist/motion/tokens.d.ts +6 -0
- package/dist/motion/tokens.js +32 -0
- package/dist/motion/view-transition.d.ts +13 -0
- package/dist/motion/view-transition.js +17 -0
- package/dist/overviews/definitions.d.ts +41 -2
- package/dist/overviews/definitions.js +111 -4
- package/dist/overviews/models.d.ts +10 -0
- package/dist/overviews/models.js +19 -0
- package/dist/overviews/registry.d.ts +92 -5
- package/dist/overviews/registry.js +468 -58
- package/dist/overviews/validate.js +2 -2
- package/dist/planner/Planner.svelte +374 -166
- package/dist/planner/PlannerControls.svelte +255 -0
- package/dist/planner/PlannerControls.svelte.d.ts +17 -0
- package/dist/planner/PlannerLifecycle.svelte +73 -0
- package/dist/planner/PlannerLifecycle.svelte.d.ts +9 -0
- package/dist/planner/app.svelte.d.ts +12 -2
- package/dist/planner/app.svelte.js +13 -3
- package/dist/planner/assistant.js +20 -2
- package/dist/planner/commands/adapter.js +9 -2
- package/dist/planner/commands/types.d.ts +1 -1
- package/dist/planner/commands/types.js +1 -0
- package/dist/planner/header-icons.d.ts +12 -0
- package/dist/planner/header-icons.js +12 -0
- package/dist/planner/host/HostPlanner.svelte +70 -0
- package/dist/planner/host/HostPlanner.svelte.d.ts +17 -0
- package/dist/planner/host/session.svelte.d.ts +28 -0
- package/dist/planner/host/session.svelte.js +186 -0
- package/dist/planner/routes.d.ts +49 -0
- package/dist/planner/routes.js +64 -0
- package/dist/planner/shell.d.ts +40 -0
- package/dist/planner/shell.js +56 -0
- package/dist/planner/tab.svelte.d.ts +6 -3
- package/dist/planner/tab.svelte.js +11 -4
- package/dist/planner/title.d.ts +15 -0
- package/dist/planner/title.js +21 -0
- package/dist/planner/title.svelte.d.ts +6 -0
- package/dist/planner/title.svelte.js +11 -0
- package/dist/planner/types.d.ts +39 -7
- package/dist/products/media.d.ts +20 -0
- package/dist/products/media.js +65 -0
- package/dist/recipes/help/descriptions.json +1 -3
- package/dist/recipes/index.d.ts +2 -0
- package/dist/recipes/index.js +6 -0
- package/dist/recipes/plumbing.d.ts +35 -1
- package/dist/recipes/plumbing.js +74 -0
- package/dist/screens/definition.d.ts +35 -0
- package/dist/screens/definition.js +132 -0
- package/dist/screens/relations.d.ts +17 -0
- package/dist/screens/relations.js +98 -0
- package/dist/screens/totals.d.ts +37 -0
- package/dist/screens/totals.js +65 -0
- package/dist/sections/info.d.ts +1 -1
- package/dist/sections/info.js +2 -2
- package/dist/settings/app-settings.d.ts +17 -1
- package/dist/settings/app-settings.js +40 -3
- package/dist/smrt-version.d.ts +2 -0
- package/dist/smrt-version.js +4 -0
- package/dist/styles/planner-forms.css +53 -0
- package/dist/styles/planner-lists.css +43 -0
- package/dist/theme/css-highlight.d.ts +6 -0
- package/dist/theme/css-highlight.js +34 -0
- package/dist/theme/custom-css.svelte.d.ts +34 -0
- package/dist/theme/custom-css.svelte.js +246 -0
- package/dist/theme/runtime.js +25 -5
- package/dist/theme/theme.d.ts +26 -3
- package/dist/theme/theme.js +70 -2
- package/dist/upstream/overlay.d.ts +14 -5
- package/dist/upstream/overlay.js +20 -2
- package/package.json +12 -6
- package/app/_app/immutable/assets/0.B5zXkXe_.css +0 -1
- package/app/_app/immutable/assets/10.hpcnxvK1.css +0 -1
- package/app/_app/immutable/assets/11.D7zoXfVV.css +0 -1
- package/app/_app/immutable/assets/12.CPobm1ED.css +0 -1
- package/app/_app/immutable/assets/2.CyaWdRdI.css +0 -1
- package/app/_app/immutable/assets/3.BlPQOes8.css +0 -1
- package/app/_app/immutable/assets/8.2gQeKBp_.css +0 -1
- package/app/_app/immutable/assets/9.HOPT4xtg.css +0 -1
- package/app/_app/immutable/assets/AiSetup.Cb22AigN.css +0 -1
- package/app/_app/immutable/assets/Button.DkP0qkG9.css +0 -1
- package/app/_app/immutable/assets/ConnectTools.BgIJOOGW.css +0 -1
- package/app/_app/immutable/assets/FieldMapForm.BCU-4pO4.css +0 -1
- package/app/_app/immutable/assets/ModelPage.Dd3LcMta.css +0 -1
- package/app/_app/immutable/assets/SectionActions.CTkVuNMF.css +0 -1
- package/app/_app/immutable/assets/SectionIcons.5Udq9vN-.css +0 -1
- package/app/_app/immutable/assets/SegmentedControl.B8SrQacd.css +0 -1
- package/app/_app/immutable/assets/dist.C5nHBk_O.css +0 -1
- package/app/_app/immutable/assets/feedback.BVKAwFck.css +0 -1
- package/app/_app/immutable/assets/forms.BChZ2RWM.css +0 -1
- package/app/_app/immutable/assets/percent.LH0z-ozZ.css +0 -1
- package/app/_app/immutable/assets/store.CGDwHkkF.css +0 -1
- package/app/_app/immutable/assets/ui.B1A1Zl2p.css +0 -1
- package/app/_app/immutable/assets/workspace.BIMkuZDb.css +0 -1
- package/app/_app/immutable/chunks/1okeBSoq.js +0 -1
- package/app/_app/immutable/chunks/2jFBkS1C.js +0 -1
- package/app/_app/immutable/chunks/6P9zxrzU.js +0 -1
- package/app/_app/immutable/chunks/B32EWqI8.js +0 -9
- package/app/_app/immutable/chunks/B4Kevpe0.js +0 -1
- package/app/_app/immutable/chunks/BKwRT_1p.js +0 -1
- package/app/_app/immutable/chunks/BS4h9ES-.js +0 -1
- package/app/_app/immutable/chunks/CMhpRMKg.js +0 -1
- package/app/_app/immutable/chunks/CPRHZZeW.js +0 -1
- package/app/_app/immutable/chunks/CRQ1Pmzr.js +0 -1
- package/app/_app/immutable/chunks/CWtfVMDz.js +0 -1
- package/app/_app/immutable/chunks/Chyo8rdT.js +0 -3
- package/app/_app/immutable/chunks/Ci0DUht6.js +0 -34
- package/app/_app/immutable/chunks/CmmuWmp6.js +0 -2
- package/app/_app/immutable/chunks/CrFNLK0f.js +0 -1
- package/app/_app/immutable/chunks/CsprTb3f.js +0 -2
- package/app/_app/immutable/chunks/CygC84VT.js +0 -2
- package/app/_app/immutable/chunks/D0VgZnk1.js +0 -1
- package/app/_app/immutable/chunks/DD7gpKb2.js +0 -1
- package/app/_app/immutable/chunks/DNRgqfTx.js +0 -1
- package/app/_app/immutable/chunks/DVRKjN-E.js +0 -1
- package/app/_app/immutable/chunks/D_J_XtJy.js +0 -846
- package/app/_app/immutable/chunks/Dp9GVO-9.js +0 -1
- package/app/_app/immutable/chunks/DqcD-WtP.js +0 -1
- package/app/_app/immutable/chunks/QukgIHDX.js +0 -1
- package/app/_app/immutable/chunks/WxSPP8QW.js +0 -4
- package/app/_app/immutable/chunks/Xp1g1t4n.js +0 -3
- package/app/_app/immutable/chunks/leQCwW2d.js +0 -1
- package/app/_app/immutable/chunks/p6bgzXiY.js +0 -1
- package/app/_app/immutable/entry/app.IZIJXhgq.js +0 -2
- package/app/_app/immutable/entry/start.BuaYHD1N.js +0 -1
- package/app/_app/immutable/nodes/0.m_U8WC7E.js +0 -10
- package/app/_app/immutable/nodes/1.Crw8ULhB.js +0 -1
- package/app/_app/immutable/nodes/10.1nQxyH9H.js +0 -4
- package/app/_app/immutable/nodes/11.Cw0JnQF3.js +0 -1
- package/app/_app/immutable/nodes/12.BIocA1aI.js +0 -1
- package/app/_app/immutable/nodes/2.CR5BwGnt.js +0 -17
- package/app/_app/immutable/nodes/3.1B56hgAG.js +0 -1
- package/app/_app/immutable/nodes/4.SSIC7sUh.js +0 -1
- package/app/_app/immutable/nodes/5.DgdwleDQ.js +0 -1
- package/app/_app/immutable/nodes/6.DmD9rqLU.js +0 -1
- package/app/_app/immutable/nodes/7.DdngsBmo.js +0 -1
- package/app/_app/immutable/nodes/8.D2Mszsua.js +0 -3
- package/app/_app/immutable/nodes/9.CLYsywul.js +0 -1
- package/app/m/content/Contents/index.html +0 -96
- package/app/m/preferences/UiPreferenceRecord/index.html +0 -96
- package/app/m/users/AccessRequest/index.html +0 -96
- package/app/m/users/ResourceGrant/index.html +0 -96
- package/app/m/users/UsersCliAuthRequest/index.html +0 -96
- package/app/m/users/UsersMagicLinkToken/index.html +0 -96
|
@@ -10,21 +10,28 @@
|
|
|
10
10
|
* never from option values: an option names a model or field, the loader looks
|
|
11
11
|
* it up in the catalog and asks the `DataSource` for it.
|
|
12
12
|
*/
|
|
13
|
-
import {
|
|
13
|
+
import { composeShortcutsLoader, } from '@happyvertical/smrt-svelte/cookbook';
|
|
14
|
+
import { createLineItemsLoader, createLineItemsWidget, createRelatedLoader, createRelatedWidget, createWidgetRegistry, lineItemColumns, parseColumnsOption, registerCoreWidgets, registerRecipeWidgets, relatedColumns, } from '@happyvertical/smrt-svelte/overview';
|
|
15
|
+
import { currencyCodeField, deriveFieldRoles, } from '@happyvertical/smrt-svelte/screens';
|
|
14
16
|
import { getModelByQualifiedName } from "../catalog/index.js";
|
|
15
|
-
import { isMoneyField } from "../data/fakes.js";
|
|
16
|
-
import {
|
|
17
|
-
import { recordLabel } from "../data/labels.js";
|
|
17
|
+
import { EPOCH, isMoneyField } from "../data/fakes.js";
|
|
18
|
+
import { humanize, labelKey } from "../data/format.js";
|
|
19
|
+
import { recordLabel, relationLabels } from "../data/labels.js";
|
|
20
|
+
import { filteredListPath, modelPath, recordPath } from "../planner/routes.js";
|
|
18
21
|
import { recipes } from "../recipes/index.js";
|
|
22
|
+
import { isPlumbing } from "../recipes/plumbing.js";
|
|
19
23
|
import { inScope } from "../recipes/scope.js";
|
|
24
|
+
import { screenDefinition } from "../screens/definition.js";
|
|
25
|
+
import { documentTotals, storedDocumentTotals, } from "../screens/totals.js";
|
|
20
26
|
/** The registry every planner overview uses. */
|
|
21
27
|
export const overviewRegistry = createWidgetRegistry();
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
/** What every data widget reads: the sample source and the app's links. */
|
|
29
|
+
function dataCapabilities(ctx) {
|
|
30
|
+
const { source, href } = ctx;
|
|
31
|
+
if (!source || !href) {
|
|
25
32
|
throw new Error('the planner widget context is missing');
|
|
26
33
|
}
|
|
27
|
-
return { source,
|
|
34
|
+
return { source, href };
|
|
28
35
|
}
|
|
29
36
|
function modelOf(qualified) {
|
|
30
37
|
const found = typeof qualified === 'string'
|
|
@@ -34,14 +41,49 @@ function modelOf(qualified) {
|
|
|
34
41
|
throw new Error(`unknown model ${String(qualified)}`);
|
|
35
42
|
return {
|
|
36
43
|
model: found.model,
|
|
37
|
-
|
|
44
|
+
packageId: found.pkg.id,
|
|
45
|
+
path: modelPath(found.pkg.id, found.model.name),
|
|
38
46
|
};
|
|
39
47
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
const REF_TYPES = new Set(['foreignKey', 'crossPackageRef']);
|
|
49
|
+
/**
|
|
50
|
+
* The one named filter the sample data knows: `parent`, with `field` (a
|
|
51
|
+
* metric's `parentField`, when its `field` is the one measured) the
|
|
52
|
+
* reference field on the widget's model that points at the record the
|
|
53
|
+
* overview is rendered on (`ctx.record`, a detail overview). Any other
|
|
54
|
+
* name is an error tile, as is `parent` outside a record view.
|
|
55
|
+
*/
|
|
56
|
+
function parentFilter(options, ctx, model) {
|
|
57
|
+
const filter = options.filter;
|
|
58
|
+
if (typeof filter !== 'string' || filter === '')
|
|
59
|
+
return undefined;
|
|
60
|
+
if (filter !== 'parent')
|
|
43
61
|
throw new Error(`unknown filter ${filter}`);
|
|
62
|
+
const { record } = ctx;
|
|
63
|
+
if (!record?.id)
|
|
64
|
+
throw new Error('the parent filter needs a record');
|
|
65
|
+
// A metric measuring `field` names the reference as `parentField`.
|
|
66
|
+
const named = typeof options.parentField === 'string' && options.parentField
|
|
67
|
+
? options.parentField
|
|
68
|
+
: options.field;
|
|
69
|
+
const field = typeof named === 'string' ? named : '';
|
|
70
|
+
const target = model.fields.find((f) => f.name === field);
|
|
71
|
+
if (!target || !REF_TYPES.has(target.type)) {
|
|
72
|
+
throw new Error(`${model.name} has no reference field ${field}`);
|
|
44
73
|
}
|
|
74
|
+
return { field, id: record.id };
|
|
75
|
+
}
|
|
76
|
+
/** The widget's rows: the model's, or those pointing at the record. */
|
|
77
|
+
async function rowsOf(source, model, parent) {
|
|
78
|
+
return parent
|
|
79
|
+
? source.listWhere(model, parent.field, parent.id)
|
|
80
|
+
: source.list(model);
|
|
81
|
+
}
|
|
82
|
+
/** Where the widget's list link goes: the list, narrowed to the record's rows. */
|
|
83
|
+
function listHref(href, found, parent) {
|
|
84
|
+
return href(parent
|
|
85
|
+
? filteredListPath(found.packageId, found.model.name, parent.field, parent.id)
|
|
86
|
+
: found.path);
|
|
45
87
|
}
|
|
46
88
|
const numeric = (value) => typeof value === 'number' && Number.isFinite(value);
|
|
47
89
|
/**
|
|
@@ -49,16 +91,18 @@ const numeric = (value) => typeof value === 'number' && Number.isFinite(value);
|
|
|
49
91
|
* over the model's sample rows. Money fields stay integer minor units.
|
|
50
92
|
*/
|
|
51
93
|
async function loadMetric(options, ctx) {
|
|
52
|
-
const { source, href } =
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
const
|
|
94
|
+
const { source, href } = dataCapabilities(ctx);
|
|
95
|
+
const found = modelOf(options.model);
|
|
96
|
+
const { model } = found;
|
|
97
|
+
const parent = parentFilter(options, ctx, model);
|
|
98
|
+
const rows = await rowsOf(source, model, parent);
|
|
99
|
+
const link = listHref(href, found, parent);
|
|
56
100
|
const measure = typeof options.measure === 'string' ? options.measure : '';
|
|
57
101
|
if (measure === 'count' || measure === '') {
|
|
58
102
|
return {
|
|
59
103
|
value: rows.length,
|
|
60
104
|
format: 'integer',
|
|
61
|
-
href:
|
|
105
|
+
href: link,
|
|
62
106
|
};
|
|
63
107
|
}
|
|
64
108
|
const field = model.fields.find((f) => f.name === options.field);
|
|
@@ -86,7 +130,7 @@ async function loadMetric(options, ctx) {
|
|
|
86
130
|
value: money ? Math.round(value) : value,
|
|
87
131
|
format: money ? 'money' : field.type === 'integer' ? 'integer' : 'decimal',
|
|
88
132
|
...(money ? { currency: 'USD' } : {}),
|
|
89
|
-
href:
|
|
133
|
+
href: link,
|
|
90
134
|
};
|
|
91
135
|
}
|
|
92
136
|
function compare(a, b) {
|
|
@@ -94,79 +138,445 @@ function compare(a, b) {
|
|
|
94
138
|
return a - b;
|
|
95
139
|
return String(a ?? '').localeCompare(String(b ?? ''));
|
|
96
140
|
}
|
|
97
|
-
/**
|
|
141
|
+
/** Framework timestamps the catalog and the samples do not carry. */
|
|
142
|
+
const SYSTEM_DATES = new Set(['createdAt', 'updatedAt']);
|
|
143
|
+
/** How a table cell renders, by the first of the field's roles a table draws. */
|
|
144
|
+
const CELL_ROLES = [
|
|
145
|
+
'identifier',
|
|
146
|
+
'status',
|
|
147
|
+
'date',
|
|
148
|
+
'money',
|
|
149
|
+
'quantity',
|
|
150
|
+
'party',
|
|
151
|
+
'title',
|
|
152
|
+
];
|
|
153
|
+
function cellRole(roles = []) {
|
|
154
|
+
return CELL_ROLES.find((role) => roles.includes(role));
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The columns a `records` table shows: the `columns` option's field names
|
|
158
|
+
* when given (unknown names are an error tile), else the framework's
|
|
159
|
+
* `relatedColumns` by role (identifier, status, lead date, a party, the
|
|
160
|
+
* amount: five, as `screenRelations` asks), leaving out the field pointing
|
|
161
|
+
* at the page's record.
|
|
162
|
+
*/
|
|
163
|
+
function recordColumns(model, roles, option, parentField) {
|
|
164
|
+
const definition = screenDefinition(model);
|
|
165
|
+
const exclude = parentField ? [parentField] : [];
|
|
166
|
+
const keys = parseColumnsOption(option);
|
|
167
|
+
if (keys.length === 0) {
|
|
168
|
+
return relatedColumns(definition, roles, { exclude, max: 5 });
|
|
169
|
+
}
|
|
170
|
+
// The framework's own column for a key where it has one (a line's unit
|
|
171
|
+
// price is not summed), else one by the field's roles.
|
|
172
|
+
const known = [
|
|
173
|
+
...lineItemColumns(definition, roles, { exclude }),
|
|
174
|
+
...relatedColumns(definition, roles, { exclude, max: keys.length + 8 }),
|
|
175
|
+
];
|
|
176
|
+
return keys.map((key) => {
|
|
177
|
+
const field = model.fields.find((f) => f.name === key);
|
|
178
|
+
if (!field)
|
|
179
|
+
throw new Error(`${model.name} has no field ${key}`);
|
|
180
|
+
const framework = known.find((column) => column.key === key);
|
|
181
|
+
if (framework)
|
|
182
|
+
return framework;
|
|
183
|
+
const role = cellRole(roles[key]);
|
|
184
|
+
return {
|
|
185
|
+
key,
|
|
186
|
+
label: REF_TYPES.has(field.type)
|
|
187
|
+
? humanize(key.replace(/Id$/, ''))
|
|
188
|
+
: humanize(key),
|
|
189
|
+
...(role ? { role } : {}),
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/** The roles a table footer sums. */
|
|
194
|
+
const SUMMED = new Set([
|
|
195
|
+
'money',
|
|
196
|
+
'quantity',
|
|
197
|
+
]);
|
|
198
|
+
/**
|
|
199
|
+
* Footer sums over EVERY matching row, not only the page shown: the money
|
|
200
|
+
* (integer minor units) and quantity columns, never one marked
|
|
201
|
+
* `summarize: false` (a unit price).
|
|
202
|
+
*/
|
|
203
|
+
export function recordSummaries(columns, rows) {
|
|
204
|
+
const out = {};
|
|
205
|
+
for (const column of columns) {
|
|
206
|
+
if (!(column.summarize ?? SUMMED.has(column.role)))
|
|
207
|
+
continue;
|
|
208
|
+
out[column.key] = rows.reduce((total, row) => {
|
|
209
|
+
const value = row[column.key];
|
|
210
|
+
return numeric(value) ? total + value : total;
|
|
211
|
+
}, 0);
|
|
212
|
+
}
|
|
213
|
+
return out;
|
|
214
|
+
}
|
|
215
|
+
/** The one currency of the rows' currency field, else USD. */
|
|
216
|
+
function currencyOf(model, rows) {
|
|
217
|
+
const field = currencyCodeField(screenDefinition(model));
|
|
218
|
+
const codes = new Set(rows
|
|
219
|
+
.map((row) => (field ? row[field] : undefined))
|
|
220
|
+
.filter((v) => typeof v === 'string' && v !== ''));
|
|
221
|
+
return codes.size === 1 ? ([...codes][0] ?? 'USD') : 'USD';
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* `records`: the first `limit` sample rows, optionally sorted by a field;
|
|
225
|
+
* each row links to its record page and carries `cells` for the table's
|
|
226
|
+
* columns (raw: money in integer minor units, dates as ISO strings, a
|
|
227
|
+
* reference as its record's label). `summaries` sum the money and quantity
|
|
228
|
+
* columns over every matching row and `total` counts them, so a footer
|
|
229
|
+
* under a page of five orders still totals all of them. A sort by a
|
|
230
|
+
* framework timestamp the samples do not carry (`createdAt`, the record
|
|
231
|
+
* view's default) falls back to the model's lead date, so "newest" still
|
|
232
|
+
* means newest.
|
|
233
|
+
*/
|
|
98
234
|
async function loadRecords(options, ctx) {
|
|
99
|
-
const { source, href } =
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
235
|
+
const { source, href } = dataCapabilities(ctx);
|
|
236
|
+
const found = modelOf(options.model);
|
|
237
|
+
const { model } = found;
|
|
238
|
+
const parent = parentFilter(options, ctx, model);
|
|
239
|
+
let rows = await rowsOf(source, model, parent);
|
|
103
240
|
if (typeof options.sort === 'string' && options.sort) {
|
|
104
|
-
const
|
|
105
|
-
if (!
|
|
106
|
-
throw new Error(`${model.name} has no field ${sort}`);
|
|
241
|
+
const named = model.fields.find((f) => f.name === options.sort);
|
|
242
|
+
if (!named && !SYSTEM_DATES.has(options.sort)) {
|
|
243
|
+
throw new Error(`${model.name} has no field ${options.sort}`);
|
|
244
|
+
}
|
|
245
|
+
const carried = rows.some((row) => row[options.sort] !== undefined);
|
|
246
|
+
const sort = carried ? options.sort : leadDateField(model)?.name;
|
|
247
|
+
if (sort) {
|
|
248
|
+
const sign = options.direction === 'asc' ? 1 : -1;
|
|
249
|
+
rows = [...rows].sort((a, b) => sign * compare(a[sort], b[sort]));
|
|
107
250
|
}
|
|
108
|
-
const sign = options.direction === 'asc' ? 1 : -1;
|
|
109
|
-
rows = [...rows].sort((a, b) => sign * compare(a[sort], b[sort]));
|
|
110
251
|
}
|
|
252
|
+
const roles = deriveFieldRoles(screenDefinition(model));
|
|
253
|
+
const columns = recordColumns(model, roles, options.columns, parent?.field);
|
|
111
254
|
const limit = numeric(options.limit) ? options.limit : 5;
|
|
112
255
|
const shown = rows.slice(0, limit);
|
|
256
|
+
const refFields = model.fields.filter((f) => REF_TYPES.has(f.type) && columns.some((c) => c.key === f.name));
|
|
257
|
+
const labels = await relationLabels(source, refFields, shown);
|
|
258
|
+
const cellsOf = (row) => Object.fromEntries(columns.map((column) => {
|
|
259
|
+
const value = row[column.key];
|
|
260
|
+
const ref = refFields.find((f) => f.name === column.key);
|
|
261
|
+
if (ref?.related && typeof value === 'string' && value) {
|
|
262
|
+
return [column.key, labels.get(labelKey(ref.related, value)) ?? ''];
|
|
263
|
+
}
|
|
264
|
+
return [column.key, value ?? null];
|
|
265
|
+
}));
|
|
266
|
+
const summaries = recordSummaries(columns, rows);
|
|
267
|
+
// A line item, link row or the like lives inside its parent: no page of
|
|
268
|
+
// its own to link a row or "View all" to.
|
|
269
|
+
const linked = !isPlumbing(model);
|
|
113
270
|
return {
|
|
114
271
|
rows: await Promise.all(shown.map(async (row) => ({
|
|
115
272
|
id: String(row.id),
|
|
116
|
-
|
|
273
|
+
// On a record's page the parent is the page: leave its name out.
|
|
274
|
+
title: await recordLabel(source, model, row, 0, parent?.field),
|
|
275
|
+
...(linked
|
|
276
|
+
? {
|
|
277
|
+
href: href(recordPath(found.packageId, model.name, String(row.id))),
|
|
278
|
+
}
|
|
279
|
+
: {}),
|
|
280
|
+
cells: cellsOf(row),
|
|
117
281
|
}))),
|
|
118
|
-
|
|
119
|
-
href: href
|
|
282
|
+
total: rows.length,
|
|
283
|
+
...(linked ? { href: listHref(href, found, parent) } : {}),
|
|
284
|
+
columns,
|
|
285
|
+
currency: currencyOf(model, rows),
|
|
286
|
+
...(Object.keys(summaries).length ? { summaries } : {}),
|
|
120
287
|
};
|
|
121
288
|
}
|
|
289
|
+
/** The chart's `period` option: how far back from the sample clock it looks. */
|
|
290
|
+
const PERIOD_DAYS = {
|
|
291
|
+
'7d': 7,
|
|
292
|
+
'30d': 30,
|
|
293
|
+
'90d': 90,
|
|
294
|
+
'12m': 365,
|
|
295
|
+
all: null,
|
|
296
|
+
};
|
|
297
|
+
const DAY = 24 * 60 * 60 * 1000;
|
|
298
|
+
/** The bucket a period's date axis uses; coarser as the window widens. */
|
|
299
|
+
function bucketOf(period) {
|
|
300
|
+
if (period === '7d' || period === '30d')
|
|
301
|
+
return 'day';
|
|
302
|
+
if (period === '90d')
|
|
303
|
+
return 'week';
|
|
304
|
+
return 'month';
|
|
305
|
+
}
|
|
306
|
+
/** The start of `date`'s bucket, as a UTC timestamp. */
|
|
307
|
+
function bucketStart(ms, bucket) {
|
|
308
|
+
const date = new Date(ms);
|
|
309
|
+
if (bucket === 'month') {
|
|
310
|
+
return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1);
|
|
311
|
+
}
|
|
312
|
+
const day = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
|
|
313
|
+
// ISO weeks start on Monday.
|
|
314
|
+
return bucket === 'week' ? day - ((date.getUTCDay() + 6) % 7) * DAY : day;
|
|
315
|
+
}
|
|
316
|
+
function nextBucket(ms, bucket) {
|
|
317
|
+
if (bucket === 'month') {
|
|
318
|
+
const date = new Date(ms);
|
|
319
|
+
return Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 1);
|
|
320
|
+
}
|
|
321
|
+
return ms + (bucket === 'week' ? 7 : 1) * DAY;
|
|
322
|
+
}
|
|
323
|
+
/** A deterministic, locale-free axis label: `2025-11` or `2025-11-03`. */
|
|
324
|
+
function bucketLabel(ms, bucket) {
|
|
325
|
+
const iso = new Date(ms).toISOString();
|
|
326
|
+
return bucket === 'month' ? iso.slice(0, 7) : iso.slice(0, 10);
|
|
327
|
+
}
|
|
328
|
+
const isDateField = (field) => field.type === 'datetime' && !field.system;
|
|
329
|
+
/** The model's lead date, for the period window: `issueDate`-like names first. */
|
|
330
|
+
function leadDateField(model) {
|
|
331
|
+
const dated = model.fields.filter(isDateField);
|
|
332
|
+
return (dated.find((f) => /^(issue|order|start|created)/i.test(f.name)) ?? dated[0]);
|
|
333
|
+
}
|
|
334
|
+
function dateOf(value) {
|
|
335
|
+
if (typeof value !== 'string' && typeof value !== 'number')
|
|
336
|
+
return undefined;
|
|
337
|
+
const ms = new Date(value).getTime();
|
|
338
|
+
return Number.isFinite(ms) ? ms : undefined;
|
|
339
|
+
}
|
|
122
340
|
/**
|
|
123
|
-
* `
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
341
|
+
* `chart`: one measure of the model's sample rows grouped by a field. This is
|
|
342
|
+
* the IN-BROWSER STAND-IN for a runtime report: a generated app's chart
|
|
343
|
+
* loader hands these same options to the runtime report compiler and renders
|
|
344
|
+
* what it returns; the planner groups the seeded rows itself so the widget
|
|
345
|
+
* can be tried before a server exists.
|
|
346
|
+
*
|
|
347
|
+
* `groupBy` names a field: a date field is bucketed (days for `7d`/`30d`,
|
|
348
|
+
* weeks for `90d`, months for `12m`/`all`) with empty buckets kept so a line
|
|
349
|
+
* stays continuous; any other field groups by value, largest first. Absent,
|
|
350
|
+
* the model's lead date field is used. `period` is a window back from the
|
|
351
|
+
* sample clock (`EPOCH`, the fixed "now" of the seeded data) over the
|
|
352
|
+
* grouped date field, else the lead date field; a model with no date field
|
|
353
|
+
* ignores it. `measure` is `count`, or `sum` / `avg` of a numeric `field`;
|
|
354
|
+
* money stays integer minor units. The widget's `style` (bar, line, table,
|
|
355
|
+
* pie or stat) is rendered by the widget itself from these points: `stat`
|
|
356
|
+
* headlines the last point against the one before, which on a date axis is
|
|
357
|
+
* the latest bucket.
|
|
127
358
|
*/
|
|
128
|
-
async function
|
|
129
|
-
const { source,
|
|
130
|
-
const
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
359
|
+
async function loadChart(options, ctx) {
|
|
360
|
+
const { source, href } = dataCapabilities(ctx);
|
|
361
|
+
const found = modelOf(options.model);
|
|
362
|
+
const { model } = found;
|
|
363
|
+
const parent = parentFilter(options, ctx, model);
|
|
364
|
+
const groupName = typeof options.groupBy === 'string' ? options.groupBy : '';
|
|
365
|
+
const groupField = groupName
|
|
366
|
+
? model.fields.find((f) => f.name === groupName)
|
|
367
|
+
: leadDateField(model);
|
|
368
|
+
if (!groupField) {
|
|
369
|
+
throw new Error(groupName
|
|
370
|
+
? `${model.name} has no field ${groupName}`
|
|
371
|
+
: `${model.name} has no date field to chart; choose a group-by field`);
|
|
372
|
+
}
|
|
373
|
+
const measure = typeof options.measure === 'string' ? options.measure : '';
|
|
374
|
+
let valueField;
|
|
375
|
+
if (measure && measure !== 'count') {
|
|
376
|
+
if (measure !== 'sum' && measure !== 'avg') {
|
|
377
|
+
throw new Error(`unknown measure ${measure}`);
|
|
378
|
+
}
|
|
379
|
+
valueField = model.fields.find((f) => f.name === options.field);
|
|
380
|
+
if (!valueField ||
|
|
381
|
+
(valueField.type !== 'integer' && valueField.type !== 'decimal')) {
|
|
382
|
+
throw new Error(`${measure} needs a numeric field of ${model.name}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
const period = typeof options.period === 'string' ? options.period : '30d';
|
|
386
|
+
if (!Object.hasOwn(PERIOD_DAYS, period)) {
|
|
387
|
+
throw new Error(`unknown period ${period}`);
|
|
388
|
+
}
|
|
389
|
+
const days = PERIOD_DAYS[period];
|
|
390
|
+
const byDate = isDateField(groupField);
|
|
391
|
+
const windowField = byDate ? groupField : leadDateField(model);
|
|
392
|
+
const since = days !== null && windowField
|
|
393
|
+
? EPOCH - days * DAY
|
|
394
|
+
: Number.NEGATIVE_INFINITY;
|
|
395
|
+
let rows = await rowsOf(source, model, parent);
|
|
396
|
+
if (windowField && since !== Number.NEGATIVE_INFINITY) {
|
|
397
|
+
rows = rows.filter((row) => {
|
|
398
|
+
const at = dateOf(row[windowField.name]);
|
|
399
|
+
return at !== undefined && at >= since && at <= EPOCH;
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
// Group: each bucket keeps the count and the sum, so `avg` is sum / count.
|
|
403
|
+
const groups = new Map();
|
|
404
|
+
const add = (label, key, row) => {
|
|
405
|
+
const group = groups.get(label) ?? { key, sum: 0, n: 0 };
|
|
406
|
+
if (valueField) {
|
|
407
|
+
const value = row[valueField.name];
|
|
408
|
+
if (!numeric(value))
|
|
409
|
+
return;
|
|
410
|
+
group.sum += value;
|
|
411
|
+
}
|
|
412
|
+
group.n += 1;
|
|
413
|
+
groups.set(label, group);
|
|
414
|
+
};
|
|
415
|
+
const bucket = bucketOf(period);
|
|
416
|
+
if (byDate) {
|
|
417
|
+
// Every bucket of the window, in order, empty ones included.
|
|
418
|
+
const start = since !== Number.NEGATIVE_INFINITY
|
|
419
|
+
? since
|
|
420
|
+
: Math.min(...rows.map((row) => dateOf(row[groupField.name]) ?? EPOCH), EPOCH);
|
|
421
|
+
for (let at = bucketStart(start, bucket); at <= EPOCH; at = nextBucket(at, bucket)) {
|
|
422
|
+
groups.set(bucketLabel(at, bucket), { key: at, sum: 0, n: 0 });
|
|
423
|
+
}
|
|
424
|
+
for (const row of rows) {
|
|
425
|
+
const at = dateOf(row[groupField.name]);
|
|
426
|
+
if (at === undefined)
|
|
427
|
+
continue;
|
|
428
|
+
const startOfBucket = bucketStart(at, bucket);
|
|
429
|
+
add(bucketLabel(startOfBucket, bucket), startOfBucket, row);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
for (const row of rows) {
|
|
434
|
+
const value = row[groupField.name];
|
|
435
|
+
const label = value === null || value === undefined || value === ''
|
|
436
|
+
? '(none)'
|
|
437
|
+
: String(value);
|
|
438
|
+
add(label, label, row);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
const money = valueField ? isMoneyField(valueField) : false;
|
|
442
|
+
const measureOf = (group) => {
|
|
443
|
+
if (!valueField)
|
|
444
|
+
return group.n;
|
|
445
|
+
const value = measure === 'avg' && group.n ? group.sum / group.n : group.sum;
|
|
446
|
+
return money ? Math.round(value) : value;
|
|
447
|
+
};
|
|
448
|
+
let points = [...groups.entries()].map(([label, group]) => ({
|
|
449
|
+
label,
|
|
450
|
+
value: measureOf(group),
|
|
451
|
+
key: group.key,
|
|
452
|
+
}));
|
|
453
|
+
points = byDate
|
|
454
|
+
? points.sort((a, b) => Number(a.key) - Number(b.key))
|
|
455
|
+
: points.sort((a, b) => b.value - a.value || a.label.localeCompare(b.label));
|
|
456
|
+
return {
|
|
457
|
+
points: points.map(({ label, value }) => ({ label, value })),
|
|
458
|
+
format: !valueField
|
|
459
|
+
? 'integer'
|
|
460
|
+
: money
|
|
461
|
+
? 'money'
|
|
462
|
+
: valueField.type === 'integer'
|
|
463
|
+
? 'integer'
|
|
464
|
+
: 'decimal',
|
|
465
|
+
...(money ? { currency: 'USD' } : {}),
|
|
466
|
+
href: listHref(href, found, parent),
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* The shortcuts' record counts: a `CookbookShortcutsLoader` that gives each of
|
|
471
|
+
* the shell's default entries (the section's menu as resolved: renames, hides,
|
|
472
|
+
* moves) its count of sample rows, in the entry's own scope. The framework
|
|
473
|
+
* composes it with its entries (`composeShortcutsLoader`): under the mounted
|
|
474
|
+
* `Planner`'s `CookbookApp` as `loaders.shortcuts`, on the static app's
|
|
475
|
+
* section pages through {@link overviewRegistry}. An entry the index does not
|
|
476
|
+
* know (no model) keeps no count.
|
|
477
|
+
*/
|
|
478
|
+
export const loadShortcutCounts = async (ctx, defaults) => {
|
|
479
|
+
const { source, entryIndex } = ctx;
|
|
480
|
+
if (!source || !entryIndex) {
|
|
481
|
+
throw new Error('the planner widget context is missing');
|
|
482
|
+
}
|
|
483
|
+
return Promise.all(defaults.map(async (item) => {
|
|
484
|
+
const entry = entryIndex.get(item.id ?? '');
|
|
139
485
|
if (!entry)
|
|
140
486
|
return item;
|
|
141
487
|
const rows = await source.list(entry.model);
|
|
142
|
-
const count = recordCount(rows.filter((row) => inScope(entry.scope, row)).length);
|
|
143
488
|
return {
|
|
144
489
|
...item,
|
|
145
|
-
|
|
146
|
-
description: item.description
|
|
147
|
-
? `${count} · ${item.description}`
|
|
148
|
-
: count,
|
|
490
|
+
count: rows.filter((row) => inScope(entry.scope, row)).length,
|
|
149
491
|
};
|
|
150
492
|
}));
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
493
|
+
};
|
|
494
|
+
/**
|
|
495
|
+
* The data loaders over the sample source and the shortcuts' counts, for the
|
|
496
|
+
* mounted `Planner`'s `CookbookApp`, whose registry composes `shortcuts` with
|
|
497
|
+
* the shell's entries.
|
|
498
|
+
*/
|
|
499
|
+
export const plannerLoaders = {
|
|
154
500
|
metric: loadMetric,
|
|
155
501
|
records: loadRecords,
|
|
156
|
-
|
|
502
|
+
chart: loadChart,
|
|
503
|
+
shortcuts: loadShortcutCounts,
|
|
504
|
+
};
|
|
505
|
+
registerCoreWidgets(overviewRegistry, {
|
|
506
|
+
...plannerLoaders,
|
|
507
|
+
shortcuts: composeShortcutsLoader(loadShortcutCounts),
|
|
157
508
|
});
|
|
509
|
+
/**
|
|
510
|
+
* The record page's own widgets (smrt#3718), registered once on the shared
|
|
511
|
+
* registry so a cookbook's stored record overview validates like a
|
|
512
|
+
* section's. The framework builds them from one record view's relations;
|
|
513
|
+
* the planner hands those over in the load context (`relations`,
|
|
514
|
+
* `viewAllHref`), and every tab or line list is one call of
|
|
515
|
+
* {@link loadRecords} with the parent filter.
|
|
516
|
+
*/
|
|
517
|
+
function recordWidgetOptions(ctx) {
|
|
518
|
+
const { relations, viewAllHref } = ctx;
|
|
519
|
+
if (!relations)
|
|
520
|
+
throw new Error('the record page context is missing');
|
|
521
|
+
return { relations, records: loadRecords, viewAllHref };
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* The page's record, read fresh at load time, for the line-items totals
|
|
525
|
+
* block: an issued document's frozen money (`storedDocumentTotals`, shown as
|
|
526
|
+
* stored with a row per tax component), else a draft's own totals by role
|
|
527
|
+
* (`documentTotals`, read against its lines); and its currency code.
|
|
528
|
+
*/
|
|
529
|
+
async function recordFigures(ctx, relations) {
|
|
530
|
+
const { source } = dataCapabilities(ctx);
|
|
531
|
+
const ref = ctx.record;
|
|
532
|
+
if (!ref?.id)
|
|
533
|
+
throw new Error('line items need a record');
|
|
534
|
+
const { model } = modelOf(ref.model);
|
|
535
|
+
const record = await source.get(model, ref.id);
|
|
536
|
+
if (!record)
|
|
537
|
+
return {};
|
|
538
|
+
const items = relations.find((r) => r.kind === 'items');
|
|
539
|
+
const lineModel = items
|
|
540
|
+
? getModelByQualifiedName(items.model)?.model
|
|
541
|
+
: undefined;
|
|
542
|
+
const lines = items && lineModel
|
|
543
|
+
? await source.listWhere(lineModel, items.field, ref.id)
|
|
544
|
+
: [];
|
|
545
|
+
const storedTotals = storedDocumentTotals(model, record, lines);
|
|
546
|
+
const totals = storedTotals ? undefined : documentTotals(model, record);
|
|
547
|
+
const code = currencyCodeField(screenDefinition(model));
|
|
548
|
+
const currency = code ? record[code] : undefined;
|
|
549
|
+
return {
|
|
550
|
+
...(storedTotals ? { storedTotals } : {}),
|
|
551
|
+
...(totals ? { totals } : {}),
|
|
552
|
+
...(typeof currency === 'string' && currency ? { currency } : {}),
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
overviewRegistry.register(createRelatedWidget((options, ctx) => createRelatedLoader(recordWidgetOptions(ctx))(options, ctx)));
|
|
556
|
+
overviewRegistry.register(createLineItemsWidget(async (options, ctx) => {
|
|
557
|
+
const base = recordWidgetOptions(ctx);
|
|
558
|
+
const { totals, storedTotals, currency } = await recordFigures(ctx, base.relations);
|
|
559
|
+
return createLineItemsLoader({
|
|
560
|
+
...base,
|
|
561
|
+
totals: () => totals,
|
|
562
|
+
storedTotals: () => storedTotals,
|
|
563
|
+
currency: () => currency,
|
|
564
|
+
})(options, ctx);
|
|
565
|
+
}));
|
|
158
566
|
/** The core widget types a section overview offers. */
|
|
159
567
|
export const CORE_WIDGET_TYPES = [
|
|
160
568
|
'shortcuts',
|
|
161
569
|
'metric',
|
|
162
570
|
'records',
|
|
571
|
+
'chart',
|
|
163
572
|
'note',
|
|
164
573
|
];
|
|
165
574
|
/**
|
|
166
575
|
* How a recipe widget's `'<specifier>#<Export>'` becomes a module: a static map
|
|
167
|
-
* of dynamic imports, one entry per package that ships widgets.
|
|
168
|
-
*
|
|
169
|
-
* `undefined` (the widget then
|
|
576
|
+
* of dynamic imports, one entry per package that ships widgets. The only
|
|
577
|
+
* published widget surface (smrt-reports' `runtime-report-chart`) needs a
|
|
578
|
+
* server, so the map is empty and every lookup is `undefined` (the widget then
|
|
579
|
+
* renders as unavailable).
|
|
170
580
|
*/
|
|
171
581
|
const RECIPE_WIDGET_MODULES = {};
|
|
172
582
|
export const resolveRecipeExport = async (specifier, exportName) => {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* rendered or loaded, and only the canonical override is kept.
|
|
8
8
|
*/
|
|
9
9
|
import { checkOverviewOverride, parseOverviewOverride, } from '@happyvertical/smrt-svelte/overview';
|
|
10
|
-
import { isOverviewId,
|
|
10
|
+
import { isOverviewId, overviewDefinition } from "./definitions.js";
|
|
11
11
|
import { overviewRegistry } from "./registry.js";
|
|
12
12
|
const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
13
13
|
function describe(id, issue) {
|
|
@@ -39,7 +39,7 @@ function without(override, ids) {
|
|
|
39
39
|
* checked again, so one bad widget does not cost the visitor the others.
|
|
40
40
|
*/
|
|
41
41
|
export function checkStoredOverride(id, raw) {
|
|
42
|
-
const definition =
|
|
42
|
+
const definition = overviewDefinition(id);
|
|
43
43
|
if (!definition) {
|
|
44
44
|
return {
|
|
45
45
|
override: null,
|