diff --git a/src/main/java/org/olat/collaboration/CollaborationToolsSettingsController.java b/src/main/java/org/olat/collaboration/CollaborationToolsSettingsController.java index 06c177f9956a4dadbee8b809393bfd4fc83fb2aa..fe13e0eefbb9161bc50a5883f21cee4eb086ddf4 100644 --- a/src/main/java/org/olat/collaboration/CollaborationToolsSettingsController.java +++ b/src/main/java/org/olat/collaboration/CollaborationToolsSettingsController.java @@ -31,7 +31,6 @@ import java.util.List; import org.olat.commons.calendar.CalendarManager; import org.olat.commons.calendar.CalendarModule; import org.olat.commons.calendar.ui.events.CalendarGUIModifiedEvent; -import org.olat.core.CoreSpringFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.form.flexible.FormItem; @@ -275,31 +274,39 @@ public class CollaborationToolsSettingsController extends BasicController { } class ChoiceOfToolsForm extends FormBasicController { - CollaborationTools cts; - MultipleSelectionElement ms; + private CollaborationTools cts; + private MultipleSelectionElement ms; - List <String>theKeys = new ArrayList<String>(); - List <String>theValues = new ArrayList<String>(); - - final String[] availableTools; + private final String[] toolsKeys; + private final String[] toolsValues; + private final String[] cssClasses; + private final String[] availableTools; + + @Autowired + private InstantMessagingModule imModule; public ChoiceOfToolsForm(UserRequest ureq, WindowControl wControl, CollaborationTools cts, final String[] availableTools) { super(ureq, wControl); this.cts = cts; this.availableTools = availableTools; + List<String> theKeys = new ArrayList<>(); + List<String> theValues = new ArrayList<>(); + List<String> theClasses = new ArrayList<>(); for (int i=0; i<availableTools.length; i++) { String k = availableTools[i]; - if (k.equals(CollaborationTools.TOOL_CHAT)) { - InstantMessagingModule imModule = CoreSpringFactory.getImpl(InstantMessagingModule.class); - if (!imModule.isEnabled() || !imModule.isGroupEnabled()) { - continue; - } + if (k.equals(CollaborationTools.TOOL_CHAT) && (!imModule.isEnabled() || !imModule.isGroupEnabled())) { + continue; } theKeys.add(""+i); - theValues.add(translate("collabtools.named."+availableTools[i])); + theValues.add(translate("collabtools.named." + availableTools[i])); + theClasses.add(translate("o_sel_" + availableTools[i])); } + toolsKeys = theKeys.toArray(new String[theKeys.size()]); + toolsValues = theValues.toArray(new String[theValues.size()]); + cssClasses = theClasses.toArray(new String[theClasses.size()]); + initForm(ureq); } @@ -314,10 +321,7 @@ class ChoiceOfToolsForm extends FormBasicController { @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { - ms = uifactory.addCheckboxesVertical( - "selection", formLayout, - theKeys.toArray(new String[theKeys.size()]), - theValues.toArray(new String[theValues.size()]), 1); + ms = uifactory.addCheckboxesVertical("selection", "selection", formLayout, toolsKeys, toolsValues, cssClasses, null, 1); ms.setElementCssClass("o_sel_collab_tools"); for (int i=0; i<availableTools.length; i++) { ms.select(""+i, cts.isToolEnabled(availableTools[i])); diff --git a/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_fr.properties index e65884bd2fac448894ef4e5cc15754b43115471d..8ab6a34e59fcb34187fe853db589a67e12430158 100644 --- a/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/commons/calendar/_i18n/LocalStrings_fr.properties @@ -1,4 +1,4 @@ -#Sun Nov 08 13:10:17 CET 2015 +#Sun Nov 29 17:18:08 CET 2015 cal.add.event=Ajouter rendez-vous cal.add.readonly=(lecture uniquement) cal.color.choose=Choisir la couleur @@ -65,6 +65,8 @@ cal.form.title=D\u00E9tails du rendez-vous cal.fri=Vendredi cal.from=De cal.goto.event=Aller au rdv. s\u00E9lectionn\u00E9 +cal.icalfeed.aggregated.info=Utilisez le lien suivant pour l'acc\u00E8s de votre calendrier (tous les calendriers agr\u00E9g\u00E9 inclus) \u00E0 partir d'autres applications. Vous pouvez copier le lien et le coller dans une application qui prend en charge le format iCal. +cal.icalfeed.aggregated.title=Flux iCal des calendriers agr\u00E9g\u00E9s cal.icalfeed.aggregated.tooltip=$\:cal.icalfeed.aggregated.title cal.icalfeed.info=Veuillez utiliser l'URL suivante pour appeler ce calendrier depuis une autre application. Vous pouvez copier l'URL et l'ins\u00E9rer dans toute autre application de calendrier qui supporte le format iCal. cal.icalfeed.regenerate.info=Le lien iCal Feed a \u00E9t\u00E9 r\u00E9actualis\u00E9. @@ -201,6 +203,7 @@ tab.links.extern.url=URL tab.links.extern.url.invalid=L'URL donn\u00E9e n'est pas valide. table.add=+ table.delete=- +table.header.aggregated.feed=Agr\u00E9g\u00E9 table.header.color=Couleur table.header.name=Nom table.header.tools=<i class\="o_icon o_icon-lg o_icon_actions"> </i> diff --git a/src/main/java/org/olat/core/commons/services/notifications/NotificationHelper.java b/src/main/java/org/olat/core/commons/services/notifications/NotificationHelper.java index 074135dbf7c14af8ccaeb7d249e923f02e39db13..33db9824de996ab066c719fabd82e6dcdbadd7e1 100644 --- a/src/main/java/org/olat/core/commons/services/notifications/NotificationHelper.java +++ b/src/main/java/org/olat/core/commons/services/notifications/NotificationHelper.java @@ -107,12 +107,9 @@ public class NotificationHelper { * @return */ public static String getFormatedName(Identity ident) { - Translator trans; - User user = null; - String formattedName = null; - + String formattedName; if (ident == null) { - trans = Util.createPackageTranslator(NotificationNewsController.class, I18nManager.getInstance().getLocaleOrDefault(null)); + Translator trans = Util.createPackageTranslator(NotificationNewsController.class, I18nManager.getInstance().getLocaleOrDefault(null)); return trans.translate("user.unknown"); } else { // Optimize: use from cache to not re-calculate user properties over and over again @@ -121,10 +118,10 @@ public class NotificationHelper { return formattedName; } } - trans = Util.createPackageTranslator(NotificationNewsController.class, I18nManager.getInstance().getLocaleOrDefault( - ident.getUser().getPreferences().getLanguage())); - user = ident.getUser(); + Translator trans = Util.createPackageTranslator(NotificationNewsController.class, I18nManager.getInstance().getLocaleOrDefault( + ident.getUser().getPreferences().getLanguage())); + User user = ident.getUser(); if (user == null) { formattedName = trans.translate("user.unknown"); } else { @@ -144,7 +141,6 @@ public class NotificationHelper { } // put formatted name in cache, times out after 5 mins userPropertiesCache.put(ident.getKey(), formattedName); - return formattedName; } diff --git a/src/main/java/org/olat/core/dispatcher/ErrorFeedbackMailer.java b/src/main/java/org/olat/core/dispatcher/ErrorFeedbackMailer.java index 283f0af80159fa6372abe7470f84d78e143d8b7c..382f490e96b254fe9d636e20f4f9748aad549be2 100644 --- a/src/main/java/org/olat/core/dispatcher/ErrorFeedbackMailer.java +++ b/src/main/java/org/olat/core/dispatcher/ErrorFeedbackMailer.java @@ -33,11 +33,11 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.olat.basesecurity.BaseSecurity; -import org.olat.core.CoreSpringFactory; import org.olat.core.id.Identity; import org.olat.core.logging.LogFileParser; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; +import org.olat.core.util.StringHelper; import org.olat.core.util.WebappHelper; import org.olat.core.util.mail.MailBundle; import org.olat.core.util.mail.MailManager; @@ -53,6 +53,25 @@ import org.olat.core.util.mail.MailManager; public class ErrorFeedbackMailer implements Dispatcher { private static final OLog log = Tracing.createLoggerFor(ErrorFeedbackMailer.class); + + private MailManager mailManager; + private BaseSecurity securityManager; + + /** + * [used by Spring] + * @param mailManager + */ + public void setMailManager(MailManager mailManager) { + this.mailManager = mailManager; + } + + /** + * [used by spring] + * @param securityManager + */ + public void setSecurityManager(BaseSecurity securityManager) { + this.securityManager = securityManager; + } /** * send email to olat support with user submitted error informaition @@ -64,27 +83,26 @@ public class ErrorFeedbackMailer implements Dispatcher { String errorNr = request.getParameter("fx_errnum"); String username = request.getParameter("username"); try { - BaseSecurity im = CoreSpringFactory.getImpl(BaseSecurity.class); - Identity ident = im.findIdentityByName(username); - // if null, user may crashed befor getting a valid session, try with - // guest user instead - if (ident == null) - ident = im.findIdentityByName("guest"); - Collection<String> logFileEntries = LogFileParser.getErrorToday(errorNr, false); - StringBuilder out = new StringBuilder(2048); - out.append(feedback) - .append("\n------------------------------------------\n\n --- from user: ").append(username).append(" ---"); - if (logFileEntries != null) { - for (Iterator<String> iter = logFileEntries.iterator(); iter.hasNext();) { - out.append(iter.next()); + if(StringHelper.containsNonWhitespace(username)) { + Identity ident = securityManager.findIdentityByName(username); + Collection<String> logFileEntries = LogFileParser.getErrorToday(errorNr, false); + StringBuilder out = new StringBuilder(2048); + out.append(feedback) + .append("\n------------------------------------------\n\n --- from user: ").append(username).append(" ---"); + if (logFileEntries != null) { + for (Iterator<String> iter = logFileEntries.iterator(); iter.hasNext();) { + out.append(iter.next()); + } } + + MailBundle bundle = new MailBundle(); + bundle.setFromId(ident); + bundle.setTo(WebappHelper.getMailConfig("mailError")); + bundle.setContent("Feedback from Error Nr.: " + errorNr, out.toString()); + mailManager.sendExternMessage(bundle, null); + } else { + log.error("Try to send a feedback without identity"); } - - MailBundle bundle = new MailBundle(); - bundle.setFromId(ident); - bundle.setTo(WebappHelper.getMailConfig("mailError")); - bundle.setContent("Feedback from Error Nr.: " + errorNr, out.toString()); - CoreSpringFactory.getImpl(MailManager.class).sendExternMessage(bundle, null); } catch (Exception e) { handleException(request, e); return; diff --git a/src/main/java/org/olat/core/dispatcher/_spring/dispatcherContext.xml b/src/main/java/org/olat/core/dispatcher/_spring/dispatcherContext.xml index dfa21c66b9abc9802aed9d3375b0ab5b2a59ba57..51cb8590e5b7f16e1c707dd00c5e199878533a31 100644 --- a/src/main/java/org/olat/core/dispatcher/_spring/dispatcherContext.xml +++ b/src/main/java/org/olat/core/dispatcher/_spring/dispatcherContext.xml @@ -68,7 +68,10 @@ <bean id="oauthcallback" class="org.olat.login.oauth.OAuthDispatcher" /> <!-- send bug report dispatcher --> - <bean id="errorMailBean" class="org.olat.core.dispatcher.ErrorFeedbackMailer" /> + <bean id="errorMailBean" class="org.olat.core.dispatcher.ErrorFeedbackMailer"> + <property name="mailManager" ref="mailManager"/> + <property name="securityManager" ref="baseSecurityManager"/> + </bean> <!-- all olat dispatchers --> <bean id="dmzbean" class="org.olat.dispatcher.DMZDispatcher"> diff --git a/src/main/java/org/olat/core/gui/control/generic/iframe/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/gui/control/generic/iframe/_i18n/LocalStrings_de.properties index 81f9b8556163948db9a9b8101b3be461a4b42edb..e582540cd0421e4228ec6b7e3e51e534ae7f5cfc 100644 --- a/src/main/java/org/olat/core/gui/control/generic/iframe/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/core/gui/control/generic/iframe/_i18n/LocalStrings_de.properties @@ -5,7 +5,7 @@ option.delivery=Layout mode=Anzeigemodus mode.standard=Standard mode.configured=Optimiert f\u00FCr OpenOLAT -mode.hover=Verwenden Sie die Standardeinstellung f?r extern erstellten Inhalt. +mode.hover=Verwenden Sie die Standardeinstellung f\u00FCr extern erstellten Inhalt. option.css=Layout anpassen option.css.none=Keine option.css.openolat=OpenOLAT Stylesheets @@ -21,7 +21,7 @@ encoding.auto=Automatisch encoding.same=Gleich wie Inhalt height.auto=Automatisch height.label=H\u00F6he Anzeigefl\u00E4che -inherit.label=Standardwerte übernehmen +inherit.label=Standardwerte \u00FCbernehmen inherit=Aus Layouteinstellungen der Lernressource \u00FCbernehmen custom=Anpassen glossary.need.jQuery=Glossar braucht jQuery diff --git a/src/main/java/org/olat/core/gui/control/generic/iframe/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/core/gui/control/generic/iframe/_i18n/LocalStrings_fr.properties index 45f14001232a13a5628de10ff9bc3b48c0baebec..50f73ea2e77c8a8e4dc4e931af9e839a5928dc50 100644 --- a/src/main/java/org/olat/core/gui/control/generic/iframe/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/core/gui/control/generic/iframe/_i18n/LocalStrings_fr.properties @@ -1,15 +1,5 @@ -#Thu Sep 03 11:24:42 CEST 2015 +#Sun Nov 29 10:58:54 CET 2015 automatic.need.js=Automatique \u00E0 besoin de javascript - - - - - - - - - - command.download=T\u00E9l\u00E9charger fichier custom=Modifi\u00E9 encoding.auto=Automatiquement @@ -24,6 +14,7 @@ inherit=H\u00E9rit\u00E9 inherit.label=H\u00E9ritage mode=Mode standard mode.configured=Modifi\u00E9 +mode.hover=Utilisez de pr\u00E9f\u00E9rence le mode standard avec les contenus cr\u00E9\u00E9s avec un \u00E9diteur externe. mode.standard=Strict option.css=Librairie CSS option.css.none=Aucune diff --git a/src/main/java/org/olat/core/util/i18n/devtools/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/core/util/i18n/devtools/_i18n/LocalStrings_fr.properties index 46ab26f59d42e7076892d9d7cbec6e56a93fd98e..287f0d35f8d7719253c7775ff82428ac3672e1cd 100644 --- a/src/main/java/org/olat/core/util/i18n/devtools/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/core/util/i18n/devtools/_i18n/LocalStrings_fr.properties @@ -1,17 +1,66 @@ -#Fri Nov 06 17:05:17 CET 2015 +#Sun Nov 29 20:40:57 CET 2015 caching.enabled=Le stockage dans la m\u00E9moire cache est activ\u00E9e. Pour utiliser les outils de d\u00E9veloppeurs, la m\u00E9moire cache devrait \u00EAtre d\u00E9sactiv\u00E9e. coreasjar=Le framework olatcore est t\u00E9l\u00E9charg\u00E9 comme Jar, ce qui fait qu'il est impossible de le modifier. devtools.title=Outils de d\u00E9veloppeurs pour traductions +devtools.warning=Le module de traduction i18n doit \u00EAtre activ\u00E9. Ajouter ou modifier les lignes suivantes dans votre fichier olat.local.properties\:<br/><br/>is.translation.server\=enabled<br/>i18n.application.src.dir\=${project.build.home.directory}/src/main/java +menu.i18nDev=Maintenance i18n +menu.i18nDev.alt=Maintenance i18n submitAddKey=Ajouter une cl\u00E9 +submitGetDupKeys=Chercher les cl\u00E9s en double +submitGetDupVals=Chercher les valeurs en double +submitMerge=Fusionner +submitMove=D\u00E9placer +submitMoveKey=D\u00E9placer la cl\u00E9 +submitMoveKeyToBundle=D\u00E9placez la cl\u00E9 +submitRemoveDeleted=Enlever les cl\u00E9s effac\u00E9es +submitRemoveEmpty=Enlever les cl\u00E9s vides +submitRemoveKey=Enlever la cl\u00E9 +submitRemovePackage=Enlever le package +submitRemoveTodo=Enlever les cl\u00E9s TODO +submitRenameKey=Renommer la cl\u00E9 +submitRenameLanguage=Renommer la langue +submitSort=Trier alphab\u00E9tiquement +task.add.key=Ajouter une cl\u00E9 +task.add.key.bundle=Bundle +task.add.key.key=Cl\u00E9 +task.add.key.locale=Locale +task.add.key.value=Valeur task.delete.key=Effacer cl\u00E9 task.delete.package=Effacer paquet task.find.douplicates=Trouver doublons task.find.unreferenced.keys=Trouver cl\u00E9s non r\u00E9f\u00E9renci\u00E9es task.merge.package=Assembler paquets task.move.key=D\u00E9placer cl\u00E9 +task.move.key.key=Cl\u00E9 +task.move.key.to.bundle=D\u00E9placer la cl\u00E9 task.move.language=D\u00E9placer langue task.move.package=D\u00E9placer paquet +task.move.package.source=Source +task.move.package.target=Cible +task.remove.deletedKeys=Enlever les cl\u00E9s effac\u00E9es +task.remove.deletedKeysCheck=Essai \u00E0 vide +task.remove.emptyKeys=Enlever les cl\u00E9s vides +task.remove.emptyKeysCheck=Essai \u00E0 vide +task.remove.key=Enlever la cl\u00E9 +task.remove.key.bundle=Bundle +task.remove.key.key=Cl\u00E9 +task.remove.key.locale=Locale +task.remove.package=Enlever le package +task.remove.package.bundle=Bundle +task.remove.todoKeys=Enlever les cl\u00E9s TODO +task.remove.todoKeysCheck=Essay \u00E0 vide +task.remove.xKeys=Enelever les cl\u00E9s X +task.remove.xKeysCheck=Essai \u00E0 vide task.remove.xkeys=Supprimer cl\u00E9s X task.rename.key=Renommer cl\u00E9 +task.rename.key.bundle=Bundle +task.rename.key.orig=Nom de la cl\u00E9 d'origine +task.rename.key.origBundle=Bundle d'origine +task.rename.key.target=Nom de la cl\u00E9 cible +task.rename.key.targetBundle=Bundle cible task.rename.language=Renommer langue +task.rename.language.source=Langue source +task.rename.language.target=Langue cible +task.sort.check=Essai \u00E0 vide +task.sort.keys=Trier tous les cl\u00E9s alphab\u00E9tiquement task.unknown.keys=Afficher/effacer les cl\u00E9s fausses diff --git a/src/main/java/org/olat/core/util/openxml/HTMLToOpenXMLHandler.java b/src/main/java/org/olat/core/util/openxml/HTMLToOpenXMLHandler.java index 03ed08d5c9eb18e14d12ec95cbaa324fa2c7c65a..47782ba9b0e7388d25f54586716ea91e18e2e8dd 100644 --- a/src/main/java/org/olat/core/util/openxml/HTMLToOpenXMLHandler.java +++ b/src/main/java/org/olat/core/util/openxml/HTMLToOpenXMLHandler.java @@ -62,6 +62,7 @@ public class HTMLToOpenXMLHandler extends DefaultHandler { private Table currentTable; private Element currentParagraph; private ListParagraph currentListParagraph; + private boolean pNeedNewParagraph = true; public HTMLToOpenXMLHandler(OpenXMLDocument document, Element paragraph) { this.factory = document; @@ -153,7 +154,7 @@ public class HTMLToOpenXMLHandler extends DefaultHandler { } } else { Element currentRun = getCurrentRun(); - String text = textBuffer.toString(); + String text = textBuffer.toString().replace("\n", "").replace("\r", ""); if(text.length() > 0 && Character.isSpaceChar(text.charAt(0))) { currentRun.appendChild(factory.createPreserveSpaceEl()); } @@ -318,7 +319,7 @@ public class HTMLToOpenXMLHandler extends DefaultHandler { public void startElement(String uri, String localName, String qName, Attributes attributes) { String tag = localName.toLowerCase(); if("p".equalsIgnoreCase(tag)) { - getCurrentParagraph(true); + getCurrentParagraph(pNeedNewParagraph); } else if("span".equalsIgnoreCase(tag)) { flushText(); @@ -361,6 +362,7 @@ public class HTMLToOpenXMLHandler extends DefaultHandler { Style[] styles = setTextPreferences(Style.italic); styleStack.add(new StyleStatus(tag, true, styles)); appendParagraph(new Spacing(90, 0)); + pNeedNewParagraph = false; } else if("div".equals(tag)) { String cl = attributes.getValue("class"); if(StringHelper.containsNonWhitespace(cl)) { @@ -368,6 +370,7 @@ public class HTMLToOpenXMLHandler extends DefaultHandler { Style[] styles = setTextPreferences(Style.italic); styleStack.add(new StyleStatus(tag, true, styles)); appendParagraph(new Spacing(120, 0)); + pNeedNewParagraph = false; } else { styleStack.add(new StyleStatus(tag, new Style[0])); } diff --git a/src/main/java/org/olat/course/nodes/fo/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/nodes/fo/_i18n/LocalStrings_fr.properties index a5768004f8a4e95b6b959b82eb1d1cb65a9f0ac7..ef2de1af067c1cb6132cc98a6923b93dc8533887 100644 --- a/src/main/java/org/olat/course/nodes/fo/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/course/nodes/fo/_i18n/LocalStrings_fr.properties @@ -1,4 +1,6 @@ -#Mon Feb 08 21:03:37 CET 2010 +#Sun Nov 29 13:41:34 CET 2015 +allow.guest.post=Permettent aux utilisateurs invit\u00E9s de r\u00E9pondre sur le forum +allow.pseudonym.post=Autoriser les messages anonymes avec pseudonyme command.closefo=Fermer visualisation command.show=Afficher forum command.showpopup=Afficher forum dans nouvelle fen\u00EAtre @@ -9,15 +11,13 @@ display.config.fieldsettitle=Configuration display.config.startPage=Avec page d'accueil? display.config.startPage.false=Non, d\u00E9marer contenu tout de suite svp display.config.startPage.true=Oui, afficher svp - - - - pane.tab.accessibility=Acc\u00E8s pane.tab.foconfig=Affichage +pane.tab.settings=Configuration peekview.allItemsLink=Toutes les contributions preview.canModerate=Animer des contributions du forum possible preview.canPost=Ecriture de contributions du forum possible preview.canRead=Lecture de contributions du forum possible preview.header=Droits dans forum pour l'utilisateur simul\u00E9 +settings.title=Configuration warn.forumdelete=Attention\: toutes les contributions seront supprim\u00E9es. diff --git a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_fr.properties index 3fd05e86e06dc1fc80211e9b75ca3fb212579a5d..ba6819f4fe2d2c2b7889cfc27a330c230ec10609 100644 --- a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_fr.properties @@ -1,4 +1,4 @@ -#Thu Sep 03 11:24:42 CEST 2015 +#Sun Nov 29 19:33:12 CET 2015 add.solution=T\u00E9l\u00E9chargez une solution add.task=Ajouter un devoir assessment.group.tool=Evaluer les groupes @@ -7,8 +7,10 @@ assignment.deadline=Attribution jusqu'au before=avant bulk.download.title=T\u00E9l\u00E9charger tous les documents que vous avez soumis bulk.review=T\u00E9l\u00E9charger la critique +bulk.revisions=T\u00E9l\u00E9charger les documents r\u00E9vis\u00E9s bulk.solutions=T\u00E9l\u00E9chargez les solutions bulk.submitted.documents=Documents soumis +bulk.submitted.revisions=T\u00E9l\u00E9charger les documents corrig\u00E9s change.group=Choisir le groupe actif change.group.description=Vous \u00EAtes inscrits dans plusieurs groupes. choose.areas=Choisir des domaines d'\u00E9tudes @@ -17,17 +19,30 @@ choosed.areas=Domaines d'\u00E9tudes choosed.groups=Groupes coach.assessment=Evaluer coach.close.revision.button=Terminer le processus de r\u00E9vision +coach.corrections.closed=Le document soumis a \u00E9t\u00E9 accept\u00E9 pour \u00E9valuation coach.corrections.description=Vous avez re\u00E7u les corrections suivantes en retour. +coach.corrections.rejected=Le document a \u00E9t\u00E9 retourn\u00E9 pour r\u00E9vision. +coach.corrections.waiting=Les documents soumis sont en attente de v\u00E9rification. coach.document=Documents +coach.document.open.editor=Cr\u00E9er une correction coach.documents.successfully.reviewed=Evaluer\! coach.need.revision.button=N\u00E9cessite une r\u00E9\u00E9criture coach.reviewed.button=Evaluer +coach.reviewed.confirm.text=Veuillez confirmer que les documents remis ont \u00E9t\u00E9 accept\u00E9s. Le devoir est donc termin\u00E9 pour l'utilisateur, qui n'aura plus d'occasion de le r\u00E9viser. +coach.reviewed.confirm.title=Confirmation\: accepter le document soumis +coach.revisions.confirm.text=Veuillez confirmer la demande d'une r\u00E9vision. L'utilisateur pourra soumettre des documents suppl\u00E9mentaires. +coach.revisions.confirm.text.warn=Ainsi, vous fermez le dossier de d\u00E9p\u00F4t. Si vous voulez continuer \u00E0 cr\u00E9er ou t\u00E9l\u00E9charger des corrections, cliquez "Annuler". +coach.revisions.confirm.title=Confirmation\: r\u00E9vision demand\u00E9e coach.revisions.description=Vous avez re\u00E7u en retour des documents retravaill\u00E9s. +coach.revisions.nofiles=La demande de r\u00E9vision a \u00E9t\u00E9 envoy\u00E9 sans document pour l'accompagner. coach.submit.corrections.to.revision.button=Envoyer les corrections coach.submitted.documents.description=Les documents suivants vous ont \u00E9t\u00E9 transmis. +coach.submitted.nofiles=La soumission du devoir a \u00E9t\u00E9 effectu\u00E9 sans le moindre document. coach.task.assigned.description=Les devoirs suivants ont \u00E9t\u00E9 assign\u00E9s. coach.waiting.assignment=Attendre une affectation +coach.waiting.assignment.description=Le devoir n'a pas encore \u00E9t\u00E9 attribu\u00E9. La soumission de documents et leur correction ne pourront commencer que lorsque le devoir sera assign\u00E9. coach.waiting.submitted.documents=Attendre les documents +coach.waiting.submitted.documents.description=Aucun document n'a \u00E9t\u00E9 soumis. Le retour et la correction ne peuvent commencer que lorsque un devoir r\u00E9solu a \u00E9t\u00E9 soumis. comment=Commentaires condition.accessibility.title=Acc\u00E8s confirm.delete.solution.description=Voulez-vous vraiment effacer la solution "{0}"? @@ -41,6 +56,7 @@ create.task=Cr\u00E9er un devoir days.after=jours apr\u00E8s document=Documents d\u00E9pos\u00E9s document.date=Date +document.open.editor=R\u00E9diger une solution download.task=T\u00E9l\u00E9charger les devoirs download.task.infos={0} ({1} MB) edit.task=Editer le devoir @@ -54,6 +70,7 @@ error.editor.atLeastOne=Vous devez choisir un type d'\u00E9diteur au moins. error.file.exists=$org.olat.core.commons.modules.bc\:cfile.already.exists error.file.invalid=$org.olat.core.commons.modules.bc\:cfile.name.notvalid error.max.documents=Vous ne pouvez pas d\u00E9poser plus de <b>{0}</b> documents, mais vous pouvez encore \u00E9diter ou \u00E9changer un fichier. +error.missing.file=Le fichier d'un devoir est manquant. error.missing.group=Vous n'avez pas encore choisi un groupe. error.missing.score.config=Configuration de l'\u00E9valuation est manquante error.missing.solutions=Vous n'avez pas encore t\u00E9l\u00E9charg\u00E9 de solution. @@ -68,6 +85,7 @@ external.editor=T\u00E9l\u00E9charger un fichier (PDF par exemple) file.name=Nom du document file.name.example=Document.html grading=Evaluation +grading.enabled=Activ\u00E9 l'\u00E9valuation des documents group.apply.toall=Appliquer au groupe group.comment=Commentaire pour le groupe group.passed=R\u00E9ussi pour le groupe @@ -77,6 +95,8 @@ info.title=$org.olat.course.nodes.ms\:info.title log.title=Historique des modifications mail.confirm.assignment.body=Affectation du devoir est r\u00E9ussi. mail.confirm.assignment.subject=Affectation +mailto.group=Courriel au groupe +mailto.user=Courriel au utilisateur max.documents=Nombre maximum de documents notifications.correction=Nouvelles corrections "{0}" de "{1}" notifications.header=Devoirs de groupe du cours "{0}" @@ -107,6 +127,8 @@ process.revision=Remaniements process.solution=Solution process.submission=D\u00E9p\u00F4t relative.dates=Dates relatives +relative.to.assignment=Affectation des devoirs +relative.to.assignment.message={0} jours apr\u00E8s l'affectation du devoir. relative.to.course.launch=Premi\u00E8re visite du participant au cours relative.to.course.start=D\u00E9but du cours ({0}) relative.to.enrollment=Inscription / r\u00E9servations @@ -121,6 +143,7 @@ run.assignment.title=Affectation d'un devoir run.coach=Corriger run.coach.corrections.description=Vous avez retourner les demandes de corrections suivantes. run.corrections.description=Votre coach a ajout\u00E9 les documents suivants \u00E0 votre intention\: +run.corrections.rejected=$\:coach.corrections.rejected run.documents.successfully.submitted=Votre/vos document(s) ont \u00E9t\u00E9 transmis avec succ\u00E8s. run.grading=Evaluation run.pick.task.description=Veuillez s'il vous pla\u00EEt choisir un devoir. @@ -129,6 +152,7 @@ run.review.closed=Votre coach a \u00E9valu\u00E9 les documents que vous lui avez run.review.description=Votre coach \u00E9valu\u00E9 les documents que vous lui avez transmis. Vous serez avertis d\u00E8s qu'une version remani\u00E9e ou corrig\u00E9e sera disponible ou vous sera demand\u00E9e. run.review.waiting=Votre coach \u00E9value les documents que vous lui avez transmis. Vous serez avertis d\u00E8s qu'une version remani\u00E9e ou corrig\u00E9e sera disponible ou vous sera demand\u00E9e. run.revised.description=Vous avez transmis les documents remani\u00E9s suivants\: +run.revised.nofiles=La r\u00E9vision a \u00E9t\u00E9 soumise sans le moindre document run.revision=P\u00E9riode de remaniement run.revision.period.description=Votre coach a ajout\u00E9 une p\u00E9riode de r\u00E9vision. Cr\u00E9er un document remani\u00E9 ou t\u00E9l\u00E9chargez-en un. run.run=Devoir @@ -139,12 +163,15 @@ run.submit=D\u00E9p\u00F4t run.submit.button=Transmettre le devoir run.submit.confirm=Le d\u00E9p\u00F4t de votre devoir est d\u00E9finitif. run.submit.confirm.group=$\:run.submit.confirm<br/>C'est un devoir de groupe\! La s\u00E9lection effectu\u00E9e ici est valable pour tous les participants du groupe "{0}"\! +run.submit.confirm.warning=Vous n'avez pas t\u00E9l\u00E9charger ou cr\u00E9er de document. Souhaitez toujours soumettre votre devoir? La remise du devoir est d\u00E9finitive et ne peut \u00EAtre r\u00E9voqu\u00E9e. Vous ne pourrez plus t\u00E9l\u00E9charger de documents ensuite. +run.submit.confirm.warning.group=$\:run.submit.confirm.warning<br/>C'ist un de vor de groupe\! Les actions effectu\u00E9es ici le sont au nom de tous les membres du groupe "{0}"\! run.submit.due.date=D\u00E9lai de d\u00E9p\u00F4t\: {0} run.submit.individual.description.all=Entrez votre solution soit en t\u00E9l\u00E9chargeant un document ou en utilisant l'\u00E9diteur int\u00E9gr\u00E9 mis \u00E0 votre disposition. run.submit.individual.description.editor=Ecrivez directement votre solution dans l'\u00E9diteur. run.submit.individual.description.upload=T\u00E9l\u00E9chargez un document termin\u00E9 en tant que solution. run.submit.revision.button=Soumettre les remaniements run.submitted.description=Vous avez rendus les solutions suivantes\: +run.submitted.nofiles=Le devoir a \u00E9t\u00E9 soumis sans le moindre document. sample.solution=Solutions sample.solution.enabled=activ\u00E9 sample.solution.visible.after=Visible apr\u00E8s le @@ -177,6 +204,7 @@ table.header.uploaded.by=T\u00E9l\u00E9charger par task.alreadyChosen=$org.olat.course.nodes.ta\:task.chosen task.assigned.description=Le devoir suivant vous a \u00E9t\u00E9 affect\u00E9\: task.assignment=Affectation +task.assignment.enabled=Assigner des devoirs aux participants task.assignment.error=Une erreur inattendue s'est produite\! task.assignment.type=$org.olat.course.nodes.ta\:form.task.type task.assignment.type.auto=$org.olat.course.nodes.ta\:form.task.type.auto @@ -201,3 +229,9 @@ wait.for.solutions=Les solutions mod\u00E8les seront visible apr\u00E8s l'heure warning.group.pick.task=Ceci est un devoir de groupe\! La s\u00E9lection effectu\u00E9e ici s'applique \u00E0 tous les participants du groupe "{0}"\! Assurez-vous que votre choix \u00E0 \u00E9t\u00E9 discut\u00E9 au sein de votre groupe\! Seul un participant du groupe pour choisir un devoir. warning.group.submit=Ceci est un devoir de groupe\! Les documents soumis le sont pour tous les participants du groupe "{0}"\! Assurez-vous que les solutions ont \u00E9t\u00E9 discut\u00E9es au sein du groupe\! Un seul membre du groupe peut soumettre la solution d\u00E9finitive. warning.group.task=Ceci est un devoir de groupe\! L'affectation des devoirs, le d\u00E9p\u00F4t de la solution comme l'\u00E9valuation sont effectu\u00E9es pour tout le groupe. Discutez avec les autres membres du groupe comme vous allez ensemble choisir puis g\u00E9rer le devoir. +warning.no.task.choosed=Il semble qu'il n'a pas \u00E9t\u00E9 possible de vous choisir un devoir en raison de changements dans la configuration de l'\u00E9l\u00E9ment de cours. +warning.no.task.choosed.coach=Il semble qu'en raison d'un changement dans la configuration de l'\u00E9l\u00E9ment de cours, un utilisateur n'a pas pu se voir assigner un devoir. +warning.tasks.in.process.delete.text=Voulez-vous vraiment supprimer ce devoir? Des utilisateurs l'ont d\u00E9j\u00E0 commenc\u00E9. Cela entra\u00EEnera des probl\u00E8mes pour ces utilisateurs. +warning.tasks.in.process.delete.title=$\:warning.tasks.in.process.title +warning.tasks.in.process.text=Il ya d\u00E9j\u00E0 des utilisateurs qui ont commenc\u00E9 les devoirs. Des modifications de la configuration du processus pourra entra\u00EEner des probl\u00E8mes pour ces utilisateurs. +warning.tasks.in.process.title=Devoirs d\u00E9j\u00E0 commenc\u00E9s diff --git a/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_fr.properties index d67b42f28d2d9b4d2d8af10435789305b2cc24ad..b8dcb6e12d8e8fbd56f49332fb0039762ab6fc60 100644 --- a/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_fr.properties @@ -1,66 +1,9 @@ -#Sun Dec 14 10:43:00 CET 2014 +#Sun Nov 29 10:55:55 CET 2015 add.member=$org.olat.group.ui.main\:add.member allow.leaving.group=Les participants peuvent quitter le groupe areachoice.no.areas.admin=Aucun domaine d'\u00E9tude trouv\u00E9. Cr\u00E9ez SVP un domaine d'\u00E9tude dans la gestion des groupes areachoice.no.areas.owner=Aucun domaine d'\u00E9tude trouv\u00E9. Les domaines d'\u00E9tude peuvent \u00EAtre cr\u00E9\u00E9s uniquement par les personnes autoris\u00E9es pour toute la gestion des groupes. assessment=$org.olat.group.ui.main\:assessment - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - chkBox.open=Publier ce groupe \u00E0 la r\u00E9servation chkBox.open.downloadList=Les utilisateurs peuvent t\u00E9l\u00E9charger la liste des membres chkBox.open.owners=Tous voient les coaches @@ -96,16 +39,7 @@ group.edit.tab.members=Membres group.edit.tab.resources=Cours group.edit.tab.rights=Autorisations group.edit.title=Editer le groupe <i>{0}</i> - - - - - - - - - - +group.id.help=Cherchez cette Id. dans la recherche avanc\u00E9e. home=$org.olat.group.ui.main\:home import.member=$org.olat.group.ui.main\:import.member mail.member=$org.olat.group.ui.main\:mail.member diff --git a/src/main/java/org/olat/group/ui/wizard/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/group/ui/wizard/_i18n/LocalStrings_fr.properties index bbb8769c5965cac841530f4ac9c00bf2f39a755a..e866e9c86eaeeb1775fd6a28127c35c8fae6475f 100644 --- a/src/main/java/org/olat/group/ui/wizard/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/group/ui/wizard/_i18n/LocalStrings_fr.properties @@ -1,4 +1,4 @@ -#Fri Nov 06 17:06:35 CET 2015 +#Sun Nov 29 10:56:31 CET 2015 action.general=Action backLink=Retour bgcopywizard.copyform.areas=Configuration domaines d'\u00E9tude @@ -34,6 +34,7 @@ copy.wizard.bgstep=Copier\: "{0}" create.form.error.emptylist=Indiquez au moins le nom d'un groupe, svp create.form.error.numberOrNull=Seulement des chiffres, svp (ou laisser vide) create.form.title.max=Nombre pr\u00E9vu <br>de participants +email.other.groups={0} et {1} autres groupes email.select.receiver.description=But email.select.receiver.participant=Participant email.select.receiver.title=But diff --git a/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_fr.properties index 5439555a3c4bcf1e5398e97fc016810aa9302fbe..84284934874101dcdd1847d84819c3ee1a47ca6c 100644 --- a/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/ims/qti/editor/_i18n/LocalStrings_fr.properties @@ -1,4 +1,4 @@ -#Sun Nov 08 13:00:33 CET 2015 +#Sun Nov 29 17:14:42 CET 2015 add_answer=Ajouter nouvelle r\u00E9ponse add_blank=Ajouter nouveau trou add_text=Ajouter nouveau fragment de texte @@ -54,7 +54,9 @@ fieldset.legend.preview=Aper\u00E7u fieldset.legend.question=Question fieldset.legend.sectionsettings=R\u00E9glages form.assessment.order_type=Ordres des sections +form.assessment.order_type.hover=D\u00E9terminer l'ordre dans lequel les sections choisies doivent \u00EAtre affich\u00E9es \u00E0 l'utilisateur. form.assessment.selection_pre=Nombre de sections dans cette \u00E9valuation +form.assessment.selection_pre.hover=Indiquez si toutes les sections ou une s\u00E9lection al\u00E9atoire seulement sera \u00E0 affich\u00E9e \u00E0 l'utilisateur. form.chngmsg.info=Vous avez modifi\u00E9 une ressource r\u00E9f\u00E9renc\u00E9e par d'autres auteurs. \u00C9crivez un message qui sera envoy\u00E9 avec l'historique des modifications \u00E9tabli automatiquement. Vous devez envoyer ce message afin de rendre effectives vos modifications. form.chngmsg.infolabel=Information form.chngmsg.informlearners=Les apprenants peuvent voir l'historique des modifications. @@ -81,6 +83,7 @@ form.imd.type=Type form.metadata.cutvalue=Nombre de points n\u00E9cessaire pour "r\u00E9ussi" form.metadata.duration=Limite de temps form.metadata.globalfeedbackNsolution=Placer les Feedback / Solutions pour tout le test +form.metadata.globalfeedbackNsolution.hover=D\u00E9terminer si l'\u00E9valuation et la solution seront pr\u00E9sent\u00E9s \u00E0 l'utilisateur. form.metadata.minutes=Min form.metadata.objectives=Description form.metadata.seconds=Sec diff --git a/src/main/java/org/olat/modules/fo/ForumNotificationsHandler.java b/src/main/java/org/olat/modules/fo/ForumNotificationsHandler.java index 71fe27d81280a1ad21ae665b9de534cb491bb937..4c9ed78bc6643109a5387306c7d43dd6d0c03ddf 100644 --- a/src/main/java/org/olat/modules/fo/ForumNotificationsHandler.java +++ b/src/main/java/org/olat/modules/fo/ForumNotificationsHandler.java @@ -99,7 +99,11 @@ public class ForumNotificationsHandler extends LogDelegator implements Notificat String name; if(modifier != null) { - name = NotificationHelper.getFormatedName(modifier); + if(modifier.equals(creator) && StringHelper.containsNonWhitespace(mInfo.getPseudonym())) { + name = mInfo.getPseudonym(); + } else { + name = NotificationHelper.getFormatedName(modifier); + } } else if(StringHelper.containsNonWhitespace(mInfo.getPseudonym())) { name = mInfo.getPseudonym(); } else if(mInfo.isGuest()) { diff --git a/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_de.properties index fc699e16b5f3f53bd1c0712f328f8b043dd9596e..a79ebeaee7aeaa9e1bbc876065f046a3f401b8d6 100644 --- a/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_de.properties @@ -9,6 +9,7 @@ anonymous.group.default=Default for group forum anonymous.posting=Erlaubt anonymous posting using a pseudonym anonymous.poster=Gastbeitrag guest=Gast +guest.suffix=(Gast) archive.forum=Forum archivieren archive.forum.dialog=Wollen Sie dieses Forum wirklich in Ihrem pers\u00F6nlichen Ordner im Unterordner "private/archive" archivieren? archive.forum.successfully=Das Forum wurde in Ihrem pers\u00F6nlichen Ordner im Unterordner "private/archive" archiviert. @@ -74,6 +75,7 @@ msg.title=Titel msg.title.re=Re\: msg.update=Editieren msg.upload=Datei anh\u00E4ngen +natural.sort=Verschaltet no=Nein notifications.entry=Nachricht "{0}" von {1} erstellt notifications.entry.modified=Nachricht "{0}" von {1} ver\u00E4ndert diff --git a/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_en.properties index 106b346c3db07bce35ca1ecb343f73083b73d77a..0f5f5d943e2790d71acb0c00d8faad3753708d6d 100644 --- a/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_en.properties @@ -29,6 +29,8 @@ filter.header.allUsers=All contributions filter.header.title=Search for persons filter.results.title=Contributions by forum.emtpy=No posts published in this forum. +guest=Guest +guest.suffix=(Guest) header.cannoteditmessage=Post cannot be edited header.cannotsavemessage=Post cannot be saved header.editmsg=Edit post @@ -76,6 +78,7 @@ msg.title=Title msg.title.re=Re\: msg.update=Edit msg.upload=Attach file +natural.sort=Thread no=No notifications.entry=Message "{0}" created by {1} notifications.entry.modified=Message "{0}" modified by {1} diff --git a/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_fr.properties index 2af4fad9ee700a94b997b2a6dc8f3ec67fdc886d..78d9b6685819b0360770e045c6df29a35e96ecf5 100644 --- a/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_fr.properties @@ -1,5 +1,13 @@ -#Mon Oct 22 15:53:49 CEST 2012 +#Sun Nov 29 11:12:42 CET 2015 +admin.menu.title=Forum +admin.menu.title.alt=Configuration de la fonction forum admin.title=Configuration des forums +anonymous.course.default=D\u00E9faut pour forums des cours +anonymous.default.disabled=Pseudonyme d\u00E9sactiv\u00E9 +anonymous.default.enabled=Pseudonyme activ\u00E9 +anonymous.group.default=D\u00E9faut pour les forums des groupes +anonymous.poster=Message d'un invit\u00E9 +anonymous.posting=Permettre aux utilisateurs invit\u00E9s les contributions aux forums archive.forum=Archiver le forum archive.forum.dialog=Etes-vous s\u00FBr de vouloir archiver ce forum dans votre dossier personnel sous private? archive.forum.successfully=Ce forum a \u00E9t\u00E9 archiv\u00E9 dans votre dossier personnel sous private. @@ -15,11 +23,14 @@ close.thread=Terminer discussion delete.att.ok=Les fichiers ont \u00E9t\u00E9 supprim\u00E9s. deleteok=La contribution a \u00E9t\u00E9 supprim\u00E9e. error.field.not.empty=Ce champ ne peut pas \u00EAtre vide. +error.pseudonym=Trop de similitude avec le nom d'un utilisateur pr\u00E9-existant filter=Filtre personne filter.header.allUsers=Contributions de toutes les personnes filter.header.title=Recherche de personnes filter.results.title=Contributions de forum.emtpy=Ce forum ne contient pas de contributions. +guest=Invit\u00E9 +guest.suffix=(Invit\u00E9) header.cannoteditmessage=Impossible d'\u00E9diter la contribution header.cannotsavemessage=Impossible de sauvegarder la contribution header.editmsg=Editer contribution @@ -62,11 +73,12 @@ msg.reply=R\u00E9pondre msg.save=Enregistrer msg.save.impossible=Retour vers l'aper\u00E7u msg.split=S\u00E9parer la contribution avec r\u00E9ponses -msg.sticky=Mettre priorit\u00E9s au sujet (sticky) +msg.sticky=En faire un sujet prioritaire (sticky) msg.title=Titre msg.title.re=Re\: msg.update=Editer msg.upload=Attacher fichier +natural.sort=Sujet de discussion no=Non notifications.entry=Message "{0}" \u00E9tabli par {1} notifications.entry.modified=Message "{0}" de {1} a \u00E9t\u00E9 modifi\u00E9 @@ -74,11 +86,13 @@ notifications.header=Il y a des nouveaux messages dans un des forums que vous av notifications.header.course=Forum dans le cours "{0}" notifications.header.group=Forum dans groupe "{0}" open.thread=Ouvrir discussion +pseudonym.suffix=(Pseudonyme) reallydeleteAtt=Voulez-vous vraiment supprimer ce(s) fichier(s)? reallydeleteleaf=Voulez-vous vraiment supprimer la contribution <i>{0}</i>? reallydeletenode1=Voulez-vous vraiment supprimer la contribution <i>{0}</i> avec sa r\u00E9ponse? reallydeletenodeN=Voulez-vous vraiment supprimer la contribution <i>{0}</i> avec l'ensemble de ses <b>{1}</b> r\u00E9ponses? reallysplitthread=Voulez-vous vraiment s\u00E9parer la contribution avec les r\u00E9ponses? +remove.sticky=Enlever la priorit\u00E9 du sujet (sticky) show.thread=Afficher discussion table.choose=D\u00E9placer ici table.closed=Termin\u00E9 @@ -105,6 +119,7 @@ table.user.lastname=Nom table.user.replies=R\u00E9ponses table.user.threads=Sujets table.userfriendlyname=Auteur +use.pseudonym=R\u00E9diger par use.pseudonym.label=Utiliser un pseudonyme viewswitch.flatview=tous (plat) viewswitch.marked=marqu\u00E9e diff --git a/src/main/java/org/olat/modules/fo/archiver/formatters/ForumOpenXMLFormatter.java b/src/main/java/org/olat/modules/fo/archiver/formatters/ForumOpenXMLFormatter.java index c756944a8aa04d427b94f42335c63bb42510a50c..d89aff44d36a62b68bf8f218b76a8bfbaa7b61a0 100644 --- a/src/main/java/org/olat/modules/fo/archiver/formatters/ForumOpenXMLFormatter.java +++ b/src/main/java/org/olat/modules/fo/archiver/formatters/ForumOpenXMLFormatter.java @@ -98,23 +98,30 @@ public class ForumOpenXMLFormatter extends ForumFormatter { MessageNode m = (MessageNode) node; StringBuilder creatorAndDate = new StringBuilder(); + Identity creator = m.getCreator(); if(StringHelper.containsNonWhitespace(m.getPseudonym())) { creatorAndDate.append(m.getPseudonym()) - .append(" ") - .append(translator.translate("pseudonym.suffix")); + .append(" "); + if(m.isGuest()) { + creatorAndDate.append(translator.translate("guest.suffix")); + } else { + creatorAndDate.append(translator.translate("pseudonym.suffix")); + } } else if(m.isGuest()) { creatorAndDate.append(translator.translate("guest")); - } else { - creatorAndDate.append(m.getCreator().getUser().getProperty(UserConstants.FIRSTNAME, null)); + } else if(creator != null) { + creatorAndDate.append(creator.getUser().getProperty(UserConstants.FIRSTNAME, null)); creatorAndDate.append(" "); - creatorAndDate.append(m.getCreator().getUser().getProperty(UserConstants.LASTNAME, null)); + creatorAndDate.append(creator.getUser().getProperty(UserConstants.LASTNAME, null)); + } else { + creatorAndDate.append("???"); } creatorAndDate.append(" "); creatorAndDate.append(formatter.formatDateAndTime(m.getCreationDate())); if (isTopThread) { document.appendHeading1(m.getTitle(), creatorAndDate.toString()); - this.isTopThread = false; + isTopThread = false; } else { document.appendHeading2(m.getTitle(), creatorAndDate.toString()); } @@ -122,16 +129,29 @@ public class ForumOpenXMLFormatter extends ForumFormatter { Identity modifier = m.getModifier(); if (modifier != null) { StringBuilder modSb = new StringBuilder(); - modSb.append(translator.translate("msg.modified")).append(": ") - .append(modifier.getUser().getProperty(UserConstants.FIRSTNAME, null)) - .append(" ") - .append(modifier.getUser().getProperty(UserConstants.LASTNAME, null)) - .append(" ") - .append(formatter.formatDateAndTime(m.getModifiedDate())); + if(modifier.equals(creator) && StringHelper.containsNonWhitespace(m.getPseudonym())) { + modSb.append(m.getPseudonym()) + .append(" "); + if(m.isGuest()) { + modSb.append(translator.translate("guest.suffix")); + } else { + modSb.append(translator.translate("pseudonym.suffix")); + } + } else { + modSb.append(translator.translate("msg.modified")).append(": ") + .append(modifier.getUser().getProperty(UserConstants.FIRSTNAME, null)) + .append(" ") + .append(modifier.getUser().getProperty(UserConstants.LASTNAME, null)) + .append(" ") + .append(formatter.formatDateAndTime(m.getModifiedDate())); + } document.appendSubtitle(modSb.toString()); } String body = m.getBody(); + if(body != null) { + body = body.replace("<p> ", "<p>"); + } document.appendHtmlText(body, new Spacing(180, 0)); // message attachments diff --git a/src/main/java/org/olat/modules/fo/manager/ForumManager.java b/src/main/java/org/olat/modules/fo/manager/ForumManager.java index 56ac4e6215d81dd3a3d2e4b73363f04b13f7dcf4..854a129a27d7a6d9db399667f6a9d321f2fadb08 100644 --- a/src/main/java/org/olat/modules/fo/manager/ForumManager.java +++ b/src/main/java/org/olat/modules/fo/manager/ForumManager.java @@ -170,20 +170,7 @@ public class ForumManager { */ public List<Message> getMessagesByForum(Forum forum){ if (forum == null) return new ArrayList<Message>(0); // fxdiff: while indexing it can somehow occur, that forum is null! - return getMessagesByForumID(forum.getKey(), 0, -1, null, true); - } - - /** - * - * @param forum_id - * @param start - * @param limit - * @param orderBy - * @param asc - * @return - */ - public List<Message> getMessagesByForumID(Long forum_id, int firstResult, int maxResults, Message.OrderBy orderBy, boolean asc) { - return getMessagesByForumID(forum_id, firstResult, maxResults, false, orderBy, asc); + return getMessagesByForumID(forum.getKey(), 0, -1, false, null, true); } /** @@ -199,7 +186,7 @@ public class ForumManager { private List<Message> getMessagesByForumID(Long forumKey, int firstResult, int maxResults, boolean onlyThreads, Message.OrderBy orderBy, boolean asc) { StringBuilder query = new StringBuilder(); query.append("select msg from fomessage as msg") - .append(" inner join fetch msg.creator as creator") + .append(" left join fetch msg.creator as creator") .append(" where msg.forum.key=:forumKey "); if(onlyThreads) { query.append(" and msg.parent is null"); @@ -218,6 +205,18 @@ public class ForumManager { return dbQuery.getResultList(); } + public List<Message> getMessageChildren(Message parentMessage) { + StringBuilder query = new StringBuilder(); + query.append("select msg from fomessage as msg") + .append(" inner join msg.parent as parentMsg") + .append(" where parentMsg.key=:parentKey"); + return dbInstance.getCurrentEntityManager() + .createQuery(query.toString(), Message.class) + .setParameter("parentKey", parentMessage.getKey()) + .getResultList(); + + } + private int countMessagesByForumID(Long forumKey, boolean onlyThreads) { StringBuilder query = new StringBuilder(); query.append("select count(msg) from fomessage as msg") @@ -274,13 +273,15 @@ public class ForumManager { .append(" ) as numOfMessages") .append(" , (select max(replies.lastModified) from fomessage as replies") .append(" where replies.threadtop.key=msg.key and replies.forum.key=:forumKey") - .append(" ) as lastModified") - .append(" , (select count(read.key) from foreadmessage as read, fomessage as posts") - .append(" where (posts.threadtop.key=msg.key or posts.key=msg.key) and read.message.key=posts.key and read.identity.key=:identityKey") - .append(" ) as numOfReadMessages"); + .append(" ) as lastModified"); + if(identity != null) { - sb.append(" ,(select count(mark.key) from ").append(MarkImpl.class.getName()).append(" as mark ") - .append(" where mark.creator.key=:identityKey and mark.resId=:forumKey and msg.key = cast(mark.resSubPath as long) and mark.resName='Forum'") + sb.append(" , (select count(read.key) from foreadmessage as read, fomessage as posts") + .append(" where (posts.threadtop.key=msg.key or posts.key=msg.key) and read.message.key=posts.key and read.identity.key=:identityKey") + .append(" ) as numOfReadMessages") + .append(" ,(select count(mark.key) from ").append(MarkImpl.class.getName()).append(" as mark, fomessage as mposts ") + .append(" where mark.creator.key=:identityKey and mark.resId=:forumKey and (mposts.threadtop.key=msg.key or mposts.key=msg.key)") + .append(" and mposts.key=cast(mark.resSubPath as long) and mark.resName='Forum'") .append(" ) as marks"); } @@ -290,10 +291,11 @@ public class ForumManager { TypedQuery<Object[]> objectsQuery = dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Object[].class) - .setParameter("forumKey", forum.getKey()) - .setParameter("identityKey", identity.getKey()); + .setParameter("forumKey", forum.getKey()); + if(identity != null) { + objectsQuery.setParameter("identityKey", identity.getKey()); + } - List<Object[]> objects = objectsQuery.getResultList(); List<ForumThread> threadList = new ArrayList<>(objects.size()); for(Object[] object:objects) { @@ -304,11 +306,11 @@ public class ForumManager { String creator = userManager.getUserDisplayName(msg.getCreator()); ForumThread thread = new ForumThread(msg, creator, lastModifed, numOfMessages); - Number readMessages = (Number)object[3]; - int numOfReadMessages = readMessages == null ? 0 : readMessages.intValue(); - thread.setNewMessages(numOfMessages - numOfReadMessages); - if(identity != null) { + Number readMessages = (Number)object[3]; + int numOfReadMessages = readMessages == null ? 0 : readMessages.intValue(); + thread.setNewMessages(numOfMessages - numOfReadMessages); + Number numOfMarkedMessagesLong = (Number)object[4]; int numOfMarkedMessages = numOfMarkedMessagesLong == null ? 0 : numOfMarkedMessagesLong.intValue(); thread.setMarkedMessages(numOfMarkedMessages); @@ -389,6 +391,14 @@ public class ForumManager { .getResultList(); } + /** + * Return the messages of a user written under it's own name + * (not under a pseudonym). + * + * @param forum + * @param user + * @return + */ public List<MessageLight> getLightMessagesByUser(Forum forum, IdentityRef user) { StringBuilder query = new StringBuilder(); query.append("select msg from folightmessage as msg") @@ -404,6 +414,15 @@ public class ForumManager { .getResultList(); } + /** + * Return the messages of a specified user under a specific + * pseudonym. + * + * @param forum + * @param user + * @param pseudonym + * @return + */ public List<MessageLight> getLightMessagesByUserUnderPseudo(Forum forum, IdentityRef user, String pseudonym) { StringBuilder query = new StringBuilder(); query.append("select msg from folightmessage as msg") @@ -821,31 +840,23 @@ public class ForumManager { } else { //it only make sense to split a thread if the current message is not a threadtop message. List<Message> threadList = getThread(msg.getThreadtop().getKey()); - List<Message> subthreadList = new ArrayList<Message>(); - subthreadList.add(msg); + List<Message> subthreadList = new ArrayList<>(); getSubthread(msg, threadList, subthreadList); - Iterator<Message> messageIterator = subthreadList.iterator(); - Message firstMessage = null; - if (messageIterator.hasNext()) { - firstMessage = messageIterator.next(); - firstMessage = getMessageById(firstMessage.getKey()); - firstMessage.setParent(null); - firstMessage.setThreadtop(null); - updateMessage(firstMessage, false); - newTopMessage = firstMessage; - } - while (firstMessage != null && messageIterator.hasNext()) { - Message message = messageIterator.next(); - message = getMessageById(firstMessage.getKey()); - message.setThreadtop(firstMessage); - updateMessage(message, false); + newTopMessage = getMessageById(msg.getKey()); + newTopMessage.setParent(null); + newTopMessage.setThreadtop(null); + newTopMessage = dbInstance.getCurrentEntityManager().merge(newTopMessage); + + for(Message message : subthreadList) { + message.setThreadtop(newTopMessage); + message = dbInstance.getCurrentEntityManager().merge(message); } dbInstance.commit();// before sending async event ForumChangedEvent event = new ForumChangedEvent(ForumChangedEvent.SPLIT, newTopMessage.getKey(), null, null); CoordinatorManager.getInstance().getCoordinator().getEventBus() - .fireEventToListenersOf(event, firstMessage.getForum()); + .fireEventToListenersOf(event, newTopMessage.getForum()); } return newTopMessage; } @@ -858,31 +869,34 @@ public class ForumManager { * @return the moved message */ public Message moveMessage(Message msg, Message topMsg) { - List<Message> oldThreadList = getThread(msg.getThreadtop().getKey()); - List<Message> subThreadList = new ArrayList<Message>(); - getSubthread(msg, oldThreadList, subThreadList); - // one has to set a new parent for all childs of the moved message + // one has to set a new parent for all children of the moved message // first message of sublist has to get the parent from the moved message - for (Message childMessage : subThreadList) { - childMessage = getMessageById(childMessage.getKey()); - childMessage.setParent(msg.getParent()); - updateMessage(childMessage, false); + List<Message> children = getMessageChildren(msg); + for (Message child : children) { + child.setParent(msg.getParent()); + dbInstance.getCurrentEntityManager().merge(child); } - // now move the message to the choosen thread + // now move the message to the chosen thread + Message targetThread = topMsg.getThreadtop(); + if(targetThread == null) { + targetThread = topMsg; + } + final Message oldMessage = getMessageById(msg.getKey()); Message message = createMessage(oldMessage.getForum(), oldMessage.getCreator(), oldMessage.isGuest()); + ((MessageImpl)message).setCreationDate(oldMessage.getCreationDate()); + message.setLastModified(oldMessage.getLastModified()); message.setModifier(oldMessage.getModifier()); - message.setLastModified(oldMessage.getLastModified()); // OLAT-6295 message.setTitle(oldMessage.getTitle()); message.setBody(oldMessage.getBody()); message.setPseudonym(oldMessage.getPseudonym()); - message.setThreadtop(topMsg); + message.setThreadtop(targetThread); message.setParent(topMsg); Status status = Status.getStatus(oldMessage.getStatusCode()); status.setMoved(true); message.setStatusCode(Status.getStatusCode(status)); - saveMessage(message); + message = saveMessage(message); //move marks OLATResourceable ores = OresHelper.createOLATResourceableInstance(Forum.class, msg.getForum().getKey()); diff --git a/src/main/java/org/olat/modules/fo/ui/ForumController.java b/src/main/java/org/olat/modules/fo/ui/ForumController.java index 67d9b37c25e5c197475bb61f4174ceb4f2a9d3bd..e32bc7198a3ed57c56d57977fdcee568c6db7026 100644 --- a/src/main/java/org/olat/modules/fo/ui/ForumController.java +++ b/src/main/java/org/olat/modules/fo/ui/ForumController.java @@ -49,6 +49,7 @@ import org.olat.modules.fo.Forum; import org.olat.modules.fo.ForumCallback; import org.olat.modules.fo.ForumChangedEvent; import org.olat.modules.fo.Message; +import org.olat.modules.fo.Status; import org.olat.modules.fo.manager.ForumManager; import org.olat.modules.fo.ui.events.SelectMessageEvent; import org.olat.modules.fo.ui.events.SelectUserEvent; @@ -159,18 +160,19 @@ public class ForumController extends BasicController implements GenericEventList if (message != null) { doThreadList(ureq); Message thread = message.getThreadtop() == null ? message : message.getThreadtop(); - - String subType = null; - if(entries.size() > 1) { - subType = entries.get(1).getOLATResourceable().getResourceableTypeName(); - } - - if("Marked".equalsIgnoreCase(subType)) { - doMarkedView(ureq, thread, message); - } else if("New".equalsIgnoreCase(subType)) { - doMarkedView(ureq, thread, message); - } else { - doThreadView(ureq, thread, message); + if(focallback.mayEditMessageAsModerator() || !Status.getStatus(thread.getStatusCode()).isHidden()) { + String subType = null; + if(entries.size() > 1) { + subType = entries.get(1).getOLATResourceable().getResourceableTypeName(); + } + + if("Marked".equalsIgnoreCase(subType)) { + doMarkedView(ureq, thread, message); + } else if("New".equalsIgnoreCase(subType)) { + doMarkedView(ureq, thread, message); + } else { + doThreadView(ureq, thread, message); + } } } } diff --git a/src/main/java/org/olat/modules/fo/ui/ForumMessageDataModel.java b/src/main/java/org/olat/modules/fo/ui/ForumMessageDataModel.java index f6f68b135859c13ff1c627394572936e5c23d571..7f52c6737eb5cae7994a603266c95f628fc4ff2b 100644 --- a/src/main/java/org/olat/modules/fo/ui/ForumMessageDataModel.java +++ b/src/main/java/org/olat/modules/fo/ui/ForumMessageDataModel.java @@ -51,8 +51,12 @@ public class ForumMessageDataModel extends DefaultFlexiTableDataModel<MessageLig @Override public void sort(SortKey orderBy) { if(orderBy != null) { - List<MessageLightView> views = new ForumMessageDataModelSort(orderBy, this, null).sort(); - super.setObjects(views); + if("natural".equals(orderBy.getKey())) { + System.out.println(); + } else { + List<MessageLightView> views = new ForumMessageDataModelSort(orderBy, this, null).sort(); + super.setObjects(views); + } } } diff --git a/src/main/java/org/olat/modules/fo/ui/ForumMessageListController.java b/src/main/java/org/olat/modules/fo/ui/ForumMessageListController.java index 61bbadcd4ebb4ea6cfaa371d47b2a9da6a07bc94..8db009683174983741358aacb618c224b2e84eb1 100644 --- a/src/main/java/org/olat/modules/fo/ui/ForumMessageListController.java +++ b/src/main/java/org/olat/modules/fo/ui/ForumMessageListController.java @@ -33,6 +33,8 @@ import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement; +import org.olat.core.gui.components.form.flexible.elements.FlexiTableSort; +import org.olat.core.gui.components.form.flexible.elements.FlexiTableSortOptions; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel; @@ -164,12 +166,17 @@ public class ForumMessageListController extends FormBasicController implements F @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + List<FlexiTableSort> sorts = new ArrayList<>(); + sorts.add(new FlexiTableSort(translate("natural.sort"), "natural")); + FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); if(withType) { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ForumMessageCols.type, new StatusTypeCellRenderer())); + sorts.add(new FlexiTableSort(translate(ForumMessageCols.type.i18nHeaderKey()), ForumMessageCols.type.name())); } columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ForumMessageCols.thread, "select", new StaticFlexiCellRenderer("select", new IndentCellRenderer()))); + sorts.add(new FlexiTableSort(translate(ForumMessageCols.thread.i18nHeaderKey()), ForumMessageCols.thread.name())); int colPos = USER_PROPS_OFFSET; for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) { @@ -185,15 +192,23 @@ public class ForumMessageListController extends FormBasicController implements F } else { col = new DefaultFlexiColumnModel(visible, userPropertyHandler.i18nColumnDescriptorLabelKey(), colPos, true, propName); } + + sorts.add(new FlexiTableSort(translate(userPropertyHandler.i18nColumnDescriptorLabelKey()), propName)); columnsModel.addFlexiColumnModel(col); colPos++; } columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ForumMessageCols.lastModified)); + sorts.add(new FlexiTableSort(translate(ForumMessageCols.lastModified.i18nHeaderKey()), ForumMessageCols.lastModified.name())); dataModel = new ForumMessageDataModel(columnsModel, getTranslator()); tableEl = uifactory.addTableElement(getWindowControl(), "messages", dataModel, getTranslator(), formLayout); tableEl.setRowCssDelegate(this); + + FlexiTableSortOptions sortOptions = new FlexiTableSortOptions(); + sortOptions.setFromColumnModel(false); + sortOptions.setSorts(sorts); + tableEl.setSortSettings(sortOptions); } @Override diff --git a/src/main/java/org/olat/modules/fo/ui/IndentCellRenderer.java b/src/main/java/org/olat/modules/fo/ui/IndentCellRenderer.java index 4578b8f352cc5fefa424ec0eee066d0349c75738..a4bceb094b94d49b522a560258f15c9cf691bc6c 100644 --- a/src/main/java/org/olat/modules/fo/ui/IndentCellRenderer.java +++ b/src/main/java/org/olat/modules/fo/ui/IndentCellRenderer.java @@ -43,7 +43,7 @@ public class IndentCellRenderer implements FlexiCellRenderer { FlexiTableComponent source, URLBuilder ubu, Translator translator) { SortKey[] keys = source.getFlexiTableElement().getOrderBy(); - if(keys != null && keys.length > 0 && keys[0] != null) { + if(keys != null && keys.length > 0 && keys[0] != null && !"natural".equals(keys[0].getKey())) { if(cellValue instanceof String) { target.append((String)cellValue); } diff --git a/src/main/java/org/olat/modules/fo/ui/MessageEditController.java b/src/main/java/org/olat/modules/fo/ui/MessageEditController.java index 74f853c2f7e19ddedd29fb9945684e0b1b344f38..79edbd2479750f21fc530e7a7c764793cdca6063 100644 --- a/src/main/java/org/olat/modules/fo/ui/MessageEditController.java +++ b/src/main/java/org/olat/modules/fo/ui/MessageEditController.java @@ -370,11 +370,7 @@ public class MessageEditController extends FormBasicController { // set values from form to message message.setTitle(titleEl.getValue()); String body = bodyEl.getValue(); - - String tinyBlanc = "<p> "; - if(body.startsWith(tinyBlanc)) { - body = "<p>" + body.substring(tinyBlanc.length(), body.length()); - } + body = body.replace("<p> ", "<p>"); message.setBody(body.trim()); if(usePseudonymEl != null && (usePseudonymEl.isAtLeastSelected(1) || guestOnly)) { diff --git a/src/main/java/org/olat/modules/fo/ui/MessageListController.java b/src/main/java/org/olat/modules/fo/ui/MessageListController.java index 31d7b4e9e06af2370db6404d8738b8649b8e7225..31f377a30d8e9fea658734c787a04dafbedf8a77 100644 --- a/src/main/java/org/olat/modules/fo/ui/MessageListController.java +++ b/src/main/java/org/olat/modules/fo/ui/MessageListController.java @@ -377,7 +377,7 @@ public class MessageListController extends BasicController implements GenericEve MessageView view = new MessageView(message, userPropertyHandlers, getLocale()); view.setNumOfChildren(0); - addMessageToCurrentMessagesAndVC(ureq, message, view, backupViews.size(), marks, stats, artefactStats, rms); + addMessageToCurrentMessagesAndVC(ureq, message, view, marks, stats, artefactStats, rms); return view; } @@ -432,10 +432,9 @@ public class MessageListController extends BasicController implements GenericEve } } - int msgNum = 0; //append ui things for (MessageLight msg: messages) { - addMessageToCurrentMessagesAndVC(ureq, msg, keyToViews.get(msg.getKey()), msgNum++, marks, stats, artefactStats, rms); + addMessageToCurrentMessagesAndVC(ureq, msg, keyToViews.get(msg.getKey()), marks, stats, artefactStats, rms); } mainVC.contextPut("messages", views); @@ -473,7 +472,7 @@ public class MessageListController extends BasicController implements GenericEve } } - private void addMessageToCurrentMessagesAndVC(UserRequest ureq, MessageLight m, MessageView messageView, int msgCount, + private void addMessageToCurrentMessagesAndVC(UserRequest ureq, MessageLight m, MessageView messageView, Map<String,Mark> marks, Map<String,MarkResourceStat> stats, Map<String,Long> artefactStats, Set<Long> readSet) { @@ -491,17 +490,21 @@ public class MessageListController extends BasicController implements GenericEve // add some data now messageView.setFormattedCreationDate(formatter.formatDateAndTime(m.getCreationDate())); messageView.setFormattedLastModified(formatter.formatDateAndTime(m.getLastModified())); - + + Identity creator = m.getCreator(); Identity modifier = m.getModifier(); if (modifier != null) { messageView.setModified(true); - messageView.setModifierFirstName(modifier.getUser().getProperty(UserConstants.FIRSTNAME, getLocale())); - messageView.setModifierLastName(modifier.getUser().getProperty(UserConstants.LASTNAME, getLocale())); + if(modifier.equals(creator) && StringHelper.containsNonWhitespace(m.getPseudonym())) { + messageView.setModifierPseudonym(m.getPseudonym()); + } else { + messageView.setModifierFirstName(modifier.getUser().getProperty(UserConstants.FIRSTNAME, getLocale())); + messageView.setModifierLastName(modifier.getUser().getProperty(UserConstants.LASTNAME, getLocale())); + } } else { messageView.setModified(false); } - Identity creator = m.getCreator(); boolean userIsMsgCreator = false; //keeps the first 15 chars if(creator != null) { @@ -536,52 +539,51 @@ public class MessageListController extends BasicController implements GenericEve } messageView.setClosed(isThreadClosed); - if(!guestOnly && !m.isGuest() && !StringHelper.containsNonWhitespace(m.getPseudonym())) { + if(!guestOnly && !m.isGuest() && creator != null && !StringHelper.containsNonWhitespace(m.getPseudonym())) { // add portrait to map for later disposal and key for rendering in velocity - DisplayPortraitController portrait = new DisplayPortraitController(ureq, getWindowControl(), m.getCreator(), true, true, false, true); + DisplayPortraitController portrait = new DisplayPortraitController(ureq, getWindowControl(), creator, true, true, false, true); messageView.setPortrait(portrait); mainVC.put("portrait_".concat(keyString), portrait.getInitialComponent()); // Add link with username that is clickable String creatorFullName = StringHelper.escapeHtml(UserManager.getInstance().getUserDisplayName(creator)); - Link visitingCardLink = LinkFactory.createCustomLink("vc_"+msgCount, "vc_"+msgCount, creatorFullName, Link.LINK_CUSTOM_CSS + Link.NONTRANSLATED, mainVC, this); + Link visitingCardLink = LinkFactory.createCustomLink("vc_".concat(keyString), "vc", creatorFullName, Link.LINK_CUSTOM_CSS + Link.NONTRANSLATED, mainVC, this); visitingCardLink.setUserObject(messageView); - LinkPopupSettings settings = new LinkPopupSettings(800, 600, "_blank"); visitingCardLink.setPopup(settings); } if(!isThreadClosed) { if((numOfChildren == 0 && userIsMsgCreator) || foCallback.mayDeleteMessageAsModerator()) { - Link deleteLink = LinkFactory.createCustomLink("dl_"+msgCount, "dl_"+msgCount, "msg.delete", Link.BUTTON_SMALL, mainVC, this); + Link deleteLink = LinkFactory.createCustomLink("dl_".concat(keyString), "dl", "msg.delete", Link.BUTTON_SMALL, mainVC, this); deleteLink.setIconLeftCSS("o_icon o_icon-fw o_icon_delete_item"); deleteLink.setUserObject(messageView); } if((numOfChildren == 0 && userIsMsgCreator) || foCallback.mayEditMessageAsModerator()) { - Link editLink = LinkFactory.createCustomLink("ed_"+msgCount, "ed_"+msgCount, "msg.update", Link.BUTTON_SMALL, mainVC, this); + Link editLink = LinkFactory.createCustomLink("ed_".concat(keyString), "ed", "msg.update", Link.BUTTON_SMALL, mainVC, this); editLink.setIconLeftCSS("o_icon o_icon-fw o_icon_edit"); editLink.setUserObject(messageView); } if(foCallback.mayReplyMessage()) { - Link quoteLink = LinkFactory.createCustomLink("qt_"+msgCount, "qt_"+msgCount, "msg.quote", Link.BUTTON_SMALL, mainVC, this); + Link quoteLink = LinkFactory.createCustomLink("qt_".concat(keyString), "qt", "msg.quote", Link.BUTTON_SMALL, mainVC, this); quoteLink.setElementCssClass("o_sel_forum_reply_quoted"); quoteLink.setIconLeftCSS("o_icon o_icon-fw o_icon_reply_with_quote"); quoteLink.setUserObject(messageView); - Link replyLink = LinkFactory.createCustomLink("rp_"+msgCount, "rp_"+msgCount, "msg.reply", Link.BUTTON_SMALL, mainVC, this); + Link replyLink = LinkFactory.createCustomLink("rp_".concat(keyString), "rp", "msg.reply", Link.BUTTON_SMALL, mainVC, this); replyLink.setElementCssClass("o_sel_forum_reply"); replyLink.setIconLeftCSS("o_icon o_icon-fw o_icon_reply"); replyLink.setUserObject(messageView); } if(foCallback.mayEditMessageAsModerator() && !threadTop) { - Link splitLink = LinkFactory.createCustomLink("split_"+msgCount, "split_"+msgCount, "msg.split", Link.LINK, mainVC, this); + Link splitLink = LinkFactory.createCustomLink("split_".concat(keyString), "split", "msg.split", Link.LINK, mainVC, this); splitLink.setIconLeftCSS("o_icon o_icon-fw o_icon_split"); splitLink.setUserObject(messageView); - Link moveLink = LinkFactory.createCustomLink("move_"+msgCount, "move_"+msgCount, "msg.move", Link.LINK, mainVC, this); + Link moveLink = LinkFactory.createCustomLink("move_".concat(keyString), "move", "msg.move", Link.LINK, mainVC, this); moveLink.setIconLeftCSS("o_icon o_icon-fw o_icon_move"); moveLink.setUserObject(messageView); } @@ -594,7 +596,7 @@ public class MessageListController extends BasicController implements GenericEve getWindowControl().getBusinessControl().getAsString() + "[Message:" + m.getKey() + "]" : currentMark.getBusinessPath(); Controller markCtrl = markingService.getMarkController(ureq, getWindowControl(), currentMark, stat, forumOres, keyString, businessPath); - mainVC.put("mark_" + msgCount, markCtrl.getInitialComponent()); + mainVC.put("mark_".concat(keyString), markCtrl.getInitialComponent()); } if(userIsMsgCreator && !StringHelper.containsNonWhitespace(m.getPseudonym())) { @@ -658,22 +660,22 @@ public class MessageListController extends BasicController implements GenericEve String command = link.getCommand(); Object uobject = link.getUserObject(); - if (command.startsWith("qt_")) { + if (command.startsWith("qt")) { doReply(ureq, (MessageView)uobject, true); - } else if (command.startsWith("rp_")) { + } else if (command.startsWith("rp")) { doReply(ureq, (MessageView)uobject, false); - } else if (command.startsWith("dl_")) { + } else if (command.startsWith("dl")) { doConfirmDeleteMessage(ureq, (MessageView)uobject); - } else if (command.startsWith("ed_")) { + } else if (command.startsWith("ed")) { doEditMessage(ureq, (MessageView)uobject); - } else if (command.startsWith("split_")) { + } else if (command.startsWith("split")) { doConfirmSplit(ureq, (MessageView)uobject); - } else if (command.startsWith("move_")) { + } else if (command.startsWith("move")) { doMoveMessage(ureq, (MessageView)uobject); } } else if(mainVC == source) { String cmd = event.getCommand(); - if (cmd.startsWith("attachment_")) { + if (cmd.startsWith("attachment")) { doDeliverAttachment(ureq, cmd); } } @@ -1148,6 +1150,7 @@ public class MessageListController extends BasicController implements GenericEve Message parentMessage = forumManager.getMessageById(parentMessageKey); message = forumManager.moveMessage(message, parentMessage); markRead(message); + DBFactory.getInstance().commit();//commit before sending event ThreadLocalUserActivityLogger.log(ForumLoggingAction.FORUM_MESSAGE_MOVE, getClass(), LoggingResourceable.wrap(message)); Long threadKey = parentMessage.getThreadtop() == null ? parentMessage.getKey() : parentMessage.getThreadtop().getKey(); diff --git a/src/main/java/org/olat/modules/fo/ui/MessageView.java b/src/main/java/org/olat/modules/fo/ui/MessageView.java index 1c2ee21dcc7f220fb858ac7ff2963319a7191a15..55d307d386996a8aac7135b65498f98d50f8e9c6 100644 --- a/src/main/java/org/olat/modules/fo/ui/MessageView.java +++ b/src/main/java/org/olat/modules/fo/ui/MessageView.java @@ -45,6 +45,7 @@ public class MessageView extends MessageLightView { private boolean modified; private String modifierFirstName; private String modifierLastName; + private String modifierPseudonym; private String creatorFirstname; private String creatorLastname; @@ -152,6 +153,14 @@ public class MessageView extends MessageLightView { this.modifierLastName = modifierLastName; } + public String getModifierPseudonym() { + return modifierPseudonym; + } + + public void setModifierPseudonym(String modifierPseudonym) { + this.modifierPseudonym = modifierPseudonym; + } + public boolean isAuthor() { return author; } diff --git a/src/main/java/org/olat/modules/fo/ui/StatusTypeCellRenderer.java b/src/main/java/org/olat/modules/fo/ui/StatusTypeCellRenderer.java index a64d6e8f1c056d1822e9b5b9c52e9f17bd9d51c4..972a40f153714038b1e831f03b870137524033b4 100644 --- a/src/main/java/org/olat/modules/fo/ui/StatusTypeCellRenderer.java +++ b/src/main/java/org/olat/modules/fo/ui/StatusTypeCellRenderer.java @@ -43,17 +43,18 @@ public class StatusTypeCellRenderer implements FlexiCellRenderer { int status = ((Number)cellValue).intValue(); Status messageStatus = Status.getStatus(status); - boolean isSticky = messageStatus.isSticky(); - boolean isClosed = messageStatus.isClosed(); + boolean isSticky = messageStatus.isSticky(); + boolean isClosed = messageStatus.isClosed(); target.append("<i class='o_icon o_forum_"); - if(isSticky && isClosed) { target.append("status_sticky_closed"); - } else if (isSticky) { + } else if(isSticky) { target.append("status_sticky"); - } else if (isClosed) { + } else if(isClosed) { target.append("status_closed"); + } else if(messageStatus.isHidden()) { + target.append("status_hidden"); } else { target.append("status_thread"); } diff --git a/src/main/java/org/olat/modules/fo/ui/ThreadListController.java b/src/main/java/org/olat/modules/fo/ui/ThreadListController.java index 2c8b95211ba71ce73187769ef11ed87e479dffa1..1d0575a6a57228ddb6424ac4271e921518bf0de0 100644 --- a/src/main/java/org/olat/modules/fo/ui/ThreadListController.java +++ b/src/main/java/org/olat/modules/fo/ui/ThreadListController.java @@ -19,6 +19,7 @@ */ package org.olat.modules.fo.ui; +import java.util.Iterator; import java.util.List; import org.olat.basesecurity.BaseSecurityModule; @@ -52,6 +53,7 @@ import org.olat.modules.fo.Forum; import org.olat.modules.fo.ForumCallback; import org.olat.modules.fo.Message; import org.olat.modules.fo.MessageRef; +import org.olat.modules.fo.Status; import org.olat.modules.fo.archiver.formatters.ForumDownloadResource; import org.olat.modules.fo.manager.ForumManager; import org.olat.modules.fo.model.ForumThread; @@ -153,6 +155,14 @@ public class ThreadListController extends FormBasicController { public void loadModel() { Identity identity = guestOnly ? null : getIdentity(); List<ForumThread> threads = forumManager.getForumThreads(forum, identity); + if(!foCallback.mayEditMessageAsModerator()) { + for(Iterator<ForumThread> threadIt=threads.iterator(); threadIt.hasNext(); ) { + if(Status.getStatus(threadIt.next().getStatusCode()).isHidden()) { + threadIt.remove(); + } + } + } + threadTableModel.setObjects(threads); threadTableModel.sort(new SortKey(ThreadListCols.thread.name(), true)); threadTable.reloadData(); diff --git a/src/main/java/org/olat/modules/fo/ui/_content/threadview.html b/src/main/java/org/olat/modules/fo/ui/_content/threadview.html index 8a2a270fe74a0791f5ccfc215a2dfc2b57449a8a..4e3246fb2f519b66b8b8cb993184a2db4d96e380 100644 --- a/src/main/java/org/olat/modules/fo/ui/_content/threadview.html +++ b/src/main/java/org/olat/modules/fo/ui/_content/threadview.html @@ -65,14 +65,13 @@ #end #foreach ($message in $messages) - #set( $count = $velocityCount - 1) <div #if($threadMode) style="margin-left: ${message.depth}em" #end class="o_forum_message o_block_large_bottom #if($message.newMessage) o_forum_message_new #end #if($message.key == $goToMessageId) o_forum_message_highlight #end" id="o_forum_message_${message.key}"> <div class="o_forum_message_header clearfix"> #if($r.available("eportfolio_${message.key}")) <div class="o_ep_collect">$r.render("eportfolio_${message.key}")</div> #end - #if($r.available("mark_${count}")) - <div class="o_mark">$r.render("mark_${count}")</div> + #if($r.available("mark_${message.key}")) + <div class="o_mark">$r.render("mark_${message.key}")</div> #end #if(!$guestOnly) #if($message.guest || ($message.pseudonym && !${message.pseudonym.isEmpty()})) @@ -93,8 +92,8 @@ $r.escapeHtml($message.pseudonym) #elseif($message.guest) $r.translate("anonymous.poster") - #elseif($r.available("vc_${count}")) - $r.render("vc_${count}") + #elseif($r.available("vc_${message.key}")) + $r.render("vc_${message.key}") #else $r.escapeHtml($message.creatorFirstname) $r.escapeHtml($message.creatorLastname) #end @@ -106,7 +105,13 @@ #if($message.modified || $message.moved) <div class="o_modified"> #if($message.modified) - $r.translate("msg.modified"): $r.escapeHtml($message.modifierFirstName) $r.escapeHtml($message.modifierLastName) $message.formattedLastModified + $r.translate("msg.modified"): + #if($message.modifierPseudonym && !${message.modifierPseudonym.isEmpty()}) + $r.escapeHtml($message.modifierPseudonym) + #else + $r.escapeHtml($message.modifierFirstName) $r.escapeHtml($message.modifierLastName) + #end + $message.formattedLastModified #end #if($message.moved) $r.translate("msg.moved") @@ -120,34 +125,34 @@ </div> <div class="o_forum_message_actions o_button_group"> - #if($r.available("open_in_thread_${count}")) - $r.render("open_in_thread_${count}") + #if($r.available("open_in_thread_${message.key}")) + $r.render("open_in_thread_${message.key}") #end - #if ($r.available("dl_${count}") || $r.available("ed_${count}")) + #if ($r.available("dl_${message.key}") || $r.available("ed_${message.key}")) <div class="btn-group"> - #if($r.available("dl_${count}")) - $r.render("dl_${count}") + #if($r.available("dl_${message.key}")) + $r.render("dl_${message.key}") #end - #if ($r.available("ed_${count}")) - $r.render("ed_${count}") + #if ($r.available("ed_${message.key}")) + $r.render("ed_${message.key}") #end </div> #end - #if ($r.available("rp_${count}")) - <div class="btn-group">$r.render("qt_${count}") $r.render("rp_${count}")</div> + #if ($r.available("rp_${message.key}")) + <div class="btn-group">$r.render("qt_${message.key}") $r.render("rp_${message.key}")</div> #end - #if($r.available("split_${count}")) + #if($r.available("split_${message.key}")) <div class="btn-group"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> <i class="o_icon o_icon-fw o_icon_actions"></i> <span class="caret"></span> </button> <ul class="dropdown-menu dropdown-menu-right"> - <li>$r.render("split_${count}")</li> - <li>$r.render("move_${count}")</li> + <li>$r.render("split_${message.key}")</li> + <li>$r.render("move_${message.key}")</li> </ul> </div> #end diff --git a/src/main/java/org/olat/repository/ui/author/AuthorListController.java b/src/main/java/org/olat/repository/ui/author/AuthorListController.java index 0410c3efdc20f08cf2089e5d02b088138ab0150d..43f3afe425478ed40cad1701389358430ba07d5a 100644 --- a/src/main/java/org/olat/repository/ui/author/AuthorListController.java +++ b/src/main/java/org/olat/repository/ui/author/AuthorListController.java @@ -557,13 +557,19 @@ public class AuthorListController extends FormBasicController implements Activat removeAsListenerAndDispose(toolsCtrl); removeAsListenerAndDispose(toolsCalloutCtrl); - toolsCtrl = new ToolsController(ureq, getWindowControl(), row); - listenTo(toolsCtrl); - - toolsCalloutCtrl = new CloseableCalloutWindowController(ureq, getWindowControl(), - toolsCtrl.getInitialComponent(), link.getFormDispatchId(), "", true, ""); - listenTo(toolsCalloutCtrl); - toolsCalloutCtrl.activate(); + RepositoryEntry entry = repositoryService.loadByKey(row.getKey()); + if(entry == null) { + tableEl.reloadData(); + showWarning("repositoryentry.not.existing"); + } else { + toolsCtrl = new ToolsController(ureq, getWindowControl(), row, entry); + listenTo(toolsCtrl); + + toolsCalloutCtrl = new CloseableCalloutWindowController(ureq, getWindowControl(), + toolsCtrl.getInitialComponent(), link.getFormDispatchId(), "", true, ""); + listenTo(toolsCalloutCtrl); + toolsCalloutCtrl.activate(); + } } private void doImport(UserRequest ureq) { @@ -916,19 +922,18 @@ public class AuthorListController extends FormBasicController implements Activat private class ToolsController extends BasicController { private final AuthoringEntryRow row; - private final RepositoryEntry entry; + private final VelocityContainer mainVC; private boolean isOwner; private boolean isOlatAdmin; private boolean isAuthor; - public ToolsController(UserRequest ureq, WindowControl wControl, AuthoringEntryRow row) { + public ToolsController(UserRequest ureq, WindowControl wControl, AuthoringEntryRow row, RepositoryEntry entry) { super(ureq, wControl); setTranslator(AuthorListController.this.getTranslator()); this.row = row; - this.entry = repositoryService.loadByKey(row.getKey()); - + Identity identity = getIdentity(); Roles roles = ureq.getUserSession().getRoles(); isOlatAdmin = roles.isOLATAdmin(); diff --git a/src/main/java/org/olat/shibboleth/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/shibboleth/_i18n/LocalStrings_fr.properties index 97a6907acda80945c3400e2ff36f595a9892aedc..5e0cb75ccb1e4385d7bdce0e564461de6e9124d3 100644 --- a/src/main/java/org/olat/shibboleth/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/shibboleth/_i18n/LocalStrings_fr.properties @@ -1,8 +1,14 @@ -#Sun Nov 08 13:11:57 CET 2015 +#Sun Nov 29 17:24:38 CET 2015 +admin.ac.attribute=Activ\u00E9 le contr\u00F4le d'acc\u00E8s par attribut admin.ac.attribute.1=Attribut Shibboleth 1 admin.ac.attribute.2=Attribut Shibboleth 2 +admin.ac.url=Lien direct pour l'acc\u00E8s SSO +admin.ac.value.1=Valeur permise pour l'attribut 1 +admin.ac.value.2=Valeur permise pour l'attribut 2 +admin.description=La configuration de base de Shibboleth doit \u00EAtre faite dans le fichier de configuration OpenOLAT. En utilisant le formulaire ci-dessous, vous pouvez activer l'acc\u00E8s des utilisateurs bas\u00E9 sur leurs attributs Shibboleth. Un maximum de deux attributs avec chacun leurs propres valeurs permises peut \u00EAtre configur\u00E9. Une personne est consid\u00E9r\u00E9e comme autoris\u00E9e si 1) la personne peut \u00EAtre authentifier avec succ\u00E8s par l'IDP et 2) l'une des valeurs des deux attributs sp\u00E9cifi\u00E9s dans la liste correspond \u00E0 celles de l'utilisateur. admin.menu.shibboleth=Shibboleth admin.menu.shibboleth.desc=Configuration du module Shibboleth +admin.title=Autorisation Shibboleth authentication.provider.description=\u00CAtes-vous membre d'une institution qui utilise Shibboleth pour l'authentification? authentication.provider.linkText=Se connecter avec un compte Shibboleth eduPersonAffiliation=Affiliation @@ -18,6 +24,7 @@ employeeNumber=Num\u00E9ro personnel error.insufficieant.attributes=Attributs Shibboleth n\u00E9cessaires\:Shib-SwissEP-UniqueID, Shib-InetOrgPerson-givenName, Shib-Person-surname, Shib-InetOrgPerson-mail, Shib-SwissEP-HomeOrganization error.shibboleth.generic=Erreur Shibboleth. Reconnectez-vous, s.v.p.\! error.shibboleth.head=OLAT - Online Learning And Training - Error +error.shibboleth.not.authorized=Vous n'\u00EAtes pas autoris\u00E9 \u00E0 vous connecter \u00E0 OpenOLAT. error.unqueid.notfound=Avez-vous un droit d'acc\u00E8s \u00E0 OLAT? Si oui, veuillez r\u00E9essayer de vous connecter, s.v.p.. givenName=Nom de famille idp.support.email=Veuillez vous adresser \u00E0 votre soutien IdP\: diff --git a/src/test/java/org/olat/modules/fo/ForumManagerTest.java b/src/test/java/org/olat/modules/fo/ForumManagerTest.java index 302935dc930c88dfa9700757f10a09f4f4eeb0d7..1d9a09babb2ffa041d87b84d1ebf27eac43ad17c 100644 --- a/src/test/java/org/olat/modules/fo/ForumManagerTest.java +++ b/src/test/java/org/olat/modules/fo/ForumManagerTest.java @@ -30,6 +30,7 @@ import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.Set; import java.util.UUID; import org.junit.Assert; @@ -40,6 +41,7 @@ import org.olat.core.id.Identity; import org.olat.modules.fo.manager.ForumManager; import org.olat.modules.fo.model.ForumThread; import org.olat.modules.fo.model.ForumUserStatistics; +import org.olat.modules.fo.ui.MessagePeekview; import org.olat.test.JunitTestHelper; import org.olat.test.OlatTestCase; import org.olat.user.UserManager; @@ -442,6 +444,182 @@ public class ForumManagerTest extends OlatTestCase { Assert.assertEquals(thread1.getKey(), messageUnderPseudo.getThreadtop().getKey()); } + @Test + public void getMessageById() { + Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-1"); + Forum forum = forumManager.addAForum(); + dbInstance.commit(); + + Message message = forumManager.createMessage(forum, id, false); + message.setTitle("Get message by id"); + message.setBody("Get message by id"); + forumManager.addTopMessage(message); + dbInstance.commit(); + + //load the message by id + Message loadedMessage = forumManager.getMessageById(message.getKey()); + dbInstance.commitAndCloseSession(); + + Assert.assertNotNull(loadedMessage); + Assert.assertEquals(message.getKey(), loadedMessage.getKey()); + Assert.assertEquals(message.getTitle(), loadedMessage.getTitle()); + Assert.assertEquals(message.getBody(), loadedMessage.getBody()); + Assert.assertNotNull(loadedMessage.getCreator()); + Assert.assertEquals(id, loadedMessage.getCreator()); + Assert.assertFalse(loadedMessage.isGuest()); + Assert.assertNull(loadedMessage.getThreadtop()); + } + + @Test + public void getPeekviewMessages() { + Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-1"); + Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-2"); + Forum forum = forumManager.addAForum(); + dbInstance.commit(); + + Message thread1 = forumManager.createMessage(forum, id1, false); + thread1.setTitle("Get peekview messages"); + thread1.setBody("Get peekview messages"); + forumManager.addTopMessage(thread1); + dbInstance.commit(); + + Message reply = forumManager.createMessage(forum, id2, false); + reply.setTitle("Re: Get peekview messages"); + reply.setBody("Get peekview messages"); + forumManager.replyToMessage(reply, thread1); + dbInstance.commitAndCloseSession(); + + Message replyPseudo = forumManager.createMessage(forum, id2, false); + replyPseudo.setTitle("Re: Get peekview messages with pseudo"); + replyPseudo.setBody("Get peekview messages and other usefull stuff we need"); + String pseudo = "Id pseudo " + UUID.randomUUID(); + replyPseudo.setPseudonym(pseudo); + forumManager.replyToMessage(replyPseudo, thread1); + dbInstance.commitAndCloseSession(); + + //load the peekview + List<MessagePeekview> peekViews = forumManager.getPeekviewMessages(forum, 2); + Assert.assertNotNull(peekViews); + Assert.assertEquals(2, peekViews.size()); + + int found = 0; + for(MessagePeekview peekView:peekViews) { + if(peekView.getKey().equals(thread1.getKey()) + || peekView.getKey().equals(reply.getKey()) + || peekView.getKey().equals(replyPseudo.getKey())) { + found++; + } + } + Assert.assertEquals(2, found); + } + + @Test + public void getPseudonym() { + Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-1"); + Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-2"); + Forum forum = forumManager.addAForum(); + dbInstance.commit(); + + Message thread1 = forumManager.createMessage(forum, id1, false); + thread1.setTitle("Get pseudonym"); + thread1.setBody("Get pseudonym"); + forumManager.addTopMessage(thread1); + dbInstance.commit(); + + Message replyPseudo = forumManager.createMessage(forum, id2, false); + replyPseudo.setTitle("Re: Get pseudonym"); + replyPseudo.setBody("Get pseudonym in forum and other usefull stuff we need"); + String pseudo = "Id pseudo " + UUID.randomUUID(); + replyPseudo.setPseudonym(pseudo); + forumManager.replyToMessage(replyPseudo, thread1); + dbInstance.commitAndCloseSession(); + + // get pseudonym of id 2 + String alias2 = forumManager.getPseudonym(forum, id2); + Assert.assertEquals(pseudo, alias2); + + // get pseudonym of id 1 + String alias1 = forumManager.getPseudonym(forum, id1); + Assert.assertNull(alias1); + } + + @Test + public void readMessages() { + Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-1"); + Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-2"); + Forum forum = forumManager.addAForum(); + dbInstance.commit(); + + Message thread1 = forumManager.createMessage(forum, id1, false); + thread1.setTitle("Read messages workflow"); + thread1.setBody("Read messages workflow"); + forumManager.addTopMessage(thread1); + dbInstance.commit(); + + Message replyPseudo = forumManager.createMessage(forum, id1, false); + replyPseudo.setTitle("Re: Read messages workflow"); + replyPseudo.setBody("Read messages workflow and other usefull stuff we need"); + String pseudo = "Id pseudo " + UUID.randomUUID(); + replyPseudo.setPseudonym(pseudo); + forumManager.replyToMessage(replyPseudo, thread1); + dbInstance.commitAndCloseSession(); + + Message reply = forumManager.createMessage(forum, id2, false); + reply.setTitle("Re: Read messages workflow"); + reply.setBody("Read messages workflow and other usefull stuff we need"); + forumManager.replyToMessage(reply, thread1); + dbInstance.commitAndCloseSession(); + + //mark thread1 as read + forumManager.markAsRead(id1, forum, thread1); + dbInstance.commitAndCloseSession(); + + //load read set and check for id1 + Set<Long> readSet = forumManager.getReadSet(id1, forum); + dbInstance.commitAndCloseSession(); + Assert.assertNotNull(readSet); + Assert.assertEquals(1, readSet.size()); + Assert.assertTrue(readSet.contains(thread1.getKey())); + + //mark thread1 as read + forumManager.markAsRead(id2, forum, reply); + forumManager.markAsRead(id2, forum, replyPseudo); + dbInstance.commitAndCloseSession(); + + //load read set and check for id2 + Set<Long> readSet2 = forumManager.getReadSet(id2, forum); + dbInstance.commitAndCloseSession(); + Assert.assertNotNull(readSet2); + Assert.assertEquals(2, readSet2.size()); + Assert.assertTrue(readSet2.contains(reply.getKey())); + Assert.assertTrue(readSet2.contains(replyPseudo.getKey())); + } + + @Test + public void updateMessage() { + Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-1"); + Forum fo = forumManager.addAForum(); + dbInstance.commit(); + + Message topMessage = forumManager.createMessage(fo, id, false); + topMessage.setTitle("Message counter"); + topMessage.setBody("Message counter"); + forumManager.addTopMessage(topMessage); + dbInstance.commit(); + + //update message + topMessage.setBody("Message counter and other stuff"); + Message updatedMessage = forumManager.updateMessage(topMessage, true); + Assert.assertNotNull(updatedMessage); + Assert.assertEquals(topMessage.getKey(), updatedMessage.getKey()); + Assert.assertEquals("Message counter", updatedMessage.getTitle()); + Assert.assertEquals("Message counter and other stuff", updatedMessage.getBody()); + Assert.assertNotNull(updatedMessage.getNumOfCharacters()); + Assert.assertEquals(27, updatedMessage.getNumOfCharacters().intValue()); + Assert.assertNotNull(updatedMessage.getNumOfWords()); + Assert.assertEquals(5, updatedMessage.getNumOfWords().intValue()); + } + @Test public void countMessagesByForumID() { Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-1"); @@ -533,6 +711,261 @@ public class ForumManagerTest extends OlatTestCase { Assert.assertEquals(2, olderLastMessages.size()); } + @Test + public void moveMessage() { + Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-1"); + Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-2"); + Identity guest3 = securityManager.getAndUpdateAnonymousUserForLanguage(Locale.ENGLISH); + Forum fo = forumManager.addAForum(); + dbInstance.commit(); + + // thread + // -> message + // -> -> message to move + // -> -> -> message child 1 + // -> -> -> -> message child 1.1 + // -> -> -> message child 2 + // -> -> message staying + + Message topMessage = forumManager.createMessage(fo, id1, false); + topMessage.setTitle("Thread move message"); + topMessage.setBody("Thread move message"); + forumManager.addTopMessage(topMessage); + dbInstance.commit(); + + Message message = forumManager.createMessage(fo, id2, false); + message.setTitle("Re: Thread move message"); + message.setBody("Thread move message"); + forumManager.replyToMessage(message, topMessage); + dbInstance.commit(); + + Message messageToMove = forumManager.createMessage(fo, id2, false); + messageToMove.setTitle("Message to move"); + messageToMove.setBody("Thread move message"); + forumManager.replyToMessage(messageToMove, message); + dbInstance.commit(); + + Message messageToMove_1 = forumManager.createMessage(fo, id2, false); + messageToMove_1.setTitle("Re: Message to move 1"); + messageToMove_1.setBody("Thread move message"); + forumManager.replyToMessage(messageToMove_1, messageToMove); + dbInstance.commit(); + + Message messageToMove_1_1 = forumManager.createMessage(fo, guest3, true); + messageToMove_1_1.setTitle("Re: Message to move 1"); + messageToMove_1_1.setBody("Thread move message"); + forumManager.replyToMessage(messageToMove_1_1, messageToMove_1); + dbInstance.commit(); + + Message messageToMove_2 = forumManager.createMessage(fo, id2, false); + messageToMove_2.setTitle("Re: Message to move 2"); + messageToMove_2.setBody("Thread move message"); + forumManager.replyToMessage(messageToMove_2, messageToMove); + dbInstance.commit(); + + Message messageToStay = forumManager.createMessage(fo, id2, false); + messageToStay.setTitle("Message to stay"); + messageToStay.setBody("Thread move message"); + forumManager.replyToMessage(messageToStay, message); + dbInstance.commit(); + + Message targetThread = forumManager.createMessage(fo, id2, false); + targetThread.setTitle("Target thread"); + targetThread.setBody("Target thread"); + forumManager.addTopMessage(targetThread); + dbInstance.commit(); + + Message targetMessage = forumManager.createMessage(fo, id2, false); + targetMessage.setTitle("Message to stay"); + targetMessage.setBody("Thread move message"); + forumManager.replyToMessage(targetMessage, targetThread); + dbInstance.commit(); + + //move the message + Message movedMessage = forumManager.moveMessage(messageToMove, targetMessage); + dbInstance.commitAndCloseSession(); + + //check target thread + List<Message> targetMessages = forumManager.getThread(targetThread.getKey()); + Assert.assertEquals(3, targetMessages.size()); + Assert.assertTrue(targetMessages.contains(targetThread)); + Assert.assertTrue(targetMessages.contains(targetMessage)); + Assert.assertTrue(targetMessages.contains(movedMessage)); + + //check thread and parent of the target thread + Message reloadedTargetThread = forumManager.getMessageById(targetThread.getKey()); + Assert.assertNull(reloadedTargetThread.getThreadtop()); + Assert.assertNull(reloadedTargetThread.getParent()); + + Message reloadedTargetMessage = forumManager.getMessageById(targetMessage.getKey()); + Assert.assertEquals(targetThread, reloadedTargetMessage.getThreadtop()); + Assert.assertEquals(targetThread, reloadedTargetMessage.getParent()); + + Message reloadedMovedMessage = forumManager.getMessageById(movedMessage.getKey()); + Assert.assertEquals(targetThread, reloadedMovedMessage.getThreadtop()); + Assert.assertEquals(targetMessage, reloadedMovedMessage.getParent()); + + //check original thread + List<Message> originMessages = forumManager.getThread(topMessage.getKey()); + Assert.assertEquals(6, originMessages.size()); + Assert.assertTrue(originMessages.contains(topMessage)); + Assert.assertTrue(originMessages.contains(message)); + Assert.assertTrue(originMessages.contains(messageToStay)); + Assert.assertTrue(originMessages.contains(messageToMove_1)); + Assert.assertTrue(originMessages.contains(messageToMove_1_1)); + Assert.assertTrue(originMessages.contains(messageToMove_2)); + Assert.assertFalse(originMessages.contains(movedMessage)); + Assert.assertFalse(originMessages.contains(messageToMove)); + + // thread + // -> message + // -> -> message child 1 + // -> -> -> message child 1.1 + // -> -> message child 2 + // -> -> message staying + + //check thread and parent of the target thread + Message reloadedTopMessage = forumManager.getMessageById(topMessage.getKey()); + Assert.assertNull(reloadedTopMessage.getThreadtop()); + Assert.assertNull(reloadedTopMessage.getParent()); + + Message reloadedMessage = forumManager.getMessageById(message.getKey()); + Assert.assertEquals(topMessage, reloadedMessage.getThreadtop()); + Assert.assertEquals(topMessage, reloadedMessage.getParent()); + + Message reloadedMessageToMove_1 = forumManager.getMessageById(messageToMove_1.getKey()); + Assert.assertEquals(topMessage, reloadedMessageToMove_1.getThreadtop()); + Assert.assertEquals(message, reloadedMessageToMove_1.getParent()); + + Message reloadedMessageToMove_1_1 = forumManager.getMessageById(messageToMove_1_1.getKey()); + Assert.assertEquals(topMessage, reloadedMessageToMove_1_1.getThreadtop()); + Assert.assertEquals(messageToMove_1, reloadedMessageToMove_1_1.getParent()); + + Message reloadedMessageToMove_2 = forumManager.getMessageById(messageToMove_1.getKey()); + Assert.assertEquals(topMessage, reloadedMessageToMove_2.getThreadtop()); + Assert.assertEquals(message, reloadedMessageToMove_2.getParent()); + + Message reloadedMessageToStay = forumManager.getMessageById(messageToStay.getKey()); + Assert.assertEquals(topMessage, reloadedMessageToStay.getThreadtop()); + Assert.assertEquals(message, reloadedMessageToStay.getParent()); + } + + @Test + public void splitMessage() { + Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-1"); + Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-2"); + Identity guest3 = securityManager.getAndUpdateAnonymousUserForLanguage(Locale.ENGLISH); + Forum fo = forumManager.addAForum(); + dbInstance.commit(); + + // thread + // -> message + // -> -> message to split + // -> -> -> message child 1 + // -> -> -> -> message child 1.1 + // -> -> -> message child 2 + // -> -> message staying + + Message topMessage = forumManager.createMessage(fo, id1, false); + topMessage.setTitle("Thread split message"); + topMessage.setBody("Thread split message"); + forumManager.addTopMessage(topMessage); + dbInstance.commit(); + + Message message = forumManager.createMessage(fo, id2, false); + message.setTitle("Re: Thread split message"); + message.setBody("Thread split message"); + forumManager.replyToMessage(message, topMessage); + dbInstance.commit(); + + Message messageToSplit = forumManager.createMessage(fo, id2, false); + messageToSplit.setTitle("Message to split"); + messageToSplit.setBody("Thread split message"); + forumManager.replyToMessage(messageToSplit, message); + dbInstance.commit(); + + Message messageToSplit_1 = forumManager.createMessage(fo, id2, false); + messageToSplit_1.setTitle("Re: Message to split 1"); + messageToSplit_1.setBody("Thread split message"); + forumManager.replyToMessage(messageToSplit_1, messageToSplit); + dbInstance.commit(); + + Message messageToSplit_1_1 = forumManager.createMessage(fo, guest3, true); + messageToSplit_1_1.setTitle("Re: Re: Message to split 1"); + messageToSplit_1_1.setBody("Thread split message"); + forumManager.replyToMessage(messageToSplit_1_1, messageToSplit_1); + dbInstance.commit(); + + Message messageToSplit_2 = forumManager.createMessage(fo, id2, false); + messageToSplit_2.setTitle("Re: Message to split 2"); + messageToSplit_2.setBody("Thread split message"); + forumManager.replyToMessage(messageToSplit_2, messageToSplit); + dbInstance.commit(); + + Message messageToStay = forumManager.createMessage(fo, id2, false); + messageToStay.setTitle("Message to stay"); + messageToStay.setBody("Thread split message"); + forumManager.replyToMessage(messageToStay, message); + dbInstance.commit(); + + //move the message + Message splitedMessage = forumManager.splitThread(messageToSplit); + dbInstance.commitAndCloseSession(); + + //check the original thread + // thread + // -> message + // -> -> message staying + List<Message> originalMessages = forumManager.getThread(topMessage.getKey()); + Assert.assertEquals(3, originalMessages.size()); + Assert.assertTrue(originalMessages.contains(topMessage)); + Assert.assertTrue(originalMessages.contains(message)); + Assert.assertTrue(originalMessages.contains(messageToStay)); + + //check thread and parent of the target thread + Message reloadedTopMessage = forumManager.getMessageById(topMessage.getKey()); + Assert.assertNull(reloadedTopMessage.getThreadtop()); + Assert.assertNull(reloadedTopMessage.getParent()); + + Message reloadedMessage = forumManager.getMessageById(message.getKey()); + Assert.assertEquals(topMessage, reloadedMessage.getThreadtop()); + Assert.assertEquals(topMessage, reloadedMessage.getParent()); + + Message reloadedMessageToStay = forumManager.getMessageById(messageToStay.getKey()); + Assert.assertEquals(topMessage, reloadedMessageToStay.getThreadtop()); + Assert.assertEquals(message, reloadedMessageToStay.getParent()); + + //check original thread + // message to split + // -> message child 1 + // -> -> message child 1.1 + // -> message child 2 + List<Message> splitedMessages = forumManager.getThread(splitedMessage.getKey()); + Assert.assertEquals(4, splitedMessages.size()); + Assert.assertTrue(splitedMessages.contains(splitedMessage)); + Assert.assertTrue(splitedMessages.contains(messageToSplit_1)); + Assert.assertTrue(splitedMessages.contains(messageToSplit_1_1)); + Assert.assertTrue(splitedMessages.contains(messageToSplit_2)); + + //check thread and parent of the splited thread + + Message reloadedmessageToSplit = forumManager.getMessageById(messageToSplit.getKey()); + Assert.assertNull(reloadedmessageToSplit.getThreadtop()); + Assert.assertNull(reloadedmessageToSplit.getParent()); + + Message reloadedMessageToSplit_1 = forumManager.getMessageById(messageToSplit_1.getKey()); + Assert.assertEquals(messageToSplit, reloadedMessageToSplit_1.getThreadtop()); + Assert.assertEquals(messageToSplit, reloadedMessageToSplit_1.getParent()); + + Message reloadedMessageToSplit_1_1 = forumManager.getMessageById(messageToSplit_1_1.getKey()); + Assert.assertEquals(messageToSplit, reloadedMessageToSplit_1_1.getThreadtop()); + Assert.assertEquals(messageToSplit_1, reloadedMessageToSplit_1_1.getParent()); + + Message reloadedMessageToSplit_2 = forumManager.getMessageById(messageToSplit_1.getKey()); + Assert.assertEquals(messageToSplit, reloadedMessageToSplit_2.getThreadtop()); + Assert.assertEquals(messageToSplit, reloadedMessageToSplit_2.getParent()); + } + @Test public void deleteMessageTree() { Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("fo-5"); diff --git a/src/test/java/org/olat/selenium/CourseTest.java b/src/test/java/org/olat/selenium/CourseTest.java index 38041c268daa79a453c969c256d220fbf2cbb03c..db823a6002d84c772f50f2ff96748f6a2f4faa84 100644 --- a/src/test/java/org/olat/selenium/CourseTest.java +++ b/src/test/java/org/olat/selenium/CourseTest.java @@ -1146,7 +1146,7 @@ public class CourseTest { */ @Test @RunAsClient - public void concurrentForum(@InitialPage LoginPage loginPage, + public void forum_concurrent(@InitialPage LoginPage loginPage, @Drone @Participant WebDriver kanuBrowser, @Drone @Student WebDriver reiBrowser) throws IOException, URISyntaxException { diff --git a/src/test/java/org/olat/selenium/page/group/GroupPage.java b/src/test/java/org/olat/selenium/page/group/GroupPage.java index d4036a2252b7e311f29fab92a45855d41ba145f8..ac12929975fc864782b565811ee3e4da942fc081 100644 --- a/src/test/java/org/olat/selenium/page/group/GroupPage.java +++ b/src/test/java/org/olat/selenium/page/group/GroupPage.java @@ -51,6 +51,34 @@ public class GroupPage { private static final By bookingConfigBy = By.className("o_sel_accesscontrol_create"); private static final By memberMenuItem = By.cssSelector("li.o_sel_group_members a"); + private static final Tool calendarTool = new Tool( + By.cssSelector("li.o_sel_group_calendar a"), + By.cssSelector(".o_sel_collab_tools label.o_sel_hasCalendar input[type='checkbox']")); + private static final Tool chatTool = new Tool( + By.cssSelector("li.o_sel_group_chat a"), + By.cssSelector(".o_sel_collab_tools label.o_sel_hasChat input[type='checkbox']")); + private static final Tool contactTool = new Tool( + By.cssSelector("li.o_sel_group_contact a"), + By.cssSelector(".o_sel_collab_tools label.o_sel_hasContactForm input[type='checkbox']")); + private static final Tool membersTool = new Tool( + By.cssSelector("li.o_sel_group_members a"), null); + private static final Tool newsTool = new Tool( + By.cssSelector("li.o_sel_group_news a"), + By.cssSelector(".o_sel_collab_tools label.o_sel_hasNews input[type='checkbox']")); + private static final Tool folderTool = new Tool( + By.cssSelector("li.o_sel_group_folder a"), + By.cssSelector(".o_sel_collab_tools label.o_sel_hasFolder input[type='checkbox']")); + private static final Tool forumTool = new Tool( + By.cssSelector("li.o_sel_group_forum a"), + By.cssSelector(".o_sel_collab_tools label.o_sel_hasForum input[type='checkbox']")); + private static final Tool wikiTool = new Tool( + By.cssSelector("li.o_sel_group_wiki a"), + By.cssSelector(".o_sel_collab_tools label.o_sel_hasWiki input[type='checkbox']")); + private static final Tool portfolioTool = new Tool( + By.cssSelector("li.o_sel_group_portfolio a"), + By.cssSelector(".o_sel_collab_tools label.o_sel_hasPortfolio input[type='checkbox']")); + + private WebDriver browser; public GroupPage() { @@ -94,51 +122,50 @@ public class GroupPage { } public IMPage openChat() { - openMenuItem("o_sel_group_chat"); + openMenuItem(chatTool); return new IMPage(browser); } public CalendarPage openCalendar() { - openMenuItem("o_sel_group_calendar"); + openMenuItem(calendarTool); return new CalendarPage(browser); } public ContactPage openContact() { - openMenuItem("o_sel_group_contact"); + openMenuItem(contactTool); return new ContactPage(browser); } public GroupPage openMembers() { - return openMenuItem("o_sel_group_members"); + return openMenuItem(membersTool); } public GroupPage openNews() { - return openMenuItem("o_sel_group_news"); + return openMenuItem(newsTool); } public FolderPage openFolder() { - openMenuItem("o_sel_group_folder"); + openMenuItem(folderTool); return new FolderPage(browser); } public ForumPage openForum() { - openMenuItem("o_sel_group_forum"); + openMenuItem(forumTool); return ForumPage.getGroupForumPage(browser); } public WikiPage openWiki() { - openMenuItem("o_sel_group_wiki"); + openMenuItem(wikiTool); return WikiPage.getGroupWiki(browser); } public PortfolioPage openPortfolio() { - openMenuItem("o_sel_group_portfolio"); + openMenuItem(portfolioTool); return new PortfolioPage(browser); } - private GroupPage openMenuItem(String cssClass) { - By newsBy = By.cssSelector("li." + cssClass + " a"); - browser.findElement(newsBy).click(); + private GroupPage openMenuItem(Tool tool) { + browser.findElement(tool.getMenuItemBy()).click(); OOGraphene.waitBusy(browser); return this; } @@ -201,13 +228,22 @@ public class GroupPage { } public GroupPage enableTools() { - By checkToolsBy = By.cssSelector(".o_sel_collab_tools input[type='checkbox']"); - List<WebElement> checkTools = browser.findElements(checkToolsBy); - Assert.assertFalse(checkTools.isEmpty()); - for(WebElement checkTool:checkTools) { - checkTool.click(); - OOGraphene.waitBusy(browser); - } + return enableTool(calendarTool) + .enableTool(chatTool) + .enableTool(contactTool) + .enableTool(newsTool) + .enableTool(folderTool) + .enableTool(forumTool) + .enableTool(wikiTool) + .enableTool(portfolioTool); + } + + private GroupPage enableTool(Tool tool) { + By checkToolsBy = tool.getCheckboxBy(); + WebElement checkToolEl = browser.findElement(checkToolsBy); + checkToolEl.click(); + OOGraphene.waitBusy(browser); + OOGraphene.waitElement(tool.getMenuItemBy(), 2, browser); return this; } @@ -316,4 +352,22 @@ public class GroupPage { List<WebElement> elements = browser.findElements(longBy); return elements.size() > 0; } + + private static class Tool { + private final By menuItemBy; + private final By checkboxBy; + + public Tool(By menuItemBy, By checkboxBy) { + this.menuItemBy = menuItemBy; + this.checkboxBy = checkboxBy; + } + + public By getMenuItemBy() { + return menuItemBy; + } + + public By getCheckboxBy() { + return checkboxBy; + } + } }