Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Disable inputs during timeseries collection [PT-187852896] #151

Merged
merged 1 commit into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
"ace-builds": "^1.4.8",
"ajv": "5.5.2",
"aws-sdk": "^2.454.0",
"classnames": "^2.5.1",
"client-oauth2": "^4.2.5",
"eventemitter3": "^4.0.0",
"firebase": "^7.6.1",
Expand Down
7 changes: 6 additions & 1 deletion src/mobile-app/components/experiment-wrapper.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
padding: 2px 4px;
width: 100%;

@include add-disabled-class();

input{
padding: 0;
width: 100%;
Expand All @@ -43,7 +45,10 @@
.headerBackIcon {
margin: 5px 15px 0 15px;
padding: 0;
&:hover {

@include add-disabled-class();

&:hover:not(.disabled) {
cursor: pointer;
}
svg {
Expand Down
25 changes: 17 additions & 8 deletions src/mobile-app/components/experiment-wrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState } from "react";
import classNames from "classnames";
import { IExperiment, IExperimentConfig, IExperimentData } from "../../shared/experiment-types";
import { Experiment } from "../../shared/components/experiment";
import { Initials } from "../../shared/components/initials";
Expand Down Expand Up @@ -29,6 +30,7 @@ const experimentConfig: IExperimentConfig = {

export const ExperimentWrapper: React.FC<IProps> = ({ experiment, experimentIdx, data, onDataChange, onBackBtnClick, onUpload, embeddedPreview }) => {
const [editing, isEditing ] = useState(false);
const [inputDisabled, setInputDisabled] = useState(false);
const { metadata } = experiment;
const workSpaceClass = embeddedPreview ? `${css.workspace} ${css.embeddedPreview}`: css.workspace;

Expand Down Expand Up @@ -68,27 +70,34 @@ export const ExperimentWrapper: React.FC<IProps> = ({ experiment, experimentIdx,
return (
<div>
<div className={css.header}>
<div className={css.headerBackIcon} onClick={onBackBtnClick}><Icon name="arrow_back"/></div>
<div className={classNames(css.headerBackIcon, {[css.disabled]: inputDisabled})} onClick={inputDisabled ? undefined : onBackBtnClick}><Icon name="arrow_back"/></div>
<Initials metadata={metadata} active={true}/>
<div className={css.headerTitle}>
<div className={css.name}>
<div className={classNames(css.name, {[css.disabled]: inputDisabled})}>
{editing
? <input defaultValue={`${name}`} onChange={saveExperimentName} onBlur={handleRename} onKeyDown={handleEnter} autoFocus={true} />
: <div onClick={handleRename}>{name}</div>
? <input defaultValue={`${name}`} onChange={inputDisabled ? undefined : saveExperimentName} onBlur={inputDisabled ? undefined : handleRename} onKeyDown={inputDisabled ? undefined : handleEnter} autoFocus={true} />
: <div onClick={inputDisabled ? undefined : handleRename}>{name}</div>
}
</div>
<div>{title}</div>
</div>
<div className={css.headerMenu}>
<MenuComponent>
<MenuItemComponent icon={"label"} onClick={handleSave}>Save</MenuItemComponent>
<MenuItemComponent icon={"upload"} onClick={onUpload}>Upload</MenuItemComponent>
<MenuItemComponent icon={"create"} onClick={handleRename}>Rename</MenuItemComponent>
<MenuItemComponent icon={"label"} disabled={inputDisabled} onClick={handleSave}>Save</MenuItemComponent>
<MenuItemComponent icon={"upload"} disabled={inputDisabled} onClick={onUpload}>Upload</MenuItemComponent>
<MenuItemComponent icon={"create"} disabled={inputDisabled} onClick={handleRename}>Rename</MenuItemComponent>
</MenuComponent>
</div>
</div>
<div className={workSpaceClass}>
<Experiment experiment={experiment} config={experimentConfig} data={data} onDataChange={onDataChange} />
<Experiment
experiment={experiment}
config={experimentConfig}
data={data}
onDataChange={onDataChange}
inputDisabled={inputDisabled}
setInputDisabled={setInputDisabled}
/>
</div>
</div>
);
Expand Down
2 changes: 2 additions & 0 deletions src/mobile-app/components/sensor.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
align-items: center;
flex-grow: 1; /* to allow the label to take up as much room as possible */

@include add-disabled-class();

// for selectable sensor
select {
margin-left: 7px;
Expand Down
33 changes: 19 additions & 14 deletions src/mobile-app/components/sensor.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState, useRef, useMemo, useEffect } from "react";
import classNames from "classnames";
import { SensorValue } from "./sensor-value";
import { Sensor, IConnectDevice, SelectDeviceFn, ITimeSeriesCapabilities, MaxNumberOfTimeSeriesValues, ISensorValues } from "../../sensors/sensor";
import { useSensor } from "../hooks/use-sensor";
Expand All @@ -15,25 +16,26 @@ interface ISensorSelectorProps {
devices: IConnectDevice[];
selectDevice: SelectDeviceFn;
cancel: () => void;
inputDisabled?: boolean;
}

const maxTime = 3;

export const SensorSelectorComponent: React.FC<ISensorSelectorProps> = ({devices, selectDevice, cancel}) => {
export const SensorSelectorComponent: React.FC<ISensorSelectorProps> = ({devices, selectDevice, cancel, inputDisabled}) => {
const sortedDevices = devices.sort((a, b) => a.id.localeCompare(b.id));
const handleCancel = () => cancel();
return (
<div className={css.sensorSelector}>
<div className={css.sensorSelectorHeader}>
<div className={css.sensorSelectorHeaderTitle}>Choose a sensor...</div>
<div className={css.sensorSelectorHeaderButtons}>
<div className={css.sensorSelectorHeaderButton} onClick={handleCancel}>Cancel</div>
<div className={css.sensorSelectorHeaderButton} onClick={inputDisabled ? undefined : handleCancel}>Cancel</div>
</div>
</div>
{sortedDevices.map((device, index) => {
const handleSelectDevice = () => selectDevice(device);
return (
<div key={index} className={css.sensorSelectorItem} onClick={handleSelectDevice}>
<div key={index} className={css.sensorSelectorItem} onClick={inputDisabled ? undefined : handleSelectDevice}>
<div className={css.sensorSelectorItemName}>{device.name}</div>
<div className={css.sensorSelectorItemRssi}>
<SensorStrength rssi={device.adData.rssi} />
Expand All @@ -54,6 +56,7 @@ interface ISensorComponentProps {
selectableSensorId?: any;
setTimeSeriesMeasurementPeriod?: (measurementPeriod: number) => void;
setSelectableSensorId?: (id: any) => void;
inputDisabled?: boolean;
}

const iconClass = {
Expand All @@ -68,7 +71,7 @@ const iconClassHi = {
error: css.errorIcon
};

export const SensorComponent: React.FC<ISensorComponentProps> = ({sensor, manualEntryMode, setManualEntryMode, isTimeSeries, timeSeriesCapabilities, selectableSensorId, setTimeSeriesMeasurementPeriod, setSelectableSensorId}) => {
export const SensorComponent: React.FC<ISensorComponentProps> = ({sensor, manualEntryMode, setManualEntryMode, isTimeSeries, timeSeriesCapabilities, selectableSensorId, setTimeSeriesMeasurementPeriod, setSelectableSensorId, inputDisabled}) => {
const {connected, connecting, deviceName, values, error} = useSensor(sensor);

const [devicesFound, setDevicesFound] = useState<IConnectDevice[]>([]);
Expand Down Expand Up @@ -159,22 +162,24 @@ export const SensorComponent: React.FC<ISensorComponentProps> = ({sensor, manual
</div>
);

const connectionLabelClassName = classNames(css.connectionLabel, {[css.disabled]: inputDisabled});

const renderError = () => (
<div className={css.connectionLabel}>
<div className={connectionLabelClassName}>
{renderIcon("error")}
{error.toString()}
</div>
);

const renderDisconnected = () => (
<div className={css.connectionLabel} onClick={connect}>
<div className={connectionLabelClassName} onClick={inputDisabled ? undefined : connect}>
{renderIcon("disconnected")}
No Sensor Connected
</div>
);

const renderConnecting = () => (
<div className={css.connectionLabel}>
<div className={connectionLabelClassName}>
{renderIcon("connected")}
{inCordova ? "Searching..." : "Connecting..."}
</div>
Expand All @@ -186,14 +191,14 @@ export const SensorComponent: React.FC<ISensorComponentProps> = ({sensor, manual
}

return (
<select onChange={handleSelectSelectableSensor}>
<select onChange={handleSelectSelectableSensor} disabled={inputDisabled}>
{sensor.selectableSensors.map(s => <option key={s.internalId} value={s.internalId}>{s.name}</option>)}
</select>
);
};

const renderConnected = () => (
<div className={css.connectionLabel}>
<div className={connectionLabelClassName}>
{renderIcon("connected")}
Connected: {renderDeviceName()}
</div>
Expand All @@ -207,10 +212,10 @@ export const SensorComponent: React.FC<ISensorComponentProps> = ({sensor, manual
return (
<MenuComponent>
{manualEntryMode && canSwitchModes
? <MenuItemComponent onClick={setSensorMode} icon="sensor">Sensor Mode</MenuItemComponent>
? <MenuItemComponent disabled={inputDisabled} onClick={setSensorMode} icon="sensor">Sensor Mode</MenuItemComponent>
: <>
{connected ? <MenuItemComponent onClick={disconnect}>Disconnect</MenuItemComponent> : <MenuItemComponent icon="settings_input_antenna" onClick={connect}>Connect</MenuItemComponent>}
{canSwitchModes ? <MenuItemComponent onClick={setEditMode} icon="create">Edit Mode</MenuItemComponent> : undefined}
{connected ? <MenuItemComponent disabled={inputDisabled} onClick={disconnect}>Disconnect</MenuItemComponent> : <MenuItemComponent icon="settings_input_antenna" disabled={inputDisabled} onClick={connect}>Connect</MenuItemComponent>}
{canSwitchModes ? <MenuItemComponent disabled={inputDisabled} onClick={setEditMode} icon="create">Edit Mode</MenuItemComponent> : undefined}
</>}
</MenuComponent>
);
Expand Down Expand Up @@ -256,7 +261,7 @@ export const SensorComponent: React.FC<ISensorComponentProps> = ({sensor, manual
<div className={css.tsvInfoRow}>
<div>Samples:</div>
<div>
<select className={css.tsvSampleRate} value={measurementPeriod} onChange={handleMeasurementPeriodChange}>
<select className={css.tsvSampleRate} value={measurementPeriod} onChange={handleMeasurementPeriodChange} disabled={inputDisabled}>
{timeSeriesPeriods.map(p => <option key={p} value={p}>{`${(1000 / p)}/sec`}</option>)}
</select>
</div>
Expand Down Expand Up @@ -330,7 +335,7 @@ export const SensorComponent: React.FC<ISensorComponentProps> = ({sensor, manual
{error ? renderError() : (connected ? renderConnected() : (connecting ? renderConnecting() : renderDisconnected()))}
{renderMenu()}
</div>
{showDeviceSelect ? <SensorSelectorComponent devices={devicesFound} selectDevice={handleSelectDevice} cancel={handleCancelSelectDevice} /> : undefined}
{showDeviceSelect ? <SensorSelectorComponent devices={devicesFound} selectDevice={handleSelectDevice} cancel={handleCancelSelectDevice} inputDisabled={inputDisabled} /> : undefined}
{isTimeSeries ? renderTimeSeries() : renderValues()}
</div>
);
Expand Down
5 changes: 4 additions & 1 deletion src/shared/components/data-table-field.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ $headerBorder: #fff;
display: flex;
justify-content: center;
align-items: center;

@include add-disabled-class($opacity: 0.35);

&.active {
background-color: $sensorGreenLight1;
&.refresh {
Expand All @@ -171,7 +174,7 @@ $headerBorder: #fff;
&.record {
background-color: $sensorGreenLight1;
}
&:hover {
&:hover:not(.disabled) {
cursor: pointer;
}
}
Expand Down
Loading
Loading