diff --git a/src/components/Widgets/TaskPropertiesWidget/Messages.js b/src/components/Widgets/TaskPropertiesWidget/Messages.js index e02e33ff8..f6f6af0f6 100644 --- a/src/components/Widgets/TaskPropertiesWidget/Messages.js +++ b/src/components/Widgets/TaskPropertiesWidget/Messages.js @@ -18,4 +18,14 @@ export default defineMessages({ id: "Widgets.TaskPropertiesWidget.task.label", defaultMessage: "Task {taskId}", }, + + expandAll: { + id: "Widgets.TaskPropertiesWidget.expandAll", + defaultMessage: "Expand All", + }, + + collapseAll: { + id: "Widgets.TaskPropertiesWidget.collapseAll", + defaultMessage: "Collapse All", + }, }) diff --git a/src/components/Widgets/TaskPropertiesWidget/TaskPropertiesWidget.jsx b/src/components/Widgets/TaskPropertiesWidget/TaskPropertiesWidget.jsx index c74691638..f3d23a152 100644 --- a/src/components/Widgets/TaskPropertiesWidget/TaskPropertiesWidget.jsx +++ b/src/components/Widgets/TaskPropertiesWidget/TaskPropertiesWidget.jsx @@ -1,4 +1,4 @@ -import { Component } from 'react' +import React, { useState } from 'react' import { FormattedMessage } from 'react-intl' import _get from 'lodash/get' import _map from 'lodash/map' @@ -19,45 +19,91 @@ const descriptor = { defaultHeight: 6, } -export default class TaskPropertiesWidget extends Component { - render() { - const taskList = _get(this.props.taskBundle, 'tasks') || [this.props.task] - const propertyLists = _map(taskList, (task) => { - const featurePropertiesList = AsMappableTask(task).osmFeatureProperties(this.props.osmElements) - - return ( -
-
- -
- { - featurePropertiesList.map((feature, index) => { - return ( -
-
- {feature.properties?.id || feature.geometry?.type} -
- -
- ) - }) - } -
- ) - }) +const TaskPropertiesWidget = (props) => { + const taskList = _get(props.taskBundle, 'tasks') || [props.task]; + const initialCollapsedState = {}; + + taskList.forEach((task) => { + const featurePropertiesList = AsMappableTask(task).osmFeatureProperties(props.osmElements); + featurePropertiesList.forEach((_, index) => { + initialCollapsedState[`${task.id}-${index}`] = true; + }); + }); + + const [collapsed, setCollapsed] = useState(initialCollapsedState); + const [allCollapsed, setAllCollapsed] = useState(true); + + const toggleCollapseAll = () => { + const newCollapsedState = {}; + taskList.forEach((task) => { + const featurePropertiesList = AsMappableTask(task).osmFeatureProperties(props.osmElements); + featurePropertiesList.forEach((_, index) => { + newCollapsedState[`${task.id}-${index}`] = !allCollapsed; + }); + }); + setCollapsed(newCollapsedState); + setAllCollapsed(!allCollapsed); + } + + const toggleCollapse = (index) => { + setCollapsed(prevState => ({ + ...prevState, + [index]: !prevState[index], + })); + } + const propertyLists = _map(taskList, (task) => { + const featurePropertiesList = AsMappableTask(task).osmFeatureProperties(props.osmElements) return ( - } - > - {propertyLists} - +
+ { + featurePropertiesList.map((feature, index) => { + const featureIndex = `${task.id}-${index}`; + const isCollapsed = collapsed[featureIndex]; + return ( +
+
toggleCollapse(featureIndex)}> +
+
+ +
+ + {feature.properties?.id || feature.geometry?.type} + +
+
+ {isCollapsed ? '▼' : '▲'} +
+
+ {!isCollapsed && ( + + )} +
+ ) + }) + } +
) - } + }) + + return ( + } + rightHeaderControls={ +
+ {allCollapsed ? : } +
+ } + > + {propertyLists} +
+ ) } registerWidgetType(TaskPropertiesWidget, descriptor) + +export default TaskPropertiesWidget;