Changeset View
Changeset View
Standalone View
Standalone View
assets/src/bundles/admin/forge-add.js
- This file was added.
/** | |||||
* Copyright (C) 2021 The Software Heritage developers | |||||
* See the AUTHORS file at the top-level directory of this distribution | |||||
* License: GNU Affero General Public License version 3, or any later version | |||||
* See top-level LICENSE file for more information | |||||
*/ | |||||
import {handleFetchError, csrfPost, htmlAlert} from 'utils/functions'; | |||||
import {swhSpinnerSrc} from 'utils/constants'; | |||||
let authorizedForgeTable; | |||||
let unauthorizedForgeTable; | |||||
let pendingAddForgeRequestsTable; | |||||
let acceptedAddForgeRequestsTable; | |||||
let rejectedAddForgeRequestsTable; | |||||
function enableRowSelection(tableSel) { | |||||
$(`${tableSel} tbody`).on('click', 'tr', function() { | |||||
if ($(this).hasClass('selected')) { | |||||
$(this).removeClass('selected'); | |||||
$(tableSel).closest('.tab-pane').find('.swh-action-need-selection').prop('disabled', true); | |||||
} else { | |||||
$(`${tableSel} tr.selected`).removeClass('selected'); | |||||
$(this).addClass('selected'); | |||||
$(tableSel).closest('.tab-pane').find('.swh-action-need-selection').prop('disabled', false); | |||||
} | |||||
}); | |||||
} | |||||
export function initForgeAddAdmin() { | |||||
$(document).ready(() => { | |||||
$.fn.dataTable.ext.errMode = 'throw'; | |||||
authorizedForgeTable = $('#swh-authorized-forge-urls').DataTable({ | |||||
serverSide: true, | |||||
ajax: Urls.admin_forge_add_authorized_urls_list(), | |||||
columns: [{data: 'url', name: 'url'}], | |||||
scrollY: '50vh', | |||||
scrollCollapse: true, | |||||
info: false | |||||
}); | |||||
enableRowSelection('#swh-authorized-forge-urls'); | |||||
swh.webapp.addJumpToPagePopoverToDataTable(authorizedForgeTable); | |||||
unauthorizedForgeTable = $('#swh-unauthorized-forge-urls').DataTable({ | |||||
serverSide: true, | |||||
ajax: Urls.admin_forge_add_unauthorized_urls_list(), | |||||
columns: [{data: 'url', name: 'url'}], | |||||
scrollY: '50vh', | |||||
scrollCollapse: true, | |||||
info: false | |||||
}); | |||||
enableRowSelection('#swh-unauthorized-forge-urls'); | |||||
swh.webapp.addJumpToPagePopoverToDataTable(unauthorizedForgeTable); | |||||
const columnsData = [ | |||||
{ | |||||
data: 'id', | |||||
name: 'id', | |||||
visible: false, | |||||
searchable: false | |||||
}, | |||||
{ | |||||
data: 'request_date', | |||||
name: 'request_date', | |||||
render: (data, type, row) => { | |||||
if (type === 'display') { | |||||
const date = new Date(data); | |||||
return date.toLocaleString(); | |||||
} | |||||
return data; | |||||
} | |||||
}, | |||||
{ | |||||
data: 'forge_type', | |||||
name: 'forge_type' | |||||
}, | |||||
{ | |||||
data: 'forge_url', | |||||
name: 'forge_url' | |||||
} | |||||
]; | |||||
pendingAddForgeRequestsTable = $('#swh-forge-add-pending-requests').DataTable({ | |||||
serverSide: true, | |||||
processing: true, | |||||
language: { | |||||
processing: `<img src="${swhSpinnerSrc}"></img>` | |||||
}, | |||||
ajax: Urls.forge_add_requests_list('pending'), | |||||
searchDelay: 1000, | |||||
columns: columnsData, | |||||
scrollY: '50vh', | |||||
scrollCollapse: true, | |||||
order: [[0, 'desc']], | |||||
responsive: { | |||||
details: { | |||||
type: 'none' | |||||
} | |||||
} | |||||
}); | |||||
enableRowSelection('#swh-forge-add-pending-requests'); | |||||
swh.webapp.addJumpToPagePopoverToDataTable(pendingAddForgeRequestsTable); | |||||
columnsData.push({ | |||||
name: 'info', | |||||
render: (data, type, row) => { | |||||
if (row.add_task_status === 'succeeded' || row.add_task_status === 'failed' || | |||||
row.note != null) { | |||||
return `<i class="mdi mdi-information-outline swh-add-request-info" aria-hidden="true" | |||||
style="cursor: pointer" | |||||
onclick="swh.forge_add.displayForgeAddRequestInfo(event, ${row.id})"></i>`; | |||||
} else { | |||||
return ''; | |||||
} | |||||
} | |||||
}); | |||||
rejectedAddForgeRequestsTable = $('#swh-forge-add-rejected-requests').DataTable({ | |||||
serverSide: true, | |||||
processing: true, | |||||
language: { | |||||
processing: `<img src="${swhSpinnerSrc}"></img>` | |||||
}, | |||||
ajax: Urls.forge_add_requests_list('rejected'), | |||||
searchDelay: 1000, | |||||
columns: columnsData, | |||||
scrollY: '50vh', | |||||
scrollCollapse: true, | |||||
order: [[0, 'desc']], | |||||
responsive: { | |||||
details: { | |||||
type: 'none' | |||||
} | |||||
} | |||||
}); | |||||
enableRowSelection('#swh-forge-add-rejected-requests'); | |||||
swh.webapp.addJumpToPagePopoverToDataTable(rejectedAddForgeRequestsTable); | |||||
columnsData.splice(columnsData.length - 1, 0, { | |||||
data: 'add_task_status', | |||||
name: 'add_task_status' | |||||
}); | |||||
acceptedAddForgeRequestsTable = $('#swh-forge-add-accepted-requests').DataTable({ | |||||
serverSide: true, | |||||
processing: true, | |||||
language: { | |||||
processing: `<img src="${swhSpinnerSrc}"></img>` | |||||
}, | |||||
ajax: Urls.forge_add_requests_list('accepted'), | |||||
searchDelay: 1000, | |||||
columns: columnsData, | |||||
scrollY: '50vh', | |||||
scrollCollapse: true, | |||||
order: [[0, 'desc']], | |||||
responsive: { | |||||
details: { | |||||
type: 'none' | |||||
} | |||||
} | |||||
}); | |||||
enableRowSelection('#swh-forge-add-accepted-requests'); | |||||
swh.webapp.addJumpToPagePopoverToDataTable(acceptedAddForgeRequestsTable); | |||||
$('#swh-forge-add-requests-nav-item').on('shown.bs.tab', () => { | |||||
pendingAddForgeRequestsTable.draw(); | |||||
}); | |||||
$('#swh-forge-add-url-filters-nav-item').on('shown.bs.tab', () => { | |||||
authorizedForgeTable.draw(); | |||||
}); | |||||
$('#swh-authorized-forges-tab').on('shown.bs.tab', () => { | |||||
authorizedForgeTable.draw(); | |||||
}); | |||||
$('#swh-unauthorized-forges-tab').on('shown.bs.tab', () => { | |||||
unauthorizedForgeTable.draw(); | |||||
}); | |||||
$('#swh-forge-add-requests-pending-tab').on('shown.bs.tab', () => { | |||||
pendingAddForgeRequestsTable.draw(); | |||||
}); | |||||
$('#swh-forge-add-requests-accepted-tab').on('shown.bs.tab', () => { | |||||
acceptedAddForgeRequestsTable.draw(); | |||||
}); | |||||
$('#swh-forge-add-requests-rejected-tab').on('shown.bs.tab', () => { | |||||
rejectedAddForgeRequestsTable.draw(); | |||||
}); | |||||
$('#swh-forge-add-requests-pending-tab').click(() => { | |||||
pendingAddForgeRequestsTable.ajax.reload(null, false); | |||||
}); | |||||
$('#swh-forge-add-requests-accepted-tab').click(() => { | |||||
acceptedAddForgeRequestsTable.ajax.reload(null, false); | |||||
}); | |||||
$('#swh-forge-add-requests-rejected-tab').click(() => { | |||||
rejectedAddForgeRequestsTable.ajax.reload(null, false); | |||||
}); | |||||
$('body').on('click', e => { | |||||
if ($(e.target).parents('.popover').length > 0) { | |||||
e.stopPropagation(); | |||||
} else if ($(e.target).parents('.swh-add-forge-request-info').length === 0) { | |||||
$('.swh-add-forge-request-info').popover('dispose'); | |||||
} | |||||
}); | |||||
}); | |||||
} | |||||
export async function addAuthorizedForgeUrl() { | |||||
const forgeUrl = $('#swh-authorized-url-prefix').val(); | |||||
const addForgeUrl = Urls.admin_forge_add_add_authorized_url(forgeUrl); | |||||
try { | |||||
const response = await csrfPost(addForgeUrl); | |||||
handleFetchError(response); | |||||
authorizedForgeTable.row.add({'url': forgeUrl}).draw(); | |||||
$('.swh-add-authorized-forge-status').html( | |||||
htmlAlert('success', 'The forge url has been successfully added in the authorized list.', true) | |||||
); | |||||
} catch (_) { | |||||
$('.swh-add-authorized-forge-status').html( | |||||
htmlAlert('warning', 'The provided forge url prefix is already registered in the authorized list.', true) | |||||
); | |||||
} | |||||
} | |||||
export async function removeAuthorizedForgeUrl() { | |||||
const forgeUrl = $('#swh-authorized-forge-urls tr.selected').text(); | |||||
if (forgeUrl) { | |||||
const removeForgeUrl = Urls.admin_forge_add_remove_authorized_url(forgeUrl); | |||||
try { | |||||
const response = await csrfPost(removeForgeUrl); | |||||
handleFetchError(response); | |||||
authorizedForgeTable.row('.selected').remove().draw(); | |||||
} catch (_) {} | |||||
} | |||||
} | |||||
export async function addUnauthorizedForgeUrl() { | |||||
const forgeUrl = $('#swh-unauthorized-url-prefix').val(); | |||||
const addForgeUrl = Urls.admin_forge_add_add_unauthorized_url(forgeUrl); | |||||
try { | |||||
const response = await csrfPost(addForgeUrl); | |||||
handleFetchError(response); | |||||
unauthorizedForgeTable.row.add({'url': forgeUrl}).draw(); | |||||
$('.swh-add-unauthorized-forge-status').html( | |||||
htmlAlert('success', 'The forge url prefix has been successfully added in the unauthorized list.', true) | |||||
); | |||||
} catch (_) { | |||||
$('.swh-add-unauthorized-forge-status').html( | |||||
htmlAlert('warning', 'The provided forge url prefix is already registered in the unauthorized list.', true) | |||||
); | |||||
} | |||||
} | |||||
export async function removeUnauthorizedForgeUrl() { | |||||
const forgeUrl = $('#swh-unauthorized-forge-urls tr.selected').text(); | |||||
if (forgeUrl) { | |||||
const removeForgeUrl = Urls.admin_forge_add_remove_unauthorized_url(forgeUrl); | |||||
try { | |||||
const response = await csrfPost(removeForgeUrl); | |||||
handleFetchError(response); | |||||
unauthorizedForgeTable.row('.selected').remove().draw(); | |||||
} catch (_) {}; | |||||
} | |||||
} | |||||
export function acceptForgeAddRequest() { | |||||
const selectedRow = pendingAddForgeRequestsTable.row('.selected'); | |||||
if (selectedRow.length) { | |||||
const acceptForgeAddRequestCallback = async() => { | |||||
const rowData = selectedRow.data(); | |||||
const acceptAddRequestUrl = Urls.admin_forge_add_request_accept(rowData['visit_type'], rowData['forge_url']); | |||||
await csrfPost(acceptAddRequestUrl); | |||||
pendingAddForgeRequestsTable.ajax.reload(null, false); | |||||
}; | |||||
swh.webapp.showModalConfirm( | |||||
'Accept forge add request ?', | |||||
'Are you sure to accept this forge add request ?', | |||||
acceptForgeAddRequestCallback); | |||||
} | |||||
} | |||||
const rejectModalHtml = ` | |||||
<form id="swh-rejection-form"> | |||||
<div class="form-group row"> | |||||
<label for="swh-rejection-reason" class="col-4 col-form-label"> | |||||
Rejection reason: | |||||
</label> | |||||
<div class="col-8"> | |||||
<select class="custom-select" id="swh-rejection-reason"> | |||||
<option value="custom" selected>Custom</option> | |||||
<option value="invalid-forge">Invalid forge</option> | |||||
<option value="invalid-forge-type">Invalid forge type</option> | |||||
<option value="forge-not-found">Forge not found</option> | |||||
</select> | |||||
</div> | |||||
</div> | |||||
<div class="form-group row"> | |||||
<textarea class="form-control" id="swh-rejection-text"></textarea> | |||||
</div> | |||||
<button type="submit" class="btn btn-default float-right" id="swh-rejection-submit"> | |||||
Reject | |||||
</button> | |||||
</form> | |||||
`; | |||||
export function rejectForgeAddRequest() { | |||||
const selectedRow = pendingAddForgeRequestsTable.row('.selected'); | |||||
const rowData = selectedRow.data(); | |||||
if (selectedRow.length) { | |||||
const rejectForgeAddRequestCallback = async() => { | |||||
$('#swh-web-modal-html').modal('hide'); | |||||
const rejectAddRequestUrl = Urls.admin_forge_add_request_reject( | |||||
rowData['visit_type'], rowData['forge_url']); | |||||
await csrfPost(rejectAddRequestUrl, {}, | |||||
JSON.stringify({note: $('#swh-rejection-text').val()})); | |||||
pendingAddForgeRequestsTable.ajax.reload(null, false); | |||||
}; | |||||
let currentRejectionReason = 'custom'; | |||||
const rejectionTexts = {}; | |||||
swh.webapp.showModalHtml('Reject forge add request ?', rejectModalHtml); | |||||
$('#swh-rejection-reason').on('change', (event) => { | |||||
// backup current textarea value | |||||
rejectionTexts[currentRejectionReason] = $('#swh-rejection-text').val(); | |||||
currentRejectionReason = event.target.value; | |||||
let newRejectionText = ''; | |||||
if (rejectionTexts.hasOwnProperty(currentRejectionReason)) { | |||||
// restore previous textarea value | |||||
newRejectionText = rejectionTexts[currentRejectionReason]; | |||||
} else { | |||||
// fill textarea with default text according to rejection type | |||||
if (currentRejectionReason === 'invalid-forge') { | |||||
newRejectionText = `The forge with URL ${rowData['forge_url']} is not ` + | |||||
`a link to a ${rowData['visit_type']} repository.`; | |||||
} else if (currentRejectionReason === 'invalid-forge-type') { | |||||
newRejectionText = `The forge with URL ${rowData['forge_url']} is not ` + | |||||
`of type ${rowData['visit_type']}.`; | |||||
} else if (currentRejectionReason === 'forge-not-found') { | |||||
newRejectionText = `The forge with URL ${rowData['forge_url']} cannot be found.`; | |||||
} | |||||
} | |||||
$('#swh-rejection-text').val(newRejectionText); | |||||
}); | |||||
$('#swh-rejection-form').on('submit', (event) => { | |||||
event.preventDefault(); | |||||
event.stopPropagation(); | |||||
// ensure confirmation modal will be displayed above the html modal | |||||
$('#swh-web-modal-html').css('z-index', 4000); | |||||
swh.webapp.showModalConfirm( | |||||
'Reject forge add request ?', | |||||
'Are you sure to reject this forge add request ?', | |||||
rejectForgeAddRequestCallback); | |||||
}); | |||||
} | |||||
} | |||||
function removeForgeAddRequest(requestTable) { | |||||
const selectedRow = requestTable.row('.selected'); | |||||
if (selectedRow.length) { | |||||
const requestId = selectedRow.data()['id']; | |||||
const removeForgeAddRequestCallback = async() => { | |||||
const removeAddRequestUrl = Urls.admin_forge_add_request_remove(requestId); | |||||
await csrfPost(removeAddRequestUrl); | |||||
requestTable.ajax.reload(null, false); | |||||
}; | |||||
swh.webapp.showModalConfirm( | |||||
'Remove forge add request ?', | |||||
'Are you sure to remove this forge add request ?', | |||||
removeForgeAddRequestCallback); | |||||
} | |||||
} | |||||
export function removePendingForgeAddRequest() { | |||||
removeForgeAddRequest(pendingAddForgeRequestsTable); | |||||
} | |||||
export function removeAcceptedForgeAddRequest() { | |||||
removeForgeAddRequest(acceptedAddForgeRequestsTable); | |||||
} | |||||
export function removeRejectedForgeAddRequest() { | |||||
removeForgeAddRequest(rejectedAddForgeRequestsTable); | |||||
} |