chg: [tag] Continuation of integrating tagging plugin - WiP
- Can tag/untag any modelpull/72/head
parent
8b659fb6af
commit
29595c6e22
|
@ -7,6 +7,7 @@ use Cake\Error\Debugger;
|
||||||
use Cake\Utility\Hash;
|
use Cake\Utility\Hash;
|
||||||
use Cake\Utility\Inflector;
|
use Cake\Utility\Inflector;
|
||||||
use Cake\View\ViewBuilder;
|
use Cake\View\ViewBuilder;
|
||||||
|
use Cake\ORM\TableRegistry;
|
||||||
use Cake\Http\Exception\MethodNotAllowedException;
|
use Cake\Http\Exception\MethodNotAllowedException;
|
||||||
use Cake\Http\Exception\NotFoundException;
|
use Cake\Http\Exception\NotFoundException;
|
||||||
|
|
||||||
|
@ -355,6 +356,7 @@ class CRUDComponent extends Component
|
||||||
|
|
||||||
if ($this->taggingSupported()) {
|
if ($this->taggingSupported()) {
|
||||||
$params['contain'][] = 'Tags';
|
$params['contain'][] = 'Tags';
|
||||||
|
$this->setAllTags();
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $this->Table->get($id, $params);
|
$data = $this->Table->get($id, $params);
|
||||||
|
@ -417,6 +419,7 @@ class CRUDComponent extends Component
|
||||||
throw new Exception("Table {$this->TableAlias} does not support tagging");
|
throw new Exception("Table {$this->TableAlias} does not support tagging");
|
||||||
}
|
}
|
||||||
if ($this->request->is('get')) {
|
if ($this->request->is('get')) {
|
||||||
|
$this->setAllTags();
|
||||||
if(!empty($id)) {
|
if(!empty($id)) {
|
||||||
$params = [
|
$params = [
|
||||||
'contain' => 'Tags',
|
'contain' => 'Tags',
|
||||||
|
@ -455,9 +458,9 @@ class CRUDComponent extends Component
|
||||||
$message = $this->getMessageBasedOnResult(
|
$message = $this->getMessageBasedOnResult(
|
||||||
$bulkSuccesses == count($ids),
|
$bulkSuccesses == count($ids),
|
||||||
$isBulk,
|
$isBulk,
|
||||||
__('{0} tagged.', $this->ObjectAlias),
|
__('{0} tagged with `{1}`.', $this->ObjectAlias, $input['tag_list']),
|
||||||
__('All {0} have been tagged.', Inflector::pluralize($this->ObjectAlias)),
|
__('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.',
|
__('{0} / {1} {2} have been tagged.',
|
||||||
$bulkSuccesses,
|
$bulkSuccesses,
|
||||||
count($ids),
|
count($ids),
|
||||||
|
@ -476,6 +479,7 @@ class CRUDComponent extends Component
|
||||||
throw new Exception("Table {$this->TableAlias} does not support tagging");
|
throw new Exception("Table {$this->TableAlias} does not support tagging");
|
||||||
}
|
}
|
||||||
if ($this->request->is('get')) {
|
if ($this->request->is('get')) {
|
||||||
|
$this->setAllTags();
|
||||||
if(!empty($id)) {
|
if(!empty($id)) {
|
||||||
$params = [
|
$params = [
|
||||||
'contain' => 'Tags',
|
'contain' => 'Tags',
|
||||||
|
@ -516,9 +520,9 @@ class CRUDComponent extends Component
|
||||||
$message = $this->getMessageBasedOnResult(
|
$message = $this->getMessageBasedOnResult(
|
||||||
$bulkSuccesses == count($ids),
|
$bulkSuccesses == count($ids),
|
||||||
$isBulk,
|
$isBulk,
|
||||||
__('{0} untagged.', $this->ObjectAlias),
|
__('{0} untagged with `{1}`.', $this->ObjectAlias, implode(', ', $tagsToRemove)),
|
||||||
__('All {0} have been untagged.', Inflector::pluralize($this->ObjectAlias)),
|
__('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.',
|
__('{0} / {1} {2} have been untagged.',
|
||||||
$bulkSuccesses,
|
$bulkSuccesses,
|
||||||
count($ids),
|
count($ids),
|
||||||
|
@ -549,6 +553,7 @@ class CRUDComponent extends Component
|
||||||
$this->Controller->restResponsePayload = $this->RestResponse->viewData($data, 'json');
|
$this->Controller->restResponsePayload = $this->RestResponse->viewData($data, 'json');
|
||||||
}
|
}
|
||||||
$this->Controller->set('entity', $data);
|
$this->Controller->set('entity', $data);
|
||||||
|
$this->setAllTags();
|
||||||
$this->Controller->viewBuilder()->setLayout('ajax');
|
$this->Controller->viewBuilder()->setLayout('ajax');
|
||||||
$this->Controller->render('/genericTemplates/tag');
|
$this->Controller->render('/genericTemplates/tag');
|
||||||
}
|
}
|
||||||
|
@ -837,6 +842,13 @@ class CRUDComponent extends Component
|
||||||
return $this->Table->behaviors()->has('Tag');
|
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
|
public function toggle(int $id, string $fieldName = 'enabled', array $params = []): void
|
||||||
{
|
{
|
||||||
if (empty($id)) {
|
if (empty($id)) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ use Cake\Database\Expression\QueryExpression;
|
||||||
use Cake\Http\Exception\NotFoundException;
|
use Cake\Http\Exception\NotFoundException;
|
||||||
use Cake\Http\Exception\MethodNotAllowedException;
|
use Cake\Http\Exception\MethodNotAllowedException;
|
||||||
use Cake\Http\Exception\ForbiddenException;
|
use Cake\Http\Exception\ForbiddenException;
|
||||||
|
use Cake\ORM\TableRegistry;
|
||||||
|
|
||||||
class IndividualsController extends AppController
|
class IndividualsController extends AppController
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,15 +27,20 @@ class TagHelper extends Helper
|
||||||
$field = 'tag_list';
|
$field = 'tag_list';
|
||||||
$values = !empty($options['allTags']) ? array_map(function($tag) {
|
$values = !empty($options['allTags']) ? array_map(function($tag) {
|
||||||
return [
|
return [
|
||||||
'text' => h($tag['text']),
|
'text' => h($tag['label']),
|
||||||
'value' => h($tag['text']),
|
'value' => h($tag['label']),
|
||||||
'data-colour' => h($tag['colour']),
|
'data-colour' => h($tag['colour']),
|
||||||
|
'data-text-colour' => h($tag['text_colour']),
|
||||||
];
|
];
|
||||||
}, $options['allTags']) : [];
|
}, $options['allTags']) : [];
|
||||||
$selectConfig = [
|
$selectConfig = [
|
||||||
'multiple' => true,
|
'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);
|
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-container my-1">';
|
||||||
$html .= '<div class="tag-list d-inline-block">';
|
$html .= '<div class="tag-list d-inline-block">';
|
||||||
foreach ($tags as $tag) {
|
foreach ($tags as $tag) {
|
||||||
if (is_array($tag)) {
|
if (is_object($tag)) {
|
||||||
$html .= $this->tag($tag);
|
$html .= $this->tag($tag);
|
||||||
} else {
|
} else {
|
||||||
$html .= $this->tag([
|
$html .= $this->tag([
|
||||||
'name' => $tag
|
'label' => $tag
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,13 +86,13 @@ class TagHelper extends Helper
|
||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tag(array $tag, array $options = [])
|
public function tag($tag, array $options = [])
|
||||||
{
|
{
|
||||||
if (empty($this->_config)) {
|
if (empty($this->_config)) {
|
||||||
$this->_config = array_merge($this->defaultConfig, $options);
|
$this->_config = array_merge($this->defaultConfig, $options);
|
||||||
}
|
}
|
||||||
$tag['colour'] = !empty($tag['colour']) ? $tag['colour'] : $this->getConfig('default_colour');
|
$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'))) {
|
if (!empty($this->getConfig('editable'))) {
|
||||||
$deleteButton = $this->Bootstrap->button([
|
$deleteButton = $this->Bootstrap->button([
|
||||||
|
@ -103,7 +108,7 @@ class TagHelper extends Helper
|
||||||
'action' => 'untag',
|
'action' => 'untag',
|
||||||
$this->getView()->get('entity')['id']
|
$this->getView()->get('entity')['id']
|
||||||
]),
|
]),
|
||||||
h($tag['name'])
|
h($tag['label'])
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
@ -118,9 +123,9 @@ class TagHelper extends Helper
|
||||||
'mx-1',
|
'mx-1',
|
||||||
'align-middle',
|
'align-middle',
|
||||||
],
|
],
|
||||||
'title' => h($tag['name']),
|
'title' => h($tag['label']),
|
||||||
'style' => sprintf('color:%s; background-color:%s', $textColour, h($tag['colour'])),
|
'style' => sprintf('color:%s; background-color:%s', $textColour, h($tag['colour'])),
|
||||||
], h($tag['name']) . $deleteButton);
|
], h($tag['label']) . $deleteButton);
|
||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
<?php
|
<?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([
|
$tagsHtml = $this->Tag->tags([
|
||||||
'allTags' => $allTags,
|
'allTags' => $allTags,
|
||||||
'tags' => $entity['tag_list'],
|
'tags' => $entity['tags'],
|
||||||
'picker' => true,
|
'picker' => true,
|
||||||
]);
|
]);
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -1,15 +1,9 @@
|
||||||
<?php
|
<?php
|
||||||
// $tags = Cake\Utility\Hash::extract($data, $field['path']);
|
// $tags = Cake\Utility\Hash::extract($data, $field['path']);
|
||||||
$tagList = Cake\Utility\Hash::get($data, 'tag_list');
|
$tags = Cake\Utility\Hash::get($data, 'tags');
|
||||||
$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([
|
echo $this->Tag->tags([
|
||||||
'allTags' => $allTags,
|
'allTags' => $allTags,
|
||||||
'tags' => $tagList,
|
'tags' => $tags,
|
||||||
'picker' => true,
|
'picker' => true,
|
||||||
'editable' => true,
|
'editable' => true,
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
<?php
|
<?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([
|
echo $this->Tag->tags([
|
||||||
'allTags' => $allTags,
|
'allTags' => $allTags,
|
||||||
'tags' => $entity->tag_list,
|
'tags' => $entity->tags,
|
||||||
'picker' => true,
|
'picker' => true,
|
||||||
'editable' => true,
|
'editable' => true,
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -1121,6 +1121,9 @@ class HtmlHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
static tag(options={}) {
|
static tag(options={}) {
|
||||||
|
if (!options.colour) {
|
||||||
|
options.colour = '#924da6'
|
||||||
|
}
|
||||||
const $tag = $('<span/>')
|
const $tag = $('<span/>')
|
||||||
.addClass(['tag', 'badge', 'border'])
|
.addClass(['tag', 'badge', 'border'])
|
||||||
.css({color: getTextColour(options.colour), 'background-color': options.colour})
|
.css({color: getTextColour(options.colour), 'background-color': options.colour})
|
||||||
|
|
|
@ -119,7 +119,7 @@ function createTagPicker(clicked) {
|
||||||
|
|
||||||
function templateTag(state) {
|
function templateTag(state) {
|
||||||
if (!state.id) {
|
if (!state.id) {
|
||||||
return state.text;
|
return state.label;
|
||||||
}
|
}
|
||||||
if (state.colour === undefined) {
|
if (state.colour === undefined) {
|
||||||
state.colour = $(state.element).data('colour')
|
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')))
|
.append($('<span></span>').text('Save').prepend($('<i></i>').addClass('fa fa-save mr-1')))
|
||||||
.click(function() {
|
.click(function() {
|
||||||
const tags = $select.select2('data').map(tag => tag.text)
|
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')
|
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')))
|
.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({
|
const theToast = UI.toast({
|
||||||
variant: 'success',
|
variant: 'success',
|
||||||
title: 'Tag deleted',
|
title: result.message,
|
||||||
bodyHtml: $('<div/>').append(
|
bodyHtml: $('<div/>').append(
|
||||||
$('<span/>').text('Cancel untag operation.'),
|
$('<span/>').text('Cancel untag operation.'),
|
||||||
$('<button/>').addClass(['btn', 'btn-primary', 'btn-sm', 'ml-3']).text('Restore tag').click(function() {
|
$('<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()
|
theToast.removeToast()
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
|
@ -189,8 +193,7 @@ function deleteTag(url, tag, clicked) {
|
||||||
}).catch((e) => {})
|
}).catch((e) => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTags(tags, $statusNode) {
|
function addTags(url, tags, $statusNode) {
|
||||||
const url = '/individuals/tag/2'
|
|
||||||
const data = {
|
const data = {
|
||||||
tag_list: tags
|
tag_list: tags
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue