From e36b701812c9c79189f51b899dbafb20aa78b35e Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Tue, 1 Oct 2024 20:03:49 +0200 Subject: [PATCH] feat(web): Improve UI styling and add registration prompt --- changelog.md | 7 + ts/00_commitinfo_data.ts | 2 +- ts_web/00_commitinfo_data.ts | 2 +- ts_web/elements/idp-logincontainer.ts | 32 ++--- ts_web/elements/idp-loginprompt.ts | 124 ++++------------- ts_web/elements/idp-registerprompt.ts | 189 ++++++++++++++++++++++++++ ts_web/elements/idp-welcome.ts | 7 +- 7 files changed, 247 insertions(+), 116 deletions(-) create mode 100644 ts_web/elements/idp-registerprompt.ts diff --git a/changelog.md b/changelog.md index cd3195b..3769e3d 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # Changelog +## 2024-10-01 - 1.2.0 - feat(web) +Improve UI styling and add registration prompt + +- Updated max-width of login container to improve layout consistency +- Added new component for user registration +- Improved styling for various elements including buttons and text boxes + ## 2024-10-01 - 1.1.1 - fix(core) Corrected typos and added missing keywords. diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index feceae8..07cacba 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@idp.global/idp.global', - version: '1.1.1', + version: '1.2.0', description: 'An identity provider software managing user authentications, registrations, and sessions.' } diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index feceae8..07cacba 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@idp.global/idp.global', - version: '1.1.1', + version: '1.2.0', description: 'An identity provider software managing user authentications, registrations, and sessions.' } diff --git a/ts_web/elements/idp-logincontainer.ts b/ts_web/elements/idp-logincontainer.ts index 885129c..700a373 100644 --- a/ts_web/elements/idp-logincontainer.ts +++ b/ts_web/elements/idp-logincontainer.ts @@ -88,31 +88,31 @@ export class IdpLogincontainer extends DeesElement { } .loginblock { - max-width: 520px; + max-width: 500px; flex-grow: 1; transform: translate3d(0px, 0px, 0px); transition: all 0.2s; box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2); - background: ${cssManager.bdTheme('#ffffff', '#181818')}; - border-top: 1px solid ${cssManager.bdTheme('#ffffff', '#333333')}; + background: ${cssManager.bdTheme('#ffffff', '#111111')}; + border-top: 1px solid ${cssManager.bdTheme('#ffffff', '#222222')}; border-radius: 16px; overflow: hidden; } - img { - width: 130px; - min-height: 34.9px; - display: block; - margin: auto; - margin-top: 16px; - margin-bottom: 25px; - filter: ${cssManager.bdTheme('invert(1)', '')}; + h1 { + font-size: 24px; + font-family: 'Cal Sans'; + text-align: center; + letter-spacing:0.0125em; + } + + .contentSpacer { + padding: 0px 0px 16px 0px; } .legalinfo { text-align: center; margin: auto; - margin-top: 10px; color: ${cssManager.bdTheme('#666', '#ccc')}; font-size: 12px; line-height: 100%; @@ -133,10 +133,10 @@ export class IdpLogincontainer extends DeesElement { return html`
- - +

idp.global

+
+ +
Legal Info | Company Website diff --git a/ts_web/elements/idp-loginprompt.ts b/ts_web/elements/idp-loginprompt.ts index edd90e0..bd35cdf 100644 --- a/ts_web/elements/idp-loginprompt.ts +++ b/ts_web/elements/idp-loginprompt.ts @@ -27,10 +27,6 @@ declare global { @customElement('idp-login') export class IdpLogin extends DeesElement { public static demo = () => html``; - public static receptionUrl = 'https://reception.lossless.one/typedrequest'; - - @property() - public activePane: 'login' | 'register' = 'login'; @property() public productOfInterest: string; @@ -60,109 +56,43 @@ export class IdpLogin extends DeesElement { color: ${cssManager.bdTheme('#333333', '#ffffff')}; } - .box { - opacity: 0; - cursor: pointer; - overflow: hidden; - transition: all 0.2s ease; - height: 0px; - } - - .box.active { - opacity: 1 !important; - height: 360px; - cursor: auto; - } - - .loginbox { - } - - .registerbox { - } - .boxcontent { margin: 0px 20px; } - .info { - text-align: center; - padding: 32px; - line-height: 1.5em; - font-size: 12px; - font-weight: 600; - color: #999; - } - .registerButton { - display: block; - transition: all 0.2s ease; - will-change: transform; - cursor: pointer; - } - - .registerButton:hover { - color: #fff; - transform: scale(1.02); + margin-top: 16px; } `, ]; public render(): TemplateResult { return html` -
-
- - - - -
- You'll go here: ${this.appData ? html`${this.appData.appUrl}` : html``} -

{this.activePane = 'register'}}>You can also register for a new account.

-
-
-
-
-
-
- - - - Send Verification Email -
- Already have an account? -

{this.activePane = 'login'}}>Login instead.

-
-
-
+
+ + + + + + Register instead
`; } @@ -174,7 +104,7 @@ export class IdpLogin extends DeesElement { const loginSubmitButton: DeesFormSubmit = loginForm.querySelector('#loginSubmitButton'); const setButtonText = async () => { if (loginPasswordInput.value) { - console.log('updating text of loginprompt.') + console.log('updating text of loginprompt.'); loginSubmitButton.text = 'Login'; } else { loginSubmitButton.text = 'Send magic link (or enter password)'; diff --git a/ts_web/elements/idp-registerprompt.ts b/ts_web/elements/idp-registerprompt.ts new file mode 100644 index 0000000..157b87e --- /dev/null +++ b/ts_web/elements/idp-registerprompt.ts @@ -0,0 +1,189 @@ +import * as plugins from '../plugins.js'; + +import { + customElement, + DeesElement, + property, + html, + type TemplateResult, + css, + cssManager, + state, + domtools, +} from '@design.estate/dees-element'; + +// third party catalogs +import '@uptime.link/webwidget'; + +import '@design.estate/dees-catalog'; +import { DeesForm, DeesFormSubmit, DeesInputText } from '@design.estate/dees-catalog'; + +declare global { + interface HTMLElementTagNameMap { + 'idp-registrationprompt': IdpRegistrationPrompt; + } +} + +@customElement('idp-registrationprompt') +export class IdpRegistrationPrompt extends DeesElement { + public static demo = () => html``; + + @property() + public productOfInterest: string; + + @property() + jwt: string; + + @property({ + reflect: true, + type: Object, + }) + appData: plugins.idpInterfaces.data.IApp; + + public jwtObserable = new domtools.plugins.smartrx.rxjs.Subject(); + + constructor() { + super(); + domtools.elementBasic.setup(); + } + + public static styles = [ + cssManager.defaultStyles, + css` + :host { + font-family: 'Geist Sans'; + display: block; + color: ${cssManager.bdTheme('#333333', '#ffffff')}; + } + + .box { + opacity: 0; + cursor: pointer; + overflow: hidden; + transition: all 0.2s ease; + height: 0px; + } + + .boxcontent { + margin: 0px 20px; + } + + .registerButton { + display: block; + transition: all 0.2s ease; + will-change: transform; + cursor: pointer; + } + + .registerButton:hover { + color: #fff; + transform: scale(1.02); + } + `, + ]; + + public render(): TemplateResult { + return html` +
+ + + + Send Verification Email + +
+ `; + } + + public async firstUpdated() { + const domtoolsInstance = await this.domtoolsPromise; + const loginForm: DeesForm = this.shadowRoot.querySelector('#loginForm'); + const loginPasswordInput: DeesInputText = loginForm.querySelector('#loginPasswordInput'); + const loginSubmitButton: DeesFormSubmit = loginForm.querySelector('#loginSubmitButton'); + const setButtonText = async () => { + if (loginPasswordInput.value) { + console.log('updating text of registrationprompt.'); + loginSubmitButton.text = 'Login'; + } else { + loginSubmitButton.text = 'Send magic link (or enter password)'; + } + }; + loginForm.changeSubject.subscribe(() => { + console.log(`checking button text ${loginPasswordInput.value}`); + setButtonText(); + }); + setButtonText(); + } + + private register = async (valueArg: { emailAddress: string }) => { + const registrationForm: DeesForm = this.shadowRoot.querySelector('#registrationForm'); + registrationForm.setStatus('pending', 'registering...'); + const firstSignupRequest = + new domtools.TypedRequest( + '/typedrequest', + 'firstRegistrationRequest' + ); + const response = await firstSignupRequest + .fire({ + email: valueArg.emailAddress, + productSlugOfInterest: this.productOfInterest, + }) + .catch((err) => { + registrationForm.setStatus('error', err.message); + return null; + }); + if (response.status === 'ok') { + registrationForm.setStatus('success', 'Please check your email!'); + } + console.log(response); + }; + + public async dispatchJwt(jwtArg?: string) { + if (jwtArg !== undefined) { + console.log(`dispatching jwt from loginprompt.`); + this.jwt = jwtArg; + await domtools.plugins.smartdelay.delayFor(200); + this.dispatchEvent( + new CustomEvent('leleLoginGotJwt', { + detail: { + jwt: this.jwt, + }, + }) + ); + this.jwtObserable.next(this.jwt); + } + } + + public async handleRefreshToken(refreshTokenArg: string, delayDispatchMillisArg = 0) { + // a refreshToken binds directly to a session. + // the refresh token is used on a continuous basis to get fresh and short-lived jwts + const refreshJwt = new domtools.TypedRequest( + '/typedrequest', + 'refreshJwt' + ); + const responseJwt = await refreshJwt.fire({ + refreshToken: refreshTokenArg, + }); + + if (responseJwt.jwt) { + this.domtools.convenience.smartdelay.delayFor(delayDispatchMillisArg).then(() => { + this.dispatchJwt(responseJwt.jwt); + }); + return responseJwt.jwt; + } else { + return null; + } + } +} diff --git a/ts_web/elements/idp-welcome.ts b/ts_web/elements/idp-welcome.ts index f1209f9..bc8ed11 100644 --- a/ts_web/elements/idp-welcome.ts +++ b/ts_web/elements/idp-welcome.ts @@ -36,6 +36,10 @@ export class IdpWelcome extends DeesElement { h1 { font-family: 'Cal Sans'; text-align: center; + font-size: 24px; + margin: 24px auto; + padding: 0px 24px; + width: 500px; letter-spacing:0.0125em; } @@ -43,7 +47,8 @@ export class IdpWelcome extends DeesElement { margin: 24px auto; width: 500px; background: #111111; - border-radius: 8px; + border-radius: 16px; + border-top: 1px solid ${cssManager.bdTheme('#ffffff', '#222222')}; padding: 24px; }