summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/dev/dnpm/oshelper/analyzer/AtcCodesHelper.java104
-rw-r--r--src/main/java/dev/dnpm/oshelper/analyzer/IPluginPart.java2
-rw-r--r--src/main/java/dev/dnpm/oshelper/atc/services/CsvAgentCodeService.java2
-rw-r--r--src/main/java/dev/dnpm/oshelper/atc/services/OnkostarAgentCodeService.java2
-rw-r--r--src/main/java/dev/dnpm/oshelper/config/PluginConfiguration.java15
-rw-r--r--src/main/resources/de/itc/onkostar/library/moduleContext.xml5
-rw-r--r--src/main/resources/dev/dnpm/oshelper/js/AtcCodesDialog.js337
-rw-r--r--src/main/resources/onkostar-config.properties2
8 files changed, 460 insertions, 9 deletions
diff --git a/src/main/java/dev/dnpm/oshelper/analyzer/AtcCodesHelper.java b/src/main/java/dev/dnpm/oshelper/analyzer/AtcCodesHelper.java
new file mode 100644
index 0000000..43929be
--- /dev/null
+++ b/src/main/java/dev/dnpm/oshelper/analyzer/AtcCodesHelper.java
@@ -0,0 +1,104 @@
+/*
+ * This file is part of onkostar-plugin-dnpm
+ *
+ * Copyright (c) 2025 the original author or authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package dev.dnpm.oshelper.analyzer;
+
+import de.itc.onkostar.api.Disease;
+import de.itc.onkostar.api.Procedure;
+import de.itc.onkostar.api.analysis.AnalyzerRequirement;
+import dev.dnpm.oshelper.atc.AgentCode;
+import dev.dnpm.oshelper.atc.services.AgentCodeService;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Component
+public class AtcCodesHelper extends BackendService {
+
+ private final List<AgentCodeService> agentCodeServices;
+
+ public AtcCodesHelper(List<AgentCodeService> agentCodeServices) {
+ this.agentCodeServices = agentCodeServices;
+ }
+
+ /**
+ * @deprecated
+ */
+ @Override
+ public boolean isRelevantForDeletedProcedure() {
+ return false;
+ }
+
+ @Override
+ public boolean isRelevantForAnalyzer(Procedure procedure, Disease disease) {
+ return false;
+ }
+
+ @Override
+ public boolean isSynchronous() {
+ return false;
+ }
+
+ @Override
+ public AnalyzerRequirement getRequirement() {
+ return AnalyzerRequirement.PROCEDURE;
+ }
+
+ /**
+ * Return list with ATC codes and agents.
+ * Usage in script:
+ *
+ * <pre>
+ * executePluginMethod(
+ * 'AtcCodesHelper',
+ * 'query',
+ * { q: '', size: 10 },
+ * function (result) {console.log(result);},
+ * false
+ * );
+ * </pre>
+ *
+ * @param input The data Map
+ * @return The result list filtered by input
+ */
+ public List<AgentCode> query(final Map<String, Object> input) {
+ String query = "";
+ if (null != input.get("q")) {
+ query = input.get("q").toString();
+ }
+
+ int size = Integer.parseInt(input.get("size").toString());
+ if (size == 0) {
+ size = 10;
+ }
+ var result = new ArrayList<AgentCode>();
+ for (var agentCodeService : this.agentCodeServices) {
+ result.addAll(agentCodeService.findAgentCodes(query, size));
+ }
+ return result.stream().distinct().sorted().collect(Collectors.toList());
+ }
+}
diff --git a/src/main/java/dev/dnpm/oshelper/analyzer/IPluginPart.java b/src/main/java/dev/dnpm/oshelper/analyzer/IPluginPart.java
index 21cbf53..119f2ac 100644
--- a/src/main/java/dev/dnpm/oshelper/analyzer/IPluginPart.java
+++ b/src/main/java/dev/dnpm/oshelper/analyzer/IPluginPart.java
@@ -29,7 +29,7 @@ import de.itc.onkostar.api.analysis.IProcedureAnalyzer;
public interface IPluginPart extends IProcedureAnalyzer {
default String getVersion() {
- return "0.4.0";
+ return "2.0.0";
}
default String getName() {
diff --git a/src/main/java/dev/dnpm/oshelper/atc/services/CsvAgentCodeService.java b/src/main/java/dev/dnpm/oshelper/atc/services/CsvAgentCodeService.java
index ebca932..4ffd1f2 100644
--- a/src/main/java/dev/dnpm/oshelper/atc/services/CsvAgentCodeService.java
+++ b/src/main/java/dev/dnpm/oshelper/atc/services/CsvAgentCodeService.java
@@ -45,7 +45,6 @@ import java.util.stream.Collectors;
* @author Paul-Christian Volkmer
* @since 2.0.0
*/
-@Service
public class CsvAgentCodeService implements AgentCodeService {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@@ -105,6 +104,7 @@ public class CsvAgentCodeService implements AgentCodeService {
} catch (IOException | FileParsingException e) {
logger.warn("Error reading information from ATC codes");
}
+ logger.info("Found {} ATC codes", result.size());
return result;
}
diff --git a/src/main/java/dev/dnpm/oshelper/atc/services/OnkostarAgentCodeService.java b/src/main/java/dev/dnpm/oshelper/atc/services/OnkostarAgentCodeService.java
index 62f12b7..024ce79 100644
--- a/src/main/java/dev/dnpm/oshelper/atc/services/OnkostarAgentCodeService.java
+++ b/src/main/java/dev/dnpm/oshelper/atc/services/OnkostarAgentCodeService.java
@@ -28,7 +28,6 @@ import dev.dnpm.oshelper.atc.AgentCode;
import dev.dnpm.oshelper.atc.AtcCode;
import dev.dnpm.oshelper.atc.UnregisteredCode;
import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.stereotype.Service;
import javax.sql.DataSource;
import java.util.List;
@@ -39,7 +38,6 @@ import java.util.List;
* @author Paul-Christian Volkmer
* @since 2.0.0
*/
-@Service
public class OnkostarAgentCodeService implements AgentCodeService {
private final JdbcTemplate jdbcTemplate;
diff --git a/src/main/java/dev/dnpm/oshelper/config/PluginConfiguration.java b/src/main/java/dev/dnpm/oshelper/config/PluginConfiguration.java
index ebf11c3..92bd4c3 100644
--- a/src/main/java/dev/dnpm/oshelper/config/PluginConfiguration.java
+++ b/src/main/java/dev/dnpm/oshelper/config/PluginConfiguration.java
@@ -24,6 +24,9 @@
package dev.dnpm.oshelper.config;
+import dev.dnpm.oshelper.atc.services.AgentCodeService;
+import dev.dnpm.oshelper.atc.services.CsvAgentCodeService;
+import dev.dnpm.oshelper.atc.services.OnkostarAgentCodeService;
import dev.dnpm.oshelper.database.SettingsRepository;
import dev.dnpm.oshelper.services.*;
import dev.dnpm.oshelper.services.consent.ConsentManagerServiceFactory;
@@ -51,7 +54,7 @@ import javax.sql.DataSource;
*/
@Configuration
@ComponentScan(basePackages = {"dev.dnpm.oshelper.analyzer", "dev.dnpm.oshelper.security"})
-@EnableJpaRepositories(basePackages = "dev.dnpm.database")
+@EnableJpaRepositories(basePackages = "dev.dnpm.oshelper.database")
public class PluginConfiguration {
@Bean
@@ -109,4 +112,14 @@ public class PluginConfiguration {
return new OsMolekulargenetikFormService();
}
+ @Bean
+ public AgentCodeService csvAgentCodeService() {
+ return new CsvAgentCodeService();
+ }
+
+ @Bean
+ public AgentCodeService onkostarAgentCodeService (final DataSource dataSource) {
+ return new OnkostarAgentCodeService(dataSource);
+ }
+
}
diff --git a/src/main/resources/de/itc/onkostar/library/moduleContext.xml b/src/main/resources/de/itc/onkostar/library/moduleContext.xml
index 3fc2a1d..0a03d31 100644
--- a/src/main/resources/de/itc/onkostar/library/moduleContext.xml
+++ b/src/main/resources/de/itc/onkostar/library/moduleContext.xml
@@ -22,9 +22,8 @@
<constructor-arg ref="consentManagerServiceFactory" />
</bean>
- <context:component-scan base-package="de.ukw.ccc.onkostar.atccodes" />
- <context:component-scan base-package="DNPM.config" />
+ <context:component-scan base-package="dev.dnpm.oshelper.config" />
<mvc:resources mapping="/app/lib/umr/**/*.js" location="classpath:/app/lib/umr/" />
- <mvc:resources mapping="/app/plugins/atccodes/**/*.js" location="classpath:/de/ukw/ccc/onkostar/atccodes/" />
+ <mvc:resources mapping="/app/plugins/oshelper/**/*.js" location="classpath:/dev/dnpm/oshelper/js/" />
</beans> \ No newline at end of file
diff --git a/src/main/resources/dev/dnpm/oshelper/js/AtcCodesDialog.js b/src/main/resources/dev/dnpm/oshelper/js/AtcCodesDialog.js
new file mode 100644
index 0000000..e6c9c53
--- /dev/null
+++ b/src/main/resources/dev/dnpm/oshelper/js/AtcCodesDialog.js
@@ -0,0 +1,337 @@
+/*
+ * This file is part of onkostar-plugin-dnpm
+ *
+ * Copyright (c) 2025 the original author or authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+class AtcCodesDialog {
+
+ static show(context, plainfield = 'wirkstoffe', jsonfield = 'wirkstoffejson') {
+
+ const availableStore = new Ext.data.ArrayStore({
+ fields: [
+ {name: 'code'},
+ {name: 'name'},
+ {name: 'system'},
+ {name: 'version'}
+ ]
+ });
+
+ const selectedStore = new Ext.data.ArrayStore({
+ fields: [
+ {name: 'code'},
+ {name: 'name'},
+ {name: 'system'},
+ {name: 'version'}
+ ]
+ });
+
+ let pluginRequestsDisabled = false;
+ let available = [];
+ let selected = [];
+ let blockIndex = null;
+
+ const findButtonFieldFormInformation = () => {
+ const findElemId = (elem) => {
+ if (elem.tagName === 'BODY') {
+ return undefined;
+ }
+
+ if (elem.tagName === 'TABLE') {
+ return elem.id;
+ }
+
+ return findElemId(elem.parentElement);
+ }
+
+ const formInfo = (formItem, blockIndex = undefined) => {
+ if (formItem.xtype === 'buttonField') {
+ return formInfo(formItem.ownerCt, formItem.blockIndex);
+ }
+
+ if (formItem.xtype === 'panel') {
+ return formInfo(formItem.ownerCt, blockIndex);
+ }
+
+ if (formItem.xtype === 'subformField') {
+ return {
+ isSubform: true,
+ formName: formItem.formName,
+ subformFieldName: formItem.subformName,
+ blockIndex: blockIndex
+ };
+ }
+
+ if (formItem.xtype === 'form') {
+ return {
+ isSubform: false,
+ };
+ }
+
+ console.warn('No information found!');
+ return undefined;
+ }
+
+ if (context.genericEditForm && document.activeElement.tagName === 'BUTTON') {
+ let elemId = findElemId(document.activeElement);
+ if (elemId) {
+ let formItem = context.genericEditForm.down('#'+elemId);
+ if (formItem) {
+ return formInfo(formItem);
+ }
+ }
+ }
+
+ return undefined;
+ }
+
+ const request = (q) => {
+ if (pluginRequestsDisabled || !context.executePluginMethod) return;
+ context.executePluginMethod(
+ 'AtcCodesHelper',
+ 'query',
+ {q: q, size: 25},
+ (response) => {
+ if (response.status.code < 0) {
+ onFailure();
+ return;
+ }
+ onSuccess(response.result);
+ },
+ false
+ );
+ };
+
+ const addItem = (item) => {
+ selected.push(item);
+ const extData = selected.map((item) => [item.code, item.name, item.system, item.version]);
+ selectedStore.loadData(extData);
+ };
+
+ const removeItem = (index) => {
+ selected.splice(index, 1);
+ const extData = selected.map((item) => [item.code, item.name, item.system, item.version]);
+ selectedStore.loadData(extData);
+ };
+
+ const save = () => {
+ const names = selected.map((item) => {
+ return item.name;
+ }).join("\n");
+
+ let field = context.getFieldByEntriesArray('wirkstoffe', blockIndex);
+ if (field) {
+ field.setValue(names);
+ }
+
+ let jsonfield = context.getFieldByEntriesArray('wirkstoffejson', blockIndex);
+ if (jsonfield) {
+ jsonfield.setValue(JSON.stringify(selected));
+ }
+ };
+
+ const onFailure = () => {
+ pluginRequestsDisabled = true;
+ Ext.MessageBox.show({
+ title: 'Hinweis',
+ msg: 'Plugin "ATC-Codes und Substanzen" nicht verfügbar. Sie können Substanzen nur über "Aus Suchfeld hinzufügen" hinzufügen.',
+ buttons: Ext.MessageBox.OKCANCEL
+ });
+ };
+
+ const onSuccess = (d) => {
+ available = d;
+ const extData = available.map((item) => [item.code, item.name, item.system, item.version]);
+ availableStore.loadData(extData);
+ }
+
+ const showDialog = () => {
+ let selectedItemIndex = -1;
+ let deselectedItemIndex = -1;
+ let queryString = '';
+
+ try {
+ selected = JSON.parse(context.getFieldValue(jsonfield, blockIndex));
+ const extData = selected.map((item) => [item.code, item.name, item.system, item.version]);
+ selectedStore.loadData(extData);
+ } catch (e) {
+ selected = [];
+ const extData = selected.map((item) => [item.code, item.name, item.system, item.version]);
+ selectedStore.loadData(extData);
+ }
+
+ const query = new Ext.form.field.Text({
+ name: 'query',
+ fieldLabel: 'Suche',
+ padding: 8,
+ listeners: {
+ change: (f) => {
+ queryString = f.value;
+ request(f.value);
+ if (f.value.length > 0) {
+ Ext.getCmp('btnUnknownAgent').setDisabled(false);
+ } else {
+ Ext.getCmp('btnUnknownAgent').setDisabled(true);
+ }
+ }
+ }
+ });
+
+ const gridColumns = [
+ {header: 'Code', width: 72, sortable: false, dataIndex: 'code'},
+ {header: 'Name', width: 300, sortable: false, dataIndex: 'name'},
+ {header: 'System', width: 72, sortable: false, dataIndex: 'system'},
+ {header: 'Version', width: 72, sortable: false, dataIndex: 'version'},
+ ];
+
+ const availableGrid = new Ext.grid.GridPanel({
+ title: 'Verfügbar',
+ store: availableStore,
+ loadMask: true,
+ border: true,
+ columns: gridColumns,
+ flex: 1,
+ overflowY: 'scroll',
+ listeners: {
+ itemclick: (dv, record, item, index) => {
+ selectedItemIndex = index;
+ Ext.getCmp('btnAddAgent').setDisabled(false);
+ },
+ itemdblclick: (dv, record, item, index) => {
+ selectedItemIndex = -1
+ addItem(available[index]);
+ Ext.getCmp('btnAddAgent').setDisabled(true);
+ }
+ }
+ });
+
+ const selectedGrid = new Ext.grid.GridPanel({
+ title: 'Ausgewählt',
+ store: selectedStore,
+ loadMask: true,
+ border: true,
+ columns: gridColumns,
+ flex: 1,
+ overflowY: 'scroll',
+ listeners: {
+ itemclick: (dv, record, item, index) => {
+ deselectedItemIndex = index;
+ Ext.getCmp('btnRmAgent').setDisabled(false);
+ },
+ itemdblclick: (dv, record, item, index) => {
+ deselectedItemIndex = -1
+ removeItem(index);
+ Ext.getCmp('btnRmAgent').setDisabled(true);
+ }
+ }
+ });
+
+ const gridLayout = Ext.create('Ext.Panel', {
+ flex: 1,
+ layout: {
+ type: 'hbox',
+ align: 'stretch'
+ },
+ items: [availableGrid, {xtype: 'splitter'}, selectedGrid]
+ });
+
+ const layout = Ext.create('Ext.Panel', {
+ flex: 1,
+ layout: {
+ type: 'vbox',
+ align: 'stretch'
+ },
+ items: [query, gridLayout]
+ });
+
+ Ext.create('Ext.window.Window', {
+ title: 'Substanz auswählen',
+ height: 600,
+ width: 1080,
+ layout: 'fit',
+ items: [layout],
+ buttons: [{
+ id: 'btnAddAgent',
+ text: 'Hinzufügen',
+ disabled: true,
+ handler: () => {
+ addItem(available[selectedItemIndex]);
+ Ext.getCmp('btnAddAgent').setDisabled(true);
+ }
+ }, {
+ id: 'btnUnknownAgent',
+ text: 'Aus Suchfeld hinzufügen',
+ disabled: true,
+ handler: () => {
+ addItem({
+ code: '',
+ name: queryString,
+ system: 'UNREGISTERED'
+ });
+ Ext.getCmp('btnUnknownAgent').setDisabled(true);
+ }
+ }, {
+ id: 'btnRmAgent',
+ text: 'Entfernen',
+ disabled: true,
+ handler: () => {
+ removeItem(deselectedItemIndex);
+ Ext.getCmp('btnRmAgent').setDisabled(true);
+ }
+ }, {
+ text: 'Übernehmen',
+ cls: 'onko-btn-cta',
+ handler: () => {
+ save();
+ let win = Ext.WindowManager.getActive();
+ if (win) {
+ win.close();
+ }
+ }
+ }]
+ }).show();
+
+ request('');
+ }
+
+ let buttonFieldFormInformation = findButtonFieldFormInformation();
+ if (buttonFieldFormInformation && buttonFieldFormInformation.blockIndex) {
+ blockIndex = buttonFieldFormInformation.blockIndex;
+ }
+
+ showDialog();
+ }
+
+}
+
+/**
+ * Wrapper for use with ExtJS
+ *
+ * Use with:
+ *
+ * let AtcCodesDialog = Ext.ClassManager.get('AtcCodesDialog');
+ * AtcCodesDialog.show(this);
+ */
+Ext.define('AtcCodesDialog', {
+ statics: {
+ show: AtcCodesDialog.show
+ }
+}); \ No newline at end of file
diff --git a/src/main/resources/onkostar-config.properties b/src/main/resources/onkostar-config.properties
index fedc077..b6b139d 100644
--- a/src/main/resources/onkostar-config.properties
+++ b/src/main/resources/onkostar-config.properties
@@ -1 +1 @@
-onkostar-api=2.12.4.1 \ No newline at end of file
+onkostar-api=2.14.2 \ No newline at end of file