Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions datamanager-app/frontend/themes/datamanager/components/all.css
Original file line number Diff line number Diff line change
Expand Up @@ -1540,3 +1540,113 @@ states, and modal-like overlays that sit inside a flex container.
justify-content: center;
}
/*endregion*/

/* ── External Providers card styling ────── */

/* Give the page breathing room — the .main grid has no
inherent padding, so we add it here. */
.external-providers {
padding: var(--lumo-space-l);
}

.external-providers .external-providers__content {
max-width: 800px;
}

.external-providers .instance-card {
display: flex;
flex-direction: column;
border-radius: var(--lumo-border-radius-m);
background-color: var(--lumo-base-color);
border: 1px solid var(--lumo-contrast-20pct);
border-left-width: 8px;
overflow: hidden;
}

.external-providers .instance-card + .instance-card {
margin-top: var(--lumo-space-m);
}

.external-providers .instance-card--connected {
border-left-color: var(--lumo-success-color);
}

.external-providers .instance-card--not-connected {
border-left-color: var(--lumo-contrast-30pct);
}

.external-providers .instance-card--invalidated {
border-left-color: var(--lumo-error-color);
}

.external-providers .instance-card__header {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: space-between;
gap: var(--lumo-space-m);
padding: var(--lumo-space-l) var(--lumo-space-l) 0 var(--lumo-space-l);
}

.external-providers .instance-card__identity {
display: flex;
flex-direction: column;
gap: 2px;
flex-grow: 1;
min-width: 0;
}

.external-providers .instance-card__action {
flex-shrink: 0;
}

.external-providers .instance-card__url {
color: var(--lumo-primary-text-color);
text-decoration: none;
}

.external-providers .instance-card__url:hover {
text-decoration: underline;
}

.external-providers .instance-card__body {
display: flex;
flex-direction: column;
gap: var(--lumo-space-s);
padding: var(--lumo-space-m) var(--lumo-space-l) var(--lumo-space-l) var(--lumo-space-l);
}

.external-providers .instance-card__status-line {
display: flex;
align-items: center;
gap: var(--lumo-space-s);
}

.external-providers .instance-card__description {
color: var(--lumo-secondary-text-color);
font-size: var(--lumo-font-size-s);
line-height: 1.5;
margin: 0;
}

.external-providers .security-note {
color: var(--lumo-tertiary-text-color);
font-size: var(--lumo-font-size-xs);
font-style: italic;
}

/* Toolbar — right-aligned with heading */

.external-providers .external-providers__toolbar {
display: flex;
justify-content: flex-end;
padding: var(--lumo-space-m) 0 var(--lumo-space-l) 0;
}

/* Button group for side-by-side Reconnect + Disconnect */

.external-providers .instance-card__action-group {
display: flex;
gap: var(--lumo-space-xs);
flex-shrink: 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
@import "virtuallist.css";
@import "toast.css";
@import "grid-templates.css";
@import "verification-sidebar.css";

vaadin-avatar-group vaadin-avatar,
.user-avatar {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -867,3 +867,86 @@ vaadin-upload-file::part(meta){
border-radius: var(--lumo-border-radius-l);
padding: var(--lumo-space-m);
}

/* ─ External Providers: Add Token dialog — loading overlay ───
*
* The `position: absolute; inset: 0` positions the overlay to exactly
* fill the nearest positioned ancestor. We declare `.dialog-app { position:
* relative }` in all.css so the AppDialog body slot becomes that ancestor,
* meaning `inset: 0` covers the body area without any min-height hacks.
*/

.token-loading-overlay {
position: absolute;
inset: 0;
background-color: var(--lumo-base-color);
z-index: 10;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: var(--lumo-space-m);
}

/*
* Pure-CSS four-dots rotating spinner (Spinner II, Temani Afif).
* A single grid div with two pseudo-elements; each carries four dots
* at the cardinal points. The outer ring (::after, larger dots, slower
* animation) and the inner ring (::before, smaller dots, margin-inset,
* linear timing) rotate at slightly different rates to produce the
* characteristic "four-dots orbit" effect.
*
* CSS variables allow theming from outside:
* --spinner-outer (default: Lumo primary color)
* --spinner-inner (default: secondary teal accent)
*
* Credit: https://codepen.io/t_afif/pen/yLMXBRL (Spinner #2)
*/
.token-loading-overlay .spinner {
width: 48px;
aspect-ratio: 1;
display: grid;
--spinner-outer: var(--lumo-primary-color);
--spinner-inner: #00acac;
}

.token-loading-overlay .spinner::after {
content: "";
grid-area: 1 / 1;
--c: radial-gradient(farthest-side, var(--spinner-outer) 92%, #0000);
background:
var(--c) 50% 0,
var(--c) 50% 100%,
var(--c) 100% 50%,
var(--c) 0 50%;
background-size: 12px 12px;
background-repeat: no-repeat;
animation: token-spin-half 1s infinite;
}

.token-loading-overlay .spinner::before {
content: "";
grid-area: 1 / 1;
margin: 4px;
--c: radial-gradient(farthest-side, var(--spinner-inner) 92%, #0000);
background:
var(--c) 50% 0,
var(--c) 50% 100%,
var(--c) 100% 50%,
var(--c) 0 50%;
background-size: 8px 8px;
background-repeat: no-repeat;
animation: token-spin-half 1s infinite linear;
}

@keyframes token-spin-half {
100% { transform: rotate(0.5turn); }
}

.token-loading-overlay .token-loading-label {
font-weight: var(--font-weight-medium);
}

.token-loading-overlay .token-loading-hint {
color: var(--lumo-tertiary-text-color);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/* ── Verification Sidebar ────── */

.verification-sidebar {
position: fixed;
inset: 0;
z-index: 100;
pointer-events: none;
}

/* Backdrop */

.verification-sidebar .vs-backdrop {
position: absolute;
inset: 0;
background-color: var(--lumo-shade-20pct);
opacity: 0;
pointer-events: none;
}

.verification-sidebar.vs-open .vs-backdrop {
pointer-events: auto;
opacity: 1;
}

/* Slide-in panel */

.verification-sidebar .vs-panel {
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 480px;
max-width: 90vw;
background-color: var(--lumo-base-color);
box-shadow: var(--lumo-box-shadow-l);
z-index: 2;
display: flex;
flex-direction: column;
pointer-events: auto;
}

/* Layout: Header / Content / Footer */

.verification-sidebar .vs-body {
box-sizing: border-box;
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
}

.verification-sidebar .vs-header {
display: flex;
align-items: center;
gap: var(--lumo-space-s);
flex-shrink: 0;
padding: var(--lumo-space-m) var(--lumo-space-l);
border-bottom: 1px solid var(--lumo-contrast-10pct);
}

.verification-sidebar .vs-title {
flex-grow: 1;
}

.verification-sidebar .vs-content {
flex-grow: 1;
flex-direction: column;
display: flex;
overflow-y: auto;
padding: var(--lumo-space-l);
min-height: 0;
gap: var(--lumo-space-s);
}

.verification-sidebar .vs-footer {
flex-shrink: 0;
border-top: 1px solid var(--lumo-contrast-10pct);
padding: var(--lumo-space-m) var(--lumo-space-l);
}

/* Provider rows */

.verification-sidebar .vs-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--lumo-space-m);
padding: var(--lumo-space-s) var(--lumo-space-m);
border: 1px solid var(--lumo-contrast-10pct);
border-radius: var(--lumo-border-radius-m);
background-color: var(--lumo-base-color);
}

.verification-sidebar .vs-row--valid {
border-left: 4px solid var(--lumo-success-color);
}

.verification-sidebar .vs-row--invalid {
border-left: 4px solid var(--lumo-error-color);
}

.verification-sidebar .vs-row--pending {
border-left: 4px solid var(--lumo-contrast-20pct);
}

/* Skipped row — provider has no token; no validation is attempted.
Dashed left accent visually separates it from rows that actually
went through the verification pipeline. */

.verification-sidebar .vs-row--skipped {
border-left: 4px dashed var(--lumo-contrast-10pct);
background-color: var(--lumo-contrast-5pct);
}

.verification-sidebar .vs-status--skipped {
color: var(--lumo-tertiary-text-color);
opacity: 0.7;
}

/* Status-label variants — keep the message visually tied to its icon. */

.verification-sidebar .vs-status-label--pending {
color: var(--lumo-tertiary-text-color);
}

.verification-sidebar .vs-status-label--valid {
color: var(--lumo-success-text-color);
font-weight: 500;
}

.verification-sidebar .vs-status-label--invalid {
color: var(--lumo-error-text-color);
font-weight: 500;
}

/* Reason shown below the provider name for invalid rows. */

.verification-sidebar .vs-invalid-reason {
display: block;
color: var(--lumo-tertiary-text-color);
font-size: var(--lumo-font-size-xs);
margin-top: 2px;
}

.verification-sidebar .vs-row__identity {
display: flex;
flex-direction: column;
gap: 2px;
flex-grow: 1;
min-width: 0;
}

.verification-sidebar .vs-row__name {
font-weight: 600;
}

.verification-sidebar .vs-row__status {
display: flex;
align-items: center;
gap: var(--lumo-space-xs);
}

.verification-sidebar .vs-spinner {
width: 1.2em;
height: 1.2em;
border: 2px solid var(--lumo-contrast-20pct);
border-top-color: var(--lumo-primary-color);
border-radius: 50%;
animation: vs-spin 0.8s linear infinite;
}

@keyframes vs-spin {
to { transform: rotate(360deg); }
}

.verification-sidebar .vs-row__actions {
display: flex;
gap: var(--lumo-space-xs);
flex-shrink: 0;
}

/* Inline Reconnect link — tertiary, so it doesn't compete with
the Reconnect button on the main-view card. */

.verification-sidebar .vs-reconnect-link {
font-size: var(--lumo-font-size-s);
}
Binary file modified datamanager-app/src/main/bundles/dev.bundle
Binary file not shown.
Loading
Loading