Skip to content

Commit 1f7de9e

Browse files
authored
Merge pull request #711 from Steinbeck-Lab/development
Development
2 parents f98082c + 45b1bc8 commit 1f7de9e

8 files changed

Lines changed: 180 additions & 93 deletions

File tree

‎docker-compose.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ services:
1010
- HOMEPAGE_URL=https://docs.api.naturalproducts.net
1111
- RELEASE_VERSION=v2.6.0
1212
- WORKERS=2
13+
- CMS_INTERNAL_AUTH_TOKEN=${CMS_INTERNAL_AUTH_TOKEN}
1314
ports:
1415
- "8000:80"
1516
volumes:

‎frontend/package-lock.json‎

Lines changed: 111 additions & 79 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎frontend/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"@testing-library/jest-dom": "^5.17.0",
1212
"@testing-library/react": "^13.4.0",
1313
"@testing-library/user-event": "^13.5.0",
14-
"axios": "^1.12.0",
14+
"axios": "^1.13.5",
1515
"dompurify": "^3.2.4",
1616
"framer-motion": "^12.6.2",
1717
"jszip": "^3.10.1",

‎frontend/src/components/convert/FormatConversionView.jsx‎

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,32 @@ const TOOLKIT_OPTIONS = [
5050
// Converter options for IUPAC
5151
const IUPAC_CONVERTER_OPTIONS = [{ id: "opsin", label: "OPSIN" }];
5252

53+
// Detect whether input text is SMILES, SELFIES, or IUPAC name
54+
const detectInputFormat = (text) => {
55+
const trimmed = text.trim();
56+
if (!trimmed) return null;
57+
58+
// SELFIES: entirely composed of [token] sequences
59+
if (/^(\[[\w@=#+\-/\\%;.,^*]+\])+$/.test(trimmed)) return "selfies";
60+
61+
// IUPAC: word-like name — only lowercase letters, digits, spaces, hyphens, commas,
62+
// parentheses; and no SMILES ring-closure patterns (letter immediately adjacent to digit)
63+
if (
64+
/^[a-z0-9][a-z0-9 ,\-().]*$/.test(trimmed) &&
65+
!/[a-z]\d/.test(trimmed) &&
66+
!/\d[a-z]/.test(trimmed)
67+
) {
68+
return "iupac";
69+
}
70+
71+
// SMILES: no whitespace, only valid SMILES characters
72+
if (!/\s/.test(trimmed) && /^[A-Za-z0-9[\]()=#@+\-/.\\%:*]+$/.test(trimmed))
73+
return "smiles";
74+
75+
// Otherwise assume IUPAC name
76+
return "iupac";
77+
};
78+
5379
const FormatConversionView = () => {
5480
const [input, setInput] = useState("");
5581
const [inputFormat, setInputFormat] = useState("smiles");
@@ -60,6 +86,7 @@ const FormatConversionView = () => {
6086
const [loading, setLoading] = useState(false);
6187
const [error, setError] = useState(null);
6288
const [copied, setCopied] = useState(false);
89+
const [autoDetected, setAutoDetected] = useState(false);
6390
// State for molecular structure display
6491
const [smilesForStructure, setSmilesForStructure] = useState("");
6592
const [showStructure, setShowStructure] = useState(false);
@@ -170,6 +197,7 @@ const FormatConversionView = () => {
170197
// When input format changes, automatically update output format if needed
171198
const handleInputFormatChange = (format) => {
172199
setInputFormat(format);
200+
setAutoDetected(false); // User manually overrode auto-detection
173201

174202
// Clear uploaded file when switching away from molsdf
175203
if (format !== "molsdf") {
@@ -182,6 +210,27 @@ const FormatConversionView = () => {
182210
}
183211
};
184212

213+
// Handle text input changes with auto-format detection
214+
const handleInputChange = (value) => {
215+
setInput(value);
216+
if (inputFormat === "molsdf") return;
217+
218+
const detected = detectInputFormat(value);
219+
if (!value.trim()) {
220+
setAutoDetected(false);
221+
return;
222+
}
223+
if (detected && detected !== inputFormat) {
224+
setInputFormat(detected);
225+
setAutoDetected(true);
226+
if (detected === "iupac" || detected === "selfies") {
227+
setOutputFormat("smiles");
228+
} else if (detected === "smiles") {
229+
setOutputFormat("canonicalsmiles");
230+
}
231+
}
232+
};
233+
185234
// When output format changes, we may need to adjust toolkit availability
186235
const handleOutputFormatChange = (format) => {
187236
setOutputFormat(format);
@@ -365,12 +414,19 @@ const FormatConversionView = () => {
365414
<form onSubmit={handleSubmit} className="space-y-4">
366415
{/* Input Format Selection */}
367416
<div>
368-
<label
369-
htmlFor="input-format-select"
370-
className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1"
371-
>
372-
Input Format
373-
</label>
417+
<div className="flex items-center justify-between mb-1">
418+
<label
419+
htmlFor="input-format-select"
420+
className="block text-sm font-medium text-gray-700 dark:text-gray-300"
421+
>
422+
Input Format
423+
</label>
424+
{autoDetected && (
425+
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-300">
426+
Auto-detected
427+
</span>
428+
)}
429+
</div>
374430
<select
375431
id="input-format-select"
376432
value={inputFormat}
@@ -498,7 +554,7 @@ const FormatConversionView = () => {
498554
<>
499555
<SMILESInput
500556
value={input}
501-
onChange={setInput}
557+
onChange={handleInputChange}
502558
label={
503559
inputFormat === "smiles"
504560
? "SMILES Input"
@@ -700,7 +756,7 @@ const FormatConversionView = () => {
700756
Converted from{" "}
701757
{INPUT_FORMAT_OPTIONS.find((o) => o.id === inputFormat)?.label ||
702758
inputFormat.toUpperCase()}
703-
to{" "}
759+
{" "}to{" "}
704760
{OUTPUT_FORMAT_OPTIONS.find((o) => o.id === outputFormat)?.label ||
705761
outputFormat.toUpperCase()}
706762
{showToolkitSelection &&

‎ops/docker-compose-dev.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ services:
2424
environment:
2525
HOMEPAGE_URL: "/latest/docs"
2626
RELEASE_VERSION: dev-latest
27+
CMS_INTERNAL_AUTH_TOKEN: ${CMS_INTERNAL_AUTH_TOKEN}
2728
pull_policy: always
2829
labels:
2930
- "traefik.enable=true"

‎ops/docker-compose-prod.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ services:
2525
environment:
2626
HOMEPAGE_URL: "/latest/docs" # App serves docs at /latest/docs
2727
RELEASE_VERSION: v2.6.0 # Or dynamically set from release tag
28+
CMS_INTERNAL_AUTH_TOKEN: ${CMS_INTERNAL_AUTH_TOKEN}
2829
# pull_policy: always # Use if pulling pre-built images
2930
labels:
3031
- "traefik.enable=true"

‎ops/docker-compose.lite.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ services:
2323
HOMEPAGE_URL: "https://docs.api.naturalproducts.net"
2424
WORKERS: "2"
2525
INCLUDE_OCSR: "false"
26+
CMS_INTERNAL_AUTH_TOKEN: ${CMS_INTERNAL_AUTH_TOKEN}
2627
HTTP_PROXY: "http://internet4nzm.rz.uni-jena.de:3128"
2728
HTTPS_PROXY: "http://internet4nzm.rz.uni-jena.de:3128"
2829
NO_PROXY: "localhost,127.0.0.1,::1,.uni-jena.de,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"

‎package-lock.json‎

Lines changed: 0 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)