Closed maryam4s26 closed 9 months ago
I'm not really sure what you mean by "disabling" the client exactly.
But if you just want to block input, then you can create a service provider that places a transparent element into the DOM at the max z-index that captures the events instead of the desktop/panels/windows/etc.
I'm not really sure what you mean by "disabling" the client exactly.
But if you just want to block input, then you can create a service provider that places a transparent element into the DOM at the max z-index that captures the events instead of the desktop/panels/windows/etc.
Could you please give me an example?
Create a service provider:
// my-provider.js
export default class DisableUIServiceProvider {
constructor(core) {
this.core = core;
this.$overlay = document.createElement('div');
}
init() {
// Provide as an API. You can also use events for this, or some other custom stuff inside this provider.
this.core.singleton('custom/disable-ui', () => ({
enable: () => this.enable(),
disable: () => this.disable(),
}));
this.$overlay.appendChild(document.createTextNode('UI has been disabled!'));
Object.assign(this.$overlay.style, {
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
zIndex: 'calc(9e999)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '40px',
fontWeight: 'bold',
color: '#fff',
})
}
provides() {
return [
'custom/disable-ui'
]
}
enable() {
if (this.$overlay.parentNode) {
document.body.removeChild(this.$overlay);
}
}
disable() {
if (!this.$overlay.parentNode) {
document.body.appendChild(this.$overlay);
}
}
}
Register:
// index.js
import DisableUIServiceProvider from './my-provider.js'
// ...
osjs.register(DisableUIServiceProvider);
// ...
Test out in browser console:
OSjs.make('custom/disable-ui').disable(); // Disable UI
OSjs.make('custom/disable-ui').enable(); // Enable UI
This only blocks mouse events, but you can probably expand this to force focus onto a hidden input field for keyboard as well.
Thank you for your complete explanation. In fact, I wanted the background to be disabled and a dialog to be shown to the user and not allowed to do anything until the user clicked the OK button. But the dialogue is not the highest and it is not @andersevenrud
// my-provider.js
export default class SessionExpiryServiceProvider extends ServiceProvider {
constructor(core, options = {}) {
super(core, options);
this.core = core;
this.timeout = core.configuration.sessionTimeout;
this.$overlay = document.createElement('div');
}
provide() {}
async init() {
setTimeout(() => {
Object.assign(this.$overlay.style, {
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
zIndex: 'calc(9e999)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '40px',
fontWeight: 'bold',
color: '#fff',
});
document.body.appendChild(this.$overlay);
const args = {
message: 'Your session has been expired. Please logout and login again.',
title: 'Error',
buttons: ['ok'],
};
this.core.make('osjs/dialog', 'confirm', args, (btn, value) => {
if(btn === 'ok') {
this.core.make('osjs/auth').logout();
}
});
}, this.timeout);
}
}
The easiest way I can think of is just to hack it so that you move the dialog into the new overlay.
Or you could just create some basic custom UI to avoid using a hack-y solution like this.
export default class SessionExpiryServiceProvider {
constructor(core) {
this.core = core;
this.$overlay = document.createElement('div');
}
init() {
const sessionTimeout = this.core.config('sessionTimeout', 5000);
Object.assign(this.$overlay.style, {
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
zIndex: 'calc(9e999)',
});
setTimeout(() => this.run(), sessionTimeout);
}
run() {
this.core.$root.appendChild(this.$overlay); // core.$root is the same as document.body, but "safe"
const args = {
message: 'Your session has been expired. Please logout and login again.',
title: 'Error',
buttons: ['ok'],
};
const instance = this.core.make('osjs/dialog', 'confirm', args, () => {
this.core.make('osjs/auth').logout();
});
// HACK: Move Window to our overlay instead of core.$contents
this.$overlay.appendChild(instance.win.$element);
}
}
Thank you for your complete explanation. Yes, it was completely correct.
And how can expand this to force focus onto a hidden input field for keyboard? @andersevenrud
Great!
Please close your own issues after they have been resolved.
I didn't see your edit. Better to post a new comment instead so I get notifications for it :)
To capture all the keyboard events you can actually just do this:
run() {
const args = {
message: 'Your session has been expired. Please logout and login again.',
title: 'Error',
buttons: ['ok'],
};
const instance = this.core.make('osjs/dialog', 'confirm', args, () => {
this.core.make('osjs/auth').logout();
});
// Prevent keys to be executed outside window
for (const n of ['keydown', 'keyup', 'keypress']) {
this.core.$root.addEventListener(n, (ev) => {
if (!instance.win.$element.contains(ev.target)) {
ev.preventDefault();
ev.stopPropagation();
}
});
}
// NOTE: core.$root is the same as document.body, but "safe"
this.core.$root.appendChild(this.$overlay);
// HACK: Move Window to our overlay instead of core.$contents
this.$overlay.appendChild(instance.win.$element);
}
thanks a lot
hi @andersevenrud . Is it possible to disable the client when necessary so that the user cannot do anything or prevent user interactions and display to the user an error dialog?