mirror of
https://github.com/code-rhapsodie/ibexa-dataflow-bundle.git
synced 2026-03-24 06:32:07 +01:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f68d49f4b | ||
|
|
6be0993c98 | ||
|
|
28f76b279b | ||
|
|
d9b1a66f92 |
58
CHANGELOG.md
58
CHANGELOG.md
@@ -1,3 +1,8 @@
|
||||
# Version 4.2.0
|
||||
|
||||
* Added error count columns to job tables
|
||||
* Fixed scheduled job run history pagination
|
||||
|
||||
# Version 4.1.2
|
||||
|
||||
* Fix main menu label
|
||||
@@ -14,56 +19,3 @@
|
||||
# Version 4.0.0
|
||||
|
||||
* Add compatibility with Ibexa 4.0+ and drop compatibility for eZPlatform 2 and Ibexa 3
|
||||
|
||||
# Version 3.2.0
|
||||
|
||||
* Fixed History page pagination is hidden by footer on Ibexa 3.3 #38
|
||||
* Added filter on history page to filter out jobs with 0 items
|
||||
* Date and times will now be displayed using the user defined timezone, and stored using php timezone
|
||||
|
||||
# Version 3.1.0
|
||||
|
||||
* Allow `LocationCreateStruct` objects inside the `$locations` argument of `ContentCreateStructure` to have more control over the created locations.
|
||||
|
||||
# Version 3.0.1
|
||||
|
||||
* Bump minimum PHP version to PHP 7.3 like code-rhapsodie/dataflow-bundle dependency.
|
||||
* Allow PHP 8.x.
|
||||
* Add GitHub Action to run tests.
|
||||
|
||||
# Version 3.0.0
|
||||
|
||||
* Add compatibility with Ibexa Content 3.3
|
||||
* Add compatibility with Symfony 5.x
|
||||
|
||||
# Version 2.3.0
|
||||
|
||||
* Added a button to display exceptions / log in a modal
|
||||
* Add log in `CodeRhapsodie\EzDataflowBundle\Filter\NotModifiedContentFilter` and `CodeRhapsodie\EzDataflowBundle\Writer\ContentWriter`
|
||||
|
||||
# Version 2.2.0
|
||||
|
||||
* Added `NotModifiedContentFilter` and a bunch of `FieldComparator` classes
|
||||
|
||||
# version 2.1.0
|
||||
|
||||
* ContentWriter return created content
|
||||
|
||||
# version 2.0.1
|
||||
|
||||
* Enclosure js code into anonymous function
|
||||
|
||||
# version 2.0.0
|
||||
|
||||
* Update to use Dataflow v2.0+
|
||||
* Add compiler pass to change the Dataflow DBAL connection factory
|
||||
* Use the DBAL connection from siteaccess
|
||||
* Add `mode` argument on `ContentStructureFactory::transform()` function
|
||||
* Add `CodeRhapsodie\EzDataflowBundle\Factory\ContentStructureFactoryInterface`
|
||||
|
||||
# version 1.0.0
|
||||
|
||||
* Initial version to use Dataflow v1.0+ into eZ Platform
|
||||
* Add Admin UI
|
||||
* Add content writer
|
||||
* Add content structure
|
||||
|
||||
@@ -11,12 +11,9 @@ Ibexa Dataflow bundle is intended to manage content imports from external data s
|
||||
> Command line notice: When you use Dataflow commands, **use `--siteaccess` instead of `--connection`** expect
|
||||
> for `code-rhapsodie:dataflow:dump-schema` command.
|
||||
|
||||
| Ibexa Dataflow Version | Ibexa Content Version | Status |
|
||||
|---------------------|-----------------------|------------------------------|
|
||||
| 4.x | 4.x | :white_check_mark: Maintened |
|
||||
| 3.x | 3.x | :white_check_mark: Maintened |
|
||||
| 2.x | eZ Platform 2.5 | :x: Not maintened |
|
||||
| 1.x | eZ Platform 2.5 | :x: Not maintained |
|
||||
| Ibexa Dataflow Version | Ibexa Content Version | Status |
|
||||
|------------------------|-----------------------|-------------------------------|
|
||||
| 4.x | 4.x | :white_check_mark: Maintained |
|
||||
|
||||
## User Interface (UI)
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4||^8.0",
|
||||
"ext-json": "*",
|
||||
"code-rhapsodie/dataflow-bundle": "^3.0||^4.0",
|
||||
"http-interop/http-factory-guzzle": "^1.2",
|
||||
"ibexa/admin-ui": "^4.0",
|
||||
|
||||
@@ -8,6 +8,8 @@ use CodeRhapsodie\DataflowBundle\Entity\Job;
|
||||
use CodeRhapsodie\DataflowBundle\Entity\ScheduledDataflow;
|
||||
use CodeRhapsodie\EzDataflowBundle\Form\CreateOneshotType;
|
||||
use CodeRhapsodie\EzDataflowBundle\Form\CreateScheduledType;
|
||||
use CodeRhapsodie\EzDataflowBundle\Form\UpdateScheduledType;
|
||||
use CodeRhapsodie\EzDataflowBundle\Gateway\ExceptionJSONDecoderAdapter;
|
||||
use CodeRhapsodie\EzDataflowBundle\Gateway\JobGateway;
|
||||
use CodeRhapsodie\EzDataflowBundle\Gateway\ScheduledDataflowGateway;
|
||||
use Doctrine\DBAL\Query\QueryBuilder;
|
||||
@@ -54,10 +56,12 @@ class DashboardController extends Controller
|
||||
$form = $this->createForm(CreateScheduledType::class, $newWorkflow, [
|
||||
'action' => $this->generateUrl('coderhapsodie.ezdataflow.workflow.create'),
|
||||
]);
|
||||
$updateForm = $this->createForm(UpdateScheduledType::class);
|
||||
|
||||
return $this->render('@ibexadesign/ezdataflow/Dashboard/repeating.html.twig', [
|
||||
'pager' => $this->getPager($this->scheduledDataflowGateway->getListQueryForAdmin(), $request),
|
||||
'form' => $form->createView(),
|
||||
'update_form' => $updateForm->createView(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -141,11 +145,15 @@ class DashboardController extends Controller
|
||||
|
||||
private function getPager(QueryBuilder $query, Request $request): Pagerfanta
|
||||
{
|
||||
$pager = new Pagerfanta(new QueryAdapter($query, function ($queryBuilder) {
|
||||
return $queryBuilder->select('COUNT(DISTINCT id) AS total_results')
|
||||
->resetQueryPart('orderBy')
|
||||
->setMaxResults(1);
|
||||
}));
|
||||
$pager = new Pagerfanta(
|
||||
new ExceptionJSONDecoderAdapter(
|
||||
new QueryAdapter($query, function ($queryBuilder) {
|
||||
return $queryBuilder->select('COUNT(DISTINCT id) AS total_results')
|
||||
->resetQueryPart('orderBy')
|
||||
->setMaxResults(1);
|
||||
})
|
||||
)
|
||||
);
|
||||
$pager->setMaxPerPage(20);
|
||||
$pager->setCurrentPage($request->query->get('page', 1));
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ class CreateOneshotType extends AbstractType
|
||||
])
|
||||
->add('requestedDate', UserTimezoneAwareDateTimeType::class, [
|
||||
'label' => 'coderhapsodie.dataflow.requestedDate',
|
||||
'years' => range(date('Y'), date('Y') + 5),
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ class CreateScheduledType extends AbstractType
|
||||
'label' => 'coderhapsodie.dataflow.frequency',
|
||||
])
|
||||
->add('next', UserTimezoneAwareDateTimeType::class, [
|
||||
'years' => range(date('Y'), date('Y') + 5),
|
||||
'label' => 'coderhapsodie.dataflow.create.next',
|
||||
])
|
||||
->add('enabled', CheckboxType::class, [
|
||||
|
||||
@@ -32,7 +32,6 @@ class UpdateScheduledType extends AbstractType
|
||||
'label' => 'coderhapsodie.dataflow.frequency',
|
||||
])
|
||||
->add('next', UserTimezoneAwareDateTimeType::class, [
|
||||
'years' => range(date('Y'), date('Y') + 5),
|
||||
'label' => 'coderhapsodie.dataflow.update.next',
|
||||
])
|
||||
;
|
||||
|
||||
@@ -4,9 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Form;
|
||||
|
||||
use Ibexa\AdminUi\Form\Type\DateTimePickerType;
|
||||
use Ibexa\Contracts\Core\Repository\UserPreferenceService;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class UserTimezoneAwareDateTimeType extends AbstractType
|
||||
@@ -21,7 +21,7 @@ class UserTimezoneAwareDateTimeType extends AbstractType
|
||||
|
||||
public function getParent()
|
||||
{
|
||||
return DateTimeType::class;
|
||||
return DateTimePickerType::class;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
|
||||
35
src/Gateway/ExceptionJSONDecoderAdapter.php
Normal file
35
src/Gateway/ExceptionJSONDecoderAdapter.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CodeRhapsodie\EzDataflowBundle\Gateway;
|
||||
|
||||
use Pagerfanta\Adapter\AdapterInterface;
|
||||
|
||||
class ExceptionJSONDecoderAdapter implements AdapterInterface
|
||||
{
|
||||
/** @var AdapterInterface */
|
||||
private $adapter;
|
||||
|
||||
public function __construct(AdapterInterface $adapter)
|
||||
{
|
||||
$this->adapter = $adapter;
|
||||
}
|
||||
|
||||
public function getNbResults()
|
||||
{
|
||||
return $this->adapter->getNbResults();
|
||||
}
|
||||
|
||||
public function getSlice($offset, $length)
|
||||
{
|
||||
$slice = $this->adapter->getSlice($offset, $length);
|
||||
array_walk($slice, static function (&$value) {
|
||||
if (isset($value['exceptions'])) {
|
||||
$value['exceptions'] = json_decode($value['exceptions'], true, 512, JSON_THROW_ON_ERROR);
|
||||
}
|
||||
});
|
||||
|
||||
return $slice;
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,8 @@ coderhapsodie.ezdataflow.history.title: History
|
||||
coderhapsodie.ezdataflow.history.list.title: 'Executions list'
|
||||
coderhapsodie.ezdataflow.history.list.name: Name
|
||||
coderhapsodie.ezdataflow.history.list.request: 'Requested on'
|
||||
coderhapsodie.ezdataflow.history.list.count: 'Items count'
|
||||
coderhapsodie.ezdataflow.history.list.error_count: 'Errors count'
|
||||
coderhapsodie.ezdataflow.history.list.count: 'Number of successes'
|
||||
coderhapsodie.ezdataflow.history.list.errors: 'Number of errors'
|
||||
coderhapsodie.ezdataflow.history.list.start: 'Started on'
|
||||
coderhapsodie.ezdataflow.history.list.end: 'Finished on'
|
||||
coderhapsodie.ezdataflow.history.list.view: 'View details'
|
||||
|
||||
@@ -20,8 +20,8 @@ coderhapsodie.ezdataflow.history.title: Historique
|
||||
coderhapsodie.ezdataflow.history.list.title: 'Liste des exécutions'
|
||||
coderhapsodie.ezdataflow.history.list.name: Nom
|
||||
coderhapsodie.ezdataflow.history.list.request: 'Demandé le'
|
||||
coderhapsodie.ezdataflow.history.list.count: 'Nombre d''objets'
|
||||
coderhapsodie.ezdataflow.history.list.error_count: 'Nombre d''erreurs'
|
||||
coderhapsodie.ezdataflow.history.list.count: 'Nombre de succès'
|
||||
coderhapsodie.ezdataflow.history.list.errors: 'Nombre d''erreurs'
|
||||
coderhapsodie.ezdataflow.history.list.start: 'Commencé le'
|
||||
coderhapsodie.ezdataflow.history.list.end: 'Terminé le'
|
||||
coderhapsodie.ezdataflow.history.list.view: 'Voir le détail'
|
||||
|
||||
@@ -43,14 +43,17 @@
|
||||
e.preventDefault();
|
||||
const loading = document.getElementById('loading_ezdataflow_history_results');
|
||||
const results = document.getElementById('ezdataflow_history_results').querySelector('.ibexa-table');
|
||||
const pagination = document.getElementById('ezdataflow_history_results').querySelector('.pag');
|
||||
loading.hidden = false;
|
||||
results.innerHTML = '';
|
||||
pagination.innerHTML = '';
|
||||
fetch('{{ path('coderhapsodie.ezdataflow.history') }}?filter=' + this.value)
|
||||
.then((r) => r.text())
|
||||
.then((content) => {
|
||||
const node = document.createElement('div');
|
||||
node.innerHTML = content;
|
||||
results.innerHTML = node.querySelector('#ezdataflow_history_results .ibexa-table').innerHTML;
|
||||
pagination.innerHTML = node.querySelector('#ezdataflow_history_results .pag').innerHTML;
|
||||
loading.hidden = true;
|
||||
})
|
||||
;
|
||||
|
||||
@@ -71,6 +71,33 @@
|
||||
.closest('ul').querySelectorAll('li.ibexa-tabs__tab');
|
||||
const tabs = document.getElementById('ibexa-tab-coderhapsodie-ezdataflow-code-rhapsodie-ezdataflow-repeating')
|
||||
.closest('.tab-content').querySelectorAll('.tab-pane');
|
||||
|
||||
// Manage ajax pagination
|
||||
document.addEventListener('click', (e) => {
|
||||
const link = e.target.closest('.ibexa-pagination a');
|
||||
if (!link) {
|
||||
return;
|
||||
}
|
||||
|
||||
const block = link.closest('.ibexa-pagination').parentNode.parentNode;
|
||||
const display = block.querySelector('.ibexa-table');
|
||||
const pagination = block.querySelector('.pag');
|
||||
const loader = document.querySelector('#' + block.dataset.loader);
|
||||
e.preventDefault();
|
||||
loader.hidden = false;
|
||||
display.innerHTML = '';
|
||||
pagination.innerHTML = '';
|
||||
fetch(link.href)
|
||||
.then((r) => r.text())
|
||||
.then((content) => {
|
||||
const node = document.createElement('div');
|
||||
node.innerHTML = content;
|
||||
display.innerHTML = node.querySelector('#' + block.id).querySelector('.ibexa-table').innerHTML;
|
||||
pagination.innerHTML = node.querySelector('#' + block.id).querySelector('.pag').innerHTML;
|
||||
loader.hidden = true;
|
||||
})
|
||||
;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{%- block content -%}
|
||||
{% form_theme update_form '@ibexadesign/ezdataflow/form_theme.html.twig' %}
|
||||
|
||||
{{ include('@ibexadesign/ezdataflow/parts/tab/schedule_list.html.twig', {
|
||||
identifier: 'ezdataflow_schedule_results',
|
||||
@@ -15,10 +16,12 @@
|
||||
title: 'coderhapsodie.ezdataflow.workflow.repeating.edit.title'|trans,
|
||||
} %}
|
||||
{% block body_content %}
|
||||
<form action="" method="post">
|
||||
<div class="form-fields"></div>
|
||||
{{ form_start(update_form) }}
|
||||
<div class="form-fields">
|
||||
{{ form_widget(update_form) }}
|
||||
</div>
|
||||
<button id="modal-edit-submit" type="submit" hidden />
|
||||
</form>
|
||||
{{ form_end(update_form) }}
|
||||
{% endblock %}
|
||||
{% block footer_content %}
|
||||
<button type="button" class="btn ibexa-btn ibexa-btn--primary ibexa-btn--trigger" data-click="#modal-edit-submit">
|
||||
@@ -52,50 +55,6 @@
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// $('#ez-modal--edit-scheduled').modal({keyboard: true, show: false});
|
||||
// $('.modal-edit').each(function (index, elem) {
|
||||
// $(elem).click(function (e) {
|
||||
// e.preventDefault();
|
||||
// $('#schedule_edit').html('');
|
||||
// $('#ez-modal--edit-scheduled').modal('show');
|
||||
// $.ajax(elem.href, {
|
||||
// success: function (result) {
|
||||
// if (result.redirect) {
|
||||
// if (window.location.href === result.redirect) {
|
||||
// window.location.reload();
|
||||
// }
|
||||
// window.location = result.redirect;
|
||||
// window.location.reload();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// $('#schedule_edit').html(result.form);
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// $('#ez-modal--edit-scheduled').on('submit', 'form', function (e) {
|
||||
// e.preventDefault();
|
||||
// url = $(this).attr('action');
|
||||
// data = new FormData(this);
|
||||
// $.ajax({
|
||||
// 'type': 'POST',
|
||||
// 'url': url,
|
||||
// 'data': data,
|
||||
// processData: false,
|
||||
// contentType: false,
|
||||
// success: function (result) {
|
||||
// if (result.redirect) {
|
||||
// window.location = result.redirect;
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// $('#schedule_edit').html(result.form);
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
|
||||
const bindFormSubmit = (modalId) => {
|
||||
document.querySelector('#'+modalId+' form').addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
@@ -134,7 +93,13 @@
|
||||
const node = document.createElement('div');
|
||||
node.innerHTML = result.form;
|
||||
editModal.querySelector('form').action = link.href;
|
||||
editModal.querySelector('.form-fields').innerHTML = node.querySelector('.form-fields').innerHTML;
|
||||
editModal.querySelector('#update_scheduled_label').value = node.querySelector('#update_scheduled_label').value;
|
||||
editModal.querySelector('#update_scheduled_options').value = node.querySelector('#update_scheduled_options').value;
|
||||
editModal.querySelector('#update_scheduled_frequency').value = node.querySelector('#update_scheduled_frequency').value;
|
||||
editModal.querySelector('#update_scheduled_next').parentNode.parentNode.ibexaInstance.flatpickrInstance.setDate(
|
||||
new Date(node.querySelector('#update_scheduled_next').value * 1000),
|
||||
true
|
||||
);
|
||||
})
|
||||
;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div id="{{ id }}" class="history-details-aware">
|
||||
<div id="{{ id }}" data-loader="loading_{{ id }}" class="history-details-aware">
|
||||
|
||||
{% set body_rows = [] %}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
{content: job.label},
|
||||
{content: date(job.requested_date)|ibexa_short_datetime},
|
||||
{content: job.count|default('—')},
|
||||
{content: job.exceptions|length},
|
||||
{content: job.start_time ? date(job.start_time)|ibexa_short_datetime : '—'},
|
||||
{content: job.end_time ? date(job.end_time)|ibexa_short_datetime : '—'},
|
||||
{content: macros.translateStatus(job.status)},
|
||||
@@ -61,6 +62,7 @@
|
||||
{ content: 'coderhapsodie.ezdataflow.history.list.name'|trans },
|
||||
{ content: 'coderhapsodie.ezdataflow.history.list.request'|trans },
|
||||
{ content: 'coderhapsodie.ezdataflow.history.list.count'|trans },
|
||||
{ content: 'coderhapsodie.ezdataflow.history.list.errors'|trans },
|
||||
{ content: 'coderhapsodie.ezdataflow.history.list.start'|trans },
|
||||
{ content: 'coderhapsodie.ezdataflow.history.list.end'|trans },
|
||||
{ content: 'coderhapsodie.ezdataflow.history.list.status'|trans },
|
||||
@@ -78,40 +80,15 @@
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
{% if pager.haveToPaginate %}
|
||||
{% include '@ibexadesign/ui/pagination.html.twig' with {
|
||||
'pager': pager,
|
||||
'paginaton_params': {
|
||||
'routeName': paginate_route,
|
||||
'routeParams': paginate_params|default({})
|
||||
}
|
||||
} %}
|
||||
{% endif %}
|
||||
<div class="pag">
|
||||
{% if pager.haveToPaginate %}
|
||||
{% include '@ibexadesign/ui/pagination.html.twig' with {
|
||||
'pager': pager,
|
||||
'paginaton_params': {
|
||||
'routeName': paginate_route,
|
||||
'routeParams': paginate_params|default({})
|
||||
}
|
||||
} %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Manage ajax pagination
|
||||
const display = document.getElementById('{{ id }}');
|
||||
display.addEventListener('click', (e) => {
|
||||
const link = e.target.closest('.ibexa-pagination a');
|
||||
if (!link) {
|
||||
return;
|
||||
}
|
||||
|
||||
const loader = document.getElementById('loading_{{ id }}');
|
||||
e.preventDefault();
|
||||
loader.hidden = false;
|
||||
display.innerHTML = '';
|
||||
fetch(link.href)
|
||||
.then((r) => r.text())
|
||||
.then((content) => {
|
||||
const node = document.createElement('div');
|
||||
node.innerHTML = content;
|
||||
display.innerHTML = node.querySelector('#{{ id }}').innerHTML;
|
||||
loader.hidden = true;
|
||||
})
|
||||
;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div id="{{ id }}" class="history-details-aware">
|
||||
<div id="{{ id }}" data-loader="loading_{{ id }}" class="history-details-aware">
|
||||
{% set body_rows = [] %}
|
||||
|
||||
{% for item in pager.currentPageResults %}
|
||||
@@ -113,40 +113,15 @@
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
{% if pager.haveToPaginate %}
|
||||
{% include '@ibexadesign/ui/pagination.html.twig' with {
|
||||
'pager': pager,
|
||||
'paginaton_params': {
|
||||
'routeName': paginate_route,
|
||||
'routeParams': paginate_params|default({})
|
||||
}
|
||||
} %}
|
||||
{% endif %}
|
||||
<div class="pag">
|
||||
{% if pager.haveToPaginate %}
|
||||
{% include '@ibexadesign/ui/pagination.html.twig' with {
|
||||
'pager': pager,
|
||||
'paginaton_params': {
|
||||
'routeName': paginate_route,
|
||||
'routeParams': paginate_params|default({})
|
||||
}
|
||||
} %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Manage ajax pagination
|
||||
const display = document.getElementById('{{ id }}');
|
||||
display.addEventListener('click', (e) => {
|
||||
const link = e.target.closest('.ibexa-pagination a');
|
||||
if (!link) {
|
||||
return;
|
||||
}
|
||||
|
||||
const loader = document.getElementById('loading_{{ id }}');
|
||||
e.preventDefault();
|
||||
loader.hidden = false;
|
||||
display.innerHTML = '';
|
||||
fetch(link.href)
|
||||
.then((r) => r.text())
|
||||
.then((content) => {
|
||||
const node = document.createElement('div');
|
||||
node.innerHTML = content;
|
||||
display.innerHTML = node.querySelector('#{{ id }}').innerHTML;
|
||||
loader.hidden = true;
|
||||
})
|
||||
;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user