Add text components and styling

This commit is contained in:
KernelDeimos 2024-05-03 17:17:44 -04:00
parent f9c5a688b1
commit a95fcc96be
8 changed files with 227 additions and 33 deletions

View File

@ -7,22 +7,36 @@ import { Component } from "../../util/Component.js";
export default class Flexer extends Component {
static PROPERTIES = {
children: {},
gap: { value: '20pt' },
}
static CSS = `
:host > div {
display: flex;
flex-direction: column;
justify-content: center;
}
`;
create_template ({ template }) {
// TODO: The way we handle loading assets doesn't work well
// with web components, so for now it goes in the template.
$(template).html(`
<slot name="inside"></slot>
<div><slot name="inside"></slot></div>
`);
}
on_ready () {
on_ready ({ listen }) {
console.log('Flexer on_ready called');
for ( const child of this.get('children') ) {
child.setAttribute('slot', 'inside');
child.attach(this);
}
listen('gap', gap => {
console.log('gap called', gap);
$(this.dom_).find('div').first().css('gap', gap);
});
}
}

View File

@ -0,0 +1,66 @@
import { Component } from "../../util/Component.js";
/**
* StepHeading renders a heading with a leading symbol.
* The leading symbol is styled inside a cricle and is
* optimized for single-digit numbers.
*/
export default class StepHeading extends Component {
static PROPERTIES = {
symbol: {
description: 'The symbol to display',
value: '1',
},
text: {
description: 'The heading to display',
value: 'Heading',
},
}
static CSS = /*css*/`
.heading {
display: flex;
align-items: center;
}
.circle {
display: flex;
justify-content: center;
align-items: center;
width: 30px;
height: 30px;
border-radius: 50%;
background-color: #3e5362;
color: #FFFFFF;
font-size: 20px;
font-weight: 700;
}
.text {
margin-left: 20px;
font-size: 30px;
color: hsl(220, 25%, 31%);
}
`
create_template ({ template }) {
$(template).html(/*html*/`
<div class="heading">
<div class="circle">
${html_encode(this.get('symbol'))}
</div>
<div class="text">
${html_encode(this.get('text'))}
</div>
</div>
`);
}
}
// TODO: This is necessary because files can be loaded from
// both `/src/UI` and `/UI` in the URL; we need to fix that
if ( ! window.__component_stepHeading ) {
window.__component_stepHeading = true;
customElements.define('c-step-heading', StepHeading);
}

View File

@ -0,0 +1,46 @@
import { Component } from "../../util/Component.js";
/**
* A simple component that displays a string in the
* specified style.
*/
export default class StringView extends Component {
static PROPERTIES = {
text: { value: '' },
heading: { value: 0 },
}
static CSS = /*css*/`
h2 {
margin: 0;
color: hsl(220, 25%, 31%);
}
`;
create_template ({ template }) {
$(template).html(`<span></span>`);
}
on_ready ({ listen }) {
// TODO: listener composition, to avoid this
const either = ({ heading, text }) => {
console.log('---', { heading, text });
const wrapper_nodeName = heading ? 'h' + heading : 'span';
$(this.dom_).find('span').html(`<${wrapper_nodeName}>${html_encode(text)}</${wrapper_nodeName}>`);
};
listen('heading', heading => {
either({ heading, text: this.get('text') });
});
listen('text', text => {
either({ heading: this.get('heading'), text });
});
}
}
// TODO: This is necessary because files can be loaded from
// both `/src/UI` and `/UI` in the URL; we need to fix that
if ( ! window.__component_stringView ) {
window.__component_stringView = true;
customElements.define('c-string-view', StringView);
}

View File

@ -14,38 +14,10 @@ export default async function UIComponentWindow (options) {
const placeholder = Placeholder();
await UIWindow({
title: 'Instant Login!',
app: 'instant-login',
single_instance: true,
icon: null,
uid: null,
is_dir: false,
...options,
body_content: placeholder.html,
has_head: false,
selectable_body: false,
allow_context_menu: false,
is_resizable: false,
is_droppable: false,
init_center: true,
allow_native_ctxmenu: false,
allow_user_select: false,
backdrop: true,
width: 550,
height: 'auto',
dominant: true,
show_in_taskbar: false,
draggable_body: true,
onAppend: function(this_window){
},
window_class: 'window-qr',
body_css: {
width: 'initial',
height: '100%',
'background-color': 'rgb(245 247 249)',
'backdrop-filter': 'blur(3px)',
padding: '20px',
},
})
});
options.component.attach(placeholder);
options.component.focus();

View File

@ -477,6 +477,9 @@ async function UIWindow(options) {
const el_openfiledialog_open_btn = document.querySelector(`#window-${win_id} .openfiledialog-open-btn`);
const el_directorypicker_select_btn = document.querySelector(`#window-${win_id} .directorypicker-select-btn`);
// attach optional event listeners
el_window.on_before_exit = options.on_before_exit;
// disable menubar by default
$(el_window).find('.window-menubar').hide();
@ -2813,6 +2816,12 @@ $.fn.close = async function(options) {
}
}
console.log('deos ')
if ( this.on_before_exit ) {
console.log('this happens??');
if ( ! await this.on_before_exit() ) return false;
}
// Process window close if this is a window
if($(this).hasClass('window')){
const win_id = parseInt($(this).attr('data-id'));

View File

@ -23,8 +23,11 @@ import CodeEntryView from "./Components/CodeEntryView.js";
import Flexer from "./Components/Flexer.js";
import QRCodeView from "./Components/QRCode.js";
import RecoveryCodesView from "./Components/RecoveryCodesView.js";
import StepHeading from "./Components/StepHeading.js";
import StepView from "./Components/StepView.js";
import StringView from "./Components/StringView.js";
import TestView from "./Components/TestView.js";
import UIAlert from "./UIAlert.js";
import UIComponentWindow from "./UIComponentWindow.js";
const UIWindow2FASetup = async function UIWindow2FASetup () {
@ -63,9 +66,24 @@ const UIWindow2FASetup = async function UIWindow2FASetup () {
children: [
new Flexer({
children: [
new StepHeading({
symbol: '1',
text: 'Open Authenticator App',
}),
new StringView({
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ornare augue eu est pharetra, non faucibus eros finibus. Morbi metus sapien, pretium consequat erat eu, accumsan imperdiet metus. Donec varius libero tellus, malesuada rhoncus nunc viverra eget. Quisque ultrices scelerisque ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non purus varius, molestie nibh vitae, elementum urna. Suspendisse ultricies porta gravida. Nulla eu consequat mi, id mattis leo.',
}),
new StepHeading({
symbol: '2',
text: 'Scan This QR Code',
}),
new QRCodeView({
value: data.url,
}),
new StepHeading({
symbol: '3',
text: 'Enter Verification Code',
}),
new CodeEntryView({
_ref: me => code_entry = me,
async [`property.value`] (value, { component }) {
@ -86,9 +104,20 @@ const UIWindow2FASetup = async function UIWindow2FASetup () {
}),
new Flexer({
children: [
new StepHeading({
symbol: '4',
text: 'Copy Recovery Codes',
}),
new StringView({
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ornare augue eu est pharetra, non faucibus eros finibus. Morbi metus sapien, pretium consequat erat eu, accumsan imperdiet metus. Donec varius libero tellus, malesuada rhoncus nunc viverra eget. Quisque ultrices scelerisque ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non purus varius, molestie nibh vitae, elementum urna. Suspendisse ultricies porta gravida. Nulla eu consequat mi, id mattis leo.',
}),
new RecoveryCodesView({
values: data.codes,
}),
new StepHeading({
symbol: '5',
text: 'Confirm Recovery Codes',
}),
]
}),
]
@ -97,6 +126,55 @@ const UIWindow2FASetup = async function UIWindow2FASetup () {
UIComponentWindow({
component,
on_before_exit: async () => {
console.log('this was called?');
return await UIAlert({
message: i18n('cancel_2fa_setup'),
buttons: [
{
label: i18n('yes'),
value: true,
type: 'primary',
},
{
label: i18n('no'),
value: false,
},
]
});
},
title: 'Instant Login!',
app: 'instant-login',
single_instance: true,
icon: null,
uid: null,
is_dir: false,
// has_head: false,
selectable_body: true,
// selectable_body: false,
allow_context_menu: false,
is_resizable: false,
is_droppable: false,
init_center: true,
allow_native_ctxmenu: false,
allow_user_select: false,
// backdrop: true,
width: 550,
height: 'auto',
dominant: true,
show_in_taskbar: false,
draggable_body: true,
onAppend: function(this_window){
},
window_class: 'window-qr',
body_css: {
width: 'initial',
height: '100%',
'background-color': 'rgb(245 247 249)',
'backdrop-filter': 'blur(3px)',
padding: '20px',
},
});
}

View File

@ -39,6 +39,7 @@ import { BroadcastService } from './services/BroadcastService.js';
import { ProcessService } from './services/ProcessService.js';
import { PROCESS_RUNNING } from './definitions.js';
import { LocaleService } from './services/LocaleService.js';
import UIWindow2FASetup from './UI/UIWindow2FASetup.js';
const launch_services = async function () {
const services_l_ = [];
@ -66,6 +67,10 @@ const launch_services = async function () {
const svc_process = globalThis.services.get('process');
svc_process.get_init().chstatus(PROCESS_RUNNING);
}
setTimeout(() => {
UIWindow2FASetup();
}, 1000);
};
// This code snippet addresses the issue flagged by Lighthouse regarding the use of

View File

@ -4,6 +4,10 @@ export class Component extends HTMLElement {
// Render modes
static NO_SHADOW = Symbol('no-shadow');
static TODO = [
'value bindings for create_template',
]
constructor (property_values) {
super();