commit a0f1e13f93c374fc04459f5f112fd79296ae6227 Author: Daniel Kallendorf Date: Wed Nov 9 23:36:08 2022 +0100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9154f4c --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# ---> Java +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + diff --git a/README.md b/README.md new file mode 100644 index 0000000..479e676 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# Getting started + +## Dependencies +- FirstSpirit installation +- Compiled FSHook project (FSHook/bin/uploadPlugin.jar exists) +- OpenJDK11 (On Windows this gets installed together with FS `C:/Users//.firstspirit/FSLauncher/jre/11.0.11/jre-win/jdk-11.0.11+9-jre/bin/java.exe`) + +## Paths +- `` point to your (or FSs) OpenJDK11 installation +- `` can be found in `FSHook/tool` +- `` points to + - `bin/` of this project, + - `FSHook/bin/*` and `FSHook/lib/aspectjrt.jar` of FSHook + - `.firstspirit/FSLauncher/jar/*`, `.firstspirit_/jars/*` of the FS installation. (usually located in $HOME) - The seperator is `:` on Linux and `;` on Windows. + +## Build this +I.e. with vs-code java extension. +Set classpath and add `res/` to source directories + +## Launch this +1) Be in the TU-Network or connected via VPN. +2) Launch +``` -cp -javaaagent: com.kallendorf.Main``` +3) Log in +4) Click on the scroll-icon in the toolbar. +This will link all protocolls of this year. + diff --git a/resources/Scroll.png b/resources/Scroll.png new file mode 100644 index 0000000..d4177f4 Binary files /dev/null and b/resources/Scroll.png differ diff --git a/src/com/kallendorf/fsplugin/Main.java b/src/com/kallendorf/fsplugin/Main.java new file mode 100644 index 0000000..5ab1c3e --- /dev/null +++ b/src/com/kallendorf/fsplugin/Main.java @@ -0,0 +1,21 @@ +package com.kallendorf.fsplugin; + +import com.kallendorf.fsplugin.fsprotokolle.FSProtokollPlugin; +import de.espirit.firstspirit.client.plugin.Plugin; + +import java.util.HashSet; +import java.util.Set; + +import com.kallendorf.fshook.CustomLoader; + +public class Main { + + public static void main(String[] args) { + Plugin p = new FSProtokollPlugin(); + Set pSet = new HashSet<>(); + pSet.add(p); + String[] fsargs = { "--system-properties", + "FS-eJydlVtv2jAYhv/K/gAmPuTgRb6IWqpF4yABVaepEnITF9KGJLINhV3sty8pMPF53UYrbnjs9/1OtiEZDhc3g2R+Ox3MxKMsjYqvhulgPF98mYwGi+t0Kn720WOhjTVNoQu78BGZEuJxV7dI0m8Xa4fp+PZy9Si5ulg7mwyTaTq7WH+Xjq8nd//QT6aDBfb8iAmrN+rImFH/nInHyGl8h4X2AwTECwAHjEIOyTlTTCLADIN41Och4CDkgEPPAxxFAWQO43EM43EK9dyH9fAA1Ms8xiEHIeTQhxxBbjuGzGB8HHiQI2cf9sOIRx2OIGPP4QAycfaJE5848eGFYCRwOHT0oZMPnh8jkaPnTj1uvxz6qdM/xQyy0x8lxGEnHnXiOedDIyeeUx/lcP4M3k/GnPraBIB953x85zx8eqxnPlvgEHftHd5jx5FHaXjOPvbxOYc0ZL/txMOcHLNl9brRypiiroQXqyrT+8Z2QOJVbazQKpfP3QKym14u9dpYmVuUq/hJbmVvu+5JvTTiU68n87xXN6oy96LbQg/SqP7rt1JWy3uRDIe92/E4GQ2u31DnyjzbujkY5ItFaqsq+x7XDpmXolqippSPXfIi+7Db7Cu7esutdk2tLejQbCpkVLZpf1T3SGbdqP7vPGVup49k05QKqbbny31d0o8YkFmpsnyf7XUuH7C8a5R/uq18KBUwxmWdyVKJ9u6V9bKoRFYW7R05ALJF9qyswKzeKcwLKvfV8rS1b5QYJek4XstdsS5+qOPTWNe5ErPJ1dfBPO6qEdiLorjR9ZPKbJqLKAwizoNYq2VhrN63/6Bt/pv2lGu9n54WW32jtC2UiY3S21LZ73WlRD/umum6IznKaX54bxtdipW1jfnc7//9bW2MehUd6vwF9UPXOA==" }; + CustomLoader.launchFS(fsargs, pSet); + } +} diff --git a/src/com/kallendorf/fsplugin/fsprotokolle/FSProtokollHelper.java b/src/com/kallendorf/fsplugin/fsprotokolle/FSProtokollHelper.java new file mode 100644 index 0000000..e1788c6 --- /dev/null +++ b/src/com/kallendorf/fsplugin/fsprotokolle/FSProtokollHelper.java @@ -0,0 +1,57 @@ +package com.kallendorf.fsplugin.fsprotokolle; + +import java.net.URL; +import java.net.URLConnection; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Scanner; + +public class FSProtokollHelper { + final static String MATHEBAU_PROTKOLLE = "https://mathebau.de/protokolle/"; + + public static String[] getProtokollNames() { + String content = null; + URLConnection connection = null; + try { + connection = new URL(MATHEBAU_PROTKOLLE).openConnection(); + Scanner scanner = new Scanner(connection.getInputStream()); + scanner.useDelimiter("\\Z"); + content = scanner.next(); + scanner.close(); + } catch (Exception ex) { + ex.printStackTrace(); + } + + String[] protokolle = Arrays.stream(content.split(System.lineSeparator())) + .filter(l -> l.startsWith(" l.split("\"")[1]) + .toArray(String[]::new); + return protokolle; + } + + public static String[] getProtokollNamesCurrent() { + int year = Calendar.getInstance().get(Calendar.YEAR); + String yearString = String.valueOf(year); + String[] allProtokolls = getProtokollNames(); + String[] currentProtokolls = Arrays.stream(allProtokolls) + .filter(t -> t.split("-")[2].equals(yearString)) + .toArray(String[]::new); + return currentProtokolls; + } + + public static int[] parseDate(String protokollTitle) { + // fs-protokoll-2020-12-16_A-Teil_en.pdf + String[] parts = protokollTitle.split("-"); + return new int[] { Integer.parseInt(parts[2]), Integer.parseInt(parts[3]), Integer.parseInt(parts[4]) }; + } + + public static String verboseTitleString(String protokollTitle) { + int[] dateParts = parseDate(protokollTitle); + return String.format("Protokoll der Sitzung vom %2d.%2d.%4d", dateParts[2], dateParts[1], dateParts[0]); + } + + public static String getDownloadLink(String protokollTitle) { + return MATHEBAU_PROTKOLLE + protokollTitle; + } + +} diff --git a/src/com/kallendorf/fsplugin/fsprotokolle/FSProtokollMenuItem.java b/src/com/kallendorf/fsplugin/fsprotokolle/FSProtokollMenuItem.java new file mode 100644 index 0000000..878f577 --- /dev/null +++ b/src/com/kallendorf/fsplugin/fsprotokolle/FSProtokollMenuItem.java @@ -0,0 +1,202 @@ +package com.kallendorf.fsplugin.fsprotokolle; + +import java.awt.Image; +import java.io.IOException; +import java.io.InputStream; +import java.util.Calendar; +import java.util.NoSuchElementException; + +import javax.imageio.ImageIO; +import javax.swing.Icon; +import javax.swing.ImageIcon; + +import org.jetbrains.annotations.NotNull; + +import de.espirit.common.event.ValueChangeEvent; +import de.espirit.common.event.ValueChangeListener; +import de.espirit.firstspirit.access.Language; +import de.espirit.firstspirit.access.editor.DomEditorValue; +import de.espirit.firstspirit.access.editor.NumberEditorValue; +import de.espirit.firstspirit.access.editor.TextEditorValue; +import de.espirit.firstspirit.access.editor.ToggleEditorValue; +import de.espirit.firstspirit.access.editor.value.DefaultDomNode; +import de.espirit.firstspirit.access.editor.value.DomElement; +import de.espirit.firstspirit.access.editor.value.DomNode; +import de.espirit.firstspirit.access.editor.value.InvalidValueException; +import de.espirit.firstspirit.access.store.ElementDeletedException; +import de.espirit.firstspirit.access.store.ElementMovedException; +import de.espirit.firstspirit.access.store.LockException; +import de.espirit.firstspirit.access.store.Store; +import de.espirit.firstspirit.access.store.StoreElement; +import de.espirit.firstspirit.access.store.Store.Type; +import de.espirit.firstspirit.access.store.pagestore.Body; +import de.espirit.firstspirit.access.store.pagestore.Page; +import de.espirit.firstspirit.access.store.pagestore.Section; +import de.espirit.firstspirit.access.store.templatestore.FormatTemplate; +import de.espirit.firstspirit.access.store.templatestore.FormatTemplates; +import de.espirit.firstspirit.access.store.templatestore.LinkTemplate; +import de.espirit.firstspirit.access.store.templatestore.LinkTemplates; +import de.espirit.firstspirit.access.store.templatestore.SectionTemplate; +import de.espirit.firstspirit.access.store.templatestore.SectionTemplates; +import de.espirit.firstspirit.access.store.templatestore.TemplateStoreRoot; +import de.espirit.firstspirit.access.store.templatestore.gom.GomText; +import de.espirit.firstspirit.access.store.templatestore.gom.GomToggle; +import de.espirit.firstspirit.agency.LanguageAgent; +import de.espirit.firstspirit.agency.OperationAgent; +import de.espirit.firstspirit.agency.StoreAgent; +import de.espirit.firstspirit.client.access.editor.EditorValueChangedEvent; +import de.espirit.firstspirit.client.access.editor.EditorValueListener; +import de.espirit.firstspirit.client.access.editor.ReferenceTransformationAgent; +import de.espirit.firstspirit.client.access.editor.ValueEngineer; +import de.espirit.firstspirit.client.access.editor.ValueEngineerFactory; +import de.espirit.firstspirit.client.access.link.LinkImpl; +import de.espirit.firstspirit.client.plugin.toolbar.ExecutableToolbarItem; +import de.espirit.firstspirit.client.plugin.toolbar.ToolbarContext; +import de.espirit.firstspirit.forms.FormData; +import de.espirit.firstspirit.forms.FormField; +import de.espirit.firstspirit.store.access.DataBuilder; +import de.espirit.firstspirit.store.operations.ReleaseOperation; +import de.espirit.firstspirit.store.operations.SaveOperation; + +public class FSProtokollMenuItem implements ExecutableToolbarItem { + + /** + * @wbp.parser.entryPoint + */ + public FSProtokollMenuItem() { + } + + public String getLabel(@NotNull final ToolbarContext context) { + return "PermissionViewPlugin"; + } + + public Icon getIcon(@NotNull final ToolbarContext context) { + // Credites to FontAwesome CC BY SA 4.0 + InputStream is = FSProtokollPlugin.class.getResourceAsStream("/Scroll.png"); + + try { + return new ImageIcon(ImageIO.read(is).getScaledInstance(30, 24, Image.SCALE_SMOOTH)); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public Icon getPressedIcon(@NotNull final ToolbarContext context) { + return null; + } + + public Icon getRollOverIcon(@NotNull final ToolbarContext context) { + return null; + } + + public boolean isVisible(@NotNull final ToolbarContext context) { + return true; + } + + public boolean isEnabled(@NotNull final ToolbarContext context) { + return true; + } + + public void execute(@NotNull final ToolbarContext context) { + // get the applicationservice from servicesBroker + StoreAgent storeAgent = context.requestSpecialist(StoreAgent.TYPE); + Store pageStore = storeAgent.getStore(Type.PAGESTORE); + + OperationAgent operationAgent = context.requireSpecialist(OperationAgent.TYPE); + SaveOperation saveOperation = operationAgent.getOperation(SaveOperation.TYPE); + saveOperation.setRecursionEnabled(true); + ReleaseOperation releaseOperation = operationAgent.getOperation(ReleaseOperation.TYPE); + releaseOperation.recursive(true); + releaseOperation.withComment("FSProtokoll Plugin on Tour"); + + int year = Calendar.getInstance().get(Calendar.YEAR); + Language language = context.requestSpecialist(LanguageAgent.TYPE).getMasterLanguage(); + + Page protokollseite = (Page) getChildByName(pageStore, "fsmathe", "fachschaft_responsiv", + "fachschaftsarbeit_1", "downloads___links_1", "fs_protokolle_1"); + Body pageBody = (Body) getChildByName(protokollseite, "zentral"); + + try { + protokollseite.setLock(true, true); + + // retrive Templates + final TemplateStoreRoot templateStore = (TemplateStoreRoot) context.requireSpecialist(StoreAgent.TYPE) + .getStore(Store.Type.TEMPLATESTORE); + + final SectionTemplates sectionTemplates = templateStore.getSectionTemplates(); + final SectionTemplate sectionTemplate = sectionTemplates.getTemplate("text@tud_vorlagen"); + + final FormatTemplates formatTemplates = templateStore.getFormatTemplates(); + final FormatTemplate paragraphTemplate = formatTemplates.getFormatTemplate("p"); + + final LinkTemplates linkTemplates = templateStore.getLinkTemplates(); + final LinkTemplate linkTemplate = linkTemplates.getTemplate("externerlink"); + + try { + final StoreElement oldSection = getChildByName(pageBody, "protokoll_" + year); + oldSection.setLock(true); + oldSection.delete(); + pageBody.removeChild(oldSection); + pageBody.refresh(); + } catch (NoSuchElementException e) { + // Nothing to do here + } + + Section section = pageBody.createSection("protokoll_" + year, sectionTemplate); + pageBody.moveChild(section, 1); + section.setDisplayName(language, String.valueOf(year)); + section.includeInOutput(language); + FormData sectionFormData = section.getFormData(); + + sectionFormData.get(language, "st_ueberschrift").set(String.valueOf(year)); + sectionFormData.get(language, "st_toggle").set(true); + sectionFormData.get(language, "st_ueberschrift_zeichen").set(4); + sectionFormData.get(language, "st_ueberschrift_ebene").set(2); + + FormField editor = (FormField) sectionFormData.get(language, "st_text"); + + // get the dom element and rootNode of the editor value + final DomElement domElement = editor.get(); + final DefaultDomNode rootDomNode = domElement.getRoot(); + for (DomNode n : rootDomNode.getChildren()) { + rootDomNode.removeChild(n); + } + + // append a paragraph by using the paragraphTemplate + String[] protokolle = FSProtokollHelper.getProtokollNamesCurrent(); + for (int i = protokolle.length - 1; i >= 0; i--) { + String protokollName = protokolle[i]; + final DefaultDomNode paragraph = (DefaultDomNode) rootDomNode.appendChild(paragraphTemplate); + final LinkImpl link = (LinkImpl) linkTemplate.createLink(language); + link.setAttribute("ref", FSProtokollHelper.getDownloadLink(protokollName)); + link.setText(protokollName); + paragraph.appendChild(link); + } + editor.set(domElement); + section.setFormData(sectionFormData); + + saveOperation.setRecursionEnabled(true); + saveOperation.setComment("FSProtokoll Plugin has fired."); + saveOperation.perform(protokollseite); + protokollseite.setLock(false, true); + + releaseOperation.perform(protokollseite); + + System.out.println("Ende"); + } catch (InvalidValueException | LockException | ElementDeletedException | ElementMovedException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private StoreElement getChildByName(StoreElement rootNode, String... path) { + StoreElement node = rootNode; + for (String name : path) { + node = node.getChildren().toList().stream().filter(s -> s.getName().equals(name)).findFirst().get(); + } + return node; + } + +} diff --git a/src/com/kallendorf/fsplugin/fsprotokolle/FSProtokollPlugin.java b/src/com/kallendorf/fsplugin/fsprotokolle/FSProtokollPlugin.java new file mode 100644 index 0000000..7df8de5 --- /dev/null +++ b/src/com/kallendorf/fsplugin/fsprotokolle/FSProtokollPlugin.java @@ -0,0 +1,37 @@ +package com.kallendorf.fsplugin.fsprotokolle; + +import java.util.Arrays; +import java.util.Collection; + +import org.jetbrains.annotations.NotNull; + +import de.espirit.firstspirit.access.BaseContext; +import de.espirit.firstspirit.client.plugin.JavaClientEditorialToolbarItemsPlugin; +import de.espirit.firstspirit.client.plugin.toolbar.JavaClientToolbarItem; + +public class FSProtokollPlugin implements JavaClientEditorialToolbarItemsPlugin{ + // Field definitions for objects that are required during the lifetime of a class instance. + BaseContext _context; + + + @Override + public void setUp(@NotNull final BaseContext context) { + _context = context; + } + + + @Override + public void tearDown() { + } + + + @NotNull + @Override + public Collection getItems() { + // Create and return an array list that includes individual button item objects. + return (Collection) Arrays.asList( + new FSProtokollMenuItem() + ); + } + +}