Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F7147860
D2320.id8017.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
15 KB
Subscribers
None
D2320.id8017.diff
View Options
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"><a href="${absoluteBadgeLinkUrl}">
+ <img src="${absoluteBadgeImageUrl}">
+</a></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">×</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">×</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">×</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
Details
Attached
Mime Type
text/plain
Expires
Thu, Jan 23, 2:08 AM (16 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3215898
Attached To
D2320: Integrate swh badges in Permalinks tab
Event Timeline
Log In to Comment