diff --git a/src/App.vue b/src/App.vue
index c8367af887..059ebc43ec 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1169,20 +1169,6 @@ textarea.input:focus {
max-width: 95%;
}
-.query-list .tag {
- margin-right: 1em;
- margin-bottom: 0.2em;
- border: 1px solid transparent;
-}
-
-.query-list .tag .delete {
- transform: rotate(45deg) scale(0.7);
-}
-
-.query-list .tag:hover {
- transform: scale(1.1);
-}
-
.fixed-page {
position: fixed;
left: 0;
diff --git a/src/components/modals/EditSearchFilterGroupModal.vue b/src/components/modals/EditSearchFilterGroupModal.vue
new file mode 100644
index 0000000000..173783ba74
--- /dev/null
+++ b/src/components/modals/EditSearchFilterGroupModal.vue
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+ {{ $t('main.filter_group_edit') }} "{{ groupToEdit.name }}"
+
+
+ {{ $t('main.filter_group_add') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/modals/EditSearchFilterModal.vue b/src/components/modals/EditSearchFilterModal.vue
index a01c286673..fafb3cbc92 100644
--- a/src/components/modals/EditSearchFilterModal.vue
+++ b/src/components/modals/EditSearchFilterModal.vue
@@ -17,17 +17,22 @@
+
+
@@ -49,14 +54,16 @@
filter label when it's too complex to read or too long.
*/
import { modalMixin } from '@/components/modals/base_modal'
+import ModalFooter from '@/components/modals/ModalFooter'
+import Combobox from '@/components/widgets/Combobox'
import TextField from '@/components/widgets/TextField'
-import ModalFooter from '@/components/modals/ModalFooter'
export default {
name: 'edit-search-filter-modal',
mixins: [modalMixin],
components: {
+ Combobox,
ModalFooter,
TextField
},
@@ -70,6 +77,10 @@ export default {
type: Boolean,
default: false
},
+ isGroupEnabled: {
+ type: Boolean,
+ default: false
+ },
isLoading: {
type: Boolean,
default: false
@@ -77,31 +88,32 @@ export default {
searchQueryToEdit: {
type: Object,
default: () => {}
+ },
+ groupOptions: {
+ type: Array,
+ default: () => []
}
},
data() {
- if (this.searchQueryToEdit && this.searchQueryToEdit.id) {
- return {
- form: {
- text: this.searchQueryToEdit.text,
- task_status_id: this.searchQueryToEdit.task_status_id
- }
- }
- } else {
- return {
- form: {
- text: '',
- task_status_id: null
- }
+ return {
+ form: {
+ id: null,
+ name: '',
+ search_filter_group_id: null,
+ search_query: '',
+ task_status_id: null
}
}
},
- computed: {},
-
methods: {
runConfirmation(event) {
+ if (!this.form.name.length) {
+ this.$refs.nameField.focus()
+ return
+ }
+
if (!event || event.keyCode === 13 || !event.keyCode) {
this.$emit('confirm', {
id: this.searchQueryToEdit.id,
@@ -113,15 +125,19 @@ export default {
watch: {
searchQueryToEdit() {
- if (this.searchQueryToEdit && this.searchQueryToEdit.id) {
+ if (this.searchQueryToEdit?.id) {
this.form.id = this.searchQueryToEdit.id
this.form.name = this.searchQueryToEdit.name
+ this.form.search_filter_group_id =
+ this.searchQueryToEdit.search_filter_group_id
this.form.search_query = this.searchQueryToEdit.search_query
} else {
this.form = {
- id: '',
+ id: null,
name: '',
- search_query: ''
+ search_filter_group_id: null,
+ search_query: '',
+ task_status_id: null
}
}
},
@@ -136,5 +152,3 @@ export default {
}
}
-
-
diff --git a/src/components/pages/Assets.vue b/src/components/pages/Assets.vue
index 2779c7313f..0b2b7b0850 100644
--- a/src/components/pages/Assets.vue
+++ b/src/components/pages/Assets.vue
@@ -61,7 +61,10 @@
{})
- .catch(err => {
- if (err) console.error(err)
- })
+ this.saveAssetSearch(searchQuery).catch(err => {
+ if (err) console.error(err)
+ })
},
removeSearchQuery(searchQuery) {
- this.removeAssetSearch(searchQuery)
- .then(() => {})
- .catch(err => {
- if (err) console.error(err)
- })
+ this.removeAssetSearch(searchQuery).catch(err => {
+ if (err) console.error(err)
+ })
},
saveScrollPosition(scrollPosition) {
diff --git a/src/components/pages/Edits.vue b/src/components/pages/Edits.vue
index 22e89b9174..d05c3f1773 100644
--- a/src/components/pages/Edits.vue
+++ b/src/components/pages/Edits.vue
@@ -65,6 +65,7 @@
@@ -577,19 +578,15 @@ export default {
},
saveSearchQuery(searchQuery) {
- this.savePersonTasksSearch(searchQuery)
- .then(() => {})
- .catch(err => {
- if (err) console.error(err)
- })
+ this.savePersonTasksSearch(searchQuery).catch(err => {
+ if (err) console.error(err)
+ })
},
removeSearchQuery(searchQuery) {
- this.removePersonTasksSearch(searchQuery)
- .then(() => {})
- .catch(err => {
- if (err) console.error(err)
- })
+ this.removePersonTasksSearch(searchQuery).catch(err => {
+ if (err) console.error(err)
+ })
},
updateActiveTab() {
diff --git a/src/components/pages/SequenceStats.vue b/src/components/pages/SequenceStats.vue
index 664e7272d1..6f8301da9a 100644
--- a/src/components/pages/SequenceStats.vue
+++ b/src/components/pages/SequenceStats.vue
@@ -41,6 +41,7 @@
diff --git a/src/components/pages/Sequences.vue b/src/components/pages/Sequences.vue
index f4d7b2f89f..4b9a0f991a 100644
--- a/src/components/pages/Sequences.vue
+++ b/src/components/pages/Sequences.vue
@@ -37,6 +37,7 @@
{})
- .catch(err => {
- console.error(err)
- })
+ this.saveTaskSearch({ searchQuery, entityType }).catch(err => {
+ console.error(err)
+ })
},
removeSearchQuery(searchQuery) {
- this.removeTaskSearch(searchQuery)
- .then(() => {})
- .catch(err => {
- console.error(err)
- })
+ this.removeTaskSearch(searchQuery).catch(err => {
+ console.error(err)
+ })
},
updateUrlParams() {
diff --git a/src/components/pages/Todos.vue b/src/components/pages/Todos.vue
index 9937673ef2..b848bfb7dd 100644
--- a/src/components/pages/Todos.vue
+++ b/src/components/pages/Todos.vue
@@ -78,6 +78,7 @@
>
@@ -361,17 +362,13 @@ export default {
},
saveSearchQuery(searchQuery) {
- this.saveTodoSearch(searchQuery)
- .then(() => {})
- .catch(console.error)
+ this.saveTodoSearch(searchQuery).catch(console.error)
},
removeSearchQuery(searchQuery) {
- this.removeTodoSearch(searchQuery)
- .then(() => {})
- .catch(err => {
- if (err) console.error(err)
- })
+ this.removeTodoSearch(searchQuery).catch(err => {
+ if (err) console.error(err)
+ })
},
onDateChanged(date) {
diff --git a/src/components/widgets/SearchQueryList.vue b/src/components/widgets/SearchQueryList.vue
index 22e9c851c1..8db7d02c89 100644
--- a/src/components/widgets/SearchQueryList.vue
+++ b/src/components/widgets/SearchQueryList.vue
@@ -1,34 +1,116 @@
+
+
+
+
+
+
+ {{ $t('main.filter_group_empty') }}
+
+
+
+ {{ searchQuery.name }}
+
+
+
+
+
+
+
-
+
{{ searchQuery.name }}
-
+
@@ -38,10 +120,17 @@
* results. It allows to modify each query too.
*/
import { mapActions } from 'vuex'
-import { Edit2Icon } from 'vue-feather-icons'
+import {
+ ChevronDownIcon,
+ Edit2Icon,
+ FolderPlusIcon,
+ Trash2Icon
+} from 'vue-feather-icons'
import { sortByName } from '@/lib/sorting'
+import stringHelpers from '@/lib/string'
import EditSearchFilterModal from '@/components/modals/EditSearchFilterModal'
+import EditSearchFilterGroupModal from '@/components/modals/EditSearchFilterGroupModal'
export default {
name: 'search-query-list',
@@ -49,41 +138,91 @@ export default {
queries: {
type: Array,
default: () => []
+ },
+ groups: {
+ type: Array,
+ default: () => []
+ },
+ isGroupEnabled: {
+ type: Boolean,
+ default: false
+ },
+ type: {
+ type: String,
+ required: true
}
},
components: {
+ ChevronDownIcon,
Edit2Icon,
- EditSearchFilterModal
+ EditSearchFilterModal,
+ EditSearchFilterGroupModal,
+ FolderPlusIcon,
+ Trash2Icon
},
data() {
return {
+ groupToEdit: {},
searchQueryToEdit: {},
errors: {
- edit: false
+ edit: false,
+ group: false
},
loading: {
- edit: false
+ edit: false,
+ group: false
},
modals: {
- edit: false
- }
+ edit: false,
+ group: false
+ },
+ toggleGroupId: null
}
},
computed: {
- userFilters() {
+ sortedFilters() {
return sortByName([...this.queries])
+ },
+ userFilters() {
+ return this.sortedFilters.filter(query => !query.search_filter_group_id)
+ },
+ userFilterGroups() {
+ return sortByName([...this.groups]).map(group => {
+ return {
+ ...group,
+ queries: this.sortedFilters.filter(
+ query => query.search_filter_group_id === group.id
+ )
+ }
+ })
+ },
+ groupOptions() {
+ return [
+ { label: '', value: null },
+ ...this.userFilterGroups.map(group => ({
+ label: group.name,
+ value: group.id
+ }))
+ ]
}
},
methods: {
- ...mapActions(['updateSearchFilter']),
-
- changeSearch(event, searchQuery) {
- const isButtonClicked = ['delete flexrow', 'edit flexrow'].includes(
- event.target.className
- )
- if (!isButtonClicked) {
- this.$emit('change-search', searchQuery)
- }
+ ...mapActions([
+ 'removeAssetSearchFilterGroup',
+ 'removeShotSearchFilterGroup',
+ 'saveAssetSearchFilterGroup',
+ 'saveShotSearchFilterGroup',
+ 'updateSearchFilter',
+ 'updateSearchFilterGroup'
+ ]),
+
+ changeSearch(searchQuery) {
+ this.$emit('change-search', searchQuery)
+ },
+
+ editGroup(group = {}) {
+ this.groupToEdit = group
+ this.modals.group = true
},
editSearch(searchQuery) {
@@ -91,69 +230,182 @@ export default {
this.modals.edit = true
},
- confirmEditSearch(searchFilter) {
- this.loading.edit = true
- this.updateSearchFilter(searchFilter)
- .then(() => {
- this.loading.edit = false
- this.modals.edit = false
- })
- .catch(err => {
- console.error(err)
- this.loading.edit = false
- this.errors.edit = true
- })
+ async confirmEditFilterGroup(filterGroup) {
+ try {
+ this.loading.group = true
+ this.errors.group = false
+
+ if (!filterGroup.id) {
+ await this[
+ `save${stringHelpers.capitalize(this.type)}SearchFilterGroup`
+ ](filterGroup)
+ } else {
+ await this.updateSearchFilterGroup(filterGroup)
+ }
+ this.modals.group = false
+ } catch (err) {
+ console.error(err)
+ this.errors.group = true
+ } finally {
+ this.loading.group = false
+ }
+ },
+
+ async confirmEditSearch(searchFilter) {
+ try {
+ this.loading.edit = true
+ this.errors.edit = false
+ await this.updateSearchFilter(searchFilter)
+ this.modals.edit = false
+ } catch (err) {
+ console.error(err)
+ this.errors.edit = true
+ } finally {
+ this.loading.edit = false
+ }
+ },
+
+ closeFilterGroupModal() {
+ this.modals.group = false
},
removeSearch(searchQuery) {
this.$emit('remove-search', searchQuery)
+ },
+
+ async removeGroup(filterGroup) {
+ try {
+ await this[
+ `remove${stringHelpers.capitalize(this.type)}SearchFilterGroup`
+ ](filterGroup)
+ } catch (err) {
+ console.error(err)
+ }
+ },
+
+ toggleFilterGroup(group) {
+ this.toggleGroupId = this.toggleGroupId !== group.id ? group.id : null
}
}
}
-
diff --git a/src/lib/string.js b/src/lib/string.js
index d31a482812..eb43bab3a0 100644
--- a/src/lib/string.js
+++ b/src/lib/string.js
@@ -41,5 +41,9 @@ export default {
.replace(/[^a-z0-9 -]/g, '')
.replace(/\s+/g, '_')
.replace(/-+/g, '_')
+ },
+
+ capitalize(str) {
+ return str.charAt(0).toUpperCase() + str.slice(1)
}
}
diff --git a/src/locales/en.js b/src/locales/en.js
index fc131f71d3..1c22b5afeb 100644
--- a/src/locales/en.js
+++ b/src/locales/en.js
@@ -391,6 +391,7 @@ export default {
cancel: 'Cancel',
clear_selection: 'Clear current selection',
close: 'Close',
+ color: 'Color',
column_visibility: 'Visible columns',
confirmation: 'Confirm',
confirmation_and_stay: 'Confirm and stay',
@@ -410,6 +411,11 @@ export default {
estimation: 'Estimation',
estimation_short: 'Est.',
files_selected: 'files selected',
+ filter_group: 'Filter Group',
+ filter_group_add: 'Add A Filter Group',
+ filter_group_edit: 'Edit A Filter Group',
+ filter_group_empty: 'No filter',
+ filter_group_error: 'An error occurred while saving this filter group.',
for: 'For',
fps: 'FPS',
frames: 'Frames',
diff --git a/src/store/api/people.js b/src/store/api/people.js
index 5ae02867fa..3f216426ce 100644
--- a/src/store/api/people.js
+++ b/src/store/api/people.js
@@ -231,6 +231,33 @@ export default {
client.get(`/api/data/persons/${personId}/done-tasks`, callback)
},
+ getUserSearchFilterGroups() {
+ return client.pget('/api/data/user/filter-groups')
+ },
+
+ createFilterGroup(listType, name, color, productionId, entityType) {
+ const data = {
+ list_type: listType,
+ name,
+ color,
+ project_id: productionId,
+ entity_type: entityType
+ }
+ return client.ppost('/api/data/user/filter-groups', data)
+ },
+
+ updateFilterGroup(filterGroup) {
+ const data = {
+ name: filterGroup.name,
+ color: filterGroup.color
+ }
+ return client.pput(`/api/data/user/filter-groups/${filterGroup.id}`, data)
+ },
+
+ removeFilterGroup(filterGroup) {
+ return client.pdel(`/api/data/user/filter-groups/${filterGroup.id}`)
+ },
+
getUserSearchFilters(callback) {
client.get('/api/data/user/filters', callback)
},
@@ -238,7 +265,8 @@ export default {
updateFilter(searchFilter) {
const data = {
name: searchFilter.name,
- search_query: searchFilter.search_query
+ search_query: searchFilter.search_query,
+ search_filter_group_id: searchFilter.search_filter_group_id
}
return client.pput(`/api/data/user/filters/${searchFilter.id}`, data)
},
@@ -254,7 +282,7 @@ export default {
return client.ppost('/api/data/user/filters', data)
},
- removeFilter(searchFilter, callback) {
+ removeFilter(searchFilter) {
return client.pdel(`/api/data/user/filters/${searchFilter.id}`)
},
diff --git a/src/store/modules/assets.js b/src/store/modules/assets.js
index 58bb2af7d6..33b8363dcc 100644
--- a/src/store/modules/assets.js
+++ b/src/store/modules/assets.js
@@ -64,6 +64,8 @@ import {
SAVE_ASSET_SEARCH_END,
REMOVE_ASSET_SEARCH_END,
SET_ASSET_TYPE_SEARCH,
+ SAVE_ASSET_SEARCH_FILTER_GROUP_END,
+ REMOVE_ASSET_SEARCH_FILTER_GROUP_END,
COMPUTE_ASSET_TYPE_STATS,
UPDATE_METADATA_DESCRIPTOR_END,
SET_CURRENT_EPISODE,
@@ -271,6 +273,7 @@ const initialState = {
assetSearchText: '',
assetSelectionGrid: {},
assetSearchQueries: [],
+ assetSearchFilterGroups: [],
assetSorting: [],
displayedAssetTypes: [],
@@ -302,6 +305,7 @@ const getters = {
assetMap: state => state.assetMap,
assetSearchText: state => state.assetSearchText,
assetSearchQueries: state => state.assetSearchQueries,
+ assetSearchFilterGroups: state => state.assetSearchFilterGroups,
assetSelectionGrid: state => state.assetSelectionGrid,
assetValidationColumns: state => state.assetValidationColumns,
@@ -350,6 +354,7 @@ const actions = {
let episode = rootGetters.currentEpisode
const isTVShow = rootGetters.isTVShow
const userFilters = rootGetters.userFilters
+ const userFilterGroups = rootGetters.userFilterGroups
const personMap = rootGetters.personMap
const taskTypeMap = rootGetters.taskTypeMap
const taskMap = rootGetters.taskMap
@@ -382,6 +387,7 @@ const actions = {
production,
assets,
userFilters,
+ userFilterGroups,
personMap,
taskMap,
taskTypeMap
@@ -558,6 +564,29 @@ const actions = {
}
},
+ saveAssetSearchFilterGroup({ commit, state, rootGetters }, filterGroup) {
+ const groupExist = state.assetSearchFilterGroups.some(
+ query => query.name === filterGroup.name
+ )
+ if (groupExist) {
+ return
+ }
+
+ const production = rootGetters.currentProduction
+ return peopleApi
+ .createFilterGroup(
+ 'asset',
+ filterGroup.name,
+ filterGroup.color,
+ production.id,
+ null
+ )
+ .then(filterGroup => {
+ commit(SAVE_ASSET_SEARCH_FILTER_GROUP_END, { filterGroup, production })
+ return filterGroup
+ })
+ },
+
removeAssetSearch({ commit, rootGetters }, searchQuery) {
const production = rootGetters.currentProduction
return peopleApi.removeFilter(searchQuery).then(() => {
@@ -566,6 +595,13 @@ const actions = {
})
},
+ removeAssetSearchFilterGroup({ commit, rootGetters }, filterGroup) {
+ const production = rootGetters.currentProduction
+ return peopleApi.removeFilterGroup(filterGroup).then(() => {
+ commit(REMOVE_ASSET_SEARCH_FILTER_GROUP_END, { filterGroup, production })
+ })
+ },
+
displayMoreAssets({ commit, rootGetters }) {
commit(DISPLAY_MORE_ASSETS, {
taskTypeMap: rootGetters.taskTypeMap,
@@ -726,6 +762,7 @@ const mutations = {
state.assetFilledColumns = {}
helpers.setListStats(state, [])
state.assetSearchQueries = []
+ state.assetSearchFilterGroups = []
state.selectedAssets = new Map()
},
@@ -743,6 +780,7 @@ const mutations = {
state.assetFilledColumns = {}
helpers.setListStats(state, [])
state.assetSearchQueries = []
+ state.assetSearchFilterGroups = []
state.selectedAssets = new Map()
},
@@ -754,7 +792,15 @@ const mutations = {
[LOAD_ASSETS_END](
state,
- { production, assets, userFilters, personMap, taskMap, taskTypeMap }
+ {
+ production,
+ assets,
+ userFilters,
+ userFilterGroups,
+ personMap,
+ taskMap,
+ taskTypeMap
+ }
) {
const validationColumns = {}
const assetTypeMap = new Map()
@@ -814,11 +860,10 @@ const mutations = {
const maxY = state.nbValidationColumns
state.assetSelectionGrid = buildSelectionGrid(maxX, maxY)
- if (userFilters.asset && userFilters.asset[production.id]) {
- state.assetSearchQueries = userFilters.asset[production.id]
- } else {
- state.assetSearchQueries = []
- }
+ state.assetSearchQueries = userFilters.asset?.[production.id] || []
+
+ state.assetSearchFilterGroups =
+ userFilterGroups.asset?.[production.id] || []
},
[ADD_ASSET](state, { taskTypeMap, taskMap, personMap, production, asset }) {
@@ -965,6 +1010,13 @@ const mutations = {
}
},
+ [SAVE_ASSET_SEARCH_FILTER_GROUP_END](state, { filterGroup }) {
+ if (!state.assetSearchFilterGroups.includes(filterGroup)) {
+ state.assetSearchFilterGroups.push(filterGroup)
+ state.assetSearchFilterGroups = sortByName(state.assetSearchFilterGroups)
+ }
+ },
+
[REMOVE_ASSET_SEARCH_END](state, { searchQuery }) {
const queryIndex = state.assetSearchQueries.findIndex(
query => query.name === searchQuery.name
@@ -974,6 +1026,15 @@ const mutations = {
}
},
+ [REMOVE_ASSET_SEARCH_FILTER_GROUP_END](state, { filterGroup }) {
+ const groupIndex = state.assetSearchFilterGroups.findIndex(
+ query => query.name === filterGroup.name
+ )
+ if (groupIndex >= 0) {
+ state.assetSearchFilterGroups.splice(groupIndex, 1)
+ }
+ },
+
[DISPLAY_MORE_ASSETS](
state,
{ taskTypeMap, taskStatusMap, taskMap, production }
diff --git a/src/store/modules/shots.js b/src/store/modules/shots.js
index 1710a5a889..4ca69106d1 100644
--- a/src/store/modules/shots.js
+++ b/src/store/modules/shots.js
@@ -62,7 +62,9 @@ import {
CLEAR_SELECTED_TASKS,
SET_PREVIEW,
SAVE_SHOT_SEARCH_END,
+ SAVE_SHOT_SEARCH_FILTER_GROUP_END,
REMOVE_SHOT_SEARCH_END,
+ REMOVE_SHOT_SEARCH_FILTER_GROUP_END,
CHANGE_SHOT_SORT,
UPDATE_METADATA_DESCRIPTOR_END,
LOCK_SHOT,
@@ -246,6 +248,7 @@ const initialState = {
shotMap: new Map(),
shotSearchText: '',
shotSearchQueries: [],
+ shotSearchFilterGroups: [],
shotSorting: [],
isFps: false,
@@ -288,6 +291,7 @@ const getters = {
shotValidationColumns: state => state.shotValidationColumns,
shotSearchQueries: state => state.shotSearchQueries,
+ shotSearchFilterGroups: state => state.shotSearchFilterGroups,
shotMap: state => state.shotMap,
shotSorting: state => state.shotSorting,
@@ -376,6 +380,7 @@ const actions = {
const production = rootGetters.currentProduction
const episodes = rootGetters.episodes
const userFilters = rootGetters.userFilters
+ const userFilterGroups = rootGetters.userFilterGroups
const taskTypeMap = rootGetters.taskTypeMap
const taskMap = rootGetters.taskMap
const episodeMap = rootGetters.episodeMap
@@ -419,6 +424,7 @@ const actions = {
production,
shots,
userFilters,
+ userFilterGroups,
taskTypeMap,
taskMap,
personMap,
@@ -587,6 +593,29 @@ const actions = {
}
},
+ saveShotSearchFilterGroup({ commit, state, rootGetters }, filterGroup) {
+ const groupExist = state.shotSearchFilterGroups.some(
+ query => query.name === filterGroup.name
+ )
+ if (groupExist) {
+ return
+ }
+
+ const production = rootGetters.currentProduction
+ return peopleApi
+ .createFilterGroup(
+ 'shot',
+ filterGroup.name,
+ filterGroup.color,
+ production.id,
+ null
+ )
+ .then(filterGroup => {
+ commit(SAVE_SHOT_SEARCH_FILTER_GROUP_END, { filterGroup, production })
+ return filterGroup
+ })
+ },
+
removeShotSearch({ commit, rootGetters }, searchQuery) {
const production = rootGetters.currentProduction
return peopleApi.removeFilter(searchQuery).then(() => {
@@ -595,6 +624,13 @@ const actions = {
})
},
+ removeShotSearchFilterGroup({ commit, rootGetters }, filterGroup) {
+ const production = rootGetters.currentProduction
+ return peopleApi.removeFilterGroup(filterGroup).then(() => {
+ commit(REMOVE_SHOT_SEARCH_FILTER_GROUP_END, { filterGroup, production })
+ })
+ },
+
getShotsCsvLines({ state, rootGetters }) {
const production = rootGetters.currentProduction
const isTVShow = rootGetters.isTVShow
@@ -746,6 +782,7 @@ const mutations = {
state.displayedEstimation = 0
state.displayedFrames = 0
state.shotSearchQueries = []
+ state.shotSearchFilterGroups = []
state.displayedSequences = []
state.displayedSequencesLength = 0
@@ -768,6 +805,7 @@ const mutations = {
state.displayedEstimation = 0
state.displayedFrames = 0
state.shotSearchQueries = []
+ state.shotSearchFilterGroups = []
state.displayedSequences = []
state.displayedSequencesLength = 0
@@ -785,6 +823,7 @@ const mutations = {
production,
shots,
userFilters,
+ userFilterGroups,
taskMap,
taskTypeMap,
personMap,
@@ -888,11 +927,9 @@ const mutations = {
state.shotSelectionGrid = buildSelectionGrid(maxX, maxY)
helpers.setListStats(state, shots)
- if (userFilters.shot && userFilters.shot[production.id]) {
- state.shotSearchQueries = userFilters.shot[production.id]
- } else {
- state.shotSearchQueries = []
- }
+ state.shotSearchQueries = userFilters.shot?.[production.id] || []
+
+ state.shotSearchFilterGroups = userFilterGroups.shot?.[production.id] || []
},
[SAVE_SHOT_SEARCH_END](state, { searchQuery }) {
@@ -900,6 +937,13 @@ const mutations = {
state.shotSearchQueries = sortByName(state.shotSearchQueries)
},
+ [SAVE_SHOT_SEARCH_FILTER_GROUP_END](state, { filterGroup }) {
+ if (!state.shotSearchFilterGroups.includes(filterGroup)) {
+ state.shotSearchFilterGroups.push(filterGroup)
+ state.shotSearchFilterGroups = sortByName(state.shotSearchFilterGroups)
+ }
+ },
+
[REMOVE_SHOT_SEARCH_END](state, { searchQuery }) {
const queryIndex = state.shotSearchQueries.findIndex(
query => query.name === searchQuery.name
@@ -909,6 +953,15 @@ const mutations = {
}
},
+ [REMOVE_SHOT_SEARCH_FILTER_GROUP_END](state, { filterGroup }) {
+ const groupIndex = state.shotSearchFilterGroups.findIndex(
+ query => query.name === filterGroup.name
+ )
+ if (groupIndex >= 0) {
+ state.shotSearchFilterGroups.splice(groupIndex, 1)
+ }
+ },
+
[LOAD_SHOT_END](state, { shot, taskTypeMap }) {
shot.tasks.forEach(task => {
helpers.populateTask(task, shot)
diff --git a/src/store/modules/user.js b/src/store/modules/user.js
index 2682456496..9cc8703bff 100644
--- a/src/store/modules/user.js
+++ b/src/store/modules/user.js
@@ -43,6 +43,9 @@ import {
LOAD_USER_FILTERS_END,
LOAD_USER_FILTERS_ERROR,
UPDATE_USER_FILTER,
+ LOAD_USER_FILTER_GROUPS_END,
+ LOAD_USER_FILTER_GROUPS_ERROR,
+ UPDATE_USER_FILTER_GROUP,
SAVE_TODO_SEARCH_END,
REMOVE_TODO_SEARCH_END,
ADD_SELECTED_TASK,
@@ -109,6 +112,7 @@ const initialState = {
todoSelectionGrid: {},
todoSearchQueries: [],
userFilters: {},
+ userFilterGroups: {},
todoListScrollPosition: 0,
timeSpentMap: {},
@@ -144,6 +148,7 @@ const getters = {
todoSelectionGrid: state => state.todoSelectionGrid,
todoSearchQueries: state => state.todoSearchQueries,
userFilters: state => state.userFilters,
+ userFilterGroups: state => state.userFilterGroups,
isTodosLoading: state => state.isTodosLoading,
isTodosLoadingError: state => state.isTodosLoadingError,
todoListScrollPosition: state => state.todoListScrollPosition,
@@ -334,9 +339,14 @@ const actions = {
commit(SET_TODOS_SEARCH, searchText)
},
- updateSearchFilter({ commit }, searchFilter) {
+ async updateSearchFilterGroup({ commit }, searchFilterGroup) {
+ await peopleApi.updateFilterGroup(searchFilterGroup)
+ commit(UPDATE_USER_FILTER_GROUP, searchFilterGroup)
+ },
+
+ async updateSearchFilter({ commit }, searchFilter) {
+ await peopleApi.updateFilter(searchFilter)
commit(UPDATE_USER_FILTER, searchFilter)
- return peopleApi.updateFilter(searchFilter)
},
loadUserSearchFilters({ commit }, callback) {
@@ -378,6 +388,7 @@ const actions = {
loadContext({ commit, rootGetters }, callback) {
return peopleApi.getContext().then(context => {
commit(LOAD_USER_FILTERS_END, context.search_filters)
+ commit(LOAD_USER_FILTER_GROUPS_END, context.search_filter_groups)
commit(LOAD_PRODUCTION_STATUS_END, context.project_status)
commit(LOAD_DEPARTMENTS_END, context.departments)
commit(LOAD_TASK_STATUSES_END, context.task_status)
@@ -701,6 +712,24 @@ const mutations = {
})
},
+ [LOAD_USER_FILTER_GROUPS_ERROR](state) {},
+ [LOAD_USER_FILTER_GROUPS_END](state, userFilterGroups) {
+ state.userFilterGroups = userFilterGroups
+ },
+ [UPDATE_USER_FILTER_GROUP](state, userFilterGroup) {
+ Object.keys(state.userFilterGroups).forEach(typeName => {
+ Object.keys(state.userFilterGroups[typeName]).forEach(projectId => {
+ const projectFilterGroups = state.userFilterGroups[typeName][projectId]
+ const filterGroup = projectFilterGroups.find(
+ f => f.id === userFilterGroup.id
+ )
+ if (filterGroup) {
+ Object.assign(filterGroup, userFilterGroup)
+ }
+ })
+ })
+ },
+
[SET_TIME_SPENT](state, timeSpent) {
if (state.user.id === timeSpent.person_id) {
state.timeSpentMap[timeSpent.task_id] = timeSpent
diff --git a/src/store/mutation-types.js b/src/store/mutation-types.js
index 3bc8469311..f0cfed8c97 100644
--- a/src/store/mutation-types.js
+++ b/src/store/mutation-types.js
@@ -93,6 +93,10 @@ export const SET_TODOS_SEARCH = 'SET_TODOS_SEARCH'
export const LOAD_USER_FILTERS_END = 'LOAD_USER_FILTERS_END'
export const LOAD_USER_FILTERS_ERROR = 'LOAD_USER_FILTERS_ERROR'
export const UPDATE_USER_FILTER = 'UPDATE_USER_FILTER'
+export const LOAD_USER_FILTER_GROUPS_END = 'LOAD_USER_FILTER_GROUPS_END'
+export const LOAD_USER_FILTER_GROUPS_ERROR = 'LOAD_USER_FILTER_GROUPS_ERROR'
+export const UPDATE_USER_FILTER_GROUP = 'UPDATE_USER_FILTER_GROUP'
+
export const SET_TODO_LIST_SCROLL_POSITION = 'SET_TODO_LIST_SCROLL_POSITION'
// Tasks
@@ -337,6 +341,11 @@ export const SAVE_ASSET_SEARCH_END = 'SAVE_ASSET_SEARCH_END'
export const REMOVE_ASSET_SEARCH_END = 'REMOVE_ASSET_SEARCH_END'
export const DISPLAY_MORE_ASSETS = 'DISPLAY_MORE_ASSETS'
+export const SAVE_ASSET_SEARCH_FILTER_GROUP_END =
+ 'SAVE_ASSET_SEARCH_FILTER_GROUP_END'
+export const REMOVE_ASSET_SEARCH_FILTER_GROUP_END =
+ 'REMOVE_ASSET_SEARCH_FILTER_GROUP_END'
+
export const COMPUTE_ASSET_TYPE_STATS = 'COMPUTE_ASSET_TYPE_STATS'
export const SET_ASSET_TYPE_SEARCH = 'SET_ASSET_TYPE_SEARCH'
@@ -443,6 +452,11 @@ export const SET_EPISODE_SEARCH = 'SET_EPISODE_SEARCH'
export const DISPLAY_MORE_SHOTS = 'DISPLAY_MORE_SHOTS'
export const DISPLAY_MORE_SEQUENCES = 'DISPLAY_MORE_SEQUENCES'
+export const SAVE_SHOT_SEARCH_FILTER_GROUP_END =
+ 'SAVE_SHOT_SEARCH_FILTER_GROUP_END'
+export const REMOVE_SHOT_SEARCH_FILTER_GROUP_END =
+ 'REMOVE_SHOT_SEARCH_FILTER_GROUP_END'
+
export const SET_SHOT_LIST_SCROLL_POSITION = 'SET_SHOT_LIST_SCROLL_POSITION'
export const SET_SEQUENCE_LIST_SCROLL_POSITION =
'SET_SEQUENCE_LIST_SCROLL_POSITION'
diff --git a/tests/unit/store/assets.spec.js b/tests/unit/store/assets.spec.js
index b4346c2c4f..f8e69fb026 100644
--- a/tests/unit/store/assets.spec.js
+++ b/tests/unit/store/assets.spec.js
@@ -771,6 +771,7 @@ describe('Assets store', () => {
assetValidationColumns: 1,
displayedAssets: 1,
assetFilledColumns: 1,
+ assetSearchFilterGroups: 1,
assetSearchQueries: 1,
displayedAssetsCount: 100,
displayedAssetsLength: 100,
@@ -786,6 +787,7 @@ describe('Assets store', () => {
assetValidationColumns: [],
displayedAssets: [],
assetFilledColumns: {},
+ assetSearchFilterGroups: [],
assetSearchQueries: [],
displayedAssetsCount: 0,
displayedAssetsLength: 0,
@@ -806,6 +808,7 @@ describe('Assets store', () => {
assetValidationColumns: 1,
displayedAssets: 1,
assetFilledColumns: 1,
+ assetSearchFilterGroups: 1,
assetSearchQueries: 1,
displayedAssetsCount: 100,
displayedAssetsLength: 100,
@@ -823,6 +826,7 @@ describe('Assets store', () => {
assetValidationColumns: [],
displayedAssets: [],
assetFilledColumns: {},
+ assetSearchFilterGroups: [],
assetSearchQueries: [],
displayedAssetsCount: 0,
displayedAssetsLength: 0,
@@ -896,6 +900,11 @@ describe('Assets store', () => {
1: 'assetSearchQueries'
}
}
+ const userFilterGroups = {
+ asset: {
+ 1: 'assetSearchFilterGroups'
+ }
+ }
const personMap = new Map()
const taskMap = new Map()
const taskTypeMap = new Map()
@@ -903,6 +912,7 @@ describe('Assets store', () => {
production,
assets,
userFilters,
+ userFilterGroups,
personMap,
taskMap,
taskTypeMap
@@ -998,6 +1008,7 @@ describe('Assets store', () => {
displayedAssetsCount: 4,
displayedAssetsLength: 2,
displayedAssetsTimeSpent: 0,
+ assetSearchFilterGroups: 'assetSearchFilterGroups',
assetSearchQueries: 'assetSearchQueries',
assetMap: new Map(Object.entries({
4: {
@@ -1961,6 +1972,7 @@ describe('Assets store', () => {
assetFilledColumns: {},
assetListScrollPosition: 0,
assetMap: new Map(),
+ assetSearchFilterGroups: [],
assetSearchQueries: [],
assetSearchText: '',
assetSelectionGrid: {},