mirror of
https://github.com/different-ai/openwork
synced 2026-04-25 17:15:34 +02:00
refactor(web): polish cloud workers shell hierarchy
This commit is contained in:
@@ -134,12 +134,16 @@ body {
|
|||||||
width: calc(100vw - 3rem);
|
width: calc(100vw - 3rem);
|
||||||
max-width: none;
|
max-width: none;
|
||||||
min-height: calc(100vh - 8rem);
|
min-height: calc(100vh - 8rem);
|
||||||
border-radius: 1.15rem;
|
border-radius: 2rem;
|
||||||
|
background: transparent;
|
||||||
|
border-color: transparent;
|
||||||
|
box-shadow: none;
|
||||||
|
backdrop-filter: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-card-shell .ow-card-body {
|
.ow-card-shell .ow-card-body {
|
||||||
min-height: calc(100vh - 8rem);
|
min-height: calc(100vh - 8rem);
|
||||||
padding: 1rem;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-card-shell .ow-app-shell {
|
.ow-card-shell .ow-app-shell {
|
||||||
@@ -275,20 +279,21 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ow-btn-secondary {
|
.ow-btn-secondary {
|
||||||
border-radius: 0.78rem;
|
border-radius: 0.82rem;
|
||||||
border: 1px solid #ced8ef;
|
border: 1px solid #cbd5e1;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #1f3a8a;
|
color: #334155;
|
||||||
font-size: 0.84rem;
|
font-size: 0.84rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
padding: 0.72rem 0.84rem;
|
padding: 0.66rem 0.84rem;
|
||||||
transition: border-color 120ms ease, background-color 120ms ease;
|
transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-btn-secondary:hover:not(:disabled),
|
.ow-btn-secondary:hover:not(:disabled),
|
||||||
.ow-btn-icon:hover:not(:disabled) {
|
.ow-btn-icon:hover:not(:disabled) {
|
||||||
border-color: #9fb2eb;
|
border-color: rgba(27, 41, 255, 0.35);
|
||||||
background: #f5f8ff;
|
color: #1b29ff;
|
||||||
|
background: rgba(27, 41, 255, 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-btn-secondary:disabled,
|
.ow-btn-secondary:disabled,
|
||||||
@@ -306,12 +311,13 @@ body {
|
|||||||
|
|
||||||
.ow-app-shell {
|
.ow-app-shell {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.7rem;
|
gap: 1rem;
|
||||||
|
align-content: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 980px) {
|
@media (min-width: 980px) {
|
||||||
.ow-app-shell {
|
.ow-app-shell {
|
||||||
grid-template-columns: 7.4rem minmax(0, 0.95fr) minmax(0, 1.05fr);
|
grid-template-columns: 16rem 21rem minmax(0, 1fr);
|
||||||
align-items: start;
|
align-items: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,109 +327,119 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ow-app-nav {
|
.ow-app-nav {
|
||||||
border: 1px solid #dbe3f4;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 0.9rem;
|
border-radius: 2rem;
|
||||||
background: #f9fbff;
|
background: #fff;
|
||||||
padding: 0.5rem;
|
padding: 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.75rem;
|
gap: 1rem;
|
||||||
|
box-shadow: 0 6px 24px rgba(15, 23, 42, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-nav-group {
|
.ow-nav-group {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.34rem;
|
gap: 0.45rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-nav-label {
|
.ow-nav-label {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 0.66rem;
|
font-size: 0.62rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.08em;
|
letter-spacing: 0.12em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: #64748b;
|
color: #94a3b8;
|
||||||
padding-left: 0.22rem;
|
padding-left: 0.35rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-nav-item {
|
.ow-nav-item {
|
||||||
border: 1px solid #dbe3f4;
|
border: 1px solid transparent;
|
||||||
border-radius: 0.72rem;
|
border-radius: 0.92rem;
|
||||||
background: #fff;
|
background: transparent;
|
||||||
color: #334155;
|
color: #475569;
|
||||||
font-size: 0.8rem;
|
font-size: 0.85rem;
|
||||||
font-weight: 700;
|
font-weight: 600;
|
||||||
padding: 0.58rem 0.5rem;
|
padding: 0.66rem 0.75rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
transition: border-color 140ms ease, background-color 140ms ease, color 140ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ow-nav-item:hover {
|
||||||
|
border-color: #e2e8f0;
|
||||||
|
background: #f8fafc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-nav-item.is-active {
|
.ow-nav-item.is-active {
|
||||||
border-color: #9fb2eb;
|
border-color: rgba(27, 41, 255, 0.24);
|
||||||
color: #1e3a8a;
|
color: #1b29ff;
|
||||||
background: #edf3ff;
|
background: rgba(27, 41, 255, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-app-nav-footer {
|
.ow-app-nav-footer {
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
border-top: 1px solid #dbe3f4;
|
border-top: 1px solid #e2e8f0;
|
||||||
padding-top: 0.58rem;
|
padding-top: 0.9rem;
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.34rem;
|
gap: 0.42rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-nav-email {
|
.ow-nav-email {
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: #475569;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-pane {
|
.ow-pane {
|
||||||
border: 1px solid #dbe3f4;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 0.92rem;
|
border-radius: 2rem;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 0.72rem;
|
padding: 1.2rem;
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.6rem;
|
gap: 0.9rem;
|
||||||
align-content: start;
|
align-content: start;
|
||||||
|
box-shadow: 0 6px 24px rgba(15, 23, 42, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-pane-head {
|
.ow-pane-head {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.16rem;
|
gap: 0.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-pane-head-row {
|
.ow-pane-head-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 0.6rem;
|
gap: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-pane-block {
|
.ow-pane-block {
|
||||||
border: 1px solid #e3e9f7;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 0.86rem;
|
border-radius: 1.1rem;
|
||||||
background: #fbfcff;
|
background: #f8fafc;
|
||||||
padding: 0.62rem;
|
padding: 0.85rem;
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.55rem;
|
gap: 0.65rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-btn-compact {
|
.ow-btn-compact {
|
||||||
font-size: 0.78rem;
|
font-size: 0.79rem;
|
||||||
padding: 0.54rem 0.72rem;
|
padding: 0.58rem 0.88rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-filter-row {
|
.ow-filter-row {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1fr) auto;
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
gap: 0.5rem;
|
gap: 0.55rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-select {
|
.ow-select {
|
||||||
border-radius: 0.78rem;
|
border-radius: 0.9rem;
|
||||||
border: 1px solid #d9e1f2;
|
border: 1px solid #cbd5e1;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #334155;
|
color: #334155;
|
||||||
padding: 0.76rem 0.8rem;
|
padding: 0.74rem 0.82rem;
|
||||||
font-size: 0.86rem;
|
font-size: 0.86rem;
|
||||||
font-weight: 600;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-select:focus-visible {
|
.ow-select:focus-visible {
|
||||||
@@ -434,7 +450,7 @@ body {
|
|||||||
|
|
||||||
.ow-overview-grid {
|
.ow-overview-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.5rem;
|
gap: 0.65rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 700px) {
|
@media (min-width: 700px) {
|
||||||
@@ -444,28 +460,28 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ow-overview-card {
|
.ow-overview-card {
|
||||||
border: 1px solid #e3e9f7;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 0.86rem;
|
border-radius: 1.1rem;
|
||||||
background: #fbfcff;
|
background: #fff;
|
||||||
padding: 0.64rem;
|
padding: 0.9rem;
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.22rem;
|
gap: 0.32rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-overview-label {
|
.ow-overview-label {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 0.7rem;
|
font-size: 0.65rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #64748b;
|
color: #94a3b8;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.06em;
|
letter-spacing: 0.1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-overview-value {
|
.ow-overview-value {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 0.94rem;
|
font-size: 1rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #1e293b;
|
color: #0f172a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-overview-value.is-ready {
|
.ow-overview-value.is-ready {
|
||||||
@@ -488,26 +504,28 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ow-empty-detail {
|
.ow-empty-detail {
|
||||||
border: 1px dashed #d1ddef;
|
border: 1px dashed #cbd5e1;
|
||||||
border-radius: 0.82rem;
|
border-radius: 1.1rem;
|
||||||
background: #f9fbff;
|
background: #f8fafc;
|
||||||
padding: 0.9rem;
|
padding: 1.2rem;
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.35rem;
|
gap: 0.42rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 979px) {
|
@media (max-width: 979px) {
|
||||||
.ow-app-nav {
|
.ow-app-nav {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: flex-start;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
border-radius: 1.35rem;
|
||||||
|
padding: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-app-nav-footer {
|
.ow-app-nav-footer {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
padding-top: 0;
|
padding-top: 0.1rem;
|
||||||
align-items: end;
|
align-items: end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,13 +546,13 @@ body {
|
|||||||
.ow-caption {
|
.ow-caption {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: #64748b;
|
color: #64748b;
|
||||||
font-size: 0.76rem;
|
font-size: 0.78rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-link {
|
.ow-link {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #1e3a8a;
|
color: #1b29ff;
|
||||||
font-size: 0.78rem;
|
font-size: 0.79rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
@@ -550,10 +568,10 @@ body {
|
|||||||
.ow-paywall-box,
|
.ow-paywall-box,
|
||||||
.ow-lookup-box,
|
.ow-lookup-box,
|
||||||
.ow-log-box {
|
.ow-log-box {
|
||||||
border-radius: 0.92rem;
|
border-radius: 1rem;
|
||||||
border: 1px solid #dbe3f4;
|
border: 1px solid #e2e8f0;
|
||||||
background: #f9fbff;
|
background: #f8fafc;
|
||||||
padding: 0.78rem;
|
padding: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-note-box p,
|
.ow-note-box p,
|
||||||
@@ -566,7 +584,7 @@ body {
|
|||||||
.ow-note-box {
|
.ow-note-box {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.42rem;
|
gap: 0.42rem;
|
||||||
color: #334155;
|
color: #475569;
|
||||||
font-size: 0.82rem;
|
font-size: 0.82rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,17 +616,17 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ow-howto {
|
.ow-howto {
|
||||||
border: 1px solid #dbe3f4;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 0.75rem;
|
border-radius: 1rem;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 0.5rem;
|
padding: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-howto summary {
|
.ow-howto summary {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 0.78rem;
|
font-size: 0.82rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #1e3a8a;
|
color: #0f172a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-howto[open] {
|
.ow-howto[open] {
|
||||||
@@ -662,8 +680,8 @@ body {
|
|||||||
|
|
||||||
.ow-step-title {
|
.ow-step-title {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 0.78rem;
|
font-size: 0.86rem;
|
||||||
color: #1e293b;
|
color: #0f172a;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,9 +694,9 @@ body {
|
|||||||
.ow-paywall-title,
|
.ow-paywall-title,
|
||||||
.ow-section-title {
|
.ow-section-title {
|
||||||
margin: 0 0 0.5rem;
|
margin: 0 0 0.5rem;
|
||||||
font-size: 0.78rem;
|
font-size: 0.95rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #1e3a8a;
|
color: #0f172a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-full {
|
.ow-full {
|
||||||
@@ -711,9 +729,9 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ow-worker-list-panel {
|
.ow-worker-list-panel {
|
||||||
max-height: 17rem;
|
max-height: 58vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding-right: 0.1rem;
|
padding-right: 0.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-worker-select {
|
.ow-worker-select {
|
||||||
@@ -722,22 +740,24 @@ body {
|
|||||||
font: inherit;
|
font: inherit;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 1px solid #dbe3f4;
|
border: 1px solid #e2e8f0;
|
||||||
border-radius: 0.76rem;
|
border-radius: 1.2rem;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 0.56rem;
|
padding: 0.82rem;
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.4rem;
|
gap: 0.45rem;
|
||||||
|
transition: border-color 140ms ease, box-shadow 140ms ease, background-color 140ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-worker-select:hover {
|
.ow-worker-select:hover {
|
||||||
border-color: #9fb2eb;
|
border-color: #cbd5e1;
|
||||||
background: #f5f8ff;
|
background: #f8fafc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-worker-select.is-active {
|
.ow-worker-select.is-active {
|
||||||
border-color: #9fb2eb;
|
border-color: #1b29ff;
|
||||||
background: #f8fbff;
|
background: rgba(27, 41, 255, 0.04);
|
||||||
|
box-shadow: inset 3px 0 0 #1b29ff, 0 8px 22px rgba(27, 41, 255, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-worker-detail {
|
.ow-worker-detail {
|
||||||
@@ -773,37 +793,76 @@ body {
|
|||||||
|
|
||||||
.ow-worker-head {
|
.ow-worker-head {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 0.4rem;
|
gap: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-worker-meta {
|
.ow-worker-meta {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 0.72rem;
|
font-size: 0.72rem;
|
||||||
color: #475569;
|
color: #64748b;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
|
font-family: var(--font-ibm-plex-mono), "JetBrains Mono", "SF Mono", monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-badge {
|
.ow-badge {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: 999px;
|
border-radius: 0.45rem;
|
||||||
border: 1px solid #b8c8ec;
|
border: 1px solid #e2e8f0;
|
||||||
background: #edf3ff;
|
background: #f8fafc;
|
||||||
color: #1e3a8a;
|
color: #64748b;
|
||||||
font-size: 0.64rem;
|
font-size: 0.62rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.08em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
padding: 0.2rem 0.42rem;
|
padding: 0.2rem 0.45rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ow-worker-badges {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ow-status-pill {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 999px;
|
||||||
|
padding: 0.22rem 0.5rem;
|
||||||
|
font-size: 0.62rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ow-status-pill.is-ready {
|
||||||
|
background: #dcfce7;
|
||||||
|
color: #166534;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ow-status-pill.is-starting {
|
||||||
|
background: #fef3c7;
|
||||||
|
color: #92400e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ow-status-pill.is-attention {
|
||||||
|
background: #ffe4e6;
|
||||||
|
color: #9f1239;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ow-status-pill.is-other {
|
||||||
|
background: #e2e8f0;
|
||||||
|
color: #475569;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-inline-actions {
|
.ow-inline-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 0.48rem;
|
gap: 0.58rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-inline-actions > .ow-input {
|
.ow-inline-actions > .ow-input {
|
||||||
@@ -813,24 +872,34 @@ body {
|
|||||||
.ow-copy-row {
|
.ow-copy-row {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto;
|
grid-template-columns: 1fr auto;
|
||||||
gap: 0.46rem;
|
gap: 0.55rem;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-btn-icon {
|
.ow-btn-icon {
|
||||||
border-radius: 0.76rem;
|
border-radius: 0.75rem;
|
||||||
border: 1px solid #ced8ef;
|
border: 1px solid #cbd5e1;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #1f3a8a;
|
color: #334155;
|
||||||
font-size: 0.74rem;
|
font-size: 0.74rem;
|
||||||
font-weight: 700;
|
font-weight: 600;
|
||||||
padding: 0.66rem 0.75rem;
|
padding: 0.6rem 0.75rem;
|
||||||
min-width: 4.2rem;
|
min-width: 4.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-btn-primary-inline {
|
.ow-btn-primary-inline {
|
||||||
width: auto;
|
width: auto;
|
||||||
min-width: 12.5rem;
|
min-width: 0;
|
||||||
box-shadow: none;
|
}
|
||||||
|
|
||||||
|
.ow-open-btn {
|
||||||
|
min-width: 12.8rem;
|
||||||
|
box-shadow: 0 10px 24px rgba(27, 41, 255, 0.22);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ow-connection-block {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.38rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ow-log-box {
|
.ow-log-box {
|
||||||
|
|||||||
@@ -280,6 +280,18 @@ function getWorkerStatusCopy(status: string): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getWorkerAddressLabel(item: WorkerListItem): string {
|
||||||
|
if (!item.instanceUrl) {
|
||||||
|
return shortValue(item.workerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new URL(item.instanceUrl).host;
|
||||||
|
} catch {
|
||||||
|
return shortValue(item.instanceUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function isWorkerLaunch(value: unknown): value is WorkerLaunch {
|
function isWorkerLaunch(value: unknown): value is WorkerLaunch {
|
||||||
if (!isRecord(value)) {
|
if (!isRecord(value)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -530,11 +542,21 @@ function CredentialRow({
|
|||||||
onCopy: () => void;
|
onCopy: () => void;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<label className="ow-field-block">
|
<label className="grid gap-2">
|
||||||
<span className="ow-field-label">{label}</span>
|
<span className="px-0.5 text-[0.67rem] font-bold uppercase tracking-[0.11em] text-slate-500">{label}</span>
|
||||||
<div className="ow-copy-row">
|
<div className="flex items-center gap-2 rounded-xl border border-slate-200 bg-slate-50 p-1.5">
|
||||||
<input readOnly value={value ?? placeholder} className="ow-input ow-mono" onClick={(event) => event.currentTarget.select()} />
|
<input
|
||||||
<button type="button" className="ow-btn-icon" disabled={!canCopy} onClick={onCopy}>
|
readOnly
|
||||||
|
value={value ?? placeholder}
|
||||||
|
className="min-w-0 flex-1 border-none bg-transparent px-2 py-1.5 font-mono text-xs text-slate-700 outline-none"
|
||||||
|
onClick={(event) => event.currentTarget.select()}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="rounded-lg border border-slate-200 bg-white px-2.5 py-1 text-xs font-medium text-slate-600 transition hover:border-[#1B29FF] hover:text-[#1B29FF] disabled:cursor-not-allowed disabled:opacity-50"
|
||||||
|
disabled={!canCopy}
|
||||||
|
onClick={onCopy}
|
||||||
|
>
|
||||||
{copied ? "Copied" : canCopy ? "Copy" : "N/A"}
|
{copied ? "Copied" : canCopy ? "Copy" : "N/A"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -1375,7 +1397,7 @@ export function CloudControlPanel() {
|
|||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{step === 2 ? (
|
{step === 2 ? (
|
||||||
<div className="ow-app-shell">
|
<div className="ow-app-shell bg-[#F4F5F7] p-3 md:p-4 rounded-[32px]">
|
||||||
<aside className="ow-app-nav">
|
<aside className="ow-app-nav">
|
||||||
<div className="ow-nav-group">
|
<div className="ow-nav-group">
|
||||||
<p className="ow-nav-label">Workspace</p>
|
<p className="ow-nav-label">Workspace</p>
|
||||||
@@ -1412,8 +1434,12 @@ export function CloudControlPanel() {
|
|||||||
<p className="ow-section-title">Workers</p>
|
<p className="ow-section-title">Workers</p>
|
||||||
<p className="ow-caption">Pick a worker to see details.</p>
|
<p className="ow-caption">Pick a worker to see details.</p>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" className="ow-btn-secondary ow-btn-compact" onClick={() => setShowLaunchForm((current) => !current)}>
|
<button
|
||||||
{showLaunchForm ? "Hide launch" : "Launch worker"}
|
type="button"
|
||||||
|
className="ow-btn-primary ow-btn-compact ow-btn-primary-inline"
|
||||||
|
onClick={() => setShowLaunchForm((current) => !current)}
|
||||||
|
>
|
||||||
|
{showLaunchForm ? "Close" : "+ New Worker"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -1501,9 +1527,12 @@ export function CloudControlPanel() {
|
|||||||
<div className="ow-worker-head">
|
<div className="ow-worker-head">
|
||||||
<div>
|
<div>
|
||||||
<p className="ow-step-title">{item.workerName}</p>
|
<p className="ow-step-title">{item.workerName}</p>
|
||||||
<p className="ow-step-detail">{meta.label}</p>
|
<p className="ow-worker-meta">{getWorkerAddressLabel(item)}</p>
|
||||||
|
</div>
|
||||||
|
<div className="ow-worker-badges">
|
||||||
|
<span className={`ow-status-pill is-${meta.bucket}`}>{meta.label}</span>
|
||||||
|
{item.isMine ? <span className="ow-badge">Yours</span> : null}
|
||||||
</div>
|
</div>
|
||||||
{item.isMine ? <span className="ow-badge">Yours</span> : null}
|
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
@@ -1550,7 +1579,7 @@ export function CloudControlPanel() {
|
|||||||
<div className="ow-inline-actions">
|
<div className="ow-inline-actions">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="ow-btn-primary ow-btn-primary-inline"
|
className="ow-btn-primary ow-btn-primary-inline ow-open-btn"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!openworkDeepLink) {
|
if (!openworkDeepLink) {
|
||||||
return;
|
return;
|
||||||
@@ -1563,6 +1592,26 @@ export function CloudControlPanel() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="ow-connection-block">
|
||||||
|
<p className="ow-field-label">Connection URL</p>
|
||||||
|
<div className="ow-copy-row">
|
||||||
|
<input
|
||||||
|
readOnly
|
||||||
|
value={openworkConnectUrl ?? "Connection URL is still preparing..."}
|
||||||
|
className="ow-input ow-mono"
|
||||||
|
onClick={(event) => event.currentTarget.select()}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="ow-btn-icon"
|
||||||
|
disabled={!openworkConnectUrl}
|
||||||
|
onClick={() => void copyToClipboard("openwork-url", openworkConnectUrl)}
|
||||||
|
>
|
||||||
|
{copiedField === "openwork-url" ? "Copied" : "Copy"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{!openworkDeepLink || !openworkConnectUrl || (!hasWorkspaceScopedUrl && openworkConnectUrl) ? (
|
{!openworkDeepLink || !openworkConnectUrl || (!hasWorkspaceScopedUrl && openworkConnectUrl) ? (
|
||||||
<div className="ow-note-box">
|
<div className="ow-note-box">
|
||||||
{!openworkDeepLink ? <p className="ow-caption">Getting connection details ready...</p> : null}
|
{!openworkDeepLink ? <p className="ow-caption">Getting connection details ready...</p> : null}
|
||||||
@@ -1572,7 +1621,7 @@ export function CloudControlPanel() {
|
|||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<details className="ow-howto">
|
<details className="ow-howto">
|
||||||
<summary>Copy details manually</summary>
|
<summary>Manual connect details</summary>
|
||||||
<p className="ow-howto-copy">
|
<p className="ow-howto-copy">
|
||||||
If one-click open doesn't work, copy these into OpenWork: Add a worker > Connect remote.
|
If one-click open doesn't work, copy these into OpenWork: Add a worker > Connect remote.
|
||||||
</p>
|
</p>
|
||||||
@@ -1581,26 +1630,22 @@ export function CloudControlPanel() {
|
|||||||
value={openworkConnectUrl}
|
value={openworkConnectUrl}
|
||||||
placeholder="URL appears once ready"
|
placeholder="URL appears once ready"
|
||||||
canCopy={Boolean(openworkConnectUrl)}
|
canCopy={Boolean(openworkConnectUrl)}
|
||||||
copied={copiedField === "openwork-url"}
|
copied={copiedField === "manual-openwork-url"}
|
||||||
onCopy={() => void copyToClipboard("openwork-url", openworkConnectUrl)}
|
onCopy={() => void copyToClipboard("manual-openwork-url", openworkConnectUrl)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CredentialRow
|
<CredentialRow
|
||||||
label="Access token"
|
label="Access token"
|
||||||
value={activeWorker?.clientToken ?? null}
|
value={activeWorker?.clientToken ?? null}
|
||||||
placeholder="Use more options to refresh"
|
placeholder="Use Worker actions to refresh"
|
||||||
canCopy={Boolean(activeWorker?.clientToken)}
|
canCopy={Boolean(activeWorker?.clientToken)}
|
||||||
copied={copiedField === "access-token"}
|
copied={copiedField === "access-token"}
|
||||||
onCopy={() => void copyToClipboard("access-token", activeWorker?.clientToken ?? null)}
|
onCopy={() => void copyToClipboard("access-token", activeWorker?.clientToken ?? null)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<figure className="ow-connect-shot">
|
|
||||||
<img src="/connect-remote-menu.png" alt="OpenWork Add a worker menu with Connect remote option" />
|
|
||||||
</figure>
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details className="ow-howto">
|
<details className="ow-howto">
|
||||||
<summary>More options</summary>
|
<summary>Worker actions</summary>
|
||||||
<div className="ow-inline-actions">
|
<div className="ow-inline-actions">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -1630,7 +1675,7 @@ export function CloudControlPanel() {
|
|||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details className="ow-howto">
|
<details className="ow-howto">
|
||||||
<summary>Technical details</summary>
|
<summary>Advanced details</summary>
|
||||||
<CredentialRow
|
<CredentialRow
|
||||||
label="Worker host URL"
|
label="Worker host URL"
|
||||||
value={activeWorker?.instanceUrl ?? null}
|
value={activeWorker?.instanceUrl ?? null}
|
||||||
|
|||||||
Reference in New Issue
Block a user