mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-15 12:47:56 +08:00
* revert all commits to before Typescript migration * update compat workflow to match latest deps (#2335) * update compat workflow to match latest deps * attempt to debug * attempt to debug * remove debugging code * typo * update deps to match desktop (#2340) * fix: don't run lint with `--fix` on push tests (#2273) * fix: don't run lint with `--fix` on push tests * npx Co-authored-by: maniarathi <mani.arathi@gmail.com> Co-authored-by: Madison Dunitz <madison.dunitz@chanzuckerberg.com> * rename X_approx_distribution to X_approximate_distribution (#2337) * Correctly handle non-finite numbers in heuristic determination of X distribution (#2342) * handle non-finites explicitly * improve and test edge case handling for distribution estimation * revert debugging changes * code readability * clean up type inferencing (#2332) * unit tests for 64 bit conversion * clean up type handling * type inference tests * more type inference fixes * use schema to determine user intent for data typing * stop using deprecated API * fbs type encoding test * add missing test * add more tests * correctly infer X type for CXG adaptor * lint * fix typo * ts migration * cleanup from PR review * lint * PR review changes * remove unused packages from client (#2359) * remove unused packages from client * add missing peer dep * fix: disable FE auth testing on compatibility tests (#2377) * update: release process (#2277) Co-authored-by: maniarathi <mani.arathi@gmail.com> * fix: remove spaces in param setup (#2380) * delete deploy workflow (#2396) * undo reformatting which now does not pass lint * fix snapshots which changed due to npm dep changes * add missing quoting to snapshot * another snapshot typo fix * TS Revert (2) - replay PR #2347 and #2354 (#2403) * replay edits from PR 2347 * TS Revert (3) - replay edits in PR #2327 (#2404) * replay edits in PR 2327 * TS Revert (4) - replay PR #2355 (#2405) * replay edits in PR 2355 * add additional babel config * reformat with new prettier config Co-authored-by: Severiano Badajoz <sbadajoz@chanzuckerberg.com> Co-authored-by: maniarathi <mani.arathi@gmail.com> Co-authored-by: Madison Dunitz <madison.dunitz@chanzuckerberg.com>
191 lines
5.2 KiB
JavaScript
191 lines
5.2 KiB
JavaScript
import React from "react";
|
|
import { connect } from "react-redux";
|
|
|
|
import {
|
|
Button,
|
|
Classes,
|
|
Code,
|
|
Colors,
|
|
Dialog,
|
|
InputGroup,
|
|
Tooltip,
|
|
} from "@blueprintjs/core";
|
|
|
|
@connect((state) => ({
|
|
idhash: state.config?.parameters?.["annotations-user-data-idhash"] ?? null,
|
|
annotations: state.annotations,
|
|
auth: state.config?.authentication,
|
|
userInfo: state.userInfo,
|
|
writableCategoriesEnabled: state.config?.parameters?.annotations ?? false,
|
|
writableGenesetsEnabled: !(
|
|
state.config?.parameters?.annotations_genesets_readonly ?? true
|
|
),
|
|
}))
|
|
class FilenameDialog extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
filenameText: "",
|
|
};
|
|
}
|
|
|
|
dismissFilenameDialog = () => {};
|
|
|
|
handleCreateFilename = () => {
|
|
const { dispatch } = this.props;
|
|
const { filenameText } = this.state;
|
|
|
|
dispatch({
|
|
type: "set annotations collection name",
|
|
data: filenameText,
|
|
});
|
|
};
|
|
|
|
filenameError = () => {
|
|
const legalNames = /^\w+$/;
|
|
const { filenameText } = this.state;
|
|
let err = false;
|
|
|
|
if (filenameText === "") {
|
|
err = "empty_string";
|
|
} else if (!legalNames.test(filenameText)) {
|
|
/*
|
|
IMPORTANT: this test must ultimately match the test applied by the
|
|
backend, which is designed to ensure a safe file name can be created
|
|
from the data collection name. If you change this, you will also need
|
|
to change the validation code in the backend, or it will have no effect.
|
|
*/
|
|
err = "characters";
|
|
}
|
|
|
|
return err;
|
|
};
|
|
|
|
filenameErrorMessage = () => {
|
|
const err = this.filenameError();
|
|
let markup = null;
|
|
|
|
if (err === "empty_string") {
|
|
markup = (
|
|
<span
|
|
style={{
|
|
fontStyle: "italic",
|
|
fontSize: 12,
|
|
marginTop: 5,
|
|
color: Colors.ORANGE3,
|
|
}}
|
|
>
|
|
Name cannot be blank
|
|
</span>
|
|
);
|
|
} else if (err === "characters") {
|
|
markup = (
|
|
<span
|
|
style={{
|
|
fontStyle: "italic",
|
|
fontSize: 12,
|
|
marginTop: 5,
|
|
color: Colors.ORANGE3,
|
|
}}
|
|
>
|
|
Only alphanumeric and underscore allowed
|
|
</span>
|
|
);
|
|
}
|
|
return markup;
|
|
};
|
|
|
|
render() {
|
|
const {
|
|
writableCategoriesEnabled,
|
|
writableGenesetsEnabled,
|
|
annotations,
|
|
idhash,
|
|
userInfo,
|
|
} = this.props;
|
|
const { filenameText } = this.state;
|
|
|
|
return (writableCategoriesEnabled || writableGenesetsEnabled) &&
|
|
annotations.promptForFilename &&
|
|
!annotations.dataCollectionNameIsReadOnly &&
|
|
!annotations.dataCollectionName &&
|
|
userInfo.is_authenticated ? (
|
|
<Dialog
|
|
icon="tag"
|
|
title="User Generated Data Directory"
|
|
isOpen={!annotations.dataCollectionName}
|
|
onClose={this.dismissFilenameDialog}
|
|
>
|
|
<form
|
|
onSubmit={(e) => {
|
|
e.preventDefault();
|
|
this.handleCreateFilename();
|
|
}}
|
|
>
|
|
<div className={Classes.DIALOG_BODY} data-testid="annotation-dialog">
|
|
<div style={{ marginBottom: 20 }}>
|
|
<p>Name your user generated data directory:</p>
|
|
<InputGroup
|
|
autoFocus
|
|
value={filenameText}
|
|
intent={this.filenameError(filenameText) ? "warning" : "none"}
|
|
onChange={(e) =>
|
|
this.setState({ filenameText: e.target.value })
|
|
}
|
|
leftIcon="tag"
|
|
data-testid="new-annotation-name"
|
|
/>
|
|
<p
|
|
style={{
|
|
marginTop: 7,
|
|
visibility: this.filenameError(filenameText)
|
|
? "visible"
|
|
: "hidden",
|
|
color: Colors.ORANGE3,
|
|
}}
|
|
>
|
|
{this.filenameErrorMessage(filenameText)}
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<p>
|
|
{"Your annotations are stored in this file: "}
|
|
<Code>
|
|
{filenameText}-cell-labels-{idhash}.csv
|
|
</Code>
|
|
</p>
|
|
<p>
|
|
{"Your gene sets are stored in this file: "}
|
|
<Code>
|
|
{filenameText}-gene-sets-{idhash}.csv
|
|
</Code>
|
|
</p>
|
|
<p style={{ fontStyle: "italic" }}>
|
|
(We added a unique ID to your filename)
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div className={Classes.DIALOG_FOOTER}>
|
|
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
|
<Tooltip content="Cancel naming collection">
|
|
<Button onClick={this.dismissFilenameDialog}>Cancel</Button>
|
|
</Tooltip>
|
|
<Button
|
|
disabled={!filenameText || this.filenameError(filenameText)}
|
|
onClick={this.handleCreateFilename}
|
|
intent="primary"
|
|
type="submit"
|
|
data-testid="submit-annotation"
|
|
>
|
|
Create user generated data directory
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</Dialog>
|
|
) : null;
|
|
}
|
|
}
|
|
|
|
export default FilenameDialog;
|