Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified accident/__pycache__/__init__.cpython-36.pyc
Binary file not shown.
Binary file modified accident/__pycache__/apps.cpython-36.pyc
Binary file not shown.
Binary file modified accident/__pycache__/filters.cpython-36.pyc
Binary file not shown.
Binary file modified accident/__pycache__/models.cpython-36.pyc
Binary file not shown.
Binary file modified accident/__pycache__/permissions.cpython-36.pyc
Binary file not shown.
Binary file modified accident/__pycache__/serializers.cpython-36.pyc
Binary file not shown.
Binary file modified accident/__pycache__/urls.cpython-36.pyc
Binary file not shown.
Binary file modified accident/__pycache__/views.cpython-36.pyc
Binary file not shown.
5 changes: 3 additions & 2 deletions accident/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ class AccidentFilter(FilterSet):
class Meta:
model = Accident
fields = {
# 'accident_class': ['number',],
'accident_class': ['exact',],
'posts_block': ['exact',],
'time_appeared': ['date__range',]
'time_appeared': ['gte', 'lte', 'date__range'],
'time_solved': ['gte', 'lte']
}

@property
Expand Down
Binary file modified accident/migrations/__pycache__/0001_initial.cpython-36.pyc
Binary file not shown.
Binary file not shown.
Binary file modified accident/migrations/__pycache__/__init__.cpython-36.pyc
Binary file not shown.
Binary file modified authorization/__pycache__/__init__.cpython-36.pyc
Binary file not shown.
Binary file modified authorization/__pycache__/apps.cpython-36.pyc
Binary file not shown.
Binary file modified authorization/__pycache__/backends.cpython-36.pyc
Binary file not shown.
Binary file modified authorization/__pycache__/models.cpython-36.pyc
Binary file not shown.
Binary file modified authorization/__pycache__/renderers.cpython-36.pyc
Binary file not shown.
Binary file modified authorization/__pycache__/serializers.cpython-36.pyc
Binary file not shown.
Binary file modified authorization/__pycache__/urls.cpython-36.pyc
Binary file not shown.
Binary file modified authorization/__pycache__/views.cpython-36.pyc
Binary file not shown.
Binary file modified authorization/migrations/__pycache__/0001_initial.cpython-36.pyc
Binary file not shown.
Binary file modified authorization/migrations/__pycache__/__init__.cpython-36.pyc
Binary file not shown.
Binary file modified conveyor/__pycache__/__init__.cpython-36.pyc
Binary file not shown.
Binary file modified conveyor/__pycache__/apps.cpython-36.pyc
Binary file not shown.
Binary file modified conveyor/__pycache__/models.cpython-36.pyc
Binary file not shown.
Binary file modified conveyor/__pycache__/serializers.cpython-36.pyc
Binary file not shown.
Binary file modified conveyor/__pycache__/urls.cpython-36.pyc
Binary file not shown.
Binary file modified conveyor/__pycache__/views.cpython-36.pyc
Binary file not shown.
Binary file modified conveyor/migrations/__pycache__/0001_initial.cpython-36.pyc
Binary file not shown.
Binary file not shown.
Binary file modified conveyor/migrations/__pycache__/__init__.cpython-36.pyc
Binary file not shown.
21,345 changes: 27 additions & 21,318 deletions package-lock.json

Large diffs are not rendered by default.

88 changes: 88 additions & 0 deletions src/components/AccidentTable.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@

.container-filter {
display: flex;
flex-direction: row;
/* position: fixed; */
}

.form-container {
display: flex;
flex-direction: row;
}

.dropdown-container {
margin-left: 1%;
}

.container-filter label {
font-size: 0.9rem;
}

.sort-container:nth-child(1) {
display: flex;
/* border: 0!important; */
flex-direction: row;
}

.sort-container > div {
display: flex;
justify-content: center;
align-items: center;
}

.filter-date-picker {
display: flex;
flex-direction: column;
justify-content: center;
width: 100%;
max-width: 100%;
}

.filter-date-picker > div {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
margin-top: 2%;
}

.filter-date-picker > div > div {
padding-right: 10%;
}

.filter-icons {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
/* margin: 4% */
}

.filter-icons > div {
display: flex;
justify-content: center;
align-items: center;
}

.Table-Accidents {
table-layout: fixed;
width: 100%;
}



.Table-Accidents > thead > tr > th:last-child {
padding-left: 20px;
padding-right: 20px;
max-width: 8%;
width: 8%;
/* padding: 1%!important; */
}
.Table-Accidents > thead > tr > th:nth-child(2) {
padding-left: 20px;
padding-right: 20px;
}

.filter-icons__elem {
cursor: pointer;
}
128 changes: 110 additions & 18 deletions src/components/AccidentTable.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import 'bootstrap/dist/css/bootstrap.min.css';
import './AccidentTable.css'
import axios from 'axios';
import { Component } from 'react';
import React from "react";
import './Monitoring.css';
import history from '../static/icons/history.svg';
import edit from '../static/icons/edit.svg';
import sort from '../static/icons/sort.svg';
import filter from '../static/icons/filter.svg';
import cross from '../static/icons/cross.svg';
import ModalEdit from './ModalEdit.js';
import ModalHistory from './ModalHistory.js';
import { getPostsToDisplayFromAccident } from './utils/postsUtils';
import toast, { Toaster } from 'react-hot-toast';

import { Dropdown, Form, Button, Col, Row } from 'react-bootstrap';

const url = "https://tractor-factory-interface.herokuapp.com/api/accident/"
// const url = "http://localhost:8000/api/accident/"
const getAccidentHistoryURL = "https://tractor-factory-interface.herokuapp.com/api/accident/";
Expand All @@ -27,12 +33,16 @@ class AccidentTable extends Component {
data_history: null,
key: null,
edit: false,
history: false
history: false,

filterClass: "Класс: Не установлен",
filterPost: null,
}
this.setActiveEdit = this.setActiveEdit.bind(this);
this.setUnactiveEdit = this.setUnactiveEdit.bind(this);
this.setActiveHistory = this.setActiveHistory.bind(this);
this.setUnactiveHistory = this.setUnactiveHistory.bind(this);
this.getFilterInputs = this.getFilterInputs.bind(this);
};

componentDidMount() {
Expand Down Expand Up @@ -160,18 +170,91 @@ class AccidentTable extends Component {
}
console.log(error);
});

};

getFilterInputs() {
/* Получаем введенные в поля фильтрации значения */
/*
TODO: 4. Сделать сортировку по датам
4.1. Функция переключатель для трех состояний стрелок (1 - вверх, 2 - вниз, 3 - отмена)
4.2. Сортировать наверное надо на фронте, чтобы не было задержек
4.3. Проверить правильно ли кладутся в хендлеры АйДишники инцидентов после сортировок
5. Не забыть поменять урл!!!!!!
*/
let dateAppearedVals = [
document.getElementById("DateAppearedPickerStart").value,
document.getElementById("DateAppearedPickerEnd").value,
]
let dateSolvedVals = [
document.getElementById("DateSolvedPickerStart").value,
document.getElementById("DateSolvedPickerEnd").value,
]
let filters = {
"accident_class": document.getElementById("selectAccidentFilter").selectedIndex,
"time_appeared": dateAppearedVals,
"time_solved": dateSolvedVals,
}
this.props.changeUrlOnFilter(filters);
}


render() {
const accidents_list = typeof this.props.accidents == 'undefined' ? null : this.props.accidents;
console.log(accidents_list);
const accidentClasses = this.props.accidentClasses;
// console.log(accidentClasses[0]);
// console.log(accidents_list);
return (
<React.Fragment>
<table className="Table-Accidents" style={{ borderColor: 'black' }} class="table table-striped table-sm table-bordered">
<div style={{height: '40vh', overflowY: 'auto'}}>

<table style={{ borderColor: 'black' }} className="table table-striped table-sm table-bordered Table-Accidents">
<thead>
<tr>
<th class="text-center"></th>
<th class="text-center">
<Form.Select id={"selectAccidentFilter"}>
<option>Класс не установлен</option>
{accidentClasses.map((obj, i) =>
<option>
{"Класс " + String(obj.number) + ": " + String(obj.name)}
</option>
)}
</Form.Select>
</th>
<th class="text-center"></th>
<th class="text-center">
<div className="filter-date-picker">
<div>
<div>От</div>
<Form.Control type="date" id={"DateAppearedPickerStart"}/>
</div>
<div>
<div>До</div>
<Form.Control type="date" id={"DateAppearedPickerEnd"}/>
</div>
</div>
</th>
<th class="text-center">
<div className="filter-date-picker">
<div>
<div>От</div>
<Form.Control type="date" id={"DateSolvedPickerStart"}/>
</div>
<div>
<div>До</div>
<Form.Control type="date" id={"DateSolvedPickerEnd"}/>
</div>
</div>
</th>
<th class="text-center">
<div className="filter-icons">
<div className="filter-icons__elem" onClick={this.getFilterInputs}><img src={filter}></img></div>
<div className="filter-icons__elem" onClick={this.props.clearFilter}><img src={cross}></img></div>
</div>
</th>
</tr>
<tr>
<th class="text-center">
Номер поста
Expand All @@ -183,35 +266,44 @@ class AccidentTable extends Component {
Описание
</th>
<th class="text-center">
Время фиксации проблемы
<div className="sort-container">
<div>Время фиксации проблемы</div>
</div>
</th>
<th class="text-center">
Время устранения проблемы
<div className="sort-container">
<div>Время устранения проблемы</div>
</div>
</th>
<th class="text-center"></th>
</tr>
</thead>
<tbody className="Table-body">
{accidents_list == null ? <p>Page is Loading ...</p> : accidents_list.map((obj, i) => (
<tr>
<td>{getPostsToDisplayFromAccident(obj)}</td>
<td>{typeof accidentClasses[obj.accident_class - 1] == 'undefined' ? "" : accidentClasses[obj.accident_class - 1].name}</td>
<td>{obj.description}</td>
<td>{obj.time_appeared.replace('T', ' ').replace('Z', '').replaceAll('-', '.').slice(0, 19)}</td>
<td>{obj.time_solved === null ? "Проблема не устранена" : obj.time_solved.replace('T', ' ').replace('Z', '').replaceAll('-', '.').slice(0, 19)}</td>
<td style={{position:'sticky', right:'0px'}}>
<img src={history} alt="" onClick={() => this.setActiveHistory(obj.id)} />
<img src={edit} alt="" onClick={() => this.setActiveEdit(obj.id)} />
</td>
</tr>
))}
{accidents_list == null ?
<tr><td colSpan={6}><p>Данные загружаются</p></td></tr> :
accidents_list.length == 0 ?
<tr><td colSpan={6}><div className="container-fluid"><p>Записи не найдены</p></div></td></tr> :
accidents_list.map((obj, i) => (
<tr>
<td>{getPostsToDisplayFromAccident(obj)}</td>
<td>{typeof accidentClasses[obj.accident_class - 1] == 'undefined' ? "" : accidentClasses[obj.accident_class - 1].name}</td>
<td>{obj.description}</td>
<td>{obj.time_appeared.replace('T', ' ').replace('Z', '').replaceAll('-', '.').slice(0, 19)}</td>
<td>{obj.time_solved === null ? "Проблема не устранена" : obj.time_solved.replace('T', ' ').replace('Z', '').replaceAll('-', '.').slice(0, 19)}</td>
<td style={{position:'sticky', right:'0px'}}>
<img src={history} alt="" onClick={() => this.setActiveHistory(obj.id)} />
<img src={edit} alt="" onClick={() => this.setActiveEdit(obj.id)} />
</td>
</tr>
))}
</tbody>
</table>
<ModalEdit isAct={this.state.edit} setUnactive={this.setUnactiveEdit} data={this.state.data} key={this.state.key}
handleOnSubmit={this.handleEditSubmit} accidentClasses={accidentClasses}/>
<ModalHistory isAct={this.state.history} setUnactive={this.setUnactiveHistory} data={this.state.data_history}
accidentsClasses={accidentClasses} />
<Toaster position='bottom-right'/>
</div>
</React.Fragment>
);
}
Expand Down
45 changes: 40 additions & 5 deletions src/components/Monitoring.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import React, { Component } from 'react';
import toast, { Toaster } from 'react-hot-toast';
import { getConfig } from './utils/configUtils';

const getAcidentURL = 'https://tractor-factory-interface.herokuapp.com/api/accident/';
// const getAcidentURL = 'http://localhost:8000/api/accident/';
let getAcidentURL = 'https://tractor-factory-interface.herokuapp.com/api/accident/';
// let getAcidentURL = 'http://localhost:8000/api/accident/';
const getAcidentClassesURL = 'https://tractor-factory-interface.herokuapp.com/api/accident/classes/';

class Monitoring extends Component {
Expand Down Expand Up @@ -59,6 +59,39 @@ class Monitoring extends Component {
clearInterval(this.intervalGetAccidents);
}

changeUrlOnFilter(params) {
/* Вызывается в дочернем компоненте таблицы.
Обрабатывает выставленне фильтры и добавляет параметры в url */
getAcidentURL = 'https://tractor-factory-interface.herokuapp.com/api/accident/';
console.log(params);
let queryParams = '';
if (params['accident_class'] > 0) {
queryParams += 'accident_class=' + String(params['accident_class']) + '&';
}
delete params['accident_class'];
for (let key in params) {
if (params[key][0] != '' && params[key][1] == '') {
// gte
queryParams += key + '__gte=' + String(params[key][0]) + '&';
} else if (params[key][0] == '' && params[key][1] != '') {
// lte
queryParams += key + '__lte=' + String(params[key][1]) + '&';
} else if (params[key][0] == '' && params[key][1] == '') {
// dont add param
continue;
} else {
// date__range
queryParams += key + '__date__range=' + params[key][0] + '%2C' + params[key][1] + '&'
}
}
console.log(queryParams);
getAcidentURL += `?${queryParams}`
}

clearFilter() {
getAcidentURL = 'https://tractor-factory-interface.herokuapp.com/api/accident/';
}

async getAccidents() {
const res = await fetch(getAcidentURL);
const data = await res.json();
Expand Down Expand Up @@ -91,9 +124,11 @@ class Monitoring extends Component {
</table>
<div className="App-Accidents" class="table-responsive">
<h1 style={{ textAlign: 'left', verticalAlign: 'middle', lineHeight: '30px', marginBottom: '30px', fontWeight: '600' }}>Список последних происшествий</h1>
<div style={{height: '40vh', overflowY: 'auto'}}>
<AccidentTable accidents={this.state.accidents} accidentClasses={this.state.accidentClasses}/>
</div>
<AccidentTable
accidents={this.state.accidents}
accidentClasses={this.state.accidentClasses}
changeUrlOnFilter={this.changeUrlOnFilter}
clearFilter={this.clearFilter}/>
</div>
<Toaster position="bottom-right"/>
</main>
Expand Down
3 changes: 3 additions & 0 deletions src/static/icons/cross.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/static/icons/filter.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/static/icons/sort.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/static/icons/sort_down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/static/icons/sort_off.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/static/icons/sort_up.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tractor_factory_interface/__pycache__/__init__.cpython-36.pyc
Binary file not shown.
Binary file modified tractor_factory_interface/__pycache__/exceptions.cpython-36.pyc
Binary file not shown.
Binary file modified tractor_factory_interface/__pycache__/settings.cpython-36.pyc
Binary file not shown.
Binary file modified tractor_factory_interface/__pycache__/urls.cpython-36.pyc
Binary file not shown.
Binary file modified tractor_factory_interface/__pycache__/wsgi.cpython-36.pyc
Binary file not shown.