diff --git a/swh/web/admin/deposit.py b/swh/web/admin/deposit.py index 1f88f3a0..874d070e 100644 --- a/swh/web/admin/deposit.py +++ b/swh/web/admin/deposit.py @@ -1,85 +1,91 @@ -# Copyright (C) 2018 The Software Heritage developers +# Copyright (C) 2018-2019 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 json import requests from django.core.cache import cache from django.conf import settings from django.contrib.admin.views.decorators import staff_member_required from django.core.paginator import Paginator from django.http import HttpResponse from django.shortcuts import render from requests.auth import HTTPBasicAuth from swh.web.admin.adminurls import admin_route from swh.web.config import get_config config = get_config()['deposit'] @admin_route(r'deposit/', view_name='admin-deposit') @staff_member_required(login_url=settings.LOGIN_URL) def _admin_origin_save(request): return render(request, 'admin/deposit.html') @admin_route(r'deposit/list/', view_name='admin-deposit-list') @staff_member_required(login_url=settings.LOGIN_URL) def _admin_deposit_list(request): table_data = {} table_data['draw'] = int(request.GET['draw']) deposits_list_url = config['private_api_url'] + 'deposits' deposits_list_auth = HTTPBasicAuth(config['private_api_user'], config['private_api_password']) try: nb_deposits = requests.get('%s?page_size=1' % deposits_list_url, auth=deposits_list_auth).json()['count'] deposits_data = cache.get('swh-deposit-list') if not deposits_data or deposits_data['count'] != nb_deposits: deposits_data = requests.get('%s?page_size=%s' % (deposits_list_url, nb_deposits), auth=deposits_list_auth).json() cache.set('swh-deposit-list', deposits_data) deposits = deposits_data['results'] search_value = request.GET['search[value]'] if search_value: deposits = \ [d for d in deposits if any(search_value.lower() in val for val in [str(v).lower() for v in d.values()])] column_order = request.GET['order[0][column]'] field_order = request.GET['columns[%s][name]' % column_order] order_dir = request.GET['order[0][dir]'] deposits = sorted(deposits, key=lambda d: d[field_order] or '') if order_dir == 'desc': deposits = list(reversed(deposits)) length = int(request.GET['length']) page = int(request.GET['start']) / length + 1 paginator = Paginator(deposits, length) data = paginator.page(page).object_list table_data['recordsTotal'] = deposits_data['count'] table_data['recordsFiltered'] = len(deposits) - table_data['data'] = [{'id': d['id'], - 'external_id': d['external_id'], - 'reception_date': d['reception_date'], - 'status': d['status'], - 'status_detail': d['status_detail'], - 'swh_id': d['swh_id'] - } for d in data] + table_data['data'] = [{ + 'id': d['id'], + 'external_id': d['external_id'], + 'reception_date': d['reception_date'], + 'status': d['status'], + 'status_detail': d['status_detail'], + 'swh_anchor_id': d['swh_anchor_id'], + 'swh_anchor_id_context': d['swh_anchor_id_context'], + 'swh_id': d['swh_id'], + 'swh_id_context': d['swh_id_context'] + } for d in data] + except Exception: - table_data['error'] = 'An error occurred while retrieving the list of deposits !' # noqa + table_data['error'] = ('An error occurred while retrieving ' + 'the list of deposits !') return HttpResponse(json.dumps(table_data), content_type='application/json') diff --git a/swh/web/assets/src/bundles/admin/deposit.js b/swh/web/assets/src/bundles/admin/deposit.js index a899964e..5e8493eb 100644 --- a/swh/web/assets/src/bundles/admin/deposit.js +++ b/swh/web/assets/src/bundles/admin/deposit.js @@ -1,79 +1,135 @@ +/** + * Copyright (C) 2018-2019 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 + */ + +function genSwhLink(data, type) { + if (type === 'display') { + if (data && data.startsWith('swh')) { + let browseUrl = Urls.browse_swh_id(data); + return `${data}`; + } + } + return data; +} + export function initDepositAdmin() { let depositsTable; $(document).ready(() => { $.fn.dataTable.ext.errMode = 'none'; depositsTable = $('#swh-admin-deposit-list') .on('error.dt', (e, settings, techNote, message) => { $('#swh-admin-deposit-list-error').text(message); }) .DataTable({ serverSide: true, ajax: Urls.admin_deposit_list(), columns: [ { data: 'id', name: 'id' }, { - data: 'external_id', - name: 'external_id', + data: 'swh_id_context', + name: 'swh_id_context', render: (data, type, row) => { - if (type === 'display') { - if (data && data.startsWith('hal')) { - return `${data}`; + if (data && type === 'display') { + let originPattern = ';origin='; + let originPatternIdx = data.indexOf(originPattern); + if (originPatternIdx !== -1) { + let originUrl = data.slice(originPatternIdx + originPattern.length); + return `${originUrl}`; } } return data; } }, { data: 'reception_date', name: 'reception_date', render: (data, type, row) => { if (type === 'display') { let date = new Date(data); return date.toLocaleString(); } return data; } }, { data: 'status', name: 'status' }, { data: 'status_detail', name: 'status_detail', render: (data, type, row) => { if (type === 'display' && data) { let text = data; if (typeof data === 'object') { text = JSON.stringify(data, null, 4); } return `
${text}
`; } return data; }, + orderable: false, + visible: false + }, + { + data: 'swh_anchor_id', + name: 'swh_anchor_id', + render: (data, type, row) => { + return genSwhLink(data, type); + }, orderable: false }, + { + data: 'swh_anchor_id_context', + name: 'swh_anchor_id_context', + render: (data, type, row) => { + return genSwhLink(data, type); + }, + orderable: false, + visible: false + }, { data: 'swh_id', name: 'swh_id', render: (data, type, row) => { - if (type === 'display') { - if (data && data.startsWith('swh')) { - let browseUrl = Urls.browse_swh_id(data); - return `${data}`; - } - } - return data; - } + return genSwhLink(data, type); + }, + orderable: false, + visible: false + }, + { + data: 'swh_id_context', + name: 'swh_id_context', + render: (data, type, row) => { + return genSwhLink(data, type); + }, + orderable: false, + visible: false } ], + scrollX: true, scrollY: '50vh', scrollCollapse: true, order: [[0, 'desc']] }); depositsTable.draw(); }); + + $('a.toggle-col').on('click', function(e) { + e.preventDefault(); + var column = depositsTable.column($(this).attr('data-column')); + column.visible(!column.visible()); + if (column.visible()) { + $(this).removeClass('col-hidden'); + } else { + $(this).addClass('col-hidden'); + } + }); + } diff --git a/swh/web/assets/src/bundles/webapp/webapp.css b/swh/web/assets/src/bundles/webapp/webapp.css index 27299ff3..ccf30767 100644 --- a/swh/web/assets/src/bundles/webapp/webapp.css +++ b/swh/web/assets/src/bundles/webapp/webapp.css @@ -1,477 +1,485 @@ /** - * Copyright (C) 2018 The Software Heritage developers + * Copyright (C) 2018-2019 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 */ html { height: 100%; overflow-x: hidden; } body { min-height: 100%; margin: 0; position: relative; padding-bottom: 120px; } a:active, a.active { outline: none; } code { background-color: #f9f2f4; } pre code { background-color: transparent; } footer { background-color: #262626; color: #fff; font-size: 0.8rem; position: absolute; bottom: 0; width: 100%; padding-top: 20px; padding-bottom: 20px; } footer a, footer a:visited, footer a:hover { color: #fecd1b; } footer a:hover { text-decoration: underline; } .link-color { color: #fecd1b; } pre { background-color: #f5f5f5; border: 1px solid #ccc; border-radius: 4px; padding: 9.5px; font-size: 0.8rem; } .btn.active { background-color: #e7e7e7; } .card { margin-bottom: 5px !important; overflow-x: auto; } .navbar-brand { padding: 5px; margin-right: 0; } .table { margin-bottom: 0; } .swh-table thead { background-color: #f2f4f5; border-top: 1px solid rgba(0, 0, 0, 0.2); font-weight: normal; } .swh-table-striped th { border-top: none; } .swh-table-striped tbody tr:nth-child(even) { background-color: #f2f4f5; } .swh-table-striped tbody tr:nth-child(odd) { background-color: #fff; } .swh-web-app-link a { text-decoration: none; border: none; } .swh-web-app-link:hover { background-color: #efeff2; } .table > thead > tr > th { border-top: none; border-bottom: 1px solid #e20026; } .table > tbody > tr > td { border-style: none; } .sitename .first-word, .sitename .second-word { color: rgba(0, 0, 0, 0.75); font-weight: normal; font-size: 1.2rem; } .sitename .first-word { font-family: 'Alegreya Sans', sans-serif; } .sitename .second-word { font-family: 'Alegreya', serif; } .swh-counter { font-size: 150%; } .swh-http-error { margin: 0 auto; text-align: center; } .swh-http-error-head { color: #2d353c; font-size: 30px; } .swh-http-error-code { bottom: 60%; color: #2d353c; font-size: 96px; line-height: 80px; margin-bottom: 10px !important; } .swh-http-error-desc { font-size: 12px; color: #647788; text-align: center; } .swh-http-error-desc pre { display: inline-block; text-align: left; max-width: 800px; white-space: pre-wrap; } .popover { max-width: 100%; z-index: 2000; } .modal { text-align: center; padding: 0 !important; } .modal::before { content: ''; display: inline-block; height: 100%; vertical-align: middle; margin-right: -4px; } .modal-dialog { display: inline-block; text-align: left; vertical-align: middle; } .dropdown-submenu { position: relative; } .dropdown-submenu .dropdown-menu { top: 0; left: -100%; margin-top: -5px; margin-left: -2px; } .dropdown-item:hover, .dropdown-item:focus { background-color: rgba(0, 0, 0, 0.1); } a.dropdown-left::before { content: "\f0d9"; font-family: 'FontAwesome'; display: block; width: 20px; height: 20px; float: left; margin-left: 0; } #swh-navbar { border-top-style: none; border-left-style: none; border-right-style: none; border-bottom-style: solid; border-bottom-width: 5px; border-image: linear-gradient(to right, rgb(226, 0, 38) 0%, rgb(254, 205, 27) 100%) 1 1 1 1; width: 100%; padding: 5px; margin-bottom: 10px; margin-top: 30px; justify-content: normal; flex-wrap: nowrap; height: 72px; overflow: hidden; } #back-to-top { display: initial; position: fixed; bottom: 30px; right: 30px; z-index: 10; } #back-to-top a img { display: block; width: 32px; height: 32px; background-size: 32px 32px; text-indent: -999px; overflow: hidden; } .swh-top-bar { direction: ltr; height: 30px; position: fixed; top: 0; left: 0; width: 100%; z-index: 99999; background-color: #262626; color: #fff; text-align: center; font-size: 14px; } .swh-top-bar ul { margin-top: 4px; padding-left: 0; white-space: nowrap; } .swh-top-bar li { display: inline-block; margin-left: 10px; margin-right: 10px; } .swh-top-bar a, .swh-top-bar a:visited { color: white; } .swh-top-bar a.swh-current-site, .swh-top-bar a.swh-current-site:visited { color: #fecd1b; } .swh-position-right { position: absolute; right: 0; } .swh-donate-link { border: 1px solid #fecd1b; background-color: #e20026; color: white !important; padding: 3px; border-radius: 3px; } .swh-navbar-content h4 { padding-top: 7px; } .swh-navbar-content .bread-crumbs { display: block; margin-left: -40px; } .swh-navbar-content .bread-crumbs li.bc-no-root { padding-top: 7px; } .main-sidebar { margin-top: 30px; } .content-wrapper { background: none; } .brand-image { max-height: 40px; } .brand-link { padding-top: 18.5px; padding-bottom: 18px; padding-left: 4px; border-bottom: 5px solid #e20026 !important; } .navbar-header a, ul.dropdown-menu a, ul.navbar-nav a, ul.nav-sidebar a { border-bottom-style: none; color: #323232; } .swh-sidebar .nav-link.active { color: #323232 !important; background-color: #e7e7e7 !important; } .swh-image-error { width: 80px; height: auto; } @media (max-width: 600px) { .swh-image-error { width: 40px; height: auto; } .swh-navbar-content h4 { font-size: 1rem; } } .form-check-label { padding-top: 4px; } .swh-id-option { display: inline-block; margin-right: 5px; line-height: 1rem; } .nav-pills .nav-link:not(.active):hover { color: rgba(0, 0, 0, 0.55); } .swh-heading-color { color: #e20026 !important; } .sidebar-mini.sidebar-collapse .main-sidebar:hover { width: 4.6rem; } .sidebar-mini.sidebar-collapse .main-sidebar:hover .user-panel > .info, .sidebar-mini.sidebar-collapse .main-sidebar:hover .nav-sidebar .nav-link p, .sidebar-mini.sidebar-collapse .main-sidebar:hover .brand-text { visibility: hidden !important; } .sidebar .nav-link p, .main-sidebar .brand-text, .sidebar .user-panel .info { transition: none; } .sidebar-mini.sidebar-mini.sidebar-collapse .sidebar { padding-right: 0; } .swh-words-logo { position: absolute; top: 0; left: 0; width: 73px; height: 73px; text-align: center; font-size: 10pt; color: rgba(0, 0, 0, 0.75); } .swh-words-logo:hover { text-decoration: none; } .swh-words-logo-swh { line-height: 1; padding-top: 13px; visibility: hidden; } hr.swh-faded-line { border: 0; height: 1px; background-image: linear-gradient(to left, #f0f0f0, #8c8b8b, #f0f0f0); } .swh-readme-txt pre { background: none; border: none; } .swh-coverage-col { padding-left: 10px; padding-right: 10px; } .swh-coverage { height: calc(65px + 1em); padding-top: 0.3rem; border: none; } .swh-coverage a { text-decoration: none; } .swh-coverage-logo { display: block; width: 100%; height: 50px; margin-left: auto; margin-right: auto; object-fit: contain; /* polyfill for old browsers, see https://github.com/bfred-it/object-fit-images */ font-family: 'object-fit: contain;'; } .swh-coverage-list { width: 100%; height: 320px; border: none; } tr.swh-tr-hover-highlight:hover td { background: #ededed; } tr.swh-api-doc-route a { text-decoration: none; } .swh-apidoc .col { margin: 10px; } + +a.toggle-col { + text-decoration: none; +} + +a.toggle-col.col-hidden { + text-decoration: line-through; +} diff --git a/swh/web/templates/admin/deposit.html b/swh/web/templates/admin/deposit.html index 3be8cfb8..4fd69a82 100644 --- a/swh/web/templates/admin/deposit.html +++ b/swh/web/templates/admin/deposit.html @@ -1,46 +1,63 @@ {% extends "layout.html" %} {% comment %} -Copyright (C) 2018 The Software Heritage developers +Copyright (C) 2018-2019 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 {% endcomment %} {% load swh_templatetags %} {% load render_bundle from webpack_loader %} {% block header %} {{ block.super }} {% render_bundle 'admin' %} {% endblock %} {% block title %} Deposit administration {% endblock %} {% block navbar-content %}

Deposit administration

{% endblock %} {% block content %}

The table below displays the whole list of software deposits into the archive submitted through HAL.

+ +
+ Toggle column: + id - + origin - + reception date - + status - + status detail - + revision - + revision with origin - + directory - + directory with origin +
+
- - + + - + + + +
deposit idexternal ididorigin reception date status status detailswh idrevisionrevision with origindirectorydirectory with origin

{% endblock content %} \ No newline at end of file