Compare commits
14 Commits
a3c380ffd1
...
1050709fd2
| Author | SHA1 | Date | |
|---|---|---|---|
| 1050709fd2 | |||
| 9d499eb986 | |||
| 85b4afd835 | |||
| 6e6ad45149 | |||
| 587e8ef70d | |||
| 9c9c584a84 | |||
| 03ee5d6fa8 | |||
| ec75fb476f | |||
| 2ed7998897 | |||
| ab4de61b42 | |||
| 0ef729256f | |||
| 5bafe0e1a2 | |||
| eec749c029 | |||
| 47eebd3e5a |
3
.gitignore
vendored
3
.gitignore
vendored
@ -10,13 +10,16 @@
|
|||||||
|
|
||||||
# production
|
# production
|
||||||
/build
|
/build
|
||||||
|
build.zip
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.env
|
.env
|
||||||
.env.local
|
.env.local
|
||||||
|
.env.development
|
||||||
.env.development.local
|
.env.development.local
|
||||||
.env.test.local
|
.env.test.local
|
||||||
|
.env.production
|
||||||
.env.production.local
|
.env.production.local
|
||||||
|
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
|
|||||||
5
package-lock.json
generated
5
package-lock.json
generated
@ -13561,6 +13561,11 @@
|
|||||||
"symbol-observable": "^1.2.0"
|
"symbol-observable": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"redux-thunk": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw=="
|
||||||
|
},
|
||||||
"regenerate": {
|
"regenerate": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz",
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
"react-scripts": "4.0.0",
|
"react-scripts": "4.0.0",
|
||||||
"reactstrap": "^8.7.1",
|
"reactstrap": "^8.7.1",
|
||||||
"redux": "^4.0.5",
|
"redux": "^4.0.5",
|
||||||
|
"redux-thunk": "^2.3.0",
|
||||||
"web-vitals": "^0.2.4",
|
"web-vitals": "^0.2.4",
|
||||||
"yup": "^0.32.5"
|
"yup": "^0.32.5"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="stylesheet" href="main.css">
|
<link rel="stylesheet" href="main.css">
|
||||||
@ -16,17 +15,14 @@
|
|||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="https://npmcdn.com/react-bootstrap-table/dist/react-bootstrap-table-all.min.css">
|
<link rel="stylesheet" href="https://npmcdn.com/react-bootstrap-table/dist/react-bootstrap-table-all.min.css">
|
||||||
</link>
|
</link>
|
||||||
|
|
||||||
<title>Migrations Tracker</title>
|
<title>Migrations Tracker</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<!-- Compiled and minified JavaScript -->
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
|
||||||
<script src="https://npmcdn.com/react-bootstrap-table/dist/react-bootstrap-table.min.js"></script>
|
<!-- This breaks things -->
|
||||||
|
<!-- <script src="https://npmcdn.com/react-bootstrap-table/dist/react-bootstrap-table.min.js"></script> -->
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@ -1,9 +1,10 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
|
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
|
||||||
|
|
||||||
// Store
|
// Store currently in progress
|
||||||
import { Provider } from "react-redux";
|
|
||||||
import store from "../redux/store";
|
// import { Provider } from "react-redux";
|
||||||
|
// import store from "../redux/store";
|
||||||
|
|
||||||
// Routes
|
// Routes
|
||||||
import Migrations from "./root/Pages/Migrations";
|
import Migrations from "./root/Pages/Migrations";
|
||||||
@ -21,12 +22,10 @@ import Navigation from "./root/Navigation";
|
|||||||
class App extends Component {
|
class App extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Provider store={store}>
|
// <Provider store={store}>
|
||||||
<Router>
|
<Router>
|
||||||
<Navigation />
|
<Navigation />
|
||||||
<div className="row">
|
<div className="col 13">
|
||||||
<div className="col s12 m4 13">
|
|
||||||
<div className="container-fluid">
|
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/" component={Home} />
|
<Route exact path="/" component={Home} />
|
||||||
<Route exact path="/book" component={Book} />
|
<Route exact path="/book" component={Book} />
|
||||||
@ -36,16 +35,12 @@ class App extends Component {
|
|||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/upcoming-migrations"
|
path="/upcoming-migrations"
|
||||||
render={(props) => (
|
render={(props) => <GenericList {...props} APILINK="/pending/" />}
|
||||||
<GenericList {...props} APILINK="/pending/" />
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/missed"
|
path="/missed"
|
||||||
render={(props) => (
|
render={(props) => <GenericList {...props} APILINK="/missed/" />}
|
||||||
<GenericList {...props} APILINK="/missed/" />
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
@ -71,23 +66,17 @@ class App extends Component {
|
|||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/historical-migrations"
|
path="/historical-migrations"
|
||||||
render={(props) => (
|
render={(props) => <GenericList {...props} APILINK="/all/" />}
|
||||||
<GenericList {...props} APILINK="/all/" />
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/booked"
|
path="/booked"
|
||||||
render={(props) => (
|
render={(props) => <GenericList {...props} APILINK="/booked/" />}
|
||||||
<GenericList {...props} APILINK="/booked/" />
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Router>
|
</Router>
|
||||||
</Provider>
|
// </Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
|
||||||
import App from './App';
|
|
||||||
|
|
||||||
test('renders learn react link', () => {
|
|
||||||
render(<App />);
|
|
||||||
const linkElement = screen.getByText(/learn react/i);
|
|
||||||
expect(linkElement).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
@ -2,6 +2,8 @@ import axios from "axios";
|
|||||||
|
|
||||||
// Axios create, exporting callAPI
|
// Axios create, exporting callAPI
|
||||||
|
|
||||||
|
|
||||||
export const callAPI = axios.create({
|
export const callAPI = axios.create({
|
||||||
baseURL: process.env.REACT_APP_API_ADDRESS,
|
baseURL: process.env.REACT_APP_API_ADDRESS,
|
||||||
|
headers: {'Authorization': "Api-Key " + process.env.REACT_APP_API_KEY}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -10,6 +10,7 @@ export const Error = () => (
|
|||||||
<span className="card-title">
|
<span className="card-title">
|
||||||
<i className="large material-icons">do_not_disturb</i>
|
<i className="large material-icons">do_not_disturb</i>
|
||||||
</span>
|
</span>
|
||||||
|
<h3>API OFFLINE</h3>
|
||||||
</center>
|
</center>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import React, { Component } from "react";
|
|||||||
import { callAPI } from "../actions/API";
|
import { callAPI } from "../actions/API";
|
||||||
import Cards from "./Pages/Cards";
|
import Cards from "./Pages/Cards";
|
||||||
import GenericList from "../root/Pages/GenericList";
|
import GenericList from "../root/Pages/GenericList";
|
||||||
|
import TimeSlotHelper from "./Pages/TimeSlotHelper";
|
||||||
|
|
||||||
import { UList } from "../root/common/Functionality/UnorderedList";
|
import { UList } from "../root/common/Functionality/UnorderedList";
|
||||||
import { builfArrayFromObject } from "../actions/Error";
|
import { builfArrayFromObject } from "../actions/Error";
|
||||||
|
|
||||||
@ -23,6 +25,19 @@ export class Home extends Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTimeslot(days) {
|
||||||
|
callAPI
|
||||||
|
.get("/timeslots/?days=" + days)
|
||||||
|
.then((request) => {
|
||||||
|
return request.data;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.setState({
|
||||||
|
error: error,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
callAPI
|
callAPI
|
||||||
.get("/")
|
.get("/")
|
||||||
@ -36,40 +51,28 @@ export class Home extends Component {
|
|||||||
error: error,
|
error: error,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
callAPI
|
|
||||||
.get("/timeslots")
|
|
||||||
.then((request) => {
|
|
||||||
this.setState({
|
|
||||||
timeslots: request.data,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
this.setState({
|
|
||||||
error: error,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
<div className="container">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="divider"></div>
|
<div className="col s12"></div>
|
||||||
|
</div>
|
||||||
<div className="section">
|
<div className="row">
|
||||||
<div className="col s7">
|
<div className="col s4 18">
|
||||||
<Cards migs={this.state.migs} />
|
<Cards migs={this.state.migs} />
|
||||||
</div>
|
</div>
|
||||||
<div className="col s5">
|
<div className="col s8 12">
|
||||||
<p>Current availability for {Date()}</p>
|
{/* <p>Current availability for {Date()}</p>
|
||||||
<UList listItems={builfArrayFromObject(this.state.timeslots)} />
|
<UList listItems={builfArrayFromObject(this.state.timeslots)} /> */}
|
||||||
|
{/* <TimeSlotHelper /> */}
|
||||||
</div>
|
</div>
|
||||||
<div className="divider"></div>
|
<div className="row">
|
||||||
<div className="section">
|
|
||||||
<div className="col s12">
|
<div className="col s12">
|
||||||
<GenericList APILINK="/pending/" />
|
<GenericList APILINK="/pending/" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="divider"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
|
import { callAPI } from "../../actions/API";
|
||||||
import FormPage from "../common/Forms/FormPage";
|
import FormPage from "../common/Forms/FormPage";
|
||||||
|
|
||||||
// Parent page for the Book component,
|
// Parent page for the Book component,
|
||||||
@ -10,9 +11,22 @@ export default class Book extends Component {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
migs: [],
|
migs: [],
|
||||||
|
timeslots: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
callAPI
|
||||||
|
.get('/gettimeslots/')
|
||||||
|
.then( (response) => {
|
||||||
|
this.setState({
|
||||||
|
timeslots: response.data
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
if (this.state.timeslots.length > 0) {
|
||||||
return (
|
return (
|
||||||
<div className="container-fluid">
|
<div className="container-fluid">
|
||||||
<div className="section">
|
<div className="section">
|
||||||
@ -22,10 +36,13 @@ export default class Book extends Component {
|
|||||||
|
|
||||||
<div className="section">
|
<div className="section">
|
||||||
<div className="col s12">
|
<div className="col s12">
|
||||||
<FormPage />
|
<FormPage timeslots={this.state.timeslots} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}else{
|
||||||
|
return(<div></div>)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import CompTable from "../common/Tables/CompTable";
|
import CompTable from "../common/Tables/CompTable";
|
||||||
import { callAPI } from "../../actions/API"
|
import { callAPI } from "../../actions/API";
|
||||||
import { Error } from "../../actions/Error";
|
import { Error } from "../../actions/Error";
|
||||||
|
|
||||||
// Missing parent page,
|
// Missing parent page,
|
||||||
@ -18,9 +18,10 @@ class GenericList extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderItems() {
|
renderItems() {
|
||||||
console.log(this.props.APILINK)
|
|
||||||
if (!this.state.error) {
|
if (!this.state.error) {
|
||||||
return <CompTable data={callAPI(this.props.APILINK)} />;
|
return (
|
||||||
|
<CompTable data={callAPI(this.props.APILINK)} key={this.state.error} />
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
console.log("error");
|
console.log("error");
|
||||||
return <Error />;
|
return <Error />;
|
||||||
@ -28,19 +29,7 @@ class GenericList extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return <div>{this.renderItems()}</div>;
|
||||||
<div className="row">
|
|
||||||
<div className="divider"></div>
|
|
||||||
<div className="section">
|
|
||||||
<div className="col s12"></div>
|
|
||||||
</div>
|
|
||||||
<div className="divider"></div>
|
|
||||||
<div className="section">
|
|
||||||
<div className="col s12">{this.renderItems()}</div>
|
|
||||||
</div>
|
|
||||||
<div className="divider"></div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
54
src/components/root/Pages/TimeSlotHelper.js
Normal file
54
src/components/root/Pages/TimeSlotHelper.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import React, { Component } from "react";
|
||||||
|
import TimeSlots from "../common/Tables/TimeSlots";
|
||||||
|
import { callAPI } from "../../actions/API";
|
||||||
|
import { Error } from "../../actions/Error";
|
||||||
|
|
||||||
|
// Missing 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 GenericList extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
error: false,
|
||||||
|
timeslots: [],
|
||||||
|
bookedslots: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
callAPI.get("/gettimeslots/").then((response) => {
|
||||||
|
this.setState({
|
||||||
|
timeslots: response.data,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderItems() {
|
||||||
|
if (!this.state.error) {
|
||||||
|
return (
|
||||||
|
<TimeSlots
|
||||||
|
timeSlots={this.state.timeslots}
|
||||||
|
bookedSlots={this.state.bookedslots}
|
||||||
|
key={this.state.timeslots}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return <Error />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <div>{this.renderItems()}</div>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default GenericList;
|
||||||
|
|
||||||
|
// if (this.state.timeslots > 0) {
|
||||||
|
// else {
|
||||||
|
// return <Error />;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
@ -23,16 +23,8 @@ const InputValidation = Yup.object().shape({
|
|||||||
.required("Please enter a domain"),
|
.required("Please enter a domain"),
|
||||||
username: Yup.string().min(2, "Too Short!").required("Required"),
|
username: Yup.string().min(2, "Too Short!").required("Required"),
|
||||||
original_server: Yup.string()
|
original_server: Yup.string()
|
||||||
.matches(
|
|
||||||
/^((([1-9]?\d|1\d\d|2[0-5][0-5]|2[0-4]\d)\.){3}([1-9]?\d|1\d\d|2[0-5][0-5]|2[0-4]\d))|(((https?):\/\/)?(www.)?[a-z0-9]+(\.[a-z]{2,}){1,3}(#?\/?[a-zA-Z0-9#]+)*\/?(\?[a-zA-Z0-9-_]+=[a-zA-Z0-9-%]+&?)?)|([a-z0-9]{0,4}-[a-z0-9]{0,2}-[a-z0-9]{0,3})$/i,
|
|
||||||
"Please enter a valid IPv4 Address or domain"
|
|
||||||
)
|
|
||||||
.required("Please enter a valid IPv4 or domain"),
|
.required("Please enter a valid IPv4 or domain"),
|
||||||
new_server: Yup.string()
|
new_server: Yup.string()
|
||||||
.matches(
|
|
||||||
/^((([1-9]?\d|1\d\d|2[0-5][0-5]|2[0-4]\d)\.){3}([1-9]?\d|1\d\d|2[0-5][0-5]|2[0-4]\d))|(((https?):\/\/)?(www.)?[a-z0-9]+(\.[a-z]{2,}){1,3}(#?\/?[a-zA-Z0-9#]+)*\/?(\?[a-zA-Z0-9-_]+=[a-zA-Z0-9-%]+&?)?)|([a-z0-9]{0,4}-[a-z0-9]{0,2}-[a-z0-9]{0,3})$/i,
|
|
||||||
"Please enter a valid IPv4 Address or domain"
|
|
||||||
)
|
|
||||||
.required("Please enter a valid IPv4 or domain"),
|
.required("Please enter a valid IPv4 or domain"),
|
||||||
agent_booked: Yup.string()
|
agent_booked: Yup.string()
|
||||||
.min(2, "Too short!")
|
.min(2, "Too short!")
|
||||||
@ -44,7 +36,7 @@ const InputValidation = Yup.object().shape({
|
|||||||
booked_date: Yup.date().required("Please enter a date!"),
|
booked_date: Yup.date().required("Please enter a date!"),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const CPanelBooking = () => {
|
export const CPanelBooking = (timeslots) => {
|
||||||
const [respID, setRespID] = useState(0);
|
const [respID, setRespID] = useState(0);
|
||||||
const [error, setError] = useState(0);
|
const [error, setError] = useState(0);
|
||||||
|
|
||||||
@ -56,7 +48,7 @@ export const CPanelBooking = () => {
|
|||||||
const onSubmit = async (values, { setSubmitting, resetForm }) => {
|
const onSubmit = async (values, { setSubmitting, resetForm }) => {
|
||||||
console.log(values);
|
console.log(values);
|
||||||
callAPI
|
callAPI
|
||||||
.post("/", values)
|
.post("/book/", values)
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
// console.log(response);
|
// console.log(response);
|
||||||
// add function here
|
// add function here
|
||||||
@ -70,6 +62,7 @@ export const CPanelBooking = () => {
|
|||||||
});
|
});
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
@ -108,12 +101,7 @@ export const CPanelBooking = () => {
|
|||||||
className="has-success"
|
className="has-success"
|
||||||
>
|
>
|
||||||
<option>Select</option>
|
<option>Select</option>
|
||||||
<option>00:00-03:00</option>
|
{timeslots.timeslots.map((slot) => <option>{slot}</option>)}
|
||||||
<option>03:00-06:00</option>
|
|
||||||
<option>06:00-09:00</option>
|
|
||||||
<option>08:00-12:00</option>
|
|
||||||
<option>12:00-18:00</option>
|
|
||||||
<option>18:00-00:00</option>
|
|
||||||
</Input>
|
</Input>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import classnames from "classnames";
|
|||||||
import { CPanelBooking } from "./CPanelBooking";
|
import { CPanelBooking } from "./CPanelBooking";
|
||||||
import EmailBooking from "./EmailBooking";
|
import EmailBooking from "./EmailBooking";
|
||||||
|
|
||||||
const FormPage = ({ item }) => {
|
const FormPage = ({ timeslots, item }) => {
|
||||||
const [activeTab, setActiveTab] = useState("1");
|
const [activeTab, setActiveTab] = useState("1");
|
||||||
|
|
||||||
const toggle = (tab) => {
|
const toggle = (tab) => {
|
||||||
@ -23,7 +23,6 @@ const FormPage = ({ item }) => {
|
|||||||
// Parent page from the Book section,
|
// Parent page from the Book section,
|
||||||
// Can be expanded to offer email migration bookings,
|
// Can be expanded to offer email migration bookings,
|
||||||
// elements below do the POST requests.
|
// elements below do the POST requests.
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Nav tabs>
|
<Nav tabs>
|
||||||
@ -52,7 +51,7 @@ const FormPage = ({ item }) => {
|
|||||||
<TabPane tabId="1">
|
<TabPane tabId="1">
|
||||||
<Row>
|
<Row>
|
||||||
<Col sm="12">
|
<Col sm="12">
|
||||||
<CPanelBooking />
|
<CPanelBooking timeslots={timeslots} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
|
|||||||
@ -5,7 +5,7 @@ export function UList(props) {
|
|||||||
<div>
|
<div>
|
||||||
<ul>
|
<ul>
|
||||||
{props.listItems.map((item) => (
|
{props.listItems.map((item) => (
|
||||||
<li liClass="white-text" className={props.liClass}>
|
<li liclass="white-text" className={props.liclass} key={item}>
|
||||||
{item}
|
{item}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -14,7 +14,6 @@ import ToolkitProvider, {
|
|||||||
const CompTable = (props) => {
|
const CompTable = (props) => {
|
||||||
const [list, setList] = useState([]);
|
const [list, setList] = useState([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const { SearchBar } = Search;
|
const { SearchBar } = Search;
|
||||||
const { ExportCSVButton } = CSVExport;
|
const { ExportCSVButton } = CSVExport;
|
||||||
const sizePerPageRenderer = ({
|
const sizePerPageRenderer = ({
|
||||||
@ -107,7 +106,6 @@ const CompTable = (props) => {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{ 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: "agent_booked", text: "Agent initials", sort: true },
|
{ dataField: "agent_booked", text: "Agent initials", sort: true },
|
||||||
{
|
{
|
||||||
dataField: "domain",
|
dataField: "domain",
|
||||||
@ -120,9 +118,7 @@ const CompTable = (props) => {
|
|||||||
{ dataField: "migration_type", text: "Type", sort: true },
|
{ dataField: "migration_type", text: "Type", sort: true },
|
||||||
{ dataField: "original_server", text: "Original Server", sort: true },
|
{ dataField: "original_server", text: "Original Server", sort: true },
|
||||||
{ dataField: "new_server", text: "New Server", sort: true },
|
{ dataField: "new_server", text: "New Server", sort: true },
|
||||||
// { dataField: "term_date", text: "Termination Date", sort: true },
|
|
||||||
{ dataField: "notes", text: "Notes", sort: true },
|
{ dataField: "notes", text: "Notes", sort: true },
|
||||||
// { dataField: "submit_time", text: "Submit Time", sort: true },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -130,7 +126,7 @@ const CompTable = (props) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="HistoricalSingle">
|
<div>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<ToolkitProvider
|
<ToolkitProvider
|
||||||
keyField="name"
|
keyField="name"
|
||||||
@ -138,12 +134,13 @@ const CompTable = (props) => {
|
|||||||
columns={columns}
|
columns={columns}
|
||||||
search
|
search
|
||||||
exportCSV
|
exportCSV
|
||||||
|
key={columns.id}
|
||||||
>
|
>
|
||||||
{(props) => (
|
{(props) => (
|
||||||
<div>
|
<div>
|
||||||
<div className="serSec">
|
<div className="serSec">
|
||||||
<h3 className="hdrOne"></h3>
|
<h3 className="hdrOne"></h3>
|
||||||
<SearchBar {...props.searchProps} />
|
<SearchBar {...props.searchProps} key={columns} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="table-responsive">
|
<div className="table-responsive">
|
||||||
@ -154,9 +151,11 @@ const CompTable = (props) => {
|
|||||||
striped
|
striped
|
||||||
hover
|
hover
|
||||||
condensed
|
condensed
|
||||||
|
key={columns.id}
|
||||||
|
keyField="id"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ExportCSVButton {...props.csvProps}>
|
<ExportCSVButton {...props.csvProps} key={columns}>
|
||||||
Export CSV!!
|
Export CSV!!
|
||||||
</ExportCSVButton>
|
</ExportCSVButton>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
133
src/components/root/common/Tables/TimeSlots.js
Normal file
133
src/components/root/common/Tables/TimeSlots.js
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
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";
|
||||||
|
|
||||||
|
// notes
|
||||||
|
//
|
||||||
|
|
||||||
|
const TimeSlots = (props) => {
|
||||||
|
const [list, setList, setTimeSlots, setBookedSlots] = 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 setList = await props.setList;
|
||||||
|
setList();
|
||||||
|
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: "bookedSlots", text: "bookedslots", sort: true },
|
||||||
|
{ dataField: "timeSlots", text: "timeslots", sort: true },
|
||||||
|
];
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getListData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{loading ? (
|
||||||
|
<ToolkitProvider
|
||||||
|
keyField="name"
|
||||||
|
data={list}
|
||||||
|
columns={columns}
|
||||||
|
search
|
||||||
|
exportCSV
|
||||||
|
key={columns.id}
|
||||||
|
keyField="id"
|
||||||
|
>
|
||||||
|
{(props) => (
|
||||||
|
<div>
|
||||||
|
<div className="serSec">
|
||||||
|
<h3 className="hdrOne"></h3>
|
||||||
|
<SearchBar {...props.searchProps} key={columns} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="table-responsive">
|
||||||
|
<BootstrapTable
|
||||||
|
{...props.baseProps}
|
||||||
|
filter={filterFactory()}
|
||||||
|
pagination={paginationFactory(options)}
|
||||||
|
striped
|
||||||
|
hover
|
||||||
|
condensed
|
||||||
|
key={columns.id}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ExportCSVButton {...props.csvProps} key={columns}>
|
||||||
|
Export CSV!!
|
||||||
|
</ExportCSVButton>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</ToolkitProvider>
|
||||||
|
) : (
|
||||||
|
<ReactBootstrap.Spinner animation="border" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TimeSlots;
|
||||||
@ -1,13 +0,0 @@
|
|||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
||||||
sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
|
||||||
monospace;
|
|
||||||
}
|
|
||||||
@ -1,6 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import "./index.css";
|
|
||||||
import App from "./components/App";
|
import App from "./components/App";
|
||||||
import reportWebVitals from "./reportWebVitals";
|
import reportWebVitals from "./reportWebVitals";
|
||||||
|
|
||||||
@ -11,7 +10,4 @@ ReactDOM.render(
|
|||||||
document.getElementById("root")
|
document.getElementById("root")
|
||||||
);
|
);
|
||||||
|
|
||||||
// If you want to start measuring performance in your app, pass a function
|
|
||||||
// to log results (for example: reportWebVitals(console.log))
|
|
||||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
|
||||||
reportWebVitals();
|
reportWebVitals();
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
export const ADD_ARTICLE = "ADD_ARTICLE";
|
export const GET_MIGRATIONS = "GET_MIGRATIONS";
|
||||||
export const DATA_LOADED = "DATA_LOADED";
|
export const DATA_LOADED = "DATA_LOADED";
|
||||||
export const API_ERRORED = "API_ERRORED";
|
export const API_ERRORED = "API_ERRORED";
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { ADD_ARTICLE } from "../constants/action-types";
|
import { GET_MIGRATIONS } from "../constants/action-types";
|
||||||
|
|
||||||
const forbiddenWords = ["spam", "money"];
|
const forbiddenWords = ["spam", "money"];
|
||||||
|
|
||||||
@ -6,7 +6,7 @@ export function forbiddenWordsMiddleware({ dispatch }) {
|
|||||||
return function (next) {
|
return function (next) {
|
||||||
return function (action) {
|
return function (action) {
|
||||||
// do your stuff
|
// do your stuff
|
||||||
if (action.type === ADD_ARTICLE) {
|
if (action.type === GET_MIGRATIONS) {
|
||||||
const foundWord = forbiddenWords.filter((word) =>
|
const foundWord = forbiddenWords.filter((word) =>
|
||||||
action.payload.title.includes(word)
|
action.payload.title.includes(word)
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,20 +1,21 @@
|
|||||||
import { ADD_ARTICLE, DATA_LOADED } from "../constants/action-types";
|
import { GET_MIGRATIONS, DATA_LOADED } from "../constants/action-types";
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
articles: [],
|
migs: [],
|
||||||
remoteArticles: [],
|
timeslots: [],
|
||||||
|
error: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
function rootReducer(state = initialState, action) {
|
function rootReducer(state = initialState, action) {
|
||||||
if (action.type === ADD_ARTICLE) {
|
if (action.type === GET_MIGRATIONS) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
articles: state.articles.concat(action.payload),
|
migs: state.migs.concat(action.payload),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === DATA_LOADED) {
|
if (action.type === DATA_LOADED) {
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
remoteArticles: state.remoteArticles.concat(action.payload),
|
timeslots: state.timeslots.concat(action.payload),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
|
|||||||
Reference in New Issue
Block a user