From 9aead2a6230d26837a319f77f14046c3902c7fcb Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 26 Feb 2019 18:13:28 +0100 Subject: [client] Add preset runscript selector to lecture details --- .../gui/configurator/StartupConfigurator.java | 203 ++++++++++++++++++--- .../dozmod/gui/window/LectureDetailsWindow.java | 9 +- .../openslx/dozmod/thrift/cache/MetaDataCache.java | 8 + 3 files changed, 195 insertions(+), 25 deletions(-) diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/configurator/StartupConfigurator.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/configurator/StartupConfigurator.java index f37a45ed..7013e437 100755 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/configurator/StartupConfigurator.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/configurator/StartupConfigurator.java @@ -1,24 +1,50 @@ package org.openslx.dozmod.gui.configurator; import java.awt.Color; +import java.awt.Dialog.ModalityType; +import java.awt.GridBagConstraints; import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicReference; import javax.swing.Box; +import javax.swing.ButtonModel; import javax.swing.DefaultComboBoxModel; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JDialog; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; - +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeListener; + +import org.apache.log4j.Logger; +import org.openslx.bwlp.thrift.iface.ImageDetailsRead; +import org.openslx.bwlp.thrift.iface.LectureRead; +import org.openslx.bwlp.thrift.iface.PresetRunScript; +import org.openslx.dozmod.gui.Gui; import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor; import org.openslx.dozmod.gui.control.ComboBox; import org.openslx.dozmod.gui.control.ComboBox.ComboBoxRenderer; import org.openslx.dozmod.gui.control.QLabel; import org.openslx.dozmod.gui.control.WordWrapLabel; import org.openslx.dozmod.gui.helper.GridManager; +import org.openslx.dozmod.gui.helper.MessageType; +import org.openslx.dozmod.thrift.Session; +import org.openslx.dozmod.thrift.cache.MetaDataCache; +import org.openslx.thrifthelper.ThriftManager; +import org.openslx.util.QuickTimer; +import org.openslx.util.QuickTimer.Task; import org.openslx.util.Util; /** @@ -26,13 +52,109 @@ import org.openslx.util.Util; * Runscript and sound (un)muting */ public class StartupConfigurator extends StartupConfiguratorLayout { - + private static final long serialVersionUID = -3497629601818983994L; private StartupSettings startupSettings = new StartupSettings(null); + private ImageDetailsRead image; + + private List scripts; + + private LectureRead lecture; + + private ChangeListener mightyListener; + public StartupConfigurator() { super(); + QuickTimer.scheduleOnce(new Task() { + @Override + public void fire() { + scripts = MetaDataCache.getPredefinedRunScripts(); + if (scripts.isEmpty()) { + Gui.asyncExec(new Runnable() { + @Override + public void run() { + btnPredefinedScripts.setVisible(false); + } + }); + } + } + }); + btnPredefinedScripts.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + showRunscriptSelector(); + } + }); + } + + private void showRunscriptSelector() { + if (scripts == null) { + Gui.showMessageBox("Wah wah wah! Null scripts", MessageType.ERROR, null, null); + return; + } + final JDialog dialog = new JDialog(SwingUtilities.getWindowAncestor(this), + "Startscripte auswählen", ModalityType.APPLICATION_MODAL); + JPanel pane = new JPanel(); + dialog.setContentPane(pane); + dialog.setMinimumSize(Gui.getScaledDimension(200, 300)); + GridManager grid = new GridManager(pane, 2, true, new Insets(2, 2, 2, 2)); + final Map mapper = new HashMap<>(); + boolean haveDisabled = false; + for (PresetRunScript ruleSet : scripts) { + JCheckBox button = new JCheckBox(ruleSet.displayname); + grid.add(button, 2); + grid.nextRow(); + mapper.put(button.getModel(), ruleSet.scriptId); + if (image != null && ruleSet.osIds != null + && !ruleSet.osIds.contains(image.osId)) { + button.setEnabled(false); + haveDisabled = true; + } + if (lecture != null && lecture.presetScriptIds != null && lecture.presetScriptIds.contains(ruleSet.scriptId)) { + button.setSelected(true); + } + } + if (haveDisabled) { + grid.add(new WordWrapLabel("Ausgegraute Elemente sind mit dem zur" + + " Veranstaltung gehörendem Betriebssystem nicht kompatibel"), 2); + grid.nextRow(); + } + JButton btnCancel = new JButton("Abbrechen"); + JButton btnOk = new JButton("SPASCHAN"); + grid.add(btnCancel).anchor(GridBagConstraints.LINE_START); + grid.add(btnOk).anchor(GridBagConstraints.LINE_END); + grid.finish(true); + btnCancel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dialog.dispose(); + } + }); + final AtomicReference> selectedScripts = new AtomicReference<>(); + btnOk.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + List selected = new ArrayList<>(); + for (Entry button : mapper.entrySet()) { + if (button.getKey().isSelected()) { + selected.add(button.getValue()); + } + } + selectedScripts.set(selected); + dialog.dispose(); + } + }); + dialog.pack(); + Gui.centerShellOverShell(SwingUtilities.getWindowAncestor(this), dialog); + dialog.setVisible(true); + // Call blocks as it's a modal window + if (selectedScripts.get() != null) { + // User clicked OK + startupSettings.selectedScripts = selectedScripts.get(); + mightyListener.stateChanged(null); + } } private void setError(final String msg) { @@ -45,7 +167,7 @@ public class StartupConfigurator extends StartupConfiguratorLayout { * @return runscript as String. If no text was entered, returns a empty * string. */ - public String getState() { + public StartupSettings getState() { setError(""); // fill remove any prior errors, we'll reset them if needed // handle user input, this is tricky since // * either an item has been selected -> editorContent will be of our enum type @@ -56,7 +178,7 @@ public class StartupConfigurator extends StartupConfiguratorLayout { } else if (cboContent instanceof String) { startupSettings.put(Field.EXTENSION, (String) cboContent); } - String taInputText = taRunScript.getText(); + startupSettings.runScript = taRunScript.getText(); RunscriptVisibility visibility = (RunscriptVisibility) cboRunscriptVisibility.getSelectedItem(); startupSettings.put(Field.VISIBILITY, Integer.toString(visibility.value)); @@ -64,7 +186,7 @@ public class StartupConfigurator extends StartupConfiguratorLayout { startupSettings.put(Field.MUTED, Integer.toString(sound.value)); setError(""); - return startupSettings.serialize() + "\n" + taInputText; + return startupSettings; } /** @@ -72,17 +194,33 @@ public class StartupConfigurator extends StartupConfiguratorLayout { * this sets the content of the text areas to the corresponding network * rules/runscript as given by the AdvancedConfiguration object * - * @param config + * @param lecture * AdvancedConfiguration to set the state to */ - public void setState(final String config) { - if (config == null || config.isEmpty()) { + public void setState(final LectureRead lecture) { + if (lecture == null) + return; + this.lecture = lecture; + setCustomScript(lecture.runscript); + QuickTimer.scheduleOnce(new Task() { + @Override + public void fire() { + try { + image = ThriftManager.getSatClient().getImageDetails(Session.getSatelliteToken(), lecture.imageBaseId); + } catch (Exception e) { + } + } + }); + } + + private void setCustomScript(final String lecture) { + if (lecture == null || lecture.isEmpty()) { cboRunscriptType.setSelectedItem(null); taRunScript.setText(""); return; } String header = null; - try (BufferedReader reader = new BufferedReader(new StringReader(config))) { + try (BufferedReader reader = new BufferedReader(new StringReader(lecture))) { header = reader.readLine(); } catch (IOException e) { // swallow ... @@ -90,7 +228,7 @@ public class StartupConfigurator extends StartupConfiguratorLayout { if (header != null) { // we should have following format: ext=;visibility=;... // e.g. ext=sh;visibility=0 - startupSettings.deserialize(header); + startupSettings.deserializeItems(header); String extension = startupSettings.get(Field.EXTENSION); for (RunscriptType type : RunscriptType.values()) { if (type.extension.equals(extension)) { @@ -123,7 +261,7 @@ public class StartupConfigurator extends StartupConfiguratorLayout { } // finished with the interpreter, remove that line from the given config // before setting that text - taRunScript.setText(config.replaceFirst(".*?\n", "")); + taRunScript.setText(lecture.replaceFirst(".*?\n", "")); } public void addToChangeMonitor(DialogChangeMonitor changeMonitor) { @@ -131,6 +269,7 @@ public class StartupConfigurator extends StartupConfiguratorLayout { changeMonitor.addEditableCombo(cboRunscriptType, null); changeMonitor.addFixedCombo(cboRunscriptVisibility, null); changeMonitor.addFixedCombo(cboSoundState, null); + // TODO: Preset runscript } private static enum Field { @@ -145,32 +284,35 @@ public class StartupConfigurator extends StartupConfiguratorLayout { } /** - * Map holding the inline settings from line 1 of the script + * Object holding all the startup settings */ - private static class StartupSettings extends HashMap { - private static final long serialVersionUID = -5893345450266600626L; + public static class StartupSettings { + + public Map items = new HashMap<>(); + public String runScript; + public List selectedScripts; public StartupSettings(String data) { super(); - deserialize(data); + deserializeItems(data); } public String put(Field key, String value) { value = value.replace(';', '_').replace('\r', '_').replace('\n', '_'); - return super.put(key.id, value); + return items.put(key.id, value); } public String get(Field key) { - String ret = super.get(key.id); + String ret = items.get(key.id); if (ret == null) return ""; return ret; } - public String serialize() { + public String serializeItems() { StringBuilder sb = new StringBuilder(); - for (Entry e : this.entrySet()) { + for (Entry e : items.entrySet()) { if (sb.length() != 0) { sb.append(';'); } @@ -181,18 +323,30 @@ public class StartupConfigurator extends StartupConfiguratorLayout { return sb.toString(); } - public void deserialize(String data) { + public void deserializeItems(String data) { if (data == null) return; - clear(); + items.clear(); String[] parts = data.split(";"); for (String s : parts) { String[] entry = s.split("="); if (entry.length == 2) { - put(entry[0], entry[1]); + items.put(entry[0], entry[1]); } } } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof StartupSettings)) + return false; + StartupSettings other = (StartupSettings) obj; + if (this.selectedScripts == other.selectedScripts) + return true; + if (this.selectedScripts == null) + return false; + return this.selectedScripts.equals(other.selectedScripts); + } } } @@ -212,6 +366,7 @@ class StartupConfiguratorLayout extends JPanel { protected final ComboBox cboRunscriptType; protected final ComboBox cboRunscriptVisibility; protected final ComboBox cboSoundState; + protected final JButton btnPredefinedScripts; public StartupConfiguratorLayout() { GridManager grid = new GridManager(this, 2, true, new Insets(5, 5, 5, 5)); @@ -275,6 +430,10 @@ class StartupConfiguratorLayout extends JPanel { grid.add(scpRunScript, 2).fill(true, true).expand(true, true); grid.nextRow(); + btnPredefinedScripts = new JButton("Vordefinierte Scripte..."); + grid.add(btnPredefinedScripts, 2).anchor(GridBagConstraints.LINE_END); + grid.nextRow(); + lblError = new QLabel(""); lblError.setForeground(Color.RED); JPanel pnlError = new JPanel(); diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureDetailsWindow.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureDetailsWindow.java index 12e6fe55..8924ed97 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureDetailsWindow.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/window/LectureDetailsWindow.java @@ -39,6 +39,7 @@ import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor; import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.NotNullConstraint; import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.TextNotEmptyConstraint; import org.openslx.dozmod.gui.changemonitor.DialogChangeMonitor.ValidationConstraint; +import org.openslx.dozmod.gui.configurator.StartupConfigurator.StartupSettings; import org.openslx.dozmod.gui.helper.DateTimeHelper; import org.openslx.dozmod.gui.helper.MessageType; import org.openslx.dozmod.gui.helper.UiFeedback; @@ -343,7 +344,7 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements ctlLocationSelector.setSelectedLocationsAsIds(lecture.locationIds); // init advanced info - ctlRunscriptConfigurator.setState(lecture.runscript); + ctlRunscriptConfigurator.setState(lecture); ctlNetshareConfigurator.setState(lecture.networkShares, lecture.presetNetworkShares); ctlLdapFilterConfigurator.setState(lecture.ldapFilters, lecture.presetLdapFilters); ctlNetrulesConfigurator.setState(lecture.networkExceptions); @@ -381,7 +382,7 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements dtpEndDate.getModel().setDate(endCal.get(Calendar.YEAR), endCal.get(Calendar.MONTH), endCal.get(Calendar.DATE)); spnEndTime.getModel().setValue(endCal.getTime()); - + // now enable the tabs the user can see given its permissions toggleEditable(true); // and always switch to the "About" tab @@ -525,10 +526,11 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements changeListenerPermissions.reset(); } // first build the LectureWrite from the GUI fields + StartupSettings startupSettings = ctlRunscriptConfigurator.getState(); final LectureWrite metadata = new LectureWrite(txtTitle.getText(), txtDescription.getText(), lecture.getImageVersionId(), chkAutoUpdate.isSelected(), chkIsActive.isSelected(), startTime, endTime, - ctlRunscriptConfigurator.getState(), null, + startupSettings.runScript, null, chkIsExam.isSelected(), chkHasInternetAccess.isSelected(), lecture.getDefaultPermissions(), ctlLocationSelector.getSelectedLocationsAsIds(), @@ -538,6 +540,7 @@ public class LectureDetailsWindow extends LectureDetailsWindowLayout implements metadata.setNetworkExceptions(ctlNetrulesConfigurator.getState()); metadata.setNetworkShares(ctlNetshareConfigurator.getState()); metadata.setLdapFilters(ctlLdapFilterConfigurator.getState()); + metadata.setPresetScriptIds(startupSettings.selectedScripts); // now trigger the actual action try { diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/cache/MetaDataCache.java b/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/cache/MetaDataCache.java index 6d75f792..8b6e4890 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/cache/MetaDataCache.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/thrift/cache/MetaDataCache.java @@ -11,6 +11,7 @@ import org.openslx.bwlp.thrift.iface.Location; import org.openslx.bwlp.thrift.iface.NetShare; import org.openslx.bwlp.thrift.iface.OperatingSystem; import org.openslx.bwlp.thrift.iface.PredefinedData; +import org.openslx.bwlp.thrift.iface.PresetRunScript; import org.openslx.bwlp.thrift.iface.Virtualizer; import org.openslx.dozmod.thrift.Session; import org.openslx.thrifthelper.ThriftManager; @@ -217,6 +218,13 @@ public class MetaDataCache { return new ArrayList(0); return pd.netShares; } + + public static List getPredefinedRunScripts() { + PredefinedData pd = predefinedData.get(); + if (pd == null || pd.ldapFilter == null) + return new ArrayList(0); + return pd.runScripts; + } -- cgit v1.2.3-55-g7522