chg: [tag] Continuation of integrating tagging plugin - WiP
- Tagging / Untaggingpull/72/head
parent
b1e5bbad1a
commit
8b659fb6af
|
@ -243,6 +243,9 @@ class CRUDComponent extends Component
|
|||
throw new NotFoundException(__('Invalid {0}.', $this->ObjectAlias));
|
||||
}
|
||||
$this->getMetaTemplates();
|
||||
if ($this->taggingSupported()) {
|
||||
$params['contain'][] = 'Tags';
|
||||
}
|
||||
$data = $this->Table->get($id, isset($params['get']) ? $params['get'] : []);
|
||||
$data = $this->getMetaFields($id, $data);
|
||||
if (!empty($params['fields'])) {
|
||||
|
@ -350,6 +353,10 @@ class CRUDComponent extends Component
|
|||
throw new NotFoundException(__('Invalid {0}.', $this->ObjectAlias));
|
||||
}
|
||||
|
||||
if ($this->taggingSupported()) {
|
||||
$params['contain'][] = 'Tags';
|
||||
}
|
||||
|
||||
$data = $this->Table->get($id, $params);
|
||||
$data = $this->attachMetaData($id, $data);
|
||||
if (isset($params['afterFind'])) {
|
||||
|
@ -404,6 +411,148 @@ class CRUDComponent extends Component
|
|||
$this->Controller->render('/genericTemplates/delete');
|
||||
}
|
||||
|
||||
public function tag($id=false): void
|
||||
{
|
||||
if (!$this->taggingSupported()) {
|
||||
throw new Exception("Table {$this->TableAlias} does not support tagging");
|
||||
}
|
||||
if ($this->request->is('get')) {
|
||||
if(!empty($id)) {
|
||||
$params = [
|
||||
'contain' => 'Tags',
|
||||
];
|
||||
$entity = $this->Table->get($id, $params);
|
||||
$this->Controller->set('id', $entity->id);
|
||||
$this->Controller->set('data', $entity);
|
||||
$this->Controller->set('bulkEnabled', false);
|
||||
} else {
|
||||
$this->Controller->set('bulkEnabled', true);
|
||||
}
|
||||
} else if ($this->request->is('post') || $this->request->is('delete')) {
|
||||
$ids = $this->getIdsOrFail($id);
|
||||
$isBulk = count($ids) > 1;
|
||||
$bulkSuccesses = 0;
|
||||
foreach ($ids as $id) {
|
||||
$params = [
|
||||
'contain' => 'Tags',
|
||||
];
|
||||
$entity = $this->Table->get($id, $params);
|
||||
// patching will mirror tag in the DB, however, we only want to add tags
|
||||
$input = $this->request->getData();
|
||||
$tagsToAdd = explode(',', $input['tag_list']);
|
||||
$entity->tag_list = $entity->tag_list;
|
||||
$input['tag_list'] = implode(',', array_merge($tagsToAdd, $entity->tag_list));
|
||||
$patchEntityParams = [
|
||||
'fields' => ['tags'],
|
||||
];
|
||||
$entity = $this->Table->patchEntity($entity, $input, $patchEntityParams);
|
||||
$savedData = $this->Table->save($entity);
|
||||
$success = true;
|
||||
if ($success) {
|
||||
$bulkSuccesses++;
|
||||
}
|
||||
}
|
||||
$message = $this->getMessageBasedOnResult(
|
||||
$bulkSuccesses == count($ids),
|
||||
$isBulk,
|
||||
__('{0} tagged.', $this->ObjectAlias),
|
||||
__('All {0} have been tagged.', Inflector::pluralize($this->ObjectAlias)),
|
||||
__('Could not tag {0}.', $this->ObjectAlias),
|
||||
__('{0} / {1} {2} have been tagged.',
|
||||
$bulkSuccesses,
|
||||
count($ids),
|
||||
Inflector::pluralize($this->ObjectAlias)
|
||||
)
|
||||
);
|
||||
$this->setResponseForController('tag', $bulkSuccesses, $message, $savedData);
|
||||
}
|
||||
$this->Controller->viewBuilder()->setLayout('ajax');
|
||||
$this->Controller->render('/genericTemplates/tagForm');
|
||||
}
|
||||
|
||||
public function untag($id=false): void
|
||||
{
|
||||
if (!$this->taggingSupported()) {
|
||||
throw new Exception("Table {$this->TableAlias} does not support tagging");
|
||||
}
|
||||
if ($this->request->is('get')) {
|
||||
if(!empty($id)) {
|
||||
$params = [
|
||||
'contain' => 'Tags',
|
||||
];
|
||||
$entity = $this->Table->get($id, $params);
|
||||
$this->Controller->set('id', $entity->id);
|
||||
$this->Controller->set('data', $entity);
|
||||
$this->Controller->set('bulkEnabled', false);
|
||||
} else {
|
||||
$this->Controller->set('bulkEnabled', true);
|
||||
}
|
||||
} else if ($this->request->is('post') || $this->request->is('delete')) {
|
||||
$ids = $this->getIdsOrFail($id);
|
||||
$isBulk = count($ids) > 1;
|
||||
$bulkSuccesses = 0;
|
||||
foreach ($ids as $id) {
|
||||
$params = [
|
||||
'contain' => 'Tags',
|
||||
];
|
||||
$entity = $this->Table->get($id, $params);
|
||||
// patching will mirror tag in the DB, however, we only want to remove tags
|
||||
$input = $this->request->getData();
|
||||
$tagsToRemove = explode(',', $input['tag_list']);
|
||||
$entity->tag_list = $entity->tag_list;
|
||||
$input['tag_list'] = implode(',', array_filter($entity->tag_list, function ($existingTag) use ($tagsToRemove) {
|
||||
return !in_array($existingTag, $tagsToRemove);
|
||||
}));
|
||||
$patchEntityParams = [
|
||||
'fields' => ['tags'],
|
||||
];
|
||||
$entity = $this->Table->patchEntity($entity, $input, $patchEntityParams);
|
||||
$savedData = $this->Table->save($entity);
|
||||
$success = true;
|
||||
if ($success) {
|
||||
$bulkSuccesses++;
|
||||
}
|
||||
}
|
||||
$message = $this->getMessageBasedOnResult(
|
||||
$bulkSuccesses == count($ids),
|
||||
$isBulk,
|
||||
__('{0} untagged.', $this->ObjectAlias),
|
||||
__('All {0} have been untagged.', Inflector::pluralize($this->ObjectAlias)),
|
||||
__('Could not untag {0}.', $this->ObjectAlias),
|
||||
__('{0} / {1} {2} have been untagged.',
|
||||
$bulkSuccesses,
|
||||
count($ids),
|
||||
Inflector::pluralize($this->ObjectAlias)
|
||||
)
|
||||
);
|
||||
$this->setResponseForController('tag', $bulkSuccesses, $message, $entity);
|
||||
}
|
||||
$this->Controller->viewBuilder()->setLayout('ajax');
|
||||
$this->Controller->render('/genericTemplates/tagForm');
|
||||
}
|
||||
|
||||
public function viewTags(int $id, array $params = []): void
|
||||
{
|
||||
if (!$this->taggingSupported()) {
|
||||
throw new Exception("Table {$this->TableAlias} does not support tagging");
|
||||
}
|
||||
if (empty($id)) {
|
||||
throw new NotFoundException(__('Invalid {0}.', $this->ObjectAlias));
|
||||
}
|
||||
|
||||
$params['contain'][] = 'Tags';
|
||||
$data = $this->Table->get($id, $params);
|
||||
if (isset($params['afterFind'])) {
|
||||
$data = $params['afterFind']($data);
|
||||
}
|
||||
if ($this->Controller->ParamHandler->isRest()) {
|
||||
$this->Controller->restResponsePayload = $this->RestResponse->viewData($data, 'json');
|
||||
}
|
||||
$this->Controller->set('entity', $data);
|
||||
$this->Controller->viewBuilder()->setLayout('ajax');
|
||||
$this->Controller->render('/genericTemplates/tag');
|
||||
}
|
||||
|
||||
public function setResponseForController($action, $success, $message, $data=[], $errors=null)
|
||||
{
|
||||
if ($success) {
|
||||
|
@ -683,6 +832,11 @@ class CRUDComponent extends Component
|
|||
return $prefixedConditions;
|
||||
}
|
||||
|
||||
public function taggingSupported()
|
||||
{
|
||||
return $this->Table->behaviors()->has('Tag');
|
||||
}
|
||||
|
||||
public function toggle(int $id, string $fieldName = 'enabled', array $params = []): void
|
||||
{
|
||||
if (empty($id)) {
|
||||
|
|
|
@ -72,4 +72,31 @@ class IndividualsController extends AppController
|
|||
}
|
||||
$this->set('metaGroup', 'ContactDB');
|
||||
}
|
||||
|
||||
public function tag($id)
|
||||
{
|
||||
$this->CRUD->tag($id);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
}
|
||||
}
|
||||
|
||||
public function untag($id)
|
||||
{
|
||||
$this->CRUD->untag($id);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
}
|
||||
}
|
||||
|
||||
public function viewTags($id)
|
||||
{
|
||||
$this->CRUD->viewTags($id);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,31 +11,38 @@ class TagHelper extends Helper
|
|||
'Bootstrap',
|
||||
'TextColour',
|
||||
'FontAwesome',
|
||||
'Form',
|
||||
'Url',
|
||||
'Tags.Tag',
|
||||
];
|
||||
|
||||
protected $_defaultConfig = [
|
||||
'default_colour' => '#983965',
|
||||
protected $defaultConfig = [
|
||||
'default_colour' => '#924da6',
|
||||
'picker' => false,
|
||||
'editable' => false,
|
||||
];
|
||||
|
||||
public function control(array $options = [])
|
||||
{
|
||||
return $this->Tag->control($options);
|
||||
}
|
||||
|
||||
public function picker(array $options = [])
|
||||
{
|
||||
$optionsHtml = '';
|
||||
foreach ($options['allTags'] as $i => $tag) {
|
||||
$optionsHtml .= $this->Bootstrap->genNode('option', [
|
||||
$field = 'tag_list';
|
||||
$values = !empty($options['allTags']) ? array_map(function($tag) {
|
||||
return [
|
||||
'text' => h($tag['text']),
|
||||
'value' => h($tag['text']),
|
||||
'data-colour' => h($tag['colour']),
|
||||
], h($tag['text']));
|
||||
}
|
||||
$html = $this->Bootstrap->genNode('select', [
|
||||
'class' => ['tag-input', 'd-none'],
|
||||
'multiple' => '',
|
||||
], $optionsHtml);
|
||||
];
|
||||
}, $options['allTags']) : [];
|
||||
$selectConfig = [
|
||||
'multiple' => true,
|
||||
// 'value' => $options['tags'],
|
||||
'class' => ['tag-input', 'd-none']
|
||||
];
|
||||
return $this->Form->select($field, $values, $selectConfig);
|
||||
}
|
||||
|
||||
protected function picker(array $options = [])
|
||||
{
|
||||
$html = $this->Tag->control($options);
|
||||
$html .= $this->Bootstrap->button([
|
||||
'size' => 'sm',
|
||||
'icon' => 'plus',
|
||||
|
@ -50,8 +57,10 @@ class TagHelper extends Helper
|
|||
|
||||
public function tags(array $options = [])
|
||||
{
|
||||
$this->_config = array_merge($this->defaultConfig, $options);
|
||||
$tags = !empty($options['tags']) ? $options['tags'] : [];
|
||||
$html = '<div class="tag-container my-1">';
|
||||
$html = '<div class="tag-container-wrapper">';
|
||||
$html .= '<div class="tag-container my-1">';
|
||||
$html .= '<div class="tag-list d-inline-block">';
|
||||
foreach ($tags as $tag) {
|
||||
if (is_array($tag)) {
|
||||
|
@ -64,25 +73,44 @@ class TagHelper extends Helper
|
|||
}
|
||||
$html .= '</div>';
|
||||
|
||||
if (!empty($options['picker'])) {
|
||||
if (!empty($this->getConfig('picker'))) {
|
||||
$html .= $this->picker($options);
|
||||
}
|
||||
$html .= '</div>';
|
||||
$html .= '</div>';
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function tag(array $tag)
|
||||
public function tag(array $tag, array $options = [])
|
||||
{
|
||||
$tag['colour'] = !empty($tag['colour']) ? $tag['colour'] : $this->getConfig()['default_colour'];
|
||||
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']));
|
||||
$deleteButton = $this->Bootstrap->button([
|
||||
'size' => 'sm',
|
||||
'icon' => 'times',
|
||||
'class' => ['ml-1', 'border-0', "text-${textColour}"],
|
||||
'variant' => 'text',
|
||||
'title' => __('Delete tag'),
|
||||
]);
|
||||
|
||||
|
||||
if (!empty($this->getConfig('editable'))) {
|
||||
$deleteButton = $this->Bootstrap->button([
|
||||
'size' => 'sm',
|
||||
'icon' => 'times',
|
||||
'class' => ['ml-1', 'border-0', "text-${textColour}"],
|
||||
'variant' => 'text',
|
||||
'title' => __('Delete tag'),
|
||||
'params' => [
|
||||
'onclick' => sprintf('deleteTag(\'%s\', \'%s\', this)',
|
||||
$this->Url->build([
|
||||
'controller' => $this->getView()->getName(),
|
||||
'action' => 'untag',
|
||||
$this->getView()->get('entity')['id']
|
||||
]),
|
||||
h($tag['name'])
|
||||
),
|
||||
],
|
||||
]);
|
||||
} else {
|
||||
$deleteButton = '';
|
||||
}
|
||||
|
||||
$html = $this->Bootstrap->genNode('span', [
|
||||
'class' => [
|
||||
'tag',
|
||||
|
|
|
@ -20,7 +20,11 @@
|
|||
),
|
||||
array(
|
||||
'field' => 'position'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'field' => 'tag_list',
|
||||
'type' => 'tags'
|
||||
),
|
||||
),
|
||||
'metaTemplates' => empty($metaTemplates) ? [] : $metaTemplates,
|
||||
'submit' => array(
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?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'],
|
||||
'picker' => true,
|
||||
]);
|
||||
?>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-2 col-form-label"><?= __('Tags') ?></div>
|
||||
<div class="col-sm-10">
|
||||
<?= $tagsHtml ?>
|
||||
</div>
|
||||
</div>
|
|
@ -1,16 +1,15 @@
|
|||
<?php
|
||||
// $tags = Cake\Utility\Hash::extract($data, $field['path']);
|
||||
$tagList = Cake\Utility\Hash::get($data, 'tag_list');
|
||||
$tagList = ['tlp:red'];
|
||||
$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'],
|
||||
];
|
||||
$this->loadHelper('Tag');
|
||||
echo $this->Tag->tags([
|
||||
'allTags' => $allTags,
|
||||
'tags' => $tagList,
|
||||
'picker' => true,
|
||||
]);
|
||||
'editable' => true,
|
||||
]);
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?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,
|
||||
'picker' => true,
|
||||
'editable' => true,
|
||||
]);
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
$form = $this->element('genericElements/Form/genericForm', [
|
||||
'entity' => null,
|
||||
'ajax' => false,
|
||||
'raw' => true,
|
||||
'data' => [
|
||||
'fields' => [
|
||||
[
|
||||
'type' => 'text',
|
||||
'field' => 'ids',
|
||||
'default' => !empty($id) ? json_encode([$id]) : ''
|
||||
],
|
||||
[
|
||||
'type' => 'text',
|
||||
'field' => 'tag_list',
|
||||
],
|
||||
],
|
||||
'submit' => [
|
||||
'action' => $this->request->getParam('action')
|
||||
]
|
||||
]
|
||||
]);
|
||||
$formHTML = sprintf('<div class="d-none">%s</div>', $form);
|
||||
echo $formHTML;
|
|
@ -217,8 +217,9 @@ class UIFactory {
|
|||
return AJAXApi.quickFetchURL(url, {
|
||||
statusNode: $statusNode[0],
|
||||
}).then((theHTML) => {
|
||||
$container.replaceWith(theHTML)
|
||||
return $container
|
||||
var $tmp = $(theHTML);
|
||||
$container.replaceWith($tmp)
|
||||
return $tmp;
|
||||
}).finally(() => {
|
||||
otherStatusNodes.forEach(overlay => {
|
||||
overlay.hide()
|
||||
|
@ -267,9 +268,9 @@ class Toaster {
|
|||
* @property {string=('primary'|'secondary'|'success'|'danger'|'warning'|'info'|'light'|'dark'|'white'|'transparent')} variant - The variant of the toast
|
||||
* @property {boolean} autohide - If the toast show be hidden after some time defined by the delay
|
||||
* @property {number} delay - The number of milliseconds the toast should stay visible before being hidden
|
||||
* @property {string} titleHtml - The raw HTML title's content of the toast
|
||||
* @property {string} mutedHtml - The raw HTML muted's content of the toast
|
||||
* @property {string} bodyHtml - The raw HTML body's content of the toast
|
||||
* @property {(jQuery|string)} titleHtml - The raw HTML title's content of the toast
|
||||
* @property {(jQuery|string)} mutedHtml - The raw HTML muted's content of the toast
|
||||
* @property {(jQuery|string)} bodyHtml - The raw HTML body's content of the toast
|
||||
* @property {boolean} closeButton - If the toast's title should include a close button
|
||||
*/
|
||||
static defaultOptions = {
|
||||
|
@ -860,7 +861,8 @@ class OverlayFactory {
|
|||
spinnerVariant: '',
|
||||
spinnerSmall: false,
|
||||
spinnerType: 'border',
|
||||
fallbackBoostrapVariant: ''
|
||||
fallbackBoostrapVariant: '',
|
||||
wrapperCSSDisplay: '',
|
||||
}
|
||||
|
||||
static overlayWrapper = '<div aria-busy="true" class="position-relative"/>'
|
||||
|
@ -875,6 +877,14 @@ class OverlayFactory {
|
|||
/** Create the HTML of the overlay */
|
||||
buildOverlay() {
|
||||
this.$overlayWrapper = $(OverlayFactory.overlayWrapper)
|
||||
if (this.options.wrapperCSSDisplay) {
|
||||
this.$overlayWrapper.css('display', this.options.wrapperCSSDisplay)
|
||||
}
|
||||
if (this.$node[0]) {
|
||||
const boundingRect = this.$node[0].getBoundingClientRect()
|
||||
this.$overlayWrapper.css('min-height', boundingRect.height)
|
||||
this.$overlayWrapper.css('min-width', boundingRect.width)
|
||||
}
|
||||
this.$overlayContainer = $(OverlayFactory.overlayContainer)
|
||||
this.$overlayBg = $(OverlayFactory.overlayBg)
|
||||
.addClass([`bg-${this.options.variant}`, (this.options.rounded ? 'rounded' : '')])
|
||||
|
@ -940,7 +950,8 @@ class OverlayFactory {
|
|||
}
|
||||
if (this.$node.is('input[type="checkbox"]') || this.$node.css('border-radius') !== '0px') {
|
||||
this.options.rounded = true
|
||||
}
|
||||
}
|
||||
this.options.wrapperCSSDisplay = this.$node.css('display')
|
||||
let classes = this.$node.attr('class')
|
||||
if (classes !== undefined) {
|
||||
classes = classes.split(' ')
|
||||
|
|
|
@ -127,18 +127,26 @@ function createTagPicker(clicked) {
|
|||
return HtmlHelper.tag(state)
|
||||
}
|
||||
|
||||
function closePicker($select, $container) {
|
||||
$select.appendTo($container)
|
||||
$container.parent().find('.picker-container').remove()
|
||||
}
|
||||
|
||||
const $clicked = $(clicked)
|
||||
const $container = $clicked.closest('.tag-container')
|
||||
$('.picker-container').remove()
|
||||
const $select = $container.parent().find('select.tag-input').removeClass('d-none').addClass('flex-grow-1')
|
||||
closePicker($select, $container)
|
||||
const $pickerContainer = $('<div></div>').addClass(['picker-container', 'd-flex'])
|
||||
const $select = $container.find('select.tag-input').removeClass('d-none').addClass('flex-grow-1')
|
||||
const $saveButton = $('<button></button>').addClass(['btn btn-primary btn-sm', 'align-self-start'])
|
||||
const $saveButton = $('<button></button>').addClass(['btn btn-primary btn-sm', 'align-self-start']).attr('type', 'button')
|
||||
.append($('<span></span>').text('Save').prepend($('<i></i>').addClass('fa fa-save mr-1')))
|
||||
const $cancelButton = $('<button></button>').addClass(['btn btn-secondary btn-sm', 'align-self-start'])
|
||||
.click(function() {
|
||||
const tags = $select.select2('data').map(tag => tag.text)
|
||||
addTags(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')))
|
||||
.click(function() {
|
||||
$select.appendTo($container)
|
||||
$pickerContainer.remove()
|
||||
closePicker($select, $container)
|
||||
})
|
||||
const $buttons = $('<span></span>').addClass(['picker-action', 'btn-group']).append($saveButton, $cancelButton)
|
||||
$select.prependTo($pickerContainer)
|
||||
|
@ -152,6 +160,56 @@ function createTagPicker(clicked) {
|
|||
})
|
||||
}
|
||||
|
||||
function deleteTag(url, tag, clicked) {
|
||||
const data = {
|
||||
tag_list: tag
|
||||
}
|
||||
const $statusNode = $(clicked).closest('.tag')
|
||||
const APIOptions = {
|
||||
statusNode: $statusNode,
|
||||
skipFeedback: true,
|
||||
}
|
||||
return AJAXApi.quickFetchAndPostForm(url, data, APIOptions).then((result) => {
|
||||
let $container = $statusNode.closest('.tag-container-wrapper')
|
||||
refreshTagList(result, $container).then(($tagContainer) => {
|
||||
$container = $tagContainer // old container might not exist anymore since it was replaced after the refresh
|
||||
})
|
||||
const theToast = UI.toast({
|
||||
variant: 'success',
|
||||
title: 'Tag deleted',
|
||||
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(() => {
|
||||
theToast.removeToast()
|
||||
})
|
||||
}),
|
||||
),
|
||||
})
|
||||
}).catch((e) => {})
|
||||
}
|
||||
|
||||
function addTags(tags, $statusNode) {
|
||||
const url = '/individuals/tag/2'
|
||||
const data = {
|
||||
tag_list: tags
|
||||
}
|
||||
const APIOptions = {
|
||||
statusNode: $statusNode
|
||||
}
|
||||
return AJAXApi.quickFetchAndPostForm(url, data, APIOptions).then((result) => {
|
||||
const $container = $statusNode.closest('.tag-container-wrapper')
|
||||
refreshTagList(result, $container)
|
||||
}).catch((e) => {})
|
||||
}
|
||||
|
||||
function refreshTagList(result, $container) {
|
||||
const controllerName = result.url.split('/')[1]
|
||||
const entityId = result.data.id
|
||||
const url = `/${controllerName}/viewTags/${entityId}`
|
||||
return UI.reload(url, $container)
|
||||
}
|
||||
|
||||
|
||||
var UI
|
||||
$(document).ready(() => {
|
||||
|
|
Loading…
Reference in New Issue