diff options
Diffstat (limited to 'web_src/js/features/pull-view-file.js')
-rw-r--r-- | web_src/js/features/pull-view-file.js | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/web_src/js/features/pull-view-file.js b/web_src/js/features/pull-view-file.js new file mode 100644 index 00000000..2472e5a0 --- /dev/null +++ b/web_src/js/features/pull-view-file.js @@ -0,0 +1,96 @@ +import {diffTreeStore} from '../modules/stores.js'; +import {setFileFolding} from './file-fold.js'; +import {POST} from '../modules/fetch.js'; + +const {pageData} = window.config; +const prReview = pageData.prReview || {}; +const viewedStyleClass = 'viewed-file-checked-form'; +const viewedCheckboxSelector = '.viewed-file-form'; // Selector under which all "Viewed" checkbox forms can be found +const expandFilesBtnSelector = '#expand-files-btn'; +const collapseFilesBtnSelector = '#collapse-files-btn'; + +// Refreshes the summary of viewed files if present +// The data used will be window.config.pageData.prReview.numberOf{Viewed}Files +function refreshViewedFilesSummary() { + const viewedFilesProgress = document.getElementById('viewed-files-summary'); + viewedFilesProgress?.setAttribute('value', prReview.numberOfViewedFiles); + const summaryLabel = document.getElementById('viewed-files-summary-label'); + if (summaryLabel) summaryLabel.innerHTML = summaryLabel.getAttribute('data-text-changed-template') + .replace('%[1]d', prReview.numberOfViewedFiles) + .replace('%[2]d', prReview.numberOfFiles); +} + +// Explicitly recounts how many files the user has currently reviewed by counting the number of checked "viewed" checkboxes +// Additionally, the viewed files summary will be updated if it exists +export function countAndUpdateViewedFiles() { + // The number of files is constant, but the number of viewed files can change because files can be loaded dynamically + prReview.numberOfViewedFiles = document.querySelectorAll(`${viewedCheckboxSelector} > input[type=checkbox][checked]`).length; + refreshViewedFilesSummary(); +} + +// Initializes a listener for all children of the given html element +// (for example 'document' in the most basic case) +// to watch for changes of viewed-file checkboxes +export function initViewedCheckboxListenerFor() { + for (const form of document.querySelectorAll(`${viewedCheckboxSelector}:not([data-has-viewed-checkbox-listener="true"])`)) { + // To prevent double addition of listeners + form.setAttribute('data-has-viewed-checkbox-listener', true); + + // The checkbox consists of a div containing the real checkbox with its label and the CSRF token, + // hence the actual checkbox first has to be found + const checkbox = form.querySelector('input[type=checkbox]'); + checkbox.addEventListener('input', function() { + // Mark the file as viewed visually - will especially change the background + if (this.checked) { + form.classList.add(viewedStyleClass); + checkbox.setAttribute('checked', ''); + prReview.numberOfViewedFiles++; + } else { + form.classList.remove(viewedStyleClass); + checkbox.removeAttribute('checked'); + prReview.numberOfViewedFiles--; + } + + // Update viewed-files summary and remove "has changed" label if present + refreshViewedFilesSummary(); + const hasChangedLabel = form.parentNode.querySelector('.changed-since-last-review'); + hasChangedLabel?.remove(); + + const fileName = checkbox.getAttribute('name'); + + // check if the file is in our difftreestore and if we find it -> change the IsViewed status + const fileInPageData = diffTreeStore().files.find((x) => x.Name === fileName); + if (fileInPageData) { + fileInPageData.IsViewed = this.checked; + } + + // Unfortunately, actual forms cause too many problems, hence another approach is needed + const files = {}; + files[fileName] = this.checked; + const data = {files}; + const headCommitSHA = form.getAttribute('data-headcommit'); + if (headCommitSHA) data.headCommitSHA = headCommitSHA; + POST(form.getAttribute('data-link'), {data}); + + // Fold the file accordingly + const parentBox = form.closest('.diff-file-header'); + setFileFolding(parentBox.closest('.file-content'), parentBox.querySelector('.fold-file'), this.checked); + }); + } +} + +export function initExpandAndCollapseFilesButton() { + // expand btn + document.querySelector(expandFilesBtnSelector)?.addEventListener('click', () => { + for (const box of document.querySelectorAll('.file-content[data-folded="true"]')) { + setFileFolding(box, box.querySelector('.fold-file'), false); + } + }); + // collapse btn, need to exclude the div of “show more” + document.querySelector(collapseFilesBtnSelector)?.addEventListener('click', () => { + for (const box of document.querySelectorAll('.file-content:not([data-folded="true"])')) { + if (box.getAttribute('id') === 'diff-incomplete') continue; + setFileFolding(box, box.querySelector('.fold-file'), true); + } + }); +} |