feat: remove lodash dependency
All checks were successful
continuous-integration/drone/pr Build is passing
All checks were successful
continuous-integration/drone/pr Build is passing
Lodash is quite big and all helpers got imported even thought not all needed. With new JS syntax it's easy to replace most helpers.
This commit is contained in:
parent
49fcce043d
commit
d9f2d879d7
|
@ -353,7 +353,7 @@ describe('Task', () => {
|
|||
.first()
|
||||
.click()
|
||||
|
||||
cy.get('.global-notification')
|
||||
cy.get('.global-notification', { timeout: 4000 })
|
||||
.should('contain', 'Success')
|
||||
cy.get('.task-view .details.labels-list .multiselect .input-wrapper span.tag')
|
||||
.should('exist')
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import {seed} from './seed'
|
||||
import merge from 'lodash/merge'
|
||||
|
||||
/**
|
||||
* A factory makes it easy to seed the database with data.
|
||||
|
@ -25,7 +24,10 @@ export class Factory {
|
|||
const data = []
|
||||
|
||||
for (let i = 1; i <= count; i++) {
|
||||
const entry = merge(this.factory(), override)
|
||||
const entry = {
|
||||
...this.factory(),
|
||||
...override,
|
||||
}
|
||||
for (const e in entry) {
|
||||
if(typeof entry[e] === 'function') {
|
||||
entry[e] = entry[e](i)
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
"dompurify": "2.3.3",
|
||||
"highlight.js": "11.2.0",
|
||||
"is-touch-device": "1.0.1",
|
||||
"lodash": "4.17.21",
|
||||
"marked": "3.0.4",
|
||||
"register-service-worker": "1.7.2",
|
||||
"snake-case": "3.0.4",
|
||||
|
|
|
@ -178,9 +178,8 @@ import Fancycheckbox from '../../input/fancycheckbox'
|
|||
import flatPickr from 'vue-flatpickr-component'
|
||||
import 'flatpickr/dist/flatpickr.css'
|
||||
|
||||
import {includesById} from '@/helpers/utils'
|
||||
import {formatISO} from 'date-fns'
|
||||
import differenceWith from 'lodash/differenceWith'
|
||||
|
||||
import PrioritySelect from '@/components/tasks/partials/prioritySelect.vue'
|
||||
import PercentDoneSelect from '@/components/tasks/partials/percentDoneSelect.vue'
|
||||
import Multiselect from '@/components/input/multiselect.vue'
|
||||
|
@ -269,13 +268,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
foundLabels() {
|
||||
const labels = (Object.values(this.$store.state.labels.labels).filter(l => {
|
||||
return l.title.toLowerCase().includes(this.labelQuery.toLowerCase())
|
||||
}) ?? [])
|
||||
|
||||
return differenceWith(labels, this.labels, (first, second) => {
|
||||
return first.id === second.id
|
||||
})
|
||||
return this.$store.getters['labels/filterLabelsByQuery'](this.labels, this.query)
|
||||
},
|
||||
flatPickerConfig() {
|
||||
return {
|
||||
|
@ -309,8 +302,13 @@ export default {
|
|||
this.prepareRelatedObjectFilter('namespace')
|
||||
|
||||
this.prepareSingleValue('labels')
|
||||
const labelIds = (typeof this.filters.labels === 'string' ? this.filters.labels : '').split(',').map(i => parseInt(i))
|
||||
this.labels = (Object.values(this.$store.state.labels.labels).filter(l => labelIds.includes(l.id)) ?? [])
|
||||
|
||||
const labels = typeof this.filters.labels === 'string'
|
||||
? this.filters.labels
|
||||
: ''
|
||||
const labelIds = labels.split(',').map(i => parseInt(i))
|
||||
|
||||
this.labels = this.$store.getters['labels/getLabelsByIds'](labelIds)
|
||||
},
|
||||
removePropertyFromFilter(propertyName) {
|
||||
// Because of the way arrays work, we can only ever remove one element at once.
|
||||
|
@ -533,10 +531,10 @@ export default {
|
|||
|
||||
this[`${kind}Service`].getAll({}, {s: query})
|
||||
.then(response => {
|
||||
// Filter the results to not include users who are already assigneid
|
||||
this.$set(this, `found${kind}`, differenceWith(response, this[kind], (first, second) => {
|
||||
return first.id === second.id
|
||||
}))
|
||||
// Filter users from the results who are already assigned
|
||||
const unassignedUsers = response.filter(({id}) => !includesById(this[kind], id))
|
||||
|
||||
this.$set(this, `found${kind}`, unassignedUsers)
|
||||
})
|
||||
.catch(e => {
|
||||
this.$message.error(e)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import TaskCollectionService from '@/services/taskCollection'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
|
||||
// FIXME: merge with DEFAULT_PARAMS in filters.vue
|
||||
const DEFAULT_PARAMS = {
|
||||
|
@ -83,7 +82,7 @@ export default {
|
|||
this.tasks = r
|
||||
this.currentPage = page
|
||||
|
||||
this.loadedList = cloneDeep(currentList)
|
||||
this.loadedList = JSON.parse(JSON.stringify(currentList))
|
||||
})
|
||||
.catch(e => {
|
||||
this.$message.error(e)
|
||||
|
|
|
@ -29,8 +29,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import differenceWith from 'lodash/differenceWith'
|
||||
|
||||
import {includesById} from '@/helpers/utils'
|
||||
import UserModel from '../../../models/user'
|
||||
import ListUserService from '../../../services/listUsers'
|
||||
import TaskAssigneeService from '../../../services/taskAssignee'
|
||||
|
@ -111,9 +110,9 @@ export default {
|
|||
this.listUserService.getAll({listId: this.listId}, {s: query})
|
||||
.then(response => {
|
||||
// Filter the results to not include users who are already assigned
|
||||
this.$set(this, 'foundUsers', differenceWith(response, this.assignees, (first, second) => {
|
||||
return first.id === second.id
|
||||
}))
|
||||
const filteredResponse = response.filter(({id}) => !includesById(this.assignees, id))
|
||||
|
||||
this.$set(this, 'foundUsers', filteredResponse)
|
||||
})
|
||||
.catch(e => {
|
||||
this.$message.error(e)
|
||||
|
|
|
@ -38,8 +38,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import differenceWith from 'lodash/differenceWith'
|
||||
|
||||
import LabelModel from '../../../models/label'
|
||||
import LabelTaskService from '../../../services/labelTask'
|
||||
|
||||
|
@ -83,13 +81,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
foundLabels() {
|
||||
const labels = (Object.values(this.$store.state.labels.labels).filter(l => {
|
||||
return l.title.toLowerCase().includes(this.query.toLowerCase())
|
||||
}) ?? [])
|
||||
|
||||
return differenceWith(labels, this.labels, (first, second) => {
|
||||
return first.id === second.id
|
||||
})
|
||||
return this.$store.getters['labels/filterLabelsByQuery'](this.labels, this.query)
|
||||
},
|
||||
loading() {
|
||||
return this.labelTaskService.loading || (this.$store.state[LOADING] && this.$store.state[LOADING_MODULE] === 'labels')
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
export function findIndexById(array : [], id : string | number) {
|
||||
return array.findIndex(({id: currentId}) => currentId === id)
|
||||
}
|
22
src/helpers/utils.ts
Normal file
22
src/helpers/utils.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
export function findIndexById(array : [], id : string | number) {
|
||||
return array.findIndex(({id: currentId}) => currentId === id)
|
||||
}
|
||||
|
||||
export function includesById(array: [], id: string | number) {
|
||||
return array.some(({id: currentId}) => currentId === id)
|
||||
}
|
||||
|
||||
// https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore#_isnil
|
||||
export function isNil(value: any) {
|
||||
return value == null
|
||||
}
|
||||
|
||||
export function omitBy(obj: {}, check: (value: any) => Boolean): {} {
|
||||
if (isNil(obj)) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return Object.fromEntries(
|
||||
Object.entries(obj).filter(([, value]) => !check(value)),
|
||||
)
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
import defaults from 'lodash/defaults'
|
||||
import isNil from 'lodash/isNil'
|
||||
import omitBy from 'lodash/omitBy'
|
||||
import {objectToCamelCase} from '@/helpers/case'
|
||||
import {omitBy, isNil} from '@/helpers/utils'
|
||||
|
||||
export default class AbstractModel {
|
||||
|
||||
|
@ -16,11 +14,14 @@ export default class AbstractModel {
|
|||
* @param data
|
||||
*/
|
||||
constructor(data) {
|
||||
|
||||
data = objectToCamelCase(data)
|
||||
|
||||
// Put all data in our model while overriding those with a value of null or undefined with their defaults
|
||||
defaults(this, omitBy(data, isNil), this.defaults())
|
||||
Object.assign(
|
||||
this,
|
||||
this.defaults(),
|
||||
omitBy(data, isNil),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
import TeamShareBaseModel from './teamShareBase'
|
||||
import merge from 'lodash/merge'
|
||||
|
||||
export default class TeamListModel extends TeamShareBaseModel {
|
||||
defaults() {
|
||||
return merge(
|
||||
super.defaults(),
|
||||
{
|
||||
listId: 0,
|
||||
},
|
||||
)
|
||||
return {
|
||||
...super.defaults(),
|
||||
listId: 0,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,11 @@
|
|||
import UserModel from './user'
|
||||
import merge from 'lodash/merge'
|
||||
|
||||
export default class TeamMemberModel extends UserModel {
|
||||
defaults() {
|
||||
return merge(
|
||||
super.defaults(),
|
||||
{
|
||||
admin: false,
|
||||
teamId: 0,
|
||||
},
|
||||
)
|
||||
return {
|
||||
...super.defaults(),
|
||||
admin: false,
|
||||
teamId: 0,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,10 @@
|
|||
import TeamShareBaseModel from './teamShareBase'
|
||||
import merge from 'lodash/merge'
|
||||
|
||||
export default class TeamNamespaceModel extends TeamShareBaseModel {
|
||||
defaults() {
|
||||
return merge(
|
||||
super.defaults(),
|
||||
{
|
||||
namespaceId: 0,
|
||||
},
|
||||
)
|
||||
return {
|
||||
...super.defaults(),
|
||||
namespaceId: 0,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,11 @@
|
|||
import UserShareBaseModel from './userShareBase'
|
||||
import merge from 'lodash/merge'
|
||||
|
||||
// This class extends the user share model with a 'rights' parameter which is used in sharing
|
||||
export default class UserListModel extends UserShareBaseModel {
|
||||
defaults() {
|
||||
return merge(
|
||||
super.defaults(),
|
||||
{
|
||||
listId: 0,
|
||||
},
|
||||
)
|
||||
return {
|
||||
...super.defaults(),
|
||||
listId: 0,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,11 @@
|
|||
import UserShareBaseModel from './userShareBase'
|
||||
import merge from 'lodash/merge'
|
||||
|
||||
// This class extends the user share model with a 'rights' parameter which is used in sharing
|
||||
export default class UserNamespaceModel extends UserShareBaseModel {
|
||||
defaults() {
|
||||
return merge(
|
||||
super.defaults(),
|
||||
{
|
||||
namespaceId: 0,
|
||||
},
|
||||
)
|
||||
return {
|
||||
...super.defaults(),
|
||||
namespaceId: 0,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
import axios from 'axios'
|
||||
import reduce from 'lodash/reduce'
|
||||
import replace from 'lodash/replace'
|
||||
import {objectToSnakeCase} from '@/helpers/case'
|
||||
import {getToken} from '@/helpers/auth'
|
||||
|
||||
|
@ -157,9 +155,10 @@ export default class AbstractService {
|
|||
*/
|
||||
getReplacedRoute(path, pathparams) {
|
||||
let replacements = this.getRouteReplacements(path, pathparams)
|
||||
return reduce(replacements, function (result, value, parameter) {
|
||||
return replace(result, parameter, value)
|
||||
}, path)
|
||||
return Object.entries(replacements).reduce(
|
||||
(result, [parameter, value]) => result.replace(parameter, value),
|
||||
path,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Vue from 'vue'
|
||||
|
||||
import {findIndexById} from '@/helpers/find'
|
||||
import {findIndexById} from '@/helpers/utils'
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import Vue from 'vue'
|
||||
import cloneDeep from 'lodash/cloneDeep'
|
||||
|
||||
import BucketService from '../../services/bucket'
|
||||
import {filterObject} from '@/helpers/filterObject'
|
||||
|
@ -206,7 +205,7 @@ export default {
|
|||
const cancel = setLoading(ctx, 'kanban')
|
||||
ctx.commit('setBucketLoading', {bucketId: bucketId, loading: true})
|
||||
|
||||
const params = cloneDeep(ps)
|
||||
const params = JSON.parse(JSON.stringify(ps))
|
||||
|
||||
params.sort_by = 'kanban_position'
|
||||
params.order_by = 'asc'
|
||||
|
|
|
@ -2,10 +2,37 @@ import LabelService from '@/services/label'
|
|||
import Vue from 'vue'
|
||||
import {setLoading} from '@/store/helper'
|
||||
|
||||
/**
|
||||
* Returns the labels by id if found
|
||||
* @param {Object} state
|
||||
* @param {Array} ids
|
||||
* @returns {Array}
|
||||
*/
|
||||
function getLabelsByIds(state, ids) {
|
||||
return Object.values(state.labels).filter(({id}) => ids.includes(id))
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a list of labels is available in the store and filters them then query
|
||||
* @param {Object} state
|
||||
* @param {Array} labels
|
||||
* @param {String} query
|
||||
* @returns {Array}
|
||||
*/
|
||||
function filterLabelsByQuery(state, labels, query) {
|
||||
const labelIds = labels.map(({id}) => id)
|
||||
const foundLabels = getLabelsByIds(state, labelIds)
|
||||
const labelQuery = query.toLowerCase()
|
||||
|
||||
return foundLabels.filter(({title}) => {
|
||||
return !title.toLowerCase().includes(labelQuery)
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
// The state is an object which has the label ids as keys.
|
||||
state: () => ({
|
||||
// The labels are stored as an object which has the label ids as keys.
|
||||
labels: {},
|
||||
loaded: false,
|
||||
}),
|
||||
|
@ -25,6 +52,14 @@ export default {
|
|||
state.loaded = loaded
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
getLabelsByIds(state) {
|
||||
return (ids) => getLabelsByIds(state, ids)
|
||||
},
|
||||
filterLabelsByQuery(state) {
|
||||
return (...arr) => filterLabelsByQuery(state, ...arr)
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
loadAllLabels(ctx, {forceLoad} = {}) {
|
||||
if (ctx.state.loaded && !forceLoad) {
|
||||
|
|
|
@ -5511,7 +5511,7 @@ lodash.truncate@^4.4.2:
|
|||
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
||||
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
|
||||
|
||||
lodash@4.17.21, lodash@4.x, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0:
|
||||
lodash@4.x, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
|
Reference in New Issue
Block a user