Skip to content

Commit d1bb2fd

Browse files
committed
rework single keyword view to use search endpoint
1 parent f17560d commit d1bb2fd

3 files changed

Lines changed: 68 additions & 42 deletions

File tree

backend/src/kitconcept/keywordmanager/services/get.py

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,21 @@
22
from plone.restapi.batching import HypermediaBatch
33
from plone.restapi.services import Service
44
from zope.component import getUtility
5-
from zope.interface import implementer
6-
from zope.publisher.interfaces import IPublishTraverse
75

86

9-
@implementer(IPublishTraverse)
107
class KeywordsGet(Service):
118
"""/@keywords Endpoint."""
129

13-
def __init__(self, context, request):
14-
super().__init__(context, request)
15-
self.context = context
16-
self.request = request
17-
self.params = []
18-
19-
def publishTraverse(self, request, name):
20-
# Consume any path segments after /@keywords as parameters
21-
self.params.append(name)
22-
return self
23-
2410
def reply(self):
2511
km = getUtility(IKeywordManager)
2612
query = {"withLengths": True}
2713
if idx := self.request.form.get("idx"):
2814
query["indexName"] = idx
2915

30-
if len(self.params) == 0:
31-
keywords = km.getKeywords(**query)
32-
else:
33-
keywords = km.getKeyword(self.params[0])
16+
keywords = km.getKeywords(**query)
3417

3518
batch = HypermediaBatch(self.request, keywords)
36-
if len(self.params) == 0:
37-
items = [{"name": name, "total": count} for name, count in batch]
38-
else:
39-
items = list(batch)
19+
items = [{"name": name, "total": count} for name, count in batch]
4020

4121
keywords_data = {
4222
"@id": batch.canonical_url,

frontend/packages/volto-keywordmanager/src/actions/keywords.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@ import { UPDATE_KEYWORDS } from 'volto-keywordmanager/constants/Keywords';
33
import { DELETE_KEYWORDS } from 'volto-keywordmanager/constants/Keywords';
44

55
export function getKeywords({
6-
id = null,
76
index = null,
87
groupKeywords = false,
98
batchSize = 25,
109
batchStart = 0,
1110
}: {
12-
id?: string | null;
1311
index?: string | null;
1412
groupKeywords?: boolean;
1513
batchSize?: number;
@@ -27,10 +25,6 @@ export function getKeywords({
2725

2826
let requestPath = '/@keywords';
2927

30-
if (id) {
31-
requestPath += `/${id}`;
32-
}
33-
3428
if (params) {
3529
requestPath += `?${params.toString()}`;
3630
}

frontend/packages/volto-keywordmanager/src/components/Keyword.tsx

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
1-
import { Spinner } from '@plone/components';
1+
import { Spinner, Table, Button } from '@plone/components';
22
import Toolbar from '@plone/volto/components/manage/Toolbar/Toolbar';
33
import Icon from '@plone/volto/components/theme/Icon/Icon';
4-
import { useEffect } from 'react';
4+
import { useEffect, useState } from 'react';
55
import { createPortal } from 'react-dom';
66
import { useDispatch } from 'react-redux';
77
import { getParentUrl } from '@plone/volto/helpers/Url/Url';
88
import { useSelector } from 'react-redux';
99
import { Link, useParams } from 'react-router-dom';
10-
import { getKeywords } from 'volto-keywordmanager/actions/keywords';
10+
import { searchContent } from '@plone/volto/actions/search/search';
1111
import Error from '@plone/volto/components/theme/Error/Error';
1212
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
1313
import { useClient } from '@plone/volto/hooks';
14+
import { deleteKeywords } from 'volto-keywordmanager/actions/keywords';
1415

1516
import backSVG from '@plone/volto/icons/back.svg';
17+
import trashSVG from '@plone/volto/icons/delete.svg';
1618

1719
const messages = defineMessages({
1820
back: {
@@ -23,9 +25,17 @@ const messages = defineMessages({
2325
id: 'loading',
2426
defaultMessage: 'Loading',
2527
},
26-
keyword: {
27-
id: 'Keyword',
28-
defaultMessage: 'Keyword',
28+
title: {
29+
id: 'title',
30+
defaultMessage: 'Title',
31+
},
32+
path: {
33+
id: 'path',
34+
defaultMessage: 'Path',
35+
},
36+
actions: {
37+
id: 'actions',
38+
defaultMessage: 'Actions',
2939
},
3040
});
3141

@@ -34,19 +44,27 @@ const KeywordView = (props) => {
3444
const params = useParams<{ id: string }>();
3545
const id = params.id;
3646
const intl = useIntl();
37-
const keywords = useSelector((state) => state.keywords);
47+
const keywords = useSelector((state) => state.search.subrequests.keywords);
3848
const dispatch = useDispatch();
3949
const isClient = useClient();
4050
const pathname = location.pathname;
41-
const options = {
42-
id: id,
43-
};
51+
const [selectedKeys, setSelectedKeys] = useState<string | Set<string>>(
52+
new Set(),
53+
);
4454

4555
useEffect(() => {
46-
dispatch(getKeywords(options));
56+
dispatch(searchContent('/', { Subject: [id] }, 'keywords'));
4757
}, []);
4858

49-
if (keywords.loading) {
59+
const handleDeleteKeywords = async (kw: string | string[]) => {
60+
if (typeof kw == 'string') {
61+
kw = [kw];
62+
}
63+
await dispatch(deleteKeywords({ items: kw }));
64+
await dispatch(searchContent('/', { Subject: [id] }, 'keywords'));
65+
};
66+
67+
if (keywords?.loading) {
5068
return <Spinner label={intl.formatMessage(messages.loading)} />;
5169
}
5270

@@ -55,8 +73,42 @@ const KeywordView = (props) => {
5573
}
5674

5775
return (
58-
<>
76+
<div
77+
id="page-keyword_manager"
78+
className="ui container controlpanel-keyword-manager"
79+
>
5980
<h1>Hello world</h1>
81+
<Table
82+
className="react-aria-Table cmsui-table"
83+
columns={[
84+
{
85+
id: 'title',
86+
name: intl.formatMessage(messages.title),
87+
isRowHeader: true,
88+
},
89+
{
90+
id: 'path',
91+
name: intl.formatMessage(messages.path),
92+
},
93+
{
94+
id: 'actions',
95+
name: intl.formatMessage(messages.actions),
96+
},
97+
]}
98+
rows={keywords?.items?.map((item) => ({
99+
id: item['@id'],
100+
textValue: item.title,
101+
title: <p>{item.title}</p>,
102+
path: <p>{item['@id']}</p>,
103+
actions: (
104+
<Button onPress={() => handleDeleteKeywords(item['@id'])}>
105+
<Icon name={trashSVG} size="20px" />
106+
</Button>
107+
),
108+
}))}
109+
selectionMode="multiple"
110+
onSelectionChange={setSelectedKeys}
111+
/>
60112
{isClient &&
61113
createPortal(
62114
<Toolbar
@@ -75,7 +127,7 @@ const KeywordView = (props) => {
75127
/>,
76128
document.getElementById('toolbar') as HTMLElement,
77129
)}
78-
</>
130+
</div>
79131
);
80132
};
81133

0 commit comments

Comments
 (0)