tag prefixing migration and improvements
This commit is contained in:
@@ -2,14 +2,12 @@ import { type Component, createSignal, createMemo, For, Show } from "solid-js";
|
||||
import { store, renameTagDefinition } from "@/store";
|
||||
import { pb } from "@/lib/pocketbase";
|
||||
import { type Note } from "@/store";
|
||||
import { Trash2, Lock, Unlock, Hash, StickyNote, Search, X, Link } from "lucide-solid";
|
||||
import { Trash2, Lock, Unlock, StickyNote, Search, Link, X } from "lucide-solid";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { TaskEditor } from "@/components/TaskEditor";
|
||||
import { TagPicker } from "@/components/TagPicker";
|
||||
import { NOTES_COLLECTION } from "@/lib/constants";
|
||||
import { TaskCard } from "@/components/TaskCard";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { NotesSidebar } from "@/components/NotesSidebar";
|
||||
|
||||
export const NotepadView: Component<{
|
||||
@@ -147,7 +145,6 @@ export const NotepadView: Component<{
|
||||
)}>
|
||||
<Show when={activeNote()} fallback={
|
||||
<div class="text-center space-y-4 opacity-40 select-none">
|
||||
<StickyNote size={64} class="mx-auto" />
|
||||
<p class="text-sm font-medium tracking-wide">Select a note or create a new one</p>
|
||||
</div>
|
||||
}>
|
||||
@@ -203,34 +200,6 @@ export const NotepadView: Component<{
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tags */}
|
||||
<div class="flex flex-wrap gap-2 items-center">
|
||||
<For each={note().tags}>
|
||||
{(tag) => (
|
||||
<Badge variant="secondary" class="h-6 px-2 text-xs bg-muted/30 border border-border/50 text-foreground shadow-sm">
|
||||
{tag}
|
||||
<Show when={canEdit}>
|
||||
<button
|
||||
class="ml-2 hover:text-destructive transition-colors shrink-0 outline-none"
|
||||
onClick={() => {
|
||||
handleUpdateNote(note().id, { tags: note().tags.filter(t => t !== tag) });
|
||||
}}
|
||||
>
|
||||
<X size={10} />
|
||||
</button>
|
||||
</Show>
|
||||
</Badge>
|
||||
)}
|
||||
</For>
|
||||
<Show when={canEdit}>
|
||||
<div class="opacity-70 hover:opacity-100 transition-opacity">
|
||||
<TagPicker
|
||||
selectedTags={note().tags || []}
|
||||
onTagsChange={(newTags) => handleUpdateNote(note().id, { tags: newTags })}
|
||||
/>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Editor Instance */}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { type Component, For, Show, createSignal, lazy, Suspense } from "solid-j
|
||||
import { ThemeToggle } from "../components/ThemeToggle";
|
||||
import { store, restoreTask, deleteTaskPermanently, addTemplate, removeTemplate, updateTemplate, upsertTagDefinition, removeTagDefinition, renameTagDefinition, addShareRule, removeShareRule, updateShareRule, createBucket, updateBucket, deleteBucket, toggleBucketSubscription } from "@/store";
|
||||
import { useTheme } from "@/components/ThemeProvider";
|
||||
import { Trash2, Undo2, ArrowLeftRight, Hash, Copy, Plus, ChevronDown, ChevronRight, Type, Share2, Users, Tag, Upload, Box, Edit2, Archive, HelpCircle } from "lucide-solid";
|
||||
import { Trash2, Undo2, ArrowLeftRight, Tag, ChevronDown, ChevronRight, Share2, Users, HelpCircle, Copy, Plus, Type, Upload, Box, Edit2, Archive } from "lucide-solid";
|
||||
import { TagPicker } from "@/components/TagPicker";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -268,7 +268,7 @@ export const SettingsView: Component<{ setView?: (v: string) => void }> = (props
|
||||
<div class="min-w-0">
|
||||
<p class="text-xs font-bold truncate">To: {getUserName(rule.targetUserId)}</p>
|
||||
<p class="text-[0.5625rem] text-muted-foreground uppercase font-black tracking-widest opacity-60 flex items-center gap-1">
|
||||
{rule.type === 'all' ? 'All Tasks' : `Tag: ${rule.tagName}`}
|
||||
{rule.type === 'all' ? 'All Tasks' : `Tag: ${rule.tagName} `}
|
||||
<span class="mx-1">•</span>
|
||||
<button
|
||||
class="hover:text-primary transition-colors hover:underline"
|
||||
@@ -320,7 +320,7 @@ export const SettingsView: Component<{ setView?: (v: string) => void }> = (props
|
||||
<div class="min-w-0">
|
||||
<p class="text-xs font-bold truncate">From: {getUserName(rule.ownerId)}</p>
|
||||
<p class="text-[0.5625rem] text-muted-foreground uppercase font-black tracking-widest opacity-60 flex items-center gap-1">
|
||||
{rule.type === 'all' ? 'All Tasks' : `Tag: ${rule.tagName}`}
|
||||
{rule.type === 'all' ? 'All Tasks' : `Tag: ${rule.tagName} `}
|
||||
<span class="mx-1">•</span>
|
||||
{rule.share_mode === 'SEND_TASK' ? 'HANDOFF' : 'COLLAB'}
|
||||
</p>
|
||||
@@ -528,7 +528,7 @@ export const SettingsView: Component<{ setView?: (v: string) => void }> = (props
|
||||
size="icon"
|
||||
class="h-8 w-8 text-muted-foreground hover:text-destructive hover:bg-destructive/10 opacity-0 group-hover/bucket:opacity-100 transition-opacity"
|
||||
onClick={() => {
|
||||
if (confirm(`Delete the bucket "${bucket.name}"? This cannot be undone and will affect all users.`)) {
|
||||
if (confirm(`Delete the bucket "${bucket.name}" ? This cannot be undone and will affect all users.`)) {
|
||||
deleteBucket(bucket.id);
|
||||
}
|
||||
}}
|
||||
@@ -889,7 +889,7 @@ export const SettingsView: Component<{ setView?: (v: string) => void }> = (props
|
||||
>
|
||||
<div class="space-y-0.5">
|
||||
<h3 class="text-base font-semibold flex items-center gap-2">
|
||||
<Hash size={16} />
|
||||
<Tag size={16} />
|
||||
Global Tags
|
||||
</h3>
|
||||
<p class="text-sm text-muted-foreground">Manage your global tag definitions and values.</p>
|
||||
@@ -902,7 +902,7 @@ export const SettingsView: Component<{ setView?: (v: string) => void }> = (props
|
||||
<Show when={isTagsOpen()}>
|
||||
<div class="space-y-2 pt-2 animate-in fade-in slide-in-from-top-2 duration-300">
|
||||
<div class="space-y-2">
|
||||
<For each={store.tagDefinitions.filter(t => !t.isUser && !store.buckets.some(b => b.name === t.name)).sort((a, b) => a.name.localeCompare(b.name))} fallback={
|
||||
<For each={store.tagDefinitions.filter(t => !t.isUser && !t.name.startsWith('#') && !store.buckets.some(b => b.name === t.name || `@${b.name} ` === t.name)).sort((a, b) => a.name.localeCompare(b.name))} fallback={
|
||||
<div class="text-center py-8 text-muted-foreground text-sm italic border border-dashed border-border rounded-xl">
|
||||
No custom tags found.
|
||||
</div>
|
||||
@@ -988,10 +988,10 @@ export const SettingsView: Component<{ setView?: (v: string) => void }> = (props
|
||||
<div class="bg-muted/50 p-1 rounded-md group-open/details:rotate-90 transition-transform">
|
||||
<ChevronRight size={12} />
|
||||
</div>
|
||||
System Tags (Users & Buckets)
|
||||
System Tags (Users, Buckets & Notes)
|
||||
</summary>
|
||||
<div class="pt-2 pl-4 space-y-2 animate-in fade-in slide-in-from-top-1 duration-200">
|
||||
<For each={store.tagDefinitions.filter(t => t.isUser || store.buckets.some(b => b.name === t.name)).sort((a, b) => a.name.localeCompare(b.name))}>
|
||||
<For each={store.tagDefinitions.filter(t => t.isUser || t.name.startsWith('#') || store.buckets.some(b => b.name === t.name || `@${b.name}` === t.name)).sort((a, b) => a.name.localeCompare(b.name))}>
|
||||
{(tag) => (
|
||||
<div class="flex flex-col sm:flex-row sm:items-center justify-between p-2 rounded-lg bg-muted/10 border border-border/20 gap-3 sm:gap-4 group opacity-80">
|
||||
<div class="flex items-center gap-3 min-w-0 flex-1">
|
||||
|
||||
Reference in New Issue
Block a user