diff --git a/addons/auth/addon/authenticators/password.js b/addons/auth/addon/authenticators/password.js index 7403eae65..aa0b13e87 100644 --- a/addons/auth/addon/authenticators/password.js +++ b/addons/auth/addon/authenticators/password.js @@ -93,19 +93,24 @@ export default class PasswordAuthenticator extends BaseAuthenticator { const authEndpointURL = this.buildAuthEndpointURL(options); const response = await fetch(authEndpointURL, { method: 'post', body }); const json = await response.json(); - return response.status < 400 ? resolve(this.normalizeData(json)) : reject(); + return response.status < 400 + ? resolve(this.normalizeData(json, login_name)) + : reject(); } /** * Normalizes the auth data. Adds convenience booleans depending on the * scope within which the session is authenticated: isGlobal, isOrg. + * If a `username` is provided, appends this to the data. * @param {object} data + * @param {string} username * @return {object} */ - normalizeData(data) { + normalizeData(data, username) { // Add booleans indicated the scope type data.isGlobal = (data?.scope?.type === 'global'); data.isOrg = (data?.scope?.type === 'org'); + if (username) data.username = username; return data; } diff --git a/addons/rose/addon/components/rose/nav/sidebar/index.hbs b/addons/rose/addon/components/rose/nav/sidebar/index.hbs index 40e3e9eaf..28250c8d6 100644 --- a/addons/rose/addon/components/rose/nav/sidebar/index.hbs +++ b/addons/rose/addon/components/rose/nav/sidebar/index.hbs @@ -2,6 +2,7 @@ ...attributes class="rose-nav-sidebar" id={{this.id}} + title={{@title}} aria-labelledby={{if @title (concat "title-" this.id)}}> {{#if @title}} diff --git a/addons/rose/addon/styles/rose/components/card/_link.scss b/addons/rose/addon/styles/rose/components/card/_link.scss index a62df13f8..c31ccbdbd 100644 --- a/addons/rose/addon/styles/rose/components/card/_link.scss +++ b/addons/rose/addon/styles/rose/components/card/_link.scss @@ -1,6 +1,8 @@ @use '../../variables/sizing'; @use '../../utilities/type'; +$xxxs: sizing.rems(xxxs); // 2 + .rose-card-link { @include type.type(s); border: sizing.rems(xxxxs) solid var(--ui-gray-subtler-2); @@ -9,6 +11,8 @@ display: inline-flex; flex-direction: column; margin: 0 sizing.rems(m) sizing.rems(m) 0; + box-shadow: 0 $xxxs $xxxs rgba(var(--stark-components), var(--opacity-4)), + 0 $xxxs $xxxs rgba(var(--stark-components), var(--opacity-4)); a { text-decoration: none; diff --git a/addons/rose/addon/styles/rose/components/header/_index.scss b/addons/rose/addon/styles/rose/components/header/_index.scss index 6ba8aba30..8885c0207 100644 --- a/addons/rose/addon/styles/rose/components/header/_index.scss +++ b/addons/rose/addon/styles/rose/components/header/_index.scss @@ -12,7 +12,12 @@ display: grid; grid-template-areas: 'brand nav utilities'; grid-template-columns: 0.01fr auto 1fr; - background: var(--black) linear-gradient(90deg, #191a1c 0%, #1b212d 100%); + background: var(--black); + box-shadow: inset 0 -#{sizing.rems(xxxxs)} 0 var(--ui-border-subtler-1); + + @media (prefers-color-scheme: light) { + box-shadow: none; + } } @media (max-width: media.width(small)) { diff --git a/addons/rose/addon/styles/rose/components/nav/_sidebar.scss b/addons/rose/addon/styles/rose/components/nav/_sidebar.scss index 010a3bd52..fcc29ca45 100644 --- a/addons/rose/addon/styles/rose/components/nav/_sidebar.scss +++ b/addons/rose/addon/styles/rose/components/nav/_sidebar.scss @@ -3,10 +3,20 @@ .rose-nav-sidebar { $threePX: sizing.rems(xxxs) + sizing.rems(xxxxs); + $yPadding: sizing.rems(xs); + padding-top: $yPadding; + padding-bottom: $yPadding; + border-bottom: sizing.rems(xxxxs) solid var(--ui-border-subtler-1); + + &:last-child { + border-bottom: 0; + } + + // TODO revisit the title .rose-nav-title { @include type.type(xs, semibold); - display: block; + display: none; color: var(--ui-gray); text-transform: uppercase; $lineHeight: 20 / 12; @@ -29,6 +39,7 @@ &.active { color: var(--action); border-color: currentColor; + background-color: var(--action-subtler-1h); } &:hover { diff --git a/addons/rose/addon/styles/rose/variables/color/_css.scss b/addons/rose/addon/styles/rose/variables/color/_css.scss index cb000c5df..5c910e93a 100644 --- a/addons/rose/addon/styles/rose/variables/color/_css.scss +++ b/addons/rose/addon/styles/rose/variables/color/_css.scss @@ -83,7 +83,7 @@ @media (prefers-color-scheme: dark) { :root { // poles - --subtle: #{darken(color(ui-gray, 900), 3%)}; + --subtle: var(--black); --stark: #{color(ui-gray, 100)}; --stark-components: 255, 255, 255; diff --git a/ui/core/app/routes/scopes/scope/authenticate.js b/ui/core/app/routes/scopes/scope/authenticate.js index d011a6b45..883bbb704 100644 --- a/ui/core/app/routes/scopes/scope/authenticate.js +++ b/ui/core/app/routes/scopes/scope/authenticate.js @@ -9,6 +9,17 @@ export default class ScopesScopeAuthenticateRoute extends Route { // =methods + beforeModel() { + if (this.session.isAuthenticated) { + const scope = this.modelFor('scopes.scope'); + if (scope.isGlobal) { + this.transitionTo('scopes.scope.orgs'); + } else { + this.transitionTo('scopes.scope.projects'); + } + } + } + /** * Returns all auth methods for the current scope, along with the current * scope and all scopes (for org navigation). @@ -28,15 +39,4 @@ export default class ScopesScopeAuthenticateRoute extends Route { // }]) }); } - - redirect() { - if (this.session.isAuthenticated) { - const scope = this.modelFor('scopes.scope'); - if (scope.isGlobal) { - this.transitionTo('scopes.scope.orgs'); - } else { - this.transitionTo('scopes.scope.projects'); - } - } - } } diff --git a/ui/core/app/styles/app.scss b/ui/core/app/styles/app.scss index 108e7c619..052ca77c0 100644 --- a/ui/core/app/styles/app.scss +++ b/ui/core/app/styles/app.scss @@ -19,7 +19,6 @@ } .rose-nav-sidebar { - margin-bottom: sizing.rems(l); margin-top: sizing.rems(xxl); & + .rose-nav-sidebar { @@ -77,7 +76,7 @@ &::after { animation: gradient 1s linear infinite; background: repeating-linear-gradient(to right, var(--subtle), var(--subtle), var(--info), var(--subtle), var(--subtle)); - background-position: 0 100%; + background-position: -100% 0; background-size: 200% auto; content: ' '; height: 3px; @@ -87,7 +86,7 @@ top: 100%; @keyframes gradient { - 0% { background-position: 0 0; } + 0% { background-position: -100% 0; } 100% { background-position: -200% 0; } } } @@ -96,9 +95,9 @@ .copyable { .copyable-button { + margin: 0; + padding: 0 sizing.rems(xxs); position: relative; top: -2px; - padding: 0 sizing.rems(xxs); - margin: 0; } } diff --git a/ui/core/app/templates/application.hbs b/ui/core/app/templates/application.hbs index 80472c19a..29dfe48eb 100644 --- a/ui/core/app/templates/application.hbs +++ b/ui/core/app/templates/application.hbs @@ -34,7 +34,7 @@ {{!-- diff --git a/ui/core/app/templates/scopes/scope/orgs/index.hbs b/ui/core/app/templates/scopes/scope/orgs/index.hbs index ed79b4e04..f073d3dcf 100644 --- a/ui/core/app/templates/scopes/scope/orgs/index.hbs +++ b/ui/core/app/templates/scopes/scope/orgs/index.hbs @@ -30,8 +30,8 @@ {{#each @model as |org|}} diff --git a/ui/core/app/templates/scopes/scope/projects/index.hbs b/ui/core/app/templates/scopes/scope/projects/index.hbs index 0d05ddf30..5995e29fe 100644 --- a/ui/core/app/templates/scopes/scope/projects/index.hbs +++ b/ui/core/app/templates/scopes/scope/projects/index.hbs @@ -30,8 +30,8 @@ {{#each @model as |project|}} diff --git a/ui/core/mirage/factories/org.js b/ui/core/mirage/factories/org.js deleted file mode 100644 index fe119cba6..000000000 --- a/ui/core/mirage/factories/org.js +++ /dev/null @@ -1,3 +0,0 @@ -import factory from '../generated/factories/org'; - -export default factory.extend(); diff --git a/ui/core/mirage/factories/project.js b/ui/core/mirage/factories/project.js deleted file mode 100644 index 2a3aae2be..000000000 --- a/ui/core/mirage/factories/project.js +++ /dev/null @@ -1,3 +0,0 @@ -import factory from '../generated/factories/project'; - -export default factory.extend(); diff --git a/ui/core/mirage/factories/scope.js b/ui/core/mirage/factories/scope.js index d60486d15..a14dbc719 100644 --- a/ui/core/mirage/factories/scope.js +++ b/ui/core/mirage/factories/scope.js @@ -5,6 +5,16 @@ export default factory.extend({ type: 'global', + /** + * Generates realistic-ish IDs while still being deterministic. + */ + id(i) { + let id = 'tv6fv3yz8p'; + if (i % 3) id = 'xk1i4dk50v'; + if (i % 2) id = 's9n819zgko'; + return `s_${id}${i}`; + }, + withChildren: trait({ afterCreate(record, server) { if (record.type === 'global') {