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

[5.x] Ability for relationship/entries fieldtype to add "hints" #10447

Merged
merged 12 commits into from
Jul 17, 2024
4 changes: 2 additions & 2 deletions resources/js/components/inputs/relationship/Item.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
>
<div class="item-move" v-if="sortable">&nbsp;</div>
<div class="item-inner">
<div v-if="statusIcon" class="little-dot rtl:ml-2 ltr:mr-2 hidden@sm:block" :class="item.status" />
<div v-if="statusIcon" class="little-dot rtl:ml-2 ltr:mr-2 hidden @sm:block" :class="item.status" />

<div
v-if="item.invalid"
Expand All @@ -27,7 +27,7 @@
/>

<div class="flex items-center flex-1 justify-end">
<div v-if="item.collection" v-text="__(item.collection.title)" class="text-4xs text-gray-600 uppercase whitespace-nowrap rtl:ml-2 ltr:mr-2 hidden @sm:block" />
<div v-if="item.hint" v-text="item.hint" class="text-4xs text-gray-600 uppercase whitespace-nowrap rtl:ml-2 ltr:mr-2 hidden @sm:block" />

<div class="flex items-center" v-if="!readOnly">
<dropdown-list>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

<loading-graphic v-if="initializing" :inline="true" />

<template v-if="!initializing && !usesSelectField">
<div ref="items" class="relationship-input-items space-y-1 outline-none">
<template v-if="!initializing">
<div ref="items" class="relationship-input-items space-y-1 outline-none" :class="{ 'mt-4': usesSelectField && items.length }">
<component
:is="itemComponent"
v-for="(item, i) in items"
Expand Down Expand Up @@ -178,7 +178,7 @@ export default {
},

canSelectOrCreate() {
return !this.readOnly && !this.maxItemsReached;
return !this.usesSelectField && !this.readOnly && !this.maxItemsReached;
},

usesSelectField() {
Expand Down Expand Up @@ -288,7 +288,7 @@ export default {
},

selectFieldSelected(selectedItemData) {
this.$emit('item-data-updated', selectedItemData.map(item => ({ id: item.id, title: item.title })));
this.$emit('item-data-updated', selectedItemData);
this.update(selectedItemData.map(item => item.id));
},

Expand Down
31 changes: 9 additions & 22 deletions resources/js/components/inputs/relationship/SelectField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@
@search:focus="$emit('focus')"
@search:blur="$emit('blur')"
>
<template #option="{ title, hint, status }">
<div class="flex justify-between items-center">
<div class="flex items-center">
<div v-if="status" class="little-dot rtl:ml-2 ltr:mr-2 hidden@sm:block" :class="status" />
<div v-text="title" />
</div>
<div v-if="hint" class="text-4xs text-gray-600 uppercase whitespace-nowrap" v-text="hint" />
</div>
</template>
<template #selected-option-container v-if="multiple"><i class="hidden"></i></template>
<template #search="{ events, attributes }" v-if="multiple">
<input
Expand All @@ -35,28 +44,6 @@
<template #no-options>
<div class="text-sm text-gray-700 rtl:text-right ltr:text-left py-2 px-4" v-text="__('No options to choose from.')" />
</template>
<template #footer="{ deselect }" v-if="multiple">
<sortable-list
item-class="sortable-item"
handle-class="sortable-item"
:value="items"
:distance="5"
:mirror="false"
@input="input"
>
<div class="vs__selected-options-outside flex flex-wrap">
<span v-for="item in items" :key="item.id" class="vs__selected mt-2" :class="{ 'sortable-item': !readOnly }">
{{ __(item.title) }}
<button v-if="!readOnly" @click="deselect(item)" type="button" :aria-label="__('Deselect option')" class="vs__deselect">
<span>×</span>
</button>
<button v-else type="button" class="vs__deselect">
<span class="opacity-50">×</span>
</button>
</span>
</div>
</sortable-list>
</template>
</v-select>
</div>

Expand Down
15 changes: 11 additions & 4 deletions src/Fieldtypes/Entries.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
use Statamic\Facades\Search;
use Statamic\Facades\Site;
use Statamic\Facades\User;
use Statamic\Http\Resources\CP\Entries\Entries as EntriesResource;
use Statamic\Http\Resources\CP\Entries\Entry as EntryResource;
use Statamic\Http\Resources\CP\Entries\EntriesFieldtypeEntries;
use Statamic\Http\Resources\CP\Entries\EntriesFieldtypeEntry as EntryResource;
use Statamic\Query\OrderedQueryBuilder;
use Statamic\Query\Scopes\Filter;
use Statamic\Query\Scopes\Filters\Concerns\QueriesFilters;
Expand Down Expand Up @@ -146,7 +146,7 @@ public function getIndexItems($request)

public function getResourceCollection($request, $items)
{
return (new EntriesResource($items))
return (new EntriesFieldtypeEntries($items, $this))
->blueprint($this->getBlueprint($request))
->columnPreferenceKey("collections.{$this->getFirstCollectionFromRequest($request)->handle()}.columns")
->additional(['meta' => [
Expand Down Expand Up @@ -317,7 +317,7 @@ protected function toItemArray($id)
return $this->invalidItemArray($id);
}

return (new EntryResource($entry))->resolve()['data'];
return (new EntryResource($entry, $this))->resolve()['data'];
}

protected function collect($value)
Expand Down Expand Up @@ -462,4 +462,11 @@ public function preload()
'blueprints' => $blueprints,
]]);
}

public function getItemHint($item): ?string
{
return collect([
count($this->getConfiguredCollections()) > 1 ? __($item->collection()->title()) : null,
])->filter()->implode(' • ');
}
}
5 changes: 5 additions & 0 deletions src/Fieldtypes/Relationship.php
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@ public function getItemData($values)
})->values();
}

public function getItemHint($item): ?string
{
return null;
}

abstract protected function toItemArray($id);

protected function invalidItemArray($id)
Expand Down
12 changes: 10 additions & 2 deletions src/Fieldtypes/Terms.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
use Statamic\Facades\Term;
use Statamic\Facades\User;
use Statamic\GraphQL\Types\TermInterface;
use Statamic\Http\Resources\CP\Taxonomies\Terms as TermsResource;
use Statamic\Http\Resources\CP\Taxonomies\TermsFieldtypeTerms as TermsResource;
use Statamic\Query\OrderedQueryBuilder;
use Statamic\Query\Scopes\Filter;
use Statamic\Query\Scopes\Filters\Fields\Terms as TermsFilter;
Expand Down Expand Up @@ -252,7 +252,7 @@ public function getIndexItems($request)

public function getResourceCollection($request, $items)
{
return (new TermsResource($items))
return (new TermsResource($items, $this))
->blueprint($this->getBlueprint($request))
->columnPreferenceKey("taxonomies.{$this->getFirstTaxonomyFromRequest($request)->handle()}.columns");
}
Expand Down Expand Up @@ -368,6 +368,7 @@ protected function toItemArray($id)
'published' => $term->published(),
'private' => $term->private(),
'edit_url' => $term->editUrl(),
'hint' => $this->getItemHint($term),
];
}

Expand Down Expand Up @@ -478,4 +479,11 @@ protected function getItemsForPreProcessIndex($values): Collection

return $this->config('max_items') === 1 ? collect([$augmented]) : $augmented->get();
}

public function getItemHint($item): ?string
{
return collect([
count($this->getConfiguredTaxonomies()) > 1 ? __($item->taxonomy()->title()) : null,
])->filter()->implode(' • ');
}
}
32 changes: 32 additions & 0 deletions src/Http/Resources/CP/Entries/EntriesFieldtypeEntries.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Statamic\Http\Resources\CP\Entries;

use Illuminate\Pagination\AbstractPaginator;
use Statamic\Fieldtypes\Entries as EntriesFieldtype;

class EntriesFieldtypeEntries extends Entries
{
private EntriesFieldtype $fieldtype;
public $collects = EntriesFieldtypeListedEntry::class;

public function __construct($resource, EntriesFieldtype $fieldtype)
{
$this->fieldtype = $fieldtype;

parent::__construct($resource);
}

protected function collectResource($resource)
{
$collection = parent::collectResource($resource);

if ($collection instanceof AbstractPaginator) {
$collection->getCollection()->each->fieldtype($this->fieldtype);
} else {
$collection->each->fieldtype($this->fieldtype);
}

return $collection;
}
}
31 changes: 31 additions & 0 deletions src/Http/Resources/CP/Entries/EntriesFieldtypeEntry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Statamic\Http\Resources\CP\Entries;

use Illuminate\Http\Resources\Json\JsonResource;
use Statamic\Fieldtypes\Entries as EntriesFieldtype;

class EntriesFieldtypeEntry extends JsonResource
{
private EntriesFieldtype $fieldtype;

public function __construct($resource, EntriesFieldtype $fieldtype)
{
$this->fieldtype = $fieldtype;

parent::__construct($resource);
}

public function toArray($request)
{
$data = [
'id' => $this->resource->id(),
'title' => $this->resource->value('title'),
'status' => $this->resource->status(),
'edit_url' => $this->resource->editUrl(),
'hint' => $this->fieldtype->getItemHint($this->resource),
];

return ['data' => $data];
}
}
31 changes: 31 additions & 0 deletions src/Http/Resources/CP/Entries/EntriesFieldtypeListedEntry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Statamic\Http\Resources\CP\Entries;

use Statamic\Fieldtypes\Entries as EntriesFieldtype;

class EntriesFieldtypeListedEntry extends ListedEntry
{
private EntriesFieldtype $fieldtype;

public function fieldtype(EntriesFieldtype $fieldtype): self
{
$this->fieldtype = $fieldtype;

return $this;
}

public function toArray($request)
{
$arr = parent::toArray($request);

if (
in_array($this->fieldtype->config('mode'), ['select', 'typeahead'])
&& ($hint = $this->fieldtype->getItemHint($this->resource))
) {
$arr['hint'] = $hint;
}

return $arr;
}
}
31 changes: 31 additions & 0 deletions src/Http/Resources/CP/Taxonomies/TermsFieldtypeListedTerm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Statamic\Http\Resources\CP\Taxonomies;

use Statamic\Fieldtypes\Terms as TermsFieldtype;

class TermsFieldtypeListedTerm extends ListedTerm
{
private TermsFieldtype $fieldtype;

public function fieldtype(TermsFieldtype $fieldtype): self
{
$this->fieldtype = $fieldtype;

return $this;
}

public function toArray($request)
{
$arr = parent::toArray($request);

if (
in_array($this->fieldtype->config('mode'), ['select', 'typeahead'])
&& ($hint = $this->fieldtype->getItemHint($this->resource))
) {
$arr['hint'] = $hint;
}

return $arr;
}
}
32 changes: 32 additions & 0 deletions src/Http/Resources/CP/Taxonomies/TermsFieldtypeTerms.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Statamic\Http\Resources\CP\Taxonomies;

use Illuminate\Pagination\AbstractPaginator;
use Statamic\Fieldtypes\Terms as TermsFieldtype;

class TermsFieldtypeTerms extends Terms
{
private TermsFieldtype $fieldtype;
public $collects = TermsFieldtypeListedTerm::class;

public function __construct($resource, TermsFieldtype $fieldtype)
{
$this->fieldtype = $fieldtype;

parent::__construct($resource);
}

protected function collectResource($resource)
{
$collection = parent::collectResource($resource);

if ($collection instanceof AbstractPaginator) {
$collection->getCollection()->each->fieldtype($this->fieldtype);
} else {
$collection->each->fieldtype($this->fieldtype);
}

return $collection;
}
}
Loading