Skip to content

Commit

Permalink
Add favicon (#1173)
Browse files Browse the repository at this point in the history
* feat: add favicon

* Adding favicon to all pages. Closes #1168

* style: minor typescript warning cleanup

* style: prettier

* style: prettier

* fix: disable log scale radio button for variables with custom range min of 0 or less. Addresses #960

* fix: enforce values greater than 0 when editing log scale variables. Addresses #960

* style: update validation text
  • Loading branch information
alexsielicki authored Jul 17, 2024
1 parent 0e1d1bf commit 19f48cc
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 136 deletions.
Binary file added web-server/img/favicon.ico
Binary file not shown.
200 changes: 87 additions & 113 deletions web-server/js/slycat-table-ingestion-react.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import React, { useState } from "react";

export default function SlycatTableIngestion(props) {

// Declare a new UI state variables...
// To track which variables are selected
// selected is an array, each element corresponds to a variable, with boolean values indicating whether it's selected.
const [selected, setSelected] = useState(props.variables.map((variable, indexVars) => variable.selected));
const [selected, setSelected] = useState(
props.variables.map((variable, indexVars) => variable.selected),
);
// To track the last selected variable
const [lastSelected, setLastSelected] = useState(0);

function anyVariablesSelected() {
for(var i = 0; i < selected.length; i++)
{
if( selected[i] )
{
for (var i = 0; i < selected.length; i++) {
if (selected[i]) {
return true;
}
}
Expand All @@ -26,170 +25,147 @@ export default function SlycatTableIngestion(props) {

function selectAll(e) {
let property = e.target.dataset.property;
for(let [index, variableSelected] of selected.entries())
{
if(variableSelected)
{
for (let [index, variableSelected] of selected.entries()) {
if (variableSelected) {
// Find the radio button that needs to be selected based on its name and value attributes
let radio = document.querySelector(`.${props.uniqueID} input[value='${property}'][name='${index}']`);
let radio = document.querySelector(
`.${props.uniqueID} input[value='${property}'][name='${index}']`,
);
// Fire the onChange handler only if radio button is not disabled
if(!radio.disabled)
{
props.onChange({currentTarget: radio});
if (!radio.disabled) {
props.onChange({ currentTarget: radio });
}
}
}
}

function select(event, varIndex) {
if(props.variables[varIndex].disabled)
{
if (props.variables[varIndex].disabled) {
return;
}
else if(event.shiftKey)
{
} else if (event.shiftKey) {
// Find start and end between lastSelected and currently shift clicked
let begin = Math.min(lastSelected, varIndex);
let end = Math.max(lastSelected, varIndex);

// Set everything in between to selected
let newSelected = selected.slice(0);
for(var i = begin; i <= end; i++)
{
if(!props.variables[i].disabled)
{
for (var i = begin; i <= end; i++) {
if (!props.variables[i].disabled) {
newSelected[i] = true;
}
}
setSelected(newSelected);
// Set current clicked to lastSelected
setLastSelected(varIndex);
}
else if(event.ctrlKey || event.metaKey)
{
} else if (event.ctrlKey || event.metaKey) {
setLastSelected(varIndex);
let newSelected = selected.slice(0);
// Invert the selected state, so Ctrl + click will either selecte unselected, or unselect selected.
newSelected[varIndex] = !newSelected[varIndex];
setSelected(newSelected);
}
else
{
} else {
// Set last selected to current variable
setLastSelected(varIndex);

// Set all selected to false
let newSelected = selected.map(x => false);
let newSelected = selected.map((x) => false);
// Set selected to true on current variable
newSelected[varIndex] = true;
setSelected(newSelected);
}
}

const propertiesItems = props.properties.map((property, indexProps) => {
if(property.type == 'bool')
{
if (property.type == "bool") {
return (
<th className='bool property-start property-end no-wrap px-2 py-2'
key={indexProps}
>
<th className="bool property-start property-end no-wrap px-2 py-2" key={indexProps}>
<span>{property.name}</span>
<i className={`fa fa-toggle-on select-all-button button ${anyVariablesSelected() ? "" : "disabled"}`}
onClick={anyVariablesSelected() ? checkAll : void(0)}
title={anyVariablesSelected() ? "Toggle selected rows" : "No rows selected"}
<i
className={`fa fa-toggle-on select-all-button button ${anyVariablesSelected() ? "" : "disabled"}`}
onClick={anyVariablesSelected() ? checkAll : void 0}
title={anyVariablesSelected() ? "Toggle selected rows" : "No rows selected"}
/>
</th>
);
} else if (property.type == "select") {
return property.values.map((value, indexVals, array) => (
<th
className={`select no-wrap px-2 py-2
${indexVals == 0 ? "property-start" : ""}
${indexVals == array.length - 1 ? "property-end" : ""}`}
key={indexVals}
>
<span>{value}</span>
<i
className={`fa fa-toggle-on select-all-button button ${anyVariablesSelected() ? "" : "disabled"}`}
title={anyVariablesSelected() ? "Toggle selected rows" : "No rows selected"}
data-property={value}
onClick={anyVariablesSelected() ? selectAll : void 0}
/>
</th>
));
}
else if(property.type == 'select')
{
return (
property.values.map((value, indexVals, array) =>
(
<th
className={`select no-wrap px-2 py-2
${indexVals==0 ? "property-start" : ""}
${indexVals==array.length-1 ? "property-end" : ""}`}
key={indexVals}
>
<span>{value}</span>
<i className={`fa fa-toggle-on select-all-button button ${anyVariablesSelected() ? "" : "disabled"}`}
title={anyVariablesSelected() ? "Toggle selected rows" : "No rows selected"}
data-property={value}
onClick={anyVariablesSelected() ? selectAll : void(0)}
/>
</th>
)
)
);
}

});

// Figure out if radio button should be disabled
function disabledRadioButton(property, value, variable) {
// Check if we have a disabledValue defined for this radio button
let disabledValue = property.disabledValues && property.disabledValues[value] && property.disabledValues[value].indexOf(variable.index) > -1;
let disabledValue =
property.disabledValues &&
property.disabledValues[value] &&
property.disabledValues[value].indexOf(variable.index) > -1;
// Also return disabled if the entire variable is disabled
return variable.disabled || disabledValue ? 'disabled' : false;
return variable.disabled || disabledValue ? "disabled" : false;
}

const variablesItems = props.variables.map((variable, indexVars, arrayVars) => {
return (
<tr key={indexVars}
title={variable.tooltip ? variable.tooltip : undefined}
style={{display: variable.hidden ? 'none' : ''}}
className={`${selected[indexVars] ? 'selected' : ''} ${lastSelected == indexVars ? 'lastSelected' : ''} ${variable.disabled ? 'disabled' : ''}`}
>
<th className='force-wrap px-2 py-1'
onClick={(event) => select(event, indexVars)}>
{variable.name}
</th>
{
props.properties.map((property, indexProps, arrayProps) => {
if(property.type == 'bool')
{
<tr
key={indexVars}
title={variable.tooltip ? variable.tooltip : undefined}
style={{ display: variable.hidden ? "none" : "" }}
className={`${selected[indexVars] ? "selected" : ""} ${lastSelected == indexVars ? "lastSelected" : ""} ${variable.disabled ? "disabled" : ""}`}
>
<th className="force-wrap px-2 py-1" onClick={(event) => select(event, indexVars)}>
{variable.name}
</th>
{props.properties.map((property, indexProps, arrayProps) => {
if (property.type == "bool") {
return (
<td
className='bool property-start property-end align-middle px-2 py-1'
<td
className="bool property-start property-end align-middle px-2 py-1"
key={property.name + indexProps}
>
<input type='checkbox'
<input
type="checkbox"
name={variable.index}
value='true'
disabled={variable.disabled ? 'disabled' : false}
defaultChecked={variable[property.name] ? 'checked' : false}
value="true"
disabled={variable.disabled ? "disabled" : false}
defaultChecked={variable[property.name] ? "checked" : false}
/>
</td>
);
} else if (property.type == "select") {
return property.values.map((value, indexVals, arrayVals) => (
<td
className={`select align-middle px-2 py-1
${indexVals == 0 ? "property-start" : ""}
${indexVals == arrayVals.length - 1 ? "property-end" : ""}`}
key={property.name + indexProps + value + indexVals}
>
<input
type="radio"
name={variable.index}
value={value}
disabled={disabledRadioButton(property, value, variable)}
checked={value == variable[property.name] ? "checked" : false}
onChange={props.onChange}
/>
</td>
));
}
else if(property.type == 'select')
{
return (
property.values.map((value, indexVals, arrayVals) =>
(
<td
className={`select align-middle px-2 py-1
${indexVals == 0 ? 'property-start' : ''}
${indexVals == arrayVals.length-1 ? 'property-end' : ''}`}
key={property.name + indexProps + value + indexVals}
>
<input
type='radio'
name={variable.index}
value={value}
disabled={disabledRadioButton(property, value, variable)}
checked={value == variable[property.name] ? 'checked' : false}
onChange={props.onChange}
/>
</td>
)
)
);
}
})
}
</tr>
})}
</tr>
);
});

Expand All @@ -202,10 +178,8 @@ export default function SlycatTableIngestion(props) {
{propertiesItems}
</tr>
</thead>
<tbody>
{variablesItems}
</tbody>
<tbody>{variablesItems}</tbody>
</table>
</div>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import VariableAliasLabels from "components/VariableAliasLabels";
import ScatterplotOptions from "components/ScatterplotOptions";
import VariableRanges from "components/VariableRanges";
import "js/slycat-table-ingestion";
import ko from "knockout";
import "../../css/controls-button-var-options.css";
import $ from "jquery";
import client from "js/slycat-web-client";
Expand Down Expand Up @@ -133,7 +132,7 @@ class ControlsButtonVarOptions extends React.PureComponent {
// Maybe it was deleted.
// Let's save to the model's artifact instead.
console.log(
"Oops, we have a pointer to project data but can't save to it. Let's save to the model's artifact instead."
"Oops, we have a pointer to project data but can't save to it. Let's save to the model's artifact instead.",
);
self.writeAliasesToModelArtifact();
},
Expand All @@ -157,11 +156,11 @@ class ControlsButtonVarOptions extends React.PureComponent {
},
error: function () {
console.log(
"Oops, can't even write aliases to model artifact. Closing dialog and popping up error dialog."
"Oops, can't even write aliases to model artifact. Closing dialog and popping up error dialog.",
);
$("#" + self.modalId).modal("hide");
dialog.ajax_error(
"There was an error saving the variable alias labels to the model's artifact."
"There was an error saving the variable alias labels to the model's artifact.",
)();
},
});
Expand Down Expand Up @@ -242,9 +241,12 @@ class ControlsButtonVarOptions extends React.PureComponent {
undefined;
// Check if variable is greater than zero
const isGreaterThanZero = this.props.table_statistics?.[index]?.min > 0;
// If not numeric or not greater than zero, add to disabledLogVariables
// Check if custom axis min variable range is 0 or less
const isCustomAxisMinZeroOrLess = this.props.variableRanges?.[index]?.min <= 0;
// If not numeric or not greater than zero or custom min variablel range is 0 or less,
// add to disabledLogVariables
// so we don't allow them for log scales.
if (!isNumericVariable || !isGreaterThanZero) {
if (!isNumericVariable || !isGreaterThanZero || isCustomAxisMinZeroOrLess) {
disabledLogVariables.push(index);
}
}
Expand Down Expand Up @@ -660,7 +662,7 @@ const mapStateToProps = (state, ownProps) => {
min: value.min,
max: value.max,
};
}
},
);

return {
Expand Down
Loading

0 comments on commit 19f48cc

Please sign in to comment.