@dxos/plugin-magazine 0.9.1-staging.ee54ba693a → 0.11.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/lib/MagazinePlugin.mjs +36 -0
- package/dist/lib/MagazinePlugin.mjs.map +1 -0
- package/dist/lib/MagazinePlugin.workerd.mjs +26 -0
- package/dist/lib/MagazinePlugin.workerd.mjs.map +1 -0
- package/dist/lib/atoms.mjs +175 -0
- package/dist/lib/atoms.mjs.map +1 -0
- package/dist/lib/capabilities.mjs +12 -0
- package/dist/lib/capabilities.mjs.map +1 -0
- package/dist/lib/chunk-FeedArticle.mjs +70 -0
- package/dist/lib/chunk-FeedArticle.mjs.map +1 -0
- package/dist/lib/chunk-FeedProperties.mjs +78 -0
- package/dist/lib/chunk-FeedProperties.mjs.map +1 -0
- package/dist/lib/chunk-MagazineArticle.mjs +267 -0
- package/dist/lib/chunk-MagazineArticle.mjs.map +1 -0
- package/dist/lib/chunk-PostArticle.mjs +174 -0
- package/dist/lib/chunk-PostArticle.mjs.map +1 -0
- package/dist/lib/chunk-PostCard.mjs +62 -0
- package/dist/lib/chunk-PostCard.mjs.map +1 -0
- package/dist/lib/chunk-app-graph-builder.mjs +91 -0
- package/dist/lib/chunk-app-graph-builder.mjs.map +1 -0
- package/dist/lib/chunk-clear-magazine.mjs +37 -0
- package/dist/lib/chunk-clear-magazine.mjs.map +1 -0
- package/dist/lib/chunk-create-object.mjs +59 -0
- package/dist/lib/chunk-create-object.mjs.map +1 -0
- package/dist/lib/chunk-curate-magazine.mjs +164 -0
- package/dist/lib/chunk-curate-magazine.mjs.map +1 -0
- package/dist/lib/chunk-date.mjs +25 -0
- package/dist/lib/chunk-date.mjs.map +1 -0
- package/dist/lib/chunk-fetch-article-content.mjs +26 -0
- package/dist/lib/chunk-fetch-article-content.mjs.map +1 -0
- package/dist/lib/chunk-load-post-content.mjs +57 -0
- package/dist/lib/chunk-load-post-content.mjs.map +1 -0
- package/dist/lib/{neutral/chunk-JFPR6OV4.mjs → chunk-meta.mjs} +19 -26
- package/dist/lib/chunk-meta.mjs.map +1 -0
- package/dist/lib/chunk-operation-handler.mjs +13 -0
- package/dist/lib/chunk-operation-handler.mjs.map +1 -0
- package/dist/lib/chunk-paths.mjs +8 -0
- package/dist/lib/chunk-paths.mjs.map +1 -0
- package/dist/lib/chunk-post-content.mjs +14 -0
- package/dist/lib/chunk-post-content.mjs.map +1 -0
- package/dist/lib/chunk-react-surface.mjs +60 -0
- package/dist/lib/chunk-react-surface.mjs.map +1 -0
- package/dist/lib/chunk-routine-templates.mjs +52 -0
- package/dist/lib/chunk-routine-templates.mjs.map +1 -0
- package/dist/lib/chunk-skill-definition.mjs +12 -0
- package/dist/lib/chunk-skill-definition.mjs.map +1 -0
- package/dist/lib/chunk-sources.mjs +576 -0
- package/dist/lib/chunk-sources.mjs.map +1 -0
- package/dist/lib/chunk-sync-feed.mjs +86 -0
- package/dist/lib/chunk-sync-feed.mjs.map +1 -0
- package/dist/lib/chunk-text.mjs +52 -0
- package/dist/lib/chunk-text.mjs.map +1 -0
- package/dist/lib/chunk-types.mjs +607 -0
- package/dist/lib/chunk-types.mjs.map +1 -0
- package/dist/lib/components.mjs +323 -0
- package/dist/lib/components.mjs.map +1 -0
- package/dist/lib/containers.mjs +11 -0
- package/dist/lib/containers.mjs.map +1 -0
- package/dist/lib/index.mjs +3 -0
- package/dist/lib/meta.mjs +2 -0
- package/dist/lib/operations.mjs +7 -0
- package/dist/lib/operations.mjs.map +1 -0
- package/dist/lib/plugin.mjs +9 -0
- package/dist/lib/plugin.mjs.map +1 -0
- package/dist/lib/plugin.workerd.mjs +3 -0
- package/dist/lib/{neutral/skills/index.mjs → skills.mjs} +15 -28
- package/dist/lib/skills.mjs.map +1 -0
- package/dist/lib/testing.mjs +71 -0
- package/dist/lib/testing.mjs.map +1 -0
- package/dist/lib/translations.mjs +74 -0
- package/dist/lib/translations.mjs.map +1 -0
- package/dist/lib/types.mjs +2 -0
- package/dist/types/src/MagazinePlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
- package/dist/types/src/capabilities/create-object.d.ts +1 -1
- package/dist/types/src/capabilities/index.d.ts +0 -1
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/routine-templates.d.ts +1 -1
- package/dist/types/src/components/PostContent/PostContent.d.ts +1 -13
- package/dist/types/src/components/PostContent/PostContent.d.ts.map +1 -1
- package/dist/types/src/components/PostContent/dedupe-images.d.ts +13 -0
- package/dist/types/src/components/PostContent/dedupe-images.d.ts.map +1 -0
- package/dist/types/src/components/PostContent/index.d.ts +1 -0
- package/dist/types/src/components/PostContent/index.d.ts.map +1 -1
- package/dist/types/src/components/PostStack/PostStack.d.ts +1 -1
- package/dist/types/src/components/PostStack/PostStack.d.ts.map +1 -1
- package/dist/types/src/components/SubscriptionStack/SubscriptionStack.d.ts +1 -1
- package/dist/types/src/components/SubscriptionStack/SubscriptionStack.d.ts.map +1 -1
- package/dist/types/src/containers/FeedArticle/FeedArticle.d.ts +4 -1
- package/dist/types/src/containers/FeedArticle/FeedArticle.d.ts.map +1 -1
- package/dist/types/src/containers/FeedProperties/FeedProperties.d.ts +4 -1
- package/dist/types/src/containers/FeedProperties/FeedProperties.d.ts.map +1 -1
- package/dist/types/src/containers/MagazineArticle/MagazineArticle.d.ts +4 -1
- package/dist/types/src/containers/MagazineArticle/MagazineArticle.d.ts.map +1 -1
- package/dist/types/src/containers/MagazineArticle/MagazineArticle.stories.d.ts.map +1 -1
- package/dist/types/src/containers/MagazineArticle/MagazineTile.d.ts +4 -1
- package/dist/types/src/containers/MagazineArticle/MagazineTile.d.ts.map +1 -1
- package/dist/types/src/containers/MagazineArticle/useToolbar.d.ts +4 -8
- package/dist/types/src/containers/MagazineArticle/useToolbar.d.ts.map +1 -1
- package/dist/types/src/containers/PostArticle/PostArticle.d.ts +4 -1
- package/dist/types/src/containers/PostArticle/PostArticle.d.ts.map +1 -1
- package/dist/types/src/containers/PostArticle/PostArticle.stories.d.ts.map +1 -1
- package/dist/types/src/containers/PostArticle/PostToolbar.d.ts +1 -1
- package/dist/types/src/containers/PostArticle/PostToolbar.d.ts.map +1 -1
- package/dist/types/src/containers/PostCard/PostCard.d.ts +4 -6
- package/dist/types/src/containers/PostCard/PostCard.d.ts.map +1 -1
- package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.d.ts +4 -1
- package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.d.ts.map +1 -1
- package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.stories.d.ts.map +1 -1
- package/dist/types/src/stories/ArticleExtractor.stories.d.ts +1 -0
- package/dist/types/src/stories/ArticleExtractor.stories.d.ts.map +1 -1
- package/dist/types/src/stories/MagazineCurate.stories.d.ts.map +1 -1
- package/dist/types/src/templates/magazine-curation.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +1 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dx.config.ts +1 -1
- package/package.json +57 -60
- package/src/MagazinePlugin.tsx +0 -3
- package/src/atoms/atoms.test.ts +5 -4
- package/src/capabilities/app-graph-builder.ts +8 -6
- package/src/capabilities/index.ts +0 -1
- package/src/capabilities/{react-surface.tsx → react-surface.ts} +10 -12
- package/src/components/PostContent/PostContent.test.ts +1 -1
- package/src/components/PostContent/PostContent.tsx +1 -41
- package/src/components/PostContent/dedupe-images.ts +48 -0
- package/src/components/PostContent/index.ts +1 -0
- package/src/containers/FeedArticle/FeedArticle.stories.tsx +2 -2
- package/src/containers/FeedArticle/FeedArticle.tsx +4 -2
- package/src/containers/FeedProperties/FeedProperties.tsx +6 -4
- package/src/containers/MagazineArticle/MagazineArticle.stories.tsx +2 -1
- package/src/containers/MagazineArticle/MagazineArticle.tsx +8 -6
- package/src/containers/MagazineArticle/MagazineTile.tsx +2 -0
- package/src/containers/MagazineArticle/useToolbar.tsx +2 -0
- package/src/containers/PostArticle/PostArticle.stories.tsx +2 -1
- package/src/containers/PostArticle/PostArticle.tsx +6 -3
- package/src/containers/PostArticle/PostToolbar.tsx +1 -1
- package/src/containers/PostCard/PostCard.tsx +3 -1
- package/src/containers/SubscriptionsArticle/SubscriptionsArticle.stories.tsx +2 -1
- package/src/containers/SubscriptionsArticle/SubscriptionsArticle.tsx +5 -3
- package/src/operations/curate-magazine.test.ts +108 -4
- package/src/operations/sync-feed.test.ts +1 -1
- package/src/operations/sync-feed.ts +1 -1
- package/src/paths.ts +3 -3
- package/src/stories/ArticleExtractor.stories.tsx +1 -1
- package/src/stories/MagazineCurate.stories.tsx +3 -2
- package/src/templates/magazine-curation.ts +3 -2
- package/src/types/Magazine.test.ts +1 -1
- package/src/types/Subscription.ts +1 -1
- package/dist/lib/neutral/FeedArticle-PEWCFFSP.mjs +0 -90
- package/dist/lib/neutral/FeedArticle-PEWCFFSP.mjs.map +0 -7
- package/dist/lib/neutral/FeedProperties-EIO7IZOA.mjs +0 -97
- package/dist/lib/neutral/FeedProperties-EIO7IZOA.mjs.map +0 -7
- package/dist/lib/neutral/MagazineArticle-5T7RTIPS.mjs +0 -325
- package/dist/lib/neutral/MagazineArticle-5T7RTIPS.mjs.map +0 -7
- package/dist/lib/neutral/MagazinePlugin.mjs +0 -62
- package/dist/lib/neutral/MagazinePlugin.mjs.map +0 -7
- package/dist/lib/neutral/MagazinePlugin.workerd.mjs +0 -12
- package/dist/lib/neutral/MagazinePlugin.workerd.mjs.map +0 -7
- package/dist/lib/neutral/PostArticle-BGIPU7XA.mjs +0 -230
- package/dist/lib/neutral/PostArticle-BGIPU7XA.mjs.map +0 -7
- package/dist/lib/neutral/PostCard-VDGN7BBA.mjs +0 -60
- package/dist/lib/neutral/PostCard-VDGN7BBA.mjs.map +0 -7
- package/dist/lib/neutral/app-graph-builder-JDPRBVHL.mjs +0 -121
- package/dist/lib/neutral/app-graph-builder-JDPRBVHL.mjs.map +0 -7
- package/dist/lib/neutral/capabilities/index.mjs +0 -21
- package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
- package/dist/lib/neutral/chunk-3K4AQKBZ.mjs +0 -12
- package/dist/lib/neutral/chunk-3K4AQKBZ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-AFPBWBTK.mjs +0 -591
- package/dist/lib/neutral/chunk-AFPBWBTK.mjs.map +0 -7
- package/dist/lib/neutral/chunk-APQRTYT3.mjs +0 -57
- package/dist/lib/neutral/chunk-APQRTYT3.mjs.map +0 -7
- package/dist/lib/neutral/chunk-GU725ZF4.mjs +0 -11
- package/dist/lib/neutral/chunk-GU725ZF4.mjs.map +0 -7
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
- package/dist/lib/neutral/chunk-JFPR6OV4.mjs.map +0 -7
- package/dist/lib/neutral/chunk-KTYLUOUG.mjs +0 -36
- package/dist/lib/neutral/chunk-KTYLUOUG.mjs.map +0 -7
- package/dist/lib/neutral/chunk-LFSQMLPK.mjs +0 -8
- package/dist/lib/neutral/chunk-LFSQMLPK.mjs.map +0 -7
- package/dist/lib/neutral/chunk-MBPX7RPI.mjs +0 -14
- package/dist/lib/neutral/chunk-MBPX7RPI.mjs.map +0 -7
- package/dist/lib/neutral/chunk-OYCDRSWB.mjs +0 -624
- package/dist/lib/neutral/chunk-OYCDRSWB.mjs.map +0 -7
- package/dist/lib/neutral/chunk-SAWKLGJU.mjs +0 -28
- package/dist/lib/neutral/chunk-SAWKLGJU.mjs.map +0 -7
- package/dist/lib/neutral/chunk-XCNCK47N.mjs +0 -15
- package/dist/lib/neutral/chunk-XCNCK47N.mjs.map +0 -7
- package/dist/lib/neutral/clear-magazine-KNY4OWY4.mjs +0 -59
- package/dist/lib/neutral/clear-magazine-KNY4OWY4.mjs.map +0 -7
- package/dist/lib/neutral/components/index.mjs +0 -338
- package/dist/lib/neutral/components/index.mjs.map +0 -7
- package/dist/lib/neutral/containers/index.mjs +0 -17
- package/dist/lib/neutral/containers/index.mjs.map +0 -7
- package/dist/lib/neutral/create-object-SYZMRR4H.mjs +0 -98
- package/dist/lib/neutral/create-object-SYZMRR4H.mjs.map +0 -7
- package/dist/lib/neutral/curate-magazine-7RMKSJC5.mjs +0 -184
- package/dist/lib/neutral/curate-magazine-7RMKSJC5.mjs.map +0 -7
- package/dist/lib/neutral/fetch-article-content-CXPKXIMR.mjs +0 -31
- package/dist/lib/neutral/fetch-article-content-CXPKXIMR.mjs.map +0 -7
- package/dist/lib/neutral/index.mjs +0 -18
- package/dist/lib/neutral/index.mjs.map +0 -7
- package/dist/lib/neutral/load-post-content-H3S4TKVM.mjs +0 -65
- package/dist/lib/neutral/load-post-content-H3S4TKVM.mjs.map +0 -7
- package/dist/lib/neutral/meta.json +0 -1
- package/dist/lib/neutral/meta.mjs +0 -8
- package/dist/lib/neutral/meta.mjs.map +0 -7
- package/dist/lib/neutral/navigation-resolver-IN4OMCDR.mjs +0 -18
- package/dist/lib/neutral/navigation-resolver-IN4OMCDR.mjs.map +0 -7
- package/dist/lib/neutral/operation-handler-JE3743BU.mjs +0 -8
- package/dist/lib/neutral/operation-handler-JE3743BU.mjs.map +0 -7
- package/dist/lib/neutral/operations/index.mjs +0 -8
- package/dist/lib/neutral/operations/index.mjs.map +0 -7
- package/dist/lib/neutral/plugin.mjs +0 -16
- package/dist/lib/neutral/plugin.mjs.map +0 -7
- package/dist/lib/neutral/plugin.workerd.mjs +0 -16
- package/dist/lib/neutral/plugin.workerd.mjs.map +0 -7
- package/dist/lib/neutral/react-surface-TZESAMG2.mjs +0 -60
- package/dist/lib/neutral/react-surface-TZESAMG2.mjs.map +0 -7
- package/dist/lib/neutral/routine-templates-D5A2L4KL.mjs +0 -52
- package/dist/lib/neutral/routine-templates-D5A2L4KL.mjs.map +0 -7
- package/dist/lib/neutral/skill-definition-3KLMUEC5.mjs +0 -8
- package/dist/lib/neutral/skill-definition-3KLMUEC5.mjs.map +0 -7
- package/dist/lib/neutral/skills/index.mjs.map +0 -7
- package/dist/lib/neutral/sync-feed-SDXYF7HU.mjs +0 -99
- package/dist/lib/neutral/sync-feed-SDXYF7HU.mjs.map +0 -7
- package/dist/lib/neutral/translations.mjs +0 -81
- package/dist/lib/neutral/translations.mjs.map +0 -7
- package/dist/lib/neutral/types/index.mjs +0 -14
- package/dist/lib/neutral/types/index.mjs.map +0 -7
- package/dist/types/src/capabilities/navigation-resolver.d.ts +0 -5
- package/dist/types/src/capabilities/navigation-resolver.d.ts.map +0 -1
- package/dist/types/src/operations/curate-magazine.skill.test.d.ts +0 -2
- package/dist/types/src/operations/curate-magazine.skill.test.d.ts.map +0 -1
- package/src/capabilities/navigation-resolver.ts +0 -21
- package/src/operations/curate-magazine.skill.conversations.json +0 -1
- package/src/operations/curate-magazine.skill.test.ts +0 -167
|
@@ -10,10 +10,11 @@ import { withPluginManager } from '@dxos/app-framework/testing';
|
|
|
10
10
|
import { type Client } from '@dxos/client';
|
|
11
11
|
import { type Space } from '@dxos/client/echo';
|
|
12
12
|
import { Filter, Tag } from '@dxos/echo';
|
|
13
|
+
import { useQuery } from '@dxos/echo-react';
|
|
13
14
|
import { ClientPlugin, initializeIdentity } from '@dxos/plugin-client/testing';
|
|
14
15
|
import { SpacePlugin } from '@dxos/plugin-space/testing';
|
|
15
16
|
import { StorybookPlugin, corePlugins } from '@dxos/plugin-testing';
|
|
16
|
-
import {
|
|
17
|
+
import { useSpaces } from '@dxos/react-client/echo';
|
|
17
18
|
import { Loading, withLayout } from '@dxos/react-ui/testing';
|
|
18
19
|
import { Text } from '@dxos/schema';
|
|
19
20
|
|
|
@@ -8,10 +8,10 @@ import React, { useCallback, useContext, useEffect, useMemo, useRef } from 'reac
|
|
|
8
8
|
import { useOperationInvoker } from '@dxos/app-framework/ui';
|
|
9
9
|
import { type AppSurface } from '@dxos/app-toolkit/ui';
|
|
10
10
|
import { Filter, Obj, Ref } from '@dxos/echo';
|
|
11
|
+
import { useObject, useQuery } from '@dxos/echo-react';
|
|
11
12
|
import { log } from '@dxos/log';
|
|
12
|
-
import { useObject, useQuery } from '@dxos/react-client/echo';
|
|
13
13
|
import { Panel } from '@dxos/react-ui';
|
|
14
|
-
import {
|
|
14
|
+
import { Attention } from '@dxos/react-ui-attention';
|
|
15
15
|
|
|
16
16
|
import { usePostContentAtom } from '#atoms';
|
|
17
17
|
import { PostContent } from '#components';
|
|
@@ -26,7 +26,8 @@ export type PostArticleProps = AppSurface.ObjectArticleProps<Subscription.Post>;
|
|
|
26
26
|
export const PostArticle = ({ role, subject, attendableId }: PostArticleProps) => {
|
|
27
27
|
// When shown as a companion the `attendableId` is a linked segment, but attention lives on the
|
|
28
28
|
// parent plank — resolve to the parent so the toolbar reads as attended (active).
|
|
29
|
-
const toolbarAttendableId =
|
|
29
|
+
const toolbarAttendableId =
|
|
30
|
+
attendableId && Attention.isLinkedSegment(attendableId) ? Attention.getParentId(attendableId) : attendableId;
|
|
30
31
|
const { invokePromise } = useOperationInvoker();
|
|
31
32
|
const registry = useContext(RegistryContext);
|
|
32
33
|
const [post] = useObject(subject);
|
|
@@ -138,3 +139,5 @@ export const PostArticle = ({ role, subject, attendableId }: PostArticleProps) =
|
|
|
138
139
|
</Panel.Root>
|
|
139
140
|
);
|
|
140
141
|
};
|
|
142
|
+
|
|
143
|
+
PostArticle.displayName = 'PostArticle';
|
|
@@ -6,7 +6,7 @@ import React, { useMemo } from 'react';
|
|
|
6
6
|
|
|
7
7
|
import { type AppSurface } from '@dxos/app-toolkit/ui';
|
|
8
8
|
import { Filter, Obj } from '@dxos/echo';
|
|
9
|
-
import { useObject, useQuery } from '@dxos/react
|
|
9
|
+
import { useObject, useQuery } from '@dxos/echo-react';
|
|
10
10
|
import { Card } from '@dxos/react-ui';
|
|
11
11
|
|
|
12
12
|
import { Subscription } from '#types';
|
|
@@ -68,3 +68,5 @@ export const PostCard = ({ subject }: PostCardProps) => {
|
|
|
68
68
|
</Card.Body>
|
|
69
69
|
);
|
|
70
70
|
};
|
|
71
|
+
|
|
72
|
+
PostCard.displayName = 'PostCard';
|
|
@@ -10,12 +10,13 @@ import { withPluginManager } from '@dxos/app-framework/testing';
|
|
|
10
10
|
import { type Client } from '@dxos/client';
|
|
11
11
|
import { type Space } from '@dxos/client/echo';
|
|
12
12
|
import { Filter } from '@dxos/echo';
|
|
13
|
+
import { useQuery } from '@dxos/echo-react';
|
|
13
14
|
import { ClientPlugin } from '@dxos/plugin-client/testing';
|
|
14
15
|
import { initializeIdentity } from '@dxos/plugin-client/testing';
|
|
15
16
|
import { SpacePlugin } from '@dxos/plugin-space/testing';
|
|
16
17
|
import { StorybookPlugin, corePlugins } from '@dxos/plugin-testing';
|
|
17
18
|
import { random } from '@dxos/random';
|
|
18
|
-
import {
|
|
19
|
+
import { useSpaces } from '@dxos/react-client/echo';
|
|
19
20
|
import { Loading, withLayout } from '@dxos/react-ui/testing';
|
|
20
21
|
|
|
21
22
|
import { translations } from '#translations';
|
|
@@ -8,11 +8,11 @@ import { useOperationInvoker } from '@dxos/app-framework/ui';
|
|
|
8
8
|
import { LayoutOperation } from '@dxos/app-toolkit';
|
|
9
9
|
import { type AppSurface, useLayout } from '@dxos/app-toolkit/ui';
|
|
10
10
|
import { Filter, Obj, Ref, Type } from '@dxos/echo';
|
|
11
|
+
import { useQuery } from '@dxos/echo-react';
|
|
11
12
|
import { invariant } from '@dxos/invariant';
|
|
12
13
|
import { SpaceOperation } from '@dxos/plugin-space';
|
|
13
|
-
import { useQuery } from '@dxos/react-client/echo';
|
|
14
14
|
import { Panel, Toolbar, useTranslation } from '@dxos/react-ui';
|
|
15
|
-
import {
|
|
15
|
+
import { Attention, useSelection } from '@dxos/react-ui-attention';
|
|
16
16
|
|
|
17
17
|
import { SubscriptionStack, type SubscriptionStackAction } from '#components';
|
|
18
18
|
import { meta } from '#meta';
|
|
@@ -39,7 +39,7 @@ export const SubscriptionsArticle = ({ role, space, attendableId }: Subscription
|
|
|
39
39
|
subject: { mode: 'single', id: action.feedId },
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
-
const companion = linkedSegment('feed');
|
|
42
|
+
const companion = Attention.linkedSegment('feed');
|
|
43
43
|
if (layout.mode === 'simple') {
|
|
44
44
|
void invokePromise(LayoutOperation.UpdateComplementary, {
|
|
45
45
|
subject: companion,
|
|
@@ -97,3 +97,5 @@ export const SubscriptionsArticle = ({ role, space, attendableId }: Subscription
|
|
|
97
97
|
</Panel.Root>
|
|
98
98
|
);
|
|
99
99
|
};
|
|
100
|
+
|
|
101
|
+
SubscriptionsArticle.displayName = 'SubscriptionsArticle';
|
|
@@ -2,14 +2,70 @@
|
|
|
2
2
|
// Copyright 2026 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import {
|
|
5
|
+
import { describe, it } from '@effect/vitest';
|
|
6
|
+
import * as Effect from 'effect/Effect';
|
|
7
|
+
import { afterEach, beforeEach, expect, test } from 'vitest';
|
|
8
|
+
|
|
9
|
+
import { AssistantTestLayer } from '@dxos/agent-runtime/testing';
|
|
10
|
+
import { ScriptedLanguageModel } from '@dxos/ai/testing';
|
|
11
|
+
import { AgentHandlers } from '@dxos/assistant-toolkit';
|
|
12
|
+
import { Operation } from '@dxos/compute';
|
|
13
|
+
import { Database, Feed, Obj, Ref, Tag } from '@dxos/echo';
|
|
8
14
|
import { EchoTestBuilder } from '@dxos/echo-client/testing';
|
|
15
|
+
import { TestHelpers } from '@dxos/effect/testing';
|
|
9
16
|
import { StateMap, TagIndex, Text } from '@dxos/schema';
|
|
10
17
|
|
|
11
|
-
import {
|
|
18
|
+
import { MagazineSkill } from '../skills';
|
|
19
|
+
import { FeedOperation, Magazine, Subscription } from '../types';
|
|
12
20
|
import { applyKeep, resolveSelected } from './curate-magazine';
|
|
21
|
+
import { MagazineOperationHandlerSet } from './index';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Whether the model picks the right articles is a judgement question, graded out-of-band; scripting
|
|
25
|
+
* its selection keeps this on the operation's own behaviour — that the chosen ids are resolved,
|
|
26
|
+
* recorded on the magazine, and counted.
|
|
27
|
+
*
|
|
28
|
+
* The script is per-test state, but the layer captures the turns array once at module load and the
|
|
29
|
+
* model indexes it lazily per call. Holding it in a closure gives the layer a stable reference while
|
|
30
|
+
* `reset` clears the script between tests, so no turn leaks from one test into the next.
|
|
31
|
+
*/
|
|
32
|
+
const createScriptedSelection = () => {
|
|
33
|
+
const turns: ScriptedLanguageModel.ScriptedTurn[] = [];
|
|
34
|
+
return {
|
|
35
|
+
aiService: ScriptedLanguageModel.scriptedAiService(turns),
|
|
36
|
+
|
|
37
|
+
/** Scripts the agent to select `ids` and then finish. Call once the posts exist. */
|
|
38
|
+
select: (ids: readonly string[]) => {
|
|
39
|
+
turns.push(
|
|
40
|
+
{ parts: [ScriptedLanguageModel.toolCall('completeJob', { success: { posts: ids.map((id) => ({ id })) } })] },
|
|
41
|
+
// The loop asks again once the tool result is fed back; a text-only turn stops it.
|
|
42
|
+
{ parts: [ScriptedLanguageModel.text('Done.')] },
|
|
43
|
+
);
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
reset: () => {
|
|
47
|
+
turns.length = 0;
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const scripted = createScriptedSelection();
|
|
53
|
+
|
|
54
|
+
const TestLayer = AssistantTestLayer({
|
|
55
|
+
operationHandlers: [MagazineOperationHandlerSet, AgentHandlers],
|
|
56
|
+
types: [
|
|
57
|
+
Feed.Feed,
|
|
58
|
+
Subscription.Subscription,
|
|
59
|
+
Subscription.Post,
|
|
60
|
+
Magazine.Magazine,
|
|
61
|
+
Tag.Tag,
|
|
62
|
+
Text.Text,
|
|
63
|
+
StateMap.StateMap,
|
|
64
|
+
TagIndex.TagIndex,
|
|
65
|
+
],
|
|
66
|
+
skills: [MagazineSkill.make()],
|
|
67
|
+
aiService: scripted.aiService,
|
|
68
|
+
});
|
|
13
69
|
|
|
14
70
|
describe('applyKeep', () => {
|
|
15
71
|
let builder: EchoTestBuilder;
|
|
@@ -89,3 +145,51 @@ describe('resolveSelected', () => {
|
|
|
89
145
|
expect(selected.map(({ post }) => post.id)).toEqual([posts[2].id, posts[0].id]);
|
|
90
146
|
});
|
|
91
147
|
});
|
|
148
|
+
|
|
149
|
+
describe('CurateMagazine', () => {
|
|
150
|
+
beforeEach(() => scripted.reset());
|
|
151
|
+
afterEach(() => scripted.reset());
|
|
152
|
+
|
|
153
|
+
it.effect(
|
|
154
|
+
'records the selected posts on the magazine and counts them',
|
|
155
|
+
Effect.fnUntraced(
|
|
156
|
+
function* (_) {
|
|
157
|
+
const subscription = yield* Database.add(
|
|
158
|
+
Subscription.makeSubscription({ name: 'Tech & Science Daily', type: 'rss' }),
|
|
159
|
+
);
|
|
160
|
+
yield* Database.flush();
|
|
161
|
+
|
|
162
|
+
const postFeed = yield* Database.load(subscription.feed);
|
|
163
|
+
const posts = ['Mars lander touches down', 'Webb images a nebula', 'Quarterly earnings'].map((title) =>
|
|
164
|
+
Obj.make(Subscription.Post, {
|
|
165
|
+
title,
|
|
166
|
+
link: `https://example.com/${title}`,
|
|
167
|
+
published: '2026-05-01T00:00:00Z',
|
|
168
|
+
source: Ref.make(subscription),
|
|
169
|
+
}),
|
|
170
|
+
);
|
|
171
|
+
yield* Feed.append(postFeed, posts);
|
|
172
|
+
yield* Database.flush();
|
|
173
|
+
|
|
174
|
+
// `Magazine.make` composes the Instructions (with the CurationOutput contract) from the topic.
|
|
175
|
+
const magazine = yield* Database.add(
|
|
176
|
+
Magazine.make({
|
|
177
|
+
name: 'The Cosmos',
|
|
178
|
+
feeds: [Ref.make(subscription)],
|
|
179
|
+
instructions: 'Curate articles about space exploration and astronomy.',
|
|
180
|
+
}),
|
|
181
|
+
);
|
|
182
|
+
yield* Database.flush();
|
|
183
|
+
|
|
184
|
+
scripted.select([posts[0].id, posts[1].id]);
|
|
185
|
+
const result = yield* Operation.invoke(FeedOperation.CurateMagazine, { magazine: Ref.make(magazine) });
|
|
186
|
+
|
|
187
|
+
const curated = yield* Effect.forEach(magazine.posts, Database.load);
|
|
188
|
+
expect(curated.map((post) => post.title)).toEqual([posts[0].title, posts[1].title]);
|
|
189
|
+
expect(result.curated).toBe(2);
|
|
190
|
+
},
|
|
191
|
+
Effect.provide(TestLayer),
|
|
192
|
+
TestHelpers.provideTestContext,
|
|
193
|
+
),
|
|
194
|
+
);
|
|
195
|
+
});
|
|
@@ -6,10 +6,10 @@ import { describe, it } from '@effect/vitest';
|
|
|
6
6
|
import * as Effect from 'effect/Effect';
|
|
7
7
|
import { afterEach, beforeEach, vi } from 'vitest';
|
|
8
8
|
|
|
9
|
+
import { AssistantTestLayer } from '@dxos/agent-runtime/testing';
|
|
9
10
|
import { Operation } from '@dxos/compute';
|
|
10
11
|
import { Database, Feed, Filter, Ref, Tag } from '@dxos/echo';
|
|
11
12
|
import { TestHelpers } from '@dxos/effect/testing';
|
|
12
|
-
import { AssistantTestLayer } from '@dxos/functions-runtime/testing';
|
|
13
13
|
import { EntityId } from '@dxos/keys';
|
|
14
14
|
|
|
15
15
|
import { FeedOperation, Subscription } from '../types';
|
|
@@ -33,7 +33,7 @@ const handler: Operation.WithHandler<typeof FeedOperation.SyncFeed> = FeedOperat
|
|
|
33
33
|
invariant(url, 'Feed URL is required.');
|
|
34
34
|
const echoFeed = yield* Database.load(subscriptionFeed.feed);
|
|
35
35
|
invariant(echoFeed, 'Backing ECHO feed not found.');
|
|
36
|
-
invariant(Feed.
|
|
36
|
+
invariant(Feed.getFeedUri(echoFeed), 'Feed not stored in a space.');
|
|
37
37
|
|
|
38
38
|
const fetcher = getFetcher(subscriptionFeed.type);
|
|
39
39
|
const { feed: feedMeta, posts } = yield* fetcher(url, { corsProxy: browserCorsProxy() });
|
package/src/paths.ts
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
// Copyright 2026 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { GraphPath } from '@dxos/app-toolkit';
|
|
6
6
|
|
|
7
7
|
import { Magazine } from '#types';
|
|
8
8
|
|
|
9
|
-
const { getSectionPath: getMagazinesPath, getObjectPath: getMagazinePath } =
|
|
9
|
+
const { getSectionPath: getMagazinesPath, getObjectPath: getMagazinePath } = GraphPath.createTypeSectionPaths(
|
|
10
10
|
Magazine.Magazine,
|
|
11
|
-
{ groupId:
|
|
11
|
+
{ groupId: GraphPath.GroupSegments.content },
|
|
12
12
|
);
|
|
13
13
|
|
|
14
14
|
export { getMagazinePath, getMagazinesPath };
|
|
@@ -20,11 +20,12 @@ import { type Client } from '@dxos/client';
|
|
|
20
20
|
import { type Space } from '@dxos/client/echo';
|
|
21
21
|
import { LayerSpec } from '@dxos/compute';
|
|
22
22
|
import { DXN, Feed, Filter, Ref } from '@dxos/echo';
|
|
23
|
+
import { useQuery } from '@dxos/echo-react';
|
|
23
24
|
import { ClientPlugin, initializeIdentity } from '@dxos/plugin-client/testing';
|
|
24
25
|
import { RoutinePlugin } from '@dxos/plugin-routine/plugin';
|
|
25
26
|
import { SpacePlugin } from '@dxos/plugin-space/testing';
|
|
26
27
|
import { StorybookPlugin, corePlugins } from '@dxos/plugin-testing';
|
|
27
|
-
import {
|
|
28
|
+
import { useSpaces } from '@dxos/react-client/echo';
|
|
28
29
|
import { Panel } from '@dxos/react-ui';
|
|
29
30
|
import { Loading, withLayout } from '@dxos/react-ui/testing';
|
|
30
31
|
import { Text } from '@dxos/schema';
|
|
@@ -106,7 +107,7 @@ const DefaultStory = () => {
|
|
|
106
107
|
|
|
107
108
|
return (
|
|
108
109
|
<Panel.Root classNames='border-is border-separator'>
|
|
109
|
-
<Panel.Content
|
|
110
|
+
<Panel.Content classNames='px-3 grid grid-cols-2 gap-3'>
|
|
110
111
|
{/* Rendered directly: the `article` role is shared with plugin-space's catch-all RecordArticle
|
|
111
112
|
(position:last), so a raw `Surface type={Article}` here is ambiguous and resolves to the
|
|
112
113
|
fallback — the deck disambiguates via the app-graph node, which a story has no equivalent of. */}
|
|
@@ -7,7 +7,8 @@ import * as Effect from 'effect/Effect';
|
|
|
7
7
|
import { Trigger } from '@dxos/compute';
|
|
8
8
|
import { Ref } from '@dxos/echo';
|
|
9
9
|
import { invariant } from '@dxos/invariant';
|
|
10
|
-
import {
|
|
10
|
+
import { makeRoutine } from '@dxos/plugin-routine';
|
|
11
|
+
import { type RoutineCapabilities } from '@dxos/plugin-routine/types';
|
|
11
12
|
|
|
12
13
|
import { FeedOperation, Magazine } from '#types';
|
|
13
14
|
|
|
@@ -33,7 +34,7 @@ export const magazineCuration: RoutineCapabilities.Template = {
|
|
|
33
34
|
const magazine = subject;
|
|
34
35
|
|
|
35
36
|
// Pre-populate the trigger's input so the magazine binding is preserved through the save flow.
|
|
36
|
-
return
|
|
37
|
+
return makeRoutine({
|
|
37
38
|
name: name ?? magazine.name ?? 'Curate Magazine',
|
|
38
39
|
// Bind the CurateMagazine operation directly as the action (an operation action, not instructions-based).
|
|
39
40
|
spec: { kind: 'runnable', runnable: Ref.fromURI(FeedOperation.CurateMagazine.meta.key) },
|
|
@@ -6,9 +6,9 @@ import { describe, it } from '@effect/vitest';
|
|
|
6
6
|
import * as Effect from 'effect/Effect';
|
|
7
7
|
import { test } from 'vitest';
|
|
8
8
|
|
|
9
|
+
import { AssistantTestLayer } from '@dxos/agent-runtime/testing';
|
|
9
10
|
import { Database, Feed, Tag } from '@dxos/echo';
|
|
10
11
|
import { TestHelpers } from '@dxos/effect/testing';
|
|
11
|
-
import { AssistantTestLayer } from '@dxos/functions-runtime/testing';
|
|
12
12
|
import { EntityId } from '@dxos/keys';
|
|
13
13
|
import { StateMap, TagIndex, Text } from '@dxos/schema';
|
|
14
14
|
|
|
@@ -171,7 +171,7 @@ export class Post extends Type.makeObject<Post>(DXN.make('org.dxos.type.subscrip
|
|
|
171
171
|
guid: Schema.String.pipe(Schema.optional),
|
|
172
172
|
}).pipe(
|
|
173
173
|
LabelAnnotation.set(['title']),
|
|
174
|
-
Annotation.IconAnnotation.set({ icon: 'ph--article--regular', hue: '
|
|
174
|
+
Annotation.IconAnnotation.set({ icon: 'ph--article--regular', hue: 'indigo' }),
|
|
175
175
|
),
|
|
176
176
|
) {}
|
|
177
177
|
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import "./chunk-J5LGTIGS.mjs";
|
|
2
|
-
|
|
3
|
-
// src/containers/FeedArticle/FeedArticle.tsx
|
|
4
|
-
import React2, { useCallback, useState } from "react";
|
|
5
|
-
import { useOperationInvoker } from "@dxos/app-framework/ui";
|
|
6
|
-
import { Filter, Obj, Query, Ref, Scope } from "@dxos/echo";
|
|
7
|
-
import { useObject, useQuery } from "@dxos/react-client/echo";
|
|
8
|
-
import { Panel as Panel2 } from "@dxos/react-ui";
|
|
9
|
-
import { PostStack } from "#components";
|
|
10
|
-
import { meta as meta2 } from "#meta";
|
|
11
|
-
import { FeedOperation } from "#types";
|
|
12
|
-
import { Subscription } from "#types";
|
|
13
|
-
|
|
14
|
-
// src/containers/FeedArticle/FeedToolbar.tsx
|
|
15
|
-
import React from "react";
|
|
16
|
-
import { Panel } from "@dxos/react-ui";
|
|
17
|
-
import { Menu, MenuBuilder, useMenuBuilder } from "@dxos/react-ui-menu";
|
|
18
|
-
import { meta } from "#meta";
|
|
19
|
-
var FeedToolbar = ({ attendableId, onSync }) => {
|
|
20
|
-
const menuActions = useMenuBuilder(() => MenuBuilder.make().action("sync", {
|
|
21
|
-
label: [
|
|
22
|
-
"sync-feed.label",
|
|
23
|
-
{
|
|
24
|
-
ns: meta.profile.key
|
|
25
|
-
}
|
|
26
|
-
],
|
|
27
|
-
icon: "ph--arrows-clockwise--regular",
|
|
28
|
-
iconOnly: true
|
|
29
|
-
}, onSync).build(), [
|
|
30
|
-
onSync
|
|
31
|
-
]);
|
|
32
|
-
return /* @__PURE__ */ React.createElement(Menu.Root, {
|
|
33
|
-
...menuActions,
|
|
34
|
-
attendableId
|
|
35
|
-
}, /* @__PURE__ */ React.createElement(Panel.Toolbar, {
|
|
36
|
-
asChild: true
|
|
37
|
-
}, /* @__PURE__ */ React.createElement(Menu.Toolbar, null)));
|
|
38
|
-
};
|
|
39
|
-
FeedToolbar.displayName = "FeedToolbar";
|
|
40
|
-
|
|
41
|
-
// src/containers/FeedArticle/FeedArticle.tsx
|
|
42
|
-
var FeedArticle = ({ role, subject, attendableId }) => {
|
|
43
|
-
const { invokePromise } = useOperationInvoker();
|
|
44
|
-
const [currentPostId, setCurrentPostId] = useState();
|
|
45
|
-
const [subscription] = useObject(subject);
|
|
46
|
-
const [postFeed] = useObject(subscription?.feed);
|
|
47
|
-
const db = Obj.getDatabase(subscription);
|
|
48
|
-
const posts = useQuery(db, postFeed ? Query.select(Filter.type(Subscription.Post)).from(Scope.feed(Obj.getURI(postFeed))) : Query.select(Filter.nothing()));
|
|
49
|
-
const handleAction = useCallback((action) => {
|
|
50
|
-
if (action.type === "current") {
|
|
51
|
-
setCurrentPostId(action.postId);
|
|
52
|
-
}
|
|
53
|
-
}, []);
|
|
54
|
-
const handleSync = useCallback(() => {
|
|
55
|
-
void invokePromise(FeedOperation.SyncFeed, {
|
|
56
|
-
feed: Ref.make(subject)
|
|
57
|
-
}, {
|
|
58
|
-
spaceId: Obj.getDatabase(subject)?.spaceId,
|
|
59
|
-
notify: {
|
|
60
|
-
error: [
|
|
61
|
-
"sync-feed-error.title",
|
|
62
|
-
{
|
|
63
|
-
ns: meta2.profile.key
|
|
64
|
-
}
|
|
65
|
-
]
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
}, [
|
|
69
|
-
subject,
|
|
70
|
-
invokePromise
|
|
71
|
-
]);
|
|
72
|
-
return /* @__PURE__ */ React2.createElement(Panel2.Root, {
|
|
73
|
-
role,
|
|
74
|
-
className: "dx-document"
|
|
75
|
-
}, /* @__PURE__ */ React2.createElement(FeedToolbar, {
|
|
76
|
-
attendableId,
|
|
77
|
-
onSync: handleSync
|
|
78
|
-
}), /* @__PURE__ */ React2.createElement(Panel2.Content, {
|
|
79
|
-
asChild: true
|
|
80
|
-
}, /* @__PURE__ */ React2.createElement(PostStack, {
|
|
81
|
-
id: subscription?.id ?? subject.id,
|
|
82
|
-
posts,
|
|
83
|
-
currentId: currentPostId,
|
|
84
|
-
onAction: handleAction
|
|
85
|
-
})));
|
|
86
|
-
};
|
|
87
|
-
export {
|
|
88
|
-
FeedArticle as default
|
|
89
|
-
};
|
|
90
|
-
//# sourceMappingURL=FeedArticle-PEWCFFSP.mjs.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/containers/FeedArticle/FeedArticle.tsx", "../../../src/containers/FeedArticle/FeedToolbar.tsx"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { useCallback, useState } from 'react';\n\nimport { useOperationInvoker } from '@dxos/app-framework/ui';\nimport { type AppSurface } from '@dxos/app-toolkit/ui';\nimport { Filter, Obj, Query, Ref, Scope } from '@dxos/echo';\nimport { useObject, useQuery } from '@dxos/react-client/echo';\nimport { Panel } from '@dxos/react-ui';\n\nimport { PostStack, type PostStackAction } from '#components';\nimport { meta } from '#meta';\nimport { FeedOperation } from '#types';\nimport { Subscription } from '#types';\n\nimport { FeedToolbar } from './FeedToolbar';\n\nexport type FeedArticleProps = AppSurface.ObjectArticleProps<Subscription.Subscription>;\n\nexport const FeedArticle = ({ role, subject, attendableId }: FeedArticleProps) => {\n const { invokePromise } = useOperationInvoker();\n const [currentPostId, setCurrentPostId] = useState<string>();\n const [subscription] = useObject(subject);\n // Subscribe to the backing queue via its Ref — `.target` alone does not re-render when the\n // feed loads after navigation (same pitfall as plugin-inbox MailboxArticle).\n const [postFeed] = useObject(subscription?.feed);\n const db = Obj.getDatabase(subscription);\n const posts = useQuery(\n db,\n postFeed\n ? Query.select(Filter.type(Subscription.Post)).from(Scope.feed(Obj.getURI(postFeed)))\n : Query.select(Filter.nothing()),\n );\n\n const handleAction = useCallback((action: PostStackAction) => {\n if (action.type === 'current') {\n setCurrentPostId(action.postId);\n }\n }, []);\n\n const handleSync = useCallback(() => {\n // Failures surface as a toast via `notify`; invokePromise resolves with `{ error }`, never throws.\n void invokePromise(\n FeedOperation.SyncFeed,\n { feed: Ref.make(subject) },\n {\n spaceId: Obj.getDatabase(subject)?.spaceId,\n notify: { error: ['sync-feed-error.title', { ns: meta.profile.key }] },\n },\n );\n }, [subject, invokePromise]);\n\n return (\n <Panel.Root role={role} className='dx-document'>\n <FeedToolbar attendableId={attendableId} onSync={handleSync} />\n <Panel.Content asChild>\n <PostStack\n id={subscription?.id ?? subject.id}\n posts={posts}\n currentId={currentPostId}\n onAction={handleAction}\n />\n </Panel.Content>\n </Panel.Root>\n );\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport React from 'react';\n\nimport { Panel } from '@dxos/react-ui';\nimport { Menu, MenuBuilder, useMenuBuilder } from '@dxos/react-ui-menu';\n\nimport { meta } from '#meta';\n\nexport type FeedToolbarProps = {\n attendableId?: string;\n onSync: () => void;\n};\n\n/**\n * Reactive feed toolbar built from the menu action-graph idiom: a single Sync action. Matches the\n * magazine/post toolbars; the feed's name is surfaced by the plank chrome, not duplicated here.\n */\nexport const FeedToolbar = ({ attendableId, onSync }: FeedToolbarProps) => {\n const menuActions = useMenuBuilder(\n () =>\n MenuBuilder.make()\n .action(\n 'sync',\n {\n label: ['sync-feed.label', { ns: meta.profile.key }],\n icon: 'ph--arrows-clockwise--regular',\n iconOnly: true,\n },\n onSync,\n )\n .build(),\n [onSync],\n );\n\n return (\n <Menu.Root {...menuActions} attendableId={attendableId}>\n <Panel.Toolbar asChild>\n <Menu.Toolbar />\n </Panel.Toolbar>\n </Menu.Root>\n );\n};\n\nFeedToolbar.displayName = 'FeedToolbar';\n"],
|
|
5
|
-
"mappings": ";;;AAIA,OAAOA,UAASC,aAAaC,gBAAgB;AAE7C,SAASC,2BAA2B;AAEpC,SAASC,QAAQC,KAAKC,OAAOC,KAAKC,aAAa;AAC/C,SAASC,WAAWC,gBAAgB;AACpC,SAASC,SAAAA,cAAa;AAEtB,SAASC,iBAAuC;AAChD,SAASC,QAAAA,aAAY;AACrB,SAASC,qBAAqB;AAC9B,SAASC,oBAAoB;;;ACX7B,OAAOC,WAAW;AAElB,SAASC,aAAa;AACtB,SAASC,MAAMC,aAAaC,sBAAsB;AAElD,SAASC,YAAY;AAWd,IAAMC,cAAc,CAAC,EAAEC,cAAcC,OAAM,MAAoB;AACpE,QAAMC,cAAcL,eAClB,MACED,YAAYO,KAAI,EACbC,OACC,QACA;IACEC,OAAO;MAAC;MAAmB;QAAEC,IAAIR,KAAKS,QAAQC;MAAI;;IAClDC,MAAM;IACNC,UAAU;EACZ,GACAT,MAAAA,EAEDU,MAAK,GACV;IAACV;GAAO;AAGV,SACE,sBAAA,cAACN,KAAKiB,MAAI;IAAE,GAAGV;IAAaF;KAC1B,sBAAA,cAACN,MAAMmB,SAAO;IAACC,SAAAA;KACb,sBAAA,cAACnB,KAAKkB,SAAO,IAAA,CAAA,CAAA;AAIrB;AAEAd,YAAYgB,cAAc;;;ADzBnB,IAAMC,cAAc,CAAC,EAAEC,MAAMC,SAASC,aAAY,MAAoB;AAC3E,QAAM,EAAEC,cAAa,IAAKC,oBAAAA;AAC1B,QAAM,CAACC,eAAeC,gBAAAA,IAAoBC,SAAAA;AAC1C,QAAM,CAACC,YAAAA,IAAgBC,UAAUR,OAAAA;AAGjC,QAAM,CAACS,QAAAA,IAAYD,UAAUD,cAAcG,IAAAA;AAC3C,QAAMC,KAAKC,IAAIC,YAAYN,YAAAA;AAC3B,QAAMO,QAAQC,SACZJ,IACAF,WACIO,MAAMC,OAAOC,OAAOC,KAAKC,aAAaC,IAAI,CAAA,EAAGC,KAAKC,MAAMb,KAAKE,IAAIY,OAAOf,QAAAA,CAAAA,CAAAA,IACxEO,MAAMC,OAAOC,OAAOO,QAAO,CAAA,CAAA;AAGjC,QAAMC,eAAeC,YAAY,CAACC,WAAAA;AAChC,QAAIA,OAAOT,SAAS,WAAW;AAC7Bd,uBAAiBuB,OAAOC,MAAM;IAChC;EACF,GAAG,CAAA,CAAE;AAEL,QAAMC,aAAaH,YAAY,MAAA;AAE7B,SAAKzB,cACH6B,cAAcC,UACd;MAAEtB,MAAMuB,IAAIC,KAAKlC,OAAAA;IAAS,GAC1B;MACEmC,SAASvB,IAAIC,YAAYb,OAAAA,GAAUmC;MACnCC,QAAQ;QAAEC,OAAO;UAAC;UAAyB;YAAEC,IAAIC,MAAKC,QAAQC;UAAI;;MAAG;IACvE,CAAA;EAEJ,GAAG;IAACzC;IAASE;GAAc;AAE3B,SACE,gBAAAwC,OAAA,cAACC,OAAMC,MAAI;IAAC7C;IAAY8C,WAAU;KAChC,gBAAAH,OAAA,cAACI,aAAAA;IAAY7C;IAA4B8C,QAAQjB;MACjD,gBAAAY,OAAA,cAACC,OAAMK,SAAO;IAACC,SAAAA;KACb,gBAAAP,OAAA,cAACQ,WAAAA;IACCC,IAAI5C,cAAc4C,MAAMnD,QAAQmD;IAChCrC;IACAsC,WAAWhD;IACXiD,UAAU3B;;AAKpB;",
|
|
6
|
-
"names": ["React", "useCallback", "useState", "useOperationInvoker", "Filter", "Obj", "Query", "Ref", "Scope", "useObject", "useQuery", "Panel", "PostStack", "meta", "FeedOperation", "Subscription", "React", "Panel", "Menu", "MenuBuilder", "useMenuBuilder", "meta", "FeedToolbar", "attendableId", "onSync", "menuActions", "make", "action", "label", "ns", "profile", "key", "icon", "iconOnly", "build", "Root", "Toolbar", "asChild", "displayName", "FeedArticle", "role", "subject", "attendableId", "invokePromise", "useOperationInvoker", "currentPostId", "setCurrentPostId", "useState", "subscription", "useObject", "postFeed", "feed", "db", "Obj", "getDatabase", "posts", "useQuery", "Query", "select", "Filter", "type", "Subscription", "Post", "from", "Scope", "getURI", "nothing", "handleAction", "useCallback", "action", "postId", "handleSync", "FeedOperation", "SyncFeed", "Ref", "make", "spaceId", "notify", "error", "ns", "meta", "profile", "key", "React", "Panel", "Root", "className", "FeedToolbar", "onSync", "Content", "asChild", "PostStack", "id", "currentId", "onAction"]
|
|
7
|
-
}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import "./chunk-J5LGTIGS.mjs";
|
|
2
|
-
|
|
3
|
-
// src/containers/FeedProperties/FeedProperties.tsx
|
|
4
|
-
import React, { useCallback, useMemo, useState } from "react";
|
|
5
|
-
import { useOperationInvoker } from "@dxos/app-framework/ui";
|
|
6
|
-
import { LayoutOperation, Paths } from "@dxos/app-toolkit";
|
|
7
|
-
import { Operation, Trigger } from "@dxos/compute";
|
|
8
|
-
import { Filter, Obj, Query, Ref } from "@dxos/echo";
|
|
9
|
-
import { useObject, useQuery } from "@dxos/react-client/echo";
|
|
10
|
-
import { IconButton, Input, useTranslation } from "@dxos/react-ui";
|
|
11
|
-
import { Form } from "@dxos/react-ui-form";
|
|
12
|
-
import { meta } from "#meta";
|
|
13
|
-
import { FeedOperation } from "#types";
|
|
14
|
-
var FeedProperties = ({ subject }) => {
|
|
15
|
-
const { t } = useTranslation(meta.profile.key);
|
|
16
|
-
const { invokePromise } = useOperationInvoker();
|
|
17
|
-
const db = useMemo(() => Obj.getDatabase(subject), [
|
|
18
|
-
subject
|
|
19
|
-
]);
|
|
20
|
-
const [pending, setPending] = useState(false);
|
|
21
|
-
const childTriggers = useQuery(db, Query.select(Filter.and(Filter.type(Trigger.Trigger), Filter.childOf(subject, {
|
|
22
|
-
transitive: false
|
|
23
|
-
}))).debugLabel("plugin-magazine.FeedProperties.syncTrigger"));
|
|
24
|
-
const syncTrigger = useMemo(() => childTriggers.find((trigger) => trigger.spec?.kind === "timer"), [
|
|
25
|
-
childTriggers
|
|
26
|
-
]);
|
|
27
|
-
const [syncEnabled, setSyncEnabled] = useObject(syncTrigger, "enabled");
|
|
28
|
-
const handleToggleSync = useCallback(async () => {
|
|
29
|
-
if (!db) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
if (syncTrigger) {
|
|
33
|
-
setSyncEnabled((enabled) => !enabled);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
setPending(true);
|
|
37
|
-
try {
|
|
38
|
-
const operation = await ensureSyncFeedOperation(db);
|
|
39
|
-
db.add(Trigger.make({
|
|
40
|
-
[Obj.Parent]: subject,
|
|
41
|
-
enabled: true,
|
|
42
|
-
spec: Trigger.specTimer("*/5 * * * *"),
|
|
43
|
-
runnable: Ref.make(operation),
|
|
44
|
-
input: {
|
|
45
|
-
feed: db.makeRef(Obj.getURI(subject))
|
|
46
|
-
}
|
|
47
|
-
}));
|
|
48
|
-
} finally {
|
|
49
|
-
setPending(false);
|
|
50
|
-
}
|
|
51
|
-
}, [
|
|
52
|
-
syncTrigger,
|
|
53
|
-
db,
|
|
54
|
-
subject,
|
|
55
|
-
setSyncEnabled
|
|
56
|
-
]);
|
|
57
|
-
const handleViewTrigger = useCallback(() => {
|
|
58
|
-
if (!db) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
void invokePromise(LayoutOperation.Open, {
|
|
62
|
-
subject: [
|
|
63
|
-
Paths.getSpacePath(db.spaceId, "settings", "org.dxos.plugin.routine.routines")
|
|
64
|
-
],
|
|
65
|
-
workspace: Paths.getSpacePath(db.spaceId)
|
|
66
|
-
});
|
|
67
|
-
}, [
|
|
68
|
-
invokePromise,
|
|
69
|
-
db
|
|
70
|
-
]);
|
|
71
|
-
return /* @__PURE__ */ React.createElement(Form.Section, null, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Label, null, t("feed-sync.label")), /* @__PURE__ */ React.createElement("div", {
|
|
72
|
-
className: "flex flex-row items-center"
|
|
73
|
-
}, /* @__PURE__ */ React.createElement(Input.Switch, {
|
|
74
|
-
checked: syncEnabled ?? false,
|
|
75
|
-
disabled: pending,
|
|
76
|
-
onCheckedChange: () => {
|
|
77
|
-
void handleToggleSync();
|
|
78
|
-
}
|
|
79
|
-
}), syncTrigger && /* @__PURE__ */ React.createElement(IconButton, {
|
|
80
|
-
iconOnly: true,
|
|
81
|
-
icon: "ph--gear--regular",
|
|
82
|
-
label: t("view-trigger.label"),
|
|
83
|
-
onClick: handleViewTrigger
|
|
84
|
-
}))));
|
|
85
|
-
};
|
|
86
|
-
var ensureSyncFeedOperation = async (db) => {
|
|
87
|
-
const existing = await db.query(Filter.and(Filter.type(Operation.PersistentOperation), Filter.key(FeedOperation.SyncFeed.meta.key))).run();
|
|
88
|
-
const [existingOperation] = existing;
|
|
89
|
-
if (existingOperation) {
|
|
90
|
-
return existingOperation;
|
|
91
|
-
}
|
|
92
|
-
return db.add(Operation.serialize(FeedOperation.SyncFeed));
|
|
93
|
-
};
|
|
94
|
-
export {
|
|
95
|
-
FeedProperties as default
|
|
96
|
-
};
|
|
97
|
-
//# sourceMappingURL=FeedProperties-EIO7IZOA.mjs.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/containers/FeedProperties/FeedProperties.tsx"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { useCallback, useMemo, useState } from 'react';\n\nimport { useOperationInvoker } from '@dxos/app-framework/ui';\nimport { LayoutOperation, Paths } from '@dxos/app-toolkit';\nimport { type AppSurface } from '@dxos/app-toolkit/ui';\nimport { Operation, Trigger } from '@dxos/compute';\nimport { Filter, Obj, Query, Ref } from '@dxos/echo';\nimport { useObject, useQuery } from '@dxos/react-client/echo';\nimport { IconButton, Input, useTranslation } from '@dxos/react-ui';\nimport { Form } from '@dxos/react-ui-form';\n\nimport { meta } from '#meta';\nimport { FeedOperation, Subscription } from '#types';\n\nexport type FeedPropertiesProps = AppSurface.ObjectPropertiesProps<Subscription.Subscription>;\n\nexport const FeedProperties = ({ subject }: FeedPropertiesProps) => {\n const { t } = useTranslation(meta.profile.key);\n const { invokePromise } = useOperationInvoker();\n const db = useMemo(() => Obj.getDatabase(subject), [subject]);\n const [pending, setPending] = useState(false);\n\n const childTriggers = useQuery(\n db,\n Query.select(Filter.and(Filter.type(Trigger.Trigger), Filter.childOf(subject, { transitive: false }))).debugLabel(\n 'plugin-magazine.FeedProperties.syncTrigger',\n ),\n );\n\n const syncTrigger = useMemo(() => childTriggers.find((trigger) => trigger.spec?.kind === 'timer'), [childTriggers]);\n\n const [syncEnabled, setSyncEnabled] = useObject(syncTrigger, 'enabled');\n\n const handleToggleSync = useCallback(async () => {\n if (!db) {\n return;\n }\n\n if (syncTrigger) {\n setSyncEnabled((enabled) => !enabled);\n return;\n }\n\n setPending(true);\n try {\n const operation = await ensureSyncFeedOperation(db);\n db.add(\n Trigger.make({\n [Obj.Parent]: subject,\n enabled: true,\n spec: Trigger.specTimer('*/5 * * * *'),\n runnable: Ref.make(operation),\n input: { feed: db.makeRef(Obj.getURI(subject)) },\n }),\n );\n } finally {\n setPending(false);\n }\n }, [syncTrigger, db, subject, setSyncEnabled]);\n\n const handleViewTrigger = useCallback(() => {\n if (!db) {\n return;\n }\n\n void invokePromise(LayoutOperation.Open, {\n subject: [Paths.getSpacePath(db.spaceId, 'settings', 'org.dxos.plugin.routine.routines')],\n workspace: Paths.getSpacePath(db.spaceId),\n });\n }, [invokePromise, db]);\n\n return (\n <Form.Section>\n <Input.Root>\n <Input.Label>{t('feed-sync.label')}</Input.Label>\n <div className='flex flex-row items-center'>\n <Input.Switch\n checked={syncEnabled ?? false}\n disabled={pending}\n onCheckedChange={() => {\n void handleToggleSync();\n }}\n />\n {syncTrigger && (\n <IconButton iconOnly icon='ph--gear--regular' label={t('view-trigger.label')} onClick={handleViewTrigger} />\n )}\n </div>\n </Input.Root>\n </Form.Section>\n );\n};\n\nconst ensureSyncFeedOperation = async (db: NonNullable<ReturnType<typeof Obj.getDatabase>>) => {\n const existing = await db\n .query(Filter.and(Filter.type(Operation.PersistentOperation), Filter.key(FeedOperation.SyncFeed.meta.key)))\n .run();\n const [existingOperation] = existing;\n if (existingOperation) {\n return existingOperation;\n }\n\n return db.add(Operation.serialize(FeedOperation.SyncFeed));\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["React", "useCallback", "useMemo", "useState", "useOperationInvoker", "LayoutOperation", "Paths", "Operation", "Trigger", "Filter", "Obj", "Query", "Ref", "useObject", "useQuery", "IconButton", "Input", "useTranslation", "Form", "meta", "FeedOperation", "FeedProperties", "subject", "t", "profile", "key", "invokePromise", "db", "getDatabase", "pending", "setPending", "childTriggers", "select", "and", "type", "childOf", "transitive", "debugLabel", "syncTrigger", "find", "trigger", "spec", "kind", "syncEnabled", "setSyncEnabled", "handleToggleSync", "enabled", "operation", "ensureSyncFeedOperation", "add", "make", "Parent", "specTimer", "runnable", "input", "feed", "makeRef", "getURI", "handleViewTrigger", "Open", "getSpacePath", "spaceId", "workspace", "Section", "Root", "Label", "div", "className", "Switch", "checked", "disabled", "onCheckedChange", "iconOnly", "icon", "label", "onClick", "existing", "query", "PersistentOperation", "SyncFeed", "run", "existingOperation", "serialize"]
|
|
7
|
-
}
|