1const form = document.getElementById('fetchmedia_form');
2
3
4function* flattenLinks(data) {
5    yield* Object.entries(data).reduce((carry, [page, links]) => {
6        const flatLinks = links.map(link => [page, link]);
7        return carry.concat(flatLinks);
8    }, []);
9}
10
11function decorateLiWithResult(page, link, res) {
12    const selector = `td[data-id="${btoa(page + link)}"]`;
13    const td = document.querySelector(selector);
14    const STATUS_OK = 200;
15
16    if (res.status === STATUS_OK) {
17        td.innerHTML = '<span class="result success"> OK ⬇✔️</span>';
18    } else {
19        td.innerHTML = `<span class="result error"> ${res.status}: ${res.status_text} ❌</span>`;
20    }
21}
22
23function requestDownloadExternalFile(linkGen) {
24    const { value, done } = linkGen.next();
25    if (done) {
26        return;
27    }
28
29    const [page, link] = value;
30    const selector = `td[data-id="${btoa(page + link)}"]`;
31    const td = document.querySelector(selector);
32    td.innerHTML = '<span class="⏳⬇">⬇️</span>';
33
34    const options = {
35        method: 'POST',
36        headers: new Headers({ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8' }),
37        body: Object.entries({
38            call: 'plugin_fetchmedia_downloadExternalFile',
39            page,
40            link,
41        }).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join('&'),
42        credentials: 'include',
43    };
44
45    fetch(`${DOKU_BASE}lib/exe/ajax.php`, options)
46        .then(response => response.json())
47        .then((res) => {
48            decorateLiWithResult(page, link, res);
49            requestDownloadExternalFile(linkGen);
50        })
51        .catch((res) => {
52            console.error(res);
53            requestDownloadExternalFile(linkGen);
54        });
55}
56
57form.addEventListener('submit',
58    (event) => {
59        event.preventDefault();
60        const body = {
61            call: 'plugin_fetchmedia_getExternalMediaLinks',
62            namespace: form.querySelector('input[name="namespace"]').value,
63            type: form.querySelector('input[name="mediatypes"]:checked').value,
64            sectok: form.querySelector('input[name="sectok"]').value,
65        };
66        const query = Object.entries(body).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join('&');
67        const options = {
68            method: 'GET',
69            headers: new Headers({ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8' }),
70            credentials: 'include',
71        };
72        const waitingMessage = window.LANG.plugins.fetchmedia['message: waiting for response'];
73        document.getElementById('fetchmedia_results').innerHTML = `<div id="waitingMessage"><p><em>${waitingMessage}</em></p></div>`;
74        fetch(`${DOKU_BASE}lib/exe/ajax.php?${query}`, options)
75            .then(response => response.json())
76            .then((data) => {
77                const TIMEOUT_TO_SHOW_WORK = 200;
78                const links = Object.entries(data);
79                if (!links.length) {
80                    const noLinksMsg = window.LANG.plugins.fetchmedia['error: no links found'];
81                    setTimeout(() => {
82                        document.getElementById('fetchmedia_results').innerHTML = `<div id="noLinksFound"><p><em>${noLinksMsg}</em></p></div>`;
83                    }, TIMEOUT_TO_SHOW_WORK);
84                    return;
85                }
86                const l10nTableHeadingPage = window.LANG.plugins.fetchmedia['table-heading: page'];
87                const l10nTableHeadingLinks = window.LANG.plugins.fetchmedia['table-heading: links'];
88                const l10nTableHeadingResults = window.LANG.plugins.fetchmedia['table-heading: results'];
89                const tableHead = `<table class="inline"><thead><tr><th>${l10nTableHeadingPage}</th><th>${l10nTableHeadingLinks}</th><th>${l10nTableHeadingResults}</th></tr></thead>`;
90                const tableRows = links.map(([page, mediaLinks]) => {
91                    const pageUrl = `${DOKU_BASE}doku.php?id=${page}`;
92                    const pageLink = `<a href="${pageUrl}" class="wikilink1" target="_blank">${page}</a>`;
93                    const numberOfLinks = mediaLinks.length;
94                    const firstUrl = mediaLinks[0];
95                    const remainingLinks = mediaLinks.slice(1);
96                    return `<tr>
97                        <td class="wikipage" rowspan="${numberOfLinks}">${pageLink}</td>
98                        <td class="mediaLink">${firstUrl}</td><td data-id="${btoa(page + firstUrl)}" class="result"></td></tr>
99                        ${remainingLinks.map(url => `<tr><td class="mediaLink">${url}</td><td data-id="${btoa(page + url)}" class="result"></td></tr>`).join('')}`;
100                });
101                // todo handle case that there are no external links
102                const table = `${tableHead + tableRows.join('')}</table>`;
103                const downloadButton = `<button id="downloadNow">${window.LANG.plugins.fetchmedia['label: button download']}</button>`;
104
105                setTimeout(() => {
106                    document.getElementById('fetchmedia_results').innerHTML = downloadButton + table;
107                    const linkGen = flattenLinks(data);
108                    document.getElementById('downloadNow').addEventListener('click', () => requestDownloadExternalFile(linkGen));
109                }, TIMEOUT_TO_SHOW_WORK);
110            })
111            .catch((error) => {
112                console.error(error);
113                const fetchError = window.LANG.plugins.fetchmedia['error: error retrieving links'];
114                document.getElementById('fetchmedia_results').innerHTML = `<div id="error"><p><em>${fetchError}</em></p></div>`;
115            });
116    },
117);
118