Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4.x] Allowing adding a blueprint to user groups #6506

Merged
merged 40 commits into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
3e3bb91
Add ability to add a blueprint to user groups
ryanmitchell Aug 16, 2022
6ec6a5f
StyleCI
ryanmitchell Aug 16, 2022
2c21848
Fixes
ryanmitchell Aug 16, 2022
21c612b
Add data test
ryanmitchell Aug 16, 2022
79caab1
Blueprint test
ryanmitchell Aug 16, 2022
9c82cc9
Add to blueprints list
ryanmitchell Aug 16, 2022
6aef51a
Add to augmented data
ryanmitchell Aug 16, 2022
4bdf194
Make sure we save values in CP (oops)
ryanmitchell Aug 16, 2022
24617c5
Groups not User Groups
ryanmitchell Aug 16, 2022
15d98c2
Title and handle are required
ryanmitchell Aug 16, 2022
d3bff70
Remove tests
ryanmitchell Aug 17, 2022
9968cc5
Bring back tests to see which fails
ryanmitchell Aug 17, 2022
f6f1358
More test attempts
ryanmitchell Aug 17, 2022
914f479
Change to use Facade
ryanmitchell Aug 17, 2022
7b41052
More attempts to find cause
ryanmitchell Aug 17, 2022
bb8c5dc
More
ryanmitchell Aug 17, 2022
d0eadb3
More trying to find the cause
ryanmitchell Aug 17, 2022
85a7f16
Again
ryanmitchell Aug 17, 2022
236f850
Bring some more back
ryanmitchell Aug 17, 2022
d0f8c07
More
ryanmitchell Aug 17, 2022
dd6f8f3
More
ryanmitchell Aug 17, 2022
eedc7c8
More
ryanmitchell Aug 17, 2022
fedb350
Bring all tests back
ryanmitchell Aug 17, 2022
6105345
Don't need this data
ryanmitchell Aug 18, 2022
9fe1aea
Bump phpunit version in actions
ryanmitchell Aug 22, 2022
fcb6c99
Merge branch '3.3' into feature/add-data-to-user-groups
ryanmitchell Nov 16, 2022
57109c5
Bug from merge
ryanmitchell Nov 16, 2022
6ed8a39
Fix typo
ryanmitchell Nov 16, 2022
58976bf
Update UserGroupTest to handle new responses
ryanmitchell Nov 16, 2022
214fb1b
Merge branch '4.x' into feature/add-data-to-user-groups
jasonvarga Jun 16, 2023
e584b3d
adjust for 4.0 blueprints
jasonvarga Jun 16, 2023
460f722
Merge branch '4.x' into feature/add-data-to-user-groups
jasonvarga Jun 21, 2023
82cfd97
not necessary
jasonvarga Jun 21, 2023
0ff05b2
wip
jasonvarga Jun 21, 2023
ed7035c
margin, icon, labels
jasonvarga Jun 21, 2023
9e14af9
create form
jasonvarga Jun 21, 2023
e6889cb
wip
jasonvarga Jun 21, 2023
6b53db6
Remove handle field. Use ensureField methods. Use translations.
jasonvarga Jun 22, 2023
0b2fb8f
Only update handle if its there
jasonvarga Jun 22, 2023
2581e1c
assign roles
jasonvarga Jun 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
151 changes: 65 additions & 86 deletions resources/js/components/user-groups/PublishForm.vue
Original file line number Diff line number Diff line change
@@ -1,112 +1,87 @@
<template>

<div>
<header class="mb-6">
<breadcrumb :url="breadcrumbUrl" :title="__('User Groups')" />
<div class="flex items-center">
<h1 class="flex-1" v-text="title || __('Create Group')" />
<button type="submit" class="btn-primary" @click="save">{{ __('Save') }}</button>
</div>
</header>

<div class="card p-0 mb-6 publish-fields @container">

<form-group
:display="__('Title')"
handle="title"
:errors="errors.title"
:instructions="__('messages.user_groups_title_instructions')"
v-model="title"
:focus="true"
/>

<form-group
fieldtype="slug"
:display="__('Handle')"
handle="handle"
:instructions="__('messages.user_groups_handle_instructions')"
:errors="errors.title"
v-model="handle"
/>

<div class="text-xs text-red-500 p-6 pt-0" v-if="initialHandle && handle != initialHandle">
{{ __('messages.role_change_handle_warning') }}
</div>

<div class="form-group publish-field w-full" v-if="$permissions.has('assign roles')">
<div class="field-inner">
<label class="publish-field-label" v-text="__('Roles')" />
<div class="help-block -mt-2">
<p>{{ __('messages.user_groups_role_instructions') }}</p>
</div>
</div>
<publish-field-meta
:config="{ handle: 'roles', type: 'user_roles' }"
:initial-value="roles">
<div slot-scope="{ meta, value, loading }">
<relationship-fieldtype
v-if="!loading"
:config="{ handle: 'roles', type: 'user_roles', mode: 'select' }"
:value="value"
:meta="meta"
handle="roles"
@input="roles = $event" />
</div>
</publish-field-meta>
<small class="help-block text-red-500 mt-2 mb-0" v-if="errors.roles" v-text="errors.roles[0]" />
</div>

<div>

<header class="mb-3">
<breadcrumb :url="cp_url('user-groups')" :title="__('User Groups')" />
<div class="flex items-center">
<h1 class="flex-1" v-text="title" />
<dropdown-list class="mr-2" v-if="canEditBlueprint">
<dropdown-item :text="__('Edit Blueprint')" :redirect="actions.editBlueprint" />
</dropdown-list>

<button
class="btn-primary"
@click.prevent="save"
v-text="__('Save')" />

<slot name="action-buttons-right" />
</div>
</header>

<publish-container
v-if="fieldset"
ref="container"
:name="publishContainer"
:blueprint="fieldset"
:values="values"
:reference="initialReference"
:meta="meta"
:errors="errors"
@updated="values = $event"
>
<div slot-scope="{ container, setFieldValue, setFieldMeta }">
<publish-tabs
:enable-sidebar="false"
@updated="setFieldValue"
@meta-updated="setFieldMeta"
@focus="container.$emit('focus', $event)"
@blur="container.$emit('blur', $event)"
></publish-tabs>
</div>
</div>
</publish-container>

</div>
</template>


<script>
import HasHiddenFields from '../publish/HasHiddenFields';

export default {

mixins: [
HasHiddenFields,
],

props: {
publishContainer: String,
initialFieldset: Object,
initialValues: Object,
initialMeta: Object,
initialReference: String,
initialTitle: String,
initialHandle: String,
initialRoles: Array,
initialUsers: Array,
action: String,
actions: Object,
method: String,
creating: Boolean,
breadcrumbUrl: String,
canEditBlueprint: Boolean,
isCreating: Boolean,
},

data() {
return {
fieldset: _.clone(this.initialFieldset),
values: _.clone(this.initialValues),
meta: _.clone(this.initialMeta),
error: null,
errors: {},
title: this.initialTitle,
handle: this.initialHandle,
roles: this.initialRoles,
users: this.initialUsers,
}
},

watch: {
'title': function(display) {
if (this.creating) {
this.handle = this.$slugify(display, '_');
}
}
},

computed: {

hasErrors() {
return this.error || Object.keys(this.errors).length;
},

payload() {
return {
title: this.title,
handle: this.handle,
roles: this.roles,
users: this.users,
}
}

},
Expand All @@ -121,16 +96,20 @@ export default {
save() {
this.clearErrors();

this.$axios[this.method](this.action, this.payload).then(response => {
window.location = response.data.redirect;
this.$axios[this.method](this.actions.save, this.visibleValues).then(response => {
this.title = response.data.title;
this.$refs.container.saved();
if (this.isCreating) window.location = response.data.redirect;
this.$toast.success(__('Saved'));
this.$nextTick(() => this.$emit('saved', response));
}).catch(e => {
if (e.response && e.response.status === 422) {
const { message, errors } = e.response.data;
this.error = message;
this.errors = errors;
this.$toast.error(message);
} else {
this.$toast.error(__('Unable to save user group'));
this.$toast.error(__('Something went wrong'));
}
});
}
Expand Down
10 changes: 9 additions & 1 deletion resources/views/blueprints/index.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@
</div>
@endforeach

<h3 class="little-heading pl-0 mb-2">{{ __('Other') }}</h3>
<h3 class="little-heading pl-0 mb-2">{{ __('Users') }}</h3>
<div class="card p-0 mb-4">
<table class="data-table">
<tr>
Expand All @@ -166,6 +166,14 @@
</div>
</td>
</tr>
<tr>
<td>
<div class="flex items-center">
<div class="w-4 h-4 mr-4">@cp_svg('icons/light/user_groups')</div>
<a href="{{ cp_route('user-groups.blueprint.edit') }}">{{ __('Group') }}</a>
</div>
</td>
</tr>
</table>
</div>

Expand Down
21 changes: 21 additions & 0 deletions resources/views/usergroups/blueprints/edit.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@extends('statamic::layout')
@section('title', __('Edit Blueprint'))

@section('content')

@include('statamic::partials.breadcrumb', [
'url' => cp_route('user-groups.index'),
'title' => __('User Groups'),
])

<blueprint-builder
action="{{ cp_route('user-groups.blueprint.update') }}"
:initial-blueprint="{{ json_encode($blueprintVueObject) }}"
></blueprint-builder>

@include('statamic::partials.docs-callout', [
'topic' => __('Blueprints'),
'url' => Statamic::docsUrl('blueprints')
])

@endsection
12 changes: 7 additions & 5 deletions resources/views/usergroups/create.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
@section('content')

<user-group-publish-form
action="{{ cp_route('user-groups.store') }}"
breadcrumb-url="{{ cp_route('user-groups.index') }}"
:actions="{{ json_encode($actions) }}"
method="post"
:creating="true"
v-cloak

publish-container="base"
:initial-title="__('Create Group')"
:initial-fieldset="{{ json_encode($blueprint) }}"
:initial-values="{{ json_encode($values) }}"
:initial-meta="{{ json_encode($meta) }}"
:is-creating="true"
></user-group-publish-form>

@endsection
18 changes: 8 additions & 10 deletions resources/views/usergroups/edit.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@

@section('content')

<collection-edit-form>
</collection-edit-form>

<user-group-publish-form
action="{{ cp_route('user-groups.update', $group->handle()) }}"
:actions="{{ json_encode($actions) }}"
method="patch"
initial-title="{{ $group->title() }}"
initial-handle="{{ $group->handle() }}"
:initial-roles="{{ json_encode($roles) }}"
:creating="false"
breadcrumb-url="{{ cp_route('user-groups.show', $group->handle()) }}"
v-cloak
publish-container="base"
initial-title="{{ $title }}"
initial-reference="{{ $reference }}"
:initial-fieldset="{{ json_encode($blueprint) }}"
:initial-values="{{ json_encode($values) }}"
:initial-meta="{{ json_encode($meta) }}"
:can-edit-blueprint="{{ Statamic\Support\Str::bool($user->can('configure fields')) }}"
></user-group-publish-form>

@endsection
3 changes: 3 additions & 0 deletions routes/cp.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
use Statamic\Http\Controllers\CP\Users\RolesController;
use Statamic\Http\Controllers\CP\Users\UserActionController;
use Statamic\Http\Controllers\CP\Users\UserBlueprintController;
use Statamic\Http\Controllers\CP\Users\UserGroupBlueprintController;
use Statamic\Http\Controllers\CP\Users\UserGroupsController;
use Statamic\Http\Controllers\CP\Users\UsersController;
use Statamic\Http\Controllers\CP\Users\UserWizardController;
Expand Down Expand Up @@ -268,6 +269,8 @@
Route::resource('users', UsersController::class);
Route::patch('users/{user}/password', [PasswordController::class, 'update'])->name('users.password.update');
Route::get('account', AccountController::class)->name('account');
Route::get('user-groups/blueprint', [UserGroupBlueprintController::class, 'edit'])->name('user-groups.blueprint.edit');
Route::patch('user-groups/blueprint', [UserGroupBlueprintController::class, 'update'])->name('user-groups.blueprint.update');
Route::resource('user-groups', UserGroupsController::class);
Route::resource('roles', RolesController::class);

Expand Down
7 changes: 4 additions & 3 deletions src/Auth/File/UserGroupRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ public function all(): Collection
return $this->groups = $this->raw()->map(function ($data, $handle) {
$group = Facades\UserGroup::make()
->handle($handle)
->title(array_get($data, 'title'));
->title(array_get($data, 'title'))
->data($data);

foreach ($data['roles'] ?? [] as $role) {
if ($role = Facades\Role::find($role)) {
Expand All @@ -46,10 +47,10 @@ public function save(UserGroupContract $group)
{
$groups = $this->raw();

$groups->put($group->handle(), array_filter([
$groups->put($group->handle(), array_filter(array_merge($group->data()->all(), [
'title' => $group->title(),
'roles' => $group->roles()->map->handle()->values()->all(),
]));
])));

if ($group->handle() !== $group->originalHandle()) {
$groups->forget($group->originalHandle());
Expand Down
21 changes: 18 additions & 3 deletions src/Auth/UserGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Statamic\Contracts\Auth\Role;
use Statamic\Contracts\Auth\UserGroup as UserGroupContract;
use Statamic\Contracts\Data\Augmentable;
use Statamic\Data\ContainsData;
use Statamic\Data\HasAugmentedData;
use Statamic\Events\UserGroupDeleted;
use Statamic\Events\UserGroupSaved;
Expand All @@ -20,11 +21,12 @@ abstract class UserGroup implements UserGroupContract, Augmentable, ArrayAccess,
protected $originalHandle;
protected $roles;

use HasAugmentedData;
use ContainsData, HasAugmentedData;

public function __construct()
{
$this->roles = collect();
$this->data = collect();
}

public function title(string $title = null)
Expand Down Expand Up @@ -161,6 +163,11 @@ public function editUrl()
return cp_route('user-groups.edit', $this->handle());
}

public function updateUrl()
{
return cp_route('user-groups.update', $this->handle());
}

public function deleteUrl()
{
return cp_route('user-groups.destroy', $this->handle());
Expand All @@ -173,9 +180,17 @@ public static function __callStatic($method, $parameters)

public function augmentedArrayData()
{
return [
return $this->data()->merge([
'title' => $this->title(),
'handle' => $this->handle(),
];
])->all();
}

/**
* @return \Statamic\Fields\Blueprint
*/
public function blueprint()
{
return Facades\UserGroup::blueprint();
}
}