Fixed ts linting issues
This commit is contained in:
Родитель
0eccc58e0a
Коммит
f22d79f6cd
|
@ -9928,7 +9928,7 @@
|
|||
},
|
||||
"pretty-bytes": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz",
|
||||
"resolved": "http://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz",
|
||||
"integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=",
|
||||
"requires": {
|
||||
"get-stdin": "^4.0.1",
|
||||
|
@ -12251,7 +12251,7 @@
|
|||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
|
||||
},
|
||||
"through2": {
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"scripts": {
|
||||
"start": "nf start -p 3000",
|
||||
"build": "react-scripts build",
|
||||
"pretest": "./node_modules/.bin/tslint 'src/**/*.ts'",
|
||||
"pretest": "./node_modules/.bin/tslint 'src/**/*.ts*'",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject",
|
||||
"electron": "webpack --config ./config/webpack.dev.config.js && electron .",
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
import { Provider } from 'react-redux';
|
||||
import createReduxStore from './store/store';
|
||||
import initialState from './store/initialState';
|
||||
import ApplicationState from './store/applicationState';
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import App from "./App";
|
||||
import { Provider } from "react-redux";
|
||||
import createReduxStore from "./store/store";
|
||||
import initialState from "./store/initialState";
|
||||
import ApplicationState from "./store/applicationState";
|
||||
|
||||
it('renders without crashing', () => {
|
||||
const defaultState: ApplicationState = initialState;
|
||||
const store = createReduxStore(defaultState);
|
||||
const div = document.createElement('div');
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>, div);
|
||||
ReactDOM.unmountComponentAtNode(div);
|
||||
it("renders without crashing", () => {
|
||||
const defaultState: ApplicationState = initialState;
|
||||
const store = createReduxStore(defaultState);
|
||||
const div = document.createElement("div");
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>, div);
|
||||
ReactDOM.unmountComponentAtNode(div);
|
||||
});
|
||||
|
|
28
src/App.tsx
28
src/App.tsx
|
@ -1,33 +1,33 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import Navbar from './components/shell/navbar';
|
||||
import Sidebar from './components/shell/sidebar';
|
||||
import MainContentRouter from './components/shell/mainContentRouter';
|
||||
import ApplicationState, { IProject } from './store/applicationState';
|
||||
import './App.scss';
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { BrowserRouter as Router } from "react-router-dom";
|
||||
import Navbar from "./components/shell/navbar";
|
||||
import Sidebar from "./components/shell/sidebar";
|
||||
import MainContentRouter from "./components/shell/mainContentRouter";
|
||||
import ApplicationState, { IProject } from "./store/applicationState";
|
||||
import "./App.scss";
|
||||
|
||||
interface AppProps {
|
||||
currentProject?: IProject
|
||||
interface IAppProps {
|
||||
currentProject?: IProject;
|
||||
}
|
||||
|
||||
function mapStateToProps(state: ApplicationState) {
|
||||
return {
|
||||
currentProject: state.currentProject
|
||||
currentProject: state.currentProject,
|
||||
};
|
||||
}
|
||||
|
||||
@connect(mapStateToProps)
|
||||
class App extends React.Component<AppProps> {
|
||||
class App extends React.Component<IAppProps> {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
currentProject: this.props.currentProject
|
||||
currentProject: this.props.currentProject,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
return (
|
||||
<Router>
|
||||
<div className="app-shell">
|
||||
|
|
|
@ -6,8 +6,7 @@ const projectService = new ProjectService();
|
|||
|
||||
export default interface IProjectActions {
|
||||
loadProjects(): Promise<IProject[]>;
|
||||
loadProject(projectId: string): Promise<IProject>;
|
||||
loadProject(project: IProject): Promise<IProject>;
|
||||
loadProject(value: IProject | string): Promise<IProject>;
|
||||
saveProject(project: IProject): Promise<IProject>;
|
||||
deleteProject(project: IProject): Promise<void>;
|
||||
closeProject();
|
||||
|
@ -18,18 +17,17 @@ export function loadProject(value: string | IProject) {
|
|||
try {
|
||||
let project: IProject = value as IProject;
|
||||
|
||||
if (typeof (value) === 'string') {
|
||||
if (typeof (value) === "string") {
|
||||
project = await projectService.get(value);
|
||||
}
|
||||
|
||||
dispatch({ type: ActionTypes.LOAD_PROJECT_SUCCESS, project: project });
|
||||
dispatch({ type: ActionTypes.LOAD_PROJECT_SUCCESS, project });
|
||||
|
||||
return project;
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function loadProjects() {
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { SyntheticEvent } from 'react'
|
||||
import './condensedList.scss';
|
||||
import { Link } from 'react-router-dom';
|
||||
import React, { SyntheticEvent } from "react";
|
||||
import "./condensedList.scss";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
interface CondensedListProps {
|
||||
title: string,
|
||||
items: any[],
|
||||
newLinkTo?: string,
|
||||
interface ICondensedListProps {
|
||||
title: string;
|
||||
items: any[];
|
||||
newLinkTo?: string;
|
||||
onClick?: (item) => void;
|
||||
onDelete?: (item) => void;
|
||||
Component: any
|
||||
Component: any;
|
||||
}
|
||||
|
||||
export default class CondensedList extends React.Component<CondensedListProps> {
|
||||
export default class CondensedList extends React.Component<ICondensedListProps> {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
|
@ -19,22 +19,7 @@ export default class CondensedList extends React.Component<CondensedListProps> {
|
|||
this.onItemDelete = this.onItemDelete.bind(this);
|
||||
}
|
||||
|
||||
onItemClick = (e, item) => {
|
||||
if (this.props.onClick) {
|
||||
this.props.onClick(item);
|
||||
}
|
||||
}
|
||||
|
||||
onItemDelete = (e: SyntheticEvent, item) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
if (this.props.onDelete) {
|
||||
this.props.onDelete(item);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
const { title, items, newLinkTo, Component } = this.props;
|
||||
|
||||
return (
|
||||
|
@ -57,10 +42,28 @@ export default class CondensedList extends React.Component<CondensedListProps> {
|
|||
}
|
||||
{(items && items.length > 0) &&
|
||||
<ul className="condensed-list-items">
|
||||
{items.map(item => <Component key={item.id} item={item} onClick={(e) => this.onItemClick(e, item)} onDelete={(e) => this.onItemDelete(e, item)} />)}
|
||||
{items.map((item) => <Component key={item.id}
|
||||
item={item}
|
||||
onClick={(e) => this.onItemClick(e, item)}
|
||||
onDelete={(e) => this.onItemDelete(e, item)} />)}
|
||||
</ul>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private onItemClick = (e, item) => {
|
||||
if (this.props.onClick) {
|
||||
this.props.onClick(item);
|
||||
}
|
||||
}
|
||||
|
||||
private onItemDelete = (e: SyntheticEvent, item) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
if (this.props.onDelete) {
|
||||
this.props.onDelete(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import React from "react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
|
||||
export default function ConditionalNavLink({ to, disabled, ...props }) {
|
||||
if (disabled) {
|
||||
return (<span className="disabled" title={props.title} >{props.children}</span>)
|
||||
return (<span className="disabled" title={props.title} >{props.children}</span>);
|
||||
} else {
|
||||
return (<NavLink title={props.title} to={to}>{props.children}</NavLink>)
|
||||
return (<NavLink title={props.title} to={to}>{props.children}</NavLink>);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
import React from 'react';
|
||||
import ConnectionPicker from './connectionPicker';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import { mount } from 'enzyme';
|
||||
import { IConnection } from '../../store/applicationState';
|
||||
import React from "react";
|
||||
import ConnectionPicker from "./connectionPicker";
|
||||
import { BrowserRouter as Router } from "react-router-dom";
|
||||
import { mount } from "enzyme";
|
||||
import { IConnection } from "../../store/applicationState";
|
||||
|
||||
describe('Connection Picker Component', () => {
|
||||
describe("Connection Picker Component", () => {
|
||||
let wrapper: any = null;
|
||||
let connections: IConnection[] = null;
|
||||
let onChangeHandler: (value: any) => void;;
|
||||
let onChangeHandler: (value: any) => void;
|
||||
|
||||
beforeEach(() => {
|
||||
connections = [
|
||||
{ id: '1', 'name': 'Connection 1', providerType: 'localFileSystemProxy', providerOptions: null },
|
||||
{ id: '2', 'name': 'Connection 2', providerType: 'localFileSystemProxy', providerOptions: null },
|
||||
{ id: '3', 'name': 'Connection 3', providerType: 'localFileSystemProxy', providerOptions: null },
|
||||
{ id: '4', 'name': 'Connection 4', providerType: 'localFileSystemProxy', providerOptions: null },
|
||||
{ id: "1", name: "Connection 1", providerType: "localFileSystemProxy", providerOptions: null },
|
||||
{ id: "2", name: "Connection 2", providerType: "localFileSystemProxy", providerOptions: null },
|
||||
{ id: "3", name: "Connection 3", providerType: "localFileSystemProxy", providerOptions: null },
|
||||
{ id: "4", name: "Connection 4", providerType: "localFileSystemProxy", providerOptions: null },
|
||||
];
|
||||
|
||||
const options = {
|
||||
connections: connections
|
||||
connections,
|
||||
};
|
||||
|
||||
onChangeHandler = jest.fn();
|
||||
|
@ -26,30 +26,30 @@ describe('Connection Picker Component', () => {
|
|||
wrapper = mount(
|
||||
<Router>
|
||||
<ConnectionPicker
|
||||
value={null}
|
||||
value=""
|
||||
options={options}
|
||||
onChange={onChangeHandler}
|
||||
/>
|
||||
</Router>
|
||||
</Router>,
|
||||
);
|
||||
});
|
||||
|
||||
it('renders a default "Select Connection" option', () => {
|
||||
const firstOption = wrapper.find('option').first();
|
||||
expect(firstOption.text()).toEqual('Select Connection');
|
||||
it("renders a default 'Select Connection' option", () => {
|
||||
const firstOption = wrapper.find("option").first();
|
||||
expect(firstOption.text()).toEqual("Select Connection");
|
||||
});
|
||||
|
||||
it('renders options from connection props', () => {
|
||||
it("renders options from connection props", () => {
|
||||
expect(wrapper).not.toBeNull();
|
||||
const optionElements = wrapper.find('option');
|
||||
const optionElements = wrapper.find("option");
|
||||
expect(optionElements.length).toEqual(connections.length + 1);
|
||||
expect(wrapper.prop('value')).not.toBeDefined();
|
||||
expect(wrapper.prop("value")).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('raises onChange event when dropdown is modified', () => {
|
||||
const connectionId = '2';
|
||||
it("raises onChange event when dropdown is modified", () => {
|
||||
const connectionId = "2";
|
||||
|
||||
wrapper.find('select').simulate('change', { target: { value: connectionId } });
|
||||
wrapper.find("select").simulate("change", { target: { value: connectionId } });
|
||||
expect(onChangeHandler).toBeCalledWith(connectionId);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,50 +1,40 @@
|
|||
import React from 'react';
|
||||
import { IConnection } from '../../store/applicationState';
|
||||
import { Link } from 'react-router-dom';
|
||||
import React from "react";
|
||||
import { IConnection } from "../../store/applicationState";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
interface ConnectionPickerProps {
|
||||
interface IConnectionPickerProps {
|
||||
id?: string;
|
||||
value: any;
|
||||
onChange: (value) => void;
|
||||
options?: {
|
||||
connections: IConnection[]
|
||||
}
|
||||
connections: IConnection[],
|
||||
};
|
||||
}
|
||||
|
||||
interface ConnectionPickerState {
|
||||
interface IConnectionPickerState {
|
||||
value: any;
|
||||
}
|
||||
|
||||
export default class ConnectionPicker extends React.Component<ConnectionPickerProps, ConnectionPickerState> {
|
||||
export default class ConnectionPicker extends React.Component<IConnectionPickerProps, IConnectionPickerState> {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
this.state = {
|
||||
value: this.props.value
|
||||
value: this.props.value,
|
||||
};
|
||||
|
||||
this.onChange = this.onChange.bind(this);
|
||||
}
|
||||
|
||||
onChange = (e) => {
|
||||
const selectedConnection = this.props.options.connections.find(connection => connection.id === e.target.value);
|
||||
|
||||
if (selectedConnection) {
|
||||
this.setState({
|
||||
value: selectedConnection.id
|
||||
}, () => this.props.onChange(selectedConnection.id));
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
public componentDidUpdate(prevProps) {
|
||||
if (prevProps.value !== this.props.value) {
|
||||
this.setState({
|
||||
value: this.props.value
|
||||
value: this.props.value || "",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let { id, options } = this.props;
|
||||
public render() {
|
||||
const { id, options } = this.props;
|
||||
const connections = options.connections || [];
|
||||
|
||||
const { value } = this.state;
|
||||
|
@ -53,7 +43,9 @@ export default class ConnectionPicker extends React.Component<ConnectionPickerPr
|
|||
<div className="input-group">
|
||||
<select id={id} value={value} onChange={this.onChange} className="form-control">
|
||||
<option value="">Select Connection</option>
|
||||
{connections.map(connection => <option key={connection.id} value={connection.id}>{connection.name}</option>)}
|
||||
{connections.map((connection) =>
|
||||
<option key={connection.id} value={connection.id}>{connection.name}</option>)
|
||||
}
|
||||
</select>
|
||||
<div className="input-group-append">
|
||||
<Link to="/connections/create" className="btn btn-primary" type="button">Add Connection</Link>
|
||||
|
@ -61,4 +53,15 @@ export default class ConnectionPicker extends React.Component<ConnectionPickerPr
|
|||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private onChange = (e) => {
|
||||
const selectedConnection = this.props.options.connections
|
||||
.find((connection) => connection.id === e.target.value);
|
||||
|
||||
if (selectedConnection) {
|
||||
this.setState({
|
||||
value: selectedConnection.id,
|
||||
}, () => this.props.onChange(selectedConnection.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import React, { SyntheticEvent } from 'react';
|
||||
import shortid from 'shortid';
|
||||
import HtmlFileReader from '../../common/htmlFileReader';
|
||||
import React, { SyntheticEvent } from "react";
|
||||
import shortid from "shortid";
|
||||
import HtmlFileReader from "../../common/htmlFileReader";
|
||||
|
||||
interface FilePickerProps {
|
||||
ref: React.RefObject<FilePicker>,
|
||||
interface IFilePickerProps {
|
||||
ref: React.RefObject<FilePicker>;
|
||||
onChange: (sender: SyntheticEvent, fileText: string | ArrayBuffer) => void;
|
||||
onError: (sender: SyntheticEvent, error: any) => void;
|
||||
}
|
||||
|
||||
export default class FilePicker extends React.Component<FilePickerProps> {
|
||||
export default class FilePicker extends React.Component<IFilePickerProps> {
|
||||
private fileInput;
|
||||
|
||||
constructor(props, context) {
|
||||
|
@ -18,24 +18,24 @@ export default class FilePicker extends React.Component<FilePickerProps> {
|
|||
this.onFileUploaded = this.onFileUploaded.bind(this);
|
||||
}
|
||||
|
||||
onFileUploaded = (e) => {
|
||||
if (e.currentTarget.files.length === 0) {
|
||||
this.props.onError(e, 'No files were selected');
|
||||
}
|
||||
|
||||
const reader = new HtmlFileReader();
|
||||
reader.readAsText(e.currentTarget.files[0])
|
||||
.then(fileText => this.props.onChange(e, fileText))
|
||||
.catch(err => this.props.onError(e, err));
|
||||
}
|
||||
|
||||
upload = () => {
|
||||
public upload = () => {
|
||||
this.fileInput.current.click();
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
return (
|
||||
<input id={shortid.generate()} ref={this.fileInput} type="file" onChange={this.onFileUploaded} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private onFileUploaded = (e) => {
|
||||
if (e.currentTarget.files.length === 0) {
|
||||
this.props.onError(e, "No files were selected");
|
||||
}
|
||||
|
||||
const reader = new HtmlFileReader();
|
||||
reader.readAsText(e.currentTarget.files[0])
|
||||
.then((fileText) => this.props.onChange(e, fileText))
|
||||
.catch((err) => this.props.onError(e, err));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,40 +1,31 @@
|
|||
import React from 'react';
|
||||
import { LocalFileSystemProxy } from '../../providers/storage/localFileSystemProxy';
|
||||
import React from "react";
|
||||
import { LocalFileSystemProxy } from "../../providers/storage/localFileSystemProxy";
|
||||
|
||||
interface LocalFolderPickerProps {
|
||||
interface ILocalFolderPickerProps {
|
||||
id: string;
|
||||
value: any;
|
||||
onChange: (value) => void;
|
||||
}
|
||||
|
||||
interface LocalFolderPickerState {
|
||||
value: any
|
||||
interface ILocalFolderPickerState {
|
||||
value: any;
|
||||
}
|
||||
|
||||
export default class LocalFolderPicker extends React.Component<LocalFolderPickerProps, LocalFolderPickerState> {
|
||||
export default class LocalFolderPicker extends React.Component<ILocalFolderPickerProps, ILocalFolderPickerState> {
|
||||
private localFileSystem: LocalFileSystemProxy;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
value: this.props.value
|
||||
value: this.props.value,
|
||||
};
|
||||
|
||||
this.localFileSystem = new LocalFileSystemProxy();
|
||||
this.selectLocalFolder = this.selectLocalFolder.bind(this);
|
||||
}
|
||||
|
||||
selectLocalFolder = async () => {
|
||||
const filePath = await this.localFileSystem.selectContainer();
|
||||
if (filePath) {
|
||||
this.setState({
|
||||
value: filePath
|
||||
}, () => this.props.onChange(filePath));
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
const { id } = this.props;
|
||||
const { value } = this.state;
|
||||
|
||||
|
@ -42,9 +33,21 @@ export default class LocalFolderPicker extends React.Component<LocalFolderPicker
|
|||
<div className="input-group">
|
||||
<input id={id} type="text" className="form-control" value={value} readOnly />
|
||||
<div className="input-group-append">
|
||||
<button className="btn btn-primary" type="button" onClick={this.selectLocalFolder}>Select Folder</button>
|
||||
<button className="btn btn-primary"
|
||||
type="button"
|
||||
onClick={this.selectLocalFolder}>Select Folder
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private selectLocalFolder = async () => {
|
||||
const filePath = await this.localFileSystem.selectContainer();
|
||||
if (filePath) {
|
||||
this.setState({
|
||||
value: filePath,
|
||||
}, () => this.props.onChange(filePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import React from 'react'
|
||||
import './tagsInput.scss'
|
||||
import { WithContext as ReactTags } from 'react-tag-input';
|
||||
import React from "react";
|
||||
import "./tagsInput.scss";
|
||||
import { WithContext as ReactTags } from "react-tag-input";
|
||||
|
||||
|
||||
interface TagsInputProps {
|
||||
interface ITagsInputProps {
|
||||
tags: any;
|
||||
onChange: (value) => void;
|
||||
}
|
||||
|
||||
interface TagsInputState {
|
||||
interface ITagsInputState {
|
||||
tags: any;
|
||||
}
|
||||
|
||||
|
@ -19,36 +18,49 @@ const KeyCodes = {
|
|||
|
||||
const delimiters = [KeyCodes.comma, KeyCodes.enter];
|
||||
|
||||
export default class TagsInput extends React.Component<TagsInputProps, TagsInputState> {
|
||||
export default class TagsInput extends React.Component<ITagsInputProps, ITagsInputState> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
tags: []
|
||||
}
|
||||
tags: [],
|
||||
};
|
||||
this.handleDelete = this.handleDelete.bind(this);
|
||||
this.handleAddition = this.handleAddition.bind(this);
|
||||
this.handleDrag = this.handleDrag.bind(this);
|
||||
}
|
||||
|
||||
convertToFlatList(tags) {
|
||||
return tags.map(element => element.text).join();
|
||||
public render() {
|
||||
const { tags } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<ReactTags tags={tags}
|
||||
handleDelete={this.handleDelete}
|
||||
handleAddition={this.handleAddition}
|
||||
handleDrag={this.handleDrag}
|
||||
delimiters={delimiters} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
handleAddition = (tag) => {
|
||||
private convertToFlatList(tags) {
|
||||
return tags.map((element) => element.text).join();
|
||||
}
|
||||
|
||||
private handleAddition = (tag) => {
|
||||
this.setState({
|
||||
tags: [...this.state.tags, tag]
|
||||
tags: [...this.state.tags, tag],
|
||||
}, () => this.props.onChange(this.convertToFlatList(this.state.tags)));
|
||||
}
|
||||
|
||||
handleDelete = (i) => {
|
||||
private handleDelete = (i) => {
|
||||
const { tags } = this.state;
|
||||
this.setState({
|
||||
tags: tags.filter((tag, index) => index !== i),
|
||||
}, () => this.props.onChange(this.convertToFlatList(this.state.tags)));
|
||||
}
|
||||
|
||||
handleDrag = (tag, currPos, newPos) => {
|
||||
private handleDrag = (tag, currPos, newPos) => {
|
||||
const tags = [...this.state.tags];
|
||||
const newTags = tags.slice();
|
||||
|
||||
|
@ -59,18 +71,4 @@ export default class TagsInput extends React.Component<TagsInputProps, TagsInput
|
|||
this.setState({ tags: newTags },
|
||||
() => this.props.onChange(this.convertToFlatList(this.state.tags)));
|
||||
}
|
||||
|
||||
render() {
|
||||
const { tags } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<ReactTags tags={tags}
|
||||
handleDelete={this.handleDelete}
|
||||
handleAddition={this.handleAddition}
|
||||
handleDrag={this.handleDrag}
|
||||
delimiters={delimiters} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import React from "react";
|
||||
|
||||
export default class ActiveLearningPage extends React.Component {
|
||||
render() {
|
||||
public render() {
|
||||
return (
|
||||
<div>ActiveLearningPage</div>
|
||||
);
|
||||
|
|
|
@ -1,41 +1,41 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import IApplicationActions, * as applicationActions from '../../../actions/applicationActions';
|
||||
import ApplicationState, { IAppSettings } from '../../../store/applicationState';
|
||||
import Form from 'react-jsonschema-form'
|
||||
import formSchema from './appSettings.json';
|
||||
import uiSchema from './appSettings.ui.json';
|
||||
import './appSettings.scss';
|
||||
import ConnectionPicker from '../../common/connectionPicker';
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { bindActionCreators } from "redux";
|
||||
import IApplicationActions, * as applicationActions from "../../../actions/applicationActions";
|
||||
import ApplicationState, { IAppSettings } from "../../../store/applicationState";
|
||||
import Form from "react-jsonschema-form";
|
||||
import formSchema from "./appSettings.json";
|
||||
import uiSchema from "./appSettings.ui.json";
|
||||
import "./appSettings.scss";
|
||||
import ConnectionPicker from "../../common/connectionPicker";
|
||||
|
||||
interface IAppSettingsProps {
|
||||
appSettings: IAppSettings,
|
||||
actions: IApplicationActions
|
||||
appSettings: IAppSettings;
|
||||
actions: IApplicationActions;
|
||||
}
|
||||
|
||||
interface IAppSettingsState {
|
||||
formSchema: any,
|
||||
uiSchema: any,
|
||||
appSettings: IAppSettings
|
||||
formSchema: any;
|
||||
uiSchema: any;
|
||||
appSettings: IAppSettings;
|
||||
}
|
||||
|
||||
function mapStateToProps(state: ApplicationState) {
|
||||
return {
|
||||
appSettings: state.appSettings
|
||||
appSettings: state.appSettings,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(applicationActions, dispatch)
|
||||
actions: bindActionCreators(applicationActions, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
export default class AppSettingsPage extends React.Component<IAppSettingsProps, IAppSettingsState> {
|
||||
private widgets: any = {
|
||||
connectionPicker: ConnectionPicker
|
||||
connectionPicker: ConnectionPicker,
|
||||
};
|
||||
|
||||
constructor(props: IAppSettingsProps) {
|
||||
|
@ -44,7 +44,7 @@ export default class AppSettingsPage extends React.Component<IAppSettingsProps,
|
|||
this.state = {
|
||||
formSchema: { ...formSchema },
|
||||
uiSchema: { ...uiSchema },
|
||||
appSettings: { ...this.props.appSettings }
|
||||
appSettings: { ...this.props.appSettings },
|
||||
};
|
||||
|
||||
this.toggleDevTools = this.toggleDevTools.bind(this);
|
||||
|
@ -52,19 +52,7 @@ export default class AppSettingsPage extends React.Component<IAppSettingsProps,
|
|||
this.onFormSubmit = this.onFormSubmit.bind(this);
|
||||
}
|
||||
|
||||
onFormSubmit = (form) => {
|
||||
|
||||
}
|
||||
|
||||
toggleDevTools = () => {
|
||||
this.props.actions.toggleDevTools(!this.props.appSettings.devToolsEnabled);
|
||||
}
|
||||
|
||||
reloadApp = () => {
|
||||
this.props.actions.reloadApplication();
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
return (
|
||||
<div className="m-3 text-light">
|
||||
<h3><i className="fas fa-cog fa-1x"></i><span className="px-2">Application Settings</span></h3>
|
||||
|
@ -81,15 +69,31 @@ export default class AppSettingsPage extends React.Component<IAppSettingsProps,
|
|||
<div className="app-settings-page-sidebar px-2">
|
||||
<div className="my-3">
|
||||
<p>Open application developer tools to help diagnose issues</p>
|
||||
<button className="btn btn-primary btn-sm" onClick={this.toggleDevTools}>Toggle Developer Tools</button>
|
||||
<button className="btn btn-primary btn-sm"
|
||||
onClick={this.toggleDevTools}>Toggle Developer Tools
|
||||
</button>
|
||||
</div>
|
||||
<div className="my-3">
|
||||
<p>Reload the app discarding all current changes</p>
|
||||
<button className="btn btn-primary btn-sm" onClick={this.reloadApp}>Refresh Application</button>
|
||||
<button className="btn btn-primary btn-sm"
|
||||
onClick={this.reloadApp}>Refresh Application
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private onFormSubmit = (form) => {
|
||||
// TODO: Submit form
|
||||
}
|
||||
|
||||
private toggleDevTools = () => {
|
||||
this.props.actions.toggleDevTools(!this.props.appSettings.devToolsEnabled);
|
||||
}
|
||||
|
||||
private reloadApp = () => {
|
||||
this.props.actions.reloadApplication();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
import React from 'react';
|
||||
import formSchema from './connectionForm.json';
|
||||
import uiSchema from './connectionForm.ui.json';
|
||||
import Form from 'react-jsonschema-form'
|
||||
import { IConnection } from '../../../store/applicationState.js';
|
||||
import LocalFolderPicker from '../../common/localFolderPicker';
|
||||
import React from "react";
|
||||
import formSchema from "./connectionForm.json";
|
||||
import uiSchema from "./connectionForm.ui.json";
|
||||
import Form from "react-jsonschema-form";
|
||||
import { IConnection } from "../../../store/applicationState.js";
|
||||
import LocalFolderPicker from "../../common/localFolderPicker";
|
||||
|
||||
interface ConnectionFormProps extends React.Props<ConnectionForm> {
|
||||
interface IConnectionFormProps extends React.Props<ConnectionForm> {
|
||||
connection: IConnection;
|
||||
onSubmit: (connection: IConnection) => void;
|
||||
}
|
||||
|
||||
interface ConnectionFormState {
|
||||
interface IConnectionFormState {
|
||||
providerName: string;
|
||||
formSchema: any;
|
||||
uiSchema: any;
|
||||
formData: IConnection;
|
||||
}
|
||||
|
||||
export default class ConnectionForm extends React.Component<ConnectionFormProps, ConnectionFormState> {
|
||||
export default class ConnectionForm extends React.Component<IConnectionFormProps, IConnectionFormState> {
|
||||
private widgets = {
|
||||
LocalFolderPicker: LocalFolderPicker
|
||||
}
|
||||
localFolderPicker: LocalFolderPicker,
|
||||
};
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
@ -29,51 +29,13 @@ export default class ConnectionForm extends React.Component<ConnectionFormProps,
|
|||
formSchema: { ...formSchema },
|
||||
uiSchema: { ...uiSchema },
|
||||
providerName: null,
|
||||
formData: this.props.connection
|
||||
formData: this.props.connection,
|
||||
};
|
||||
|
||||
this.onFormChange = this.onFormChange.bind(this);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this.props.connection && prevProps.connection !== this.props.connection) {
|
||||
this.bindForm(this.props.connection);
|
||||
}
|
||||
}
|
||||
|
||||
onFormChange = (args) => {
|
||||
const providerType = args.formData.providerType;
|
||||
|
||||
if (providerType !== this.state.providerName) {
|
||||
this.bindForm(args.formData, true);
|
||||
}
|
||||
};
|
||||
|
||||
private bindForm(connection: IConnection, resetProviderOptions: boolean = false) {
|
||||
const providerType = connection.providerType;
|
||||
const providerSchema = require(`../../../providers/storage/${providerType}.json`);
|
||||
const providerUiSchema = require(`../../../providers/storage/${providerType}.ui.json`);
|
||||
|
||||
const formSchema = { ...this.state.formSchema };
|
||||
formSchema.properties['providerOptions'] = providerSchema;
|
||||
|
||||
const uiSchema = { ...this.state.uiSchema };
|
||||
uiSchema['providerOptions'] = providerUiSchema;
|
||||
|
||||
const formData = { ...connection };
|
||||
if (resetProviderOptions) {
|
||||
formData.providerOptions = {};
|
||||
}
|
||||
|
||||
this.setState({
|
||||
providerName: providerType,
|
||||
formSchema: formSchema,
|
||||
uiSchema: uiSchema,
|
||||
formData: formData
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
return (
|
||||
<div className="app-connections-page-detail m-3 text-light">
|
||||
<h3><i className="fas fa-plug fa-1x"></i><span className="px-2">Connection Settings</span></h3>
|
||||
|
@ -90,4 +52,42 @@ export default class ConnectionForm extends React.Component<ConnectionFormProps,
|
|||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public componentDidUpdate(prevProps) {
|
||||
if (this.props.connection && prevProps.connection !== this.props.connection) {
|
||||
this.bindForm(this.props.connection);
|
||||
}
|
||||
}
|
||||
|
||||
private onFormChange = (args) => {
|
||||
const providerType = args.formData.providerType;
|
||||
|
||||
if (providerType !== this.state.providerName) {
|
||||
this.bindForm(args.formData, true);
|
||||
}
|
||||
}
|
||||
|
||||
private bindForm(connection: IConnection, resetProviderOptions: boolean = false) {
|
||||
const providerType = connection.providerType;
|
||||
const providerSchema = require(`../../../providers/storage/${providerType}.json`);
|
||||
const providerUiSchema = require(`../../../providers/storage/${providerType}.ui.json`);
|
||||
|
||||
const formSchema = { ...this.state.formSchema };
|
||||
formSchema.properties["providerOptions"] = providerSchema;
|
||||
|
||||
const uiSchema = { ...this.state.uiSchema };
|
||||
uiSchema["providerOptions"] = providerUiSchema;
|
||||
|
||||
const formData = { ...connection };
|
||||
if (resetProviderOptions) {
|
||||
formData.providerOptions = {};
|
||||
}
|
||||
|
||||
this.setState({
|
||||
providerName: providerType,
|
||||
formSchema,
|
||||
uiSchema,
|
||||
formData,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import React from "react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
|
||||
export default function ConnectionItem({ item, onClick, onDelete }) {
|
||||
return (
|
||||
|
@ -11,4 +11,4 @@ export default function ConnectionItem({ item, onClick, onDelete }) {
|
|||
</NavLink>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import React from 'react';
|
||||
import { Route } from 'react-router-dom';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import ConnectionItem from './connectionItem';
|
||||
import CondensedList from '../../common/condensedList';
|
||||
import ApplicationState, { IConnection } from '../../../store/applicationState.js';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
import IConnectionActions, * as connectionActions from '../../../actions/connectionActions';
|
||||
import ConnectionForm from './connectionForm';
|
||||
import './connectionsPage.scss';
|
||||
import React from "react";
|
||||
import { Route } from "react-router-dom";
|
||||
import { connect } from "react-redux";
|
||||
import { bindActionCreators } from "redux";
|
||||
import ConnectionItem from "./connectionItem";
|
||||
import CondensedList from "../../common/condensedList";
|
||||
import ApplicationState, { IConnection } from "../../../store/applicationState.js";
|
||||
import { RouteComponentProps } from "react-router-dom";
|
||||
import IConnectionActions, * as connectionActions from "../../../actions/connectionActions";
|
||||
import ConnectionForm from "./connectionForm";
|
||||
import "./connectionsPage.scss";
|
||||
|
||||
export interface IConnectionPageProps extends RouteComponentProps, React.Props<ConnectionPage> {
|
||||
connections: IConnection[];
|
||||
|
@ -16,18 +16,18 @@ export interface IConnectionPageProps extends RouteComponentProps, React.Props<C
|
|||
}
|
||||
|
||||
export interface IConnectionPageState {
|
||||
connection: IConnection
|
||||
connection: IConnection;
|
||||
}
|
||||
|
||||
function mapStateToProps(state: ApplicationState) {
|
||||
return {
|
||||
connections: state.connections
|
||||
connections: state.connections,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(connectionActions, dispatch)
|
||||
actions: bindActionCreators(connectionActions, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -37,62 +37,38 @@ export default class ConnectionPage extends React.Component<IConnectionPageProps
|
|||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
connection: null
|
||||
connection: null,
|
||||
};
|
||||
|
||||
this.onFormSubmit = this.onFormSubmit.bind(this);
|
||||
this.onConnectionDelete = this.onConnectionDelete.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
public componentDidMount() {
|
||||
this.props.actions.loadConnections();
|
||||
|
||||
const connectionId = this.props.match.params['connectionId'];
|
||||
const connectionId = this.props.match.params["connectionId"];
|
||||
if (connectionId) {
|
||||
this.loadConnection(connectionId);
|
||||
}
|
||||
}
|
||||
|
||||
loadConnection(connectionId: string) {
|
||||
this.props.actions.loadConnection(connectionId)
|
||||
.then(connection => {
|
||||
this.setState({
|
||||
connection: connection
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
this.setState({
|
||||
connection: null
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onConnectionDelete = (connection: IConnection) => {
|
||||
this.props.actions.deleteConnection(connection);
|
||||
}
|
||||
|
||||
componentDidUpdate = (prevProps) => {
|
||||
const prevConnectionId = prevProps.match.params['connectionId'];
|
||||
const newConnectionId = this.props.match.params['connectionId'];
|
||||
public componentDidUpdate = (prevProps) => {
|
||||
const prevConnectionId = prevProps.match.params["connectionId"];
|
||||
const newConnectionId = this.props.match.params["connectionId"];
|
||||
|
||||
if (prevConnectionId !== newConnectionId) {
|
||||
this.loadConnection(newConnectionId);
|
||||
}
|
||||
}
|
||||
|
||||
onFormSubmit = (connection: IConnection) => {
|
||||
this.props.actions.saveConnection(connection).then(() => {
|
||||
this.props.history.push('/connections');
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
return (
|
||||
<div className="app-connections-page">
|
||||
<div className="app-connections-page-list bg-lighter-1">
|
||||
<CondensedList
|
||||
title="Connections"
|
||||
newLinkTo={'/connections/create'}
|
||||
newLinkTo={"/connections/create"}
|
||||
onDelete={this.onConnectionDelete}
|
||||
Component={ConnectionItem}
|
||||
items={this.props.connections} />
|
||||
|
@ -112,4 +88,28 @@ export default class ConnectionPage extends React.Component<IConnectionPageProps
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private loadConnection(connectionId: string) {
|
||||
this.props.actions.loadConnection(connectionId)
|
||||
.then((connection) => {
|
||||
this.setState({
|
||||
connection,
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
this.setState({
|
||||
connection: null,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private onConnectionDelete = (connection: IConnection) => {
|
||||
this.props.actions.deleteConnection(connection);
|
||||
}
|
||||
|
||||
private onFormSubmit = (connection: IConnection) => {
|
||||
this.props.actions.saveConnection(connection).then(() => {
|
||||
this.props.history.push("/connections");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import React from "react";
|
||||
|
||||
export default class EditorPage extends React.Component {
|
||||
render() {
|
||||
public render() {
|
||||
return (
|
||||
<div>EditorPage</div>
|
||||
);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import React from "react";
|
||||
|
||||
export default class ExportPage extends React.Component {
|
||||
render() {
|
||||
public render() {
|
||||
return (
|
||||
<div>ExportPage</div>
|
||||
);
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import './homePage.scss';
|
||||
import IProjectActions, * as projectActions from '../../../actions/projectActions';
|
||||
import ApplicationState, { IProject } from '../../../store/applicationState';
|
||||
import CondensedList from '../../common/condensedList';
|
||||
import RecentProjectItem from './recentProjectItem';
|
||||
import FilePicker from '../../common/filePicker';
|
||||
import { Link, RouteComponentProps } from 'react-router-dom';
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { bindActionCreators } from "redux";
|
||||
import "./homePage.scss";
|
||||
import IProjectActions, * as projectActions from "../../../actions/projectActions";
|
||||
import ApplicationState, { IProject } from "../../../store/applicationState";
|
||||
import CondensedList from "../../common/condensedList";
|
||||
import RecentProjectItem from "./recentProjectItem";
|
||||
import FilePicker from "../../common/filePicker";
|
||||
import { Link, RouteComponentProps } from "react-router-dom";
|
||||
|
||||
interface HomepageProps extends RouteComponentProps, React.Props<HomePage> {
|
||||
recentProjects: IProject[],
|
||||
actions: IProjectActions
|
||||
interface IHomepageProps extends RouteComponentProps, React.Props<HomePage> {
|
||||
recentProjects: IProject[];
|
||||
actions: IProjectActions;
|
||||
}
|
||||
|
||||
function mapStateToProps(state: ApplicationState) {
|
||||
return {
|
||||
recentProjects: state.recentProjects
|
||||
recentProjects: state.recentProjects,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(projectActions, dispatch)
|
||||
actions: bindActionCreators(projectActions, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
export default class HomePage extends React.Component<HomepageProps> {
|
||||
export default class HomePage extends React.Component<IHomepageProps> {
|
||||
private filePicker: React.RefObject<FilePicker>;
|
||||
|
||||
constructor(props: HomepageProps, context) {
|
||||
constructor(props: IHomepageProps, context) {
|
||||
super(props, context);
|
||||
|
||||
this.filePicker = React.createRef<FilePicker>();
|
||||
|
@ -42,25 +42,7 @@ export default class HomePage extends React.Component<HomepageProps> {
|
|||
this.props.actions.loadProjects();
|
||||
}
|
||||
|
||||
onProjectFileUpload = (e, projectJson) => {
|
||||
const project: IProject = JSON.parse(projectJson);
|
||||
this.loadSelectedProject(project);
|
||||
}
|
||||
|
||||
onProjectFileUploadError = (e, err) => {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
loadSelectedProject = (project: IProject) => {
|
||||
this.props.actions.loadProject(project)
|
||||
this.props.history.push(`/projects/${project.id}/settings`);
|
||||
}
|
||||
|
||||
deleteProject = (project: IProject) => {
|
||||
this.props.actions.deleteProject(project);
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
return (
|
||||
<div className="app-homepage">
|
||||
<div className="app-homepage-main">
|
||||
|
@ -95,4 +77,23 @@ export default class HomePage extends React.Component<HomepageProps> {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private onProjectFileUpload = (e, projectJson) => {
|
||||
const project: IProject = JSON.parse(projectJson);
|
||||
this.loadSelectedProject(project);
|
||||
}
|
||||
|
||||
private onProjectFileUploadError = (e, err) => {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
private loadSelectedProject = (project: IProject) => {
|
||||
this.props.actions.loadProject(project).then(() => {
|
||||
this.props.history.push(`/projects/${project.id}/settings`);
|
||||
});
|
||||
}
|
||||
|
||||
private deleteProject = (project: IProject) => {
|
||||
this.props.actions.deleteProject(project);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react';
|
||||
import React from "react";
|
||||
|
||||
export default function RecentProjectItem({ item, onClick, onDelete }) {
|
||||
return (
|
||||
|
@ -10,4 +10,4 @@ export default function RecentProjectItem({ item, onClick, onDelete }) {
|
|||
</a>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import React from "react";
|
||||
|
||||
export default class ProfileSettingsPage extends React.Component {
|
||||
render() {
|
||||
public render() {
|
||||
return (
|
||||
<div>ProfileSettingsPage</div>
|
||||
);
|
||||
|
|
|
@ -1,60 +1,60 @@
|
|||
import React from 'react';
|
||||
import Form from 'react-jsonschema-form'
|
||||
import deepmerge from 'deepmerge';
|
||||
import formSchema from './projectForm.json';
|
||||
import uiSchema from './projectForm.ui.json';
|
||||
import TagsInput from '../../common/tagsInput'
|
||||
import ConnectionPicker from '../../common/connectionPicker';
|
||||
import { IProject, IConnection } from '../../../store/applicationState.js';
|
||||
import React from "react";
|
||||
import Form from "react-jsonschema-form";
|
||||
import deepmerge from "deepmerge";
|
||||
import formSchema from "./projectForm.json";
|
||||
import uiSchema from "./projectForm.ui.json";
|
||||
import TagsInput from "../../common/tagsInput";
|
||||
import ConnectionPicker from "../../common/connectionPicker";
|
||||
import { IProject, IConnection } from "../../../store/applicationState.js";
|
||||
|
||||
interface ProjectFormProps extends React.Props<ProjectForm> {
|
||||
interface IProjectFormProps extends React.Props<ProjectForm> {
|
||||
project: IProject;
|
||||
connections: IConnection[];
|
||||
onSubmit: (project: IProject) => void;
|
||||
}
|
||||
|
||||
interface ProjectFormState {
|
||||
interface IProjectFormState {
|
||||
formSchema: any;
|
||||
uiSchema: any;
|
||||
}
|
||||
|
||||
export default class ProjectForm extends React.Component<ProjectFormProps, ProjectFormState>{
|
||||
export default class ProjectForm extends React.Component<IProjectFormProps, IProjectFormState> {
|
||||
private widgets = {
|
||||
connectionPicker: ConnectionPicker,
|
||||
tagsInput: TagsInput
|
||||
}
|
||||
tagsInput: TagsInput,
|
||||
};
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
uiSchema: { ...uiSchema },
|
||||
formSchema: { ...formSchema }
|
||||
formSchema: { ...formSchema },
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
public componentDidUpdate(prevProps) {
|
||||
if (prevProps.connections !== this.props.connections) {
|
||||
const overrideUiSchema = {
|
||||
sourceConnectionId: {
|
||||
'ui:options': {
|
||||
connections: this.props.connections
|
||||
}
|
||||
"ui:options": {
|
||||
connections: this.props.connections,
|
||||
},
|
||||
},
|
||||
targetConnectionId: {
|
||||
'ui:options': {
|
||||
connections: this.props.connections
|
||||
}
|
||||
}
|
||||
"ui:options": {
|
||||
connections: this.props.connections,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.setState({
|
||||
uiSchema: deepmerge(uiSchema, overrideUiSchema)
|
||||
uiSchema: deepmerge(uiSchema, overrideUiSchema),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
return (
|
||||
<Form
|
||||
widgets={this.widgets}
|
||||
|
@ -63,6 +63,6 @@ export default class ProjectForm extends React.Component<ProjectFormProps, Proje
|
|||
formData={this.props.project}
|
||||
onSubmit={this.props.onSubmit}>
|
||||
</Form>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,56 +1,56 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
import ProjectForm from './projectForm'
|
||||
import IProjectActions, * as projectActions from '../../../actions/projectActions';
|
||||
import ApplicationState, { IProject, IConnection } from '../../../store/applicationState';
|
||||
import IConnectionActions, * as connectionActions from '../../../actions/connectionActions';
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { bindActionCreators } from "redux";
|
||||
import { RouteComponentProps } from "react-router-dom";
|
||||
import ProjectForm from "./projectForm";
|
||||
import IProjectActions, * as projectActions from "../../../actions/projectActions";
|
||||
import ApplicationState, { IProject, IConnection } from "../../../store/applicationState";
|
||||
import IConnectionActions, * as connectionActions from "../../../actions/connectionActions";
|
||||
|
||||
interface ProjectSettingsPageProps extends RouteComponentProps, React.Props<ProjectSettingsPage> {
|
||||
interface IProjectSettingsPageProps extends RouteComponentProps, React.Props<ProjectSettingsPage> {
|
||||
currentProject: IProject;
|
||||
projectActions: IProjectActions;
|
||||
connectionActions: IConnectionActions;
|
||||
connections: IConnection[];
|
||||
}
|
||||
|
||||
interface ProjectSettingsPageState {
|
||||
interface IProjectSettingsPageState {
|
||||
project: IProject;
|
||||
}
|
||||
|
||||
function mapStateToProps(state: ApplicationState) {
|
||||
return {
|
||||
currentProject: state.currentProject,
|
||||
connections: state.connections
|
||||
connections: state.connections,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
projectActions: bindActionCreators(projectActions, dispatch),
|
||||
connectionActions: bindActionCreators(connectionActions, dispatch)
|
||||
connectionActions: bindActionCreators(connectionActions, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
export default class ProjectSettingsPage extends React.Component<ProjectSettingsPageProps, ProjectSettingsPageState> {
|
||||
export default class ProjectSettingsPage extends React.Component<IProjectSettingsPageProps, IProjectSettingsPageState> {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
project: this.props.currentProject
|
||||
project: this.props.currentProject,
|
||||
};
|
||||
|
||||
this.onFormSubmit = this.onFormSubmit.bind(this);
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const projectId = this.props.match.params['projectId'];
|
||||
public async componentDidMount() {
|
||||
const projectId = this.props.match.params["projectId"];
|
||||
if (!this.state.project && projectId) {
|
||||
const currentProject = await this.props.projectActions.loadProject(projectId);
|
||||
|
||||
this.setState({
|
||||
project: currentProject
|
||||
project: currentProject,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -59,22 +59,7 @@ export default class ProjectSettingsPage extends React.Component<ProjectSettings
|
|||
}
|
||||
}
|
||||
|
||||
onFormSubmit = (form) => {
|
||||
this.setState({
|
||||
project: {
|
||||
...form.formData,
|
||||
sourceConnection: this.props.connections.find(connection => connection.id === form.formData.sourceConnectionId),
|
||||
targetConnection: this.props.connections.find(connection => connection.id === form.formData.targetConnectionId)
|
||||
}
|
||||
}, () => {
|
||||
this.props.projectActions.saveProject(this.state.project)
|
||||
.then(project => {
|
||||
this.props.history.push(`/projects/${project.id}/edit`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
return (
|
||||
<div className="m-3 text-light">
|
||||
<h3><i className="fas fa-sliders-h fa-1x"></i><span className="px-2">Project Settings</span></h3>
|
||||
|
@ -87,4 +72,21 @@ export default class ProjectSettingsPage extends React.Component<ProjectSettings
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private onFormSubmit = (form) => {
|
||||
this.setState({
|
||||
project: {
|
||||
...form.formData,
|
||||
sourceConnection: this.props.connections
|
||||
.find((connection) => connection.id === form.formData.sourceConnectionId),
|
||||
targetConnection: this.props.connections
|
||||
.find((connection) => connection.id === form.formData.targetConnectionId),
|
||||
},
|
||||
}, () => {
|
||||
this.props.projectActions.saveProject(this.state.project)
|
||||
.then((project) => {
|
||||
this.props.history.push(`/projects/${project.id}/edit`);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import React from 'react';
|
||||
import { Route } from 'react-router-dom';
|
||||
import HomePage from '../pages/homepage/homePage';
|
||||
import ActiveLearningPage from '../pages/activeLearningPage';
|
||||
import AppSettingsPage from '../pages/appSettings/appSettingsPage';
|
||||
import ConnectionPage from '../pages/connections/connectionsPage';
|
||||
import EditorPage from '../pages/editorPage';
|
||||
import ExportPage from '../pages/exportPage';
|
||||
import ProjectSettingsPage from '../pages/projectSettings/projectSettingsPage';
|
||||
import ProfileSettingsPage from '../pages/profileSettingsPage';
|
||||
import React from "react";
|
||||
import { Route } from "react-router-dom";
|
||||
import HomePage from "../pages/homepage/homePage";
|
||||
import ActiveLearningPage from "../pages/activeLearningPage";
|
||||
import AppSettingsPage from "../pages/appSettings/appSettingsPage";
|
||||
import ConnectionPage from "../pages/connections/connectionsPage";
|
||||
import EditorPage from "../pages/editorPage";
|
||||
import ExportPage from "../pages/exportPage";
|
||||
import ProjectSettingsPage from "../pages/projectSettings/projectSettingsPage";
|
||||
import ProfileSettingsPage from "../pages/profileSettingsPage";
|
||||
|
||||
export default function MainContentRouter() {
|
||||
return (
|
||||
|
@ -24,4 +24,4 @@ export default function MainContentRouter() {
|
|||
<Route path="/projects/:projectId/active-learning" component={ActiveLearningPage} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
import React from 'react';
|
||||
import Navbar from './navbar';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import { shallow, mount } from 'enzyme';
|
||||
import React from "react";
|
||||
import Navbar from "./navbar";
|
||||
import { BrowserRouter as Router } from "react-router-dom";
|
||||
import { mount } from "enzyme";
|
||||
|
||||
describe('Sidebar Component', () => {
|
||||
it('renders correctly', () => {
|
||||
describe("Sidebar Component", () => {
|
||||
it("renders correctly", () => {
|
||||
const wrapper = mount(
|
||||
<Router>
|
||||
<Navbar />
|
||||
</Router>
|
||||
</Router>,
|
||||
);
|
||||
|
||||
expect(wrapper).not.toBeNull();
|
||||
|
||||
const logo = wrapper.find('.app-navbar-logo ul li a');
|
||||
const logo = wrapper.find(".app-navbar-logo ul li a");
|
||||
expect(logo.length).toEqual(1);
|
||||
|
||||
const brand = wrapper.find('.app-navbar-brand span');
|
||||
expect(brand.text()).toEqual('Visual Object Tagging Tool');
|
||||
const brand = wrapper.find(".app-navbar-brand span");
|
||||
expect(brand.text()).toEqual("Visual Object Tagging Tool");
|
||||
|
||||
const profile = wrapper.find('.app-navbar-menu ul li a')
|
||||
const profile = wrapper.find(".app-navbar-menu ul li a");
|
||||
expect(profile.length).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Link, NavLink } from 'react-router-dom';
|
||||
import React from "react";
|
||||
import { Link, NavLink } from "react-router-dom";
|
||||
|
||||
export default function Navbar() {
|
||||
return (
|
||||
|
@ -14,9 +14,13 @@ export default function Navbar() {
|
|||
</div>
|
||||
<div className="app-navbar-menu">
|
||||
<ul>
|
||||
<li><NavLink title="Profile Settings" to={`/profile`}><i className="fas fa-user-circle"></i></NavLink></li>
|
||||
<li>
|
||||
<NavLink title="Profile Settings" to={`/profile`}>
|
||||
<i className="fas fa-user-circle"></i>
|
||||
</NavLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
import React from 'react';
|
||||
import Sidebar from './sidebar';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import { mount } from 'enzyme';
|
||||
import { IProject } from '../../store/applicationState';
|
||||
import React from "react";
|
||||
import Sidebar from "./sidebar";
|
||||
import { BrowserRouter as Router } from "react-router-dom";
|
||||
import { mount } from "enzyme";
|
||||
import { IProject } from "../../store/applicationState";
|
||||
|
||||
describe('Sidebar Component', () => {
|
||||
it('renders correctly', () => {
|
||||
describe("Sidebar Component", () => {
|
||||
it("renders correctly", () => {
|
||||
const project: IProject = null;
|
||||
const wrapper = mount(
|
||||
<Router>
|
||||
<Sidebar project={project} />
|
||||
</Router>
|
||||
</Router>,
|
||||
);
|
||||
|
||||
expect(wrapper).not.toBeNull();
|
||||
|
||||
const links = wrapper.find('ul li');
|
||||
const links = wrapper.find("ul li");
|
||||
expect(links.length).toEqual(6);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import ConditionalNavLink from '../common/conditionalNavLink';
|
||||
import React from "react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
import ConditionalNavLink from "../common/conditionalNavLink";
|
||||
|
||||
export default function Sidebar({ project }) {
|
||||
const projectId = project ? project.id : null;
|
||||
|
@ -8,11 +8,35 @@ export default function Sidebar({ project }) {
|
|||
return (
|
||||
<div className="bg-lighter-2 app-sidebar">
|
||||
<ul>
|
||||
<li><ConditionalNavLink disabled={!projectId} title="Tag Editor" to={`/projects/${projectId}/edit`}><i className="fas fa-bookmark"></i></ConditionalNavLink></li>
|
||||
<li><ConditionalNavLink disabled={!projectId} title="Project Settings" to={`/projects/${projectId}/settings`}><i className="fas fa-sliders-h"></i></ConditionalNavLink></li>
|
||||
<li><ConditionalNavLink disabled={!projectId} title="Export" to={`/projects/${projectId}/export`}><i className="fas fa-external-link-square-alt"></i></ConditionalNavLink></li>
|
||||
<li><ConditionalNavLink disabled={!projectId} title="Active Learning" to={`/projects/${projectId}/active-learning`}><i className="fas fa-graduation-cap"></i></ConditionalNavLink></li>
|
||||
<li><NavLink title="Connections" to={`/connections`}><i className="fas fa-plug"></i></NavLink></li>
|
||||
<li>
|
||||
<ConditionalNavLink disabled={!projectId}
|
||||
title="Tag Editor"
|
||||
to={`/projects/${projectId}/edit`}>
|
||||
<i className="fas fa-bookmark"></i>
|
||||
</ConditionalNavLink>
|
||||
</li>
|
||||
<li>
|
||||
<ConditionalNavLink disabled={!projectId}
|
||||
title="Project Settings"
|
||||
to={`/projects/${projectId}/settings`}>
|
||||
<i className="fas fa-sliders-h"></i>
|
||||
</ConditionalNavLink>
|
||||
</li>
|
||||
<li>
|
||||
<ConditionalNavLink disabled={!projectId}
|
||||
title="Export"
|
||||
to={`/projects/${projectId}/export`}>
|
||||
<i className="fas fa-external-link-square-alt"></i></ConditionalNavLink></li>
|
||||
<li>
|
||||
<ConditionalNavLink disabled={!projectId}
|
||||
title="Active Learning"
|
||||
to={`/projects/${projectId}/active-learning`}>
|
||||
<i className="fas fa-graduation-cap"></i>
|
||||
</ConditionalNavLink>
|
||||
</li>
|
||||
<li>
|
||||
<NavLink title="Connections" to={`/connections`}><i className="fas fa-plug"></i></NavLink>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="app-sidebar-fill"></div>
|
||||
<ul>
|
||||
|
@ -20,4 +44,4 @@ export default function Sidebar({ project }) {
|
|||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
import React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import ReactDOM from 'react-dom';
|
||||
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
|
||||
import '../node_modules/@fortawesome/fontawesome-free/css/all.css';
|
||||
import './assets/css/bootstrap-theme-slate.css';
|
||||
import './index.scss';
|
||||
import App from './App';
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
import createReduxStore from './store/store';
|
||||
import initialState from './store/initialState';
|
||||
import ApplicationState from './store/applicationState';
|
||||
import registerProviders from './registerProviders';
|
||||
|
||||
import React from "react";
|
||||
import { Provider } from "react-redux";
|
||||
import ReactDOM from "react-dom";
|
||||
import "../node_modules/bootstrap/dist/css/bootstrap.min.css";
|
||||
import "../node_modules/@fortawesome/fontawesome-free/css/all.css";
|
||||
import "./assets/css/bootstrap-theme-slate.css";
|
||||
import "./index.scss";
|
||||
import App from "./App";
|
||||
import * as serviceWorker from "./serviceWorker";
|
||||
import createReduxStore from "./store/store";
|
||||
import initialState from "./store/initialState";
|
||||
import ApplicationState from "./store/applicationState";
|
||||
import registerProviders from "./registerProviders";
|
||||
|
||||
registerProviders();
|
||||
const defaultState: ApplicationState = initialState;
|
||||
|
@ -21,7 +20,7 @@ ReactDOM.render(
|
|||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>
|
||||
, document.getElementById('root'));
|
||||
, document.getElementById("root"));
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
"object-literal-sort-keys": false,
|
||||
"no-console": false,
|
||||
"no-shadowed-variable": false,
|
||||
"ordered-imports": false
|
||||
"ordered-imports": false,
|
||||
"no-string-literal": false
|
||||
},
|
||||
"rulesDirectory": []
|
||||
}
|
Загрузка…
Ссылка в новой задаче