branch develop updated (8ef242d5 -> d193ac8f)
This is an automated email from the git hooks/post-receive script. New change to branch develop in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git from 8ef242d5 remove unused dependency new d193ac8f Signalement de contenu inapproprié (ref #63) The 1 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit d193ac8ff671230742299a4d8cc6210d5b3df773 Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Thu Jun 15 13:28:31 2017 +0200 Signalement de contenu inapproprié (ref #63) Summary of changes: .../pollen/persistence/entity/ReportResume.java | 43 + .../pollen/persistence/entity/ReportTopiaDao.java | 26 + .../db/migration/h2/V3_0_0_3__add_reports.sql | 11 + .../migration/postgresql/V3_0_0_3__add_reports.sql | 11 + pollen-persistence/src/main/xmi/pollen.properties | 2 +- pollen-persistence/src/main/xmi/pollen.zargo | Bin 25580 -> 26098 bytes .../rest/api/PollenRestApiApplicationListener.java | 4 +- .../org/chorem/pollen/rest/api/v1/ChoiceApi.java | 20 + .../org/chorem/pollen/rest/api/v1/CommentApi.java | 22 + .../org/chorem/pollen/rest/api/v1/PollApi.java | 20 + pollen-rest-api/src/main/resources/mapping | 64 +- pollen-services/src/main/config/PollenServices.ini | 8 +- .../chorem/pollen/services/PollenUIContext.java | 9 + .../chorem/pollen/services/bean/ChoiceBean.java | 10 + .../chorem/pollen/services/bean/CommentBean.java | 10 + .../org/chorem/pollen/services/bean/PollBean.java | 10 + .../chorem/pollen/services/bean/ReportBean.java | 65 ++ .../chorem/pollen/services/bean/ReportLevel.java | 30 + .../pollen/services/bean/ReportResumeBean.java | 53 + .../org/chorem/pollen/services/bean/VoteBean.java | 10 + .../pollen/services/service/ChoiceService.java | 4 + .../pollen/services/service/CommentService.java | 4 + .../service/FavoriteListImportFromLdap.java | 3 +- .../services/service/NotificationService.java | 89 ++ .../pollen/services/service/PollService.java | 4 + .../services/service/PollenServiceSupport.java | 9 + .../services/service/PollenUIUrlRenderService.java | 11 + .../pollen/services/service/ReportService.java | 191 ++++ .../pollen/services/service/VoteService.java | 4 + .../services/service/mail/AbstractReportEmail.java | 70 ++ .../service/mail/AbstractReportForAdminEmail.java | 49 + .../services/service/mail/ChoiceReportEmail.java | 35 + .../service/mail/ChoiceReportForAdminEmail.java | 35 + .../services/service/mail/CommentReportEmail.java | 26 + .../service/mail/CommentReportForAdminEmail.java | 26 + .../pollen/services/service/mail/EmailService.java | 145 +++ .../services/service/mail/PollReportEmail.java | 22 + .../service/mail/PollReportForAdminEmail.java | 22 + .../pollen/services/service/mail/PollenMail.java | 16 +- .../resources/email/ChoiceReportEmail.mustache | 8 + .../resources/email/ChoiceReportEmail_fr.mustache | 8 + .../email/ChoiceReportForAdminEmail.mustache | 14 + .../email/ChoiceReportForAdminEmail_fr.mustache | 14 + .../resources/email/CommentReportEmail.mustache | 8 + .../resources/email/CommentReportEmail_fr.mustache | 8 + .../email/CommentReportForAdminEmail.mustache | 14 + .../email/CommentReportForAdminEmail_fr.mustache | 14 + .../main/resources/email/PollReportEmail.mustache | 8 + .../resources/email/PollReportEmail_fr.mustache | 8 + .../email/PollReportForAdminEmail.mustache | 14 + .../email/PollReportForAdminEmail_fr.mustache | 14 + .../i18n/pollen-services_en_GB.properties | 10 + .../i18n/pollen-services_fr_FR.properties | 10 + .../src/main/web/css/{main.css => blaze.css} | 561 ++++----- pollen-ui-riot-js/src/main/web/css/main.css | 1193 +------------------- pollen-ui-riot-js/src/main/web/i18n.json | 38 +- pollen-ui-riot-js/src/main/web/index.html | 1 + pollen-ui-riot-js/src/main/web/js/ChoiceService.js | 24 + .../src/main/web/js/CommentService.js | 24 + pollen-ui-riot-js/src/main/web/js/Poll.js | 48 + pollen-ui-riot-js/src/main/web/js/PollService.js | 24 + pollen-ui-riot-js/src/main/web/js/Session.js | 3 +- .../src/main/web/tag/poll/ChoiceView.tag.html | 7 + .../src/main/web/tag/poll/Comments.tag.html | 3 +- .../src/main/web/tag/poll/Poll.tag.html | 3 +- .../src/main/web/tag/poll/Report.tag.html | 232 ++++ .../src/main/web/tag/popup/Modal.tag.html | 3 +- .../src/main/web/tag/popup/NewPassword.tag.html | 4 +- .../main/web/tag/popup/ResendValidation.tag.html | 2 +- .../web/tag/voterList/VoterListActions.tag.html | 2 +- 70 files changed, 1965 insertions(+), 1552 deletions(-) create mode 100644 pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ReportResume.java create mode 100644 pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ReportTopiaDao.java create mode 100644 pollen-persistence/src/main/resources/db/migration/h2/V3_0_0_3__add_reports.sql create mode 100644 pollen-persistence/src/main/resources/db/migration/postgresql/V3_0_0_3__add_reports.sql create mode 100644 pollen-services/src/main/java/org/chorem/pollen/services/bean/ReportBean.java create mode 100644 pollen-services/src/main/java/org/chorem/pollen/services/bean/ReportLevel.java create mode 100644 pollen-services/src/main/java/org/chorem/pollen/services/bean/ReportResumeBean.java create mode 100644 pollen-services/src/main/java/org/chorem/pollen/services/service/ReportService.java create mode 100644 pollen-services/src/main/java/org/chorem/pollen/services/service/mail/AbstractReportEmail.java create mode 100644 pollen-services/src/main/java/org/chorem/pollen/services/service/mail/AbstractReportForAdminEmail.java create mode 100644 pollen-services/src/main/java/org/chorem/pollen/services/service/mail/ChoiceReportEmail.java create mode 100644 pollen-services/src/main/java/org/chorem/pollen/services/service/mail/ChoiceReportForAdminEmail.java create mode 100644 pollen-services/src/main/java/org/chorem/pollen/services/service/mail/CommentReportEmail.java create mode 100644 pollen-services/src/main/java/org/chorem/pollen/services/service/mail/CommentReportForAdminEmail.java create mode 100644 pollen-services/src/main/java/org/chorem/pollen/services/service/mail/PollReportEmail.java create mode 100644 pollen-services/src/main/java/org/chorem/pollen/services/service/mail/PollReportForAdminEmail.java create mode 100644 pollen-services/src/main/resources/email/ChoiceReportEmail.mustache create mode 100644 pollen-services/src/main/resources/email/ChoiceReportEmail_fr.mustache create mode 100644 pollen-services/src/main/resources/email/ChoiceReportForAdminEmail.mustache create mode 100644 pollen-services/src/main/resources/email/ChoiceReportForAdminEmail_fr.mustache create mode 100644 pollen-services/src/main/resources/email/CommentReportEmail.mustache create mode 100644 pollen-services/src/main/resources/email/CommentReportEmail_fr.mustache create mode 100644 pollen-services/src/main/resources/email/CommentReportForAdminEmail.mustache create mode 100644 pollen-services/src/main/resources/email/CommentReportForAdminEmail_fr.mustache create mode 100644 pollen-services/src/main/resources/email/PollReportEmail.mustache create mode 100644 pollen-services/src/main/resources/email/PollReportEmail_fr.mustache create mode 100644 pollen-services/src/main/resources/email/PollReportForAdminEmail.mustache create mode 100644 pollen-services/src/main/resources/email/PollReportForAdminEmail_fr.mustache copy pollen-ui-riot-js/src/main/web/css/{main.css => blaze.css} (80%) create mode 100644 pollen-ui-riot-js/src/main/web/tag/poll/Report.tag.html -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit d193ac8ff671230742299a4d8cc6210d5b3df773 Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Thu Jun 15 13:28:31 2017 +0200 Signalement de contenu inapproprié (ref #63) --- .../pollen/persistence/entity/ReportResume.java | 43 + .../pollen/persistence/entity/ReportTopiaDao.java | 26 + .../db/migration/h2/V3_0_0_3__add_reports.sql | 11 + .../migration/postgresql/V3_0_0_3__add_reports.sql | 11 + pollen-persistence/src/main/xmi/pollen.properties | 2 +- pollen-persistence/src/main/xmi/pollen.zargo | Bin 25580 -> 26098 bytes .../rest/api/PollenRestApiApplicationListener.java | 4 +- .../org/chorem/pollen/rest/api/v1/ChoiceApi.java | 20 + .../org/chorem/pollen/rest/api/v1/CommentApi.java | 22 + .../org/chorem/pollen/rest/api/v1/PollApi.java | 20 + pollen-rest-api/src/main/resources/mapping | 64 +- pollen-services/src/main/config/PollenServices.ini | 8 +- .../chorem/pollen/services/PollenUIContext.java | 9 + .../chorem/pollen/services/bean/ChoiceBean.java | 10 + .../chorem/pollen/services/bean/CommentBean.java | 10 + .../org/chorem/pollen/services/bean/PollBean.java | 10 + .../chorem/pollen/services/bean/ReportBean.java | 65 ++ .../chorem/pollen/services/bean/ReportLevel.java | 30 + .../pollen/services/bean/ReportResumeBean.java | 53 + .../org/chorem/pollen/services/bean/VoteBean.java | 10 + .../pollen/services/service/ChoiceService.java | 4 + .../pollen/services/service/CommentService.java | 4 + .../service/FavoriteListImportFromLdap.java | 3 +- .../services/service/NotificationService.java | 89 ++ .../pollen/services/service/PollService.java | 4 + .../services/service/PollenServiceSupport.java | 9 + .../services/service/PollenUIUrlRenderService.java | 11 + .../pollen/services/service/ReportService.java | 191 ++++ .../pollen/services/service/VoteService.java | 4 + .../services/service/mail/AbstractReportEmail.java | 70 ++ .../service/mail/AbstractReportForAdminEmail.java | 49 + .../services/service/mail/ChoiceReportEmail.java | 35 + .../service/mail/ChoiceReportForAdminEmail.java | 35 + .../services/service/mail/CommentReportEmail.java | 26 + .../service/mail/CommentReportForAdminEmail.java | 26 + .../pollen/services/service/mail/EmailService.java | 145 +++ .../services/service/mail/PollReportEmail.java | 22 + .../service/mail/PollReportForAdminEmail.java | 22 + .../pollen/services/service/mail/PollenMail.java | 16 +- .../resources/email/ChoiceReportEmail.mustache | 8 + .../resources/email/ChoiceReportEmail_fr.mustache | 8 + .../email/ChoiceReportForAdminEmail.mustache | 14 + .../email/ChoiceReportForAdminEmail_fr.mustache | 14 + .../resources/email/CommentReportEmail.mustache | 8 + .../resources/email/CommentReportEmail_fr.mustache | 8 + .../email/CommentReportForAdminEmail.mustache | 14 + .../email/CommentReportForAdminEmail_fr.mustache | 14 + .../main/resources/email/PollReportEmail.mustache | 8 + .../resources/email/PollReportEmail_fr.mustache | 8 + .../email/PollReportForAdminEmail.mustache | 14 + .../email/PollReportForAdminEmail_fr.mustache | 14 + .../i18n/pollen-services_en_GB.properties | 10 + .../i18n/pollen-services_fr_FR.properties | 10 + .../src/main/web/css/{main.css => blaze.css} | 561 ++++----- pollen-ui-riot-js/src/main/web/css/main.css | 1193 +------------------- pollen-ui-riot-js/src/main/web/i18n.json | 38 +- pollen-ui-riot-js/src/main/web/index.html | 1 + pollen-ui-riot-js/src/main/web/js/ChoiceService.js | 24 + .../src/main/web/js/CommentService.js | 24 + pollen-ui-riot-js/src/main/web/js/Poll.js | 48 + pollen-ui-riot-js/src/main/web/js/PollService.js | 24 + pollen-ui-riot-js/src/main/web/js/Session.js | 3 +- .../src/main/web/tag/poll/ChoiceView.tag.html | 7 + .../src/main/web/tag/poll/Comments.tag.html | 3 +- .../src/main/web/tag/poll/Poll.tag.html | 3 +- .../src/main/web/tag/poll/Report.tag.html | 232 ++++ .../src/main/web/tag/popup/Modal.tag.html | 3 +- .../src/main/web/tag/popup/NewPassword.tag.html | 4 +- .../main/web/tag/popup/ResendValidation.tag.html | 2 +- .../web/tag/voterList/VoterListActions.tag.html | 2 +- 70 files changed, 1965 insertions(+), 1552 deletions(-) diff --git a/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ReportResume.java b/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ReportResume.java new file mode 100644 index 00000000..19265ff5 --- /dev/null +++ b/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ReportResume.java @@ -0,0 +1,43 @@ +package org.chorem.pollen.persistence.entity; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ReportResume { + + protected long score; + + protected long count; + + protected long ignore; + + public ReportResume(Long score, Long count, Long ignore) { + this.score = score == null ? 0 : score; + this.count = count == null ? 0 : count; + this.ignore = ignore == null ? 0 : ignore; + } + + public long getScore() { + return score; + } + + public void setScore(long score) { + this.score = score; + } + + public long getCount() { + return count; + } + + public void setCount(long count) { + this.count = count; + } + + public long getIgnore() { + return ignore; + } + + public void setIgnore(long ignore) { + this.ignore = ignore; + } +} diff --git a/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ReportTopiaDao.java b/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ReportTopiaDao.java new file mode 100644 index 00000000..09a24ef0 --- /dev/null +++ b/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/ReportTopiaDao.java @@ -0,0 +1,26 @@ +package org.chorem.pollen.persistence.entity; + +import com.google.common.collect.Maps; + +import java.util.Map; + +public class ReportTopiaDao extends AbstractReportTopiaDao<Report> { + + public static final String REPORT_REQUEST = "SELECT new "+ ReportResume.class.getCanonicalName() +"(" + + "sum(" + Report.PROPERTY_LEVEL + "), " + + "count(*), " + + "sum(CASE WHEN " + Report.PROPERTY_IGNORE + " = true THEN 1 ELSE 0 END)) " + + "FROM " + Report.class.getCanonicalName() + " " + + "WHERE " + Report.PROPERTY_TARGET_ID + " = :" + Report.PROPERTY_TARGET_ID + " "; + + public ReportResume getReportResume(String targetId) { + + Map<String, Object> parameters = Maps.newHashMap(); + parameters.put(Report.PROPERTY_TARGET_ID, targetId); + + ReportResume report = findAnyOrNull(REPORT_REQUEST, parameters); + + return report; + } + +} //ReportingTopiaDao diff --git a/pollen-persistence/src/main/resources/db/migration/h2/V3_0_0_3__add_reports.sql b/pollen-persistence/src/main/resources/db/migration/h2/V3_0_0_3__add_reports.sql new file mode 100644 index 00000000..41ddb425 --- /dev/null +++ b/pollen-persistence/src/main/resources/db/migration/h2/V3_0_0_3__add_reports.sql @@ -0,0 +1,11 @@ +-- reporting + +CREATE TABLE REPORT ( + TOPIAID VARCHAR(255) NOT NULL PRIMARY KEY, + TOPIAVERSION BIGINT NOT NULL, + TOPIACREATEDATE TIMESTAMP, + LEVEL INTEGER, + EMAIL VARCHAR(255), + IGNORE BOOLEAN, + TARGETID VARCHAR(255) +); diff --git a/pollen-persistence/src/main/resources/db/migration/postgresql/V3_0_0_3__add_reports.sql b/pollen-persistence/src/main/resources/db/migration/postgresql/V3_0_0_3__add_reports.sql new file mode 100644 index 00000000..4762588d --- /dev/null +++ b/pollen-persistence/src/main/resources/db/migration/postgresql/V3_0_0_3__add_reports.sql @@ -0,0 +1,11 @@ +-- reporting + +CREATE TABLE report ( + topiaid character varying(255) NOT NULL PRIMARY KEY, + topiaversion bigint NOT NULL, + topiacreatedate timestamp without time zone, + level integer, + email character varying(255), + ignore boolean, + targetid character varying(255) +); diff --git a/pollen-persistence/src/main/xmi/pollen.properties b/pollen-persistence/src/main/xmi/pollen.properties index a388b72a..997cd1b8 100644 --- a/pollen-persistence/src/main/xmi/pollen.properties +++ b/pollen-persistence/src/main/xmi/pollen.properties @@ -18,7 +18,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # #L% ###m -model.tagvalue.version=3.0.0.2 +model.tagvalue.version=3.0.0.3 #model.tagValue.notGenerateToString=true #model.tagValue.constantPrefix=PROPERTY_ #model.tagValue.useEnumerationName=true diff --git a/pollen-persistence/src/main/xmi/pollen.zargo b/pollen-persistence/src/main/xmi/pollen.zargo index d62821be..2ad42e70 100644 Binary files a/pollen-persistence/src/main/xmi/pollen.zargo and b/pollen-persistence/src/main/xmi/pollen.zargo differ diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplicationListener.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplicationListener.java index 48f76140..98bdc852 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplicationListener.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplicationListener.java @@ -41,6 +41,7 @@ import org.chorem.pollen.services.bean.FavoriteListMemberBean; import org.chorem.pollen.services.bean.PaginationParameterBean; import org.chorem.pollen.services.bean.PollBean; import org.chorem.pollen.services.bean.PollenUserBean; +import org.chorem.pollen.services.bean.ReportBean; import org.chorem.pollen.services.bean.VoteBean; import org.chorem.pollen.services.bean.VoteToChoiceBean; import org.chorem.pollen.services.bean.VoterListBean; @@ -91,7 +92,8 @@ public class PollenRestApiApplicationListener implements WebMotionServerListener VoterListBean.class, VoterListMemberBean.class, PaginationParameterBean.class, - PollenUIContext.class + PollenUIContext.class, + ReportBean.class ); private Scheduler scheduler; diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceApi.java index 6d6a6a71..8db3babf 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceApi.java @@ -23,11 +23,14 @@ package org.chorem.pollen.rest.api.v1; import org.chorem.pollen.persistence.entity.Choice; import org.chorem.pollen.persistence.entity.Poll; +import org.chorem.pollen.persistence.entity.Report; import org.chorem.pollen.services.bean.ChoiceBean; import org.chorem.pollen.services.bean.PollenEntityId; import org.chorem.pollen.services.bean.PollenEntityRef; +import org.chorem.pollen.services.bean.ReportBean; import org.chorem.pollen.services.service.ChoiceService; import org.chorem.pollen.services.service.InvalidFormException; +import org.chorem.pollen.services.service.ReportService; import org.debux.webmotion.server.WebMotionController; import java.util.List; @@ -70,4 +73,21 @@ public class ChoiceApi extends WebMotionController { } + public void addReport(ReportService reportService, PollenEntityId<Poll> pollId, PollenEntityId<Choice> choiceId, ReportBean report) throws InvalidFormException { + + reportService.addChoiceReport(pollId.getEntityId(), choiceId.getEntityId(), report); + + } + + public List<ReportBean> getReports(ReportService reportService, PollenEntityId<Poll> pollId, PollenEntityId<Choice> choiceId) { + + return reportService.getChoiceReports(pollId.getEntityId(), choiceId.getEntityId()); + } + + public void ignoreReport(ReportService reportService, PollenEntityId<Poll> pollId, PollenEntityId<Choice> choiceId, PollenEntityId<Report> reportId) { + + reportService.ignoreChoiceReport(pollId.getEntityId(), choiceId.getEntityId(), reportId.getEntityId()); + + } + } diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentApi.java index d36c8bd5..f8d074e7 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentApi.java @@ -23,15 +23,20 @@ package org.chorem.pollen.rest.api.v1; import org.chorem.pollen.persistence.entity.Comment; import org.chorem.pollen.persistence.entity.Poll; +import org.chorem.pollen.persistence.entity.Report; import org.chorem.pollen.services.bean.CommentBean; import org.chorem.pollen.services.bean.PaginationParameterBean; import org.chorem.pollen.services.bean.PaginationResultBean; import org.chorem.pollen.services.bean.PollenEntityId; import org.chorem.pollen.services.bean.PollenEntityRef; +import org.chorem.pollen.services.bean.ReportBean; import org.chorem.pollen.services.service.CommentService; import org.chorem.pollen.services.service.InvalidFormException; +import org.chorem.pollen.services.service.ReportService; import org.debux.webmotion.server.WebMotionController; +import java.util.List; + /** * TODO @@ -77,4 +82,21 @@ public class CommentApi extends WebMotionController { } + public void addReport(ReportService reportService, PollenEntityId<Poll> pollId, PollenEntityId<Comment> commentId, ReportBean report) throws InvalidFormException { + + reportService.addCommentReport(pollId.getEntityId(), commentId.getEntityId(), report); + + } + + public List<ReportBean> getReports(ReportService reportService, PollenEntityId<Poll> pollId, PollenEntityId<Comment> commentId) { + + return reportService.getCommentReports(pollId.getEntityId(), commentId.getEntityId()); + } + + public void ignoreReport(ReportService reportService, PollenEntityId<Poll> pollId, PollenEntityId<Comment> commentId, PollenEntityId<Report> reportId) { + + reportService.ignoreCommentReport(pollId.getEntityId(), commentId.getEntityId(), reportId.getEntityId()); + + } + } diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollApi.java index 7df49fc3..4bc7d89f 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollApi.java @@ -24,17 +24,20 @@ package org.chorem.pollen.rest.api.v1; import com.google.common.collect.Lists; import org.chorem.pollen.persistence.entity.ChoiceType; import org.chorem.pollen.persistence.entity.Poll; +import org.chorem.pollen.persistence.entity.Report; import org.chorem.pollen.services.bean.ChoiceBean; import org.chorem.pollen.services.bean.PaginationParameterBean; import org.chorem.pollen.services.bean.PaginationResultBean; import org.chorem.pollen.services.bean.PollBean; import org.chorem.pollen.services.bean.PollenEntityId; import org.chorem.pollen.services.bean.PollenEntityRef; +import org.chorem.pollen.services.bean.ReportBean; import org.chorem.pollen.services.bean.VoterListBean; import org.chorem.pollen.services.bean.VoterListMemberBean; import org.chorem.pollen.services.service.FeedService; import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.service.PollService; +import org.chorem.pollen.services.service.ReportService; import org.debux.webmotion.server.WebMotionController; import org.debux.webmotion.server.render.Render; @@ -141,4 +144,21 @@ public class PollApi extends WebMotionController { public Render getFeedForPoll(FeedService feedService, PollenEntityId<Poll> pollId) { return renderAtom(feedService.getFeedForPoll(pollId.getEntityId())); } + + public void addReport(ReportService reportService, PollenEntityId<Poll> pollId, ReportBean report) throws InvalidFormException { + + reportService.addPollReport(pollId.getEntityId(), report); + + } + + public List<ReportBean> getReports(ReportService reportService, PollenEntityId<Poll> pollId) { + + return reportService.getPollReports(pollId.getEntityId()); + } + + public void ignoreReport(ReportService reportService, PollenEntityId<Poll> pollId, PollenEntityId<Report> reportId) { + + reportService.ignorePollReport(pollId.getEntityId(), reportId.getEntityId()); + + } } diff --git a/pollen-rest-api/src/main/resources/mapping b/pollen-rest-api/src/main/resources/mapping index 2d1c78cc..63300517 100644 --- a/pollen-rest-api/src/main/resources/mapping +++ b/pollen-rest-api/src/main/resources/mapping @@ -61,9 +61,12 @@ POST,PUT /v1/resendValidation AuthApi.resendValidation # ChoiceApi -GET /v1/polls/{pollId}/choices ChoiceApi.getChoices -POST /v1/polls/{pollId}/choices ChoiceApi.addChoice -GET /v1/polls/{pollId}/choices/{choiceId} ChoiceApi.getChoice +GET /v1/polls/{pollId}/choices ChoiceApi.getChoices +POST /v1/polls/{pollId}/choices ChoiceApi.addChoice +GET /v1/polls/{pollId}/choices/{choiceId} ChoiceApi.getChoice +POST /v1/polls/{pollId}/choices/{choiceId}/reports ChoiceApi.addReport +GET /v1/polls/{pollId}/choices/{choiceId}/reports ChoiceApi.getReports +GET /v1/polls/{pollId}/choices/{choiceId}/reports/{reportId}/ignore ChoiceApi.ignoreReport #fix me POST,PUT /v1/polls/{pollId}/choices/{choiceId} ChoiceApi.editChoice @@ -72,12 +75,15 @@ DELETE /v1/polls/{pollId}/choices/{choiceId} ChoiceApi.deleteChoice # CommentApi -GET /v1/polls/{pollId}/comments CommentApi.getComments -POST /v1/polls/{pollId}/comments CommentApi.addComment -GET /v1/polls/{pollId}/comments/new CommentApi.getNewComment -GET /v1/polls/{pollId}/comments/{commentId} CommentApi.getComment -PUT,POST /v1/polls/{pollId}/comments/{commentId} CommentApi.editComment -DELETE /v1/polls/{pollId}/comments/{commentId} CommentApi.deleteComment +GET /v1/polls/{pollId}/comments CommentApi.getComments +POST /v1/polls/{pollId}/comments CommentApi.addComment +GET /v1/polls/{pollId}/comments/new CommentApi.getNewComment +GET /v1/polls/{pollId}/comments/{commentId} CommentApi.getComment +PUT,POST /v1/polls/{pollId}/comments/{commentId} CommentApi.editComment +DELETE /v1/polls/{pollId}/comments/{commentId} CommentApi.deleteComment +POST /v1/polls/{pollId}/comments/{commentId}/reports CommentApi.addReport +GET /v1/polls/{pollId}/comments/{commentId}/reports CommentApi.getReports +GET /v1/polls/{pollId}/comments/{commentId}/reports/{reportId}/ignore CommentApi.ignoreReport # FavoriteListApi @@ -104,30 +110,34 @@ DELETE /v1/favoriteLists/{favoriteListId}/lists/{childListId} FavoriteListApi. # PollApi -GET /v1/polls/new PollApi.getNewPoll -GET /v1/polls PollApi.getPolls -GET /v1/polls/created PollApi.getCreatedPolls -GET /v1/polls/invited PollApi.getInvitedPolls -GET /v1/polls/participated PollApi.getParticipatedPolls -POST /v1/polls PollApi.createPoll -POST,GET /v1/polls/create PollApi.createPoll -GET /v1/polls/edit PollApi.editPoll +GET /v1/polls/new PollApi.getNewPoll +GET /v1/polls PollApi.getPolls +GET /v1/polls/created PollApi.getCreatedPolls +GET /v1/polls/invited PollApi.getInvitedPolls +GET /v1/polls/participated PollApi.getParticipatedPolls +POST /v1/polls PollApi.createPoll +POST,GET /v1/polls/create PollApi.createPoll +GET /v1/polls/edit PollApi.editPoll #fix me -POST,PUT /v1/polls/{pollId} PollApi.editPoll -POST /v1/polls/{pollId}/edit PollApi.editPoll +POST,PUT /v1/polls/{pollId} PollApi.editPoll +POST /v1/polls/{pollId}/edit PollApi.editPoll -GET /v1/polls/{pollId} PollApi.getPoll -DELETE /v1/polls/{pollId} PollApi.deletePoll +GET /v1/polls/{pollId} PollApi.getPoll +DELETE /v1/polls/{pollId} PollApi.deletePoll -POST /v1/polls/{pollId}/clone PollApi.clonePoll +POST /v1/polls/{pollId}/clone PollApi.clonePoll -GET /v1/polls/{pollId}/export PollApi.exportPoll -PUT /v1/polls/{pollId}/close PollApi.closePoll -PUT /v1/polls/{pollId}/reopen PollApi.reopenPoll -PUT /v1/polls/{pollId}/assign PollApi.assignPoll +GET /v1/polls/{pollId}/export PollApi.exportPoll +PUT /v1/polls/{pollId}/close PollApi.closePoll +PUT /v1/polls/{pollId}/reopen PollApi.reopenPoll +PUT /v1/polls/{pollId}/assign PollApi.assignPoll -GET /v1/polls/{pollId}/feed PollApi.getFeedForPoll +GET /v1/polls/{pollId}/feed PollApi.getFeedForPoll + +POST /v1/polls/{pollId}/reports PollApi.addReport +GET /v1/polls/{pollId}/reports PollApi.getReports +GET /v1/polls/{pollId}/reports/{reportId}/ignore PollApi.ignoreReport # PollenResourceApi diff --git a/pollen-services/src/main/config/PollenServices.ini b/pollen-services/src/main/config/PollenServices.ini index ac25e9bb..147756c5 100644 --- a/pollen-services/src/main/config/PollenServices.ini +++ b/pollen-services/src/main/config/PollenServices.ini @@ -164,4 +164,10 @@ type = string description = pollen.configuration.resendEmailsCronSchedule key = pollen.resendEmailsCronSchedule type = string -defaultValue = "0 0/5 * * * ?" \ No newline at end of file +defaultValue = "0 0/5 * * * ?" + +[option reportMaxScore] +description = pollen.configuration.report.maxScore +key = pollen.report.maxScore +type = long +defaultValue = 100 \ No newline at end of file diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/PollenUIContext.java b/pollen-services/src/main/java/org/chorem/pollen/services/PollenUIContext.java index 01d0a137..e2b07a45 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/PollenUIContext.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/PollenUIContext.java @@ -17,6 +17,7 @@ public class PollenUIContext implements Serializable { private String pollEditUrl; + private String resourceUrl; public String getUiEndPoint() { return uiEndPoint; @@ -57,4 +58,12 @@ public class PollenUIContext implements Serializable { public void setPollEditUrl(String pollEditUrl) { this.pollEditUrl = pollEditUrl; } + + public String getResourceUrl() { + return resourceUrl; + } + + public void setResourceUrl(String resourceUrl) { + this.resourceUrl = resourceUrl; + } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/ChoiceBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/ChoiceBean.java index 61df736a..7f8d42e5 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/bean/ChoiceBean.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/ChoiceBean.java @@ -45,6 +45,8 @@ public class ChoiceBean extends PollenBean<Choice> { protected boolean choiceIsDeletable; + protected ReportResumeBean report; + public ChoiceBean() { super(Choice.class); } @@ -124,4 +126,12 @@ public class ChoiceBean extends PollenBean<Choice> { public void setChoiceIsDeletable(boolean choiceIsDeletable) { this.choiceIsDeletable = choiceIsDeletable; } + + public ReportResumeBean getReport() { + return report; + } + + public void setReport(ReportResumeBean report) { + this.report = report; + } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/CommentBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/CommentBean.java index de911b15..e4d235da 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/bean/CommentBean.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/CommentBean.java @@ -43,6 +43,8 @@ public class CommentBean extends PollenBean<Comment> { protected Date postDate; + protected ReportResumeBean report; + public CommentBean() { super(Comment.class); } @@ -120,4 +122,12 @@ public class CommentBean extends PollenBean<Comment> { public void setAuthorName(String authorName) { this.authorName = authorName; } + + public ReportResumeBean getReport() { + return report; + } + + public void setReport(ReportResumeBean report) { + this.report = report; + } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollBean.java index 806ab670..3a64b9d2 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollBean.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollBean.java @@ -137,6 +137,8 @@ public class PollBean extends PollenBean<Poll> { protected String notificationLocale; + protected ReportResumeBean report; + @Override public void fromEntity(Poll entity) { @@ -528,4 +530,12 @@ public class PollBean extends PollenBean<Poll> { public void setParticipantCount(long participantCount) { this.participantCount = participantCount; } + + public ReportResumeBean getReport() { + return report; + } + + public void setReport(ReportResumeBean report) { + this.report = report; + } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/ReportBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/ReportBean.java new file mode 100644 index 00000000..1b8f209b --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/ReportBean.java @@ -0,0 +1,65 @@ +package org.chorem.pollen.services.bean; + +import org.chorem.pollen.persistence.entity.Report; +import org.chorem.pollen.persistence.entity.ReportImpl; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ReportBean extends PollenBean<Report> { + + protected ReportLevel level; + + protected String email; + + protected boolean ignore; + + public ReportBean() { + super(Report.class); + } + + public ReportLevel getLevel() { + return level; + } + + public void setLevel(ReportLevel level) { + this.level = level; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public boolean isIgnore() { + return ignore; + } + + public void setIgnore(boolean ignore) { + this.ignore = ignore; + } + + @Override + public void fromEntity(Report entity) { + setEntityId(entity.getTopiaId()); + + setLevel(ReportLevel.of(entity.getLevel())); + setEmail(entity.getEmail()); + setIgnore(entity.isIgnore()); + } + + @Override + public Report toEntity() { + Report entity = new ReportImpl(); + + entity.setTopiaId(getEntityId()); + entity.setLevel(getLevel().getScore()); + entity.setEmail(getEmail()); + entity.setIgnore(isIgnore()); + + return entity; + } +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/ReportLevel.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/ReportLevel.java new file mode 100644 index 00000000..7eb76378 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/ReportLevel.java @@ -0,0 +1,30 @@ +package org.chorem.pollen.services.bean; + +import java.util.stream.Stream; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public enum ReportLevel { + + OFF_TOPIC(1), + SPAM(5), + ILLEGAL(100); + + protected int score; + + ReportLevel(int score) { + this.score = score; + } + + public int getScore() { + return score; + } + + public static ReportLevel of(int score) { + return Stream.of(values()) + .filter(level -> score == level.getScore()) + .findAny() + .orElse(null); + } +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/ReportResumeBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/ReportResumeBean.java new file mode 100644 index 00000000..bb46b5c7 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/ReportResumeBean.java @@ -0,0 +1,53 @@ +package org.chorem.pollen.services.bean; + +import org.chorem.pollen.persistence.entity.ReportResume; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ReportResumeBean { + + public static ReportResumeBean of(ReportResume report) { + ReportResumeBean reportBean = null; + + if (report.getCount() > 0) { + + reportBean = new ReportResumeBean(); + + reportBean.setScore(report.getScore()); + reportBean.setCount(report.getCount()); + reportBean.setIgnore(report.getIgnore()); + } + return reportBean; + } + + protected long score; + + protected long count; + + protected long ignore; + + public long getScore() { + return score; + } + + public void setScore(long score) { + this.score = score; + } + + public long getCount() { + return count; + } + + public void setCount(long count) { + this.count = count; + } + + public long getIgnore() { + return ignore; + } + + public void setIgnore(long ignore) { + this.ignore = ignore; + } +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/VoteBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/VoteBean.java index 0f138661..3be138ca 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/bean/VoteBean.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/VoteBean.java @@ -59,6 +59,8 @@ public class VoteBean extends PollenBean<Vote> { protected final Set<VoteToChoiceBean> choice = new LinkedHashSet<>(); + private ReportResumeBean report; + public VoteBean() { super(Vote.class); } @@ -200,4 +202,12 @@ public class VoteBean extends PollenBean<Vote> { public void setWeight(double weight) { this.weight = weight; } + + public void setReport(ReportResumeBean report) { + this.report = report; + } + + public ReportResumeBean getReport() { + return report; + } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java index a35790aa..e3c908b5 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java @@ -31,6 +31,7 @@ import org.chorem.pollen.persistence.entity.PollenPrincipal; import org.chorem.pollen.persistence.entity.PollenResource; import org.chorem.pollen.services.bean.ChoiceBean; import org.chorem.pollen.services.bean.PollenEntityRef; +import org.chorem.pollen.services.bean.ReportResumeBean; import org.chorem.pollen.services.service.security.PermissionVerb; import java.util.Calendar; @@ -52,6 +53,9 @@ public class ChoiceService extends PollenServiceSupport { protected final Function<ChoiceBean, ChoiceBean> choiceBeanFunction = input -> { if (isNotPermitted(PermissionVerb.editChoice, input.getEntityId())) { input.setPermission(null); + } else { + ReportResumeBean report = getReportService().getReport(input.getEntityId()); + input.setReport(report); } if (input.getChoiceType() == ChoiceType.RESOURCE) { diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java index eb2a2cd1..91642546 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java @@ -30,6 +30,7 @@ import org.chorem.pollen.services.bean.CommentBean; import org.chorem.pollen.services.bean.PaginationParameterBean; import org.chorem.pollen.services.bean.PaginationResultBean; import org.chorem.pollen.services.bean.PollenEntityRef; +import org.chorem.pollen.services.bean.ReportResumeBean; import org.chorem.pollen.services.service.security.PermissionVerb; import org.nuiton.util.pagination.PaginationParameter; import org.nuiton.util.pagination.PaginationResult; @@ -49,6 +50,9 @@ public class CommentService extends PollenServiceSupport { private final Function<CommentBean, CommentBean> commentFunction = input -> { if (isNotPermitted(PermissionVerb.editComment, input.getEntityId())) { input.setPermission(null); + } else { + ReportResumeBean report = getReportService().getReport(input.getEntityId()); + input.setReport(report); } return input; }; diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromLdap.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromLdap.java index bb8d4468..1b9210ca 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromLdap.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromLdap.java @@ -93,9 +93,10 @@ public class FavoriteListImportFromLdap extends PollenServiceSupport implements Pattern loginLdapPattern = Pattern.compile("ldaps?://(([^:]+):([^@]+)@)?.*"); Matcher matcher = loginLdapPattern.matcher(ldap); if (matcher.find() && matcher.group(1) != null) { + env.put(Context.SECURITY_AUTHENTICATION, "simple"); if (matcher.group(2) != null) { String login = URLDecoder.decode(matcher.group(2), "UTF-8"); - env.put(Context.SECURITY_PRINCIPAL, login); + env.put(Context.SECURITY_PRINCIPAL, "cn=" + login); } if (matcher.group(3) != null) { String password = URLDecoder.decode(matcher.group(3), "UTF-8"); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java index d132ee2f..90fce101 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java @@ -28,20 +28,27 @@ import org.chorem.pollen.persistence.entity.FavoriteList; import org.chorem.pollen.persistence.entity.Poll; import org.chorem.pollen.persistence.entity.PollType; import org.chorem.pollen.persistence.entity.PollenUser; +import org.chorem.pollen.persistence.entity.Report; import org.chorem.pollen.persistence.entity.Vote; import org.chorem.pollen.persistence.entity.VoterList; import org.chorem.pollen.persistence.entity.VoterListMember; import org.chorem.pollen.services.PollenUIContext; import org.chorem.pollen.services.service.mail.ChoiceAddedEmail; +import org.chorem.pollen.services.service.mail.ChoiceReportEmail; +import org.chorem.pollen.services.service.mail.ChoiceReportForAdminEmail; import org.chorem.pollen.services.service.mail.CommentAddedEmail; import org.chorem.pollen.services.service.mail.CommentDeletedEmail; import org.chorem.pollen.services.service.mail.CommentEditedEmail; +import org.chorem.pollen.services.service.mail.CommentReportEmail; +import org.chorem.pollen.services.service.mail.CommentReportForAdminEmail; import org.chorem.pollen.services.service.mail.EmailService; import org.chorem.pollen.services.service.mail.LostPasswordEmail; import org.chorem.pollen.services.service.mail.PollClosedEmail; import org.chorem.pollen.services.service.mail.PollCreatedEmail; import org.chorem.pollen.services.service.mail.PollEndReminderEmail; import org.chorem.pollen.services.service.mail.PollInvitationEmail; +import org.chorem.pollen.services.service.mail.PollReportEmail; +import org.chorem.pollen.services.service.mail.PollReportForAdminEmail; import org.chorem.pollen.services.service.mail.ResendValidationEmail; import org.chorem.pollen.services.service.mail.RestrictedPollInvitationEmail; import org.chorem.pollen.services.service.mail.UserAccountCreatedEmail; @@ -52,7 +59,9 @@ import org.chorem.pollen.services.service.mail.UserAccountPasswordChangedEmail; import org.chorem.pollen.services.service.mail.VoteAddedEmail; import org.chorem.pollen.services.service.mail.VoteDeletedEmail; import org.chorem.pollen.services.service.mail.VoteEditedEmail; +import org.nuiton.topia.persistence.TopiaEntity; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -296,4 +305,84 @@ public class NotificationService extends PollenServiceSupport { pollEndReminderEmail.addTo(poll.getCreator().getEmail()); emailService.send(pollEndReminderEmail); } + + public void onAddCommentReport(Poll poll, Comment comment, Report report) { + + EmailService emailService = getEmailService(); + + // email to poll creator + if (StringUtils.isNotBlank(poll.getCreator().getEmail())) { + CommentReportEmail commentReportEmail = emailService.newCommentReportEmail(poll, comment, report); + + commentReportEmail.addTo(poll.getCreator().getEmail()); + emailService.send(commentReportEmail); + } + + // email to administrators + getAdminsToSentReport(poll, comment).forEach(admin -> { + CommentReportForAdminEmail commentReportForAdminEmail = emailService.newCommentReportForAdminEmail(poll, comment, report, admin); + + commentReportForAdminEmail.addTo(admin.getEmail()); + emailService.send(commentReportForAdminEmail); + }); + + } + + protected List<PollenUser> getAdminsToSentReport(Poll poll, TopiaEntity target) { + long score = getReportService().getScore(target); + + List<PollenUser> admins = Collections.emptyList(); + + if (StringUtils.isBlank(poll.getCreator().getEmail()) || score >= getPollenServiceConfig().getReportMaxScore()) { + + admins = getPollenUserDao().forAdministratorEquals(true).findAll(); + + } + + return admins; + } + + public void onAddChoiceReport(Poll poll, Choice choice, Report report) { + + EmailService emailService = getEmailService(); + + // email to poll creator + if (StringUtils.isNotBlank(poll.getCreator().getEmail())) { + ChoiceReportEmail choiceReportEmail = emailService.newChoiceReportEmail(poll, choice, report); + + choiceReportEmail.addTo(poll.getCreator().getEmail()); + emailService.send(choiceReportEmail); + } + + // email to administrators + getAdminsToSentReport(poll, choice).forEach(admin -> { + ChoiceReportForAdminEmail choiceReportForAdminEmail = emailService.newChoiceReportForAdminEmail(poll, choice, report, admin); + + choiceReportForAdminEmail.addTo(admin.getEmail()); + emailService.send(choiceReportForAdminEmail); + }); + + } + + public void onAddPollReport(Poll poll, Report report) { + + EmailService emailService = getEmailService(); + + // email to poll creator + if (StringUtils.isNotBlank(poll.getCreator().getEmail())) { + PollReportEmail pollReportEmail = emailService.newPollReportEmail(poll, report); + + pollReportEmail.addTo(poll.getCreator().getEmail()); + emailService.send(pollReportEmail); + } + + // email to administrators + getAdminsToSentReport(poll, poll).forEach(admin -> { + PollReportForAdminEmail pollReportForAdminEmail = emailService.newPollReportForAdminEmail(poll, report, admin); + + pollReportForAdminEmail.addTo(admin.getEmail()); + emailService.send(pollReportForAdminEmail); + }); + + } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java index 4e572fa9..3b270f76 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java @@ -36,6 +36,7 @@ import org.chorem.pollen.services.bean.PaginationParameterBean; import org.chorem.pollen.services.bean.PaginationResultBean; import org.chorem.pollen.services.bean.PollBean; import org.chorem.pollen.services.bean.PollenEntityRef; +import org.chorem.pollen.services.bean.ReportResumeBean; import org.chorem.pollen.services.bean.VoterListBean; import org.chorem.pollen.services.bean.VoterListMemberBean; import org.chorem.pollen.services.config.PollenServicesConfig; @@ -71,6 +72,9 @@ public class PollService extends PollenServiceSupport { input.setCreatorEmail(null); input.setCreatorName(null); + } else { + ReportResumeBean report = getReportService().getReport(input.getEntityId()); + input.setReport(report); } boolean commentIsVisible = isPermitted(PermissionVerb.readComment, input.getEntityId()); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java index f78d185a..88b0a6ca 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java @@ -39,6 +39,7 @@ import org.chorem.pollen.persistence.entity.PollenPrincipalTopiaDao; import org.chorem.pollen.persistence.entity.PollenResourceTopiaDao; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.persistence.entity.PollenUserTopiaDao; +import org.chorem.pollen.persistence.entity.ReportTopiaDao; import org.chorem.pollen.persistence.entity.SessionTokenTopiaDao; import org.chorem.pollen.persistence.entity.VoteToChoiceTopiaDao; import org.chorem.pollen.persistence.entity.VoteTopiaDao; @@ -142,6 +143,10 @@ public abstract class PollenServiceSupport implements PollenService { return newService(SecurityService.class); } + protected ReportService getReportService() { + return newService(ReportService.class); + } + protected PollenResourceService getPollenResourceService() { return newService(PollenResourceService.class); } @@ -208,6 +213,10 @@ public abstract class PollenServiceSupport implements PollenService { return getPersistenceContext().getPollenUserDao(); } + protected ReportTopiaDao getReportTopiaDao() { + return getPersistenceContext().getReportDao(); + } + protected SessionTokenTopiaDao getSessionTokenDao() { return getPersistenceContext().getSessionTokenDao(); } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUIUrlRenderService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUIUrlRenderService.java index 31c11eed..6b7f4573 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUIUrlRenderService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUIUrlRenderService.java @@ -96,4 +96,15 @@ public class PollenUIUrlRenderService extends PollenServiceSupport { } return url; } + + public String getResourceUrl(String resourceUrl, String resourceId) { + String url = null; + + if (resourceUrl != null) { + checkNotNull(resourceId); + + url = resourceUrl.replace("{resourceId}", resourceId); + } + return url; + } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/ReportService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/ReportService.java new file mode 100644 index 00000000..746db08e --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/ReportService.java @@ -0,0 +1,191 @@ +package org.chorem.pollen.services.service; + +import org.chorem.pollen.persistence.entity.Choice; +import org.chorem.pollen.persistence.entity.Comment; +import org.chorem.pollen.persistence.entity.Poll; +import org.chorem.pollen.persistence.entity.Report; +import org.chorem.pollen.persistence.entity.ReportResume; +import org.chorem.pollen.services.bean.ReportBean; +import org.chorem.pollen.services.bean.ReportResumeBean; +import org.chorem.pollen.services.service.security.PermissionVerb; +import org.nuiton.topia.persistence.TopiaEntity; + +import java.util.List; + +import static org.nuiton.i18n.I18n.l; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ReportService extends PollenServiceSupport { + + + public void addPollReport(String pollId, ReportBean reportBean) throws InvalidFormException { + + checkNotNull(pollId); + checkPermission(PermissionVerb.readPoll, pollId); + + Poll poll = getPollService().getPoll0(pollId); + + Report report = getReportService().addReport(reportBean, poll); + + getNotificationService().onAddPollReport(poll, report); + + } + + public List<ReportBean> getPollReports(String pollId) { + + checkNotNull(pollId); + checkPermission(PermissionVerb.editPoll, pollId); + + return getReportService().getReports(pollId); + + } + + public void ignorePollReport(String pollId, String reportId) { + checkNotNull(pollId); + checkNotNull(reportId); + checkPermission(PermissionVerb.editPoll, pollId); + + ignoreReport(reportId, pollId); + } + + public void addChoiceReport(String pollId, String choiceId, ReportBean reportBean) throws InvalidFormException { + + checkNotNull(pollId); + checkNotNull(choiceId); + checkPermission(PermissionVerb.readChoice, choiceId); + + Poll poll = getPollService().getPoll0(pollId); + + Choice choice = getChoiceService().getChoice(poll, choiceId); + + Report report = getReportService().addReport(reportBean, choice); + + getNotificationService().onAddChoiceReport(poll, choice, report); + + } + + public List<ReportBean> getChoiceReports(String pollId, String choiceId) { + + checkNotNull(pollId); + checkNotNull(choiceId); + checkPermission(PermissionVerb.editPoll, pollId); + + return getReportService().getReports(choiceId); + + } + + public void ignoreChoiceReport(String pollId, String choiceId, String reportId) { + checkNotNull(pollId); + checkNotNull(choiceId); + checkNotNull(reportId); + checkPermission(PermissionVerb.editPoll, pollId); + + ignoreReport(reportId, choiceId); + } + + public void addCommentReport(String pollId, String commentId, ReportBean reportBean) throws InvalidFormException { + + checkNotNull(pollId); + checkNotNull(commentId); + checkPermission(PermissionVerb.readComment, commentId); + + Poll poll = getPollService().getPoll0(pollId); + + Comment comment = getCommentService().getComment(poll, commentId); + + Report report = getReportService().addReport(reportBean, comment); + + getNotificationService().onAddCommentReport(poll, comment, report); + + } + + public List<ReportBean> getCommentReports(String pollId, String commentId) { + + checkNotNull(pollId); + checkNotNull(commentId); + checkPermission(PermissionVerb.editPoll, pollId); + + return getReportService().getReports(commentId); + + } + + public void ignoreCommentReport(String pollId, String commentId, String reportId) { + checkNotNull(pollId); + checkNotNull(commentId); + checkNotNull(reportId); + checkPermission(PermissionVerb.editPoll, pollId); + + ignoreReport(reportId, commentId); + } + + + protected List<ReportBean> getReports(String targetId) { + checkNotNull(targetId); + + List<Report> reports = getReportTopiaDao().forTargetIdEquals(targetId).findAll(); + + return toBeanList(ReportBean.class, reports); + } + + protected Report addReport(ReportBean report, TopiaEntity target) throws InvalidFormException { + + checkNotNull(report); + checkIsNotPersisted(report); + + checkNotNull(target); + checkIsPersisted(target); + + ErrorMap errorMap = checkReport(report); + errorMap.failIfNotEmpty(); + + Report reportEntity = report.toEntity(); + reportEntity.setTargetId(target.getTopiaId()); + + reportEntity = getReportTopiaDao().create(reportEntity); + + commit(); + + return reportEntity; + + } + + protected ErrorMap checkReport(ReportBean report) { + ErrorMap errors = new ErrorMap(); + + checkNotNull(errors, Report.PROPERTY_LEVEL, report.getLevel(), l(getLocale(), "pollen.error.report.level.mandatory")); + checkNotNull(errors, Report.PROPERTY_EMAIL, report.getEmail(), l(getLocale(), "pollen.error.report.email.mandatory")); + checkValidEmail(errors, Report.PROPERTY_EMAIL, report.getEmail(), l(getLocale(), "pollen.error.report.email.invalid")); + + return errors; + } + + protected void ignoreReport(String reportId, String targetId) { + + checkNotNull(reportId); + checkNotNull(targetId); + + Report report = getReportTopiaDao() + .forTopiaIdEquals(reportId) + .addEquals(Report.PROPERTY_TARGET_ID, targetId) + .findUnique(); + + report.setIgnore(true); + + commit(); + } + + public ReportResumeBean getReport(String targetId) { + + ReportResume report = getReportTopiaDao().getReportResume(targetId); + + return ReportResumeBean.of(report); + } + + public long getScore(TopiaEntity target) { + + ReportResume report = getReportTopiaDao().getReportResume(target.getTopiaId()); + return report.getScore(); + } +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java index ab933ac4..d526b1f9 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java @@ -34,6 +34,7 @@ import org.chorem.pollen.persistence.entity.VoterList; import org.chorem.pollen.persistence.entity.VoterListMember; import org.chorem.pollen.services.bean.ChoiceBean; import org.chorem.pollen.services.bean.PollenEntityRef; +import org.chorem.pollen.services.bean.ReportResumeBean; import org.chorem.pollen.services.bean.VoteBean; import org.chorem.pollen.services.bean.VoteToChoiceBean; import org.chorem.pollen.services.service.security.PermissionVerb; @@ -63,6 +64,9 @@ public class VoteService extends PollenServiceSupport { if (input.isAnonymous()) { input.setVoterName(null); } + } else { + ReportResumeBean report = getReportService().getReport(input.getEntityId()); + input.setReport(report); } return input; }; diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/AbstractReportEmail.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/AbstractReportEmail.java new file mode 100644 index 00000000..9f3cd340 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/AbstractReportEmail.java @@ -0,0 +1,70 @@ +package org.chorem.pollen.services.service.mail; + +import org.chorem.pollen.persistence.entity.Poll; +import org.chorem.pollen.persistence.entity.Report; +import org.chorem.pollen.services.bean.ReportLevel; +import org.nuiton.topia.persistence.TopiaEntity; + +import java.util.Locale; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public abstract class AbstractReportEmail<T extends TopiaEntity> extends PollenMail { + + protected Poll poll; + + protected T target; + + protected Report report; + + protected String url; + + public AbstractReportEmail(Locale locale) { + super(locale); + } + + public Poll getPoll() { + return poll; + } + + public void setPoll(Poll poll) { + this.poll = poll; + } + + public T getTarget() { + return target; + } + + public void setTarget(T target) { + this.target = target; + } + + public Report getReport() { + return report; + } + + public void setReport(Report report) { + this.report = report; + } + + public boolean isIllegal() { + return ReportLevel.ILLEGAL.getScore() == report.getLevel(); + } + + public boolean isSpam() { + return ReportLevel.SPAM.getScore() == report.getLevel(); + } + + public boolean isOffTopic() { + return ReportLevel.OFF_TOPIC.getScore() == report.getLevel(); + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/AbstractReportForAdminEmail.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/AbstractReportForAdminEmail.java new file mode 100644 index 00000000..a5544bc3 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/AbstractReportForAdminEmail.java @@ -0,0 +1,49 @@ +package org.chorem.pollen.services.service.mail; + +import org.chorem.pollen.persistence.entity.PollenUser; +import org.chorem.pollen.persistence.entity.Report; +import org.chorem.pollen.persistence.entity.ReportResume; +import org.nuiton.topia.persistence.TopiaEntity; + +import java.util.List; +import java.util.Locale; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public abstract class AbstractReportForAdminEmail<T extends TopiaEntity> extends AbstractReportEmail<T> { + + protected PollenUser administrator; + + protected List<Report> reports; + + protected ReportResume resume; + + public AbstractReportForAdminEmail(Locale locale) { + super(locale); + } + + public PollenUser getAdministrator() { + return administrator; + } + + public void setAdministrator(PollenUser administrator) { + this.administrator = administrator; + } + + public List<Report> getReports() { + return reports; + } + + public void setReports(List<Report> reports) { + this.reports = reports; + } + + public ReportResume getResume() { + return resume; + } + + public void setResume(ReportResume resume) { + this.resume = resume; + } +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/ChoiceReportEmail.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/ChoiceReportEmail.java new file mode 100644 index 00000000..ec4bf50c --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/ChoiceReportEmail.java @@ -0,0 +1,35 @@ +package org.chorem.pollen.services.service.mail; + +import org.chorem.pollen.persistence.entity.Choice; +import org.nuiton.i18n.I18n; + +import java.util.Locale; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ChoiceReportEmail extends AbstractReportEmail<Choice> { + + private String choiceValue; + + public ChoiceReportEmail(Locale locale) { + super(locale); + } + + @Override + public String getSubject() { + return I18n.l(locale, "pollen.service.mail.ChoiceReportEmail.subject", poll.getTitle()); + } + + public String getChoiceValue() { + return choiceValue; + } + + public void setChoiceValue(String choiceValue) { + this.choiceValue = choiceValue; + } + + public String getChoiceCreateDate() { + return formatDate(target.getTopiaCreateDate()); + } +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/ChoiceReportForAdminEmail.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/ChoiceReportForAdminEmail.java new file mode 100644 index 00000000..86a51ccf --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/ChoiceReportForAdminEmail.java @@ -0,0 +1,35 @@ +package org.chorem.pollen.services.service.mail; + +import org.chorem.pollen.persistence.entity.Choice; +import org.nuiton.i18n.I18n; + +import java.util.Locale; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ChoiceReportForAdminEmail extends AbstractReportForAdminEmail<Choice> { + + private String choiceValue; + + public ChoiceReportForAdminEmail(Locale locale) { + super(locale); + } + + @Override + public String getSubject() { + return I18n.l(locale, "pollen.service.mail.ChoiceReportForAdminEmail.subject", poll.getTitle()); + } + + public String getChoiceValue() { + return choiceValue; + } + + public void setChoiceValue(String choiceValue) { + this.choiceValue = choiceValue; + } + + public String getChoiceCreateDate() { + return formatDate(target.getTopiaCreateDate()); + } +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/CommentReportEmail.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/CommentReportEmail.java new file mode 100644 index 00000000..2c841968 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/CommentReportEmail.java @@ -0,0 +1,26 @@ +package org.chorem.pollen.services.service.mail; + +import org.chorem.pollen.persistence.entity.Comment; +import org.nuiton.i18n.I18n; + +import java.util.Locale; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class CommentReportEmail extends AbstractReportEmail<Comment> { + + public CommentReportEmail(Locale locale) { + super(locale); + } + + @Override + public String getSubject() { + return I18n.l(locale, "pollen.service.mail.CommentReportEmail.subject", poll.getTitle()); + } + + public String getCommentPostDate() { + return formatDate(target.getPostDate()); + } + +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/CommentReportForAdminEmail.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/CommentReportForAdminEmail.java new file mode 100644 index 00000000..7db8bf08 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/CommentReportForAdminEmail.java @@ -0,0 +1,26 @@ +package org.chorem.pollen.services.service.mail; + +import org.chorem.pollen.persistence.entity.Comment; +import org.nuiton.i18n.I18n; + +import java.util.Locale; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class CommentReportForAdminEmail extends AbstractReportForAdminEmail<Comment> { + + public CommentReportForAdminEmail(Locale locale) { + super(locale); + } + + @Override + public String getSubject() { + return I18n.l(locale, "pollen.service.mail.CommentReportForAdminEmail.subject", poll.getTitle()); + } + + public String getCommentPostDate() { + return formatDate(target.getPostDate()); + } + +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java index de62686e..8552b21c 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java @@ -41,7 +41,9 @@ import org.chorem.pollen.persistence.entity.EmailToResendImpl; import org.chorem.pollen.persistence.entity.EmailToResendTopiaDao; import org.chorem.pollen.persistence.entity.Poll; import org.chorem.pollen.persistence.entity.PollenPrincipal; +import org.chorem.pollen.persistence.entity.PollenResource; import org.chorem.pollen.persistence.entity.PollenUser; +import org.chorem.pollen.persistence.entity.Report; import org.chorem.pollen.persistence.entity.Vote; import org.chorem.pollen.services.PollenUIContext; import org.chorem.pollen.services.bean.PollenEntityId; @@ -53,6 +55,7 @@ import org.nuiton.topia.persistence.TopiaConfigurationBuilder; import java.io.StringWriter; import java.util.Arrays; import java.util.Collection; +import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Locale; @@ -414,4 +417,146 @@ public class EmailService extends PollenServiceSupport { return stringWriter.toString(); } + public CommentReportEmail newCommentReportEmail(Poll poll, Comment comment, Report report) { + // FIXME BAVENCOFF 15/06/2017 la local du mail devrait etre celle du destinataire + CommentReportEmail email = new CommentReportEmail(getLocale()); + email.setPoll(poll); + email.setTarget(comment); + + comment.getAuthor().getName(); //FIXME BAVENCOFF 14/06/2017 pb de lazy hibernate + + email.setReport(report); + + PollenEntityId<Poll> pollId = getPollenEntityId(poll); + String pollUrl = getPollenUIUrlRenderService().getPollVoteUrl( + getUIContext().getPollVoteUrl(), + pollId.getReducedId(), + poll.getCreator().getPermission().getToken()); + email.setUrl(pollUrl); + + return email; + } + + public CommentReportForAdminEmail newCommentReportForAdminEmail(Poll poll, Comment comment, Report report, PollenUser admin) { + // FIXME BAVENCOFF 15/06/2017 la local du mail devrait etre celle du destinataire + CommentReportForAdminEmail email = new CommentReportForAdminEmail(getLocale()); + email.setPoll(poll); + email.setTarget(comment); + + comment.getAuthor().getName(); //FIXME BAVENCOFF 14/06/2017 pb de lazy hibernate + + email.setReport(report); + + PollenEntityId<Poll> pollId = getPollenEntityId(poll); + String pollUrl = getPollenUIUrlRenderService().getPollVoteUrl( + getUIContext().getPollVoteUrl(), + pollId.getReducedId(), + null); + email.setUrl(pollUrl); + + email.setAdministrator(admin); + email.setReports(getReportTopiaDao().forTargetIdEquals(comment.getTopiaId()).findAll()); + email.setResume(getReportTopiaDao().getReportResume(comment.getTopiaId())); + + return email; + } + + public ChoiceReportEmail newChoiceReportEmail(Poll poll, Choice choice, Report report) { + // FIXME BAVENCOFF 15/06/2017 la local du mail devrait etre celle du destinataire + ChoiceReportEmail email = new ChoiceReportEmail(getLocale()); + email.setPoll(poll); + email.setTarget(choice); + email.setReport(report); + email.setChoiceValue(getChoiceValue(choice)); + + PollenEntityId<Poll> pollId = getPollenEntityId(poll); + String pollUrl = getPollenUIUrlRenderService().getPollVoteUrl( + getUIContext().getPollVoteUrl(), + pollId.getReducedId(), + poll.getCreator().getPermission().getToken()); + email.setUrl(pollUrl); + + return email; + } + + public ChoiceReportForAdminEmail newChoiceReportForAdminEmail(Poll poll, Choice choice, Report report, PollenUser admin) { + // FIXME BAVENCOFF 15/06/2017 la local du mail devrait etre celle du destinataire + ChoiceReportForAdminEmail email = new ChoiceReportForAdminEmail(getLocale()); + email.setPoll(poll); + email.setTarget(choice); + email.setReport(report); + email.setChoiceValue(getChoiceValue(choice)); + + PollenEntityId<Poll> pollId = getPollenEntityId(poll); + String pollUrl = getPollenUIUrlRenderService().getPollVoteUrl( + getUIContext().getPollVoteUrl(), + pollId.getReducedId(), + null); + email.setUrl(pollUrl); + + email.setAdministrator(admin); + email.setReports(getReportTopiaDao().forTargetIdEquals(choice.getTopiaId()).findAll()); + email.setResume(getReportTopiaDao().getReportResume(choice.getTopiaId())); + + return email; + } + + public PollReportEmail newPollReportEmail(Poll poll, Report report) { + // FIXME BAVENCOFF 15/06/2017 la local du mail devrait etre celle du destinataire + PollReportEmail email = new PollReportEmail(getLocale()); + email.setPoll(poll); + email.setTarget(poll); + email.setReport(report); + + PollenEntityId<Poll> pollId = getPollenEntityId(poll); + String pollUrl = getPollenUIUrlRenderService().getPollVoteUrl( + getUIContext().getPollVoteUrl(), + pollId.getReducedId(), + poll.getCreator().getPermission().getToken()); + email.setUrl(pollUrl); + + return email; + } + + public PollReportForAdminEmail newPollReportForAdminEmail(Poll poll, Report report, PollenUser admin) { + // FIXME BAVENCOFF 15/06/2017 la local du mail devrait etre celle du destinataire + PollReportForAdminEmail email = new PollReportForAdminEmail(getLocale()); + email.setPoll(poll); + email.setTarget(poll); + email.setReport(report); + + PollenEntityId<Poll> pollId = getPollenEntityId(poll); + String pollUrl = getPollenUIUrlRenderService().getPollVoteUrl( + getUIContext().getPollVoteUrl(), + pollId.getReducedId(), + null); + email.setUrl(pollUrl); + + email.setAdministrator(admin); + email.setReports(getReportTopiaDao().forTargetIdEquals(poll.getTopiaId()).findAll()); + email.setResume(getReportTopiaDao().getReportResume(poll.getTopiaId())); + + return email; + } + + protected String getChoiceValue(Choice choice) { + String value; + switch (choice.getChoiceType()) { + case DATE: + case DATETIME: + Date date = new Date(Long.parseLong(choice.getChoiceValue())); + value = PollenMail.formatDate(date, getLocale()); + break; + case RESOURCE: + PollenResource resource = getPollenResourceDao().forTopiaIdEquals(choice.getChoiceValue()).findUnique(); + PollenEntityId<PollenResource> resourceId = getPollenEntityId(resource); + value = getPollenUIUrlRenderService().getResourceUrl( + getUIContext().getResourceUrl(), + resourceId.getReducedId()); + break; + default: + value = choice.getChoiceValue(); + } + return value; + } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/PollReportEmail.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/PollReportEmail.java new file mode 100644 index 00000000..9dfcf4f8 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/PollReportEmail.java @@ -0,0 +1,22 @@ +package org.chorem.pollen.services.service.mail; + +import org.chorem.pollen.persistence.entity.Poll; +import org.nuiton.i18n.I18n; + +import java.util.Locale; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class PollReportEmail extends AbstractReportEmail<Poll> { + + public PollReportEmail(Locale locale) { + super(locale); + } + + @Override + public String getSubject() { + return I18n.l(locale, "pollen.service.mail.PollReportEmail.subject", poll.getTitle()); + } + +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/PollReportForAdminEmail.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/PollReportForAdminEmail.java new file mode 100644 index 00000000..dcf38ffa --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/PollReportForAdminEmail.java @@ -0,0 +1,22 @@ +package org.chorem.pollen.services.service.mail; + +import org.chorem.pollen.persistence.entity.Poll; +import org.nuiton.i18n.I18n; + +import java.util.Locale; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class PollReportForAdminEmail extends AbstractReportForAdminEmail<Poll> { + + public PollReportForAdminEmail(Locale locale) { + super(locale); + } + + @Override + public String getSubject() { + return I18n.l(locale, "pollen.service.mail.PollReportForAdminEmail.subject", poll.getTitle()); + } + +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/PollenMail.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/PollenMail.java index f1f59166..38b7f734 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/PollenMail.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/PollenMail.java @@ -38,6 +38,15 @@ import java.util.Set; */ public abstract class PollenMail { + public static String formatDate(Date date, Locale locale) { + String result = null; + if (date != null) { + DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT, locale); + result = formatter.format(date); + } + return result; + } + protected final Locale locale; protected Set<String> tos; @@ -89,12 +98,7 @@ public abstract class PollenMail { } protected String formatDate(Date date) { - String result = null; - if (date != null) { - DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT, locale); - result = formatter.format(date); - } - return result; + return formatDate(date, locale); } public String getSigning() { diff --git a/pollen-services/src/main/resources/email/ChoiceReportEmail.mustache b/pollen-services/src/main/resources/email/ChoiceReportEmail.mustache new file mode 100644 index 00000000..837877db --- /dev/null +++ b/pollen-services/src/main/resources/email/ChoiceReportEmail.mustache @@ -0,0 +1,8 @@ +Hello {{poll.creator.name}}, + +A choice of poll "{{poll.title}}" is report as {{#isIllegal}}patently illegal{{/isIllegal}}{{#isSpam}}a Spam or advertising{{/isSpam}}{{#isOffTopic}}off topic{{/isOffTopic}} by {{report.email}}. + +This choice has been created by {{target.creator.name}} on {{choiceCreateDate}} : +"{{choiceValue}}" + +You can delete this choice ou ignore this report here : {{url}} \ No newline at end of file diff --git a/pollen-services/src/main/resources/email/ChoiceReportEmail_fr.mustache b/pollen-services/src/main/resources/email/ChoiceReportEmail_fr.mustache new file mode 100644 index 00000000..4d722b4a --- /dev/null +++ b/pollen-services/src/main/resources/email/ChoiceReportEmail_fr.mustache @@ -0,0 +1,8 @@ +Bonjour {{poll.creator.name}}, + +Un choix du votre sondage "{{poll.title}}" est signalé comme {{#isIllegal}}manifestement illégal{{/isIllegal}}{{#isSpam}}un Spam ou une publicité{{/isSpam}}{{#isOffTopic}}hors sujet{{/isOffTopic}} par {{report.email}}. + +Le choix a été créé par {{target.creator.name}} le {{choiceCreateDate}} : +"{{choiceValue}}" + +Vous pouvez supprimer ce choix ou ignorer ce signalement ici : {{url}} \ No newline at end of file diff --git a/pollen-services/src/main/resources/email/ChoiceReportForAdminEmail.mustache b/pollen-services/src/main/resources/email/ChoiceReportForAdminEmail.mustache new file mode 100644 index 00000000..f3eb95d4 --- /dev/null +++ b/pollen-services/src/main/resources/email/ChoiceReportForAdminEmail.mustache @@ -0,0 +1,14 @@ +Hello {{administrator.name}}, + +A choice of poll "{{poll.title}}" (created by {{poll.creator.name}} {{poll.creator.email}}) is report as {{#isIllegal}}patently illegal{{/isIllegal}}{{#isSpam}}a Spam or advertising{{/isSpam}}{{#isOffTopic}}off topic{{/isOffTopic}} by {{report.email}}. + +This choice has been created by {{target.creator.name}} on {{choiceCreateDate}} : +"{{choiceValue}}" + +For this choice, there are {{resume.count}} reports (including {{resume.ignore}} ignores) for a total score of {{resume.score}} + +{{#reports}} + - {{level}} {{email}} {{#ignore}}Ignore{{/ignore}} +{{/reports}} + +You can see this choice here : {{url}} \ No newline at end of file diff --git a/pollen-services/src/main/resources/email/ChoiceReportForAdminEmail_fr.mustache b/pollen-services/src/main/resources/email/ChoiceReportForAdminEmail_fr.mustache new file mode 100644 index 00000000..0e55a286 --- /dev/null +++ b/pollen-services/src/main/resources/email/ChoiceReportForAdminEmail_fr.mustache @@ -0,0 +1,14 @@ +Hello {{administrator.name}}, + +A choice of poll "{{poll.title}}" (created by {{poll.creator.name}} {{poll.creator.email}}) is report as {{#isIllegal}}patently illegal{{/isIllegal}}{{#isSpam}}a Spam or advertising{{/isSpam}}{{#isOffTopic}}off topic{{/isOffTopic}} by {{report.email}}. + +This choice has been created by {{target.creator.name}} on {{choiceCreateDate}} : +"{{choiceValue}}" + +Pour ce choix il y a {{resume.count}} signalements (dont {{resume.ignore}} ignorés) pour un score total de {{resume.score}} + +{{#reports}} + - {{level}} {{email}} {{#ignore}}Ignore{{/ignore}} +{{/reports}} + +You can see this choice here : {{url}} \ No newline at end of file diff --git a/pollen-services/src/main/resources/email/CommentReportEmail.mustache b/pollen-services/src/main/resources/email/CommentReportEmail.mustache new file mode 100644 index 00000000..d20199ad --- /dev/null +++ b/pollen-services/src/main/resources/email/CommentReportEmail.mustache @@ -0,0 +1,8 @@ +Hello {{poll.creator.name}}, + +A comment of your poll "{{poll.title}}" is report as {{#isIllegal}}patently illegal{{/isIllegal}}{{#isSpam}}a Spam or advertising{{/isSpam}}{{#isOffTopic}}off topic{{/isOffTopic}} by {{report.email}}. + +This comment has been created by {{target.creator.name}} on {{choiceCreateDate}} : +"{{target.text}}" + +You can delete this comment ou ignore this report here : {{url}} \ No newline at end of file diff --git a/pollen-services/src/main/resources/email/CommentReportEmail_fr.mustache b/pollen-services/src/main/resources/email/CommentReportEmail_fr.mustache new file mode 100644 index 00000000..880edfef --- /dev/null +++ b/pollen-services/src/main/resources/email/CommentReportEmail_fr.mustache @@ -0,0 +1,8 @@ +Bonjour {{poll.creator.name}}, + +Un commentaire de votre sondage "{{poll.title}}" est signalé comme {{#isIllegal}}manifestement illégal{{/isIllegal}}{{#isSpam}}un Spam ou une publicité{{/isSpam}}{{#isOffTopic}}hors sujet{{/isOffTopic}} par {{report.email}}. + +Le commentaire a été écrit par {{target.author.name}} le {{commentPostDate}} : +"{{target.text}}" + +Vous pouvez supprimer ce commentaire ou ignorer ce signalement ici : {{url}} \ No newline at end of file diff --git a/pollen-services/src/main/resources/email/CommentReportForAdminEmail.mustache b/pollen-services/src/main/resources/email/CommentReportForAdminEmail.mustache new file mode 100644 index 00000000..f0cc793e --- /dev/null +++ b/pollen-services/src/main/resources/email/CommentReportForAdminEmail.mustache @@ -0,0 +1,14 @@ +Hello {{administrator.name}}, + +A comment of poll "{{poll.title}}" (created by {{poll.creator.name}} {{poll.creator.email}}) is report as {{#isIllegal}}patently illegal{{/isIllegal}}{{#isSpam}}a Spam or advertising{{/isSpam}}{{#isOffTopic}}off topic{{/isOffTopic}} by {{report.email}}. + +This comment has been created by {{target.creator.name}} on {{commentPostDate}} : +"{{target.text}}" + +For this comment, there are {{resume.count}} reports (including {{resume.ignore}} ignores) for a total score of {{resume.score}} + +{{#reports}} + - {{level}} {{email}} {{#ignore}}Ignore{{/ignore}} +{{/reports}} + +You can see this comment here : {{url}} \ No newline at end of file diff --git a/pollen-services/src/main/resources/email/CommentReportForAdminEmail_fr.mustache b/pollen-services/src/main/resources/email/CommentReportForAdminEmail_fr.mustache new file mode 100644 index 00000000..e30d2423 --- /dev/null +++ b/pollen-services/src/main/resources/email/CommentReportForAdminEmail_fr.mustache @@ -0,0 +1,14 @@ +Bonjour {{administrator.name}}, + +Un commentaire du sondage "{{poll.title}}" (créé par {{poll.creator.name}} {{poll.creator.email}}) est signalé comme {{#isIllegal}}manifestement illégal{{/isIllegal}}{{#isSpam}}un Spam ou une publicité{{/isSpam}}{{#isOffTopic}}hors sujet{{/isOffTopic}} par {{report.email}}. + +Le commentaire a été écrit par {{target.author.name}} le {{commentPostDate}} : +"{{target.text}}" + +Pour ce commentaire il y a {{resume.count}} signalements (dont {{resume.ignore}} ignorés) pour un score total de {{resume.score}} + +{{#reports}} + - {{level}} {{email}} {{#ignore}}Ignoré{{/ignore}} +{{/reports}} + +Vous pouvez voir ce commentaire ici : {{url}} \ No newline at end of file diff --git a/pollen-services/src/main/resources/email/PollReportEmail.mustache b/pollen-services/src/main/resources/email/PollReportEmail.mustache new file mode 100644 index 00000000..2bce3a7f --- /dev/null +++ b/pollen-services/src/main/resources/email/PollReportEmail.mustache @@ -0,0 +1,8 @@ +Hello {{poll.creator.name}}, + +Your poll "{{poll.title}}" is report as {{#isIllegal}}patently illegal{{/isIllegal}}{{#isSpam}}a Spam or advertising{{/isSpam}}{{#isOffTopic}}off topic{{/isOffTopic}} by {{report.email}}. +{{#target.description}} + {{target.description}} +{{/target.description}} + +You can delete this poll ou ignore this report here : {{url}} \ No newline at end of file diff --git a/pollen-services/src/main/resources/email/PollReportEmail_fr.mustache b/pollen-services/src/main/resources/email/PollReportEmail_fr.mustache new file mode 100644 index 00000000..845ee385 --- /dev/null +++ b/pollen-services/src/main/resources/email/PollReportEmail_fr.mustache @@ -0,0 +1,8 @@ +Bonjour {{user.name}}, + +Votre sondage "{{poll.title}}" est signalé comme {{#isIllegal}}manifestement illégal{{/isIllegal}}{{#isSpam}}un Spam ou une publicité{{/isSpam}}{{#isOffTopic}}hors sujet{{/isOffTopic}} par {{report.email}}. +{{#target.description}} + {{target.description}} +{{/target.description}} + +Vous pouvez supprimer votre sondage ou ignorer ce signalement ici : {{url}} \ No newline at end of file diff --git a/pollen-services/src/main/resources/email/PollReportForAdminEmail.mustache b/pollen-services/src/main/resources/email/PollReportForAdminEmail.mustache new file mode 100644 index 00000000..47671876 --- /dev/null +++ b/pollen-services/src/main/resources/email/PollReportForAdminEmail.mustache @@ -0,0 +1,14 @@ +Hello {{administrator.name}}, + +A poll "{{poll.title}}" (created by {{poll.creator.name}} {{poll.creator.email}}) is report as {{#isIllegal}}patently illegal{{/isIllegal}}{{#isSpam}}a Spam or advertising{{/isSpam}}{{#isOffTopic}}off topic{{/isOffTopic}} by {{report.email}}. +{{#target.description}} + {{target.description}} +{{/target.description}} + +For this poll, there are {{resume.count}} reports (including {{resume.ignore}} ignores) for a total score of {{resume.score}} + +{{#reports}} + - {{level}} {{email}} {{#ignore}}Ignore{{/ignore}} +{{/reports}} + +You can see this poll here : {{url}} \ No newline at end of file diff --git a/pollen-services/src/main/resources/email/PollReportForAdminEmail_fr.mustache b/pollen-services/src/main/resources/email/PollReportForAdminEmail_fr.mustache new file mode 100644 index 00000000..7382a74d --- /dev/null +++ b/pollen-services/src/main/resources/email/PollReportForAdminEmail_fr.mustache @@ -0,0 +1,14 @@ +Bonjour {{administrator.name}}, + +Le sondage "{{poll.title}}" (créé par {{poll.creator.name}} {{poll.creator.email}}) est signalé comme {{#isIllegal}}manifestement illégal{{/isIllegal}}{{#isSpam}}un Spam ou une publicité{{/isSpam}}{{#isOffTopic}}hors sujet{{/isOffTopic}} par {{report.email}}. +{{#target.description}} + {{target.description}} +{{/target.description}} + +Pour ce sondage il y a {{resume.count}} signalements (dont {{resume.ignore}} ignorés) pour un score total de {{resume.score}} + +{{#reports}} + - {{level}} {{email}} {{#ignore}}Ignoré{{/ignore}} +{{/reports}} + +Vous pouvez voir ce sondage ici : {{url}} \ No newline at end of file diff --git a/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties b/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties index a6fda29f..0b78d8bd 100644 --- a/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties +++ b/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties @@ -21,6 +21,7 @@ pollen.configuration.defaultVoteVisibility=Default vote visiblity pollen.configuration.devMode=Dev mode pollen.configuration.logConfigurationFile=Path to log configuration file pollen.configuration.registration.emailAddressPattern=Regular expression that the user email address must match for registration +pollen.configuration.report.maxScore=Maximum score for reporting before administrators are notified pollen.configuration.resendEmailsCronSchedule=Time between two cron jobs of email resending pollen.configuration.resource.maxSize=Maximum size of pollen resource pollen.configuration.secret= @@ -79,6 +80,9 @@ pollen.error.poll.unique.voterList.mandatory.for.restrictedPoll=A voter list is pollen.error.poll.voteCountingType.mandatory=vote counting type is mandatory pollen.error.poll.voteVisibility.mandatory=vote visibility is mandatory pollen.error.poll.voterList.mandatory.for.groupedPoll=At least one voter list ins mandatory for a grouped poll +pollen.error.report.email.invalid=Email invalid +pollen.error.report.email.mandatory=Email can not be empty +pollen.error.report.level.mandatory=Report level can not be empty pollen.error.resource.empty=No resource sent pollen.error.resource.maxSize=File "%s" of %4.2f %s can't be over %4.2f %s. pollen.error.resource.notExist=Image don't exist @@ -123,15 +127,21 @@ pollen.service.feed.voteEdited.title=%s edited his vote pollen.service.mail.ChoiceAddedEmail.subject=[Pollen] A choice was added in poll %s pollen.service.mail.ChoiceDeletedEmail.subject=[Pollen] A choice was deleted in poll %s pollen.service.mail.ChoiceEditedEmail.subject=[Pollen] A choice was edited in poll %s +pollen.service.mail.ChoiceReportEmail.subject=[Pollen] A choice was reported in your poll %s +pollen.service.mail.ChoiceReportForAdminEmail.subject=[Pollen] A choice was reported in poll %s pollen.service.mail.CommentAddedEmail.subject=[Pollen] A comment was added in poll %s pollen.service.mail.CommentDeletedEmail.subject=[Pollen] A comment was deleted in poll %s pollen.service.mail.CommentEditedEmail.subject=[Pollen] A comment was edited in poll %s +pollen.service.mail.CommentReportEmail.subject=[Pollen] A comment was reported in your poll %s +pollen.service.mail.CommentReportForAdminEmail.subject=[Pollen] A comment was reported in poll %s pollen.service.mail.LostPasswordEmail.subject=[Pollen] Lost password for %s pollen.service.mail.PollChoicePeriodEndedEmail.subject=[Pollen] Add Choice period ended for poll %s pollen.service.mail.PollChoicePeriodStartedEmail.subject=[Pollen] Add Choice period started for poll %s pollen.service.mail.PollClosedEmail.subject=[Pollen] Poll %s is closed pollen.service.mail.PollCreatedEmail.subject=[Pollen] Poll creation (%s) pollen.service.mail.PollEndReminderEmail.subject=[Pollen] Your poll %s ends soon +pollen.service.mail.PollReportEmail.subject=[Pollen] Your poll %s was reported +pollen.service.mail.PollReportForAdminEmail.subject=[Pollen] A poll %s was reported pollen.service.mail.PollVotePeriodEndedEmail.subject=[Pollen] Vote period ended for poll %s pollen.service.mail.PollVotePeriodStartedEmail.subject=[Pollen] Vote period started for poll %s pollen.service.mail.PollVoteReminderEmail.subject=[Pollen] Reminder to vote on poll %s diff --git a/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties b/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties index 0119f0d5..2675ce7c 100644 --- a/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties +++ b/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties @@ -21,6 +21,7 @@ pollen.configuration.defaultVoteVisibility=Visibilité des votes par défaut pollen.configuration.devMode=Mode développement pollen.configuration.logConfigurationFile=Chemin vers le fichier de configuration des logs pollen.configuration.registration.emailAddressPattern=Expression régulière que doivent vérifier les adresses email des utilisateurs lors de l'inscription +pollen.configuration.report.maxScore=Score maximum pour un signalement avant que les administrateurs soient avertis pollen.configuration.resendEmailsCronSchedule=Intervalle entre deux lancements de la tâche de renvoi des emails en erreur pollen.configuration.resource.maxSize=Taille maximal pour un fichier de resource de Pollen pollen.configuration.secret= @@ -78,6 +79,9 @@ pollen.error.poll.unique.voterList.mandatory.for.restrictedPoll=une liste de vot pollen.error.poll.voteCountingType.mandatory=le type de vote est obligatoire pollen.error.poll.voteVisibility.mandatory=la visiblité des votes est obligatoire pollen.error.poll.voterList.mandatory.for.groupedPoll=Au moins une liste de votant est obligatoire pour un sondage groupé +pollen.error.report.email.invalid=Le courriel n'est pas valid +pollen.error.report.email.mandatory=Le courriel est obligatoire +pollen.error.report.level.mandatory=Le type de signalement est obligatoire pollen.error.resource.empty=Aucune resource envoyé pollen.error.resource.maxSize=Le fichier « %s » de %4.2f %s ne doit pas dépasser %4.2f %s. pollen.error.resource.notExist=L'image n'existe pas sur le serveur @@ -122,15 +126,21 @@ pollen.service.feed.voteEdited.title=%s a modifié son vote pollen.service.mail.ChoiceAddedEmail.subject=[Pollen] Un choix a été ajouté au sondage %s pollen.service.mail.ChoiceDeletedEmail.subject=[Pollen] Un choix a été supprimé du sondage %s pollen.service.mail.ChoiceEditedEmail.subject=[Pollen] Un choix a été modifié sur le sondage %s +pollen.service.mail.ChoiceReportEmail.subject=[Pollen] Un choix a été signalé comme inapproprié sur votre sondage %s +pollen.service.mail.ChoiceReportForAdminEmail.subject=[Pollen] Un choix a été signalé comme inapproprié sur le sondage %s pollen.service.mail.CommentAddedEmail.subject=[Pollen] Un commentaire a été ajouté au sondage %s pollen.service.mail.CommentDeletedEmail.subject=[Pollen] Un commentaire a été supprimé du sondage %s pollen.service.mail.CommentEditedEmail.subject=[Pollen] Un commentaire a été modifié sur le sondage %s +pollen.service.mail.CommentReportEmail.subject=[Pollen] Un commentaire a été signalé comme inapproprié sur votre sondage %s +pollen.service.mail.CommentReportForAdminEmail.subject=[Pollen] Un commentaire a été signalé comme inapproprié sur le sondage %s pollen.service.mail.LostPasswordEmail.subject=[Pollen] Mot de passe perdu du compte %s pollen.service.mail.PollChoicePeriodEndedEmail.subject=[Pollen] Période d'ajout de choix terminée pour le sondage %s pollen.service.mail.PollChoicePeriodStartedEmail.subject=[Pollen] Période d'ajout de choix commencée pour le sondage %s pollen.service.mail.PollClosedEmail.subject=[Pollen] Le sondage %s est clôt pollen.service.mail.PollCreatedEmail.subject=[Pollen] Création du sondage %s pollen.service.mail.PollEndReminderEmail.subject=[Pollen] Votre sondage %s se termine bientôt +pollen.service.mail.PollReportEmail.subject=[Pollen] Votre sondage %s a été signalé comme inapproprié +pollen.service.mail.PollReportForAdminEmail.subject=[Pollen] Le sondage %s a été signalé comme inapproprié pollen.service.mail.PollVotePeriodEndedEmail.subject=[Pollen] Période de vote terminée pour le sondage %s pollen.service.mail.PollVotePeriodStartedEmail.subject=[Pollen] Période de vote commencée pour le sondage %s pollen.service.mail.PollVoteReminderEmail.subject=[Pollen] Rappel du vote au sondage %s diff --git a/pollen-ui-riot-js/src/main/web/css/main.css b/pollen-ui-riot-js/src/main/web/css/blaze.css similarity index 80% copy from pollen-ui-riot-js/src/main/web/css/main.css copy to pollen-ui-riot-js/src/main/web/css/blaze.css index c2f43b2e..e51d83cb 100644 --- a/pollen-ui-riot-js/src/main/web/css/main.css +++ b/pollen-ui-riot-js/src/main/web/css/blaze.css @@ -1,316 +1,3 @@ -/*- - * #%L - * Pollen :: UI (Riot Js) - * %% - * Copyright (C) 2009 - 2017 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% - */ - - -html { - -webkit-text-size-adjust:none; -} - -body { - font-size: 16px; -} - -* { - margin: 0; - padding: 0; - box-sizing: border-box; - font-family: 'Open Sans', sans-serif; - - -webkit-user-select: none; /* Chrome all / Safari all */ - -moz-user-select: none; /* Firefox all */ - -ms-user-select: none; /* IE 10+ */ - user-select: none; -} - -input, textarea { - -webkit-user-select: text; /* Chrome all / Safari all */ - -moz-user-select: text; /* Firefox all */ - -ms-user-select: text; /* IE 10+ */ - user-select: text; -} - -.body-wrapper { - width: 100%; - min-height: 100%; - display: flex; - flex-direction: column; - position: absolute; -} - -.body-container { - display: flex; - flex-wrap: wrap; - margin-left: auto; - margin-right: auto; - justify-content: center; - margin-bottom: 30px; -} - -.instance-title::before { - content: var(--title); - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; -} - -.body-content { - flex-grow: 1; - overflow: hidden; -} - -@media (orientation: portrait) { - .body-content { - width: 100%; - flex-direction: row; - } -} - -@media (orientation: landscape) { - .body-content { - height: 100%; - flex-direction: column; - } -} - -a { - text-decoration: none; - color: var(--main); - cursor: pointer; -} - -.container { - max-width: 1024px; - margin: 15px auto 0 auto; -} - -@media (max-width: 1034px) { - .container { - margin: 15px 5px 0 5px; - } -} - -.actions { - padding: 5px 0; - display: flex; - justify-content: space-between; -} - -.actions .c-button, -.actions-left .c-button, -.actions-right .c-button { - margin: 2px; -} - -.actions-left { - padding: 5px 0; - display: flex; - justify-content: flex-start; - flex-wrap: wrap-reverse; -} - -.actions-right { - padding: 5px 0; - display: flex; - justify-content: flex-end; - flex-wrap: wrap; -} - -.actions .actions-left, -.actions .actions-right { - padding: 0; -} - -a.c-button, -input.c-button, -button.c-button { - display: inline-block; -} - -ul { - margin-left: .5em; -} - -.cursor-pointer { - cursor: pointer; -} - -.c-overlay, .o-modal { - position: fixed; -} - -.colors-main, -.colors-main input, -.colors-main textarea, -.colors-main select { - background-color: var(--background); - color: var(--default); -} - -.colors-main-invers, -.colors-main-invers a { - background-color: var(--main); - color: var(--background); -} - -.card { - display: block; - margin: 5px auto; - padding: 0.5em; - border-radius: 4px; - border: 1px solid var(--main); - box-shadow: 0 0 1px hsla(0,0%,7%,.6); - color: var(--main); -} - -.poll-created { - color: var(--poll-created); - border-color: var(--poll-created); -} - -.poll-adding_choices { - color: var(--poll-adding_choices); - border-color: var(--poll-adding_choices); -} - -.poll-voting { - color: var(--poll-voting); - border-color: var(--poll-voting); -} - -.poll-closed { - color: var(--poll-closed); - border-color: var(--poll-closed); -} - -.info-label { - font-size: 0.5em; - color: var(--info); -} - -/* Steps */ -.tabs { - border-bottom: 1px solid var(--separator); - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - margin: 0 auto; -} - -.tab { - margin-left: 12px; - margin-right: 12px; -} - -.tab button, -.tab a { - border: none; - font-size: 1em; - color: var(--default); - background: transparent; -} - -.tab.selected, -.tab.selected a { - color: var(--main); - border-bottom: 2px solid; -} - -@media (max-width: 640px) { - .tabs.tabs-one-small .tab { - display: none; - } - - .tabs.tabs-one-small .tab.selected { - display: block; - width: 100%; - text-align: center; - border-bottom: none; - } -} - -time-picker .next, -time-picker .prev { - border-color: var(--brand); -} - -time-picker .prev:hover, -time-picker .next:hover { - background-color: var(--brand); -} - -.dropdown-content { - background-color: var(--dropdown); - box-shadow: 0 8px 16px 0 var(--dropdown-shadow); -} - -.dropdown-content a { - background-color: var(--dropdown); - color: var(--dropdown-text); -} - -.dropdown-content a:hover { - background-color: var(--dropdown-hover); -} - -.separator-top { - border-top: 1px solid var(--separator); -} - -.separator-bottom { - border-bottom: 1px solid var(--separator); -} - -.separator-left { - border-left: 1px solid var(--separator); -} - -.separator-right { - border-right: 1px solid var(--separator); -} - -.winner { - color: var(--winner); -} - -.anonymous-voter { - color: var(--anonymous); - font-style: italic; -} - -qrcodebutton .o-modal, -qrcode { - background-color: var(--qrcode); -} - -pollenfooter, -pollenfooter a { - background-color: var(--footer); - color: var(--footer-text); -} - -pollenfooter a:hover { - color: var(--footer-text-hover); -} - /************************************************************** ***** Reprise de blaze CSS ******************************** ***************************************************************/ @@ -1070,7 +757,7 @@ select.c-field:not([multiple]) { display:block; border-radius:4px; background-color:var(--background); - box-shadow:0 0 1px hsla(0,0%,7%,.6); + box-shadow:0 0 1px var(--shadow); overflow:hidden; } @@ -1090,9 +777,7 @@ select.c-field:not([multiple]) { padding:0; } -.c-card__body, -.c-card__footer, -.c-card__item { +.c-card__body,.c-card__footer,.c-card__item { padding:.5em; } @@ -1118,6 +803,139 @@ select.c-field:not([multiple]) { border-bottom:1px solid rgba(202,212,216,.5); } +.c-card--accordion label.c-card__item { + display:block; + position:relative; + width:100%; + padding-left:2em; + cursor:pointer; +} + +.c-card--accordion label.c-card__item:before { + position:absolute; + left:.75em; + content:"+"; +} + +.c-card--accordion>input,.c-card--accordion>input+.c-card__item+.c-card__item { + display:none; +} + +.c-card--accordion>input:checked+.c-card__item+.c-card__item { + display:block; +} + +.c-card--accordion>input:checked+.c-card__item:before { + transform:rotate(45deg); +} + +.c-card--menu { + display:block; + width:100%; + max-height:280px; + margin:.5em 0 0; + z-index:1; + overflow-y:auto; + overflow-x:hidden; + -webkit-overflow-scrolling:touch; +} + +.c-card--grouped .c-card__item:not(:last-child) { + border-bottom:0; +} + +.c-card__divider { + height:1px; + background-color:var(--defaut); + overflow:hidden; +} + +.c-card__item--divider { + background-color:var(--defaut); + color:var(--background); + font-weight:700; +} + +.c-card__item--brand { + background-color:var(--brand); + color:var(--background);; +} + +.c-card__item--info { + background-color:var(--info); + color:var(--background); +} + +.c-card__item--warning { + background-color:var(--warning); + color:var(--background); +} + +.c-card__item--success { + background-color:#4caf50; + color:var(--background); +} + +.c-card__item--error { + background-color:var(--error); + color:var(--background); +} + +.c-card__item--disabled { + cursor:not-allowed; + opacity:.6; +} + +.c-card--accordion label.c-card__item:not(.c-card__item--disabled):not(.c-card__item--divider):hover,.c-card--menu .c-card__item:not(.c-card__item--disabled):not(.c-card__item--divider):hover { + background-color:var(--disabled); + cursor:pointer; +} + +.c-card--accordion label.c-card__item:not(.c-card__item--disabled):not(.c-card__item--divider):hover.c-card__item--brand,.c-card--menu .c-card__item:not(.c-card__item--disabled):not(.c-card__item--divider):hover.c-card__item--brand { + background-color:var(--brand-over); +} + +.c-card--accordion label.c-card__item:not(.c-card__item--disabled):not(.c-card__item--divider):hover.c-card__item--info,.c-card--menu .c-card__item:not(.c-card__item--disabled):not(.c-card__item--divider):hover.c-card__item--info { + background-color:var(--info-hover); +} + +.c-card--accordion label.c-card__item:not(.c-card__item--disabled):not(.c-card__item--divider):hover.c-card__item--warning,.c-card--menu .c-card__item:not(.c-card__item--disabled):not(.c-card__item--divider):hover.c-card__item--warning { + background-color:var(--warbning-hover); +} + +.c-card--accordion label.c-card__item:not(.c-card__item--disabled):not(.c-card__item--divider):hover.c-card__item--success,.c-card--menu .c-card__item:not(.c-card__item--disabled):not(.c-card__item--divider):hover.c-card__item--success { + background-color:var(--success-hover); +} + +.c-card--accordion label.c-card__item:not(.c-card__item--disabled):not(.c-card__item--divider):hover.c-card__item--error,.c-card--menu .c-card__item:not(.c-card__item--disabled):not(.c-card__item--divider):hover.c-card__item--error { + background-color:var(--error-hover); +} + +.c-card--accordion>input:checked+.c-card__item,.c-card__item--active { + background-color:rgba(202,212,216,.5); + font-weight:700; +} + +.c-card--accordion>input:checked+.c-card__item.c-card__item--brand,.c-card__item--active.c-card__item--brand { + background-color:var(--brand-active); +} + +.c-card--accordion>input:checked+.c-card__item.c-card__item--info,.c-card__item--active.c-card__item--info { + background-color:var(--info-active); +} + +.c-card--accordion>input:checked+.c-card__item.c-card__item--warning,.c-card__item--active.c-card__item--warning { + background-color:var(--warning-active); +} + +.c-card--accordion>input:checked+.c-card__item.c-card__item--success,.c-card__item--active.c-card__item--success { + background-color:var(--success-active); +} + +.c-card--accordion>input:checked+.c-card__item.c-card__item--error,.c-card__item--active.c-card__item--error { + background-color:var(--error-active); +} + .c-overlay { display:block; position:absolute; @@ -1498,3 +1316,112 @@ h5.c-heading { h6.c-heading{ font-size:.67em; } + +.o-fieldset, +.o-fieldset.c-list { + display:block; + width:100%; + margin:.5em 0; + padding:0; + border:0; +} + +.o-fieldset__legend { + display:block; + width:100%; + padding:1em 0; + cursor:pointer; + padding:.25em 0; +} + +.o-form-element { + position:relative; + padding:1em 0; +} + +.o-form-element .c-label:first-child { + padding:0 0 .5em; +} + +.c-badge { + border:1px solid var(--default); + background-color:var(--default); + color:var(--background); + display:inline-block; + margin:0; + padding:.25em .5em; + border-radius:4px; + font-size:.8em; + font-weight:700; + line-height:1.2; +} + +.c-badge.c-badge--ghost { + border:1px solid var(--default); + background-color:transparent; + color:var(--default); +} + +.c-badge--rounded { + border-radius:30em; +} + +.c-badge--brand { + border:1px solid var(--brand); + background-color:var(--brand); + color:var(--background); +} + +.c-badge--brand.c-badge--ghost { + border:1px solid var(--brand); + background-color:transparent; + color:var(--brand); +} + +.c-badge--info { + border:1px solid var(--info); + background-color:var(--info); + color:var(--background); +} + +.c-badge--info.c-badge--ghost { + border:1px solid var(--info); + background-color:transparent; + color:var(--info); +} + +.c-badge--warning { + border:1px solid var(--warning); + background-color:var(--warning); + color:var(--background); +} + +.c-badge--warning.c-badge--ghost { + border:1px solid var(--warning); + background-color:transparent; + color:var(--warning); +} + +.c-badge--success { + border:1px solid var(--success); + background-color:var(--success); + color:var(--background); +} + +.c-badge--success.c-badge--ghost { + border:1px solid var(--success); + background-color:transparent; + color:var(--success); +} + +.c-badge--error { + border:1px solid var(--error); + background-color:var(--error); + color:var(--background); +} + +.c-badge--error.c-badge--ghost { + border:1px solid var(--error); + background-color:transparent; + color:var(--error); +} diff --git a/pollen-ui-riot-js/src/main/web/css/main.css b/pollen-ui-riot-js/src/main/web/css/main.css index c2f43b2e..d04b499b 100644 --- a/pollen-ui-riot-js/src/main/web/css/main.css +++ b/pollen-ui-riot-js/src/main/web/css/main.css @@ -205,6 +205,11 @@ ul { color: var(--info); } +.error-label { + font-size: 0.5em; + color: var(--error); +} + /* Steps */ .tabs { border-bottom: 1px solid var(--separator); @@ -310,1191 +315,3 @@ pollenfooter a { pollenfooter a:hover { color: var(--footer-text-hover); } - -/************************************************************** -***** Reprise de blaze CSS ******************************** -***************************************************************/ -.c-button{ - border:1px solid transparent; - background-color:var(--default); - color:var(--background); - display:inline; - max-width:100%; - margin:0; - padding:.5em; - border-radius:4px; - outline:0; - font-family:inherit; - font-size:1em; - line-height:normal; - text-align:center; - text-decoration:none; - text-overflow:ellipsis; - white-space:nowrap; - cursor:pointer; - overflow:hidden; - vertical-align:middle; - -webkit-appearance:none; - -moz-appearance:none; - appearance:none; - -webkit-user-select:none; - -moz-user-select:none; - -ms-user-select:none; - user-select:none; -} - -.c-button.c-button--active { - background-color:var(--active); -} - -.c-button:not(:disabled):hover { - background-color:var(--btn-hover); -} - -.c-button:not(:disabled):focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-button:not(:disabled):active { - background-color:var(--active); -} - -.c-button:disabled { - cursor:not-allowed; - opacity:.5; -} - -.c-button--close { - border:1px solid transparent; - color:inherit; - position:absolute; - right:.5em; - padding:0; - outline:0; - font-size:1.4em; - font-weight:700; - line-height:1; -} - - -.c-button--close,.c-button--close.c-button--active { - background-color:transparent; -} - -.c-button--close:not(:disabled):hover { - background-color:hsla(0,0%,9%,0); -} - -.c-button--close:not(:disabled):focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-button--close:not(:disabled):active { - background-color:transparent; -} - -.c-button--block { - display:inline-block; - width:100%; -} - -.c-button--rounded { - border-radius:30em; -} - -.c-button--brand { - border:1px solid transparent; - background-color:var(--brand); - color:var(--background); -} - -.c-button--brand.c-button--active { - background-color:var(--brand-active); -} - -.c-button--brand:not(:disabled):hover { - background-color:var(--brand-hover); -} - -.c-button--brand:not(:disabled):focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-button--brand:not(:disabled):active { - background-color:var(--brand-active); -} - -.c-button--info { - border:1px solid transparent; - background-color:var(--info); - color:var(--background); -} - -.c-button--info.c-button--active { - background-color:var(--info-active); -} - -.c-button--info:not(:disabled):hover { - background-color:var(--info-hover); -} - -.c-button--info:not(:disabled):focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-button--info:not(:disabled):active { - background-color:var(--info-active); -} - -.c-button--warning { - border:1px solid transparent; - background-color:var(--warning); - color:var(--background); -} - -.c-button--warning.c-button--active { - background-color:var(--warning-active); -} - -.c-button--warning:not(:disabled):hover { - background-color:var(--warning-hover); -} - -.c-button--warning:not(:disabled):focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-button--warning:not(:disabled):active { - background-color:var(--warning-active); -} - -.c-button--success { - border:1px solid transparent; - background-color:var(--success); - color:var(--background); -} - -.c-button--success.c-button--active { - background-color:var(--success-active); -} - -.c-button--success:not(:disabled):hover { - background-color:var(--success-hover); -} - -.c-button--success:not(:disabled):focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-button--success:not(:disabled):active { - background-color:var(--success-active); -} - -.c-button--error { - border:1px solid transparent; - background-color:var(--error); - color:var(--background); -} - -.c-button--error.c-button--active { - background-color:var(--error-active); -} - -.c-button--error:not(:disabled):hover { - background-color:var(--error-hover); -} - -.c-button--error:not(:disabled):focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-button--error:not(:disabled):active { - background-color:var(--error-active); -} - -.c-button--ghost { - border:1px solid var(--default); - background-color:transparent; - color:var(--default); -} - -.colors-main-invers .c-button--ghost, -.colors-main-invers .c-button--ghost-brand, -.colors-main-invers .c-button--ghost-info, -.colors-main-invers .c-button--ghost-warning, -.colors-main-invers .c-button--ghost-success, -.colors-main-invers .c-button--ghost-error { - background-color: var(--background); -} - -.c-button--ghost.c-button--active { - border-color:var(--active); - background-color:var(--active); - color:var(--background); -} - -.c-button--ghost:not(:disabled):hover { - background-color:var(--default); - color:var(--background); -} - -.c-button--ghost:not(:disabled):focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-button--ghost:not(:disabled):active { - border-color:var(--active); - background-color:var(--active); - color:var(--background); -} - -.c-button--ghost-brand { - border:1px solid var(--brand); - background-color:transparent; - color:var(--brand); -} - -.c-button--ghost-brand.c-button--active { - border-color:var(--brand-active); - background-color:var(--brand-active); - color:var(--background); -} - -.c-button--ghost-brand:not(:disabled):hover { - background-color:var(--brand); - color:var(--background); -} - -.c-button--ghost-brand:not(:disabled):focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-button--ghost-brand:not(:disabled):active { - border-color:var(--brand-active); - background-color:var(--brand-active); - color:var(--background); -} - -.c-button--ghost-info { - border:1px solid var(--info); - background-color:transparent; - color:var(--info); -} - -.c-button--ghost-info.c-button--active { - border-color:var(--info-active); - background-color:var(--info-active); - color:var(--background); -} - -.c-button--ghost-info:not(:disabled):hover { - background-color:var(--info); - color:var(--background); -} - -.c-button--ghost-info:not(:disabled):focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-button--ghost-info:not(:disabled):active { - border-color:var(--info-active); - background-color:var(--info-active); - color:var(--background); -} - -.c-button--ghost-warning { - border:1px solid var(--warning); - background-color:transparent; - color:var(--warning); -} - -.c-button--ghost-warning.c-button--active { - border-color:var(--warning-active); - background-color:var(--warning-active); - color:var(--background); -} - -.c-button--ghost-warning:not(:disabled):hover { - background-color:var(--warning); - color:var(--background); -} - -.c-button--ghost-warning:not(:disabled):focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-button--ghost-warning:not(:disabled):active { - border-color:var(--warning-active); - background-color:var(--warning-active); - color:var(--background); -} - -.c-button--ghost-success { - border:1px solid var(--success); - background-color:transparent; - color:var(--success); -} - -.c-button--ghost-success.c-button--active { - border-color:var(--success-active); - background-color:var(--success-active); - color:var(--background); -} - -.c-button--ghost-success:not(:disabled):hover { - background-color:var(--success); - color:var(--background); -} - -.c-button--ghost-success:not(:disabled):focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-button--ghost-success:not(:disabled):active { - border-color:var(--success-active); - background-color:var(--success-active); - color:var(--background); -} - -.c-button--ghost-error { - border:1px solid var(--error); - background-color:transparent; - color:var(--error); -} - -.c-button--ghost-error.c-button--active { - border-color:var(--error-active); - background-color:var(--error-active); - color:var(--background); -} - -.c-button--ghost-error:not(:disabled):hover { - background-color:var(--error); - color:var(--background); -} - -.c-button--ghost-error:not(:disabled):focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-button--ghost-error:not(:disabled):active { - border-color:var(--error-active); - background-color:var(--error-active); - color:var(--background); -} - -.c-button__icon-left { - padding-right:.5em; -} - -.c-button__icon-right { - padding-left:.5em; -} - -.c-input-group { - display:-ms-flexbox; - display:flex; -} - -.c-input-group .c-button { - border-radius:0; -} - -.c-input-group .c-button:not(:first-child) { - border-left-width:0; -} - -.c-input-group .c-button:first-child { - border-top-left-radius:4px; - border-bottom-left-radius:4px; -} - -.c-input-group .c-button:last-child { - border-top-right-radius:4px; - border-bottom-right-radius:4px; -} - -.c-input-group .o-field { - -ms-flex:1; - flex:1; -} - -.c-input-group .o-field .c-field { - border-radius:0; -} - -.c-input-group .o-field:not(:first-child) .c-field { - border-left-width:0; -} - -.c-input-group .o-field:first-child .c-field { - border-top-left-radius:4px; - border-bottom-left-radius:4px; -} - -.c-input-group .o-field:last-child .c-field { - border-top-right-radius:4px; - border-bottom-right-radius:4px; -} - -.c-input-group .o-field--fixed { - -ms-flex:0 1 auto; - flex:0 1 auto; -} - -.c-input-group--rounded .c-button:first-child { - border-top-left-radius:30em; - border-bottom-left-radius:30em; -} - -.c-input-group--rounded .c-button:last-child { - border-top-right-radius:30em; - border-bottom-right-radius:30em; -} - -.c-input-group--rounded .o-field:first-child .c-field { - border-top-left-radius:30em; - border-bottom-left-radius:30em; -} - -.c-input-group--rounded .o-field:last-child .c-field { - border-top-right-radius:30em; - border-bottom-right-radius:30em; -} - -.c-input-group--rounded-left .c-button:first-child,.c-input-group--rounded-left .o-field:first-child .c-field { - border-top-left-radius:30em; - border-bottom-left-radius:30em; -} - -.c-input-group--rounded-right .c-button:last-child,.c-input-group--rounded-right .o-field:last-child .c-field { - border-top-right-radius:30em; - border-bottom-right-radius:30em; -} - -.c-input-group--stacked { - display:-ms-flexbox; - display:flex; - -ms-flex-wrap:wrap; - flex-wrap:wrap; -} - -.c-input-group--stacked .c-button:not(:first-child),.c-input-group--stacked .o-field:not(:first-child) .c-field { - border-left-width:1px; -} - -.c-input-group--stacked .c-button,.c-input-group--stacked .o-field { - -ms-flex:0 0 100%; - flex:0 0 100%; - max-width:100%; - margin-left:0; -} - -.c-input-group--stacked .c-button:not(:first-child) { - border-top:0; -} - -.c-input-group--stacked .c-button:not(:first-child):not(:last-child) { - border-radius:0; -} - -.c-input-group--stacked .c-button:first-child { - border-radius:4px 4px 0 0; -} - -.c-input-group--stacked .c-button:last-child { - border-radius:0 0 4px 4px; -} - -.c-input-group--stacked .o-field:not(:first-child) .c-field { - border-top:0; -} - -.c-input-group--stacked .o-field:not(:first-child):not(:last-child) .c-field { - border-radius:0; -} - -.c-input-group--stacked .o-field:first-child .c-field { - border-radius:4px 4px 0 0; -} - -.c-input-group--stacked .o-field:last-child .c-field { - border-radius:0 0 4px 4px; -} - -.o-field { - position:relative; -} - -.o-field .c-field--success~.c-icon { - color:var(--success); -} - -.o-field .c-field--error~.c-icon { - color:var(--error); -} - -.o-field .c-field:disabled~.c-icon { - color:var(--default); -} - -.o-field .c-icon { - position:absolute;top:50%; - transform:translateY(-50%); - color:var(--default); -} - -.o-field--icon-right .c-field+.c-icon { - right:.5em; -} - -.o-field--icon-right .c-field { - padding-right:2em; -} - -.o-field--icon-left .c-icon:first-child { - left:.5em; -} - -.o-field--icon-left .c-field { - padding-left:2em; -} - -.c-label { - padding:1em 0; -} - -.c-field { - display:block; - width:100%; - margin:0; - padding:.5em; - border:1px solid var(--default); - border-radius:4px; - outline:0; - background-color:var(--background); - font-family:inherit; - font-size:1em; - font-weight:400; - resize:vertical; - -webkit-appearance:none; - -moz-appearance:none; - appearance:none; -} - -.c-field:focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); - -} - -select.c-field { - cursor:pointer; -} - -select.c-field:not([multiple]) { - padding-right:1em; - background:url("data:image/png;base64,R0lGODlhDwAUAIABAAAAAP///yH5BAEAAAEALAAAAAAPABQAAAIXjI+py+0Po5wH2HsXzmw//lHiSJZmUAAAOw==") no-repeat 99% 50%; -} - -.c-field input { - margin-right:.125em; - outline:0; - font-size:1em; -} - -.c-field--label { - margin:.5em 0 0; -} - -.c-field--error { - border-color:var(--error); - color:var(--error); -} - -.c-field--success { - border-color:var(--success); - color:inherit; -} - -.c-field--choice { - border:0; - border-radius:0; - background-color:transparent; -} - -.c-field--disabled, -.c-field:disabled { - color:var(--default); - cursor:not-allowed; - border-color:var(--default); - background-color:var(--disabled); -} - -.c-field--disabled.c-field--choice, -.c-field:disabled.c-field--choice { - background-color:transparent; -} - -.c-field input:disabled { - color:var(--default); - cursor:not-allowed; -} - -.o-form-element { - position:relative; - padding:1em 0 -} - -.o-form-element .c-label:first-child { - padding:0 0 .5em -} - -.c-toggle { - display:-ms-flexbox; - display:flex; - -ms-flex-align:center; - align-items:center; - width:auto; - cursor:pointer; - -webkit-user-select:none; - -moz-user-select:none; - -ms-user-select:none; - user-select:none; -} - -.c-toggle input:not(:checked)+.c-toggle__track { - background-color:var(--disabled); -} - -.c-toggle input:not(:checked)+.c-toggle__track .c-toggle__handle { - transform:translateZ(0); -} - -.c-toggle input:disabled+.c-toggle__track, -.c-toggle input:disabled+.c-toggle__track .c-toggle__handle { - background-color:var(--disabled); - cursor:not-allowed; -} - -.c-toggle--brand .c-toggle__track { - background-color:var(--brand); -} - -.c-toggle--info .c-toggle__track { - background-color:var(--info); -} - -.c-toggle--warning .c-toggle__track { - background-color:var(--warning); -} - -.c-toggle--success .c-toggle__track { - background-color:var(--success); -} - -.c-toggle--error .c-toggle__track { - background-color:var(--error); -} - -.c-toggle input { - display:none; -} - -.c-toggle__track { - -ms-flex:1; - flex:1; - padding-right:1em; - padding-left:1em; - -ms-flex:0 1 auto; - flex:0 1 auto; - background-color:var(--default); - position:relative; - width:1em; - height:.5em; - margin:0 .5em; - border-radius:30em; -} - -.c-toggle__handle { - position:absolute; - top:-.25em; - left:0; - width:1em; - height:1em; - transform:translateX(100%); - border-radius:30em; - background-color:var(--toggle); - box-shadow:0 1px 4px -1px var(--toggle-shadow); -} - -.o-modal { - position:absolute; - top:50%; - left:50%; - transform:translate(-50%,-50%); - display:block; - width:80%; - border:0 solid var(--default); - border-radius:4px; - background-color:var(--background); - overflow:hidden; - z-index:1; -} - -.o-modal .c-card { - background-color:transparent; - box-shadow:none; -} - -.o-modal .c-card__body { - position:relative; -} - -.c-card { - padding:0; - list-style:none; - display:block; - border-radius:4px; - background-color:var(--background); - box-shadow:0 0 1px hsla(0,0%,7%,.6); - overflow:hidden; -} - -.c-card>.o-image:not(:first-child) { - padding:1em 0 0; -} - -.c-card+.c-card { - margin:.5em 0 0; -} - -.c-card__header { - padding:.5em .5em 0; -} - -.c-card__header .c-heading { - padding:0; -} - -.c-card__body, -.c-card__footer, -.c-card__item { - padding:.5em; -} - -.c-card__item+.c-card__footer--block { - padding:0; -} - -.c-card__footer--block { - padding:.5em 0 0; -} - -.c-card__footer--block .c-input-group .c-button:first-child { - border-top-left-radius:0; - border-bottom-left-radius:0; -} - -.c-card__footer--block .c-input-group .c-button:last-child { - border-top-right-radius:0; - border-bottom-right-radius:0; -} - -.c-card__item:not(:last-child) { - border-bottom:1px solid rgba(202,212,216,.5); -} - -.c-overlay { - display:block; - position:absolute; - top:0; - right:0; - bottom:0; - left:0; - width:100%; - height:100%; - background-color: var(--overlay); - z-index:1; -} - -.c-hint { - position:absolute; - padding:0 .5em; - transform:scale(.8); - transform-origin:top left; - color:var(--active); - font-size:1em; - opacity:0; - pointer-events:none; -} - -.c-field:focus~.c-hint, -.c-hint--static, -.c-label__field:focus~.c-hint { - transform:scale(.9);opacity:1; -} - -.c-hint--success { - color:var(--success); -} - -.c-hint--error { - color:var(--error); -} - -.c-alerts { - display:block; - position:absolute; - width:250px; - max-height:100%; - background-color:transparent; - z-index:1; - overflow-y:auto -} - -.c-alert { - background-color:var(--default); - color:var(--background); - position:relative; - margin:0 0 1em; - padding:1em 3em 1em 1em; - border-radius:4px; -} - -.c-alert--brand { - background-color:var(--brand); - color:var(--background); -} - -.c-alert--info { - background-color:var(--info); - color:var(--background); -} - -.c-alert--warning { - background-color:var(--warning); - color:var(--background); -} - -.c-alert--success { - background-color:var(--success); - color:var(--background); -} - -.c-alert--error { - background-color:var(--error); - color:var(--background); -} - -.c-pagination { - display:block; - width:100%; - padding:1em; - font-size:.83em; - text-align:center; -} - -.c-pagination__controls { - display:inline-block; - text-align:center; -} - -.c-pagination__controls--backward { - float:left; - text-align:left; -} - -.c-pagination__controls--forward { - float:right; - text-align:right; -} - -.c-pagination__control,.c-pagination__page { - border:1px solid transparent; - background-color: var(--default); - color: var(--background); - display:inline; - max-width:100%; - margin:0; - padding:.5em; - border-radius:4px; - outline:0; - font-family:inherit; - font-size:1em; - line-height:normal; - text-align:center; - text-decoration:none; - text-overflow:ellipsis; - white-space:nowrap; - cursor:pointer; - overflow:hidden; - vertical-align:middle; - -webkit-appearance:none; - -moz-appearance:none; - appearance:none; - -webkit-user-select:none; - -moz-user-select:none; - -ms-user-select:none; - user-select:none; - border:1px solid var(--brand); - background-color:transparent; - color: var(--brand); - min-width:2.4em; - border-radius:30em; -} - -.c-pagination__control.c-button--active,.c-pagination__page.c-button--active { - background-color:var(--active); -} - -.c-pagination__control:not(:disabled):hover,.c-pagination__page:not(:disabled):hover { - background-color:var(--btn-hover); -} - -.c-pagination__control:not(:disabled):active,.c-pagination__page:not(:disabled):active { - background-color:var(--active); -} - -.c-pagination__control:disabled,.c-pagination__page:disabled { - cursor:not-allowed; - opacity:.5; -} - -.c-pagination__control.c-button--active,.c-pagination__page.c-button--active { - border-color: var(--brand-active); - background-color: var(--brand-active); - color: var(--background); -} - -.c-pagination__control:not(:disabled):hover,.c-pagination__page:not(:disabled):hover { - background-color: var(--brand); - color: var(--background); -} - -.c-pagination__control:not(:disabled):focus,.c-pagination__page:not(:disabled):focus { - border-color: var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-pagination__control:not(:disabled):active,.c-pagination__page:not(:disabled):active { - border-color: var(--brand-active); - background-color: var(--brand-active); - color: var(--background); -} - -.c-pagination__page--current { - background-color: var(--brand); - color: var(--background); -} - -.c-pagination__ellipsis { - padding:0 1em; -} -.c-code { - margin:-.125em; - padding:.25em .25em .125em; - background-color: var(--code); - color: var(--code-text); - display:inline; - font-family:Consolas,Andale Mono WT,Andale Mono,Lucida Console,Lucida Sans Typewriter,DejaVu Sans Mono,Bitstream Vera Sans Mono,Liberation Mono,Nimbus Mono L,Monaco,Courier New,Courier,monospace; - font-weight:400; -} - -.c-code--multiline { - display:block; - padding:.5em 1em; - border-radius:4px; - white-space:pre; - overflow-x:auto; -} - -.c-calendar { - display:-ms-flexbox; - display:flex; - -ms-flex-wrap:wrap; - flex-wrap:wrap; - -ms-flex-align:center; - align-items:center; - padding-right:.001em; - padding-left:.001em; - max-width:400px; - padding:.25em; - border:1px solid var(--default); - border-radius:4px; - background-color: var(--background); - text-align:center; - z-index:1; -} - -.c-calendar__control,.c-calendar__date { - background-color: var(--background); - color:var(--default); - display:inline; - -ms-flex:0 0 14.28%; - flex:0 0 14.28%; - max-width:14.28%; - margin:0; - padding:1em .5em; - border:1px solid transparent; - border-radius:4px; - outline:0; - font-size:1em; - cursor:pointer; - -webkit-user-select:none; - -moz-user-select:none; - -ms-user-select:none; - user-select:none; -} - -.c-calendar__control.c-button--active,.c-calendar__date.c-button--active { - background-color: var(--active); -} - -.c-calendar__control:not(:disabled):hover,.c-calendar__date:not(:disabled):hover { - background-color: var(--background); -} - -.c-calendar__control:not(:disabled):focus,.c-calendar__date:not(:disabled):focus { - border-color: var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-calendar__control:not(:disabled):active,.c-calendar__date:not(:disabled):active { - background-color:var(--active); -} - -.c-calendar__header { - -ms-flex:1; - flex:1; - -ms-flex:0 0 70%; - flex:0 0 70%; - max-width:70%; -} - -.c-calendar__day,.c-calendar__header { - padding-right:1em; - padding-left:1em; - padding-right:.001em; - padding-left:.001em; - padding:.5em 0; -} - -.c-calendar__day { - -ms-flex:1; - flex:1; - -ms-flex:0 0 14.28%; - flex:0 0 14.28%; - max-width:14.28%; - font-weight:700; -} - -.c-calendar__date:hover { - border:1px solid var(--default); -} - -.c-calendar__date--in-month { - color: var(--default); -} - -.c-calendar__date--today { - border-color: var(--info); -} - -.c-calendar__date--selected,.c-calendar__date--selected:hover { - border:1px solid transparent; - background-color:var(--brand); - color: var(--background); - border-color:var(--brand); -} - -.c-calendar__date--selected.c-button--active,.c-calendar__date--selected:hover.c-button--active { - background-color: var(--brand-active); -} - -.c-calendar__date--selected:hover:not(:disabled):hover,.c-calendar__date--selected:not(:disabled):hover { - background-color:var(--brand-hover); -} - -.c-calendar__date--selected:hover:not(:disabled):focus,.c-calendar__date--selected:not(:disabled):focus { - border-color:var(--focus); - box-shadow:inset 0 0 0 2px var(--shadow); -} - -.c-calendar__date--selected:hover:not(:disabled):active,.c-calendar__date--selected:not(:disabled):active { - background-color: var(--brand-active); -} - -.u-super { - font-size:2em; -} - -.u-xlarge { - font-size:1.5em; -} - -.u-large { - font-size:1.17em; -} - -.u-medium { - font-size:1em; -} - -.u-small { - font-size:.83em; -} - -.u-xsmall{ - font-size:.67em; -} - -.c-heading, -.c-heading__sub { - margin:0; - padding:1em 0 .5em; - font-weight:400; -} - -.c-heading__sub { - padding:0; - font-size:.8em; - opacity:.6; -} - -h1.c-heading { - font-size:2em; -} - -h2.c-heading { - font-size:1.5em; -} - -h3.c-heading { - font-size:1.17em; -} - -h4.c-heading { - font-size:1em; -} - -h5.c-heading { - font-size:.83em; -} - -h6.c-heading{ - font-size:.67em; -} diff --git a/pollen-ui-riot-js/src/main/web/i18n.json b/pollen-ui-riot-js/src/main/web/i18n.json index 4866404c..115077db 100644 --- a/pollen-ui-riot-js/src/main/web/i18n.json +++ b/pollen-ui-riot-js/src/main/web/i18n.json @@ -438,7 +438,24 @@ "modal_ok": "Ok", "confirm_cancel": "Annuler", "confirm_delete": "Supprimer", - "information_ok": "Ok" + "information_ok": "Ok", + "report_title": "Signaler !", + "report_add_title": "Signaler comme inapproprié !", + "report_add_action": "Signaler", + "report_level": "Que souhaitez-vous signaler ?", + "report_level_spam": "Spam", + "report_level_spam_detail": "Un Spam ou une publicité", + "report_level_off_topic": "Hors-sujet", + "report_level_off_topic_detail": "Un contenu hors-sujet", + "report_level_illegal": "Illégal", + "report_level_illegal_detail": "Un contenu manifestement illégal", + "report_email": "Votre courriel", + "report_email_placeholder": "Votre-courriel@exemple.com", + "report_count": "Signalement", + "report_score": "Score", + "report_reports_title": "Signalements", + "report_toIgnore": "Ignorer", + "report_ignores": "Ignorés" }, "en": { "main_pollen_title": "Pollen - ", @@ -867,6 +884,23 @@ "modal_ok": "Ok", "confirm_cancel": "Cancel", "confirm_delete": "Delete", - "information_ok": "Ok" + "information_ok": "Ok", + "report_title": "Report !", + "report_add_title": "Report as inappropriate !", + "report_add_action": "Report", + "report_level": "What whould you report ?", + "report_level_spam": "Spam", + "report_level_spam_detail": "A Spam or advertising", + "report_level_off_topic": "Oft topic", + "report_level_off_topic_detail": "A off topic content", + "report_level_illegal": "Illegal", + "report_level_illegal_detail": "A manifestly illegal content", + "report_email": "Your email", + "report_email_placeholder": "your-email@exemple.com", + "report_count": "Reporting", + "report_score": "Score", + "report_reports_title": "Reports", + "report_toIgnore": "Ignore", + "report_ignores": "Ignores" } } diff --git a/pollen-ui-riot-js/src/main/web/index.html b/pollen-ui-riot-js/src/main/web/index.html index 1b1aaa44..5d8f1ed7 100644 --- a/pollen-ui-riot-js/src/main/web/index.html +++ b/pollen-ui-riot-js/src/main/web/index.html @@ -27,6 +27,7 @@ <title>Pollen</title> <link href="./css/font-awesome.css" rel="stylesheet"> <link href="./css/custom.css" rel="stylesheet"> + <link href="./css/blaze.css" rel="stylesheet"> <link href="./css/main.css" rel="stylesheet"> </head> <body> diff --git a/pollen-ui-riot-js/src/main/web/js/ChoiceService.js b/pollen-ui-riot-js/src/main/web/js/ChoiceService.js index 381c4d9f..c48203f0 100644 --- a/pollen-ui-riot-js/src/main/web/js/ChoiceService.js +++ b/pollen-ui-riot-js/src/main/web/js/ChoiceService.js @@ -54,6 +54,30 @@ class ChoiceService extends FetchService { } return this.doDelete(url); } + + addReport(pollId, choiceId, report, permission) { + let url = "/v1/polls/" + pollId + "/choices/" + choiceId + "/reports"; + if (permission) { + url += "?permission=" + permission; + } + return this.form(url, {report: report}); + } + + getReports(pollId, choiceId, permission) { + let args = {}; + if (permission) { + args.permission = permission; + } + return this.getWithParams("/v1/polls/" + pollId + "/choices/" + choiceId + "/reports", args); + } + + ignoreReport(pollId, choiceId, reportId, permission) { + let args = {}; + if (permission) { + args.permission = permission; + } + return this.getWithParams("/v1/polls/" + pollId + "/choices/" + choiceId + "/reports/" + reportId + "/ignore", args); + } } module.exports = singleton(ChoiceService); diff --git a/pollen-ui-riot-js/src/main/web/js/CommentService.js b/pollen-ui-riot-js/src/main/web/js/CommentService.js index 43decbbd..b9de087a 100644 --- a/pollen-ui-riot-js/src/main/web/js/CommentService.js +++ b/pollen-ui-riot-js/src/main/web/js/CommentService.js @@ -62,6 +62,30 @@ class CommentService extends FetchService { } return this.doDelete(url); } + + addReport(pollId, commentId, report, permission) { + let url = "/v1/polls/" + pollId + "/comments/" + commentId + "/reports"; + if (permission) { + url += "?permission=" + permission; + } + return this.form(url, {report: report}); + } + + getReports(pollId, commentId, permission) { + let args = {}; + if (permission) { + args.permission = permission; + } + return this.getWithParams("/v1/polls/" + pollId + "/comments/" + commentId + "/reports", args); + } + + ignoreReport(pollId, commentId, reportId, permission) { + let args = {}; + if (permission) { + args.permission = permission; + } + return this.getWithParams("/v1/polls/" + pollId + "/comments/" + commentId + "/reports/" + reportId + "/ignore", args); + } } module.exports = singleton(CommentService); diff --git a/pollen-ui-riot-js/src/main/web/js/Poll.js b/pollen-ui-riot-js/src/main/web/js/Poll.js index c16d2739..b8357a3e 100644 --- a/pollen-ui-riot-js/src/main/web/js/Poll.js +++ b/pollen-ui-riot-js/src/main/web/js/Poll.js @@ -342,6 +342,54 @@ class Poll { return Promise.reject("Init poll after delete comment"); } + isPoll(target) { + return this === target; + } + + isComment(target) { + return this.comments && this.comments.indexOf(target) >= 0; + } + + isChoice(target) { + return this.choices && this.choices.indexOf(target) >= 0; + } + + _getService(target) { + let service; + if (this.isPoll(target)) { + service = pollService; + } else if (this.isComment(target)) { + service = commentService; + } else if (this.isChoice(target)) { + service = choiceService; + } + return service; + } + + addReport(target, report) { + if (this.id) { + let service = this._getService(target); + return service.addReport(this.id, target.id, report, this.permission || ""); + } + return Promise.reject("Init poll after add report"); + } + + getReports(target) { + if (this.id) { + let service = this._getService(target); + return service.getReports(this.id, target.id, this.permission || ""); + } + return Promise.reject("Init poll after load reports"); + } + + ignoreReport(target, report) { + if (this.id) { + let service = this._getService(target); + return service.ignoreReport(this.id, target.id, report.id, this.permission || ""); + } + return Promise.reject("Init poll after ignore report"); + } + } module.exports = singleton(Poll); diff --git a/pollen-ui-riot-js/src/main/web/js/PollService.js b/pollen-ui-riot-js/src/main/web/js/PollService.js index 12bd3f98..3db34cca 100644 --- a/pollen-ui-riot-js/src/main/web/js/PollService.js +++ b/pollen-ui-riot-js/src/main/web/js/PollService.js @@ -87,6 +87,30 @@ class PollService extends FetchService { } return this.put(url); } + + addReport(pollId, targetId, report, permission) { + let url = "/v1/polls/" + pollId + "/reports"; + if (permission) { + url += "?permission=" + permission; + } + return this.form(url, {report: report}); + } + + getReports(pollId, targetId, permission) { + let args = {}; + if (permission) { + args.permission = permission; + } + return this.getWithParams("/v1/polls/" + pollId + "/reports", args); + } + + ignoreReport(pollId, targetId, reportId, permission) { + let args = {}; + if (permission) { + args.permission = permission; + } + return this.getWithParams("/v1/polls/" + pollId + "/reports/" + reportId + "/ignore", args); + } } module.exports = singleton(PollService); diff --git a/pollen-ui-riot-js/src/main/web/js/Session.js b/pollen-ui-riot-js/src/main/web/js/Session.js index d3144848..52c7c7ad 100644 --- a/pollen-ui-riot-js/src/main/web/js/Session.js +++ b/pollen-ui-riot-js/src/main/web/js/Session.js @@ -41,7 +41,8 @@ class Session { userValidateUrl: window.location.origin + "/#signcheck/{userId}/{token}", pollVoteUrl: window.location.origin + "/#poll/{pollId}/vote/{token}", pollVoteEditUrl: window.location.origin + "/#poll/{pollId}/vote/{voteId}/{token}", - pollEditUrl: window.location.origin + "/#poll/{pollId}/edit/{token}" + pollEditUrl: window.location.origin + "/#poll/{pollId}/edit/{token}", + resourceUrl: this.configuration.endPoint + "/v1/resources/{resourceId}/download" }; // pour contenir les traductions this.i18n = require("../i18n.json"); diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/ChoiceView.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/ChoiceView.tag.html index 53e0b7ef..b08d405d 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/ChoiceView.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/ChoiceView.tag.html @@ -1,3 +1,4 @@ +require("./Report.tag.html"); <ChoiceView> <div class="choice-view {with-info : opts.choice.choiceType === 'RESOURCE' || opts.choice.description}" onclick={openModalImage} @@ -26,6 +27,7 @@ <i class="fa fa-question-circle" aria-hidden="true"></i> </div> </div> + <Report target={opts.choice}/> <div if={showModalImage} onclick={closeModalImage}> <div class="c-overlay"></div> @@ -104,7 +106,12 @@ </script> <style> + choiceview { + display: flex; + } + .choice-view { + flex-grow: 1; display: flex; justify-content: center; } diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Comments.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Comments.tag.html index 9865aeed..7f09740f 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Comments.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Comments.tag.html @@ -1,5 +1,5 @@ require("../Pagination.tag.html"); - +require("./Report.tag.html"); <Comments> <form show="{loaded}" onsubmit="{addComment}" class="comment-form"> <div class="comment"> @@ -69,6 +69,7 @@ require("../Pagination.tag.html"); </div> <div class="user"> {comment.authorName} + <Report target={comment}/> <div class="comment-date"> {formatDate(comment.postDate)} </div> diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag.html index f433e424..d79da368 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag.html @@ -4,7 +4,7 @@ require("./Results.tag.html"); require("./Choices.tag.html"); require("./Settings.tag.html"); require("../popup/QrCodeButton.tag.html"); - +require("./Report.tag.html"); <Poll> <div class="tabs"> @@ -120,6 +120,7 @@ require("../popup/QrCodeButton.tag.html"); <h1> <QrCodeButton if={poll.pollType === "FREE"} value="{window.location.origin}{window.location.pathname}#poll/{poll.id}/vote"/> {poll.title} + <Report target={poll}/> <a href="{session.configuration.endPoint}/v1/polls/{poll.id}/feed?permission={poll.permission}" class="fa fa-rss-square" aria-hidden="true"></a> </h1> diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Report.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Report.tag.html new file mode 100644 index 00000000..689b518a --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Report.tag.html @@ -0,0 +1,232 @@ +require("../popup/Modal.tag.html"); +<Report> + + <span class="label info-label" + show={!poll.permission} + onclick={openModalAddReport} title={__.title}> + <i class="fa fa-bell" aria-hidden="true"></i> + </span> + + <span class="label {opts.target.report.count > opts.target.report.ignore ? 'error-label' : 'info-label'}" + if={poll.permission && opts.target.report && opts.target.report.count} + onclick={openReports} + title="{__.count} : {opts.target.report.count}{opts.target.report.ignore > 0 ? ' (' + opts.target.report.ignore + ' ' + __.ignores + ')' : ''} {__.score} : {opts.target.report.score}"> + <i class="fa fa-exclamation-circle" aria-hidden="true"></i> + </span> + + <modal ref="modalAddReport" header={__.add_title} onsubmit={submitAddReport} label={__.add_action} type="warning"> + <fieldset class="o-fieldset"> + <legend class="o-fieldset__legend">{parent.__.level}</legend> + <label class="c-field c-field--choice"> + <input type="radio" + name="level" + ref="level" + required + value="SPAM"> + {parent.__.level_spam_detail} + </label> + <label class="c-field c-field--choice"> + <input type="radio" + name="level" + ref="level" + value="OFF_TOPIC"> + {parent.__.level_off_topic_detail} + </label> + <label class="c-field c-field--choice"> + <input type="radio" + name="level" + ref="level" + value="ILLEGAL"> + {parent.__.level_illegal_detail} + </label> + </fieldset> + + <div class="o-form-element"> + <label class="c-label" for="email">{parent.__.email}</label> + <input type="email" + id="email" + ref="email" + placeholder="{parent.__.email_placeholder}" + value={parent.session.getUser() && parent.session.getUser().email} + required + class="c-field"> + </div> + </modal> + + <modal ref="modalReports" header={__.reports_title} only-ok="true"> + <div show={hasReports(false, 'ILLEGAL')}> + <div class="c-card__item c-card__item--error">{parent.__.level_illegal}</div> + <div class="c-card__item"> + <div each={report in parent.filterReports(false, 'ILLEGAL')} class="report"> + <div class="report-email"> + {report.email} + </div> + <div onclick={parent.parent.ignoreReport(report)} title={parent.parent.__.toIgnore}> + <i class="fa fa-ban" aria-hidden="true"></i> + </div> + </div> + </div> + </div> + <div show={hasReports(false, 'SPAM')}> + <div class="c-card__item c-card__item--warning">{parent.__.level_spam}</div> + <div class="c-card__item"> + <div each={report in parent.filterReports(false, 'SPAM')} class="report"> + <div class="report-email"> + {report.email} + </div> + <div onclick={parent.parent.ignoreReport(report)} title={parent.parent.__.toIgnore}> + <i class="fa fa-ban" aria-hidden="true"></i> + </div> + </div> + </div> + </div> + <div show={hasReports(false, 'OFF_TOPIC')}> + <div class="c-card__item c-card__item--info">{parent.__.level_off_topic}</div> + <div class="c-card__item"> + <div each={report in parent.filterReports(false, 'OFF_TOPIC')} class="report"> + <div class="report-email"> + {report.email} + </div> + <div onclick={parent.parent.ignoreReport(report)} title={parent.parent.__.toIgnore}> + <i class="fa fa-ban" aria-hidden="true"></i> + </div> + </div> + </div> + </div> + <div class="c-card__item" + show={hasIgnoreReports()}> + {parent.__.ignores} : + <button type="button" + show={hasReports(true, 'ILLEGAL')} + onclick={parent.showIgnoreReports('ILLEGAL')} + class="c-button c-button--rounded c-button--error u-small"> + {parent.filterReports(true, 'ILLEGAL').length} + {parent.__.level_illegal} + </button> + <button type="button" + show={hasReports(true, 'SPAM')} + onclick={parent.showIgnoreReports('SPAM')} + class="c-button c-button--rounded c-button--warning u-small"> + {parent.filterReports(true, 'SPAM').length} + {parent.__.level_spam} + </button> + <button type="button" + show={hasReports(true, 'OFF_TOPIC')} + onclick={parent.showIgnoreReports('OFF_TOPIC')} + class="c-button c-button--rounded c-button--info u-small"> + {parent.filterReports(true, 'OFF_TOPIC').length} + {parent.__.level_off_topic} + </button> + <div each={report in parent.ignoreReports}> + <div class="report-email"> + {report.email} + </div> + </div> + </div> + </modal> + + <script type="es6"> + this.session = require("../../js/Session"); + this.installBundle(this.session, "report"); + this.poll = require("../../js/Poll.js"); + this.reports = []; + this.ignoreReports = []; + + this.openModalAddReport = e => { + e.preventDefault(); + e.stopPropagation(); + this.refs.modalAddReport.refs.level.forEach(radio => {radio.checked = false;}); + this.refs.modalAddReport.open().then(() => {this.update();}, () => {}); + }; + + this.submitAddReport = () => { + let report = { + level: this.refs.modalAddReport.refs.level.find(radio => radio.checked).value, + email: this.refs.modalAddReport.refs.email.value + }; + + return this.poll.addReport(this.opts.target, report); + + }; + + this.openReports = e => { + e.preventDefault(); + e.stopPropagation(); + this.poll.getReports(this.opts.target).then(reports => { + this.reports = reports; + this.refs.modalReports.open().then(() => { + if (this.poll.isPoll(this.opts.target)) { + this.poll.reloadPoll(); + } else if (this.poll.isComment(this.opts.target)) { + this.poll.loadComments(); + } else if (this.poll.isChoice(this.opts.target)) { + this.poll.loadChoices(); + } else { + this.update(); + } + }, () => {}); + this.update(); + }); + }; + + this.ignoreReport = report => () => { + this.poll.ignoreReport(this.opts.target, report).then(() => { + this.poll.getReports(this.opts.target).then(reports => { + this.reports = reports; + this.update(); + }); + }); + }; + + this.hasReports = (ignore, level) => { + return this.filterReports(ignore, level).length > 0; + }; + + this.hasIgnoreReports = () => { + return this.reports.filter(report => report.ignore).length > 0; + }; + + this.filterReports = (ignore, level) => { + return this.reports.filter(report => report.ignore === ignore && report.level === level); + }; + + this.showIgnoreReports = (level) => () => { + this.ignoreReports = this.filterReports(true, level); + }; + + + </script> + + <style> + report { + float: right; + font-size: 1rem; + text-align: left; + } + + .label { + vertical-align: text-top; + } + + td { + padding-right: 10px; + padding-left: 10px; + } + + .ignore { + text-decoration: line-through; + } + + .report { + display: flex; + justify-content: space-between; + align-items: baseline; + } + + .report-email { + padding-right: 20px; + } + + </style> + +</Report> diff --git a/pollen-ui-riot-js/src/main/web/tag/popup/Modal.tag.html b/pollen-ui-riot-js/src/main/web/tag/popup/Modal.tag.html index ce3e435a..3781f995 100644 --- a/pollen-ui-riot-js/src/main/web/tag/popup/Modal.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/popup/Modal.tag.html @@ -5,7 +5,7 @@ <form class="c-card c-card--higher" onsubmit={submit}> <header class="c-card__header"> <h2 class="c-heading"> - {opts.title} + {opts.header} </h2> </header> <div class="c-card__body"> @@ -14,6 +14,7 @@ <footer class="c-card__footer c-card__footer--block"> <div class="c-input-group"> <button type="button" + show={!opts.onlyOk} class="c-button c-button--block c-button--brand" onclick={cancel}> {__.cancel} diff --git a/pollen-ui-riot-js/src/main/web/tag/popup/NewPassword.tag.html b/pollen-ui-riot-js/src/main/web/tag/popup/NewPassword.tag.html index af23b655..418988e7 100644 --- a/pollen-ui-riot-js/src/main/web/tag/popup/NewPassword.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/popup/NewPassword.tag.html @@ -19,7 +19,7 @@ * #L% */ <NewPassword> - <Modal ref="modal" title={__.title} onsubmit={submit} label={__.action}> + <Modal ref="modal" header={__.title} onsubmit={submit} label={__.action}> <input class="c-field {c-field--error : parent.error}" ref="email" type="email" @@ -34,7 +34,7 @@ <i class="fa fa-envelope"></i> {parent.__.sent} </div> </Modal> - + <script type="es6"> let session = require("../../js/Session"); let authService = require("../../js/AuthService"); diff --git a/pollen-ui-riot-js/src/main/web/tag/popup/ResendValidation.tag.html b/pollen-ui-riot-js/src/main/web/tag/popup/ResendValidation.tag.html index 341dda46..be682276 100644 --- a/pollen-ui-riot-js/src/main/web/tag/popup/ResendValidation.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/popup/ResendValidation.tag.html @@ -19,7 +19,7 @@ * #L% */ <ResendValidation> - <Modal ref="modal" title={__.title} onsubmit={submit} label={__.action}> + <Modal ref="modal" header={__.title} onsubmit={submit} label={__.action}> <input class="c-field {c-field--error : parent.error}" ref="email" type="email" diff --git a/pollen-ui-riot-js/src/main/web/tag/voterList/VoterListActions.tag.html b/pollen-ui-riot-js/src/main/web/tag/voterList/VoterListActions.tag.html index dcb11adf..7e3436eb 100644 --- a/pollen-ui-riot-js/src/main/web/tag/voterList/VoterListActions.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/voterList/VoterListActions.tag.html @@ -57,7 +57,7 @@ <i class="fa fa-times" aria-hidden="true"></i> </button> - <modal title={__.importFavoriteList} + <modal header={__.importFavoriteList} ref="importFavoriteListModal"> <div show={favoriteLists.length === 0}> {__.importFavoriteList_none} -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
participants (1)
-
chorem.org scm