xref: /webtrees/resources/views/admin/data-fix-page.phtml (revision bd29d468ac3a5ed7a23d7dd8f300504dda83fc72)
1<?php
2
3use Fisharebest\Webtrees\Http\RequestHandlers\ControlPanel;
4use Fisharebest\Webtrees\Http\RequestHandlers\DataFixData;
5use Fisharebest\Webtrees\Http\RequestHandlers\DataFixPage;
6use Fisharebest\Webtrees\Http\RequestHandlers\DataFixUpdateAll;
7use Fisharebest\Webtrees\Http\RequestHandlers\HelpText;
8use Fisharebest\Webtrees\Http\RequestHandlers\ManageTrees;
9use Fisharebest\Webtrees\I18N;
10use Fisharebest\Webtrees\Module\ModuleDataFixInterface;
11use Fisharebest\Webtrees\Tree;
12use Fisharebest\Webtrees\View;
13
14/**
15 * @var ModuleDataFixInterface $data_fix
16 * @var string                 $latest_version
17 * @var string                 $title
18 * @var Tree                   $tree
19 * @var string                 $pending_url
20 */
21
22?>
23
24<?= view('components/breadcrumbs', ['links' => [route(ControlPanel::class) => I18N::translate('Control panel'), route(ManageTrees::class, ['tree' => $tree->name()]) => I18N::translate('Manage family trees'), route(DataFixPage::class, ['tree' => $tree->name()]) => view('icons/data-fix') . I18N::translate('Data fixes'), $title]]) ?>
25
26<h1><?= $title ?></h1>
27
28<form action="#" id="data-fix-options">
29    <p>
30        <?= $data_fix->description() ?>
31    </p>
32
33    <?= $data_fix->fixOptions($tree) ?>
34
35    <div class="row mb-3">
36        <div class="col-sm-3">
37        </div>
38
39        <div class="col-sm-9">
40            <button class="btn btn-primary" type="button" id="btn-search">
41                <?= view('icons/search') ?>
42                <?= I18N::translate('Search') ?>
43            </button>
44
45            <button class="btn btn-primary" type="button" id="btn-update-all">
46                <?= view('icons/data-fix') ?>
47                <?= I18N::translate('Update all') ?>
48            </button>
49        </div>
50    </div>
51</form>
52
53<div id="data-fix-table-container" class="d-none">
54    <table
55        id="data-fix-table"
56        class="table table-bordered table-sm table-hover wt-data-fix-table"
57        <?= view('lists/datatables-attributes') ?>
58        data-server-side="true"
59        data-filter="false"
60        data-processing="true"
61        data-sort="false"
62    >
63        <thead>
64            <tr>
65                <th class="w-75">
66                    <?= I18N::translate('Record') ?>
67                </th>
68                <th class="w-25">
69                    <?= view('icons/data-fix') ?>
70                    <?= I18N::translate('Data fix') ?>
71                </th>
72            </tr>
73        </thead>
74        <tbody>
75        </tbody>
76    </table>
77
78    <hr>
79
80    <a href="#" data-bs-toggle="modal" data-bs-backdrop="static" data-bs-target="#wt-ajax-modal" data-wt-href="<?= e(route(HelpText::class, ['topic' => 'data-fixes'])) ?>">
81        <?= view('icons/help') ?>
82        <?= I18N::translate('Why does this list include records that do not need to be updated?') ?>
83    </a>
84</div>
85
86<div id="data-fix-progress" class="d-none">
87    <div class="progress">
88        <div class="progress-bar" role="progressbar"></div>
89    </div>
90</div>
91
92<?= view('modals/ajax') ?>
93
94<?php View::push('javascript') ?>
95<script>
96  (function () {
97    let form = document.getElementById('data-fix-options');
98    let container = document.getElementById('data-fix-table-container');
99    let table = document.getElementById('data-fix-table');
100    let progress = document.getElementById('data-fix-progress');
101    let progressbar = progress.querySelector('.progress-bar');
102    let queue = [];
103
104    function getParams () {
105      let formData = new FormData(form);
106      let params = {};
107      formData.forEach(function (value, key) {
108        params[key] = value;
109      });
110
111      return params;
112    }
113
114    function addParamsToUrl (u) {
115      let url = new URL(u);
116      let formData = new FormData(form);
117      formData.forEach(function (value, key) {
118        url.searchParams.append(key, value);
119      });
120
121      return url.toString();
122
123    }
124
125    form.addEventListener('submit', function (event) {
126      event.preventDefault();
127    });
128
129    container.addEventListener('click', function (event) {
130      if ('updateUrl' in event.target.dataset) {
131        event.preventDefault();
132
133        webtrees.httpPost(event.target.dataset.updateUrl)
134          .then(function (response) {
135            $(table).DataTable().ajax.reload(null, false);
136          })
137          .catch(function (error) {
138            alert(error);
139        });
140      }
141    });
142
143    document.getElementById('btn-search').addEventListener('click', function (event) {
144      event.preventDefault();
145
146      // If we were in the middle of doing "update all", stop processing.
147      queue = [];
148
149      progress.classList.add('d-none');
150
151      if ($.fn.dataTable.isDataTable(table)) {
152        $(table).DataTable().ajax.reload();
153      } else {
154        $(table).DataTable({
155          'ajax': {
156            'url': <?= json_encode(route(DataFixData::class, ['tree' => $tree->name(), 'data_fix' => $data_fix->name()]), JSON_THROW_ON_ERROR) ?>,
157            'data': function (data) {
158              $.extend(data, getParams());
159            }
160          }
161        });
162      }
163
164      container.classList.remove('d-none');
165    });
166
167    document.getElementById('btn-update-all').addEventListener('click', function (event) {
168      event.preventDefault();
169
170      progressbar.innerHTML = '';
171      progressbar.style.width = '0%';
172
173      container.classList.add('d-none');
174      progress.classList.remove('d-none');
175
176      let url = addParamsToUrl(<?= json_encode(route(DataFixUpdateAll::class, ['tree' => $tree->name(), 'data_fix' => $data_fix->name()]), JSON_THROW_ON_ERROR) ?>);
177
178      webtrees.httpPost(url)
179        .then(function (response) {
180          return response.json();
181        })
182        .then(async function (data) {
183          queue = data;
184          while (queue.length > 0) {
185            let datum = queue.shift();
186            await webtrees.httpPost(datum.url)
187              .then(function () {
188                let progressbar = progress.querySelector('.progress-bar');
189                progressbar.innerHTML = datum.progress;
190                progressbar.style.width = datum.percent;
191              });
192          }
193        })
194        .catch(function (error) {
195          progress.innerHTML = error;
196        });
197    });
198  })();
199</script>
200<?php View::endpush() ?>
201