This commit is contained in:
root
2023-03-29 15:20:05 +00:00
parent 5ec489e0e0
commit a0bb8f2d1e
25468 changed files with 3063105 additions and 28 deletions

View File

@@ -0,0 +1,42 @@
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Button, Dropdown, DropdownButton } from 'react-bootstrap';
import { toast } from 'react-toastify';
import Axios from 'axios';
export default class Backup extends Component {
backup = (format) => {
var url = 'api/backup?format=' + format + '&token=' + window.token;
toast.info('Your backup has started downloading...');
Axios.get(url, {
responseType: 'blob'
})
.then((resp) => {
var a = document.createElement('a');
a.href = url;
a.download = "";
document.body.appendChild(a);
a.click();
a.remove();
toast.success('Backup downloaded');
})
.catch((err) => {
console.log(err);
})
}
render() {
return (
<DropdownButton title="Backup" variant="primary" className="m-2 d-inline-block">
<Dropdown.Item href="#" onClick={() => { this.backup('json') }}>JSON</Dropdown.Item>
<Dropdown.Item href="#" onClick={() => { this.backup('csv') }}>CSV</Dropdown.Item>
</DropdownButton>
);
}
}
if (document.getElementById('Backup')) {
ReactDOM.render(<Backup />, document.getElementById('Backup'));
}

View File

@@ -0,0 +1,140 @@
import React, { Component, version } from 'react';
import ReactDOM from 'react-dom';
import Axios from 'axios';
import { Modal, Collapse, Button } from 'react-bootstrap';
export default class Changelog extends Component {
constructor(props) {
super(props)
this.state = {
changelog: {},
modal: false,
loading: true,
hidden: false,
}
}
componentDidMount = () => {
if( (window.config.auth == true && window.authenticated == true) || window.config.auth == false) {
this.getChangelog();
}
}
getChangelog = () => {
Axios.get('api/update/changelog?token=' + window.token)
.then((resp) => {
this.setState({
changelog: resp.data.data,
loading: false
});
})
}
showModal = () => {
this.setState({
modal: true,
});
}
hideModal = () => {
this.setState({
modal: false,
});
}
toggleHidden = () => {
var hidden = this.state.hidden;
if(hidden) {
this.setState({
hidden: false
});
} else {
this.setState({
hidden: true
});
}
}
versionList = (key, data) => {
return (
<div key={key}>
<h5>Version: {key}</h5>
<ul>
{data.map((e,i) => {
if(e.link == '') {
return <li key={key.split('.').join() + i}>{e.description}</li>
} else {
return <li key={key + i}><a href={e.link} target="_blank" rel="noopener noreferer">{e.description}</a></li>
}
})}
</ul>
</div>
);
}
makeChangelog() {
var changelog = this.state.changelog;
var versionsVis = [];
var versionsHid = [];
var i = 0;
for(var key in changelog) {
if(i <= 5) {
versionsVis.push(this.versionList(key, changelog[key]));
} else {
versionsHid.push(this.versionList(key, changelog[key]));
}
i++;
}
return {
visible: versionsVis,
hidden: versionsHid
};
}
render() {
var show = this.state.modal;
var loading = this.state.loading;
var showHidden = this.state.hidden;
if(loading) {
return <></>
} else {
var changelog = this.makeChangelog();
return (
<div className="text-muted ml-1 d-inline-block">
<i className="ti-link mouse" onClick={this.showModal} />
<Modal show={show} onHide={this.hideModal} animation={true}>
<Modal.Body>
<h3>Changelog:</h3>
{changelog.visible}
{changelog.hidden.length > 5 &&
<>
<Collapse in={showHidden}>
<div>
{changelog.hidden}
</div>
</Collapse>
<div className="w-100 text-center">
{showHidden ?
<Button variant="primary" className="mx-auto mouse" onClick={this.toggleHidden}>Show less</Button>
:
<Button variant="primary" className="mx-auto mouse" onClick={this.toggleHidden}>Show more</Button>
}
</div>
</>
}
</Modal.Body>
</Modal>
</div>
);
}
}
}
if (document.getElementById('Changelog')) {
ReactDOM.render(<Changelog />, document.getElementById('Changelog'));
}

View File

@@ -0,0 +1,37 @@
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Container } from 'react-bootstrap';
import { Row } from 'react-bootstrap';
import { Col } from 'react-bootstrap';
import Backup from './Backup';
import Restore from './Restore';
export default class DataRow extends Component {
render() {
if( (window.config.auth == true && window.authenticated == true) || window.config.auth == false) {
return (
<Container className="mb-4">
<Row>
<Col sm={{ span: 12 }} className="text-center">
<p>Use these buttons to backup/restore your data</p>
</Col>
</Row>
<Row>
<Col sm={{ span: 12 }} className="text-center">
<Backup />
<Restore />
</Col>
</Row>
</Container>
);
} else {
return (
<></>
)
}
}
}
if (document.getElementById('DataRow')) {
ReactDOM.render(<DataRow />, document.getElementById('DataRow'));
}

View File

@@ -0,0 +1,209 @@
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Button, Modal, Form, Tooltip, OverlayTrigger, Dropdown, DropdownButton } from 'react-bootstrap';
import { toast } from 'react-toastify';
import Axios from 'axios';
import CSVFileValidator from 'csv-file-validator';
export default class Restore extends Component {
constructor(props) {
super(props);
this.state = {
show: false,
data: null,
uploadReady: false,
filename: 'Upload your backup',
format: 'json'
};
}
showModal = (format) => {
this.setState({
show: true,
format: format
});
}
hideModal = () => {
this.setState({
show: false
});
}
readFile = (e, format) => {
var file = e.target.files[0];
var reader = new FileReader();
reader.readAsText(file, 'UTF-8');
reader.onload = function(evt) {
var data = evt.target.result.trim();
if(format == 'csv') {
var csv = data.substr(45);
var config = {
headers: [
{
name: "id",
inputName: 'id',
required: false,
},
{
name: "ping",
inputName: 'ping',
required: true,
requiredError: function (headerName, rowNumber, columnNumber) {
return `${headerName} is required in the ${rowNumber} row / ${columnNumber} column`
}
},
{
name: "upload",
inputName: 'upload',
required: true,
requiredError: function (headerName, rowNumber, columnNumber) {
return `${headerName} is required in the ${rowNumber} row / ${columnNumber} column`
}
},
{
name: "download",
inputName: 'download',
required: true,
requiredError: function (headerName, rowNumber, columnNumber) {
return `${headerName} is required in the ${rowNumber} row / ${columnNumber} column`
}
},
{
name: "created_at",
inputName: 'created_at',
required: false,
},
{
name: "server_id",
inputName: 'server_id',
required: false,
},
{
name: "server_name",
inputName: 'server_name',
required: false,
},
{
name: "server_host",
inputName: 'server_host',
required: false,
},
{
name: "url",
inputName: 'url',
required: false,
},
{
name: "scheduled",
inputName: 'scheduled',
required: false,
},
{
name: "failed",
inputName: 'failed',
required: false,
},
{
name: "updated_at",
inputName: 'updated_at',
required: false,
}
]
};
CSVFileValidator(csv, config)
.then((e) => {
if(e.inValidMessages.length > 0) {
toast.error('Your upload file is not valid ' + format.toUpperCase());
} else {
this.setState({
data: data,
uploadReady: true,
filename: file.name
});
}
})
.catch((e) => {
toast.error('Your upload file is not valid ' + format.toUpperCase());
})
} else {
try {
var data = JSON.parse(data);
this.setState({
data: data,
uploadReady: true,
filename: file.name
});
} catch(e) {
console.log(e);
toast.error('Your upload file is not valid ' + format.toUpperCase());
}
}
}.bind(this)
reader.onerror = function (evt) {
toast.error('Something went wrong parsing your backup file.');
}
}
uploadFile = () => {
var data = { data: this.state.data, format: this.state.format };
var url = 'api/restore?token=' + window.token;
Axios.post(url, data)
.then((resp) => {
toast.success('Your data is being restored...');
this.setState({
show: false,
data: null,
uploadReady: false,
filename: 'Upload your backup'
});
})
.catch((err) => {
console.log(err);
})
}
render() {
var show = this.state.show;
var uploadReady = this.state.uploadReady;
var filename = this.state.filename;
return (
<>
<DropdownButton variant="secondary" title="Restore" className="m-2 d-inline-block">
<Dropdown.Item href="#" onClick={() => { this.showModal('json') }}>JSON</Dropdown.Item>
<Dropdown.Item href="#" onClick={() => { this.showModal('csv') }}>CSV</Dropdown.Item>
</DropdownButton>
<Modal show={show} onHide={this.hideModal} animation={true}>
<Modal.Header closeButton>
<Modal.Title>Restore from a backup</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>Upload your {this.state.format.toUpperCase()} backup file here:</p>
<Form.File
id="restoreFileInput"
label={"Upload " + this.state.format.toUpperCase() + " file"}
className="mb-3"
custom
>
<Form.File.Input onChange={(e) => { this.readFile(e, this.state.format) }} />
<Form.File.Label data-browse="Choose file">
{filename}
</Form.File.Label>
</Form.File>
{uploadReady === true &&
<Button variant="secondary" onClick={this.uploadFile}>Restore</Button>
}
</Modal.Body>
</Modal>
</>
);
}
}
if (document.getElementById('Restore')) {
ReactDOM.render(<Restore />, document.getElementById('Restore'));
}