Some semi-major changes
- Added notes to each page with info/goals - removed the clutter - moved files into more meaningful directories - renamed route Reports to Migrations - Added a Reports route that's empty
This commit is contained in:
parent
8382419e5f
commit
36353aba65
@ -3,14 +3,18 @@ import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
|
|||||||
|
|
||||||
// Routes
|
// Routes
|
||||||
import Upcoming from "./root/Pages/Upcoming";
|
import Upcoming from "./root/Pages/Upcoming";
|
||||||
import Reports from "./root/Pages/Reports";
|
import Migrations from "./root/Pages/Migrations";
|
||||||
import Historical from "./root/Pages/Historical";
|
import Historical from "./root/Pages/Historical";
|
||||||
|
import Reports from "./root/Pages/Reports";
|
||||||
import Book from "./root/Pages/Book";
|
import Book from "./root/Pages/Book";
|
||||||
import IDSingle from "./root/Pages/IDSingle";
|
import IDSingle from "./root/Pages/IDSingle";
|
||||||
// Components
|
// Components
|
||||||
import Home from "./root/Home";
|
import Home from "./root/Home";
|
||||||
import Navigation from "./root/Navigation";
|
import Navigation from "./root/Navigation";
|
||||||
|
|
||||||
|
// Main app component, react-router comes from here,
|
||||||
|
// and links to all of the sub pages
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
@ -21,9 +25,10 @@ class App extends Component {
|
|||||||
<Route exact path="/" component={Home} />
|
<Route exact path="/" component={Home} />
|
||||||
<Route exact path="/book" component={Book} />
|
<Route exact path="/book" component={Book} />
|
||||||
<Route exact path="/upcoming-migrations" component={Upcoming} />
|
<Route exact path="/upcoming-migrations" component={Upcoming} />
|
||||||
|
<Route exact path="/migrations" component={Migrations} />
|
||||||
<Route exact path="/reports" component={Reports} />
|
<Route exact path="/reports" component={Reports} />
|
||||||
<Route exact path="/historical-migrations" component={Historical} />
|
<Route exact path="/historical-migrations" component={Historical} />
|
||||||
<Route exact path="/reports/:migrationId" component={IDSingle} />
|
<Route path="/migrations/:migrationId" component={IDSingle} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
</Router>
|
</Router>
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
|
// Axios create, exporting callAPI
|
||||||
|
|
||||||
export const callAPI = axios.create({
|
export const callAPI = axios.create({
|
||||||
baseURL: "https://devapi.benjamyn.love/migrations/",
|
baseURL: "https://devapi.benjamyn.love/migrations/",
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,20 +1,19 @@
|
|||||||
import React from 'react'
|
import React from "react";
|
||||||
|
|
||||||
|
// Generic error
|
||||||
|
|
||||||
const Error = () => (
|
const Error = () => (
|
||||||
<div>
|
<div>
|
||||||
|
<div className="card-panel blue-grey darken-1">
|
||||||
|
<div className="card-content white-text">
|
||||||
<div className="card-panel blue-grey darken-1">
|
<center>
|
||||||
<div className="card-content white-text">
|
<span className="card-title">
|
||||||
<center>
|
<i className="large material-icons">do_not_disturb</i>
|
||||||
<span className="card-title"><i className="large material-icons">do_not_disturb</i></span>
|
</span>
|
||||||
</center>
|
</center>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
export default Error;
|
export default Error;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
import axios from "axios";
|
|
||||||
|
|
||||||
const url = `https://devapi.benjamyn.love/migrations/`;
|
|
||||||
|
|
||||||
export const getMigrations = () => (dispatch) => {
|
|
||||||
axios
|
|
||||||
.get(url)
|
|
||||||
.then((response) => {
|
|
||||||
dispatch({
|
|
||||||
migs: response.data,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
this.setState({
|
|
||||||
error: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@ -1,9 +1,17 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
import { callAPI } from "../actions/API";
|
import { callAPI } from "../actions/API";
|
||||||
import Migrations from "./Pages/Migrations";
|
import Cards from "./Pages/Cards";
|
||||||
import SideMigrations from "./Pages/Migrations/SideMigrations";
|
import SideMigrations from "./Pages/Migrations/SideMigrations";
|
||||||
|
|
||||||
|
// Homepage/Cards, first API call here to pass down to cards
|
||||||
|
// and the pending migration list, if there's no data, nothing will show
|
||||||
|
// This would benefit from an error/notification if there is no data
|
||||||
|
//
|
||||||
|
// Two main components linked here are the Dashboard, and the SideMigrations comp,
|
||||||
|
// SideMigrations calls the pending migration list, with its own API call
|
||||||
|
// Dashboard performs the rendering of the cards and the numbers from each migration status.
|
||||||
|
|
||||||
export class Home extends Component {
|
export class Home extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -34,19 +42,11 @@ export class Home extends Component {
|
|||||||
<div className="divider"></div>
|
<div className="divider"></div>
|
||||||
|
|
||||||
<div className="section">
|
<div className="section">
|
||||||
<div className="col s6">
|
<div className="col s7">
|
||||||
<Migrations migs={this.state.migs} />
|
<Cards migs={this.state.migs} />
|
||||||
</div>
|
</div>
|
||||||
<div className="col s6">
|
<div className="col s5">
|
||||||
<p>
|
<p>Migrations tracker</p>
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam
|
|
||||||
quis est vitae sapien venenatis viverra. Suspendisse bibendum
|
|
||||||
tristique est, et gravida neque porta ut. Pellentesque egestas
|
|
||||||
vehicula nulla eu aliquet. Morbi id lacus eget lorem aliquam
|
|
||||||
ornare. Vivamus pulvinar ligula sapien, ut pulvinar eros
|
|
||||||
sollicitudin sodales. Donec sed ipsum sit amet mauris posuere
|
|
||||||
maximus. Aenean finibus turpis eu urna suscipit venenatis.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="divider"></div>
|
<div className="divider"></div>
|
||||||
<div className="section">
|
<div className="section">
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
import InLineSearch from "./Pages/Functionality/InlineSearchBar";
|
||||||
|
|
||||||
|
// Navbar class component, Just simple href's to retain styling
|
||||||
|
|
||||||
export class Navigation extends Component {
|
export class Navigation extends Component {
|
||||||
render() {
|
render() {
|
||||||
@ -16,6 +19,9 @@ export class Navigation extends Component {
|
|||||||
<li>
|
<li>
|
||||||
<Link to="/upcoming-migrations">Upcoming Migrations</Link>
|
<Link to="/upcoming-migrations">Upcoming Migrations</Link>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<Link to="/migrations">Migrations</Link>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Link to="/reports">Reports</Link>
|
<Link to="/reports">Reports</Link>
|
||||||
</li>
|
</li>
|
||||||
@ -26,6 +32,18 @@ export class Navigation extends Component {
|
|||||||
<Link to="/book">Book</Link>
|
<Link to="/book">Book</Link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
{/* Inline UUID search bar is here */}
|
||||||
|
<ul className="right hide-on-med-and-down">
|
||||||
|
<li style={{ paddingRight: "1em" }}>UUID:</li>
|
||||||
|
<li>
|
||||||
|
<InLineSearch style={{ paddingRight: "4em" }}></InLineSearch>
|
||||||
|
</li>
|
||||||
|
{/* <li>
|
||||||
|
<Link>
|
||||||
|
<IdSearchForm />
|
||||||
|
</Link>
|
||||||
|
</li> */}
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@ -1,61 +0,0 @@
|
|||||||
import React, { Component, useEffect, useState } from "react";
|
|
||||||
import moment from "moment";
|
|
||||||
import { Col, FormGroup, Row, Container, Label } from "reactstrap";
|
|
||||||
import { Formik, Form } from "formik";
|
|
||||||
import { Input, Submit } from "formstrap";
|
|
||||||
import { callAPI } from "../../../actions/API";
|
|
||||||
|
|
||||||
const initialValues = {
|
|
||||||
submit_time: moment().format("YYYY-MM-DD"),
|
|
||||||
};
|
|
||||||
const onSubmit = async (values, { setSubmitting }) => {
|
|
||||||
callAPI
|
|
||||||
.get("/", values)
|
|
||||||
.then((response) => {
|
|
||||||
console.log(response.data);
|
|
||||||
this.setState({
|
|
||||||
singlemigs: response.data,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
setSubmitting(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default class GetSingleMigration extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
singlemigs: [],
|
|
||||||
e: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Formik initialValues={initialValues} onSubmit={onSubmit}>
|
|
||||||
<Form>
|
|
||||||
<Container>
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<FormGroup>
|
|
||||||
<Label for="Migration ID">Migration ID</Label>
|
|
||||||
<Input
|
|
||||||
type="text"
|
|
||||||
name="id"
|
|
||||||
id="id"
|
|
||||||
placeholder="Migration ID"
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Submit withSpinner>Submit</Submit>
|
|
||||||
</Container>
|
|
||||||
</Form>
|
|
||||||
</Formik>
|
|
||||||
{/* <ShowMigrations /> */}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
|
|
||||||
import { Col, FormGroup, Row, Container, Label } from "reactstrap";
|
|
||||||
import { Formik, Form } from "formik";
|
|
||||||
import { Input, Submit } from "formstrap";
|
|
||||||
|
|
||||||
export default function IdSearchForm({ api }) {
|
|
||||||
const initialValues = {};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Formik initialValues={initialValues} onSubmit={api}>
|
|
||||||
<Container>
|
|
||||||
<Form>
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<FormGroup>
|
|
||||||
<Label for="migrationId"></Label>
|
|
||||||
<Input
|
|
||||||
type="text"
|
|
||||||
name="migrationId"
|
|
||||||
id="migrationId"
|
|
||||||
placeholder="uuid"
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<Submit withSpinner>Submit</Submit>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Form>
|
|
||||||
</Container>
|
|
||||||
</Formik>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,150 +0,0 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import { callAPI } from "../../../actions/API";
|
|
||||||
import BootstrapTable from "react-bootstrap-table-next";
|
|
||||||
import paginationFactory from "react-bootstrap-table2-paginator";
|
|
||||||
import * as ReactBootstrap from "react-bootstrap";
|
|
||||||
import filterFactory from "react-bootstrap-table2-filter";
|
|
||||||
import ToolkitProvider, {
|
|
||||||
Search,
|
|
||||||
CSVExport,
|
|
||||||
} from "react-bootstrap-table2-toolkit";
|
|
||||||
|
|
||||||
const ShowMigrations = () => {
|
|
||||||
const [list, setList] = useState([]);
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const { SearchBar } = Search;
|
|
||||||
const { ExportCSVButton } = CSVExport;
|
|
||||||
const sizePerPageRenderer = ({
|
|
||||||
options,
|
|
||||||
currSizePerPage,
|
|
||||||
onSizePerPageChange,
|
|
||||||
}) => (
|
|
||||||
<div className="btn-group" role="group">
|
|
||||||
{options.map((option) => {
|
|
||||||
const isSelect = currSizePerPage === `${option.page}`;
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
key={option.text}
|
|
||||||
type="button"
|
|
||||||
onClick={() => onSizePerPageChange(option.page)}
|
|
||||||
className={`btn ${isSelect ? "btn-secondary" : "btn-success"}`}
|
|
||||||
>
|
|
||||||
{option.text}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const getListData = async () => {
|
|
||||||
try {
|
|
||||||
const data = await console.log(data);
|
|
||||||
setList(data.data);
|
|
||||||
setLoading(true);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const options = {
|
|
||||||
paginationSize: 4,
|
|
||||||
pageStartIndex: 0,
|
|
||||||
// alwaysShowAllBtns: true, // Always show next and previous button
|
|
||||||
// withFirstAndLast: false, // Hide the going to First and Last page button
|
|
||||||
// hideSizePerPage: true, // Hide the sizePerPage dropdown always
|
|
||||||
// hidePageListOnlyOnePage: true, // Hide the pagination list when only one page
|
|
||||||
firstPageText: "First",
|
|
||||||
prePageText: "Back",
|
|
||||||
nextPageText: "Next",
|
|
||||||
lastPageText: "Last",
|
|
||||||
nextPageTitle: "First page",
|
|
||||||
prePageTitle: "Pre page",
|
|
||||||
firstPageTitle: "Next page",
|
|
||||||
lastPageTitle: "Last page",
|
|
||||||
showTotal: true,
|
|
||||||
disablePageTitle: true,
|
|
||||||
sizePerPageList: [
|
|
||||||
{
|
|
||||||
text: "50",
|
|
||||||
value: 50,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "100",
|
|
||||||
value: 100,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sizePerPageRenderer, // A numeric array is also available. the purpose of above example is custom the text
|
|
||||||
};
|
|
||||||
const columns = [
|
|
||||||
{ dataField: "id", text: "ID", hidden: true },
|
|
||||||
{ dataField: "submit_time", text: "Submit Time", sort: true },
|
|
||||||
{
|
|
||||||
dataField: "domain",
|
|
||||||
text: "Domain",
|
|
||||||
sort: true,
|
|
||||||
formatter: (cell, row) => <a href={"reports/" + row.id}> {cell} </a>,
|
|
||||||
},
|
|
||||||
{ dataField: "booked_date", text: "Booked Date", sort: true },
|
|
||||||
{ dataField: "booked_time", text: "Booked Time", sort: true },
|
|
||||||
{ dataField: "original_server", text: "Original Server", sort: true },
|
|
||||||
{ dataField: "new_server", text: "New Server", sort: true },
|
|
||||||
{ dataField: "username", text: "Username", sort: true },
|
|
||||||
{ dataField: "brand", text: "Brand", sort: true },
|
|
||||||
{ dataField: "ticket_id", text: "TicketID", sort: true },
|
|
||||||
{ dataField: "migration_status", text: "Status", sort: true },
|
|
||||||
{ dataField: "agent_booked", text: "Agent initials", sort: true },
|
|
||||||
{ dataField: "additional_domains", text: "Additional Domains", sort: true },
|
|
||||||
{ dataField: "migration_type", text: "Type", sort: true },
|
|
||||||
{ dataField: "term_date", text: "Termination Date", sort: true },
|
|
||||||
{ dataField: "notes", text: "Notes", sort: true },
|
|
||||||
{
|
|
||||||
dataField: "report",
|
|
||||||
text: "Show Detailed Report",
|
|
||||||
formatter: (cell, row) => <a href={cell + row.id}> {cell} </a>,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
getListData();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="ShowMigrations">
|
|
||||||
{loading ? (
|
|
||||||
<ToolkitProvider
|
|
||||||
keyField="name"
|
|
||||||
data={list}
|
|
||||||
columns={columns}
|
|
||||||
search
|
|
||||||
exportCSV
|
|
||||||
>
|
|
||||||
{(props) => (
|
|
||||||
<div>
|
|
||||||
<div className="serSec">
|
|
||||||
<h3 className="hdrOne"></h3>
|
|
||||||
<SearchBar {...props.searchProps} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="table-responsive">
|
|
||||||
<BootstrapTable
|
|
||||||
{...props.baseProps}
|
|
||||||
filter={filterFactory()}
|
|
||||||
pagination={paginationFactory(options)}
|
|
||||||
striped
|
|
||||||
hover
|
|
||||||
condensed
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<ExportCSVButton {...props.csvProps}>
|
|
||||||
Export CSV!!
|
|
||||||
</ExportCSVButton>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</ToolkitProvider>
|
|
||||||
) : (
|
|
||||||
<ReactBootstrap.Spinner animation="border" />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ShowMigrations;
|
|
||||||
@ -2,6 +2,9 @@ import React, { Component } from "react";
|
|||||||
|
|
||||||
import FormPage from "./Forms/FormPage";
|
import FormPage from "./Forms/FormPage";
|
||||||
|
|
||||||
|
// Parent page for the Book component,
|
||||||
|
// links directly to FormPage which contains the POST request
|
||||||
|
|
||||||
export default class Book extends Component {
|
export default class Book extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
79
src/components/root/Pages/Cards.js
Normal file
79
src/components/root/Pages/Cards.js
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import React, { Component } from "react";
|
||||||
|
|
||||||
|
// styles and collects each endpoint
|
||||||
|
// booked, awaitterm, complete and missed
|
||||||
|
// is referenced on Home
|
||||||
|
|
||||||
|
class Cards extends Component {
|
||||||
|
bookedMig() {
|
||||||
|
return this.props.migs[0]["booked_count"];
|
||||||
|
}
|
||||||
|
waitingMig() {
|
||||||
|
return this.props.migs[0]["awaitterm_count"];
|
||||||
|
}
|
||||||
|
completedMig() {
|
||||||
|
return this.props.migs[0]["complete_count"];
|
||||||
|
}
|
||||||
|
missedMig() {
|
||||||
|
return this.props.migs[0]["missed_count"];
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (!this.props.migs[0]) {
|
||||||
|
return <div />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="row">
|
||||||
|
<div className="col s6 m4">
|
||||||
|
<div className="card grey darken-1">
|
||||||
|
<div className="card-content white-text">
|
||||||
|
<span className="card-title"></span>
|
||||||
|
{this.bookedMig()}
|
||||||
|
</div>
|
||||||
|
<div className="card-action">
|
||||||
|
<a href="/upcoming-migrations">booked</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col s6 m4">
|
||||||
|
<div className="card grey darken-1">
|
||||||
|
<div className="card-content white-text">
|
||||||
|
<span className="card-title"></span>
|
||||||
|
<p></p>
|
||||||
|
{this.waitingMig()}
|
||||||
|
</div>
|
||||||
|
<div className="card-action">
|
||||||
|
<a href="/upcoming-migrations">waiting</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col s6 m4">
|
||||||
|
<div className="card grey darken-1">
|
||||||
|
<div className="card-content white-text">
|
||||||
|
<span className="card-title"></span>
|
||||||
|
{this.completedMig()}
|
||||||
|
</div>
|
||||||
|
<div className="card-action">
|
||||||
|
<a href="/historical-migrations">complete</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col s6 m3">
|
||||||
|
<div className="card grey darken-1">
|
||||||
|
<div className="card-content white-text">
|
||||||
|
<span className="card-title"></span>
|
||||||
|
{this.missedMig()}
|
||||||
|
</div>
|
||||||
|
<div className="card-action">
|
||||||
|
<a href="/historical-migrations">missed</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Cards;
|
||||||
@ -6,6 +6,11 @@ import { Formik, Form } from "formik";
|
|||||||
import { Input, Submit } from "formstrap";
|
import { Input, Submit } from "formstrap";
|
||||||
import { callAPI } from "../../../actions/API";
|
import { callAPI } from "../../../actions/API";
|
||||||
|
|
||||||
|
// Main form and POST Request to add migrations
|
||||||
|
// found at /book under the web hosting migration tab
|
||||||
|
// Things to add:
|
||||||
|
// better date time picking.
|
||||||
|
|
||||||
export const CPanelBooking = () => {
|
export const CPanelBooking = () => {
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
submit_time: moment().format("YYYY-MM-DD"),
|
submit_time: moment().format("YYYY-MM-DD"),
|
||||||
@ -15,7 +20,7 @@ export const CPanelBooking = () => {
|
|||||||
callAPI
|
callAPI
|
||||||
.post("/", values)
|
.post("/", values)
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
console.log(JSON.stringify(response.values));
|
console.log(response.data.id);
|
||||||
// add function here
|
// add function here
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
|
|||||||
@ -1,39 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
var DatePicker = require("reactstrap-date-picker");
|
|
||||||
|
|
||||||
class DateTimePicker extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
value: new Date().toISOString(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
handleChange(value, formattedValue) {
|
|
||||||
this.setState({
|
|
||||||
value: value, // ISO String, ex: "2016-11-19T12:00:00.000Z"
|
|
||||||
formattedValue: formattedValue, // Formatted String, ex: "11/19/2016"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate() {
|
|
||||||
// Access ISO String and formatted values from the DOM.
|
|
||||||
var hiddenInputElement = document.getElementById("example-datepicker");
|
|
||||||
console.log(hiddenInputElement.value); // ISO String, ex: "2016-11-19T12:00:00.000Z"
|
|
||||||
console.log(hiddenInputElement.getAttribute("data-formattedvalue")); // Formatted String, ex: "11/19/2016"
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<DatePicker
|
|
||||||
id="example-datepicker"
|
|
||||||
value={this.state.value}
|
|
||||||
onChange={(v, f) => this.handleChange(v, f)}
|
|
||||||
minDate={Date()}
|
|
||||||
width="100%"
|
|
||||||
size="lg"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default DateTimePicker;
|
|
||||||
@ -1,5 +1,8 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
|
// Needs to be populated with email specific migration
|
||||||
|
// information
|
||||||
|
|
||||||
export default class EmailBooking extends Component {
|
export default class EmailBooking extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -20,6 +20,10 @@ const FormPage = (props) => {
|
|||||||
if (activeTab !== tab) setActiveTab(tab);
|
if (activeTab !== tab) setActiveTab(tab);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Parent page from the Book section,
|
||||||
|
// Can be expanded to offer email migration bookings,
|
||||||
|
// elements below do the POST requests.
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Nav tabs>
|
<Nav tabs>
|
||||||
|
|||||||
@ -5,6 +5,9 @@ import { Formik, Form } from "formik";
|
|||||||
import { Input, Submit } from "formstrap";
|
import { Input, Submit } from "formstrap";
|
||||||
import { callAPI } from "../../../actions/API";
|
import { callAPI } from "../../../actions/API";
|
||||||
|
|
||||||
|
// Main form element for the UUID linking Migrations page,
|
||||||
|
// Contians the PUT request to modify data from the API
|
||||||
|
|
||||||
const ReportSingleMigration = ({ item }) => {
|
const ReportSingleMigration = ({ item }) => {
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
submit_time: item.submit_time,
|
submit_time: item.submit_time,
|
||||||
38
src/components/root/Pages/Functionality/IdSearchForm.js
Normal file
38
src/components/root/Pages/Functionality/IdSearchForm.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { FormGroup, Label } from "reactstrap";
|
||||||
|
import { Formik, Form } from "formik";
|
||||||
|
import { Input, Submit } from "formstrap";
|
||||||
|
|
||||||
|
// Needs to be changed, to not use a library,
|
||||||
|
// currently the form populates the fields on migrations, if you
|
||||||
|
// enter a UUID into field,
|
||||||
|
|
||||||
|
export default function IdSearchForm({ api }) {
|
||||||
|
const initialValues = {};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Formik initialValues={initialValues} onSubmit={api}>
|
||||||
|
{/* <Container>
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Col> */}
|
||||||
|
<Form>
|
||||||
|
<FormGroup>
|
||||||
|
<Label for="migrationId"></Label>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
name="migrationId"
|
||||||
|
id="migrationId"
|
||||||
|
placeholder="uuid"
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<Submit withSpinner>Submit</Submit>
|
||||||
|
</Form>
|
||||||
|
{/* </Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
</Container> */}
|
||||||
|
</Formik>
|
||||||
|
);
|
||||||
|
}
|
||||||
38
src/components/root/Pages/Functionality/InlineSearchBar.js
Normal file
38
src/components/root/Pages/Functionality/InlineSearchBar.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
// Inline search bar with direct UUID linking,
|
||||||
|
// Changes URL and populates the form at /migrations/ with the information from the request
|
||||||
|
|
||||||
|
class InLineSearch extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = { data: "" };
|
||||||
|
|
||||||
|
this.onChange = this.onChange.bind(this);
|
||||||
|
}
|
||||||
|
onChange(e) {
|
||||||
|
this.setState({ data: e.target.value });
|
||||||
|
}
|
||||||
|
onKeyPressed = (e) => {
|
||||||
|
// This is so we can access the state within the function
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
window.location.href =
|
||||||
|
"https://devui.benjamyn.love/migrations/" + this.state.data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
<input
|
||||||
|
className="right"
|
||||||
|
name="uuidIn"
|
||||||
|
value={this.state.data}
|
||||||
|
onChange={this.onChange}
|
||||||
|
onKeyDown={this.onKeyPressed}
|
||||||
|
></input>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default InLineSearch;
|
||||||
@ -1,9 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
|
|
||||||
export default function SubmitMigration() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
import DataGrid from 'react-data-grid';
|
|
||||||
import 'react-data-grid/dist/react-data-grid.css';
|
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{ key: 'id', name: 'ID' },
|
|
||||||
{ key: 'title', name: 'Title' }
|
|
||||||
];
|
|
||||||
|
|
||||||
const rows = [
|
|
||||||
{ id: 0, title: 'Example' },
|
|
||||||
{ id: 1, title: 'Demo' },
|
|
||||||
{ id: 3, title: 'Example' },
|
|
||||||
{ id: 4, title: 'Demo' },
|
|
||||||
{ id: 5, title: 'Example' },
|
|
||||||
{ id: 6, title: 'Demo' },
|
|
||||||
{ id: 7, title: 'Example' },
|
|
||||||
{ id: 8, title: 'Demo' },
|
|
||||||
{ id: 9, title: 'Demo' },
|
|
||||||
{ id: 10, title: 'Example' },
|
|
||||||
{ id: 11, title: 'Demo' },
|
|
||||||
{ id: 12, title: 'Example' },
|
|
||||||
{ id: 13, title: 'Demo' },
|
|
||||||
{ id: 14, title: 'Example' },
|
|
||||||
{ id: 15, title: 'Demo' },
|
|
||||||
{ id: 16, title: 'Demo' },
|
|
||||||
{ id: 17, title: 'Example' },
|
|
||||||
{ id: 18, title: 'Demo' },
|
|
||||||
{ id: 19, title: 'Example' },
|
|
||||||
{ id: 20, title: 'Demo' },
|
|
||||||
{ id: 21, title: 'Example' },
|
|
||||||
{ id: 22, title: 'Demo' }
|
|
||||||
];
|
|
||||||
|
|
||||||
function Table() {
|
|
||||||
return (
|
|
||||||
<DataGrid
|
|
||||||
columns={columns}
|
|
||||||
rows={rows}
|
|
||||||
rowsGetter={this.state.sidemigs.domain}
|
|
||||||
rowsCount={20}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export default Table;
|
|
||||||
@ -1,9 +1,15 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
import { callAPI } from "../../actions/API";
|
import { callAPI } from "../../actions/API";
|
||||||
import HistoricalSingle from "./Migrations/HistoricalSingle";
|
import HistoricalSingle from "./Tables/HistoricalSingle";
|
||||||
import Error from "../../actions/Error";
|
import Error from "../../actions/Error";
|
||||||
|
|
||||||
|
// Parent page for the /historical-migrations page,
|
||||||
|
// is referenced in the react route, and calls the main table using
|
||||||
|
// HIstoricalSingle,
|
||||||
|
// All migrations are called, and can be searched
|
||||||
|
// It actuall does error reporting, using `renderItems`
|
||||||
|
|
||||||
class Historical extends Component {
|
class Historical extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|||||||
@ -1,28 +1,50 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
import ReportSingleMigration from "./Migrations/ReportSingleMigration";
|
import ReportSingleMigration from "./Forms/ReportSingleMigration";
|
||||||
import { callAPI } from "../../actions/API";
|
import { callAPI } from "../../actions/API";
|
||||||
|
|
||||||
export default class Reports extends Component {
|
// This class will populate a form from a UUID in the address bar,
|
||||||
render() {
|
// e.g. /migrations/a7740b79-a7d9-4de7-b01e-00522fa4455a
|
||||||
const migrationId = ({ migrationId }) => {
|
// the form will populate with that migration UUID
|
||||||
console.log(migrationId.migrationId);
|
// ReportSingleMigration is the form that you can modify and sent PUT requests
|
||||||
callAPI
|
// to the DB
|
||||||
.get(`/${migrationId.migrationId}/`)
|
|
||||||
.then((response) =>
|
|
||||||
this.setState({
|
|
||||||
redirect: true,
|
|
||||||
migs: response.data,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
export default class Reports extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
migs: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
componentDidMount() {
|
||||||
|
const {
|
||||||
|
match: { params },
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const urlID = callAPI
|
||||||
|
.get(`/${params.migrationId}/`)
|
||||||
|
.then((response) =>
|
||||||
|
this.setState({
|
||||||
|
migs: response.data,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
// const urlID = ({ migrationId }) => {
|
||||||
|
// console.log(migrationId.migrationId);
|
||||||
|
|
||||||
|
// };
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ReportSingleMigration key={migrationId.id} item={migrationId} />
|
{/* {this.state.migs} */}
|
||||||
|
<ReportSingleMigration
|
||||||
|
key={this.state.migs.id}
|
||||||
|
item={this.state.migs}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,63 +1,47 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
class Migrations extends Component {
|
import IdSearchForm from "./Functionality/IdSearchForm";
|
||||||
bookedMig() {
|
import ReportSingleMigration from "./Forms/ReportSingleMigration";
|
||||||
return this.props.migs.filter(
|
import { callAPI } from "../../actions/API";
|
||||||
(booked) => booked.migration_status === "Booked"
|
|
||||||
).length;
|
// /migrations in the address bar,
|
||||||
}
|
// Allows the modification of migrations, and also populating a form
|
||||||
waitingMig() {
|
// by UUID.
|
||||||
return this.props.migs.filter(
|
// IDSearchForm is the UUID form at the top of the page,
|
||||||
(waiting) => waiting.migration_status === "Waiting Termination"
|
// ReportSingleMigration is the actual form, witha PUT API request on that page.
|
||||||
).length;
|
|
||||||
}
|
export default class Migrations extends Component {
|
||||||
completedMig() {
|
constructor(props) {
|
||||||
return this.props.migs.filter(
|
super(props);
|
||||||
(complete) => complete.migration_status === "Completed"
|
this.state = {
|
||||||
).length;
|
migs: [],
|
||||||
|
redirect: false,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const onSubmit = async (migrationId, { setSubmitting }) => {
|
||||||
|
callAPI
|
||||||
|
.get(`/${migrationId.migrationId}/`)
|
||||||
|
.then((response) =>
|
||||||
|
this.setState({
|
||||||
|
redirect: true,
|
||||||
|
migs: response.data,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
setSubmitting(false);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className="row">
|
<div>
|
||||||
<div className="col s6 m4">
|
<IdSearchForm api={onSubmit} />
|
||||||
<div className="card grey darken-1">
|
<ReportSingleMigration
|
||||||
<div className="card-content white-text">
|
key={this.state.migs.id}
|
||||||
<span className="card-title"></span>
|
item={this.state.migs}
|
||||||
{this.bookedMig()}
|
/>
|
||||||
</div>
|
|
||||||
<div className="card-action">
|
|
||||||
<a href="/upcoming-migrations">booked</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="col s6 m4">
|
|
||||||
<div className="card grey darken-1">
|
|
||||||
<div className="card-content white-text">
|
|
||||||
<span className="card-title"></span>
|
|
||||||
<p></p>
|
|
||||||
{this.waitingMig()}
|
|
||||||
</div>
|
|
||||||
<div className="card-action">
|
|
||||||
<a href="/upcoming-migrations">waiting</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="col s6 m4">
|
|
||||||
<div className="card grey darken-1">
|
|
||||||
<div className="card-content white-text">
|
|
||||||
<span className="card-title"></span>
|
|
||||||
{this.completedMig()}
|
|
||||||
</div>
|
|
||||||
<div className="card-action">
|
|
||||||
<a href="/historical-migrations">complete</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Migrations;
|
|
||||||
|
|||||||
@ -1,22 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
|
|
||||||
const MigrationSingle = ({ item }) => (
|
|
||||||
<div className="col s4 m4">
|
|
||||||
<div className="card-panel">
|
|
||||||
<div className="card-content black-text">
|
|
||||||
<ul className="collection with-header">
|
|
||||||
<li className="collection-header">
|
|
||||||
<a href={item.id}>
|
|
||||||
<p>{item.migration_status}</p>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li className="collection-item">{item.domain}</li>
|
|
||||||
<li className="collection-item">{item.booked_time}</li>
|
|
||||||
<li className="collection-item">{item.migration_status}</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default MigrationSingle;
|
|
||||||
@ -1,7 +1,10 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { SingleSide } from "./SingleSide";
|
import { SingleSide } from "../Tables/SingleSide";
|
||||||
import { callAPI } from "../../../actions/API";
|
import { callAPI } from "../../../actions/API";
|
||||||
|
|
||||||
|
// Side Migrations is displayed on the Home page,
|
||||||
|
// This page contains the API request, and storing state for the request,
|
||||||
|
|
||||||
export default class SideMigrations extends Component {
|
export default class SideMigrations extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|||||||
@ -1,40 +1,13 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
import IdSearchForm from "./AllReports/IdSearchForm";
|
// This page was should hold a way to generate reports/lists of
|
||||||
import ReportSingleMigration from "./Migrations/ReportSingleMigration";
|
// Migrations in varied statuses.
|
||||||
import { callAPI } from "../../actions/API";
|
|
||||||
|
|
||||||
export default class Reports extends Component {
|
export default class Reports extends Component {
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
migs: [],
|
|
||||||
redirect: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const onSubmit = async (migrationId, { setSubmitting }) => {
|
|
||||||
callAPI
|
|
||||||
.get(`/${migrationId.migrationId}/`)
|
|
||||||
.then((response) =>
|
|
||||||
this.setState({
|
|
||||||
redirect: true,
|
|
||||||
migs: response.data,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
setSubmitting(false);
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<IdSearchForm api={onSubmit} />
|
<h1>Reports</h1>
|
||||||
<ReportSingleMigration
|
|
||||||
key={this.state.migs.id}
|
|
||||||
item={this.state.migs}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,9 @@ import ToolkitProvider, {
|
|||||||
CSVExport,
|
CSVExport,
|
||||||
} from "react-bootstrap-table2-toolkit";
|
} from "react-bootstrap-table2-toolkit";
|
||||||
|
|
||||||
|
// Main table for the Historical migrations tab,
|
||||||
|
// receives all API information and displays as a table with a searchbox
|
||||||
|
|
||||||
const HistoricalSingle = () => {
|
const HistoricalSingle = () => {
|
||||||
const [list, setList] = useState([]);
|
const [list, setList] = useState([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@ -82,7 +85,7 @@ const HistoricalSingle = () => {
|
|||||||
dataField: "domain",
|
dataField: "domain",
|
||||||
text: "Domain",
|
text: "Domain",
|
||||||
sort: true,
|
sort: true,
|
||||||
formatter: (cell, row) => <a href={"reports/" + row.id}> {cell} </a>,
|
formatter: (cell, row) => <a href={"migrations/" + row.id}> {cell} </a>,
|
||||||
},
|
},
|
||||||
{ dataField: "booked_date", text: "Booked Date", sort: true },
|
{ dataField: "booked_date", text: "Booked Date", sort: true },
|
||||||
{ dataField: "booked_time", text: "Booked Time", sort: true },
|
{ dataField: "booked_time", text: "Booked Time", sort: true },
|
||||||
@ -2,6 +2,10 @@ import React from "react";
|
|||||||
import { BootstrapTable, TableHeaderColumn } from "react-bootstrap-table";
|
import { BootstrapTable, TableHeaderColumn } from "react-bootstrap-table";
|
||||||
import "../../../../react-bootstrap-table.css";
|
import "../../../../react-bootstrap-table.css";
|
||||||
|
|
||||||
|
// Single Side is directly referenced on the SideMigrations page,
|
||||||
|
// receives data from the get request and only displays small amounts of info
|
||||||
|
// this could be fleshed out/ linked to UUID's
|
||||||
|
|
||||||
export const SingleSide = ({ data }) => {
|
export const SingleSide = ({ data }) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -9,6 +9,10 @@ import ToolkitProvider, {
|
|||||||
CSVExport,
|
CSVExport,
|
||||||
} from "react-bootstrap-table2-toolkit";
|
} from "react-bootstrap-table2-toolkit";
|
||||||
|
|
||||||
|
// Directly linked to the parent page "Upcoming"
|
||||||
|
// this element creates the table
|
||||||
|
// Each domain links to a uuid, which then links to the page Migrations/uuid
|
||||||
|
|
||||||
const UpcomingSingle = () => {
|
const UpcomingSingle = () => {
|
||||||
const [list, setList] = useState([]);
|
const [list, setList] = useState([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@ -82,7 +86,7 @@ const UpcomingSingle = () => {
|
|||||||
dataField: "domain",
|
dataField: "domain",
|
||||||
text: "Domain",
|
text: "Domain",
|
||||||
sort: true,
|
sort: true,
|
||||||
formatter: (cell, row) => <a href={"reports/" + row.id}> {cell} </a>,
|
formatter: (cell, row) => <a href={"migrations/" + row.id}> {cell} </a>,
|
||||||
},
|
},
|
||||||
{ dataField: "booked_date", text: "Booked Date", sort: true },
|
{ dataField: "booked_date", text: "Booked Date", sort: true },
|
||||||
{ dataField: "booked_time", text: "Booked Time", sort: true },
|
{ dataField: "booked_time", text: "Booked Time", sort: true },
|
||||||
@ -1,6 +1,11 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
import UpcomingSingle from "./Tables/UpcomingSingle";
|
||||||
|
|
||||||
import UpcomingSingle from "./Migrations/UpcomingSingle";
|
// Upcoming parent page,
|
||||||
|
// Most of the good stuff is happening in UpcomingSingle, which does the
|
||||||
|
// main rendering of the table,
|
||||||
|
// may want to eventually do the API call here, to re-use the table
|
||||||
|
// instead of duplicating it.
|
||||||
|
|
||||||
class Upcoming extends Component {
|
class Upcoming extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
Reference in New Issue
Block a user