quick add fixes for tasks. tagging current bucket context. preserving state when clicking off
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { type Component, createSignal, createMemo, onCleanup, onMount } from "solid-js";
|
import { type Component, createSignal, onCleanup, onMount } from "solid-js";
|
||||||
import { store, currentTaskContext } from "@/store";
|
import { store } from "@/store";
|
||||||
import { Plus, X } from "lucide-solid";
|
import { Plus, X } from "lucide-solid";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
@@ -7,37 +7,6 @@ import { QuickEntryForm } from "./QuickEntryForm";
|
|||||||
|
|
||||||
export const QuickEntry: Component = () => {
|
export const QuickEntry: Component = () => {
|
||||||
const [isOpen, setIsOpen] = createSignal(false);
|
const [isOpen, setIsOpen] = createSignal(false);
|
||||||
// Autofill tags based on context when opening
|
|
||||||
const initialTags = createMemo(() => {
|
|
||||||
if (!isOpen()) return [];
|
|
||||||
|
|
||||||
const tags: string[] = [];
|
|
||||||
const ctx = currentTaskContext();
|
|
||||||
|
|
||||||
if (store.isNotepadMode) {
|
|
||||||
// Not in a specific context, but in Notes mode.
|
|
||||||
// We use global window variable set by Layout to get the active note id
|
|
||||||
const activeNoteId = (window as any)._activeNoteId;
|
|
||||||
if (activeNoteId) {
|
|
||||||
const note = store.notes.find(n => n.id === activeNoteId);
|
|
||||||
if (note && note.title) {
|
|
||||||
const noteTagName = note.title.trim();
|
|
||||||
if (noteTagName) tags.push(noteTagName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (typeof ctx === 'object') {
|
|
||||||
if ('bucketId' in ctx) {
|
|
||||||
// Bucket View: Autofill bucket name
|
|
||||||
const bucketName = ctx.name;
|
|
||||||
if (bucketName) tags.push(`@${bucketName}`);
|
|
||||||
} else if ('userId' in ctx) {
|
|
||||||
// Shared User View: Autofill user name (assuming name IS the tag for sharing)
|
|
||||||
const userName = ctx.name;
|
|
||||||
if (userName) tags.push(`@${userName}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tags;
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleKeyDown = (e: KeyboardEvent) => {
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
if ((e.metaKey || e.ctrlKey) && e.key === "k") {
|
if ((e.metaKey || e.ctrlKey) && e.key === "k") {
|
||||||
@@ -66,10 +35,10 @@ export const QuickEntry: Component = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{isOpen() && (
|
{isOpen() && (
|
||||||
<div class="fixed inset-0 z-[100] flex items-end md:items-start justify-center md:pt-[15vh] px-0 md:px-4 pb-0 md:pb-4">
|
<div class="fixed inset-0 z-[100] flex items-start justify-center md:pt-[15vh] px-0 md:px-4 pb-0 md:pb-4">
|
||||||
<div class="absolute inset-0 bg-background/80 backdrop-blur-sm" onClick={() => setIsOpen(false)} />
|
<div class="absolute inset-0 bg-background/80 backdrop-blur-sm" onClick={() => setIsOpen(false)} />
|
||||||
|
|
||||||
<div class="relative w-full max-w-xl max-h-[100vh] md:max-h-[80vh] bg-card border border-border rounded-t-2xl md:rounded-2xl shadow-2xl overflow-hidden animate-in fade-in slide-in-from-bottom-4 md:zoom-in-95 duration-200 flex flex-col">
|
<div class="relative w-full max-w-xl max-h-[100vh] md:max-h-[80vh] bg-card border border-border rounded-b-2xl md:rounded-2xl shadow-2xl overflow-hidden animate-in fade-in slide-in-from-top-4 md:slide-in-from-bottom-0 md:zoom-in-95 duration-200 flex flex-col">
|
||||||
<div class="absolute top-3 right-4 z-[101]">
|
<div class="absolute top-3 right-4 z-[101]">
|
||||||
<Button
|
<Button
|
||||||
size="icon"
|
size="icon"
|
||||||
@@ -85,7 +54,6 @@ export const QuickEntry: Component = () => {
|
|||||||
<QuickEntryForm
|
<QuickEntryForm
|
||||||
onSuccess={() => setIsOpen(false)}
|
onSuccess={() => setIsOpen(false)}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
initialTags={initialTags()}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { type Component, createSignal, createEffect, onMount, For, Show, Suspense, lazy } from "solid-js";
|
import { type Component, createSignal, createEffect, onMount, For, Show, Suspense, lazy } from "solid-js";
|
||||||
import { addTask, calculateDateFromUrgency, calculateUrgencyFromDate, store, upsertTagDefinition, type TaskTemplate } from "@/store";
|
import { addTask, calculateDateFromUrgency, calculateUrgencyFromDate, store, upsertTagDefinition, type TaskTemplate, currentTaskContext } from "@/store";
|
||||||
import { Search, Command, Clock, ArrowUpCircle, Copy, ChevronDown, Gauge } from "lucide-solid";
|
import { Search, Command, Clock, ArrowUpCircle, Copy, ChevronDown, Gauge, RotateCcw } from "lucide-solid";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { TextField, TextFieldInput } from "@/components/ui/textfield";
|
import { TextField, TextFieldInput } from "@/components/ui/textfield";
|
||||||
@@ -21,26 +21,42 @@ interface QuickEntryFormProps {
|
|||||||
initialTags?: string[];
|
initialTags?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const QuickEntryForm: Component<QuickEntryFormProps> = (props) => {
|
// Global state for QuickEntry persistence
|
||||||
const { resolvedTheme } = useTheme();
|
const [input, setInput] = createSignal("");
|
||||||
// Diff tracking for reactive tags
|
|
||||||
let lastParsedTags: string[] = [];
|
|
||||||
|
|
||||||
const [input, setInput] = createSignal(props.initialTitle || "");
|
|
||||||
const [priority, setPriority] = createSignal<string>("");
|
const [priority, setPriority] = createSignal<string>("");
|
||||||
const [urgency, setUrgency] = createSignal<string>("");
|
const [urgency, setUrgency] = createSignal<string>("");
|
||||||
const [tags, setTags] = createSignal<string[]>(props.initialTags || []);
|
const [tags, setTags] = createSignal<string[]>([]);
|
||||||
const [description, setDescription] = createSignal("");
|
const [description, setDescription] = createSignal("");
|
||||||
const [editorInstance, setEditorInstance] = createSignal<any>(null);
|
|
||||||
const [size, setSize] = createSignal<string>("3");
|
const [size, setSize] = createSignal<string>("3");
|
||||||
const [dateString, setDateString] = createSignal<string>("");
|
const [dateString, setDateString] = createSignal<string>("");
|
||||||
|
|
||||||
|
let lastParsedTags: string[] = [];
|
||||||
|
|
||||||
|
const resetQuickEntryState = () => {
|
||||||
|
setInput("");
|
||||||
|
setPriority("");
|
||||||
|
setUrgency("");
|
||||||
|
setTags([]);
|
||||||
|
setDescription("");
|
||||||
|
setSize("3");
|
||||||
|
setDateString("");
|
||||||
|
lastParsedTags = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const QuickEntryForm: Component<QuickEntryFormProps> = (props) => {
|
||||||
|
const { resolvedTheme } = useTheme();
|
||||||
|
|
||||||
|
const [editorInstance, setEditorInstance] = createSignal<any>(null);
|
||||||
|
|
||||||
let inputRef: HTMLInputElement | undefined;
|
let inputRef: HTMLInputElement | undefined;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (props.autoFocus) {
|
if (props.autoFocus) {
|
||||||
setTimeout(() => inputRef?.focus(), 100);
|
setTimeout(() => inputRef?.focus(), 100);
|
||||||
}
|
}
|
||||||
|
if (props.initialTitle && !input()) {
|
||||||
|
setInput(props.initialTitle);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reactive sync from props (handles context changes while open)
|
// Reactive sync from props (handles context changes while open)
|
||||||
@@ -187,6 +203,33 @@ export const QuickEntryForm: Component<QuickEntryFormProps> = (props) => {
|
|||||||
finalDueDate = new Date(dateStr);
|
finalDueDate = new Date(dateStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply context tags at the time of creation
|
||||||
|
const ctx = currentTaskContext();
|
||||||
|
if (store.isNotepadMode) {
|
||||||
|
const activeNoteId = (window as any)._activeNoteId;
|
||||||
|
if (activeNoteId) {
|
||||||
|
const note = store.notes.find(n => n.id === activeNoteId);
|
||||||
|
if (note && note.title) {
|
||||||
|
const noteTagName = note.title.trim();
|
||||||
|
if (noteTagName && !finalTags.includes(noteTagName)) finalTags.push(noteTagName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (typeof ctx === 'object') {
|
||||||
|
if ('bucketId' in ctx) {
|
||||||
|
const bucketName = ctx.name;
|
||||||
|
if (bucketName) {
|
||||||
|
const tag = `@${bucketName}`;
|
||||||
|
if (!finalTags.includes(tag)) finalTags.push(tag);
|
||||||
|
}
|
||||||
|
} else if ('userId' in ctx) {
|
||||||
|
const userName = ctx.name;
|
||||||
|
if (userName) {
|
||||||
|
const tag = `@${userName}`;
|
||||||
|
if (!finalTags.includes(tag)) finalTags.push(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addTask(title.replace(/\s+/g, " ").trim(), {
|
addTask(title.replace(/\s+/g, " ").trim(), {
|
||||||
priority: finalPriority,
|
priority: finalPriority,
|
||||||
dueDate: finalDueDate || undefined,
|
dueDate: finalDueDate || undefined,
|
||||||
@@ -195,14 +238,7 @@ export const QuickEntryForm: Component<QuickEntryFormProps> = (props) => {
|
|||||||
size: parseInt(size())
|
size: parseInt(size())
|
||||||
});
|
});
|
||||||
|
|
||||||
setInput("");
|
resetQuickEntryState();
|
||||||
setPriority("");
|
|
||||||
setUrgency("");
|
|
||||||
setTags([]);
|
|
||||||
setDescription("");
|
|
||||||
setSize("3");
|
|
||||||
lastParsedTags = [];
|
|
||||||
setDateString("");
|
|
||||||
|
|
||||||
const instance = editorInstance();
|
const instance = editorInstance();
|
||||||
if (instance) instance.commands.setContent("");
|
if (instance) instance.commands.setContent("");
|
||||||
@@ -420,6 +456,18 @@ export const QuickEntryForm: Component<QuickEntryFormProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
class="h-9 w-9 text-muted-foreground hover:text-destructive"
|
||||||
|
onClick={() => {
|
||||||
|
resetQuickEntryState();
|
||||||
|
editorInstance()?.commands.setContent("");
|
||||||
|
}}
|
||||||
|
title="Restart Quick Entry"
|
||||||
|
>
|
||||||
|
<RotateCcw size={16} />
|
||||||
|
</Button>
|
||||||
<Show when={(store.templates || []).length > 0}>
|
<Show when={(store.templates || []).length > 0}>
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger
|
<PopoverTrigger
|
||||||
|
|||||||
Reference in New Issue
Block a user