Skip to content

Commit

Permalink
refactor editable table to allow to reuse on other pages
Browse files Browse the repository at this point in the history
Signed-off-by: Tomás Castillo <[email protected]>
  • Loading branch information
tomrndom committed Jun 10, 2024
1 parent b80d721 commit 9bfc27f
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 336 deletions.
2 changes: 1 addition & 1 deletion src/actions/event-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,7 @@ export const normalizeBulkEvents = (entity) => {
id: e.id,
title: e.title,
selection_plan_id: e.selection_plan_id,
location_id: e.location.id,
location_id: e.location?.id || e.location_id,
start_date: e.start_date,
speakers: e.speakers,
end_date: e.end_date,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import React, { useState, useEffect } from "react";
import EditableTableHeading from "./EventsEditableTableHeading";
import EventsEditableTableRow from "./EventsEditableTableRow";
import EditableTableHeading from "./EditableTableHeading";
import EditableTableRow from "./EditableTableRow";
import ReactTooltip from "react-tooltip";
import {
getAllEventTypes,
getAllTrackCategory,
getAllLocations,
getAllSelectionPlans,
} from "../../../utils/summitUtils";
import T from "i18n-react/dist/i18n-react";

const defaults = {
Expand All @@ -18,28 +12,24 @@ const defaults = {
colWidth: "",
};

const EventsEditableTable = (props) => {
const EditableTable = (props) => {
const {
options,
columns,
currentSummit,
page,
events,
data,
handleSort,
updateEvents,
handleDeleteEvent,
updateData,
handleDeleteRow,
resetData,
} = props;
let tableClass = options.hasOwnProperty("className") ? options.className : "";
const [editButton, setEditButton] = useState(false);
const [editEnabled, setEditEnabled] = useState(false);
const [selected, setSelected] = useState([]);
const [selectAll, setSelectAll] = useState(false);
tableClass += options.actions?.edit ? " table-hover" : "";

const activityTypeOptions = getAllEventTypes(currentSummit);
const activtyCategoryOptions = getAllTrackCategory(currentSummit);
const selectionPlanOptions = getAllSelectionPlans(currentSummit);
tableClass += options.actions?.edit ? " table-hover" : "";

const getSortDir = (columnKey, columnIndex, sortCol, sortDir) => {
if (columnKey && columnKey === sortCol) {
Expand Down Expand Up @@ -75,39 +65,39 @@ const EventsEditableTable = (props) => {

useEffect(() => {
if (selectAll) {
setSelected(events);
setSelected(data);
setSelectAll(true);
} else {
setSelectAll(false);
setSelected([]);
}
}, [selectAll]);

const updateSelected = (event, checked) => {
let selectedEvent = event;
const eventIndex = selected.findIndex((s) => s.id === selectedEvent.id);
let exists = eventIndex !== -1;
const updateSelected = (row, checked) => {
let selectedRow = row;
const rowIndex = selected.findIndex((s) => s.id === selectedRow.id);
let exists = rowIndex !== -1;

if (checked) {
if (exists) {
// if already on selected list, replace with new data
const updatedSelected = Object.assign({}, selectedEvent);
const updatedSelected = Object.assign({}, selectedRow);
const newSelected = selected.slice();
newSelected[eventIndex] = updatedSelected;
newSelected[rowIndex] = updatedSelected;
setSelected(newSelected);
} else {
// append to list
setSelected((currSelected) => [...currSelected, selectedEvent]);
setSelected((currSelected) => [...currSelected, selectedRow]);
}
} else {
setSelected(selected.filter((se) => se.id !== selectedEvent.id));
setSelected(selected.filter((se) => se.id !== selectedRow.id));
}
};

const onUpdateEvents = (evt) => {
evt.stopPropagation();
evt.preventDefault();
updateEvents(currentSummit.id, selected);
updateData(currentSummit.id, selected);
resetState();
};

Expand Down Expand Up @@ -200,27 +190,24 @@ const EventsEditableTable = (props) => {
</thead>
<tbody>
{columns.length > 0 &&
events.map((event, i) => {
if (Array.isArray(event) && event.length !== columns.length) {
data.map((row, i) => {
if (Array.isArray(row) && row.length !== columns.length) {
console.warn(
`Data at row ${i} is ${event.length}. It should be ${columns.length}.`
`Data at row ${i} is ${row.length}. It should be ${columns.length}.`
);
return <tr key={"row_" + i} />;
}

return (
<tr role="row" key={`row_${event["id"]}`}>
<EventsEditableTableRow
event={event}
<tr role="row" key={`row_${row["id"]}`}>
<EditableTableRow
row={row}
currentSummit={currentSummit}
editEnabled={editEnabled}
selected={selected}
updateSelected={updateSelected}
selectAll={selectAll}
deleteEvent={handleDeleteEvent}
activityTypeOptions={activityTypeOptions}
activtyCategoryOptions={activtyCategoryOptions}
selectionPlanOptions={selectionPlanOptions}
deleteRow={handleDeleteRow}
columns={columns}
actions={options.actions}
/>
Expand All @@ -234,4 +221,4 @@ const EventsEditableTable = (props) => {
);
};

export default EventsEditableTable;
export default EditableTable;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import PropTypes from "prop-types";

const EventsEditableTableHeading = (props) => {
const EditableTableHeading = (props) => {
const {
editEnabled,
sortable,
Expand Down Expand Up @@ -41,7 +41,7 @@ const EventsEditableTableHeading = (props) => {
);
};

EventsEditableTableHeading.propTypes = {
EditableTableHeading.propTypes = {
onSort: PropTypes.func,
sortDir: PropTypes.number,
columnIndex: PropTypes.number,
Expand All @@ -50,4 +50,4 @@ EventsEditableTableHeading.propTypes = {
sortFunc: PropTypes.func,
};

export default EventsEditableTableHeading;
export default EditableTableHeading;
121 changes: 121 additions & 0 deletions src/components/tables/editable-table/EditableTableRow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import React, { useEffect, useState } from "react";
import { Input } from "openstack-uicore-foundation/lib/components";
import T from "i18n-react/dist/i18n-react";
import history from "../../../history";

const EditableTableRow = (props) => {
const {
row,
columns,
editEnabled,
selected,
updateSelected,
deleteRow,
selectAll,
currentSummit,
actions,
} = props;
const [checked, setChecked] = useState(false);
const [editData, setEditData] = useState(row);

useEffect(() => {
updateSelected(editData, checked);
}, [checked, row]);
useEffect(() => {
setChecked(selectAll);
}, [selectAll]);
useEffect(() => {
if (selected.length === 0) {
setChecked(false);
}
}, [selected]);
useEffect(() => {
updateSelected(editData, checked);
}, [editData])
useEffect(() => {
if (!editEnabled) {
setEditData(row);
}
}, [editEnabled]);

const onRowChange = (ev) => {
const {value, id, type} = ev.target;
if(type === 'speakerinput') {
const newSpeakers = {...editData, [id]: [...row[id], value]};
setEditData(newSpeakers);
} else {
const newEventData = {...editData, [id]: value };
setEditData(newEventData);
}

};

const onRemoveOption = (rowId, id) => {
const newOptions = row[id].filter(s => s.id !== rowId);
const newEventData = {...editData, [id]: newOptions};
setEditData(newEventData);
};

return (
<>
<td className="bulk-edit-col-checkbox">
<input
type="checkbox"
onChange={() => setChecked(!checked)}
checked={checked}
/>
</td>
<td className="bulk-edit-col-id">{row.id}</td>
{selected.find((s) => s.id === row.id) && editEnabled && checked ? (
<>
{columns.map((col, index) => {
if(col.columnKey === "id") {
return;
}
else if(col.editableField === true) {
// Default field as text
return (
<td key={`row-edit-${col.columnKey}-${index}`} className="bulk-edit-col">
<Input
type="text"
id={col.columnKey}
placeholder={T.translate(
`bulk_actions_page.placeholders.${col.columnKey}`
)}
onChange={onRowChange}
value={row[col.columnKey]}
/>
</td>
)}
else if (col.editableField) {
return (
<td key={`row-edit-${col.columnKey}-${index}`} className="bulk-edit-col">
{col.editableField({value: "", placeholder: row[col.columnKey].name, onChange: onRowChange, rowData: editData[col.columnKey], onRemoveOption: onRemoveOption})}
</td>
)
}
else {return (<td key={`row-edit-${col.columnKey}-${index}`} className="bulk-edit-col">{row[col.columnKey]}</td>)}
})}
</>
) : columns.map((col, i) =>
col.columnKey !== "id" && <td key={`${row.id}${i}`}>{col.render ? col.render(row[col.columnKey]) : row[col.columnKey]}</td>)
}
{(actions.edit || actions.delete) && (
<td className="action-display-tc">
{actions.edit && (
<span onClick={() => history.push(`/app/summits/${currentSummit.id}/events/${row.id}`)}>
<i className="fa fa-pencil-square-o edit-icon"></i>
</span>
)}
{actions.delete && (
<span onClick={() => deleteRow(row.id)}>
<i className="fa fa-trash-o delete-icon"></i>
</span>
)}
</td>
)}
</>
);
};

export default EditableTableRow;
Loading

0 comments on commit 9bfc27f

Please sign in to comment.