ui optimizations
This commit is contained in:
parent
afb330ed5d
commit
6116069fff
|
|
@ -1 +1 @@
|
|||
1.0.41
|
||||
1.0.50
|
||||
|
|
@ -39,7 +39,7 @@ export async function fetchMentionItems(query: string): Promise<{ items: Mention
|
|||
.filter(c => !c.deletedAt && !c.archivedAt && (c.type === 'person' || c.type === 'project' || c.type === 'company'))
|
||||
.toArray();
|
||||
|
||||
const q = query.toLowerCase();
|
||||
const q = query.replace(/_/g, ' ').toLowerCase();
|
||||
const items = all
|
||||
.map(buildMentionItem)
|
||||
.filter(m => m.mentionName.toLowerCase().includes(q))
|
||||
|
|
@ -48,10 +48,11 @@ export async function fetchMentionItems(query: string): Promise<{ items: Mention
|
|||
const exactMatch = items.some(m => m.mentionName.toLowerCase() === q);
|
||||
const createOptions: CreateOption[] = [];
|
||||
if (query.length > 0 && !exactMatch) {
|
||||
const displayName = query.replace(/_/g, ' ');
|
||||
createOptions.push(
|
||||
{ type: 'person', label: `+ Person "${query}" anlegen`, query },
|
||||
{ type: 'project', label: `+ Projekt "${query}" anlegen`, query },
|
||||
{ type: 'company', label: `+ Firma "${query}" anlegen`, query }
|
||||
{ type: 'person', label: `+ Person "${displayName}" anlegen`, query },
|
||||
{ type: 'project', label: `+ Projekt "${displayName}" anlegen`, query },
|
||||
{ type: 'company', label: `+ Firma "${displayName}" anlegen`, query }
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +60,7 @@ export async function fetchMentionItems(query: string): Promise<{ items: Mention
|
|||
}
|
||||
|
||||
export async function createMentionContext(opt: CreateOption): Promise<string> {
|
||||
const name = opt.query;
|
||||
const name = opt.query.replace(/_/g, ' ');
|
||||
const slug = name.toLowerCase().replace(/\s+/g, '-');
|
||||
const id = opt.type === 'company' ? `f-${slug}` : opt.type === 'person' ? `u-${slug}` : `p-${slug}`;
|
||||
const contextName = opt.type === 'company' ? `Firma ${name}` : opt.type === 'person' ? `Person ${name}` : `Project ${name}`;
|
||||
|
|
|
|||
|
|
@ -158,7 +158,8 @@ function showCreatePopup(name: string, type: 'person' | 'project' | 'company', x
|
|||
async function handlePersonClick(name: string, event: MouseEvent, sourceEl: HTMLElement) {
|
||||
const ctx = await findContextByMentionName(name, 'person');
|
||||
if (ctx) {
|
||||
const ratingCtx = findRatingContext(sourceEl);
|
||||
const isEmployee = (ctx.meta as Record<string, unknown> | null)?.personSubType === 'employee';
|
||||
const ratingCtx = isEmployee ? findRatingContext(sourceEl) : null;
|
||||
showPersonPopup(name, ctx.id, ratingCtx, event.clientX, event.clientY, sourceEl);
|
||||
} else {
|
||||
showCreatePopup(name, 'person', event.clientX, event.clientY);
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@
|
|||
{placeholder}
|
||||
{minHeight}
|
||||
onchange={(md) => editorContent = md}
|
||||
onsave={save}
|
||||
/>
|
||||
{:else}
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
<MarkdownEditor
|
||||
content={editText}
|
||||
onchange={(md) => editText = md}
|
||||
onsave={saveEdit}
|
||||
minHeight="100px"
|
||||
/>
|
||||
<div class="flex justify-end gap-1 mt-1">
|
||||
|
|
|
|||
|
|
@ -14,8 +14,10 @@
|
|||
placeholder?: string;
|
||||
minHeight?: string;
|
||||
onchange?: (markdown: string) => void;
|
||||
onsave?: () => void;
|
||||
onsavearchive?: () => void;
|
||||
}
|
||||
let { content = '', placeholder = '', minHeight = '80px', onchange }: Props = $props();
|
||||
let { content = '', placeholder = '', minHeight = '80px', onchange, onsave, onsavearchive }: Props = $props();
|
||||
|
||||
let element: HTMLDivElement;
|
||||
let editor: Editor | null = null;
|
||||
|
|
@ -42,7 +44,7 @@
|
|||
onchange?.(md);
|
||||
}
|
||||
|
||||
async function handlePaste(_view: any, event: ClipboardEvent): Promise<boolean> {
|
||||
function handlePaste(_view: any, event: ClipboardEvent): boolean {
|
||||
const items = event.clipboardData?.items;
|
||||
if (!items) return false;
|
||||
|
||||
|
|
@ -50,12 +52,14 @@
|
|||
if (item.type.startsWith('image/')) {
|
||||
event.preventDefault();
|
||||
const blob = item.getAsFile();
|
||||
if (!blob) continue;
|
||||
|
||||
const id = await storeImage(blob);
|
||||
const url = await getImageUrl(id);
|
||||
if (url && editor) {
|
||||
editor.chain().focus().setImage({ src: url }).run();
|
||||
if (blob) {
|
||||
storeImage(blob)
|
||||
.then((id) => getImageUrl(id))
|
||||
.then((url) => {
|
||||
if (url && editor) {
|
||||
editor.chain().focus().setImage({ src: url }).run();
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -82,6 +86,17 @@
|
|||
content: initialContent,
|
||||
editorProps: {
|
||||
handlePaste,
|
||||
handleKeyDown: (_view, event) => {
|
||||
if (event.key === 'Enter' && (event.ctrlKey || event.metaKey) && event.shiftKey) {
|
||||
onsavearchive?.();
|
||||
return true;
|
||||
}
|
||||
if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {
|
||||
onsave?.();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
attributes: {
|
||||
style: `min-height: ${minHeight}`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,9 +187,11 @@
|
|||
>
|
||||
{/if}
|
||||
{#if isProcessed}
|
||||
<span
|
||||
class="ml-2.5 rounded bg-[#444] px-1.5 py-0.5 text-[0.7em] text-[#aaa]"
|
||||
>BESPROCHEN</span
|
||||
<button
|
||||
class="ml-2.5 rounded bg-[#444] px-1.5 py-0.5 text-[0.7em] text-[#aaa] hover:bg-[#555] hover:text-white"
|
||||
title="Als aktiv markieren"
|
||||
onclick={(e) => { e.stopPropagation(); processedTopicIds.remove(topic.id); }}
|
||||
>BESPROCHEN</button
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -212,6 +214,8 @@
|
|||
bind:this={noteEditor}
|
||||
placeholder="- Notiz... (z.B. '-> NAME' or '@P:PROJECT')"
|
||||
onchange={(md) => (noteText = md)}
|
||||
onsave={handleSaveOnly}
|
||||
onsavearchive={handleDone}
|
||||
/>
|
||||
|
||||
{#if showDailyControls}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,8 @@ export const TiptapMention = Extension.create({
|
|||
const opt = createOptions[index - items.length];
|
||||
if (!opt) return;
|
||||
await createMentionContext(opt);
|
||||
const tag = opt.type === 'company' ? quoteMention('@F:', opt.query) : opt.type === 'person' ? quoteMention('@', opt.query) : quoteMention('@P:', opt.query);
|
||||
const displayName = opt.query.replace(/_/g, ' ');
|
||||
const tag = opt.type === 'company' ? quoteMention('@F:', displayName) : opt.type === 'person' ? quoteMention('@', displayName) : quoteMention('@P:', displayName);
|
||||
console.log('[tiptap-mention] inserting after create:', tag);
|
||||
editor.chain().focus()
|
||||
.deleteRange({ from: savedFrom, to: savedTo })
|
||||
|
|
|
|||
Loading…
Reference in New Issue