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