diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index e02dbd4..678be9d 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -392,6 +392,24 @@ class DashboardController extends Controller { } } + // User Profile Update + public function postUserProfileUpdate(Request $request) + { + $this->validate($request, [ + 'name' => 'required|string|max:255' + ]); + + $user = User::find(Auth::id()); + $user->name = $request['name']; + $user->website = $request['website']; + $user->facebook = $request['facebook']; + $user->soundcloud = $request['soundcloud']; + $user->instagram = $request['instagram']; + $user->twitter = $request['twitter']; + $user->save(); + return 'success'; + } + // User Profile Image Upload public function postUserProfileImageUpload(Request $request) { diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php index 07f6139..3c4b267 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -15,9 +15,15 @@ class CreateUsersTable extends Migration { Schema::create('users', function(Blueprint $table) { $table->increments('id'); - $table->string('name'); $table->string('email')->unique(); + $table->string('name'); + $table->string('website')->nullable(); + $table->string('facebook')->nullable(); + $table->string('twitter')->nullable(); + $table->string('instagram')->nullable(); + $table->string('soundcloud')->nullable(); $table->string('password'); + $table->string('api_token', 60)->unique(); $table->rememberToken(); $table->timestamps(); }); diff --git a/database/migrations/2017_11_21_193450_add_api_token_to_users_table.php b/database/migrations/2017_11_21_193450_add_api_token_to_users_table.php deleted file mode 100644 index 7655086..0000000 --- a/database/migrations/2017_11_21_193450_add_api_token_to_users_table.php +++ /dev/null @@ -1,32 +0,0 @@ -string('api_token', 60)->unique(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::table('users', function(Blueprint $table) { - $table->dropColumn('api_token'); - }); - } -} diff --git a/public/img/dashboard/star-bg.svg b/public/img/dashboard/star-bg.svg new file mode 100644 index 0000000..dca0cdf --- /dev/null +++ b/public/img/dashboard/star-bg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/assets/js/dashboard.js b/resources/assets/js/dashboard.js index c2c99aa..d5c2f19 100644 --- a/resources/assets/js/dashboard.js +++ b/resources/assets/js/dashboard.js @@ -703,8 +703,82 @@ function userProfileImageInit() { }); } -function userPasswordInit() { - const $form = $("#user-password"), +function userProfileUpdateInit() { + const $form = $("#user-profile-update"), + $submit = $form.find(".submit-button"), + $inputs = $form.find("input"), + $name = $("#name"), + $website = $("#website"), + $facebook = $("#facebook"), + $soundcloud = $("#soundcloud"), + $instagram = $("#instagram"), + $twitter = $("#twitter"), + $token = $("#token"); + + let formData = {}, + submitting = false; + + const getFormData = function() { + formData = { + name: $name.val(), + website: $website.val(), + facebook: $facebook.val(), + soundcloud: $soundcloud.val(), + instagram: $instagram.val(), + twitter: $twitter.val(), + _token: $token.val() + }; + }; + + // remove the error class from an input and enable submit when its value changes + $inputs.on("input change", function() { + $submit.removeClass("no-input"); + $(this).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(); + + // submit the update + $.ajax({ + type: "POST", + url: "/dashboard/user/profile-update", + data: formData + }).always(function(response) { + hideLoadingModal(); + submitting = false; + + if (response === "success") { + $submit.addClass("no-input"); + showAlert("User profile updated successfully"); + } else { + // add the error class to fields that haven't been filled correctly + for (let errorName in response.responseJSON.errors) { + if ($form.find(`[name='${errorName}']`).length) { + $form.find(`[name='${errorName}']`).addClass("error"); + } + } + + showAlert("Error updating user profile"); + } + }); + } + }); +} + +function userPasswordUpdateInit() { + const $form = $("#user-password-update"), $submit = $form.find(".submit-button"), $inputs = $form.find("input"), $oldpass = $("#oldpass"), @@ -806,7 +880,11 @@ $(document).ready(function() { userProfileImageInit(); } - if ($("#user-password").length) { - userPasswordInit(); + if ($("#user-profile-update").length) { + userProfileUpdateInit(); + } + + if ($("#user-password-update").length) { + userPasswordUpdateInit(); } }); diff --git a/resources/assets/sass/dashboard.scss b/resources/assets/sass/dashboard.scss index acc0a82..dc5bf0c 100644 --- a/resources/assets/sass/dashboard.scss +++ b/resources/assets/sass/dashboard.scss @@ -39,6 +39,7 @@ body { } .site-content { + position: relative; display: flex; min-height: 100vh; flex-direction: column; @@ -48,6 +49,33 @@ body { } } +.dashboard-background { + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + background-image: url("/img/dashboard/star-bg.svg"); + background-position: center top; + background-size: 65px auto; + background-repeat: repeat; + + &:after { + content: ""; + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + background-color: fade-out(#fff, 0.02); + } +} + +.navbar, .dashboard-footer { + z-index: 10; + position: relative; +} + .navbar { margin-bottom: $grid-gutter-width; border: 0; @@ -652,223 +680,283 @@ body { } } -.edit-item { - $label-height: 30px; +form { margin-top: 10px; - .CodeMirror { - height: 300px; - padding: 5px; - - &-code { - margin-bottom: 10px; - } - } - - .picker__holder { - overflow-y: hidden; - - .picker__button--today { - white-space: nowrap; - } - - .picker__select--year, .picker__select--month, .picker__month, .picker__day, .picker__weekday, .picker__footer { - @include media-breakpoint-down(sm) { - font-size: 16px; - } - } - - .picker__select--year, .picker__select--month { - width: auto; - height: 1.5em; - padding: 0px; - } - } - - label { - min-height: $label-height; - line-height: $label-height; - - @include media-breakpoint-up(md) { - margin-bottom: 0px; - } - } - - .text-display, .mkd-editor-container, input, select { + .form-title { + @include font-sans-semibold; + margin-top: 0px; margin-bottom: 15px; - } - - input { - display: block; - width: 100%; - - &:not([type="file"]) { - padding: 5px 8px; - border: 1px solid darken($c-dashboard-light, 10%); - border-radius: 2px; - transition: border-color 150ms; - - &.error { - border-color: $c-dashboard-error; - } - } - - &[type="file"] { - height: $label-height; - font-size: 14px; - } - - &.date-picker { - cursor: pointer; - } - } - - .current-image { - margin-bottom: 15px; - display: block; - width: 125px; - max-width: 100%; - } - - .edit-button { - margin-bottom: ($grid-gutter-width / 2); - display: inline-block; - padding: 5px 10px; - border-radius: 5px; + font-size: 14px; text-transform: uppercase; - transition: background-color 150ms; - cursor: pointer; - - &:hover, &:focus { - text-decoration: none; - } - - &.view { - border: 1px solid darken($c-dashboard-dark, 5%); - background-color: $c-dashboard-dark; - color: $c-text-light; - - &:hover { - background-color: lighten($c-dashboard-dark, 5%); - } - } - - &.delete { - border: 1px solid darken($c-dashboard-delete, 5%); - background-color: $c-dashboard-delete; - color: $c-text-light; - - &:hover { - background-color: lighten($c-dashboard-delete, 5%); - } - } } - .back-button { - float: left; - } + &.edit-item { + $label-height: 30px; - .submit-button { - float: right; - transition: opacity 150ms; + .CodeMirror { + height: 300px; + padding: 5px; - &.no-input { - opacity: 0.65; - pointer-events: none; - } - } - - .back-button, .submit-button { - margin: 20px 15px 15px 15px; - - @include media-breakpoint-down(sm) { - float: none; - width: calc(100% - 30px); - - &:first-child { - margin-top: 20px; - margin-bottom: 5px; - } - - &:last-child { - margin-top: 5px; - margin-bottom: 20px; + &-code { + margin-bottom: 10px; } } - &.no-horizontal-margins { - margin-right: 0px; - margin-left: 0px; + .picker__holder { + overflow-y: hidden; - @include media-breakpoint-down(sm) { - width: 100%; + .picker__button--today { + white-space: nowrap; + } + + .picker__select--year, .picker__select--month, .picker__month, .picker__day, .picker__weekday, .picker__footer { + @include media-breakpoint-down(sm) { + font-size: 16px; + } + } + + .picker__select--year, .picker__select--month { + width: auto; + height: 1.5em; + padding: 0px; } } - } - &.user-profile-image { - display: block; - width: 100%; - max-width: 150px; + label { + min-height: $label-height; + line-height: $label-height; - @include media-breakpoint-down(sm) { - margin: $grid-gutter-width auto; + @include media-breakpoint-up(md) { + margin-bottom: 0px; + } } - .image-display { - @include aspect-ratio(1, 1); - position: relative; + .text-display, .mkd-editor-container, input, select { + margin-bottom: 15px; + } + + input { + display: block; width: 100%; - border: 1px solid darken($c-dashboard-light, 10%); - border-radius: 3px; - background-position: center center; - background-size: cover; - background-repeat: no-repeat; - } - .image-buttons { - margin-top: 20px; - display: flex; - justify-content: space-around; + &:not([type="file"]) { + padding: 5px 8px; + border: 1px solid darken($c-dashboard-light, 10%); + border-radius: 2px; + transition: border-color 150ms; - input { - display: none; + &.error { + border-color: $c-dashboard-error; + } } - .image-upload-button, .image-delete-button { - display: block; - width: 40px; - height: 40px; - min-height: 0; - border: 1px solid darken($c-dashboard-light, 14%); - border-radius: 3px; - background-color: darken($c-dashboard-light, 10%); - background-position: center center; - background-size: 50% auto; - background-repeat: no-repeat; - font-size: 0px; - line-height: 1; + &[type="file"] { + height: $label-height; + font-size: 14px; + } + + &.date-picker { cursor: pointer; + } + } + + .current-image { + margin-bottom: 15px; + display: block; + width: 125px; + max-width: 100%; + } + + .edit-button { + margin-bottom: ($grid-gutter-width / 2); + display: inline-block; + padding: 5px 10px; + border-radius: 5px; + text-transform: uppercase; + transition: background-color 150ms; + cursor: pointer; + + &:hover, &:focus { + text-decoration: none; + } + + &.view { + border: 1px solid darken($c-dashboard-dark, 5%); + background-color: $c-dashboard-dark; + color: $c-text-light; &:hover { - background-color: darken($c-dashboard-light, 7%); + background-color: lighten($c-dashboard-dark, 5%); } } - .image-upload-button { - background-image: url("/img/dashboard/icons/upload.svg"); - transition: background-color 150ms; + &.delete { + border: 1px solid darken($c-dashboard-delete, 5%); + background-color: $c-dashboard-delete; + color: $c-text-light; + + &:hover { + background-color: lighten($c-dashboard-delete, 5%); + } + } + } + + .back-button { + float: left; + } + + .submit-button { + float: right; + transition: opacity 150ms; + + &.no-input { + opacity: 0.65; + pointer-events: none; + } + } + + .back-button, .submit-button { + margin: 20px 15px 15px 15px; + + @include media-breakpoint-down(sm) { + float: none; + width: calc(100% - 30px); + + &:first-child { + margin-top: 20px; + margin-bottom: 5px; + } + + &:last-child { + margin-top: 5px; + margin-bottom: 20px; + } + } + } + } +} + +.dashboard-settings-container { + @include media-breakpoint-up(lg) { + display: flex; + flex-direction: row; + } + + form { + &.user-profile-image { + display: block; + width: 100%; + max-width: 150px; + + @include media-breakpoint-down(md) { + margin: $grid-gutter-width auto; } - .image-delete-button { - background-image: url("/img/dashboard/icons/trash-alt.svg"); - opacity: 1; - transition: background-color 150ms, opacity 150ms; + @include media-breakpoint-up(lg) { + flex-shrink: 0; + } - &.inactive { - opacity: 0.35; - pointer-events: none; + .image-display { + @include aspect-ratio(1, 1); + position: relative; + width: 100%; + border: 1px solid darken($c-dashboard-light, 10%); + border-radius: 3px; + background-position: center center; + background-size: cover; + background-repeat: no-repeat; + } + + .image-buttons { + margin-top: 20px; + display: flex; + justify-content: space-around; + + input { + display: none; } + + .image-upload-button, .image-delete-button { + display: block; + width: 40px; + height: 40px; + min-height: 0; + border: 1px solid darken($c-dashboard-light, 14%); + border-radius: 3px; + background-color: darken($c-dashboard-light, 10%); + background-position: center center; + background-size: 50% auto; + background-repeat: no-repeat; + font-size: 0px; + line-height: 1; + cursor: pointer; + + &:hover { + background-color: darken($c-dashboard-light, 7%); + } + } + + .image-upload-button { + background-image: url("/img/dashboard/icons/upload.svg"); + transition: background-color 150ms; + } + + .image-delete-button { + background-image: url("/img/dashboard/icons/trash-alt.svg"); + opacity: 1; + transition: background-color 150ms, opacity 150ms; + + &.inactive { + opacity: 0.35; + pointer-events: none; + } + } + } + } + + &.user-profile-update { + @include media-breakpoint-down(md) { + border-top: 1px solid darken($c-dashboard-light, 10%); + border-bottom: 1px solid darken($c-dashboard-light, 10%); + } + + @include media-breakpoint-up(lg) { + margin-right: $grid-gutter-width; + margin-left: $grid-gutter-width; + width: 100%; + padding: 0px $grid-gutter-width; + flex-grow: 1; + border-right: 1px solid darken($c-dashboard-light, 10%); + border-left: 1px solid darken($c-dashboard-light, 10%); + } + } + + &.user-password-update { + @include media-breakpoint-up(lg) { + width: 225px; + flex-shrink: 0; + } + } + + .form-title { + @include media-breakpoint-down(md) { + margin-top: 25px; + margin-bottom: 20px; + text-align: center; + } + } + + .submit-button { + @include media-breakpoint-down(sm) { + margin-right: auto; + margin-left: auto; + width: 100%; + } + + @include media-breakpoint-up(md) { + float: none; + margin: ($grid-gutter-width / 2) 0px; } } } diff --git a/resources/views/dashboard/pages/settings.blade.php b/resources/views/dashboard/pages/settings.blade.php index c4ae57d..3b6843a 100644 --- a/resources/views/dashboard/pages/settings.blade.php +++ b/resources/views/dashboard/pages/settings.blade.php @@ -7,32 +7,75 @@
-
-
diff --git a/resources/views/templates/dashboard.blade.php b/resources/views/templates/dashboard.blade.php index 38dd14c..b917375 100644 --- a/resources/views/templates/dashboard.blade.php +++ b/resources/views/templates/dashboard.blade.php @@ -8,6 +8,7 @@ @endsection @section('page-top') +
@include('dashboard.sections.nav') @endsection diff --git a/routes/web.php b/routes/web.php index 2e2a1f7..468e1e6 100644 --- a/routes/web.php +++ b/routes/web.php @@ -46,6 +46,7 @@ Route::group([ 'prefix' => 'dashboard' ], function() { // Dashboard Settings Route::get('/settings', 'DashboardController@getSettings'); Route::post('/user/password-update', 'DashboardController@postUserPasswordUpdate'); + Route::post('/user/profile-update', 'DashboardController@postUserProfileUpdate'); Route::post('/user/profile-image-upload', 'DashboardController@postUserProfileImageUpload'); Route::delete('/user/profile-image-delete', 'DashboardController@deleteUserProfileImageDelete'); diff --git a/traditional-bootstrap/routes/web.php b/traditional-bootstrap/routes/web.php index 179f009..e1c1173 100644 --- a/traditional-bootstrap/routes/web.php +++ b/traditional-bootstrap/routes/web.php @@ -29,19 +29,29 @@ Route::get('/logout', 'Auth\LoginController@logout'); */ Route::group([ 'prefix' => 'dashboard' ], function() { + // Dashboard CMS Route::get('/', 'DashboardController@getIndex'); - Route::get('/credits', 'DashboardController@getCredits'); Route::get('/view/{model}', 'DashboardController@getView'); Route::get('/edit/{model}', 'DashboardController@getEditList'); Route::get('/edit/{model}/{id}', 'DashboardController@getEditItem'); Route::get('/export/{model}', 'DashboardController@getExport'); + Route::post('/reorder', 'DashboardController@postReorder'); + Route::post('/update', 'DashboardController@postUpdate'); Route::post('/image-upload', 'DashboardController@postImageUpload'); Route::post('/file-upload', 'DashboardController@postFileUpload'); - Route::post('/update', 'DashboardController@postUpdate'); - Route::post('/reorder', 'DashboardController@postReorder'); Route::delete('/delete', 'DashboardController@deleteDelete'); Route::delete('/image-delete', 'DashboardController@deleteImageDelete'); Route::delete('/file-delete', 'DashboardController@deleteFileDelete'); + + // Dashboard Settings + Route::get('/settings', 'DashboardController@getSettings'); + Route::post('/user/password-update', 'DashboardController@postUserPasswordUpdate'); + Route::post('/user/profile-update', 'DashboardController@postUserProfileUpdate'); + Route::post('/user/profile-image-upload', 'DashboardController@postUserProfileImageUpload'); + Route::delete('/user/profile-image-delete', 'DashboardController@deleteUserProfileImageDelete'); + + // Credits Page + Route::get('/credits', 'DashboardController@getCredits'); }); /*