@ai-matrx/associations 0.10.7 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/dist/{CommentThread-DobuYuwz.d.cts → CommentThread-ar5rzifm.d.cts} +60 -22
- package/dist/{CommentThread-DobuYuwz.d.ts → CommentThread-ar5rzifm.d.ts} +60 -22
- package/dist/index.cjs +9 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +182 -58
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +182 -58
- package/dist/react/index.js.map +1 -1
- package/dist/react/lazy/index.d.cts +1 -1
- package/dist/react/lazy/index.d.ts +1 -1
- package/package.json +3 -3
package/dist/react/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ComponentType } from 'react';
|
|
3
|
-
import { j as AssociationsNotifier, W as WindowShellPort, k as CapturePort, P as PickerOverrideMap, E as EntityDoorsPort, l as AuthorDisplayPort, m as AssociationsStore, n as CategoryMutationResult, o as CategoryDimension, p as PlatformCategory, q as CategoriesEntry, r as EntityTypeToken, s as UniversalCandidate, t as CandidateRecord, u as PlatformComment, v as CommentsEntry, w as CommentMutationResult, e as AssociationPickerProps, x as EntityDoorProps, y as EntityRefProps, z as ContentRole } from '../CommentThread-
|
|
4
|
-
export { B as AssociationCaptureToolbar, A as AssociationCaptureToolbarProps, D as AssociationCard, F as AssociationCardGrid, b as AssociationCardGridProps, a as AssociationCardProps, G as AssociationEntitySelect, H as AssociationEntitySelectAdapter, I as AssociationEntitySelectItem, c as AssociationEntitySelectProps, J as AssociationList, d as AssociationListProps, K as AssociationWindow, f as AssociationWindowProps, L as AssociationWriteResult, M as AttachedItemsSheet, g as AttachedItemsSheetProps, N as CaptureAttach, O as CaptureAttachResult, Q as CaptureToolbarAction, R as CategorySelect, C as CategorySelectProps, S as CategoryTagPicker, h as CategoryTagPickerProps, T as CommentComposer, V as CommentComposerProps, X as CommentThread, i as CommentThreadProps, Y as ContainerLink, Z as ContainerResourceRow, _ as ContainerResourcesAdapter, $ as DefaultEntityIcon, a0 as
|
|
3
|
+
import { j as AssociationsNotifier, W as WindowShellPort, k as CapturePort, P as PickerOverrideMap, E as EntityDoorsPort, l as AuthorDisplayPort, m as AssociationsStore, n as CategoryMutationResult, o as CategoryDimension, p as PlatformCategory, q as CategoriesEntry, r as EntityTypeToken, s as UniversalCandidate, t as CandidateRecord, u as PlatformComment, v as CommentsEntry, w as CommentMutationResult, e as AssociationPickerProps, x as EntityDoorProps, y as EntityRefProps, z as ContentRole } from '../CommentThread-ar5rzifm.cjs';
|
|
4
|
+
export { B as AssociationCaptureToolbar, A as AssociationCaptureToolbarProps, D as AssociationCard, F as AssociationCardGrid, b as AssociationCardGridProps, a as AssociationCardProps, G as AssociationEntitySelect, H as AssociationEntitySelectAdapter, I as AssociationEntitySelectItem, c as AssociationEntitySelectProps, J as AssociationList, d as AssociationListProps, K as AssociationWindow, f as AssociationWindowProps, L as AssociationWriteResult, M as AttachedItemsSheet, g as AttachedItemsSheetProps, N as CaptureAttach, O as CaptureAttachResult, Q as CaptureToolbarAction, R as CategorySelect, C as CategorySelectProps, S as CategoryTagPicker, h as CategoryTagPickerProps, T as CommentComposer, V as CommentComposerProps, X as CommentThread, i as CommentThreadProps, Y as ContainerLink, Z as ContainerResourceRow, _ as ContainerResourcesAdapter, $ as DefaultEntityIcon, a0 as PrimaryContainerEntity, a1 as PrimaryEntity, a2 as PrimaryEntityProvider, a3 as PrimaryFiledEntity, a4 as TagPickerIcon, a5 as UniversalAssociationPicker, U as UniversalAssociationPickerProps, a6 as UseAssociationEntitySelectAdapterArgs, a7 as UseAssociationsArgs, a8 as UseAssociationsReturn, a9 as UseContainerLinksArgs, aa as UseContainerLinksReturn, ab as attachedKey, ac as buildCommentTree, ad as containerLinksArgs, ae as useAssociationEntitySelectAdapter, af as useAssociations, ag as useContainerLinks, ah as useContainerLinksAdapter, ai as useEntityRelationships, aj as usePrimaryEntity } from '../CommentThread-ar5rzifm.cjs';
|
|
5
5
|
|
|
6
6
|
interface AssociationsUiPorts {
|
|
7
7
|
notifier?: AssociationsNotifier;
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ComponentType } from 'react';
|
|
3
|
-
import { j as AssociationsNotifier, W as WindowShellPort, k as CapturePort, P as PickerOverrideMap, E as EntityDoorsPort, l as AuthorDisplayPort, m as AssociationsStore, n as CategoryMutationResult, o as CategoryDimension, p as PlatformCategory, q as CategoriesEntry, r as EntityTypeToken, s as UniversalCandidate, t as CandidateRecord, u as PlatformComment, v as CommentsEntry, w as CommentMutationResult, e as AssociationPickerProps, x as EntityDoorProps, y as EntityRefProps, z as ContentRole } from '../CommentThread-
|
|
4
|
-
export { B as AssociationCaptureToolbar, A as AssociationCaptureToolbarProps, D as AssociationCard, F as AssociationCardGrid, b as AssociationCardGridProps, a as AssociationCardProps, G as AssociationEntitySelect, H as AssociationEntitySelectAdapter, I as AssociationEntitySelectItem, c as AssociationEntitySelectProps, J as AssociationList, d as AssociationListProps, K as AssociationWindow, f as AssociationWindowProps, L as AssociationWriteResult, M as AttachedItemsSheet, g as AttachedItemsSheetProps, N as CaptureAttach, O as CaptureAttachResult, Q as CaptureToolbarAction, R as CategorySelect, C as CategorySelectProps, S as CategoryTagPicker, h as CategoryTagPickerProps, T as CommentComposer, V as CommentComposerProps, X as CommentThread, i as CommentThreadProps, Y as ContainerLink, Z as ContainerResourceRow, _ as ContainerResourcesAdapter, $ as DefaultEntityIcon, a0 as
|
|
3
|
+
import { j as AssociationsNotifier, W as WindowShellPort, k as CapturePort, P as PickerOverrideMap, E as EntityDoorsPort, l as AuthorDisplayPort, m as AssociationsStore, n as CategoryMutationResult, o as CategoryDimension, p as PlatformCategory, q as CategoriesEntry, r as EntityTypeToken, s as UniversalCandidate, t as CandidateRecord, u as PlatformComment, v as CommentsEntry, w as CommentMutationResult, e as AssociationPickerProps, x as EntityDoorProps, y as EntityRefProps, z as ContentRole } from '../CommentThread-ar5rzifm.js';
|
|
4
|
+
export { B as AssociationCaptureToolbar, A as AssociationCaptureToolbarProps, D as AssociationCard, F as AssociationCardGrid, b as AssociationCardGridProps, a as AssociationCardProps, G as AssociationEntitySelect, H as AssociationEntitySelectAdapter, I as AssociationEntitySelectItem, c as AssociationEntitySelectProps, J as AssociationList, d as AssociationListProps, K as AssociationWindow, f as AssociationWindowProps, L as AssociationWriteResult, M as AttachedItemsSheet, g as AttachedItemsSheetProps, N as CaptureAttach, O as CaptureAttachResult, Q as CaptureToolbarAction, R as CategorySelect, C as CategorySelectProps, S as CategoryTagPicker, h as CategoryTagPickerProps, T as CommentComposer, V as CommentComposerProps, X as CommentThread, i as CommentThreadProps, Y as ContainerLink, Z as ContainerResourceRow, _ as ContainerResourcesAdapter, $ as DefaultEntityIcon, a0 as PrimaryContainerEntity, a1 as PrimaryEntity, a2 as PrimaryEntityProvider, a3 as PrimaryFiledEntity, a4 as TagPickerIcon, a5 as UniversalAssociationPicker, U as UniversalAssociationPickerProps, a6 as UseAssociationEntitySelectAdapterArgs, a7 as UseAssociationsArgs, a8 as UseAssociationsReturn, a9 as UseContainerLinksArgs, aa as UseContainerLinksReturn, ab as attachedKey, ac as buildCommentTree, ad as containerLinksArgs, ae as useAssociationEntitySelectAdapter, af as useAssociations, ag as useContainerLinks, ah as useContainerLinksAdapter, ai as useEntityRelationships, aj as usePrimaryEntity } from '../CommentThread-ar5rzifm.js';
|
|
5
5
|
|
|
6
6
|
interface AssociationsUiPorts {
|
|
7
7
|
notifier?: AssociationsNotifier;
|
package/dist/react/index.js
CHANGED
|
@@ -1193,6 +1193,77 @@ import {
|
|
|
1193
1193
|
useRef as useRef3,
|
|
1194
1194
|
useState
|
|
1195
1195
|
} from "react";
|
|
1196
|
+
|
|
1197
|
+
// src/edges.ts
|
|
1198
|
+
var ASSOCIATION_TARGET_TYPES = [
|
|
1199
|
+
"organization",
|
|
1200
|
+
// an org — the top-level container resources attach into
|
|
1201
|
+
"scope",
|
|
1202
|
+
"scope_type",
|
|
1203
|
+
"project",
|
|
1204
|
+
"task",
|
|
1205
|
+
"context_item",
|
|
1206
|
+
"thread",
|
|
1207
|
+
"war_room",
|
|
1208
|
+
"category",
|
|
1209
|
+
"conversation",
|
|
1210
|
+
// a chat conversation a working_document is attached to
|
|
1211
|
+
"fc_set",
|
|
1212
|
+
// a flashcard set (card→set membership)
|
|
1213
|
+
"fc_card",
|
|
1214
|
+
// a flashcard (card→card hierarchy, quiz→card)
|
|
1215
|
+
"study_media",
|
|
1216
|
+
// a study-media artifact (summary/mind_map) — converter lineage target
|
|
1217
|
+
"assessment",
|
|
1218
|
+
// a quiz / practice test — a converter lineage target + origin (assessment→artifact 'source')
|
|
1219
|
+
"note",
|
|
1220
|
+
// a note — the origin a converted study artifact links back to (artifact→note 'source' lineage, P4)
|
|
1221
|
+
"file",
|
|
1222
|
+
// a file (card→file media + source lineage)
|
|
1223
|
+
"quiz_session",
|
|
1224
|
+
// a quiz a card is used in
|
|
1225
|
+
"agent",
|
|
1226
|
+
// an orchestrator agent — the container an Orchestra's member agents attach into (role 'member'); an 'orchestra' self-edge marks the orchestrator
|
|
1227
|
+
"agent_term_list",
|
|
1228
|
+
// a term list — durable file attachments target its vocabulary resource
|
|
1229
|
+
"research_tag",
|
|
1230
|
+
// a research tag a source is filed under (rs_source_tag M2M collapsed into associations)
|
|
1231
|
+
"skill",
|
|
1232
|
+
// a skill — projects link to it (skill→project, role 'member'); code_files attach as resources (code_file→skill, role 'resource')
|
|
1233
|
+
"surface",
|
|
1234
|
+
// a UI surface — agents bind here (agent→surface); context menu reads via agent.menu_surface
|
|
1235
|
+
"plan_entity",
|
|
1236
|
+
// a Content Planning source/media citation — plan_node role edges (about/cites/embeds) target it
|
|
1237
|
+
"plan_node",
|
|
1238
|
+
// a planned page — research topics/tags attach here and follow realization into web_page
|
|
1239
|
+
"web_site",
|
|
1240
|
+
// a web.site — parties attach onto a site's roster (party→web_site role 'writes_for')
|
|
1241
|
+
"seo_topic",
|
|
1242
|
+
// a taxonomy topic — plan_node/plan_entity tag into it (role 'topic')
|
|
1243
|
+
"seo_keyword",
|
|
1244
|
+
// a keyword — plan_node attaches secondaries (role 'secondary_keyword'; the primary is an FK, never an edge)
|
|
1245
|
+
"web_page",
|
|
1246
|
+
// a canonical page — the page workspace attaches notes/tasks/files/keywords onto it (keyword edges: role 'primary'|'supporting')
|
|
1247
|
+
"web_screenshot",
|
|
1248
|
+
// a page capture — per-image attachments on the page workspace
|
|
1249
|
+
"party",
|
|
1250
|
+
// a CRM person/company (crm.party) — the record page attaches tasks/files/notes onto it
|
|
1251
|
+
"crm_outreach_list",
|
|
1252
|
+
// a CRM outreach list (a worked send/dial queue) — parties and resources attach into it
|
|
1253
|
+
"crm_deal",
|
|
1254
|
+
// a CRM deal (crm.deal) — people on it (role 'deal_contact'), tasks/files attach onto it
|
|
1255
|
+
"rulebook",
|
|
1256
|
+
// a Masterwork Rulebook — its Scout interviews attach here (conversation→rulebook, role 'interview')
|
|
1257
|
+
"research_topic",
|
|
1258
|
+
// a research topic — Sources are filed under it (processed_document→research_topic, the landing door's edge)
|
|
1259
|
+
"media_source_library"
|
|
1260
|
+
// a media-catalog Library — Sources are catalogued into it (processed_document→media_source_library)
|
|
1261
|
+
];
|
|
1262
|
+
function isAssociationTargetType(value) {
|
|
1263
|
+
return typeof value === "string" && ASSOCIATION_TARGET_TYPES.includes(value);
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
// src/react/hooks/useContainerLinks.ts
|
|
1196
1267
|
function metadataRecord(metadata) {
|
|
1197
1268
|
if (metadata === null || typeof metadata !== "object" || Array.isArray(metadata)) {
|
|
1198
1269
|
return metadata == null ? {} : null;
|
|
@@ -1201,6 +1272,7 @@ function metadataRecord(metadata) {
|
|
|
1201
1272
|
}
|
|
1202
1273
|
function useContainerLinks(args) {
|
|
1203
1274
|
const { containerType, containerId, orgId } = args;
|
|
1275
|
+
const outgoing = args.direction === "outgoing";
|
|
1204
1276
|
const store = useAssociationsStore();
|
|
1205
1277
|
const {
|
|
1206
1278
|
edges,
|
|
@@ -1211,7 +1283,7 @@ function useContainerLinks(args) {
|
|
|
1211
1283
|
type: containerType,
|
|
1212
1284
|
id: containerId
|
|
1213
1285
|
});
|
|
1214
|
-
const conversationKey = containerType === "conversation" && containerId ? `conversation:${containerId}` : null;
|
|
1286
|
+
const conversationKey = !outgoing && containerType === "conversation" && containerId ? `conversation:${containerId}` : null;
|
|
1215
1287
|
const activeConversationKey = useRef3(conversationKey);
|
|
1216
1288
|
const conversationGeneration = useRef3(0);
|
|
1217
1289
|
const [conversationResult, setConversationResult] = useState(null);
|
|
@@ -1267,9 +1339,9 @@ function useContainerLinks(args) {
|
|
|
1267
1339
|
}, [loadConversationFiles]);
|
|
1268
1340
|
const conversationFiles = conversationResult?.key === conversationKey ? conversationResult.files : [];
|
|
1269
1341
|
const conversationFileError = conversationResult?.key === conversationKey ? conversationResult.error : null;
|
|
1270
|
-
const conversationFileStatus = containerType !== "conversation" ? "idle" : conversationResult?.key !== conversationKey ? "loading" : conversationResult.loading ? "loading" : conversationFileError ? "error" : "ready";
|
|
1342
|
+
const conversationFileStatus = outgoing || containerType !== "conversation" ? "idle" : conversationResult?.key !== conversationKey ? "loading" : conversationResult.loading ? "loading" : conversationFileError ? "error" : "ready";
|
|
1271
1343
|
const incomingGeneric = edges.filter(
|
|
1272
|
-
(edge) => edge.direction === "incoming" && !(containerType === "conversation" && edge.otherType === "file")
|
|
1344
|
+
(edge) => outgoing ? edge.direction === "outgoing" : edge.direction === "incoming" && !(containerType === "conversation" && edge.otherType === "file")
|
|
1273
1345
|
).map((edge) => ({
|
|
1274
1346
|
edgeId: edge.id,
|
|
1275
1347
|
resourceId: edge.otherId,
|
|
@@ -1278,7 +1350,29 @@ function useContainerLinks(args) {
|
|
|
1278
1350
|
label: edge.label ?? null,
|
|
1279
1351
|
metadata: edge.metadata ?? {}
|
|
1280
1352
|
}));
|
|
1281
|
-
const incoming = containerType === "conversation" ? [...incomingGeneric, ...conversationFiles] : incomingGeneric;
|
|
1353
|
+
const incoming = !outgoing && containerType === "conversation" ? [...incomingGeneric, ...conversationFiles] : incomingGeneric;
|
|
1354
|
+
const endpoints = (token, resourceId) => {
|
|
1355
|
+
if (!containerId) return { error: "Missing container id" };
|
|
1356
|
+
if (outgoing) {
|
|
1357
|
+
if (!isAssociationTargetType(token)) {
|
|
1358
|
+
return {
|
|
1359
|
+
error: `A ${token.replace(/_/g, " ")} cannot be filed under: it is not a container type.`
|
|
1360
|
+
};
|
|
1361
|
+
}
|
|
1362
|
+
return {
|
|
1363
|
+
sourceType: containerType,
|
|
1364
|
+
sourceId: containerId,
|
|
1365
|
+
targetType: token,
|
|
1366
|
+
targetId: resourceId
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1369
|
+
return {
|
|
1370
|
+
sourceType: token,
|
|
1371
|
+
sourceId: resourceId,
|
|
1372
|
+
targetType: containerType,
|
|
1373
|
+
targetId: containerId
|
|
1374
|
+
};
|
|
1375
|
+
};
|
|
1282
1376
|
const linksFor = (token) => incoming.filter((link) => link.token === token);
|
|
1283
1377
|
const countFor = (token) => incoming.reduce((n, link) => link.token === token ? n + 1 : n, 0);
|
|
1284
1378
|
const attachedIdsFor = (token) => {
|
|
@@ -1289,39 +1383,36 @@ function useContainerLinks(args) {
|
|
|
1289
1383
|
return set;
|
|
1290
1384
|
};
|
|
1291
1385
|
const attach = async (token, resourceId, label, metadata, options) => {
|
|
1292
|
-
|
|
1386
|
+
const ends = endpoints(token, resourceId);
|
|
1387
|
+
if ("error" in ends) return { ok: false, error: ends.error };
|
|
1293
1388
|
const result = await store.add({
|
|
1294
|
-
|
|
1295
|
-
sourceId: resourceId,
|
|
1296
|
-
targetType: containerType,
|
|
1297
|
-
targetId: containerId,
|
|
1389
|
+
...ends,
|
|
1298
1390
|
...orgId != null ? { orgId } : {},
|
|
1299
1391
|
...label !== void 0 ? { label } : {},
|
|
1300
1392
|
...metadata !== void 0 ? { metadata } : {},
|
|
1301
1393
|
...options?.role !== void 0 ? { role: options.role } : {},
|
|
1302
1394
|
...options?.replaceMetadata !== void 0 ? { replaceMetadata: options.replaceMetadata } : {}
|
|
1303
1395
|
});
|
|
1304
|
-
if (result.ok && containerType === "conversation" && token === "file") {
|
|
1396
|
+
if (result.ok && !outgoing && containerType === "conversation" && token === "file") {
|
|
1305
1397
|
await loadConversationFiles();
|
|
1306
1398
|
}
|
|
1307
1399
|
return result;
|
|
1308
1400
|
};
|
|
1309
1401
|
const detach = async (token, resourceId, role) => {
|
|
1310
|
-
|
|
1402
|
+
const ends = endpoints(token, resourceId);
|
|
1403
|
+
if ("error" in ends) return { ok: false, error: ends.error };
|
|
1311
1404
|
const result = await store.remove({
|
|
1312
|
-
|
|
1313
|
-
sourceId: resourceId,
|
|
1314
|
-
targetType: containerType,
|
|
1315
|
-
targetId: containerId,
|
|
1405
|
+
...ends,
|
|
1316
1406
|
...role !== void 0 ? { role } : {}
|
|
1317
1407
|
});
|
|
1318
|
-
if (result.ok && containerType === "conversation" && token === "file") {
|
|
1408
|
+
if (result.ok && !outgoing && containerType === "conversation" && token === "file") {
|
|
1319
1409
|
await loadConversationFiles();
|
|
1320
1410
|
}
|
|
1321
1411
|
return result;
|
|
1322
1412
|
};
|
|
1323
1413
|
const setPinned = async (token, resourceId, pinned, role) => {
|
|
1324
|
-
|
|
1414
|
+
const ends = endpoints(token, resourceId);
|
|
1415
|
+
if ("error" in ends) return { ok: false, error: ends.error };
|
|
1325
1416
|
const exactRole = role ?? null;
|
|
1326
1417
|
const link = incoming.find(
|
|
1327
1418
|
(candidate) => candidate.token === token && candidate.resourceId === resourceId && candidate.role === exactRole
|
|
@@ -1335,10 +1426,7 @@ function useContainerLinks(args) {
|
|
|
1335
1426
|
};
|
|
1336
1427
|
}
|
|
1337
1428
|
return store.add({
|
|
1338
|
-
|
|
1339
|
-
sourceId: resourceId,
|
|
1340
|
-
targetType: containerType,
|
|
1341
|
-
targetId: containerId,
|
|
1429
|
+
...ends,
|
|
1342
1430
|
...orgId != null ? { orgId } : {},
|
|
1343
1431
|
...link.label != null ? { label: link.label } : {},
|
|
1344
1432
|
...role !== void 0 ? { role } : {},
|
|
@@ -1348,16 +1436,17 @@ function useContainerLinks(args) {
|
|
|
1348
1436
|
const reload = async () => {
|
|
1349
1437
|
await Promise.all([
|
|
1350
1438
|
reloadGeneric(),
|
|
1351
|
-
containerType === "conversation" ? loadConversationFiles() : Promise.resolve()
|
|
1439
|
+
!outgoing && containerType === "conversation" ? loadConversationFiles() : Promise.resolve()
|
|
1352
1440
|
]);
|
|
1353
1441
|
};
|
|
1354
|
-
const status = !containerId ? genericStatus : conversationFileStatus === "error" ? "error" : containerType === "conversation" && (conversationFileStatus === "idle" || conversationFileStatus === "loading") ? "loading" : genericStatus;
|
|
1442
|
+
const status = !containerId ? genericStatus : conversationFileStatus === "error" ? "error" : !outgoing && containerType === "conversation" && (conversationFileStatus === "idle" || conversationFileStatus === "loading") ? "loading" : genericStatus;
|
|
1355
1443
|
const error = conversationFileError ?? genericError;
|
|
1356
1444
|
return {
|
|
1357
1445
|
status,
|
|
1358
1446
|
error,
|
|
1359
1447
|
reload,
|
|
1360
1448
|
totalCount: incoming.length,
|
|
1449
|
+
presentTokens: [...new Set(incoming.map((link) => link.token))],
|
|
1361
1450
|
countFor,
|
|
1362
1451
|
attachedIdsFor,
|
|
1363
1452
|
linksFor,
|
|
@@ -1366,6 +1455,21 @@ function useContainerLinks(args) {
|
|
|
1366
1455
|
setPinned
|
|
1367
1456
|
};
|
|
1368
1457
|
}
|
|
1458
|
+
function containerLinksArgs(container) {
|
|
1459
|
+
if (container?.direction === "outgoing") {
|
|
1460
|
+
return {
|
|
1461
|
+
containerType: container.type,
|
|
1462
|
+
containerId: container.id,
|
|
1463
|
+
orgId: container.orgId ?? null,
|
|
1464
|
+
direction: "outgoing"
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1467
|
+
return {
|
|
1468
|
+
containerType: container?.type ?? "organization",
|
|
1469
|
+
containerId: container?.id ?? null,
|
|
1470
|
+
orgId: container?.orgId ?? null
|
|
1471
|
+
};
|
|
1472
|
+
}
|
|
1369
1473
|
|
|
1370
1474
|
// src/react/hooks/useEntityTitles.ts
|
|
1371
1475
|
import { useEffect as useEffect3, useState as useState2 } from "react";
|
|
@@ -2206,7 +2310,7 @@ function AssociationPicker(props) {
|
|
|
2206
2310
|
const Override = pickerOverrides?.[props.token];
|
|
2207
2311
|
if (Override) return /* @__PURE__ */ jsx6(Override, { ...props });
|
|
2208
2312
|
const title = `Add ${info.labelPlural}`;
|
|
2209
|
-
const subtitle = props.containerLabel ? `Attach to ${props.containerLabel}` : "Click an item to attach or detach it";
|
|
2313
|
+
const subtitle = props.filing ? `File ${props.containerLabel ?? "this"} under a ${info.label.toLowerCase()}` : props.containerLabel ? `Attach to ${props.containerLabel}` : "Click an item to attach or detach it";
|
|
2210
2314
|
if (!props.open) return null;
|
|
2211
2315
|
return /* @__PURE__ */ jsx6(
|
|
2212
2316
|
AssociationWindow,
|
|
@@ -2823,8 +2927,9 @@ function AttachedItemsSheet(props) {
|
|
|
2823
2927
|
const Icon = info.Icon ?? DefaultEntityIcon;
|
|
2824
2928
|
const title = info.labelPlural;
|
|
2825
2929
|
const containerName = props.container?.label ?? props.containerLabel;
|
|
2930
|
+
const filing = props.container?.direction === "outgoing";
|
|
2826
2931
|
const subtitle = props.container ? /* @__PURE__ */ jsxs7("span", { className: "inline-flex min-w-0 max-w-full items-center gap-1", children: [
|
|
2827
|
-
"Attached to",
|
|
2932
|
+
filing ? "What this is filed under:" : "Attached to",
|
|
2828
2933
|
/* @__PURE__ */ jsx9(
|
|
2829
2934
|
DoorRef,
|
|
2830
2935
|
{
|
|
@@ -3100,11 +3205,7 @@ function AssociationCard({
|
|
|
3100
3205
|
attach,
|
|
3101
3206
|
detach,
|
|
3102
3207
|
setPinned
|
|
3103
|
-
} = useContainerLinks(
|
|
3104
|
-
containerType: container?.type ?? "organization",
|
|
3105
|
-
containerId: container?.id ?? null,
|
|
3106
|
-
orgId: container?.orgId ?? null
|
|
3107
|
-
});
|
|
3208
|
+
} = useContainerLinks(containerLinksArgs(container));
|
|
3108
3209
|
if (!container) {
|
|
3109
3210
|
store.errorSink({
|
|
3110
3211
|
code: "association_card_no_container",
|
|
@@ -3115,7 +3216,8 @@ function AssociationCard({
|
|
|
3115
3216
|
}
|
|
3116
3217
|
const count = countFor(token);
|
|
3117
3218
|
const loading = status === "loading" || status === "idle";
|
|
3118
|
-
const
|
|
3219
|
+
const filing = container.direction === "outgoing";
|
|
3220
|
+
const canAttach = info.canListCandidates && (!filing || isAssociationTargetType(token));
|
|
3119
3221
|
const canDrillIn = count > 0;
|
|
3120
3222
|
return /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
3121
3223
|
/* @__PURE__ */ jsxs8(
|
|
@@ -3163,7 +3265,7 @@ function AssociationCard({
|
|
|
3163
3265
|
/* @__PURE__ */ jsx10("span", { className: "block text-[11px] text-muted-foreground tabular-nums", children: loading ? /* @__PURE__ */ jsxs8("span", { className: "inline-flex items-center gap-1", children: [
|
|
3164
3266
|
/* @__PURE__ */ jsx10(SpinnerIcon, { className: "h-3 w-3 animate-spin" }),
|
|
3165
3267
|
"Loading\u2026"
|
|
3166
|
-
] }) : `${count} attached` })
|
|
3268
|
+
] }) : `${count} ${container.direction === "outgoing" ? "filed under" : "attached"}` })
|
|
3167
3269
|
] })
|
|
3168
3270
|
]
|
|
3169
3271
|
}
|
|
@@ -3209,6 +3311,7 @@ function AssociationCard({
|
|
|
3209
3311
|
token,
|
|
3210
3312
|
...container.label !== void 0 ? { containerLabel: container.label } : {},
|
|
3211
3313
|
orgId: container.orgId ?? null,
|
|
3314
|
+
...filing ? { filing: true } : {},
|
|
3212
3315
|
attachedIds: attachedIdsFor(token),
|
|
3213
3316
|
onAttach: (resourceId, title) => attach(token, resourceId, title),
|
|
3214
3317
|
onDetach: (resourceId) => detach(token, resourceId)
|
|
@@ -3226,31 +3329,55 @@ function AssociationCardGrid({
|
|
|
3226
3329
|
className
|
|
3227
3330
|
}) {
|
|
3228
3331
|
const store = useAssociationsStore();
|
|
3332
|
+
const primary = usePrimaryEntity();
|
|
3229
3333
|
const excluded = new Set(excludeTokens ?? []);
|
|
3230
|
-
const
|
|
3231
|
-
|
|
3334
|
+
const filing = primary?.direction === "outgoing";
|
|
3335
|
+
const links = useContainerLinks(containerLinksArgs(primary));
|
|
3336
|
+
const base2 = tokens ?? store.registry.curatedTokens();
|
|
3337
|
+
const withPresent = filing ? [
|
|
3338
|
+
...base2,
|
|
3339
|
+
...links.presentTokens.filter(
|
|
3340
|
+
(t) => isEntityTypeToken(t) && !base2.includes(t)
|
|
3341
|
+
)
|
|
3342
|
+
] : base2;
|
|
3343
|
+
const list = withPresent.filter(
|
|
3344
|
+
(token) => !excluded.has(token) && (!filing || isAssociationTargetType(token))
|
|
3232
3345
|
);
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
);
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3346
|
+
const roleIds = new Set(CONTENT_ROLES.map((r) => r.id));
|
|
3347
|
+
const roleless = filing ? list.filter((token) => {
|
|
3348
|
+
const role = store.registry.getEntityInfo(token).contentRole;
|
|
3349
|
+
return !role || !roleIds.has(role);
|
|
3350
|
+
}) : [];
|
|
3351
|
+
return /* @__PURE__ */ jsxs9("div", { className: cn7("space-y-5", className), children: [
|
|
3352
|
+
CONTENT_ROLES.map((role) => {
|
|
3353
|
+
const inRole = list.filter(
|
|
3354
|
+
(token) => store.registry.getEntityInfo(token).contentRole === role.id
|
|
3355
|
+
);
|
|
3356
|
+
if (inRole.length === 0) return null;
|
|
3357
|
+
return /* @__PURE__ */ jsxs9("section", { children: [
|
|
3358
|
+
/* @__PURE__ */ jsxs9("div", { className: "mb-2.5 flex items-baseline gap-3 pl-1.5", children: [
|
|
3359
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
|
|
3360
|
+
/* @__PURE__ */ jsx11(
|
|
3361
|
+
"span",
|
|
3362
|
+
{
|
|
3363
|
+
className: cn7("h-2.5 w-2.5 rounded-full", role.accentBar)
|
|
3364
|
+
}
|
|
3365
|
+
),
|
|
3366
|
+
/* @__PURE__ */ jsx11("h3", { className: "text-sm font-semibold text-foreground", children: role.title })
|
|
3367
|
+
] }),
|
|
3368
|
+
/* @__PURE__ */ jsx11("p", { className: "hidden text-xs text-muted-foreground sm:block", children: role.tagline })
|
|
3248
3369
|
] }),
|
|
3249
|
-
/* @__PURE__ */ jsx11("
|
|
3370
|
+
/* @__PURE__ */ jsx11("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2 lg:grid-cols-3", children: inRole.map((token) => /* @__PURE__ */ jsx11(AssociationCard, { token }, token)) })
|
|
3371
|
+
] }, role.id);
|
|
3372
|
+
}),
|
|
3373
|
+
roleless.length > 0 && /* @__PURE__ */ jsxs9("section", { children: [
|
|
3374
|
+
/* @__PURE__ */ jsxs9("div", { className: "mb-2.5 flex items-baseline gap-3 pl-1.5", children: [
|
|
3375
|
+
/* @__PURE__ */ jsx11("h3", { className: "text-sm font-semibold text-foreground", children: "Filed under" }),
|
|
3376
|
+
/* @__PURE__ */ jsx11("p", { className: "hidden text-xs text-muted-foreground sm:block", children: "Libraries, topics and other places this is kept." })
|
|
3250
3377
|
] }),
|
|
3251
|
-
/* @__PURE__ */ jsx11("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2 lg:grid-cols-3", children:
|
|
3252
|
-
] }
|
|
3253
|
-
|
|
3378
|
+
/* @__PURE__ */ jsx11("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2 lg:grid-cols-3", children: roleless.map((token) => /* @__PURE__ */ jsx11(AssociationCard, { token }, token)) })
|
|
3379
|
+
] })
|
|
3380
|
+
] });
|
|
3254
3381
|
}
|
|
3255
3382
|
|
|
3256
3383
|
// src/react/components/AssociationList.tsx
|
|
@@ -3262,11 +3389,7 @@ function metadataIsPinned2(metadata) {
|
|
|
3262
3389
|
}
|
|
3263
3390
|
function useContainerLinksAdapter(container, tokens) {
|
|
3264
3391
|
const store = useAssociationsStore();
|
|
3265
|
-
const links = useContainerLinks(
|
|
3266
|
-
containerType: container?.type ?? "organization",
|
|
3267
|
-
containerId: container?.id ?? null,
|
|
3268
|
-
orgId: container?.orgId ?? null
|
|
3269
|
-
});
|
|
3392
|
+
const links = useContainerLinks(containerLinksArgs(container));
|
|
3270
3393
|
const rows = container ? (tokens ?? store.registry.curatedTokens()).flatMap(
|
|
3271
3394
|
(token) => links.linksFor(token).map((l) => ({
|
|
3272
3395
|
key: l.edgeId,
|
|
@@ -5320,6 +5443,7 @@ export {
|
|
|
5320
5443
|
UnresolvedRef,
|
|
5321
5444
|
attachedKey,
|
|
5322
5445
|
buildCommentTree,
|
|
5446
|
+
containerLinksArgs,
|
|
5323
5447
|
getContentRoleMeta,
|
|
5324
5448
|
lazyPickerOverride,
|
|
5325
5449
|
lazyWindowShell,
|