This is an automated email from the git hooks/post-receive script. New commit to branch feature/882 in repository chorem. See http://git.chorem.org/chorem.git commit 3446bf77ef341663cf16ab44f6d5f1a694db5bcd Author: kootox <jean.couteau@gmail.com> Date: Fri Jan 30 15:09:36 2015 +0100 refs #882 : CRM Poc using Bootcards. To be continued. (Roughly showing companies list + each company info) --- .../webmotion/actions/crm/CompaniesAction.java | 85 ++++ chorem-webmotion/src/main/resources/mapping | 4 + .../WEB-INF/jsp/crm/cards/companyInfoCard.jsp | 26 ++ .../jsp/crm/cards/contactDetailsListCard.jsp | 28 ++ .../WEB-INF/jsp/crm/cards/employeesListCard.jsp | 29 ++ .../webapp/WEB-INF/jsp/crm/cards/notesListCard.jsp | 34 ++ .../src/main/webapp/WEB-INF/jsp/crm/companies.jsp | 435 +++++++++++++++++++++ .../src/main/webapp/WEB-INF/jsp/crm/company2.jsp | 13 + 8 files changed, 654 insertions(+) diff --git a/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/CompaniesAction.java b/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/CompaniesAction.java new file mode 100644 index 0000000..d282feb --- /dev/null +++ b/chorem-webmotion/src/main/java/org/chorem/webmotion/actions/crm/CompaniesAction.java @@ -0,0 +1,85 @@ +package org.chorem.webmotion.actions.crm; + +import org.chorem.ChoremClient; +import org.chorem.entities.Company; +import org.chorem.entities.ContactDetails; +import org.chorem.entities.Employee; +import org.chorem.entities.Note; +import org.debux.webmotion.server.WebMotionController; +import org.debux.webmotion.server.render.Render; +import org.nuiton.wikitty.query.WikittyQuery; +import org.nuiton.wikitty.query.WikittyQueryMaker; + +import java.util.List; + +/** + * Created by couteau on 28/01/15. + */ +public class CompaniesAction extends WebMotionController { + /** + * Rend le graphe des devis envoyés par mois + * + * @param client + * @return + */ + public Render listCompanies(ChoremClient client) { + + //list all the companies + WikittyQuery companiesQuery = new WikittyQueryMaker().exteq(Company.EXT_COMPANY).end(); + List<Company> companies = client.findAllByQuery(Company.class, companiesQuery).getAll(); + + //get the first company info to init the page + Company company = companies.get(0); + List<Note> notes = listNotes(client, company.getWikittyId()); + List<ContactDetails> contactDetails = listContactDetails(client, company.getWikittyId()); + List<Employee> employees = listEmployee(client, company.getWikittyId()); + + return renderView("crm/companies.jsp", + "companies", companies, + "company", company, + "contactDetails", contactDetails, + "employees", employees, + "notes", notes); + } + + public Render viewCompany(ChoremClient client, String id) { + Company company = client.restore(Company.class, id); + List<Note> notes = listNotes(client, id); + List<ContactDetails> contactDetails = listContactDetails(client, id); + List<Employee> employees = listEmployee(client, id); + + return renderView("crm/company2.jsp", + "company", company, + "contactDetails", contactDetails, + "employees", employees, + "notes", notes); + + } + + public List<Note> listNotes(ChoremClient client, String companyId) { + WikittyQuery notesQuery = new WikittyQueryMaker().and() + .exteq(Note.EXT_NOTE) + .eq(Note.FQ_FIELD_NOTE_TARGET, companyId).end(); + List<Note> notes = client.findAllByQuery(Note.class, notesQuery).getAll(); + + return notes; + } + + public List<ContactDetails> listContactDetails(ChoremClient client, String companyId) { + WikittyQuery contactDetailsQuery = new WikittyQueryMaker().and() + .exteq(ContactDetails.EXT_CONTACTDETAILS) + .eq(ContactDetails.FQ_FIELD_CONTACTDETAILS_TARGET, companyId).end(); + List<ContactDetails> contactDetails = client.findAllByQuery(ContactDetails.class, contactDetailsQuery).getAll(); + + return contactDetails; + } + + public List<Employee> listEmployee(ChoremClient client, String companyId) { + WikittyQuery employeesQuery = new WikittyQueryMaker().and() + .exteq(Employee.EXT_EMPLOYEE) + .eq(Employee.FQ_FIELD_EMPLOYEE_COMPANY, companyId).end(); + List<Employee> employees = client.findAllByQuery(Employee.class, employeesQuery).getAll(); + + return employees; + } +} diff --git a/chorem-webmotion/src/main/resources/mapping b/chorem-webmotion/src/main/resources/mapping index e1bf470..f813fca 100644 --- a/chorem-webmotion/src/main/resources/mapping +++ b/chorem-webmotion/src/main/resources/mapping @@ -13,6 +13,7 @@ default.render=org.debux.webmotion.server.render.DefaultRender * /sales/funnel/json/* DecoratorFilter.decorate wmDecoratorNo=true * /sales/funnel/partial/* DecoratorFilter.decorate wmDecoratorNo=true * /crm/export DecoratorFilter.decorate wmDecoratorNo=true +* /crm/companies/* DecoratorFilter.decorate wmDecoratorNo=true * /project/editProject.html DecoratorFilter.decorate wmDecoratorNo=true * /financial/expenseAccounts/expenseAccountEntryEdit.html DecoratorFilter.decorate wmDecoratorNo=true * /hr/employeeEdit/json/* DecoratorFilter.decorate wmDecoratorNo=true @@ -93,6 +94,9 @@ GET /* DecoratorFilter.decorate * /crm/account/{id} action:crm.AccountAction.view * /crm/quotation/edit/{id} action:crm.QuotationAction.edit * /crm/export action:crm.ExportAction.exportContactBase +* /crm/companies action:crm.CompaniesAction.listCompanies +* /crm/companies/{id} action:crm.CompaniesAction.viewCompany +* /crm/companies/add action:crm.CompaniesAction.addCompany GET /rest/project/projects?page={page}&count={count} action:project.ProjectsAction.findAllProjects page=1,count=10 GET /project/projects view:projects/projects.jsp diff --git a/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/cards/companyInfoCard.jsp b/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/cards/companyInfoCard.jsp new file mode 100644 index 0000000..3c90b3d --- /dev/null +++ b/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/cards/companyInfoCard.jsp @@ -0,0 +1,26 @@ +<%@page contentType="text/html" pageEncoding="UTF-8"%> + +<div class="panel panel-default"> + + <div class="panel-heading clearfix"> + <h3 class="panel-title pull-left">Informations</h3> + + <div class="btn-group pull-right"> + <a class="btn btn-primary" href="#" data-toggle="modal" data-target="#editModal"> + <i class="fa fa-pencil"></i><span>Edit</span> + </a> + </div> + + </div> + + <div class="list-group"> + <div class="list-group-item"> + <p class="list-group-item-text">Nom</p> + <h4 class="list-group-item-heading">${company.name}</h4> + </div> + <div class="list-group-item"> + <p class="list-group-item-text">Type</p> + <h4 class="list-group-item-heading">${company.type}</h4> + </div> + </div> +</div> \ No newline at end of file diff --git a/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/cards/contactDetailsListCard.jsp b/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/cards/contactDetailsListCard.jsp new file mode 100644 index 0000000..3f42b1e --- /dev/null +++ b/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/cards/contactDetailsListCard.jsp @@ -0,0 +1,28 @@ +<%@page contentType="text/html" pageEncoding="UTF-8"%> + +<div class="panel panel-default"> + + <div class="panel-heading clearfix"> + <h3 class="panel-title pull-left">Coordonnées</h3> + <div class="btn-group pull-right"> + <a class="btn btn-primary" href="#" + data-toggle="modal" + data-target="#editModal"> + <i class="fa fa-plus"></i> + <span>Add</span> + </a> + </div> + + </div> + + <div class="list-group"> + + <c:forEach var="contactDetail" items="${contactDetails}"> + <div class="list-group-item"> + <p class="list-group-item-text">${contactDetail.type}</p> + <h4 class="list-group-item-heading">${contactDetail.value}</h4> + </div> + </c:forEach> + + </div> +</div> \ No newline at end of file diff --git a/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/cards/employeesListCard.jsp b/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/cards/employeesListCard.jsp new file mode 100644 index 0000000..10cb08e --- /dev/null +++ b/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/cards/employeesListCard.jsp @@ -0,0 +1,29 @@ + <%@page contentType="text/html" pageEncoding="UTF-8"%> + +<div id="contactCard"> + +<div class="panel panel-default"> + <div class="panel-heading clearfix"> + <h3 class="panel-title pull-left">Contacts</h3> + <div class="btn-group pull-right visible-xs"> + <a class="btn btn-primary" href="#" data-toggle="modal" data-target="#editModal"> + <i class="fa fa-plus"></i> + <span>Add</span> + </a> + </div> + <a class="btn btn-primary pull-right hidden-xs" href="#" data-toggle="modal" data-target="#editModal"> + <i class="fa fa-pencil"></i><span>Edit</span> + </a> + </div> + <div class="list-group"> + + <c:forEach var="employee" items="${employees}"> + <a class="list-group-item" href="#"> + <h4 class="list-group-item-heading">${employee.person}</h4> + <p class="list-group-item-text">${company.name}</p> + </a> + </c:forEach> + + </div> + +</div> \ No newline at end of file diff --git a/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/cards/notesListCard.jsp b/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/cards/notesListCard.jsp new file mode 100644 index 0000000..56f91db --- /dev/null +++ b/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/cards/notesListCard.jsp @@ -0,0 +1,34 @@ +<%@page contentType="text/html" pageEncoding="UTF-8"%> + +<div class="panel panel-default"> + + <div class="panel-heading clearfix"> + <h3 class="panel-title pull-left">Notes</h3> + + <div class="btn-group pull-right"> + <a class="btn btn-primary" href="#" + data-toggle="modal" + data-target="#editModal"> + <i class="fa fa-plus"></i> + <span>Add</span> + </a> + </div> + + </div> + + <div class="list-group"> + + <c:forEach var="note" items="${notes}"> + <a class="list-group-item" href="#"> + <h4 class="list-group-item-heading">${note.title}</h4> + <p class="list-group-item-text">${note.date}</p> + </a> + </c:forEach> + + </div> + + <div class="panel-footer"> + <small class="pull-left">List Card Footer</small> + </div> + + </div> \ No newline at end of file diff --git a/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/companies.jsp b/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/companies.jsp new file mode 100644 index 0000000..33934e5 --- /dev/null +++ b/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/companies.jsp @@ -0,0 +1,435 @@ +<%-- + #%L + Chorem :: webmotion + %% + Copyright (C) 2011 - 2015 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + #L% + --%> +<%@page contentType="text/html" pageEncoding="UTF-8"%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f" %> +<%@ taglib uri="/WEB-INF/wikitty.tld" prefix="w"%> + +<head> + <link href="https://cdnjs.cloudflare.com/ajax/libs/bootcards/1.1.0/css/bootcards-desktop..." rel="stylesheet"> + <link href="https://netdna.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet" /> +</head> + +<body> + + <div class="container bootcards-container push-right"> + + <div class="row"> + + <!-- left list column --> + <div class="col-sm-5 bootcards-list" id="list" data-title="Companies"> + <div class="panel panel-default"> + <div class="panel-body"> + <div class="search-form"> + <div class="row"> + <div class="col-xs-9"> + <div class="form-group"> + <input type="text" class="form-control" placeholder="Search Companies..."> + <i class="fa fa-search"></i> + </div> + </div> + <div class="col-xs-3"> + <a class="btn btn-primary btn-block" href="#" onclick="bootcards.hideOffCanvasMenu()" > + <i class="fa fa-plus"></i> + <span>Add</span> + </a> + </div> + </div> + </div> + </div><!--panel body--> + + <div class="list-group"> + + <c:forEach var="company" items="${companies}"> + <a class="list-group-item pjax" href="<c:url value="/crm/companies/${company.wikittyId}"/>""> + <i class="fa fa-3x fa-building-o pull-left"></i> + <h4 class="list-group-item-heading">${company.name}</h4> + <p class="list-group-item-text">${company.type} </p> + </a> + </c:forEach> + + </div><!--list-group--> + </div><!--panel--> + + </div><!--list--> + + <!--list details column--> + <div id='listDetails' class="col-sm-7 bootcards-cards hidden-xs"> + + <!-- company info card --> + <%@include file="cards/companyInfoCard.jsp" %> + + <!-- contact details card --> + <%@include file="cards/contactDetailsListCard.jsp" %> + + <!-- notes card --> + <%@include file="cards/notesListCard.jsp" %> + + <!--employees card --> + <%@include file="cards/employeesListCard.jsp" %> + + + </div><!--list-details--> + + </div><!--row--> + + + </div><!--container--> + + <!--edit contact modal--> + <div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="editModal" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + + <form class="form-horizontal" method="POST" action="/contacts/{{contact.id}}" data-pjax="#main"> + + <div class="modal-header"> + + <div class="btn-group pull-left"> + <button class="btn btn-danger" data-dismiss="modal"> + Cancel + </button> + </div> + + <div class="btn-group pull-right"> + <button class="btn btn-success" data-dismiss="modal"> + <i class="fa fa-check"></i>Save + </button> + </div> + + <h4 class="modal-title"> + Edit Contact + </h4> + </div> + + <div class="modal-body"> + <input type="hidden" name="companyId" value="{{contact.companyId}}"> + <input type="hidden" name="_method" value="put"> + <div class="form-group"> + <label class="col-xs-4 control-label">First Name</label> + <div class="col-xs-8"> + <input type="text" name="firstName" class="form-control" placeholder="First Name" + value="Sofia"> + </div> + </div> + <div class="form-group"> + <label class="col-xs-4 control-label">Last Name</label> + <div class="col-xs-8"> + <input type="text" name="lastName" class="form-control" placeholder="Last Name" + value="Acey"> + </div> + </div> + <div class="form-group"> + <label class="col-xs-4 control-label">Company</label> + <div class="col-xs-8"> + <input type="text" name="department" class="form-control" placeholder="Department" + value="Masung Corp."> + </div> + </div> + <div class="form-group"> + <label class="col-xs-4 control-label">Phone</label> + <div class="col-xs-8"> + <input type="text" name="phone" class="form-control" + placeholder="Phone" + value="+1 650-555-0055"> + </div> + </div> + <div class="form-group"> + <label class="col-xs-4 control-label">Email</label> + <div class="col-xs-8"> + <input type="email" name="email" class="form-control" placeholder="Email" + value="Sofia.Acey@masung.com"> + </div> + </div> + + </div> + </form> + + <div class="modal-footer"> + <button type="button" class="btn btn-danger btn-block" + onclick="bootcards.confirmDelete('contact'); return false;"> + <i class="fa fa-trash-o"></i> + Delete Contact + </button> + </div> + + </div><!--modal-content--> + </div> + </div><!--modal--> + + <!-- Bootstrap & jQuery core JavaScript + ================================================== --> + <!-- Placed at the end of the document so the pages load faster --> + <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.pjax/1.9.2/jquery.pjax.min.js"></script> + <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script> + + <!-- Bootcards JS --> + <script src="https://cdnjs.cloudflare.com/ajax/libs/bootcards/1.1.0/js/bootcards.js"></script> + + <!--recommended: FTLabs FastClick library--> + <script src="https://cdnjs.cloudflare.com/ajax/libs/fastclick/1.0.3/fastclick.min.js"></script> + + <script type="text/javascript"> + + /* + * Initialize Bootcards. + * + * Parameters: + * - offCanvasBackdrop (boolean): show a backdrop when the offcanvas is shown + * - offCanvasHideOnMainClick (boolean): hide the offcanvas menu on clicking outside the off canvas + * - enableTabletPortraitMode (boolean): enable single pane mode for tablets in portraitmode + * - disableRubberBanding (boolean): disable the iOS rubber banding effect + * - disableBreakoutSelector (boolean) : for iOS apps that are added to the home screen: + jQuery selector to target links for which a fix should be added to not + allow those links to break out of fullscreen mode. + */ + bootcards.init( { + offCanvasBackdrop : true, + offCanvasHideOnMainClick : true, + enableTabletPortraitMode : true, + disableRubberBanding : true + }); + + //enable FastClick + window.addEventListener('load', function() { + FastClick.attach(document.body); + }, false); + + //activate the sub-menu options in the offcanvas menu + $('.collapse').collapse(); + + //highlight first list group option (if non active yet) + if ( $('.list-group a.active').length === 0 ) { + $('.list-group a').first().addClass('active'); + } + + /* + * Add click handlers to links to force a pjax (partial) load + * http://pjax.heroku.com/ + */ + bootcards.addPJaxHandlers = function(pjaxTarget) { + + //add pjax click handler to links + $('a.pjax').off().on('click', function(e) { + var $this = $(this); + var tgtUrl = $this.attr('href'); + + $.pjax( { + container : pjaxTarget, + url : tgtUrl + }); + + //add active class if this is a list item (removing it from all siblings) + if ($this.hasClass('list-group-item')) { + $this + .addClass('active') + .siblings() + .removeClass('active'); + } + + e.preventDefault(); + }); + + }; + + //pjax on all a's that have the data-pjax attribute (the attribute's value is the pjax target container) + $(document).ready( function() { + + //publish event when changing main menu option + $("a[data-title]").on("click", function() { + $.Topic( "navigateTo" ).publish( $(this).data("title") ); + }); + + var $body = $("body"); + + //fix for status bar bug in iOS 8 + if (bootcards.isFullScreen) { + $body + .prepend("<div class='statusbar' />") + .addClass("fullscreen"); + } + + //destroy modals on close (to reload the contents when using the remote property) + $body.on('hidden.bs.modal', '.modal', function () { + $(this).removeData('bs.modal'); + }); + + var pjaxTarget = (bootcards.isXS() ? '#list' : '#listDetails'); + + if (bootcards.isXS() ) { + + //restrict footer to only 4 items + var $footer = $(".navbar-fixed-bottom .btn-group"); + if ($footer.length>0) { + var $links = $('a', $footer); + + if ($links.length > 4) { + $links.each( function(idx) { + if (idx >= 4) { this.remove(); } + }); + } + } + + } + + bootcards.addPJaxHandlers(pjaxTarget); + + $(document) + .pjax('a[data-pjax]') + .on('submit', 'form[data-pjax]', function(event) { + //use pjax to submit forms + $.pjax.submit(event); + }) + .on('pjax:start', function(event) { + + //hide the offcanvas menu + $("#offCanvasMenu").removeClass("active"); + $("#main").removeClass("active"); + + }) + .on('pjax:end', function(event) { + + var $tgt = $(event.target); + var tgtId = $tgt.attr('id'); + + if ( bootcards.isXS() ) { + //function only performed on small screens (smartphones) + + //we only use the list column + var details = $('#listDetails'); + if (details.length>0) { + details.remove(); + } + + //change class on container elements (list>card and vice versa) + if ( tgtId == 'main') { + + $('#list') + .removeClass('bootcards-cards') + .addClass('bootcards-list'); + + //show the back button + $('.btn-menu').removeClass('hidden'); + $('.btn-back').addClass('hidden'); + + //get the panel + var $main = $("#main"); + var $panel = $("#main > .panel"); + if ($panel.length>0) { + + var row = $('<div class="row"></div>'); + var container = $('<div class="col-sm-5 bootcards-list" id="list"></div>') + .appendTo(row); + + $panel.appendTo(container); + + row.appendTo($main); + } + + } else if (tgtId == 'list') { + + var $list = $('#list'); + + if ( !$list.hasClass('bootcards-cards')) { + + $list + .addClass('bootcards-cards') + .removeClass('bootcards-list'); + + //show the menu button + $('.btn-menu').addClass('hidden'); + $('.btn-back').removeClass('hidden'); + + //scroll to the top of the card + $list.animate({scrollTop:0}, '500', 'easeOutExpo'); + } + + } + + } + + bootcards.addPJaxHandlers(pjaxTarget); + + //highlight first list group option (if non active yet) + if ( $('.list-group a.active').length === 0 ) { + $('.list-group a').first().addClass('active'); + } + + //enable single pane portrait mode when loading content with pjax + if ( tgtId == 'main' && bootcards.portraitModeEnabled ) { + + //do some cleaning up first + if (bootcards.listOffcanvasToggle) { + bootcards.listOffcanvasToggle.remove(); + bootcards.listTitleEl.remove(); + Bootcards.OffCanvas.$menuTitleEl.remove(); + } + bootcards.listOffcanvasToggle = null; + bootcards.listTitleEl = null; + Bootcards.OffCanvas.$menuTitleEl = null; + bootcards.listEl = null; + bootcards.cardsEl = null; + + bootcards._setOrientation(true); + + if (bootcards.listTitleEl) { + bootcards.listTitleEl.find('button').show(); + } + + //add the resize events again + $(window) + .off() + .on( 'resize', function() { + setTimeout( function() { + bootcards._setOrientation(false); + if (chartSalesProductType !== null) { chartSalesProductType.redraw(); } + if (closedSalesChart !== null) { closedSalesChart.redraw(); } + if (dbSizeChart !== null) { dbSizeChart.redraw(); } + if (barChartClosedSales !== null) { barChartClosedSales.redraw(); } + } , 250); + } ); + + } + + }) + .on('pjax:complete', function(event) { + //called after a pjax content update + + //check for any modals to close + var modal = $(event.relatedTarget).closest('.modal'); + if (modal.length) { + modal.modal('hide'); + } + + }); + + }); + + + /* + * Enable FTLabs' FastClick + * https://github.com/ftlabs/fastclick + */ + window.addEventListener('load', function() { + FastClick.attach(document.body); + }, false); + + </script> + </body> diff --git a/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/company2.jsp b/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/company2.jsp new file mode 100644 index 0000000..972664c --- /dev/null +++ b/chorem-webmotion/src/main/webapp/WEB-INF/jsp/crm/company2.jsp @@ -0,0 +1,13 @@ +<%@page contentType="text/html" pageEncoding="UTF-8"%> + +<!-- company info card --> +<%@include file="cards/companyInfoCard.jsp" %> + +<!-- contact details card --> +<%@include file="cards/contactDetailsListCard.jsp" %> + +<!-- notes card --> +<%@include file="cards/notesListCard.jsp" %> + +<!--employees card --> +<%@include file="cards/employeesListCard.jsp" %> \ No newline at end of file -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.