Skip to content

Commit

Permalink
feat: dialog to confirm reload
Browse files Browse the repository at this point in the history
Closes #3240 #3886
  • Loading branch information
smbea committed Jan 23, 2024
1 parent 90434d5 commit 25322de
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 2 deletions.
4 changes: 4 additions & 0 deletions app/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,10 @@ renderer.on('client:error', function(...args) {
done(null);
});

renderer.on('app:reload', async function() {
app.mainWindow.reload();
});

app.on('web-contents-created', (event, webContents) => {

// open new window externally
Expand Down
2 changes: 1 addition & 1 deletion app/lib/menu/menu-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ class MenuBuilder {
submenuTemplate.push({
label: 'Reload',
accelerator: 'CommandOrControl+R',
click: (_, browserWindow) => browserWindow.reload()
click: () => app.emit('menu:action', 'reload-modeler')
});

submenuTemplate.push({
Expand Down
1 change: 1 addition & 0 deletions app/lib/preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const {
const generateId = require('./util/generate-id');

const allowedEvents = [
'app:reload',
'app:quit-aborted',
'app:quit-allowed',
'client:error',
Expand Down
45 changes: 44 additions & 1 deletion client/src/app/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,46 @@ export class App extends PureComponent {
return true;
};

/**
* Reload modeler.
*
* @return {Promise<boolean>} resolved to true if modeler is reloaded
*/
reloadModeler = async () => {
const dialog = this.getGlobal('dialog');
const hasUnsavedTabs = this.hasUnsavedTabs();

if (!hasUnsavedTabs) {
this.reload();
return;
}

const { button } = await dialog.showReloadDialog(hasUnsavedTabs);

if (button === 'save') {
await this.saveAllTabs();
this.reload();

} else if (button === 'reload') {
this.reload();
return true;
} else {
return false;
}
};


hasUnsavedTabs = () => {
const { tabs } = this.state;
return tabs.some((tab) => {
return this.isDirty(tab) || this.isUnsaved(tab);
});
};

reload = async (options) => {
this.getGlobal('backend').send('app:reload', options);
};

isEmptyTab = (tab) => {
return tab === EMPTY_TAB;
};
Expand Down Expand Up @@ -1453,7 +1493,6 @@ export class App extends PureComponent {
}

saveAllTabs = () => {

const {
tabs
} = this.state;
Expand Down Expand Up @@ -1838,6 +1877,10 @@ export class App extends PureComponent {
return this.resizeTab();
}

if (action === 'reload-modeler') {
return this.reloadModeler(options);
}

if (action === 'log') {
const {
action,
Expand Down
114 changes: 114 additions & 0 deletions client/src/app/__tests__/AppSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3143,6 +3143,120 @@ describe('<App>', function() {

});


describe('reload', function() {

describe('no unsaved changed', function() {

it('should not show dialog', async function() {

// given
const dialog = new Dialog();

const { app } = createApp({
globals: {
dialog
}
});

const reload = spy(app, 'reload');
const showReloadDialog = spy(dialog, 'showReloadDialog');

// when
dialog.setShowReloadModelerDialogResponse({ button: 'reload' });
app.reloadModeler();

// then
expect(reload).to.have.been.called;
expect(showReloadDialog).to.not.have.been.called;
});

});


describe('unsaved changes', function() {

it('should sve changes and reload app', async function() {

// given
const dialog = new Dialog();

const { app } = createApp({
globals: {
dialog
}
});

sinon.stub(app, 'hasUnsavedTabs').returns(true);

const reload = spy(app, 'reload');
const showReloadDialog = spy(dialog, 'showReloadDialog');
const save = spy(app, 'saveAllTabs');

// when
dialog.setShowReloadModelerDialogResponse({ button: 'save' });
await app.reloadModeler();

// then
expect(showReloadDialog).to.have.been.called;
expect(save).to.have.been.called;
expect(reload).to.have.been.called;
});

it('should reload app without saving', async function() {

// given
const dialog = new Dialog();

const { app } = createApp({
globals: {
dialog
}
});

sinon.stub(app, 'hasUnsavedTabs').returns(true);

const reload = spy(app, 'reload');
const showReloadDialog = spy(dialog, 'showReloadDialog');

// when
dialog.setShowReloadModelerDialogResponse({ button: 'reload' });
await app.reloadModeler();

// then
expect(showReloadDialog).to.have.been.called;
expect(reload).to.have.been.called;
});


it('should NOT reload app', async function() {

// given
const dialog = new Dialog();

const { app } = createApp({
globals: {
dialog
}
});

sinon.stub(app, 'hasUnsavedTabs').returns(true);

const reload = spy(app, 'reload');
const showReloadDialog = spy(dialog, 'showReloadDialog');

// when
dialog.setShowReloadModelerDialogResponse({ button: 'cancel' });
app.reloadModeler();

// then
expect(showReloadDialog).to.have.been.called;
expect(reload).to.not.have.been.called;
});

});
});

});


Expand Down
10 changes: 10 additions & 0 deletions client/src/app/__tests__/mocks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ export class Dialog extends Mock {
this.showCloseFileDialogResponse = new Response();
this.showEmptyFileDialogResponse = new Response();
this.showFileExplorerDialogResponse = new Response();
this.showReloadModelerDialogResponse = new Response();
}

setShowOpenFilesDialogResponse(index, response) {
Expand Down Expand Up @@ -350,6 +351,10 @@ export class Dialog extends Mock {
this.showEmptyFileDialogResponse.setResponse(index, response);
}

setShowReloadModelerDialogResponse(index, response) {
this.showReloadModelerDialogResponse.setResponse(index, response);
}

showOpenFilesDialog() {
return this.showOpenFilesDialogResponse.next();
}
Expand Down Expand Up @@ -381,6 +386,11 @@ export class Dialog extends Mock {
showFileExplorerDialog() {
return this.showFileExplorerDialogResponse.next();
}

showReloadDialog() {
return this.showReloadModelerDialogResponse.next();
}

}

export class FileSystem extends Mock {
Expand Down
27 changes: 27 additions & 0 deletions client/src/remote/Dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,31 @@ export default class Dialog {
});
};

/**
* Shows dialog asking user for confirmation to reload the modeler.
*/
showReloadDialog() {
const isLinux = this.backend.getPlatform() == 'linux';

const buttons = [
{ id: 'save', label: 'Save' },
{ id: 'reload', label: 'Continue without saving' },
{ id: 'cancel', label: 'Cancel' },
];

// Re-order buttons for linux
if (isLinux) {
buttons.push(buttons.shift());
}

return this.show({
buttons,
defaultId: isLinux ? 1 : 0,
message: 'Reloading the modeler will discard all unsaved changes. Do you want to save before reloading?',
type: 'warning',
title: 'Reload Modeler'
});
}


}
41 changes: 41 additions & 0 deletions client/src/remote/__tests__/DialogSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,45 @@ describe('dialog', function() {
dialog.showFileExplorerDialog(options);
});


it('#showReloadDialog', function() {

// given
const sendSpy = (type, opts) => {

// then
expect(type).to.equal('dialog:show');

const isLinux = process.platform === 'linux';

let buttons;

if (isLinux) {
buttons = [
{ id: 'cancel', label: 'Cancel' },
{ id: 'reload', label: 'Reload' }
];
} else {
buttons = [
{ id: 'reload', label: 'Reload' },
{ id: 'cancel', label: 'Cancel' }
];
}

expect(opts).to.eql({
buttons,
defaultId: isLinux ? 1 : 0,
type: 'warning',
title: 'Reload Modeler',
message: 'Reloading the modeler will discard all unsaved changes. Do you want to continue?'
});
};

const backend = new Backend({ send: sendSpy });
const dialog = new Dialog(backend);

// when
dialog.showEmptyFileDialog();

});
});

0 comments on commit 25322de

Please sign in to comment.