in frontend/src/services/OrderingService.ts [3:305]
function moveWidget(
widgets: Array<Widget>,
index: number,
newIndex: number
): Array<Widget> {
// If new position is out of bounds, don't move anything.
if (newIndex < 0 || newIndex >= widgets.length) {
if (newIndex == widgets.length && widgets[index].section) {
const widgetsCopy = widgets.map((widget) => ({
...widget,
}));
let widget = widgetsCopy[index];
let parent = widgetsCopy.find((w) => w.id === widget.section);
if (parent) {
widget.section = undefined;
parent.content.widgetIds = parent.content.widgetIds.filter(
(id: string) => id !== widget.id
);
}
return widgetsCopy;
}
return widgets;
}
// Create a new widgets array so we don't modify the one
// passed as parameter.
const reordered = widgets.map((widget) => ({
...widget,
}));
const originalIndex = index;
const originalNewIndex = newIndex;
let widget = reordered[index];
let neighbor = reordered[newIndex];
if (!widget.section && !neighbor.section) {
if (
widget.widgetType !== WidgetType.Section &&
neighbor.widgetType !== WidgetType.Section
) {
// Swap widget with neighbor
let oldPosition = widget.order;
let newPosition = neighbor.order;
widget.order = newPosition;
neighbor.order = oldPosition;
reordered[newIndex] = widget;
reordered[index] = neighbor;
} else if (
widget.widgetType === WidgetType.Section &&
neighbor.widgetType === WidgetType.Section
) {
if (index < newIndex) {
while (
neighbor.id === widgets[originalNewIndex].id ||
neighbor.section === widgets[originalNewIndex].id
) {
let oldPosition = widget.order;
let newPosition = neighbor.order;
widget.order = newPosition;
neighbor.order = oldPosition;
reordered[newIndex] = widget;
reordered[index] = neighbor;
index++;
newIndex++;
if (newIndex >= widgets.length) {
break;
}
widget = reordered[index];
neighbor = reordered[newIndex];
}
} else {
while (
widget.id === widgets[originalIndex].id ||
widget.section === widgets[originalIndex].id
) {
let oldPosition = widget.order;
let newPosition = neighbor.order;
widget.order = newPosition;
neighbor.order = oldPosition;
reordered[newIndex] = widget;
reordered[index] = neighbor;
index++;
newIndex++;
if (index >= widgets.length) {
break;
}
widget = reordered[index];
neighbor = reordered[newIndex];
}
}
} else if (widget.widgetType === WidgetType.Section && index > newIndex) {
while (
widget.id === widgets[originalIndex].id ||
widget.section === widgets[originalIndex].id
) {
let oldPosition = widget.order;
let newPosition = neighbor.order;
widget.order = newPosition;
neighbor.order = oldPosition;
reordered[newIndex] = widget;
reordered[index] = neighbor;
index++;
newIndex++;
if (index >= widgets.length) {
break;
}
widget = reordered[index];
neighbor = reordered[newIndex];
}
} else if (widget.widgetType === WidgetType.Section && index < newIndex) {
// Swap widget with neighbor
let oldPosition = widget.order;
let newPosition = neighbor.order;
widget.order = newPosition;
neighbor.order = oldPosition;
reordered[newIndex] = widget;
reordered[index] = neighbor;
} else if (neighbor.widgetType === WidgetType.Section && index > newIndex) {
widget.section = neighbor.id;
neighbor.content.widgetIds = [
...(neighbor.content.widgetIds || []),
widget.id,
];
} else if (neighbor.widgetType === WidgetType.Section && index < newIndex) {
// Swap widget with neighbor
let oldPosition = widget.order;
let newPosition = neighbor.order;
widget.order = newPosition;
neighbor.order = oldPosition;
reordered[newIndex] = widget;
reordered[index] = neighbor;
widget.section = neighbor.id;
neighbor.content.widgetIds = [
widget.id,
...(neighbor.content.widgetIds || []),
];
}
} else if (widget.section && neighbor.section) {
// Swap widget with neighbor
let oldPosition = widget.order;
let newPosition = neighbor.order;
widget.order = newPosition;
neighbor.order = oldPosition;
reordered[newIndex] = widget;
reordered[index] = neighbor;
const parent = widgets.find((w) => w.id === widget.section);
if (parent) {
const indexWidget = parent.content.widgetIds.findIndex(
(id: string) => id === widget.id
);
const indexNeighbor = parent.content.widgetIds.findIndex(
(id: string) => id === neighbor.id
);
const widgetId = parent.content.widgetIds[indexWidget];
const neighborId = parent.content.widgetIds[indexNeighbor];
parent.content.widgetIds[indexWidget] = neighborId;
parent.content.widgetIds[indexNeighbor] = widgetId;
}
} else if (widget.section) {
if (index < newIndex) {
let parent = widgets.find((w) => w.id === widget.section);
if (parent) {
widget.section = undefined;
parent.content.widgetIds = parent.content.widgetIds.filter(
(id: string) => id !== widget.id
);
}
} else {
// Swap widget with neighbor
let oldPosition = widget.order;
let newPosition = neighbor.order;
widget.order = newPosition;
neighbor.order = oldPosition;
reordered[newIndex] = widget;
reordered[index] = neighbor;
let parent = widgets.find((w) => w.id === widget.section);
if (parent) {
widget.section = undefined;
parent.content.widgetIds = parent.content.widgetIds.filter(
(id: string) => id !== widget.id
);
}
}
} else if (neighbor.section) {
if (index > newIndex) {
if (widget.widgetType === WidgetType.Section) {
let parent = reordered.find((w) => w.id === neighbor.section);
if (parent) {
const belowWidgets = [widget];
for (const id of widget.content && widget.content.widgetIds
? widget.content.widgetIds
: []) {
const contentWidget = reordered.find((w) => w.id === id);
if (contentWidget) {
belowWidgets.push(contentWidget);
}
}
for (let belowWidget of belowWidgets) {
let firstIndex = index;
let secondIndex = newIndex;
let secondWidget = reordered[newIndex];
while (belowWidget.order > parent.order) {
// Swap widget with secondWidget
let oldPosition = belowWidget.order;
let newPosition = secondWidget.order;
belowWidget.order = newPosition;
secondWidget.order = oldPosition;
reordered[secondIndex] = belowWidget;
reordered[firstIndex] = secondWidget;
firstIndex--;
secondIndex--;
belowWidget = reordered[firstIndex];
secondWidget = reordered[secondIndex];
}
index++;
newIndex++;
}
}
} else {
let parent = widgets.find((w) => w.id === neighbor.section);
if (parent) {
parent.content.widgetIds = [...parent.content.widgetIds, widget.id];
widget.section = parent.id;
}
}
} else {
let first = index;
while (
first < reordered.length &&
(first === index || reordered[first].section)
) {
first++;
}
if (first >= reordered.length) {
return widgets;
}
const belowWidgets = [reordered[first]];
if (reordered[first].widgetType === WidgetType.Section) {
for (const id of reordered[first].content.widgetIds) {
const contentWidget = reordered.find((w) => w.id === id);
if (contentWidget) {
belowWidgets.push(contentWidget);
}
}
}
for (let belowWidget of belowWidgets) {
let firstIndex = first;
let secondIndex = first - 1;
let secondWidget = reordered[first - 1];
while (belowWidget.order > widget.order) {
// Swap widget with neighbor
let oldPosition = belowWidget.order;
let newPosition = secondWidget.order;
belowWidget.order = newPosition;
secondWidget.order = oldPosition;
reordered[secondIndex] = belowWidget;
reordered[firstIndex] = secondWidget;
firstIndex--;
secondIndex--;
belowWidget = reordered[firstIndex];
secondWidget = reordered[secondIndex];
}
first++;
}
}
}
return reordered;
}