mirror of
https://github.com/ANL-CEEESA/UnitCommitment.jl.git
synced 2025-12-06 00:08:52 -06:00
Compare commits
2 Commits
12c5f9ccca
...
61179bb7c7
| Author | SHA1 | Date | |
|---|---|---|---|
| 61179bb7c7 | |||
| 8b170cdbbf |
@@ -6,11 +6,7 @@
|
||||
|
||||
import SectionHeader from "../Common/SectionHeader/SectionHeader";
|
||||
import SectionButton from "../Common/Buttons/SectionButton";
|
||||
import {
|
||||
faDownload,
|
||||
faPlus,
|
||||
faUpload,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { faDownload, faPlus, faUpload } from "@fortawesome/free-solid-svg-icons";
|
||||
import { offerDownload } from "../Common/io";
|
||||
import FileUploadElement from "../Common/Buttons/FileUploadElement";
|
||||
import { useRef } from "react";
|
||||
@@ -20,16 +16,11 @@ import DataTable, {
|
||||
generateCsv,
|
||||
generateTableColumns,
|
||||
generateTableData,
|
||||
parseCsv,
|
||||
parseCsv
|
||||
} from "../Common/Forms/DataTable";
|
||||
|
||||
import { ColumnDefinition } from "tabulator-tables";
|
||||
import {
|
||||
changeBusData,
|
||||
createBus,
|
||||
deleteBus,
|
||||
renameBus,
|
||||
} from "../../core/Operations/busOps";
|
||||
import { changeBusData, createBus, deleteBus, renameBus } from "../../core/Operations/busOps";
|
||||
import { CaseBuilderSectionProps } from "./CaseBuilder";
|
||||
import { UnitCommitmentScenario } from "../../core/Data/types";
|
||||
|
||||
@@ -128,13 +119,13 @@ function BusesComponent(props: CaseBuilderSectionProps) {
|
||||
return (
|
||||
<div>
|
||||
<SectionHeader title="Buses">
|
||||
<SectionButton icon={faPlus} tooltip="Add" onClick={onAdd} />
|
||||
<SectionButton icon={faUpload} tooltip="Upload" onClick={onUpload} />
|
||||
<SectionButton
|
||||
icon={faDownload}
|
||||
tooltip="Download"
|
||||
onClick={onDownload}
|
||||
/>
|
||||
<SectionButton icon={faUpload} tooltip="Upload" onClick={onUpload} />
|
||||
<SectionButton icon={faPlus} tooltip="Add" onClick={onAdd} />
|
||||
</SectionHeader>
|
||||
<DataTable
|
||||
onRowDeleted={onDelete}
|
||||
|
||||
@@ -44,11 +44,13 @@ const CaseBuilder = () => {
|
||||
return processedScenario!!;
|
||||
});
|
||||
const [undoStack, setUndoStack] = useState<UnitCommitmentScenario[]>([]);
|
||||
const [redoStack, setRedoStack] = useState<UnitCommitmentScenario[]>([]);
|
||||
const [toastMessage, setToastMessage] = useState<string>("");
|
||||
|
||||
const setAndSaveScenario = (
|
||||
newScenario: UnitCommitmentScenario,
|
||||
updateUndoStack = true,
|
||||
clearRedoStack = true,
|
||||
) => {
|
||||
if (updateUndoStack) {
|
||||
const newUndoStack = [...undoStack, scenario];
|
||||
@@ -57,6 +59,9 @@ const CaseBuilder = () => {
|
||||
}
|
||||
setUndoStack(newUndoStack);
|
||||
}
|
||||
if (clearRedoStack) {
|
||||
setRedoStack([]);
|
||||
}
|
||||
setScenario(newScenario);
|
||||
localStorage.setItem("scenario", JSON.stringify(newScenario));
|
||||
};
|
||||
@@ -90,8 +95,19 @@ const CaseBuilder = () => {
|
||||
|
||||
const onUndo = () => {
|
||||
if (undoStack.length === 0) return;
|
||||
const newRedoStack = [...redoStack, scenario];
|
||||
if (newRedoStack.length > 25) {
|
||||
newRedoStack.splice(0, newRedoStack.length - 25);
|
||||
}
|
||||
setRedoStack(newRedoStack);
|
||||
setUndoStack(undoStack.slice(0, -1));
|
||||
setAndSaveScenario(undoStack[undoStack.length - 1]!, false);
|
||||
setAndSaveScenario(undoStack[undoStack.length - 1]!, false, false);
|
||||
};
|
||||
|
||||
const onRedo = () => {
|
||||
if (redoStack.length === 0) return;
|
||||
setRedoStack(redoStack.slice(0, -1));
|
||||
setAndSaveScenario(redoStack[redoStack.length - 1]!, true, false);
|
||||
};
|
||||
|
||||
const onSolve = async () => {
|
||||
@@ -128,7 +144,10 @@ const CaseBuilder = () => {
|
||||
onSave={onSave}
|
||||
onLoad={onLoad}
|
||||
onUndo={onUndo}
|
||||
onRedo={onRedo}
|
||||
onSolve={onSolve}
|
||||
canUndo={undoStack.length > 0}
|
||||
canRedo={redoStack.length > 0}
|
||||
/>
|
||||
<div className="content">
|
||||
<Parameters
|
||||
|
||||
@@ -9,13 +9,17 @@ import SiteHeaderButton from "../Common/Buttons/SiteHeaderButton";
|
||||
import { useRef } from "react";
|
||||
import FileUploadElement from "../Common/Buttons/FileUploadElement";
|
||||
import { UnitCommitmentScenario } from "../../core/Data/types";
|
||||
import { faDownload, faGear, faRotateLeft, faRotateRight, faTrash, faUpload } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
interface HeaderProps {
|
||||
onClear: () => void;
|
||||
onSave: () => void;
|
||||
onUndo: () => void;
|
||||
onRedo: () => void;
|
||||
onLoad: (data: UnitCommitmentScenario) => void;
|
||||
onSolve: () => void;
|
||||
canUndo: boolean;
|
||||
canRedo: boolean;
|
||||
}
|
||||
|
||||
function Header(props: HeaderProps) {
|
||||
@@ -33,13 +37,33 @@ function Header(props: HeaderProps) {
|
||||
<h1>UnitCommitment.jl</h1>
|
||||
<h2>Case Builder</h2>
|
||||
<div className={styles.buttonContainer}>
|
||||
<SiteHeaderButton title="Undo" onClick={props.onUndo} />
|
||||
<SiteHeaderButton title="Clear" onClick={props.onClear} />
|
||||
<SiteHeaderButton title="Load" onClick={onLoad} />
|
||||
<SiteHeaderButton title="Save" onClick={props.onSave} />
|
||||
<SiteHeaderButton title="Load" icon={faUpload} onClick={onLoad} />
|
||||
<SiteHeaderButton
|
||||
title="Save"
|
||||
icon={faDownload}
|
||||
onClick={props.onSave}
|
||||
/>
|
||||
<SiteHeaderButton
|
||||
title="Undo"
|
||||
icon={faRotateLeft}
|
||||
onClick={props.onUndo}
|
||||
disabled={!props.canUndo}
|
||||
/>
|
||||
<SiteHeaderButton
|
||||
title="Redo"
|
||||
icon={faRotateRight}
|
||||
onClick={props.onRedo}
|
||||
disabled={!props.canRedo}
|
||||
/>
|
||||
<SiteHeaderButton
|
||||
title="Clear"
|
||||
icon={faTrash}
|
||||
onClick={props.onClear}
|
||||
/>
|
||||
<SiteHeaderButton
|
||||
title="Solve"
|
||||
variant="primary"
|
||||
icon={faGear}
|
||||
onClick={props.onSolve}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -175,13 +175,13 @@ const ProfiledUnitsComponent = (props: CaseBuilderSectionProps) => {
|
||||
return (
|
||||
<div>
|
||||
<SectionHeader title="Profiled units">
|
||||
<SectionButton icon={faPlus} tooltip="Add" onClick={onAdd} />
|
||||
<SectionButton icon={faUpload} tooltip="Upload" onClick={onUpload} />
|
||||
<SectionButton
|
||||
icon={faDownload}
|
||||
tooltip="Download"
|
||||
onClick={onDownload}
|
||||
/>
|
||||
<SectionButton icon={faUpload} tooltip="Upload" onClick={onUpload} />
|
||||
<SectionButton icon={faPlus} tooltip="Add" onClick={onAdd} />
|
||||
</SectionHeader>
|
||||
<DataTable
|
||||
onRowDeleted={onDelete}
|
||||
|
||||
@@ -153,13 +153,13 @@ const PriceSensitiveLoadsComponent = (props: CaseBuilderSectionProps) => {
|
||||
return (
|
||||
<div>
|
||||
<SectionHeader title="Price-sensitive loads">
|
||||
<SectionButton icon={faPlus} tooltip="Add" onClick={onAdd} />
|
||||
<SectionButton icon={faUpload} tooltip="Upload" onClick={onUpload} />
|
||||
<SectionButton
|
||||
icon={faDownload}
|
||||
tooltip="Download"
|
||||
onClick={onDownload}
|
||||
/>
|
||||
<SectionButton icon={faUpload} tooltip="Upload" onClick={onUpload} />
|
||||
<SectionButton icon={faPlus} tooltip="Add" onClick={onAdd} />
|
||||
</SectionHeader>
|
||||
<DataTable
|
||||
onRowDeleted={onDelete}
|
||||
|
||||
@@ -213,13 +213,13 @@ const StorageUnitsComponent = (props: CaseBuilderSectionProps) => {
|
||||
return (
|
||||
<div>
|
||||
<SectionHeader title="Storage units">
|
||||
<SectionButton icon={faPlus} tooltip="Add" onClick={onAdd} />
|
||||
<SectionButton icon={faUpload} tooltip="Upload" onClick={onUpload} />
|
||||
<SectionButton
|
||||
icon={faDownload}
|
||||
tooltip="Download"
|
||||
onClick={onDownload}
|
||||
/>
|
||||
<SectionButton icon={faUpload} tooltip="Upload" onClick={onUpload} />
|
||||
<SectionButton icon={faPlus} tooltip="Add" onClick={onAdd} />
|
||||
</SectionHeader>
|
||||
<DataTable
|
||||
onRowDeleted={onDelete}
|
||||
|
||||
@@ -229,13 +229,13 @@ const ThermalUnitsComponent = (props: CaseBuilderSectionProps) => {
|
||||
return (
|
||||
<div>
|
||||
<SectionHeader title="Thermal units">
|
||||
<SectionButton icon={faPlus} tooltip="Add" onClick={onAdd} />
|
||||
<SectionButton icon={faUpload} tooltip="Upload" onClick={onUpload} />
|
||||
<SectionButton
|
||||
icon={faDownload}
|
||||
tooltip="Download"
|
||||
onClick={onDownload}
|
||||
/>
|
||||
<SectionButton icon={faUpload} tooltip="Upload" onClick={onUpload} />
|
||||
<SectionButton icon={faPlus} tooltip="Add" onClick={onAdd} />
|
||||
</SectionHeader>
|
||||
<DataTable
|
||||
onRowDeleted={onDelete}
|
||||
|
||||
@@ -181,13 +181,13 @@ const TransmissionLinesComponent = (props: CaseBuilderSectionProps) => {
|
||||
return (
|
||||
<div>
|
||||
<SectionHeader title="Transmission lines">
|
||||
<SectionButton icon={faPlus} tooltip="Add" onClick={onAdd} />
|
||||
<SectionButton icon={faUpload} tooltip="Upload" onClick={onUpload} />
|
||||
<SectionButton
|
||||
icon={faDownload}
|
||||
tooltip="Download"
|
||||
onClick={onDownload}
|
||||
/>
|
||||
<SectionButton icon={faUpload} tooltip="Upload" onClick={onUpload} />
|
||||
<SectionButton icon={faPlus} tooltip="Add" onClick={onAdd} />
|
||||
</SectionHeader>
|
||||
<DataTable
|
||||
onRowDeleted={onDelete}
|
||||
|
||||
@@ -5,16 +5,33 @@
|
||||
*/
|
||||
|
||||
.SiteHeaderButton {
|
||||
padding: 6px 24px;
|
||||
margin: 0 0 0 8px;
|
||||
padding: 6px 16px;
|
||||
margin: 0 0 0 0;
|
||||
line-height: 24px;
|
||||
border: var(--box-border);
|
||||
box-shadow: var(--box-shadow);
|
||||
border-radius: var(--border-radius);
|
||||
border-radius: 0;
|
||||
cursor: pointer;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.SiteHeaderButton:not(:last-child) {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.SiteHeaderButton:first-child {
|
||||
border-radius: var(--border-radius) 0 0 var(--border-radius);
|
||||
}
|
||||
|
||||
.SiteHeaderButton:last-child {
|
||||
border-radius: 0 var(--border-radius) var(--border-radius) 0;
|
||||
}
|
||||
|
||||
.SiteHeaderButton:only-child {
|
||||
border-radius: var(--border-radius);
|
||||
border-right: var(--box-border);
|
||||
}
|
||||
|
||||
.light {
|
||||
@@ -42,3 +59,9 @@
|
||||
.primary:active {
|
||||
background: color-mix(in hsl, #000, var(--primary) 90%);
|
||||
}
|
||||
|
||||
.disabled {
|
||||
color: var(--contrast-20);
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@@ -5,24 +5,33 @@
|
||||
*/
|
||||
|
||||
import styles from "./SiteHeaderButton.module.css";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
||||
|
||||
function SiteHeaderButton({
|
||||
title,
|
||||
icon,
|
||||
onClick,
|
||||
variant = "light",
|
||||
disabled = false,
|
||||
}: {
|
||||
title: string;
|
||||
icon: IconDefinition;
|
||||
onClick?: () => void;
|
||||
variant?: "light" | "primary";
|
||||
disabled?: boolean;
|
||||
}) {
|
||||
const variantClass = variant === "primary" ? styles.primary : styles.light;
|
||||
const disabledClass = disabled ? styles.disabled : "";
|
||||
|
||||
return (
|
||||
<button
|
||||
className={`${styles.SiteHeaderButton} ${variantClass}`}
|
||||
className={`${styles.SiteHeaderButton} ${variantClass} ${disabledClass}`}
|
||||
title={title}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
>
|
||||
{title}
|
||||
<FontAwesomeIcon icon={icon} />
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user