First implementation of database
This commit is contained in:
parent
3c089f5d16
commit
64a584927b
15 changed files with 609 additions and 402 deletions
|
@ -1,26 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
$relativePath = "../";
|
$relativePath = "../";
|
||||||
|
require_once $relativePath . 'classes/dao.php';
|
||||||
|
|
||||||
$file = '../data/stock-v2.json';
|
$dao = new Dao();
|
||||||
$fp = fopen($file, 'r');
|
|
||||||
$result = fread($fp, filesize($file));
|
$categories = $dao->get_categories();
|
||||||
fclose($fp);
|
|
||||||
|
|
||||||
ob_start();
|
|
||||||
?>
|
|
||||||
<tr>
|
|
||||||
<th class="id-column">Id</th>
|
|
||||||
<th class="name-column">Nom</th>
|
|
||||||
<th class="icon-column">
|
|
||||||
<a href="https://materialdesignicons.com/" target="_blank">
|
|
||||||
Icone
|
|
||||||
<i class="fas fa-external-link-alt"></i>
|
|
||||||
</a>
|
|
||||||
</th>
|
|
||||||
<th class="actions-column">Actions</th>
|
|
||||||
</tr>
|
|
||||||
<?php
|
|
||||||
$tableHeader = ob_get_clean();
|
|
||||||
ob_start();
|
ob_start();
|
||||||
?>
|
?>
|
||||||
<div class="admin-container">
|
<div class="admin-container">
|
||||||
|
@ -30,48 +15,23 @@ ob_start();
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<h1 class="text-center">Gestion des Catégories</h1>
|
<h1 class="text-center">Gestion des Catégories</h1>
|
||||||
<h2 class="text-center">Ajouter une catégorie</h2>
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
<?= $tableHeader ?>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<input type="text" class="form-control" id="idInput" placeholder="Id">
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input type="text" class="form-control" id="nameInput" placeholder="Nom">
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input type="text" class="form-control" id="iconInput" placeholder="Icone">
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<button type="submit" class="btn btn-success" onclick="addNewItem()"><i class="fas fa-check"></i>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h2 class="text-center">Liste des catégories</h2>
|
<div style="display: flex">
|
||||||
<table id="categoriesTable">
|
<button class="btn btn-success" style="margin: auto" onclick="listManager.showEditPopup(-1)">
|
||||||
<tbody>
|
<i class="mdi mdi-plus"></i>
|
||||||
<?= $tableHeader ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div style="display: flex; margin-top: 100px; margin-bottom: 100px">
|
|
||||||
<button class="btn btn-success btn-lg" style="margin: auto"
|
|
||||||
onclick="saveDataset()">
|
|
||||||
Sauvegarder les catégories
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ul id="dataList">
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
let json_dump = <?php echo $result; ?>;
|
let json_dump = <?php echo json_encode($categories); ?>;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</>
|
</div>
|
||||||
|
|
||||||
<link type="text/css" rel="stylesheet" href="https://cdn.materialdesignicons.com/4.4.95/css/materialdesignicons.min.css"
|
<link type="text/css" rel="stylesheet" href="https://cdn.materialdesignicons.com/4.4.95/css/materialdesignicons.min.css"
|
||||||
media="screen,projection"/>
|
media="screen,projection"/>
|
||||||
|
@ -82,6 +42,12 @@ ob_start();
|
||||||
<?php
|
<?php
|
||||||
$pageContent = ob_get_clean();
|
$pageContent = ob_get_clean();
|
||||||
$pageTitle = "Gestion des catégories";
|
$pageTitle = "Gestion des catégories";
|
||||||
$pageScripts = "<script type=\"text/javascript\" src=\"" . $relativePath . "assets/js/saveManager.js\"></script><script type=\"text/javascript\" src=\"" . $relativePath . "assets/js/categories.js\"></script>";
|
$pageScripts =
|
||||||
|
"
|
||||||
|
<script type=\"text/javascript\" src=\"" . $relativePath . "assets/js/jquery-confirm-defaults.js\"></script>
|
||||||
|
<script type=\"text/javascript\" src=\"" . $relativePath . "assets/js/saveManager.js\"></script>
|
||||||
|
<script type=\"text/javascript\" src=\"" . $relativePath . "assets/js/listManager.js\"></script>
|
||||||
|
<script type=\"text/javascript\" src=\"" . $relativePath . "assets/js/categories.js\"></script>
|
||||||
|
";
|
||||||
include($relativePath . "includes/template.php");
|
include($relativePath . "includes/template.php");
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
echo 'Ouverture du fichier V1...
|
|
||||||
';
|
|
||||||
$file = '../data/stock.json';
|
|
||||||
$fp = fopen($file, 'r');
|
|
||||||
$result = json_decode(fread($fp, filesize($file)));
|
|
||||||
fclose($fp);
|
|
||||||
|
|
||||||
|
|
||||||
function getConvertedTypes($oldTypes) {
|
|
||||||
$newTypes = [];
|
|
||||||
$counter = 1;
|
|
||||||
foreach ($oldTypes as $type) {
|
|
||||||
array_push($newTypes, (object) ["id" => strval($counter), "name" => $type, "icon" => "file"]);
|
|
||||||
$counter += 1;
|
|
||||||
}
|
|
||||||
return $newTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getConvertedArticles($articles, $newTypes) {
|
|
||||||
foreach ($articles as $article) {
|
|
||||||
$article->description = "Pas de description";
|
|
||||||
foreach ($article->type as $key=>$value) {
|
|
||||||
$article->type[$key] = getTypeIdFromName($value, $newTypes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $articles;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTypeIdFromName($name, $types) {
|
|
||||||
foreach ($types as $type) {
|
|
||||||
if ($type->name == $name)
|
|
||||||
return $type->id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($result) {
|
|
||||||
echo 'Conversion en cours...
|
|
||||||
';
|
|
||||||
$newTypes = getConvertedTypes($result->types);
|
|
||||||
$newArticles = getConvertedArticles($result->articles, $newTypes);
|
|
||||||
$v2File = json_encode(["types"=>$newTypes, "articles"=>$newArticles]);
|
|
||||||
echo 'Conversion réussie...
|
|
||||||
';
|
|
||||||
echo 'Sauvegarde dans fichier V2...
|
|
||||||
';
|
|
||||||
$fp = fopen('../data/stock-v2.json', 'w');
|
|
||||||
$result = fwrite($fp, $v2File);
|
|
||||||
fclose($fp);
|
|
||||||
echo 'Sauvegarde réussie...
|
|
||||||
';
|
|
||||||
} else {
|
|
||||||
echo 'Echec!
|
|
||||||
'; // Allows to create a newline
|
|
||||||
var_dump($_POST);
|
|
||||||
}
|
|
39
admin/save_manager.php
Normal file
39
admin/save_manager.php
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
$relativePath = "../";
|
||||||
|
require_once $relativePath . 'classes/dao.php';
|
||||||
|
|
||||||
|
$rest_json = file_get_contents("php://input");
|
||||||
|
$_POST = json_decode($rest_json, true);
|
||||||
|
|
||||||
|
|
||||||
|
//var_dump($_POST);
|
||||||
|
$result = -1;
|
||||||
|
$status = 0;
|
||||||
|
$message = "Success";
|
||||||
|
|
||||||
|
$dao = new Dao();
|
||||||
|
|
||||||
|
if ($_POST["function"] == "create_category")
|
||||||
|
$result = $dao->create_category($_POST["data"]);
|
||||||
|
else if ($_POST["function"] == "update_category") {
|
||||||
|
$result = $dao->update_category($_POST["data"]);
|
||||||
|
} else if ($_POST["function"] == "remove_category")
|
||||||
|
$result = $dao->remove_category($_POST["data"]);
|
||||||
|
else {
|
||||||
|
$status = 1;
|
||||||
|
$message = "Error: Unknown function";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result < 0) {
|
||||||
|
$status = 2;
|
||||||
|
$message = "Error: SQL error";
|
||||||
|
}
|
||||||
|
|
||||||
|
$array = array(
|
||||||
|
"status" => $status,
|
||||||
|
"message" => $message,
|
||||||
|
"data" => $result,
|
||||||
|
);
|
||||||
|
|
||||||
|
echo json_encode($array);
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
<?php
|
<?php
|
||||||
$relativePath = "../";
|
$relativePath = "../";
|
||||||
|
require_once $relativePath.'classes/dao.php';
|
||||||
|
|
||||||
$file = '../data/stock-v2.json';
|
$dao = new Dao();
|
||||||
$fp = fopen($file, 'r');
|
|
||||||
$result = fread($fp, filesize($file));
|
$stock = $dao->get_articles();
|
||||||
fclose($fp);
|
$categories = $dao->get_categories();
|
||||||
|
|
||||||
|
for ($i = 0; $i < sizeof($stock); $i++) {
|
||||||
|
$article_categories = $dao->get_article_categories($stock[$i]["id"]);
|
||||||
|
$stock[$i]["type"] = $article_categories;
|
||||||
|
}
|
||||||
|
|
||||||
ob_start();
|
ob_start();
|
||||||
?>
|
?>
|
||||||
|
@ -16,7 +22,6 @@ ob_start();
|
||||||
<th class="code-column">Code Barre</th>
|
<th class="code-column">Code Barre</th>
|
||||||
<th class="type-column">Type</th>
|
<th class="type-column">Type</th>
|
||||||
<th class="image-column">Image</th>
|
<th class="image-column">Image</th>
|
||||||
<th class="actions-column">Actions</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
<?php
|
<?php
|
||||||
$tableHeader = ob_get_clean();
|
$tableHeader = ob_get_clean();
|
||||||
|
@ -29,7 +34,7 @@ ob_start();
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<h1 class="text-center">Gestion des Stocks</h1>
|
<h1 class="text-center">Gestion des Stocks</h1>
|
||||||
<?php if ($result): ?>
|
<?php if ($stock): ?>
|
||||||
<h2 class="text-center">Ajouter un article</h2>
|
<h2 class="text-center">Ajouter un article</h2>
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -56,10 +61,6 @@ ob_start();
|
||||||
<td>
|
<td>
|
||||||
<input type="text" class="form-control" id="imageInput" placeholder="Lien Image">
|
<input type="text" class="form-control" id="imageInput" placeholder="Lien Image">
|
||||||
</td>
|
</td>
|
||||||
<td>
|
|
||||||
<button type="submit" class="btn btn-success" onclick="addNewItem()"><i class="fas fa-check"></i>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -87,13 +88,22 @@ ob_start();
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
let json_dump =
|
let json_dump = {
|
||||||
|
types:
|
||||||
<?php
|
<?php
|
||||||
if ($result)
|
if ($categories)
|
||||||
echo $result;
|
echo json_encode($categories);
|
||||||
else
|
else
|
||||||
echo 'undefined'
|
echo 'undefined';
|
||||||
?>;
|
?>,
|
||||||
|
articles:
|
||||||
|
<?php
|
||||||
|
if ($stock)
|
||||||
|
echo json_encode($stock);
|
||||||
|
else
|
||||||
|
echo 'undefined';
|
||||||
|
?>
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,25 @@
|
||||||
#categoriesTable tr {
|
#dataList {
|
||||||
border-bottom: 1px solid #dedede;
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dataList li {
|
||||||
|
text-align: center;
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
display: flex;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dataList li:hover {
|
||||||
|
background-color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dataList li div {
|
||||||
|
margin: auto;
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mdi {
|
.mdi {
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actions-column {
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.id-column {
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-column {
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
|
|
9
assets/css/jquery-confirm.min.css
vendored
Normal file
9
assets/css/jquery-confirm.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,135 +1,143 @@
|
||||||
let currentDataset = [];
|
// let listContainer = $("#dataList");
|
||||||
let currentTypes = [];
|
// let currentTypes = [];
|
||||||
let originalEditedItem = {};
|
// let displayedTypes = [];
|
||||||
|
|
||||||
function initValuesFromPHPDump() {
|
|
||||||
currentDataset = json_dump.articles; // json_dump is set using PHP
|
|
||||||
currentTypes = json_dump.types;
|
|
||||||
console.log(currentDataset);
|
|
||||||
console.log(currentTypes);
|
|
||||||
generateTable(currentTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let listManager;
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
initValuesFromPHPDump();
|
listManager = new ListManager($("#dataList"), json_dump,
|
||||||
setEditFieldValues('', '', '');
|
[
|
||||||
|
{
|
||||||
|
name: 'icon',
|
||||||
|
description: 'Icone',
|
||||||
|
type: 'icon'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
description: 'Nom',
|
||||||
|
type: 'text'
|
||||||
|
},
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
//
|
||||||
|
// function initValuesFromPHPDump() {
|
||||||
function generateTable(dataset) {
|
// currentTypes = json_dump;
|
||||||
for (let i = 0; i < dataset.length; i++) {
|
// console.log(currentTypes);
|
||||||
generateLine(dataset[i]);
|
//
|
||||||
}
|
// }
|
||||||
}
|
//
|
||||||
|
// $(document).ready(function () {
|
||||||
function generateLine(item) {
|
// initValuesFromPHPDump();
|
||||||
$.selector_cache('#categoriesTable').append(
|
// generateList();
|
||||||
'<tr id="row_' + item.id + '">' +
|
// console.log(displayedTypes);
|
||||||
'<td>' + item.id + '</td>' +
|
// });
|
||||||
'<td>' + item.name + '</td>' +
|
//
|
||||||
'<td><span class="mdi mdi-' + item.icon + '"></span></td>' +
|
// function generateList() {
|
||||||
'<td>' +
|
// for (let i = 0; i < currentTypes.length; i++) {
|
||||||
'<button class="btn btn-danger" id="delete_' + item.id + '" onclick="deleteItem(this)"><i class="fas fa-times"></i></button>' +
|
// createNewListEntry(currentTypes[i]);
|
||||||
'<button class="btn btn-primary" id="edit_' + item.id + '" onclick="editItem(this)"><i class="fas fa-edit"></i></button>' +
|
// }
|
||||||
'</td>' +
|
// }
|
||||||
'</tr>'
|
//
|
||||||
);
|
// function createNewListEntry(type) {
|
||||||
}
|
// displayedTypes.push(
|
||||||
|
// $("<li id='listItem_" + type["id"] + "' onclick='showEditPopup(" + displayedTypes.length + ")'>" +
|
||||||
function addNewItem() {
|
// "<div>" +
|
||||||
if (isItemInputFilled()) {
|
// "<span class='category-icon'><i class='mdi mdi-" + type["icon"] + "'></i></span>" +
|
||||||
let item = {
|
// "<span class='category-title'>" + type["name"] + "</span>" +
|
||||||
id: $.selector_cache('#idInput').val(),
|
// "</div>" +
|
||||||
name: $.selector_cache('#nameInput').val(),
|
// "</li>"));
|
||||||
icon: $.selector_cache('#iconInput').val(),
|
// listContainer.append(displayedTypes[displayedTypes.length - 1]);
|
||||||
};
|
// }
|
||||||
if (isIdAvailable(item.id)) {
|
//
|
||||||
updateExistingItemsType(originalEditedItem.id, item.id);
|
// function deleteListEntry(id) {
|
||||||
setEditFieldValues('', '', '');
|
// $('#listItem_' + id).remove();
|
||||||
currentTypes.push(item);
|
// }
|
||||||
generateLine(item);
|
//
|
||||||
}
|
//
|
||||||
}
|
// function showEditPopup(index) {
|
||||||
}
|
// let defaultValues = {
|
||||||
|
// name: "",
|
||||||
function editItem(elem) {
|
// icon: ""
|
||||||
if (isItemInputEmpty()) {
|
// };
|
||||||
let id = elem.id.replace('edit_', '');
|
// let title = "Créer une catégorie";
|
||||||
let item = getTypeOfId(id);
|
// if (index !== -1) {
|
||||||
originalEditedItem = item;
|
// defaultValues = currentTypes[index];
|
||||||
setEditFieldValues(item.id, item.name, item.icon);
|
// title = "Modifier la catégorie";
|
||||||
removeItemFromList(item); // Move the item in the edit fields
|
// }
|
||||||
}
|
// $.confirm({
|
||||||
}
|
// title: title,
|
||||||
|
// content:
|
||||||
function deleteItem(elem) {
|
// '<form action="" class="categoryForm">' +
|
||||||
let id = elem.id.replace('delete_', '');
|
// '<div class="form-group">' +
|
||||||
let item = getTypeOfId(id);
|
// '<label for="nameInput">Nom :</label>' +
|
||||||
updateExistingItemsType(id, undefined);
|
// '<input id="nameInput" type="text" placeholder="Nom" class="name-input form-control" value="' + defaultValues['name'] + '" required />' +
|
||||||
removeItemFromList(item);
|
// '<label for="iconInput">Icone :</label>' +
|
||||||
}
|
// '<input id="iconInput" type="text" placeholder="icone" class="icon-input form-control" value="' + defaultValues['icon'] + '" required />' +
|
||||||
|
// '</div>' +
|
||||||
function removeItemFromList(item) {
|
// '</form>',
|
||||||
currentTypes.splice(currentTypes.indexOf(item), 1);
|
// buttons: {
|
||||||
$('#row_' + item.id).remove();
|
// formSubmit: {
|
||||||
}
|
// text: 'Sauvegarder',
|
||||||
|
// btnClass: 'btn-blue',
|
||||||
function setEditFieldValues(id, name, icon) {
|
// action: async function () {
|
||||||
$.selector_cache('#idInput').val(id);
|
// let name = this.$content.find('#nameInput').val();
|
||||||
$.selector_cache('#nameInput').val(name);
|
// let icon = this.$content.find('#iconInput').val();
|
||||||
$.selector_cache('#iconInput').val(icon);
|
// if (!name) {
|
||||||
}
|
// $.alert('Merci de donner un nom');
|
||||||
|
// return false;
|
||||||
function updateExistingItemsType(oldTypeID, newTypeID) {
|
// } else if (!icon) {
|
||||||
for (let i = 0; i < currentDataset.length; i++) {
|
// $.alert('Merci de donner une icone');
|
||||||
for (let k = 0; k < currentDataset[i].type.length; k++) {
|
// return false;
|
||||||
if (currentDataset[i].type[k] === oldTypeID) {
|
// }
|
||||||
console.log(newTypeID);
|
// let itemToSave;
|
||||||
if (newTypeID !== undefined)
|
// if (index !== -1) {
|
||||||
currentDataset[i].type[k] = newTypeID;
|
// currentTypes[index]['name'] = name;
|
||||||
else
|
// currentTypes[index]['icon'] = icon;
|
||||||
currentDataset[i].type.splice(k, 1);
|
// itemToSave = currentTypes[index];
|
||||||
break;
|
// displayedTypes[index].find(".category-title").text(name);
|
||||||
}
|
// displayedTypes[index].find(".mdi")[0].className = "mdi mdi-" + icon;
|
||||||
}
|
// } else {
|
||||||
}
|
// itemToSave = {
|
||||||
}
|
// name: name,
|
||||||
|
// icon: icon,
|
||||||
function getTypeOfId(id) {
|
// display_order: 0,
|
||||||
let item = {};
|
// };
|
||||||
for (let i = 0; i < currentTypes.length; i++) {
|
// }
|
||||||
if (currentTypes[i].id === id) {
|
// let id = await SaveManager.saveCategory(itemToSave, index === -1);
|
||||||
item = currentTypes[i];
|
// if (id >= 0 && index === -1) {
|
||||||
break;
|
// itemToSave = {
|
||||||
}
|
// name: name,
|
||||||
}
|
// icon: icon,
|
||||||
return item;
|
// display_order: 0,
|
||||||
}
|
// id: id
|
||||||
|
// };
|
||||||
function isIdAvailable(id) {
|
// currentTypes[displayedTypes.length] = itemToSave;
|
||||||
let isAvailable = true;
|
// createNewListEntry(itemToSave);
|
||||||
for (let i = 0; i < currentTypes.length; i++) {
|
// }
|
||||||
if (currentTypes[i].id === id) {
|
// }
|
||||||
isAvailable = false;
|
// },
|
||||||
break;
|
// deleteButton: {
|
||||||
}
|
// text: 'Supprimer',
|
||||||
}
|
// btnClass: 'btn-red',
|
||||||
return isAvailable;
|
// isHidden: index === -1,
|
||||||
}
|
// action: function () {
|
||||||
|
// let id = currentTypes[index]['id'];
|
||||||
function isItemInputEmpty() {
|
// SaveManager.deleteCategory(id);
|
||||||
return $.selector_cache('#idInput').val() === '' &&
|
// deleteListEntry(id);
|
||||||
$.selector_cache('#nameInput').val() === '' &&
|
// }
|
||||||
$.selector_cache('#iconInput').val() === '';
|
// },
|
||||||
}
|
// cancelButton: {
|
||||||
|
// text: 'Annuler',
|
||||||
function isItemInputFilled() {
|
// },
|
||||||
return $.selector_cache('#idInput').val() !== '' &&
|
// },
|
||||||
$.selector_cache('#nameInput').val() !== '' &&
|
// onContentReady: function () {
|
||||||
$.selector_cache('#iconInput').val() !== '';
|
// // bind to events
|
||||||
}
|
// let jc = this;
|
||||||
|
// this.$content.find('form').on('submit', function (e) {
|
||||||
function saveDataset() {
|
// // if the user submits the form by pressing enter in the field.
|
||||||
SaveManager.saveData(currentTypes, currentDataset);
|
// e.preventDefault();
|
||||||
}
|
// jc.$$formSubmit.trigger('click'); // reference the button and click it
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
|
@ -70,78 +70,3 @@ function animateCss($elem, animationName, callback) {
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
jconfirm.defaults = {
|
|
||||||
title: 'Title',
|
|
||||||
titleClass: '',
|
|
||||||
type: 'red',
|
|
||||||
typeAnimated: true,
|
|
||||||
draggable: false,
|
|
||||||
dragWindowGap: 15,
|
|
||||||
dragWindowBorder: true,
|
|
||||||
animateFromElement: true,
|
|
||||||
smoothContent: true,
|
|
||||||
content: 'content',
|
|
||||||
escapeKey: 'ok',
|
|
||||||
buttons: {},
|
|
||||||
defaultButtons: {
|
|
||||||
ok: {
|
|
||||||
keys: ['enter'],
|
|
||||||
text: 'OK',
|
|
||||||
action: function () {
|
|
||||||
}
|
|
||||||
},
|
|
||||||
close: {
|
|
||||||
action: function () {
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
contentLoaded: function (data, status, xhr) {
|
|
||||||
},
|
|
||||||
icon: '',
|
|
||||||
lazyOpen: false,
|
|
||||||
bgOpacity: null,
|
|
||||||
theme: 'supervan',
|
|
||||||
animation: 'scale',
|
|
||||||
closeAnimation: 'scale',
|
|
||||||
animationSpeed: 300,
|
|
||||||
animationBounce: 1,
|
|
||||||
rtl: false,
|
|
||||||
container: 'body',
|
|
||||||
containerFluid: false,
|
|
||||||
backgroundDismiss: false,
|
|
||||||
backgroundDismissAnimation: 'shake',
|
|
||||||
autoClose: false,
|
|
||||||
closeIcon: null,
|
|
||||||
closeIconClass: false,
|
|
||||||
watchInterval: 100,
|
|
||||||
columnClass: 'xlarge',
|
|
||||||
boxWidth: '50%',
|
|
||||||
scrollToPreviousElement: true,
|
|
||||||
scrollToPreviousElementAnimate: true,
|
|
||||||
useBootstrap: true,
|
|
||||||
offsetTop: 40,
|
|
||||||
offsetBottom: 40,
|
|
||||||
bootstrapClasses: {
|
|
||||||
container: 'container',
|
|
||||||
containerFluid: 'container-fluid',
|
|
||||||
row: 'row',
|
|
||||||
},
|
|
||||||
onContentReady: function () {
|
|
||||||
},
|
|
||||||
onOpenBefore: function () {
|
|
||||||
// after the modal is displayed.
|
|
||||||
$('body').css('overflow', 'hidden');
|
|
||||||
},
|
|
||||||
onOpen: function () {
|
|
||||||
},
|
|
||||||
onClose: function () {
|
|
||||||
// before the modal is hidden.
|
|
||||||
$('body').css('overflow', 'auto');
|
|
||||||
},
|
|
||||||
onDestroy: function () {
|
|
||||||
},
|
|
||||||
onAction: function () {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
73
assets/js/jquery-confirm-defaults.js
vendored
Normal file
73
assets/js/jquery-confirm-defaults.js
vendored
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
jconfirm.defaults = {
|
||||||
|
title: 'Title',
|
||||||
|
titleClass: '',
|
||||||
|
type: 'red',
|
||||||
|
typeAnimated: true,
|
||||||
|
draggable: false,
|
||||||
|
dragWindowGap: 15,
|
||||||
|
dragWindowBorder: true,
|
||||||
|
animateFromElement: false,
|
||||||
|
smoothContent: true,
|
||||||
|
content: 'content',
|
||||||
|
escapeKey: 'ok',
|
||||||
|
buttons: {},
|
||||||
|
defaultButtons: {
|
||||||
|
ok: {
|
||||||
|
keys: ['enter'],
|
||||||
|
text: 'OK',
|
||||||
|
action: function () {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
close: {
|
||||||
|
action: function () {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
contentLoaded: function (data, status, xhr) {
|
||||||
|
},
|
||||||
|
icon: '',
|
||||||
|
lazyOpen: false,
|
||||||
|
bgOpacity: null,
|
||||||
|
theme: 'material',
|
||||||
|
animation: 'scale',
|
||||||
|
closeAnimation: 'scale',
|
||||||
|
animationSpeed: 300,
|
||||||
|
animationBounce: 1.3,
|
||||||
|
rtl: false,
|
||||||
|
container: 'body',
|
||||||
|
containerFluid: false,
|
||||||
|
backgroundDismiss: false,
|
||||||
|
backgroundDismissAnimation: 'shake',
|
||||||
|
autoClose: false,
|
||||||
|
closeIcon: null,
|
||||||
|
closeIconClass: false,
|
||||||
|
watchInterval: 100,
|
||||||
|
columnClass: 'xlarge',
|
||||||
|
boxWidth: '50%',
|
||||||
|
scrollToPreviousElement: true,
|
||||||
|
scrollToPreviousElementAnimate: true,
|
||||||
|
useBootstrap: true,
|
||||||
|
offsetTop: 40,
|
||||||
|
offsetBottom: 40,
|
||||||
|
bootstrapClasses: {
|
||||||
|
container: 'container',
|
||||||
|
containerFluid: 'container-fluid',
|
||||||
|
row: 'row',
|
||||||
|
},
|
||||||
|
onContentReady: function () {
|
||||||
|
},
|
||||||
|
onOpenBefore: function () {
|
||||||
|
// after the modal is displayed.
|
||||||
|
$('body').css('overflow', 'hidden');
|
||||||
|
},
|
||||||
|
onOpen: function () {
|
||||||
|
},
|
||||||
|
onClose: function () {
|
||||||
|
// before the modal is hidden.
|
||||||
|
$('body').css('overflow', 'auto');
|
||||||
|
},
|
||||||
|
onDestroy: function () {
|
||||||
|
},
|
||||||
|
onAction: function () {
|
||||||
|
}
|
||||||
|
};
|
10
assets/js/jquery-confirm.min.js
vendored
Normal file
10
assets/js/jquery-confirm.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
167
assets/js/listManager.js
Normal file
167
assets/js/listManager.js
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
|
||||||
|
class ListManager {
|
||||||
|
|
||||||
|
currentTypes = [];
|
||||||
|
displayedTypes = [];
|
||||||
|
editableTypes = [];
|
||||||
|
|
||||||
|
constructor(listContainer, initialData, editableTypes) {
|
||||||
|
this.listContainer = listContainer;
|
||||||
|
this.currentTypes = initialData;
|
||||||
|
this.editableTypes = editableTypes;
|
||||||
|
this.generateList();
|
||||||
|
}
|
||||||
|
|
||||||
|
generateList() {
|
||||||
|
for (let i = 0; i < this.currentTypes.length; i++) {
|
||||||
|
this.createNewListEntry(this.currentTypes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createNewListEntry(item) {
|
||||||
|
let listItem = this.getListItem(item);
|
||||||
|
this.displayedTypes.push($(listItem));
|
||||||
|
const index = this.displayedTypes.length-1;
|
||||||
|
let JQueryItem = this.displayedTypes[index];
|
||||||
|
this.listContainer.append(JQueryItem);
|
||||||
|
JQueryItem.on('click', () => {
|
||||||
|
this.showEditPopup(index);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteListEntry(id) {
|
||||||
|
$('#listItem_' + id).remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
getListItem(item) {
|
||||||
|
let listItem = "<li id='listItem_" + item["id"] + "'><div>";
|
||||||
|
for (let i = 0; i < this.editableTypes.length; i++) {
|
||||||
|
listItem += "<span class='list-" + this.editableTypes[i]["name"] + "'>";
|
||||||
|
if (this.editableTypes[i]["type"] === "icon")
|
||||||
|
listItem += "<i class='mdi mdi-" + item["icon"] + "' style='margin-right: 5px'></i></span>";
|
||||||
|
else
|
||||||
|
listItem += item["name"] + '</span>';
|
||||||
|
}
|
||||||
|
listItem += "</div></li>";
|
||||||
|
return listItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFormData(defaultValues) {
|
||||||
|
let formData = '<form action="" class="categoryForm"><div class="form-group">';
|
||||||
|
for (let i = 0; i < this.editableTypes.length; i++) {
|
||||||
|
let inputId = this.editableTypes[i]['name'] + 'Input';
|
||||||
|
let value = defaultValues[this.editableTypes[i]['name']];
|
||||||
|
formData += '<label for="' + inputId + '">' + this.editableTypes[i]['description'] + ' :</label>' +
|
||||||
|
'<input id="' + inputId + '" type="text" placeholder="Entrez une valeur" class="form-control" value="' + value + '" required />';
|
||||||
|
}
|
||||||
|
formData += "</div></form>";
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFormValues(form) {
|
||||||
|
let values = [];
|
||||||
|
for (let i = 0; i < this.editableTypes.length; i++) {
|
||||||
|
values.push(form.find('#' + this.editableTypes[i]['name'] + 'Input').val())
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
isFormValid(values) {
|
||||||
|
let isValid = true;
|
||||||
|
for (let i = 0; i < values.length; i++) {
|
||||||
|
if (values[i] === '') {
|
||||||
|
isValid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
insertFormDataIntoObject(values, object) {
|
||||||
|
for (let i = 0; i < values.length; i++) {
|
||||||
|
object[this.editableTypes[i]['name']] = values[i];
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateListItem(values, index) {
|
||||||
|
for (let i = 0; i < values.length; i++) {
|
||||||
|
if (this.editableTypes[i]['type'] === 'icon')
|
||||||
|
this.displayedTypes[index].find(".mdi")[0].className = "mdi mdi-" + values[i];
|
||||||
|
else
|
||||||
|
this.displayedTypes[index].find(".list-" + this.editableTypes[i]['name']).text(values[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showEditPopup(index) {
|
||||||
|
let defaultValues = {
|
||||||
|
name: "",
|
||||||
|
icon: ""
|
||||||
|
};
|
||||||
|
let title = "Créer une nouvelle entrée";
|
||||||
|
if (index !== -1) {
|
||||||
|
defaultValues = this.currentTypes[index];
|
||||||
|
title = "Modifier l'entrée";
|
||||||
|
}
|
||||||
|
let formData = this.getFormData(defaultValues);
|
||||||
|
let thisInstance = this;
|
||||||
|
$.confirm({
|
||||||
|
title: title,
|
||||||
|
content: formData,
|
||||||
|
buttons: {
|
||||||
|
formSubmit: {
|
||||||
|
text: 'Sauvegarder',
|
||||||
|
btnClass: 'btn-blue',
|
||||||
|
action: async function () {
|
||||||
|
let values = thisInstance.getFormValues(this.$content);
|
||||||
|
if (!thisInstance.isFormValid(values)) {
|
||||||
|
$.alert('Merci de rentrer toutes les valeurs');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let itemToSave = {};
|
||||||
|
if (index !== -1) {
|
||||||
|
itemToSave = thisInstance.currentTypes[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
itemToSave = thisInstance.insertFormDataIntoObject(values, itemToSave);
|
||||||
|
|
||||||
|
if (index !== -1) {
|
||||||
|
thisInstance.currentTypes[index] = itemToSave;
|
||||||
|
thisInstance.updateListItem(values, index);
|
||||||
|
}
|
||||||
|
let id = await SaveManager.saveCategory(itemToSave, index === -1);
|
||||||
|
if (id >= 0 && index === -1) {
|
||||||
|
itemToSave["id"] = id;
|
||||||
|
thisInstance.currentTypes[thisInstance.displayedTypes.length] = itemToSave;
|
||||||
|
thisInstance.createNewListEntry(itemToSave);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteButton: {
|
||||||
|
text: 'Supprimer',
|
||||||
|
btnClass: 'btn-red',
|
||||||
|
isHidden: index === -1,
|
||||||
|
action: function () {
|
||||||
|
let id = thisInstance.currentTypes[index]['id'];
|
||||||
|
SaveManager.deleteCategory(id);
|
||||||
|
thisInstance.deleteListEntry(id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancelButton: {
|
||||||
|
text: 'Annuler',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onContentReady: function () {
|
||||||
|
// bind to events
|
||||||
|
let jc = this;
|
||||||
|
this.$content.find('form').on('submit', function (e) {
|
||||||
|
// if the user submits the form by pressing enter in the field.
|
||||||
|
e.preventDefault();
|
||||||
|
jc.$$formSubmit.trigger('click'); // reference the button and click it
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,76 +1,40 @@
|
||||||
|
|
||||||
class SaveManager {
|
class SaveManager {
|
||||||
|
|
||||||
static saveData(types, dataset) {
|
static deleteCategory(id) {
|
||||||
let finalDataset = {
|
let data = {
|
||||||
v1: SaveManager.generateV1JSON(types, dataset),
|
function: "remove_category",
|
||||||
v2: SaveManager.generateV2JSON(types, dataset)
|
data: id,
|
||||||
};
|
};
|
||||||
console.log(finalDataset);
|
console.log(data);
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "write_json.php",
|
url: "save_manager.php",
|
||||||
data: JSON.stringify(finalDataset),
|
data: JSON.stringify(data),
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
contentType: "application/json; charset=utf-8",
|
contentType: "application/json; charset=utf-8",
|
||||||
complete: function (data) {
|
complete: function (data) {
|
||||||
alert(data.responseText);
|
$.alert(data.responseText);
|
||||||
console.log(data);
|
console.log(data);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static generateV1JSON(savedTypes, savedDataset) {
|
static async saveCategory(category, isNew) {
|
||||||
let types = [];
|
let data = {
|
||||||
// Replace type objects by names
|
function: isNew ? "create_category" : "update_category",
|
||||||
for (let i = 0; i < savedTypes.length; i++) {
|
data: category,
|
||||||
types.push(savedTypes[i].name);
|
};
|
||||||
}
|
|
||||||
let dataset = JSON.parse(JSON.stringify(savedDataset)); // Deep copy of object
|
|
||||||
for (let i = 0; i < dataset.length; i++) {
|
|
||||||
// Replace type ids by names
|
|
||||||
for (let k = 0; k < dataset[i].type.length; k++) {
|
|
||||||
dataset[i].type[k] = SaveManager.getTypeOfId(savedTypes, dataset[i].type[k]).name;
|
|
||||||
}
|
|
||||||
// remove the description field
|
|
||||||
delete dataset[i].description
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
types: types,
|
|
||||||
articles: dataset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static generateV2JSON(savedTypes, savedDataset) {
|
let response = await $.ajax({
|
||||||
return {
|
|
||||||
types: savedTypes,
|
|
||||||
articles: savedDataset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static getTypeOfId(types, id) {
|
|
||||||
let item = {};
|
|
||||||
for (let i = 0; i < types.length; i++) {
|
|
||||||
if (types[i].id === id) {
|
|
||||||
item = types[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
static convertToV2() {
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "convert_json.php",
|
url: "save_manager.php",
|
||||||
|
data: JSON.stringify(data),
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
contentType: "application/json; charset=utf-8",
|
contentType: "application/json; charset=utf-8",
|
||||||
complete: function (data) {
|
|
||||||
alert(data.responseText);
|
|
||||||
console.log(data);
|
|
||||||
window.location.reload();
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
console.log(response);
|
||||||
|
return response['data'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
assets/js/sortable.min.js
vendored
Normal file
2
assets/js/sortable.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
83
classes/dao.php
Normal file
83
classes/dao.php
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
class Dao
|
||||||
|
{
|
||||||
|
private $conn;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$username = 'proximo';
|
||||||
|
$password = $this->read_password();
|
||||||
|
$dsn = 'mysql:dbname=proximo;host=127.0.0.1';
|
||||||
|
try {
|
||||||
|
$this->conn = new PDO($dsn, $username, $password, [PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8']);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo "error";
|
||||||
|
echo $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function read_password()
|
||||||
|
{
|
||||||
|
$real_path = __DIR__ . DIRECTORY_SEPARATOR . ".htpassdb";
|
||||||
|
$file = fopen($real_path, "r") or die("Unable to open DB password file!");
|
||||||
|
$password = fgets($file);
|
||||||
|
fclose($file);
|
||||||
|
return trim($password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_articles()
|
||||||
|
{
|
||||||
|
$sql = 'SELECT * FROM articles';
|
||||||
|
$cursor = $this->conn->prepare($sql);
|
||||||
|
$cursor->execute();
|
||||||
|
return $cursor->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_article_categories($article_id)
|
||||||
|
{
|
||||||
|
$sql = 'SELECT category_id FROM article_categories WHERE article_id=?';
|
||||||
|
$cursor = $this->conn->prepare($sql);
|
||||||
|
$cursor->execute([$article_id]);
|
||||||
|
$result = $cursor->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
$final = [];
|
||||||
|
foreach ($result as $row) {
|
||||||
|
array_push($final, $row["category_id"]);
|
||||||
|
}
|
||||||
|
return $final;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_categories()
|
||||||
|
{
|
||||||
|
$sql = 'SELECT * FROM categories';
|
||||||
|
$cursor = $this->conn->prepare($sql);
|
||||||
|
$cursor->execute();
|
||||||
|
return $cursor->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create_category($category) {
|
||||||
|
$sql = 'INSERT INTO categories (name, icon) VALUES (?, ?)';
|
||||||
|
$cursor = $this->conn->prepare($sql);
|
||||||
|
$data = [$category["name"], $category["icon"]];
|
||||||
|
$cursor->execute($data);
|
||||||
|
return $this->conn->lastInsertId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update_category($category)
|
||||||
|
{
|
||||||
|
$sql = 'UPDATE categories SET name=?, icon=? WHERE id=?';
|
||||||
|
$cursor = $this->conn->prepare($sql);
|
||||||
|
$data = [$category["name"], $category["icon"], $category["id"]];
|
||||||
|
$cursor->execute($data);
|
||||||
|
return $category["id"];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function remove_category($id)
|
||||||
|
{
|
||||||
|
$sql = 'DELETE FROM categories WHERE id=?';
|
||||||
|
$cursor = $this->conn->prepare($sql);
|
||||||
|
$data = [$id];
|
||||||
|
return $cursor->execute($data);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,8 +28,8 @@ if (!isset($hasHeader))
|
||||||
<link type="text/css" rel="stylesheet" href="<?= $relativePath ?>assets/css/hamburger.css"
|
<link type="text/css" rel="stylesheet" href="<?= $relativePath ?>assets/css/hamburger.css"
|
||||||
media="screen,projection"/>
|
media="screen,projection"/>
|
||||||
<link type="text/css" rel="stylesheet" href="<?= $relativePath ?>assets/css/sidenav.css" media="screen,projection"/>
|
<link type="text/css" rel="stylesheet" href="<?= $relativePath ?>assets/css/sidenav.css" media="screen,projection"/>
|
||||||
<link type="text/css" rel="stylesheet" href="<?= $relativePath ?>assets/css/bootstrapOverwrite.css"
|
<link type="text/css" rel="stylesheet" href="<?= $relativePath ?>assets/css/bootstrapOverwrite.css" media="screen,projection"/>
|
||||||
media="screen,projection"/>
|
<link type="text/css" rel="stylesheet" href="<?= $relativePath ?>assets/css/jquery-confirm.min.css" media="screen,projection"/>
|
||||||
<link rel="icon" type="image/png" href="<?= $relativePath ?>assets/images/favicon.png">
|
<link rel="icon" type="image/png" href="<?= $relativePath ?>assets/images/favicon.png">
|
||||||
<!--Let browser know website is optimized for mobile-->
|
<!--Let browser know website is optimized for mobile-->
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
@ -71,6 +71,8 @@ if (!isset($hasHeader))
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.2/jquery-confirm.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.2/jquery-confirm.min.js"></script>
|
||||||
<script type="text/javascript" src="<?= $relativePath ?>assets/js/init.js"></script>
|
<script type="text/javascript" src="<?= $relativePath ?>assets/js/init.js"></script>
|
||||||
<script type="text/javascript" src="<?= $relativePath ?>assets/js/sidenav.js"></script>
|
<script type="text/javascript" src="<?= $relativePath ?>assets/js/sidenav.js"></script>
|
||||||
|
<script type="text/javascript" src="<?= $relativePath ?>assets/js/jquery-confirm.min.js"></script>
|
||||||
|
<script src="<?= $relativePath ?>assets/js/sortable.min.js"></script>
|
||||||
<?= $pageScripts ?>
|
<?= $pageScripts ?>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Reference in a new issue