mirror of
https://github.com/prurigro/hypothetical.git
synced 2024-11-24 16:51:25 -05:00
Link to the dashboard credits page from a new footer element instead of the user dropdown, organize the dashboard blades by folder now that we have so many of them, and implement user password reset functionality
This commit is contained in:
parent
d06cae1c67
commit
83a8dede40
17 changed files with 292 additions and 56 deletions
|
@ -2,10 +2,12 @@
|
||||||
|
|
||||||
use App\Http\Requests;
|
use App\Http\Requests;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Auth;
|
||||||
use File;
|
use File;
|
||||||
use Image;
|
use Image;
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||||
|
use App\User;
|
||||||
use App\Dashboard;
|
use App\Dashboard;
|
||||||
|
|
||||||
class DashboardController extends Controller {
|
class DashboardController extends Controller {
|
||||||
|
@ -23,7 +25,7 @@ class DashboardController extends Controller {
|
||||||
*/
|
*/
|
||||||
public function getIndex()
|
public function getIndex()
|
||||||
{
|
{
|
||||||
return view('dashboard.home');
|
return view('dashboard.pages.home');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,7 +33,17 @@ class DashboardController extends Controller {
|
||||||
*/
|
*/
|
||||||
public function getCredits()
|
public function getCredits()
|
||||||
{
|
{
|
||||||
return view('dashboard.credits');
|
return view('dashboard.pages.credits');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dashboard settings
|
||||||
|
*/
|
||||||
|
public function getSettings()
|
||||||
|
{
|
||||||
|
return view('dashboard.pages.settings', [
|
||||||
|
'user' => User::find(Auth::id())
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,7 +54,7 @@ class DashboardController extends Controller {
|
||||||
$model_class = Dashboard::getModel($model, 'view');
|
$model_class = Dashboard::getModel($model, 'view');
|
||||||
|
|
||||||
if ($model_class != null) {
|
if ($model_class != null) {
|
||||||
return view('dashboard.view', [
|
return view('dashboard.pages.view', [
|
||||||
'heading' => $model_class::getDashboardHeading($model),
|
'heading' => $model_class::getDashboardHeading($model),
|
||||||
'column_headings' => $model_class::getDashboardColumnData('headings'),
|
'column_headings' => $model_class::getDashboardColumnData('headings'),
|
||||||
'model' => $model,
|
'model' => $model,
|
||||||
|
@ -62,7 +74,7 @@ class DashboardController extends Controller {
|
||||||
$model_class = Dashboard::getModel($model, 'edit');
|
$model_class = Dashboard::getModel($model, 'edit');
|
||||||
|
|
||||||
if ($model_class != null) {
|
if ($model_class != null) {
|
||||||
return view('dashboard.edit-list', [
|
return view('dashboard.pages.edit-list', [
|
||||||
'heading' => $model_class::getDashboardHeading($model),
|
'heading' => $model_class::getDashboardHeading($model),
|
||||||
'model' => $model,
|
'model' => $model,
|
||||||
'rows' => $model_class::getDashboardData(),
|
'rows' => $model_class::getDashboardData(),
|
||||||
|
@ -101,7 +113,7 @@ class DashboardController extends Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return view('dashboard.edit-item', [
|
return view('dashboard.pages.edit-item', [
|
||||||
'heading' => $model_class::getDashboardHeading($model),
|
'heading' => $model_class::getDashboardHeading($model),
|
||||||
'model' => $model,
|
'model' => $model,
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
|
@ -280,6 +292,23 @@ class DashboardController extends Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User Password: Change the current user's password
|
||||||
|
*/
|
||||||
|
public function postUserPassword(Request $request)
|
||||||
|
{
|
||||||
|
$this->validate($request, [
|
||||||
|
'oldpass' => 'required|string|min:6',
|
||||||
|
'newpass' => 'required|string|min:6|confirmed'
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (User::find(Auth::id())->updatePassword($request['oldpass'], $request['newpass'])) {
|
||||||
|
return 'success';
|
||||||
|
} else {
|
||||||
|
return 'old-password-fail';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dashboard Delete: Delete rows
|
* Dashboard Delete: Delete rows
|
||||||
*/
|
*/
|
||||||
|
|
17
app/User.php
17
app/User.php
|
@ -4,6 +4,7 @@ namespace App;
|
||||||
|
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
|
use Hash;
|
||||||
|
|
||||||
class User extends Authenticatable
|
class User extends Authenticatable
|
||||||
{
|
{
|
||||||
|
@ -26,4 +27,20 @@ class User extends Authenticatable
|
||||||
protected $hidden = [
|
protected $hidden = [
|
||||||
'password', 'remember_token', 'api_token'
|
'password', 'remember_token', 'api_token'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the user's password
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public function updatePassword($oldpass, $newpass)
|
||||||
|
{
|
||||||
|
if (Hash::check($oldpass, $this->password)) {
|
||||||
|
$this->password = Hash::make($newpass);
|
||||||
|
$this->save();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
2
resources/assets/js/app.js
vendored
2
resources/assets/js/app.js
vendored
|
@ -125,4 +125,4 @@ router.afterEach((to, from) => {
|
||||||
const App = new Vue({
|
const App = new Vue({
|
||||||
router,
|
router,
|
||||||
store
|
store
|
||||||
}).$mount("#page-content");
|
}).$mount("#vue-container");
|
||||||
|
|
168
resources/assets/js/dashboard.js
vendored
168
resources/assets/js/dashboard.js
vendored
|
@ -1,3 +1,23 @@
|
||||||
|
const $loadingModal = $("#loading-modal"),
|
||||||
|
fadeTime = 250;
|
||||||
|
|
||||||
|
// show the loading modal
|
||||||
|
const showLoadingModal = function() {
|
||||||
|
$loadingModal.css({
|
||||||
|
visibility: "visible",
|
||||||
|
opacity: 1
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// hide the loading modal
|
||||||
|
const hideLoadingModal = function() {
|
||||||
|
$loadingModal.css({ opacity: 0 });
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
$loadingModal.css({ visibility: "hidden" });
|
||||||
|
}, fadeTime);
|
||||||
|
};
|
||||||
|
|
||||||
// declare a reverse function for jquery
|
// declare a reverse function for jquery
|
||||||
jQuery.fn.reverse = [].reverse;
|
jQuery.fn.reverse = [].reverse;
|
||||||
|
|
||||||
|
@ -6,8 +26,7 @@ function askConfirmation(message, command, cancelCommand) {
|
||||||
const $confirmationModal = $("#confirmation-modal"),
|
const $confirmationModal = $("#confirmation-modal"),
|
||||||
$heading = $confirmationModal.find(".card-header"),
|
$heading = $confirmationModal.find(".card-header"),
|
||||||
$cancelButton = $confirmationModal.find(".btn.cancel-button"),
|
$cancelButton = $confirmationModal.find(".btn.cancel-button"),
|
||||||
$confirmButton = $confirmationModal.find(".btn.confirm-button"),
|
$confirmButton = $confirmationModal.find(".btn.confirm-button");
|
||||||
fadeTime = 250;
|
|
||||||
|
|
||||||
// close the confirmation modal and unbind its events
|
// close the confirmation modal and unbind its events
|
||||||
const closeConfirmationModal = function() {
|
const closeConfirmationModal = function() {
|
||||||
|
@ -21,7 +40,10 @@ function askConfirmation(message, command, cancelCommand) {
|
||||||
|
|
||||||
// hide the modal
|
// hide the modal
|
||||||
$confirmationModal.css({ opacity: 0 });
|
$confirmationModal.css({ opacity: 0 });
|
||||||
setTimeout(function() { $confirmationModal.css({ visibility: "hidden" }); }, fadeTime);
|
|
||||||
|
setTimeout(function() {
|
||||||
|
$confirmationModal.css({ visibility: "hidden" });
|
||||||
|
}, fadeTime);
|
||||||
};
|
};
|
||||||
|
|
||||||
// close the modal if the escape button is pressed
|
// close the modal if the escape button is pressed
|
||||||
|
@ -67,8 +89,7 @@ function askConfirmation(message, command, cancelCommand) {
|
||||||
function showAlert(message, command) {
|
function showAlert(message, command) {
|
||||||
const $alertModal = $("#alert-modal"),
|
const $alertModal = $("#alert-modal"),
|
||||||
$message = $alertModal.find(".message"),
|
$message = $alertModal.find(".message"),
|
||||||
$acceptButton = $alertModal.find(".btn.accept-button"),
|
$acceptButton = $alertModal.find(".btn.accept-button");
|
||||||
fadeTime = 250;
|
|
||||||
|
|
||||||
// close the alert modal and unbind its events
|
// close the alert modal and unbind its events
|
||||||
const closeAlertModal = function() {
|
const closeAlertModal = function() {
|
||||||
|
@ -160,7 +181,7 @@ function editListInit() {
|
||||||
if (response === "success") {
|
if (response === "success") {
|
||||||
$listItem.slideUp(150, function() { $listItem.remove(); });
|
$listItem.slideUp(150, function() { $listItem.remove(); });
|
||||||
} else {
|
} else {
|
||||||
showAlert("ERROR: Failed to delete record");
|
showAlert("Failed to delete record");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -225,7 +246,7 @@ function editListInit() {
|
||||||
}
|
}
|
||||||
}).always(function(response) {
|
}).always(function(response) {
|
||||||
if (response !== "success") {
|
if (response !== "success") {
|
||||||
showAlert("ERROR: Sorting failed", function() {
|
showAlert("Sorting failed", function() {
|
||||||
document.location.reload(true);
|
document.location.reload(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -277,8 +298,6 @@ function editItemInit() {
|
||||||
$fileUploads = $(".file-upload"),
|
$fileUploads = $(".file-upload"),
|
||||||
$imgUploads = $(".image-upload"),
|
$imgUploads = $(".image-upload"),
|
||||||
$token = $("#token"),
|
$token = $("#token"),
|
||||||
$spinner = $("#loading-modal"),
|
|
||||||
fadeTime = 250,
|
|
||||||
model = $editItem.data("model"),
|
model = $editItem.data("model"),
|
||||||
id = $editItem.data("id"),
|
id = $editItem.data("id"),
|
||||||
operation = id === "new" ? "create" : "update";
|
operation = id === "new" ? "create" : "update";
|
||||||
|
@ -291,20 +310,6 @@ function editItemInit() {
|
||||||
minutes,
|
minutes,
|
||||||
changes = false;
|
changes = false;
|
||||||
|
|
||||||
// show the loading modal
|
|
||||||
const showLoadingModal = function() {
|
|
||||||
$spinner.css({
|
|
||||||
visibility: "visible",
|
|
||||||
opacity: 1
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// hide the loading modal
|
|
||||||
const hideLoadingModal = function() {
|
|
||||||
$spinner.css({ opacity: 0 });
|
|
||||||
setTimeout(function() { $spinner.css({ visibility: "hidden" }); }, fadeTime);
|
|
||||||
};
|
|
||||||
|
|
||||||
// fill the formData object with data from all the form fields
|
// fill the formData object with data from all the form fields
|
||||||
const getFormData = function() {
|
const getFormData = function() {
|
||||||
// function to add a column and value to the formData object
|
// function to add a column and value to the formData object
|
||||||
|
@ -390,7 +395,7 @@ function editItemInit() {
|
||||||
uploadFile(row_id, currentFile + 1);
|
uploadFile(row_id, currentFile + 1);
|
||||||
} else {
|
} else {
|
||||||
hideLoadingModal();
|
hideLoadingModal();
|
||||||
showAlert("ERROR: Failed to upload file");
|
showAlert("Failed to upload file");
|
||||||
console.log(response.responseText);
|
console.log(response.responseText);
|
||||||
submitting = false;
|
submitting = false;
|
||||||
}
|
}
|
||||||
|
@ -436,7 +441,7 @@ function editItemInit() {
|
||||||
uploadImage(row_id, currentImage + 1);
|
uploadImage(row_id, currentImage + 1);
|
||||||
} else {
|
} else {
|
||||||
hideLoadingModal();
|
hideLoadingModal();
|
||||||
showAlert("ERROR: Failed to upload image");
|
showAlert("Failed to upload image");
|
||||||
submitting = false;
|
submitting = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -475,7 +480,7 @@ function editItemInit() {
|
||||||
if (response === "success") {
|
if (response === "success") {
|
||||||
$(`#current-image-${name}`).slideUp(200);
|
$(`#current-image-${name}`).slideUp(200);
|
||||||
} else {
|
} else {
|
||||||
showAlert("ERROR: Failed to delete the image: " + response);
|
showAlert("Failed to delete image: " + response);
|
||||||
}
|
}
|
||||||
|
|
||||||
submitting = false;
|
submitting = false;
|
||||||
|
@ -510,7 +515,7 @@ function editItemInit() {
|
||||||
if (response === "success") {
|
if (response === "success") {
|
||||||
$(`#current-file-${name}`).slideUp(200);
|
$(`#current-file-${name}`).slideUp(200);
|
||||||
} else {
|
} else {
|
||||||
showAlert("ERROR: Failed to delete the file: " + response);
|
showAlert("Failed to delete file: " + response);
|
||||||
}
|
}
|
||||||
|
|
||||||
submitting = false;
|
submitting = false;
|
||||||
|
@ -566,13 +571,16 @@ function editItemInit() {
|
||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
|
// load the initial value into the editor
|
||||||
simplemde[column].value($this.attr("value"));
|
simplemde[column].value($this.attr("value"));
|
||||||
simplemde[column].codemirror.refresh();
|
simplemde[column].codemirror.refresh();
|
||||||
|
|
||||||
|
// watch for changes to simplemde editor contents
|
||||||
simplemde[column].codemirror.on("change", contentChanged);
|
simplemde[column].codemirror.on("change", contentChanged);
|
||||||
}, 500);
|
}, 500);
|
||||||
});
|
});
|
||||||
|
|
||||||
// initialize change events for back button
|
// watch for changes to input and select element contents
|
||||||
$editItem.find("input, select").on("input change", contentChanged);
|
$editItem.find("input, select").on("input change", contentChanged);
|
||||||
|
|
||||||
// initialize back button
|
// initialize back button
|
||||||
|
@ -609,7 +617,7 @@ function editItemInit() {
|
||||||
uploadImage(response.replace(/^id:/, ""), 0);
|
uploadImage(response.replace(/^id:/, ""), 0);
|
||||||
} else {
|
} else {
|
||||||
hideLoadingModal();
|
hideLoadingModal();
|
||||||
showAlert("ERROR: Failed to " + operation + " record");
|
showAlert("Failed to " + operation + " record");
|
||||||
submitting = false;
|
submitting = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -617,11 +625,111 @@ function editItemInit() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function userPasswordInit() {
|
||||||
|
const $form = $("#user-password"),
|
||||||
|
$submit = $form.find(".submit-button"),
|
||||||
|
$inputs = $form.find("input"),
|
||||||
|
$oldpass = $("#oldpass"),
|
||||||
|
$newpass = $("#newpass"),
|
||||||
|
$newpassConfirmation = $("#newpass_confirmation"),
|
||||||
|
$token = $("#token");
|
||||||
|
|
||||||
|
let formData = {},
|
||||||
|
submitting = false;
|
||||||
|
|
||||||
|
const getFormData = function() {
|
||||||
|
formData = {
|
||||||
|
oldpass: $oldpass.val(),
|
||||||
|
newpass: $newpass.val(),
|
||||||
|
newpass_confirmation: $newpassConfirmation.val(),
|
||||||
|
_token: $token.val()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// remove the error class from inputs and enable submit if all inputs have data when changes are made
|
||||||
|
$inputs.on("input change", function() {
|
||||||
|
let enableSubmit = true;
|
||||||
|
|
||||||
|
for (let i = 0; i < $inputs.length; i++) {
|
||||||
|
if ($inputs[i].value === "") {
|
||||||
|
enableSubmit = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableSubmit) {
|
||||||
|
$submit.removeClass("no-input");
|
||||||
|
} else {
|
||||||
|
$submit.addClass("no-input");
|
||||||
|
}
|
||||||
|
|
||||||
|
$inputs.removeClass("error");
|
||||||
|
});
|
||||||
|
|
||||||
|
// initialize submit button
|
||||||
|
$submit.on("click", function() {
|
||||||
|
if (!submitting) {
|
||||||
|
submitting = true;
|
||||||
|
|
||||||
|
// remove the error class from inputs
|
||||||
|
$inputs.removeClass("error");
|
||||||
|
|
||||||
|
// show the loading modal
|
||||||
|
showLoadingModal();
|
||||||
|
|
||||||
|
// populate the formData object
|
||||||
|
getFormData();
|
||||||
|
|
||||||
|
if (formData.newpass !== formData.newpass_confirmation) {
|
||||||
|
// fail with an error if the newpass and newpass_confirmation don't match
|
||||||
|
$newpassConfirmation.val("");
|
||||||
|
$newpass.addClass("error");
|
||||||
|
$newpassConfirmation.addClass("error");
|
||||||
|
showAlert("New passwords do not match");
|
||||||
|
submitting = false;
|
||||||
|
} else {
|
||||||
|
// submit the update
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: "/dashboard/user-password",
|
||||||
|
data: formData
|
||||||
|
}).always(function(response) {
|
||||||
|
if (response === "success") {
|
||||||
|
hideLoadingModal();
|
||||||
|
|
||||||
|
showAlert("Password updated successfully", function() {
|
||||||
|
$inputs.val("").trigger("change");
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
submitting = false;
|
||||||
|
|
||||||
|
if (response === "old-password-fail") {
|
||||||
|
$oldpass.addClass("error");
|
||||||
|
showAlert("Old password is not correct");
|
||||||
|
} else {
|
||||||
|
$newpass.addClass("error");
|
||||||
|
$newpassConfirmation.val("");
|
||||||
|
hideLoadingModal();
|
||||||
|
showAlert("New password must be at least 6 characters");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// run once the document is ready
|
// run once the document is ready
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
if ($("#edit-list").length) {
|
if ($("#edit-list").length) {
|
||||||
editListInit();
|
editListInit();
|
||||||
} else if ($("#edit-item").length) {
|
}
|
||||||
|
|
||||||
|
if ($("#edit-item").length) {
|
||||||
editItemInit();
|
editItemInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($("#user-password").length) {
|
||||||
|
userPasswordInit();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
49
resources/assets/sass/dashboard.scss
vendored
49
resources/assets/sass/dashboard.scss
vendored
|
@ -10,7 +10,9 @@
|
||||||
|
|
||||||
// Colours
|
// Colours
|
||||||
$c-text: #111; // text
|
$c-text: #111; // text
|
||||||
|
$c-text-inactive: fade-out($c-text, 0.25); // inactive text
|
||||||
$c-text-light: #fff; // light text
|
$c-text-light: #fff; // light text
|
||||||
|
$c-text-light-inactive: fade-out($c-text-light, 0.25); // inactive light text
|
||||||
$c-input-bg: #fff; // white
|
$c-input-bg: #fff; // white
|
||||||
$c-dashboard-error: #a80000;
|
$c-dashboard-error: #a80000;
|
||||||
$c-dashboard-dark: #3e6087;
|
$c-dashboard-dark: #3e6087;
|
||||||
|
@ -33,6 +35,16 @@ body {
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.site-content {
|
||||||
|
display: flex;
|
||||||
|
min-height: 100vh;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.page-content {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.navbar {
|
.navbar {
|
||||||
margin-bottom: $grid-gutter-width;
|
margin-bottom: $grid-gutter-width;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
@ -103,7 +115,8 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-link {
|
.nav-link {
|
||||||
color: fade-out($c-text-light, 0.25);
|
color: $c-text-light-inactive;
|
||||||
|
transition: color 150ms;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
color: $c-text-light;
|
color: $c-text-light;
|
||||||
|
@ -138,9 +151,37 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active, &:hover, &:focus, &:active {
|
&.active, &:hover, &:focus, &:active {
|
||||||
background-color: fade-out(#000, 0.95);
|
|
||||||
color: $c-text;
|
color: $c-text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover, &:focus {
|
||||||
|
background-color: fade-out(#000, 0.97);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: fade-out(#000, 0.93);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-footer {
|
||||||
|
margin-top: $grid-gutter-width;
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px ($grid-gutter-width / 2);
|
||||||
|
background-color: $c-dashboard-dark;
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $c-text-light-inactive;
|
||||||
|
transition: color 150ms;
|
||||||
|
|
||||||
|
&:hover, &:focus {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: $c-text-light;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -663,6 +704,10 @@ body {
|
||||||
border: 1px solid darken($c-dashboard-light, 10%);
|
border: 1px solid darken($c-dashboard-light, 10%);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
transition: border-color 150ms;
|
transition: border-color 150ms;
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
border-color: $c-dashboard-error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&[type="file"] {
|
&[type="file"] {
|
||||||
|
|
23
resources/views/dashboard/pages/settings.blade.php
Normal file
23
resources/views/dashboard/pages/settings.blade.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
@extends('dashboard.core', [
|
||||||
|
'heading' => 'Settings'
|
||||||
|
])
|
||||||
|
|
||||||
|
@section('dashboard-body')
|
||||||
|
<input type="hidden" id="token" value="{{ csrf_token() }}" />
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-md-8">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 col-md-4">
|
||||||
|
<form id="user-password" class="edit-item">
|
||||||
|
<input class="text-input" type="password" name="oldpass" id="oldpass" placeholder="Old Password" value="" />
|
||||||
|
<input class="text-input" type="password" name="newpass" id="newpass" placeholder="New Password" value="" />
|
||||||
|
<input class="text-input" type="password" name="newpass_confirmation" id="newpass_confirmation" placeholder="Repeat New Password" value="" />
|
||||||
|
<button type="button" class="submit-button no-horizontal-margins btn btn-primary no-input">Update Password</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
3
resources/views/dashboard/sections/footer.blade.php
Normal file
3
resources/views/dashboard/sections/footer.blade.php
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<footer class="dashboard-footer">
|
||||||
|
<a class="{{ $current_page == 'credits' ? 'active' : '' }}" href="/dashboard/credits">Credits</a>
|
||||||
|
</footer>
|
|
@ -1,6 +1,4 @@
|
||||||
<nav class="navbar navbar-expand-lg">
|
<nav class="navbar navbar-expand-lg">
|
||||||
@set('current_page', preg_replace([ '/^.*\//', '/\/.*/' ], [ '', '' ], Request::url()))
|
|
||||||
|
|
||||||
<a class="navbar-brand" href="/dashboard">
|
<a class="navbar-brand" href="/dashboard">
|
||||||
{{ env('APP_NAME') }} Dashboard
|
{{ env('APP_NAME') }} Dashboard
|
||||||
</a>
|
</a>
|
||||||
|
@ -27,7 +25,7 @@
|
||||||
@set('dropdown_id', preg_replace([ '/\ \ */', '/[^a-z\-]/' ], [ '-', '' ], strtolower($menu_item['title'])))
|
@set('dropdown_id', preg_replace([ '/\ \ */', '/[^a-z\-]/' ], [ '-', '' ], strtolower($menu_item['title'])))
|
||||||
|
|
||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
<span id="menu-dropdown-{{ $dropdown_id }}" class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<span id="menu-dropdown-{{ $dropdown_id }}" class="nav-link dropdown-toggle {{ array_search($current_page, array_column($menu_item['submenu'], 'model')) !== false ? 'active' : '' }}" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
{{ $menu_item['title'] }} <span class="caret"></span>
|
{{ $menu_item['title'] }} <span class="caret"></span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
@ -47,12 +45,12 @@
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
<a id="user-dropdown" class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<a id="user-dropdown" class="nav-link dropdown-toggle {{ $current_page == 'settings' ? 'active' : '' }}" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
{{ Auth::user()->name }} <span class="caret"></span>
|
{{ Auth::user()->name }} <span class="caret"></span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="user-dropdown">
|
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="user-dropdown">
|
||||||
<a class="dropdown-item {{ $current_page == 'credits' ? 'active' : '' }}" href="/dashboard/credits">Credits</a>
|
<a class="dropdown-item {{ $current_page == 'settings' ? 'active' : '' }}" href="/dashboard/settings">Settings</a>
|
||||||
<a class="dropdown-item" href="/logout">Logout</a>
|
<a class="dropdown-item" href="/logout">Logout</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
|
@ -36,14 +36,18 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="{{ $device_mobile ? 'mobile-browser' : 'desktop-browser' }}">
|
<body class="{{ $device_mobile ? 'mobile-browser' : 'desktop-browser' }}">
|
||||||
@yield('page-top')
|
<div class="flex-wrapper">
|
||||||
|
<div class="site-content">
|
||||||
|
@yield('page-top')
|
||||||
|
|
||||||
<div id="page-content">
|
<div class="page-content">
|
||||||
@yield('page-content')
|
@yield('page-content')
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@yield('page-bottom')
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@yield('page-bottom')
|
|
||||||
|
|
||||||
@if(Config::get('app.debug'))
|
@if(Config::get('app.debug'))
|
||||||
<script id="__bs_script__">//<![CDATA[
|
<script id="__bs_script__">//<![CDATA[
|
||||||
document.write("<script async src='http://{{ env('BS_HOST', 'localhost') }}:3000/browser-sync/browser-sync-client.js?version={{ env('CACHE_BUST') }}'><\/script>".replace("HOST", location.hostname));
|
document.write("<script async src='http://{{ env('BS_HOST', 'localhost') }}:3000/browser-sync/browser-sync-client.js?version={{ env('CACHE_BUST') }}'><\/script>".replace("HOST", location.hostname));
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
@extends('templates.base', [ 'title' => 'Dashboard' ])
|
@extends('templates.base', [ 'title' => 'Dashboard' ])
|
||||||
|
@set('current_page', preg_replace([ '/^.*\//', '/\/.*/' ], [ '', '' ], Request::url()))
|
||||||
|
|
||||||
@section('page-includes')
|
@section('page-includes')
|
||||||
<script src="/js/lib-dashboard.js?version={{ env('CACHE_BUST') }}"></script>
|
<script src="/js/lib-dashboard.js?version={{ env('CACHE_BUST') }}"></script>
|
||||||
|
@ -7,5 +8,9 @@
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('page-top')
|
@section('page-top')
|
||||||
@include('dashboard.nav')
|
@include('dashboard.sections.nav')
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('page-bottom')
|
||||||
|
@include('dashboard.sections.footer')
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
@ -7,15 +7,17 @@
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('page-content')
|
@section('page-content')
|
||||||
<nav-component></nav-component>
|
<div id="vue-container">
|
||||||
|
<nav-component></nav-component>
|
||||||
|
|
||||||
<div class="flex-wrapper">
|
<div class="flex-wrapper">
|
||||||
<div class="page-container">
|
<div class="page-container">
|
||||||
<div id="router-view" class="main-content">
|
<div id="router-view" class="main-content">
|
||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer-component></footer-component>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer-component></footer-component>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
@ -31,6 +31,7 @@ Route::get('/logout', 'Auth\LoginController@logout');
|
||||||
Route::group([ 'prefix' => 'dashboard' ], function() {
|
Route::group([ 'prefix' => 'dashboard' ], function() {
|
||||||
Route::get('/', 'DashboardController@getIndex');
|
Route::get('/', 'DashboardController@getIndex');
|
||||||
Route::get('/credits', 'DashboardController@getCredits');
|
Route::get('/credits', 'DashboardController@getCredits');
|
||||||
|
Route::get('/settings', 'DashboardController@getSettings');
|
||||||
Route::get('/view/{model}', 'DashboardController@getView');
|
Route::get('/view/{model}', 'DashboardController@getView');
|
||||||
Route::get('/edit/{model}', 'DashboardController@getEditList');
|
Route::get('/edit/{model}', 'DashboardController@getEditList');
|
||||||
Route::get('/edit/{model}/{id}', 'DashboardController@getEditItem');
|
Route::get('/edit/{model}/{id}', 'DashboardController@getEditItem');
|
||||||
|
@ -39,6 +40,7 @@ Route::group([ 'prefix' => 'dashboard' ], function() {
|
||||||
Route::post('/file-upload', 'DashboardController@postFileUpload');
|
Route::post('/file-upload', 'DashboardController@postFileUpload');
|
||||||
Route::post('/update', 'DashboardController@postUpdate');
|
Route::post('/update', 'DashboardController@postUpdate');
|
||||||
Route::post('/reorder', 'DashboardController@postReorder');
|
Route::post('/reorder', 'DashboardController@postReorder');
|
||||||
|
Route::post('/user-password', 'DashboardController@postUserPassword');
|
||||||
Route::delete('/delete', 'DashboardController@deleteDelete');
|
Route::delete('/delete', 'DashboardController@deleteDelete');
|
||||||
Route::delete('/image-delete', 'DashboardController@deleteImageDelete');
|
Route::delete('/image-delete', 'DashboardController@deleteImageDelete');
|
||||||
Route::delete('/file-delete', 'DashboardController@deleteFileDelete');
|
Route::delete('/file-delete', 'DashboardController@deleteFileDelete');
|
||||||
|
|
Loading…
Reference in a new issue