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