share rules update stable
This commit is contained in:
+77
-9
@@ -221,12 +221,27 @@ export const matchesFilter = (task: Task) => {
|
|||||||
const isExplicitlyShared = task.sharedWith?.some(s => s.userId === currentUserId);
|
const isExplicitlyShared = task.sharedWith?.some(s => s.userId === currentUserId);
|
||||||
|
|
||||||
// Tag-based share rules targeting me
|
// Tag-based share rules targeting me
|
||||||
const isTagRuleShared = store.shareRules.some(r =>
|
const isTagRuleShared = store.shareRules.some(r => {
|
||||||
r.targetUserId === currentUserId &&
|
if (r.targetUserId !== currentUserId) return false;
|
||||||
r.ownerId === task.ownerId &&
|
|
||||||
r.type === 'tag' &&
|
// Global Rule / Self-Rule: Match purely on tag, ignore owner check
|
||||||
task.tags?.includes(r.tagName || "")
|
// logic: If I have a rule for tag "T" assigned to myself, show ANY task with tag "T"
|
||||||
);
|
if (r.ownerId === r.targetUserId && r.type === 'tag') {
|
||||||
|
const tagName = r.tagName || "";
|
||||||
|
|
||||||
|
// EXCLUDE Buckets from the main "Mine" view
|
||||||
|
// The user wants to see "Direct Shares" (User Tags), not "Bucket Subscriptions" here.
|
||||||
|
const isBucket = store.buckets.some(b => b.name.toLowerCase() === tagName.toLowerCase());
|
||||||
|
if (isBucket) return false;
|
||||||
|
|
||||||
|
return task.tags?.some(t => t.toLowerCase() === tagName.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard Rule: Match owner AND tag
|
||||||
|
return r.ownerId === task.ownerId &&
|
||||||
|
r.type === 'tag' &&
|
||||||
|
task.tags?.includes(r.tagName || "");
|
||||||
|
});
|
||||||
|
|
||||||
// Bucket visibility logic for "My Bucket":
|
// Bucket visibility logic for "My Bucket":
|
||||||
// Users requested: "Any user who adds that bucket to their workspaces list can view the workspace and see tasks in that bucket from all users."
|
// Users requested: "Any user who adds that bucket to their workspaces list can view the workspace and see tasks in that bucket from all users."
|
||||||
@@ -778,6 +793,9 @@ export const initStore = async () => {
|
|||||||
.map(id => store.buckets.find(b => b.id === id)?.name)
|
.map(id => store.buckets.find(b => b.id === id)?.name)
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
|
||||||
|
// Sync System Tags & Share Rules FIRST to ensure Self-Rules exist for query construction
|
||||||
|
await syncSystemTagsAndRules();
|
||||||
|
|
||||||
// Add rules from shareRules store (which was just synced)
|
// Add rules from shareRules store (which was just synced)
|
||||||
const incomingRules = store.shareRules.filter(r => r.targetUserId === currentUserId);
|
const incomingRules = store.shareRules.filter(r => r.targetUserId === currentUserId);
|
||||||
|
|
||||||
@@ -823,6 +841,7 @@ export const initStore = async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 1. Fetch Global Rule Tasks (from ANY user)
|
||||||
// 1. Fetch Global Rule Tasks (from ANY user)
|
// 1. Fetch Global Rule Tasks (from ANY user)
|
||||||
if (globalTagRules.length > 0) {
|
if (globalTagRules.length > 0) {
|
||||||
// We want tasks that have ANY of these tags, AND are not completed
|
// We want tasks that have ANY of these tags, AND are not completed
|
||||||
@@ -943,8 +962,8 @@ export const initStore = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync System Tags & Share Rules (Heavy maintenance task)
|
// Sync System Tags & Share Rules (Moved to top of backgroundSync to ensure rules exist before use)
|
||||||
await syncSystemTagsAndRules();
|
// await syncSystemTagsAndRules();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fire off background sync after a short delay
|
// Fire off background sync after a short delay
|
||||||
@@ -1619,6 +1638,45 @@ export const syncSystemTagsAndRules = async () => {
|
|||||||
// Legacy loop removed to prevent exponential growth
|
// Legacy loop removed to prevent exponential growth
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// --- Ensure Self-Rule for Current User (Global Subscription) ---
|
||||||
|
// This is the critical piece for "Global Sharing".
|
||||||
|
// We must ensure the user has a rule: Owner=Me, Target=Me, Tag=Me.
|
||||||
|
if (user.id === currentUserId) {
|
||||||
|
const selfRuleExists = normalizedRules.some(r =>
|
||||||
|
r.ownerId === currentUserId &&
|
||||||
|
r.targetUserId === currentUserId &&
|
||||||
|
r.type === 'tag' &&
|
||||||
|
r.tagName === userName
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!selfRuleExists) {
|
||||||
|
try {
|
||||||
|
const record = await pb.collection(SHARE_RULES_COLLECTION).create({
|
||||||
|
ownerId: currentUserId,
|
||||||
|
targetUserId: currentUserId,
|
||||||
|
type: 'tag',
|
||||||
|
tagName: userName,
|
||||||
|
share_mode: 'ADD_USER' // Mode doesn't strictly matter for self-rule visibility, but ADD_USER is safe default
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update local store immediately to ensure loadAllHistory sees it
|
||||||
|
const newRule: ShareRule = {
|
||||||
|
id: record.id,
|
||||||
|
ownerId: currentUserId,
|
||||||
|
targetUserId: currentUserId,
|
||||||
|
type: 'tag',
|
||||||
|
tagName: userName,
|
||||||
|
share_mode: 'ADD_USER'
|
||||||
|
};
|
||||||
|
setStore("shareRules", prev => [...prev, newRule]);
|
||||||
|
|
||||||
|
console.log(`Created self-rule for global sharing: ${userName}`);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Failed to create self-rule for ${userName}`, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -1694,12 +1752,15 @@ export const loadAllHistory = async () => {
|
|||||||
|
|
||||||
// Add Share Rules
|
// Add Share Rules
|
||||||
const incomingRules = store.shareRules.filter(r => r.targetUserId === userId);
|
const incomingRules = store.shareRules.filter(r => r.targetUserId === userId);
|
||||||
|
console.log("[DEBUG] loadAllHistory - Incoming Rules for User:", userId, incomingRules);
|
||||||
|
|
||||||
if (incomingRules.length > 0) {
|
if (incomingRules.length > 0) {
|
||||||
const rulesToFetch: string[] = [];
|
const rulesToFetch: string[] = [];
|
||||||
|
|
||||||
incomingRules.forEach((rule: any) => {
|
incomingRules.forEach((rule: any) => {
|
||||||
// Global Rule (Self-Targeted)
|
// Global Rule (Self-Targeted)
|
||||||
if (rule.ownerId === rule.targetUserId && rule.type === 'tag' && rule.tagName) {
|
if (rule.ownerId === rule.targetUserId && rule.type === 'tag' && rule.tagName) {
|
||||||
|
console.log("[DEBUG] Found Self-Rule:", rule.tagName);
|
||||||
rulesToFetch.push(`tags ~ "${rule.tagName}"`);
|
rulesToFetch.push(`tags ~ "${rule.tagName}"`);
|
||||||
} else {
|
} else {
|
||||||
// Standard Rule
|
// Standard Rule
|
||||||
@@ -1716,7 +1777,14 @@ export const loadAllHistory = async () => {
|
|||||||
// Let's just push them as individual queries for safety.
|
// Let's just push them as individual queries for safety.
|
||||||
|
|
||||||
rulesToFetch.forEach(filter => {
|
rulesToFetch.forEach(filter => {
|
||||||
promises.push(pb.collection(TASGRID_COLLECTION).getFullList({ filter, sort: '-created', fields: LIST_FIELDS, requestKey: null }).catch(() => []));
|
console.log("[DEBUG] Fetching with filter:", filter);
|
||||||
|
promises.push(pb.collection(TASGRID_COLLECTION).getFullList({ filter, sort: '-created', fields: LIST_FIELDS, requestKey: null }).then(res => {
|
||||||
|
console.log(`[DEBUG] Filter "${filter}" returned ${res.length} items`);
|
||||||
|
return res;
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(`[DEBUG] Filter "${filter}" FAILED:`, err);
|
||||||
|
return [];
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user