diff --git a/src/components/cylc/Drawer.vue b/src/components/cylc/Drawer.vue
index 29a08f18c..e758a08c5 100644
--- a/src/components/cylc/Drawer.vue
+++ b/src/components/cylc/Drawer.vue
@@ -38,7 +38,7 @@ along with this program. If not, see .
Dashboard
-
+ Workflows
diff --git a/src/components/cylc/Header.vue b/src/components/cylc/Header.vue
index acddfa1ae..6f343136a 100644
--- a/src/components/cylc/Header.vue
+++ b/src/components/cylc/Header.vue
@@ -18,24 +18,7 @@ along with this program. If not, see .
-
+
.
data-cy="filter-id"
clearable
placeholder="Filter by ID"
- v-model="localValue.id"
+ v-model="model.id"
ref="filterIDInput"
/>
@@ -38,9 +38,9 @@ along with this program. If not, see .
class="mb-2 mb-md-0"
>
@@ -48,35 +48,14 @@ along with this program. If not, see .
-
diff --git a/src/components/cylc/TaskFilterSelect.vue b/src/components/cylc/TaskFilterSelect.vue
index ec71e0457..fa5e2673d 100644
--- a/src/components/cylc/TaskFilterSelect.vue
+++ b/src/components/cylc/TaskFilterSelect.vue
@@ -3,14 +3,18 @@
:items="items"
clearable
multiple
- v-model="localValue"
+ v-model="model"
>
-
- Select All
-
+
+
+ Select All
+
+
+
@@ -33,7 +37,7 @@
@@ -55,24 +59,18 @@
v-if="index === maxVisibleStates"
class="text-grey text-caption"
>
- (+{{ localValue.length - maxVisibleStates }})
+ (+{{ model.length - maxVisibleStates }})
diff --git a/src/components/cylc/analysis/TimeSeries.vue b/src/components/cylc/analysis/TimeSeries.vue
index c5469cbe7..7d9073645 100644
--- a/src/components/cylc/analysis/TimeSeries.vue
+++ b/src/components/cylc/analysis/TimeSeries.vue
@@ -33,14 +33,14 @@ along with this program. If not, see .
ref="selectTasks"
>
-
+
Select all
Deselect all
-
+
diff --git a/src/components/cylc/common/sort.js b/src/components/cylc/common/sort.js
index 06d46252a..dc98c600d 100644
--- a/src/components/cylc/common/sort.js
+++ b/src/components/cylc/common/sort.js
@@ -70,27 +70,26 @@ export const DEFAULT_COMPARATOR = (left, right) => {
* @param {Object[]} array - list of string values, or of objects with string values
* @param {Object} value - a value to be inserted in the list, or an object wrapping the value (see iteratee)
* @param {SortedIndexByIteratee=} iteratee - an optional function used to return the value of the element of the list}
- * @param {SortedIndexByComparator=} comparator - function used to compare the newValue with otherValues in the list
+ * @param {{comparator: SortedIndexByComparator, reverse: boolean}=} options - an optional object with a comparator function and a reverse flag
* @return {number} - sorted index
*/
-export function sortedIndexBy (array, value, iteratee, options = {}) {
- // comparator, reverse = false) {
+export function sortedIndexBy (array, value, iteratee = (x) => x, options = {}) {
if (array.length === 0) {
return 0
}
- // If given a function, use it. Otherwise, simply use identity function.
- const iterateeFunction = iteratee || ((value) => value)
// If given a function, use it. Otherwise, simply use locale sort with numeric enabled
- const comparatorFunction = options.comparator || ((leftObject, leftValue, rightObject, rightValue) => DEFAULT_COMPARATOR(leftValue, rightValue))
+ const comparator = options.comparator || (
+ (leftObject, leftValue, rightObject, rightValue) => DEFAULT_COMPARATOR(leftValue, rightValue)
+ )
let low = 0
let high = array.length
- const newValue = iterateeFunction(value)
+ const newValue = iteratee(value)
while (low < high) {
const mid = Math.floor((low + high) / 2)
- const midValue = iterateeFunction(array[mid])
- let higher = comparatorFunction(value, newValue, array[mid], midValue)
+ const midValue = iteratee(array[mid])
+ let higher = comparator(value, newValue, array[mid], midValue)
if (options.reverse) {
higher = higher * -1
}
diff --git a/src/plugins/vuetify.js b/src/plugins/vuetify.js
index 19b147213..3b4f8410e 100644
--- a/src/plugins/vuetify.js
+++ b/src/plugins/vuetify.js
@@ -22,6 +22,7 @@ import { VCombobox } from 'vuetify/components/VCombobox'
import { VSelect } from 'vuetify/components/VSelect'
import { VTextarea } from 'vuetify/components/VTextarea'
import { VTextField } from 'vuetify/components/VTextField'
+import { VCardActions } from 'vuetify/components/VCard'
import colors from 'vuetify/util/colors'
import { mdiClose } from '@mdi/js'
import { useReducedAnimation } from '@/composables/localStorage'
@@ -75,11 +76,20 @@ export const vuetifyOptions = {
mdi
}
},
+ aliases: {
+ VSelectActions: VCardActions,
+ },
defaults: {
VTooltip: {
activator: 'parent',
location: 'bottom',
},
+ VList: {
+ slim: true,
+ },
+ VSelectActions: {
+ class: 'mt-n2'
+ },
...inputDefaults
},
}
diff --git a/src/store/workflows.module.js b/src/store/workflows.module.js
index 7fcd95797..6f22a4cf1 100644
--- a/src/store/workflows.module.js
+++ b/src/store/workflows.module.js
@@ -124,7 +124,7 @@ function getIndex (state, id) {
return state.cylcTree.$index[id]
}
-/* Add a child node under a parent Node */
+/** Add a child node under a parent Node */
function addChild (parentNode, childNode) {
// determine which list to add this node to
// console.log(`$t ++ ${childNode.id}`)
@@ -144,20 +144,12 @@ function addChild (parentNode, childNode) {
}
// insert the child preserving sort order
- let comparator
- if (['cycle', 'family'].includes(parentNode.type)) {
- // sort by type, then name
- // (this makes families sort before tasks in the graph)
- comparator = (n) => `${n.type}-${n.name}`
- } else {
- // sort by name
- comparator = (n) => n.name
- }
+ const iteratee = (n) => `${n.type}-${n.name}` // (this makes families sort before tasks in the tree)
const reverse = ['cycle', 'job'].includes(childNode.type)
const index = sortedIndexBy(
parentNode[key],
childNode,
- comparator,
+ iteratee,
{ reverse }
)
parentNode[key].splice(index, 0, childNode)
diff --git a/tests/e2e/specs/tree.cy.js b/tests/e2e/specs/tree.cy.js
index 71838d275..2c458b068 100644
--- a/tests/e2e/specs/tree.cy.js
+++ b/tests/e2e/specs/tree.cy.js
@@ -266,18 +266,14 @@ describe('Tree view', () => {
it('Provides a select all functionality', () => {
cy.visit('/#/tree/one')
- cy
- .get('[data-cy="filter task state"]')
+ cy.get('[data-cy="filter task state"]')
.get('.v-list-item--active')
.should('have.length', 0)
- cy
- .get('[data-cy="filter task state"]')
+ cy.get('[data-cy="filter task state"]')
.click()
- .get('.v-list-item')
- .contains('Select All')
- .click({ force: true })
- cy
- .get('[data-cy="filter task state"]')
+ .get('[data-cy=task-filter-select-all]')
+ .click()
+ cy.get('[data-cy="filter task state"]')
.get('.v-list-item--active')
.should('have.length', 8)
})
diff --git a/tests/unit/components/cylc/common/sort.spec.js b/tests/unit/components/cylc/common/sort.spec.js
index 9a367bfd4..b895aa9a8 100644
--- a/tests/unit/components/cylc/common/sort.spec.js
+++ b/tests/unit/components/cylc/common/sort.spec.js
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-import { DEFAULT_COMPARATOR } from '@/components/cylc/common/sort'
+import { DEFAULT_COMPARATOR, sortedIndexBy } from '@/components/cylc/common/sort'
describe('DEFAULT_COMPARATOR', () => {
it.each([
@@ -31,3 +31,47 @@ describe('DEFAULT_COMPARATOR', () => {
expect(DEFAULT_COMPARATOR(a, b)).toEqual(expected)
})
})
+
+describe('sortedIndexBy', () => {
+ it.each([
+ [['a', 'c', 'e'], 'a', 0],
+ [['a', 'c', 'e'], 'b', 1],
+ [['a', 'c', 'e'], 'c', 1],
+ [['a', 'c', 'e'], 'd', 2],
+ [['a', 'c', 'e'], 'x', 3],
+ [[], 'x', 0],
+ ])('sortedIndexBy(%o, %o) -> %i', (arr, value, expected) => {
+ expect(sortedIndexBy(arr, value)).toEqual(expected)
+ })
+
+ it('uses the iteratee function to determine the value for comparison', () => {
+ const arr = [{ key: 'a' }, { key: 'c' }, { key: 'e' }]
+ const value = { key: 'b' }
+ const iteratee = (x) => x.key
+ expect(sortedIndexBy(arr, value, iteratee)).toEqual(1)
+ })
+
+ it.each([
+ [[8], 0],
+ [[8, 8], 0],
+ [[8, 8, 8], 3],
+ ])('%#) uses a custom comparator if provided', (value, expected) => {
+ const arr = [[8, 8], [8, 8], [8, 8]]
+ const comparator = (leftObj, leftVal, rightObj, rightVal) => (
+ leftObj.length - rightObj.length
+ )
+ expect(sortedIndexBy(arr, value, (x) => x, { comparator })).toEqual(expected)
+ })
+
+ it('reverses the comparison if reverse option is true', () => {
+ const arr = ['e', 'c', 'a']
+ const value = 'd'
+ expect(sortedIndexBy(arr, value, (x) => x, { reverse: true })).toEqual(1)
+ })
+
+ it('handles numeric collation correctly by default', () => {
+ const arr = ['1', '2']
+ const value = '10'
+ expect(sortedIndexBy(arr, value)).toEqual(2)
+ })
+})