Skip to content

Commit ff6542e

Browse files
jaygeorgejasonvarga
authored andcommitted
Use globals Sites UI on collection and taxonomy configure
Reuse enable switches and site groups without origin chains, and keep storing a flat list of site handles.
1 parent 420a92a commit ff6542e

8 files changed

Lines changed: 173 additions & 17 deletions

File tree

lang/en/validation.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@
174174
'email_available' => 'A user with this email already exists.',
175175
'fieldset_imported_recursively' => 'Fieldset :handle is being imported recursively.',
176176
'one_site_without_origin' => 'At least one site must not have an origin.',
177+
'at_least_one_site_enabled' => 'At least one site must be enabled.',
177178
'options_require_keys' => 'All options must have keys.',
178179
'origin_cannot_be_disabled' => 'Cannot select a disabled origin.',
179180
'parent_cannot_be_itself' => 'Cannot be its own parent.',

resources/js/components/collections/OneOrManySitesField.vue

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,20 @@ export default {
6060
},
6161
6262
sites() {
63-
if (!this.publishContainer.values.value.sites) return [];
63+
const sites = this.publishContainer.values.value.sites;
6464
65-
return this.publishContainer.values.value.sites.map((handle, i) => {
65+
if (!sites?.length) return [];
66+
67+
if (typeof sites[0] === 'object') {
68+
return sites
69+
.filter((site) => site.enabled)
70+
.map((site) => ({
71+
handle: site.handle,
72+
name: site.name,
73+
}));
74+
}
75+
76+
return sites.map((handle, i) => {
6677
return {
6778
handle,
6879
name: this.publishContainer.meta.value.sites.data[i].title,

resources/js/components/globals/Sites.vue

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<template>
22
<div class="flex flex-col gap-3">
3-
<div class="flex flex-wrap items-center gap-3 rounded-xl border border-gray-200 bg-gray-50 px-3 pr-2 py-2 dark:border-gray-700 dark:bg-gray-800">
3+
<div
4+
v-if="showOrigins"
5+
class="flex flex-wrap items-center gap-3 rounded-xl border border-gray-200 bg-gray-50 px-3 pr-2 py-2 dark:border-gray-700 dark:bg-gray-800"
6+
>
47
<Checkbox
58
size="sm"
69
solo
@@ -53,15 +56,15 @@
5356
<table class="grid-table">
5457
<thead>
5558
<tr>
56-
<th scope="col" class="checkbox-column w-8">
59+
<th v-if="showOrigins" scope="col" class="checkbox-column w-8">
5760
<span class="sr-only">{{ __('Select') }}</span>
5861
</th>
5962
<th scope="col">
6063
<div class="flex items-center justify-between">
6164
{{ __('Site') }}
6265
</div>
6366
</th>
64-
<th scope="col">
67+
<th v-if="showOrigins" scope="col">
6568
<div class="flex items-center justify-between">
6669
{{ __('Origin') }}
6770
</div>
@@ -71,9 +74,10 @@
7174
<tbody>
7275
<template v-for="group in siteGroups" :key="group.key">
7376
<tr v-if="hasNamedGroups">
74-
<td colspan="3" class="sticky top-[calc(--spacing(7)+1px)] z-(--z-index-above) bg-gray-50 py-2! dark:bg-gray-800">
77+
<td :colspan="columnCount" class="sticky top-[calc(--spacing(7)+1px)] z-(--z-index-above) bg-gray-50 py-2! dark:bg-gray-800">
7578
<div class="flex items-center gap-4 ps-1!">
7679
<Checkbox
80+
v-if="showOrigins"
7781
size="sm"
7882
solo
7983
:model-value="isGroupSelected(group)"
@@ -90,7 +94,7 @@
9094
</td>
9195
</tr>
9296
<tr v-for="site in group.items" :key="site.handle">
93-
<td class="checkbox-column ps-3!">
97+
<td v-if="showOrigins" class="checkbox-column ps-3!">
9498
<Checkbox
9599
size="sm"
96100
class="pt-2.5"
@@ -106,7 +110,7 @@
106110
<Heading :text="__(site.name)" />
107111
</div>
108112
</td>
109-
<td class="grid-cell">
113+
<td v-if="showOrigins" class="grid-cell">
110114
<Select
111115
class="w-full"
112116
:options="siteOriginOptions(site)"
@@ -180,6 +184,14 @@ export default {
180184
},
181185
182186
computed: {
187+
showOrigins() {
188+
return this.config.origins !== false;
189+
},
190+
191+
columnCount() {
192+
return this.showOrigins ? 3 : 1;
193+
},
194+
183195
hasNamedGroups() {
184196
return hasNamedSiteGroups(this.sites);
185197
},

src/Fieldtypes/GlobalSetSites.php

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,45 @@ class GlobalSetSites extends Fieldtype
1111
{
1212
protected $selectable = false;
1313

14-
public function rules(): array
14+
protected function configFieldItems(): array
1515
{
1616
return [
17-
$this->cannotAllHaveOriginsRule(),
18-
$this->originsMustBeEnabledRule(),
17+
'origins' => [
18+
'display' => __('Origins'),
19+
'type' => 'toggle',
20+
'default' => true,
21+
],
22+
];
23+
}
24+
25+
public function rules(): array
26+
{
27+
$rules = [
28+
$this->atLeastOneSiteEnabledRule(),
1929
];
30+
31+
if ($this->config('origins', true)) {
32+
$rules[] = $this->cannotAllHaveOriginsRule();
33+
$rules[] = $this->originsMustBeEnabledRule();
34+
}
35+
36+
return $rules;
37+
}
38+
39+
private function atLeastOneSiteEnabledRule()
40+
{
41+
return new class implements ValidationRule
42+
{
43+
public function passes($attribute, $value)
44+
{
45+
return collect($value)->filter->enabled->isNotEmpty();
46+
}
47+
48+
public function message()
49+
{
50+
return __('statamic::validation.at_least_one_site_enabled');
51+
}
52+
};
2053
}
2154

2255
private function cannotAllHaveOriginsRule()

src/Http/Controllers/CP/Collections/CollectionsController.php

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,18 @@ public function edit($collection)
258258
'default_publish_state' => $collection->defaultPublishState(),
259259
'template' => $collection->template(),
260260
'layout' => $collection->layout(),
261-
'sites' => $collection->sites()->all(),
261+
'sites' => Site::multiEnabled()
262+
? Site::all()->map(function ($site) use ($collection) {
263+
return [
264+
'name' => $site->name(),
265+
'handle' => $site->handle(),
266+
'group' => $site->group(),
267+
'group_handle' => $site->groupHandle(),
268+
'enabled' => $collection->sites()->contains($site->handle()),
269+
'origin' => null,
270+
];
271+
})->values()->all()
272+
: $collection->sites()->all(),
262273
'propagate' => $collection->propagate(),
263274
'routes' => $collection->routes()->unique()->count() === 1
264275
? $collection->routes()->first()
@@ -343,6 +354,14 @@ public function update(Request $request, $collection)
343354
->previewTargets($values['preview_targets']);
344355

345356
if ($sites = Arr::get($values, 'sites')) {
357+
if (Site::multiEnabled()) {
358+
$sites = collect($sites)
359+
->filter(fn ($site) => $site['enabled'] ?? false)
360+
->map(fn ($site) => $site['handle'])
361+
->values()
362+
->all();
363+
}
364+
346365
$collection
347366
->sites($sites)
348367
->originBehavior($values['origin_behavior']);
@@ -598,8 +617,8 @@ protected function editFormBlueprint($collection)
598617
'display' => __('Localizations'),
599618
'fields' => [
600619
'sites' => [
601-
'type' => 'sites',
602-
'mode' => 'select',
620+
'type' => 'global_set_sites',
621+
'origins' => false,
603622
'required' => true,
604623
],
605624
'propagate' => [

src/Http/Controllers/CP/Taxonomies/TaxonomiesController.php

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,18 @@ public function edit($taxonomy)
156156
'title' => $taxonomy->title(),
157157
'blueprints' => $taxonomy->termBlueprints()->map->handle()->all(),
158158
'collections' => $taxonomy->collections()->map->handle()->all(),
159-
'sites' => $taxonomy->sites()->all(),
159+
'sites' => Site::multiEnabled()
160+
? Site::all()->map(function ($site) use ($taxonomy) {
161+
return [
162+
'name' => $site->name(),
163+
'handle' => $site->handle(),
164+
'group' => $site->group(),
165+
'group_handle' => $site->groupHandle(),
166+
'enabled' => $taxonomy->sites()->contains($site->handle()),
167+
'origin' => null,
168+
];
169+
})->values()->all()
170+
: $taxonomy->sites()->all(),
160171
'preview_targets' => $taxonomy->basePreviewTargets(),
161172
'term_template' => $taxonomy->hasCustomTermTemplate() ? $taxonomy->termTemplate() : null,
162173
'template' => $taxonomy->hasCustomTemplate() ? $taxonomy->template() : null,
@@ -190,6 +201,14 @@ public function update(Request $request, $taxonomy)
190201
->layout($values['layout'] ?? null);
191202

192203
if ($sites = Arr::get($values, 'sites')) {
204+
if (Site::multiEnabled()) {
205+
$sites = collect($sites)
206+
->filter(fn ($site) => $site['enabled'] ?? false)
207+
->map(fn ($site) => $site['handle'])
208+
->values()
209+
->all();
210+
}
211+
193212
$taxonomy->sites($sites);
194213
}
195214

@@ -290,8 +309,8 @@ protected function editFormBlueprint($taxonomy)
290309
'display' => __('Localizations'),
291310
'fields' => [
292311
'sites' => [
293-
'type' => 'sites',
294-
'mode' => 'select',
312+
'type' => 'global_set_sites',
313+
'origins' => false,
295314
'required' => true,
296315
],
297316
],

tests/Feature/Collections/UpdateCollectionTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,40 @@ public function settings_links_to_true_will_also_create_the_default_blueprint_if
153153
$this->assertEquals(['test', 'link'], $blueprints->map->handle()->values()->all());
154154
}
155155

156+
#[Test]
157+
public function it_updates_collection_sites_from_enabled_rows_and_ignores_origins()
158+
{
159+
$this->setSites([
160+
'en' => ['name' => 'English', 'locale' => 'en_US', 'url' => 'http://test.com/'],
161+
'fr' => ['name' => 'French', 'locale' => 'fr_FR', 'url' => 'http://fr.test.com/'],
162+
'de' => ['name' => 'German', 'locale' => 'de_DE', 'url' => 'http://de.test.com/'],
163+
]);
164+
165+
$collection = Collection::make('test')->sites(['en', 'fr'])->save();
166+
167+
$this
168+
->actingAs($this->userWithPermission())
169+
->update($collection, [
170+
'sites' => [
171+
['name' => 'English', 'handle' => 'en', 'enabled' => true, 'origin' => null],
172+
['name' => 'French', 'handle' => 'fr', 'enabled' => false, 'origin' => 'en'],
173+
['name' => 'German', 'handle' => 'de', 'enabled' => true, 'origin' => 'en'],
174+
],
175+
'origin_behavior' => 'root',
176+
'propagate' => true,
177+
'structured' => false,
178+
'require_slugs' => true,
179+
'preview_targets' => [],
180+
])
181+
->assertOk();
182+
183+
$updated = Collection::findByHandle('test');
184+
185+
$this->assertEquals(['en', 'de'], $updated->sites()->all());
186+
$this->assertEquals('root', $updated->originBehavior());
187+
$this->assertTrue($updated->propagate());
188+
}
189+
156190
private function userWithoutPermission()
157191
{
158192
$this->setTestRoles(['test' => ['access cp']]);

tests/Feature/Taxonomies/UpdateTaxonomyTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,33 @@ public function it_associates_taxonomies_with_collections()
7575
$this->assertTrue($collectionThree->taxonomies()->contains($taxonomy));
7676
}
7777

78+
#[Test]
79+
public function it_updates_taxonomy_sites_from_enabled_rows_and_ignores_origins()
80+
{
81+
$this->setSites([
82+
'en' => ['name' => 'English', 'locale' => 'en_US', 'url' => 'http://test.com/'],
83+
'fr' => ['name' => 'French', 'locale' => 'fr_FR', 'url' => 'http://fr.test.com/'],
84+
'de' => ['name' => 'German', 'locale' => 'de_DE', 'url' => 'http://de.test.com/'],
85+
]);
86+
87+
$taxonomy = tap(Taxonomy::make('test')->sites(['en', 'fr']))->save();
88+
89+
$this
90+
->actingAs($this->userWithPermission())
91+
->update($taxonomy, [
92+
'sites' => [
93+
['name' => 'English', 'handle' => 'en', 'enabled' => true, 'origin' => null],
94+
['name' => 'French', 'handle' => 'fr', 'enabled' => false, 'origin' => 'en'],
95+
['name' => 'German', 'handle' => 'de', 'enabled' => true, 'origin' => 'en'],
96+
],
97+
'preview_targets' => [],
98+
'collections' => [],
99+
])
100+
->assertOk();
101+
102+
$this->assertEquals(['en', 'de'], Taxonomy::findByHandle('test')->sites()->all());
103+
}
104+
78105
private function userWithoutPermission()
79106
{
80107
$this->setTestRoles(['test' => ['access cp']]);

0 commit comments

Comments
 (0)