Architecture decisions: files, diagram references, views and panels
- *.archify-decision files: id (unique, words), title, status, date, elements, diagrams, supersedes, and prose; parsed, merged and link-checked in the model index; diagnostics on the file - diagrams point at decisions with decisions: [...] on the diagram, nodes and edges; stripped before Archify, unknown ids reported, completion, hover and go-to-definition for the ids and for elements/diagrams/ supersedes in decision files - Decisions panel on the main.archify page; Decisions rail panel under a diagram (hover lights up the node or connection); decisions on element cards and in the element dialog; decision view for the file, with a lost-model note outside a model - Archify | New Decision… command and template; editor schemas; the three New Model examples carry decisions; docs, changelog, 0.8.0
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { MODEL_EXAMPLES, mainFromExample } from '../language/examples';
|
||||
import { diagramName, invalidNameReason } from '../language/templates';
|
||||
import { DECISION_EXT, slugify } from '../model/decisions';
|
||||
import { MAIN_FILE } from '../model/format';
|
||||
import { DECISION_VIEW_TYPE } from '../views/decisionView';
|
||||
import { readText } from '../util/files';
|
||||
import { DIAGRAM_EDITOR_VIEW_TYPE } from '../views/diagramView';
|
||||
import { CommandContext, exists, targetUri } from './context';
|
||||
@@ -30,6 +32,38 @@ export function modelCommands(ctx: CommandContext): vscode.Disposable[] {
|
||||
await vscode.commands.executeCommand('vscode.openWith', vscode.Uri.joinPath(root, MAIN_FILE), DIAGRAM_EDITOR_VIEW_TYPE, vscode.ViewColumn.Active);
|
||||
}),
|
||||
|
||||
// Creates a decision file in the clicked folder of a model and opens it.
|
||||
vscode.commands.registerCommand('archify.newDecision', async (arg?: unknown) => {
|
||||
const folder = await parentFolder(arg);
|
||||
if (!folder) return;
|
||||
const root = await ctx.models.rootOf(vscode.Uri.joinPath(folder, 'x'));
|
||||
if (!root) {
|
||||
vscode.window.showWarningMessage(`Archify: ${vscode.workspace.asRelativePath(folder, true)} is not inside a model (no ${MAIN_FILE} in it or a folder above it). Decisions belong to a model.`);
|
||||
return;
|
||||
}
|
||||
const index = await ctx.models.index(root);
|
||||
const title = await vscode.window.showInputBox({
|
||||
title: 'Archify | New Decision',
|
||||
prompt: `Title of the decision (file goes into ${vscode.workspace.asRelativePath(folder, true)})`,
|
||||
placeHolder: 'OpenSearch for product search',
|
||||
validateInput: async (value) => {
|
||||
if (!value.trim()) return 'Enter a title.';
|
||||
const id = slugify(value);
|
||||
if (index.decisions.decisions.has(id)) return `A decision with id "${id}" already exists in this model.`;
|
||||
if (await exists(vscode.Uri.joinPath(folder, `${id}${DECISION_EXT}`))) return `${id}${DECISION_EXT} already exists.`;
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
if (title === undefined) return;
|
||||
const id = slugify(title);
|
||||
const target = vscode.Uri.joinPath(folder, `${id}${DECISION_EXT}`);
|
||||
const template = await readText(vscode.Uri.joinPath(ctx.extension.extensionUri, 'templates', 'decision.archify-decision'));
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
const text = template.replace('__ID__', id).replace('__TITLE__', JSON.stringify(title.trim())).replace('__DATE__', today);
|
||||
await vscode.workspace.fs.writeFile(target, Buffer.from(text, 'utf8'));
|
||||
await vscode.commands.executeCommand('vscode.openWith', target, DECISION_VIEW_TYPE);
|
||||
}),
|
||||
|
||||
// Creates a new model folder from one of the shipped examples and opens its model page.
|
||||
vscode.commands.registerCommand('archify.newModel', async (arg?: unknown) => {
|
||||
const picked = await vscode.window.showQuickPick(
|
||||
|
||||
Reference in New Issue
Block a user