feat: integrate todo note microservice and modularize frontend
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>UniDesk Control Plane</title>
|
||||
<link rel="stylesheet" href="/vendor/xyflow.css" />
|
||||
<link rel="stylesheet" href="/style.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -1015,7 +1015,130 @@ input:focus, select:focus, textarea:focus { border-color: var(--accent-2); }
|
||||
align-items: start;
|
||||
}
|
||||
.pipeline-grid .panel:nth-child(3), .pipeline-grid .panel:nth-child(5) { grid-column: 1 / -1; }
|
||||
.pipeline-node-table table { min-width: 1080px; }
|
||||
.pipeline-flow-frame {
|
||||
height: min(68vh, 720px);
|
||||
min-height: 520px;
|
||||
border: 1px solid var(--line-soft);
|
||||
background:
|
||||
radial-gradient(circle at 18% 22%, rgba(78, 183, 168, 0.11), transparent 30%),
|
||||
linear-gradient(135deg, rgba(215, 161, 58, 0.09), transparent 44%),
|
||||
#0b1319;
|
||||
}
|
||||
.pipeline-flow-frame .react-flow__pane { cursor: grab; }
|
||||
.pipeline-flow-frame .react-flow__controls {
|
||||
border: 1px solid var(--line);
|
||||
box-shadow: none;
|
||||
}
|
||||
.pipeline-flow-frame .react-flow__controls-button {
|
||||
border-bottom-color: var(--line-soft);
|
||||
background: #111a22;
|
||||
color: var(--text);
|
||||
}
|
||||
.pipeline-flow-frame .react-flow__controls-button svg { fill: currentColor; }
|
||||
.pipeline-flow-frame .react-flow__minimap {
|
||||
border: 1px solid var(--line);
|
||||
background: rgba(8, 13, 18, 0.88);
|
||||
}
|
||||
.pipeline-flow-frame .react-flow__edges {
|
||||
z-index: 5;
|
||||
}
|
||||
.pipeline-flow-frame .react-flow__nodes {
|
||||
z-index: 4;
|
||||
}
|
||||
.pipeline-flow-frame .react-flow__edge-path {
|
||||
stroke: rgba(129, 147, 159, 0.72);
|
||||
stroke-width: 2;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
filter: drop-shadow(0 0 5px rgba(78, 183, 168, 0.12));
|
||||
}
|
||||
.pipeline-flow-frame .react-flow__edge {
|
||||
opacity: 0.82;
|
||||
z-index: 12;
|
||||
}
|
||||
.pipeline-flow-frame .react-flow__edge:hover,
|
||||
.pipeline-flow-frame .react-flow__edge.selected {
|
||||
opacity: 1;
|
||||
}
|
||||
.pipeline-flow-frame .react-flow__edge:hover .react-flow__edge-path,
|
||||
.pipeline-flow-frame .react-flow__edge.selected .react-flow__edge-path {
|
||||
stroke-width: 2.8;
|
||||
}
|
||||
.pipeline-flow-frame .react-flow__edge.succeeded .react-flow__edge-path { stroke: var(--accent-2); }
|
||||
.pipeline-flow-frame .react-flow__edge.running .react-flow__edge-path { stroke: var(--accent); }
|
||||
.pipeline-flow-frame .react-flow__edge.failed .react-flow__edge-path { stroke: var(--danger); }
|
||||
.pipeline-flow-frame .pipeline-flow-handle {
|
||||
width: 9px;
|
||||
height: 18px;
|
||||
border: 1px solid rgba(78, 183, 168, 0.8);
|
||||
border-radius: 2px;
|
||||
background: #071016;
|
||||
}
|
||||
.pipeline-flow-frame .pipeline-flow-handle.input.top,
|
||||
.pipeline-flow-frame .pipeline-flow-handle.input.bottom {
|
||||
width: 18px;
|
||||
height: 9px;
|
||||
}
|
||||
.pipeline-flow-frame .pipeline-flow-handle.input.left { left: -6px; }
|
||||
.pipeline-flow-frame .pipeline-flow-handle.input.top { top: -6px; }
|
||||
.pipeline-flow-frame .pipeline-flow-handle.input.bottom { bottom: -6px; }
|
||||
.pipeline-flow-frame .pipeline-flow-handle.output.right {
|
||||
right: -6px;
|
||||
border-color: rgba(215, 161, 58, 0.86);
|
||||
}
|
||||
.pipeline-flow-node {
|
||||
width: 236px;
|
||||
border: 1px solid rgba(129, 147, 159, 0.4);
|
||||
background: linear-gradient(180deg, rgba(19, 29, 38, 0.98), rgba(10, 18, 24, 0.98));
|
||||
color: var(--text);
|
||||
box-shadow: 0 14px 34px rgba(0,0,0,0.32);
|
||||
}
|
||||
.pipeline-flow-node-body {
|
||||
position: relative;
|
||||
padding: 10px 12px;
|
||||
}
|
||||
.pipeline-flow-node.succeeded { border-color: rgba(78, 183, 168, 0.72); }
|
||||
.pipeline-flow-node.running { border-color: rgba(215, 161, 58, 0.82); }
|
||||
.pipeline-flow-node.failed { border-color: rgba(207, 106, 84, 0.78); }
|
||||
.pipeline-flow-node.quality-gate { background: linear-gradient(180deg, rgba(22, 38, 34, 0.98), rgba(10, 19, 17, 0.98)); }
|
||||
.pipeline-flow-node.control-block { background: linear-gradient(180deg, rgba(36, 31, 20, 0.98), rgba(17, 15, 11, 0.98)); }
|
||||
.flow-node-label {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
text-align: left;
|
||||
}
|
||||
.flow-node-label strong {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: var(--text);
|
||||
font-size: 12px;
|
||||
}
|
||||
.flow-node-label span {
|
||||
color: var(--muted);
|
||||
font-size: 10px;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.flow-node-label code {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: var(--accent);
|
||||
}
|
||||
.pipeline-flow-summary {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-top: 8px;
|
||||
color: var(--muted);
|
||||
}
|
||||
.pipeline-flow-summary span {
|
||||
padding: 3px 7px;
|
||||
border: 1px solid var(--line-soft);
|
||||
background: rgba(255,255,255,0.03);
|
||||
}
|
||||
.component-strata {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(128px, 1fr));
|
||||
@@ -1268,3 +1391,300 @@ input:focus, select:focus, textarea:focus { border-color: var(--accent-2); }
|
||||
.compact-row, .heartbeat-row, .log-row, .endpoint-list article, .volume-route, .findjob-hero, .pipeline-hero { grid-template-columns: 1fr; align-items: start; }
|
||||
.docker-hero, .monitor-hero { flex-direction: column; }
|
||||
}
|
||||
|
||||
.shell.rail-collapsed {
|
||||
grid-template-columns: 58px minmax(0, 1fr);
|
||||
}
|
||||
.rail-toggle {
|
||||
margin-left: auto;
|
||||
min-width: 24px;
|
||||
height: 24px;
|
||||
border: 1px solid var(--line-soft);
|
||||
color: var(--muted);
|
||||
background: rgba(0,0,0,0.18);
|
||||
}
|
||||
.rail-toggle:hover { color: var(--text); border-color: var(--accent); }
|
||||
.rail.collapsed {
|
||||
padding-inline: 8px;
|
||||
}
|
||||
.rail.collapsed .brand {
|
||||
justify-content: center;
|
||||
padding-inline: 0;
|
||||
}
|
||||
.rail.collapsed .brand-text,
|
||||
.rail.collapsed .module > span:not(.module-code) {
|
||||
display: none;
|
||||
}
|
||||
.rail.collapsed .rail-toggle {
|
||||
position: absolute;
|
||||
top: 44px;
|
||||
left: 8px;
|
||||
width: 40px;
|
||||
}
|
||||
.rail.collapsed .module {
|
||||
grid-template-columns: 1fr;
|
||||
justify-items: center;
|
||||
min-height: 38px;
|
||||
padding: 7px 4px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.rail.collapsed .module-code {
|
||||
font-size: 10px;
|
||||
letter-spacing: 0.08em;
|
||||
}
|
||||
|
||||
.todo-note-page {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
.todo-note-hero {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(280px, 1.35fr) minmax(260px, 0.9fr) minmax(220px, 0.7fr);
|
||||
gap: 8px;
|
||||
align-items: stretch;
|
||||
}
|
||||
.todo-note-layout {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(260px, 0.52fr) minmax(680px, 1.8fr);
|
||||
gap: 10px;
|
||||
align-items: start;
|
||||
}
|
||||
.todo-list-panel .panel-body,
|
||||
.todo-main-stack .panel-body {
|
||||
min-width: 0;
|
||||
}
|
||||
.todo-create-list,
|
||||
.todo-add-form {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
}
|
||||
.todo-instance-list {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
margin-top: 8px;
|
||||
max-height: calc(100vh - 310px);
|
||||
overflow: auto;
|
||||
}
|
||||
.todo-instance-row {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 2px 8px;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--line-soft);
|
||||
color: var(--muted);
|
||||
background: var(--panel-3);
|
||||
text-align: left;
|
||||
}
|
||||
.todo-instance-row.active,
|
||||
.todo-instance-row:hover {
|
||||
color: var(--text);
|
||||
border-color: var(--accent-2);
|
||||
background: rgba(78, 183, 168, 0.09);
|
||||
}
|
||||
.todo-instance-row strong {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.todo-instance-row code {
|
||||
grid-column: 1 / -1;
|
||||
color: #bcd2d7;
|
||||
}
|
||||
.todo-workbench {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
font-size: var(--todo-font-size, 13px);
|
||||
}
|
||||
.todo-toolbar {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(260px, 1fr) auto auto;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
.todo-filter-strip,
|
||||
.todo-toolbar-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
align-items: center;
|
||||
}
|
||||
.todo-filter {
|
||||
min-height: 28px;
|
||||
padding: 4px 8px;
|
||||
border: 1px solid var(--line);
|
||||
color: var(--muted);
|
||||
background: rgba(12, 18, 24, 0.62);
|
||||
}
|
||||
.todo-filter.active,
|
||||
.todo-filter:hover {
|
||||
color: var(--text);
|
||||
border-color: var(--accent-2);
|
||||
background: rgba(78, 183, 168, 0.11);
|
||||
}
|
||||
.todo-font-control {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
color: var(--muted);
|
||||
}
|
||||
.todo-font-control input { width: 86px; padding: 0; }
|
||||
.todo-stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 8px;
|
||||
}
|
||||
.todo-root-drop {
|
||||
padding: 6px 8px;
|
||||
border: 1px dashed var(--line);
|
||||
color: var(--muted);
|
||||
background: rgba(255,255,255,0.02);
|
||||
}
|
||||
.todo-tree {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
max-height: calc(100vh - 398px);
|
||||
min-height: 280px;
|
||||
overflow: auto;
|
||||
align-content: start;
|
||||
}
|
||||
.todo-row-wrap {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
}
|
||||
.todo-row {
|
||||
display: grid;
|
||||
grid-template-columns: 28px 24px minmax(240px, 1fr) 178px minmax(360px, auto);
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
margin-left: calc(var(--todo-depth, 0) * 18px);
|
||||
padding: 6px;
|
||||
border: 1px solid var(--line-soft);
|
||||
background: var(--panel-3);
|
||||
}
|
||||
.todo-row.completed {
|
||||
opacity: 0.76;
|
||||
}
|
||||
.todo-row.completed .todo-title-cell strong {
|
||||
text-decoration: line-through;
|
||||
color: var(--muted);
|
||||
}
|
||||
.todo-row.dragging {
|
||||
border-color: var(--accent);
|
||||
background: rgba(215, 161, 58, 0.08);
|
||||
}
|
||||
.todo-expand {
|
||||
min-width: 24px;
|
||||
height: 24px;
|
||||
border: 1px solid var(--line-soft);
|
||||
color: var(--muted);
|
||||
background: rgba(0,0,0,0.14);
|
||||
}
|
||||
.todo-expand:disabled { opacity: 0.45; cursor: default; }
|
||||
.todo-title-cell {
|
||||
min-width: 0;
|
||||
display: grid;
|
||||
gap: 3px;
|
||||
}
|
||||
.todo-title-cell strong {
|
||||
overflow-wrap: anywhere;
|
||||
color: var(--text);
|
||||
font-size: var(--todo-font-size, 13px);
|
||||
}
|
||||
.todo-meta-line {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
color: var(--muted);
|
||||
font-size: 11px;
|
||||
}
|
||||
.todo-reminder { color: var(--accent); }
|
||||
.todo-reminder-input {
|
||||
min-width: 176px;
|
||||
padding: 5px 6px;
|
||||
}
|
||||
.todo-row-actions,
|
||||
.todo-edit-inline {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
}
|
||||
.todo-row-actions .ghost-btn {
|
||||
min-height: 24px;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
.todo-children {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
@media (max-width: 1120px) {
|
||||
.todo-note-layout,
|
||||
.todo-note-hero,
|
||||
.todo-toolbar {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.todo-row {
|
||||
grid-template-columns: 28px 24px minmax(220px, 1fr);
|
||||
}
|
||||
.todo-reminder-input,
|
||||
.todo-row-actions {
|
||||
grid-column: 3;
|
||||
}
|
||||
.todo-stats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.shell.rail-collapsed {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
}
|
||||
.rail.collapsed {
|
||||
height: 42px;
|
||||
padding: 4px 6px;
|
||||
}
|
||||
.rail.collapsed .brand {
|
||||
justify-content: flex-start;
|
||||
padding: 0 8px 0 0;
|
||||
}
|
||||
.rail.collapsed .rail-toggle {
|
||||
position: static;
|
||||
width: 24px;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.rail.collapsed .module {
|
||||
width: auto;
|
||||
min-width: 88px;
|
||||
min-height: 30px;
|
||||
grid-template-columns: auto 1fr;
|
||||
justify-items: start;
|
||||
gap: 5px;
|
||||
padding: 4px 8px;
|
||||
margin: 0;
|
||||
}
|
||||
.rail.collapsed .module > span:not(.module-code) {
|
||||
display: inline;
|
||||
}
|
||||
.todo-stats-grid,
|
||||
.todo-create-list,
|
||||
.todo-add-form {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.todo-tree {
|
||||
max-height: none;
|
||||
min-height: 220px;
|
||||
}
|
||||
.todo-row {
|
||||
grid-template-columns: 24px minmax(0, 1fr);
|
||||
margin-left: 0;
|
||||
}
|
||||
.todo-row > input[type="checkbox"] { grid-column: 1; }
|
||||
.todo-title-cell,
|
||||
.todo-reminder-input,
|
||||
.todo-row-actions {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user