chg: [tag] Continuation of integrating tagging plugin - WiP

- Can tag/untag any model
pull/72/head
mokaddem 2021-08-26 16:12:55 +02:00
parent 8b659fb6af
commit 29595c6e22
8 changed files with 49 additions and 43 deletions

View File

@ -7,6 +7,7 @@ use Cake\Error\Debugger;
use Cake\Utility\Hash;
use Cake\Utility\Inflector;
use Cake\View\ViewBuilder;
use Cake\ORM\TableRegistry;
use Cake\Http\Exception\MethodNotAllowedException;
use Cake\Http\Exception\NotFoundException;
@ -355,6 +356,7 @@ class CRUDComponent extends Component
if ($this->taggingSupported()) {
$params['contain'][] = 'Tags';
$this->setAllTags();
}
$data = $this->Table->get($id, $params);
@ -417,6 +419,7 @@ class CRUDComponent extends Component
throw new Exception("Table {$this->TableAlias} does not support tagging");
}
if ($this->request->is('get')) {
$this->setAllTags();
if(!empty($id)) {
$params = [
'contain' => 'Tags',
@ -455,9 +458,9 @@ class CRUDComponent extends Component
$message = $this->getMessageBasedOnResult(
$bulkSuccesses == count($ids),
$isBulk,
__('{0} tagged.', $this->ObjectAlias),
__('{0} tagged with `{1}`.', $this->ObjectAlias, $input['tag_list']),
__('All {0} have been tagged.', Inflector::pluralize($this->ObjectAlias)),
__('Could not tag {0}.', $this->ObjectAlias),
__('Could not tag {0} with `{1}`.', $this->ObjectAlias, $input['tag_list']),
__('{0} / {1} {2} have been tagged.',
$bulkSuccesses,
count($ids),
@ -476,6 +479,7 @@ class CRUDComponent extends Component
throw new Exception("Table {$this->TableAlias} does not support tagging");
}
if ($this->request->is('get')) {
$this->setAllTags();
if(!empty($id)) {
$params = [
'contain' => 'Tags',
@ -516,9 +520,9 @@ class CRUDComponent extends Component
$message = $this->getMessageBasedOnResult(
$bulkSuccesses == count($ids),
$isBulk,
__('{0} untagged.', $this->ObjectAlias),
__('{0} untagged with `{1}`.', $this->ObjectAlias, implode(', ', $tagsToRemove)),
__('All {0} have been untagged.', Inflector::pluralize($this->ObjectAlias)),
__('Could not untag {0}.', $this->ObjectAlias),
__('Could not untag {0} with `{1}`.', $this->ObjectAlias, $input['tag_list']),
__('{0} / {1} {2} have been untagged.',
$bulkSuccesses,
count($ids),
@ -549,6 +553,7 @@ class CRUDComponent extends Component
$this->Controller->restResponsePayload = $this->RestResponse->viewData($data, 'json');
}
$this->Controller->set('entity', $data);
$this->setAllTags();
$this->Controller->viewBuilder()->setLayout('ajax');
$this->Controller->render('/genericTemplates/tag');
}
@ -837,6 +842,13 @@ class CRUDComponent extends Component
return $this->Table->behaviors()->has('Tag');
}
public function setAllTags()
{
$this->Tags = TableRegistry::getTableLocator()->get('Tags.Tags');
$allTags = $this->Tags->find()->all()->toList();
$this->Controller->set('allTags', $allTags);
}
public function toggle(int $id, string $fieldName = 'enabled', array $params = []): void
{
if (empty($id)) {

View File

@ -9,6 +9,7 @@ use Cake\Database\Expression\QueryExpression;
use Cake\Http\Exception\NotFoundException;
use Cake\Http\Exception\MethodNotAllowedException;
use Cake\Http\Exception\ForbiddenException;
use Cake\ORM\TableRegistry;
class IndividualsController extends AppController
{

View File

@ -27,15 +27,20 @@ class TagHelper extends Helper
$field = 'tag_list';
$values = !empty($options['allTags']) ? array_map(function($tag) {
return [
'text' => h($tag['text']),
'value' => h($tag['text']),
'text' => h($tag['label']),
'value' => h($tag['label']),
'data-colour' => h($tag['colour']),
'data-text-colour' => h($tag['text_colour']),
];
}, $options['allTags']) : [];
$selectConfig = [
'multiple' => true,
// 'value' => $options['tags'],
'class' => ['tag-input', 'd-none']
'class' => ['tag-input', 'd-none'],
'data-url' => $this->Url->build([
'controller' => $this->getView()->getName(),
'action' => 'tag',
$this->getView()->get('entity')['id']
]),
];
return $this->Form->select($field, $values, $selectConfig);
}
@ -63,11 +68,11 @@ class TagHelper extends Helper
$html .= '<div class="tag-container my-1">';
$html .= '<div class="tag-list d-inline-block">';
foreach ($tags as $tag) {
if (is_array($tag)) {
if (is_object($tag)) {
$html .= $this->tag($tag);
} else {
$html .= $this->tag([
'name' => $tag
'label' => $tag
]);
}
}
@ -81,13 +86,13 @@ class TagHelper extends Helper
return $html;
}
public function tag(array $tag, array $options = [])
public function tag($tag, array $options = [])
{
if (empty($this->_config)) {
$this->_config = array_merge($this->defaultConfig, $options);
}
$tag['colour'] = !empty($tag['colour']) ? $tag['colour'] : $this->getConfig('default_colour');
$textColour = $this->TextColour->getTextColour(h($tag['colour']));
$textColour = !empty($tag['text_colour']) ? $tag['text_colour'] : $this->TextColour->getTextColour(h($tag['colour']));;
if (!empty($this->getConfig('editable'))) {
$deleteButton = $this->Bootstrap->button([
@ -103,7 +108,7 @@ class TagHelper extends Helper
'action' => 'untag',
$this->getView()->get('entity')['id']
]),
h($tag['name'])
h($tag['label'])
),
],
]);
@ -118,9 +123,9 @@ class TagHelper extends Helper
'mx-1',
'align-middle',
],
'title' => h($tag['name']),
'title' => h($tag['label']),
'style' => sprintf('color:%s; background-color:%s', $textColour, h($tag['colour'])),
], h($tag['name']) . $deleteButton);
], h($tag['label']) . $deleteButton);
return $html;
}
}

View File

@ -1,13 +1,7 @@
<?php
$allTags = [
['id' => 'tlp:red', 'text' => 'tlp:red', 'colour' => 'red'],
['id' => 'tlp:green', 'text' => 'tlp:green', 'colour' => 'green'],
['id' => 'tlp:amber', 'text' => 'tlp:amber', 'colour' => '#983965'],
['id' => 'tlp:white', 'text' => 'tlp:white', 'colour' => 'white'],
];
$tagsHtml = $this->Tag->tags([
'allTags' => $allTags,
'tags' => $entity['tag_list'],
'tags' => $entity['tags'],
'picker' => true,
]);
?>

View File

@ -1,15 +1,9 @@
<?php
// $tags = Cake\Utility\Hash::extract($data, $field['path']);
$tagList = Cake\Utility\Hash::get($data, 'tag_list');
$allTags = [
['id' => 'tlp:red', 'text' => 'tlp:red', 'colour' => 'red'],
['id' => 'tlp:green', 'text' => 'tlp:green', 'colour' => 'green'],
['id' => 'tlp:amber', 'text' => 'tlp:amber', 'colour' => '#983965'],
['id' => 'tlp:white', 'text' => 'tlp:white', 'colour' => 'white'],
];
$tags = Cake\Utility\Hash::get($data, 'tags');
echo $this->Tag->tags([
'allTags' => $allTags,
'tags' => $tagList,
'tags' => $tags,
'picker' => true,
'editable' => true,
]);

View File

@ -1,13 +1,7 @@
<?php
$allTags = [
['id' => 'tlp:red', 'text' => 'tlp:red', 'colour' => 'red'],
['id' => 'tlp:green', 'text' => 'tlp:green', 'colour' => 'green'],
['id' => 'tlp:amber', 'text' => 'tlp:amber', 'colour' => '#983965'],
['id' => 'tlp:white', 'text' => 'tlp:white', 'colour' => 'white'],
];
echo $this->Tag->tags([
'allTags' => $allTags,
'tags' => $entity->tag_list,
'tags' => $entity->tags,
'picker' => true,
'editable' => true,
]);

View File

@ -1121,6 +1121,9 @@ class HtmlHelper {
}
static tag(options={}) {
if (!options.colour) {
options.colour = '#924da6'
}
const $tag = $('<span/>')
.addClass(['tag', 'badge', 'border'])
.css({color: getTextColour(options.colour), 'background-color': options.colour})

View File

@ -119,7 +119,7 @@ function createTagPicker(clicked) {
function templateTag(state) {
if (!state.id) {
return state.text;
return state.label;
}
if (state.colour === undefined) {
state.colour = $(state.element).data('colour')
@ -141,7 +141,7 @@ function createTagPicker(clicked) {
.append($('<span></span>').text('Save').prepend($('<i></i>').addClass('fa fa-save mr-1')))
.click(function() {
const tags = $select.select2('data').map(tag => tag.text)
addTags(tags, $(this))
addTags($select.data('url'), tags, $(this))
})
const $cancelButton = $('<button></button>').addClass(['btn btn-secondary btn-sm', 'align-self-start']).attr('type', 'button')
.append($('<span></span>').text('Cancel').prepend($('<i></i>').addClass('fa fa-times mr-1')))
@ -176,11 +176,15 @@ function deleteTag(url, tag, clicked) {
})
const theToast = UI.toast({
variant: 'success',
title: 'Tag deleted',
title: result.message,
bodyHtml: $('<div/>').append(
$('<span/>').text('Cancel untag operation.'),
$('<button/>').addClass(['btn', 'btn-primary', 'btn-sm', 'ml-3']).text('Restore tag').click(function() {
addTags([tag], $container.find('.tag-container')).then(() => {
const split = url.split('/')
const controllerName = split[1]
const id = split[3]
const urlRetag = `/${controllerName}/tag/${id}`
addTags(urlRetag, [tag], $container.find('.tag-container')).then(() => {
theToast.removeToast()
})
}),
@ -189,8 +193,7 @@ function deleteTag(url, tag, clicked) {
}).catch((e) => {})
}
function addTags(tags, $statusNode) {
const url = '/individuals/tag/2'
function addTags(url, tags, $statusNode) {
const data = {
tag_list: tags
}