Erweiterung einer bestehenden Liferay-Portal-Anwendung … · Prozessschnittstellen von dem ganzen...

53
Abschlussprüfung Winter 2017/2018 Erweiterung einer bestehenden Liferay-Portal-Anwendung um 2 zusätzliche Portlets Prüfungsteilnehmer: Andrey Boivalenko Fachinformatiker Anwendungsentwicklung Projektverantwortlicher: Herr Holger Werkhäuser +49 (6151) 62912-0 Ausbildungsbetrieb: e.i.s. Konzept AG Elektronische Informations-Systeme Steubenpl. 17, 64293 Darmstadt

Transcript of Erweiterung einer bestehenden Liferay-Portal-Anwendung … · Prozessschnittstellen von dem ganzen...

Abschlussprüfung Winter 2017/2018

Erweiterung einer bestehenden Liferay-Portal-Anwendung

um 2 zusätzliche Portlets

Prüfungsteilnehmer:

Andrey Boivalenko

Fachinformatiker Anwendungsentwicklung

Projektverantwortlicher:

Herr Holger Werkhäuser

+49 (6151) 62912-0

Ausbildungsbetrieb:

e.i.s. Konzept AG Elektronische Informations-Systeme

Steubenpl. 17, 64293 Darmstadt

2

Inhaltsverzeichnis 1 Beschreibung der Ausgangssituation ........................................................................................ 3

1.1 Projektumfeld ......................................................................................................................... 3

1.2 Prozessschnittstellen ........................................................................................................... 3

1.3 Ansprechpartner ................................................................................................................... 3

1.4 IST-Zustand und Projektziele ............................................................................................. 4

1.5 Kundenwünsche ................................................................................................................... 4

1.6 Abgrenzung ........................................................................................................................... 5

1.7 Abweichungen vom Projektantrag ..................................................................................... 5

2 Ressourcen- und Ablaufplanung ................................................................................................ 5

2.1.1 Sachmittelplanung ........................................................................................................ 5

2.1.2 Personalplanung ........................................................................................................... 6

2.1.3 Terminplanung .............................................................................................................. 6

2.1.4 Kostenplanung .............................................................................................................. 6

2.1.5 Kosten-Nutzung-Analyse ............................................................................................. 7

2.2 Ablaufplanung ....................................................................................................................... 8

3 Durchführung und Auftragsbearbeitung .................................................................................... 9

3.1 Arbeitsumgebung Einrichten ............................................................................................... 9

3.1.1 Prozessbeschreibung ................................................................................................... 9

3.1.2 Arbeitsumgebungsbeschreibung .............................................................................. 11

3.1.3 Arbeitsumgebung einrichten ..................................................................................... 11

3.2 Einarbeitung in Spezifikation der Portlets ....................................................................... 12

3.3 Implementierung ................................................................................................................. 12

3.3.1 Backend der Portlets .................................................................................................. 13

3.3.2 Frontend der Portlets.................................................................................................. 14

4 Projektergebnisse ....................................................................................................................... 18

4.1 Soll-Ist-Vergleich ................................................................................................................. 22

4.2 Qualitätskontrolle ................................................................................................................ 22

4.3 Fazit ...................................................................................................................................... 22

5 Abkürzungsverzeichnis .............................................................................................................. 23

6 Literaturverzeichnis .................................................................................................................... 25

7 Anlage mit der Dokumentation des Quellcodes aus der Implementierungsphase ........... 25

7.1 Backend vom Portlet „Handlungsfelder“ .............................................................................. 25

7.2 Backend vom Portlet „Kennzahlen“ ...................................................................................... 31

7.3 Frontend vom Portlet „Handlungsfelder“ ............................................................................. 35

7.4 Frontend vom Portlet „Kennzahlen“ ..................................................................................... 45

3

1 Beschreibung der Ausgangssituation

1.1 Projektumfeld

Die e.i.s. Konzept AG ist ein mittelständiges Unternehmen mit Schwerpunkt auf der

Individualentwicklung von Software für die Automobilbranche. Die Firma hat sich auf die

Erstellung von Webanwendungen mit Java im Portalumfeld1 spezialisiert.

Die 20 Mitarbeiter, hauptsächlich Softwareentwickler, arbeiten im Firmensitz in Darmstadt.

Die Projektarbeit findet in der Firma e.i.s. Konzept AG statt.

1.2 Prozessschnittstellen

Das Produkt ADP ist eine firmeneigene Webanwendung mit offline Funktionalität zur

Berichterfassung, welches bei mehreren Kunden von der Firma im Einsatz ist.

Strategischer Geschäftsplan ist ein Modul von dem ADP. Die Erstellung des "strategischen

Geschäftsplanes" (SGP) erfolgt über eine händische Zusammenfassung von ca. 470

verschiedenen quantitativen und qualitativen Daten für insgesamt 600 Vollfunktionspartner.

Die aus dem Strategischen Geschäftsplan resultierenden Maßnahmen sollen weiter über ADP

verfolgt werden.

Prozessschnittstellen der entsprechenden Projektarbeit betreffen zwar die

Prozessschnittstellen von dem ganzen ADP, weil die Portlets, die zu implementieren sind,

sich mit Administration von Systemwerten des ganzen SGP Projekts befassen, sind aber mit

bekanntem Schema von den Tabellen in einer konkreten Datenbank

eingeschränkt.

1.3 Ansprechpartner

Der einzige Ansprechpartner für das Projekt ist der Herr Severin von der e.i.s Konzept AG, der

das komplette SGP Projekt von vielen Gesprächen und Meetings mit Kunden spezifiziert hat.

Wobei wurden über manche besondere technische Aspekte, die bei der richtigen

1 Ein Portal ist eine besondere Form der Webanwendung

4

Projektierung von Portlets2 zu beachten sind, von anderen Mitarbeiter des Liferay Portal3

Teams in der Firma beraten.

1.4 IST-Zustand und Projektziele

Bisher können die Systemwerte, die sich auf implementierende Portlets beziehen, nur über die

Datenbank direkt gepflegt werden. Dabei mussten Kunden beim Datenbank Administrator von

e.i.s Konzept AG einen Antrag stellen lassen um Systemwerte zu ändern, zu ergänzen oder

zu löschen. Danach teilte der Datenbank Administrator in einige Tagen den Kunden

geänderte Systemwerte und die werden Im Endeffekt in Excel Dokumentation von Kunden

eingetragen werden. Der Prozess war langsam, aufwendig und manchmal fehlerhaft.

Durch die Erweiterung erhalten die Kunden bzw. Anwendungsbenutzer die Möglichkeit,

Systemwerte über eine grafische Oberfläche innerhalb der bestehenden Anwendung zu

konfigurieren. Es gibt auch anderen Nutzen der Projekteinführung, die im Kapitel 2.1.5

„Kosten-Nutzung-Analyse“ genauer beschrieben werden.

Das Ziel des Projektes: Erweiterung der bestehenden Liferay-Portal-Anwendung „ADP –

Strategischer Geschäftsplan“ um 2 Portlets zur Administration von Systemwerten.

Diese sollen unter Verwendung des firmeninternen Frameworks umgesetzt werden, welches

wiederum verschiedene Open-Source-Frameworks für die Entwicklung von Portal-Projekten

einsetzt.

1.5 Kundenwünsche

Wie im Kapitel 1.3 schon erwähnt, wird die Projektarbeit auf Grund einer exakten

Spezifikation gemacht, die für das ganze SGP Projekt geeignet ist. In dieser Spezifikation ist

es deutlich beschrieben, welche Kundewünsche bezüglich des SGP Projekt und insbesondere

für den Abschlussprojektteil sind. Da gibt es ganze Information wie die entsprechenden

2 Portlets sind beliebig kombinierbare Komponenten einer Benutzeroberfläche, die von einem Portalserver angezeigt und verwaltet werden. 3 Liferay Portal - ist eine lizenzkostenfreie Open-Source-Software, die in Unternehmen als Mitarbeiter- und Geschäftsprozess-orientiertes Enterprise Portal eingesetzt wird. Mit Liferay können Informationen, Daten und Anwendungen unter einer einheitlichen Bedienungsoberfläche im Browser des Mitarbeiters vereint und personalisiert werden, um dadurch die Geschäftsprozesse im Unternehmen elektronisch zu unterstützen. Liferay Portal ist in Java entwickelt.

5

Portlets des Abschlussprojektes aussehen sollen und welche Funktionalität die Portlets haben

sollen. Anhand der Spezifikation wird im Teil „Projektergebnisse“ außerdem unter dem Punkt

„Soll-Ist-Vergleich“ vergleicht, wie genau das erstellende Projekt der Spezifikation entspricht.

1.6 Abgrenzung

Die Portlets, die zu implementieren sind, sind nur zu Administration von Systemwerten gedacht

und nicht zur Erfassung davon der Daten. Dafür gibt’s andere Portlets. Die Portlets enthalten

Listen von entsprechenden Werten, die angezeigt, zugefügt, bearbeitet und gelöscht werden

können. Die Änderungen von diesen Manipulationen werden schließlich in der Datenbank

gespeichert.

1.7 Abweichungen vom Projektantrag

Der Projektantrag wurde zwar von der IHK genehmigt. Es war aber vorgeschrieben, dass

eine Kosten-Nutzung-Analyse sowie organisatorischen Schnittstellen in der Projekt-

Dokumentation ergänzt werden soll. Dies wurde akzeptiert und entsprechend nachbearbeitet.

2 Ressourcen- und Ablaufplanung

In diesem Kapitel werden die zur Verfügung stehende Zeit sowie die Ressourcen des

Projektes geplant.

2.1.1 Sachmittelplanung

Zur Entwicklung des Front- und Backends des Projekts wird eine IDE benötigt. Dabei

wurde auf die bereits im Ausbildungsbetrieb verwendete, kostenlose Eclipse IDE

zurückgegriffen. Um die Webanwendung und das genutzte Backend bereit zu stellen,

wird ein Java Applicationserver benötigt. Da für die Portletsimplementierung besondere

Vorgaben gelten, wurde hierzu der kostenlose Liferay Portal Server verwendet. Die zu

Benutzung und Test der Anwendungen verwendeten Browser (Microsoft Internet

Explorer, Mozilla Firefox und Google Chrome) sind ebenso kostenlos erhältlich. Der nötige

Entwicklungsrechner und Arbeitsplatz wurde von der e.i.s. Konzept AG im Rahmen der

Ausbildung bereitgestellt.

6

Als Datenbank-Tool zum Zugriff zur Datenbank wurde Aqua Data Studio mit Trial Lizenz von

14 Tagen verwendet.

2.1.2 Personalplanung

Die für das Projekt nötigen Tätigkeiten werden vom Auszubildenden eigenständig erledigt.

2.1.3 Terminplanung

Das Projekt wird vom Auszubildenden in Teilabschnitten neben den üblichen Aufgaben des

Tagesgeschäfts durchgeführt. Als Bearbeitungszeitraum ist der 09.10.2017 bis zum

20.10.2017 geplant.

2.1.4 Kostenplanung

Da es sich hier um eine Erzeugung der Anwendungen handelt, werden die

Kostenplanung anhand der Stundensätze unseres Firmenstandards berechnet. Für einen

Entwickler betragen die Kosten pro Mannstunde 95 €, für einen Projektleiter 130 €.

Die Positionen sind nach ihrer Einordnung im Projektablauf gegliedert. Es ist zu beachten,

dass die unterstrichenen Positionen von mir durchgeführt wurden.

Nr. Position Mannstunden

Stundensatz (Euro)

Total (Euro)

1 Spezifikation Erstellen bezüglich der Portlets

16 130 Euro 2080 Euro

2 Einarbeitung in Spezifikation der Portlets

5 95 Euro 475 Euro

3 Erstellung von Backend der Portlets

10 95 Euro 950 Euro

4 Erweiterung von Frontend der Portlets

20 95 Euro 1900 Euro

5 Testphase 10 95 Euro 950 Euro

6 Testphase 4 130 Euro 520 Euro

7 Erstellung der Projekt Dokumentation und

Präsentation

22 95 Euro 2090 Euro

8 Kosten Gesamt 8965 Euro

Abbildung 1

Die Kosten sollen nur einmal investiert werden. Es gibt keine weiteren Kosten, die die

Projektumsetzung angehen.

7

2.1.5 Kosten-Nutzung-Analyse

Um eine Effizienz des Projektes bzw. der Projekteinführung beurteilen zu können, wird eine

Kosten-Nutzung-Analyse durchgeführt. Dabei werden präziser Kosten-Nutzung und Nutzen

allgemein betrachtet und dann schließlich die analysiert bzw. zusammengefasst.

2.1.5.1 Nutzen

Wie im Kapitel 1.4 „IST-Zustand und Projektziele“ erwähnt war, war der Prozess der

Änderung von Systemwerten ziemlich schwer und aufwendig. Dadurch, dass Systemwerte

nach der Umsetzung des Projektes direkt von Kunden gepflegt werden können, ist den

ganzen Geschäftsprozess klarer und effizienter aus Kundesicht geworden. Dabei sind

folgende neue Möglichkeiten erschienen:

1. Mit der Projektumsetzung kam die Möglichkeit, die Daten ordentlich zu strukturieren.

2. Dass die Daten ordentlich strukturiert sind, machen Kunden bei Steuerung der

Systemwerten weniger Fehler wie früher. Es geht sowohl um menschliche Fehler als auch

um Systemfehler, die den Kunden angezeigt werden können, falls sie unrichtige Daten ins

System eingeben würden.

3. Man kann ganze Änderungen von Systemwerten von vorherigen Jahren einfach und

komfortable nachvollziehen und vergleichen

4. Mit der Projektumsetzung kann nun nicht nur der Datenbank Administrator, sondern

auch der Anwender des Systems Systemwerte steuern. Es spart Geld, das dem Datenbank

Administrator für seine Arbeit bezahlt werden musste.

5. Der Anwender verbraucht weniger Zeit im Vergleich zum Datenbank Administrator,

um Systemwerte zu steuern.

2.1.5.2 Kosten-Nutzung

Im Kapitel 2.1.4 wurde berechnet welche Gesamt Kosten sind, um das Projekt umzusetzen.

Die Kosten werden nur einmal investiert. Es gibt keine weiteren Kosten die die

Projektumsetzung angehen.

Die Kosten von Dienstleistungen von einem Datenbank Administrator bezüglich der

8

Systemwerten (pro Jahr ca 30 Tage):

95 Euro * 2 Stunden/Tag * 30 Tage = 5700 Euro.

Die Kosten von Dienstleistungen von einem Anwender bezüglich der Systemwerten

(pro Jahr) nach der Einsetzung des Projektes:

95 Euro * 1 Stunden/Tag * 30 Tage = 2850 Euro.

Dass die Systemwerte mindestens 5 Jahren gepflegt werden müssen, wird nun eine

Effizienz der Umsetzung des Projektes berechnet:

Jahre Kosten vor Einsetzung

Kosten nach Einsetzung

Effizienz ( Euro )

1 5700 Euro 8965 Euro - 3265 Euro

2 5700 Euro 2850 Euro 2850 Euro

3 5700 Euro 2850 Euro 2850 Euro

4 5700 Euro 2850 Euro 2850 Euro

5 5700 Euro 2850 Euro 2850 Euro

Abbildung 2

Obwohl die Effizienz vom ersten Jahr unvorteilhaft ist, wird die in nächsten Jahren erfolgreich

kompensiert. Effizienz für 5 Jahre:

2850*4 – 3265= 8135 Euro.

Dadurch das Projekt eigesetzt wird, sparen Kunden 8135 Euro für 5 Jahre.

2.1.5.3 Kosten-Nutzung-Analyse

Von den Kapitel 2.1.5.1 und Kapitel 2.1.5.2 wird es sicher festgestellt, dass die

Vorteile von der Projektumsetzung ziemlich sinnvoll sind und das Projekt ist einzusetzen.

2.2 Ablaufplanung

Die Ablaufplanung des Projektes hat die folgende Struktur:

Phase Tätigkeit Dauer (h)

Einarbeitung

Arbeitsumgebung Einrichten

3

Einarbeitung in Spezifikation der Portlets

5

9

Implementierung

Erstellung von Backend der Portlets

10

Erweiterung von Frontend der Portlets

20

Testphase 10

Dokumentation

Erstellung der Projekt Dokumentation und

Präsentation

22

Abbildung 3

Gesamter Dauer von allen Phasen ist 70 Stunden. Das ist vorgegebene maximale Zeit, die für

eine Projektarbeit verbraucht werden darf.

3 Durchführung und Auftragsbearbeitung

Nachdem die Aufbauplanung des Projektes abgeschlossen ist, kann mit der

Einarbeitungsphase zur Ermittlung des Ist-Zustandes begonnen werden. Dabei muss vorher

die Arbeitsumgebung eingerichtet werden und die Spezifikation bezüglich der

Implementierung von Portlets durchgearbeitet werden.

3.1 Arbeitsumgebung Einrichten

3.1.1 Prozessbeschreibung

Um die Arbeitsumgebung für das Projekt eirichten zu können muss man vorher

Geschäftsprozesse verstehen, die dahinten laufen.

10

Abbildung 4

Von der Abbildung 4 wird es zusammenschließt:

1. Händler Netz Entwickler planen SGP vor. Es werden Kennzahlen und

Handlungsfelder erst mal eingestellt.

2. Gebietsleiter entscheiden ob die Zahlen stimmen

3. Händler selbst entscheidet ob die Zahlen stimmen

4. Alle Händler entscheiden im Gespräch miteinander ob die Zahlen stimmen

5. Falls die Händler die Zahlen zustimmen, kommen die Zahlen zu Regionalleiter und er

gibt im Endeffekt die Freigabe von Zahlen frei

6. In einiger Zeit werden Phasen wieder wiederholt.

Handlungsfelder sind von Kunden ausgedachte Felder, die definieren und messen können,

wie gut Autohäuser in bestimmten Bereichen etwas machen. Wenn man konkrete

Handlungsfelder anschaut, kann eine Bewertung anhand Soll-Ist-Vergleich vorgenommen

werden und eine Entschließung gemacht werden ob der Wert gut erfüllt oder nicht. Im Fall

wenn ein Wert negativ ausfällt gibt’s die Maßnahmen die mit dem Ziel erstellt werden, dass

das besser wird für das nächstes Jahr.

Kennzahlen sind Zahlen die verschiedene Parameter messen, z.B. Kundenzufriedenheit. Im

Fall wenn ein Wert niedrig ist werden genauso bestimmten Maßnahmen wie bei

Handlungsfelder erstellt die dafür da sind um die entsprechenden Kennzahlen besser zu

machen.

11

3.1.2 Arbeitsumgebungsbeschreibung

Bei den Anwendungen handelt es sich um 2 neue Portlets innerhalb einer

bestehenden Liferay-Portal-Anwendung. Diese werden mit folgenden Technologien

umgesetzt:

Java EE (Enterprise Edition)

HTML

Javascript

CSS

SQL

Für die Entwicklung werden folgenden Frameworks verwendet:

Firmeninternes Portal-Framework

Spring (Core + MVC)

MyBatis (Datenbankzugriffe)

DOJO (Javascript Frontend)

Für die Entwicklung wird folgende Software benötigt:

Liferay IDE (Eclipsebasierte Entwicklungsumgebung für Liferay Portal)

Liferay Portal Server 6.2.0 (Portalserver mit Tomcat)

AquaDataStudio (Datenbank-Tool)

Diverse Browser (Internet Explorer, Chrome, Firefox)

Optional: JRebel

Alle diese obenstehenden Begriffe werden im Abkürzungsverzeichnis erklärt.

3.1.3 Arbeitsumgebung einrichten

Um die Arbeitsumgebung einrichten zu können muss:

1. das Java Development Kit (JDK) heruntergeladen und auf dem Rechner installiert

werden

2. ein Liferay IDE und einen Liferay Portal Server aus dem Fileserver von der Firma

herunterladen werden.

3. das Liferay IDE gestartet werden und eine neue Liferay IDE Arbeitsumgebung

eingestellt werden

4. eine Kopie des SGP Projektes aus SVN in die entsprechenden Liferay IDE

Arbeitsumgebung ausgecheckt werden

5. das Aqua Data Studio gestartet werden

6. einen Liferay Portal Server in arbeitsfähiger Liferay IDE mit dem SGP Projekt

gestartet werden, um zu testen, ob der Liferay Portal Server lauffähig ist.

12

3.2 Einarbeitung in Spezifikation der Portlets

Einarbeitung in Spezifikation der Portlets bestand aus:

1. Die ganze Spezifikation wurde von mir durchgelesen (mehr als 80 Seiten)

2. Die Spezifikation bezüglich der implementieren Portlets wurde von mir noch mal

durchgelesen und analysiert.

3. Gespräche mit Kollegen bezüglich der implementierenden Portlets wurden

durchgeführt.

4. Vorbereitung zur Implementierungsphase des Portlets wurde durchgeführt dadurch,

dass technische Aspekte mit anderen Portlets in Projekten wie SGP, GKSA usw.

verglichen wurden. Dabei wurde zusammengefasst welche DOJO Web Komponenten

zu verwenden sind.

3.3 Implementierung

Das Projekt teilt sich in backend und webapp (Frontend). Diese sind Subprojekte des

Hauptprojektes. Nachdem die Arbeitsumgebung eigerichtet ist, soll Im Root-Ordner des

Hauptprojektes die Struktur folgendermaßen aussehen:

Abbildung 5

Inhalte des Hauptprojektes:

pom.xml: Maven Konfiguration des Hauptprojektes. Hier werden Informationen zum

Projekt selbst, wie Name, Organisation oder Version angegeben, sowie Abhängigkeiten

(=Java-Bibliotheken, welche zum Bau des Projektes automatisch runtergeladen und

beigefügt werden), Erstellungsprofile, Plugins, usw.

build-<Plattform>-<Zielsystem>.cmd: Dies sind Build-Commands, mit denen die

Webanwendung für bestimmte Plattformen und Zielsysteme über die Windowskonsole

(CMD) oder Powershell-Konsole erstellt werden kann. Der Build der verschiedenen

Versionen erfolgt über Profile.

clean-package.cmd: Hier wird die Webanwendung mit den Standardprofilen erstellt.

13

concat-sql.cmd: Sind Views in der Anwendung definiert, so sammelt dieses Skript alle

SQL-Dateien (.sql) aus einem bestimmten Verzeichnis (wird später noch erwähnt) und

erzeugt daraus eine große SQL-Datei, mit der die Views bei der Installation auf einmal

installiert werden können. Die Datei muss von Hand erweitert werden, wenn neue SQL-

Dateien einbezogen werden sollen.

3.3.1 Backend der Portlets

3.3.1.1 Inhalte des Backendprojektes

Im Subprojekt Backend wird alles entwickelt, das für die Datenverarbeitung zuständig ist.

Abbildung 6

Inhalte des Backendprojektes:

pom.xml: Maven Konfiguration des Backendprojektes. Hier werden Informationen zum

Projekt selbst, wie Name, Organisation oder Version angegeben, sowie Abhängigkeiten

(=Java-Bibliotheken, welche zum Bau des Projektes automatisch runtergeladen und

beigefügt werden), Erstellungsprofile, Plugins, usw.

src/main/java: Hier findet die Implementierung der oben genannten

Datenverarbeitungsobjekte statt.

src/main/resources/i18n: Hier können Property-Dateien abgelegt werden, die im

Backend verfügbar sein müssen (z.B. wenn eine Übersetzung im Services stattfindet).

Dies ist insbesondere dann wichtig, wenn das Backend von mehreren Webanwendungen

verwendet werden soll.

src/main/resources/jasperreports: Hier werden die Templates für Jasperreports

abgelegt.

src/main/resources/mybatis: Hier werden die XML-Konfigurationen für die MyBatis-

Mapper abgelegt. In diesen sind die Statements für die im Mapper definierten Methoden

hinterlegt.

14

src/main/resources/setup/database: Hier werden die SQL-Dateien mit View-Definition

abgelegt.4

3.3.1.2 Erstellung von Backend der Portlets

Erstellung von Backend betrifft Im Wesentlichen dies:

POJO-Java-Beans für MyBatis (Java-Beans, die von den Repositories und Mappern

befüllt werden; die Datenobjekte)

MyBatis-Mapper (früher DAOs genannt; stellen Methoden für den Datenbankzugriff

bereit)

Services (die die Daten aufbereiten und die Schnittstelle zwischen Datenbank und

Frontend (Webapp) bilden)

3.3.2 Frontend der Portlets

3.3.2.1 Inhalte des Webappprojektes

Im Subprojekt webapp wird das komplette Frontend entwickelt. Dies beinhaltet alles, das der

Benutzer sehen und mit dem der Anwender interagieren kann. Zusätzlich dazu muss hier die

Schnittstelle zwischen Backend und GUI entstehen.

4 Interne Quelle

15

Abbildung 7

16

Inhalte des Webappprojektes:

pom.xml: Maven Konfiguration des Webappprojektes. Hier werden Informationen zum

Projekt selbst, wie Name, Organisation oder Version angegeben, sowie Abhängigkeiten

(=Java-Bibliotheken, welche zum Bau des Projektes automatisch runtergeladen und

beigefügt werden), Erstellungsprofile, Plugins, usw.

src/main/java: Hier findet die Implementierung der Schnittstellen von GUI und Backend

statt. Dies erfolgt in EPF2 mittels Spring-Controllern.

src/main/resources/config/spring: Hier werden unter anderem die Spring-

Konfigurationen der Portlets abgelegt, sowie eine Anwendungskonfiguration.

src/main/resources/config/spring/applicationContext.xml: Dies ist die Spring-

Hauptkonfiguration der Anwendung. In dieser Datei werden die anderen XML-Dateien

des Verzeichnisses zusammengeführt und die zu ladenden Übersetzungsdateien

definiert

src/main/resources/config/spring/datasource.xml: Hier werden die Datasources für

den Datenbankzugriff über MyBatis definiert. Für die lokale Entwicklung befindet sich

diese Datei unter src/main/enf/development/config/spring.

src/main/resources/config/spring/db.xml: Erweiterte MyBatis Konfiguration

src/main/resources/config/spring/fileshare.xml: Hier wird der Zugriff auf den Fileshare

konfiguriert.

src/main/resources/config/spring/mybatis.xml: Die Basis-Mybatis-Konfiguration.

src/main/resources/config/spring/user-role-mapping: Die Konfiguration für die

Sicherheitsabfragen.

src/main/resources/config/env.properties: Hier werden sämtliche

Konfigurationsparameter wie Datenbank-URL / Benutzer / Passwort usw. hinterlegt.

src/main/resources/config/roles.csv: In dieser Datei können Anwendungsfunktionen

definiert werden und diese dann Anwendungsrollen zugewiesen werden.

src/main/resources/i18n: Hier können Property-Dateien abgelegt werden, die im

Frontend verfügbar sein müssen (z.B. für Tabellenüberschriften).

src/main/resources/logback.xml: Hier wird das Logging der Anwendung konfiguriert.

src/main/env/<System>: Hier werden die Parameter für unterschiedliche Systeme

(siehe Build des Hauptprojektes) konfiguriert.

src/main/webapp/css: Alles was mit der Gestaltung des Frontends mit CSS zu tun hat

ist hier richtig.

src/main/webapp/images: Hier werden Bilder hinterlegt.

src/main/webapp/js: Alle Javascript-Dateien werden hier abgelegt.

src/main/webapp/WEB-INF/jsp: Hier werden die JSPs für die Anzeige der Daten

entwickelt.

17

src/main/webapp/WEB-INF/liferay-display.xml: In dieser Datei werden die

Informationen für das Hinzufügen eines Portlets auf eine Seite im Liferay hinterlegt. Die

Portlets können hier gruppiert werden.

src/main/webapp/WEB-INF/liferay-portlet.xml: In dieser Datei werden die Portlets für

den Liferay konfiguriert. Hier kann auch eingestellt werden, welche Rollen Zugriff auf das

Portlet haben sollen und welche Javascript-/CSS-Ressourcen von Portlet automatisch

mitgeladen werden sollen, dies erspart einen separaten Import der entsprechenden

Dateien in den jeweiligen JSPs

src/main/webapp/WEB-INF/portlet.xml: In dieser Datei werden die Portlets für die

Portlet-Applikation laut JSR286 konfiguriert.

src/main/webapp/WEB-INF/web.xml: Konfiguration der Web-Anwendung. Dies

umschließt die Seiten-Struktur, Aufruf-Filter, Kontext-Parameter (/Resources), Sicherheit

(z.B. Nutzer-Anmeldung), Start- & Fehler-Seite, uvm.5

3.3.2.2 Erstellung von Frontend der Portlets

Erstellung von Frontend betrifft Im Wesentlichen dies:

Java-Controllers.

Sie sind für Verbindung zwischen Services und GUI geeignet. Im Controller wird definiert,

welche jsp Seite die erste Aufruf Seite ist. Außerdem wird da Business Logik organisiert.

Java-Beans und Search-Beans

Beans, die von den Controller benutzt werden, um dann sich mit Beans von Backend in

Verbindung zu setzen.

JavaServer Pages.

JavaServer Pages, abgekürzt JSP, ist auf JHTML basierende Web-Programmiersprache

zur einfachen dynamischen Erzeugung von HTML- und XML-Ausgaben eines

Webservers.

Sie erlaubt, Java-Code und spezielle JSP-Aktionen in HTML- oder XML-Seiten

einzubetten. Dabei ermöglicht es die JSP-Syntax, mittels spezieller XML-Tags (JSP-

Aktionen) vordefinierte Funktionalität einzubinden.

5 Interne Quelle

18

4 Projektergebnisse

Die Portlets „Handlungsfelder“ und „Kennzahlen“ wurden von mir implementiert.

Das Portlet „Handlungsfelder“ (Analyse Markt):

Abbildung 8

19

Das Portlet „Handlungsfelder“ (Analyse Unternehmen):

Abbildung 9

20

Das Portlet „Kennzahlen“ (Kennzahlen Vertrieb):

Abbildung 10

21

Das Portlet „Kennzahlen“ (Kennzahlen Service):

Abbildung 11

Auf den Abbildungen 8-11 wird präsentiert, welche Portlets implementiert wurden.

22

4.1 Soll-Ist-Vergleich

Bisher können die Systemwerte nur über die Datenbank direkt gepflegt werden. Durch die

Erweiterung erhalten die Anwendungsbenutzer die Möglichkeit, diese über eine grafische

Oberfläche innerhalb der bestehenden Anwendung zu konfigurieren.

Wie im 1.3 Kapitel erwähnt, gab’s eine Spezifikation zu Portlets. Die Portlets wurden nach

Spezifikation implementiert. Dabei werden beachtet, dass Portlets ganze Funktionalität

verfügen wie in der Spezifikation beschrieben ist.

4.2 Qualitätskontrolle

Es wurde eine Projektabnahme durch den Projektleiter durchgeführt. Dabei werden ein paar

Hinweisen vom Projektleiter gesagt, z.B. welche GUI-Elemente am besten benutzt werden

sollen und wie die Methoden von Controllers umprogrammiert werden sollen, dass weniger

Code gibt.

4.3 Fazit

Innerhalb der Implementierungsphase der Projektarbeit wurden von mir verschiedene

Probleme erkannt, die behoben werden mussten. Am häufigsten sind Probleme mit GUI

Elementen von dem DOJO Framework aufgetreten. Das Lesen von der offiziellen

Dokumentation dieses Frameworks hat zur Lösungsfindung beigetragen. Es entstanden

zusätzlich immer kleine Probleme entweder in Controller oder in JSP Seiten, die im DEBUG-

Modus behoben wurden.

23

5 Abkürzungsverzeichnis

Aqua Data Studio (Databank-Tool) - visuelles Datenbank-Abfrage- und

Verwaltungswerkzeug, das in der Programmiersprache Java entwickelt wird. Es ist für die

Plattformen Windows, Linux sowie Mac OS X verfügbar.

Applikation Server - ein Server in einem Computernetzwerk, der Anwendungsprogramme

ausführt. Im engeren Sinne bezeichnet der Begriff eine Software, die spezielle Dienste zur

Verfügung stellt, wie beispielsweise Transaktionen, Authentifizierung oder den Zugriff auf

Verzeichnisdienste, Webservices und Datenbanken über definierte Schnittstellen.

CSS - Cascading Style Sheets für gestufte Gestaltungsbögen), kurz CSS genannt, ist eine

Stylesheet-Sprache für elektronische Dokumente und zusammen mit HTML und DOM eine

der Kernsprachen des World Wide Webs

DOJO (JavaScript Frontend) - eine freie, modulare JavaScript-Bibliothek, die zur raschen

Entwicklung von JavaScript- oder Ajax-basierenden Anwendungen und Websites dient.

EPF2 Framework – ein Portal Framework von E.I.S. Konzept

HTML - Die Hypertext Markup Language, abgekürzt HTML, ist eine textbasierte

Auszeichnungssprache zur Strukturierung digitaler Dokumente wie Texte mit Hyperlinks,

Bildern und anderen Inhalten.

JRebel – ein Werkzeug, welches das dynamische Deployen von Java Web-Applikationen in

einem Applikations-Server unterstützt

Java EE (Enterprise Edition) - abgekürzt Java EE oder früher J2EE, ist die Spezifikation

einer Softwarearchitektur für die transaktionsbasierte Ausführung von in Java

programmierten Anwendungen und insbesondere Web-Anwendungen. Sie ist eine der

großen Plattformen, die um den Middleware-Markt kämpfen. Größter Konkurrent ist dabei die

.NET-Plattform von Microsoft.

JavaBeans - sind Software-Komponenten für die Programmiersprache Java. JavaBeans

werden auch als Container zur Datenübertragung verwendet. Daher zeichnen sich alle

24

JavaBeans durch folgende Eigenschaften aus:Öffentlicher parameterloser Konstruktor,

Serialisierbarkeit (Serializable), Öffentliche Zugriffsmethoden (Public Getters/Setters)

Javascript - ist eine Skriptsprache, die für dynamisches HTML in Webbrowsern entwickelt

wurde, um Benutzerinteraktionen auszuwerten, Inhalte zu verändern, nachzuladen oder zu

generieren und so die Möglichkeiten von HTML und CSS zu erweitern. Heute findet

JavaScript auch außerhalb von Browsern Anwendung, so etwa auf Servern und in

Microcontrollern

Liferay IDE - Eclipsebasierte Entwicklungsumgebung für Liferay Portal

Liferay-Portal (Server) - lizenzkostenfreie Open-Source-Software, die in Unternehmen als

Mitarbeiter- und Geschäftsprozess-orientiertes Enterprise Portal eingesetzt wird. Mit Liferay

können Informationen, Daten und Anwendungen unter einer einheitlichen

Bedienungsoberfläche im Browser des Mitarbeiters vereint und personalisiert werden, um

dadurch die Geschäftsprozesse im Unternehmen elektronisch zu unterstützen. Liferay Portal

ist in Java entwickelt.

Maven - ein Build-Management-Tool der Apache Software Foundation und basiert auf Java.

Mit ihm kann man insbesondere Java-Programme standardisiert erstellen und verwalten.

MyBatis - ein Open-Source-Persistenz-Framework für Java und .NET

Portlets - beliebig kombinierbare Komponenten einer Benutzeroberfläche, die von einem

Portalserver angezeigt und verwaltet werden. Sie erzeugen Fragmente von HTML-Code und

fügen sich in einer Portalseite ein. Typischerweise besteht eine Portalseite aus vielen, nicht-

überlappenden Portlet-Fenstern („Kacheln“), in denen jeweils ein Portlet ausgeführt wird.

Spring - ist ein Framework für die Java-Plattform. Ziel des Spring Frameworks ist es, die

Entwicklung mit Java/Java EE zu vereinfachen und gute Programmierpraktiken zu fördern.

25

6 Literaturverzeichnis

1. Interne Spezifikation für das Projekt

2. Interne Quellen (interne Unterlagen)

3. DOJO Dokumentation https://dojotoolkit.org/documentation/

7 Anlage mit der Dokumentation des Quellcodes aus der Implementierungsphase

7.1 Backend vom Portlet „Handlungsfelder“

package com.eiskonzept.portal.prm2.mapper.handlungsfeld;

import java.util.Date;

import java.util.List;

import org.apache.ibatis.annotations.Param;

import org.springframework.stereotype.Component;

import com.eiskonzept.portal.prm2.domain.handlungsfeld.Handlungsfeld;

import com.eiskonzept.portal.prm2.domain.handlungsfeld.Handlungsfeld2SGP;

@Component

public interface HandlungsfeldMapper {

public List<Handlungsfeld> listHandlungsfelderByFilter(@Param("typ") Integer typ,

@Param("datum") Date datum);

public List<Handlungsfeld> listChildHandlungsfelder(@Param("parentId") Integer parentId);

public void insertHandlungsfeld(@Param("bean") Handlungsfeld feld, @Param("typ") Integer

typ,

@Param("userId") Integer userId);

public void updateHandlungsfeld(@Param("bean") Handlungsfeld feld, @Param("typ")

Integer typ,

26

@Param("userId") Integer userId);

public Handlungsfeld getHandlungsfeld(final @Param("id") Integer id);

public Handlungsfeld2SGP getHandlungsfeld2SGP(final @Param("id") Integer id);

public void insertHandlungsfeld2SGP(@Param("bean") Handlungsfeld2SGP bean);

public void updateHandlungsfeld2SGP(@Param("bean") Handlungsfeld2SGP bean);

}

//

package com.eiskonzept.portal.prm2.service.handlungsfeld;

import java.util.Collections;

import java.util.Date;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import org.springframework.transaction.annotation.Isolation;

import org.springframework.transaction.annotation.Propagation;

import org.springframework.transaction.annotation.Transactional;

import com.eiskonzept.portal.prm2.domain.handlungsfeld.Handlungsfeld;

import com.eiskonzept.portal.prm2.domain.user.User;

import com.eiskonzept.portal.prm2.mapper.handlungsfeld.HandlungsfeldMapper;

import com.eiskonzept.portal.prm2.mapper.user.UserMapper;

@Component

public class HandlungsfeldService {

27

@Autowired

private HandlungsfeldMapper handlungsfeldMapper;

@Autowired

private UserMapper userMapper;

@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation = Propagation.NEVER)

public List<Handlungsfeld> listHandlungsfelderByFilter(final Integer typ, final Date datum) {

return handlungsfeldMapper.listHandlungsfelderByFilter(typ, datum);

}

@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation =

Propagation.REQUIRES_NEW)

public void insertlistHandlungsfelderByFilter(final Handlungsfeld feld, final Integer typ, final Integer

userId) {

handlungsfeldMapper.insertHandlungsfeld(feld, typ, userId);

}

@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation =

Propagation.REQUIRES_NEW)

public void storelistHandlungsfelderByFilter(final Handlungsfeld feld, final Integer typ, final Integer

userId) {

handlungsfeldMapper.updateHandlungsfeld(feld, typ, userId);

}

@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation =

Propagation.REQUIRES_NEW)

public void storeHandlungsfelder(List<Handlungsfeld> list, Integer typ, String userLogin) {

//Collections.sort(list);

User user = userMapper.getUserByLogin(userLogin);

//int sort = 1;

for (Handlungsfeld f : list) {

28

//f.setSort(sort);

if (f.getId() == null || f.getId() < 0) {

handlungsfeldMapper.insertHandlungsfeld(f, typ, user.getId());

} else {

handlungsfeldMapper.updateHandlungsfeld(f, typ, user.getId());

}

//sort++;

}

}

// Children

@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation = Propagation.NEVER)

public List<Handlungsfeld> listChildHandlungsfelder(final Integer id) {

return handlungsfeldMapper.listChildHandlungsfelder(id);

}

@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation =

Propagation.REQUIRES_NEW)

public void storeChildHandungsfelder(List<Handlungsfeld> list, Integer typ, Integer parentId, String

userLogin) {

User user = userMapper.getUserByLogin(userLogin);

// int sort = 1;

for (Handlungsfeld f : list) {

// f.setSort(sort);

if (f.getId() == null || f.getId() < 0) {

f.setParent(parentId);

handlungsfeldMapper.insertHandlungsfeld(f, typ, user.getId());

} else {

handlungsfeldMapper.updateHandlungsfeld(f, typ, user.getId());

}

// sort++;

}

29

}

@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation = Propagation.NEVER)

public Handlungsfeld getHandlungsfeld(final int id){

return handlungsfeldMapper.getHandlungsfeld(id);

}

}

//

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper

namespace="com.eiskonzept.portal.prm2.mapper.handlungsfeld.HandlungsfeldMap

per">

<select id="listHandlungsfelderByFilter" resultType="handlungsfeld">

select

HDF_ID as "id",

HDF_BEZEICHNUNG as "bezeichnung",

HDF_PARENT as "parent",

HDF_GRUPPE as "gruppe",

HDF_SORT as "sort",

HDF_HINWEIS as "hinweis",

HDF_GUELTIG_VON as "gueltigVon",

HDF_GUELTIG_BIS as "gueltigBis",

HDF_DELETED as "deleted",

HDF_PARTNER as "partner",

HDF_UCR as "ucr",

HDF_ULC as "ulc",

(SELECT COUNT(*) FROM PRM2.SGP_HANDLUNGSFELD F0 WHERE F0.HDF_PARENT =

F.HDF_ID and HDF_DELETED ='N') AS "childCount"

from PRM2.SGP_HANDLUNGSFELD F

where HDF_GRUPPE = #{typ}

and HDF_PARENT IS NULL

and HDF_PARTNER IS NULL

and HDF_DELETED ='N'

<if test="datum != null">

and (HDF_GUELTIG_VON IS NULL OR HDF_GUELTIG_VON &lt;= #{datum})

and (HDF_GUELTIG_BIS IS NULL OR HDF_GUELTIG_BIS &gt;= #{datum})

</if>

order by

HDF_SORT asc

</select>

<select id="listChildHandlungsfelder" resultType="handlungsfeld">

select

HDF_ID as "id",

HDF_BEZEICHNUNG as "bezeichnung",

HDF_PARENT as "parent",

HDF_GRUPPE as "gruppe",

HDF_SORT as "sort",

HDF_HINWEIS as "hinweis",

30

HDF_GUELTIG_VON as "gueltigVon",

HDF_GUELTIG_BIS as "gueltigBis",

HDF_DELETED as "deleted",

HDF_PARTNER as "partner",

HDF_UCR as "ucr",

HDF_ULC as "ulc"

from PRM2.SGP_HANDLUNGSFELD

where HDF_PARENT = #{parentId}

and HDF_PARTNER IS NULL

and HDF_DELETED ='N'

order by

HDF_SORT asc

</select>

<insert id="insertHandlungsfeld" flushCache="true"

statementType="PREPARED" timeout="20" keyProperty="bean.id"

keyColumn="HDF_ID" useGeneratedKeys="true">

INSERT INTO PRM2.SGP_HANDLUNGSFELD (HDF_BEZEICHNUNG, HDF_PARENT,

HDF_GRUPPE, HDF_SORT, HDF_HINWEIS, HDF_GUELTIG_VON, HDF_GUELTIG_BIS,

HDF_DELETED, HDF_UCR, HDF_ULC, HDF_PARTNER)

VALUES(#{bean.bezeichnung}, #{bean.parent}, #{typ}, #{bean.sort},

#{bean.hinweis}, #{bean.gueltigVon}, #{bean.gueltigBis}, #{bean.deleted},

#{userId}, #{userId}, #{bean.partner})

</insert>

<update id="updateHandlungsfeld" flushCache="true"

statementType="PREPARED" timeout="20">

UPDATE PRM2.SGP_HANDLUNGSFELD

SET

HDF_BEZEICHNUNG = #{bean.bezeichnung},

HDF_PARENT = #{bean.parent},

HDF_GRUPPE = #{typ},

HDF_SORT = #{bean.sort},

HDF_HINWEIS = #{bean.hinweis},

HDF_GUELTIG_VON = #{bean.gueltigVon},

HDF_GUELTIG_BIS = #{bean.gueltigBis},

HDF_DELETED = #{bean.deleted},

HDF_ULC = #{userId},

HDF_PARTNER = #{bean.partner}

WHERE HDF_ID = #{bean.id}

</update>

<select id="getHandlungsfeld" resultType="handlungsfeld">

select

HDF_ID as "id",

HDF_BEZEICHNUNG as "bezeichnung",

HDF_PARENT as "parent",

HDF_GRUPPE as "gruppe",

HDF_SORT as "sort",

HDF_HINWEIS as "hinweis",

HDF_GUELTIG_VON as "gueltigVon",

HDF_GUELTIG_BIS as "gueltigBis",

HDF_DELETED as "deleted",

HDF_PARTNER as "partner",

HDF_UCR as "ucr",

HDF_ULC as "ulc",

(SELECT COUNT(*) FROM PRM2.SGP_HANDLUNGSFELD F0 WHERE F0.HDF_PARENT =

F.HDF_ID) AS "childCount"

from PRM2.SGP_HANDLUNGSFELD F

where HDF_ID = #{id}

</select>

31

<select id="getHandlungsfeld2SGP" resultType="handlungsfeld2SGP">

SELECT

HDF2SGP_ID AS "id",

HDF2SGP_SGPID AS "sgpId",

HDF2SGP_HDF AS "hdf",

HDF2SGP_SORT AS "sort",

HDF2SGP_DELETED AS "deleted",

HDF2SGP_UCR AS "ucr",

HDF2SGP_ULC AS "ulc"

FROM PRM2.SGP_HANDLUNGSFELD2SGP

WHERE HDF2SGP_ID = #{id}

</select>

<insert id="insertHandlungsfeld2SGP" flushCache="true"

statementType="PREPARED" timeout="20" keyProperty="bean.id"

keyColumn="HDF2SGP_ID" useGeneratedKeys="true">

INSERT INTO PRM2.SGP_HANDLUNGSFELD2SGP (HDF2SGP_SGPID, HDF2SGP_HDF,

HDF2SGP_SORT, HDF2SGP_DELETED, HDF2SGP_UCR, HDF2SGP_ULC)

VALUES(#{bean.sgpId}, #{bean.hdf}, #{bean.sort}, #{bean.deleted},

#{bean.ucr}, #{bean.ulc})

</insert>

<update id="updateHandlungsfeld2SGP" flushCache="true"

statementType="PREPARED" timeout="20">

UPDATE PRM2.SGP_HANDLUNGSFELD2SGP

SET

HDF2SGP_SORT = #{bean.sort},

HDF2SGP_DELETED = #{bean.deleted},

HDF2SGP_ULC = #{bean.ulc}

WHERE HDF2SGP_ID = #{bean.id}

</update>

</mapper>

7.2 Backend vom Portlet „Kennzahlen“

package com.eiskonzept.portal.prm2.mapper.kennzahlen;

import java.util.List;

import org.apache.ibatis.annotations.Param;

import org.springframework.stereotype.Component;

import com.eiskonzept.portal.prm2.domain.kennzahlen.KennzahlenAdmin;

@Component

public interface KennzahlenAdminMapper {

32

public List<KennzahlenAdmin> listKennzahlenAdminByFilter(@Param("kennz_bereich")

String kennz_bereich, @Param("datum") Integer datum);

public void insertKennzahlenAdmin(@Param("bean") KennzahlenAdmin bean,

@Param("typ") String typ, @Param("userId") Integer userId);

public void updateKennzahlenAdmin(@Param("bean") KennzahlenAdmin bean,

@Param("typ") String typ, @Param("userId") Integer userId);

}

//

package com.eiskonzept.portal.prm2.service.kennzahlen;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import org.springframework.transaction.annotation.Isolation;

import org.springframework.transaction.annotation.Propagation;

import org.springframework.transaction.annotation.Transactional;

import com.eiskonzept.portal.prm2.domain.kennzahlen.KennzahlenAdmin;

import com.eiskonzept.portal.prm2.domain.kennzahlen.KennzahlenGruppe;

import com.eiskonzept.portal.prm2.domain.user.User;

import com.eiskonzept.portal.prm2.mapper.kennzahlen.KennzahlenAdminMapper;

import com.eiskonzept.portal.prm2.mapper.kennzahlen.KennzahlenGruppeAdminMapper;

import com.eiskonzept.portal.prm2.mapper.user.UserMapper;

@Component

public class KennzahlenAdminService {

@Autowired

33

private KennzahlenAdminMapper kennzahlenAdminMapper;

@Autowired

private KennzahlenGruppeAdminMapper kennzahlenGruppeAdminMapper;

@Autowired

private UserMapper userMapper;

@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation =

Propagation.NEVER)

public List<KennzahlenAdmin> listKennzahlenAdminByFilter(final String kennz_bereich,

final Integer datum) {

return kennzahlenAdminMapper.listKennzahlenAdminByFilter(kennz_bereich, datum);

}

@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation =

Propagation.REQUIRES_NEW)

public void insertlistKennzahlenAdminByFilter(final KennzahlenAdmin feld, final String typ,

final Integer userId) {

kennzahlenAdminMapper.insertKennzahlenAdmin(feld,typ, userId);

}

@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation =

Propagation.REQUIRES_NEW)

public void updateKennzahlenAdmin(final KennzahlenAdmin feld, final String typ, final

Integer userId) {

kennzahlenAdminMapper.updateKennzahlenAdmin(feld,typ, userId);

}

@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation =

Propagation.REQUIRES_NEW)

public void storeKennzahlenAdmin(List<KennzahlenAdmin> list, String typ, String

userLogin) {

User user = userMapper.getUserByLogin(userLogin);

34

// int sort = 1;

for (KennzahlenAdmin f : list) {

// f.setSort(sort);

if (f.getId() == null || f.getId() < 0) {

kennzahlenAdminMapper.insertKennzahlenAdmin(f, typ, user.getId());

} else {

kennzahlenAdminMapper.updateKennzahlenAdmin(f, typ, user.getId());

}

// sort++;

}

}

@Transactional(isolation = Isolation.READ_UNCOMMITTED, propagation =

Propagation.NEVER)

public List<KennzahlenGruppe> listKennzahlenGruppe() {

return kennzahlenGruppeAdminMapper.listKennzahlenGruppe();

}

}

//

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper

namespace="com.eiskonzept.portal.prm2.mapper.kennzahlen.KennzahlenAdminMapp

er">

<select id="listKennzahlenAdminByFilter"

resultType="kennzahlenAdmin">

SELECT

KENNZ_ID as "id",

KENNZ_BEZEICHNUNG as "bezeichnung",

KENNZ_BEREICH as "kennz_bereich",

KENNZ_SORT as "sort",

KENNZ_NACHKOMMA as "nachkoma",

KENNZ_EINHEIT_INFO as "kennz_einheit_info",

KENNZ_GRUPPE as "kennz_gruppe",

KENNZ_DELETED as "deleted",

KENNZ_GUELTIG_VON as "gueltigVon",

KENNZ_GUELTIG_BIS as "gueltigBis",

KENNZ_KEY_MART as "kennz_key_mart",

KENNZ_HINWEIS as "hinweis",

KENNZ_UCR as "ucr",

KENNZ_ULC as "ulc"

35

FROM PRM2.SGP_KENNZAHL

WHERE KENNZ_BEREICH = #{kennz_bereich}

and KENNZ_DELETED ='N'

<if test="datum != null">

and (KENNZ_GUELTIG_VON IS NULL OR KENNZ_GUELTIG_VON &lt;= #{datum})

and (KENNZ_GUELTIG_BIS IS NULL OR KENNZ_GUELTIG_BIS &gt;= #{datum})

</if>

order by

KENNZ_SORT asc

</select>

<insert id="insertKennzahlenAdmin" flushCache="true"

statementType="PREPARED" timeout="20" keyProperty="bean.id"

keyColumn="KENNZ_ID" useGeneratedKeys="true">

INSERT INTO prm2.sgp_kennzahl (KENNZ_BEZEICHNUNG, KENNZ_BEREICH,

KENNZ_SORT, KENNZ_NACHKOMMA, KENNZ_EINHEIT_INFO, KENNZ_GRUPPE,

KENNZ_DELETED, KENNZ_GUELTIG_VON, KENNZ_GUELTIG_BIS, KENNZ_KEY_MART,

KENNZ_HINWEIS, KENNZ_UCR, KENNZ_ULC)

VALUES(#{bean.bezeichnung}, #{typ}, #{bean.sort}, #{bean.nachkoma},

#{bean.kennz_einheit_info},#{bean.kennz_gruppe}, #{bean.deleted},

#{bean.gueltigVon},

#{bean.gueltigBis},#{bean.kennz_key_mart},#{bean.hinweis}, #{userId},

#{userId})

</insert>

<update id="updateKennzahlenAdmin" flushCache="true"

statementType="PREPARED" timeout="20">

UPDATE PRM2.sgp_kennzahl

SET

KENNZ_BEZEICHNUNG = #{bean.bezeichnung},

KENNZ_BEREICH = #{typ},

KENNZ_SORT = #{bean.sort},

KENNZ_NACHKOMMA = #{bean.nachkoma},

KENNZ_EINHEIT_INFO = #{bean.kennz_einheit_info},

KENNZ_GRUPPE = #{bean.kennz_gruppe},

KENNZ_DELETED = #{bean.deleted},

KENNZ_GUELTIG_VON = #{bean.gueltigVon},

KENNZ_GUELTIG_BIS = #{bean.gueltigBis},

KENNZ_KEY_MART = #{bean.kennz_key_mart},

KENNZ_HINWEIS = #{bean.hinweis},

KENNZ_ULC = #{userId}

WHERE KENNZ_ID = #{bean.id}

</update>

</mapper>

//

7.3 Frontend vom Portlet „Handlungsfelder“

private List<HandlungsfelderBean> createList(List<Handlungsfeld>

listHandlungsfelderByFilter) {

List<HandlungsfelderBean> list = new ArrayList<HandlungsfelderBean>();

for (Handlungsfeld p : listHandlungsfelderByFilter) {

list.add(new HandlungsfelderBean(p));

36

}

return list;

}

}

//

package com.eiskonzept.portal.prm2_sgp.controller.administration.handlungsfelder;

import java.io.Serializable;

import java.util.Date;

import java.util.List;

public class SearchBean implements Serializable {

private static final long serialVersionUID = -330664870279031977L;

private Integer typ;

private Integer id;

Integer parentId;

private Date gueltig;

private List<HandlungsfelderBean> list;

public Integer getTyp() {

return typ;

}

public void setTyp(Integer typ) {

37

this.typ = typ;

}

public Date getGueltig() {

return gueltig;

}

public void setGueltig(Date gueltig) {

this.gueltig = gueltig;

}

public List<HandlungsfelderBean> getList() {

return list;

}

public void setList(List<HandlungsfelderBean> list) {

this.list = list;

}

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

@Override

public String toString() {

return "SearchBean [typ=" + typ + ", id=" + id + ", partnerId=" + parentId + ", gueltig="

+ gueltig + ", list="

+ list + "]";

38

}

public Integer getParentId() {

return parentId;

}

public void setParentId(Integer parentId) {

this.parentId = parentId;

}

}

//

<%@ page import="de.eis.portlet.framework.util.SPRWindowState"%>

<%@ page trimDirectiveWhitespaces="true" %>

<%@ include file="/WEB-INF/jsp/epf2/include.jsp"%>

<%@ taglib prefix="spr" uri="http://eiskonzept.com/eis-spr"%>

<%@ taglib prefix="epf2" uri="http://eiskonzept.com/ns/epf2" %>

<%@ taglib prefix="eis" uri="http://eiskonzept.com/ns/epf2-nav"%>

<div id="${ns}content" class="claro prm Collage">

<%@ include file="/WEB-INF/jsp/epf2/inc-header.jsp"%>

<spr:actionURL var="urlStore"

windowState="<%=SPRWindowState.EXCLUSIVE.toString()%>">

<portlet:param name="action" value="storeHandlungsfelder" />

</spr:actionURL>

<spr:actionURL var="urlSearch"

windowState="<%=SPRWindowState.EXCLUSIVE.toString()%>">

<portlet:param name="action" value="searchHandlungsfelder" />

</spr:actionURL>

<spr:actionURL var="childSearch"

windowState="<%=SPRWindowState.EXCLUSIVE.toString()%>">

<portlet:param name="action" value="searchChildHandlungsfelder" />

</spr:actionURL>

<eis:nav label="Zurück zur Übersicht" key="analyse.handlungsfeldliste"

spr="true"

windowState="<%=SPRWindowState.EXCLUSIVE.toString()%>"

root="true">

<eis:nav-param name="action"

value="searchHandlungsfelder" />

<eis:nav-param name="typ" value="${searchBean.typ}"

postParam="true"/>

39

<eis:nav-param name="id" value="${searchBean.id}"

postParam="true"/>

<eis:nav-param name="gueltig"

value="${searchBean.gueltig}" postParam="true"/>

</eis:nav>

<div id="${ns}tabcontainer">

<div id="${ns}tab">

<form:form id="${ns}filterForm" modelAttribute="searchBean"

data-dojo-type="eisdojo/EisForm" method="POST">

<div class="searchbar">

<div class="styled-select searchbarItem">

<div class="searchbarItem">

<label for="${ns}gueltig">

<spring:message

code="txt.sgp.portlet.sgphandlungsfelder.label.gueltig" />

</label>

<form:input

path="gueltig"

id="${ns}gueltig"

data-dojo-type="eisdojo/EisDateTextBox"

onkeyup="return eventOnEnter(event,

function(){${ns}search();});"

/>

</div>

<div class="searchbarItem">

<button type="button" class="btn-sekundaer icon-

search" onclick="${ns}search();">

<span>

<spring:message

code="txt.sgp.portlet.sgphandlungsfelder.label.suchen" />

</span>

</button>

</div>

</div>

</div>

<%@ include file="table.jsp"%>

</form:form>

</div>

</div>

<script type="text/javascript">

var ${ns}qedit = null;

require(["eisdojo/EisQuickEditUtil", 'eisdojo/EisDateTextBox',

'dojo/domReady!'],function(QuickEditUtil){

${ns}qedit = new QuickEditUtil({tableId:

'handlungsfeldertable${ns}', ns:'${ns}', hiddenRow:true});

${ns}qedit.initSortButtons();

40

});

function moveRowUp${ns}(item){

${ns}qedit.moveRowUp(item);

}

function moveRowDown${ns}(item){

${ns}qedit.moveRowDown(item);

}

function removeRow${ns}(item){

if (confirm("Wollen Sie das Handlungsfeld wirklch löschen?

Klicken Sie auf OK, um das Handlungsfeld zu löschen"))

{

${ns}qedit.removeRow(item);

${ns}qedit.initSortButtons();

}

}

function childListOpen${ns}(id){

//alert('jo');

${ns}qedit.removeNewRow();

loadFormAsync('${ns}','${childSearch}',

'${ns}content','${ns}filterForm', {'parentId': id});

}

function ${ns}search() {

${ns}qedit.removeNewRow();

loadFormAsync('${ns}','${urlSearch}',

'${ns}content','${ns}filterForm');

};

function save${ns}() {

require(["dijit/registry"],function(registry) {

if (registry.byId('${ns}filterForm').validate()){

${ns}qedit.removeNewRow();

loadFormAsync('${ns}','${urlStore}',

'${ns}content','${ns}filterForm');

}

});

};

/*

function updateOptionen${ns}() {

loadFormAsync('${ns}','${urlSearch}',

'${ns}content','${ns}filterForm');

}

*/

function newHandlungsfeld${ns}(){

${ns}qedit.addNewRow();

// loadFormAsync('${ns}','${urlAdd}',

'${ns}content','${ns}filterForm');

}

// Search-Bar initialisieren

registerListForInstantiation(

[

41

'${ns}filterForm'

//, '${ns}selectedAktiv'

//, '${ns}selectedGruppe'*/

],

{

portlet: '${ns}',

init: true

}

);

// Tabelle initialisieren

//registerGroupForInstantiation('handlungsfeldertable${ns}',

{portlet:'${ns}', init: true});

//registerForInstantiation({portlet: '${ns}', id: '${ns}gueltig',

init: true});

function ${ns}disableDates(checked){

require(['dijit/registry'],function(registry) {

registry.byId('${ns}gueltig').set('disabled', !checked);

});

${ns}search();

}

<%@ include file="tabs.jsp"%>

</script>

<%@ include file="/WEB-INF/jsp/epf2/inc-footer.jsp"%>

</div> <!-- content -->

//

<table class="etable eistable" style="width: 100%; margin-top: 10px;

margin-bottom: 10px; vertical-align: top;" id="handlungsfeldertable${ns}">

<tr class="head eistablerow eistablerowheader">

<td class="eistablecell

eistablecellheader">Position</td>

<td class="eistablecell

eistablecellheader">Handlungsfeld*</td>

<td class="eistablecell eistablecellheader">Hinweis

für GL/Händler</td>

<td class="eistablecell eistablecellheader">Gültig

von</td>

<td class="eistablecell eistablecellheader">Gültig

bis</td>

<td class="eistablecell eistablecellheader"></td>

</tr>

<c:set var="listEmpty" value="${empty searchBean.list}"/>

42

<c:if test="${!listEmpty}">

<c:forEach items="${searchBean.list}" var="handlungsfeld"

varStatus="handlungsfeldStatus">

<c:if test="${!handlungsfeld.deleted}">

<tr class="qedit_sortable_row">

<td class="eistable_hidden">

<form:hidden

path="list[${handlungsfeldStatus.index}].id"

value="${handlungsfeld.id}" />

<form:hidden

class="qedit_sort_indicator"

path="list[${handlungsfeldStatus.index}].sort"

value="${handlungsfeld.sort}" />

<form:hidden

class="qedit_delete_indicator"

path="list[${handlungsfeldStatus.index}].deleted" value="false" />

<form:hidden

path="list[${handlungsfeldStatus.index}].ucr"

value="${handlungsfeld.ucr}" />

<form:hidden

path="list[${handlungsfeldStatus.index}].ulc"

value="${handlungsfeld.ulc}" />

</td>

<td style="width: 50px; text-align:

center; vertical-align: top;" align="center" >

<div

style="display:table-cell; width:30px;">

<button type="button"

class="btn-icon-only qedit_sort_up" onclick="moveRowUp${ns}(this)" ><span

class="icon-button-up"></span></button>

</div>

<div

style="display:table-cell; width:30px;">

<button type="button"

class="btn-icon-only qedit_sort_down"

onclick="moveRowDown${ns}(this)"><span class="icon-button-

down"></span></button>

</div>

</td>

<td style="width: 300px; vertical-align:

top;"><form:input id="${ns}bezeichnung.${handlungsfeldStatus.index}"

type="text"

path="list[${handlungsfeldStatus.index}].bezeichnung"

data-dojo-

type="dijit/form/ValidationTextBox" data-dojo-props ="required:true"

style="width:100%" /></td>

<td style="width:200px; vertical-align:

top;"><form:textarea id="${ns}hinweis.${handlungsfeldStatus.index}"

path="list[${handlungsfeldStatus.index}].hinweis"

data-dojo-

type="dijit/form/ValidationTextBox" data-dojo-

props="value:'${handlungsfeld.hinweis}'"

43

style="width:100%" /></td>

<td align="center" style="vertical-

align: top; text-align: center; width: 80px; ">

<form:input

id="${ns}gueltigVon.${handlungsfeldStatus.index}"

path="list[${handlungsfeldStatus.index}].gueltigVon"

data-dojo-

type="eisdojo/EisDateTextBox" />

</td>

<td align="center" style="vertical-

align: top; text-align: center; width: 80px; ">

<form:input

id="${ns}gueltigBis.${handlungsfeldStatus.index}"

path="list[${handlungsfeldStatus.index}].gueltigBis"

data-dojo-

type="eisdojo/EisDateTextBox" />

</td>

<td>

<button type="button"

style="background-color: #a9a2a7;"

onclick="childListOpen${ns}(${handlungsfeld.id})">

Unterpunkte

(${handlungsfeld.childCount})

</button>

</td>

<td style="text-align: center; width:

60px; vertical-align: top; border-right: none;">

<button type="button"

class="btn-no-button qedit_remove" onclick="removeRow${ns}(this)">

<div style="display:

table-cell; text-align: center; vertical-align: middle;" class="icon-minus-

circle">

</div>

<div style="display:

table-cell; text-align: center; vertical-align: middle;" >

<span

class="underlineBtn">Löschen</span>

</div>

</button>

</td>

</tr>

</c:if>

</c:forEach>

</c:if>

<tr class="qedit_hiddenrow qedit_sortable_row">

<td class="eistable_hidden">

<input type="hidden" name="list[].id"

value="-1" />

<input type="hidden" name="list[].sort"

value="-1" class="qedit_sort_indicator"/>

44

<input type="hidden"

name="list[].deleted" value="false" class="qedit_delete_indicator"/>

</td>

<td style="width: 50px">

<div

style="display:table-cell; width:30px;">

<button type="button"

class="btn-icon-only qedit_sort_up" onclick="moveRowUp${ns}(this)"><span

class="icon-button-up"></span></button>

</div>

<div

style="display:table-cell; width:30px;">

<button type="button"

class="btn-icon-only qedit_sort_down"

onclick="moveRowDown${ns}(this)"><span class="icon-button-

down"></span></button>

</div>

</td>

<td style="width: 300px; vertical-align:

top;">

<input

type="text"

name="list[].bezeichnung" value=""

data-dojo-

type0="dijit/form/ValidationTextBox" data-dojo-props="required:true"

style="width:100%" />

</td>

<td style="width:200px; vertical-align: top;">

<input

type="text"

name="list[].hinweis" value=""

data-dojo-

type0="dijit/form/ValidationTextBox" data-dojo-prop=""

style="width:100%" />

</td>

<td align="center" style="vertical-align: top;

text-align: center; width: 80px; ">

<input type="text"

name="list[].gueltigVon"

value=""

data-dojo-

type0="eisdojo/EisDateTextBox" />

</td>

<td align="center" style="vertical-align: top;

text-align: center; width: 80px; ">

<input type="text"

name="list[].gueltigBis"

value=""

data-dojo-

type0="eisdojo/EisDateTextBox" />

</td>

<td>

&nbsp;

</td>

45

<td style="text-align: center; vertical-align:

middle; border-right: none;">

<button type="button" class="btn-

no-button qedit_remove" onclick="removeRow${ns}(this)">

<div style="display: table-

cell; text-align: center; vertical-align: middle;" class="icon-minus-

circle">

</div>

<div style="display: table-

cell; text-align: center; vertical-align: middle;"><span>Löschen</span>

</div>

</button>

</td>

</tr>

</table>

<button type="button" class="btn-sekundaer icon-plus"

onclick="newHandlungsfeld${ns}()">Neues Handlungsfeld

hinzufügen</button>

<button type="button" class="btn-primaer icon-save"

style="float: right; margin-right: 50px;"

onclick="save${ns}()">Speichern</button>

7.4 Frontend vom Portlet „Kennzahlen“

<table class="etable eistable" style="width: 100%; margin-top: 10px;

margin-bottom: 10px; vertical-align: top;" id="kennzahlAdmintable${ns}">

<tr class="head eistablerow eistablerowheader">

<td class="eistablecell

eistablecellheader">Position</td>

<td class="eistablecell

eistablecellheader">Kennzahl*</td>

<td class="eistablecell

eistablecellheader">Nachkoma</td>

<td class="eistablecell eistablecellheader">KPI-

Schlüssel</td>

<td class="eistablecell eistablecellheader">Hinweis

für GL/Händler</td>

<td class="eistablecell

eistablecellheader">Kennzahlen Einheit Information</td>

<td class="eistablecell

eistablecellheader">Kennzahlen Gruppe</td>

<td class="eistablecell eistablecellheader">Gültig

von [Jahr]</td>

<td class="eistablecell eistablecellheader">Gültig

bis [Jahr]</td>

<td class="eistablecell eistablecellheader"></td>

</tr>

<c:set var="listEmpty" value="${empty searchBean.list}"/>

<c:if test="${!listEmpty}">

46

<c:forEach items="${searchBean.list}" var="kennzahlAdmin"

varStatus="kennzahladminStatus">

<c:if test="${!kennzahlAdmin.deleted}">

<tr class="qedit_sortable_row">

<td class="eistable_hidden">

<form:hidden

path="list[${kennzahladminStatus.index}].id"

value="${kennzahlAdmin.id}" />

<form:hidden

class="qedit_sort_indicator"

path="list[${kennzahladminStatus.index}].sort"

value="${kennzahlAdmin.sort}" />

<form:hidden

class="qedit_delete_indicator"

path="list[${kennzahladminStatus.index}].deleted" value="false" />

<form:hidden

path="list[${kennzahladminStatus.index}].ucr"

value="${kennzahlAdmin.ucr}" />

<form:hidden

path="list[${kennzahladminStatus.index}].ulc"

value="${kennzahlAdmin.ulc}" />

</td>

<td style="width: 50px; text-align:

center; vertical-align: top;" align="center" >

<div

style="display:table-cell; width:30px;">

<button type="button"

class="btn-icon-only qedit_sort_up" onclick="moveRowUp${ns}(this)" ><span

class="icon-button-up"></span></button>

</div>

<div

style="display:table-cell; width:30px;">

<button type="button"

class="btn-icon-only qedit_sort_down"

onclick="moveRowDown${ns}(this)"><span class="icon-button-

down"></span></button>

</div>

</td>

<td style="width: 300px; vertical-align:

top;"><form:input id="${ns}bezeichnung.${kennzahladminStatus.index}"

type="text"

path="list[${kennzahladminStatus.index}].bezeichnung"

data-dojo-

type="dijit/form/ValidationTextBox" data-dojo-props ="required:true"

style="width:100%" /></td>

<td align="center" style="vertical-

align: top; text-align: center; width: 80px;"><form:input

id="${ns}nachkoma.${kennzahladminStatus.index}"

type="text"

path="list[${kennzahladminStatus.index}].nachkoma"

data-dojo-

type="dijit/form/ValidationTextBox" data-dojo-props ="required:true"

style="width:100%" /></td>

47

<td style="width: 300px; vertical-align:

top;"><form:input id="${ns}kennz_key_mart.${kennzahladminStatus.index}"

type="text"

path="list[${kennzahladminStatus.index}].kennz_key_mart"

data-dojo-

type="dijit/form/ValidationTextBox" data-dojo-

props="value:'${kennzahlAdmin.kennz_key_mart}'"

style="width:100%" /></td>

<td style="width:200px; vertical-align:

top;"><form:textarea id="${ns}hinweis.${kennzahladminStatus.index}"

path="list[${kennzahladminStatus.index}].hinweis"

data-dojo-

type="eisdojo/EisValidationTextArea" data-dojo-

props="value:'${kennzahlAdmin.hinweis}'"

style="width:100%" /></td>

<td style="width:200px; vertical-align:

top;"><form:textarea

id="${ns}kennz_einheit_info.${kennzahladminStatus.index}"

path="list[${kennzahladminStatus.index}].kennz_einheit_info"

data-dojo-

type="eisdojo/EisValidationTextArea" data-dojo-

props="value:'${kennzahlAdmin.kennz_einheit_info}'"

style="width:100%" /></td>

<td align="center" style="vertical-

align: top; text-align: center; width: 80px; ">

<form:select

path="list[${kennzahladminStatus.index}].kennz_gruppe"

id="${ns}kennz_gruppe.${kennzahladminStatus.index}"

data-dojo-

type="dijit/form/Select" data-dojo-props ="required:true,

value:'${kennzahlAdmin.kennz_gruppe}'" cssStyle="width:280px;">

<form:options

items="${kennzahlenGruppeListe}"

itemValue="id"

itemLabel="bezeichnung" />

</form:select>

</td>

<%--

<td

<select name="select1" data-dojo-

type="dijit/form/Select">

<option

value="1">Kennzahlen</option>

<option value="2"

selected="selected">Simply Grow</option>

<option

value="3">Kundenzufriedenheit</option>

</select>

48

</td>

--%>

<td align="center" style="vertical-

align: top; text-align: center; width: 80px; ">

<form:input

id="${ns}gueltigVon.${kennzahladminStatus.index}"

path="list[${kennzahladminStatus.index}].gueltigVon"

data-dojo-

type="dijit/form/ValidationTextBox" data-dojo-props="maxLength: 4, regExp:

'[0-9]{4}'"

style="width:100%" /></td>

<td align="center" style="vertical-

align: top; text-align: center; width: 80px; ">

<form:input

id="${ns}gueltigBis.${kennzahladminStatus.index}"

path="list[${kennzahladminStatus.index}].gueltigBis"

data-dojo-

type="dijit/form/ValidationTextBox" data-dojo-props="maxLength: 4, regExp:

'[0-9]{4}'"

style="width:100%" /></td>

<td style="text-align: center; width:

60px; vertical-align: top; border-right: none;">

<button type="button"

class="btn-no-button qedit_remove" onclick="removeRow${ns}(this)">

<div style="display:

table-cell; text-align: center; vertical-align: middle;" class="icon-minus-

circle">

</div>

<div style="display:

table-cell; text-align: center; vertical-align: middle;" >

<span

class="underlineBtn">Löschen</span>

</div>

</button>

</td>

</tr>

</c:if>

</c:forEach>

</c:if>

<tr class="qedit_hiddenrow qedit_sortable_row">

<td class="eistable_hidden">

<input type="hidden" name="list[].id"

value="-1" />

<input type="hidden" name="list[].sort"

value="-1" class="qedit_sort_indicator"/>

<input type="hidden"

name="list[].deleted" value="false" class="qedit_delete_indicator"/>

</td>

49

<td style="width: 50px; text-align: center;

vertical-align: top;" align="center" >

<div

style="display:table-cell; width:30px;">

<button type="button"

class="btn-icon-only qedit_sort_up" onclick="moveRowUp${ns}(this)"><span

class="icon-button-up"></span></button>

</div>

<div

style="display:table-cell; width:30px;">

<button type="button"

class="btn-icon-only qedit_sort_down"

onclick="moveRowDown${ns}(this)"><span class="icon-button-

down"></span></button>

</div>

</td>

<td style="width: 300px; vertical-align:

top;">

<input

type="text"

name="list[].bezeichnung" value=""

data-dojo-

type0="dijit/form/ValidationTextBox" data-dojo-props="required:true"

style="width:100%" />

</td>

<td align="center" style="vertical-align: top;

text-align: center; width: 80px;">

<input

type="text"

name="list[].nachkoma" value=""

data-dojo-

type0="dijit/form/ValidationTextBox" data-dojo-props="required:true"

style="width:100%" />

</td>

<td style="width: 300px; vertical-align:

top;">

<input

type="text"

name="list[].kennz_key_mart" value=""

data-dojo-

type0="dijit/form/ValidationTextBox"

style="width:100%" />

</td>

<td style="width:200px; vertical-align:

top;">

<textarea

name="list[].hinweis"

value=""

data-dojo-

type0="eisdojo/EisValidationTextArea" data-dojo-props=""

style="width:100%"

></textarea>

</td>

<td style="width:200px; vertical-align:

top;">

50

<textarea

name="list[].kennz_einheit_info" value=""

data-dojo-

type0="eisdojo/EisValidationTextArea" data-dojo-props=""

style="width:100%"

></textarea>

</td>

<td align="center" style="vertical-

align: top; text-align: center; width: 80px; ">

<select name="list[].kennz_gruppe"

data-dojo-type0="dijit/form/Select"

data-dojo-props ="required:true"

style="width:280px;">

<c:forEach var="kat"

items="${kennzahlenGruppeListe}">

<option

value="${kat.id}" >${kat.bezeichnung}</option>

</c:forEach>

</select>

</td>

<td align="center" style="vertical-

align: top; text-align: center; width: 80px; ">

<input type="text"

name="list[].gueltigVon"

value="" data-dojo-props="maxLength:,4, regExp: '[0-9]{4}'"

data-dojo-

type0="dijit/form/ValidationTextBox" />

</td>

<td align="center" style="vertical-

align: top; text-align: center; width: 80px; ">

<input type="text"

name="list[].gueltigBis"

value="" data-dojo-props="maxLength: 4, regExp: '[0-9]{4}'"

data-dojo-

type0="dijit/form/ValidationTextBox" />

</td>

<td style="text-align: center; width: 60px;

vertical-align: top; border-right: none;">

<button type="button" class="btn-

no-button qedit_remove" onclick="removeRow${ns}(this)">

<div style="display: table-

cell; text-align: center; vertical-align: middle;" class="icon-minus-

circle">

</div>

<div style="display: table-

cell; text-align: center; vertical-align: middle;"><span>Löschen</span>

</div>

</button>

</td>

</tr>

</table>

<button type="button" class="btn-sekundaer icon-plus"

onclick="newAdminKennzahlenFeld${ns}()">Neue Kennzahl

hinzufügen</button>

51

<button type="button" class="btn-primaer icon-save"

style="float: right; margin-right: 50px;"

onclick="save${ns}()">Speichern</button>

//

<%@ page import="de.eis.portlet.framework.util.SPRWindowState"%>

<%@ page trimDirectiveWhitespaces="true" %>

<%@ include file="/WEB-INF/jsp/epf2/include.jsp"%>

<%@ taglib prefix="spr" uri="http://eiskonzept.com/eis-spr"%>

<%@ taglib prefix="epf2" uri="http://eiskonzept.com/ns/epf2" %>

<%@ taglib prefix="eis" uri="http://eiskonzept.com/ns/epf2-nav"%>

<div id="${ns}content" class="claro prm Collage">

<%@ include file="/WEB-INF/jsp/epf2/inc-header.jsp"%>

<spr:actionURL var="urlStore"

windowState="<%=SPRWindowState.EXCLUSIVE.toString()%>">

<portlet:param name="action" value="storeKennzahlenAdmin" />

</spr:actionURL>

<spr:actionURL var="urlSearch"

windowState="<%=SPRWindowState.EXCLUSIVE.toString()%>">

<portlet:param name="action" value="searchKennzahlenAdmin" />

</spr:actionURL>

<div id="${ns}tabcontainer">

<div id="${ns}tab">

<form:form id="${ns}filterForm" modelAttribute="searchBean"

data-dojo-type="eisdojo/EisForm" method="POST">

<div class="searchbar">

<div class="styled-select searchbarItem">

<div class="searchbarItem">

<label for="${ns}gueltig">

<spring:message

code="txt.sgp.portlet.sgphandlungsfelder.label.gueltig" />

</label>

<form:input

path="gueltig"

id="${ns}gueltig"

data-dojo-type="eisdojo/EisDateTextBox"

onkeyup="return eventOnEnter(event,

function(){${ns}search();});"

/>

</div>

<div class="searchbarItem">

<button type="button" class="btn-sekundaer icon-

search" onclick="${ns}search();">

<span>

52

<spring:message

code="txt.sgp.portlet.sgphandlungsfelder.label.suchen" />

</span>

</button>

</div>

</div>

</div>

<%@ include file="table.jsp"%>

</form:form>

</div>

</div>

<script type="text/javascript">

var ${ns}qedit = null;

require(["eisdojo/EisQuickEditUtil", 'eisdojo/EisDateTextBox',

"dojo/parser", "dijit/form/Select",

'dojo/domReady!'],function(QuickEditUtil){

${ns}qedit = new QuickEditUtil({tableId:

'kennzahlAdmintable${ns}', ns:'${ns}', hiddenRow:true});

${ns}qedit.initSortButtons();

});

function moveRowUp${ns}(item){

${ns}qedit.moveRowUp(item);

}

function moveRowDown${ns}(item){

${ns}qedit.moveRowDown(item);

}

function removeRow${ns}(item){

if (confirm("Wollen Sie die Kennzahl wirklch löschen? Klicken

Sie auf OK, um die Kennzahl zu löschen"))

{

${ns}qedit.removeRow(item);

${ns}qedit.initSortButtons();

}

}

function ${ns}search() {

${ns}qedit.removeNewRow();

loadFormAsync('${ns}','${urlSearch}',

'${ns}content','${ns}filterForm');

};

function save${ns}() {

require(["dijit/registry"],function(registry) {

if (registry.byId('${ns}filterForm').validate()){

${ns}qedit.removeNewRow();

53

loadFormAsync('${ns}','${urlStore}',

'${ns}content','${ns}filterForm');

}

});

};

function newAdminKennzahlenFeld${ns}(){

${ns}qedit.addNewRow();

}

// Search-Bar initialisieren

registerListForInstantiation(

[

'${ns}filterForm'

//, '${ns}selectedAktiv'

//, '${ns}selectedGruppe'*/

],

{

portlet: '${ns}',

init: true

}

);

// Tabelle initialisieren

//registerGroupForInstantiation('handlungsfeldertable${ns}',

{portlet:'${ns}', init: true});

//registerForInstantiation({portlet: '${ns}', id: '${ns}gueltig',

init: true});

function ${ns}disableDates(checked){

require(['dijit/registry'],function(registry) {

registry.byId('${ns}gueltig').set('disabled', !checked);

});

${ns}search();

}

<%@ include file="tabs.jsp"%>

</script>

<%@ include file="/WEB-INF/jsp/epf2/inc-footer.jsp"%>

</div> <!-- content -->