Add the wizardy behaviour

This commit is contained in:
KernelDeimos 2024-05-03 00:42:06 -04:00
parent 662fd13548
commit 22234ad1c1
8 changed files with 136 additions and 37 deletions

View File

@ -1,18 +0,0 @@
export default class Button extends Component {
static PROPERTIES = {
label_key: {
description: 'The key to use to look up the label for the button',
},
click: {
description: 'The function to call when the button is clicked',
},
}
create_template ({ template }) {
$(template).html(`
<button class="button button-block button-primary" data-button>
${i18n(this.get('label_key'))}
</button>
`);
}
}

View File

@ -76,8 +76,8 @@ export default class CodeEntryView extends Component {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
$(this.dom_).find('.code-confirm-btn').prop('disabled', true); $(this).prop('disabled', true);
$(this.dom_).find('.error').hide(); $(this).closest('.error').hide();
// Check if already checking code to prevent multiple requests // Check if already checking code to prevent multiple requests
if(is_checking_code) if(is_checking_code)
@ -86,7 +86,7 @@ export default class CodeEntryView extends Component {
is_checking_code = true; is_checking_code = true;
// set animation // set animation
$(this.dom_).find('.code-confirm-btn').html(`<svg style="width:20px; margin-top: 5px;" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><title>circle anim</title><g fill="#fff" class="nc-icon-wrapper"><g class="nc-loop-circle-24-icon-f"><path d="M12 24a12 12 0 1 1 12-12 12.013 12.013 0 0 1-12 12zm0-22a10 10 0 1 0 10 10A10.011 10.011 0 0 0 12 2z" fill="#eee" opacity=".4"></path><path d="M24 12h-2A10.011 10.011 0 0 0 12 2V0a12.013 12.013 0 0 1 12 12z" data-color="color-2"></path></g><style>.nc-loop-circle-24-icon-f{--animation-duration:0.5s;transform-origin:12px 12px;animation:nc-loop-circle-anim var(--animation-duration) infinite linear}@keyframes nc-loop-circle-anim{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}</style></g></svg>`); $(this).html(`<svg style="width:20px; margin-top: 5px;" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><title>circle anim</title><g fill="#fff" class="nc-icon-wrapper"><g class="nc-loop-circle-24-icon-f"><path d="M12 24a12 12 0 1 1 12-12 12.013 12.013 0 0 1-12 12zm0-22a10 10 0 1 0 10 10A10.011 10.011 0 0 0 12 2z" fill="#eee" opacity=".4"></path><path d="M24 12h-2A10.011 10.011 0 0 0 12 2V0a12.013 12.013 0 0 1 12 12z" data-color="color-2"></path></g><style>.nc-loop-circle-24-icon-f{--animation-duration:0.5s;transform-origin:12px 12px;animation:nc-loop-circle-anim var(--animation-duration) infinite linear}@keyframes nc-loop-circle-anim{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}</style></g></svg>`);
}) })
// Elements // Elements
@ -126,10 +126,10 @@ export default class CodeEntryView extends Component {
for(let i=0; i< numberCodeInputs.length; i++){ for(let i=0; i< numberCodeInputs.length; i++){
current_code += numberCodeInputs[i].value; current_code += numberCodeInputs[i].value;
} }
this.set('value', current_code);
// Automatically submit if 6 digits entered // Automatically submit if 6 digits entered
if(current_code.length === 6){ if(current_code.length === 6){
this.set('value', current_code);
$(this.dom_).find('.code-confirm-btn').prop('disabled', false); $(this.dom_).find('.code-confirm-btn').prop('disabled', false);
$(this.dom_).find('.code-confirm-btn').trigger('click'); $(this.dom_).find('.code-confirm-btn').trigger('click');
} }

View File

@ -19,7 +19,6 @@ export default class Flexer extends Component {
on_ready () { on_ready () {
console.log('Flexer on_ready called'); console.log('Flexer on_ready called');
debugger;
for ( const child of this.get('children') ) { for ( const child of this.get('children') ) {
child.setAttribute('slot', 'inside'); child.setAttribute('slot', 'inside');
child.attach(this); child.attach(this);

View File

@ -18,8 +18,6 @@ export default class QRCodeView extends Component {
` `
create_template ({ template }) { 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(` $(template).html(`
<div class="qr-code opt-qr-code"> <div class="qr-code opt-qr-code">
</div> </div>

View File

@ -0,0 +1,67 @@
import { Component } from "../../util/Component.js";
export default class StepView extends Component {
static PROPERTIES = {
children: {},
done: { value: false },
position: { value: 0 },
}
static CSS = `
#wrapper { display: none }
`;
create_template ({ template }) {
$(template).html(`
<div id="wrapper">
<slot name="inside"></slot>
</div>
`);
}
on_ready ({ listen }) {
for ( const child of this.get('children') ) {
child.setAttribute('slot', 'inside');
child.attach(this);
$(child).hide();
}
// show the first child
$(this.children[0]).show();
// listen for changes to the current step
listen('position', position => {
// hide all children
for ( const child of this.children ) {
$(child).hide();
}
// show the child at the current position
$(this.children[position]).show();
});
// now that we're ready, show the wrapper
$(this.dom_).find('#wrapper').show();
}
back () {
if ( this.get('position') === 0 ) return;
this.set('position', this.get('position') - 1);
}
next () {
if ( this.get('position') === this.children.length - 1 ) {
this.set('done', true);
return;
}
this.set('position', this.get('position') + 1);
}
}
// 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_stepView ) {
window.__component_stepView = true;
customElements.define('c-step-view', StepView);
}

View File

@ -0,0 +1,28 @@
import { Component } from "../../util/Component.js";
/**
* A simple component when you just need to test something.
*/
export default class TestView extends Component {
static CSS = `
div {
background-color: lightblue;
padding: 1em;
border-radius: 0.5em;
}
`;
create_template ({ template }) {
$(template).html(`
<div>I am a test view</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_testView ) {
window.__component_testView = true;
customElements.define('c-test-view', TestView);
}

View File

@ -22,6 +22,8 @@
import CodeEntryView from "./Components/CodeEntryView.js"; import CodeEntryView from "./Components/CodeEntryView.js";
import Flexer from "./Components/Flexer.js"; import Flexer from "./Components/Flexer.js";
import QRCodeView from "./Components/QRCode.js"; import QRCodeView from "./Components/QRCode.js";
import StepView from "./Components/StepView.js";
import TestView from "./Components/TestView.js";
import UIComponentWindow from "./UIComponentWindow.js"; import UIComponentWindow from "./UIComponentWindow.js";
const UIWindow2FASetup = async function UIWindow2FASetup () { const UIWindow2FASetup = async function UIWindow2FASetup () {
@ -35,18 +37,29 @@ const UIWindow2FASetup = async function UIWindow2FASetup () {
}); });
const data = await resp.json(); const data = await resp.json();
const component = new Flexer({ let stepper;
children: [ const component =
new QRCodeView({ new StepView({
value: data.url, _ref: me => stepper = me,
}), children: [
new CodeEntryView({ new Flexer({
on_update () { children: [
// NEXT new QRCodeView({
} value: data.url,
}), }),
] new CodeEntryView({
}); [`property.value`] (value) {
console.log('value? ', value)
stepper.next();
}
}),
new TestView(),
]
}),
new TestView(),
]
})
;
UIComponentWindow({ UIComponentWindow({
component, component,

View File

@ -24,8 +24,20 @@ export class Component extends HTMLElement {
let initial_value; let initial_value;
if ( property_values && key in property_values ) { if ( property_values && key in property_values ) {
initial_value = property_values[key]; initial_value = property_values[key];
} else if ( this.constructor.PROPERTIES[key].value !== undefined ) {
initial_value = this.constructor.PROPERTIES[key].value;
} }
this.values_[key] = ValueHolder.adapt(initial_value); this.values_[key] = ValueHolder.adapt(initial_value);
const listener_key = `property.${key}`;
if ( property_values[listener_key] ) {
this.values_[key].sub(property_values[listener_key]);
}
}
// Convenience for setting a property while composing components
if ( property_values && property_values.hasOwnProperty('_ref') ) {
property_values._ref(this);
} }
} }