diff --git a/src/views/SettingsView.tsx b/src/views/SettingsView.tsx index 66081ca..d47e0f7 100644 --- a/src/views/SettingsView.tsx +++ b/src/views/SettingsView.tsx @@ -119,7 +119,7 @@ export const SettingsView: Component<{ setView?: (v: string) => void }> = (props Tag Sharing -

Share through tags only: `@people` collaborate, `@buckets` route work, and `#notes` stay link-only.

+

Share through tags: `@people` to collaborate, `@buckets` to move tasks to buckets, and `#notes` to link tasks to notes.

{isSharingOpen() ? : } @@ -131,7 +131,7 @@ export const SettingsView: Component<{ setView?: (v: string) => void }> = (props

User Tag Policies

- Control how each @user tag behaves. Collaborative tags keep work shared. Handoff tags route work into that user's queue. + Control how each @user share tag behaves. Collaborative keeps tasks in both of your lists. Handoff moves tasks from your list to theirs.

void }> = (props - {/* Add new share rule */} -
-
- - -
+ {/* Add new share rule */} +
+
+ + +
- {/* Share Mode Selection */} -
- - -
+ {/* Share Mode Selection */} +
+ + +
- - { + if (val) { + setShareTag(val); + const tagDef = store.tagDefinitions.find(t => t.name === val); + const isBucket = tagDef?.isBucket || store.buckets.some(b => b.name === val); + const isUser = tagDef?.isUser; - if (isBucket) { - setShareMode('SEND_TASK'); - } else if (isUser) { - setShareMode('ADD_USER'); + if (isBucket) { + setShareMode('SEND_TASK'); + } else if (isUser) { + setShareMode('ADD_USER'); + } } - } - }} - options={store.tagDefinitions.filter(t => t.name.startsWith("@")).map(t => t.name)} - placeholder="Select a tag" - itemComponent={(props: any) => {props.item.rawValue}} - > - - {shareTag() || "Select a tag..."} - - - - + }} + options={store.tagDefinitions.filter(t => t.name.startsWith("@")).map(t => t.name)} + placeholder="Select a tag" + itemComponent={(props: any) => {props.item.rawValue}} + > + + {shareTag() || "Select a tag..."} + + + + + +
+ + value={allUsers().find(u => u.id === shareUserId()) || null} + onChange={(user) => setShareUserId(user?.id || "")} + options={availableUsers()} + optionValue="id" + optionTextValue="name" + placeholder={usersLoading() ? "Loading..." : "Select user..."} + itemComponent={(itemProps: any) => ( + {itemProps.item.rawValue.name} + )} + > + + > + {(state) => state.selectedOption()?.name || "Select user..."} + + + + + +
+

+ {shareMode() === 'ADD_USER' + ? "Collaborative contexts add access through the selected @tag." + : "Handoff contexts transfer ownership when that @tag is applied."} +

-
- - value={allUsers().find(u => u.id === shareUserId()) || null} - onChange={(user) => setShareUserId(user?.id || "")} - options={availableUsers()} - optionValue="id" - optionTextValue="name" - placeholder={usersLoading() ? "Loading..." : "Select user..."} - itemComponent={(itemProps: any) => ( - {itemProps.item.rawValue.name} - )} - > - - > - {(state) => state.selectedOption()?.name || "Select user..."} - - - - -
-

- {shareMode() === 'ADD_USER' - ? "Collaborative contexts add access through the selected @tag." - : "Handoff contexts transfer ownership when that @tag is applied."} -

-
- - {/* Active share rules */} - {/* Active share rules - Outgoing */} -
-

-
- Sharing With Others -

- { - const tagDef = r.type === 'tag' ? store.tagDefinitions.find(t => t.name === r.tagName) : null; - const isBucketTag = r.type === 'tag' && store.buckets.some(b => b.name === r.tagName); - const isSystem = tagDef?.isUser || tagDef?.isBucket || isBucketTag; - const isOwner = r.ownerId === pb.authStore.model?.id; - return !isSystem && isOwner; - })} fallback={ -
- You aren't sharing with anyone yet. -
- }> - {(rule) => ( -
-
-
- {rule.type === 'all' ? : } -
-
-

To: {getUserName(rule.targetUserId)}

-

- {rule.type === 'all' ? 'All Tasks' : `Tag: ${rule.tagName} `} - - -

-
-
- -
- )} -
-
- - {/* Active share rules - Incoming */} -
-

-
- Shared With You -

- { - const tagDef = r.type === 'tag' ? store.tagDefinitions.find(t => t.name === r.tagName) : null; - const isBucketTag = r.type === 'tag' && store.buckets.some(b => b.name === r.tagName); - const isSystem = tagDef?.isUser || tagDef?.isBucket || isBucketTag; - const isTarget = r.targetUserId === pb.authStore.model?.id; - return !isSystem && isTarget; - })} fallback={ -
- No one has shared with you yet. -
- }> - {(rule) => ( -
-
-
- {rule.type === 'all' ? : } -
-
-

From: {getUserName(rule.ownerId)}

-

- {rule.type === 'all' ? 'All Tasks' : `Tag: ${rule.tagName} `} - - {rule.share_mode === 'SEND_TASK' ? 'HANDOFF' : 'COLLAB'} -

-
-
- {/* No delete button for incoming rules unless we add leave logic later */} -
- )} -
-
- - {/* Active share rules - System */} -
- -
- -
- System Rules (Auto-Generated) -
-
+ {/* Active share rules */} + {/* Active share rules - Outgoing */} +
+

+
+ Sharing With Others +

{ const tagDef = r.type === 'tag' ? store.tagDefinitions.find(t => t.name === r.tagName) : null; const isBucketTag = r.type === 'tag' && store.buckets.some(b => b.name === r.tagName); - return tagDef?.isUser || tagDef?.isBucket || isBucketTag; - })}> - {(rule) => { - const tagDef = store.tagDefinitions.find(t => t.name === rule.tagName); - return ( -
-
- -
-

- {/* If it's a user tag, show the person's name. If it's a bucket, show the bucket name (tagName). */} - {tagDef?.isUser ? getUserName(rule.targetUserId) : rule.tagName} - {tagDef?.isUser ? : } -

-

- Auto-shared via {tagDef?.isUser ? 'User' : 'Bucket'} Tag - - -

-
+ const isSystem = tagDef?.isUser || tagDef?.isBucket || isBucketTag; + const isOwner = r.ownerId === pb.authStore.model?.id; + return !isSystem && isOwner; + })} fallback={ +
+ You aren't sharing with anyone yet. +
+ }> + {(rule) => ( +
+
+
+ {rule.type === 'all' ? : } +
+
+

To: {getUserName(rule.targetUserId)}

+

+ {rule.type === 'all' ? 'All Tasks' : `Tag: ${rule.tagName} `} + + +

- ); - }} + +
+ )}
-
+ + {/* Active share rules - Incoming */} +
+

+
+ Shared With You +

+ { + const tagDef = r.type === 'tag' ? store.tagDefinitions.find(t => t.name === r.tagName) : null; + const isBucketTag = r.type === 'tag' && store.buckets.some(b => b.name === r.tagName); + const isSystem = tagDef?.isUser || tagDef?.isBucket || isBucketTag; + const isTarget = r.targetUserId === pb.authStore.model?.id; + return !isSystem && isTarget; + })} fallback={ +
+ No one has shared with you yet. +
+ }> + {(rule) => ( +
+
+
+ {rule.type === 'all' ? : } +
+
+

From: {getUserName(rule.ownerId)}

+

+ {rule.type === 'all' ? 'All Tasks' : `Tag: ${rule.tagName} `} + + {rule.share_mode === 'SEND_TASK' ? 'HANDOFF' : 'COLLAB'} +

+
+
+ {/* No delete button for incoming rules unless we add leave logic later */} +
+ )} +
+
+ + {/* Active share rules - System */} +
+ +
+ +
+ System Rules (Auto-Generated) +
+
+ { + const tagDef = r.type === 'tag' ? store.tagDefinitions.find(t => t.name === r.tagName) : null; + const isBucketTag = r.type === 'tag' && store.buckets.some(b => b.name === r.tagName); + return tagDef?.isUser || tagDef?.isBucket || isBucketTag; + })}> + {(rule) => { + const tagDef = store.tagDefinitions.find(t => t.name === rule.tagName); + return ( +
+
+ +
+

+ {/* If it's a user tag, show the person's name. If it's a bucket, show the bucket name (tagName). */} + {tagDef?.isUser ? getUserName(rule.targetUserId) : rule.tagName} + {tagDef?.isUser ? : } +

+

+ Auto-shared via {tagDef?.isUser ? 'User' : 'Bucket'} Tag + + +

+
+
+
+ ); + }} +
+
+
@@ -506,7 +506,7 @@ export const SettingsView: Component<{ setView?: (v: string) => void }> = (props Shared Buckets -

Each bucket is a real `@context` with a policy, metadata, soft delete, and personal pinning.

+

Buckets are shared spaces where tasks can be moved and collaborated on.

{isBucketsOpen() ? : }