242 lines
6.7 KiB
TypeScript
242 lines
6.7 KiB
TypeScript
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';
|
|
import { IdpState } from '../states/idp.state.js';
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
'idp-registrationprompt': IdpRegistrationPrompt;
|
|
}
|
|
}
|
|
|
|
@customElement('idp-registrationprompt')
|
|
export class IdpRegistrationPrompt extends DeesElement {
|
|
public static demo = () => html`<idp-login></idp-login>`;
|
|
|
|
@property()
|
|
accessor productOfInterest: string;
|
|
|
|
@property()
|
|
accessor jwt: string;
|
|
|
|
@property({
|
|
reflect: true,
|
|
type: Object,
|
|
})
|
|
accessor appData: plugins.idpInterfaces.data.IApp;
|
|
|
|
public jwtObserable = new domtools.plugins.smartrx.rxjs.Subject<string>();
|
|
|
|
constructor() {
|
|
super();
|
|
domtools.elementBasic.setup();
|
|
}
|
|
|
|
public static styles = [
|
|
cssManager.defaultStyles,
|
|
css`
|
|
:host {
|
|
--foreground: hsl(0 0% 98%);
|
|
--muted-foreground: hsl(240 5% 64.9%);
|
|
|
|
font-family: 'Geist Sans', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
display: block;
|
|
color: var(--foreground);
|
|
}
|
|
|
|
.form-header {
|
|
margin-bottom: 32px;
|
|
text-align: center;
|
|
}
|
|
|
|
.form-header h2 {
|
|
font-size: 24px;
|
|
font-weight: 600;
|
|
color: var(--foreground);
|
|
margin: 0 0 8px 0;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
|
|
.form-header p {
|
|
font-size: 14px;
|
|
color: var(--muted-foreground);
|
|
margin: 0;
|
|
}
|
|
|
|
dees-form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 16px;
|
|
}
|
|
|
|
.form-footer {
|
|
margin-top: 24px;
|
|
text-align: center;
|
|
font-size: 14px;
|
|
color: var(--muted-foreground);
|
|
}
|
|
|
|
.form-footer a {
|
|
color: var(--foreground);
|
|
text-decoration: none;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: opacity 0.15s ease;
|
|
}
|
|
|
|
.form-footer a:hover {
|
|
opacity: 0.8;
|
|
}
|
|
`,
|
|
];
|
|
|
|
public render(): TemplateResult {
|
|
return html`
|
|
<idp-centercontainer>
|
|
<div class="form-header">
|
|
<h2>Create your account</h2>
|
|
<p>Get started with your permanent identity</p>
|
|
</div>
|
|
<dees-form
|
|
id="registrationForm"
|
|
@formData="${(eventArg) => {
|
|
this.register({
|
|
emailAddress: eventArg.detail.data.emailAddress,
|
|
});
|
|
}}"
|
|
>
|
|
<dees-input-text
|
|
.required=${true}
|
|
key="emailAddress"
|
|
label="Email Address"
|
|
></dees-input-text>
|
|
<dees-input-checkbox
|
|
.label="${'I agree to the Terms and Conditions'}"
|
|
.required=${true}
|
|
></dees-input-checkbox>
|
|
<dees-form-submit>Send Verification Email</dees-form-submit>
|
|
</dees-form>
|
|
<div class="form-footer">
|
|
Already have an account? <a @click=${async () => {
|
|
const idpState = await IdpState.getSingletonInstance();
|
|
idpState.domtools.router.pushUrl('/login');
|
|
}}>Sign in</a>
|
|
</div>
|
|
</idp-centercontainer>
|
|
`;
|
|
}
|
|
|
|
public async firstUpdated() {
|
|
await this.domtoolsPromise;
|
|
const idpState = await IdpState.getSingletonInstance();
|
|
const loggedIn = await idpState.idpClient.determineLoginStatus();
|
|
if (loggedIn) {
|
|
idpState.domtools.router.pushUrl('/');
|
|
}
|
|
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 idpState = await IdpState.getSingletonInstance();
|
|
const firstSignupRequest =
|
|
idpState.idpClient.typedsocket.createTypedRequest<plugins.idpInterfaces.request.IReq_FirstRegistration>(
|
|
'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 idpState = await IdpState.getSingletonInstance();
|
|
const refreshJwt = idpState.idpClient.typedsocket.createTypedRequest<plugins.idpInterfaces.request.IReq_RefreshJwt>(
|
|
'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;
|
|
}
|
|
}
|
|
|
|
public async show() {
|
|
await this.updateComplete;
|
|
const centerContainer = this.shadowRoot.querySelector('idp-centercontainer');
|
|
await centerContainer.show();
|
|
}
|
|
|
|
public async hide() {
|
|
await this.updateComplete;
|
|
const centerContainer = this.shadowRoot.querySelector('idp-centercontainer');
|
|
await centerContainer.hide();
|
|
}
|
|
}
|