Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combine both download modals into one #7068

Merged
merged 10 commits into from
May 25, 2023
Merged
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
- Added a machine-learning based quick select mode. Activate it via the "AI" button in the toolbar after selecting the quick-select tool. [#7051](https://github.com/scalableminds/webknossos/pull/7051)
- Added support for remote datasets encoded with [brotli](https://datatracker.ietf.org/doc/html/rfc7932). [#7041](https://github.com/scalableminds/webknossos/pull/7041)
- Teams can be edited more straight-forwardly in a popup in the team edit page. [#7043](https://github.com/scalableminds/webknossos/pull/7043)
- Added support to download layers of a dataset as (OME) TIFF files in the download modal when viewing a dataset. [#7068](https://github.com/scalableminds/webknossos/pull/7068)
- Annotations with Editable Mappings (a.k.a Supervoxel Proofreading) can now be merged. [#7026](https://github.com/scalableminds/webknossos/pull/7026)
- The file size and inodes of artifacts are now aggregated and shown in the Voxelytics workflow list. [#7071](https://github.com/scalableminds/webknossos/pull/7071)
- It is possible to disable the automatic loading of meshes during proofreading. [##7076](https://github.com/scalableminds/webknossos/pull/7076)
Expand Down
10 changes: 6 additions & 4 deletions frontend/javascripts/messages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ A reload is necessary to return to a valid state.`,
"Importing a volume annotation cannot be undone. However, if you want to restore an earlier version of this annotation, use the 'Restore Older Version' functionality in the dropdown next to the 'Save' button.",
"download.wait": "Please wait...",
"download.close_window": "You may close this window after the download has started.",
"download.python_do_not_share": _.template(
"These snippets are pre-configured and contain your personal access token and <%- typeName %> meta data. Do not share this information with anyone you do not trust!",
),
"download.export_as_tiff": _.template(
"Export this <%- typeName %> as TIFF image(s). This may take a few moments depending on the size of your configured export.",
),
"add_script.confirm_change": "This will replace the code you have written. Continue?",
"data.enabled_render_missing_data_black":
"You just enabled the option to render missing data black. All layers will now be reloaded.",
Expand Down Expand Up @@ -344,12 +350,8 @@ instead. Only enable this option if you understand its effect. All layers will n
"annotation.shared_teams_edited_failed":
"Updating the sharing options for the annotation failed. Please retry or see the error message in the console.",
"annotation.download": "The following annotation data is available for download immediately.",
"annotation.export":
"Export this annotation as TIFF image(s). This may take a few moments depending on the size of your configured export.",
"annotation.export_no_worker":
"This WEBKNOSSOS instance is not configured to run export jobs. To learn more about this feature please contact us at ",
"annotation.python_do_not_share":
"These snippets are pre-configured and contain your personal access token and annotation meta data. Do not share this information with anyone you do not trust!",
"annotation.register_for_token": "Please log in to get an access token for the script below.",
"project.delete": "Do you really want to delete this project?",
"project.increase_instances":
Expand Down
246 changes: 142 additions & 104 deletions frontend/javascripts/oxalis/view/action-bar/download_modal_view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type TabKeys = "download" | "export" | "python";
type Props = {
isOpen: boolean;
onClose: () => void;
isAnnotation: boolean;
initialTab?: TabKeys;
initialBoundingBoxId?: number;
};
Expand Down Expand Up @@ -180,26 +181,6 @@ async function copyToClipboard(code: string) {
Toast.success("Snippet copied to clipboard.");
}

export function MoreInfoHint() {
return (
<Hint
style={{
margin: "0px 12px 0px 12px",
}}
>
For more information on how to work with annotation files visit the{" "}
<a
href="https://docs.webknossos.org/webknossos/tooling.html"
target="_blank"
rel="noreferrer"
>
user documentation
</a>
.
</Hint>
);
}

export function CopyableCodeSnippet({ code, onCopy }: { code: string; onCopy?: () => void }) {
return (
<pre>
Expand All @@ -224,6 +205,42 @@ export function CopyableCodeSnippet({ code, onCopy }: { code: string; onCopy?: (
);
}

function getPythonAnnotationDownloadSnippet(authToken: string | null, tracing: HybridTracing) {
return `import webknossos as wk

with wk.webknossos_context(
token="${authToken || "<insert token here>"}",
url="${window.location.origin}"
):
annotation = wk.Annotation.download("${tracing.annotationId}")
`;
}

function getPythonDatasetDownloadSnippet(authToken: string | null, dataset: APIDataset) {
const nonDefaultHost = !document.location.host.endsWith("webknossos.org");
const indentation = "\n ";
const contextUrlAddendum = nonDefaultHost ? `, url="${window.location.origin}"` : "";
const maybeUrlParameter = nonDefaultHost
? `${indentation}webknossos_url="${window.location.origin}"`
: "";

return `import webknossos as wk

with wk.webknossos_context(token="${authToken || "<insert token here>"}"${contextUrlAddendum}):
# Download the dataset.
dataset = wk.Dataset.download(
dataset_name_or_url="${dataset.name}",
organization_id="${dataset.owningOrganization}",${maybeUrlParameter}
)
# Alternatively, directly open the dataset. Image data will be
# streamed when being accessed.
remote_dataset = wk.Dataset.open_remote(
dataset_name_or_url="${dataset.name}",
organization_id="${dataset.owningOrganization}",${maybeUrlParameter}
)
`;
}

const okTextForTab = new Map<TabKeys, string | null>([
["download", "Download"],
["export", "Export"],
Expand All @@ -233,6 +250,7 @@ const okTextForTab = new Map<TabKeys, string | null>([
function _DownloadModalView({
isOpen,
onClose,
isAnnotation,
initialTab,
initialBoundingBoxId,
}: Props): JSX.Element {
Expand All @@ -242,6 +260,7 @@ function _DownloadModalView({
const rawUserBoundingBoxes = useSelector((state: OxalisState) =>
getUserBoundingBoxesFromState(state),
);
const typeName = isAnnotation ? "annotation" : "dataset";
const isMergerModeEnabled = useSelector(
(state: OxalisState) => state.temporaryConfiguration.isMergerModeEnabled,
);
Expand Down Expand Up @@ -355,7 +374,7 @@ function _DownloadModalView({
type="warning"
>
{activeUser != null
? messages["annotation.python_do_not_share"]
? messages["download.python_do_not_share"]({ typeName })
: messages["annotation.register_for_token"]}
</Text>
</Row>
Expand All @@ -376,6 +395,25 @@ function _DownloadModalView({
setKeepWindowOpen(e.target.checked);
};

const typeDependentFileName = isAnnotation ? "annotation files" : "datasets";
const moreInfoHint = (
<Hint
style={{
margin: "0px 12px 0px 12px",
}}
>
For more information on how to work with {typeDependentFileName} visit the{" "}
<a
href="https://docs.webknossos.org/webknossos/tooling.html"
target="_blank"
rel="noreferrer"
>
user documentation
</a>
.
</Hint>
);

const workerInfo = (
<Row>
<Divider
Expand Down Expand Up @@ -410,14 +448,10 @@ function _DownloadModalView({
"loading...",
[activeUser],
);
const wkInitSnippet = `import webknossos as wk

with wk.webknossos_context(
token="${authToken || "<insert token here>"}",
url="${window.location.origin}"
):
annotation = wk.Annotation.download("${tracing.annotationId}")
`;
const wkInitSnippet = isAnnotation
? getPythonAnnotationDownloadSnippet(authToken, tracing)
: getPythonDatasetDownloadSnippet(authToken, dataset);

const alertTokenIsPrivate = () => {
if (authToken) {
Expand All @@ -441,7 +475,7 @@ with wk.webknossos_context(

return (
<Modal
title="Download this annotation"
title={`Download this ${typeName}`}
open={isOpen}
width={600}
footer={
Expand All @@ -461,90 +495,94 @@ with wk.webknossos_context(
style={{ overflow: "visible" }}
>
<Tabs activeKey={activeTabKey} onChange={handleTabChange} type="card">
<TabPane tab="Download" key="download">
<Row>
{maybeShowWarning()}
<Text
{isAnnotation ? (
<TabPane tab="Download" key="download">
<Row>
{maybeShowWarning()}
<Text
style={{
margin: "0 6px 12px",
}}
>
{!hasVolumes ? "This is a Skeleton-only annotation. " : ""}
{!hasSkeleton ? "This is a Volume-only annotation. " : ""}
{messages["annotation.download"]}
</Text>
</Row>
<Divider
style={{
margin: "0 6px 12px",
margin: "18px 0",
}}
>
{!hasVolumes ? "This is a Skeleton-only annotation. " : ""}
{!hasSkeleton ? "This is a Volume-only annotation. " : ""}
{messages["annotation.download"]}
</Text>
</Row>
<Divider
style={{
margin: "18px 0",
}}
>
Options
</Divider>
<Row>
<Col
span={9}
Options
</Divider>
<Row>
<Col
span={9}
style={{
lineHeight: "20px",
padding: "5px 12px",
}}
>
Select the data you would like to download.
</Col>
<Col span={15}>
<CheckboxGroup
onChange={handleCheckboxChange}
defaultValue={["Volume", "Skeleton"]}
>
{hasVolumes ? (
<div>
<Checkbox
style={checkboxStyle}
value="Volume"
// If no skeleton is available, volume is always selected
checked={!hasSkeleton ? true : includeVolumeData}
disabled={!hasSkeleton}
>
Volume annotations as WKW
</Checkbox>
<Hint
style={{
marginLeft: 24,
marginBottom: 12,
}}
>
Download a zip folder containing WKW files.
</Hint>
</div>
) : null}

<Checkbox style={checkboxStyle} value="Skeleton" checked disabled>
{hasSkeleton ? "Skeleton annotations" : "Meta data"} as NML
</Checkbox>
<Hint
style={{
marginLeft: 24,
marginBottom: 12,
}}
>
An NML file will always be included with any download.
</Hint>
</CheckboxGroup>
</Col>
</Row>
<Divider
style={{
lineHeight: "20px",
padding: "5px 12px",
margin: "18px 0",
}}
>
Select the data you would like to download.
</Col>
<Col span={15}>
<CheckboxGroup onChange={handleCheckboxChange} defaultValue={["Volume", "Skeleton"]}>
{hasVolumes ? (
<div>
<Checkbox
style={checkboxStyle}
value="Volume"
// If no skeleton is available, volume is always selected
checked={!hasSkeleton ? true : includeVolumeData}
disabled={!hasSkeleton}
>
Volume annotations as WKW
</Checkbox>
<Hint
style={{
marginLeft: 24,
marginBottom: 12,
}}
>
Download a zip folder containing WKW files.
</Hint>
</div>
) : null}

<Checkbox style={checkboxStyle} value="Skeleton" checked disabled>
{hasSkeleton ? "Skeleton annotations" : "Meta data"} as NML
</Checkbox>
<Hint
style={{
marginLeft: 24,
marginBottom: 12,
}}
>
An NML file will always be included with any download.
</Hint>
</CheckboxGroup>
</Col>
</Row>
<Divider
style={{
margin: "18px 0",
}}
/>
<MoreInfoHint />
</TabPane>

/>
{moreInfoHint}
</TabPane>
) : null}
<TabPane tab="TIFF Export" key="export">
<Row>
<Text
style={{
margin: "0 6px 12px",
}}
>
{messages["annotation.export"]}
{messages["download.export_as_tiff"]({ typeName })}
</Text>
</Row>
{activeTabKey === "export" && !features().jobsEnabled ? (
Expand Down Expand Up @@ -656,7 +694,7 @@ with wk.webknossos_context(
margin: "18px 0",
}}
/>
<MoreInfoHint />
{moreInfoHint}
<Checkbox
style={{ position: "absolute", bottom: -62 }}
checked={keepWindowOpen}
Expand All @@ -678,7 +716,7 @@ with wk.webknossos_context(
<a href="https://docs.webknossos.org/webknossos-py/" target="_blank" rel="noreferrer">
WEBKNOSSOS Python API
</a>
. To download and use this annotation in your Python project, simply copy and paste
. To download and use this {typeName} in your Python project, simply copy and paste
the code snippets to your script.
</Text>
</Row>
Expand All @@ -699,7 +737,7 @@ with wk.webknossos_context(
margin: "18px 0",
}}
/>
<MoreInfoHint />
{moreInfoHint}
</TabPane>
</Tabs>
</Modal>
Expand Down
Loading