diff --git a/assets/agenda/actions.ts b/assets/agenda/actions.ts index afb577ab5..4b586bf6d 100644 --- a/assets/agenda/actions.ts +++ b/assets/agenda/actions.ts @@ -399,6 +399,18 @@ export function fetchItem(id: any) { }; } +export function fetchItemsById(ids: Array): Promise> { + return server.get(`/agenda/search?ids=${ids.join(', ')}`); +} + +export function fetchItemsByIdToRedux(ids: string[]): (dispatch: any) => Promise { + return (dispatch: any) => { + return fetchItemsById(ids).then((response) => { + dispatch(recieveItem(response)); + }); + }; +} + export const WATCH_EVENTS = 'WATCH_EVENTS'; export function watchEvents(ids: any) { return (dispatch: any, getState: any) => { diff --git a/assets/agenda/components/AgendaPreviewEvent.tsx b/assets/agenda/components/AgendaPreviewEvent.tsx index 9cbee77ea..485e6b8aa 100644 --- a/assets/agenda/components/AgendaPreviewEvent.tsx +++ b/assets/agenda/components/AgendaPreviewEvent.tsx @@ -1,11 +1,10 @@ import * as React from 'react'; import {connect} from 'react-redux'; import classNames from 'classnames'; -import {get} from 'lodash'; import {gettext} from 'utils'; import {getName, getInternalNote} from '../utils'; -import {fetchItem} from '../actions'; +import {fetchItemsByIdToRedux} from '../actions'; import AgendaTime from './AgendaTime'; import AgendaListItemLabels from './AgendaListItemLabels'; @@ -15,10 +14,24 @@ import AgendaPreviewAttachments from './AgendaPreviewAttachments'; import AgendaTags from './AgendaTags'; import AgendaEdNote from './AgendaEdNote'; import AgendaInternalNote from './AgendaInternalNote'; +import {IAgendaItem} from 'interfaces'; -class AgendaPreviewEventComponent extends React.Component { - static propTypes: any; - constructor(props: any) { +interface AgendaPreviewEventProps { + item: { + event_ids: Array; + }; + itemsById: Record; + eventIds: string[]; + fetchItemsByIdToRedux: (ids: string[]) => Promise; +} + +interface AgendaPreviewEventState { + loading: boolean; + expandedEvents: Record; +} + +class AgendaPreviewEventComponent extends React.Component { + constructor(props: AgendaPreviewEventProps) { super(props); this.state = { @@ -34,24 +47,34 @@ class AgendaPreviewEventComponent extends React.Component { this.reloadEvent(); } - componentDidUpdate(prevProps: any) { - if (get(prevProps.item, 'event_ids') !== get(this.props.item, 'event_ids')) { + componentDidUpdate(prevProps: AgendaPreviewEventProps) { + if (prevProps.eventIds !== this.props.eventIds) { this.reloadEvent(); } } reloadEvent() { - const {item, fetchEvent} = this.props; - const eventIds = item.event_ids || []; - + const {eventIds, fetchItemsByIdToRedux} = this.props; + + if (eventIds == null || eventIds.length == 0) { + return; + } + + this.setState({loading: true}); - Promise.all(eventIds.map((id: string) => fetchEvent(id))) - .catch((error) => console.error('Failed to fetch events:', error)) - .finally(() => this.setState({loading: false})); + + fetchItemsByIdToRedux(eventIds) + .finally(() => { + this.setState({loading: false}); + }) + .catch((error) => { + console.error("Error fetching items:", error); + this.setState({loading: false}); + }); } toggleExpanded(eventId: string) { - this.setState((prevState: any) => ({ + this.setState((prevState) => ({ expandedEvents: { ...prevState.expandedEvents, [eventId]: !prevState.expandedEvents[eventId], @@ -59,24 +82,25 @@ class AgendaPreviewEventComponent extends React.Component { })); } - renderEvent(item: any) { - const isExpanded = this.state.expandedEvents[item.guid] || false; + renderEvent(item: IAgendaItem) { + const isExpanded = this.state.expandedEvents[item._id] || false; + return (
- this.toggleExpanded(item.guid)}> + this.toggleExpanded(item._id)}> -

this.toggleExpanded(item.guid)}>{getName(item)}

+

this.toggleExpanded(item._id)}>{getName(item)}

@@ -105,6 +129,8 @@ class AgendaPreviewEventComponent extends React.Component { } render() { + const {itemsById, eventIds} = this.props; + return (
@@ -112,7 +138,10 @@ class AgendaPreviewEventComponent extends React.Component { {this.state.loading ? (
) : ( - this.props.events.map((event: any) => this.renderEvent(event)) + eventIds + .map((id) => itemsById[id]) + .filter((event) => event != null) + .map((event) => this.renderEvent(event)) )}
@@ -120,15 +149,13 @@ class AgendaPreviewEventComponent extends React.Component { } } -const mapStateToProps = (state: any, ownProps: any) => { - const eventIds = ownProps.item.event_ids || []; - return { - events: eventIds.map((eventId: string) => state.itemsById[eventId]), - }; -}; +const mapStateToProps = (state: any, ownProps: any) => ({ + itemsById: state.itemsById, + eventIds: ownProps.item.event_ids || [], +}); const mapDispatchToProps = (dispatch: any) => ({ - fetchEvent: (eventId: string) => dispatch(fetchItem(eventId)), + fetchItemsByIdToRedux: (ids: string[]) => dispatch(fetchItemsByIdToRedux(ids)), }); export const AgendaPreviewEvent = connect(mapStateToProps, mapDispatchToProps)(AgendaPreviewEventComponent); diff --git a/assets/agenda/components/AgendaPreviewPlanning.tsx b/assets/agenda/components/AgendaPreviewPlanning.tsx index f140ba08e..29bd86ae9 100644 --- a/assets/agenda/components/AgendaPreviewPlanning.tsx +++ b/assets/agenda/components/AgendaPreviewPlanning.tsx @@ -3,7 +3,7 @@ import {connect} from 'react-redux'; import {gettext} from 'utils'; import {isPlanningItem} from '../utils'; -import {fetchItem} from '../actions'; +import {fetchItemsByIdToRedux} from '../actions'; import AgendaPreviewCoverages from './AgendaPreviewCoverages'; import {IAgendaItem, ICoverageItemAction, IUser, IAgendaPreviewConfig, IArticle, IAgendaState} from 'interfaces'; @@ -16,6 +16,7 @@ interface IOwnProps { restrictCoverageInfo?: boolean; previewConfig: IAgendaPreviewConfig; planningItems?: Array; + fetchItemsByIdToRedux: (ids: string[]) => Promise; } interface IReduxStateProps { @@ -53,18 +54,26 @@ class AgendaPreviewPlanningComponent extends React.Component { } fetchSecondaryPlanningItems() { - const {item, planningId} = this.props; + const {item, planningId, fetchItemsByIdToRedux} = this.props; const planningIds = item.planning_ids?.filter((id:string) => id !== planningId) || []; this.setState({loading: true}); - try { - Promise.all(planningIds.map((id: string) => fetchItem(id))); - } catch (error) { - console.error('Failed to fetch secondary planning items:', error); - } finally { - this.setState({loading: false}); + + if (planningIds == null || planningIds.length == 0) { + return; + } + + this.setState({loading: true}); + + fetchItemsByIdToRedux(planningIds) + .finally(() => { + this.setState({loading: false}); + }) + .catch((error) => { + console.error("Error fetching items:", error); + this.setState({loading: false}); + }); } - } toggleExpanded(planningItemId: string) { this.setState((prevState) => ({ @@ -153,7 +162,7 @@ class AgendaPreviewPlanningComponent extends React.Component {
- {gettext('Secondary Planning Items')} + {gettext('Related Planning Items')} {loading ? (
@@ -213,9 +222,13 @@ const mapStateToProps = (state: any, ownProps: any) => { }; }; +const mapDispatchToProps = (dispatch: any) => ({ + fetchItemsByIdToRedux: (ids: string[]) => dispatch(fetchItemsByIdToRedux(ids)), +}); + export const AgendaPreviewPlanning = connect< IReduxStateProps, {}, IOwnProps, IAgendaState ->(mapStateToProps)(AgendaPreviewPlanningComponent); +>(mapStateToProps, mapDispatchToProps)(AgendaPreviewPlanningComponent);