Skip to content

Commit f60c6f5

Browse files
author
Andres
committed
Context menu overhaul, close #368
1 parent 026fc08 commit f60c6f5

File tree

8 files changed

+97
-78
lines changed

8 files changed

+97
-78
lines changed

.eslintrc.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@
8888
}],
8989
"lines-between-class-members": ["error", "always"],
9090
"max-depth": ["error", 6],
91-
"max-len": ["warn", 200],
91+
"max-len": ["warn", 300],
9292
"max-lines": ["warn", 300],
9393
"max-nested-callbacks": ["error", 4],
9494
"max-params": ["error", 4],

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
===================
33

44
* Gaucho now runs as a single-instance app
5+
* Overhaul of menu and context menu options
6+
* Suite-related actions moved to context menu
7+
* "Import suite" is not part of settings
58
* Adds cut-copy-paste items to context menu
69
* Dependencies updated
710

src/app/api/context_menu.js

+35-11
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ class ContextMenu extends EventEmitter {
2424
this.emit(event, this.extraData);
2525
} : undefined,
2626
type: item.type || "normal",
27-
role: item.role
27+
role: item.role,
28+
sublabel: item.sublabel
2829
});
2930
this.menu.append(menuItem);
3031
}
@@ -41,8 +42,8 @@ class ContextMenu extends EventEmitter {
4142
}
4243

4344
class DefaultContextMenu extends ContextMenu {
44-
constructor(extraOptions = []) {
45-
super(extraOptions.concat([{
45+
constructor(extraOptions = [], includeEditFields = true) {
46+
const editableFields = [{
4647
label: "Cut",
4748
role: "cut"
4849
}, {
@@ -53,7 +54,9 @@ class DefaultContextMenu extends ContextMenu {
5354
role: "paste"
5455
}, {
5556
type: "separator"
56-
}, {
57+
}];
58+
59+
const baseFields = [{
5760
label: "Settings",
5861
event: "settings"
5962
}, {
@@ -62,7 +65,11 @@ class DefaultContextMenu extends ContextMenu {
6265
}, {
6366
label: "Quit",
6467
event: "quit"
65-
}]));
68+
}];
69+
70+
const fields = includeEditFields ? editableFields.concat(baseFields) : baseFields;
71+
72+
super(extraOptions.concat(fields));
6673
}
6774

6875
toggle(extraData) {
@@ -81,12 +88,29 @@ class DefaultContextMenu extends ContextMenu {
8188
}
8289

8390
class TabMenu extends DefaultContextMenu {
84-
constructor() {
85-
super([{label: "Delete",
86-
event: "delete"}, {label: "Rename",
87-
event: "rename"}, {label: "Export Suite",
88-
event: "export-suite"}, {label: "Duplicate Suite",
89-
event: "duplicate-suite"}, {type: "separator"}]);
91+
constructor(suiteTitle) {
92+
super([{
93+
label: `Run "${suiteTitle}"`,
94+
event: "run-suite"
95+
}, {
96+
label: "Stop Suite",
97+
event: "stop-suite"
98+
}, {
99+
label: "Schedule",
100+
event: "schedule-suite"
101+
}, {type: "separator"}, {
102+
label: "Delete",
103+
event: "delete"
104+
}, {
105+
label: "Rename",
106+
event: "rename"
107+
}, {
108+
label: "Export",
109+
event: "export-suite"
110+
}, {
111+
label: "Duplicate",
112+
event: "duplicate-suite"
113+
}, {type: "separator"}], false);
90114
}
91115
}
92116

src/app/components/navbar/navbar.vue

-35
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,8 @@
3131
<script>
3232
"use strict";
3333
34-
const app = require('electron').remote;
35-
const dialog = app.dialog;
3634
const ipcRenderer = require('electron').ipcRenderer;
37-
3835
const EventHandler = require('../../event_handler');
39-
40-
const schedulerModal = require('../../api/scheduler_modal');
4136
const aboutModal = require('../../api/about_modal');
4237
4338
const components = {
@@ -63,36 +58,6 @@ module.exports = {
6358
case "about":
6459
this.openAboutModal();
6560
break;
66-
case "runSuite":
67-
this.$store.dispatch("runSuite");
68-
break;
69-
case "stopSuite":
70-
this.$store.dispatch("stopSuite", this.$store.state.tasks.selectedSuite);
71-
break;
72-
case "importSuite":
73-
if (this.$store.getters.canAddSuite) {
74-
dialog.showOpenDialog({
75-
filters: [{
76-
name: 'json',
77-
extensions: ['json']
78-
}]
79-
}).then((dialogResult) => {
80-
if (dialogResult.filePaths && dialogResult.filePaths[0]) {
81-
const filename = dialogResult.filePaths[0];
82-
this.$store.dispatch("importSuite", filename).catch((err) => {
83-
console.warn(err);
84-
});
85-
}
86-
});
87-
}
88-
break;
89-
case "scheduleSuite":
90-
schedulerModal("Schedule Suite Execution").then((res) => {
91-
this.$store.dispatch("scheduleSuite", res);
92-
}, () => {
93-
// Cancelled scheduling
94-
});
95-
break;
9661
case "settings":
9762
this.$store.commit("toggleSettings");
9863
break;

src/app/components/navbar/navbar_menu.vue

+1-25
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,7 @@ module.exports = {
3636
name: "Quit",
3737
value: "quit"
3838
}];
39-
40-
let extraOptions = [];
41-
42-
if (this.$store.state.editMode) {
43-
const canImportSuite = this.$store.getters.canAddSuite;
44-
extraOptions = [{
45-
name: "Import Suite",
46-
value: "importSuite",
47-
disabled: !canImportSuite
48-
}];
49-
} else {
50-
extraOptions = [{
51-
name: "Run Suite",
52-
value: "runSuite"
53-
}, {
54-
name: "Stop Suite",
55-
value: "stopSuite"
56-
}, {
57-
name: "Schedule Suite",
58-
value: "scheduleSuite"
59-
}];
60-
}
61-
return extraOptions.concat([{
62-
value: "divider"
63-
}], defaultOptions);
39+
return defaultOptions;
6440
}
6541
},
6642
methods: {

src/app/components/navbar/suite_tabs.vue

+23-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<template>
22
<div class="tabs is-fullwidth">
33
<draggable v-model="suites" tag="ul" v-bind="draggableOptions" @end="suiteDragEnd">
4-
<li v-for="(suite, index) in suites" class="tab-suite-item" @contextmenu.stop="context(index)" :style="{ width: tabsWidth }"
5-
:class="{'is-active': isSelected(index), 'inactive': !isSelected(index)}" @click="selectSuite(index)" @dragover="selectSuite(index)" :key="index"
4+
<li v-for="(suite, index) in suites" class="tab-suite-item" :style="{ width: tabsWidth }" :class="{'is-active': isSelected(index), 'inactive': !isSelected(index)}" @click="selectSuite(index)" @contextmenu.stop="context(index)"
5+
@dragover="selectSuite(index)" :key="index"
66
>
77
<a class="columns is-mobile is-centered tab-content">
88
<div class="column tab-text-container">
@@ -37,11 +37,10 @@ const dialog = app.dialog;
3737
3838
const AppAlerts = require('../../api/app_alerts');
3939
const ContextMenu = require('../../api/context_menu');
40+
const schedulerModal = require('../../api/scheduler_modal');
4041
4142
const constants = require('../../../common/constants.js');
4243
43-
const tabMenu = new ContextMenu.TabMenu();
44-
4544
const components = {
4645
"draggable": require('vuedraggable')
4746
};
@@ -79,6 +78,26 @@ module.exports = {
7978
},
8079
methods: {
8180
context(index) {
81+
const tabMenu = new ContextMenu.TabMenu(this.suites[index].title);
82+
83+
tabMenu.on("run-suite", (i) => {
84+
this.selectSuite(i);
85+
this.$store.dispatch("runSuite");
86+
});
87+
tabMenu.on("stop-suite", (i) => {
88+
this.selectSuite(i);
89+
this.$store.dispatch("stopSuite", i);
90+
});
91+
tabMenu.on("schedule-suite", (i) => {
92+
this.selectSuite(i);
93+
const title = this.suites[i].title;
94+
schedulerModal(`Schedule "${title}" Execution`).then((res) => {
95+
this.$store.dispatch("scheduleSuite", res);
96+
}, () => {
97+
// Cancelled scheduling
98+
});
99+
});
100+
82101
tabMenu.on("delete", (i) => {
83102
this.removeSuite(i);
84103
});

src/app/components/settings/button_item.vue

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<div class="field">
33
<div class="control has-text-centered">
4-
<button class="button is-primary is-fullwidth" @click="onClick">
4+
<button class="button is-primary is-fullwidth" @click="onClick" :disabled="disabled">
55
<slot></slot>
66
</button>
77
<small class="settings-label" v-if="label">{{label}}</small>
@@ -14,7 +14,16 @@
1414
"use strict";
1515
1616
module.exports = {
17-
props: ["label"],
17+
props: {
18+
label: {
19+
type: String,
20+
required: false
21+
},
22+
disabled: {
23+
type: Boolean,
24+
default: false
25+
}
26+
},
1827
methods: {
1928
onClick() {
2029
this.$emit("select");

src/app/components/settings/settings_actions.vue

+23
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<button-item @select="resetSettings">Reset Settings</button-item>
55
<button-item @select="exportTasks">Export Tasks</button-item>
66
<button-item @select="importTasks" label="Warning: This will override your previous tasks">Import Tasks</button-item>
7+
<button-item @select="importSuite" :disabled="!canImportSuite">Import Suite</button-item>
78
<button-item @select="clearTasks" label="Warning: This will remove all your suites and tasks">Clear Tasks</button-item>
89
</div>
910
</div>
@@ -29,6 +30,11 @@ const components = {
2930
3031
module.exports = {
3132
components: components,
33+
computed: {
34+
canImportSuite() {
35+
return this.$store.getters.canAddSuite;
36+
}
37+
},
3238
methods: {
3339
importTasks() {
3440
dialog.showOpenDialog({
@@ -77,6 +83,23 @@ module.exports = {
7783
},
7884
resetSettings() {
7985
this.$emit("resetSettings");
86+
},
87+
importSuite() {
88+
if (this.canImportSuite) {
89+
dialog.showOpenDialog({
90+
filters: [{
91+
name: 'json',
92+
extensions: ['json']
93+
}]
94+
}).then((dialogResult) => {
95+
if (dialogResult.filePaths && dialogResult.filePaths[0]) {
96+
const filename = dialogResult.filePaths[0];
97+
this.$store.dispatch("importSuite", filename).catch((err) => {
98+
console.warn(err);
99+
});
100+
}
101+
});
102+
}
80103
}
81104
}
82105
};

0 commit comments

Comments
 (0)