Page MenuHomeSoftware Heritage

D2320.id8017.diff
No OneTemporary

D2320.id8017.diff

diff --git a/cypress/integration/persistent-identifiers.spec.js b/cypress/integration/persistent-identifiers.spec.js
--- a/cypress/integration/persistent-identifiers.spec.js
+++ b/cypress/integration/persistent-identifiers.spec.js
@@ -5,14 +5,15 @@
* See top-level LICENSE file for more information
*/
-let origin;
-let url;
+let origin, originBadgeUrl, originBrowseUrl;
+let url, urlPrefix;
let browsedObjectMetadata;
let cntPid, cntPidWithOrigin, cntPidWithOriginAndLines;
let dirPid, dirPidWithOrigin;
let relPid, relPidWithOrigin;
let revPid, revPidWithOrigin;
let snpPid, snpPidWithOrigin;
+let testsData;
const firstSelLine = 6;
const lastSelLine = 12;
@@ -22,10 +23,13 @@
origin = this.origin[1];
url = this.Urls.browse_origin_content(origin.url, origin.content[0].path);
url = `${url}?release=${origin.release}#L${firstSelLine}-L${lastSelLine}`;
- });
-
- beforeEach(function() {
+ originBadgeUrl = this.Urls.swh_badge('origin', origin.url);
+ originBrowseUrl = this.Urls.browse_origin(origin.url);
cy.visit(url).window().then(win => {
+ urlPrefix = `${win.location.protocol}//${win.location.hostname}`;
+ if (win.location.port) {
+ urlPrefix += `:${win.location.port}`;
+ }
browsedObjectMetadata = win.swh.webapp.getBrowsedSwhObjectMetadata();
cntPid = `swh:1:cnt:${browsedObjectMetadata.sha1_git}`;
cntPidWithOrigin = `${cntPid};origin=${origin.url}`;
@@ -38,9 +42,52 @@
relPidWithOrigin = `${relPid};origin=${origin.url}`;
snpPid = `swh:1:snp:${browsedObjectMetadata.snapshot}`;
snpPidWithOrigin = `${snpPid};origin=${origin.url}`;
+
+ testsData = [
+ {
+ 'objectType': 'content',
+ 'objectPids': [cntPidWithOriginAndLines, cntPidWithOrigin, cntPid],
+ 'badgeUrl': this.Urls.swh_badge('content', browsedObjectMetadata.sha1_git),
+ 'badgePidUrl': this.Urls.swh_badge_pid(cntPidWithOriginAndLines),
+ 'browseUrl': this.Urls.browse_swh_id(cntPidWithOriginAndLines)
+ },
+ {
+ 'objectType': 'directory',
+ 'objectPids': [dirPidWithOrigin, dirPid],
+ 'badgeUrl': this.Urls.swh_badge('directory', browsedObjectMetadata.directory),
+ 'badgePidUrl': this.Urls.swh_badge_pid(dirPidWithOrigin),
+ 'browseUrl': this.Urls.browse_swh_id(dirPidWithOrigin)
+ },
+ {
+ 'objectType': 'release',
+ 'objectPids': [relPidWithOrigin, relPid],
+ 'badgeUrl': this.Urls.swh_badge('release', browsedObjectMetadata.release),
+ 'badgePidUrl': this.Urls.swh_badge_pid(relPidWithOrigin),
+ 'browseUrl': this.Urls.browse_swh_id(relPidWithOrigin)
+ },
+ {
+ 'objectType': 'revision',
+ 'objectPids': [revPidWithOrigin, revPid],
+ 'badgeUrl': this.Urls.swh_badge('revision', browsedObjectMetadata.revision),
+ 'badgePidUrl': this.Urls.swh_badge_pid(revPidWithOrigin),
+ 'browseUrl': this.Urls.browse_swh_id(revPidWithOrigin)
+ },
+ {
+ 'objectType': 'snapshot',
+ 'objectPids': [snpPidWithOrigin, snpPid],
+ 'badgeUrl': this.Urls.swh_badge('snapshot', browsedObjectMetadata.snapshot),
+ 'badgePidUrl': this.Urls.swh_badge_pid(snpPidWithOrigin),
+ 'browseUrl': this.Urls.browse_swh_id(snpPidWithOrigin)
+ }
+ ];
+
});
});
+ beforeEach(function() {
+ cy.visit(url);
+ });
+
it('should open and close identifiers tab when clicking on handle', function() {
cy.get('#swh-identifiers')
.should('have.class', 'ui-slideouttab-ready');
@@ -63,30 +110,7 @@
cy.get('.ui-slideouttab-handle')
.click();
- const testData = [
- {
- 'objectType': 'content',
- 'objectPid': cntPidWithOriginAndLines
- },
- {
- 'objectType': 'directory',
- 'objectPid': dirPidWithOrigin
- },
- {
- 'objectType': 'release',
- 'objectPid': relPidWithOrigin
- },
- {
- 'objectType': 'revision',
- 'objectPid': revPidWithOrigin
- },
- {
- 'objectType': 'snapshot',
- 'objectPid': snpPidWithOrigin
- }
- ];
-
- for (let td of testData) {
+ for (let td of testsData) {
cy.get(`a[href="#swh-id-tab-${td.objectType}"]`)
.click();
@@ -94,8 +118,8 @@
.should('be.visible');
cy.get(`#swh-id-tab-${td.objectType} .swh-id`)
- .contains(td.objectPid)
- .should('have.attr', 'href', this.Urls.browse_swh_id(td.objectPid));
+ .contains(td.objectPids[0])
+ .should('have.attr', 'href', this.Urls.browse_swh_id(td.objectPids[0]));
}
@@ -143,26 +167,11 @@
cy.get('.ui-slideouttab-handle')
.click();
- const testData = [
- {
- 'objectType': 'directory',
- 'objectPids': [dirPidWithOrigin, dirPid]
- },
- {
- 'objectType': 'release',
- 'objectPids': [relPidWithOrigin, relPid]
- },
- {
- 'objectType': 'revision',
- 'objectPids': [revPidWithOrigin, revPid]
- },
- {
- 'objectType': 'snapshot',
- 'objectPids': [snpPidWithOrigin, snpPid]
- }
- ];
+ for (let td of testsData) {
+
+ // already tested
+ if (td.objectType === 'content') continue;
- for (let td of testData) {
cy.get(`a[href="#swh-id-tab-${td.objectType}"]`)
.click();
@@ -187,4 +196,64 @@
});
+ it('should display swh badges in identifiers tab for browsed objects', function() {
+ cy.get('.ui-slideouttab-handle')
+ .click();
+
+ const originBadgeUrl = this.Urls.swh_badge('origin', origin.url);
+
+ for (let td of testsData) {
+ cy.get(`a[href="#swh-id-tab-${td.objectType}"]`)
+ .click();
+
+ cy.get(`#swh-id-tab-${td.objectType} .swh-badge-origin`)
+ .should('have.attr', 'src', originBadgeUrl);
+
+ cy.get(`#swh-id-tab-${td.objectType} .swh-badge-${td.objectType}`)
+ .should('have.attr', 'src', td.badgeUrl);
+
+ }
+
+ });
+
+ it('should display badge integration info when clicking on it', function() {
+
+ cy.get('.ui-slideouttab-handle')
+ .click();
+
+ for (let td of testsData) {
+ cy.get(`a[href="#swh-id-tab-${td.objectType}"]`)
+ .click();
+
+ cy.get(`#swh-id-tab-${td.objectType} .swh-badge-origin`)
+ .click()
+ .wait(500);
+
+ for (let badgeType of ['html', 'md', 'rst']) {
+ cy.get(`.modal .swh-badge-${badgeType}`)
+ .contains(`${urlPrefix}${originBrowseUrl}`)
+ .contains(`${urlPrefix}${originBadgeUrl}`);
+ }
+
+ cy.get('.modal.show .close')
+ .click()
+ .wait(500);
+
+ cy.get(`#swh-id-tab-${td.objectType} .swh-badge-${td.objectType}`)
+ .click()
+ .wait(500);
+
+ for (let badgeType of ['html', 'md', 'rst']) {
+ cy.get(`.modal .swh-badge-${badgeType}`)
+ .contains(`${urlPrefix}${td.browseUrl}`)
+ .contains(`${urlPrefix}${td.badgePidUrl}`);
+ }
+
+ cy.get('.modal.show .close')
+ .click()
+ .wait(500);
+
+ }
+ });
+
});
diff --git a/swh/web/assets/src/bundles/browse/swh-ids-utils.js b/swh/web/assets/src/bundles/browse/swh-ids-utils.js
--- a/swh/web/assets/src/bundles/browse/swh-ids-utils.js
+++ b/swh/web/assets/src/bundles/browse/swh-ids-utils.js
@@ -88,6 +88,7 @@
let tabSlideOptions = {
tabLocation: 'right',
+ clickScreenToCloseFilters: ['.ui-slideouttab-panel', '.modal'],
offset: function() {
const width = $(window).width();
if (width < BREAKPOINT_SM) {
diff --git a/swh/web/assets/src/bundles/webapp/badges.js b/swh/web/assets/src/bundles/webapp/badges.js
new file mode 100644
--- /dev/null
+++ b/swh/web/assets/src/bundles/webapp/badges.js
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 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
+ */
+
+export function showBadgeInfoModal(objectType, objectPid) {
+ let badgeImageUrl;
+ let badgeLinkUrl;
+ if (objectType === 'origin') {
+ badgeImageUrl = Urls.swh_badge(objectType, objectPid);
+ badgeLinkUrl = Urls.browse_origin(objectPid);
+ } else {
+ badgeImageUrl = Urls.swh_badge_pid(objectPid);
+ badgeLinkUrl = Urls.browse_swh_id(objectPid);
+ }
+ let urlPrefix = `${window.location.protocol}//${window.location.hostname}`;
+ if (window.location.port) {
+ urlPrefix += `:${window.location.port}`;
+ }
+ const absoluteBadgeImageUrl = `${urlPrefix}${badgeImageUrl}`;
+ const absoluteBadgeLinkUrl = `${urlPrefix}${badgeLinkUrl}`;
+ const html = `
+ <a href="${absoluteBadgeLinkUrl}">
+ <img class="swh-badge" src="${absoluteBadgeImageUrl}">
+ </a>
+ <div>
+ <label>HTML</label>
+ <pre class="swh-badge-html">&lt;a href="${absoluteBadgeLinkUrl}"&gt;
+ &lt;img src="${absoluteBadgeImageUrl}"&gt;
+&lt;/a&gt;</pre>
+ </div>
+ <div>
+ <label>Markdown</label>
+ <pre class="swh-badge-md">[![SWH](${absoluteBadgeImageUrl})](${absoluteBadgeLinkUrl})</pre>
+ </div>
+ <div>
+ <label>reStructuredText</label>
+ <pre class="swh-badge-rst">.. image:: ${absoluteBadgeImageUrl}
+ :target: ${absoluteBadgeLinkUrl}</pre>
+ </div>`;
+ swh.webapp.showModalHtml('Software Heritage badge integration', html);
+}
diff --git a/swh/web/assets/src/bundles/webapp/index.js b/swh/web/assets/src/bundles/webapp/index.js
--- a/swh/web/assets/src/bundles/webapp/index.js
+++ b/swh/web/assets/src/bundles/webapp/index.js
@@ -24,3 +24,4 @@
export * from './notebook-rendering';
export * from './xss-filtering';
export * from './history-counters';
+export * from './badges';
diff --git a/swh/web/assets/src/bundles/webapp/webapp-utils.js b/swh/web/assets/src/bundles/webapp/webapp-utils.js
--- a/swh/web/assets/src/bundles/webapp/webapp-utils.js
+++ b/swh/web/assets/src/bundles/webapp/webapp-utils.js
@@ -198,6 +198,12 @@
$('#swh-web-modal-confirm').modal('show');
}
+export function showModalHtml(title, html) {
+ $('#swh-web-modal-html .modal-title').text(title);
+ $('#swh-web-modal-html .modal-body').html(html);
+ $('#swh-web-modal-html').modal('show');
+}
+
export function addJumpToPagePopoverToDataTable(dataTableElt) {
dataTableElt.on('draw.dt', function() {
$('.paginate_button.disabled').css('cursor', 'pointer');
diff --git a/swh/web/assets/src/bundles/webapp/webapp.css b/swh/web/assets/src/bundles/webapp/webapp.css
--- a/swh/web/assets/src/bundles/webapp/webapp.css
+++ b/swh/web/assets/src/bundles/webapp/webapp.css
@@ -182,6 +182,7 @@
.modal {
text-align: center;
padding: 0 !important;
+ z-index: 50000;
}
.modal::before {
@@ -580,3 +581,14 @@
.wrapper {
overflow: hidden;
}
+
+.swh-badge {
+ padding-bottom: 1rem;
+ cursor: pointer;
+}
+
+.swh-badge-html,
+.swh-badge-md,
+.swh-badge-rst {
+ white-space: pre-wrap;
+}
diff --git a/swh/web/browse/utils.py b/swh/web/browse/utils.py
--- a/swh/web/browse/utils.py
+++ b/swh/web/browse/utils.py
@@ -1091,6 +1091,7 @@
swh_ids.append({
'object_type': swh_object['type'],
+ 'object_id': swh_object['id'],
'object_icon': object_icon,
'swh_id': swh_id,
'swh_id_url': reverse('browse-swh-id',
diff --git a/swh/web/templates/includes/global-modals.html b/swh/web/templates/includes/global-modals.html
--- a/swh/web/templates/includes/global-modals.html
+++ b/swh/web/templates/includes/global-modals.html
@@ -18,21 +18,36 @@
</div>
<div class="modal fade" id="swh-web-modal-confirm" tabindex="-1" role="dialog" aria-labelledby="swh-web-modal-confirm-label" aria-hidden="true">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <h6 class="modal-title" id="swh-web-modal-confirm-label"></h6>
- <button type="button" class="close" data-dismiss="modal" aria-label="Close">
- <span aria-hidden="true">&times;</span>
- </button>
- </div>
- <div class="modal-body">
- <p></p>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default btn-sm" data-dismiss="modal">Cancel</button>
- <button type="button" id="swh-web-modal-confirm-ok-btn" class="btn btn-default btn-sm" data-dismiss="modal">Ok</button>
- </div>
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h6 class="modal-title" id="swh-web-modal-confirm-label"></h6>
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true">&times;</span>
+ </button>
+ </div>
+ <div class="modal-body">
+ <p></p>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default btn-sm" data-dismiss="modal">Cancel</button>
+ <button type="button" id="swh-web-modal-confirm-ok-btn" class="btn btn-default btn-sm" data-dismiss="modal">Ok</button>
</div>
</div>
</div>
+</div>
+
+<div class="modal fade" id="swh-web-modal-html" tabindex="-1" role="dialog" aria-labelledby="swh-web-modal-html-label" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h6 class="modal-title" id="swh-web-modal-html-label"></h6>
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true">&times;</span>
+ </button>
+ </div>
+ <div class="modal-body">
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/swh/web/templates/includes/show-swh-ids.html b/swh/web/templates/includes/show-swh-ids.html
--- a/swh/web/templates/includes/show-swh-ids.html
+++ b/swh/web/templates/includes/show-swh-ids.html
@@ -52,6 +52,14 @@
{% endif %}
<div class="card">
<div class="card-body swh-id-ui">
+ {% if snapshot_context and snapshot_context.origin_info %}
+ <img class="swh-badge swh-badge-origin" src="{% url 'swh-badge' 'origin' snapshot_context.origin_info.url %}"
+ onclick="swh.webapp.showBadgeInfoModal('origin', '{{ snapshot_context.origin_info.url }}')"
+ title="Click to display badge integration info">
+ {% endif %}
+ <img class="swh-badge swh-badge-{{ swh_id.object_type }}" src="{% url 'swh-badge' swh_id.object_type swh_id.object_id %}"
+ onclick="swh.webapp.showBadgeInfoModal('{{ swh_id.object_type }}', $(this).parent().find('.swh-id').text())"
+ title="Click to display badge integration info">
<pre><a class="swh-id" id="{{ swh_id.swh_id }}" href="{{ swh_id.swh_id_url }}">{{ swh_id.swh_id }}</a></pre>
{% if swh_id.show_options %}
<div class="float-left">
@@ -80,7 +88,6 @@
<button type="button" class="btn btn-default btn-sm btn-swh-id-copy"
title="Copy persistent identifier to clipboard">
<i class="fa fa-clipboard fa-fw" aria-hidden="true"></i>Copy identifier
- </button>
<button type="button" class="btn btn-default btn-sm btn-swh-id-url-copy"
title="Copy url resolving the persistent identifier to clipboard">
<i class="fa fa-clipboard fa-fw" aria-hidden="true"></i>Copy permalink

File Metadata

Mime Type
text/plain
Expires
Thu, Jan 23, 2:08 AM (19 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3215898

Event Timeline