Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ff9bf7afa4 | |||
| 8ad5499f06 | |||
| bd8c610584 | |||
| 11daf918b6 |
@@ -17,6 +17,8 @@ export const FilterBar: Component<{ mode?: 'tasks' | 'notes', class?: string, tr
|
|||||||
const [tagSearch, setTagSearch] = createSignal("");
|
const [tagSearch, setTagSearch] = createSignal("");
|
||||||
const [newTemplateName, setNewTemplateName] = createSignal("");
|
const [newTemplateName, setNewTemplateName] = createSignal("");
|
||||||
const [isSaving, setIsSaving] = createSignal(false);
|
const [isSaving, setIsSaving] = createSignal(false);
|
||||||
|
const [isJobStatusOpen, setIsJobStatusOpen] = createSignal(false);
|
||||||
|
const [isJobDivisionOpen, setIsJobDivisionOpen] = createSignal(false);
|
||||||
|
|
||||||
const mode = () => props.mode || 'tasks';
|
const mode = () => props.mode || 'tasks';
|
||||||
|
|
||||||
@@ -30,13 +32,36 @@ export const FilterBar: Component<{ mode?: 'tasks' | 'notes', class?: string, tr
|
|||||||
const hasActiveFilters = () => {
|
const hasActiveFilters = () => {
|
||||||
const f = currentFilter();
|
const f = currentFilter();
|
||||||
const baseActive = (f.query || "") !== "" || (f.tags || []).length > 0 || f.editedToday || f.ownedByMe || f.starred;
|
const baseActive = (f.query || "") !== "" || (f.tags || []).length > 0 || f.editedToday || f.ownedByMe || f.starred;
|
||||||
|
const jobActive = (f.jobStatus?.length || 0) > 0 || (f.jobDivision?.length || 0) > 0;
|
||||||
if (mode() === 'tasks') {
|
if (mode() === 'tasks') {
|
||||||
return baseActive || f.priorityMin !== 1 || f.priorityMax !== 10 || f.urgencyMin !== 1 || f.urgencyMax !== 10;
|
return baseActive || f.priorityMin !== 1 || f.priorityMax !== 10 || f.urgencyMin !== 1 || f.urgencyMax !== 10;
|
||||||
}
|
}
|
||||||
return baseActive;
|
return baseActive || jobActive;
|
||||||
};
|
};
|
||||||
|
|
||||||
const allTags = () => store.tagDefinitions.map(d => d.name).sort();
|
const allTags = () => store.tagDefinitions.map(d => d.name).sort();
|
||||||
|
const JOB_STATUSES = [
|
||||||
|
"Estimating",
|
||||||
|
"Est Sent",
|
||||||
|
"Est Hold",
|
||||||
|
"Follow Up",
|
||||||
|
"Awarded",
|
||||||
|
"In Progress",
|
||||||
|
"On Hold",
|
||||||
|
"Billed (In Progress)",
|
||||||
|
"Billed (Closed)",
|
||||||
|
"Archive",
|
||||||
|
"Not Awarded",
|
||||||
|
"Not Bidding"
|
||||||
|
];
|
||||||
|
const JOB_DIVISIONS = ["C#", "R#", "S#"];
|
||||||
|
const normalizeFilterTags = (items: Array<string | { name: string; excluded: boolean }> | undefined) => {
|
||||||
|
if (!items) return [] as { name: string; excluded: boolean }[];
|
||||||
|
return items.map((i: any) => {
|
||||||
|
if (typeof i === "string") return { name: i, excluded: false };
|
||||||
|
return { name: i.name, excluded: !!i.excluded };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={cn(mode() === 'tasks' ? "fixed top-4 right-5 sm:right-6 z-[60]" : "relative", props.class)}>
|
<div class={cn(mode() === 'tasks' ? "fixed top-4 right-5 sm:right-6 z-[60]" : "relative", props.class)}>
|
||||||
@@ -54,10 +79,14 @@ export const FilterBar: Component<{ mode?: 'tasks' | 'notes', class?: string, tr
|
|||||||
title="Filters & Search"
|
title="Filters & Search"
|
||||||
>
|
>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<Search size={18} class={cn("transition-transform duration-300", isOpen() && "scale-110")} />
|
<Search
|
||||||
{hasActiveFilters() && !isOpen() && (
|
size={18}
|
||||||
<div class="absolute -top-1 -right-1 w-2 h-2 rounded-full bg-primary animate-pulse border border-background" />
|
class={cn(
|
||||||
)}
|
"transition-transform duration-300",
|
||||||
|
isOpen() && "scale-110",
|
||||||
|
hasActiveFilters() && "text-primary"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent class="w-[calc(100vw-2rem)] sm:w-[480px] p-0 overflow-hidden bg-card border-border shadow-2xl rounded-2xl animate-in fade-in zoom-in-95 duration-200 z-[100]">
|
<PopoverContent class="w-[calc(100vw-2rem)] sm:w-[480px] p-0 overflow-hidden bg-card border-border shadow-2xl rounded-2xl animate-in fade-in zoom-in-95 duration-200 z-[100]">
|
||||||
@@ -240,6 +269,160 @@ export const FilterBar: Component<{ mode?: 'tasks' | 'notes', class?: string, tr
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
<Show when={mode() === 'notes'}>
|
||||||
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6">
|
||||||
|
<div class="space-y-2.5">
|
||||||
|
<label class="text-[0.625rem] font-black uppercase tracking-widest text-muted-foreground ml-1">Job Status</label>
|
||||||
|
<div class="flex flex-wrap gap-2 min-h-[44px] p-2 bg-muted/10 border border-dashed border-border/60 rounded-xl">
|
||||||
|
<For each={normalizeFilterTags(currentFilter().jobStatus as any)}>
|
||||||
|
{(status) => (
|
||||||
|
<Badge
|
||||||
|
variant="secondary"
|
||||||
|
class={cn(
|
||||||
|
"h-7 px-2.5 rounded-lg text-xs gap-2 transition-all border shadow-sm",
|
||||||
|
status.excluded
|
||||||
|
? "bg-red-500/10 text-red-600 border-red-500/20 hover:bg-red-500/20"
|
||||||
|
: "bg-blue-500/10 text-blue-600 border-blue-500/20 hover:bg-blue-500/20"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="flex items-center gap-2 cursor-pointer h-full"
|
||||||
|
onClick={() => {
|
||||||
|
const current = normalizeFilterTags(currentFilter().jobStatus as any);
|
||||||
|
const next = current.map(s =>
|
||||||
|
s.name === status.name ? { ...s, excluded: !s.excluded } : s
|
||||||
|
);
|
||||||
|
currentSetFilter({ jobStatus: next as any });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Show when={status.excluded} fallback={<Tag size={12} class="opacity-70" />}>
|
||||||
|
<Minus size={12} class="opacity-100" />
|
||||||
|
</Show>
|
||||||
|
<span class={cn(status.excluded && "line-through opacity-70")}>{status.name}</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class="p-0.5 hover:bg-foreground/10 rounded transition-colors"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
const next = normalizeFilterTags(currentFilter().jobStatus as any).filter(s => s.name !== status.name);
|
||||||
|
currentSetFilter({ jobStatus: next as any });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<X size={10} />
|
||||||
|
</button>
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
<Popover open={isJobStatusOpen()} onOpenChange={setIsJobStatusOpen}>
|
||||||
|
<PopoverTrigger class="h-7 px-3 bg-muted/40 border-none shadow-none focus:ring-0 text-[0.625rem] font-bold uppercase tracking-wider rounded-lg hover:bg-muted/60 transition-colors">
|
||||||
|
<span>+ Status</span>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent class="w-[220px] p-0" align="start">
|
||||||
|
<Command>
|
||||||
|
<CommandInput placeholder="Search status..." />
|
||||||
|
<CommandList>
|
||||||
|
<CommandEmpty>No status found.</CommandEmpty>
|
||||||
|
<CommandGroup>
|
||||||
|
<For each={JOB_STATUSES}>
|
||||||
|
{(status) => (
|
||||||
|
<CommandItem
|
||||||
|
value={status}
|
||||||
|
onSelect={() => {
|
||||||
|
const current = normalizeFilterTags(currentFilter().jobStatus as any);
|
||||||
|
if (!current.some(s => s.name === status)) {
|
||||||
|
currentSetFilter({ jobStatus: [...current, { name: status, excluded: false }] as any });
|
||||||
|
}
|
||||||
|
setIsJobStatusOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{status}
|
||||||
|
</CommandItem>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</Command>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="space-y-2.5">
|
||||||
|
<label class="text-[0.625rem] font-black uppercase tracking-widest text-muted-foreground ml-1">Job Division</label>
|
||||||
|
<div class="flex flex-wrap gap-2 min-h-[44px] p-2 bg-muted/10 border border-dashed border-border/60 rounded-xl">
|
||||||
|
<For each={normalizeFilterTags(currentFilter().jobDivision as any)}>
|
||||||
|
{(division) => (
|
||||||
|
<Badge
|
||||||
|
variant="secondary"
|
||||||
|
class={cn(
|
||||||
|
"h-7 px-2.5 rounded-lg text-xs gap-2 transition-all border shadow-sm",
|
||||||
|
division.excluded
|
||||||
|
? "bg-red-500/10 text-red-600 border-red-500/20 hover:bg-red-500/20"
|
||||||
|
: "bg-emerald-500/10 text-emerald-600 border-emerald-500/20 hover:bg-emerald-500/20"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="flex items-center gap-2 cursor-pointer h-full"
|
||||||
|
onClick={() => {
|
||||||
|
const current = normalizeFilterTags(currentFilter().jobDivision as any);
|
||||||
|
const next = current.map(d =>
|
||||||
|
d.name === division.name ? { ...d, excluded: !d.excluded } : d
|
||||||
|
);
|
||||||
|
currentSetFilter({ jobDivision: next as any });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Show when={division.excluded} fallback={<Tag size={12} class="opacity-70" />}>
|
||||||
|
<Minus size={12} class="opacity-100" />
|
||||||
|
</Show>
|
||||||
|
<span class={cn(division.excluded && "line-through opacity-70")}>{division.name}</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class="p-0.5 hover:bg-foreground/10 rounded transition-colors"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
const next = normalizeFilterTags(currentFilter().jobDivision as any).filter(d => d.name !== division.name);
|
||||||
|
currentSetFilter({ jobDivision: next as any });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<X size={10} />
|
||||||
|
</button>
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
<Popover open={isJobDivisionOpen()} onOpenChange={setIsJobDivisionOpen}>
|
||||||
|
<PopoverTrigger class="h-7 px-3 bg-muted/40 border-none shadow-none focus:ring-0 text-[0.625rem] font-bold uppercase tracking-wider rounded-lg hover:bg-muted/60 transition-colors">
|
||||||
|
<span>+ Division</span>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent class="w-[200px] p-0" align="start">
|
||||||
|
<Command>
|
||||||
|
<CommandInput placeholder="Search division..." />
|
||||||
|
<CommandList>
|
||||||
|
<CommandEmpty>No division found.</CommandEmpty>
|
||||||
|
<CommandGroup>
|
||||||
|
<For each={JOB_DIVISIONS}>
|
||||||
|
{(division) => (
|
||||||
|
<CommandItem
|
||||||
|
value={division}
|
||||||
|
onSelect={() => {
|
||||||
|
const current = normalizeFilterTags(currentFilter().jobDivision as any);
|
||||||
|
if (!current.some(d => d.name === division)) {
|
||||||
|
currentSetFilter({ jobDivision: [...current, { name: division, excluded: false }] as any });
|
||||||
|
}
|
||||||
|
setIsJobDivisionOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{division}
|
||||||
|
</CommandItem>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</Command>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
{/* Tags Multi-select */}
|
{/* Tags Multi-select */}
|
||||||
<div class="space-y-2.5">
|
<div class="space-y-2.5">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { type Component, createMemo, For, Show } from "solid-js";
|
import { type Component, createMemo, createResource, For, Show } from "solid-js";
|
||||||
import { store, getFavoriteTag } from "@/store";
|
import { store, setNoteFilter, getFavoriteTag } from "@/store";
|
||||||
import { pb } from "@/lib/pocketbase";
|
import { pb } from "@/lib/pocketbase";
|
||||||
import { Plus, Lock, Star } from "lucide-solid";
|
import { Plus, Lock, Star } from "lucide-solid";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -12,6 +12,79 @@ export const NotesSidebar: Component<{
|
|||||||
setSelectedNoteId: (id: string | null) => void;
|
setSelectedNoteId: (id: string | null) => void;
|
||||||
}> = (props) => {
|
}> = (props) => {
|
||||||
const currentUserId = pb.authStore.model?.id;
|
const currentUserId = pb.authStore.model?.id;
|
||||||
|
const [accessibleJobs] = createResource(currentUserId, async (userId) => {
|
||||||
|
if (!userId) return new Set<string>();
|
||||||
|
try {
|
||||||
|
const items = await pb.collection('Job_Info_Prod').getFullList({
|
||||||
|
filter: [
|
||||||
|
`EstimatorUser = "${userId}"`,
|
||||||
|
`OfficeRepUser = "${userId}"`,
|
||||||
|
`ProjectManagerUser = "${userId}"`,
|
||||||
|
`Estimator = "${userId}"`,
|
||||||
|
`Office_Rep = "${userId}"`,
|
||||||
|
`Project_Manager = "${userId}"`
|
||||||
|
].join(" || "),
|
||||||
|
fields: "id",
|
||||||
|
requestKey: null
|
||||||
|
});
|
||||||
|
return new Set(items.map((r: any) => String(r.id)));
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Failed to load job access list for notes filter:", e);
|
||||||
|
return new Set<string>();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const [jobFilterIds] = createResource(
|
||||||
|
() => {
|
||||||
|
const f = store.noteFilter;
|
||||||
|
const normalize = (items: Array<string | { name: string; excluded: boolean }> | undefined) => {
|
||||||
|
if (!items) return [] as { name: string; excluded: boolean }[];
|
||||||
|
return items.map((i: any) => (typeof i === "string" ? { name: i, excluded: false } : { name: i.name, excluded: !!i.excluded }));
|
||||||
|
};
|
||||||
|
const status = normalize(f.jobStatus as any).sort((a, b) => a.name.localeCompare(b.name));
|
||||||
|
const division = normalize(f.jobDivision as any).sort((a, b) => a.name.localeCompare(b.name));
|
||||||
|
const key = JSON.stringify({ status, division });
|
||||||
|
return key;
|
||||||
|
},
|
||||||
|
async (key) => {
|
||||||
|
if (!key) return null;
|
||||||
|
const parsed = JSON.parse(key) as { status: Array<{ name: string; excluded: boolean }>; division: Array<{ name: string; excluded: boolean }> };
|
||||||
|
const status = parsed.status || [];
|
||||||
|
const division = parsed.division || [];
|
||||||
|
if (status.length === 0 && division.length === 0) return null;
|
||||||
|
|
||||||
|
const parts: string[] = [];
|
||||||
|
const statusInclude = status.filter(s => !s.excluded).map(s => s.name);
|
||||||
|
const statusExclude = status.filter(s => s.excluded).map(s => s.name);
|
||||||
|
const divisionInclude = division.filter(d => !d.excluded).map(d => d.name);
|
||||||
|
const divisionExclude = division.filter(d => d.excluded).map(d => d.name);
|
||||||
|
|
||||||
|
if (statusInclude.length > 0) {
|
||||||
|
parts.push(`(${statusInclude.map(s => `Job_Status = "${s}"`).join(" || ")})`);
|
||||||
|
}
|
||||||
|
if (statusExclude.length > 0) {
|
||||||
|
parts.push(`(${statusExclude.map(s => `Job_Status != "${s}"`).join(" && ")})`);
|
||||||
|
}
|
||||||
|
if (divisionInclude.length > 0) {
|
||||||
|
parts.push(`(${divisionInclude.map(d => `Job_Division = "${d}"`).join(" || ")})`);
|
||||||
|
}
|
||||||
|
if (divisionExclude.length > 0) {
|
||||||
|
parts.push(`(${divisionExclude.map(d => `Job_Division != "${d}"`).join(" && ")})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const filter = parts.join(" && ");
|
||||||
|
try {
|
||||||
|
const items = await pb.collection('Job_Info_Prod').getFullList({
|
||||||
|
filter,
|
||||||
|
fields: "id",
|
||||||
|
requestKey: null
|
||||||
|
});
|
||||||
|
return new Set(items.map((r: any) => String(r.id)));
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Failed to load job filter list for notes:", e);
|
||||||
|
return new Set<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const filteredNotes = createMemo(() => {
|
const filteredNotes = createMemo(() => {
|
||||||
const filter = store.noteFilter;
|
const filter = store.noteFilter;
|
||||||
@@ -56,7 +129,30 @@ export const NotesSidebar: Component<{
|
|||||||
|
|
||||||
// Owned By Me Filter
|
// Owned By Me Filter
|
||||||
if (filter.ownedByMe) {
|
if (filter.ownedByMe) {
|
||||||
n = n.filter(note => note.user === currentUserId);
|
const accessible = accessibleJobs();
|
||||||
|
n = n.filter(note => {
|
||||||
|
if (note.tags?.includes("prism_job")) {
|
||||||
|
if (!accessible) return false;
|
||||||
|
const jobIdTag = note.tags.find(t => t.startsWith("job_id:"));
|
||||||
|
const jobId = jobIdTag?.split(":")[1]?.trim();
|
||||||
|
if (!jobId) return false;
|
||||||
|
return accessible.has(jobId);
|
||||||
|
}
|
||||||
|
return note.user === currentUserId;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Job Status / Division Filter (notes only)
|
||||||
|
if ((filter.jobStatus?.length || 0) > 0 || (filter.jobDivision?.length || 0) > 0) {
|
||||||
|
const allowedJobIds = jobFilterIds();
|
||||||
|
n = n.filter(note => {
|
||||||
|
if (!note.tags?.includes("prism_job")) return false;
|
||||||
|
if (!allowedJobIds) return false;
|
||||||
|
const jobIdTag = note.tags.find(t => t.startsWith("job_id:"));
|
||||||
|
const jobId = jobIdTag?.split(":")[1]?.trim();
|
||||||
|
if (!jobId) return false;
|
||||||
|
return allowedJobIds.has(jobId);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Starred Filter
|
// Starred Filter
|
||||||
@@ -93,15 +189,24 @@ export const NotesSidebar: Component<{
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div class="p-4 border-b border-border bg-card/50 backdrop-blur flex justify-between items-center gap-2">
|
<div class="p-4 border-b border-border bg-card/50 backdrop-blur flex justify-between items-center gap-2">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Search notes, tags..."
|
||||||
|
value={store.noteFilter.query}
|
||||||
|
onInput={(e) => setNoteFilter({ query: e.currentTarget.value })}
|
||||||
|
class="w-full bg-muted/30 border border-border/50 rounded-xl px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary/40 transition-all placeholder:text-muted-foreground/30"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2 shrink-0">
|
||||||
<FilterBar
|
<FilterBar
|
||||||
mode="notes"
|
mode="notes"
|
||||||
class="relative top-0 right-0 z-0"
|
class="relative top-0 right-0 z-0"
|
||||||
triggerClass="w-full justify-start gap-2 px-3 h-9 bg-muted/40 hover:bg-muted/60 border-border/40"
|
triggerClass="h-9 w-9 p-0 bg-muted/40 hover:bg-muted/60 border-border/40"
|
||||||
/>
|
/>
|
||||||
|
<Button onClick={handleCreateNote} size="sm" variant="default" class="h-9 w-9 p-0 shrink-0 shadow-sm rounded-xl">
|
||||||
|
<Plus size={18} />
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={handleCreateNote} size="sm" variant="default" class="h-9 w-9 p-0 shrink-0 shadow-sm rounded-xl">
|
|
||||||
<Plus size={18} />
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
+15
-4
@@ -171,6 +171,8 @@ export interface Filter {
|
|||||||
editedToday: boolean;
|
editedToday: boolean;
|
||||||
ownedByMe: boolean;
|
ownedByMe: boolean;
|
||||||
starred: boolean;
|
starred: boolean;
|
||||||
|
jobStatus: FilterTag[];
|
||||||
|
jobDivision: FilterTag[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Background sync for Context Switcher (polling fallback for realtime)
|
// Background sync for Context Switcher (polling fallback for realtime)
|
||||||
@@ -298,7 +300,9 @@ export const [store, setStore] = createStore<TaskStore>({
|
|||||||
urgencyMax: 10,
|
urgencyMax: 10,
|
||||||
editedToday: false,
|
editedToday: false,
|
||||||
ownedByMe: false,
|
ownedByMe: false,
|
||||||
starred: false
|
starred: false,
|
||||||
|
jobStatus: [],
|
||||||
|
jobDivision: []
|
||||||
},
|
},
|
||||||
shareRules: [],
|
shareRules: [],
|
||||||
filterTemplates: [],
|
filterTemplates: [],
|
||||||
@@ -316,7 +320,9 @@ export const [store, setStore] = createStore<TaskStore>({
|
|||||||
urgencyMax: 10,
|
urgencyMax: 10,
|
||||||
editedToday: false,
|
editedToday: false,
|
||||||
ownedByMe: false,
|
ownedByMe: false,
|
||||||
starred: false
|
starred: false,
|
||||||
|
jobStatus: [],
|
||||||
|
jobDivision: []
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1095,6 +1101,7 @@ const runLegacyTagMigration = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const initStore = async () => {
|
export const initStore = async () => {
|
||||||
if (!pb.authStore.isValid || store.isInitializing) return;
|
if (!pb.authStore.isValid || store.isInitializing) return;
|
||||||
setStore("isInitializing", true);
|
setStore("isInitializing", true);
|
||||||
@@ -2735,7 +2742,9 @@ export const clearFilter = () => {
|
|||||||
urgencyMax: 10,
|
urgencyMax: 10,
|
||||||
editedToday: false,
|
editedToday: false,
|
||||||
ownedByMe: false,
|
ownedByMe: false,
|
||||||
starred: false
|
starred: false,
|
||||||
|
jobStatus: [],
|
||||||
|
jobDivision: []
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2817,7 +2826,9 @@ export const clearNoteFilter = () => {
|
|||||||
urgencyMax: 10,
|
urgencyMax: 10,
|
||||||
editedToday: false,
|
editedToday: false,
|
||||||
ownedByMe: false,
|
ownedByMe: false,
|
||||||
starred: false
|
starred: false,
|
||||||
|
jobStatus: [],
|
||||||
|
jobDivision: []
|
||||||
});
|
});
|
||||||
syncPreferences();
|
syncPreferences();
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user