diff --git a/mig/assets/css/V3/style.css b/mig/assets/css/V3/style.css index 09e1b6890..df3cda7f3 100644 --- a/mig/assets/css/V3/style.css +++ b/mig/assets/css/V3/style.css @@ -4,7 +4,7 @@ # --- BEGIN_HEADER --- # # style - Core UI V3 specific but skin-independent styling -# Copyright (C) 2003-2019 The MiG Project lead by Brian Vinter +# Copyright (C) 2003-2024 The MiG Project lead by Brian Vinter # # This file is part of MiG. # @@ -808,3 +808,11 @@ var, sampl, code { .table-responsive .table td, .table-responsive .table th { padding: 0.5rem 1.2rem; } + +/* Highligt replacement and supplement information for published Archives */ +.archive-update-header { + background-color: #ffcc00; /* Yellow for attention */ + padding: 10px; + border: 1px solid #ff9900; + margin-bottom: 20px; +} diff --git a/mig/shared/defaults.py b/mig/shared/defaults.py index 77c92c0b8..115446022 100644 --- a/mig/shared/defaults.py +++ b/mig/shared/defaults.py @@ -306,6 +306,7 @@ public_archive_index = 'published-archive.html' public_archive_files = 'published-files.json' public_archive_doi = 'published-doi.json' +public_archive_updates = 'published-updates.json' public_doi_index = 'archive-doi-index.html' edit_lock_suffix = '.editor_lock__' diff --git a/mig/shared/freezefunctions.py b/mig/shared/freezefunctions.py index 1ea62c4d4..a942db540 100644 --- a/mig/shared/freezefunctions.py +++ b/mig/shared/freezefunctions.py @@ -41,10 +41,11 @@ brief_list, pretty_format_user, get_site_base_url from mig.shared.defaults import freeze_meta_filename, freeze_lock_filename, \ wwwpublic_alias, public_archive_dir, public_archive_index, \ - public_archive_files, public_archive_doi, freeze_flavors, keyword_final, \ - keyword_pending, keyword_updating, keyword_auto, keyword_any, \ - keyword_all, max_freeze_files, archives_cache_filename, \ - freeze_on_tape_filename, archive_marks_dir, csrf_field + public_archive_files, public_archive_doi, public_archive_updates, \ + freeze_flavors, keyword_final, keyword_pending, keyword_updating, \ + keyword_auto, keyword_any, keyword_all, max_freeze_files, \ + archives_cache_filename, freeze_on_tape_filename, archive_marks_dir, \ + csrf_field from mig.shared.fileio import checksum_file, write_file, copy_file, copy_rec, \ move_file, move_rec, remove_rec, delete_file, delete_symlink, \ makedirs_rec, make_symlink, make_temp_dir, acquire_file_lock, \ @@ -67,7 +68,7 @@ ('DESCRIPTION', 'Description')] __meta_archive_internals = [freeze_meta_filename, freeze_lock_filename] __public_archive_internals = [public_archive_index, public_archive_files, - public_archive_doi] + public_archive_doi, public_archive_updates] def brief_freeze(freeze_dict): @@ -158,10 +159,12 @@ def build_freezeitem_object(configuration, freeze_dict, summary=False, if freeze_state not in (keyword_updating, keyword_final): show_finalize = True register_doi = False + assign_updates = False if freeze_state == keyword_final and flavor != 'backup' and \ configuration.site_freeze_doi_url and \ freeze_dict.get('PUBLISH_URL', ''): register_doi = True + assign_updates = True if summary: freeze_files = len(freeze_dict.get('FILES', [])) @@ -291,6 +294,18 @@ def build_freezeitem_object(configuration, freeze_dict, summary=False, 'text': 'Request archive DOI', } freeze_obj['registerdoi_link'] = registerdoi_link + if assign_updates: + assignupdates_link = { + 'object_type': 'link', + 'destination': + "javascript: confirmDialog(%s, '%s');" % + ('assignfreezeupdates', 'Really assign archive updates for %s?' % freeze_id), + 'class': 'assignarchiveupdateslink iconspace genericbutton', + 'title': 'Assign an update for %s archive %s' % (flavor, freeze_id), + 'text': 'Assign archive replacement or supplementary archive material', + } + # TODO: implement backend to handle assigment to published-updates.json + freeze_obj['assignupdates_link'] = assignupdates_link return freeze_obj @@ -311,9 +326,9 @@ def parse_time_delta(str_value): elif unit == 'h': multiplier = 60 elif unit == 'd': - multiplier = 24*60 + multiplier = 24 * 60 elif unit == 'w': - multiplier = 7*24*60 + multiplier = 7 * 24 * 60 minutes = multiplier * count return datetime.timedelta(minutes=minutes) @@ -974,6 +989,8 @@ def write_landing_page(freeze_dict, arch_dir, frozen_files, cached, arch_url = published_url(freeze_dict, configuration) files_url = published_url(freeze_dict, configuration, public_archive_files) doi_url = published_url(freeze_dict, configuration, public_archive_doi) + updates_url = published_url( + freeze_dict, configuration, public_archive_updates) freeze_dict['PUBLISH_URL'] = arch_url _logger.debug("create landing page for %s on %s" % (freeze_id, arch_url)) publish_preamble = "" @@ -1134,11 +1151,93 @@ def write_landing_page(freeze_dict, arch_dir, frozen_files, cached, } }); } - """ % (sorted_hash_algos, files_url, doi_url) + function ajax_showupdates() { + var url = lookup_url('%s'); + console.debug('loading archive updates data from '+url+' ...'); + $('#updatescontents').html('Loading archive updates data ...'); + $('#updatescontents').addClass('spinner iconleftpad'); + var updates_req = $.ajax({ + url: url, + type: 'GET', + dataType: 'json', + success: function(jsonRes, textStatus) { + console.debug('got response from updates lookup: '+textStatus); + console.debug(jsonRes); + var updates_data = ''; + var updates_url = jsonRes.id; + /* Users can assign archive updates to a published archive. + If so the result here is a dict with the following contents: + * replaces_id: ID of another archive that this replaces + * replaces_url: URL of another archive that this replaces + * replaced_by_id: ID of another archive replacing this + * replaced_by_url: URL of another archive replacing this + + Planned but still pending additional fields for references are + * supplements_id: ID of another archive that this supplements + * supplements_url: URL of another archive that this supplements + * supplemented_by_id: ID of another archive supplementing this + * supplemented_by_url: URL of another archive supplementing this + We could make it supplements lists but it quickly gets hairy. + */ + var updates = jsonRes.updates; + if (updates !== undefined) { + updates_data += '
'; + updates_data += 'The author(s) of this archive has created the new '; + updates_data += 'public '+replaced_by_id+' archive '; + updates_data += 'as a replacement for this archive. Please refer to '; + updates_data += 'that linked new archive for additional information '; + updates_data + ='about the update and changes.
'; + updates_data += 'The author(s) of the previously published '; + updates_data += ''+replaces_id+' archive '; + updates_data += 'created this archive to replace it. Please see '; + updates_data += 'that linked old archive for additional details '; + updates_data + ='about the original publication.
+You can assign updates to already finalized published archives. This may be +useful in case you fouund errors in the existing archive or want to reference +the already published contents in another archive. +
+ +