Skip to content

Commit 5e3a4e5

Browse files
authored
Merge pull request #98 from lubianat/s3_urls
Use icons for copying URL and navigating to validator
2 parents ac96561 + e8893f4 commit 5e3a4e5

File tree

4 files changed

+141
-12
lines changed

4 files changed

+141
-12
lines changed
434 Bytes
Loading
446 Bytes
Loading
Lines changed: 69 additions & 0 deletions
Loading

ome2024-ngff-challenge/src/ZarrListItem.svelte

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import { loadMultiscales, ngffTable } from "./tableStore";
55
import Thumbnail from "./Thumbnail.svelte";
66
import { onDestroy } from "svelte";
7-
7+
import copyImage from "/copy.png";
8+
import checkImage from "/ome-logomark.svg";
9+
import externalDataImage from "/original-data.svg";
810
export let rowData;
911
export let textFilter;
1012
export let sortedBy = undefined;
@@ -76,6 +78,31 @@
7678
});
7779
7880
$: description = (textFilter != "" && rowData.description?.toLowerCase().includes(textFilter.toLowerCase())) ? rowData.description : "";
81+
82+
let isShaking = false;
83+
// Adapted from https://github.com/IDR/ome-ngff-samples/blob/main/index.md
84+
function copyTextToClipboard(text) {
85+
var textArea = document.createElement("textarea");
86+
// Place in the top-left corner of screen regardless of scroll position.
87+
textArea.style.position = 'fixed';
88+
textArea.value = text;
89+
document.body.appendChild(textArea);
90+
textArea.focus();
91+
textArea.select();
92+
let successful = false;
93+
try {
94+
successful = document.execCommand("copy");
95+
} catch (err) {
96+
console.log("Oops, unable to copy");
97+
}
98+
document.body.removeChild(textArea);
99+
100+
if (successful) {
101+
// trigger shake for 1s
102+
isShaking = true;
103+
setTimeout(() => (isShaking = false), 1000);
104+
}
105+
};
79106
</script>
80107
81108
<div class="zarr-list-item">
@@ -85,7 +112,9 @@
85112
{/if}
86113
</div>
87114
<div>
88-
<div title="{rowData.url}"><strong>{@html formatUrlToName(rowData.url)}</strong></div>
115+
<div title="{rowData.url}"><strong>{@html formatUrlToName(rowData.url)} </strong>
116+
117+
</div>
89118
<div class={textFilter == "" ? "hideOnSmall" : ""}>
90119
<!-- If we're not filtering by text (name/description) then hide the name on small screen -->
91120
{@html rowData.name ? rowData.name.replaceAll(textFilter, `<mark>${textFilter}</mark>`) : ""}
@@ -102,19 +131,27 @@
102131
</div>
103132
{/if}
104133
<div>
105-
Open in <a
106-
title="Open in Validator: {rowData.url}"
107-
href="https://ome.github.io/ome-ngff-validator/?source={rowData.url}"
108-
target="_blank"
109-
>OME-Validator.
110-
</a>
134+
<button
135+
class="no_border"
136+
class:shake={isShaking}
137+
title="Copy S3 URL to clipboard"
138+
on:click={(event) => copyTextToClipboard(rowData.url)
139+
}
140+
>
141+
<img class="icon" src={copyImage} />
142+
</button>
143+
144+
<a title="Validate NGFF with 'ome-ngff-validator' in new browser tab" target="_blank"
145+
href="https://ome.github.io/ome-ngff-validator/?source={rowData.url}">
146+
<img class="icon" style="opacity: 0.9" src={checkImage}/></a>
111147
112148
{#if rowData.origin }
113-
Browse <a
114-
title="Link to original data: {rowData.origin}"
149+
150+
<a title="Link to original data: {rowData.origin}"
115151
href={rowData.origin}
116-
target="_blank"
117-
>Original data</a>.
152+
target="_blank">
153+
<img class="icon" style="opacity: 0.9" src={externalDataImage}/></a>
154+
118155
{/if}
119156
</div>
120157
<div>
@@ -155,4 +192,27 @@
155192
display: none;
156193
}
157194
}
195+
196+
197+
:root {
198+
--icon-size: 20px;
199+
}
200+
201+
.icon {
202+
width: var(--icon-size);
203+
height: var(--icon-size);
204+
aspect-ratio: 1 / 1;
205+
}
206+
.no_border {
207+
border: none;
208+
background: none;
209+
padding: 0;
210+
}
211+
212+
.shake {
213+
animation: 0.1s linear 0s infinite alternate seesaw;
214+
}
215+
216+
@keyframes seesaw { from { transform: rotate(-0.05turn) } to { transform: rotate(0.05turn); } }
217+
158218
</style>

0 commit comments

Comments
 (0)