" \t// The module cache\n\tvar installedModules = {};\n\n\t// The require function\n\tfunction __webpack_require__(moduleId) {\n\n\t\t// Check if module is in cache\n\t\tif(installedModules[moduleId]) {\n\t\t\treturn installedModules[moduleId].exports;\n\t\t}\n\t\t// Create a new module (and put it into the cache)\n\t\tvar module = installedModules[moduleId] = {\n\t\t\ti: moduleId,\n\t\t\tl: false,\n\t\t\texports: {}\n\t\t};\n\n\t\t// Execute the module function\n\t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t\t// Flag the module as loaded\n\t\tmodule.l = true;\n\n\t\t// Return the exports of the module\n\t\treturn module.exports;\n\t}\n\n\n\t// expose the modules object (__webpack_modules__)\n\t__webpack_require__.m = modules;\n\n\t// expose the module cache\n\t__webpack_require__.c = installedModules;\n\n\t// define getter function for harmony exports\n\t__webpack_require__.d = function(exports, name, getter) {\n\t\tif(!__webpack_require__.o(exports, name)) {\n\t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n\t\t}\n\t};\n\n\t// define __esModule on exports\n\t__webpack_require__.r = function(exports) {\n\t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t\t}\n\t\tObject.defineProperty(exports, '__esModule', { value: true });\n\t};\n\n\t// create a fake namespace object\n\t// mode & 1: value is a module id, require it\n\t// mode & 2: merge all properties of value into the ns\n\t// mode & 4: return value when already ns object\n\t// mode & 8|1: behave like require\n\t__webpack_require__.t = function(value, mode) {\n\t\tif(mode & 1) value = __webpack_require__(value);\n\t\tif(mode & 8) return value;\n\t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n\t\tvar ns = Object.create(null);\n\t\t__webpack_require__.r(ns);\n\t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n\t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n\t\treturn ns;\n\t};\n\n\t// getDefaultExport function for compatibility with non-harmony modules\n\t__webpack_require__.n = function(module) {\n\t\tvar getter = module && module.__esModule ?\n\t\t\tfunction getDefault() { return module['default']; } :\n\t\t\tfunction getModuleExports() { return module; };\n\t\t__webpack_require__.d(getter, 'a', getter);\n\t\treturn getter;\n\t};\n\n\t// Object.prototype.hasOwnProperty.call\n\t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n\t// __webpack_public_path__\n\t__webpack_require__.p = \"/static/\";\n\n\n\t// Load entry module and return exports\n\treturn __webpack_require__(__webpack_require__.s = 264);\n",
"/**\n * Copyright (C) 2018-2019 The Software Heritage developers\n * See the AUTHORS file at the top-level directory of this distribution\n * License: GNU Affero General Public License version 3, or any later version\n * See top-level LICENSE file for more information\n */\n\nimport {handleFetchError, handleFetchErrors, csrfPost} from 'utils/functions';\nimport vaultTableRowTemplate from './vault-table-row.ejs';\n\nlet progress =\n `<div class=\"progress\">\n <div class=\"progress-bar progress-bar-success progress-bar-striped\"\n role=\"progressbar\" aria-valuenow=\"100\" aria-valuemin=\"0\"\n aria-valuemax=\"100\" style=\"width: 100%;height: 100%;\">\n </div>\n </div>;`;\n\nlet pollingInterval = 5000;\nlet checkVaultId;\n\nfunction updateProgressBar(progressBar, cookingTask) {\n if (cookingTask.status === 'new') {\n progressBar.css('background-color', 'rgba(128, 128, 128, 0.5)');\n } else if (cookingTask.status === 'pending') {\n progressBar.css('background-color', 'rgba(0, 0, 255, 0.5)');\n } else if (cookingTask.status === 'done') {\n progressBar.css('background-color', '#5cb85c');\n } else if (cookingTask.status === 'failed') {\n progressBar.css('background-color', 'rgba(255, 0, 0, 0.5)');\n progressBar.css('background-image', 'none');\n }\n progressBar.text(cookingTask.progress_message || cookingTask.status);\n if (cookingTask.status === 'new' || cookingTask.status === 'pending') {\n progressBar.addClass('progress-bar-animated');\n } else {\n progressBar.removeClass('progress-bar-striped');\n }\n}\n\nlet recookTask;\n\n// called when the user wants to download a cooked archive\nexport function fetchCookedObject(fetchUrl) {\n recookTask = null;\n // first, check if the link is still available from the vault\n fetch(fetchUrl)\n .then(response => {\n // link is still alive, proceed to download\n if (response.ok) {\n $('#vault-fetch-iframe').attr('src', fetchUrl);\n // link is dead\n } else {\n // get the associated cooking task\n let vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));\n for (let i = 0; i < vaultCookingTasks.length; ++i) {\n if (vaultCookingTasks[i].fetch_url === fetchUrl) {\n recookTask = vaultCookingTasks[i];\n break;\n }\n }\n // display a modal asking the user if he wants to recook the archive\n $('#vault-recook-object-modal').modal('show');\n }\n });\n}\n\n// called when the user wants to recook an archive\n// for which the download link is not available anymore\nexport function recookObject() {\n if (recookTask) {\n // stop cooking tasks status polling\n clearTimeout(checkVaultId);\n // build cook request url\n let cookingUrl;\n if (recookTask.object_type === 'directory') {\n cookingUrl = Urls.api_1_vault_cook_directory(recookTask.object_id);\n } else {\n cookingUrl = Urls.api_1_vault_cook_revision_gitfast(recookTask.object_id);\n }\n if (recookTask.email) {\n cookingUrl += '?email=' + recookTask.email;\n }\n // request archive cooking\n csrfPost(cookingUrl)\n .then(handleFetchError)\n .then(() => {\n // update task status\n recookTask.status = 'new';\n let vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));\n for (let i = 0; i < vaultCookingTasks.length; ++i) {\n if (vaultCookingTasks[i].object_id === recookTask.object_id) {\n vaultCookingTasks[i] = recookTask;\n break;\n }\n }\n // save updated tasks to local storage\n localStorage.setItem('swh-vault-cooking-tasks', JSON.stringify(vaultCookingTasks));\n // restart cooking tasks status polling\n checkVaultCookingTasks();\n // hide recook archive modal\n $('#vault-recook-object-modal').modal('hide');\n })\n // something went wrong\n .catch(() => {\n checkVaultCookingTasks();\n $('#vault-recook-object-modal').modal('hide');\n });\n }\n}\n\nfunction checkVaultCookingTasks() {\n let vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));\n if (!vaultCookingTasks || vaultCookingTasks.length === 0) {\n $('.swh-vault-table tbody tr').remove();\n checkVaultId = setTimeout(checkVaultCookingTasks, pollingInterval);\n return;\n }\n let cookingTaskRequests = [];\n let tasks = {};\n let currentObjectIds = [];\n\n for (let i = 0; i < vaultCookingTasks.length; ++i) {\n let cookingTask = vaultCookingTasks[i];\n currentObjectIds.push(cookingTask.object_id);\n tasks[cookingTask.object_id] = cookingTask;\n let cookingUrl;\n if (cookingTask.object_type === 'directory') {\n cookingUrl = Urls.api_1_vault_cook_directory(cookingTask.object_id);\n } else {\n cookingUrl = Urls.api_1_vault_cook_revision_gitfast(cookingTask.object_id);\n }\n if (cookingTask.status !== 'done' && cookingTask.status !== 'failed') {\n cookingTaskRequests.push(fetch(cookingUrl));\n }\n }\n $('.swh-vault-table tbody tr').each((i, row) => {\n let objectId = $(row).find('.vault-object-info').data('object-id');\n if ($.inArray(objectId, currentObjectIds) === -1) {\n $(row).remove();\n }\n });\n Promise.all(cookingTaskRequests)\n .then(handleFetchErrors)\n .then(responses => Promise.all(responses.map(r => r.json())))\n .then(cookingTasks => {\n let table = $('#vault-cooking-tasks tbody');\n for (let i = 0; i < cookingTasks.length; ++i) {\n let cookingTask = tasks[cookingTasks[i].obj_id];\n cookingTask.status = cookingTasks[i].status;\n cookingTask.fetch_url = cookingTasks[i].fetch_url;\n cookingTask.progress_message = cookingTasks[i].progress_message;\n }\n for (let i = 0; i < vaultCookingTasks.length; ++i) {\n let cookingTask = vaultCookingTasks[i];\n let rowTask = $(`#vault-task-${cookingTask.object_id}`);\n\n if (!rowTask.length) {\n\n let browseUrl = cookingTask.browse_url;\n if (!browseUrl) {\n if (cookingTask.object_type === 'directory') {\n browseUrl = Urls.browse_directory(cookingTask.object_id);\n } else {\n browseUrl = Urls.browse_revision(cookingTask.object_id);\n }\n }\n\n let progressBar = $.parseHTML(progress)[0];\n let progressBarContent = $(progressBar).find('.progress-bar');\n updateProgressBar(progressBarContent, cookingTask);\n table.prepend(vaultTableRowTemplate({\n browseUrl: browseUrl,\n cookingTask: cookingTask,\n progressBar: progressBar,\n Urls: Urls,\n swh: swh\n }));\n } else {\n let progressBar = rowTask.find('.progress-bar');\n updateProgressBar(progressBar, cookingTask);\n let downloadLink = rowTask.find('.vault-dl-link');\n if (cookingTask.status === 'done') {\n downloadLink[0].innerHTML =\n '<button class=\"btn btn-default btn-sm\" ' +\n `onclick=\"swh.vault.fetchCookedObject('${cookingTask.fetch_url}')\">` +\n '<i class=\"mdi mdi-download mdi-fw\" aria-hidden=\"true\"></i>Download</button>';\n } else {\n downloadLink[0].innerHTML = '';\n }\n }\n }\n localStorage.setItem('swh-vault-cooking-tasks', JSON.stringify(vaultCookingTasks));\n checkVaultId = setTimeout(checkVaultCookingTasks, pollingInterval);\n })\n .catch(() => {});\n}\n\nexport function removeCookingTaskInfo(tasksToRemove) {\n let vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));\n if (!vaultCookingTasks) {\n return;\n }\n vaultCookingTasks = $.grep(vaultCookingTasks, task => {\n return $.inArray(task.object_id, tasksToRemove) === -1;\n });\n localStorage.setItem('swh-vault-cooking-tasks', JSON.stringify(vaultCookingTasks));\n}\n\nexport function initUi() {\n\n $('#vault-tasks-toggle-selection').change(event => {\n $('.vault-task-toggle-selection').prop('checked', event.currentTarget.checked);\n });\n\n $('#vault-remove-tasks').click(() => {\n clearTimeout(checkVaultId);\n let tasksToRemove = [];\n $('.swh-vault-table tbody tr').each((i, row) => {\n let taskSelected = $(row).find('.vault-task-toggle-selection').prop('checked');\n if (taskSelected) {\n let objectId = $(row).find('.vault-object-info').data('object-id');\n tasksToRemove.push(objectId);\n $(row).remove();\n }\n });\n removeCookingTaskInfo(tasksToRemove);\n $('#vault-tasks-toggle-selection').prop('checked', false);\n checkVaultId = setTimeout(checkVaultCookingTasks, pollingInterval);\n });\n\n checkVaultCookingTasks();\n\n window.onfocus = () => {\n clearTimeout(checkVaultId);\n checkVaultCookingTasks();\n };\n\n}\n",
"/**\n * Copyright (C) 2018-2019 The Software Heritage developers\n * See the AUTHORS file at the top-level directory of this distribution\n * License: GNU Affero General Public License version 3, or any later version\n * See top-level LICENSE file for more information\n */\n\nimport {handleFetchError, csrfPost, htmlAlert} from 'utils/functions';\n\nconst alertStyle = {\n 'position': 'fixed',\n 'left': '1rem',\n 'bottom': '1rem',\n 'z-index': '100000'\n};\n\nexport function vaultRequest(objectType, objectId) {\n let vaultUrl;\n if (objectType === 'directory') {\n vaultUrl = Urls.api_1_vault_cook_directory(objectId);\n } else {\n vaultUrl = Urls.api_1_vault_cook_revision_gitfast(objectId);\n }\n // check if object has already been cooked\n fetch(vaultUrl)\n .then(response => response.json())\n .then(data => {\n // object needs to be cooked\n if (data.exception === 'NotFoundExc' || data.status === 'failed') {\n // if last cooking has failed, remove previous task info from localStorage\n // in order to force the recooking of the object\n swh.vault.removeCookingTaskInfo([objectId]);\n $(`#vault-cook-${objectType}-modal`).modal('show');\n // object has been cooked and should be in the vault cache,\n // it will be asked to cook it again if it is not\n } else if (data.status === 'done') {\n $(`#vault-fetch-${objectType}-modal`).modal('show');\n } else {\n const cookingServiceDownAlert =\n $(htmlAlert('danger',\n 'Archive cooking service is currently experiencing issues.<br/>' +\n 'Please try again later.',\n true));\n cookingServiceDownAlert.css(alertStyle);\n $('body').append(cookingServiceDownAlert);\n }\n });\n}\n\nfunction addVaultCookingTask(cookingTask) {\n\n const swhidsContext = swh.webapp.getSwhIdsContext();\n cookingTask.origin = swhidsContext[cookingTask.object_type].context.origin;\n cookingTask.path = swhidsContext[cookingTask.object_type].context.path;\n cookingTask.browse_url = swhidsContext[cookingTask.object_type].swhid_with_context_url;\n if (!cookingTask.browse_url) {\n cookingTask.browse_url = swhidsContext[cookingTask.object_type].swhid_url;\n }\n\n let vaultCookingTasks = JSON.parse(localStorage.getItem('swh-vault-cooking-tasks'));\n if (!vaultCookingTasks) {\n vaultCookingTasks = [];\n }\n if (vaultCookingTasks.find(val => {\n return val.object_type === cookingTask.object_type &&\n val.object_id === cookingTask.object_id;\n }) === undefined) {\n let cookingUrl;\n if (cookingTask.object_type === 'directory') {\n cookingUrl = Urls.api_1_vault_cook_directory(cookingTask.object_id);\n } else {\n cookingUrl = Urls.api_1_vault_cook_revision_gitfast(cookingTask.object_id);\n }\n if (cookingTask.email) {\n cookingUrl += '?email=' + cookingTask.email;\n }\n\n csrfPost(cookingUrl)\n .then(handleFetchError)\n .then(() => {\n vaultCookingTasks.push(cookingTask);\n localStorage.setItem('swh-vault-cooking-tasks', JSON.stringify(vaultCookingTasks));\n $('#vault-cook-directory-modal').modal('hide');\n $('#vault-cook-revision-modal').modal('hide');\n const cookingTaskCreatedAlert =\n $(htmlAlert('success',\n 'Archive cooking request successfully submitted.<br/>' +\n `Go to the <a href=\"${Urls.browse_vault()}\">Downloads</a> page ` +\n 'to get the download link once it is ready.',\n true));\n cookingTaskCreatedAlert.css(alertStyle);\n $('body').append(cookingTaskCreatedAlert);\n })\n .catch(() => {\n $('#vault-cook-directory-modal').modal('hide');\n $('#vault-cook-revision-modal').modal('hide');\n const cookingTaskFailedAlert =\n $(htmlAlert('danger',\n 'Archive cooking request submission failed.',\n true));\n cookingTaskFailedAlert.css(alertStyle);\n $('body').append(cookingTaskFailedAlert);\n });\n }\n}\n\nfunction validateEmail(email) {\n let re = /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n return re.test(String(email).toLowerCase());\n}\n\nexport function cookDirectoryArchive(directoryId) {\n let email = $('#swh-vault-directory-email').val().trim();\n if (!email || validateEmail(email)) {\n let cookingTask = {\n 'object_type': 'directory',\n 'object_id': directoryId,\n 'email': email,\n 'status': 'new'\n };\n addVaultCookingTask(cookingTask);\n\n } else {\n $('#invalid-email-modal').modal('show');\n }\n}\n\nexport function fetchDirectoryArchive(directoryId) {\n $('#vault-fetch-directory-modal').modal('hide');\n const vaultUrl = Urls.api_1_vault_cook_directory(directoryId);\n fetch(vaultUrl)\n .then(response => response.json())\n .then(data => {\n swh.vault.fetchCookedObject(data.fetch_url);\n });\n}\n\nexport function cookRevisionArchive(revisionId) {\n let email = $('#swh-vault-revision-email').val().trim();\n if (!email || validateEmail(email)) {\n let cookingTask = {\n 'object_type': 'revision',\n 'object_id': revisionId,\n 'email': email,\n 'status': 'new'\n };\n addVaultCookingTask(cookingTask);\n } else {\n $('#invalid-email-modal').modal('show');\n }\n}\n\nexport function fetchRevisionArchive(revisionId) {\n $('#vault-fetch-directory-modal').modal('hide');\n const vaultUrl = Urls.api_1_vault_cook_revision_gitfast(revisionId);\n fetch(vaultUrl)\n .then(response => response.json())\n .then(data => {\n swh.vault.fetchCookedObject(data.fetch_url);\n });\n}\n",
"/**\n * Copyright (C) 2018-2020 The Software Heritage developers\n * See the AUTHORS file at the top-level directory of this distribution\n * License: GNU Affero General Public License version 3, or any later version\n * See top-level LICENSE file for more information\n */\n\n// utility functions\n\nexport function handleFetchError(response) {\n if (!response.ok) {\n throw response;\n }\n return response;\n}\n\nexport function handleFetchErrors(responses) {\n for (let i = 0; i < responses.length; ++i) {\n if (!responses[i].ok) {\n throw responses[i];\n }\n }\n return responses;\n}\n\nexport function staticAsset(asset) {\n return `${__STATIC__}${asset}`;\n}\n\nexport function csrfPost(url, headers = {}, body = null) {\n headers['X-CSRFToken'] = Cookies.get('csrftoken');\n return fetch(url, {\n credentials: 'include',\n headers: headers,\n method: 'POST',\n body: body\n });\n}\n\nexport function isGitRepoUrl(url, domain) {\n let endOfPattern = '\\\\/[\\\\w\\\\.-]+\\\\/?(?!=.git)(?:\\\\.git(?:\\\\/?|\\\\#[\\\\w\\\\.\\\\-_]+)?)?$';\n let pattern = `(?:git|https?|git@)(?:\\\\:\\\\/\\\\/)?${domain}[/|:][A-Za-z0-9-/]+?` + endOfPattern;\n let re = new RegExp(pattern);\n return re.test(url);\n};\n\nexport function removeUrlFragment() {\n history.replaceState('', document.title, window.location.pathname + window.location.search);\n}\n\nexport function selectText(startNode, endNode) {\n let selection = window.getSelection();\n selection.removeAllRanges();\n let range = document.createRange();\n range.setStart(startNode, 0);\n if (endNode.nodeName !== '#text') {\n range.setEnd(endNode, endNode.childNodes.length);\n } else {\n range.setEnd(endNode, endNode.textContent.length);\n }\n selection.addRange(range);\n}\n\nexport function htmlAlert(type, message, closable = false) {\n let closeButton = '';\n let extraClasses = '';\n if (closable) {\n closeButton =\n `<button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-label=\"Close\">\n <span aria-hidden=\"true\">×</span>\n </button>`;\n extraClasses = 'alert-dismissible';\n }\n return `<div class=\"alert alert-${type} ${extraClasses}\" role=\"alert\">${message}${closeButton}</div>`;\n}\n",
"/**\n * Copyright (C) 2018 The Software Heritage developers\n * See the AUTHORS file at the top-level directory of this distribution\n * License: GNU Affero General Public License version 3, or any later version\n * See top-level LICENSE file for more information\n */\n\n// bundle for the vault related views\n\nimport './vault.css';\nexport * from './vault-ui';\nexport * from './vault-create-tasks';\n"