Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Organization new filters #239

Merged
merged 1 commit into from Nov 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
68 changes: 68 additions & 0 deletions frontend/src/modules/organization/organization-employees-field.js
@@ -0,0 +1,68 @@
import IntegerRangeField from '@/shared/fields/integer-range-field'

export default class OrganizationEmployeesField extends IntegerRangeField {
constructor(name, label, config = {}) {
super(name, label)

this.placeholder = config.placeholder
this.hint = config.hint
this.required = config.required
this.matches = config.matches
this.filterable = config.filterable || false
this.custom = config.custom || false
}

dropdownOptions() {
return [
{
value: [1, 10],
label: '1-10'
},
{
value: [11, 50],
label: '11-50'
},
{
value: [51, 200],
label: '51-200'
},
{
value: [201, 500],
label: '201-500'
},
{
value: [501, 1000],
label: '501-1000'
},
{
value: [1001, 5000],
label: '1001-5000'
},
{
value: [5001, 10000],
label: '5001-10000'
},
{
value: [10001, null],
label: '10001+'
}
]
}

forFilter() {
return {
name: this.name,
label: this.label,
custom: this.custom,
props: {
options: this.dropdownOptions(),
multiple: true
},
defaultValue: null,
value: null,
defaultOperator: 'between',
operator: 'between',
type: 'select'
}
}
}
@@ -0,0 +1,28 @@
import IntegerRangeField from '@/shared/fields/integer-range-field'

export default class OrganizationMemberCountField extends IntegerRangeField {
constructor(name, label, config = {}) {
super(name, label)

this.placeholder = config.placeholder
this.hint = config.hint
this.required = config.required
this.matches = config.matches
this.filterable = config.filterable || false
this.custom = config.custom || false
}

forFilter() {
return {
name: this.name,
label: this.label,
custom: this.custom,
props: {},
defaultValue: [],
value: [],
defaultOperator: 'between',
operator: 'between',
type: 'number'
}
}
}
14 changes: 14 additions & 0 deletions frontend/src/modules/organization/organization-model.js
Expand Up @@ -3,6 +3,8 @@ import IdField from '@/shared/fields/id-field'
import { GenericModel } from '@/shared/model/generic-model'
import DateTimeField from '@/shared/fields/date-time-field'
import StringField from '@/shared/fields/string-field'
import OrganizationMemberCountField from '@/modules/organization/organization-member-count-field'
import OrganizationEmployeesField from '@/modules/organization/organization-employees-field'

function label(name) {
return i18n(`entities.member.fields.${name}`)
Expand All @@ -20,6 +22,18 @@ const fields = {
updatedAt: new DateTimeField(
'updatedAt',
label('updatedAt')
),
members: new OrganizationMemberCountField(
'memberCount',
'# of members',
{ filterable: true }
),
employees: new OrganizationEmployeesField(
'employees',
'# of employees',
{
filterable: true
}
)
}

Expand Down
3 changes: 2 additions & 1 deletion frontend/src/shared/filter/components/filter-list-item.vue
Expand Up @@ -40,6 +40,7 @@
v-bind="filter.props"
v-model:value="model.value"
v-model:operator="model.operator"
:default-operator="filter.defaultOperator"
:is-expanded="filter.expanded"
/>
<div
Expand Down Expand Up @@ -231,7 +232,7 @@ const clickOutsideListener = (event) => {
// clicks outside
!(
component === event.target ||
component.contains(event.target) ||
component?.contains(event.target) ||
// we need the following condition to validate clicks
// on popovers that are not DOM children of this component,
// since popper is adding fixed components to the body directly
Expand Down
Expand Up @@ -3,13 +3,14 @@
class="filter-type-number filter-with-operator-and-input"
>
<app-inline-select-input
v-if="defaultOperator !== 'between'"
v-model="operator"
popper-placement="bottom-start"
prefix="Number:"
class="mb-2"
:options="computedOperatorOptions"
/>
<div class="flex -mx-1">
<div class="flex -mx-1 gap-2">
<el-input
ref="inputRef"
v-model="model"
Expand All @@ -21,7 +22,6 @@
operator === 'is_empty' ||
operator === 'is_not_empty'
"
class="mx-1"
></el-input>
<el-input
v-if="operator === 'between'"
Expand All @@ -32,7 +32,6 @@
operator === 'is_empty' ||
operator === 'is_not_empty'
"
class="mx-1"
></el-input>
</div>
</div>
Expand All @@ -59,6 +58,10 @@ const props = defineProps({
type: [Array, Number],
default: null
},
defaultOperator: {
type: String,
default: null
},
operator: {
type: String,
default: null
Expand Down Expand Up @@ -133,6 +136,7 @@ watch(expanded, async (newValue) => {
input[type='number']::-webkit-inner-spin-button,
input[type='number']::-webkit-outer-spin-button {
-webkit-appearance: none;
appearance: none;
margin: 0;
}
}
Expand Down
17 changes: 15 additions & 2 deletions frontend/src/shared/filter/helpers/build-api-payload.js
Expand Up @@ -91,9 +91,22 @@ function _buildAttributeBlock(attribute) {
}, [])
}
} else if (attribute.operator === 'between') {
// TODO: Chech if this exceptions is needed
const bottomLimit = attribute.value[0]
const topLimit = attribute.value[1]

rule = {
between: attribute.value
// Range from ... to
...(!!(topLimit && bottomLimit) && {
between: attribute.value
}),
// Range from ...
...(!!(bottomLimit && !topLimit) && {
gte: bottomLimit
}),
// Range ... to
...(!!(!bottomLimit && topLimit) && {
lte: topLimit
})
}
} else if (attribute.operator === null) {
rule = Array.isArray(attribute.value)
Expand Down