Skip to content

Commit 2e0dc87

Browse files
committed
Allow filtering by ID instead of only task name
1 parent b9d8255 commit 2e0dc87

File tree

7 files changed

+74
-61
lines changed

7 files changed

+74
-61
lines changed

src/components/cylc/TaskFilter.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2525
class="pr-md-2 mb-2 mb-md-0"
2626
>
2727
<v-text-field
28-
data-cy="filter-task-name"
28+
data-cy="filter-id"
2929
clearable
3030
:clear-icon="$options.icons.mdiClose"
3131
dense
3232
flat
3333
hide-details
3434
outlined
35-
placeholder="Filter by task name"
36-
v-model="localValue.name"
37-
ref="filterNameInput"
35+
placeholder="Filter by ID"
36+
v-model="localValue.id"
37+
ref="filterIDInput"
3838
/>
3939
</v-col>
4040
<v-col
@@ -86,7 +86,7 @@ export default {
8686
Task
8787
},
8888
props: {
89-
value: Object // { name, states }
89+
value: Object // { id, states }
9090
},
9191
data () {
9292
return {

src/components/cylc/common/filter.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,21 @@
1818
/* Logic for filtering tasks. */
1919

2020
/**
21-
* Return true if a node has matches the specified name/state filter.
21+
* Return true if a node matches the specified id/state filter.
2222
*
2323
* @export
24-
* @param {{ name: string, state: string }} node
25-
* @param {?string} name
24+
* @param {Object} node
25+
* @param {?string} id
2626
* @param {?string[]} states
2727
* @return {boolean}
2828
*/
29-
export function matchNode (node, name, states) {
29+
export function matchNode (node, id, states) {
3030
let ret = true
31-
if (name?.trim()) {
32-
ret &&= node.name.includes(name)
31+
if (id?.trim()) {
32+
ret &&= node.tokens.relative_id.includes(id)
3333
}
3434
if (states?.length) {
35-
ret &&= states.includes(node.state)
35+
ret &&= states.includes(node.node.state)
3636
}
3737
return ret
3838
}

src/components/cylc/table/Table.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ export default {
254254
},
255255
computed: {
256256
filteredTasks () {
257-
return this.tasks.filter(({ task }) => matchNode(task.node, this.tasksFilter.name, this.tasksFilter.states))
257+
return this.tasks.filter(({ task }) => matchNode(task, this.tasksFilter.id, this.tasksFilter.states))
258258
}
259259
},
260260
methods: {

src/components/cylc/tree/Tree.vue

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ export default {
202202
}
203203
},
204204
filterByTaskName () {
205-
return Boolean(this.tasksFilter.name?.trim())
205+
return Boolean(this.tasksFilter.id?.trim())
206206
},
207207
filterByTaskState () {
208208
return Boolean(this.tasksFilter.states?.length)
@@ -237,20 +237,31 @@ export default {
237237
this.filterNode(node)
238238
}
239239
},
240-
filterNode (node) {
241-
let filtered = false
240+
/**
241+
* Update tree cache entry for this node (and its children if applicable)
242+
* with whether the node matches the filters.
243+
*
244+
* @param {Object} node
245+
* @param {boolean} parentFiltered - whether the parent of this node
246+
* matches the filter.
247+
* @return {boolean} - whether this node matches the filter.
248+
*/
249+
filterNode (node, parentFiltered = false) {
250+
const isMatch = (
251+
matchNode(node, this.tasksFilter.id, this.tasksFilter.states) ||
252+
parentFiltered
253+
)
254+
let filtered = isMatch
242255
if (node.type === 'cycle') {
243256
// follow the family tree from cycle point nodes
244257
for (const child of node.familyTree[0]?.children || []) {
245-
filtered = this.filterNode(child) || filtered
258+
filtered = this.filterNode(child, isMatch) || filtered
246259
}
247260
} else if (['workflow', 'family'].includes(node.type)) {
248261
// follow children for workflow or family nodes
249262
for (const child of node.children) {
250-
filtered = this.filterNode(child) || filtered
263+
filtered = this.filterNode(child, isMatch) || filtered
251264
}
252-
} else if (node.type === 'task') {
253-
filtered = matchNode(node.node, this.tasksFilter.name, this.tasksFilter.states)
254265
}
255266
if (this.treeItemCache[node.id]) {
256267
this.treeItemCache[node.id].filtered = filtered

tests/e2e/specs/table.cy.js

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ describe('Table view', () => {
3333
.should('have.length', 7)
3434
.should('be.visible')
3535
cy
36-
.get('[data-cy=filter-task-name]')
36+
.get('[data-cy=filter-id]')
3737
.should('be.empty')
3838
cy
3939
.get('[data-cy=filter-task-states]')
@@ -42,7 +42,7 @@ describe('Table view', () => {
4242
.find('input[type="hidden"]')
4343
.should('have.value', '')
4444
})
45-
it('Should filter by task name', () => {
45+
it('Should filter by ID', () => {
4646
cy.visit('/#/table/one')
4747
cy
4848
.get('.c-table table > tbody > tr')
@@ -52,18 +52,17 @@ describe('Table view', () => {
5252
.get('td > div.d-flex > div')
5353
.contains('sleepy')
5454
.should('be.visible')
55-
// eep should filter sleepy
56-
cy
57-
.get('[data-cy=filter-task-name]')
58-
.type('eep')
59-
cy
60-
.get('td > div.d-flex > div')
61-
.contains('sleepy')
62-
.should('be.visible')
63-
cy
64-
.get('.c-table table > tbody > tr')
65-
.should('have.length', 1)
66-
.should('be.visible')
55+
for (const id of ['eep', '/sle']) {
56+
cy.get('[data-cy=filter-id]')
57+
.clear()
58+
.type(id)
59+
cy.get('td > div.d-flex > div')
60+
.contains('sleepy')
61+
.should('be.visible')
62+
cy.get('.c-table table > tbody > tr')
63+
.should('have.length', 1)
64+
.should('be.visible')
65+
}
6766
})
6867
it('Should filter by task state', () => {
6968
cy.visit('/#/table/one')
@@ -91,7 +90,7 @@ describe('Table view', () => {
9190
.should('have.length', 1)
9291
.should('be.visible')
9392
})
94-
it('Should filter by task name and states', () => {
93+
it('Should filter by ID and states', () => {
9594
cy.visit('/#/table/one')
9695
cy
9796
.get('.c-table table > tbody > tr')
@@ -109,7 +108,7 @@ describe('Table view', () => {
109108
.should('have.length', 2)
110109
.should('be.visible')
111110
cy
112-
.get('[data-cy=filter-task-name]')
111+
.get('[data-cy=filter-id]')
113112
.type('eventually')
114113
cy
115114
.get('td > div.d-flex > div')

tests/e2e/specs/tree.cy.js

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -185,30 +185,33 @@ describe('Tree view', () => {
185185

186186
describe('filters', () => {
187187
const initialNumTasks = 7
188-
it('Should filter by task name', () => {
188+
it('Should filter by ID', () => {
189189
cy.visit('/#/tree/one')
190190
// Should not filter by default
191-
cy
192-
.get('.node-data-task:visible')
191+
cy.get('.node-data-task:visible')
193192
.should('have.length', initialNumTasks)
194193
.contains('waiting')
195-
// eep should filter sleepy
196-
cy
197-
.get('[data-cy=filter-task-name]')
198-
.type('eep')
199-
cy
200-
.get('.node-data-task:visible')
201-
.should('have.length.lessThan', initialNumTasks)
202-
.contains('sleepy')
203-
cy
204-
.get('.node-data-task')
205-
.contains('waiting')
206-
.should('not.be.visible')
194+
for (const id of ['eed', '/suc', 'GOOD', 'SUC']) {
195+
cy.get('[data-cy=filter-id]')
196+
.clear()
197+
.type(id)
198+
cy.get('.node-data-task:visible')
199+
.should('have.length.lessThan', initialNumTasks)
200+
.contains('succeeded')
201+
cy.get('.node-data-task')
202+
.contains('waiting')
203+
.should('not.be.visible')
204+
}
207205
// It should stop filtering when input is cleared
208-
cy.get('[data-cy=filter-task-name]')
206+
cy.get('[data-cy=filter-id]')
209207
.clear()
210208
.get('.node-data-task:visible')
211209
.should('have.length', initialNumTasks)
210+
// It should filter by cycle point
211+
cy.get('[data-cy=filter-id]')
212+
.type('2000') // (matches all tasks)
213+
.get('.node-data-task:visible')
214+
.should('have.length', initialNumTasks)
212215
})
213216
it('Should filter by task states', () => {
214217
cy.visit('/#/tree/one')
@@ -231,14 +234,14 @@ describe('Tree view', () => {
231234
.get('.node-data-task:visible')
232235
.should('have.length', 1)
233236
})
234-
it('Should filter by task name and states', () => {
237+
it('Should filter by ID and states', () => {
235238
cy.visit('/#/tree/one')
236239
cy
237240
.get('.node-data-task')
238241
.contains('failed')
239242
.should('be.visible')
240243
cy
241-
.get('[data-cy=filter-task-name]')
244+
.get('[data-cy=filter-id]')
242245
.type('i')
243246
cy
244247
.get('[data-cy=filter-task-states]')
@@ -275,7 +278,7 @@ describe('Tree view', () => {
275278
.contains('sleepy')
276279
.as('sleepyTask')
277280
.should('be.visible')
278-
cy.get('[data-cy=filter-task-name]')
281+
cy.get('[data-cy=filter-id]')
279282
.type('sleep')
280283
cy.get('[data-cy=collapse-all]')
281284
.click()

tests/unit/components/cylc/table/table.vue.spec.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,24 +100,24 @@ describe('Table component', () => {
100100
expect(wrapper.find('div')).to.not.equal(null)
101101
})
102102
describe('Filter', () => {
103-
describe('Filter by name', () => {
104-
it('should not filter by name or tasks by default', () => {
103+
describe('Filter by ID', () => {
104+
it('should not filter by ID or task state by default', () => {
105105
const wrapper = mountFunction({
106106
propsData: {
107107
tasks: simpleTableTasks
108108
}
109109
})
110110
expect(wrapper.vm.filteredTasks.length).to.equal(3)
111111
})
112-
it('should filter by name', () => {
112+
it('should filter by ID', () => {
113113
const wrapper = mountFunction({
114114
propsData: {
115115
tasks: simpleTableTasks
116116
},
117117
data () {
118118
return {
119119
tasksFilter: {
120-
name: 'taskA'
120+
id: 'taskA'
121121
}
122122
}
123123
}
@@ -132,7 +132,7 @@ describe('Table component', () => {
132132
data () {
133133
return {
134134
tasksFilter: {
135-
name: '',
135+
id: '',
136136
states: [
137137
TaskState.WAITING.name
138138
]
@@ -150,7 +150,7 @@ describe('Table component', () => {
150150
data () {
151151
return {
152152
tasksFilter: {
153-
name: 'taskA',
153+
id: 'taskA',
154154
states: [
155155
TaskState.WAITING.name
156156
]

0 commit comments

Comments
 (0)