feat(account): Refactor account UI styles into reusable design tokens, apply updated styles across views and fix login submit behavior
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 528 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 124 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 434 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 120 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 79 KiB |
@@ -1,5 +1,14 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-12-01 - 1.5.0 - feat(account)
|
||||||
|
Refactor account UI styles into reusable design tokens, apply updated styles across views and fix login submit behavior
|
||||||
|
|
||||||
|
- Introduce accountDesignTokens and split shared styles into tokens (accountDesignTokens), cardStyles and typographyStyles while keeping a legacy default export for compatibility
|
||||||
|
- Apply new design tokens to account components (content, baseview, subscriptions) and switch background to use CSS variable (--background)
|
||||||
|
- Small UI tweaks: smoother transition easing on view container, updated icon for organization entries and adjusted spacing
|
||||||
|
- Add placeholder sections for Upcoming Billable Items and Past Invoices in subscriptions view
|
||||||
|
- Fix login prompt submit handling by disabling the submit button via its #loginSubmitButton selector and improving button text logic
|
||||||
|
|
||||||
## 2025-04-03 - 1.4.3 - fix(website)
|
## 2025-04-03 - 1.4.3 - fix(website)
|
||||||
Update packageManager configuration in package.json and refine view container background styling
|
Update packageManager configuration in package.json and refine view container background styling
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@idp.global/idp.global',
|
name: '@idp.global/idp.global',
|
||||||
version: '1.4.3',
|
version: '1.5.0',
|
||||||
description: 'An identity provider software managing user authentications, registrations, and sessions.'
|
description: 'An identity provider software managing user authentications, registrations, and sessions.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@idp.global/idp.global',
|
name: '@idp.global/idp.global',
|
||||||
version: '1.4.3',
|
version: '1.5.0',
|
||||||
description: 'An identity provider software managing user authentications, registrations, and sessions.'
|
description: 'An identity provider software managing user authentications, registrations, and sessions.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
} from '@design.estate/dees-element';
|
} from '@design.estate/dees-element';
|
||||||
|
|
||||||
import { LeleAccountNavigation } from './navigation.js';
|
import { LeleAccountNavigation } from './navigation.js';
|
||||||
|
import { accountDesignTokens } from './sharedstyles.js';
|
||||||
|
|
||||||
import * as views from './views/index.js';
|
import * as views from './views/index.js';
|
||||||
import * as accountstate from '../../states/accountstate.js';
|
import * as accountstate from '../../states/accountstate.js';
|
||||||
@@ -36,15 +37,13 @@ export class IdpAccountContent extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
accountDesignTokens,
|
||||||
css`
|
css`
|
||||||
:host {
|
:host {
|
||||||
display: block;
|
display: block;
|
||||||
color: #fff;
|
|
||||||
padding-top: 10px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: ${cssManager.bdTheme('#eeeeeb', '#000000')}
|
background: var(--background);
|
||||||
}
|
}
|
||||||
:host([hidden]) {
|
:host([hidden]) {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -72,7 +71,7 @@ export class IdpAccountContent extends DeesElement {
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
overscroll-behavior: contain;
|
overscroll-behavior: contain;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s ease;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
import * as plugins from '../../plugins.js';
|
import * as plugins from '../../plugins.js';
|
||||||
import * as states from '../../states/accountstate.js';
|
import * as states from '../../states/accountstate.js';
|
||||||
import { IdpState } from '../../states/idp.state.js';
|
import { IdpState } from '../../states/idp.state.js';
|
||||||
|
import { accountDesignTokens } from './sharedstyles.js';
|
||||||
|
|
||||||
import { commitinfo } from '../../../dist_ts/00_commitinfo_data.js';
|
import { commitinfo } from '../../../dist_ts/00_commitinfo_data.js';
|
||||||
|
|
||||||
@@ -23,108 +24,122 @@ declare global {
|
|||||||
|
|
||||||
@customElement('lele-accountnavigation')
|
@customElement('lele-accountnavigation')
|
||||||
export class LeleAccountNavigation extends DeesElement {
|
export class LeleAccountNavigation extends DeesElement {
|
||||||
@property()
|
|
||||||
accessor options: { text: string; id: string }[] = [
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
text: 'Apps',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
text: 'Users',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '3',
|
|
||||||
text: 'Activity',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '4',
|
|
||||||
text: 'Billing & Subscription',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
|
accountDesignTokens,
|
||||||
css`
|
css`
|
||||||
:host {
|
:host {
|
||||||
display: block;
|
display: flex;
|
||||||
color: ${cssManager.bdTheme('#333', '#fff')};
|
flex-direction: column;
|
||||||
padding: 10px;
|
background: var(--card);
|
||||||
padding-left: 0px;
|
border-right: 1px solid var(--border);
|
||||||
background: ${cssManager.bdTheme('#eeeeeb', '#000')};
|
height: 100%;
|
||||||
border-right: ${cssManager.bdTheme('1px solid #ccc', '1px solid #111')};
|
|
||||||
}
|
}
|
||||||
:host([hidden]) {
|
:host([hidden]) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.logoArea {
|
||||||
|
padding: 20px 16px;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
font-family: 'Cal Sans';
|
font-family: 'Cal Sans', 'Geist Sans', sans-serif;
|
||||||
letter-spacing: 0.0125em;
|
letter-spacing: -0.02em;
|
||||||
font-size: 16px;
|
font-size: 20px;
|
||||||
text-align: center;
|
font-weight: 600;
|
||||||
padding: 16px 0px 16px 0px;
|
color: var(--foreground);
|
||||||
margin: -8px -8px -16px 0px;
|
cursor: pointer;
|
||||||
border-bottom: 1px solid #111111;
|
transition: opacity 0.15s ease;
|
||||||
cursor: default;
|
display: flex;
|
||||||
position: relative;
|
align-items: center;
|
||||||
z-index: 10;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo:hover {
|
.logo:hover {
|
||||||
background: ${unsafeCSS(plugins.deesCatalog.colors.dark.blue)};
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo dees-icon {
|
||||||
|
font-size: 24px;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navContent {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.commitinfo {
|
.commitinfo {
|
||||||
|
flex-shrink: 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: absolute;
|
font-family: 'Geist Mono', monospace;
|
||||||
bottom: 0px;
|
font-size: 10px;
|
||||||
left: 0px;
|
padding: 12px 16px;
|
||||||
font-family: 'Intel One Mono';
|
border-top: 1px solid var(--border);
|
||||||
width: 100%;
|
color: var(--muted-foreground);
|
||||||
font-size: 12px;
|
opacity: 0.6;
|
||||||
padding: 8px;
|
background: var(--card);
|
||||||
border-top: ${cssManager.bdTheme('1px solid #ccc', '1px solid #333')};
|
|
||||||
color: ${cssManager.bdTheme('#666', '#ccc')};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigationGroupLabel {
|
.navigationGroupLabel {
|
||||||
width: min-content;
|
font-size: 10px;
|
||||||
white-space: nowrap;
|
font-weight: 600;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: 12px;
|
letter-spacing: 0.08em;
|
||||||
font-weight: 300;
|
color: var(--muted-foreground);
|
||||||
border-bottom: 1px solid;
|
padding: 20px 16px 8px;
|
||||||
border-image: linear-gradient(to right, orange, #44444400) 1;
|
opacity: 0.7;
|
||||||
color: ${cssManager.bdTheme('#666', '#ccc')};
|
}
|
||||||
margin-bottom: 5px;
|
|
||||||
padding-top: 32px;
|
.navigationGroupLabel:first-of-type {
|
||||||
padding-left: 10px;
|
padding-top: 16px;
|
||||||
padding-bottom: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigationOption {
|
.navigationOption {
|
||||||
border-top-right-radius: 30px;
|
display: flex;
|
||||||
border-bottom-right-radius: 30px;
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
margin: 2px 8px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
padding: 8px;
|
color: var(--muted-foreground);
|
||||||
padding-left: 10px;
|
transition: all 0.15s ease;
|
||||||
margin-bottom: 5px;
|
cursor: pointer;
|
||||||
font-size: 14px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigationOption:hover {
|
.navigationOption:hover {
|
||||||
cursor: default;
|
background: var(--muted);
|
||||||
background: ${cssManager.bdTheme('#bbb', plugins.deesCatalog.colors.dark.blue)};
|
color: var(--foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navigationOption dees-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
opacity: 0.7;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigationOption:hover dees-icon {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
height: 1px;
|
||||||
|
background: var(--border);
|
||||||
|
margin: 8px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
dees-input-dropdown {
|
dees-input-dropdown {
|
||||||
margin-top: 16px;
|
margin: 8px;
|
||||||
margin-bottom: 16px;
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
@@ -136,10 +151,15 @@ export class LeleAccountNavigation extends DeesElement {
|
|||||||
|
|
||||||
public render(): TemplateResult {
|
public render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<style></style>
|
<div class="logoArea">
|
||||||
<div class="commitinfo">idp.global v${commitinfo.version}</div>
|
<div class="logo">
|
||||||
<div class="logo">idp.global</div>
|
<dees-icon .icon=${'lucide:fingerprint'}></dees-icon>
|
||||||
<div class="navigationGroupLabel">Account Settings</div>
|
idp.global
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="navContent">
|
||||||
|
<div class="navigationGroupLabel">Account</div>
|
||||||
<div
|
<div
|
||||||
class="navigationOption"
|
class="navigationOption"
|
||||||
@click=${async () => {
|
@click=${async () => {
|
||||||
@@ -147,7 +167,25 @@ export class LeleAccountNavigation extends DeesElement {
|
|||||||
subrouter.pushUrl('');
|
subrouter.pushUrl('');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
overview
|
<dees-icon .icon=${'lucide:home'}></dees-icon>
|
||||||
|
Overview
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="navigationOption"
|
||||||
|
@click=${async () => {
|
||||||
|
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<dees-icon .icon=${'lucide:shield'}></dees-icon>
|
||||||
|
Manage Roles
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="navigationOption"
|
||||||
|
@click=${async () => {
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<dees-icon .icon=${'lucide:plus'}></dees-icon>
|
||||||
|
Create Organization
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="navigationOption"
|
class="navigationOption"
|
||||||
@@ -156,26 +194,15 @@ export class LeleAccountNavigation extends DeesElement {
|
|||||||
idpState.domtools.router.pushUrl('/logout');
|
idpState.domtools.router.pushUrl('/logout');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
logout
|
<dees-icon .icon=${'lucide:power'}></dees-icon>
|
||||||
|
Log Out
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
class="navigationOption"
|
|
||||||
@click=${async () => {
|
|
||||||
|
|
||||||
}}
|
<div class="divider"></div>
|
||||||
>
|
|
||||||
manage roles
|
<div class="navigationGroupLabel">Organization</div>
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="navigationOption"
|
|
||||||
@click=${async () => {
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
create an org
|
|
||||||
</div>
|
|
||||||
<div class="navigationGroupLabel">Organization Settings</div>
|
|
||||||
<dees-input-dropdown
|
<dees-input-dropdown
|
||||||
.label=${'choose org:'}
|
.label=${'Select organization'}
|
||||||
@selectedOption=${(eventArg: CustomEvent) => {
|
@selectedOption=${(eventArg: CustomEvent) => {
|
||||||
const currentState = states.accountState.getState();
|
const currentState = states.accountState.getState();
|
||||||
states.accountState.dispatchAction(
|
states.accountState.dispatchAction(
|
||||||
@@ -184,9 +211,38 @@ export class LeleAccountNavigation extends DeesElement {
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
></dees-input-dropdown>
|
></dees-input-dropdown>
|
||||||
${this.options.map((option) => {
|
|
||||||
return html` <div class="navigationOption">${option.text}</div> `;
|
<div
|
||||||
})}
|
class="navigationOption"
|
||||||
|
@click=${async () => {}}
|
||||||
|
>
|
||||||
|
<dees-icon .icon=${'lucide:box'}></dees-icon>
|
||||||
|
Apps
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="navigationOption"
|
||||||
|
@click=${async () => {}}
|
||||||
|
>
|
||||||
|
<dees-icon .icon=${'lucide:users'}></dees-icon>
|
||||||
|
Users
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="navigationOption"
|
||||||
|
@click=${async () => {}}
|
||||||
|
>
|
||||||
|
<dees-icon .icon=${'lucide:activity'}></dees-icon>
|
||||||
|
Activity
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="navigationOption"
|
||||||
|
@click=${async () => {}}
|
||||||
|
>
|
||||||
|
<dees-icon .icon=${'lucide:wallet'}></dees-icon>
|
||||||
|
Billing
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="commitinfo">v${commitinfo.version}</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,117 @@
|
|||||||
import { css } from '@design.estate/dees-element';
|
import { css } from '@design.estate/dees-element';
|
||||||
|
|
||||||
export default css`
|
/**
|
||||||
|
* Design tokens matching the login page aesthetic (idp-centercontainer.ts)
|
||||||
|
*/
|
||||||
|
export const accountDesignTokens = css`
|
||||||
|
:host {
|
||||||
|
--background: hsl(240 10% 3.9%);
|
||||||
|
--foreground: hsl(0 0% 98%);
|
||||||
|
--muted: hsl(240 3.7% 15.9%);
|
||||||
|
--muted-foreground: hsl(240 5% 64.9%);
|
||||||
|
--border: hsl(240 3.7% 15.9%);
|
||||||
|
--card: hsl(240 6% 6%);
|
||||||
|
|
||||||
|
font-family: 'Geist Sans', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||||
|
color: var(--foreground);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Card container styles
|
||||||
|
*/
|
||||||
|
export const cardStyles = css`
|
||||||
|
.card {
|
||||||
|
background: var(--card);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 32px;
|
||||||
|
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typography styles for consistent text hierarchy
|
||||||
|
*/
|
||||||
|
export const typographyStyles = css`
|
||||||
h1 {
|
h1 {
|
||||||
margin-top: 50px;
|
font-size: 24px;
|
||||||
border-bottom: 1px solid;
|
font-weight: 600;
|
||||||
border-image: radial-gradient(rgba(136, 136, 136, 0.44), rgba(136, 136, 136, 0)) 1 / 1 / 0 stretch;
|
color: var(--foreground);
|
||||||
padding-bottom: 10px;
|
margin: 0 0 8px 0;
|
||||||
font-weight: 500;
|
letter-spacing: -0.02em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
border-top: 1px dotted #666;
|
font-size: 18px;
|
||||||
padding-top: 16px;
|
font-weight: 600;
|
||||||
|
color: var(--foreground);
|
||||||
|
margin: 24px 0 8px 0;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
line-height: 1.5em;
|
font-size: 14px;
|
||||||
|
color: var(--muted-foreground);
|
||||||
|
margin: 0 0 16px 0;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--muted-foreground);
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
dees-button {
|
dees-button {
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
width: 200px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dees-input-text {
|
dees-input-text {
|
||||||
max-width: 400px;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigation styles for the sidebar
|
||||||
|
*/
|
||||||
|
export const navigationStyles = css`
|
||||||
|
.nav-item {
|
||||||
|
padding: 10px 16px;
|
||||||
|
margin: 2px 8px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--muted-foreground);
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item:hover {
|
||||||
|
background: var(--muted);
|
||||||
|
color: var(--foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item.active {
|
||||||
|
background: var(--muted);
|
||||||
|
color: var(--foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-group-label {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
color: var(--muted-foreground);
|
||||||
|
padding: 24px 16px 8px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Legacy export for backwards compatibility
|
||||||
|
*/
|
||||||
|
export default css`
|
||||||
|
${accountDesignTokens}
|
||||||
|
${typographyStyles}
|
||||||
|
`;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
directives,
|
directives,
|
||||||
} from '@design.estate/dees-element';
|
} from '@design.estate/dees-element';
|
||||||
|
|
||||||
import sharedStyles from '../sharedstyles.js';
|
import sharedStyles, { accountDesignTokens, cardStyles, typographyStyles } from '../sharedstyles.js';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
@@ -52,34 +52,75 @@ export class BaseView extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
sharedStyles,
|
accountDesignTokens,
|
||||||
|
cardStyles,
|
||||||
|
typographyStyles,
|
||||||
css`
|
css`
|
||||||
:host {
|
:host {
|
||||||
display: block;
|
display: block;
|
||||||
max-width: 900px;
|
padding: 48px;
|
||||||
margin: auto;
|
|
||||||
color: ${cssManager.bdTheme('#333', '#fff')};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.viewHost {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: var(--card);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 32px;
|
||||||
|
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
.slug {
|
.slug {
|
||||||
color: orange;
|
color: var(--foreground);
|
||||||
|
font-weight: 600;
|
||||||
|
font-family: 'Geist Mono', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint {
|
||||||
|
display: block;
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--muted-foreground);
|
||||||
|
margin: 16px 0;
|
||||||
|
padding: 12px 16px;
|
||||||
|
background: var(--muted);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dees-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
margin-top: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.orgGrid {
|
.orgGrid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-gap: 16px;
|
grid-gap: 16px;
|
||||||
grid-template-columns: ${cssManager.cssGridColumns(2, 16)};
|
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||||
|
margin-top: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.org {
|
.org {
|
||||||
padding: 16px;
|
padding: 20px;
|
||||||
border-top: 1px solid #444;
|
background: var(--card);
|
||||||
background: ${cssManager.bdTheme('#ccc', '#222')};
|
border: 1px solid var(--border);
|
||||||
border-radius: 16px;
|
border-radius: 12px;
|
||||||
|
color: var(--foreground);
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.org:hover {
|
.org:hover {
|
||||||
cursor: default;
|
background: var(--muted);
|
||||||
background: ${cssManager.bdTheme('#CCC', '#333')};
|
border-color: var(--muted-foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.org dees-icon {
|
||||||
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
@@ -100,6 +141,7 @@ export class BaseView extends DeesElement {
|
|||||||
if (state.accountState.getState().organizations.length === 0) {
|
if (state.accountState.getState().organizations.length === 0) {
|
||||||
render(
|
render(
|
||||||
html`
|
html`
|
||||||
|
<div class="card">
|
||||||
<h1>Setup Your Account</h1>
|
<h1>Setup Your Account</h1>
|
||||||
<p>
|
<p>
|
||||||
There are no organizations for your account. Please create one now. Alternatively you
|
There are no organizations for your account. Please create one now. Alternatively you
|
||||||
@@ -109,7 +151,7 @@ export class BaseView extends DeesElement {
|
|||||||
<dees-input-text .label=${'Organization Name'} .key=${'orgName'}></dees-input-text>
|
<dees-input-text .label=${'Organization Name'} .key=${'orgName'}></dees-input-text>
|
||||||
</dees-form>
|
</dees-form>
|
||||||
<p>
|
<p>
|
||||||
The organization slug corresponds to the organization name:<br />
|
The organization slug will be:<br />
|
||||||
<span class="slug"
|
<span class="slug"
|
||||||
>${directives.subscribe(
|
>${directives.subscribe(
|
||||||
state.accountState.select((stateArg) => stateArg.newOrg.chosenSlug)
|
state.accountState.select((stateArg) => stateArg.newOrg.chosenSlug)
|
||||||
@@ -118,6 +160,7 @@ export class BaseView extends DeesElement {
|
|||||||
</p>
|
</p>
|
||||||
<span class="hint"></span>
|
<span class="hint"></span>
|
||||||
<dees-button .disabled=${true}>Create the Organization</dees-button>
|
<dees-button .disabled=${true}>Create the Organization</dees-button>
|
||||||
|
</div>
|
||||||
`,
|
`,
|
||||||
viewHost
|
viewHost
|
||||||
);
|
);
|
||||||
@@ -169,6 +212,7 @@ export class BaseView extends DeesElement {
|
|||||||
render(
|
render(
|
||||||
html`
|
html`
|
||||||
<h1>Select An Organization</h1>
|
<h1>Select An Organization</h1>
|
||||||
|
<p>Choose an organization to manage its settings and billing.</p>
|
||||||
<div class="orgGrid">
|
<div class="orgGrid">
|
||||||
${state.accountState.getState().organizations.map((orgArg) => {
|
${state.accountState.getState().organizations.map((orgArg) => {
|
||||||
return html`
|
return html`
|
||||||
@@ -180,7 +224,7 @@ export class BaseView extends DeesElement {
|
|||||||
parentElement.subrouter.pushUrl(`/org/${orgArg.data.slug}/billing`);
|
parentElement.subrouter.pushUrl(`/org/${orgArg.data.slug}/billing`);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<dees-icon .iconFA=${"wallet"} style="display: inline-block; transform: translateY(3px); padding-right: 4px;"></dees-icon> ${orgArg.data.name}
|
<dees-icon .icon=${'lucide:building2'} style="display: inline-block; transform: translateY(3px); padding-right: 8px;"></dees-icon> ${orgArg.data.name}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
css,
|
css,
|
||||||
} from '@design.estate/dees-element';
|
} from '@design.estate/dees-element';
|
||||||
|
|
||||||
import sharedStyles from '../sharedstyles.js';
|
import sharedStyles, { accountDesignTokens, cardStyles, typographyStyles } from '../sharedstyles.js';
|
||||||
|
|
||||||
import * as state from '../../../states/accountstate.js';
|
import * as state from '../../../states/accountstate.js';
|
||||||
|
|
||||||
@@ -46,48 +46,106 @@ export class SubscriptionView extends DeesElement {
|
|||||||
|
|
||||||
public static styles = [
|
public static styles = [
|
||||||
cssManager.defaultStyles,
|
cssManager.defaultStyles,
|
||||||
sharedStyles,
|
accountDesignTokens,
|
||||||
|
cardStyles,
|
||||||
|
typographyStyles,
|
||||||
css`
|
css`
|
||||||
:host {
|
:host {
|
||||||
display: block;
|
display: block;
|
||||||
|
padding: 48px;
|
||||||
max-width: 900px;
|
max-width: 900px;
|
||||||
margin: auto;
|
margin: 0 auto;
|
||||||
color: ${cssManager.bdTheme('#333', '#fff')};
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
margin-bottom: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: var(--card);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 24px;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--foreground);
|
||||||
|
margin: 24px 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dees-table {
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dees-button {
|
||||||
|
margin-top: 16px;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
]
|
]
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
return html`
|
return html`
|
||||||
<h1>-> Billing & Subscription</h1>
|
<h1>Billing & Subscription</h1>
|
||||||
This page allows you to setup how you are billed for any workspace.global charges.
|
<p>Manage your billing settings and subscriptions for your organization.</p>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
<h2>Payment Method</h2>
|
<h2>Payment Method</h2>
|
||||||
|
<div class="card">
|
||||||
<p>Our customer-side billing is handled by paddle.com. You subscribe to a free plan there,
|
<p>Our customer-side billing is handled by paddle.com. You subscribe to a free plan there,
|
||||||
and we will bill any occurring charges as an extra on the monthly date of your choosing.
|
and we will bill any occurring charges as an extra on the monthly date of your choosing.
|
||||||
Paddle.com will take care of proper VAT invoices that will allow for VAT reduction according to the law.</p>
|
Paddle.com will take care of proper VAT invoices that will allow for VAT reduction according to the law.</p>
|
||||||
|
|
||||||
<h3>Paddle</h3>
|
<h3>Paddle</h3>
|
||||||
<dees-button @click=${async () => {
|
<dees-button @click=${async () => {
|
||||||
await this.domtoolsPromise;
|
await this.domtoolsPromise;
|
||||||
this.domtools.router.pushUrl(`/org/${state.accountState.getState().selectedOrg.data.slug}/paddlesetup`)
|
this.domtools.router.pushUrl(`/org/${state.accountState.getState().selectedOrg.data.slug}/paddlesetup`)
|
||||||
}}>set up paddle.com</dees-button>
|
}}>Set up Paddle.com</dees-button>
|
||||||
<h3>Enterprise billing</h3>
|
|
||||||
Once you have 100 or more Pro Plan users, you can request custom Enterprise billing for your organization here. Note: You are currently not eligible.
|
<h3>Enterprise Billing</h3>
|
||||||
|
<p>Once you have 100 or more Pro Plan users, you can request custom Enterprise billing for your organization here.</p>
|
||||||
|
<p><em>Note: You are currently not eligible.</em></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
<h2>Subscriptions</h2>
|
<h2>Subscriptions</h2>
|
||||||
|
<div class="card">
|
||||||
<p>
|
<p>
|
||||||
The total price of a subscription already includes all taxes. If you are a VAT registered business,
|
The total price of a subscription already includes all taxes. If you are a VAT registered business,
|
||||||
the actual price might be cheaper in case you can claim VAT exemption from the purchase.
|
the actual price might be cheaper in case you can claim VAT exemption from the purchase.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Note: Subscriptions are tied to prganizations. You are only seeing subcriptions regarding ${'org1'} right now.
|
<em>Note: Subscriptions are tied to organizations. Select the respective organization from the sidebar to view its subscriptions.</em>
|
||||||
To see other organization, select the respective organization at the top left of this page.
|
|
||||||
</p>
|
</p>
|
||||||
<dees-table .heading1=${'Subscriptions'} .heading2=${`for organization ${'org1'}`} .data=${this.subscriptions}></dees-table>
|
<dees-table .heading1=${'Subscriptions'} .heading2=${`for organization`} .data=${this.subscriptions}></dees-table>
|
||||||
<dees-button>Add subscription</dees-button>
|
<dees-button>Add Subscription</dees-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
<h2>Accrued IaaS Usage</h2>
|
<h2>Accrued IaaS Usage</h2>
|
||||||
<p>Note: The accrued IaaS Usage will be charged by adjusting the workspsace.gobal IaaS Postpaid Access price prior the renewal date.</p>
|
<div class="card">
|
||||||
<dees-table .heading1=${'Subscriptions'} .heading2=${`for organization ${'org1'}`} .data=${this.subscriptions}></dees-table>
|
<p>The accrued IaaS Usage will be charged by adjusting the workspace.global IaaS Postpaid Access price prior to the renewal date.</p>
|
||||||
|
<dees-table .heading1=${'Usage'} .heading2=${`for organization`} .data=${this.subscriptions}></dees-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
<h2>Upcoming Billable Items</h2>
|
<h2>Upcoming Billable Items</h2>
|
||||||
|
<div class="card">
|
||||||
|
<p>No upcoming billable items.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
<h2>Past Invoices</h2>
|
<h2>Past Invoices</h2>
|
||||||
|
<div class="card">
|
||||||
|
<p>No past invoices available.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,9 +167,9 @@ export class IdpLoginPrompt extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private login = async (valueArg: { emailAddress: string; passwordArg: string }) => {
|
private login = async (valueArg: { emailAddress: string; passwordArg: string }) => {
|
||||||
// lets disable the register button
|
// lets disable the submit button
|
||||||
const registerButton: plugins.deesCatalog.DeesButton = this.shadowRoot.querySelector('.registerButton');
|
const loginSubmitButton: plugins.deesCatalog.DeesFormSubmit = this.shadowRoot.querySelector('#loginSubmitButton');
|
||||||
registerButton.disabled = true;
|
loginSubmitButton.disabled = true;
|
||||||
// lets define the needed requests
|
// lets define the needed requests
|
||||||
const idpState = await IdpState.getSingletonInstance();
|
const idpState = await IdpState.getSingletonInstance();
|
||||||
const loginForm: DeesForm = this.shadowRoot.querySelector('#loginForm');
|
const loginForm: DeesForm = this.shadowRoot.querySelector('#loginForm');
|
||||||
|
|||||||
Reference in New Issue
Block a user