Compare commits
3 Commits
587dac99c5
...
0233453084
Author | SHA1 | Date | |
---|---|---|---|
0233453084 | |||
c026b5f1a8 | |||
5d99baea8e |
@ -10,7 +10,9 @@
|
||||
"/@popperjs/core/dist/umd/popper.min.js.map",
|
||||
"/bootstrap/dist/js/bootstrap.bundle.min.js.map",
|
||||
"/bootstrap-icons/font/fonts/bootstrap-icons.woff",
|
||||
"/tsparticles-confetti/tsparticles.confetti.bundle.min.js"
|
||||
"/tsparticles-confetti/tsparticles.confetti.bundle.min.js",
|
||||
"/bootstrap-table/dist/bootstrap-table.min.js",
|
||||
"/bootstrap-table/dist/bootstrap-table.min.css"
|
||||
],
|
||||
"debugMode": false
|
||||
}
|
||||
|
9
package-lock.json
generated
9
package-lock.json
generated
@ -16,6 +16,7 @@
|
||||
"body-parser": "^1.20.2",
|
||||
"bootstrap": "^5.3.0-alpha3",
|
||||
"bootstrap-icons": "^1.10.5",
|
||||
"bootstrap-table": "^1.22.1",
|
||||
"csv": "^6.2.11",
|
||||
"eta": "^2.0.1",
|
||||
"express": "^4.18.2",
|
||||
@ -1299,6 +1300,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/bootstrap-table": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.22.1.tgz",
|
||||
"integrity": "sha512-Nw8p+BmaiMDSfoer/p49YeI3vJQAWhudxhyKMuqnJBb3NRvCRewMk7JDgiN9SQO3YeSejOirKtcdWpM0dtddWg==",
|
||||
"peerDependencies": {
|
||||
"jquery": "3"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
|
@ -24,6 +24,7 @@
|
||||
"body-parser": "^1.20.2",
|
||||
"bootstrap": "^5.3.0-alpha3",
|
||||
"bootstrap-icons": "^1.10.5",
|
||||
"bootstrap-table": "^1.22.1",
|
||||
"csv": "^6.2.11",
|
||||
"eta": "^2.0.1",
|
||||
"express": "^4.18.2",
|
||||
|
@ -88,6 +88,26 @@ export function parseIntRelation(data: string, relation_name: string = 'id', doN
|
||||
}`);
|
||||
}
|
||||
|
||||
export function parseIntOrUndefined(data: string) {
|
||||
|
||||
/**
|
||||
* Function to parse a string into a number or return undefined if it is not a number
|
||||
*
|
||||
* @export
|
||||
* @param {string || any} data
|
||||
* @returns {object}
|
||||
*/
|
||||
export function parseIntOrUndefined(data: any) {
|
||||
return isNaN(parseInt(data)) ? undefined : parseInt(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to create a sortBy compatible object from a string
|
||||
*
|
||||
* @export
|
||||
* @param {string} SortField
|
||||
* @param {string} Order
|
||||
* @returns {object}
|
||||
*/
|
||||
export function parseDynamicSortBy(SortField: string, Order: string){
|
||||
return JSON.parse(`{ "${SortField}": "${Order}" }`);
|
||||
}
|
||||
|
@ -1,6 +1,19 @@
|
||||
<%~ E.includeFile("partials/head.eta.html", {"title": "Dashboard"}) %> <%~ E.includeFile("partials/controls.eta.html", {"active": "Dashboard"}) %>
|
||||
|
||||
<h1 onclick="doTheConfetti()" class="user-select-none">Good evening, ${user}</h1>
|
||||
<h1 onclick="doTheConfetti()" class="user-select-none" id="greeting">Good evening, ${user}</h1>
|
||||
<script>
|
||||
// Handle greeting
|
||||
var today = new Date();
|
||||
var curHr = today.getHours();
|
||||
|
||||
if (curHr < 12) {
|
||||
document.getElementById("greeting").innerHTML = "Good morning";
|
||||
} else if (curHr < 18) {
|
||||
document.getElementById("greeting").innerHTML = "Good afternoon";
|
||||
} else {
|
||||
document.getElementById("greeting").innerHTML = "Good evening";
|
||||
}
|
||||
</script>
|
||||
<div class="container text-center">
|
||||
<div class="row">
|
||||
<div class="card col m-2">
|
||||
|
@ -93,13 +93,13 @@
|
||||
<a href="/settings/category/new" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#itemModifyModal" onclick="primeCreateNew()">Create new item</a>
|
||||
</div>
|
||||
</div>
|
||||
<table class="table align-middle">
|
||||
<table class="table align-middle" id="itemList" data-sortable="true" data-search-highlight="true" data-pagination="true" data-page-size="25" data-remember-order="true">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">SKU</th>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Status</th>
|
||||
<th scope="col">Actions</th>
|
||||
<th scope="col" data-field="SKU" class="sku" data-sortable="true">SKU</th>
|
||||
<th scope="col" data-field="name" data-sortable="true">Name</th>
|
||||
<th scope="col" data-field="status" data-sortable="true">Status</th>
|
||||
<th scope="col" data-field="actions" data-searchable="false">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<% if(it.items.length == 0) { %>
|
||||
@ -109,49 +109,8 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
<% } %>
|
||||
<tbody>
|
||||
<% it.items.forEach(function(user){ %>
|
||||
<tr>
|
||||
<td scope="row" data-bs-toggle="tooltip" data-bs-placement="left" data-bs-title="ID: <%= user.id %>">
|
||||
<% if (user.SKU == null) { %>
|
||||
<i>No SKU assigned</i>
|
||||
<% } else { %> <%= user.SKU %> <% } %></td>
|
||||
<td><%= user.name %></td>
|
||||
<% if(user.status == "normal") { %>
|
||||
|
||||
<td><span class="badge text-bg-success"><%= user.status %></span></td>
|
||||
<% } else if(user.status == "stolen") { %>
|
||||
<td><span class="badge text-bg-danger"><%= user.status %></span></td>
|
||||
<% } else if(user.status == "lost") { %>
|
||||
<td><span class="badge text-bg-warning"><%= user.status %></span></td>
|
||||
<% } else if(user.status == "borrowed") { %>
|
||||
<td><span class="badge text-bg-info"><%= user.status %></span></td>
|
||||
<% } %>
|
||||
<td>
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#itemModifyModal" onclick="primeEdit(); getDataForEdit('<%= user.id %>')">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-danger" onclick="preFillDeleteModalNxt('<%= user.id %>','items','Item')" data-bs-toggle="modal" data-bs-target="#staticBackdrop">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
<% if(it.maxPages > 1) { %>
|
||||
<nav aria-label="Page selector">
|
||||
<ul class="pagination justify-content-center">
|
||||
<li class="page-item <%= it.currentPage-1 < 1 ? 'disabled' : ''%>"><a class="page-link" href="?page=<%= it.currentPage - 1 %>">Previous</a></li>
|
||||
<% for (var i = 1; i <= it.maxPages; i++) { %>
|
||||
<li class="page-item <%= it.currentPage == i ? 'active' : ''%>"><a class="page-link" href="?page=<%= i %>"><%= i %></a></li>
|
||||
<% } %>
|
||||
|
||||
<li class="page-item <%= it.currentPage+1 > it.maxPages ? 'disabled' : ''%>"><a class="page-link" href="?page=<%= it.currentPage + 1 %>">Next</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<% } %>
|
||||
</div>
|
||||
<script src="/js/editItems.js"></script>
|
||||
<script src="/js/itemPageHandler.js"></script>
|
||||
<%~ E.includeFile("partials/controlsFoot.eta.html") %> <%~ E.includeFile("partials/foot.eta.html") %>
|
||||
|
@ -137,7 +137,7 @@
|
||||
</div>
|
||||
<!-- Align the mode picker at the bottom of the navbar -->
|
||||
|
||||
<ul class="nav flex-column mb-2 position-absolute bottom-0 align-items-center w-100">
|
||||
<ul class="nav flex-column mb-5 position-absolute bottom-0 align-items-center w-100">
|
||||
<div class="input-group mb-3 justify-content-center w-100">
|
||||
<label class="btn btn-secondary" for="mode_light"><i class="bi bi-brightness-high"></i></label>
|
||||
<input type="radio" class="btn-check" name="options" id="mode_light" autocomplete="off" />
|
||||
@ -177,7 +177,23 @@
|
||||
});
|
||||
</script>
|
||||
</ul>
|
||||
<div onclick="toggleAutoReload();" class="text-secondary versionInfo nav flex-column position-absolute bottom-0 align-items-center w-100">AssetFlow Alpha V0.0.1 </div>
|
||||
<div onclick="toggleAutoReload();" class="text-secondary versionInfo nav flex-column position-absolute bottom-0 align-items-center w-100" id="versionInfo">AssetFlow Alpha <i>No version info</i> </div>
|
||||
<script>
|
||||
// Request /api/v1/version
|
||||
// If the response is 200, set the commit hash
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/api/v1/version",
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
$('#versionInfo').text(`AssetFlow Alpha ${data.version} ${data.commit}`);
|
||||
},
|
||||
error: function (data) {
|
||||
createNewToast('<i class="bi bi-exclamation-triangle-fill"></i> Unable to load version information', "text-bg-danger", 3000, false)
|
||||
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</nav>
|
||||
|
||||
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4" style="min-height: 100%">
|
||||
|
@ -6,6 +6,17 @@
|
||||
<script src="/js/handleSidebarTriangles.js"></script>
|
||||
<script src="/js/formHandler.js"></script>
|
||||
<script>
|
||||
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
|
||||
const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
|
||||
</script>
|
||||
function activateTooltips(){
|
||||
// Enable all bootstrap tooltips.
|
||||
// https://getbootstrap.com/docs/5.3/components/tooltips/#enable-tooltips
|
||||
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
|
||||
}
|
||||
function activatePopovers(){
|
||||
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
|
||||
const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
|
||||
}
|
||||
|
||||
activatePopovers();
|
||||
activateTooltips();
|
||||
</script>
|
||||
|
@ -1,8 +1,2 @@
|
||||
<script>
|
||||
// Enable all bootstrap tooltips.
|
||||
// https://getbootstrap.com/docs/5.3/components/tooltips/#enable-tooltips
|
||||
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -8,7 +8,6 @@
|
||||
<title>AssetFlow - <%= it.title %></title>
|
||||
<meta name="author" content="[Project-Name-Here]" />
|
||||
|
||||
<!--<link rel="icon" href="/favicon.ico" />-->
|
||||
<link rel="icon" href="/logo/Design_icon.svg" type="image/svg+xml" />
|
||||
|
||||
<script src="/js/handleColorMode.js"></script>
|
||||
@ -21,7 +20,8 @@
|
||||
<script src="/static/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="/static/@popperjs/core/dist/umd/popper.min.js"></script>
|
||||
<script src="/static/tsparticles-confetti/tsparticles.confetti.bundle.min.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="/static/bootstrap-table/dist/bootstrap-table.min.css">
|
||||
<script src="/static/bootstrap-table/dist/bootstrap-table.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- The body and html tag need to be left open! -->
|
||||
|
@ -6,6 +6,7 @@ import itemRoute from './items.js';
|
||||
import categoryRoute from './categories.js';
|
||||
import storageUnitRoute from './storageUnits.js';
|
||||
import storageLocationRoute from './storageLocations.js';
|
||||
import versionRoute from './version.js'
|
||||
|
||||
import search_routes from './search/index.js';
|
||||
|
||||
@ -27,7 +28,7 @@ Router.route('/categories').get(categoryRoute.get).post(categoryRoute.post).patc
|
||||
// TODO: Migrate routes to lowercase.
|
||||
Router.route('/storageUnits').get(storageUnitRoute.get).post(storageUnitRoute.post).patch(storageUnitRoute.patch).delete(storageUnitRoute.del);
|
||||
Router.route('/storageLocations').get(storageLocationRoute.get).post(storageLocationRoute.post).patch(storageLocationRoute.patch).delete(storageLocationRoute.del);
|
||||
|
||||
Router.route('/version').get(versionRoute.get);
|
||||
Router.use('/search', search_routes);
|
||||
|
||||
Router.route('/test').get(testRoute.get);
|
||||
|
@ -1,16 +1,18 @@
|
||||
import { Request, Response } from 'express';
|
||||
import { prisma, __path, log } from '../../../index.js';
|
||||
import { itemStatus } from '@prisma/client';
|
||||
import { parseIntRelation, parseIntOrUndefined } from '../../../assets/helper.js';
|
||||
import { parseIntRelation, parseIntOrUndefined, parseDynamicSortBy } from '../../../assets/helper.js';
|
||||
// Get item.
|
||||
function get(req: Request, res: Response) {
|
||||
if (req.query.getAll === undefined) {
|
||||
// Check if required fields are present
|
||||
if (!req.query.id) {
|
||||
res.status(400).json({ errorcode: 'VALIDATION_ERROR', error: 'One or more required fields are missing' });
|
||||
return;
|
||||
}
|
||||
async function get(req: Request, res: Response) {
|
||||
// Set sane defaults if undefined.
|
||||
if (req.query.sort === undefined) {
|
||||
req.query.sort = 'id';
|
||||
}
|
||||
if (req.query.order === undefined) {
|
||||
req.query.order = 'asc';
|
||||
}
|
||||
|
||||
if (req.query.id) {
|
||||
// Check if number is a valid integer
|
||||
if (!Number.isInteger(parseInt(req.query.id.toString()))) {
|
||||
res.status(400).json({ errorcode: 'VALIDATION_ERROR', error: 'The id field must be an integer' });
|
||||
@ -48,8 +50,53 @@ function get(req: Request, res: Response) {
|
||||
res.status(500).json({ errorcode: 'DB_ERROR', error: err });
|
||||
});
|
||||
} else {
|
||||
// Get all items
|
||||
const itemCountNotFiltered = await prisma.item.count({});
|
||||
|
||||
// Get all items (filtered)
|
||||
const itemCountFiltered = await prisma.item.count({
|
||||
where: {
|
||||
OR: [
|
||||
{
|
||||
SKU: {
|
||||
// Probably use prisma's Full-text search if it's out of beta
|
||||
// @ts-ignore
|
||||
contains: req.query.search.length > 0 ? req.query.search : ''
|
||||
}
|
||||
},
|
||||
{
|
||||
name: {
|
||||
// @ts-ignore
|
||||
contains: req.query.search.length > 0 ? req.query.search : ''
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
orderBy: parseDynamicSortBy(req.query.sort.toString(), req.query.order.toString())
|
||||
});
|
||||
// log.core.debug('Dynamic relation:', parseDynamicSortBy(req.query.sort.toString(), req.query.order.toString()));
|
||||
|
||||
prisma.item
|
||||
.findMany({
|
||||
take: parseIntOrUndefined(req.query.limit),
|
||||
skip: parseIntOrUndefined(req.query.offset),
|
||||
where: {
|
||||
OR: [
|
||||
{
|
||||
SKU: {
|
||||
// @ts-ignore
|
||||
contains: req.query.search.length > 0 ? req.query.search : ''
|
||||
}
|
||||
},
|
||||
{
|
||||
name: {
|
||||
// @ts-ignore
|
||||
contains: req.query.search.length > 0 ? req.query.search : ''
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
orderBy: parseDynamicSortBy(req.query.sort.toString(), req.query.order.toString()),
|
||||
// Get contactInfo, category, storageLocation( storageUnit<contactInfo> ) from relations.
|
||||
include: {
|
||||
contactInfo: true,
|
||||
@ -67,7 +114,7 @@ function get(req: Request, res: Response) {
|
||||
})
|
||||
.then((items) => {
|
||||
if (items) {
|
||||
res.status(200).json(JSON.stringify(items));
|
||||
res.status(200).json(JSON.stringify({ total: itemCountFiltered, totalNotFiltered: itemCountNotFiltered, items: items }));
|
||||
} else {
|
||||
res.status(410).json({ errorcode: 'NOT_EXISTING', error: 'Item does not exist' });
|
||||
}
|
||||
@ -97,7 +144,7 @@ function post(req: Request, res: Response) {
|
||||
.create({
|
||||
data: {
|
||||
SKU: req.body.sku,
|
||||
amount: parseIntOrUndefined(req.body.ammount), // FIXME: This is silently failing if NaN..
|
||||
amount: parseIntOrUndefined(req.body.amount), // FIXME: This is silently failing if NaN..
|
||||
name: req.body.name,
|
||||
comment: req.body.comment,
|
||||
status: req.body.status, // Only enum(itemStatus) values are valid
|
||||
@ -167,7 +214,7 @@ async function patch(req: Request, res: Response) {
|
||||
},
|
||||
data: {
|
||||
SKU: req.body.sku,
|
||||
amount: parseIntOrUndefined(req.body.ammount), // FIXME: This is silently failing if NaN..
|
||||
amount: parseIntOrUndefined(req.body.amount), // FIXME: This is silently failing if NaN..
|
||||
name: req.body.name,
|
||||
comment: req.body.comment,
|
||||
status: req.body.status, // Only enum(itemStatus) values are valid
|
||||
|
10
src/routes/api/v1/version.ts
Normal file
10
src/routes/api/v1/version.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import express, { Request, Response } from 'express';
|
||||
|
||||
function get(req: Request, res: Response) {
|
||||
const revision = require('child_process')
|
||||
.execSync('git rev-parse --short HEAD')
|
||||
.toString().trim()
|
||||
res.status(200).send({ version: '1.0.0', commit: revision });
|
||||
};
|
||||
|
||||
export default { get };
|
@ -2,33 +2,13 @@ import { Request, Response } from 'express';
|
||||
import { prisma, __path, log } from '../../index.js';
|
||||
|
||||
async function get(req: Request, res: Response) {
|
||||
// If no page is provided redirect to first
|
||||
if (req.query.page === undefined) {
|
||||
res.redirect('?page=1');
|
||||
return;
|
||||
}
|
||||
|
||||
let page = parseInt(req.query.page.toString());
|
||||
const itemCount = await prisma.item.count({}); // Count all items in the DB
|
||||
|
||||
const takeSize = 25; // Amount of times per page
|
||||
const pageSize = Math.ceil(itemCount / takeSize); // Amount of pages, always round up
|
||||
|
||||
// If page is less then 1 or more then the max page size redirect to first or last page. If itemCount is 0 do not redirect.
|
||||
if (page < 1) {
|
||||
res.redirect('?page=1');
|
||||
return;
|
||||
} else if (page > pageSize && itemCount !== 0) {
|
||||
res.redirect('?page=' + pageSize);
|
||||
return;
|
||||
}
|
||||
prisma.item
|
||||
.findMany({ skip: (page - 1) * takeSize, take: takeSize, orderBy: { SKU: "asc" } }) // Skip the amount of items per page times the page number minus 1; skip has to be (page-1)*takeSize because skip is 0 indexed
|
||||
.findMany({}) // Skip the amount of items per page times the page number minus 1; skip has to be (page-1)*takeSize because skip is 0 indexed
|
||||
.then((items) => {
|
||||
prisma.storageLocation.findMany({}).then((locations) => {
|
||||
prisma.itemCategory.findMany({}).then((categories) => {
|
||||
prisma.contactInfo.findMany({}).then((contactInfo) => {
|
||||
res.render(__path + '/src/frontend/items.eta.html', { items: items, currentPage: page, maxPages: pageSize, storeLocs: locations, categories: categories, contactInfo: contactInfo });
|
||||
res.render(__path + '/src/frontend/items.eta.html', { items: items, storeLocs: locations, categories: categories, contactInfo: contactInfo });
|
||||
})
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,13 @@
|
||||
var amountOfForms = $('.frontendForm').length;
|
||||
|
||||
function isNewDataLoaderAvailable() {
|
||||
try {
|
||||
return FLAG_supports_new_data_loader;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$('.frontendForm').each(function () {
|
||||
// TODO Handle empty strings as null or undefined, not as ''
|
||||
$(this).on('submit', function (e) {
|
||||
@ -26,7 +35,12 @@ $('.frontendForm').each(function () {
|
||||
// Clear all fields
|
||||
form.find('input, textarea').val('');
|
||||
// Create toast
|
||||
createNewToast('<i class="bi bi-check2"></i> Changes saved successfully.', "text-bg-success")
|
||||
if(isNewDataLoaderAvailable()) {
|
||||
createNewToast('<i class="bi bi-check2"></i> Changes saved successfully.', "text-bg-success", undefined, false)
|
||||
} else {
|
||||
createNewToast('<i class="bi bi-check2"></i> Changes saved successfully.', "text-bg-success")
|
||||
}
|
||||
|
||||
},
|
||||
error: function (data) {
|
||||
console.log('error');
|
||||
|
@ -10,7 +10,6 @@ trinagles.each(function () {
|
||||
$(this).addClass('rotate');
|
||||
}
|
||||
|
||||
console.log('target', target);
|
||||
target.on('show.bs.collapse', function () {
|
||||
$(triTar).addClass('rotate');
|
||||
$(triTar).removeClass('derotate');
|
||||
|
58
static/js/itemPageHandler.js
Normal file
58
static/js/itemPageHandler.js
Normal file
@ -0,0 +1,58 @@
|
||||
const FLAG_supports_new_data_loader = true;
|
||||
|
||||
/**
|
||||
* Should we ever implement items in items, have a look at this:
|
||||
* https://examples.bootstrap-table.com/index.html?extensions/treegrid.html#extensions/treegrid.html
|
||||
*/
|
||||
|
||||
function loadPageData() {
|
||||
const itemList = $('#itemList');
|
||||
// itemList.empty();
|
||||
itemList.bootstrapTable('destroy')
|
||||
itemList.bootstrapTable({url: "/api/v1/items", search: true, showRefresh: true, responseHandler: dataResponseHandler, sidePagination: 'server', serverSort: true})
|
||||
setTimeout(() => {
|
||||
activateTooltips();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function dataResponseHandler(res) {
|
||||
json = JSON.parse(res);
|
||||
// console.log(json)
|
||||
totalNotFiltered = json.totalNotFiltered;
|
||||
total = json.total;
|
||||
json = json.items;
|
||||
json.forEach((item) => {
|
||||
colorStatus = '';
|
||||
if(item.SKU == null) item.SKU = '<i>No SKU assigned</i>';
|
||||
switch (item.status) {
|
||||
case 'normal':
|
||||
colorStatus = 'success';
|
||||
break;
|
||||
case 'stolen':
|
||||
colorStatus = 'danger';
|
||||
break;
|
||||
case 'lost':
|
||||
colorStatus = 'warning';
|
||||
break;
|
||||
case 'borrowed':
|
||||
colorStatus = 'info';
|
||||
break;
|
||||
default:
|
||||
colorStatus = 'secondary';
|
||||
}
|
||||
item.status = `<span class="badge text-bg-${colorStatus}">${item.status}</span>`;
|
||||
item.actions = `
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#itemModifyModal" onclick="primeEdit(); getDataForEdit('${item.id}')">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button class="btn btn-danger" onclick="preFillDeleteModalNxt('${item.id}','items','Item')" data-bs-toggle="modal" data-bs-target="#staticBackdrop">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>`
|
||||
item.SKU = `<p data-bs-toggle="tooltip" data-bs-placement="left" data-bs-title="ID: ${item.id}">${item.SKU}</p>`
|
||||
});
|
||||
///// --------------------------------- /////
|
||||
|
||||
return {"rows": json, total: total, totalNotFiltered: totalNotFiltered, totalRows: total};
|
||||
}
|
||||
|
||||
loadPageData()
|
@ -26,6 +26,11 @@ function createNewToast(message, colorSelector, autoHideTime = 1500, autoReload
|
||||
targetContainer.appendChild(newToast);
|
||||
currentToasts.push(newToast);
|
||||
$(newToast).toast('show');
|
||||
try {
|
||||
loadPageData();
|
||||
} catch (error) {
|
||||
console.debug("Page does not support new data loading.")
|
||||
}
|
||||
setTimeout(() => {
|
||||
destroyToast(newToast.id);
|
||||
if (autoReload && !forceSkipReload) {
|
||||
|
Loading…
Reference in New Issue
Block a user