drupalorg-1.0.x-dev/js/fork_management.js
js/fork_management.js
(function (Drupal, drupalSettings, once) {
/**
* Fetches activity from a URL and renders the results.
*/
function forkAccess(forkId, action = 'check', sourceLink = '') {
const actionPath = action === 'request' ? 'request' : 'check';
const urlParams = new URLSearchParams();
urlParams.append('fork_id', forkId);
urlParams.append('format', 'json');
if (sourceLink !== '') {
urlParams.append('source_link', sourceLink);
}
return fetch(
`${drupalSettings.path.baseUrl}drupalorg-api/issue-fork/${actionPath}-access?${
urlParams
}`,
).then((response) => response.json());
}
/**
* Creates a fork.
*/
function createFork(createForkForm) {
// URL params for the controller.
const urlParams = new URLSearchParams();
urlParams.append('format', 'json');
// Build the params from the form values.
const formData = new FormData(createForkForm);
const formProps = Object.fromEntries(formData);
Object.keys(formProps).forEach(function (key) {
urlParams.append(key, formProps[key]);
});
// Do the request.
return fetch(`${createForkForm.action}?${urlParams}`).then((response) =>
response.json(),
);
}
/**
* Fetch fork and related branches information.
*/
function fetchForkInformation(force = false) {
let forksManagementWrapper = document.getElementById(
'forks-management-wrapper',
);
if (forksManagementWrapper !== null) {
// If we already have forks, we don't need to make any calls.
if (
force ||
forksManagementWrapper.getElementsByClassName('fork').length === 0
) {
const sourceLink = forksManagementWrapper.dataset.sourceLink;
const urlParams = new URLSearchParams();
urlParams.append('format', 'html');
urlParams.append('source_link', sourceLink);
return fetch(
`${drupalSettings.path.baseUrl}drupalorg/issue-fork/management?${
urlParams
}`,
)
.then((response) => response.text())
.then((response) => {
forksManagementWrapper.outerHTML = response;
// Re-attach all behaviors for the new markup.
Drupal.attachBehaviors();
// Update the variable to see if the issue title was populated.
forksManagementWrapper = document.getElementById(
'forks-management-wrapper',
);
if (forksManagementWrapper.dataset.issueTitle !== '') {
document.querySelector('h1').innerText = Drupal.t(
'Forks management: @title',
{
'@title': forksManagementWrapper.dataset.issueTitle,
},
);
}
})
.catch((error) => {
// console.log(error);
});
}
}
}
/**
* Checks if there are new branches.
*/
function pollNewBranches() {
const forksManagementWrapper = document.getElementById(
'forks-management-wrapper',
);
if (forksManagementWrapper.classList.contains('stop-polling')) {
return;
}
const sourceLink = forksManagementWrapper.dataset.sourceLink;
Array.from(forksManagementWrapper.getElementsByClassName('fork')).forEach(
function (element, index) {
const forkId = element.dataset.forkId;
const urlParams = new URLSearchParams();
urlParams.append('fork_id', forkId);
urlParams.append('source_link', sourceLink);
const forkBranches = forksManagementWrapper.querySelector(
`.fork-branches[data-fork-id="${forkId}"]`,
);
Array.from(forkBranches.getElementsByClassName('branch-link')).forEach(
(e) => {
urlParams.append('existing_branches[]', e.innerText);
},
);
// Check for new branches.
return fetch(
`${drupalSettings.path.baseUrl}drupalorg-api/issue-fork/check-branches?${
urlParams
}`,
)
.then((response) => response.json())
.then((result) => {
if (result.status && result.new_branches) {
// No need to continue polling, just fetch the new information.
forksManagementWrapper.classList.add('stop-polling');
fetchForkInformation(true);
}
})
.catch((error) => {
// console.log(error);
});
},
);
}
/**
* Updates a request button depending on the status.
*/
function updateRequestButton(
forkId,
status,
message = '',
markDisabled = false,
) {
const requestAccessLink = document.querySelector(
`.fork[data-fork-id="${forkId}"] .request-access`,
);
if (status) {
requestAccessLink.innerHTML = Drupal.t('Access granted');
} else {
requestAccessLink.innerHTML = Drupal.t('Request failed');
requestAccessLink.title = message;
}
if (markDisabled) {
requestAccessLink.classList.add('is-disabled');
}
}
Drupal.behaviors.drupalorgForkCheckAccess = {
async attach(context, settings) {
// Check access to the different forks listed, if any.
const forks = document.querySelectorAll('.fork');
if (forks.length && drupalSettings.user.uid) {
Promise.all(
Array.from(forks).map((fork) => forkAccess(fork.dataset.forkId)),
)
.then((resultsArray) => {
resultsArray.forEach((result) => {
if (result.access) {
updateRequestButton(
result.fork_id,
result.access,
result.message,
true,
);
}
});
})
.catch((error) => {
// console.log(error);
});
}
},
};
Drupal.behaviors.drupalorgForkCreateFork = {
async attach(context, settings) {
const createForkForm = document.getElementById('create-fork-form');
if (createForkForm !== null) {
const withBranch = document.getElementById('with-branch');
if (withBranch !== null) {
const branchNameWrapper = document.getElementById(
'branch-name-wrapper',
);
const sourceBranchWrapper = document.getElementById(
'source-branch-wrapper',
);
withBranch.addEventListener('change', function () {
if (this.checked) {
branchNameWrapper.style.display = '';
sourceBranchWrapper.style.display = '';
} else {
branchNameWrapper.style.display = 'none';
sourceBranchWrapper.style.display = 'none';
}
});
}
const submitButton = createForkForm.querySelector(
'input[type="submit"]',
);
submitButton.addEventListener('click', function (e) {
e.preventDefault();
if (!submitButton.classList.contains('is-disabled')) {
submitButton.value = Drupal.t('Creating issue fork...');
submitButton.classList.add('is-disabled');
createFork(createForkForm)
.then((result) => {
if (result.created) {
submitButton.value = Drupal.t('Created!');
// Reload the page.
const wrapperDiv =
document.getElementById('new-fork-wrapper');
wrapperDiv.innerHTML = Drupal.t(
'<b>Fork created!</b> Fetching new fork information...',
);
fetchForkInformation();
} else {
submitButton.value = Drupal.t('Creation failed');
if (result.message) {
alert(
Drupal.checkPlain(
`${submitButton.value}: ${result.message}`,
),
);
}
}
})
.catch((error) => {
// console.log(error);
});
}
return false;
});
}
},
};
Drupal.behaviors.drupalorgForkRequestAccess = {
async attach(context, settings) {
const requestButtons = document.querySelectorAll(
'.forks-management .request-access',
);
requestButtons.forEach(function (requestButton) {
requestButton.addEventListener('click', function (e) {
const forkId = requestButton.dataset.forkId;
const sourceLink = requestButton.dataset.sourceLink;
e.preventDefault();
if (!requestButton.classList.contains('is-disabled')) {
requestButton.innerHTML = Drupal.t('Requesting access...');
requestButton.classList.add('is-disabled');
forkAccess(forkId, 'request', sourceLink)
.then((result) => {
updateRequestButton(
result.fork_id,
result.access,
result.message,
);
})
.catch((error) => {
// console.log(error);
});
}
return false;
});
});
},
};
Drupal.behaviors.drupalorgForkFetchData = {
async attach(context, settings) {
// We only want this on the first load.
const forksContext = once('drupalorgForkFetchData', 'body', context);
if (forksContext.length) {
fetchForkInformation();
}
},
};
Drupal.behaviors.drupalorgForkPollBranches = {
async attach(context, settings) {
const forksManagementWrapper = document.getElementById(
'forks-management-wrapper',
);
// Only do it if we already have a fork, and we are not polling yet, and the user is logged in.
if (
forksManagementWrapper.getElementsByClassName('fork').length &&
!forksManagementWrapper.classList.contains('polling') &&
drupalSettings.user.uid
) {
forksManagementWrapper.classList.add('polling');
let counter = 0;
const pollingInterval = setInterval(function () {
counter++;
pollNewBranches();
// Stop polling after a minute.
if (
counter > 60 ||
forksManagementWrapper.classList.contains('stop-polling')
) {
clearInterval(pollingInterval);
}
}, 1000);
}
},
};
})(Drupal, drupalSettings, once);
