diff --git a/.env.production.example b/.env.production.example
index bbbed471bc..e8c592eceb 100644
--- a/.env.production.example
+++ b/.env.production.example
@@ -1,7 +1,32 @@
-SFTP_HOST=sftp-host-production
-SFTP_PORT=sftp-port-production
-SFTP_UPLOAD_FOLDER=sftp-upload-folder # e.g. uploads
-SFTP_USER=sftp-user-production
+# default uri of your Chemotion ELN for http links in e-mails and notification:
+PUBLIC_URL='http://sld.tld'
+# senders e-mail:
+DEVISE_SENDER='no-reply@sld.tld'
+
+## SMTP config
+# Remote mail server
+SMTP_ADDRESS='smtp.sld.tld'
+SMTP_PORT=587
+# login user name & password:
+SMTP_USERNAME='no-reply@sld.tld'
+SMTP_PASSWORD='s3cr3tPW'
+# optional, HELO domain
+SMTP_DOMAIN='sld.tld'
+# detect STARTTLS
+SMTP_TLS=true
+# authentication type ('plain' 'login' (Base64 encoded) or 'cram_md5')
+SMTP_AUTH='plain'
+# how OpenSSL checks the certificate ('none' or 'peer')
+SMTP_SSL_MODE='none'
+
+# disable mail delivery
+# DISABLE_MAIL_DELIVERY='nomail'
+
+
+#SFTP_HOST=sftp-host-production
+#SFTP_PORT=sftp-port-production
+#SFTP_UPLOAD_FOLDER=sftp-upload-folder # e.g. uploads
+#SFTP_USER=sftp-user-production
# Choose between password and ssh-key authentication.
# The default key locations are ~/.ssh/id_rsa,~/.ssh/id_dsa. If you want to use
diff --git a/.eslintrc b/.eslintrc
index bda07eb179..12395e3e8f 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,5 +1,5 @@
{
- "parser": "babel-eslint",
+ "parser": "@babel/eslint-parser",
"plugins": [
"react"
],
diff --git a/.nvmrc b/.nvmrc
index 158c00641a..fa6bc3a85c 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-v14.16.0
+v14.20.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8ecd3c73fb..cf97c0e52f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,7 +10,35 @@
* Fixes
-# [v1.3.1-pre]
+## [v1.4.0]
+> 2022-09-26
+
+* Important for admin and developers:
+ * change of environment variable: use PUBLIC_URL instead of HOST and SMTP_HOST
+ * nodejs upd to 14.20.0
+ * drop support for bionic
+
+* Features and Improvements:
+ * ketcherservice: server generation of sample svg
+ * Reaction coefficient: improve yield calculation (https://github.com/ComPlat/chemotion_ELN/issues/544)
+ * Metadata-converter: v0.6.0
+ * Chemspectra: v0.10.15 (allow reprocessing, read Bruker processed files if present)
+ * Inbox: delete multiple attachments at once (https://github.com/ComPlat/chemotion_ELN/issues/571)
+ * research-plan: improve context-menu in tables
+
+
+* Fixes:
+ * SVG generation for sample and reaction: (https://github.com/ComPlat/chemotion_ELN/issues/846)
+ * Sample amount metric
+ * report svg composer: skip image if image file does not exist.
+ * chemspectra: duplicate image generation
+
+
+
+
+
+
+## [v1.3.1]
> 2022-07-07
* Features and Improvements:
diff --git a/VERSION b/VERSION
index 78402df0cf..e1e5a88fb6 100644
--- a/VERSION
+++ b/VERSION
@@ -1,3 +1,3 @@
-version: 1.3.1
-base_revision: d7c0c64dda79f938430e5236ce7559ab3bc17242
+version: 1.4.0
+base_revision: 9a6c2441a52356989aa69da67f8283a27a279ff6
current_revision: 0
diff --git a/app/packs/src/components/CollectionManagement.js b/app/packs/src/components/CollectionManagement.js
index 3b1ffd6da2..2e9cef559a 100644
--- a/app/packs/src/components/CollectionManagement.js
+++ b/app/packs/src/components/CollectionManagement.js
@@ -5,7 +5,6 @@ import MyCollections from './collection_management/MyCollections';
import MySharedCollections from './collection_management/MySharedCollections';
import SharedWithMeCollections from './collection_management/SharedWithMeCollections';
import SyncWithMeCollections from './collection_management/SyncWithMeCollections';
-import XTabs from './extra/CollectionManagementXTabs';
const CollectionManagement = () => {
const tabContents = [
@@ -14,17 +13,6 @@ const CollectionManagement = () => {
,
,
];
- const offset = tabContents.length;
- for (let j = 0; j < XTabs.count; j += 1) {
- if (XTabs[`on${j}`]()) {
- const NoName = XTabs[`content${j}`];
- tabContents.push((
-
-
-
- ));
- }
- }
return (
diff --git a/app/packs/src/components/CollectionTree.js b/app/packs/src/components/CollectionTree.js
index cd5f1d09b6..50c2ca3254 100644
--- a/app/packs/src/components/CollectionTree.js
+++ b/app/packs/src/components/CollectionTree.js
@@ -10,7 +10,6 @@ import LoadingActions from './actions/LoadingActions';
import UIStore from './stores/UIStore';
import ElementStore from './stores/ElementStore';
import InboxStore from './stores/InboxStore';
-import Xdiv from './extra/CollectionTreeXdiv';
import UserInfos from './UserInfos';
import DeviceBox from './inbox/DeviceBox';
@@ -287,11 +286,6 @@ export default class CollectionTree extends React.Component {
render() {
let {ownCollectionVisible, inboxVisible, inbox} = this.state
- let extraDiv = [];
- for (let j=0;j < Xdiv.count;j++){
- let NoName = Xdiv["content"+j];
- extraDiv.push(
);
- }
const ownCollectionDisplay = ownCollectionVisible ? '' : 'none';
const inboxDisplay = inboxVisible ? '' : 'none';
@@ -320,7 +314,6 @@ export default class CollectionTree extends React.Component {
{this.remoteSyncInSubtrees()}
- {extraDiv.map((e)=>{return e})}
- {tdExtraContents.map(e => e)}
diff --git a/app/packs/src/components/ReactionDetails.js b/app/packs/src/components/ReactionDetails.js
index e5b5d3190e..586c65bad3 100644
--- a/app/packs/src/components/ReactionDetails.js
+++ b/app/packs/src/components/ReactionDetails.js
@@ -20,7 +20,6 @@ import ReactionDetailsProperties from './ReactionDetailsProperties';
import GreenChemistry from './green_chem/GreenChemistry';
import Utils from './utils/Functions';
import PrintCodeButton from './common/PrintCodeButton';
-import XTabs from './extra/ReactionDetailsXTabs';
import UIStore from './stores/UIStore';
import UIActions from './actions/UIActions';
import { setReactionByType } from './ReactionDetailsShare';
@@ -231,19 +230,6 @@ export default class ReactionDetails extends Component {
);
}
- extraTab(ind) {
- const reaction = this.state.reaction || {};
- const num = ind;
- const NoName = XTabs["content"+num];
- const TabName = XTabs["title"+num];
- return (
-
-
-
-
-
- );
- }
reactionSVG(reaction) {
if(!reaction.svgPath) {
@@ -450,19 +436,6 @@ export default class ReactionDetails extends Component {
green_chemistry: 'Green Chemistry'
}
- for (let j = 0; j < XTabs.count; j += 1) {
- if (XTabs[`on${j}`](reaction)) {
- const NoName = XTabs[`content${j}`];
- tabContentsMap[`xtab_${j}`] = (
-
-
-
-
-
- );
- tabTitlesMap[`xtab_${j}`] = XTabs[`title${j}`];
- }
- }
addSegmentTabs(reaction, this.handleSegmentsChange, tabContentsMap);
diff --git a/app/packs/src/components/SampleDetails.js b/app/packs/src/components/SampleDetails.js
index c746fd1cd2..c53fd775cf 100644
--- a/app/packs/src/components/SampleDetails.js
+++ b/app/packs/src/components/SampleDetails.js
@@ -34,9 +34,6 @@ import PubchemLabels from './PubchemLabels';
import ElementReactionLabels from './ElementReactionLabels';
import SampleDetailsContainers from './SampleDetailsContainers';
-import XLabels from './extra/SampleDetailsXLabels';
-import XTabs from './extra/SampleDetailsXTabs';
-
import StructureEditorModal from './structure_editor/StructureEditorModal';
import Sample from './models/Sample';
@@ -557,7 +554,6 @@ export default class SampleDetails extends React.Component {
{colLabel}
- {this.extraLabels().map((Lab, i) =>
)}
@@ -1136,13 +1132,6 @@ export default class SampleDetails extends React.Component {
);
}
- extraLabels() {
- let labels = [];
- for (let j = 0; j < XLabels.count; j += 1) {
- labels.push(XLabels[`content${j}`]);
- }
- return labels;
- }
sampleIsValid() {
const { sample, loadingMolecule, quickCreator } = this.state;
@@ -1295,19 +1284,6 @@ export default class SampleDetails extends React.Component {
measurements: 'Measurements!'
};
- for (let j = 0; j < XTabs.count; j += 1) {
- if (XTabs[`on${j}`](sample)) {
- const NoName = XTabs[`content${j}`];
- tabContentsMap[`xtab_${j}`] = (
-
-
-
-
-
- );
- tabTitlesMap[`xtab_${j}`] = XTabs[`title${j}`];
- }
- }
addSegmentTabs(sample, this.handleSegmentsChange, tabContentsMap);
const stb = [];
diff --git a/app/packs/src/components/inbox/InboxModal.js b/app/packs/src/components/inbox/InboxModal.js
index d39ecac019..73987287b3 100644
--- a/app/packs/src/components/inbox/InboxModal.js
+++ b/app/packs/src/components/inbox/InboxModal.js
@@ -9,8 +9,6 @@ import LoadingActions from '../actions/LoadingActions';
import DeviceBox from '../inbox/DeviceBox';
import UnsortedBox from '../inbox/UnsortedBox';
-import Xdiv from '../extra/CollectionTreeXdiv';
-
export default class InboxModal extends React.Component {
constructor(props) {
super(props);
@@ -90,11 +88,6 @@ export default class InboxModal extends React.Component {
const { showCollectionTree } = this.props;
const { visible, inboxVisible } = this.state;
- const extraDiv = [];
- for (let j = 0; j < Xdiv.count; j += 1) {
- const NoName = Xdiv[`Xdiv${j}`];
- extraDiv.push(
);
- }
const panelClass = showCollectionTree ? 'small-col col-md-6' : 'small-col col-md-5';
const inboxDisplay = inboxVisible ? '' : 'none';
diff --git a/app/packs/src/components/routes.js b/app/packs/src/components/routes.js
index 9fdec921e9..afd9f4c66b 100644
--- a/app/packs/src/components/routes.js
+++ b/app/packs/src/components/routes.js
@@ -5,18 +5,11 @@ import UserStore from './stores/UserStore';
import UIActions from './actions/UIActions';
import UserActions from './actions/UserActions';
import ElementActions from './actions/ElementActions';
-import rXr from './extra/routesXroutes';
import * as routesUtils from './routesUtils';
import UIFetcher from './fetchers/UIFetcher';
import klasses from '../../../../config/klasses.json';
-const allRoutes = (r) => {
- let rts = { ...r };
- for (let i = 0; i < rXr.count; i++) { rts = { ...rts, ...rXr[`content${i}`] }; }
- return rts;
-}
-
const routes = {
'/': 'root',
target: {
@@ -134,5 +127,5 @@ klasses && klasses.forEach((klass) => {
export default function() {
Aviator.root = '/mydb';
Aviator.pushStateEnabled = true;
- Aviator.setRoutes(allRoutes(routes));
+ Aviator.setRoutes(routes);
}
diff --git a/app/packs/src/components/search/SearchFilter.js b/app/packs/src/components/search/SearchFilter.js
index b37da55f05..20accf6e87 100644
--- a/app/packs/src/components/search/SearchFilter.js
+++ b/app/packs/src/components/search/SearchFilter.js
@@ -2,7 +2,7 @@ import React from 'react'
import {Button, FormControl} from 'react-bootstrap'
import Select from 'react-select'
import UIActions from '../actions/UIActions';
-import XSearchParams from "../extra/AdvancedSearchXSearchParams";
+
export default class SearchFilter extends React.Component {
constructor(props) {
@@ -60,11 +60,7 @@ export default class SearchFilter extends React.Component {
}
];
- for (let i = 0; i < XSearchParams.count; i++){
- if (XSearchParams[`on${i}`]) {
- this.listOptions = this.listOptions.concat(XSearchParams[`content${i}`])
- }
- }
+
this.andOrOps = [
{ value: "AND", label: "AND" },
diff --git a/app/packs/src/components/stores/CollectionStore.js b/app/packs/src/components/stores/CollectionStore.js
index ac61505b30..a07dc3a115 100644
--- a/app/packs/src/components/stores/CollectionStore.js
+++ b/app/packs/src/components/stores/CollectionStore.js
@@ -1,12 +1,6 @@
import alt from '../alt';
import CollectionActions from '../actions/CollectionActions';
-import {extraThing} from '../utils/Functions';
-import Xlisteners from '../extra/CollectionStoreXlisteners';
-import Xhandlers from '../extra/CollectionStoreXhandlers';
-import Xstate from '../extra/CollectionStoreXstate';
-
-
class CollectionStore {
constructor() {
@@ -18,15 +12,8 @@ class CollectionStore {
lockedRoots: [],
syncInRoots: [],
visibleRootsIds: [],
- ...extraThing(Xstate)
};
- for (let i = 0 ; i < Xlisteners.count; i++){
- Object.keys(Xlisteners["content"+i]).map((k)=>{
- this.bindAction(Xlisteners["content" + i][k],
- Xhandlers["content" + i][k].bind(this))
- });
- }
this.bindListeners({
handleTakeOwnership: CollectionActions.takeOwnership,
diff --git a/app/packs/src/components/stores/ElementStore.js b/app/packs/src/components/stores/ElementStore.js
index 8b8905443c..ca680df78a 100644
--- a/app/packs/src/components/stores/ElementStore.js
+++ b/app/packs/src/components/stores/ElementStore.js
@@ -31,10 +31,6 @@ import WellplatesFetcher from '../fetchers/WellplatesFetcher';
import ScreensFetcher from '../fetchers/ScreensFetcher';
import ModalImportConfirm from '../contextActions/ModalImportConfirm';
-import { extraThing } from '../utils/Functions';
-import Xlisteners from '../extra/ElementStoreXlisteners';
-import Xhandlers from '../extra/ElementStoreXhandlers';
-import Xstate from '../extra/ElementStoreXstate';
import { elementShowOrNew } from '../routesUtils';
import DetailActions from '../actions/DetailActions';
@@ -112,18 +108,9 @@ class ElementStore {
activeKey: 0,
deletingElement: null,
////
- ...extraThing(Xstate)
};
-
- for (let i = 0; i < Xlisteners.count; i++){
- Object.keys(Xlisteners["content"+i]).map((k) => {
- this.bindAction(Xlisteners["content" + i][k],
- Xhandlers["content" + i][k].bind(this))
- });
- }
-
this.bindListeners({
handleFetchAllDevices: ElementActions.fetchAllDevices,
handleFetchDeviceById: ElementActions.fetchDeviceById,
diff --git a/app/packs/src/components/utils/Functions.js b/app/packs/src/components/utils/Functions.js
index f2d273c3e1..21bf45ca53 100644
--- a/app/packs/src/components/utils/Functions.js
+++ b/app/packs/src/components/utils/Functions.js
@@ -24,11 +24,6 @@ const Functions = {
link.dispatchEvent(event);
},
- extraThing(extra) {
- let obj = {};
- for (let i = 0; i < extra['count'];i++){obj={...obj,...extra['content'+i]} }
- return obj;
- }
};
diff --git a/app/packs/src/libHome/Home.js b/app/packs/src/libHome/Home.js
index f10965a001..8d1711316c 100644
--- a/app/packs/src/libHome/Home.js
+++ b/app/packs/src/libHome/Home.js
@@ -3,17 +3,8 @@ import ReactDOM from 'react-dom';
import { Grid, Row } from 'react-bootstrap';
import Navigation from '../components/Navigation'
-import XHome from '../components/extra/HomeXHome'
import WelcomeMessage from '../components/WelcomeMessage';
-const extraHomes = () => {
- const homes = [];
- const count = XHome.count || 0;
- for (let j = 0; j < count; j += 1) {
- homes.push(XHome[`content${j}`]);
- }
- return homes;
-};
class Home extends Component {
constructor(props) {
@@ -23,17 +14,14 @@ class Home extends Component {
render() {
return (
- { XHome.count && XHome.count > 0
- ? extraHomes().map((Annex, i) =>
)
- :
-
-
-
-
-
-
-
- }
+
+
+
+
+
+
+
+
);
}
diff --git a/config/deploy.rb b/config/deploy.rb
index 72ea102fc5..51d61ec910 100644
--- a/config/deploy.rb
+++ b/config/deploy.rb
@@ -15,7 +15,7 @@
set :bundle_jobs, 4 # parallel bundler
set :nvm_type, :user
-set :nvm_node, File.exist?('.nvmrc') && File.read('.nvmrc').strip || 'v14.16.0'
+set :nvm_node, File.exist?('.nvmrc') && File.read('.nvmrc').strip || 'v14.20.0'
set :npm_version, File.exist?('.npm-version') && File.read('.npm-version').strip || '7.11.1'
set :nvm_map_bins, fetch(:nvm_map_bins, []).push('rake')
set :nvm_map_bins, fetch(:nvm_map_bins, []).push('bundle')
diff --git a/scripts/install_development.sh b/scripts/install_development.sh
index e4611544a7..f3b06280c3 100755
--- a/scripts/install_development.sh
+++ b/scripts/install_development.sh
@@ -19,12 +19,12 @@ PROD=chemotion
# PROD_HOME=$(eval echo "~$PROD")
## RUBY
-RUBY_VERSION=2.6.6 # 2.5 recommended for bionic
+RUBY_VERSION=2.6.8
BUNDLER_VERSION=1.17.3
## NODEJS
NVM_VERSION='v0.38.0'
-NODE_VERSION=14.16.0
+NODE_VERSION=14.20.0
NPM_VERSION=7.11.1
YARN_VERSION=1.22.10
@@ -79,12 +79,8 @@ PART_9='log-rotation'
## supported Distribution Version
. /etc/os-release
-V18='bionic'
V20='focal'
V10='buster'
-# if [ "$VERSION_CODENAME" = "$V18" ]; then
-# RUBY_VERSION=2.5.8
-# fi
GRE='\033[0;32m'
@@ -130,7 +126,7 @@ rm_tmp_repo() {
trap "rm_tmp; rm_tmp_repo; red 'An error has occured'" ERR
-if [ "$VERSION_CODENAME" = "$V10" ] || [ "$VERSION_CODENAME" = "$V18" ] || [ "$VERSION_CODENAME" = "$V20" ]; then
+if [ "$VERSION_CODENAME" = "$V10" ] || [ "$VERSION_CODENAME" = "$V20" ]; then
sharpi "Running installation for $PRETTY_NAME "
else
error "The installation for your distribution ($PRETTY_NAME) has not been tested"
diff --git a/scripts/install_production.sh b/scripts/install_production.sh
index b92a803e18..f94d6a5736 100755
--- a/scripts/install_production.sh
+++ b/scripts/install_production.sh
@@ -11,7 +11,7 @@ set -euo pipefail
############# VARIABLES ####################
REPO='https://github.com/ComPlat/chemotion_ELN.git'
-BRANCH='v1.3'
+BRANCH='v1.4'
TMP_REPO_DIR="/tmp/${BRANCH}.git"
## user account name (to be created or to be used)
@@ -20,12 +20,12 @@ PROD=production
# PROD_HOME=$(eval echo "~$PROD")
## RUBY
-RUBY_VERSION=2.6.6 # 2.5 recommended for bionic
+RUBY_VERSION=2.6.8
BUNDLER_VERSION=1.17.3
## NODEJS
NVM_VERSION='v0.38.0'
-NODE_VERSION=14.16.0
+NODE_VERSION=14.20.0
NPM_VERSION=7.11.1
APP_NAME=chemotion_ELN # used for naming directories and files
@@ -87,12 +87,8 @@ PART_11='configure NGINX'
## supported Distribution Version
. /etc/os-release
-V18='bionic'
V20='focal'
V10='buster'
-# if [ "$VERSION_CODENAME" = "$V18" ]; then
-# RUBY_VERSION=2.5.8
-# fi
GRE='\033[0;32m'
YEL='\033[0;33m'
@@ -137,7 +133,7 @@ rm_tmp_repo() {
trap "rm_tmp; rm_tmp_repo; red 'An error has occured'" ERR
-if [ "$VERSION_CODENAME" = "$V10" ] || [ "$VERSION_CODENAME" = "$V18" ] || [ "$VERSION_CODENAME" = "$V20" ]; then
+if [ "$VERSION_CODENAME" = "$V10" ] || [ "$VERSION_CODENAME" = "$V20" ]; then
sharpi "Running installation for $PRETTY_NAME "
else
error "The installation for your distribution ($PRETTY_NAME) has not been tested"
diff --git a/scripts/update_production.sh b/scripts/update_production.sh
index f611f6aa93..411759bc97 100755
--- a/scripts/update_production.sh
+++ b/scripts/update_production.sh
@@ -9,7 +9,7 @@ set -euo pipefail
## CHEMOTION ELN GIT REPOSITORY
REPO='https://github.com/ComPlat/chemotion_ELN.git'
-BRANCH='v1.3'
+BRANCH='v1.4'
TMP_REPO_DIR="/tmp/${BRANCH}.git"
## user account name (to be created or to be used)
@@ -17,12 +17,12 @@ PROD=production
PROD_HOME=$(eval echo "~$PROD")
## RUBY
-RUBY_VERSION=2.6.6
+RUBY_VERSION=2.6.8
BUNDLER_VERSION=1.17.3
## NODEJS
NVM_VERSION='v0.38.0'
-NODE_VERSION=14.16.0
+NODE_VERSION=14.20.0
NPM_VERSION=7.11.1
## default naming of directories and files