@manta-eu/react 0.8.0 → 0.9.0
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/dist/action-plan-changes/ActionPlanChangesTable.js +1 -1
- package/dist/action-plan-changes/build-change-tree.js.map +1 -1
- package/dist/ad-preview/AdPluralDisplay.js +1 -1
- package/dist/ad-preview/GoogleAdGroupAdSingularDisplay.js +1 -3
- package/dist/ad-preview/GoogleAdGroupAdSingularDisplay.js.map +1 -1
- package/dist/ad-preview/MetaAdPreview.js +1 -1
- package/dist/ad-preview/meta-ad-copy.d.ts.map +1 -1
- package/dist/ad-preview/meta-ad-model.js.map +1 -1
- package/dist/components/ErrorBoundary.d.ts.map +1 -1
- package/dist/components/ad-preview/business-avatar.d.ts.map +1 -1
- package/dist/components/ad-preview/business-identity.d.ts.map +1 -1
- package/dist/components/ad-preview/business-info.d.ts.map +1 -1
- package/dist/components/ad-preview/facebook/carousel.d.ts.map +1 -1
- package/dist/components/ad-preview/facebook/constants.d.ts.map +1 -1
- package/dist/components/ad-preview/facebook/header.js +1 -1
- package/dist/components/ad-preview/facebook/instream-reels.d.ts.map +1 -1
- package/dist/components/ad-preview/facebook/marketplace.d.ts.map +1 -1
- package/dist/components/ad-preview/google/search.js +1 -1
- package/dist/components/ad-preview/instagram/feed.js +1 -1
- package/dist/components/ad-preview/instagram/search-result.d.ts.map +1 -1
- package/dist/components/ad-preview/use-scroll-navigation.d.ts.map +1 -1
- package/dist/components/ai-elements/conversation.js +1 -1
- package/dist/components/badge/index.d.ts.map +1 -1
- package/dist/components/badge/index.js +1 -1
- package/dist/components/banner/index.d.ts.map +1 -1
- package/dist/components/branding/MantaGridAnimation.js +1 -1
- package/dist/components/breadcrumbs/index.js +1 -1
- package/dist/components/button/index.d.ts.map +1 -1
- package/dist/components/calendar/index.js +2 -2
- package/dist/components/card/index.d.ts.map +1 -1
- package/dist/components/chart/ForecastEventCard.js +1 -1
- package/dist/components/chart/ForecastHoverCard.js +1 -1
- package/dist/components/chart/ForecastLegend.d.ts.map +1 -1
- package/dist/components/chart/ForecastLegend.js +10 -2
- package/dist/components/chart/ForecastLegend.js.map +1 -1
- package/dist/components/chart/annotations.d.ts.map +1 -1
- package/dist/components/chart/chart-colors.d.ts.map +1 -1
- package/dist/components/chart/chart-schemas.d.ts +599 -599
- package/dist/components/chart/chart-schemas.d.ts.map +1 -1
- package/dist/components/chart/chart-schemas.js.map +1 -1
- package/dist/components/chart/chart.js +1 -1
- package/dist/components/chart/forecast-model.d.ts +1 -1
- package/dist/components/chart/forecast-model.d.ts.map +1 -1
- package/dist/components/chart/forecast-model.js.map +1 -1
- package/dist/components/chart/forecast.d.ts.map +1 -1
- package/dist/components/chat/chat-input/index.d.ts +1 -1
- package/dist/components/chat/chat-input/index.js +1 -1
- package/dist/components/chat/chat-input-footer/index.js +1 -1
- package/dist/components/chat/chat-reasoning/index.js +1 -1
- package/dist/components/chat-view/Chat.js +3 -3
- package/dist/components/chat-view/FileMessagePart.js +1 -1
- package/dist/components/chat-view/GraphContextPanel.js +1 -1
- package/dist/components/chat-view/MessageItem.js +1 -1
- package/dist/components/command/index.d.ts +15 -15
- package/dist/components/command/index.d.ts.map +1 -1
- package/dist/components/command/index.js +1 -1
- package/dist/components/dropdown/index.js +1 -1
- package/dist/components/file-dropzone/index.d.ts +25 -0
- package/dist/components/file-dropzone/index.d.ts.map +1 -0
- package/dist/components/file-dropzone/index.js +70 -0
- package/dist/components/file-dropzone/index.js.map +1 -0
- package/dist/components/graph/AgentsGraphListRow.js +1 -1
- package/dist/components/input/ai-action-buttons.js +1 -1
- package/dist/components/input/input-date-range.js +1 -1
- package/dist/components/input/input-field.d.ts.map +1 -1
- package/dist/components/input/input-field.js +1 -1
- package/dist/components/input/textarea.d.ts.map +1 -1
- package/dist/components/input/textarea.js +2 -2
- package/dist/components/input-otp/index.d.ts +6 -6
- package/dist/components/input-otp/index.d.ts.map +1 -1
- package/dist/components/layouts/InstallPrompt.js +1 -1
- package/dist/components/layouts/KnowledgeGraphStartupGate.d.ts +1 -1
- package/dist/components/layouts/RouteLayout.js +1 -1
- package/dist/components/layouts/page/PageHeaderActions.js +1 -1
- package/dist/components/loader/index.d.ts.map +1 -1
- package/dist/components/manta-logo/index.d.ts.map +1 -1
- package/dist/components/modal/index.d.ts.map +1 -1
- package/dist/components/onboarding/SidebarSpotlight.js +1 -1
- package/dist/components/pill/index.d.ts.map +1 -1
- package/dist/components/planning/ActionPlanDetailView.js +1 -1
- package/dist/components/planning/ManualActionList.d.ts +1 -1
- package/dist/components/planning/PlanDetailFooter.js +1 -1
- package/dist/components/planning/plan-detail-utils.d.ts.map +1 -1
- package/dist/components/planning/plan-detail-utils.js +2 -0
- package/dist/components/planning/plan-detail-utils.js.map +1 -1
- package/dist/components/progress/index.d.ts.map +1 -1
- package/dist/components/radio/index.d.ts.map +1 -1
- package/dist/components/rdf-insights/CampaignPerformanceSummary.js +1 -1
- package/dist/components/rdf-insights/InsightCard.js +1 -1
- package/dist/components/rdf-insights/ProductProfitability.js +1 -1
- package/dist/components/rdf-insights/ProductSalesRanking.js +1 -1
- package/dist/components/rdf-insights/ProductVariantsTable.js +1 -1
- package/dist/components/rdf-insights/RoasBenchmark.js +1 -1
- package/dist/components/select/index.d.ts.map +1 -1
- package/dist/components/sheet/index.d.ts.map +1 -1
- package/dist/components/sidebar/company-picker.js +1 -1
- package/dist/components/sidebar/nav-menu.js +1 -1
- package/dist/components/skeleton/index.d.ts +4 -4
- package/dist/components/skeleton/index.d.ts.map +1 -1
- package/dist/components/status/index.d.ts.map +1 -1
- package/dist/components/table/index.d.ts.map +1 -1
- package/dist/components/table/index.js.map +1 -1
- package/dist/components/table/use-table-state.js.map +1 -1
- package/dist/components/table-skeleton/index.js +1 -1
- package/dist/components/tabs/index.d.ts.map +1 -1
- package/dist/components/thinking/index.d.ts.map +1 -1
- package/dist/components/toast/index.d.ts +1 -0
- package/dist/components/toast/index.d.ts.map +1 -1
- package/dist/components/toast/index.js +1 -0
- package/dist/components/toast/index.js.map +1 -1
- package/dist/components/tool-invocation-card/DefaultResultDisplay.js +1 -1
- package/dist/components/tool-invocation-card/ToolOutputRenderer.js +1 -1
- package/dist/components/tree-multi-select/tree-multi-select-rows.js.map +1 -1
- package/dist/datastore-picker/DatastoreRow.js +1 -1
- package/dist/easing.d.ts.map +1 -1
- package/dist/entity-tree/EntityRelationTree.js +1 -1
- package/dist/explain-fact/EntityChip.js +1 -1
- package/dist/explain-fact/conclusion/ConclusionSubtitle.js +1 -1
- package/dist/explain-fact/inspector/InspectorBindings.js +1 -1
- package/dist/explain-fact/inspector/SupportsSection.js +1 -1
- package/dist/explain-fact/proof-tree/ProofRowContent.js +1 -1
- package/dist/explain-fact/proof-tree/ProofRowValue.js +1 -1
- package/dist/globals.css +33 -0
- package/dist/graph/GraphContextPanel.js +1 -1
- package/dist/graph/GraphControls.d.ts +1 -1
- package/dist/graph/GraphControls.d.ts.map +1 -1
- package/dist/graph/GraphControls.js +1 -1
- package/dist/graph/GraphErrorBoundary.d.ts +1 -1
- package/dist/graph/GraphErrorBoundary.d.ts.map +1 -1
- package/dist/graph/NodeContextMenu.d.ts +1 -1
- package/dist/graph/NodeContextMenu.d.ts.map +1 -1
- package/dist/graph/NodeContextMenu.js +1 -1
- package/dist/graph/NodeDetailPanel/PropertyDiffView.js +1 -1
- package/dist/graph/NodeDetailPanel/TypeSummaryPanel.d.ts.map +1 -1
- package/dist/graph/NodeDetailPanel/TypeSummaryPanel.js.map +1 -1
- package/dist/graph/custom-nodes.d.ts +4 -4
- package/dist/graph/custom-nodes.d.ts.map +1 -1
- package/dist/graph/custom-nodes.js +1 -1
- package/dist/graph/graph-layout.js.map +1 -1
- package/dist/graph/graph-list-utils.js.map +1 -1
- package/dist/graph/graph-model.js.map +1 -1
- package/dist/graph/graph-store.js.map +1 -1
- package/dist/graph/nodes/AdsDailyReportTemplateView.d.ts +1 -1
- package/dist/graph/nodes/AdsDailyReportTemplateView.d.ts.map +1 -1
- package/dist/graph/nodes/AttioCallRecordingView.d.ts +1 -1
- package/dist/graph/nodes/AttioCallRecordingView.d.ts.map +1 -1
- package/dist/graph/nodes/AttioCompanyView.d.ts +1 -1
- package/dist/graph/nodes/AttioCompanyView.d.ts.map +1 -1
- package/dist/graph/nodes/AttioDealView.d.ts +1 -1
- package/dist/graph/nodes/AttioDealView.d.ts.map +1 -1
- package/dist/graph/nodes/AttioMeetingView.d.ts +1 -1
- package/dist/graph/nodes/AttioMeetingView.d.ts.map +1 -1
- package/dist/graph/nodes/AttioNoteView.d.ts +1 -1
- package/dist/graph/nodes/AttioNoteView.d.ts.map +1 -1
- package/dist/graph/nodes/AttioTaskView.d.ts +1 -1
- package/dist/graph/nodes/AttioTaskView.d.ts.map +1 -1
- package/dist/graph/nodes/BrandAssetAnalysisActionView.d.ts +1 -1
- package/dist/graph/nodes/BrandAssetAnalysisActionView.d.ts.map +1 -1
- package/dist/graph/nodes/BrandAssetAnalysisView.d.ts +1 -1
- package/dist/graph/nodes/BrandAssetAnalysisView.d.ts.map +1 -1
- package/dist/graph/nodes/BrandFontSuggestionView.d.ts +1 -1
- package/dist/graph/nodes/BrandFontSuggestionView.d.ts.map +1 -1
- package/dist/graph/nodes/BrandGuidelinesView.d.ts +1 -1
- package/dist/graph/nodes/BrandGuidelinesView.d.ts.map +1 -1
- package/dist/graph/nodes/ConnectedAccountCard.d.ts +1 -1
- package/dist/graph/nodes/ConnectedAccountCard.d.ts.map +1 -1
- package/dist/graph/nodes/CoresignalCompanyView.d.ts +1 -1
- package/dist/graph/nodes/CoresignalCompanyView.d.ts.map +1 -1
- package/dist/graph/nodes/CoresignalEmployeeView.d.ts +1 -1
- package/dist/graph/nodes/CoresignalEmployeeView.d.ts.map +1 -1
- package/dist/graph/nodes/CoresignalExperienceView.d.ts +1 -1
- package/dist/graph/nodes/CoresignalExperienceView.d.ts.map +1 -1
- package/dist/graph/nodes/CoresignalJobView.d.ts +1 -1
- package/dist/graph/nodes/CoresignalJobView.d.ts.map +1 -1
- package/dist/graph/nodes/CoresignalKeyExecutiveDepartureView.d.ts +1 -1
- package/dist/graph/nodes/CoresignalKeyExecutiveDepartureView.d.ts.map +1 -1
- package/dist/graph/nodes/EntityCardShell.d.ts +1 -1
- package/dist/graph/nodes/EntityCardShell.d.ts.map +1 -1
- package/dist/graph/nodes/Ga4DailyOverviewView.d.ts +1 -1
- package/dist/graph/nodes/Ga4DailyOverviewView.d.ts.map +1 -1
- package/dist/graph/nodes/Ga4FunnelEventCountView.d.ts +1 -1
- package/dist/graph/nodes/Ga4FunnelEventCountView.d.ts.map +1 -1
- package/dist/graph/nodes/Ga4TrafficSourceView.d.ts +1 -1
- package/dist/graph/nodes/Ga4TrafficSourceView.d.ts.map +1 -1
- package/dist/graph/nodes/GoogleAdGroupAdView.d.ts +1 -1
- package/dist/graph/nodes/GoogleAdGroupAdView.d.ts.map +1 -1
- package/dist/graph/nodes/GoogleAdGroupCriterionView.d.ts +1 -1
- package/dist/graph/nodes/GoogleAdGroupCriterionView.d.ts.map +1 -1
- package/dist/graph/nodes/GoogleAdGroupView.d.ts +1 -1
- package/dist/graph/nodes/GoogleAdGroupView.d.ts.map +1 -1
- package/dist/graph/nodes/GoogleCampaignBudgetView.d.ts +1 -1
- package/dist/graph/nodes/GoogleCampaignBudgetView.d.ts.map +1 -1
- package/dist/graph/nodes/GoogleCampaignCriterionView.d.ts +1 -1
- package/dist/graph/nodes/GoogleCampaignCriterionView.d.ts.map +1 -1
- package/dist/graph/nodes/GoogleCampaignInsightView.d.ts +1 -1
- package/dist/graph/nodes/GoogleCampaignInsightView.d.ts.map +1 -1
- package/dist/graph/nodes/GoogleCampaignView.d.ts +1 -1
- package/dist/graph/nodes/GoogleCampaignView.d.ts.map +1 -1
- package/dist/graph/nodes/GoogleCustomerClientView.d.ts +1 -1
- package/dist/graph/nodes/GoogleCustomerClientView.d.ts.map +1 -1
- package/dist/graph/nodes/GoogleCustomerView.d.ts +1 -1
- package/dist/graph/nodes/GoogleCustomerView.d.ts.map +1 -1
- package/dist/graph/nodes/GoogleSearchTermInsightView.d.ts +1 -1
- package/dist/graph/nodes/GoogleSearchTermInsightView.d.ts.map +1 -1
- package/dist/graph/nodes/LinkedinAdAccountView.d.ts +1 -1
- package/dist/graph/nodes/LinkedinAdAccountView.d.ts.map +1 -1
- package/dist/graph/nodes/MetaAdAccountActivityView.d.ts +1 -1
- package/dist/graph/nodes/MetaAdAccountActivityView.d.ts.map +1 -1
- package/dist/graph/nodes/MetaAdAccountView.d.ts +1 -1
- package/dist/graph/nodes/MetaAdAccountView.d.ts.map +1 -1
- package/dist/graph/nodes/MetaAdImageView.d.ts +1 -1
- package/dist/graph/nodes/MetaAdImageView.d.ts.map +1 -1
- package/dist/graph/nodes/MetaAdSetView.d.ts +1 -1
- package/dist/graph/nodes/MetaAdSetView.d.ts.map +1 -1
- package/dist/graph/nodes/MetaAdView.d.ts +1 -1
- package/dist/graph/nodes/MetaAdView.d.ts.map +1 -1
- package/dist/graph/nodes/MetaCampaignView.d.ts +1 -1
- package/dist/graph/nodes/MetaCampaignView.d.ts.map +1 -1
- package/dist/graph/nodes/MetaInsightView.d.ts +1 -1
- package/dist/graph/nodes/MetaInsightView.d.ts.map +1 -1
- package/dist/graph/nodes/RenderedTemplateView.d.ts +1 -1
- package/dist/graph/nodes/RenderedTemplateView.d.ts.map +1 -1
- package/dist/graph/nodes/SchemaActionView.d.ts +1 -1
- package/dist/graph/nodes/SchemaActionView.d.ts.map +1 -1
- package/dist/graph/nodes/ShopifyShopView.d.ts +1 -1
- package/dist/graph/nodes/ShopifyShopView.d.ts.map +1 -1
- package/dist/graph/nodes/SlackChannelView.d.ts +1 -1
- package/dist/graph/nodes/SlackChannelView.d.ts.map +1 -1
- package/dist/graph/nodes/SlackMessageView.d.ts +1 -1
- package/dist/graph/nodes/SlackMessageView.d.ts.map +1 -1
- package/dist/graph/nodes/SlackUserView.d.ts +1 -1
- package/dist/graph/nodes/SlackUserView.d.ts.map +1 -1
- package/dist/graph/nodes/SlackWorkspaceView.d.ts +1 -1
- package/dist/graph/nodes/SlackWorkspaceView.d.ts.map +1 -1
- package/dist/graph/nodes/attio-shared.d.ts +1 -1
- package/dist/graph/nodes/attio-shared.d.ts.map +1 -1
- package/dist/graph/nodes/attio-shared.js +1 -1
- package/dist/graph/nodes/brand-shared.d.ts.map +1 -1
- package/dist/graph/nodes/card-rows.js +1 -1
- package/dist/graph/nodes/google-campaign-utils.d.ts.map +1 -1
- package/dist/graph/nodes/insight-shared.d.ts +1 -1
- package/dist/graph/nodes/insight-shared.d.ts.map +1 -1
- package/dist/graph/special-nodes/BaseNode.d.ts +2 -2
- package/dist/graph/special-nodes/BaseNode.d.ts.map +1 -1
- package/dist/graph/special-nodes/BaseNode.js +1 -1
- package/dist/graph/special-nodes/DynamicNode.d.ts +1 -1
- package/dist/graph/special-nodes/DynamicNode.d.ts.map +1 -1
- package/dist/graph/special-nodes/EntityValueChip.js +1 -1
- package/dist/graph/special-nodes/GenericNode.d.ts +1 -1
- package/dist/graph/special-nodes/GenericNode.d.ts.map +1 -1
- package/dist/graph/special-nodes/GenericView.d.ts +1 -1
- package/dist/graph/special-nodes/GenericView.d.ts.map +1 -1
- package/dist/graph/special-nodes/NodeFrame.d.ts +1 -1
- package/dist/graph/special-nodes/NodeFrame.d.ts.map +1 -1
- package/dist/graph/special-nodes/NodeFrame.js +1 -1
- package/dist/graph/special-nodes/TypeSummaryNode.d.ts +1 -1
- package/dist/graph/special-nodes/TypeSummaryNode.d.ts.map +1 -1
- package/dist/graph/special-nodes/TypeSummaryNode.js +1 -1
- package/dist/graph/special-nodes/card-facts.js.map +1 -1
- package/dist/hooks/resolved-terms.d.ts +1 -0
- package/dist/hooks/resolved-terms.d.ts.map +1 -1
- package/dist/hooks/resolved-terms.js +2 -1
- package/dist/hooks/resolved-terms.js.map +1 -1
- package/dist/hooks/use-action-plans-list.d.ts.map +1 -1
- package/dist/hooks/use-action-plans-list.js.map +1 -1
- package/dist/hooks/use-activity-feed.js.map +1 -1
- package/dist/hooks/use-connection-problems.d.ts.map +1 -1
- package/dist/hooks/use-conversation-starters.d.ts +2 -2
- package/dist/hooks/use-entity-relations.d.ts.map +1 -1
- package/dist/hooks/use-entity.d.ts.map +1 -1
- package/dist/hooks/use-latest-rendered-template.d.ts.map +1 -1
- package/dist/hooks/use-manual-actions.d.ts.map +1 -1
- package/dist/hooks/use-manual-actions.js.map +1 -1
- package/dist/hooks/use-sparql-construct.d.ts +2 -0
- package/dist/hooks/use-sparql-construct.d.ts.map +1 -1
- package/dist/hooks/use-sparql-construct.js +2 -1
- package/dist/hooks/use-sparql-construct.js.map +1 -1
- package/dist/hooks/useActionGraph.d.ts.map +1 -1
- package/dist/hooks/useActionGraph.js.map +1 -1
- package/dist/hooks/useActionPlanDetail.d.ts +2 -2
- package/dist/hooks/useActionPlanDetail.d.ts.map +1 -1
- package/dist/hooks/useAuth.d.ts +1 -1
- package/dist/hooks/useAuth.d.ts.map +1 -1
- package/dist/hooks/useAuth.js +3 -1
- package/dist/hooks/useAuth.js.map +1 -1
- package/dist/hooks/useConversationGraphContext.js.map +1 -1
- package/dist/hooks/useConversations.js.map +1 -1
- package/dist/hooks/useDatastoreSelection.js.map +1 -1
- package/dist/hooks/useValidateActionPlan.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/build-config.js.map +1 -1
- package/dist/lib/datastore-route-table.d.ts +3 -0
- package/dist/lib/datastore-route-table.d.ts.map +1 -1
- package/dist/lib/datastore-route-table.js +3 -0
- package/dist/lib/datastore-route-table.js.map +1 -1
- package/dist/lib/default-map.d.ts.map +1 -1
- package/dist/lib/default-map.js.map +1 -1
- package/dist/lib/hooks/{useChatUpload.d.ts → useFileUpload.d.ts} +3 -3
- package/dist/lib/hooks/{useChatUpload.d.ts.map → useFileUpload.d.ts.map} +1 -1
- package/dist/lib/hooks/{useChatUpload.js → useFileUpload.js} +2 -2
- package/dist/lib/hooks/{useChatUpload.js.map → useFileUpload.js.map} +1 -1
- package/dist/lib/merge-refs.d.ts.map +1 -1
- package/dist/lib/rdf/insights.js.map +1 -1
- package/dist/lib/structured-data/schema-converter.d.ts +2 -2
- package/dist/lib/structured-data/schema-converter.d.ts.map +1 -1
- package/dist/lib/structured-data/schema-converter.js.map +1 -1
- package/dist/lib/tanstack-query.js +1 -1
- package/dist/lib/tanstack-query.js.map +1 -1
- package/dist/lib/term-batcher.d.ts +3 -1
- package/dist/lib/term-batcher.d.ts.map +1 -1
- package/dist/lib/term-batcher.js +2 -2
- package/dist/lib/term-batcher.js.map +1 -1
- package/dist/lib/use-can-scroll.d.ts.map +1 -1
- package/dist/lib/use-color-palette.d.ts.map +1 -1
- package/dist/lib/use-toggle-set.js.map +1 -1
- package/dist/lib/utils.js +1 -1
- package/dist/ontology/OntologyTermText.js +1 -1
- package/dist/providers/ActiveChatProvider.d.ts +1 -1
- package/dist/providers/ActiveDatastoreProvider.js.map +1 -1
- package/dist/providers/ChatManagerProvider.js.map +1 -1
- package/dist/providers/commands/CommandContext.js +1 -1
- package/dist/routes/activity/components/ActivityTable.js +1 -1
- package/dist/routes/activity/detail/ActivityDetail.d.ts.map +1 -1
- package/dist/routes/activity/detail/ActivityDetail.js +1 -1
- package/dist/routes/activity/detail/ActivityStepsRail.js +1 -1
- package/dist/routes/activity/detail/ActivityTimeline.js +1 -1
- package/dist/routes/data-collection/index.d.ts +3 -0
- package/dist/routes/data-collection/index.d.ts.map +1 -0
- package/dist/routes/data-collection/index.js +43 -0
- package/dist/routes/data-collection/index.js.map +1 -0
- package/dist/routes/data-explorer/class-properties.js.map +1 -1
- package/dist/routes/data-explorer/class-relations.d.ts +2 -2
- package/dist/routes/data-explorer/components/DataExplorerLayout.d.ts.map +1 -1
- package/dist/routes/data-explorer/components/DataExplorerLayout.js +5 -2
- package/dist/routes/data-explorer/components/DataExplorerLayout.js.map +1 -1
- package/dist/routes/data-explorer/components/DetailHeader.js +1 -1
- package/dist/routes/data-explorer/components/DetailHeader.js.map +1 -1
- package/dist/routes/data-explorer/components/Rail.d.ts.map +1 -1
- package/dist/routes/data-explorer/components/Rail.js +3 -3
- package/dist/routes/data-explorer/components/Rail.js.map +1 -1
- package/dist/routes/data-explorer/components/SegmentBuilder.js +1 -1
- package/dist/routes/data-explorer/components/class-detail/ClassDetail.js +1 -1
- package/dist/routes/data-explorer/components/class-detail/CreateRecordAction.js +1 -1
- package/dist/routes/data-explorer/components/class-detail/Overview.js +1 -1
- package/dist/routes/data-explorer/components/ontology-coverage/CoverageNamespaceRail.js +1 -1
- package/dist/routes/data-explorer/components/ontology-coverage/CoverageSkeleton.js +1 -1
- package/dist/routes/data-explorer/components/record-detail/CreateAction.js +1 -1
- package/dist/routes/data-explorer/components/record-detail/RecordActions.d.ts.map +1 -1
- package/dist/routes/data-explorer/components/record-detail/RecordActions.js +12 -9
- package/dist/routes/data-explorer/components/record-detail/RecordActions.js.map +1 -1
- package/dist/routes/data-explorer/components/record-detail/RecordDetail.js +1 -1
- package/dist/routes/data-explorer/components/record-detail/RecordRefresh.d.ts +7 -0
- package/dist/routes/data-explorer/components/record-detail/RecordRefresh.d.ts.map +1 -0
- package/dist/routes/data-explorer/components/record-detail/RecordRefresh.js +104 -0
- package/dist/routes/data-explorer/components/record-detail/RecordRefresh.js.map +1 -0
- package/dist/routes/data-explorer/components/uploads/IngestRunsList.d.ts +8 -0
- package/dist/routes/data-explorer/components/uploads/IngestRunsList.d.ts.map +1 -0
- package/dist/routes/data-explorer/components/uploads/IngestRunsList.js +18 -0
- package/dist/routes/data-explorer/components/uploads/IngestRunsList.js.map +1 -0
- package/dist/routes/data-explorer/components/uploads/IngestStateStatus.d.ts +14 -0
- package/dist/routes/data-explorer/components/uploads/IngestStateStatus.d.ts.map +1 -0
- package/dist/routes/data-explorer/components/uploads/IngestStateStatus.js +33 -0
- package/dist/routes/data-explorer/components/uploads/IngestStateStatus.js.map +1 -0
- package/dist/routes/data-explorer/components/uploads/UploadedFilesList.d.ts +8 -0
- package/dist/routes/data-explorer/components/uploads/UploadedFilesList.d.ts.map +1 -0
- package/dist/routes/data-explorer/components/uploads/UploadedFilesList.js +34 -0
- package/dist/routes/data-explorer/components/uploads/UploadedFilesList.js.map +1 -0
- package/dist/routes/data-explorer/components/uploads/UploadsPages.d.ts +7 -0
- package/dist/routes/data-explorer/components/uploads/UploadsPages.d.ts.map +1 -0
- package/dist/routes/data-explorer/components/uploads/UploadsPages.js +35 -0
- package/dist/routes/data-explorer/components/uploads/UploadsPages.js.map +1 -0
- package/dist/routes/data-explorer/coverage.d.ts.map +1 -1
- package/dist/routes/data-explorer/index.d.ts +1 -0
- package/dist/routes/data-explorer/index.d.ts.map +1 -1
- package/dist/routes/data-explorer/index.js +1 -0
- package/dist/routes/data-explorer/index.js.map +1 -1
- package/dist/routes/data-explorer/namespaces.d.ts +4 -0
- package/dist/routes/data-explorer/namespaces.d.ts.map +1 -1
- package/dist/routes/data-explorer/namespaces.js +6 -1
- package/dist/routes/data-explorer/namespaces.js.map +1 -1
- package/dist/routes/data-explorer/sparql-client.js.map +1 -1
- package/dist/routes/data-explorer/uploads.d.ts +56 -0
- package/dist/routes/data-explorer/uploads.d.ts.map +1 -0
- package/dist/routes/data-explorer/uploads.js +140 -0
- package/dist/routes/data-explorer/uploads.js.map +1 -0
- package/dist/routes/datastores/components/DatastoreTableSkeleton.js +1 -1
- package/dist/routes/datastores/components/DatastoresToolbar.js +1 -1
- package/dist/routes/datastores/components/LinkUnlinkedDatastoreDialog.d.ts +1 -0
- package/dist/routes/datastores/components/LinkUnlinkedDatastoreDialog.d.ts.map +1 -1
- package/dist/routes/datastores/components/LinkUnlinkedDatastoreDialog.js +17 -10
- package/dist/routes/datastores/components/LinkUnlinkedDatastoreDialog.js.map +1 -1
- package/dist/routes/datastores/components/StatusBadge.d.ts +7 -8
- package/dist/routes/datastores/components/StatusBadge.d.ts.map +1 -1
- package/dist/routes/datastores/components/StatusBadge.js +17 -1
- package/dist/routes/datastores/components/StatusBadge.js.map +1 -1
- package/dist/routes/datastores/components/UnlinkedDatastoresPanel.js +1 -1
- package/dist/routes/datastores/flatten.d.ts +6 -1
- package/dist/routes/datastores/flatten.d.ts.map +1 -1
- package/dist/routes/datastores/flatten.js +37 -2
- package/dist/routes/datastores/flatten.js.map +1 -1
- package/dist/routes/datastores/hooks/useDatastoreColumns.d.ts +4 -2
- package/dist/routes/datastores/hooks/useDatastoreColumns.d.ts.map +1 -1
- package/dist/routes/datastores/hooks/useDatastoreColumns.js +9 -7
- package/dist/routes/datastores/hooks/useDatastoreColumns.js.map +1 -1
- package/dist/routes/datastores/index.d.ts.map +1 -1
- package/dist/routes/datastores/index.js +54 -19
- package/dist/routes/datastores/index.js.map +1 -1
- package/dist/routes/integrations/catalog-shape.js.map +1 -1
- package/dist/routes/integrations/components/ConnectionRow.js +1 -1
- package/dist/routes/integrations/components/ProviderLogo.d.ts.map +1 -1
- package/dist/routes/integrations/components/connect-forms/DashConnectForm.js.map +1 -1
- package/dist/routes/integrations/components/connect-forms/GoogleMerchantCenterConnectForm.d.ts +3 -0
- package/dist/routes/integrations/components/connect-forms/GoogleMerchantCenterConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/GoogleMerchantCenterConnectForm.js +38 -0
- package/dist/routes/integrations/components/connect-forms/GoogleMerchantCenterConnectForm.js.map +1 -0
- package/dist/routes/integrations/components/connect-forms/MetaAdsConnectForm.js.map +1 -1
- package/dist/routes/integrations/components/connect-forms/MicrosoftAdsConnectForm.js.map +1 -1
- package/dist/routes/integrations/components/connect-forms/google-ads-account-tree.js.map +1 -1
- package/dist/routes/integrations/components/connect-forms/google-analytics-property-tree.js.map +1 -1
- package/dist/routes/integrations/components/connect-forms/google-merchant-center-account-tree.d.ts +4 -0
- package/dist/routes/integrations/components/connect-forms/google-merchant-center-account-tree.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/google-merchant-center-account-tree.js +32 -0
- package/dist/routes/integrations/components/connect-forms/google-merchant-center-account-tree.js.map +1 -0
- package/dist/routes/integrations/components/connect-forms/setup-account-unavailable-reason.d.ts.map +1 -1
- package/dist/routes/integrations/components/connect-forms/setup-account-unavailable-reason.js +1 -0
- package/dist/routes/integrations/components/connect-forms/setup-account-unavailable-reason.js.map +1 -1
- package/dist/routes/integrations/connect-forms.d.ts +1 -0
- package/dist/routes/integrations/connect-forms.d.ts.map +1 -1
- package/dist/routes/integrations/connect-forms.js +1 -0
- package/dist/routes/integrations/connect-forms.js.map +1 -1
- package/dist/routes/integrations/connection-view.d.ts.map +1 -1
- package/dist/routes/integrations/connection-view.js +1 -0
- package/dist/routes/integrations/connection-view.js.map +1 -1
- package/dist/routes/integrations/types.d.ts.map +1 -1
- package/dist/routes/memories/components/ChangeScopeDialog.js +1 -1
- package/dist/routes/memories/components/ConflictMemoryCard.js +1 -1
- package/dist/routes/memories/components/ConsolidationReviewDialog.js +1 -1
- package/dist/routes/memories/components/LoadingSkeleton.js +1 -1
- package/dist/routes/memories/components/MemoriesFilters.js +1 -1
- package/dist/routes/memories/components/MemoriesTabPanel.js +1 -1
- package/dist/routes/memories/components/MemoryActions.js +1 -1
- package/dist/routes/memories/components/MemoryFields.js +1 -1
- package/dist/routes/memories/components/MemoryFormDialog.js +1 -1
- package/dist/routes/memories/expiry-utils.js.map +1 -1
- package/dist/routes/memories/hooks/useDuplicateDetection.js.map +1 -1
- package/dist/routes/memories/hooks/useLiveContext.d.ts.map +1 -1
- package/dist/routes/memories/hooks/useMemoryColumns.d.ts.map +1 -1
- package/dist/routes/memories/hooks/useMemoryColumns.js +1 -1
- package/dist/routes/memories/hooks/useMemoryTable.js.map +1 -1
- package/dist/routes/plans/components/ActionPlanPage.js +1 -1
- package/dist/routes/plans/components/ActionPlansFilters.js +1 -1
- package/dist/routes/plans/components/ActionPlansPage.js +1 -1
- package/dist/routes/plans/components/ActionPlansTableBody.js +1 -1
- package/dist/routes/plans/components/actionPlansTableConfig.d.ts +7 -7
- package/dist/routes/plans/components/actionPlansTableConfig.d.ts.map +1 -1
- package/dist/routes/plans/index.js +1 -1
- package/dist/routes/rules/components/RuleAffectedActionPlansSection.js +1 -1
- package/dist/routes/rules/components/RuleDetailsPage.js +1 -1
- package/dist/routes/rules/components/RuleProducersSection.js +1 -1
- package/dist/routes/rules/components/RuleSetup.js +1 -1
- package/dist/routes/rules/components/RulesOverviewPage.js +1 -1
- package/dist/routes/rules/components/datalog-editor/FactsPreview.js +1 -1
- package/dist/routes/rules/components/datalog-editor/SparqlQueryPanel.js +1 -1
- package/dist/routes/rules/components/rule-actionability.js.map +1 -1
- package/dist/rules/RuleNarrativeSegments.js +1 -1
- package/dist/rules/datalog-ast/DatalogAtomComponent.js +1 -1
- package/dist/rules/datalog-ast/DatalogBodyFormulaComponent.js +1 -1
- package/dist/rules/datalog-ast/DatalogExpressionRenderer.js +1 -1
- package/dist/rules/datalog-ast/DatalogTermComponent.js +1 -1
- package/dist/rules/datalog-cache.js.map +1 -1
- package/dist/rules/rule-narrative-format.d.ts.map +1 -1
- package/dist/rules/rule-narrative-renderer.js.map +1 -1
- package/dist/shared/graph-derived-queries.d.ts.map +1 -1
- package/dist/shared/graph-derived-queries.js +2 -1
- package/dist/shared/graph-derived-queries.js.map +1 -1
- package/dist/style.js +1 -1
- package/dist/templates/slack-to-markdown.js +1 -1
- package/package.json +27 -14
- package/src/app-subpaths.json +1 -0
- package/src/components/badge/index.tsx +1 -1
- package/src/components/calendar/index.tsx +2 -2
- package/src/components/chart/ForecastLegend.tsx +15 -13
- package/src/components/chart/forecast-model.ts +6 -8
- package/src/components/chat-view/Chat.tsx +2 -2
- package/src/components/file-dropzone/index.tsx +165 -0
- package/src/components/input/input-field.tsx +1 -1
- package/src/components/input/textarea.tsx +1 -1
- package/src/components/planning/plan-detail-utils.tsx +2 -0
- package/src/components/table/index.tsx +0 -1
- package/src/components/toast/index.tsx +1 -0
- package/src/graph/NodeDetailPanel/TypeSummaryPanel.tsx +12 -14
- package/src/hooks/resolved-terms.ts +6 -1
- package/src/hooks/use-sparql-construct.ts +4 -2
- package/src/hooks/useAuth.ts +3 -1
- package/src/index.ts +1 -0
- package/src/lib/chat-types.ts +1 -1
- package/src/lib/datastore-route-table.ts +6 -0
- package/src/lib/hooks/{useChatUpload.ts → useFileUpload.ts} +2 -2
- package/src/lib/tanstack-query.ts +2 -2
- package/src/lib/term-batcher.ts +3 -3
- package/src/lib/utils.ts +1 -1
- package/src/routes/data-collection/index.tsx +82 -0
- package/src/routes/data-explorer/components/DataExplorerLayout.tsx +5 -2
- package/src/routes/data-explorer/components/DetailHeader.tsx +4 -4
- package/src/routes/data-explorer/components/Rail.tsx +13 -2
- package/src/routes/data-explorer/components/record-detail/RecordActions.tsx +22 -16
- package/src/routes/data-explorer/components/record-detail/RecordRefresh.tsx +150 -0
- package/src/routes/data-explorer/components/uploads/IngestRunsList.tsx +63 -0
- package/src/routes/data-explorer/components/uploads/IngestStateStatus.tsx +45 -0
- package/src/routes/data-explorer/components/uploads/UploadedFilesList.tsx +93 -0
- package/src/routes/data-explorer/components/uploads/UploadsPages.tsx +80 -0
- package/src/routes/data-explorer/index.tsx +6 -0
- package/src/routes/data-explorer/namespaces.ts +7 -1
- package/src/routes/data-explorer/uploads.ts +205 -0
- package/src/routes/datastores/components/LinkUnlinkedDatastoreDialog.tsx +49 -10
- package/src/routes/datastores/components/StatusBadge.tsx +22 -7
- package/src/routes/datastores/flatten.ts +50 -2
- package/src/routes/datastores/hooks/useDatastoreColumns.tsx +21 -1
- package/src/routes/datastores/index.tsx +64 -13
- package/src/routes/integrations/components/connect-forms/GoogleMerchantCenterConnectForm.tsx +61 -0
- package/src/routes/integrations/components/connect-forms/google-merchant-center-account-tree.ts +38 -0
- package/src/routes/integrations/components/connect-forms/setup-account-unavailable-reason.ts +1 -0
- package/src/routes/integrations/connect-forms.ts +1 -0
- package/src/routes/integrations/connection-view.ts +1 -0
- package/src/rules/datalog-ast/DatalogBodyFormulaComponent.tsx +1 -1
- package/src/rules/datalog-ast/DatalogTermComponent.tsx +1 -1
- package/src/shacl/shacl-form-types.ts +1 -1
- package/src/shared/graph-derived-queries.ts +2 -0
- package/src/style.ts +1 -1
- package/src/templates/slack-to-markdown.ts +1 -1
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { userIriPrefix } from "@manta-eu/client/shared/stakeholder-iri";
|
|
2
|
+
import { isIngestableExtension } from "@manta-eu/client/shared/upload";
|
|
3
|
+
import { ingestManual } from "@manta-eu/ldo";
|
|
4
|
+
import { ingest, nfo, nmo, prov } from "@manta-eu/ldo/namespaces";
|
|
5
|
+
import { getExtension } from "@manta-eu/lib/file";
|
|
6
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
7
|
+
import type { RDF } from "ldkit/rdf";
|
|
8
|
+
import { useCallback, useMemo } from "react";
|
|
9
|
+
import { bindingCount, bindingValue, useSparqlSelect } from "#ldo-ui";
|
|
10
|
+
|
|
11
|
+
export const uploadsLimit = 500;
|
|
12
|
+
|
|
13
|
+
export const ingestPollIntervalMs = 15_000;
|
|
14
|
+
|
|
15
|
+
const uploadsQueryKey = ["uploaded-files"] as const;
|
|
16
|
+
|
|
17
|
+
export type UploadedFile = {
|
|
18
|
+
iri: string;
|
|
19
|
+
fileName: string;
|
|
20
|
+
mediaType?: string;
|
|
21
|
+
byteSize?: number;
|
|
22
|
+
extension?: string;
|
|
23
|
+
uploadedAt?: string;
|
|
24
|
+
uploader?: string;
|
|
25
|
+
purpose?: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type IngestStatus = "ingested" | "unparsable" | "gone" | "too_large";
|
|
29
|
+
|
|
30
|
+
export type IngestRun = {
|
|
31
|
+
iri: string;
|
|
32
|
+
file: string;
|
|
33
|
+
status: IngestStatus;
|
|
34
|
+
endedAt?: string;
|
|
35
|
+
recordsRead?: number;
|
|
36
|
+
recordsDropped?: number;
|
|
37
|
+
dataset?: string;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type FileIngestState = { kind: "waiting" } | { kind: "stored" } | { kind: "run"; run: IngestRun };
|
|
41
|
+
|
|
42
|
+
const ingestStatuses = new Set<string>(["ingested", "unparsable", "gone", "too_large"]);
|
|
43
|
+
|
|
44
|
+
function isIngestStatus(value: string | undefined): value is IngestStatus {
|
|
45
|
+
return value !== undefined && ingestStatuses.has(value);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Operators see every file node; members see the files a user uploaded.
|
|
49
|
+
export function uploadedFilesQuery(includeAllFiles: boolean): string {
|
|
50
|
+
const uploaderPattern = includeAllFiles
|
|
51
|
+
? `OPTIONAL { ?file <${prov.wasAttributedTo}> ?uploader }`
|
|
52
|
+
: `?file <${prov.wasAttributedTo}> ?uploader .
|
|
53
|
+
FILTER(STRSTARTS(STR(?uploader), "${userIriPrefix}"))`;
|
|
54
|
+
|
|
55
|
+
return `SELECT ?file ?fileName ?mediaType ?byteSize ?extension ?uploadedAt ?uploader ?purpose WHERE {
|
|
56
|
+
?file a <${nfo.FileDataObject}> .
|
|
57
|
+
FILTER(isIRI(?file))
|
|
58
|
+
${uploaderPattern}
|
|
59
|
+
OPTIONAL { ?file <${nfo.fileName}> ?fileName }
|
|
60
|
+
OPTIONAL { ?file <${nmo.contentMimeType}> ?mediaType }
|
|
61
|
+
OPTIONAL { ?file <${nfo.fileSize}> ?byteSize }
|
|
62
|
+
OPTIONAL { ?file <${nfo.fileExtension}> ?extension }
|
|
63
|
+
OPTIONAL { ?file <${prov.generatedAtTime}> ?uploadedAt }
|
|
64
|
+
OPTIONAL { ?file <${ingestManual.uploadPurpose}> ?purpose }
|
|
65
|
+
}
|
|
66
|
+
ORDER BY DESC(STR(?uploadedAt)) STR(?file)
|
|
67
|
+
LIMIT ${uploadsLimit}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const ingestRunsQuery = `SELECT ?run ?file ?status ?endedAt ?recordsRead ?recordsDropped ?dataset WHERE {
|
|
71
|
+
?run a <${ingest.IngestRun}> ;
|
|
72
|
+
<${prov.used}> ?file ;
|
|
73
|
+
<${ingest.status}> ?status .
|
|
74
|
+
FILTER(isIRI(?run))
|
|
75
|
+
OPTIONAL { ?run <${prov.endedAtTime}> ?endedAt }
|
|
76
|
+
OPTIONAL { ?run <${ingest.recordsRead}> ?recordsRead }
|
|
77
|
+
OPTIONAL { ?run <${ingest.recordsDropped}> ?recordsDropped }
|
|
78
|
+
OPTIONAL { ?run <${prov.generated}> ?dataset }
|
|
79
|
+
}
|
|
80
|
+
ORDER BY DESC(STR(?endedAt)) STR(?run)
|
|
81
|
+
LIMIT ${uploadsLimit}`;
|
|
82
|
+
|
|
83
|
+
export function uploadedFilesFromBindings(bindings: RDF.Bindings[]): UploadedFile[] {
|
|
84
|
+
const files = new Map<string, UploadedFile>();
|
|
85
|
+
|
|
86
|
+
for (const binding of bindings) {
|
|
87
|
+
const iri = bindingValue(binding, "file");
|
|
88
|
+
|
|
89
|
+
if (!iri || files.has(iri)) continue;
|
|
90
|
+
|
|
91
|
+
const fileName = bindingValue(binding, "fileName") ?? iri;
|
|
92
|
+
|
|
93
|
+
files.set(iri, {
|
|
94
|
+
iri,
|
|
95
|
+
fileName,
|
|
96
|
+
mediaType: bindingValue(binding, "mediaType"),
|
|
97
|
+
byteSize: bindingCount(binding, "byteSize"),
|
|
98
|
+
extension: bindingValue(binding, "extension") ?? getExtension(fileName),
|
|
99
|
+
uploadedAt: bindingValue(binding, "uploadedAt"),
|
|
100
|
+
uploader: bindingValue(binding, "uploader"),
|
|
101
|
+
purpose: bindingValue(binding, "purpose"),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return [...files.values()];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function ingestRunsFromBindings(bindings: RDF.Bindings[]): IngestRun[] {
|
|
109
|
+
const runs = new Map<string, IngestRun>();
|
|
110
|
+
|
|
111
|
+
for (const binding of bindings) {
|
|
112
|
+
const iri = bindingValue(binding, "run");
|
|
113
|
+
const file = bindingValue(binding, "file");
|
|
114
|
+
const status = bindingValue(binding, "status");
|
|
115
|
+
|
|
116
|
+
if (!iri || !file || !isIngestStatus(status) || runs.has(iri)) continue;
|
|
117
|
+
|
|
118
|
+
runs.set(iri, {
|
|
119
|
+
iri,
|
|
120
|
+
file,
|
|
121
|
+
status,
|
|
122
|
+
endedAt: bindingValue(binding, "endedAt"),
|
|
123
|
+
recordsRead: bindingCount(binding, "recordsRead"),
|
|
124
|
+
recordsDropped: bindingCount(binding, "recordsDropped"),
|
|
125
|
+
dataset: bindingValue(binding, "dataset"),
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return [...runs.values()];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function latestRunByFile(runs: readonly IngestRun[]): Map<string, IngestRun> {
|
|
133
|
+
const latest = new Map<string, IngestRun>();
|
|
134
|
+
|
|
135
|
+
for (const run of runs) {
|
|
136
|
+
const current = latest.get(run.file);
|
|
137
|
+
|
|
138
|
+
if (!current || (run.endedAt ?? "") > (current.endedAt ?? "")) latest.set(run.file, run);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return latest;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Only a file recorded with the "file" purpose is picked up by ingest; a bundle or an older upload is only stored.
|
|
145
|
+
export function fileIngestState(file: UploadedFile, run: IngestRun | undefined): FileIngestState {
|
|
146
|
+
if (run) return { kind: "run", run };
|
|
147
|
+
|
|
148
|
+
return file.purpose === "file" && isIngestableExtension(file.extension) ? { kind: "waiting" } : { kind: "stored" };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function filesWithIngestState(
|
|
152
|
+
files: readonly UploadedFile[],
|
|
153
|
+
runs: readonly IngestRun[],
|
|
154
|
+
): UploadedFileWithState[] {
|
|
155
|
+
const latest = latestRunByFile(runs);
|
|
156
|
+
|
|
157
|
+
return files.map((file) => ({ ...file, state: fileIngestState(file, latest.get(file.iri)) }));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function hasWaitingFile(files: readonly UploadedFileWithState[]): boolean {
|
|
161
|
+
return files.some((file) => file.state.kind === "waiting");
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export type UploadedFileWithState = UploadedFile & { state: FileIngestState };
|
|
165
|
+
|
|
166
|
+
type UseUploadsOptions = { includeAllFiles: boolean };
|
|
167
|
+
|
|
168
|
+
export function useUploads(options: UseUploadsOptions) {
|
|
169
|
+
const { includeAllFiles } = options;
|
|
170
|
+
|
|
171
|
+
const filesQuery = useSparqlSelect({
|
|
172
|
+
query: uploadedFilesQuery(includeAllFiles),
|
|
173
|
+
queryKey: [...uploadsQueryKey, "files", includeAllFiles],
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const files = useMemo(() => uploadedFilesFromBindings(filesQuery.data ?? []), [filesQuery.data]);
|
|
177
|
+
|
|
178
|
+
const runsQuery = useSparqlSelect({
|
|
179
|
+
query: ingestRunsQuery,
|
|
180
|
+
queryKey: [...uploadsQueryKey, "runs"],
|
|
181
|
+
refetchInterval: (query) =>
|
|
182
|
+
hasWaitingFile(filesWithIngestState(files, ingestRunsFromBindings(query.state.data ?? [])))
|
|
183
|
+
? ingestPollIntervalMs
|
|
184
|
+
: false,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
const runs = useMemo(() => ingestRunsFromBindings(runsQuery.data ?? []), [runsQuery.data]);
|
|
188
|
+
const filesWithState = useMemo(() => filesWithIngestState(files, runs), [files, runs]);
|
|
189
|
+
const fileByIri = useMemo(() => new Map(files.map((file) => [file.iri, file])), [files]);
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
files: filesWithState,
|
|
193
|
+
runs,
|
|
194
|
+
fileByIri,
|
|
195
|
+
hasWaiting: hasWaitingFile(filesWithState),
|
|
196
|
+
isLoading: filesQuery.isLoading || runsQuery.isLoading,
|
|
197
|
+
error: filesQuery.error ?? runsQuery.error,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function useInvalidateUploads() {
|
|
202
|
+
const queryClient = useQueryClient();
|
|
203
|
+
|
|
204
|
+
return useCallback(() => queryClient.invalidateQueries({ queryKey: uploadsQueryKey }), [queryClient]);
|
|
205
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useLinkUnlinkedDatastoreMutation, useDatastoreTreeQuery, useUnlinkedDatastoresQuery } from "@manta-eu/client";
|
|
2
2
|
import { parseError } from "@manta-eu/client/shared/error-utils";
|
|
3
|
+
import { normalizeGroupPath, pathSegments } from "@manta-eu/client/shared/team";
|
|
3
4
|
import { isPresent } from "@manta-eu/lib/present";
|
|
4
5
|
import { useQueryClient } from "@tanstack/react-query";
|
|
5
6
|
import { useState } from "react";
|
|
@@ -30,6 +31,7 @@ export type SuggestedLinkTarget = {
|
|
|
30
31
|
export type LinkUnlinkedDatastoreDialogProps = {
|
|
31
32
|
datastoreId: string;
|
|
32
33
|
organizationNames: string[];
|
|
34
|
+
groupPathsByOrganization: Map<string, string[]>;
|
|
33
35
|
existingOrganizationNames: Set<string>;
|
|
34
36
|
suggestedMatch?: SuggestedLinkTarget;
|
|
35
37
|
onClose: () => void;
|
|
@@ -37,8 +39,17 @@ export type LinkUnlinkedDatastoreDialogProps = {
|
|
|
37
39
|
|
|
38
40
|
type Mode = "new" | "existing";
|
|
39
41
|
|
|
42
|
+
const organizationRootPath = "/";
|
|
43
|
+
|
|
40
44
|
export function LinkUnlinkedDatastoreDialog(props: LinkUnlinkedDatastoreDialogProps) {
|
|
41
|
-
const {
|
|
45
|
+
const {
|
|
46
|
+
datastoreId,
|
|
47
|
+
organizationNames,
|
|
48
|
+
groupPathsByOrganization,
|
|
49
|
+
existingOrganizationNames,
|
|
50
|
+
suggestedMatch,
|
|
51
|
+
onClose,
|
|
52
|
+
} = props;
|
|
42
53
|
const { mantaClient } = useMantaClient();
|
|
43
54
|
const queryClient = useQueryClient();
|
|
44
55
|
|
|
@@ -46,6 +57,11 @@ export function LinkUnlinkedDatastoreDialog(props: LinkUnlinkedDatastoreDialogPr
|
|
|
46
57
|
const [organizationName, setOrganizationName] = useState("");
|
|
47
58
|
const [existingOrganizationName, setExistingOrganizationName] = useState(suggestedMatch?.organizationName ?? "");
|
|
48
59
|
const [name, setName] = useState(suggestedMatch?.name ?? "");
|
|
60
|
+
const [parentGroupPath, setParentGroupPath] = useState(
|
|
61
|
+
suggestedMatch ? normalizeGroupPath(suggestedMatch.parentPath.join("/")) : organizationRootPath,
|
|
62
|
+
);
|
|
63
|
+
const parentGroupPaths = groupPathsByOrganization.get(existingOrganizationName) ?? [];
|
|
64
|
+
const offeredParentGroupPath = parentGroupPaths.includes(parentGroupPath) ? parentGroupPath : organizationRootPath;
|
|
49
65
|
|
|
50
66
|
const linkMutation = useLinkUnlinkedDatastoreMutation(mantaClient, {
|
|
51
67
|
onSuccess: (result) => {
|
|
@@ -53,7 +69,11 @@ export function LinkUnlinkedDatastoreDialog(props: LinkUnlinkedDatastoreDialogPr
|
|
|
53
69
|
void queryClient.invalidateQueries({ queryKey: useDatastoreTreeQuery.getKey() });
|
|
54
70
|
void queryClient.invalidateQueries({ queryKey: useUnlinkedDatastoresQuery.getKey() });
|
|
55
71
|
void queryClient.invalidateQueries({ queryKey: ["DatastoreProvisioningStatuses"] });
|
|
56
|
-
toast.success(
|
|
72
|
+
toast.success(
|
|
73
|
+
result.linkUnlinkedDatastore.pending
|
|
74
|
+
? `Linked to '${datastoreId}', which is still being built`
|
|
75
|
+
: `Linked to the existing datastore '${datastoreId}'`,
|
|
76
|
+
);
|
|
57
77
|
toastProviderWarning(result.linkUnlinkedDatastore.providerWarning);
|
|
58
78
|
onClose();
|
|
59
79
|
} else {
|
|
@@ -72,12 +92,12 @@ export function LinkUnlinkedDatastoreDialog(props: LinkUnlinkedDatastoreDialogPr
|
|
|
72
92
|
|
|
73
93
|
const canSubmit = mode === "new" ? !!organizationName.trim() && !tenantCheck.blocked : !!existingOrganizationName;
|
|
74
94
|
const atExistingOrganizationRoot = mode === "existing" && !name.trim();
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
95
|
+
const parentPath = pathSegments(offeredParentGroupPath);
|
|
96
|
+
|
|
97
|
+
function selectOrganization(organization: string) {
|
|
98
|
+
setExistingOrganizationName(organization);
|
|
99
|
+
setParentGroupPath(organizationRootPath);
|
|
100
|
+
}
|
|
81
101
|
|
|
82
102
|
function submit() {
|
|
83
103
|
if (!canSubmit) return;
|
|
@@ -107,7 +127,7 @@ export function LinkUnlinkedDatastoreDialog(props: LinkUnlinkedDatastoreDialogPr
|
|
|
107
127
|
: {
|
|
108
128
|
datastoreId,
|
|
109
129
|
organizationName: existingOrganizationName,
|
|
110
|
-
...(isPresent(
|
|
130
|
+
...(isPresent(parentPath) ? { parentPath } : {}),
|
|
111
131
|
name: name.trim(),
|
|
112
132
|
atOrganizationRoot: false,
|
|
113
133
|
};
|
|
@@ -143,7 +163,7 @@ export function LinkUnlinkedDatastoreDialog(props: LinkUnlinkedDatastoreDialogPr
|
|
|
143
163
|
</>
|
|
144
164
|
) : (
|
|
145
165
|
<>
|
|
146
|
-
<Select value={existingOrganizationName} onValueChange={
|
|
166
|
+
<Select value={existingOrganizationName} onValueChange={selectOrganization}>
|
|
147
167
|
<SelectTrigger label="Organization" id="link-organization">
|
|
148
168
|
<SelectValue placeholder="Select an organization…" />
|
|
149
169
|
</SelectTrigger>
|
|
@@ -155,6 +175,25 @@ export function LinkUnlinkedDatastoreDialog(props: LinkUnlinkedDatastoreDialogPr
|
|
|
155
175
|
))}
|
|
156
176
|
</SelectContent>
|
|
157
177
|
</Select>
|
|
178
|
+
{isPresent(parentGroupPaths) && (
|
|
179
|
+
<Select
|
|
180
|
+
value={offeredParentGroupPath}
|
|
181
|
+
onValueChange={setParentGroupPath}
|
|
182
|
+
disabled={atExistingOrganizationRoot}
|
|
183
|
+
>
|
|
184
|
+
<SelectTrigger label="Under" id="link-parent-group">
|
|
185
|
+
<SelectValue />
|
|
186
|
+
</SelectTrigger>
|
|
187
|
+
<SelectContent>
|
|
188
|
+
<SelectItem value={organizationRootPath}>Organization root</SelectItem>
|
|
189
|
+
{parentGroupPaths.map((path) => (
|
|
190
|
+
<SelectItem key={path} value={path}>
|
|
191
|
+
{path}
|
|
192
|
+
</SelectItem>
|
|
193
|
+
))}
|
|
194
|
+
</SelectContent>
|
|
195
|
+
</Select>
|
|
196
|
+
)}
|
|
158
197
|
<Input
|
|
159
198
|
label="Datastore name"
|
|
160
199
|
placeholder="Leave empty to link to the organization root"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { enableDatastoreRemoval } from "@manta-eu/client/shared/constants";
|
|
1
2
|
import { isPresent } from "@manta-eu/lib/present";
|
|
2
3
|
import { LoaderCircle } from "lucide-react";
|
|
3
4
|
import { Badge, type BadgeVariant } from "#components/badge/index";
|
|
@@ -7,13 +8,13 @@ import {
|
|
|
7
8
|
type DatastoreStatusCategory,
|
|
8
9
|
} from "#components/datastore-management/tree";
|
|
9
10
|
|
|
10
|
-
export type DatastoreStatusFilterValue = "noDatastore" | "checking" | DatastoreStatusCategory;
|
|
11
|
+
export type DatastoreStatusFilterValue = "noDatastore" | "checking" | "notBuilt" | DatastoreStatusCategory;
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
): DatastoreStatusFilterValue {
|
|
13
|
+
type StatusNode = { datastoreId?: string; removed: boolean; isUnlinked?: boolean; unbuilt?: boolean };
|
|
14
|
+
|
|
15
|
+
export function datastoreStatusFilterValue(node: StatusNode, status?: DatastoreStatus): DatastoreStatusFilterValue {
|
|
16
16
|
if (!isPresent(node.datastoreId)) return "noDatastore";
|
|
17
|
+
if (node.unbuilt === true && status?.exists !== true) return "notBuilt";
|
|
17
18
|
return datastoreStatusCategory(node, status) ?? "checking";
|
|
18
19
|
}
|
|
19
20
|
|
|
@@ -33,10 +34,23 @@ const badgeConfigByFilterValue: Record<DatastoreStatusFilterValue, BadgeConfig>
|
|
|
33
34
|
variant: "destructive",
|
|
34
35
|
title: "This id never reached the datastore registry, so nothing will build it. Provision it again.",
|
|
35
36
|
},
|
|
37
|
+
notBuilt: {
|
|
38
|
+
label: "Not built",
|
|
39
|
+
variant: "warning",
|
|
40
|
+
title: "Registered in Infisical, but no datastore exists for it. Link it to build it, or delete it.",
|
|
41
|
+
},
|
|
36
42
|
offline: { label: "Offline", variant: "destructive" },
|
|
37
43
|
unavailable: { label: "Status unavailable", variant: "copy" },
|
|
38
44
|
checking: { label: "Checking…", variant: "copy", spinning: true },
|
|
39
|
-
removed:
|
|
45
|
+
removed: enableDatastoreRemoval
|
|
46
|
+
? { label: "Removed", variant: "copy" }
|
|
47
|
+
: {
|
|
48
|
+
label: "Removed",
|
|
49
|
+
variant: "warning",
|
|
50
|
+
title:
|
|
51
|
+
"Out of use: a permanent delete stopped partway, or it was removed before removal was turned off. " +
|
|
52
|
+
"Delete it permanently only if it should go for good.",
|
|
53
|
+
},
|
|
40
54
|
noDatastore: { label: "No datastore", variant: "copy" },
|
|
41
55
|
};
|
|
42
56
|
|
|
@@ -44,6 +58,7 @@ const filterOptionOrder: DatastoreStatusFilterValue[] = [
|
|
|
44
58
|
"ready",
|
|
45
59
|
"materializing",
|
|
46
60
|
"notRegistered",
|
|
61
|
+
"notBuilt",
|
|
47
62
|
"offline",
|
|
48
63
|
"unavailable",
|
|
49
64
|
"removed",
|
|
@@ -55,7 +70,7 @@ export const datastoreStatusFilterOptions: { id: "ALL" | DatastoreStatusFilterVa
|
|
|
55
70
|
];
|
|
56
71
|
|
|
57
72
|
export type DatastoreStatusBadgeProps = {
|
|
58
|
-
node:
|
|
73
|
+
node: StatusNode;
|
|
59
74
|
status?: DatastoreStatus;
|
|
60
75
|
};
|
|
61
76
|
|
|
@@ -25,6 +25,7 @@ export type DatastoreRow = {
|
|
|
25
25
|
// Real in the datastore, but no Keycloak node behind it, so it can only be selected.
|
|
26
26
|
isRealmDefault?: boolean;
|
|
27
27
|
isUnlinked?: boolean;
|
|
28
|
+
unbuilt?: boolean;
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
export function realmDefaultRow(datastoreId: Realm): DatastoreRow {
|
|
@@ -105,6 +106,15 @@ export function hiddenRowCount(
|
|
|
105
106
|
return visibleDatastoreRows(rows, { ...visibility, [key]: true }).length - shownCount;
|
|
106
107
|
}
|
|
107
108
|
|
|
109
|
+
export function hiddenRemovedRowCount(rows: DatastoreRow[], visibility: DatastoreRowVisibility): number {
|
|
110
|
+
if (visibility.showArchived) return 0;
|
|
111
|
+
|
|
112
|
+
const shown = new Set(visibleDatastoreRows(rows, visibility));
|
|
113
|
+
return rows.filter(
|
|
114
|
+
(row) => row.removed && !shown.has(row) && matchesVisibility(row, { ...visibility, showArchived: true }),
|
|
115
|
+
).length;
|
|
116
|
+
}
|
|
117
|
+
|
|
108
118
|
// Matches Keycloak's own org lookup (ensureOrganization), which is case-insensitive and trims too.
|
|
109
119
|
export function organizationNameKey(name: string): string {
|
|
110
120
|
return name.trim().toLowerCase();
|
|
@@ -118,6 +128,33 @@ export function organizationNames(rows: DatastoreRow[]): string[] {
|
|
|
118
128
|
return [...new Set(rows.filter((row) => row.isOrganization).map((row) => row.organizationName))].sort();
|
|
119
129
|
}
|
|
120
130
|
|
|
131
|
+
export function removedSubtreeRowIds(rows: DatastoreRow[]): Set<string> {
|
|
132
|
+
const ids = new Set<string>();
|
|
133
|
+
let removedDepth: number | undefined;
|
|
134
|
+
for (const row of rows) {
|
|
135
|
+
if (removedDepth === undefined || row.depth <= removedDepth) removedDepth = row.removed ? row.depth : undefined;
|
|
136
|
+
if (removedDepth !== undefined) ids.add(row.id);
|
|
137
|
+
}
|
|
138
|
+
return ids;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function outsideRemovedSubtrees(rows: DatastoreRow[]): DatastoreRow[] {
|
|
142
|
+
const removed = removedSubtreeRowIds(rows);
|
|
143
|
+
return rows.filter((row) => !removed.has(row.id));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function organizationGroupPaths(rows: DatastoreRow[]): Map<string, string[]> {
|
|
147
|
+
const paths = new Map<string, string[]>();
|
|
148
|
+
for (const row of outsideRemovedSubtrees(rows)) {
|
|
149
|
+
if (row.isOrganization || row.isRealmDefault === true || row.isUnlinked === true) continue;
|
|
150
|
+
|
|
151
|
+
const organizationPaths = paths.get(row.organizationName);
|
|
152
|
+
if (organizationPaths) organizationPaths.push(row.path);
|
|
153
|
+
else paths.set(row.organizationName, [row.path]);
|
|
154
|
+
}
|
|
155
|
+
return paths;
|
|
156
|
+
}
|
|
157
|
+
|
|
121
158
|
export function visibilityForStatusFilter(
|
|
122
159
|
visibility: DatastoreRowVisibility,
|
|
123
160
|
status: DatastoreStatusFilterValue | "ALL",
|
|
@@ -125,11 +162,21 @@ export function visibilityForStatusFilter(
|
|
|
125
162
|
return match(status)
|
|
126
163
|
.with("removed", () => ({ ...visibility, showArchived: true }))
|
|
127
164
|
.with("noDatastore", () => ({ ...visibility, showUnprovisioned: true }))
|
|
128
|
-
.with(
|
|
165
|
+
.with(
|
|
166
|
+
"ALL",
|
|
167
|
+
"ready",
|
|
168
|
+
"materializing",
|
|
169
|
+
"notRegistered",
|
|
170
|
+
"notBuilt",
|
|
171
|
+
"offline",
|
|
172
|
+
"unavailable",
|
|
173
|
+
"checking",
|
|
174
|
+
() => visibility,
|
|
175
|
+
)
|
|
129
176
|
.exhaustive();
|
|
130
177
|
}
|
|
131
178
|
|
|
132
|
-
export function unlinkedDatastoreRow(datastoreId: string): DatastoreRow {
|
|
179
|
+
export function unlinkedDatastoreRow(datastoreId: string, built = true): DatastoreRow {
|
|
133
180
|
return {
|
|
134
181
|
id: `unlinked:${datastoreId}`,
|
|
135
182
|
name: datastoreId,
|
|
@@ -142,6 +189,7 @@ export function unlinkedDatastoreRow(datastoreId: string): DatastoreRow {
|
|
|
142
189
|
removed: false,
|
|
143
190
|
isOrganization: false,
|
|
144
191
|
isUnlinked: true,
|
|
192
|
+
unbuilt: !built,
|
|
145
193
|
};
|
|
146
194
|
}
|
|
147
195
|
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
Blocks,
|
|
7
7
|
Check,
|
|
8
8
|
DatabaseZap,
|
|
9
|
+
Hammer,
|
|
9
10
|
Link2,
|
|
10
11
|
MoreHorizontal,
|
|
11
12
|
Pencil,
|
|
@@ -113,6 +114,8 @@ type UseDatastoreColumnsArgs = {
|
|
|
113
114
|
onDelete: (row: DatastoreRow) => void;
|
|
114
115
|
onRename: (row: DatastoreRow) => void;
|
|
115
116
|
onRegister: (row: DatastoreRow) => void;
|
|
117
|
+
registeringDatastoreIds: ReadonlySet<string>;
|
|
118
|
+
removedSubtreeRowIds: ReadonlySet<string>;
|
|
116
119
|
onManageUsers: (row: DatastoreRow) => void;
|
|
117
120
|
onManageCustomApps: (row: DatastoreRow) => void;
|
|
118
121
|
onBringOnline: (row: DatastoreRow) => void;
|
|
@@ -141,6 +144,8 @@ export function useDatastoreColumns(args: UseDatastoreColumnsArgs): ColumnDef<Da
|
|
|
141
144
|
onDelete,
|
|
142
145
|
onRename,
|
|
143
146
|
onRegister,
|
|
147
|
+
registeringDatastoreIds,
|
|
148
|
+
removedSubtreeRowIds,
|
|
144
149
|
onManageUsers,
|
|
145
150
|
onManageCustomApps,
|
|
146
151
|
onBringOnline,
|
|
@@ -311,6 +316,8 @@ export function useDatastoreColumns(args: UseDatastoreColumnsArgs): ColumnDef<Da
|
|
|
311
316
|
const status = hasDatastore ? statusByDatastoreId[datastoreId] : undefined;
|
|
312
317
|
const category = datastoreStatusCategory(datastoreRow, status);
|
|
313
318
|
const notRegistered = category === "notRegistered";
|
|
319
|
+
const buildable = category === "materializing";
|
|
320
|
+
const registering = hasDatastore && registeringDatastoreIds.has(datastoreId);
|
|
314
321
|
const reason = match({ notRegistered, materializing: isMaterializing(status) && !isRealmDefault })
|
|
315
322
|
.with({ notRegistered: true }, () => "Not registered - use Register to fix, then try selecting again.")
|
|
316
323
|
.with({ materializing: true }, () => "Still materializing - this can take a few minutes.")
|
|
@@ -359,12 +366,13 @@ export function useDatastoreColumns(args: UseDatastoreColumnsArgs): ColumnDef<Da
|
|
|
359
366
|
Bring online
|
|
360
367
|
</Button>
|
|
361
368
|
)}
|
|
362
|
-
{!isUnlinked && hasDatastore && !
|
|
369
|
+
{!isUnlinked && hasDatastore && !removedSubtreeRowIds.has(datastoreRow.id) && notRegistered && (
|
|
363
370
|
<Button
|
|
364
371
|
data-testid={`datastore-register-${datastoreRow.id}`}
|
|
365
372
|
size="sm"
|
|
366
373
|
variant="secondary"
|
|
367
374
|
icon={RefreshCw}
|
|
375
|
+
disabled={registering}
|
|
368
376
|
onClick={() => onRegister(datastoreRow)}
|
|
369
377
|
>
|
|
370
378
|
Register
|
|
@@ -439,6 +447,16 @@ export function useDatastoreColumns(args: UseDatastoreColumnsArgs): ColumnDef<Da
|
|
|
439
447
|
Provision datastore
|
|
440
448
|
</DropdownItem>
|
|
441
449
|
))}
|
|
450
|
+
{hasDatastore && !removedSubtreeRowIds.has(datastoreRow.id) && buildable && (
|
|
451
|
+
<DropdownItem
|
|
452
|
+
icon={<Hammer className="size-4" />}
|
|
453
|
+
disabled={registering}
|
|
454
|
+
title="Starts a build, or joins the one already running"
|
|
455
|
+
onSelect={() => onRegister(datastoreRow)}
|
|
456
|
+
>
|
|
457
|
+
Build datastore now
|
|
458
|
+
</DropdownItem>
|
|
459
|
+
)}
|
|
442
460
|
<DropdownItem icon={<Plus className="size-4" />} onSelect={() => onAddChild(datastoreRow)}>
|
|
443
461
|
Add datastore
|
|
444
462
|
</DropdownItem>
|
|
@@ -505,6 +523,8 @@ export function useDatastoreColumns(args: UseDatastoreColumnsArgs): ColumnDef<Da
|
|
|
505
523
|
onRestore,
|
|
506
524
|
onDelete,
|
|
507
525
|
onRegister,
|
|
526
|
+
registeringDatastoreIds,
|
|
527
|
+
removedSubtreeRowIds,
|
|
508
528
|
onRename,
|
|
509
529
|
onManageUsers,
|
|
510
530
|
onManageCustomApps,
|