|
@@ -26,9 +26,8 @@ import Button from './Components/Button.js';
|
|
* @param operation_id If provided, is saved in the data-operation-id attribute, for later lookup.
|
|
* @param operation_id If provided, is saved in the data-operation-id attribute, for later lookup.
|
|
* @param show_progress Enable a progress bar, and display `(foo%)` after the status message
|
|
* @param show_progress Enable a progress bar, and display `(foo%)` after the status message
|
|
* @param on_cancel A callback run when the Cancel button is clicked. Without it, no Cancel button will appear.
|
|
* @param on_cancel A callback run when the Cancel button is clicked. Without it, no Cancel button will appear.
|
|
- * @returns {Promise<{set_progress: *, set_status: *, close: *, element: Element}>} Object for managing the progress dialog
|
|
|
|
|
|
+ * @returns {Promise<{set_progress: *, set_status: *, close: *, show_error: *, element: Element}>} Object for managing the progress dialog
|
|
* @constructor
|
|
* @constructor
|
|
- * TODO: Error display
|
|
|
|
* TODO: Debouncing logic (show only after a delay, then hide only after a delay)
|
|
* TODO: Debouncing logic (show only after a delay, then hide only after a delay)
|
|
*/
|
|
*/
|
|
async function UIWindowProgress({
|
|
async function UIWindowProgress({
|
|
@@ -37,30 +36,47 @@ async function UIWindowProgress({
|
|
on_cancel = null,
|
|
on_cancel = null,
|
|
} = {}){
|
|
} = {}){
|
|
const placeholder_cancel_btn = Placeholder();
|
|
const placeholder_cancel_btn = Placeholder();
|
|
|
|
+ const placeholder_ok_btn = Placeholder();
|
|
|
|
|
|
let h = '';
|
|
let h = '';
|
|
h += `<div ${operation_id ? `data-operation-id="${operation_id}"` : ''}>`;
|
|
h += `<div ${operation_id ? `data-operation-id="${operation_id}"` : ''}>`;
|
|
- h += `<div style="display: flex; align-items: center;">`;
|
|
|
|
- // spinner
|
|
|
|
- h += `<svg style="margin-right: 7px; overflow: visible;" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><title>circle anim</title><g fill="#212121" 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="#212121" 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>`;
|
|
|
|
- // Progress report
|
|
|
|
- h += `<div style="font-size:15px; overflow: hidden; flex-grow: 1; text-overflow: ellipsis; white-space: nowrap;">
|
|
|
|
- <span class="progress-msg">${i18n('preparing')}</span>`;
|
|
|
|
|
|
+ h += `<div class="progress-running">`;
|
|
|
|
+ h += `<div style="display: flex; align-items: center; gap: 7px;">`;
|
|
|
|
+ // spinner
|
|
|
|
+ h += `<svg style="overflow: visible;" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24"><title>circle anim</title><g fill="#212121" 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="#212121" 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>`;
|
|
|
|
+ // Progress report
|
|
|
|
+ h += `<div style="font-size:15px; overflow: hidden; flex-grow: 1; text-overflow: ellipsis; white-space: nowrap;">
|
|
|
|
+ <span class="progress-msg">${i18n('preparing')}</span>`;
|
|
|
|
+ if (show_progress) {
|
|
|
|
+ h += ` (<span class="progress-percent">0%</span>)`;
|
|
|
|
+ }
|
|
|
|
+ h += `</div>`;
|
|
|
|
+ h +=`</div>`;
|
|
if (show_progress) {
|
|
if (show_progress) {
|
|
- h += ` (<span class="progress-percent">0%</span>)`;
|
|
|
|
|
|
+ h += `<div class="progress-bar-container" style="margin-top:20px;">`;
|
|
|
|
+ h += `<div class="progress-bar"></div>`;
|
|
|
|
+ h += `</div>`;
|
|
}
|
|
}
|
|
|
|
+ if (on_cancel) {
|
|
|
|
+ h += `<div style="display: flex; justify-content: flex-end;">`;
|
|
|
|
+ h += placeholder_cancel_btn.html;
|
|
|
|
+ h += `</div>`;
|
|
|
|
+ }
|
|
|
|
+ h += `</div>`;
|
|
|
|
+ h += `<div class="progress-error" style="display: none">`;
|
|
|
|
+ h += `<div style="display: flex; align-items: center; gap: 7px;">`;
|
|
|
|
+ // Alert icon
|
|
|
|
+ h += `<img style="width:24px; height:24px;" src="${html_encode(window.icons['warning-sign.svg'])}" />`;
|
|
|
|
+ // Progress report
|
|
|
|
+ h += `<div style="font-size:15px; overflow: hidden; flex-grow: 1; text-overflow: ellipsis; white-space: nowrap;">
|
|
|
|
+ <span class="progress-error-title"></span>`;
|
|
|
|
+ h += `</div>`;
|
|
h += `</div>`;
|
|
h += `</div>`;
|
|
- h +=`</div>`;
|
|
|
|
- if (show_progress) {
|
|
|
|
- h += `<div class="progress-bar-container" style="margin-top:20px;">`;
|
|
|
|
- h += `<div class="progress-bar"></div>`;
|
|
|
|
- h += `</div>`;
|
|
|
|
- }
|
|
|
|
- if (on_cancel) {
|
|
|
|
|
|
+ h += `<p class="progress-error-message"></p>`;
|
|
h += `<div style="display: flex; justify-content: flex-end;">`;
|
|
h += `<div style="display: flex; justify-content: flex-end;">`;
|
|
- h += placeholder_cancel_btn.html;
|
|
|
|
|
|
+ h += placeholder_ok_btn.html;
|
|
h += `</div>`;
|
|
h += `</div>`;
|
|
- }
|
|
|
|
|
|
+ h += `</div>`;
|
|
h += `</div>`;
|
|
h += `</div>`;
|
|
|
|
|
|
const el_window = await UIWindow({
|
|
const el_window = await UIWindow({
|
|
@@ -106,6 +122,15 @@ async function UIWindowProgress({
|
|
cancel_btn.attach(placeholder_cancel_btn);
|
|
cancel_btn.attach(placeholder_cancel_btn);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ const ok_btn = new Button({
|
|
|
|
+ label: i18n('ok'),
|
|
|
|
+ style: 'small',
|
|
|
|
+ on_click: () => {
|
|
|
|
+ $(el_window).close();
|
|
|
|
+ },
|
|
|
|
+ });
|
|
|
|
+ ok_btn.attach(placeholder_ok_btn);
|
|
|
|
+
|
|
return {
|
|
return {
|
|
element: el_window,
|
|
element: el_window,
|
|
set_status: (text) => {
|
|
set_status: (text) => {
|
|
@@ -118,7 +143,12 @@ async function UIWindowProgress({
|
|
close: () => {
|
|
close: () => {
|
|
$(el_window).close();
|
|
$(el_window).close();
|
|
},
|
|
},
|
|
- // TODO: show_error(), which replaces the window content with a title, error message, and OK button
|
|
|
|
|
|
+ show_error: (title, message) => {
|
|
|
|
+ el_window.querySelector('.progress-running').style.display = 'none';
|
|
|
|
+ el_window.querySelector('.progress-error').style.display = 'block';
|
|
|
|
+ el_window.querySelector('.progress-error-title').innerText = title;
|
|
|
|
+ el_window.querySelector('.progress-error-message').innerText = message;
|
|
|
|
+ },
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|