Skip to content
Snippets Groups Projects
Commit 37f5dec0 authored by Antoine Lambert's avatar Antoine Lambert Committed by Antoine Lambert
Browse files

WIP

parent f15e17c4
Branches swhid-iframe
No related tags found
No related merge requests found
/**
* Copyright (C) 2018-2019 The Software Heritage developers
* Copyright (C) 2018-2021 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
......@@ -22,6 +22,19 @@ export function highlightLine(i, firstHighlighted = false) {
return lineTd;
}
// function to highlight a range of lines
export function highlightLines(first, last) {
if (!first) {
return;
}
if (!last) {
last = first;
}
for (let i = first; i <= last; ++i) {
highlightLine(i);
}
}
// function to reset highlighting
export function resetHighlightedLines() {
firstHighlightedLine = null;
......@@ -60,9 +73,7 @@ export async function highlightCode(showLineNumbers = true) {
} else if (lines[0] < lines[lines.length - 1]) {
firstHighlightedLine = parseInt(lines[0]);
scrollToLine(highlightLine(lines[0]));
for (let i = lines[0] + 1; i <= lines[lines.length - 1]; ++i) {
highlightLine(i);
}
highlightLines(lines[0] + 1, lines[lines.length - 1]);
}
}
......@@ -88,9 +99,7 @@ export async function highlightCode(showLineNumbers = true) {
if (evt.shiftKey && firstHighlightedLine && line > firstHighlightedLine) {
const firstLine = firstHighlightedLine;
resetHighlightedLines();
for (let i = firstLine; i <= line; ++i) {
highlightLine(i);
}
highlightLines(firstLine, line);
firstHighlightedLine = firstLine;
window.location.hash = `#L${firstLine}-L${line}`;
} else {
......@@ -115,3 +124,7 @@ export async function highlightCode(showLineNumbers = true) {
});
}
export function disableCodeSelection() {
$('.swh-content').unbind();
}
......@@ -279,6 +279,7 @@ def context_processor(request):
),
"swh_web_version": get_distribution("swh.web").version,
"visit_types": ORIGIN_VISIT_TYPES,
"iframe_mode": False,
}
......
# Copyright (C) 2021 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
from django.conf.urls import url
from django.shortcuts import render
from django.views.decorators.clickjacking import xframe_options_exempt
from swh.model.hashutil import hash_to_bytes
from swh.model.identifiers import ObjectType, QualifiedSWHID
from swh.web.browse.snapshot_context import get_snapshot_context
from swh.web.browse.utils import (
content_display_max_size,
get_directory_entries,
prepare_content_for_display,
request_content,
)
from swh.web.common import archive
from swh.web.common.exc import BadInputExc, NotFoundExc, http_status_code_message
from swh.web.common.identifiers import get_swhid
from swh.web.common.utils import gen_path_info, reverse
@xframe_options_exempt
def swhid_iframe(request, swhid):
focus_swhid = request.GET.get("focus_swhid", swhid)
swhid_parsed = None
snapshot_context = None
view_data = {}
breadcrumbs = []
try:
swhid_parsed = get_swhid(swhid)
focus_swhid_parsed = get_swhid(focus_swhid)
if swhid_parsed.origin or swhid_parsed.visit:
snapshot_context = get_snapshot_context(
origin_url=swhid_parsed.origin,
snapshot_id=swhid_parsed.visit.object_id.hex()
if swhid_parsed.visit
else None,
)
path = swhid_parsed.path.decode("utf-8") if swhid_parsed.path else ""
error_info = {"status_code": 200, "description": None}
if swhid_parsed and swhid_parsed.object_type == ObjectType.CONTENT:
content_data = request_content(f"sha1_git:{swhid_parsed.object_id.hex()}")
content = None
language = None
mimetype = None
if content_data.get("raw_data") is not None:
content_display_data = prepare_content_for_display(
content_data["raw_data"], content_data["mimetype"], path
)
content = content_display_data["content_data"]
language = content_display_data["language"]
mimetype = content_display_data["mimetype"]
view_data = {
"content": content,
"content_size": content_data.get("length"),
"max_content_size": content_display_max_size,
"filename": path.split("/")[-1],
"encoding": content_data.get("encoding"),
"mimetype": mimetype,
"language": language,
}
elif swhid_parsed and swhid_parsed.object_type == ObjectType.DIRECTORY:
dirs, files = get_directory_entries(swhid_parsed.object_id.hex())
for d in dirs:
if d["type"] == "rev":
d["url"] = None
else:
dir_swhid = QualifiedSWHID(
object_type=ObjectType.DIRECTORY,
object_id=hash_to_bytes(d["target"]),
origin=swhid_parsed.origin,
visit=swhid_parsed.visit,
anchor=swhid_parsed.anchor,
path=(path or "/") + d["name"] + "/",
)
d["url"] = reverse(
"swhid-iframe",
url_args={"swhid": str(dir_swhid)},
query_params={"focus_swhid": focus_swhid},
)
for f in files:
object_id = hash_to_bytes(f["target"])
cnt_swhid = QualifiedSWHID(
object_type=ObjectType.CONTENT,
object_id=object_id,
origin=swhid_parsed.origin,
visit=swhid_parsed.visit,
anchor=swhid_parsed.anchor,
path=(path or "/") + f["name"],
lines=(
focus_swhid_parsed.lines
if object_id == focus_swhid_parsed.object_id
else None
),
)
f["url"] = reverse(
"swhid-iframe",
url_args={"swhid": str(cnt_swhid)},
query_params={"focus_swhid": focus_swhid},
)
view_data = {"dirs": dirs, "files": files}
elif swhid_parsed:
error_info = {
"status_code": 400,
"description": (
f"Objects of type {swhid_parsed.object_type} are not supported"
),
}
if swhid_parsed and view_data:
filename = None
if swhid_parsed.object_type == ObjectType.CONTENT:
split_path = path.split("/")
filename = split_path[-1]
path = path[: -len(filename)]
path_info = gen_path_info(path) if path != "/" else []
root_dir = None
if snapshot_context and snapshot_context["root_directory"]:
root_dir = snapshot_context["root_directory"]
elif focus_swhid_parsed.object_type == ObjectType.DIRECTORY:
root_dir = focus_swhid_parsed.object_id.hex()
if root_dir:
root_dir_swhid = QualifiedSWHID(
object_type=ObjectType.DIRECTORY,
object_id=hash_to_bytes(root_dir),
origin=swhid_parsed.origin,
visit=swhid_parsed.visit,
anchor=swhid_parsed.anchor,
)
breadcrumbs.append(
{
"name": root_dir[:7],
"url": reverse(
"swhid-iframe",
url_args={"swhid": str(root_dir_swhid)},
query_params={"focus_swhid": focus_swhid},
),
}
)
for pi in path_info:
dir_info = archive.lookup_directory_with_path(root_dir, pi["path"])
dir_swhid = QualifiedSWHID(
object_type=ObjectType.DIRECTORY,
object_id=hash_to_bytes(dir_info["target"]),
origin=swhid_parsed.origin,
visit=swhid_parsed.visit,
anchor=swhid_parsed.anchor,
path="/" + pi["path"] + "/",
)
breadcrumbs.append(
{
"name": pi["name"],
"url": reverse(
"swhid-iframe",
url_args={"swhid": str(dir_swhid)},
query_params={"focus_swhid": focus_swhid},
),
}
)
if filename:
breadcrumbs.append({"name": filename, "url": None})
except BadInputExc as e:
error_info = {"status_code": 400, "description": f"BadInputExc: {str(e)}"}
except NotFoundExc as e:
error_info = {"status_code": 404, "description": f"NotFoundExc: {str(e)}"}
except Exception as e:
error_info = {"status_code": 500, "description": str(e)}
return render(
request,
"misc/iframe.html",
{
**view_data,
"iframe_mode": True,
"object_type": swhid_parsed.object_type.value if swhid_parsed else None,
"lines": swhid_parsed.lines if swhid_parsed else None,
"breadcrumbs": breadcrumbs,
"swhid": swhid,
"focus_swhid": focus_swhid,
"error_code": error_info["status_code"],
"error_message": http_status_code_message.get(error_info["status_code"]),
"error_description": error_info["description"],
},
status=error_info["status_code"],
)
urlpatterns = [
url(
r"^iframe/(?P<swhid>swh:[0-9]+:[a-z]+:[0-9a-f]+.*)$",
swhid_iframe,
name="swhid-iframe",
),
]
# Copyright (C) 2019 The Software Heritage developers
# Copyright (C) 2019-2021 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
......@@ -51,6 +51,7 @@ urlpatterns = [
url(r"^stat_counters/", _stat_counters, name="stat-counters"),
url(r"^", include("swh.web.misc.badges")),
url(r"^metrics/prometheus/$", prometheus_metrics, name="metrics-prometheus"),
url(r"^", include("swh.web.misc.iframe")),
]
......
......@@ -183,6 +183,10 @@ In order to facilitate the browsing of the archive and generate relevant entry p
<a href="{% url 'browse-search' %}">search interface</a> is available. Currently, it enables to search software origins from the URLs they were retrieved
from. More search criteria will be added in the future.
<h4 class="mt-1 mb-1">SWHID iframe test</h4>
<iframe style="width: 100%; height: 500px; border: 1px solid rgba(0, 0, 0, 0.125);" src="http://localhost:5004/iframe/swh:1:dir:3ed3ad16396b9f5976e5636bbf6aa45d386b81c3;origin=https://github.com/torvalds/linux;visit=swh:1:snp:d0b2c61c65af28faf3eaafedfe4fb37103ef11b7;anchor=swh:1:rev:c7d102232649226a69dddd58a4942cf13cff4f7c;path=/drivers/"></iframe>
<script>
swh.webapp.initPage('help');
</script>
......
{% comment %}
Copyright (C) 2017-2018 The Software Heritage developers
Copyright (C) 2017-2021 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 %}
{% if breadcrumbs %}
{% if breadcrumbs|length > 1 or breadcrumbs.0.url %}
<nav class="bread-crumbs swh-browse-bread-crumbs">
<ul>
{% for bc in breadcrumbs %}
{% if bc.url %}
<li class="swh-path"><a href="{{ bc.url | safe }}">{{ bc.name }}</a></li>
<li>/</li>
{% else %}
<li>{{ bc.name }}</li>
{% endif %}
{% endfor %}
</ul>
</nav>
{% endif %}
<nav class="bread-crumbs swh-browse-bread-crumbs">
<ul>
{% for bc in breadcrumbs %}
{% if bc.url %}
<li class="swh-path"><a href="{{ bc.url | safe }}">{{ bc.name }}</a></li>
<li>/</li>
{% else %}
<li>{{ bc.name }}</li>
{% endif %}
{% endfor %}
</ul>
</nav>
{% endif %}
{% comment %}
Copyright (C) 2017-2020 The Software Heritage developers
Copyright (C) 2017-2021 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
......@@ -12,12 +12,14 @@ See top-level LICENSE file for more information
{% if snapshot_context and snapshot_context.is_empty %}
{% include "includes/empty-snapshot.html" %}
{% else %}
<div class="card">
{% if filename %}
<div class="swh-content-filename card-header bg-gray-light swh-heading-color">
{{ filename }}
</div>
{% endif %}
{% if not iframe_mode %}
<div class="card">
{% if filename %}
<div class="swh-content-filename card-header bg-gray-light swh-heading-color">
{{ filename }}
</div>
{% endif %}
{% endif %}
<div class="swh-content">
{% if content_size > max_content_size %}
Content is too large to be displayed (size is greater than {{ max_content_size|filesizeformat }}).
......@@ -47,7 +49,9 @@ See top-level LICENSE file for more information
{% include "includes/http-error.html" %}
{% endif %}
</div>
</div>
{% if not iframe_mode %}
</div>
{% endif %}
{% if content %}
<script>
......
{% comment %}
Copyright (C) 2017-2020 The Software Heritage developers
Copyright (C) 2017-2021 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 %}
{% include "includes/revision-info.html" %}
{% if not iframe_mode %}
{% include "includes/revision-info.html" %}
{% endif %}
{% if snapshot_context and snapshot_context.is_empty %}
{% include "includes/empty-snapshot.html" %}
......@@ -53,7 +55,9 @@ See top-level LICENSE file for more information
</tbody>
</table>
</div>
<hr class="mt-0 mb-2">
{% if not iframe_mode %}
<hr class="mt-0 mb-2">
{% endif %}
{% elif "revision_found" in swh_object_metadata and swh_object_metadata.revision_found is False %}
<i>Revision {{ swh_object_metadata.revision }} could not be found in the archive.</i>
<br/>
......
{% comment %}
Copyright (C) 2018 The Software Heritage developers
Copyright (C) 2018-2021 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
......@@ -18,16 +18,18 @@ See top-level LICENSE file for more information
<div class="swh-http-error-desc">
<pre>{{ error_description }}</pre>
<div>
<a class="btn" onclick="window.history.back();">
<i class="mdi mdi-arrow-left" aria-hidden="true"></i>
Go back to previous page
</a>
or
<a class="btn" href="{% url 'swh-web-homepage' %}">
<i class="mdi mdi-arrow-left" aria-hidden="true"></i>
Go back to homepage
</a>
</div>
{% if not iframe_mode %}
<div>
<a class="btn" onclick="window.history.back();">
<i class="mdi mdi-arrow-left" aria-hidden="true"></i>
Go back to previous page
</a>
or
<a class="btn" href="{% url 'swh-web-homepage' %}">
<i class="mdi mdi-arrow-left" aria-hidden="true"></i>
Go back to homepage
</a>
</div>
{% endif %}
</div>
</div>
\ No newline at end of file
{% comment %}
Copyright (C) 2021 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 %}
<!DOCTYPE html>
{% load static %}
{% load render_bundle from webpack_loader %}
{% load swh_templatetags %}
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Software Heritage archived object</title>
{% render_bundle 'vendors' %}
{% render_bundle 'webapp' %}
<script>
/*
@licstart The following is the entire license notice for the JavaScript code in this page.
Copyright (C) 2021 The Software Heritage developers
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
@licend The above is the entire license notice for the JavaScript code in this page.
*/
</script>
<style>
.card {
border: none;
}
.card-header {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 80px;
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
}
.breadcrumbs-container {
border-top: 1px solid rgba(0, 0, 0, 0.125);
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
background: white;
margin-left: -20px;
margin-right: -20px;
}
.breadcrumbs-container ul {
padding-left: 25px;
}
.card-block {
margin-top: 78px;
overflow: auto;
}
pre {
margin-bottom: 0;
padding: 0;
}
.bread-crumbs {
font-size: large;
}
.hljs-ln-numbers {
cursor: default !important;
}
</style>
</head>
<body style="padding-bottom: 0;">
<div class="wrapper" style="margin-left: 0;">
<div class="content">
<div class="container-fluid">
<div class="card">
<div class="card-header bg-gray-light">
<div class="d-flex align-items-center">
<a href="https://www.softwareheritage.org"
target="_blank" rel="noopener noreferrer">
<div class="brand-text sitename">
<img src="{% static 'img/swh-logo.svg' %}" style="height: 40px;"/>
<span class="first-word pl-1">Software</span> <span class="second-word">Heritage</span>
</div>
</a>
<a class="ml-auto d-none d-lg-block" href="{% url 'browse-swhid' swhid %}"
target="_blank" rel="noopener noreferrer">
<img src="{% url 'swh-badge-swhid' swhid %}">
</a>
<div class="ml-auto d-flex align-items-center">
{% if swhid != focus_swhid %}
<a class="d-flex align-items-center pr-2" href="{% url 'swhid-iframe' focus_swhid %}"
title="Reset view to its original state">
<div class="d-none d-lg-block">Reset view</div>
<i class="mdi mdi-refresh" aria-hidden="true"></i>
</a>
{% endif %}
<a class="d-none d-lg-block" href="https://archive.softwareheritage.org"
target="_blank" rel="noopener noreferrer">
Go to archive
<i class="mdi mdi-open-in-new" aria-hidden="true"></i>
</a>
<a class="d-md-none" href="{% url 'browse-swhid' swhid %}"
target="_blank" rel="noopener noreferrer"
title="Go to archive">
<i class="mdi mdi-open-in-new" aria-hidden="true"></i>
</a>
</div>
</div>
<div class="d-flex align-items-center breadcrumbs-container mt-1">
{% include "includes/breadcrumbs.html" %}
</div>
</div>
<div class="card-block">
{% if error_code != 200 %}
{% include "includes/http-error.html" %}
{% elif object_type == "cnt" %}
{% include "includes/content-display.html" %}
{% elif object_type == "dir" %}
{% include "includes/directory-display.html" %}
{% endif %}
</div>
</div>
</div>
</div>
</div>
<a href="{% url 'jslicenses' %}" rel="jslicense" style="display: none;">JavaScript license information</a>
{% if object_type == "cnt" %}
<script>
setTimeout(function() {
swh.webapp.disableCodeSelection();
{% if lines %}
swh.webapp.highlightLines({{ lines.0|jsonify }}, {{ lines.1|jsonify }});
{% endif %}
}, 500);
</script>
{% endif %}
</body>
</html>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment