Skip to content

Commit 7cb7ab4

Browse files
committed
Vue 3: fix analysis view
1 parent 5b99d8f commit 7cb7ab4

File tree

6 files changed

+147
-160
lines changed

6 files changed

+147
-160
lines changed

src/components/cylc/analysis/AnalysisTable.vue

Lines changed: 61 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
1818
<template>
1919
<v-row
2020
no-gutters
21-
class="flex-grow-1 position-relative"
21+
class="c-table flex-grow-1 position-relative"
2222
>
2323
<v-col
2424
cols="12"
@@ -28,25 +28,25 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2828
fluid
2929
class="pa-0"
3030
>
31+
<!-- eslint-disable-next-line vuetify/no-deprecated-components -->
3132
<v-data-table
3233
:headers="shownHeaders"
3334
:items="tasks"
34-
:sort-by.sync="sortBy"
35-
dense
36-
:footer-props="{
37-
itemsPerPageOptions: [10, 20, 50, 100, 200, -1],
38-
showFirstLastPage: true
39-
}"
40-
:options="{ itemsPerPage: 50 }"
35+
:sort-by="sortBy"
36+
density="compact"
37+
v-model:items-per-page="itemsPerPage"
4138
>
4239
<!-- Use custom format for values in columns that have a specified formatter: -->
4340
<!-- Used to make durations human readable -->
4441
<!-- Durations of 0 will be undefined unless allowZeros is true -->
4542
<template
46-
v-for="header in shownHeaders.filter(header => header.hasOwnProperty('formatter'))"
47-
v-slot:[`item.${header.value}`]="{ value }"
43+
v-for="header in shownHeaders"
44+
v-slot:[`item.${header.key}`]="{ item }"
4845
>
49-
{{ header.formatter(value, header.allowZeros) }}
46+
{{ formatCell(item, header) }}
47+
</template>
48+
<template v-slot:bottom>
49+
<v-data-table-footer :itemsPerPageOptions="$options.itemsPerPageOptions" />
5050
</template>
5151
</v-data-table>
5252
</v-container>
@@ -73,19 +73,22 @@ export default {
7373
7474
data () {
7575
return {
76-
sortBy: 'name',
76+
itemsPerPage: 50,
77+
sortBy: [
78+
{ key: 'name', order: 'asc' }
79+
],
7780
headers: [
7881
{
79-
text: 'Task',
80-
value: 'name'
82+
title: 'Task',
83+
key: 'name'
8184
},
8285
{
83-
text: 'Platform',
84-
value: 'platform'
86+
title: 'Platform',
87+
key: 'platform'
8588
},
8689
{
87-
text: 'Count',
88-
value: 'count'
90+
title: 'Count',
91+
key: 'count'
8992
}
9093
]
9194
}
@@ -105,50 +108,75 @@ export default {
105108
}
106109
const timingHeaders = [
107110
{
108-
text: `Mean T-${times}`,
109-
value: `mean${times}Time`,
111+
title: `Mean T-${times}`,
112+
key: `mean${times}Time`,
110113
formatter: formatDuration,
111114
allowZeros: false
112115
},
113116
{
114-
text: `Std Dev T-${times}`,
115-
value: `stdDev${times}Time`,
117+
title: `Std Dev T-${times}`,
118+
key: `stdDev${times}Time`,
116119
formatter: formatDuration,
117120
allowZeros: true
118121
},
119122
{
120-
text: `Min T-${times}`,
121-
value: `min${times}Time`,
123+
title: `Min T-${times}`,
124+
key: `min${times}Time`,
122125
formatter: formatDuration,
123126
allowZeros: false
124127
},
125128
{
126-
text: `Q1 T-${times}`,
127-
value: `${times.toLowerCase()}Quartiles[0]`,
129+
title: `Q1 T-${times}`,
130+
key: `${times.toLowerCase()}Quartiles.0`,
128131
formatter: formatDuration,
129132
allowZeros: false
130133
},
131134
{
132-
text: `Median T-${times}`,
133-
value: `${times.toLowerCase()}Quartiles[1]`,
135+
title: `Median T-${times}`,
136+
key: `${times.toLowerCase()}Quartiles.1`,
134137
formatter: formatDuration,
135138
allowZeros: false
136139
},
137140
{
138-
text: `Q3 T-${times}`,
139-
value: `${times.toLowerCase()}Quartiles[2]`,
141+
title: `Q3 T-${times}`,
142+
key: `${times.toLowerCase()}Quartiles.2`,
140143
formatter: formatDuration,
141144
allowZeros: false
142145
},
143146
{
144-
text: `Max T-${times}`,
145-
value: `max${times}Time`,
147+
title: `Max T-${times}`,
148+
key: `max${times}Time`,
146149
formatter: formatDuration,
147150
allowZeros: false
148151
}
149152
]
150153
return this.headers.concat(timingHeaders)
151154
}
152-
}
155+
},
156+
157+
methods: {
158+
formatCell (item, header) {
159+
const arrayMatch = header.key.match(/^(.+)\.(\d+)$/)
160+
const key = arrayMatch?.[1] ?? header.key
161+
let value = item.value[key]
162+
if (arrayMatch) {
163+
const index = arrayMatch[2]
164+
value = value[index]
165+
}
166+
if (header.formatter) {
167+
return header.formatter(value, header.allowZeros)
168+
}
169+
return value
170+
}
171+
},
172+
173+
itemsPerPageOptions: [
174+
{ value: 10, title: '10' },
175+
{ value: 20, title: '20' },
176+
{ value: 50, title: '50' },
177+
{ value: 100, title: '100' },
178+
{ value: 200, title: '200' },
179+
{ value: -1, title: 'All' }
180+
],
153181
}
154182
</script>

src/components/cylc/analysis/filter.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export function matchTask (task, tasksFilter) {
3030
if (tasksFilter.name?.trim()) {
3131
ret &&= task.name.includes(tasksFilter.name)
3232
}
33-
if (tasksFilter.platformOption?.trim()) {
33+
if (tasksFilter.platformOption.trim?.()) {
3434
ret &&= task.platform === tasksFilter.platformOption
3535
}
3636
return ret
@@ -44,12 +44,12 @@ export function matchTask (task, tasksFilter) {
4444
* @return {array} - An array of unique platform objects
4545
*/
4646
export function platformOptions (tasks) {
47-
const platformOptions = [{ text: 'All', value: null }]
47+
const platformOptions = [{ value: -1, title: 'All' }]
4848
const platforms = []
4949
for (const task of tasks) {
5050
if (!platforms.includes(task.platform)) {
5151
platforms.push(task.platform)
52-
platformOptions.push({ text: task.platform, value: task.platform })
52+
platformOptions.push({ value: task.platform, title: task.platform })
5353
}
5454
}
5555
return platformOptions

src/views/Analysis.vue

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
1818
<template>
1919
<div class="c-analysis">
2020
<v-container
21-
fluid
22-
class="c-table ma-0 pa-2 h-100 flex-column d-flex"
21+
fluid
22+
class="pa-2"
2323
>
2424
<!-- Filters -->
25-
<v-row
26-
class="d-flex flex-wrap table-option-bar no-gutters flex-grow-0"
27-
>
25+
<v-row no-gutters>
2826
<v-col
2927
cols="12"
3028
md="4"
@@ -33,10 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
3331
<v-text-field
3432
id="c-analysis-filter-task-name"
3533
clearable
36-
dense
37-
flat
3834
hide-details
39-
outlined
4035
placeholder="Filter by task name"
4136
v-model.trim="tasksFilter.name"
4237
ref="filterNameInput"
@@ -50,11 +45,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
5045
<v-select
5146
id="c-analysis-filter-task-timings"
5247
:items="timingOptions"
53-
dense
54-
flat
5548
hide-details
56-
outlined
57-
prefix="Displaying: "
49+
prefix="Displaying:"
5850
v-model="tasksFilter.timingOption"
5951
/>
6052
</v-col>
@@ -66,11 +58,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
6658
<v-select
6759
id="c-analysis-filter-task-platforms"
6860
:items="platformOptions"
69-
dense
70-
flat
7161
hide-details
72-
outlined
73-
prefix="Platform: "
62+
prefix="Platform:"
7463
v-model="tasksFilter.platformOption"
7564
/>
7665
</v-col>
@@ -79,7 +68,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
7968
<AnalysisTable
8069
:tasks="filteredTasks"
8170
:timingOption="tasksFilter.timingOption"
82-
/>
71+
/>
8372
</v-container>
8473
</div>
8574
</template>
@@ -89,12 +78,11 @@ import {
8978
pick,
9079
debounce
9180
} from 'lodash'
92-
import Vue from 'vue'
9381
import gql from 'graphql-tag'
94-
import pageMixin from '@/mixins/index'
82+
import { getPageTitle } from '@/utils/index'
9583
import graphqlMixin from '@/mixins/graphql'
96-
import ViewToolbar from '@/components/cylc/ViewToolbar'
97-
import AnalysisTable from '@/components/cylc/analysis/AnalysisTable'
84+
import ViewToolbar from '@/components/cylc/ViewToolbar.vue'
85+
import AnalysisTable from '@/components/cylc/analysis/AnalysisTable.vue'
9886
import {
9987
matchTask,
10088
platformOptions
@@ -137,20 +125,20 @@ query analysisQuery ($workflows: [ID]) {
137125
138126
/** The callback which gets called when data comes in from the query */
139127
class AnalysisCallback {
128+
/**
129+
* @param {Object[]} tasks
130+
*/
140131
constructor (tasks) {
141132
this.tasks = tasks
142133
}
143134
135+
/**
136+
* Add tasks contained in data to this.tasks
137+
*/
144138
add (data) {
145-
// add tasks contained in data to this.tasks
146-
for (const task of data.tasks) {
147-
// add new entry
148-
Vue.set(
149-
this.tasks,
150-
this.tasks.length,
151-
pick(task, taskFields)
152-
)
153-
}
139+
this.tasks.push(
140+
...data.tasks.map((task) => pick(task, taskFields))
141+
)
154142
}
155143
156144
// called when new objects are added
@@ -173,21 +161,20 @@ class AnalysisCallback {
173161
}
174162
175163
export default {
164+
name: 'Analysis',
165+
176166
mixins: [
177-
pageMixin,
178167
graphqlMixin
179168
],
180169
181-
name: 'Analysis',
182-
183170
components: {
184171
ViewToolbar,
185172
AnalysisTable
186173
},
187174
188-
metaInfo () {
175+
head () {
189176
return {
190-
title: this.getPageTitle('App.workflow', { name: this.workflowName })
177+
title: getPageTitle('App.workflow', { name: this.workflowName })
191178
}
192179
},
193180
@@ -219,16 +206,15 @@ export default {
219206
callback: new AnalysisCallback(tasks),
220207
/** Object containing all of the tasks added by the callback */
221208
tasks,
222-
sortBy: 'name',
223209
timingOptions: [
224-
{ text: 'Total times', value: 'totalTimes' },
225-
{ text: 'Run times', value: 'runTimes' },
226-
{ text: 'Queue times', value: 'queueTimes' }
210+
{ value: 'totalTimes', title: 'Total times' },
211+
{ value: 'runTimes', title: 'Run times' },
212+
{ value: 'queueTimes', title: 'Queue times' },
227213
],
228214
tasksFilter: {
229215
name: '',
230216
timingOption: 'totalTimes',
231-
platformOption: null
217+
platformOption: -1,
232218
}
233219
}
234220
},

0 commit comments

Comments
 (0)