feat(web): Implement view container and update elements

This commit is contained in:
2024-09-29 16:48:06 +02:00
parent 7735b4070a
commit a4fde94a36
15 changed files with 182 additions and 40 deletions
+16
View File
@@ -0,0 +1,16 @@
# Changelog
## 2024-09-29 - 1.1.0 - feat(web)
Implement view container and update elements
- Add IdpViewcontainer element for managing views
- Update idp-welcome element to load IdpLogincontainer element
- Rename wg-loginprompt and wg-logincontainer to idp-login and idp-logincontainer
- Fix CSS styling and references in elements
- Re-add idp-registration-stepper element
## 2024-09-29 - 1.0.0 - Initial Release
Project initialization and initial documentation setup.
- Added README
- Initial project setup
+2 -1
View File
@@ -45,7 +45,8 @@
"@push.rocks/websetup": "^3.0.15", "@push.rocks/websetup": "^3.0.15",
"@push.rocks/webstore": "^2.0.20", "@push.rocks/webstore": "^2.0.20",
"@serve.zone/platformclient": "^1.0.6", "@serve.zone/platformclient": "^1.0.6",
"@tsclass/tsclass": "^4.1.2" "@tsclass/tsclass": "^4.1.2",
"@uptime.link/webwidget": "^1.1.2"
}, },
"devDependencies": { "devDependencies": {
"@git.zone/tsbuild": "^2.1.17", "@git.zone/tsbuild": "^2.1.17",
+16
View File
@@ -98,6 +98,9 @@ importers:
'@tsclass/tsclass': '@tsclass/tsclass':
specifier: ^4.1.2 specifier: ^4.1.2
version: 4.1.2 version: 4.1.2
'@uptime.link/webwidget':
specifier: ^1.1.2
version: 1.1.2
devDependencies: devDependencies:
'@git.zone/tsbuild': '@git.zone/tsbuild':
specifier: ^2.1.17 specifier: ^2.1.17
@@ -1343,6 +1346,9 @@ packages:
'@ungap/structured-clone@1.2.0': '@ungap/structured-clone@1.2.0':
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
'@uptime.link/webwidget@1.1.2':
resolution: {integrity: sha512-6ssyDdl7Zk6jXglfKGMK/sKRWxz52jy1fnKRZxom6eyo0PiTWVLXxqlVqmjbfi+QnQq3dBVVsIU/q/OXm1FGIQ==}
'@webcontainer/api@1.3.0': '@webcontainer/api@1.3.0':
resolution: {integrity: sha512-gnb5P7Qr7xIvOEiUUODhKG6o8i4ZpVFdoKdnggOnWYaGOTECM94PK3alTYifa9YIL304VJkH/liT+fbnKCXa+A==} resolution: {integrity: sha512-gnb5P7Qr7xIvOEiUUODhKG6o8i4ZpVFdoKdnggOnWYaGOTECM94PK3alTYifa9YIL304VJkH/liT+fbnKCXa+A==}
@@ -5795,6 +5801,16 @@ snapshots:
'@ungap/structured-clone@1.2.0': {} '@ungap/structured-clone@1.2.0': {}
'@uptime.link/webwidget@1.1.2':
dependencies:
'@design.estate/dees-catalog': 1.1.8
'@design.estate/dees-domtools': 2.0.57
'@design.estate/dees-element': 2.0.36
'@design.estate/dees-wcctools': 1.0.90
transitivePeerDependencies:
- encoding
- supports-color
'@webcontainer/api@1.3.0': {} '@webcontainer/api@1.3.0': {}
'@yr/monotone-cubic-spline@1.0.3': {} '@yr/monotone-cubic-spline@1.0.3': {}
+3 -3
View File
@@ -1,8 +1,8 @@
/** /**
* autocreated commitinfo by @pushrocks/commitinfo * autocreated commitinfo by @push.rocks/commitinfo
*/ */
export const commitinfo = { export const commitinfo = {
name: '@idp.global/idp.global', name: '@idp.global/idp.global',
version: 'x.x.x', version: '1.1.0',
description: 'website for lossless.com' description: 'An identity provider software managing user authentications, registrations, and sessions.'
} }
+8
View File
@@ -0,0 +1,8 @@
/**
* autocreated commitinfo by @push.rocks/commitinfo
*/
export const commitinfo = {
name: '@idp.global/idp.global',
version: '1.1.0',
description: 'An identity provider software managing user authentications, registrations, and sessions.'
}
+12 -12
View File
@@ -15,13 +15,13 @@ import { commitinfo } from '../../dist_ts/00_commitinfo_data.js';
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
'wg-logincontainer': IdpLogincontainer; 'idp-logincontainer': IdpLogincontainer;
} }
} }
@customElement('idp-logincontainer') @customElement('idp-logincontainer')
export class IdpLogincontainer extends DeesElement { export class IdpLogincontainer extends DeesElement {
public static demo = () => html`<wg-logincontainer></wg-logincontainer>`; public static demo = () => html`<idp-logincontainer></idp-logincontainer>`;
@query('.loginPromptContainer') @query('.loginPromptContainer')
loginPromptContainer: HTMLDivElement; loginPromptContainer: HTMLDivElement;
@@ -48,6 +48,7 @@ export class IdpLogincontainer extends DeesElement {
cssManager.defaultStyles, cssManager.defaultStyles,
css` css`
:host { :host {
font-family: 'Geist Sans';
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
@@ -118,7 +119,6 @@ export class IdpLogincontainer extends DeesElement {
padding: 8px; padding: 8px;
background: ${cssManager.bdTheme('#f5f5f5', '#111')}; background: ${cssManager.bdTheme('#f5f5f5', '#111')};
border-top: 1px solid ${cssManager.bdTheme('#ccc', '#222222')}; border-top: 1px solid ${cssManager.bdTheme('#ccc', '#222222')};
font-family: 'Hubot Sans';
color: ${cssManager.bdTheme('#666', '#888')}; color: ${cssManager.bdTheme('#666', '#888')};
} }
@@ -136,7 +136,7 @@ export class IdpLogincontainer extends DeesElement {
<img <img
src="https://assetbroker.lossless.one/brandfiles/00general/plain_workspaceglobal.svg" src="https://assetbroker.lossless.one/brandfiles/00general/plain_workspaceglobal.svg"
/> />
<wg-loginprompt></wg-loginprompt> <idp-login></idp-login>
<div class="legalinfo"> <div class="legalinfo">
<a href="https://legal.task.vc/" target="_blank">Legal Info</a> <a href="https://legal.task.vc/" target="_blank">Legal Info</a>
| <a href="https://task.vc/" target="_blank">Company Website</a> | <a href="https://task.vc/" target="_blank">Company Website</a>
@@ -165,7 +165,7 @@ export class IdpLogincontainer extends DeesElement {
<img <img
src="https://assetbroker.lossless.one/brandfiles/00general/plain_workspaceglobal.svg" src="https://assetbroker.lossless.one/brandfiles/00general/plain_workspaceglobal.svg"
/> />
<wg-transfermanager></wg-transfermanager> <idp-transfermanager></idp-transfermanager>
<div class="legalinfo"> <div class="legalinfo">
<a href="https://legal.task.vc/" target="_blank">Legal Info</a> <a href="https://legal.task.vc/" target="_blank">Legal Info</a>
| <a href="https://task.vc/" target="_blank">Company Website</a> | <a href="https://task.vc/" target="_blank">Company Website</a>
@@ -222,7 +222,7 @@ export class IdpLogincontainer extends DeesElement {
this.showComponent('loginPrompt'); this.showComponent('loginPrompt');
} else if ((await this.receptionClient.determineLoginStatus()) && action === 'login') { } else if ((await this.receptionClient.determineLoginStatus()) && action === 'login') {
await this.showComponent('transferManager'); await this.showComponent('transferManager');
const wgTransferManager = this.shadowRoot.querySelector('wg-transfermanager'); const wgTransferManager = this.shadowRoot.querySelector('idp-transfermanager');
await wgTransferManager.handleTransfer(); await wgTransferManager.handleTransfer();
} else if ((await this.receptionClient.determineLoginStatus()) && action === 'manage') { } else if ((await this.receptionClient.determineLoginStatus()) && action === 'manage') {
this.showComponent('loginManager'); this.showComponent('loginManager');
@@ -246,19 +246,19 @@ export class IdpLogincontainer extends DeesElement {
); );
} }
const wgLogin = this.shadowRoot.querySelector('wg-loginprompt'); const idpLogin = this.shadowRoot.querySelector('idp-login');
const wgTransferManager = this.shadowRoot.querySelector('wg-transfermanager'); const idpTransferManager = this.shadowRoot.querySelector('idp-transfermanager');
wgLogin.appData = appData; idpLogin.appData = appData;
wgTransferManager.appData = appData; idpTransferManager.appData = appData;
await this.determineNextAction(); await this.determineNextAction();
wgLogin.jwtObserable.subscribe({ idpLogin.jwtObserable.subscribe({
next: async (jwtArg) => { next: async (jwtArg) => {
console.log('loggedIn'); console.log('loggedIn');
await this.receptionClient.storeJwt(jwtArg); await this.receptionClient.storeJwt(jwtArg);
await this.determineNextAction(); await this.determineNextAction();
}, },
}); });
wgLogin.dispatchJwt(); idpLogin.dispatchJwt();
} }
} }
+11 -9
View File
@@ -13,20 +13,20 @@ import {
} from '@design.estate/dees-element'; } from '@design.estate/dees-element';
// third party catalogs // third party catalogs
import '@uptimelink/webwidget'; import '@uptime.link/webwidget';
import '@design.estate/dees-catalog'; import '@design.estate/dees-catalog';
import { DeesForm, DeesFormSubmit, DeesInputText } from '@design.estate/dees-catalog'; import { DeesForm, DeesFormSubmit, DeesInputText } from '@design.estate/dees-catalog';
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
'wg-loginprompt': WgLogin; 'idp-login': IdpLogin;
} }
} }
@customElement('wg-loginprompt') @customElement('idp-login')
export class WgLogin extends DeesElement { export class IdpLogin extends DeesElement {
public static demo = () => html`<wg-loginprompt></wg-loginprompt>`; public static demo = () => html`<idp-login></idp-login>`;
public static receptionUrl = 'https://reception.lossless.one/typedrequest'; public static receptionUrl = 'https://reception.lossless.one/typedrequest';
@property() @property()
@@ -40,6 +40,7 @@ export class WgLogin extends DeesElement {
@property({ @property({
reflect: true, reflect: true,
type: Object,
}) })
appData: plugins.idpInterfaces.data.IApp; appData: plugins.idpInterfaces.data.IApp;
@@ -54,6 +55,7 @@ export class WgLogin extends DeesElement {
cssManager.defaultStyles, cssManager.defaultStyles,
css` css`
:host { :host {
font-family: 'Geist Sans';
display: block; display: block;
color: ${cssManager.bdTheme('#333333', '#ffffff')}; color: ${cssManager.bdTheme('#333333', '#ffffff')};
} }
@@ -190,12 +192,12 @@ export class WgLogin extends DeesElement {
const loginForm: DeesForm = this.shadowRoot.querySelector('#loginForm'); const loginForm: DeesForm = this.shadowRoot.querySelector('#loginForm');
const loginRequestWithUsernameAndPassword = const loginRequestWithUsernameAndPassword =
new domtools.TypedRequest<plugins.idpInterfaces.request.IReq_LoginWithEmailOrUsernameAndPassword>( new domtools.TypedRequest<plugins.idpInterfaces.request.IReq_LoginWithEmailOrUsernameAndPassword>(
WgLogin.receptionUrl, IdpLogin.receptionUrl,
'loginWithEmailOrUsernameAndPassword' 'loginWithEmailOrUsernameAndPassword'
); );
const loginRequestWithEmail = const loginRequestWithEmail =
new domtools.TypedRequest<plugins.idpInterfaces.request.IReq_LoginWithEmail>( new domtools.TypedRequest<plugins.idpInterfaces.request.IReq_LoginWithEmail>(
WgLogin.receptionUrl, IdpLogin.receptionUrl,
'loginWithEmail' 'loginWithEmail'
); );
@@ -241,7 +243,7 @@ export class WgLogin extends DeesElement {
registrationForm.setStatus('pending', 'registering...'); registrationForm.setStatus('pending', 'registering...');
const firstSignupRequest = const firstSignupRequest =
new domtools.TypedRequest<plugins.idpInterfaces.request.IReq_FirstRegistration>( new domtools.TypedRequest<plugins.idpInterfaces.request.IReq_FirstRegistration>(
WgLogin.receptionUrl, IdpLogin.receptionUrl,
'firstRegistrationRequest' 'firstRegistrationRequest'
); );
const response = await firstSignupRequest const response = await firstSignupRequest
@@ -279,7 +281,7 @@ export class WgLogin extends DeesElement {
// a refreshToken binds dierctly to a session. // a refreshToken binds dierctly to a session.
// the refresh token is used on a continuous basis to get fresh and short-lived jwts // the refresh token is used on a continuous basis to get fresh and short-lived jwts
const refreshJwt = new domtools.TypedRequest<plugins.idpInterfaces.request.IReq_RefreshJwt>( const refreshJwt = new domtools.TypedRequest<plugins.idpInterfaces.request.IReq_RefreshJwt>(
WgLogin.receptionUrl, IdpLogin.receptionUrl,
'refreshJwt' 'refreshJwt'
); );
const responseJwt = await refreshJwt.fire({ const responseJwt = await refreshJwt.fire({
+3 -3
View File
@@ -14,12 +14,12 @@ import {
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
'wg-transfermanager': WgTransfermanager; 'idp-transfermanager': IdpTransfermanager;
} }
} }
@customElement('wg-transfermanager') @customElement('idp-transfermanager')
export class WgTransfermanager extends DeesElement { export class IdpTransfermanager extends DeesElement {
public appData: plugins.idpInterfaces.data.IApp; public appData: plugins.idpInterfaces.data.IApp;
+19 -10
View File
@@ -1,4 +1,5 @@
import * as plugins from '../plugins.js'; import * as plugins from '../plugins.js';
import * as elements from '../elements/index.js';
import { import {
customElement, customElement,
@@ -10,11 +11,11 @@ import {
css, css,
type TemplateResult, type TemplateResult,
} from '@design.estate/dees-element'; } from '@design.estate/dees-element';
import type { IdpViewcontainer } from '../views/viewcontainer.js';
@customElement('idp-welcome') @customElement('idp-welcome')
export class IdpWelcome extends DeesElement { export class IdpWelcome extends DeesElement {
@property() viewContainer: IdpViewcontainer;
public someProperty = 'someProperty';
constructor() { constructor() {
super(); super();
@@ -25,16 +26,15 @@ export class IdpWelcome extends DeesElement {
css` css`
:host { :host {
display: block; display: block;
height: 100px;
color: #fff; color: #fff;
font-family: 'Geist Sans'; font-family: 'Geist Sans';
} }
:host([hidden]) { :host([hidden]) {
font-family: 'Cal Sans';
display: none; display: none;
} }
h1 { h1 {
font-family: 'Cal Sans';
text-align: center; text-align: center;
letter-spacing:0.0125em; letter-spacing:0.0125em;
} }
@@ -57,17 +57,26 @@ export class IdpWelcome extends DeesElement {
return html` return html`
<style></style> <style></style>
<h1>idp.global</h1> <h1>idp.global</h1>
<div class="textbox">
Do you want to sign in or register?
<dees-button @click=${() => {
this.viewContainer.loadElement(elements.IdpLogincontainer);
}}>Sign In</dees-button>
<dees-button @click=${() => {}}>Register</dees-button>
</div>
<div class="textbox">
Do you want to use idp.global for your app?
<dees-button @click=${() => {}}>Open Developer Dashboard</dees-button>
</div>
<div class="textbox"> <div class="textbox">
idp.global is a Open Source identity provider for the world wide web. You can get the code if you want to improve it. idp.global is a Open Source identity provider for the world wide web. You can get the code if you want to improve it.
<dees-button @click=${() => { <dees-button @click=${() => {
window.location.href = 'https://code.foss.global/idp.global/idp.global'; window.open('https://code.foss.global/idp.global/idp.global', '_blank');
}}>Get the code</dees-button> }}>Get the code</dees-button>
</div> </div>
<div class="textbox">
Do you want to sign in or register?
<dees-button @click=${() => {}}>Sign In</dees-button>
<dees-button @click=${() => {}}>Register</dees-button>
</div>
`; `;
} }
} }
+5
View File
@@ -0,0 +1,5 @@
export * from './idp-registration-stepper.js';
export * from './idp-logincontainer.js';
export * from './idp-loginprompt.js';
export * from './idp-transfermanager.js';
export * from './idp-welcome.js';
+7 -1
View File
@@ -2,6 +2,7 @@ import * as serviceworker from '@api.global/typedserver/web_serviceworker_client
import * as domtools from '@design.estate/dees-domtools'; import * as domtools from '@design.estate/dees-domtools';
import { html, render } from '@design.estate/dees-element'; import { html, render } from '@design.estate/dees-element';
import { IdpViewcontainer } from './views/index.js';
import { IdpWelcome } from './elements/idp-welcome.js'; import { IdpWelcome } from './elements/idp-welcome.js';
const run = async () => { const run = async () => {
@@ -52,10 +53,15 @@ const run = async () => {
--background-accent: #303f9f; --background-accent: #303f9f;
} }
</style> </style>
<idp-welcome></idp-welcome> <idp-viewcontainer></idp-viewcontainer>
`; `;
render(mainTemplate, document.body); render(mainTemplate, document.body);
const viewContainer: IdpViewcontainer = document.querySelector('idp-viewcontainer');
viewContainer.loadElement(IdpWelcome);
}; };
run(); run();
+2 -1
View File
@@ -13,5 +13,6 @@ export { typedrequest };
// @design.estate scope // @design.estate scope
import * as deesCatalog from '@design.estate/dees-catalog'; import * as deesCatalog from '@design.estate/dees-catalog';
import * as deesElement from '@design.estate/dees-element';
export { deesCatalog }; export { deesCatalog, deesElement };
+1
View File
@@ -0,0 +1 @@
export * from './viewcontainer.js';
+77
View File
@@ -0,0 +1,77 @@
import * as plugins from '../plugins.js';
import {
customElement,
DeesElement,
property,
html,
cssManager,
unsafeCSS,
css,
type TemplateResult,
} from '@design.estate/dees-element';
@customElement('idp-viewcontainer')
export class IdpViewcontainer extends DeesElement {
constructor() {
super();
}
public static styles = [
cssManager.defaultStyles,
css`
:host {
display: block;
color: #fff;
font-family: 'Geist Sans';
}
:host([hidden]) {
display: none;
}
.viewContainer {
min-width: 100vh;
min-height: 100vh;
}
`,
];
public render(): TemplateResult {
return html`
<style></style>
<div class="viewContainer">
</div>
`;
}
public currentElement: plugins.deesElement.DeesElement;
public async loadElement(viewElement: typeof plugins.deesElement.DeesElement) {
// Wait until the viewContainer itself is rendered
await this.updateComplete;
// Select the viewContainer
const viewContainer = this.shadowRoot.querySelector('.viewContainer');
// Check if viewContainer is present
if (!viewContainer) {
throw new Error('View container not found in the rendered DOM.');
}
// Remove the current element if it exists
if (this.currentElement) {
viewContainer.removeChild(this.currentElement);
}
// Create a new instance of the viewElement
const newElement = new viewElement();
(newElement as any).viewContainer = this;
viewContainer.appendChild(newElement);
// Wait until the new element is fully rendered
await newElement.updateComplete;
// Set the new element as the current element
this.currentElement = newElement;
}
}