This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository bow. See http://git.chorem.org/bow.git commit d5a2dc7f1e6d77707798148f97b8f4ead7191e21 Author: Benjamin POUSSIN <poussin@codelutin.com> Date: Mon Jul 20 04:23:53 2015 +0200 fixes #229: Partage de bookmark entre utilisateur fixes #1263: Add support for group (private/public) and with specific tag share some bookmark with this groups --- .../main/java/org/chorem/bow/BookmarkUtils.java | 13 ++ bow-ui/src/main/java/org/chorem/bow/BowConfig.java | 2 + bow-ui/src/main/java/org/chorem/bow/BowProxy.java | 1 + bow-ui/src/main/java/org/chorem/bow/BowUtils.java | 27 +++ .../bow/action/bookmark/AddOrUpdateAction.java | 25 ++- .../chorem/bow/action/group/GroupEditAction.java | 214 +++++++++++++++++++++ .../chorem/bow/action/group/GroupViewAction.java | 86 +++++++++ .../main/resources/i18n/bow-ui_en_GB.properties | 18 +- .../main/resources/i18n/bow-ui_fr_FR.properties | 18 +- bow-ui/src/main/resources/struts.xml | 24 +++ bow-ui/src/main/webapp/WEB-INF/bowutils.tld | 6 + .../src/main/webapp/WEB-INF/jsp/editBookmark.jsp | 2 +- bow-ui/src/main/webapp/WEB-INF/jsp/groupEdit.jsp | 113 +++++++++++ bow-ui/src/main/webapp/WEB-INF/jsp/groupView.jsp | 79 ++++++++ .../src/main/webapp/WEB-INF/jsp/inc/rightMenu.jsp | 1 + bow-ui/src/main/webapp/css/global.css | 22 ++- bow-ui/src/main/xmi/bow-model.zargo | Bin 9807 -> 10493 bytes pom.xml | 3 +- 18 files changed, 638 insertions(+), 16 deletions(-) diff --git a/bow-ui/src/main/java/org/chorem/bow/BookmarkUtils.java b/bow-ui/src/main/java/org/chorem/bow/BookmarkUtils.java index 690d348..c5ad503 100644 --- a/bow-ui/src/main/java/org/chorem/bow/BookmarkUtils.java +++ b/bow-ui/src/main/java/org/chorem/bow/BookmarkUtils.java @@ -45,6 +45,8 @@ import org.jsoup.nodes.Document; import org.nuiton.wikitty.entities.Element; import org.nuiton.wikitty.query.WikittyQuery; import org.nuiton.wikitty.query.WikittyQueryMaker; +import org.nuiton.wikitty.query.WikittyQueryResult; +import org.nuiton.wikitty.services.WikittyServiceAuthorisation; public class BookmarkUtils { @@ -66,7 +68,18 @@ public class BookmarkUtils { search.eq(BowBookmark.FQ_FIELD_WIKITTYAUTHORISATION_READER, userId); search.eq(BowBookmark.FQ_FIELD_WIKITTYAUTHORISATION_WRITER, userId); search.eq(BowBookmark.FQ_FIELD_WIKITTYAUTHORISATION_ADMIN, userId); + + search.containsOne(BowBookmark.ELEMENT_FIELD_WIKITTYAUTHORISATION_PARENT) + .select(Element.ID).where() + .or() + // si on est membre d'un group on peut voir les bookmarks de ce groupe + .eq(BowGroup.ELEMENT_FIELD_WIKITTYGROUP_MEMBERS, userId) + // on peut aussi voir tous les bookmarks public + .eq(BowGroup.ELEMENT_FIELD_WIKITTYAUTHORISATION_READER, WikittyServiceAuthorisation.PUBLIC) + .close() + .close(); search.close(); + return search; } diff --git a/bow-ui/src/main/java/org/chorem/bow/BowConfig.java b/bow-ui/src/main/java/org/chorem/bow/BowConfig.java index b40aa59..555ee5f 100644 --- a/bow-ui/src/main/java/org/chorem/bow/BowConfig.java +++ b/bow-ui/src/main/java/org/chorem/bow/BowConfig.java @@ -38,6 +38,8 @@ public class BowConfig { /** to use log facility, just put in your code: log.info(\"...\"); */ private static final Log log = LogFactory.getLog(BowConfig.class); + public static final String GROUP_MARK = "@"; + /** Singleton instance. */ protected static ApplicationConfig config; diff --git a/bow-ui/src/main/java/org/chorem/bow/BowProxy.java b/bow-ui/src/main/java/org/chorem/bow/BowProxy.java index 09f70cc..cf00c45 100644 --- a/bow-ui/src/main/java/org/chorem/bow/BowProxy.java +++ b/bow-ui/src/main/java/org/chorem/bow/BowProxy.java @@ -83,6 +83,7 @@ public class BowProxy extends WikittyClient { extensions.addAll(BowUserImpl.extensions); // inherit BowPreference, WikittyUser extensions.addAll(BowImportImpl.extensions); // inherit BowBookmark, WikittyLabel, WikittyAuthorisation extensions.addAll(BowSearchPrefixImpl.extensions); // inherit BowBookmark, WikittyLabel + extensions.addAll(BowGroupImpl.extensions); // inherit BowBookmark, WikittyLabel ws = WikittyServiceFactory.buildWikittyService(config); ws.storeExtension(null, extensions); diff --git a/bow-ui/src/main/java/org/chorem/bow/BowUtils.java b/bow-ui/src/main/java/org/chorem/bow/BowUtils.java index b4dd42a..b4794eb 100644 --- a/bow-ui/src/main/java/org/chorem/bow/BowUtils.java +++ b/bow-ui/src/main/java/org/chorem/bow/BowUtils.java @@ -35,6 +35,7 @@ import org.apache.commons.codec.binary.Base64; import org.apache.commons.collections4.CollectionUtils; import org.nuiton.wikitty.query.WikittyQuery; import org.nuiton.wikitty.query.WikittyQueryMaker; +import org.nuiton.wikitty.services.WikittyServiceAuthorisation; public class BowUtils { @@ -118,6 +119,32 @@ public class BowUtils { return result; } + /** + * Recupere la liste des noms des groupes parmi les tags. Un groupe dans + * les tags commence par "@" mais son nom ne contient pas ce '@'. Il est + * donc retire avant d'etre retourne. + * @param tags + * @return + */ + public static Set<String> getGroups(Set<String> tags) { + Set<String> result = new HashSet<String>(); + if (CollectionUtils.isNotEmpty(tags)) { + for (String t : tags) { + if (StringUtils.startsWith(t, BowConfig.GROUP_MARK)) { + result.add(StringUtils.substringAfter(t, BowConfig.GROUP_MARK)); + } + } + } + return result; + } + + public static boolean isPublicGroup(BowGroup g) { + Set<String> reader = g.getReader(); + boolean result = org.apache.commons.collections.CollectionUtils.isNotEmpty(reader) + && reader.contains(WikittyServiceAuthorisation.PUBLIC); + return result; + } + public static String formatDate(Date date) { String result = DateFormatUtils.format(date, BOW_DATE_SHORT_PATTERN); return result; diff --git a/bow-ui/src/main/java/org/chorem/bow/action/bookmark/AddOrUpdateAction.java b/bow-ui/src/main/java/org/chorem/bow/action/bookmark/AddOrUpdateAction.java index 8a6889a..74ac2b7 100644 --- a/bow-ui/src/main/java/org/chorem/bow/action/bookmark/AddOrUpdateAction.java +++ b/bow-ui/src/main/java/org/chorem/bow/action/bookmark/AddOrUpdateAction.java @@ -22,6 +22,9 @@ package org.chorem.bow.action.bookmark; import java.util.Collections; import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; @@ -29,6 +32,7 @@ import org.apache.commons.logging.LogFactory; import org.chorem.bow.BookmarkUtils; import org.chorem.bow.BowBookmark; import org.chorem.bow.BowBookmarkImpl; +import org.chorem.bow.BowGroup; import org.chorem.bow.BowProxy; import org.chorem.bow.BowUser; import org.chorem.bow.BowUtils; @@ -229,7 +233,26 @@ public class AddOrUpdateAction extends BowBaseAction { // on met a jour les infos bookmark.setDescription(name); bookmark.setLink(link); - bookmark.setLabels(BowUtils.getWords(tags)); + Set<String> tagsWord = BowUtils.getWords(tags); + bookmark.setLabels(tagsWord); + + // add in WikittyAuthorisation.parent all groups (tag start with @) + // where current user is member + Set<String> groupsName = BowUtils.getGroups(tagsWord); + WikittyQuery groupsQuery = new WikittyQueryMaker().and() + .containsOne(BowGroup.ELEMENT_FIELD_WIKITTYGROUP_NAME, groupsName) + .eq(BowGroup.ELEMENT_FIELD_WIKITTYGROUP_MEMBERS, userId) + .end(); + WikittyQueryResult<String> groupsId = proxy.findAllByQuery(groupsQuery); + bookmark.setParent(new HashSet<String>(groupsId.getAll())); + + if (groupsName.size() != groupsId.size()) { + List<BowGroup> groups = proxy.restore(BowGroup.class, groupsId.getAll()); + for (BowGroup g : groups) { + groupsName.remove(g.getName()); + } + addActionMessage(t("bow.group.not.members", StringUtils.join(groupsName, ", "))); + } // Si l'alias prive souhaite est deja utilise on ne l'accept pas diff --git a/bow-ui/src/main/java/org/chorem/bow/action/group/GroupEditAction.java b/bow-ui/src/main/java/org/chorem/bow/action/group/GroupEditAction.java new file mode 100644 index 0000000..09e0390 --- /dev/null +++ b/bow-ui/src/main/java/org/chorem/bow/action/group/GroupEditAction.java @@ -0,0 +1,214 @@ +/* + * #%L + * BOW UI + * %% + * Copyright (C) 2010 - 2015 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ +package org.chorem.bow.action.group; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.chorem.bow.BowGroup; +import org.chorem.bow.BowGroupImpl; +import org.chorem.bow.BowProxy; +import org.chorem.bow.BowSession; +import org.chorem.bow.BowUser; +import org.chorem.bow.BowUserHelper; +import org.chorem.bow.BowUtils; +import org.chorem.bow.action.BowBaseAction; +import org.nuiton.wikitty.entities.Wikitty; +import org.nuiton.wikitty.entities.WikittyUserHelper; +import org.nuiton.wikitty.query.WikittyQuery; +import org.nuiton.wikitty.query.WikittyQueryMaker; +import org.nuiton.wikitty.query.WikittyQueryResult; +import org.nuiton.wikitty.services.WikittyServiceAuthorisation; + +/** + * Handles RSS flux demande + * - tagLine + * - fullTextLine + * - count: number of bookmark to retrieve + * + * @author poussin + * @version $Revision$ + * <p/> + * Last update: $Date$ + * by : $Author$ + */ +public class GroupEditAction extends BowBaseAction { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + private static final Log log = LogFactory.getLog(GroupEditAction.class); + + private static final long serialVersionUID = 1L; + + protected String groupId; + protected BowGroup group; + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public BowGroup getGroup() { + if (group == null) { + loadGroup(); + } + return group; + } + + public boolean isPublic() { + return BowUtils.isPublicGroup(getGroup()); + } + + public void setPublic(boolean pub) { + String reader; + if (pub) { + reader = WikittyServiceAuthorisation.PUBLIC; + } else { + reader = getGroup().getWikittyId(); + } + getGroup().setReader(Collections.singleton(reader)); + } + + public void loadGroup() { + log.fatal("group load " + group); + BowProxy proxy = getBowProxy(); + if (groupId == null) { + BowSession session = getBowSession(); + BowUser user = session.getUser(); + + group = new BowGroupImpl(); + // add Wikitty to force add in preload too + group.addMembers(proxy.castTo(Wikitty.class, user)); + setPublic(false); + } else { + group = proxy.restore(BowGroup.class, groupId, "WikittyGroup.members"); + } + log.fatal("group loaded " + group); + } + + public String load() throws Exception { + return SUCCESS; + } + + public String removeMe() throws Exception { + String result = SUCCESS; + try { + BowSession session = getBowSession(); + + BowUser user = session.getUser(); + BowProxy proxy = session.getProxy(); + + // group is loaded by prepare method + getGroup().removeMembers(user.getWikittyId()); + if (CollectionUtils.isEmpty(getGroup().getMembers())) { + addActionMessage(t("bow.group.delete.no.member")); + proxy.delete(group); + } else { + proxy.store(group); + } + + } catch (Exception eee) { + addActionError(t("bow.error.internal")); + log.error(eee.getMessage(), eee); + result = ERROR; + } + return result; + } + + public String save() throws Exception { + log.fatal("group save " + group); + String result = SUCCESS; + try { + BowSession session = getBowSession(); + BowProxy proxy = session.getProxy(); + + if (StringUtils.isNotBlank(getGroup().getName())) { + Map<String, String> logins = new HashMap<String, String>(); + // convert user login to id + for (String login : getGroup().getMembers()) { + if (StringUtils.startsWith(login, "add ")) { + logins.put(StringUtils.substringAfter(login, "add "), login); + } + } + if (!logins.isEmpty()) { + WikittyQuery criteria = new WikittyQueryMaker().containsOne( + BowUser.ELEMENT_FIELD_WIKITTYUSER_LOGIN, logins.keySet()).end(); + WikittyQueryResult<Wikitty> users = proxy.findAllByQuery(Wikitty.class, criteria); + getGroup().removeMembers(logins.values().toArray(new String[logins.size()])); + getGroup().addMembers(users.getAll().toArray(new Wikitty[users.size()])); + + if (users.size() != logins.size()) { + for (Wikitty w : users) { + logins.remove(WikittyUserHelper.getLogin(w)); + } + addActionError(t("bow.group.some.user.not.found", + StringUtils.join(logins.keySet(), ", "))); + result = ERROR; + } + + } + if (result == SUCCESS && CollectionUtils.isEmpty(getGroup().getMembers())) { + addActionMessage(t("bow.group.delete.no.member")); + proxy.delete(group); + } else { + // force admin to group all time + getGroup().setAdmin(Collections.singleton(getGroup().getWikittyId())); + + proxy.store(group); + } + } else { + addActionError(t("bow.group.name.blank")); + result = ERROR; + } + + } catch (Exception eee) { + addActionError(t("bow.error.internal")); + log.error(eee.getMessage(), eee); + result = ERROR; + } + return result; + } + + public String delete() throws Exception { + log.fatal("group delete " + group); + String result = SUCCESS; + try { + BowSession session = getBowSession(); + BowProxy proxy = session.getProxy(); + proxy.delete(group); + + } catch (Exception eee) { + addActionError(t("bow.error.internal")); + log.error(eee.getMessage(), eee); + result = ERROR; + } + return result; + } + +} diff --git a/bow-ui/src/main/java/org/chorem/bow/action/group/GroupViewAction.java b/bow-ui/src/main/java/org/chorem/bow/action/group/GroupViewAction.java new file mode 100644 index 0000000..5989720 --- /dev/null +++ b/bow-ui/src/main/java/org/chorem/bow/action/group/GroupViewAction.java @@ -0,0 +1,86 @@ +/* + * #%L + * BOW UI + * %% + * Copyright (C) 2010 - 2015 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ +package org.chorem.bow.action.group; + +import java.util.List; +import java.util.Set; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.chorem.bow.BowGroup; +import org.chorem.bow.BowProxy; +import org.chorem.bow.BowSession; +import org.chorem.bow.BowUser; +import org.chorem.bow.action.BowBaseAction; +import org.nuiton.wikitty.query.WikittyQuery; +import org.nuiton.wikitty.query.WikittyQueryMaker; +import org.nuiton.wikitty.query.WikittyQueryResult; +import org.nuiton.wikitty.services.WikittyServiceAuthorisation; + +/** + * Used view groups + * + * @author poussin + * @version $Revision$ + * <p/> + * Last update: $Date$ + * by : $Author$ + */ +public class GroupViewAction extends BowBaseAction { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + private static final Log log = LogFactory.getLog(GroupViewAction.class); + + private static final long serialVersionUID = 1L; + + protected List<BowGroup> groups; + + public List<BowGroup> getGroups() { + return groups; + } + + @Override + public String execute() throws Exception { + String result = SUCCESS; + try { + + BowSession session = getBowSession(); + + BowUser user = session.getUser(); + BowProxy proxy = session.getProxy(); + + WikittyQuery criteria = new WikittyQueryMaker().and().eq(BowGroup.ELEMENT_FIELD_WIKITTYGROUP_MEMBERS, user).end(); + WikittyQueryResult<String> groupsId = proxy.findAllByQuery(criteria); + groups = proxy.restore(BowGroup.class, groupsId.getAll(), "WikittyGroup.members"); + + if (log.isDebugEnabled()) { + log.debug(String.format("Group found='%s'" + groups.size())); + } + + } catch (Exception eee) { + addActionError(t("bow.error.internal")); + log.error(eee.getMessage(), eee); + result = ERROR; + } + return result; + } + +} diff --git a/bow-ui/src/main/resources/i18n/bow-ui_en_GB.properties b/bow-ui/src/main/resources/i18n/bow-ui_en_GB.properties index cc4a151..1608e5b 100644 --- a/bow-ui/src/main/resources/i18n/bow-ui_en_GB.properties +++ b/bow-ui/src/main/resources/i18n/bow-ui_en_GB.properties @@ -2,8 +2,8 @@ bow.action.locale.english=English bow.action.locale.french=Français bow.admin.dataMigration.success=Data migration successful bow.admin.dataMigration04to05=Migrate all data from 0.4 to 0.5 -bow.admin.dataMigration05to06=Migrate all data from 1.1 to 1.2 -bow.admin.dataMigration11to12= +bow.admin.dataMigration05to06=Migrate all data from 0.5 to 0.6 +bow.admin.dataMigration11to12=Migrate all data from 1.1 to 1.2 bow.admin.dataReindexation=All data reindexation (and migration if needed) bow.admin.forbidden=You don't have admin rights \! bow.admin.forceMigration= @@ -56,6 +56,19 @@ bow.footer.userSupport=User support bow.forgotPassword.emailDoesntExist=This email address doesn''t exist bow.forgotpwd.submit=Send bow.forgotpwd.title=Forgot your password? +bow.group.delete.no.member=No more members, delete group +bow.group.members=Members +bow.group.name.blank=Group's name empty +bow.group.new=Create new group +bow.group.not.members=You are not groups members: %s +bow.group.some.user.not.found=Some users not found: %s +bow.groupEdit.delete=delete +bow.groupEdit.members=Members +bow.groupEdit.name=Name +bow.groupEdit.public=Public groupe (all people can see it) +bow.groupEdit.save=Save +bow.groupEdit.title=Edit group +bow.groupView.title=Groups bow.home.latestBookmarks=The latest added bookmarks bow.home.mostUsedBookmarks=The most used bookmarks bow.home.title=Home @@ -173,6 +186,7 @@ bow.temporary.link.searchDescription= bow.temporary.link.suggestion= bow.temporary.link.suggestionDescription= bow.token.generate.successful=The token has been regenerated successfully +bow.users=Users popup.addurl.alias.private=Private alias popup.addurl.alias.public=Public alias popup.addurl.link=Url diff --git a/bow-ui/src/main/resources/i18n/bow-ui_fr_FR.properties b/bow-ui/src/main/resources/i18n/bow-ui_fr_FR.properties index 9bb8918..d81fdb4 100644 --- a/bow-ui/src/main/resources/i18n/bow-ui_fr_FR.properties +++ b/bow-ui/src/main/resources/i18n/bow-ui_fr_FR.properties @@ -2,8 +2,8 @@ bow.action.locale.english=English bow.action.locale.french=Français bow.admin.dataMigration.success=Les données ont été migrées avec succès bow.admin.dataMigration04to05=Migrer toutes les données de la version 0.4 à 0.5 -bow.admin.dataMigration05to06=Migrer toutes les données de la version 1.1 à 1.2 -bow.admin.dataMigration11to12= +bow.admin.dataMigration05to06=Migrer toutes les données de la version 0.5 à 0.6 +bow.admin.dataMigration11to12=Migrer toutes les données de la version 1.1 à 1.2 bow.admin.dataReindexation=Réindexation des données bow.admin.forbidden=Vous n'êtes pas administrateur \! bow.admin.forceMigration= @@ -56,6 +56,19 @@ bow.footer.userSupport=Support utilisateur bow.forgotPassword.emailDoesntExist=Cette adresse email n''existe pas bow.forgotpwd.submit=Envoyer bow.forgotpwd.title=Vous avez oublié votre mot de passe ? +bow.group.delete.no.member=Plus de membre, suppression du groupe +bow.group.members=Membres +bow.group.name.blank=Nom du groupe vide +bow.group.new=Créer un nouveau groupe +bow.group.not.members=Vous n'êtes pas membres des groupes: %s +bow.group.some.user.not.found=Certain utilisateurs n'ont pas été trouvé: %s +bow.groupEdit.delete=Supprimer +bow.groupEdit.members=Membres +bow.groupEdit.name=Nom +bow.groupEdit.public=Groupe public (visible de tout le monde) +bow.groupEdit.save=Sauver +bow.groupEdit.title=Modification d'un Groupe +bow.groupView.title=Les groupes bow.home.latestBookmarks=Les derniers marque-pages ajoutés bow.home.mostUsedBookmarks=Les marque-pages les plus utilisés bow.home.title=Accueil @@ -173,6 +186,7 @@ bow.temporary.link.searchDescription= bow.temporary.link.suggestion= bow.temporary.link.suggestionDescription= bow.token.generate.successful=Le token a été regénéré avec succès +bow.users=Utilisateurs popup.addurl.alias.private=Alias privé popup.addurl.alias.public=Alias public popup.addurl.link=Url diff --git a/bow-ui/src/main/resources/struts.xml b/bow-ui/src/main/resources/struts.xml index 39718af..ac94790 100644 --- a/bow-ui/src/main/resources/struts.xml +++ b/bow-ui/src/main/resources/struts.xml @@ -56,6 +56,7 @@ <interceptor-ref name="defaultStack"> <param name="store.operationMode">AUTOMATIC</param> <param name="fileUpload.allowedExtensions">.html</param> + <param name="params.ordered">true</param> </interceptor-ref> </interceptor-stack> </interceptors> @@ -161,6 +162,29 @@ </action> </package> + <package name="group" extends="restrictedArea"> + <action name="groupView" class="org.chorem.bow.action.group.GroupViewAction"> + <result name="error">/WEB-INF/jsp/groupView.jsp</result> + <result>/WEB-INF/jsp/groupView.jsp</result> + </action> + <action name="groupRemoveMe" class="org.chorem.bow.action.group.GroupEditAction" method="removeMe"> + <result name="error" type="redirectAction">groupView</result> + <result type="redirectAction">groupView</result> + </action> + <action name="groupEdit" class="org.chorem.bow.action.group.GroupEditAction" method="load"> + <result name="error">/WEB-INF/jsp/groupEdit.jsp</result> + <result>/WEB-INF/jsp/groupEdit.jsp</result> + </action> + <action name="groupSave" class="org.chorem.bow.action.group.GroupEditAction" method="save"> + <result name="error">/WEB-INF/jsp/groupEdit.jsp</result> + <result type="redirectAction">groupView</result> + </action> + <action name="groupDelete" class="org.chorem.bow.action.group.GroupEditAction" method="delete"> + <result name="error">/WEB-INF/jsp/groupEdit.jsp</result> + <result type="redirectAction">groupView</result> + </action> + </package> + <!-- Fragment: en prevision de faire un peu d'ajax si l'utilisateur le souhaite --> <package name="fragment" namespace="/fragment" extends="restrictedArea"> <action name="editBookmark" class="org.chorem.bow.action.bookmark.EditAction"> diff --git a/bow-ui/src/main/webapp/WEB-INF/bowutils.tld b/bow-ui/src/main/webapp/WEB-INF/bowutils.tld index 5c2eb2a..ca2d045 100644 --- a/bow-ui/src/main/webapp/WEB-INF/bowutils.tld +++ b/bow-ui/src/main/webapp/WEB-INF/bowutils.tld @@ -13,4 +13,10 @@ <function-class>org.chorem.bow.BowUtils</function-class> <function-signature>String toBase64(byte[] b)</function-signature> </function> + + <function> + <name>isPublicGroup</name> + <function-class>org.chorem.bow.BowUtils</function-class> + <function-signature>boolean isPublicGroup(org.chorem.bow.BowGroup)</function-signature> + </function> </taglib> diff --git a/bow-ui/src/main/webapp/WEB-INF/jsp/editBookmark.jsp b/bow-ui/src/main/webapp/WEB-INF/jsp/editBookmark.jsp index dab5b08..8eadad1 100644 --- a/bow-ui/src/main/webapp/WEB-INF/jsp/editBookmark.jsp +++ b/bow-ui/src/main/webapp/WEB-INF/jsp/editBookmark.jsp @@ -36,7 +36,7 @@ <h2><s:text name="popup.addurl.title" /></h2> </div> <div class="formFrame fond"> - <s:form id="popupAddUrlForm" action="addUrl" method="post"> + <s:form id="popupAddUrlForm" cssClass="pretty-form" action="addUrl" method="post"> <s:hidden name="tagLine" value="%{tagLine}" /> <s:hidden name="fullTextLine" value="%{fullTextLine}" /> <s:hidden name="bookmarkId" value="%{bookmark.wikittyId}"/> diff --git a/bow-ui/src/main/webapp/WEB-INF/jsp/groupEdit.jsp b/bow-ui/src/main/webapp/WEB-INF/jsp/groupEdit.jsp new file mode 100644 index 0000000..37eb485 --- /dev/null +++ b/bow-ui/src/main/webapp/WEB-INF/jsp/groupEdit.jsp @@ -0,0 +1,113 @@ +<%-- +#%L +bow + +$Id$ +$HeadURL$ +%% +Copyright (C) 2010 CodeLutin +%% +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +#L% +--%> + +<%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> +<%@taglib prefix="s" uri="/struts-tags" %> + +<html xmlns:s="http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" + xmlns:jsp="http://java.sun.com/JSP/Page"> +<head> + <title><s:text name="bow.groupEdit.title"/></title> + <s:url var="css" value="/css/bookmark.css" /> + <link href="${css}" rel="stylesheet" type="text/css"/> + <s:head/> + <script> + function addUserEnter(e) { + if (e.keyCode === 13) { + addUser(); + return false; + } + } + function addUser() { + var members = document.getElementById("members"); + var userLogin = document.getElementById("userLogin"); + + if (userLogin.value) { + var o = document.createElement("option"); + o.value="add " + userLogin.value; + o.innerHTML = userLogin.value; + members.appendChild(o); + userLogin.value = ""; + } + } + + function removeUser() { + var members = document.getElementById("members"); + for (var i = 0; i < members.options.length; i++) { + var o = members.options[i]; + if (o.selected) { + members.removeChild(o); + } + } + } + + function prepareSendMembers() { + var members = document.getElementById("members"); + for (var i = 0; i < members.options.length; i++) { + members.options[i].selected = true; + } + } + + function showAddedMembers() { + var members = document.getElementById("members"); + for (var i = 0; i < members.options.length; i++) { + var o = members.options[i]; + if (o.value.indexOf("add ") === 0) { // start with 'add ' + o.innerHTML = o.value.substring(4); + } + } + } + </script> +</head> +<body onload="showAddedMembers()"> + <div id="content"> + <div class="menu clearfix"> + <h2><s:text name="bow.groupEdit.title" /></h2> + </div> + <div class="formFrame fond"> + <s:form id="groupEditForm" cssClass="pretty-form" action="groupSave" + method="post" onsubmit="prepareSendMembers()"> + <s:hidden name="tagLine" value="%{tagLine}" /> + <s:hidden name="fullTextLine" value="%{fullTextLine}" /> + <s:hidden name="groupId" value="%{groupId}"/> + + <s:checkbox labelposition="left" name="public" labelSeparator=" " key="bow.groupEdit.public" + value="%{public}" /> + <s:textfield disabled="%{groupId != null}" name="group.name" labelSeparator=" " key="bow.groupEdit.name" + value="%{group.name}" /> + + <s:select id="members" + list="%{group.getMembers(false)}" listKey="wikittyId" listValue="getFqField('WikittyUser.login')" + multiple="true" size="10" + name="group.members" labelSeparator=" " key="bow.groupEdit.members" /> + <button type='button' name="-" onclick="removeUser()">-</button> + <div><s:textfield id="userLogin" onkeypress="return addUserEnter(event)"/> <button type='button' name="+" onclick="addUser()">+</button></div> + + <s:submit cssClass="submit-button" key="bow.groupEdit.save" name="submit" /> + <s:submit cssClass="submit-button" key="bow.groupEdit.delete" name="delete" action="groupDelete"/> + </s:form> + </div> + </div> +</body> +</html> diff --git a/bow-ui/src/main/webapp/WEB-INF/jsp/groupView.jsp b/bow-ui/src/main/webapp/WEB-INF/jsp/groupView.jsp new file mode 100644 index 0000000..50984d9 --- /dev/null +++ b/bow-ui/src/main/webapp/WEB-INF/jsp/groupView.jsp @@ -0,0 +1,79 @@ +<%-- +#%L +bow + +$Id$ +$HeadURL$ +%% +Copyright (C) 2010 CodeLutin +%% +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +#L% +--%> + +<%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> +<%@taglib prefix="s" uri="/struts-tags" %> +<%@taglib uri="/WEB-INF/bowutils" prefix="u" %> + +<html xmlns:s="http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" + xmlns:jsp="http://java.sun.com/JSP/Page"> +<head> + <title><s:text name="bow.groupView.title"/></title> + <s:url var="css" value="/css/bookmark.css" /> + <link href="${css}" rel="stylesheet" type="text/css"/> + <s:head/> +</head> +<body> +<div id="content"> + <div class="menu clearfix"> + <h2><s:text name="bow.groupView.title"/></h2> + </div> + <s:actionerror/> + + <div class="formFrame fond"> + <s:a action="groupEdit"><s:text name="bow.group.new" /></s:a> + <ul> + <s:iterator value="groups" var="group"> + <s:set name="group" value="group"/> + <li class="public-${u:isPublicGroup(group)}"> + <span class="group-name">${group.name}</span> + <span class="group-members">${group.members.size()} <s:text name="bow.group.members"/></span> + + <span class="group-actions"> + <s:url var="groupEdit" action="groupEdit" escapeAmp="true"> + <s:param name="groupId" value="%{#group.wikittyId}" /> + </s:url> + <a class="edit" href="${groupEdit}">edit</a> + + <s:url var="groupRemoveMe" action="groupRemoveMe" escapeAmp="true"> + <s:param name="groupId" value="%{#group.wikittyId}" /> + <s:param name="user" value="%{#bowSession.user.wikittyId}" /> + </s:url> + <a class="removeMe" href="${groupRemoveMe}">removeMe</a> + + <s:url var="rss" action="atom" escapeAmp="true"> + <s:param name="token" value="%{#bowSession.user.wikittyId}" /> + <s:param name="tagLine" value="@%{#group.name}" /> + </s:url> + <a class="atom" href="${rss}">atom</a> + </span> + </li> + </s:iterator> + </ul> + + </div> + +</div> +</body> +</html> diff --git a/bow-ui/src/main/webapp/WEB-INF/jsp/inc/rightMenu.jsp b/bow-ui/src/main/webapp/WEB-INF/jsp/inc/rightMenu.jsp index 4d55c3c..a248720 100644 --- a/bow-ui/src/main/webapp/WEB-INF/jsp/inc/rightMenu.jsp +++ b/bow-ui/src/main/webapp/WEB-INF/jsp/inc/rightMenu.jsp @@ -57,6 +57,7 @@ <s:text name="bow.rightMenu.addUrl.link" /> </s:a> </li> + <li><s:a action="groupView"><s:text name="bow.groupView.title" /></s:a></li> </ul> <!--div id="nuage"--> <jsp:include page="tagsCloud.jsp" flush="true"/> diff --git a/bow-ui/src/main/webapp/css/global.css b/bow-ui/src/main/webapp/css/global.css index 3e6bdb3..bf9f21b 100644 --- a/bow-ui/src/main/webapp/css/global.css +++ b/bow-ui/src/main/webapp/css/global.css @@ -182,26 +182,32 @@ form, .wwFormTable{ } -form#popupAddUrlForm input, form#popupAddUrlForm textarea { +form.pretty-form>input, form.pretty-form>textarea, form.pretty-form>select { + display: block; width: 100%; font-family: Helvetica, sans-serif; font-size: 1.4em; margin: 0px 0px 10px 0px; } -form#popupAddUrlForm textarea:focus, form#popupAddUrlForm input:focus { +form.pretty-form>label { + display: block; + text-align: left; + margin-right: 15px; + width: 100%; +} + +form.pretty-form textarea:focus, form.pretty-form input:focus, form.pretty-form select:focus { border:1px solid #666; background:#e3f1f1; } -form#popupAddUrlForm input.submit-button { +form.pretty-form input.submit-button { width: 100px; float: right; + margin: 10px; } -form#popupAddUrlForm label { - float: left; - text-align: left; - margin-right: 15px; - width: 100px; +.public-true .group-name { + background-color: darkgray; } diff --git a/bow-ui/src/main/xmi/bow-model.zargo b/bow-ui/src/main/xmi/bow-model.zargo index abbdfde..f3b2871 100644 Binary files a/bow-ui/src/main/xmi/bow-model.zargo and b/bow-ui/src/main/xmi/bow-model.zargo differ diff --git a/pom.xml b/pom.xml index ec0d596..02a745b 100644 --- a/pom.xml +++ b/pom.xml @@ -117,7 +117,7 @@ <nuitonConfigVersion>3.0-rc-2</nuitonConfigVersion> <nuitonWebVersion>1.17</nuitonWebVersion> <nuitonI18nVersion>3.3</nuitonI18nVersion> - <wikittyVersion>3.11</wikittyVersion> + <wikittyVersion>3.12-SNAPSHOT</wikittyVersion> <slf4jVersion>1.6.1</slf4jVersion> <struts2Version>2.3.16.3</struts2Version> <struts2jqueryVersion>3.7.1</struts2jqueryVersion> @@ -248,7 +248,6 @@ <groupId>com.jgeppert.struts2.jquery</groupId> <artifactId>struts2-jquery-plugin</artifactId> <version>${struts2jqueryVersion}</version> - <scope>runtime</scope> </dependency> <dependency> -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.