Skip to content

Commit

Permalink
feat(train): pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
jakowenko committed Sep 20, 2021
1 parent 3fffa6e commit f749437
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 41 deletions.
21 changes: 16 additions & 5 deletions api/src/controllers/train.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,35 @@ const train = require('../util/train.util');
const filesystem = require('../util/fs.util');
const { jwt } = require('../util/auth.util');
const { BAD_REQUEST } = require('../constants/http-status');
const { AUTH, STORAGE } = require('../constants');
const { AUTH, STORAGE, UI } = require('../constants');
const { tryParseJSON } = require('../util/validators.util');

module.exports.get = async (req, res) => {
const limit = UI.PAGINATION.LIMIT;
const { page } = req.query;
const token = AUTH ? jwt.sign({ route: 'storage' }) : null;
const db = database.connect();
let files = req.query.name
? db
.prepare(
'SELECT id, name, filename, createdAt FROM file WHERE name = ? AND isActive = 1 ORDER BY name ASC, id DESC'
'SELECT id, name, filename, createdAt FROM file WHERE name = ? AND isActive = 1 ORDER BY id DESC LIMIT ?,?'
)
.all(req.query.name)
.bind(req.query.name, limit * (page - 1), limit)
.all()
: db
.prepare(
'SELECT id, name, filename, createdAt FROM file WHERE isActive = 1 ORDER BY name ASC, id DESC'
'SELECT id, name, filename, createdAt FROM file WHERE isActive = 1 ORDER BY id DESC LIMIT ?,?'
)
.bind(limit * (page - 1), limit)
.all();

const [total] = req.query.name
? db
.prepare('SELECT COUNT(*) count FROM file WHERE name = ? AND isActive = 1')
.bind(req.query.name)
.all()
: db.prepare('SELECT COUNT(*) count FROM file WHERE isActive = 1').all();

files.forEach((file) => {
file.results = [];
const trainings = db.prepare('SELECT * FROM train WHERE fileId = ?').all(file.id);
Expand Down Expand Up @@ -67,7 +78,7 @@ module.exports.get = async (req, res) => {
return output;
})
);
res.send(files);
res.send({ limit, total: total.count, files });
};

module.exports.delete = async (req, res) => {
Expand Down
5 changes: 3 additions & 2 deletions api/src/routes/train.routes.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
const express = require('express');
const multer = require('multer');
const { jwt } = require('../middlewares');
const { jwt, expressValidator, validate } = require('../middlewares');
const controller = require('../controllers/train.controller');

const { query } = expressValidator;
const router = express.Router();

router
.get('/', jwt, controller.get)
.get('/', jwt, validate([query('page').default(1).isInt()]), controller.get)
.patch('/:id', jwt, controller.patch)
.get('/status', controller.status)
.post('/add/:name', multer().array('files[]'), controller.add)
Expand Down
118 changes: 84 additions & 34 deletions frontend/src/views/Train.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,37 @@
ref="header"
/>
<div
class="loading-wrapper p-d-flex p-jc-center"
class="loading-wrapper p-d-flex p-flex-column p-jc-center"
v-if="loading.files || loading.status || !matches.source.length"
:style="{ top: headerHeight + toolbarHeight + 'px' }"
>
<i
v-if="loading.files || (loading.status && !status.length)"
class="pi pi-spin pi-spinner p-as-center"
style="font-size: 2.5rem"
></i>
<div v-else-if="loading.status && status.length" class="p-as-center progress-holder">
<p class="p-mb-3 p-text-bold p-text-center">Training in progress...</p>
<i v-if="loading.files || loading.status" class="pi pi-spin pi-spinner p-as-center" style="font-size: 2.5rem"></i>
<div v-if="loading.status && status.length" class="p-mt-5 p-as-center progress-holder">
<p class="p-mb-3 p-text-bold p-text-center">Training...</p>
<div v-for="name in status" :key="name" class="p-mb-3">
<div class="p-mb-1 p-text-bold">{{ name.name }} - {{ name.trained }}/{{ name.total }}</div>
<ProgressBar :value="name.percent" />
</div>
</div>
<div v-else class="p-text-center p-as-center">
<div v-if="!loading.status && !loading.files && !matches.source.length" class="p-text-center p-as-center">
<p class="p-text-bold p-mb-3">No files found</p>
</div>
</div>
<div v-else class="p-d-flex p-jc-center" :style="{ marginTop: headerHeight + 'px' }">
<div
v-else
class="p-d-flex p-jc-center"
:style="{ marginTop: headerHeight + 'px' }"
:class="isPaginationVisible ? 'pagination-padding' : ''"
>
<Grid type="train" :folders="folders" :matches="{ filtered, ...matches }" style="width: 100%" />
</div>
<div
v-if="isPaginationVisible"
class="pagination p-d-flex p-jc-center"
:style="{ top: headerHeight + toolbarHeight + 'px' }"
>
<Pagination :pagination="pagination" :loading="loading" />
</div>
</div>
</template>

Expand All @@ -42,17 +50,25 @@ import Grid from '@/components/Grid.vue';
import Sleep from '@/util/sleep.util';
import ApiService from '@/services/api.service';
import Header from '@/components/Header.vue';
import Pagination from '@/components/Pagination.vue';
export default {
components: {
Grid,
Header,
ProgressBar,
Pagination,
},
data: () => ({
pagination: {
total: 0,
page: 1,
temp: 1,
limit: 0,
},
loading: {
files: true,
status: true,
files: false,
status: false,
},
folders: [],
status: [],
Expand All @@ -69,6 +85,9 @@ export default {
toolbarHeight: Number,
},
computed: {
isPaginationVisible() {
return this.pagination.total > this.pagination.limit;
},
areAllSelected() {
return this.filtered.length > 0 && this.matches.selected.length === this.filtered.length;
},
Expand Down Expand Up @@ -98,6 +117,26 @@ export default {
this.emitter.on('realoadTrain', (...args) => this.init(...args));
this.emitter.on('toggleAsset', (...args) => this.selected(...args));
this.emitter.on('assetLoaded', (...args) => this.assetLoaded(...args));
this.emitter.on('paginate', (value) => {
this.pagination.temp = value;
this.clear(['source', 'selected', 'disabled', 'loaded']);
this.get().status();
});
},
beforeUnmount() {
const emitters = [
'trainingFolder',
'folders',
'clearSelected',
'realoadTrain',
'toggleAsset',
'assetLoaded',
'paginate',
];
emitters.forEach((emitter) => {
this.emitter.off(emitter);
});
},
async mounted() {
this.headerHeight = this.$refs.header.getHeight();
Expand All @@ -106,22 +145,37 @@ export default {
watch: {},
methods: {
async init() {
this.clear(['source', 'selected', 'disabled', 'loaded']);
const promises = [];
this.status = [];
this.matches.selected = [];
promises.push(this.get().status());
await Promise.all(promises);
},
clear(items) {
items.forEach((item) => {
this.matches[item] = [];
});
},
get() {
const $this = this;
return {
async files() {
try {
$this.loading.files = true;
const { data } = $this.trainingFolder
? await ApiService.get(`train?name=${$this.trainingFolder}`)
: await ApiService.get('train');
$this.matches.source = data;
? await ApiService.get(`train?name=${$this.trainingFolder}`, { params: { page: $this.pagination.temp } })
: await ApiService.get('train', { params: { page: $this.pagination.temp } });
$this.matches.source = data.files;
$this.pagination.limit = data.limit;
$this.pagination.total = data.total;
if (data.files.length) $this.pagination.page = $this.pagination.temp;
if ($this.pagination.temp > 1 && !data.files.length) {
$this.pagination.temp -= 1;
await $this.get().files();
return;
}
$this.loading.files = false;
} catch (error) {
$this.emitter.emit('error', error);
Expand Down Expand Up @@ -282,34 +336,30 @@ export default {
}
}
.fixed {
.pagination {
position: fixed;
top: $tool-bar-height;
z-index: 5;
left: 300px;
top: 100px;
z-index: 3;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 100%;
background: var(--surface-a);
max-width: $max-width;
padding: 0.5rem 0;
background: var(--surface-b);
}
.name {
text-align: center;
white-space: nowrap;
font-size: 0.9rem;
@media only screen and (max-width: 576px) {
font-size: 0.75rem !important;
}
}
.status {
font-size: 0.8rem;
@media only screen and (max-width: 576px) {
font-size: 0.65rem !important;
}
.pagination-padding {
padding-top: 2rem;
@media only screen and (max-width: 576px) {
padding-top: 2.25rem;
}
}
.progress-holder {
width: 30%;
min-width: 300px;
@media only screen and (max-width: 576px) {
width: 70%;
}
Expand Down

0 comments on commit f749437

Please sign in to comment.