mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-24 17:48:30 +02:00
Fix dialog and invalid variable style
This commit is contained in:
@@ -33,9 +33,10 @@ export const plugin: PluginDefinition = {
|
|||||||
name: 'token',
|
name: 'token',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
label: '1Password Service Account Token',
|
label: '1Password Service Account Token',
|
||||||
description: '',
|
description:
|
||||||
|
'Token can be generated from the 1Password website by visiting Developer > Service Accounts',
|
||||||
// biome-ignore lint/suspicious/noTemplateCurlyInString: Yaak template syntax
|
// biome-ignore lint/suspicious/noTemplateCurlyInString: Yaak template syntax
|
||||||
defaultValue: '${[ONEPASSWORD_TOKEN]}',
|
defaultValue: '${[1PASSWORD_TOKEN]}',
|
||||||
password: true,
|
password: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { createWorkspaceModel, type Folder, modelTypeLabel } from '@yaakapp-internal/models';
|
import { createWorkspaceModel, type Folder, modelTypeLabel } from '@yaakapp-internal/models';
|
||||||
import { applySync, calculateSync } from '@yaakapp-internal/sync';
|
import { applySync, calculateSync } from '@yaakapp-internal/sync';
|
||||||
import { Banner } from '../components/core/Banner';
|
import { Banner } from '../components/core/Banner';
|
||||||
|
import { Button } from '../components/core/Button';
|
||||||
import { InlineCode } from '../components/core/InlineCode';
|
import { InlineCode } from '../components/core/InlineCode';
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
@@ -13,7 +14,7 @@ import {
|
|||||||
} from '../components/core/Table';
|
} from '../components/core/Table';
|
||||||
import { activeWorkspaceIdAtom } from '../hooks/useActiveWorkspace';
|
import { activeWorkspaceIdAtom } from '../hooks/useActiveWorkspace';
|
||||||
import { createFastMutation } from '../hooks/useFastMutation';
|
import { createFastMutation } from '../hooks/useFastMutation';
|
||||||
import { showConfirm } from '../lib/confirm';
|
import { showDialog } from '../lib/dialog';
|
||||||
import { jotaiStore } from '../lib/jotai';
|
import { jotaiStore } from '../lib/jotai';
|
||||||
import { pluralizeCount } from '../lib/pluralize';
|
import { pluralizeCount } from '../lib/pluralize';
|
||||||
import { showPrompt } from '../lib/prompt';
|
import { showPrompt } from '../lib/prompt';
|
||||||
@@ -78,81 +79,92 @@ export const syncWorkspace = createFastMutation<
|
|||||||
|
|
||||||
console.log('Directory changes detected', { dbOps, ops });
|
console.log('Directory changes detected', { dbOps, ops });
|
||||||
|
|
||||||
const confirmed = force
|
if (force) {
|
||||||
? true
|
|
||||||
: await showConfirm({
|
|
||||||
id: 'commit-sync',
|
|
||||||
title: 'Changes Detected',
|
|
||||||
size: 'md',
|
|
||||||
confirmText: 'Apply Changes',
|
|
||||||
color: isDeletingWorkspace ? 'danger' : 'primary',
|
|
||||||
description: (
|
|
||||||
<div className="h-full grid grid-rows-[auto_auto_minmax(0,1fr)] gap-3">
|
|
||||||
{isDeletingWorkspace ? (
|
|
||||||
<Banner color="danger">
|
|
||||||
🚨 <strong>Changes contain a workspace deletion!</strong>
|
|
||||||
</Banner>
|
|
||||||
) : (
|
|
||||||
<span />
|
|
||||||
)}
|
|
||||||
<p>
|
|
||||||
{pluralizeCount('file', dbOps.length)} in the directory{' '}
|
|
||||||
{dbOps.length === 1 ? 'has' : 'have'} changed. Do you want to update your workspace?
|
|
||||||
</p>
|
|
||||||
<Table scrollable>
|
|
||||||
<TableHead>
|
|
||||||
<TableRow>
|
|
||||||
<TableHeaderCell>Type</TableHeaderCell>
|
|
||||||
<TableHeaderCell>Name</TableHeaderCell>
|
|
||||||
<TableHeaderCell>Operation</TableHeaderCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
|
||||||
{dbOps.map((op, i) => {
|
|
||||||
let name: string;
|
|
||||||
let label: string;
|
|
||||||
let color: string;
|
|
||||||
let model: string;
|
|
||||||
|
|
||||||
if (op.type === 'dbCreate') {
|
|
||||||
label = 'create';
|
|
||||||
name = resolvedModelNameWithFolders(op.fs.model);
|
|
||||||
color = 'text-success';
|
|
||||||
model = modelTypeLabel(op.fs.model);
|
|
||||||
} else if (op.type === 'dbUpdate') {
|
|
||||||
label = 'update';
|
|
||||||
name = resolvedModelNameWithFolders(op.fs.model);
|
|
||||||
color = 'text-info';
|
|
||||||
model = modelTypeLabel(op.fs.model);
|
|
||||||
} else if (op.type === 'dbDelete') {
|
|
||||||
label = 'delete';
|
|
||||||
name = resolvedModelNameWithFolders(op.model);
|
|
||||||
color = 'text-danger';
|
|
||||||
model = modelTypeLabel(op.model);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
// biome-ignore lint/suspicious/noArrayIndexKey: none
|
|
||||||
<TableRow key={i}>
|
|
||||||
<TableCell>{model}</TableCell>
|
|
||||||
<TruncatedWideTableCell className="text-text">
|
|
||||||
{name}
|
|
||||||
</TruncatedWideTableCell>
|
|
||||||
<TableCell className="text-right">
|
|
||||||
<InlineCode className={color}>{label}</InlineCode>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
});
|
|
||||||
if (confirmed) {
|
|
||||||
await applySync(workspaceId, syncDir, ops);
|
await applySync(workspaceId, syncDir, ops);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showDialog({
|
||||||
|
id: 'commit-sync',
|
||||||
|
title: 'Changes Detected',
|
||||||
|
size: 'md',
|
||||||
|
render: ({ hide }) => (
|
||||||
|
<form
|
||||||
|
className="h-full grid grid-rows-[auto_auto_minmax(0,1fr)_auto] gap-3"
|
||||||
|
onSubmit={async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
await applySync(workspaceId, syncDir, ops);
|
||||||
|
hide();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isDeletingWorkspace ? (
|
||||||
|
<Banner color="danger">
|
||||||
|
🚨 <strong>Changes contain a workspace deletion!</strong>
|
||||||
|
</Banner>
|
||||||
|
) : (
|
||||||
|
<span />
|
||||||
|
)}
|
||||||
|
<p>
|
||||||
|
{pluralizeCount('file', dbOps.length)} in the directory{' '}
|
||||||
|
{dbOps.length === 1 ? 'has' : 'have'} changed. Do you want to update your workspace?
|
||||||
|
</p>
|
||||||
|
<Table scrollable className="my-4">
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableHeaderCell>Type</TableHeaderCell>
|
||||||
|
<TableHeaderCell>Name</TableHeaderCell>
|
||||||
|
<TableHeaderCell>Operation</TableHeaderCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{dbOps.map((op, i) => {
|
||||||
|
let name: string;
|
||||||
|
let label: string;
|
||||||
|
let color: string;
|
||||||
|
let model: string;
|
||||||
|
|
||||||
|
if (op.type === 'dbCreate') {
|
||||||
|
label = 'create';
|
||||||
|
name = resolvedModelNameWithFolders(op.fs.model);
|
||||||
|
color = 'text-success';
|
||||||
|
model = modelTypeLabel(op.fs.model);
|
||||||
|
} else if (op.type === 'dbUpdate') {
|
||||||
|
label = 'update';
|
||||||
|
name = resolvedModelNameWithFolders(op.fs.model);
|
||||||
|
color = 'text-info';
|
||||||
|
model = modelTypeLabel(op.fs.model);
|
||||||
|
} else if (op.type === 'dbDelete') {
|
||||||
|
label = 'delete';
|
||||||
|
name = resolvedModelNameWithFolders(op.model);
|
||||||
|
color = 'text-danger';
|
||||||
|
model = modelTypeLabel(op.model);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
// biome-ignore lint/suspicious/noArrayIndexKey: none
|
||||||
|
<TableRow key={i}>
|
||||||
|
<TableCell className="text-text-subtle">{model}</TableCell>
|
||||||
|
<TruncatedWideTableCell>{name}</TruncatedWideTableCell>
|
||||||
|
<TableCell className="text-right">
|
||||||
|
<InlineCode className={color}>{label}</InlineCode>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
<footer className="py-3 flex flex-row-reverse items-center gap-3">
|
||||||
|
<Button type="submit" color="primary">
|
||||||
|
Apply Changes
|
||||||
|
</Button>
|
||||||
|
<Button onClick={hide} color="secondary">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</footer>
|
||||||
|
</form>
|
||||||
|
),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -69,11 +69,7 @@ export function Dialog({
|
|||||||
animate={{ top: 0, scale: 1 }}
|
animate={{ top: 0, scale: 1 }}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
className,
|
className,
|
||||||
'grid',
|
'grid grid-rows-[auto_auto_minmax(0,1fr)]',
|
||||||
title != null && description != null && 'grid-rows-[auto_minmax(0,1fr)_minmax_(0,1fr)]',
|
|
||||||
title == null && description != null && 'grid-rows-[auto_minmax(0,1fr)]',
|
|
||||||
title != null && description == null && 'grid-rows-[auto_minmax(0,1fr)]',
|
|
||||||
title == null && description == null && 'grid-rows-[minmax(0,1fr)]',
|
|
||||||
'grid-cols-1', // must be here for inline code blocks to correctly break words
|
'grid-cols-1', // must be here for inline code blocks to correctly break words
|
||||||
'relative bg-surface pointer-events-auto',
|
'relative bg-surface pointer-events-auto',
|
||||||
'rounded-lg',
|
'rounded-lg',
|
||||||
@@ -87,16 +83,20 @@ export function Dialog({
|
|||||||
size === 'dynamic' && 'min-w-[20rem] max-w-[100vw]',
|
size === 'dynamic' && 'min-w-[20rem] max-w-[100vw]',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{title && (
|
{title ? (
|
||||||
<Heading className="px-6 mt-4 mb-2" level={1} id={titleId}>
|
<Heading className="px-6 mt-4 mb-2" level={1} id={titleId}>
|
||||||
{title}
|
{title}
|
||||||
</Heading>
|
</Heading>
|
||||||
|
) : (
|
||||||
|
<span />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{description && (
|
{description ? (
|
||||||
<div className="min-h-0 px-6 text-text-subtle mb-3" id={descriptionId}>
|
<div className="min-h-0 px-6 text-text-subtle mb-3" id={descriptionId}>
|
||||||
{description}
|
{description}
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
<span />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -106,20 +106,19 @@ function templateTags(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let invalid = false;
|
|
||||||
if (option.type === 'function') {
|
if (option.type === 'function') {
|
||||||
const tokens = parseTemplate(rawTag);
|
const tokens = parseTemplate(rawTag);
|
||||||
const values = collectArgumentValues(tokens, option);
|
const values = collectArgumentValues(tokens, option);
|
||||||
for (const arg of option.args) {
|
for (const arg of option.args) {
|
||||||
if (!('optional' in arg)) continue;
|
if (!('optional' in arg)) continue;
|
||||||
if (!arg.optional && values[arg.name] == null) {
|
if (!arg.optional && values[arg.name] == null) {
|
||||||
invalid = true;
|
option.invalid = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const widget = new TemplateTagWidget({ ...option, invalid }, rawTag, node.from);
|
const widget = new TemplateTagWidget(option, rawTag, node.from);
|
||||||
const deco = Decoration.replace({ widget, inclusive: true });
|
const deco = Decoration.replace({ widget, inclusive: true });
|
||||||
widgets.push(deco.range(node.from, node.to));
|
widgets.push(deco.range(node.from, node.to));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user