@anchrd/intel-ui 0.38.0 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -2
- package/src/access-summary/access-summary.tsx +1 -11
- package/src/app/app-tree/app-tree.tsx +37 -0
- package/src/board/board-assignee/board-assignee.ts +18 -0
- package/src/board/board-data/board-data.ts +31 -5
- package/src/board/board-data/board-data.types.ts +10 -1
- package/src/board/board-kanban/board-kanban.ts +63 -9
- package/src/board/board-kanban/board-kanban.tsx +371 -63
- package/src/board/board-panel/board-panel.tsx +222 -31
- package/src/board/board-settings/board-settings.tsx +209 -0
- package/src/board/board-stripes/board-stripes.ts +128 -0
- package/src/board/board-table/board-table.ts +23 -105
- package/src/board/board-table/board-table.tsx +436 -135
- package/src/board/board-task/board-task.ts +105 -0
- package/src/board/board-task/board-task.tsx +364 -0
- package/src/frontmatter/frontmatter.tsx +11 -2
- package/src/i18n/de.json +44 -3
- package/src/i18n/en.json +44 -3
- package/src/i18n/es.json +44 -3
- package/src/router/selection-search.ts +17 -2
- package/src/styles.css +29 -25
- package/src/user-name/user-name.ts +17 -0
package/src/i18n/es.json
CHANGED
|
@@ -33,8 +33,15 @@
|
|
|
33
33
|
"auth.signOutFailed": "El cierre de sesión ha fallado. Comprueba tu conexión e inténtalo de nuevo.",
|
|
34
34
|
"board.addCard": "+ Tarea",
|
|
35
35
|
"board.addCardIn": "Añadir una tarea a {column}",
|
|
36
|
-
"board.
|
|
36
|
+
"board.addLabel": "Añadir etiqueta",
|
|
37
|
+
"board.addLink": "Vínculo",
|
|
38
|
+
"board.cardLabel": "Abrir {title}, en {column}. Alt y una flecha la mueve.",
|
|
39
|
+
"board.column.archive": "Archivo",
|
|
37
40
|
"board.column.assignee": "Asignada a",
|
|
41
|
+
"board.column.default.backlog": "Backlog",
|
|
42
|
+
"board.column.default.doing": "En curso",
|
|
43
|
+
"board.column.default.done": "Hecho",
|
|
44
|
+
"board.column.default.todo": "Pendiente",
|
|
38
45
|
"board.column.dependsOn": "Espera a",
|
|
39
46
|
"board.column.due": "Vence",
|
|
40
47
|
"board.column.labels": "Etiquetas",
|
|
@@ -42,17 +49,51 @@
|
|
|
42
49
|
"board.column.title": "Título",
|
|
43
50
|
"board.columnEmpty": "Aquí todavía no hay nada.",
|
|
44
51
|
"board.createFailed": "No se pudo crear la tarea.",
|
|
52
|
+
"board.drag.lifted": "{card} recogida",
|
|
53
|
+
"board.drag.moved": "{card} movida a {column}",
|
|
54
|
+
"board.drag.putBack": "{card} devuelta",
|
|
55
|
+
"board.dragInstructions": "Arrastra una tarjeta con el ratón para moverla. Sin puntero: mantén Alt y pulsa una flecha — izquierda y derecha cambian de columna, arriba y abajo mueven dentro de una.",
|
|
45
56
|
"board.failed": "No se pudo cargar este tablero.",
|
|
46
57
|
"board.filter.all": "Todas las columnas",
|
|
47
58
|
"board.filter.status": "Mostrar columna",
|
|
48
59
|
"board.filterEmpty": "Ninguna tarjeta coincide con este filtro.",
|
|
49
|
-
"board.
|
|
60
|
+
"board.fromDate": "desde {date}",
|
|
61
|
+
"board.group.empty": "Sin valor",
|
|
50
62
|
"board.group.none": "Nada",
|
|
51
|
-
"board.group.status": "Columna",
|
|
52
63
|
"board.groupBy": "Agrupar por",
|
|
64
|
+
"board.link.blocker": "Espera a",
|
|
65
|
+
"board.link.outside": "Fuera de este tablero",
|
|
66
|
+
"board.link.subtask": "Subtarea",
|
|
67
|
+
"board.links": "Vinculado",
|
|
68
|
+
"board.moveTo": "Mover a una columna",
|
|
69
|
+
"board.progress": "{done} de {total} hechas",
|
|
70
|
+
"board.removeLabel": "Quitar la etiqueta {label}",
|
|
71
|
+
"board.settings.addColumn": "+ Columna",
|
|
72
|
+
"board.settings.columnName": "Nombre de la columna {column}",
|
|
73
|
+
"board.settings.description": "Columnas y lo que muestra el tablero.",
|
|
74
|
+
"board.settings.duplicateName": "Dos columnas se llaman {column}. Los nombres deben distinguirlas.",
|
|
75
|
+
"board.settings.failed": "No se pudieron guardar los ajustes.",
|
|
76
|
+
"board.settings.moveDown": "Bajar {column}",
|
|
77
|
+
"board.settings.moveUp": "Subir {column}",
|
|
78
|
+
"board.settings.newColumn": "Nueva columna",
|
|
79
|
+
"board.settings.open": "Ajustes del tablero",
|
|
80
|
+
"board.settings.remove": "Quitar {column}",
|
|
81
|
+
"board.settings.removeBlocked": "{column} no está vacía. Mueve sus tarjetas primero.",
|
|
82
|
+
"board.settings.showArchive": "Mostrar la columna de archivo",
|
|
83
|
+
"board.settings.showArchiveHint": "Está en todos los tableros. Oculta, sus tarjetas desaparecen de todas las vistas.",
|
|
84
|
+
"board.settings.title": "Ajustes del tablero",
|
|
85
|
+
"board.stripes.root": "Nivel {level}, tiene subtareas",
|
|
86
|
+
"board.stripes.under": "Nivel {level} · superior en {column}",
|
|
87
|
+
"board.table.collapse": "Ocultar lo que hay bajo {row}",
|
|
88
|
+
"board.table.columns": "Columnas",
|
|
89
|
+
"board.table.expand": "Mostrar lo que hay bajo {row}",
|
|
90
|
+
"board.table.filteredBy": "solo {column}",
|
|
91
|
+
"board.table.groupedBy": "agrupado por {column}",
|
|
53
92
|
"board.tableEmpty": "Este tablero aún no tiene tarjetas.",
|
|
93
|
+
"board.taskGone": "Esta tarjeta ya no está en este tablero. O está archivada, o ya no existe.",
|
|
54
94
|
"board.unassigned": "Nadie todavía",
|
|
55
95
|
"board.unknownColumn": "no está en este tablero",
|
|
96
|
+
"board.untilDate": "vence {date}",
|
|
56
97
|
"board.view.kanban": "Kanban",
|
|
57
98
|
"board.view.table": "Tabla",
|
|
58
99
|
"common.cancel": "Cancelar",
|
|
@@ -7,6 +7,14 @@ export type IntelView = (typeof IntelViews)[number];
|
|
|
7
7
|
export type SelectionSearch = Record<string, unknown> & {
|
|
8
8
|
select?: string;
|
|
9
9
|
view?: Exclude<IntelView, "editor">;
|
|
10
|
+
/**
|
|
11
|
+
* The card of the selected board that is open, by its node id.
|
|
12
|
+
*
|
|
13
|
+
* ⚠️ **Beside `select`, not instead of it.** A task is not a level of the tree the sidebar can
|
|
14
|
+
* select; it is something shown INSIDE the board that is selected. Carrying it as `select` would
|
|
15
|
+
* make the tree try to reveal a node it does not draw, and the back button would leave the board.
|
|
16
|
+
*/
|
|
17
|
+
task?: string;
|
|
10
18
|
};
|
|
11
19
|
|
|
12
20
|
// One search parameter carries "open this one" into an area: the header search names a hit, the
|
|
@@ -20,10 +28,12 @@ export type SelectionSearch = Record<string, unknown> & {
|
|
|
20
28
|
// ⚠️ Unknown parameters are passed through rather than dropped. The portal's connect flow returns
|
|
21
29
|
// to `/tools` with its own marker, and a validator that kept only what it knows would delete it.
|
|
22
30
|
export function selectionSearch(search: Record<string, unknown>): SelectionSearch {
|
|
23
|
-
const { select, view, ...rest } = search;
|
|
31
|
+
const { select, view, task, ...rest } = search;
|
|
24
32
|
const withSelect =
|
|
25
33
|
typeof select === "string" && select.length > 0 ? { ...rest, select } : { ...rest };
|
|
26
|
-
|
|
34
|
+
const withTask =
|
|
35
|
+
typeof task === "string" && task.length > 0 ? { ...withSelect, task } : withSelect;
|
|
36
|
+
return view === "graph" || view === "runs" ? { ...withTask, view } : withTask;
|
|
27
37
|
}
|
|
28
38
|
|
|
29
39
|
// Screens are lazy route components with no route object at hand, so they read the parameter off
|
|
@@ -41,3 +51,8 @@ export function viewFrom(search: unknown): IntelView {
|
|
|
41
51
|
export function graphViewFrom(search: unknown): boolean {
|
|
42
52
|
return viewFrom(search) === "graph";
|
|
43
53
|
}
|
|
54
|
+
|
|
55
|
+
export function openTaskFrom(search: unknown): string | null {
|
|
56
|
+
const task = (search as { task?: unknown } | null)?.task;
|
|
57
|
+
return typeof task === "string" && task.length > 0 ? task : null;
|
|
58
|
+
}
|
package/src/styles.css
CHANGED
|
@@ -44,20 +44,24 @@
|
|
|
44
44
|
grid of achromatic dots codes nothing, and neither does a graph whose blocked node looks like
|
|
45
45
|
its neighbour.
|
|
46
46
|
|
|
47
|
-
⚠️ A step
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
⚠️ **A step belongs to a FAMILY, not to a status and not to a depth.** Every card descending
|
|
48
|
+
from the same root task takes the same step, whatever column it sits in and however deep it
|
|
49
|
+
hangs — that is what lets somebody see that the card in `Backlog` belongs to the one in
|
|
50
|
+
`In progress`. Depth is carried by the NUMBER of stripes, never by the hue: two channels for
|
|
51
|
+
two questions.
|
|
52
52
|
|
|
53
|
-
⚠️
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
--board-
|
|
60
|
-
--board-
|
|
53
|
+
⚠️ **Six, and then they repeat.** Two families sharing a step is not a fault. At twenty root
|
|
54
|
+
tasks every other answer is a palette nobody can tell apart, and a colour that cannot be told
|
|
55
|
+
apart says less than none.
|
|
56
|
+
|
|
57
|
+
⚠️ Colour is never the only channel. Every card that carries stripes also names its level and
|
|
58
|
+
where its parent sits, in text, so a reader who does not see the difference reads it instead. */
|
|
59
|
+
--board-family-1: oklch(0.58 0.02 260);
|
|
60
|
+
--board-family-2: oklch(0.55 0.16 255);
|
|
61
|
+
--board-family-3: oklch(0.65 0.15 65);
|
|
62
|
+
--board-family-4: oklch(0.55 0.14 150);
|
|
63
|
+
--board-family-5: oklch(0.53 0.18 305);
|
|
64
|
+
--board-family-6: oklch(0.56 0.15 20);
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
.dark {
|
|
@@ -90,12 +94,12 @@
|
|
|
90
94
|
--sidebar-ring: oklch(0.556 0 0);
|
|
91
95
|
/* The same six steps, lifted for a dark surface. Same hues, same order — a board must not change
|
|
92
96
|
which colour a column has when the reader switches the appearance. */
|
|
93
|
-
--board-
|
|
94
|
-
--board-
|
|
95
|
-
--board-
|
|
96
|
-
--board-
|
|
97
|
-
--board-
|
|
98
|
-
--board-
|
|
97
|
+
--board-family-1: oklch(0.72 0.02 260);
|
|
98
|
+
--board-family-2: oklch(0.7 0.14 255);
|
|
99
|
+
--board-family-3: oklch(0.78 0.13 65);
|
|
100
|
+
--board-family-4: oklch(0.72 0.13 150);
|
|
101
|
+
--board-family-5: oklch(0.7 0.16 305);
|
|
102
|
+
--board-family-6: oklch(0.71 0.14 20);
|
|
99
103
|
}
|
|
100
104
|
|
|
101
105
|
@theme inline {
|
|
@@ -130,12 +134,12 @@
|
|
|
130
134
|
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
131
135
|
--color-sidebar-border: var(--sidebar-border);
|
|
132
136
|
--color-sidebar-ring: var(--sidebar-ring);
|
|
133
|
-
--color-board-
|
|
134
|
-
--color-board-
|
|
135
|
-
--color-board-
|
|
136
|
-
--color-board-
|
|
137
|
-
--color-board-
|
|
138
|
-
--color-board-
|
|
137
|
+
--color-board-family-1: var(--board-family-1);
|
|
138
|
+
--color-board-family-2: var(--board-family-2);
|
|
139
|
+
--color-board-family-3: var(--board-family-3);
|
|
140
|
+
--color-board-family-4: var(--board-family-4);
|
|
141
|
+
--color-board-family-5: var(--board-family-5);
|
|
142
|
+
--color-board-family-6: var(--board-family-6);
|
|
139
143
|
}
|
|
140
144
|
|
|
141
145
|
@layer base {
|
|
@@ -39,3 +39,20 @@ export function useUserName(userId: string | null): string | null {
|
|
|
39
39
|
if (userId === null || me === null || me.id !== userId) return null;
|
|
40
40
|
return displayNameOf(me);
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The one or two letters that stand for a name in a circle.
|
|
45
|
+
*
|
|
46
|
+
* ⚠️ Lives here rather than beside the circle that first needed it: two surfaces now draw the same
|
|
47
|
+
* circle — the access summary and a task's assignee — and two copies of this would drift into two
|
|
48
|
+
* different abbreviations of the same person.
|
|
49
|
+
*/
|
|
50
|
+
export function initials(value: string): string {
|
|
51
|
+
const parts = value
|
|
52
|
+
.replace(/@.*$/, "")
|
|
53
|
+
.split(/[\s._+-]+/)
|
|
54
|
+
.filter(Boolean);
|
|
55
|
+
if (parts.length === 0) return "?";
|
|
56
|
+
if (parts.length === 1) return (parts[0]?.slice(0, 2) ?? "?").toUpperCase();
|
|
57
|
+
return `${parts[0]?.[0] ?? ""}${parts.at(-1)?.[0] ?? ""}`.toUpperCase();
|
|
58
|
+
}
|