PMCORE-2550: Advanced Search , improve user filter module (suggest)

This commit is contained in:
Rodrigo Quelca
2020-12-15 20:55:45 +00:00
parent 87861e6bca
commit b51e08a556
10 changed files with 183 additions and 149 deletions

View File

@@ -66,7 +66,8 @@ const services = {
PUT_MY_FILTERS: "/cases/advanced-search/filter/", PUT_MY_FILTERS: "/cases/advanced-search/filter/",
DELETE_MY_FILTERS: "/cases/advanced-search/filter/", DELETE_MY_FILTERS: "/cases/advanced-search/filter/",
SEARCH: "/home/search", SEARCH: "/home/search",
PROCESSES: "/home/processes" PROCESSES: "/home/processes",
USERS: "/home/users"
}; };
export default { export default {

View File

@@ -172,10 +172,13 @@ export let cases = {
export let casesHeader = { export let casesHeader = {
get() { get() {
return new Promise((resolutionFunc, rejectionFunc) => { return axios.get(window.config.SYS_SERVER +
resolutionFunc({ '/api/1.0/' +
data: headerData window.config.SYS_WORKSPACE +
}); '/home/counters', {
headers: {
'Authorization': 'Bearer ' + window.config.SYS_CREDENTIALS.accessToken
}
}); });
} }
}; };

View File

@@ -57,6 +57,18 @@ export let filters = {
keys: {}, keys: {},
}); });
}, },
/**
* Service to get the users list
*/
userList(query) {
return Api.get({
service: "USERS",
params: {
text: query,
},
keys: {},
});
},
/** /**
* Service to get the users list * Service to get the users list
*/ */

View File

@@ -51,7 +51,7 @@ export default {
} }
.v-btn-texts-header { .v-btn-texts-header {
font-size: 0.7vw; font-size: 0.8vw;
} }
.v-btn-header { .v-btn-header {
min-width: 150px; min-width: 150px;
@@ -60,4 +60,4 @@ export default {
padding-bottom: 5px !important; padding-bottom: 5px !important;
padding-top: 5px !important; padding-top: 5px !important;
} }
</style> </style>

View File

@@ -105,7 +105,7 @@
v-for="tag in tags" v-for="tag in tags"
@remove="customRemove(removeTag, tag)" @remove="customRemove(removeTag, tag)"
:key="tag" :key="tag"
:title="tag" :title="searchTagsModels[tag].tagText"
:variant="tagVariant" :variant="tagVariant"
class="mr-1" class="mr-1"
> >
@@ -173,6 +173,9 @@ import DueDate from "./popovers/DueDate.vue";
import LastModifiedDate from "./popovers/LastModifiedDate.vue"; import LastModifiedDate from "./popovers/LastModifiedDate.vue";
import CaseTitle from "./popovers/CaseTitle.vue"; import CaseTitle from "./popovers/CaseTitle.vue";
import ProcessName from "./popovers/ProcessName.vue"; import ProcessName from "./popovers/ProcessName.vue";
import CasePriority from "./popovers/CasePriority.vue";
import CaseStatus from "./popovers/CaseStatus.vue";
import CurrentUser from "./popovers/CurrentUser.vue";
import api from "./../../api/index"; import api from "./../../api/index";
export default { export default {
@@ -184,7 +187,10 @@ export default {
DueDate, DueDate,
LastModifiedDate, LastModifiedDate,
CaseTitle, CaseTitle,
ProcessName ProcessName,
CasePriority,
CaseStatus,
CurrentUser
}, },
data() { data() {
return { return {
@@ -224,7 +230,6 @@ export default {
filterBy: ["caseTitle"], filterBy: ["caseTitle"],
values: {} values: {}
}, },
ProcessName: { ProcessName: {
title: `${this.$i18n.t('ID_FILTER')}: ${this.$i18n.t('ID_PROCESS_NAME')}`, title: `${this.$i18n.t('ID_FILTER')}: ${this.$i18n.t('ID_PROCESS_NAME')}`,
optionLabel: this.$i18n.t('ID_PROCESS_NAME'), optionLabel: this.$i18n.t('ID_PROCESS_NAME'),
@@ -233,6 +238,45 @@ export default {
tagText: "", tagText: "",
filterBy: ["process", "processOption"], filterBy: ["process", "processOption"],
processOption: {"PRO_TITLE": ""} processOption: {"PRO_TITLE": ""}
},
CasePriority: {
title: `${this.$i18n.t('ID_FILTER')}: ${this.$i18n.t('ID_PRIORITY')}`,
optionLabel: this.$i18n.t('ID_PRIORITY'),
detail: this.$i18n.t('ID_PLEASE_SELECT_THE_PRIORITY_FOR_THE_SEARCH'),
options: [
{ text: this.$i18n.t('ID_VERY_LOW'), value: "VL" },
{ text: this.$i18n.t('ID_LOW'), value: "L" },
{ text: this.$i18n.t('ID_NORMAL'), value: "N" },
{ text: this.$i18n.t('ID_HIGH'), value: "H" },
{ text: this.$i18n.t('ID_VERY_HIGH'), value: "VH" }
],
tagText: "",
filterBy: ["priorities"],
casePriorities: []
},
CaseStatus: {
title: `${this.$i18n.t('ID_FILTER')}: ${this.$i18n.t('ID_STATUS')}`,
optionLabel: this.$i18n.t('ID_STATUS'),
detail: this.$i18n.t('ID_PLEASE_SELECT_THE_STATUS_FOR_THE_SEARCH'),
options: [
{ text: this.$i18n.t('ID_CASES_STATUS_DRAFT'), value: "DRAFT" },
{ text: this.$i18n.t('ID_CASES_STATUS_TO_DO'), value: "TO_DO" },
{ text: this.$i18n.t('ID_CASES_STATUS_COMPLETED'), value: "COMPLETED" },
{ text: this.$i18n.t('ID_CASES_STATUS_CANCELLED'), value: "CANCELLED" },
{ text: this.$i18n.t('ID_CASES_STATUS_PAUSED'), value: "PAUSED" },
],
tagText: "",
filterBy: ["caseStatuses"],
caseStatuses: []
},
CurrentUser: {
title: `${this.$i18n.t('ID_FILTER')}: ${this.$i18n.t('ID_CURRENT_USER')}`,
optionLabel: this.$i18n.t('ID_CURRENT_USER'),
detail: "",
placeholder: this.$i18n.t('ID_USER_NAME'),
tagText: "",
filterBy: ["userId", "selectedOption"],
selectedOption: {"USR_FULLNAME": ""}
} }
}, },
text: "", text: "",
@@ -295,32 +339,42 @@ export default {
let label = ""; let label = "";
switch (type) { switch (type) {
case "CaseNumber": case "CaseNumber":
label = `${this.$i18n.t("ID_IUD")}: ${params.filterCases}` this.searchTagsModels[type].tagText = `${this.$i18n.t("ID_IUD")}: ${params.filterCases}`
this.searchTagsModels[type].values["filterCases"] = params.filterCases; this.searchTagsModels[type].values["filterCases"] = params.filterCases;
break; break;
case "DueDate": case "DueDate":
label = `${this.$i18n.t('ID_FROM')}: ${params.dueDateFrom} ${this.$i18n.t('ID_TO')}: ${params.dueDateTo}`; this.searchTagsModels[type].tagText = `${this.$i18n.t('ID_FROM')}: ${params.dueDateFrom} ${this.$i18n.t('ID_TO')}: ${params.dueDateTo}`;
this.searchTagsModels[type].values["dueDateFrom"] = params.dueDateFrom; this.searchTagsModels[type].values["dueDateFrom"] = params.dueDateFrom;
this.searchTagsModels[type].values["dueDateTo"] = params.dueDateTo; this.searchTagsModels[type].values["dueDateTo"] = params.dueDateTo;
break; break;
case "LastModifiedDate": case "LastModifiedDate":
label = `${this.$i18n.t('ID_FROM')}: ${params.delegationDateFrom} ${this.$i18n.t('ID_TO')}: ${params.delegationDateTo}`; this.searchTagsModels[type].tagText = `${this.$i18n.t('ID_FROM')}: ${params.delegationDateFrom} ${this.$i18n.t('ID_TO')}: ${params.delegationDateTo}`;
this.searchTagsModels[type].values["delegationDateFrom"] = params.delegationDateFrom; this.searchTagsModels[type].values["delegationDateFrom"] = params.delegationDateFrom;
this.searchTagsModels[type].values["delegationDateTo"] = params.delegationDateTo; this.searchTagsModels[type].values["delegationDateTo"] = params.delegationDateTo;
break; break;
case "CaseTitle": case "CaseTitle":
label = `${this.$i18n.t("ID_CASE_TITLE")}: ${params.caseTitle}`; this.searchTagsModels[type].tagText = `${this.$i18n.t("ID_CASE_TITLE")}: ${params.caseTitle}`;
this.searchTagsModels[type].values["caseTitle"] = params.caseTitle; this.searchTagsModels[type].values["caseTitle"] = params.caseTitle;
break; break;
case "ProcessName": case "ProcessName":
label = `${this.$i18n.t("ID_PROCESS")}: ${params.processOption.PRO_TITLE || ''}`; this.searchTagsModels[type].tagText = `${this.$i18n.t("ID_PROCESS")}: ${params.processOption.PRO_TITLE || ''}`;
this.searchTagsModels[type].processOption = params.processOption || null; this.searchTagsModels[type].processOption = params.processOption || null;
break; break;
case "CasePriority":
this.searchTagsModels[type].tagText = `${this.$i18n.t('ID_PRIORITY')}: ${_.map(params.selectedOptions, 'text').join(",") || ''}`;
this.searchTagsModels[type].casePriorities = _.map(params.selectedOptions, 'value');
break;
case "CaseStatus":
this.searchTagsModels[type].tagText = `${this.$i18n.t('ID_STATUS')}: ${_.map(params.selectedOptions, 'text').join(",") || ''}`;
this.searchTagsModels[type].caseStatuses = _.map(params.selectedOptions, 'value');
break;
case "CurrentUser":
this.searchTagsModels[type].tagText = `${this.$i18n.t("ID_USER")}: ${params.selectedOption.USR_FULLNAME || ''}`;
this.searchTagsModels[type].selectedOption = params.selectedOption || null;
break;
default: default:
break; break;
} }
this.searchTagsModels[type].tagText = label;
}, },
cleanAllTags() { cleanAllTags() {
this.searchTags = []; this.searchTags = [];
@@ -403,7 +457,7 @@ export default {
filters: this.filters filters: this.filters
}); });
} }
}, }
}; };
</script> </script>
<style scoped> <style scoped>

View File

@@ -1,18 +1,12 @@
<template> <template>
<div id=""> <div>
<SearchPopover :target="tag" @savePopover="onOk" :title="info.title"> <SearchPopover :target="tag" @savePopover="onOk" :title="info.title">
<template v-slot:target-item>
<div @click="onClickTag(tag)" :id="tag">
<b-icon icon="tags-fill" font-scale="1"></b-icon>
{{ tagText }}
</div>
</template>
<template v-slot:body> <template v-slot:body>
<p>{{ info.detail }}</p> <p>{{ info.detail }}</p>
<b-form-group :label="info.label"> <b-form-group :label="info.label">
<b-form-checkbox <b-form-checkbox
v-for="option in info.options" v-for="option in info.options"
v-model="selected" v-model="info.casePriorities"
:key="option.value" :key="option.value"
:value="option.value" :value="option.value"
name="flavour-2a" name="flavour-2a"
@@ -31,19 +25,9 @@ import SearchPopover from "./SearchPopover.vue";
export default { export default {
components: { components: {
SearchPopover, SearchPopover
}, },
props: ["tag", "info"], props: ["tag", "info"],
data() {
return {
selected: [], // Must be an array reference!
};
},
computed: {
tagText: function() {
return `${this.$i18n.t('ID_PRIORITY')}: ${this.selected.join(",")}`;
},
},
methods: { methods: {
/** /**
* Ok button handler * Ok button handler
@@ -55,12 +39,22 @@ export default {
* Submit button handler * Submit button handler
*/ */
handleSubmit() { handleSubmit() {
this.$nextTick(() => { let selectedOptions = [];
this.$emit("updateSearchTag", { let self = this;
priorities: this.selected.join(","), _.forEach(this.info.casePriorities, function(value) {
}); selectedOptions.push(
this.$root.$emit("bv::hide::popover"); _.find(self.info.options, function(o) {
return o.value === value;
})
);
}); });
this.$emit("updateSearchTag", {
CasePriority: {
priorities: this.info.casePriorities.join(","),
selectedOptions: selectedOptions,
},
});
this.$root.$emit("bv::hide::popover");
}, },
/** /**
* Tag Click handler * Tag Click handler

View File

@@ -1,22 +1,16 @@
<template> <template>
<div id=""> <div>
<SearchPopover <SearchPopover
:target="tag" :target="tag"
@savePopover="onOk" @savePopover="onOk"
:title="info.title" :title="info.title"
> >
<template v-slot:target-item>
<div @click="onClickTag(tag)" :id="tag">
<b-icon icon="tags-fill" font-scale="1"></b-icon>
{{ tagText }}
</div>
</template>
<template v-slot:body> <template v-slot:body>
<h6>{{ info.detail }}</h6> <h6>{{ info.detail }}</h6>
<b-form-group :label="info.label"> <b-form-group :label="info.label">
<b-form-checkbox <b-form-checkbox
v-for="option in info.options" v-for="option in info.options"
v-model="selected" v-model="info.caseStatuses"
:key="option.value" :key="option.value"
:value="option.value" :value="option.value"
name="flavour-2a" name="flavour-2a"
@@ -35,19 +29,9 @@ import SearchPopover from "./SearchPopover.vue";
export default { export default {
components: { components: {
SearchPopover, SearchPopover
}, },
props: ["tag", "info"], props: ["tag", "info"],
data() {
return {
selected: [], // Must be an array reference!
};
},
computed: {
tagText: function() {
return `${this.$i18n.t('ID_STATUS')}: ${this.selected.join(",")}`;
},
},
methods: { methods: {
/** /**
* Ok button handler * Ok button handler
@@ -59,12 +43,18 @@ export default {
* Submit button handler * Submit button handler
*/ */
handleSubmit() { handleSubmit() {
this.$nextTick(() => { let selectedOptions = [];
this.$emit("updateSearchTag", { let self = this;
caseStatuses: this.selected.join(","), _.forEach(this.info.caseStatuses, function(value) {
}); selectedOptions.push(_.find(self.info.options, function(o) { return o.value === value; }));
this.$root.$emit("bv::hide::popover");
}); });
this.$emit("updateSearchTag", {
CaseStatus: {
caseStatuses: this.info.caseStatuses.join(","),
selectedOptions: selectedOptions
}
});
this.$root.$emit("bv::hide::popover")
}, },
/** /**
* Tag Click handler * Tag Click handler

View File

@@ -1,36 +1,27 @@
<template> <template>
<div id=""> <div>
<SearchPopover <SearchPopover :target="tag" @savePopover="onOk" :title="info.title">
:target="tag"
@savePopover="onOk"
:title="info.title"
>
<template v-slot:target-item>
<div @click="onClickTag(tag)" :id="tag">
<b-icon icon="tags-fill" font-scale="1"></b-icon>
{{ tagText }}
</div>
</template>
<template v-slot:body> <template v-slot:body>
<p>{{ info.detail }}</p> <p>{{ info.detail }}</p>
<form ref="form" @submit.stop.prevent="handleSubmit"> <form ref="form" @submit.stop.prevent="handleSubmit">
<b-form-group <b-form-group
:state="valueState"
label-for="name" label-for="name"
:invalid-feedback="$t('ID_PROCESS_IS_REQUIRED')" :invalid-feedback="$t('ID_PROCESS_IS_REQUIRED')"
> >
<vue-bootstrap-typeahead <multiselect
class="mb-4" v-model="info.selectedOption"
id="name" :options="users"
v-model="query" placeholder="Sselect one"
:minMatchingChars="minMatchingChars" label="USR_FULLNAME"
:data="users" track-by="USR_ID"
:serializer="(item) => item.USR_FULLNAME" :show-no-results="false"
@search-change="asyncFind"
:placeholder="info.placeholder" :loading="isLoading"
required id="ajax"
:state="valueState" :limit="10"
/> :clear-on-select="true"
>
</multiselect>
</b-form-group> </b-form-group>
</form> </form>
</template> </template>
@@ -40,41 +31,39 @@
<script> <script>
import SearchPopover from "./SearchPopover.vue"; import SearchPopover from "./SearchPopover.vue";
import VueBootstrapTypeahead from "vue-bootstrap-typeahead"; import Multiselect from "vue-multiselect";
import api from "./../../../api/index"; import api from "./../../../api/index";
export default { export default {
components: { components: {
SearchPopover, SearchPopover,
VueBootstrapTypeahead Multiselect
}, },
props: ["tag", "info"], props: ["tag", "info"],
data() { data() {
return { return {
minMatchingChars: 1,
query: "",
users: [], users: [],
valueState: null isLoading: false
}; };
}, },
computed: { methods: {
tagText: function() { /**
return `${this.$i18n.t('ID_USER')}: ${this.query}`; * Find asynchronously in the server
} * @param {string} query - string from the text field
}, */
watch: {
query(newQuery) { asyncFind(query) {
this.isLoading = true;
api.filters api.filters
.userValues(this.query) .userList(query)
.then((response) => { .then((response) => {
this.users = response.data; this.users = response.data;
this.isLoading = false;
}) })
.catch((e) => { .catch((e) => {
console.error(err); console.error(err);
}); });
} },
},
methods: {
/** /**
* Form validations review * Form validations review
*/ */
@@ -93,25 +82,16 @@ export default {
* Form submit handler * Form submit handler
*/ */
handleSubmit() { handleSubmit() {
// Exit when the form isn't valid this.$emit("updateSearchTag", {
if (!this.checkFormValidity()) { CurrentUser: {
return; selectedOption: this.info.selectedOption,
} userId: this.info.selectedOption.USR_ID
this.$nextTick(() => { }
let user = _.find(this.users, { USR_FULLNAME: this.query });
this.$emit("updateSearchTag", {
userId: user.USR_UID
});
this.$root.$emit("bv::hide::popover");
}); });
},
/**
* Cick tag event handler
*/
onClickTag() {
this.$root.$emit("bv::hide::popover"); this.$root.$emit("bv::hide::popover");
} }
} }
}; };
</script> </script>
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
<style scoped></style> <style scoped></style>

View File

@@ -1,5 +1,5 @@
<template> <template>
<div id=""> <div>
<SearchPopover :target="tag" @savePopover="onOk" :title="info.title"> <SearchPopover :target="tag" @savePopover="onOk" :title="info.title">
<template v-slot:body> <template v-slot:body>
<p>{{ info.detail }}</p> <p>{{ info.detail }}</p>
@@ -8,18 +8,18 @@
label-for="name" label-for="name"
:invalid-feedback="$t('ID_PROCESS_IS_REQUIRED')" :invalid-feedback="$t('ID_PROCESS_IS_REQUIRED')"
> >
<multiselect <multiselect
v-model="info.processOption" v-model="info.processOption"
:options="processes" :options="processes"
placeholder="Select one" placeholder="Select one"
label="PRO_TITLE" label="PRO_TITLE"
track-by="PRO_ID" track-by="PRO_ID"
:show-no-results="false" :show-no-results="false"
@search-change="asyncFind" @search-change="asyncFind"
:loading="isLoading" :loading="isLoading"
id="ajax" id="ajax"
:limit="10" :limit="10"
:clear-on-select="true" :clear-on-select="true"
> >
</multiselect> </multiselect>
</b-form-group> </b-form-group>
@@ -31,13 +31,13 @@
<script> <script>
import SearchPopover from "./SearchPopover.vue"; import SearchPopover from "./SearchPopover.vue";
import Multiselect from 'vue-multiselect' import Multiselect from "vue-multiselect";
import api from "./../../../api/index"; import api from "./../../../api/index";
export default { export default {
components: { components: {
SearchPopover, SearchPopover,
Multiselect, Multiselect
}, },
props: ["tag", "info"], props: ["tag", "info"],
data() { data() {
@@ -50,15 +50,15 @@ export default {
/** /**
* Find asynchronously in the server * Find asynchronously in the server
* @param {string} query - string from the text field * @param {string} query - string from the text field
*/ */
asyncFind (query) { asyncFind(query) {
this.isLoading = true this.isLoading = true;
api.filters api.filters
.processList(query) .processList(query)
.then((response) => { .then((response) => {
this.processes = response.data; this.processes = response.data;
this.countries = response this.countries = response;
this.isLoading = false this.isLoading = false;
}) })
.catch((e) => { .catch((e) => {
console.error(err); console.error(err);
@@ -82,13 +82,13 @@ export default {
* Form submit handler * Form submit handler
*/ */
handleSubmit() { handleSubmit() {
this.$emit("updateSearchTag", { this.$emit("updateSearchTag", {
ProcessName: { ProcessName: {
processOption: this.info.processOption, processOption: this.info.processOption,
process: this.info.processOption.PRO_ID process: this.info.processOption.PRO_ID,
} }
}); });
this.$root.$emit("bv::hide::popover"); this.$root.$emit("bv::hide::popover");
} }
} }
}; };

View File

@@ -361,15 +361,15 @@ export default {
}; };
_.forEach(response, (v) => { _.forEach(response, (v) => {
data.push({ data.push({
title: v.name, title: this.$i18n.t(v.id),
counter: v.count, counter: v.counter,
item: v.item, item: v.item,
icon: info[v.item].icon, icon: info[v.id].icon,
onClick: (obj) => { onClick: (obj) => {
that.filterHeader = obj.item; that.filterHeader = obj.item;
that.$refs["vueTable"].getData(); that.$refs["vueTable"].getData();
}, },
class: info[v.item].class, class: info[v.id].class,
}); });
}); });
return data; return data;