Skip to content

Commit

Permalink
introduce groups filter
Browse files Browse the repository at this point in the history
  • Loading branch information
allyoucanmap committed Jan 24, 2025
1 parent 6dc5ad6 commit b784bf2
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 49 deletions.
2 changes: 1 addition & 1 deletion web/client/plugins/ResourcesCatalog/ResourceDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ function ResourceDetails({
"type": "boolean",
"labelId": "resourcesCatalog.columnFeatured",
"path": "attributes.featured",
"disableIf": "{!state('resourceCanEdit')}",
"disableIf": "{state('userrole') !== 'ADMIN'}",
"editable": true
}
]
Expand Down
8 changes: 6 additions & 2 deletions web/client/plugins/ResourcesCatalog/ResourcesFiltersForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,18 @@ function ResourcesFiltersForm({
{
id: 'context',
labelId: 'resourcesCatalog.contextsFilter',
type: 'filter',
disableIf: '{state("userrole") !== "ADMIN"}'
type: 'filter'
}
]
},
{
type: 'divider'
},
{
type: 'select',
facet: "group",
disableIf: '{!state("userrole")}'
},
{
type: 'select',
facet: "context"
Expand Down
81 changes: 68 additions & 13 deletions web/client/plugins/ResourcesCatalog/api/__tests__/resources-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ describe('resources api', () => {
},
{
"CATEGORY": { "operator": "EQUAL_TO", "name": "GEOSTORY" }
},
{
"CATEGORY": { "operator": "EQUAL_TO", "name": "CONTEXT" }
}
]
}
Expand Down Expand Up @@ -80,16 +83,62 @@ describe('resources api', () => {
});
expect(json).toEqual({
"AND": {
"FIELD": { "field": "NAME", "operator": "ILIKE", "value": "%A%" },
"FIELD": [
{
"field": "NAME",
"operator": "ILIKE",
"value": "%A%"
},
{
"field": "CREATION",
"operator": "GREATER_THAN_OR_EQUAL_TO",
"value": "2025-01-22T00:00:00"
},
{
"field": "CREATION",
"operator": "LESS_THAN_OR_EQUAL_TO",
"value": "2025-01-24T23:59:59"
},
{
"field": "LASTUPDATE",
"operator": "GREATER_THAN_OR_EQUAL_TO",
"value": "2025-01-22T00:00:00"
},
{
"field": "LASTUPDATE",
"operator": "LESS_THAN_OR_EQUAL_TO",
"value": "2025-01-24T23:59:59"
}
],
"ATTRIBUTE": { "name": "featured", "operator": "EQUAL_TO", "type": "STRING", "value": "true" },
"OR": {
"AND": {
"CATEGORY": { "operator": "EQUAL_TO", "name": "MAP" },
"OR": {
"ATTRIBUTE": { "name": "context", "operator": "EQUAL_TO", "type": "STRING", "value": "contextName" }
"GROUP": {
"operator": 'IN',
"names": "group01"
},
"OR": [
{
"AND": {
"CATEGORY": { "operator": "EQUAL_TO", "name": "MAP" },
"OR": {
"ATTRIBUTE": { "name": "context", "operator": "EQUAL_TO", "type": "STRING", "value": "contextName" }
}
}
},
{
"FIELD": [
{
"field": "CREATOR",
"operator": "EQUAL_TO",
"value": "admin"
},
{
"field": "CREATOR",
"operator": "EQUAL_TO",
"value": "creator"
}
]
}
}
]
}
});
} catch (e) {
Expand All @@ -104,13 +153,19 @@ describe('resources api', () => {
});
requestResources({
params: {
page: 2,
pageSize: 24,
f: ['map', 'featured'],
q: 'A',
'filter{ctx.in}': ['contextName']
'page': 2,
'pageSize': 24,
'f': ['map', 'featured', 'my-resources'],
'q': 'A',
'filter{ctx.in}': ['contextName'],
'filter{group.in}': ['group01'],
'filter{creator.in}': ['creator'],
'filter{creation.gte}': '2025-01-22T00:00:00',
'filter{creation.lte}': '2025-01-24T23:59:59',
'filter{lastUpdate.gte}': '2025-01-22T00:00:00',
'filter{lastUpdate.lte}': '2025-01-24T23:59:59'
}
})
}, { user: { name: 'admin' } })
.then((response) => {
expect(response).toEqual({
total: 0,
Expand Down
49 changes: 48 additions & 1 deletion web/client/plugins/ResourcesCatalog/api/resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import { searchListByAttributes, getResource } from '../../../observables/geostore';
import { castArray } from 'lodash';
import isString from 'lodash/isString';
import GeoStoreDAO from '../../../api/GeoStoreDAO';

const splitFilterValue = (value) => {
const parts = value.split(':');
Expand All @@ -29,6 +30,7 @@ const getFilter = ({
const ctx = castArray(query['filter{ctx.in}'] || []);
const categories = ['MAP', 'DASHBOARD', 'GEOSTORY', 'CONTEXT'];
const creators = castArray(query['filter{creator.in}'] || []);
const groups = castArray(query['filter{group.in}'] || []);
const categoriesFilters = categories.filter(category => f.includes(category.toLocaleLowerCase()));
const associatedContextFilters = ctx.map((ctxValue) => {
const { value } = splitFilterValue(ctxValue);
Expand Down Expand Up @@ -76,10 +78,17 @@ const getFilter = ({
value: [true]
}] : [])
],
...(groups.length && {
GROUP: [
{
operator: ['IN'],
names: groups
}
]
}),
OR: [
{
AND: categories
.filter(name => name !== 'CONTEXT' || name === 'CONTEXT' && user?.role === 'ADMIN')
.map(name => {
return (
!categoriesFilters.length && !associatedContextFilters.length
Expand Down Expand Up @@ -279,6 +288,44 @@ export const facets = [
};
});
}
},
{
id: 'group',
type: 'select',
labelId: 'resourcesCatalog.groups',
key: 'filter{group.in}',
getLabelValue: (item) => {
return item.value;
},
getFilterByField: (field, value) => {
return { label: value, value };
},
loadItems: ({ params, config }) => {
const { page, pageSize, q } = params;
return GeoStoreDAO.getGroups(q ? `*${q}*` : '*', {
...config,
params: {
start: parseFloat(page) * pageSize,
limit: pageSize,
all: true
}
})
.then((response) => {
const groups = castArray(response?.ExtGroupList?.Group).map((item) => {
return {
...item,
filterValue: item.groupName,
value: item.groupName,
label: `${item.groupName}`
};
});
const totalCount = response?.ExtGroupList?.GroupCount;
return {
items: groups,
isNextPageAvailable: (page + 1) < (totalCount / pageSize)
};
});
}
}
];

Expand Down
15 changes: 10 additions & 5 deletions web/client/plugins/ResourcesCatalog/components/FilterGroup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const Title = ({
};

const FilterGroup = ({
items,
items: itemsProp,
loadItems,
title,
titleId,
Expand All @@ -43,11 +43,13 @@ const FilterGroup = ({
}) => {
const isMounted = useIsMounted();

const [groupItems, setGroupItems] = useState(items);
const [groupItems, setGroupItems] = useState(itemsProp);
const [loading, setLoading] = useState(false);

const shouldRequestItems = loadItems && typeof loadItems === 'function';

useEffect(() => {
if (loadItems && typeof loadItems === 'function') {
if (shouldRequestItems) {
if (!loading) {
setLoading(true);
loadItems({ page_size: 999999 })
Expand All @@ -57,7 +59,10 @@ const FilterGroup = ({
.finally(()=> isMounted(() => setLoading(false)));
}
}
}, [JSON.stringify(query)]);
}, [JSON.stringify(query), shouldRequestItems]);

// avoid to use groupItems when not async to get the latest updated items
const items = shouldRequestItems ? groupItems : itemsProp;

return (
<FlexBox classNames={['ms-filter-group']} column gap="sm">
Expand All @@ -69,7 +74,7 @@ const FilterGroup = ({
<FlexBox column gap="sm" classNames={root ? ['_padding-l-sm'] : []}>
{loading ?
<Message msgId={loadingItemsMsgId}/>
: !isEmpty(groupItems) ? content(groupItems)
: !isEmpty(items) ? content(items)
: !loading ? <Message msgId={noItemsMsgId}/> : null
}
</FlexBox>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,18 @@ import Icon from '../components/Icon';
import Message from '../../../components/I18N/Message';
import useIsMounted from '../hooks/useIsMounted';
import Spinner from '../components/Spinner';
import { castArray } from 'lodash';

function ResourcePermissions({
editing,
user,
resource,
onChange
}) {

const [availableGroups, setGroups] = useState([]);
const [loading, setLoading] = useState(false);
const init = useRef(false);
const isMounted = useIsMounted();

useEffect(() => {
GeoStoreDAO.getAvailableGroups(user)
.then((response) => isMounted(() => {
setGroups(response);
}));
}, [user]);

useEffect(() => {
if (resource?.permissions === undefined && !init.current) {
init.current = true;
Expand Down Expand Up @@ -128,11 +120,33 @@ function ResourcePermissions({
{
id: 'group',
labelId: 'resourcesCatalog.groups',
request: ({ q }) => {
return Promise.resolve(availableGroups.filter(group => (group?.groupName || '').toLowerCase().includes(q.toLowerCase())));
request: ({ q, page: pageParam, pageSize }) => {
const page = pageParam - 1;
return GeoStoreDAO.getGroups(q ? `*${q}*` : '*', {
params: {
start: parseFloat(page) * pageSize,
limit: pageSize,
all: true
}
})
.then((response) => {
const groups = castArray(response?.ExtGroupList?.Group).map((item) => {
return {
...item,
filterValue: item.groupName,
value: item.groupName,
label: `${item.groupName}`
};
});
const totalCount = response?.ExtGroupList?.GroupCount;
return {
groups,
isNextPageAvailable: (page + 1) < (totalCount / pageSize)
};
});
},
responseToEntries: ({ response, entries }) => {
return response.map((group) => {
return response.groups.map((group) => {
const permissions = (entries || []).find(entry => entry.id === group.id)?.permissions;
return {
type: 'group',
Expand Down
2 changes: 1 addition & 1 deletion web/client/reducers/__tests__/context-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('context reducer', () => {
it('loadContext', () => {
const CONTEXT = {};
const state = stateMocker(setContext(CONTEXT));
expect(currentContextSelector(state)).toBe(CONTEXT);
expect(currentContextSelector(state)).toEqual(CONTEXT);
});
it('setResource', () => {
const RESOURCE = {};
Expand Down
2 changes: 1 addition & 1 deletion web/client/selectors/__tests__/context-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import CONTEXT_SHORT_RESOURCE from '../../test-resources/geostore/resources/reso
const stateMocker = createStateMocker({context});
describe('context selectors', () => {
it('currentContextSelector', () => {
expect(currentContextSelector(stateMocker(setContext(CONTEXT_DATA)))).toBe(CONTEXT_DATA);
expect(currentContextSelector(stateMocker(setContext(CONTEXT_DATA)))).toEqual(CONTEXT_DATA);
});
it('contextMonitoredStateSelector', () => {
expect(contextMonitoredStateSelector(stateMocker())).toBe('{}');
Expand Down
28 changes: 15 additions & 13 deletions web/client/utils/ContextCreatorUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,20 @@ export const migrateContextConfiguration = (context) => {
};
return {
...context,
plugins: Object.fromEntries(Object.keys(context.plugins)
.map((key) => {
const plugins = context.plugins[key];
return [key, plugins.map((plugin) => {
if (changedPluginsNames[plugin.name]) {
return {
...plugin,
name: changedPluginsNames[plugin.name]
};
}
return plugin;
})];
}))
...(context?.plugins && {
plugins: Object.fromEntries(Object.keys(context.plugins)
.map((key) => {
const plugins = context.plugins[key];
return [key, plugins.map((plugin) => {
if (changedPluginsNames[plugin.name]) {
return {
...plugin,
name: changedPluginsNames[plugin.name]
};
}
return plugin;
})];
}))
})
};
};

0 comments on commit b784bf2

Please sign in to comment.