Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
8233a1c
basic table to list and display SI units
herrdivad Mar 26, 2026
4a39480
adding only the visual components for unit assignment
herrdivad Mar 26, 2026
9a08ace
function for updating row configurations for Data Table Unit Assignment
herrdivad Mar 26, 2026
6808996
save unit configuration state to JSON
herrdivad Mar 26, 2026
d6cb98e
"-" now folds in, trash button to delete
herrdivad Mar 26, 2026
e420645
Update [skip ci]
actions-user Mar 26, 2026
b87a19e
Adding auto-generated Operations description for SI Units
herrdivad Mar 27, 2026
7daf8bb
Merge remote-tracking branch 'origin/SIunit-frontend-for-backend-217'…
herrdivad Mar 27, 2026
b715b52
Update [skip ci]
actions-user Mar 27, 2026
0b7532f
adding multi-assignment functionality for SI units
herrdivad Mar 27, 2026
2a6c3a0
Merge remote-tracking branch 'origin/SIunit-frontend-for-backend-217'…
herrdivad Mar 27, 2026
42db7e4
JSON save and load assignments now bound to uuid of units
herrdivad Mar 27, 2026
a374d08
Update [skip ci]
actions-user Mar 27, 2026
d7dbbab
adding SI units offcanvas
herrdivad Apr 7, 2026
4b39757
Offcanvas getting info about used output table index and axis
herrdivad Apr 7, 2026
4be6bb7
Hover button label update
herrdivad Apr 7, 2026
bd161c1
Update [skip ci]
actions-user Apr 7, 2026
e058940
adding custom scalar operation editor for SI units conversions
herrdivad Apr 8, 2026
fff1f39
3 State toggle for collapse button
herrdivad Apr 8, 2026
de65aca
Merge remote-tracking branch 'origin/SIunit-frontend-for-backend-217'…
herrdivad Apr 8, 2026
33e7878
change custom conversion editor to modal
herrdivad Apr 8, 2026
240c26d
Update [skip ci]
actions-user Apr 8, 2026
5342a68
adding overwrite confirmation
herrdivad Apr 8, 2026
5fdaabf
Update [skip ci]
actions-user Apr 8, 2026
c363531
adding input column information to Offcanvas default assignment context
herrdivad Apr 10, 2026
90ec215
SI Units score
herrdivad Apr 13, 2026
8559e23
update gitignore
herrdivad Apr 14, 2026
99c316b
Update [skip ci]
actions-user Apr 14, 2026
aea2666
change spacing
herrdivad May 28, 2026
6a7b3b0
Merge branch 'master' into SIunit-frontend-for-backend-217
herrdivad May 28, 2026
be3b1a0
Some reworks after merge
herrdivad May 28, 2026
c394921
Fix SI units component and receiving from backend
herrdivad May 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ __pycache__/
*.save
.DS_Store

AGENTS.md

/dist
/public
/node_modules
Expand Down
2 changes: 1 addition & 1 deletion src/js/components/admin/AdminApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ provideGlobalGridOptions({


function AdminAppContent() {
const {profiles, setProfiles, profile, setProfile} = useAdminApp();
const {profiles, setProfiles, profile, setProfile, options} = useAdminApp();
const [status, setStatus] = useState('list');
const [selectedFile, setSelectedFile] = useState(null);
const [originProfile, setOriginProfile] = useState(null);
Expand Down
297 changes: 178 additions & 119 deletions src/js/components/admin/form/TableForm.js
Original file line number Diff line number Diff line change
@@ -1,143 +1,202 @@
import React, {useMemo} from "react"
import React, {useState, useMemo} from "react"
import PropTypes from 'prop-types';

import HeaderInput from './table/HeaderInput'
import TableColumn from './TableColumn'
import TableIdentifier from './TableIdentifier'
import ExtendedHeaderInput from "./table/ExtendedHeaderInput";
import {Col, Form, Row} from "react-bootstrap";
import {Button, Col, Form, Offcanvas, Row} from "react-bootstrap";
import SIunits from "./controllComponents/SIunits";
import {useAdminApp} from "../AppContext";


function TableForm({
table, inputTables, inputColumns,
updateTable, updateHeader,
addOperation, updateOperation, updateOperationDescription, removeOperation,
fileMetadataOptions, tableMetadataOptions
table, inputTables, inputColumns,
updateTable, updateHeader,
addOperation, updateOperation, updateOperationDescription, removeOperation,
fileMetadataOptions, tableMetadataOptions,
outputTableIndex,
tableIdx
}) {
const {options} = useAdminApp();
const [showSiUnits, setShowSiUnits] = useState(false);
const [siUnitsContext, setSiUnitsContext] = useState(null);
const {options, profile, setProfile} = useAdminApp();
const creatableHeaderOptions = {"DATA TYPE": options["DATA TYPE"], XUNITS: options.XUNITS, YUNITS: options.YUNITS};

const fixedHeaderOptions = useMemo(() => {
const openSiUnits = (axis) => {
const inputColumn = axis === "X" ? table?.table?.xColumn : table?.table?.yColumn;

setSiUnitsContext({
outputTableIndex,
axis,
inputColumn
});
setShowSiUnits(true);
};

const axisForHeaderOption = (optionKey) => {
if (optionKey === "XUNITS") return "X";
if (optionKey === "YUNITS") return "Y";
return null;
};

const fixedHeaderOptions = useMemo(() => {
return Object.fromEntries(
Object.entries(options).filter(
([key]) => !(key in creatableHeaderOptions) && !["rdf", "VERSION"].includes(key)
)
);
}, [options]);

return (
<div>
<div className="fw-bold">
Table header
</div>

{Object.keys(fixedHeaderOptions).map((optionKey, index) => (
<HeaderInput key={index} optionKey={optionKey} value={table.header[optionKey]}
values={fixedHeaderOptions[optionKey]} updateHeader={updateHeader}/>
))}

{Object.keys(creatableHeaderOptions).map((optionKey, index) => (
<ExtendedHeaderInput key={index} optionKey={optionKey} value={table.header[optionKey]}
values={creatableHeaderOptions[optionKey]} updateHeader={updateHeader}/>
))}

{(table.header['DATA CLASS'] === 'NTUPLES') && (
<Form.Group as={Row}>
<Form.Label as={Col} sm={4}>NTUPLES PAGE HEADER</Form.Label>
<Col sm={8}>
<Form.Select
size="sm"
value={table.header['NTUPLES_PAGE_HEADER']}
onChange={event => {
const {value} = event.target;
updateHeader('NTUPLES_PAGE_HEADER', value);
}}
>
<option value="___+">Incrementing Page Index</option>
<option value="___TABLE_NAME">Input Table Name</option>
<option disabled>---METADATA---</option>
<>
{[...new Set(tableMetadataOptions.map(o => o.key))].map((option, optionIndex) => (
<option key={optionIndex} data-idx={optionIndex} value={option}>{option}</option>
))}
</>
</Form.Select>
</Col>
</Form.Group>
)}
<div className="mt-3 fw-bold">
Table columns
</div>

{(table.header['DATA CLASS'] === 'XYDATA') ? (
([key]) => !(key in creatableHeaderOptions) && !["rdf", "VERSION"].includes(key)
)
);
}, [options]);

return (
<div>
<div className="mb-2">
Which metadata should be used for the x-values?
</div>
{['FIRSTX', 'LASTX', 'DELTAX'].map((headerKey, index) => (
<TableIdentifier
key={index}
index={index + 1000}
headerKey={headerKey}
table={table}
inputTables={inputTables}
updateHeader={updateHeader}
fileMetadataOptions={fileMetadataOptions}
tableMetadataOptions={tableMetadataOptions}
<div className="fw-bold">
Table header
</div>

{Object.keys(fixedHeaderOptions).map((optionKey, index) => (
<HeaderInput key={index} optionKey={optionKey} value={table.header[optionKey]}
values={fixedHeaderOptions[optionKey]} updateHeader={updateHeader}/>
))}

{Object.keys(creatableHeaderOptions).map((optionKey, index) => {
const axis = axisForHeaderOption(optionKey);
return (
<ExtendedHeaderInput key={index} optionKey={optionKey} value={table.header[optionKey]}
values={creatableHeaderOptions[optionKey]} updateHeader={updateHeader}
leftElement={axis ? (
<Button
variant="outline-info"
type="button"
onClick={() => openSiUnits(axis)}
>
SI Units
</Button>
) : null}/>
);
})}

{(table.header['DATA CLASS'] === 'NTUPLES') && (
<Form.Group as={Row}>
<Form.Label as={Col} sm={4}>NTUPLES PAGE HEADER</Form.Label>
<Col sm={8}>
<Form.Select
size="sm"
value={table.header['NTUPLES_PAGE_HEADER']}
onChange={event => {
const {value} = event.target;
updateHeader('NTUPLES_PAGE_HEADER', value);
}}
>
<option value="___+">Incrementing Page Index</option>
<option value="___TABLE_NAME">Input Table Name</option>
<option disabled>---METADATA---</option>
<>
{[...new Set(tableMetadataOptions.map(o => o.key))].map((option, optionIndex) => (
<option key={optionIndex} data-idx={optionIndex} value={option}>{option}</option>
))}
</>
</Form.Select>
</Col>
</Form.Group>
)}
<div className="mt-3 fw-bold">
Table columns
</div>

{(table.header['DATA CLASS'] === 'XYDATA') ? (
<div>
<div className="mb-2">
Which metadata should be used for the x-values?
</div>
{['FIRSTX', 'LASTX', 'DELTAX'].map((headerKey, index) => (
<TableIdentifier
key={index}
index={index + 1000}
headerKey={headerKey}

table={table}
inputTables={inputTables}
updateHeader={updateHeader}
fileMetadataOptions={fileMetadataOptions}
tableMetadataOptions={tableMetadataOptions}
/>
))}
</div>
) : (
<TableColumn
table={table.table}
label="Which column should be used as x-values?"
columnKey="xColumn"
operationsKey="xOperations"
inputColumns={inputColumns}
updateTable={updateTable}
addOperation={addOperation}
updateOperation={updateOperation}
updateOperationDescription={updateOperationDescription}
removeOperation={removeOperation}
tableMetadataOptions={tableMetadataOptions}
inputTables={inputTables}
/>
)}

<TableColumn
table={table.table}
label="Which column should be used as y-values?"
columnKey="yColumn"
operationsKey="yOperations"
inputColumns={inputColumns}
updateTable={updateTable}
addOperation={addOperation}
updateOperation={updateOperation}
updateOperationDescription={updateOperationDescription}
removeOperation={removeOperation}
tableMetadataOptions={tableMetadataOptions}
inputTables={inputTables}
/>
))}

<small className="text-muted">The data you pick will determine which table columns are going to
converted.</small>

<Offcanvas
show={showSiUnits}
onHide={() => setShowSiUnits(false)}
placement="start"
style={{width: "min(1100px, 50vw)"}}
>
<Offcanvas.Header closeButton>
<Offcanvas.Title>SI Units</Offcanvas.Title>
</Offcanvas.Header>
<Offcanvas.Body>
<SIunits
profile={profile}
setProfile={setProfile}
defaultAssignmentContext={siUnitsContext}
tableIdx={tableIdx}
/>
</Offcanvas.Body>
</Offcanvas>
</div>
) : (
<TableColumn
table={table.table}
label="Which column should be used as x-values?"
columnKey="xColumn"
operationsKey="xOperations"
inputColumns={inputColumns}
updateTable={updateTable}
addOperation={addOperation}
updateOperation={updateOperation}
updateOperationDescription={updateOperationDescription}
removeOperation={removeOperation}
tableMetadataOptions={tableMetadataOptions}
inputTables={inputTables}
/>
)}

<TableColumn
table={table.table}
label="Which column should be used as y-values?"
columnKey="yColumn"
operationsKey="yOperations"
inputColumns={inputColumns}
updateTable={updateTable}
addOperation={addOperation}
updateOperation={updateOperation}
updateOperationDescription={updateOperationDescription}
removeOperation={removeOperation}
tableMetadataOptions={tableMetadataOptions}
inputTables={inputTables}
/>

<small className="text-muted">The data you pick will determine which table columns are going to
converted.</small>
</div>
)
)
}

TableForm.propTypes = {
table: PropTypes.object,
inputTables: PropTypes.array,
inputColumns: PropTypes.array,
updateTable: PropTypes.func,
updateHeader: PropTypes.func,
updateOperationDescription: PropTypes.func,
addOperation: PropTypes.func,
updateOperation: PropTypes.func,
removeOperation: PropTypes.func,
fileMetadataOptions: PropTypes.array,
tableMetadataOptions: PropTypes.array
table: PropTypes.object,
inputTables: PropTypes.array,
inputColumns: PropTypes.array,
options: PropTypes.object,
updateTable: PropTypes.func,
updateHeader: PropTypes.func,
updateOperationDescription: PropTypes.func,
addOperation: PropTypes.func,
updateOperation: PropTypes.func,
removeOperation: PropTypes.func,
fileMetadataOptions: PropTypes.array,
tableMetadataOptions: PropTypes.array,
profile: PropTypes.object,
setProfile: PropTypes.func,
outputTableIndex: PropTypes.number,
tableIdx: PropTypes.number
}

export default TableForm
Loading
Loading