Keep track of editing state with query string; allow deleting of program items
This commit is contained in:
parent
116c803ec7
commit
4a5b5ae7d9
@ -1,9 +1,8 @@
|
|||||||
import classNames = require("classnames");
|
import classNames = require("classnames");
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as ReactDOM from "react-dom";
|
import { SortableContainer, SortableElement, SortableHandle, SortEnd } from "react-sortable-hoc";
|
||||||
import { SortableContainer, SortableElement, SortableHandle, SortEnd, arrayMove } from "react-sortable-hoc";
|
import { Button, Form, Icon, List } from "semantic-ui-react";
|
||||||
import { Form, Icon, List } from "semantic-ui-react";
|
|
||||||
|
|
||||||
import { DurationView, SectionChooser } from "@app/components/index";
|
import { DurationView, SectionChooser } from "@app/components/index";
|
||||||
import { Duration } from "@common/Duration";
|
import { Duration } from "@common/Duration";
|
||||||
@ -11,21 +10,31 @@ import { ProgramItem, Section } from "@common/sprinklersRpc";
|
|||||||
|
|
||||||
import "@app/styles/ProgramSequenceView";
|
import "@app/styles/ProgramSequenceView";
|
||||||
|
|
||||||
const Handle = SortableHandle(() => <Icon name="bars"/>);
|
type ItemChangeHandler = (index: number, newItem: ProgramItem) => void;
|
||||||
|
type ItemRemoveHandler = (index: number) => void;
|
||||||
|
|
||||||
|
const Handle = SortableHandle(() => <Button basic icon><Icon name="bars"/></Button>);
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
class ProgramSequenceItem extends React.Component<{
|
class ProgramSequenceItem extends React.Component<{
|
||||||
sequenceItem: ProgramItem, sections: Section[], onChange?: (newItem: ProgramItem) => void,
|
sequenceItem: ProgramItem,
|
||||||
|
idx: number,
|
||||||
|
sections: Section[],
|
||||||
|
editing: boolean,
|
||||||
|
onChange: ItemChangeHandler,
|
||||||
|
onRemove: ItemRemoveHandler,
|
||||||
}> {
|
}> {
|
||||||
renderContent() {
|
renderContent() {
|
||||||
const { sequenceItem, sections } = this.props;
|
const { editing, sequenceItem, sections } = this.props;
|
||||||
const editing = this.props.onChange != null;
|
|
||||||
const section = sections[sequenceItem.section];
|
const section = sections[sequenceItem.section];
|
||||||
const duration = Duration.fromSeconds(sequenceItem.duration);
|
const duration = Duration.fromSeconds(sequenceItem.duration);
|
||||||
|
|
||||||
if (editing) {
|
if (editing) {
|
||||||
return (
|
return (
|
||||||
<Form.Group>
|
<Form.Group>
|
||||||
|
<Button icon negative onClick={this.onRemove}>
|
||||||
|
<Icon name="cancel" />
|
||||||
|
</Button>
|
||||||
<SectionChooser
|
<SectionChooser
|
||||||
label="Section"
|
label="Section"
|
||||||
sections={sections}
|
sections={sections}
|
||||||
@ -50,7 +59,7 @@ class ProgramSequenceItem extends React.Component<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const editing = this.props.onChange != null;
|
const { editing }= this.props;
|
||||||
return (
|
return (
|
||||||
<li className="programSequence-item ui form">
|
<li className="programSequence-item ui form">
|
||||||
{editing ? <Handle /> : <List.Icon name="caret right"/>}
|
{editing ? <Handle /> : <List.Icon name="caret right"/>}
|
||||||
@ -60,44 +69,43 @@ class ProgramSequenceItem extends React.Component<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onSectionChange = (newSection: Section) => {
|
private onSectionChange = (newSection: Section) => {
|
||||||
if (!this.props.onChange) {
|
this.props.onChange(this.props.idx, new ProgramItem({
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.props.onChange(new ProgramItem({
|
|
||||||
...this.props.sequenceItem, section: newSection.id,
|
...this.props.sequenceItem, section: newSection.id,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private onDurationChange = (newDuration: Duration) => {
|
private onDurationChange = (newDuration: Duration) => {
|
||||||
if (!this.props.onChange) {
|
this.props.onChange(this.props.idx, new ProgramItem({
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.props.onChange(new ProgramItem({
|
|
||||||
...this.props.sequenceItem, duration: newDuration.toSeconds(),
|
...this.props.sequenceItem, duration: newDuration.toSeconds(),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onRemove = () => {
|
||||||
|
this.props.onRemove(this.props.idx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProgramSequenceItemD = SortableElement(ProgramSequenceItem);
|
const ProgramSequenceItemD = SortableElement(ProgramSequenceItem);
|
||||||
|
|
||||||
type ItemChangeHandler = (newItem: ProgramItem, index: number) => void;
|
const ProgramSequenceList = SortableContainer(observer((props: {
|
||||||
|
|
||||||
const ProgramSequenceList = SortableContainer(observer(({ className, list, sections, onChange }: {
|
|
||||||
className: string,
|
className: string,
|
||||||
list: ProgramItem[],
|
list: ProgramItem[],
|
||||||
sections: Section[],
|
sections: Section[],
|
||||||
onChange?: ItemChangeHandler,
|
editing: boolean,
|
||||||
|
onChange: ItemChangeHandler,
|
||||||
|
onRemove: ItemRemoveHandler,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { className, list, sections, ...rest } = props;
|
||||||
const listItems = list.map((item, index) => {
|
const listItems = list.map((item, index) => {
|
||||||
const onChangeHandler = onChange ? (newItem: ProgramItem) => onChange(newItem, index) : undefined;
|
|
||||||
const key = `item-${index}`;
|
const key = `item-${index}`;
|
||||||
return (
|
return (
|
||||||
<ProgramSequenceItemD
|
<ProgramSequenceItemD
|
||||||
sequenceItem={item}
|
{...rest}
|
||||||
sections={sections}
|
|
||||||
key={key}
|
key={key}
|
||||||
|
sequenceItem={item}
|
||||||
index={index}
|
index={index}
|
||||||
onChange={onChangeHandler}
|
idx={index}
|
||||||
|
sections={sections}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -112,23 +120,28 @@ class ProgramSequenceView extends React.Component<{
|
|||||||
const { sequence, sections } = this.props;
|
const { sequence, sections } = this.props;
|
||||||
const editing = this.props.editing || false;
|
const editing = this.props.editing || false;
|
||||||
const className = classNames("programSequence", { editing });
|
const className = classNames("programSequence", { editing });
|
||||||
const onChange = editing ? this.changeItem : undefined;
|
|
||||||
return (
|
return (
|
||||||
<ProgramSequenceList
|
<ProgramSequenceList
|
||||||
className={className}
|
className={className}
|
||||||
useDragHandle
|
useDragHandle
|
||||||
list={sequence}
|
list={sequence}
|
||||||
sections={sections}
|
sections={sections}
|
||||||
onChange={onChange}
|
editing={editing}
|
||||||
|
onChange={this.changeItem}
|
||||||
|
onRemove={this.removeItem}
|
||||||
onSortEnd={this.onSortEnd}
|
onSortEnd={this.onSortEnd}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private changeItem: ItemChangeHandler = (newItem, index) => {
|
private changeItem: ItemChangeHandler = (index, newItem) => {
|
||||||
this.props.sequence[index] = newItem;
|
this.props.sequence[index] = newItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private removeItem: ItemRemoveHandler = (index) => {
|
||||||
|
this.props.sequence.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
private onSortEnd = ({oldIndex, newIndex}: SortEnd) => {
|
private onSortEnd = ({oldIndex, newIndex}: SortEnd) => {
|
||||||
const { sequence: array } = this.props;
|
const { sequence: array } = this.props;
|
||||||
if (newIndex >= array.length) {
|
if (newIndex >= array.length) {
|
||||||
|
@ -2,7 +2,7 @@ import { observer } from "mobx-react";
|
|||||||
import { RouterStore } from "mobx-react-router";
|
import { RouterStore } from "mobx-react-router";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { Button, ButtonProps, Table } from "semantic-ui-react";
|
import { Button, ButtonProps, Icon, Table } from "semantic-ui-react";
|
||||||
|
|
||||||
import { ProgramSequenceView, ScheduleView } from "@app/components";
|
import { ProgramSequenceView, ScheduleView } from "@app/components";
|
||||||
import * as rp from "@app/routePaths";
|
import * as rp from "@app/routePaths";
|
||||||
@ -20,9 +20,16 @@ class ProgramRows extends React.Component<{
|
|||||||
|
|
||||||
const { name, running, enabled, schedule, sequence } = program;
|
const { name, running, enabled, schedule, sequence } = program;
|
||||||
|
|
||||||
const buttonStyle: ButtonProps = { size: "small", compact: true };
|
const buttonStyle: ButtonProps = { size: "small", compact: false };
|
||||||
const detailUrl = rp.program(device.id, program.id);
|
const detailUrl = rp.program(device.id, program.id);
|
||||||
|
|
||||||
|
const stopStartButton = (
|
||||||
|
<Button onClick={this.cancelOrRun} {...buttonStyle} positive={!running} negative={running}>
|
||||||
|
<Icon name={running ? "stop" : "play"} />
|
||||||
|
{running ? "Stop" : "Run"}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
|
||||||
const mainRow = (
|
const mainRow = (
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
<Table.Cell className="program--number">{"" + program.id}</Table.Cell>
|
<Table.Cell className="program--number">{"" + program.id}</Table.Cell>
|
||||||
@ -32,13 +39,13 @@ class ProgramRows extends React.Component<{
|
|||||||
<span>{running ? "Running" : "Not running"}</span>
|
<span>{running ? "Running" : "Not running"}</span>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
<Table.Cell>
|
<Table.Cell>
|
||||||
<Button onClick={this.cancelOrRun} {...buttonStyle} positive={!running} negative={running}>
|
{stopStartButton}
|
||||||
{running ? "Stop" : "Run"}
|
|
||||||
</Button>
|
|
||||||
<Button as={Link} to={detailUrl} {...buttonStyle} primary>
|
<Button as={Link} to={detailUrl} {...buttonStyle} primary>
|
||||||
|
<Icon name="edit"/>
|
||||||
Open
|
Open
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={this.toggleExpanded} {...buttonStyle}>
|
<Button onClick={this.toggleExpanded} {...buttonStyle}>
|
||||||
|
<Icon name="list"/>
|
||||||
{expanded ? "Hide Details" : "Show Details"}
|
{expanded ? "Hide Details" : "Show Details"}
|
||||||
</Button>
|
</Button>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Form, Header, Segment } from "semantic-ui-react";
|
import { Form, Header, Icon, Segment } from "semantic-ui-react";
|
||||||
|
|
||||||
import { DurationView, SectionChooser } from "@app/components";
|
import { DurationView, SectionChooser } from "@app/components";
|
||||||
import { UiStore } from "@app/state";
|
import { UiStore } from "@app/state";
|
||||||
@ -47,6 +47,7 @@ export default class RunSectionForm extends React.Component<{
|
|||||||
onClick={this.run}
|
onClick={this.run}
|
||||||
disabled={!this.isValid}
|
disabled={!this.isValid}
|
||||||
>
|
>
|
||||||
|
<Icon name="play"/>
|
||||||
Run
|
Run
|
||||||
</Form.Button>
|
</Form.Button>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -21,7 +21,7 @@ function PausedState({ paused, togglePaused }: PausedStateProps) {
|
|||||||
"sectionRunner--pausedState-unpaused": !paused,
|
"sectionRunner--pausedState-unpaused": !paused,
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<Button className={classes} size="tiny" onClick={togglePaused}>
|
<Button className={classes} size="medium" onClick={togglePaused}>
|
||||||
<Icon name={paused ? "pause" : "play"}/>
|
<Icon name={paused ? "pause" : "play"}/>
|
||||||
{paused ? "Paused" : "Processing"}
|
{paused ? "Paused" : "Processing"}
|
||||||
</Button>
|
</Button>
|
||||||
@ -137,7 +137,7 @@ export default class SectionRunnerView extends React.Component<{
|
|||||||
return (
|
return (
|
||||||
<Segment className="sectionRunner">
|
<Segment className="sectionRunner">
|
||||||
<div style={{ display: "flex", alignContent: "baseline" }}>
|
<div style={{ display: "flex", alignContent: "baseline" }}>
|
||||||
<h4 style={{ marginBottom: 0 }}>Section Runner Queue</h4>
|
<h3 style={{ marginBottom: 0 }}>Section Runner Queue</h3>
|
||||||
<div className="flex-spacer"/>
|
<div className="flex-spacer"/>
|
||||||
<PausedState paused={paused} togglePaused={this.togglePaused}/>
|
<PausedState paused={paused} togglePaused={this.togglePaused}/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { createViewModel, IViewModel } from "mobx-utils";
|
import { createViewModel, IViewModel } from "mobx-utils";
|
||||||
|
import * as qs from "query-string";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { RouteComponentProps } from "react-router";
|
import { RouteComponentProps } from "react-router";
|
||||||
import { Button, CheckboxProps, Form, Input, InputOnChangeData, Menu, Modal } from "semantic-ui-react";
|
import { Button, CheckboxProps, Form, Icon, Input, InputOnChangeData, Menu, Modal } from "semantic-ui-react";
|
||||||
|
|
||||||
import { ProgramSequenceView, ScheduleView } from "@app/components";
|
import { ProgramSequenceView, ScheduleView } from "@app/components";
|
||||||
import * as rp from "@app/routePaths";
|
import * as rp from "@app/routePaths";
|
||||||
@ -10,26 +11,20 @@ import { AppState, injectState } from "@app/state";
|
|||||||
import log from "@common/logger";
|
import log from "@common/logger";
|
||||||
import { Program, SprinklersDevice } from "@common/sprinklersRpc";
|
import { Program, SprinklersDevice } from "@common/sprinklersRpc";
|
||||||
|
|
||||||
|
interface ProgramPageProps extends RouteComponentProps<{ deviceId: string, programId: string }> {
|
||||||
|
appState: AppState;
|
||||||
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
class ProgramPage extends React.Component<{
|
class ProgramPage extends React.Component<ProgramPageProps> {
|
||||||
appState: AppState,
|
|
||||||
} & RouteComponentProps<{ deviceId: string, programId: number }>, {
|
|
||||||
programView: Program & IViewModel<Program> | undefined,
|
|
||||||
}> {
|
|
||||||
private device!: SprinklersDevice;
|
|
||||||
private program!: Program;
|
|
||||||
|
|
||||||
constructor(p: any) {
|
|
||||||
super(p);
|
|
||||||
this.state = {
|
|
||||||
programView: undefined,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
get isEditing(): boolean {
|
get isEditing(): boolean {
|
||||||
return this.state.programView != null;
|
return qs.parse(this.props.location.search).editing != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device!: SprinklersDevice;
|
||||||
|
program!: Program;
|
||||||
|
programView: Program & IViewModel<Program> | null = null;
|
||||||
|
|
||||||
renderName(program: Program) {
|
renderName(program: Program) {
|
||||||
const { name } = program;
|
const { name } = program;
|
||||||
if (this.isEditing) {
|
if (this.isEditing) {
|
||||||
@ -64,9 +59,11 @@ class ProgramPage extends React.Component<{
|
|||||||
editButtons = (
|
editButtons = (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Button primary onClick={this.save}>
|
<Button primary onClick={this.save}>
|
||||||
|
<Icon name="save" />
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
<Button negative onClick={this.cancelEditing}>
|
<Button negative onClick={this.stopEditing}>
|
||||||
|
<Icon name="cancel" />
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
@ -74,17 +71,23 @@ class ProgramPage extends React.Component<{
|
|||||||
} else {
|
} else {
|
||||||
editButtons = (
|
editButtons = (
|
||||||
<Button primary onClick={this.startEditing}>
|
<Button primary onClick={this.startEditing}>
|
||||||
|
<Icon name="edit"/>
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
const stopStartButton = (
|
||||||
|
<Button onClick={this.cancelOrRun} positive={!running} negative={running}>
|
||||||
|
<Icon name={running ? "stop" : "play"} />
|
||||||
|
{running ? "Stop" : "Run"}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<Modal.Actions>
|
<Modal.Actions>
|
||||||
<Button positive={!running} negative={running} onClick={this.cancelOrRun}>
|
{stopStartButton}
|
||||||
{running ? "Stop" : "Run"}
|
|
||||||
</Button>
|
|
||||||
{editButtons}
|
{editButtons}
|
||||||
<Button onClick={this.close}>
|
<Button onClick={this.close}>
|
||||||
|
<Icon name="arrow left" />
|
||||||
Close
|
Close
|
||||||
</Button>
|
</Button>
|
||||||
</Modal.Actions>
|
</Modal.Actions>
|
||||||
@ -92,17 +95,32 @@ class ProgramPage extends React.Component<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { deviceId, programId } = this.props.match.params;
|
const { deviceId, programId: pid } = this.props.match.params;
|
||||||
const device = this.device = this.props.appState.sprinklersRpc.getDevice(deviceId);
|
const programId = Number(pid);
|
||||||
// TODO: check programId
|
// tslint:disable-next-line:prefer-conditional-expression
|
||||||
if (device.programs.length <= programId || !device.programs[programId]) {
|
if (!this.device || this.device.id !== deviceId) {
|
||||||
return null;
|
this.device = this.props.appState.sprinklersRpc.getDevice(deviceId);
|
||||||
|
}
|
||||||
|
// tslint:disable-next-line:prefer-conditional-expression
|
||||||
|
if (!this.program || this.program.id !== programId) {
|
||||||
|
if (this.device.programs.length > programId && programId >= 0) {
|
||||||
|
this.program = this.device.programs[programId];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.isEditing) {
|
||||||
|
if (this.programView == null && this.program) {
|
||||||
|
this.programView = createViewModel(this.program);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.programView != null) {
|
||||||
|
this.programView = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.program = device.programs[programId];
|
|
||||||
|
|
||||||
const { programView } = this.state;
|
const program = this.programView || this.program;
|
||||||
const program = programView || this.program;
|
const editing = this.isEditing;
|
||||||
const editing = programView != null;
|
|
||||||
|
|
||||||
const { running, enabled, schedule, sequence } = program;
|
const { running, enabled, schedule, sequence } = program;
|
||||||
|
|
||||||
@ -144,37 +162,25 @@ class ProgramPage extends React.Component<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private startEditing = () => {
|
private startEditing = () => {
|
||||||
let { programView } = this.state;
|
this.props.history.push({ search: qs.stringify({ editing: true }) });
|
||||||
if (programView) { // stop editing, so save
|
|
||||||
programView.submit();
|
|
||||||
programView = undefined;
|
|
||||||
} else { // start editing
|
|
||||||
programView = createViewModel(this.program);
|
|
||||||
}
|
|
||||||
this.setState({ programView });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private save = () => {
|
private save = () => {
|
||||||
let { programView } = this.state;
|
if (!this.programView || !this.program) {
|
||||||
if (programView) { // stop editing, so save
|
return;
|
||||||
programView.submit();
|
|
||||||
programView = undefined;
|
|
||||||
}
|
}
|
||||||
this.setState({ programView });
|
this.programView.submit();
|
||||||
this.program.update()
|
this.program.update()
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
log.info({ data }, "Program updated");
|
log.info({ data }, "Program updated");
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
log.error({ err }, "error updating Program");
|
log.error({ err }, "error updating Program");
|
||||||
});
|
});
|
||||||
|
this.stopEditing();
|
||||||
}
|
}
|
||||||
|
|
||||||
private cancelEditing = () => {
|
private stopEditing = () => {
|
||||||
let { programView } = this.state;
|
this.props.history.push({ search: "" });
|
||||||
if (programView) {
|
|
||||||
programView = undefined; // stop editing
|
|
||||||
}
|
|
||||||
this.setState({ programView });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private close = () => {
|
private close = () => {
|
||||||
@ -183,16 +189,14 @@ class ProgramPage extends React.Component<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onNameChange = (e: any, p: InputOnChangeData) => {
|
private onNameChange = (e: any, p: InputOnChangeData) => {
|
||||||
const { programView } = this.state;
|
if (this.programView) {
|
||||||
if (programView) {
|
this.programView.name = p.value;
|
||||||
programView.name = p.value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onEnabledChange = (e: any, p: CheckboxProps) => {
|
private onEnabledChange = (e: any, p: CheckboxProps) => {
|
||||||
const { programView } = this.state;
|
if (this.programView) {
|
||||||
if (programView) {
|
this.programView.enabled = p.checked!;
|
||||||
programView.enabled = p.checked!;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,11 @@
|
|||||||
z-index: 2000;
|
z-index: 2000;
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-bottom: .5em;
|
margin-bottom: .5em;
|
||||||
i.icon {
|
.fields {
|
||||||
margin: .5rem;
|
margin: 0em 0em 1em !important;
|
||||||
|
}
|
||||||
|
.ui.icon.button {
|
||||||
|
height: fit-content;
|
||||||
}
|
}
|
||||||
.header {
|
.header {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
"@types/object-assign": "^4.0.30",
|
"@types/object-assign": "^4.0.30",
|
||||||
"@types/pino": "^4.16.0",
|
"@types/pino": "^4.16.0",
|
||||||
"@types/prop-types": "^15.5.4",
|
"@types/prop-types": "^15.5.4",
|
||||||
|
"@types/query-string": "^6.1.0",
|
||||||
"@types/react": "16.4.7",
|
"@types/react": "16.4.7",
|
||||||
"@types/react-dom": "16.0.6",
|
"@types/react-dom": "16.0.6",
|
||||||
"@types/react-hot-loader": "^4.1.0",
|
"@types/react-hot-loader": "^4.1.0",
|
||||||
@ -100,6 +101,7 @@
|
|||||||
"postcss-preset-env": "^5.2.3",
|
"postcss-preset-env": "^5.2.3",
|
||||||
"promise": "^8.0.1",
|
"promise": "^8.0.1",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
|
"query-string": "^6.1.0",
|
||||||
"react": "16.4.1",
|
"react": "16.4.1",
|
||||||
"react-dev-utils": "^5.0.1",
|
"react-dev-utils": "^5.0.1",
|
||||||
"react-dom": "16.4.1",
|
"react-dom": "16.4.1",
|
||||||
|
15
yarn.lock
15
yarn.lock
@ -111,6 +111,10 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
|
"@types/query-string@^6.1.0":
|
||||||
|
version "6.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/query-string/-/query-string-6.1.0.tgz#5f721f9503bdf517d474c66cf4423da5dd2d5698"
|
||||||
|
|
||||||
"@types/range-parser@*":
|
"@types/range-parser@*":
|
||||||
version "1.2.2"
|
version "1.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.2.tgz#fa8e1ad1d474688a757140c91de6dace6f4abc8d"
|
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.2.tgz#fa8e1ad1d474688a757140c91de6dace6f4abc8d"
|
||||||
@ -5727,6 +5731,13 @@ qs@~6.4.0:
|
|||||||
version "6.4.0"
|
version "6.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
|
||||||
|
|
||||||
|
query-string@^6.1.0:
|
||||||
|
version "6.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.1.0.tgz#01e7d69f6a0940dac67a937d6c6325647aa4532a"
|
||||||
|
dependencies:
|
||||||
|
decode-uri-component "^0.2.0"
|
||||||
|
strict-uri-encode "^2.0.0"
|
||||||
|
|
||||||
querystring-es3@^0.2.0:
|
querystring-es3@^0.2.0:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
|
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
|
||||||
@ -6781,6 +6792,10 @@ stream-to@~0.2.0:
|
|||||||
version "0.2.2"
|
version "0.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/stream-to/-/stream-to-0.2.2.tgz#84306098d85fdb990b9fa300b1b3ccf55e8ef01d"
|
resolved "https://registry.yarnpkg.com/stream-to/-/stream-to-0.2.2.tgz#84306098d85fdb990b9fa300b1b3ccf55e8ef01d"
|
||||||
|
|
||||||
|
strict-uri-encode@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
|
||||||
|
|
||||||
string-width@^1.0.1, string-width@^1.0.2:
|
string-width@^1.0.1, string-width@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user