Skip to content

Commit a8217f3

Browse files
committed
Merge branch 'develop' into user-set-password
2 parents 35c70d7 + a619fc2 commit a8217f3

9 files changed

Lines changed: 801 additions & 707 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
2323

2424
### Added
2525
- Separated `BakeCommand` class into multiple methods to make it easier for sprinkle to add custom command to the `bake` command.
26+
- Allow null group assignment for users ([#867]; [#964])
2627

2728
### Fix
2829
- `bake` command return error if account sprinkle is not included ([#944])
@@ -31,6 +32,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
3132
### Changed
3233
- Account sprinkle now extend the Core `BakeCommand` class to add the `create-admin` to the general bake command. Any sprinkle already extending the Core `BakeCommand` might need adjustments.
3334
- Updated custom Eloquent relations (`belongsToManyThrough`, `morphToManyUnique`, `belongsToManyUnique`, `morphToManyUnique`, etc.) to support Laravel 5.8. See [The `belongsToMany` Method](https://laravel.com/docs/5.5/upgrade#upgrade-5.5.0).
35+
- Update to AdminLTE 2.3.11 ([#1014])
3436

3537
### Removed
3638
- Removed `belongsToManyConstrained` (deprecated in 4.1.6)
@@ -784,6 +786,7 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x
784786
[#838]: https://github.com/userfrosting/UserFrosting/issues/838
785787
[#853]: https://github.com/userfrosting/UserFrosting/issues/853
786788
[#854]: https://github.com/userfrosting/UserFrosting/issues/854
789+
[#867]: https://github.com/userfrosting/UserFrosting/issues/867
787790
[#869]: https://github.com/userfrosting/UserFrosting/issues/869
788791
[#872]: https://github.com/userfrosting/UserFrosting/issues/872
789792
[#881]: https://github.com/userfrosting/UserFrosting/issues/881
@@ -797,6 +800,7 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x
797800
[#953]: https://github.com/userfrosting/UserFrosting/issues/953
798801
[#958]: https://github.com/userfrosting/UserFrosting/issues/958
799802
[#963]: https://github.com/userfrosting/UserFrosting/issues/963
803+
[#964]: https://github.com/userfrosting/UserFrosting/issues/964
800804
[#965]: https://github.com/userfrosting/UserFrosting/issues/965
801805
[#968]: https://github.com/userfrosting/UserFrosting/issues/968
802806
[#976]: https://github.com/userfrosting/UserFrosting/issues/976
@@ -809,6 +813,7 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x
809813
[#993]: https://github.com/userfrosting/UserFrosting/issues/993
810814
[#998]: https://github.com/userfrosting/UserFrosting/issues/998
811815
[#1012]: https://github.com/userfrosting/UserFrosting/issues/1012
816+
[#1014]: https://github.com/userfrosting/UserFrosting/issues/1014
812817

813818
[v4.2.0]: https://github.com/userfrosting/UserFrosting/compare/v4.1.22...v4.2.0
814819
[v4.2.1]: https://github.com/userfrosting/UserFrosting/compare/v4.2.0...v.4.2.1
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
/*
4+
* UserFrosting (http://www.userfrosting.com)
5+
*
6+
* @link https://github.com/userfrosting/UserFrosting
7+
* @copyright Copyright (c) 2019 Alexander Weissman
8+
* @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License)
9+
*/
10+
11+
namespace UserFrosting\Sprinkle\Account\Database\Migrations\v430;
12+
13+
use Illuminate\Database\Schema\Blueprint;
14+
use UserFrosting\Sprinkle\Core\Database\Migration;
15+
16+
/**
17+
* Groups table migration
18+
* Changes `group_id` column properties to allow user to be created without a group.
19+
* Version 4.3.0.
20+
*
21+
* See https://laravel.com/docs/5.4/migrations#tables
22+
*
23+
* @author Amos Folz
24+
*/
25+
class UpdateUsersTable extends Migration
26+
{
27+
/**
28+
* {@inheritdoc}
29+
*/
30+
public static $dependencies = [
31+
'\UserFrosting\Sprinkle\Account\Database\Migrations\v400\GroupsTable',
32+
'\UserFrosting\Sprinkle\Account\Database\Migrations\v400\UsersTable',
33+
'\UserFrosting\Sprinkle\Account\Database\Migrations\v420\AddingForeignKeys',
34+
];
35+
36+
/**
37+
* {@inheritdoc}
38+
*/
39+
public function up()
40+
{
41+
if ($this->schema->hasTable('users')) {
42+
$this->schema->table('users', function (Blueprint $table) {
43+
$table->unsignedInteger('group_id')->default(null)->comment('The id of the user group.')->nullable()->change();
44+
});
45+
}
46+
}
47+
48+
/**
49+
* {@inheritdoc}
50+
*/
51+
public function down()
52+
{
53+
$this->schema->table('users', function (Blueprint $table) {
54+
$table->unsignedInteger('group_id')->default(1)->comment('The id of the user group.')->change();
55+
});
56+
}
57+
}

app/sprinkles/admin/assets/userfrosting/js/widgets/users.js

Lines changed: 47 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Set up the form in a modal after being successfully attached to the body.
77
*/
88
function attachUserForm() {
9-
$("body").on('renderSuccess.ufModal', function (data) {
9+
$("body").on('renderSuccess.ufModal', function(data) {
1010
var modal = $(this).ufModal('getModal');
1111
var form = modal.find('.js-form');
1212

@@ -15,14 +15,16 @@ function attachUserForm() {
1515
width: '100%'
1616
});
1717

18+
19+
1820
// Set up the form for submission
1921
form.ufForm({
2022
validator: page.validators
2123
}).on("submitSuccess.ufForm", function() {
2224
// Reload page on success
2325
window.location.reload();
2426
});
25-
27+
2628
toggleSetPasswordMode(modal, 'link');
2729

2830
// On submission, submit either the PUT request, or POST for a password reset, depending on the toggle state
@@ -47,14 +49,14 @@ function toggleSetPasswordMode(el, changePasswordMode) {
4749
if (validator) {
4850
//Iterate through named elements inside of the form, and mark them as error free
4951
el.find("input[type='password']").each(function() {
50-
validator.successList.push(this); //mark as error free
52+
validator.successList.push(this); //mark as error free
5153
});
52-
validator.resetForm();//remove error class on name elements and clear history
53-
validator.reset();//remove all error and success data
54+
validator.resetForm(); //remove error class on name elements and clear history
55+
validator.reset(); //remove all error and success data
5456
}
5557
el.find("input[type='password']").closest('.form-group')
56-
.removeClass('has-error has-success');
57-
el.find('.form-control-feedback').each(function () {
58+
.removeClass('has-error has-success');
59+
el.find('.form-control-feedback').each(function() {
5860
$(this).remove();
5961
});
6062
} else {
@@ -80,14 +82,14 @@ function toggleChangePasswordMode(el, userName, changePasswordMode) {
8082
if (validator) {
8183
//Iterate through named elements inside of the form, and mark them as error free
8284
el.find("input[type='password']").each(function() {
83-
validator.successList.push(this); //mark as error free
85+
validator.successList.push(this); //mark as error free
8486
});
85-
validator.resetForm();//remove error class on name elements and clear history
86-
validator.reset();//remove all error and success data
87+
validator.resetForm(); //remove error class on name elements and clear history
88+
validator.reset(); //remove all error and success data
8789
}
8890
el.find("input[type='password']").closest('.form-group')
89-
.removeClass('has-error has-success');
90-
el.find('.form-control-feedback').each(function () {
91+
.removeClass('has-error has-success');
92+
el.find('.form-control-feedback').each(function() {
9193
$(this).remove();
9294
});
9395
} else {
@@ -130,19 +132,19 @@ function updateUser(userName, fieldName, fieldValue) {
130132
return $.parseJSON(result);
131133
}
132134
} catch (e) {
133-
// statements to handle any exceptions
134-
console.log("Warning: Could not parse expected JSON response.");
135-
return {};
135+
// statements to handle any exceptions
136+
console.log("Warning: Could not parse expected JSON response.");
137+
return {};
136138
}
137139
}
138140
}
139-
}).fail(function (jqXHR) {
141+
}).fail(function(jqXHR) {
140142
// Error messages
141143
if (debugAjax && jqXHR.responseText) {
142144
document.write(jqXHR.responseText);
143145
document.close();
144146
} else {
145-
console.log("Error (" + jqXHR.status + "): " + jqXHR.responseText );
147+
console.log("Error (" + jqXHR.status + "): " + jqXHR.responseText);
146148

147149
// Display errors on failure
148150
// TODO: ufAlerts widget should have a 'destroy' method
@@ -151,12 +153,12 @@ function updateUser(userName, fieldName, fieldValue) {
151153
} else {
152154
$("#alerts-page").ufAlerts('clear');
153155
}
154-
156+
155157
$("#alerts-page").ufAlerts('fetch').ufAlerts('render');
156158
}
157159

158160
return jqXHR;
159-
}).done(function (response) {
161+
}).done(function(response) {
160162
window.location.reload();
161163
});
162164
}
@@ -166,8 +168,8 @@ function updateUser(userName, fieldName, fieldValue) {
166168
* @param {module:jQuery} el jQuery wrapped element to target.
167169
* @param {{delete_redirect: string}} options Options used to modify behaviour of button actions.
168170
*/
169-
function bindUserButtons(el, options) {
170-
if (!options) options = {};
171+
function bindUserButtons(el, options) {
172+
if (!options) options = {};
171173

172174
/**
173175
* Buttons that launch a modal dialog
@@ -200,38 +202,38 @@ function updateUser(userName, fieldName, fieldValue) {
200202
msgTarget: $("#alerts-page")
201203
});
202204

203-
$("body").on('renderSuccess.ufModal', function (data) {
205+
$("body").on('renderSuccess.ufModal', function(data) {
204206
var modal = $(this).ufModal('getModal');
205207
var form = modal.find('.js-form');
206208

207209
// Set up collection widget
208210
var roleWidget = modal.find('.js-form-roles');
209211
roleWidget.ufCollection({
210-
dropdown : {
212+
dropdown: {
211213
ajax: {
212-
url : site.uri.public + '/api/roles'
214+
url: site.uri.public + '/api/roles'
213215
},
214-
placeholder : "Select a role"
216+
placeholder: "Select a role"
215217
},
216218
dropdownTemplate: modal.find('#user-roles-select-option').html(),
217-
rowTemplate : modal.find('#user-roles-row').html()
219+
rowTemplate: modal.find('#user-roles-row').html()
218220
});
219221

220222
// Get current roles and add to widget
221223
$.getJSON(site.uri.public + '/api/users/u/' + userName + '/roles')
222-
.done(function (data) {
223-
$.each(data.rows, function (idx, role) {
224-
role.text = role.name;
225-
roleWidget.ufCollection('addRow', role);
224+
.done(function(data) {
225+
$.each(data.rows, function(idx, role) {
226+
role.text = role.name;
227+
roleWidget.ufCollection('addRow', role);
228+
});
226229
});
227-
});
228230

229231
// Set up form for submission
230232
form.ufForm()
231-
.on("submitSuccess.ufForm", function() {
232-
// Reload page on success
233-
window.location.reload();
234-
});
233+
.on("submitSuccess.ufForm", function() {
234+
// Reload page on success
235+
window.location.reload();
236+
});
235237
});
236238
});
237239

@@ -248,7 +250,7 @@ function updateUser(userName, fieldName, fieldValue) {
248250
msgTarget: $("#alerts-page")
249251
});
250252

251-
$("body").on('renderSuccess.ufModal', function () {
253+
$("body").on('renderSuccess.ufModal', function() {
252254
var modal = $(this).ufModal('getModal');
253255
var form = modal.find('.js-form');
254256

@@ -284,16 +286,16 @@ function updateUser(userName, fieldName, fieldValue) {
284286
msgTarget: $("#alerts-page")
285287
});
286288

287-
$("body").on('renderSuccess.ufModal', function () {
289+
$("body").on('renderSuccess.ufModal', function() {
288290
var modal = $(this).ufModal('getModal');
289291
var form = modal.find('.js-form');
290292

291293
form.ufForm()
292-
.on("submitSuccess.ufForm", function() {
293-
// Navigate or reload page on success
294-
if (options.delete_redirect) window.location.href = options.delete_redirect;
295-
else window.location.reload();
296-
});
294+
.on("submitSuccess.ufForm", function() {
295+
// Navigate or reload page on success
296+
if (options.delete_redirect) window.location.href = options.delete_redirect;
297+
else window.location.reload();
298+
});
297299
});
298300
});
299301

@@ -307,12 +309,12 @@ function updateUser(userName, fieldName, fieldValue) {
307309
updateUser(btn.data('user_name'), 'flag_verified', '1');
308310
});
309311

310-
el.find('.js-user-enable').click(function () {
312+
el.find('.js-user-enable').click(function() {
311313
var btn = $(this);
312314
updateUser(btn.data('user_name'), 'flag_enabled', '1');
313315
});
314316

315-
el.find('.js-user-disable').click(function () {
317+
el.find('.js-user-disable').click(function() {
316318
var btn = $(this);
317319
updateUser(btn.data('user_name'), 'flag_enabled', '0');
318320
});
@@ -330,4 +332,4 @@ function bindUserCreationButton(el) {
330332

331333
attachUserForm();
332334
});
333-
};
335+
};

app/sprinkles/admin/locale/en_US/messages.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
'MANAGE' => 'Manage group',
6060
'NAME' => 'Group name',
6161
'NAME_EXPLAIN' => 'Please enter a name for the group',
62+
'NONE' => 'No group',
6263
'NOT_EMPTY' => "You can't do that because there are still users associated with the group <strong>{{name}}</strong>.",
6364
'PAGE_DESCRIPTION' => 'A listing of the groups for your site. Provides management tools for editing and deleting groups.',
6465
'SUMMARY' => 'Group Summary',

app/sprinkles/admin/src/Controller/UserController.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,10 @@ public function updateInfo(Request $request, Response $response, $args)
12261226
return $response->withJson([], 400);
12271227
}
12281228

1229+
if (isset($data['group_id']) && $data['group_id'] == 0) {
1230+
$data['group_id'] = null;
1231+
}
1232+
12291233
// Begin transaction - DB will be rolled back if an exception occurs
12301234
Capsule::transaction(function () use ($data, $user, $currentUser) {
12311235
// Update the user and generate success messages

app/sprinkles/admin/templates/forms/user.html.twig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
<input type="text" class="form-control" name="theme" value="{{user.group.name}}" disabled>
2626
{% else %}
2727
<select id="input-group" class="form-control js-select2" name="group_id">
28+
<option value="0">{{translate('GROUP.NONE')}}</option>
29+
<option disabled="disabled">-----</option>
2830
{% for group in groups %}
2931
<option value="{{group.id}}" {% if (group.id == user.group_id) %}selected{% endif %}>{{group.name}}</option>
3032
{% endfor %}

app/sprinkles/admin/templates/pages/user.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@
9494
<i class="fa fa-fw fa-bolt fa-lg text-yellow" title="{{translate('UNACTIVATED')}}"></i>
9595
{% endif %}
9696
</div>
97-
<h4 class="text-muted text-center">{{user.user_name}}{% if 'group' not in fields.hidden %} • {{user.group.name}}{% endif %}</h4>
97+
<h4 class="text-muted text-center">{{user.user_name}}{% if 'group' not in fields.hidden and user.group.name is not null %} • {{user.group.name}}{% endif %}</h4>
9898

9999
{% if 'email' not in fields.hidden %}
100100
<hr>

0 commit comments

Comments
 (0)