Skip to content

Commit 320871e

Browse files
Searchsetting-like-macos
1 parent ad06e85 commit 320871e

File tree

9 files changed

+466
-2
lines changed

9 files changed

+466
-2
lines changed

packages/volto/news/news.internal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Introduces a global search for Control Panel settings, not just control panel names. @Manik-Khajuria-5

packages/volto/src/actions/controlpanels/controlpanels.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ import {
1111
UPDATE_CONTROLPANEL,
1212
SYSTEM_INFORMATION,
1313
DATABASE_INFORMATION,
14+
GET_CONTROLPANEL_SCHEMAS,
1415
} from '@plone/volto/constants/ActionTypes';
1516
import { getSite } from '@plone/volto/actions/site/site';
17+
import { fetchControlpanelSchemas } from '@plone/volto/components/manage/Controlpanels/utils';
1618

1719
/**
1820
* Get controlpanel function.
@@ -121,3 +123,20 @@ export function getDatabaseInformation() {
121123
},
122124
};
123125
}
126+
127+
export function getControlpanelSchemas(ids) {
128+
return async (dispatch, getState) => {
129+
const currentSchemas = getState().controlpanels?.schemas || {};
130+
131+
const schemasObject = await fetchControlpanelSchemas(
132+
ids,
133+
currentSchemas,
134+
dispatch,
135+
);
136+
137+
return dispatch({
138+
type: `${GET_CONTROLPANEL_SCHEMAS}_SUCCESS`,
139+
result: schemasObject,
140+
});
141+
};
142+
}
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/**
2+
* @module components/manage/Controlpanels/utils
3+
*/
4+
5+
import { getControlpanel } from '@plone/volto/actions/controlpanels/controlpanels';
6+
import last from 'lodash/last';
7+
8+
/**
9+
* @function fetchControlpanelSchemas
10+
* @param {Array<string>} ids
11+
* @param {Object} currentSchemas
12+
* @param {Function} dispatch
13+
* @returns {Promise<Object>}
14+
*/
15+
16+
export async function fetchControlpanelSchemas(ids, currentSchemas, dispatch) {
17+
const idsToFetch = ids.filter((id) => !currentSchemas[id]);
18+
19+
if (idsToFetch.length === 0) {
20+
return {};
21+
}
22+
23+
const schemaPromises = idsToFetch.map(async (id) => {
24+
try {
25+
const result = await dispatch(getControlpanel(id));
26+
return { panelId: id, schema: result };
27+
} catch (error) {
28+
error.panelId = id;
29+
return { panelId: id, schema: null, error };
30+
}
31+
});
32+
33+
const schemaResults = await Promise.allSettled(schemaPromises);
34+
35+
const schemasObject = {};
36+
schemaResults.forEach((result) => {
37+
if (result.status === 'fulfilled') {
38+
const { panelId, schema } = result.value;
39+
if (schema) {
40+
schemasObject[panelId] = schema;
41+
}
42+
}
43+
});
44+
45+
return schemasObject;
46+
}
47+
48+
/**
49+
* @function searchSchemaFields
50+
* @param {Object} schema
51+
* @param {string} query
52+
* @param {string} schemaId
53+
* @returns {Array}
54+
*/
55+
function searchSchemaFields(schema, query, schemaId) {
56+
if (
57+
!schema ||
58+
typeof schema !== 'object' ||
59+
!query ||
60+
query.trim().length < 2
61+
) {
62+
return [];
63+
}
64+
65+
const actualSchema = schema.schema || schema;
66+
const panelTitle = (schema.title || schema.id).toLowerCase().trim();
67+
const searchTerm = query.trim().toLowerCase();
68+
const matches = [];
69+
const properties = actualSchema.properties || {};
70+
const fieldsets = actualSchema.fieldsets || [];
71+
72+
fieldsets.forEach((fieldset) => {
73+
const fieldsetFeilds = fieldset.fields;
74+
75+
fieldsetFeilds.forEach((fieldName) => {
76+
if (typeof fieldName !== 'string') {
77+
return;
78+
}
79+
80+
const fieldNameLower = fieldName.toLowerCase();
81+
let isMatch = fieldNameLower.includes(searchTerm);
82+
isMatch = isMatch || panelTitle.includes(searchTerm);
83+
84+
const fieldProperty = properties[fieldName];
85+
let matchedValue = fieldName;
86+
87+
if (fieldProperty) {
88+
const title = fieldProperty.title || '';
89+
const description = fieldProperty.description || '';
90+
91+
if (title.toLowerCase().includes(searchTerm)) {
92+
isMatch = true;
93+
matchedValue = title;
94+
} else if (description.toLowerCase().includes(searchTerm)) {
95+
isMatch = true;
96+
matchedValue = description;
97+
} else if (isMatch) {
98+
matchedValue = title || fieldName;
99+
}
100+
}
101+
102+
if (isMatch) {
103+
matches.push({
104+
id: `${schemaId}-${fieldName}`,
105+
title: fieldName.toUpperCase().replace(/_/g, ' '),
106+
key: fieldName.replace(/_/g, ' '),
107+
value: matchedValue,
108+
url: `/controlpanel/${schemaId}#${fieldName}`,
109+
schemaId,
110+
});
111+
}
112+
});
113+
});
114+
115+
return matches;
116+
}
117+
118+
/**
119+
* @function searchSettings
120+
* @param {Array} controlpanels
121+
* @param {Object} schemas
122+
* @param {string} query
123+
* @returns {Array}
124+
*/
125+
126+
export function searchSettings(controlpanels, schemas, query) {
127+
if (!query || query.trim().length < 2) {
128+
return [];
129+
}
130+
131+
const groupedMatches = {};
132+
133+
for (const panel of controlpanels) {
134+
const panelId = last(panel['@id']?.split('/')) || panel.id;
135+
const schema = schemas[panelId];
136+
137+
if (!schema) {
138+
continue;
139+
}
140+
141+
const matches = searchSchemaFields(schema, query, panelId);
142+
143+
if (matches.length > 0) {
144+
if (!groupedMatches[panelId]) {
145+
groupedMatches[panelId] = {
146+
title: panel.title || panelId,
147+
group: panel.group || '',
148+
panelId,
149+
url: `/controlpanel/${panelId}`,
150+
matches: [],
151+
};
152+
}
153+
154+
matches.forEach((match) => {
155+
groupedMatches[panelId].matches.push({
156+
key: match.key,
157+
value: match.value,
158+
title: match.title,
159+
url: match.url,
160+
});
161+
});
162+
}
163+
}
164+
165+
return Object.values(groupedMatches);
166+
}

0 commit comments

Comments
 (0)