Skip to content

Commit

Permalink
Add isLoading config
Browse files Browse the repository at this point in the history
  • Loading branch information
Nige White committed Nov 30, 2023
1 parent 3cac1db commit dd5dc88
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 46 deletions.
25 changes: 25 additions & 0 deletions resources/scss/src/component/Base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,28 @@
top : -10000px;
z-index : 1000;
}

.b-masked {
position : relative;

.neo-load-mask {
position : absolute;
inset : 0;
background-color : inherit;
z-index : 4;
display : grid;
justify-content : center;
align-content : center;

.neo-load-mask-body {
display : flex;
flex-flow : row nowrap;
gap : 0.7em;

.fa-spinner {
width : 1em;
height : 1em;
}
}
}
}
42 changes: 41 additions & 1 deletion src/component/Base.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,13 @@ class Base extends CoreBase {
* The vdom markup for this component.
* @member {Object} _vdom={}
*/
_vdom: {}
_vdom: {},
/**
* Set to `true` to show a spinner centered in the component.
* Set to a string to show a message next to a spinner centered in the component.
* @member {Boolean|String} isLoading=false
*/
isLoading_: null
}

/**
Expand Down Expand Up @@ -653,6 +659,40 @@ class Base extends CoreBase {
ComponentManager.register(this)
}

afterSetIsLoading(value) {
const
{ cls, vdom } = this,
maskIndex = vdom.cn.findIndex(c => c.cls === 'neo-load-mask');

// Remove the load mask
if (maskIndex !== -1) {
vdom.cn.splice(maskIndex, 1);
}

if (value) {
vdom.cn.push(this.loadMask = {
cls : 'neo-load-mask',
cn : [{
cls : 'neo-load-mask-body',
cn : [{
cls : 'fa fa-spinner fa-spin'
}, {
cls : 'neo-loading-message',
html : typeof value === 'string' ? value : null
}]
}]
});
NeoArray.add(cls, 'b-masked');
}
else {
NeoArray.remove(cls, 'b-masked');
}

this.cls = cls
this.update();
}


/**
* Triggered after the maxHeight config got changed
* @param {Number|String|null} value
Expand Down
51 changes: 37 additions & 14 deletions test/components/files/button/Base.mjs
Original file line number Diff line number Diff line change
@@ -1,17 +1,40 @@
StartTest(t => {
t.it('Checking if neo.mjs got started', async t => {
if (!globalThis.Neo?.Main) {
console.log('Starting the neo.mjs workers setup');

await import('../../../../src/MicroLoader.mjs');
}

setTimeout(() => {
Neo.worker.App.createNeoInstance({
ntype : 'button',
iconCls: 'fa fa-home',
text : 'Hello Siesta'
})
}, 300)
let button;

t.beforeEach(async t => {
// Causes errors
// button && await Neo.worker.App.destroyNeoInstance(button);
});

t.it('Sanity', async t => {
button = await Neo.worker.App.createNeoInstance({
ntype : 'button',
iconCls: 'fa fa-home',
text : 'Hello Siesta'
});
});

t.it('Should show isLoading UI', async t => {
button = await Neo.worker.App.createNeoInstance({
ntype : 'button',
iconCls : 'fa fa-home',
text : 'Hello Siesta',
isLoading : 'Loading...'
});

// Spinner and text exist
await t.waitForSelector('button .fa-spinner.fa-spin');
t.selectorExists('button .neo-loading-message:contains(Loading...)');

await Neo.worker.App.setConfigs({ id: button, isLoading : true });

// Just a spinner now, no text
await t.waitForSelectorNotFound('button .neo-loading-message:contains(Loading...)');
t.selectorExists('button .neo-loading-message:contains()');

await Neo.worker.App.setConfigs({ id: button, isLoading : false });

// Not loading now,
await t.waitForSelectorNotFound('button .neo-load-mask');
});
});
50 changes: 21 additions & 29 deletions test/components/files/form/field/Select.mjs
Original file line number Diff line number Diff line change
@@ -1,35 +1,27 @@
StartTest(t => {
t.it('Checking if neo.mjs got started', async t => {
if (!globalThis.Neo?.Main) {
console.log('Starting the neo.mjs workers setup');
t.it('Sanity', async t => {
Neo.worker.App.createNeoInstance({
ntype : 'selectfield',
labelPosition: 'inline',
labelText : 'US States',
labelWidth : 80,
width : 300,

await import('../../../../../src/MicroLoader.mjs');
}
store : {
autoLoad : true,
keyProperty: 'abbreviation',
url : '../../resources/examples/data/us_states.json',

setTimeout(() => {
Neo.worker.App.createNeoInstance({
ntype : 'selectfield',
labelPosition: 'inline',
labelText : 'US States',
labelWidth : 80,
width : 300,

store : {
autoLoad : true,
keyProperty: 'abbreviation',
url : '../../resources/examples/data/us_states.json',

model: {
fields: [{
name: 'abbreviation',
type: 'string'
}, {
name: 'name',
type: 'string'
}]
}
model: {
fields: [{
name: 'abbreviation',
type: 'string'
}, {
name: 'name',
type: 'string'
}]
}
})
}, 1000)
}
});
});
});
30 changes: 28 additions & 2 deletions test/components/siesta.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,34 @@
const project = new Siesta.Project.Browser();

project.configure({
title : 'Neo Component Tests',
isEcmaModule: true
title : 'Neo Component Tests',
isEcmaModule : true,
preload : [{
type : 'js',
url : '../../../../src/MicroLoader.mjs',
isEcmaModule : true
}],
testClass : Class('My.Test.Class', {
isa : Siesta.Test.Browser,
override : {
setup(callback, errback) {
this.SUPER(function() {
// We need to call the startup callback only when we know we are
// ready to start testing.
const
{ global } = this,
startupTimer = setInterval(() => {
if (global.Neo?.worker?.App && global.Neo.worker.Manager && global.Neo.Main) {
clearInterval(startupTimer);

// TODO: Find what we actually need to wait for
setTimeout(callback, 300);
}
}, 100);
}, errback);
}
}
})
});

project.plan(
Expand Down

0 comments on commit dd5dc88

Please sign in to comment.