Skip to content

Commit d7700ff

Browse files
author
Guillaume Chau
committed
feat(ui): Task stop + console output
1 parent 0a6891a commit d7700ff

File tree

16 files changed

+327
-50
lines changed

16 files changed

+327
-50
lines changed

packages/@vue/cli-ui/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"semver": "^5.5.0",
2929
"shortid": "^2.2.8",
3030
"subscriptions-transport-ws": "^0.9.5",
31+
"terminate": "^2.1.0",
3132
"vue": "^2.5.13",
3233
"vue-apollo": "^3.0.0-beta.5",
3334
"vue-i18n": "^7.6.0",

packages/@vue/cli-ui/src/components/ItemLogo.vue

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,23 @@ export default {
118118
>>> svg
119119
fill $vue-ui-color-light
120120
121+
&.danger
122+
.vue-ui-icon
123+
>>> svg
124+
fill $vue-ui-color-danger
125+
&.warning
126+
.vue-ui-icon
127+
>>> svg
128+
fill $vue-ui-color-warning
129+
&.info
130+
.vue-ui-icon
131+
>>> svg
132+
fill $vue-ui-color-info
133+
&.success
134+
.vue-ui-icon
135+
>>> svg
136+
fill $vue-ui-color-success
137+
121138
@keyframes zoom
122139
0%
123140
transform scale(0)

packages/@vue/cli-ui/src/components/StatusBar.vue

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,6 @@
4646
:message="consoleLogLast"
4747
/>
4848
<div v-else class="last-message">{{ $t('components.status-bar.log.empty') }}</div>
49-
<!-- <TerminalView
50-
:cols="100"
51-
:rows="1"
52-
:content="consoleLogLast"
53-
auto-size
54-
:options="{
55-
scorllback: 0,
56-
disableStdin: true
57-
}"
58-
/> -->
5949
</div>
6050
</div>
6151
</div>

packages/@vue/cli-ui/src/components/TaskItem.vue

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
>
88
<div class="content">
99
<ItemLogo
10-
icon="assignment"
10+
:icon="iconData.icon"
11+
:class="iconData.class"
1112
v-tooltip="status"
1213
/>
1314

@@ -21,6 +22,14 @@
2122
</template>
2223

2324
<script>
25+
const icons = {
26+
idle: { icon: 'assignment', class: '' },
27+
running: { icon: 'more_horiz', class: 'info' },
28+
done: { icon: 'check_circle', class: 'success' },
29+
error: { icon: 'error', class: 'danger' },
30+
terminated: { icon: 'error', class: '' }
31+
}
32+
2433
export default {
2534
props: {
2635
task: {
@@ -37,6 +46,10 @@ export default {
3746
computed: {
3847
status () {
3948
return this.$t(`types.task.status.${this.task.status}`)
49+
},
50+
51+
iconData () {
52+
return icons[this.task.status]
4053
}
4154
}
4255
}

packages/@vue/cli-ui/src/components/TerminalView.vue

Lines changed: 85 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,31 @@
11
<template>
22
<div class="terminal-view">
3-
<div ref="render" class="xterm-render"></div>
3+
<div v-if="toolbar" class="toolbar">
4+
<VueIcon
5+
icon="dvr"
6+
/>
7+
<div class="title">{{ title }}</div>
8+
<VueButton
9+
class="icon-button"
10+
icon-left="delete_forever"
11+
v-tooltip="$t('components.terminal-view.buttons.clear')"
12+
@click="clear(); $emit('clear')"
13+
/>
14+
<VueIcon
15+
icon="lens"
16+
class="separator"
17+
/>
18+
<VueButton
19+
class="icon-button"
20+
icon-left="subdirectory_arrow_left"
21+
v-tooltip="$t('components.terminal-view.buttons.scroll')"
22+
@click="scrollToBottom()"
23+
/>
24+
</div>
25+
26+
<div class="view">
27+
<div ref="render" class="xterm-render"></div>
28+
</div>
429

530
<resize-observer v-if="autoSize" @notify="fit"/>
631
</div>
@@ -62,6 +87,16 @@ export default {
6287
options: {
6388
type: Object,
6489
default: () => ({})
90+
},
91+
92+
toolbar: {
93+
type: Boolean,
94+
default: false
95+
},
96+
97+
title: {
98+
type: String,
99+
default: null
65100
}
66101
},
67102
@@ -79,6 +114,10 @@ export default {
79114
80115
mounted () {
81116
this.initTerminal()
117+
118+
if (this.autoSize) {
119+
this.$nextTick(this.fit)
120+
}
82121
},
83122
84123
beforeDestroy () {
@@ -100,18 +139,32 @@ export default {
100139
term.on('focus', () => this.$emit('focus'))
101140
},
102141
103-
setContent (value) {
142+
setContent (value, ln = true) {
143+
if (ln && value.indexOf('\n') !== -1) {
144+
value.split('\n').forEach(
145+
t => this.setContent(t)
146+
)
147+
return
148+
}
104149
if (typeof value === 'string') {
105-
this.$_terminal.write(value)
150+
this.$_terminal[ln ? 'writeln' : 'write'](value)
106151
} else {
107152
this.$_terminal.writeln('')
108153
}
109154
},
110155
156+
addLog (log) {
157+
this.setContent(log.text, log.type === 'stdout')
158+
},
159+
111160
clear () {
112161
this.$_terminal.clear()
113162
},
114163
164+
scrollToBottom () {
165+
this.$_terminal.scrollToBottom()
166+
},
167+
115168
handleLink (event, uri) {
116169
this.$emit('link', uri)
117170
},
@@ -148,12 +201,33 @@ export default {
148201
@import "~@/style/imports"
149202
150203
.terminal-view
151-
position relative
152-
153-
.xterm-render
154-
width 100%
155-
height 100%
156-
>>> .xterm
157-
.xterm-cursor-layer
158-
display none
204+
v-box()
205+
align-items stretch
206+
background $vue-ui-color-light-neutral
207+
208+
.toolbar
209+
h-box()
210+
align-items center
211+
padding 6px 6px 6px $padding-item
212+
> :not(.separator)
213+
space-between-x(6px)
214+
> * + .separator
215+
margin-left 6px
216+
.title
217+
flex 100% 1 1
218+
width 0
219+
ellipsis()
220+
221+
.view
222+
flex 100% 1 1
223+
height 0
224+
position relative
225+
padding-left $padding-item
226+
227+
.xterm-render
228+
width 100%
229+
height 100%
230+
>>> .xterm
231+
.xterm-cursor-layer
232+
display none
159233
</style>

packages/@vue/cli-ui/src/graphql-api/connectors/tasks.js

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const execa = require('execa')
2+
const terminate = require('terminate')
23

34
const channels = require('../channels')
45
const cwd = require('./cwd')
@@ -7,6 +8,8 @@ const logs = require('./logs')
78

89
const { getCommand } = require('../utils/command')
910

11+
const MAX_LOGS = 2000
12+
1013
const tasks = new Map()
1114

1215
function getTasks () {
@@ -113,25 +116,31 @@ function run (id, context) {
113116
}, context)
114117

115118
child.stdout.on('data', buffer => {
116-
// TODO logs
117-
console.log(buffer.toString())
119+
addLog({
120+
taskId: task.id,
121+
type: 'stdout',
122+
text: buffer.toString()
123+
}, context)
118124
})
119125

120126
child.stderr.on('data', buffer => {
121-
// TODO logs
122-
console.log(buffer.toString())
127+
addLog({
128+
taskId: task.id,
129+
type: 'stderr',
130+
text: buffer.toString()
131+
}, context)
123132
})
124133

125134
child.on('close', (code, signal) => {
126-
if (signal === 'SIGINT') {
135+
if (code === null) {
127136
updateOne({
128137
id: task.id,
129-
status: 'error',
138+
status: 'terminated',
130139
child: null
131140
}, context)
132141
logs.add({
133142
message: `Task ${task.id} was terminated`,
134-
type: 'error'
143+
type: 'warn'
135144
}, context)
136145
} else if (code !== 0) {
137146
updateOne({
@@ -140,7 +149,7 @@ function run (id, context) {
140149
child: null
141150
}, context)
142151
logs.add({
143-
message: `Task ${task.id} ended with error code`,
152+
message: `Task ${task.id} ended with error code ${code}`,
144153
type: 'error'
145154
}, context)
146155
} else {
@@ -162,7 +171,28 @@ function run (id, context) {
162171
function stop (id, context) {
163172
const task = findOne(id, context)
164173
if (task && task.status === 'running') {
165-
task.child.kill('SIGINT') // TODO not working
174+
terminate(task.child.pid)
175+
}
176+
return task
177+
}
178+
179+
function addLog (log, context) {
180+
const task = findOne(log.taskId, context)
181+
if (task) {
182+
if (task.logs.length === MAX_LOGS) {
183+
task.logs.shift()
184+
}
185+
task.logs.push(log)
186+
context.pubsub.publish(channels.TASK_LOG_ADDED, {
187+
taskLogAdded: log
188+
})
189+
}
190+
}
191+
192+
function clearLogs (id, context) {
193+
const task = findOne(id, context)
194+
if (task) {
195+
task.logs = []
166196
}
167197
return task
168198
}
@@ -172,5 +202,6 @@ module.exports = {
172202
findOne,
173203
run,
174204
stop,
175-
updateOne
205+
updateOne,
206+
clearLogs
176207
}

packages/@vue/cli-ui/src/graphql-api/resolvers.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ module.exports = {
7272
pluginInvoke: (root, { id }, context) => plugins.runInvoke(id, context),
7373
pluginUpdate: (root, { id }, context) => plugins.update(id, context),
7474
taskRun: (root, { id }, context) => tasks.run(id, context),
75-
taskStop: (root, { id }, context) => tasks.stop(id, context)
75+
taskStop: (root, { id }, context) => tasks.stop(id, context),
76+
taskLogsClear: (root, { id }, context) => tasks.clearLogs(id, context)
7677
},
7778

7879
Subscription: {
@@ -84,15 +85,15 @@ module.exports = {
8485
// Iterator
8586
(parent, args, { pubsub }) => pubsub.asyncIterator(channels.PROGRESS_CHANGED),
8687
// Filter
87-
(payload, variables) => payload.progressChanged.id === variables.id
88+
(payload, vars) => payload.progressChanged.id === vars.id
8889
)
8990
},
9091
progressRemoved: {
9192
subscribe: withFilter(
9293
// Iterator
9394
(parent, args, { pubsub }) => pubsub.asyncIterator(channels.PROGRESS_REMOVED),
9495
// Filter
95-
(payload, variables) => payload.progressRemoved.id === variables.id
96+
(payload, vars) => payload.progressRemoved.id === vars.id
9697
)
9798
},
9899
consoleLogAdded: {
@@ -103,6 +104,12 @@ module.exports = {
103104
},
104105
taskChanged: {
105106
subscribe: (parent, args, { pubsub }) => pubsub.asyncIterator(channels.TASK_CHANGED)
107+
},
108+
taskLogAdded: {
109+
subscribe: withFilter(
110+
(parent, args, { pubsub }) => pubsub.asyncIterator(channels.TASK_LOG_ADDED),
111+
(payload, vars) => payload.taskLogAdded.taskId === vars.id
112+
)
106113
}
107114
}
108115
}

0 commit comments

Comments
 (0)