diff --git a/src/main/java/no/nibio/vips/logic/controller/servlet/OrganizationController.java b/src/main/java/no/nibio/vips/logic/controller/servlet/OrganizationController.java new file mode 100644 index 0000000000000000000000000000000000000000..771aa88c44e850d4bf4410af4ad769184e6bfa36 --- /dev/null +++ b/src/main/java/no/nibio/vips/logic/controller/servlet/OrganizationController.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2019 NIBIO <http://www.nibio.no/>. + * + * This file is part of VIPSLogic. + * VIPSLogic is free software: you can redistribute it and/or modify + * it under the terms of the NIBIO Open Source License as published by + * NIBIO, either version 1 of the License, or (at your option) any + * later version. + * + * VIPSLogic 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 + * NIBIO Open Source License for more details. + * + * You should have received a copy of the NIBIO Open Source License + * along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>. + * + */ + +package no.nibio.vips.logic.controller.servlet; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.TimeZone; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import no.nibio.vips.gis.GISUtil; +import no.nibio.vips.gis.LonLatStringFormatException; +import no.nibio.vips.logic.entity.Organization; +import no.nibio.vips.logic.entity.VipsLogicUser; +import no.nibio.vips.logic.util.Globals; +import no.nibio.vips.logic.util.SessionControllerGetter; +import no.nibio.vips.util.ServletUtil; +import no.nibio.web.forms.FormValidation; +import no.nibio.web.forms.FormValidationException; +import no.nibio.web.forms.FormValidator; + +/** + * @copyright 2019 <a href="http://www.bioforsk.no/">Bioforsk</a> + * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no> + */ +public class OrganizationController extends HttpServlet { + + /** + * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods. + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + protected void processRequest(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.setContentType("text/html;charset=UTF-8"); + + VipsLogicUser user = (VipsLogicUser) request.getSession().getAttribute("user"); + // Basic authorization + if(!user.isSuperUser() && ! user.isOrganizationAdmin()){ + response.sendError(403,"Access not authorized"); + return; + } + String action = request.getParameter("action"); + // Default view for superuser: List of all organizations + // the user is a member + if(action == null && user.isSuperUser()) + { + List<Organization> organizations = SessionControllerGetter.getUserBean().getTopLevelOrganizations(); + request.setAttribute("organizations", organizations); + request.getRequestDispatcher("/organizationList.ftl").forward(request, response); + } + else if(action.equals("editOrganization") || action.equals("newOrganization")) + { + Organization organization; + List<VipsLogicUser> organizationUsers; + try + { + organization = SessionControllerGetter.getUserBean().getOrganization(Integer.valueOf(request.getParameter("organizationId"))); + organizationUsers = SessionControllerGetter.getUserBean().getUsersByOrganization(organization.getOrganizationId()); + Collections.sort(organizationUsers); + } + catch(NumberFormatException ex) + { + organization = new Organization(); + organizationUsers = Collections.EMPTY_LIST; + } + + //System.out.println(""); + if(organization.getDefaultMapCenter() != null) + { + request.setAttribute("defaultMapCenterLon", organization.getDefaultMapCenter().getCoordinate().x); + request.setAttribute("defaultMapCenterLat", organization.getDefaultMapCenter().getCoordinate().y); + } + + request.setAttribute("messageKey", request.getParameter("messageKey") != null ? request.getParameter("messageKey") : null); + request.setAttribute("organizationUsers", organizationUsers); + request.setAttribute("countries", SessionControllerGetter.getUserBean().getCountries()); + request.setAttribute("timeZones", TimeZone.getAvailableIDs()); + request.setAttribute("organization", organization); + request.getRequestDispatcher("/organizationForm.ftl").forward(request, response); + } + else if(action.equals("organizationFormSubmit")) + { + try + { + Integer organizationId = Integer.valueOf(request.getParameter("organizationId")); + Organization organization = organizationId > 0 ? + SessionControllerGetter.getUserBean().getOrganization(organizationId) + : new Organization(); + + FormValidation formValidation = FormValidator.validateForm("organizationForm", request, getServletContext()); + if(formValidation.isValid()) + { + organization.setOrganizationName(formValidation.getFormField("organizationName").getWebValue()); + organization.setAddress1(formValidation.getFormField("address1").getWebValue()); + organization.setAddress2(formValidation.getFormField("address2").getWebValue()); + organization.setPostalCode(formValidation.getFormField("postalCode").getWebValue()); + organization.setCountryCode(SessionControllerGetter.getUserBean().getCountry(formValidation.getFormField("countryCode").getWebValue())); + organization.setCity(formValidation.getFormField("city").getWebValue()); + organization.setDefaultLocale(formValidation.getFormField("defaultLocale").getWebValue()); + organization.setDefaultTimeZone(formValidation.getFormField("defaultTimeZone").getWebValue()); + organization.setVipswebUrl(formValidation.getFormField("vipswebUrl").getWebValue()); + Integer archiveUserId = formValidation.getFormField("archiveUserId").getValueAsInteger(); + organization.setArchiveUser(archiveUserId > 0 ? SessionControllerGetter.getUserBean().getVipsLogicUser(archiveUserId) : null); + organization.setDefaultVipsCoreUserId( + formValidation.getFormField("defaultVipsCoreUserId").isEmpty() ? + null + : formValidation.getFormField("defaultVipsCoreUserId").getValueAsInteger() + ); + organization.setDefaultMapZoom( + formValidation.getFormField("defaultMapZoom").isEmpty() ? + null + : formValidation.getFormField("defaultVipsCoreUserId").getValueAsInteger() + ); + organization.setDefaultMapCenter( + formValidation.getFormField("defaultMapCenter").isEmpty() || formValidation.getFormField("defaultMapCenter").getWebValue().trim().equals(",") ? + null + : new GISUtil().getJtsPointFromString(formValidation.getFormField("defaultMapCenter").getWebValue()) + ); + + organization = SessionControllerGetter.getUserBean().storeOrganization(organization); + + response.sendRedirect( + Globals.PROTOCOL + "://" + ServletUtil.getServerName(request) + + "/organization?action=editOrganization&organizationId=" + organization.getOrganizationId() + + "&messageKey=organizationStored" + ); + } + } + catch(FormValidationException | LonLatStringFormatException | NumberFormatException ex) + { + ex.printStackTrace(); + response.sendError(500, ex.getClass().toString() + ": " + ex.getMessage()); + } + } + } + + // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code."> + /** + * Handles the HTTP <code>GET</code> method. + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + processRequest(request, response); + } + + /** + * Handles the HTTP <code>POST</code> method. + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + processRequest(request, response); + } + + /** + * Returns a short description of the servlet. + * @return a String containing servlet description + */ + @Override + public String getServletInfo() { + return "Short description"; + }// </editor-fold> + +} diff --git a/src/main/java/no/nibio/vips/logic/controller/session/UserBean.java b/src/main/java/no/nibio/vips/logic/controller/session/UserBean.java index 2c5de313dec72f56308d94a6b257b2bf8c800025..80a92d6d45dc0ff7deb90e6e9610993389a01969 100755 --- a/src/main/java/no/nibio/vips/logic/controller/session/UserBean.java +++ b/src/main/java/no/nibio/vips/logic/controller/session/UserBean.java @@ -787,6 +787,11 @@ public class UserBean { return new ArrayList<>(); } } + + public List<Country> getCountries() + { + return em.createNamedQuery("Country.findAll").getResultList(); + } public List<OrganizationGroup> getOrganizationGroups(Organization organization) { try @@ -912,4 +917,12 @@ public class UserBean { public List<OrganizationGroup> getOrganizationGroups() { return em.createNamedQuery("OrganizationGroup.findAll").getResultList(); } + + public Country getCountry(String webValue) { + return em.find(Country.class, webValue); + } + + public Organization storeOrganization(Organization organization) { + return em.merge(organization); + } } diff --git a/src/main/java/no/nibio/vips/logic/entity/Country.java b/src/main/java/no/nibio/vips/logic/entity/Country.java index 99a57f73edfa867b527e77ccea789e179c8e09e4..e4aec6817584eeadaf6bf08a2c691af8fcce6b83 100755 --- a/src/main/java/no/nibio/vips/logic/entity/Country.java +++ b/src/main/java/no/nibio/vips/logic/entity/Country.java @@ -40,14 +40,14 @@ import javax.xml.bind.annotation.XmlTransient; import com.fasterxml.jackson.annotation.JsonIgnore; /** - * @copyright 2016 <a href="http://www.nibio.no/">NIBIO</a> + * @copyright 2019 <a href="http://www.nibio.no/">NIBIO</a> * @author Tor-Einar Skog <tor-einar.skog@nibio.no> */ @Entity @Table(name = "country") @XmlRootElement @NamedQueries({ - @NamedQuery(name = "Country.findAll", query = "SELECT c FROM Country c"), + @NamedQuery(name = "Country.findAll", query = "SELECT c FROM Country c ORDER BY c.countryCode ASC"), @NamedQuery(name = "Country.findByCountryCode", query = "SELECT c FROM Country c WHERE c.countryCode = :countryCode"), @NamedQuery(name = "Country.findByCountryCodes", query = "SELECT c FROM Country c WHERE c.countryCode IN(:countryCodes)") }) @@ -133,7 +133,8 @@ public class Country implements Serializable { public String getCountryName(String language) { Locale locale = new Locale(language, this.countryCode); - return locale.getDisplayCountry(); + Locale langLocale = new Locale(language); + return locale.getDisplayCountry(langLocale); } /** diff --git a/src/main/java/no/nibio/vips/logic/entity/VipsLogicUser.java b/src/main/java/no/nibio/vips/logic/entity/VipsLogicUser.java index 7e3ae38d69022b9888117b12d0d6398215452e5c..ef85a50284ddb9e446ad1ce5441f2470155deb37 100755 --- a/src/main/java/no/nibio/vips/logic/entity/VipsLogicUser.java +++ b/src/main/java/no/nibio/vips/logic/entity/VipsLogicUser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 NIBIO <http://www.nibio.no/>. + * Copyright (c) 2015-2019 NIBIO <http://www.nibio.no/>. * * This file is part of VIPSLogic. * VIPSLogic is free software: you can redistribute it and/or modify @@ -42,11 +42,10 @@ import javax.validation.constraints.Size; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; import com.fasterxml.jackson.annotation.JsonIgnore; -import java.util.Locale; import java.util.UUID; /** - * @copyright 2015 <a href="http://www.nibio.no/">NIBIO</a> + * @copyright 2019 <a href="http://www.nibio.no/">NIBIO</a> * @author Tor-Einar Skog <tor-einar.skog@nibio.no> */ @Entity @@ -64,7 +63,7 @@ import java.util.UUID; @NamedQuery(name = "VipsLogicUser.findByLastName", query = "SELECT v FROM VipsLogicUser v WHERE v.lastName = :lastName"), @NamedQuery(name = "VipsLogicUser.findByCompletePhoneNumber", query = "SELECT v FROM VipsLogicUser v WHERE v.phoneCountryCode || v.phone = :completePhoneNumber") }) -public class VipsLogicUser implements Serializable { +public class VipsLogicUser implements Serializable, Comparable{ private static final long serialVersionUID = 1L; private Integer userId; @@ -509,4 +508,12 @@ public class VipsLogicUser implements Serializable { public void setFreeSms(boolean freeSms) { this.freeSms = freeSms; } + + @Override + public int compareTo(Object o) { + VipsLogicUser other = (VipsLogicUser)o; + return (this.getLastName() + ", " + this.getFirstName()).compareTo(other.getLastName() + ", " + other.getFirstName()); + } + + } diff --git a/src/main/java/no/nibio/vips/logic/util/GISEntityUtil.java b/src/main/java/no/nibio/vips/logic/util/GISEntityUtil.java index 2b0d3b27b195d26fe55f17462f7928e81da68f24..0000b69afdff9fb6ed58ff5f324e9329dd604f43 100755 --- a/src/main/java/no/nibio/vips/logic/util/GISEntityUtil.java +++ b/src/main/java/no/nibio/vips/logic/util/GISEntityUtil.java @@ -19,11 +19,6 @@ package no.nibio.vips.logic.util; -import com.vividsolutions.jts.geom.Coordinate; -import com.vividsolutions.jts.geom.Geometry; -import com.vividsolutions.jts.geom.GeometryFactory; -import com.vividsolutions.jts.geom.Point; -import com.vividsolutions.jts.geom.PrecisionModel; import java.util.ArrayList; import java.util.HashMap; import java.util.List; diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties index 53c3b33031c03b7ca1efed1bbfc2182cc250a971..c39e20255222ce706470b3d2537077fecb568572 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties @@ -464,3 +464,17 @@ previousCrop=Previous crop tillageMethod=Tillage method cropSusceptibility=Crop susceptibility organizationsArchiveUser=The organization's standard archive user +organizations=Organizations +editOrganization=Edit organization +newOrganization=New organization +address=Address +postalCode=Postal code +defaultLocale=Default language +city=City +defaultTimeZone=Default time zone +vipswebUrl=VIPSWeb URL +defaultVipsCoreUserId=Default VIPSCore user ID +archiveUserId=Archive user +defaultMapZoom=Default map zoom +defaultMapCenter=Default map center +organizationStored=Organization was stored diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties index 4c3ef394a1a4730e31afbe80acac14f94361c89b..e0460a5c646641302ac139d8141df9d8264de1f4 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties @@ -464,3 +464,17 @@ previousCrop=Previous crop tillageMethod=Tillage method cropSusceptibility=Crop susceptibility organizationsArchiveUser=The organization's standard archive user +organizations=Organizations +editOrganization=Edit organization +newOrganization=New organization +address=Address +postalCode=Postal code +defaultLocale=Default language +city=City +defaultTimeZone=Default time zone +vipswebUrl=VIPSWeb URL +defaultVipsCoreUserId=Default VIPSCore user ID +archiveUserId=Archive user +defaultMapZoom=Default map zoom +defaultMapCenter=Default map center +organizationStored=Organization was stored diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties index 440c0415d87b01877ccc01c056ab70cba9573933..f7e92b32aca946f125b0ce80918cd8a894312c8b 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties @@ -463,3 +463,17 @@ previousCrop=Previous crop tillageMethod=Tillage method cropSusceptibility=Crop susceptibility organizationsArchiveUser=The organization's standard archive user +organizations=Organizations +editOrganization=Edit organization +newOrganization=New organization +address=Address +postalCode=Postal code +defaultLocale=Default language +city=City +defaultTimeZone=Default time zone +vipswebUrl=VIPSWeb URL +defaultVipsCoreUserId=Default VIPSCore user ID +archiveUserId=Archive user +defaultMapZoom=Default map zoom +defaultMapCenter=Default map center +organizationStored=Organization was stored diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties index d1b1548ecd2f2c8383725983c224a54b517bf2fa..298e9cd000ee7984350dd1122f7ade8b662a31f0 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties @@ -464,3 +464,17 @@ previousCrop=Forrige kulturvekst tillageMethod=Pl\u00f8yemetode cropSusceptibility=Kulturvekstens sykdomsmottakelighet organizationsArchiveUser=Organisasjonens standard arkivbrukerkonto +organizations=Organisasjoner +editOrganization=Rediger organisasjon +newOrganization=Ny organisasjon +address=Adresse +postalCode=Postnummer +defaultLocale=Standardspr\u00e5k +city=By +defaultTimeZone=Standard tidssone +vipswebUrl=VIPSWeb URL +defaultVipsCoreUserId=Standard brukerID i VIPSCore +archiveUserId=Arkivbruker +defaultMapZoom=Standard zoomniv\u00e5 p\u00e5 kart +defaultMapCenter=Standard kartsentrum +organizationStored=Organisasjonen ble lagret diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties index d0d19cc16b25f850dbfbd08fcd29acb177e625ae..910852b29a4b4d136837c3b09689a1952ed354c9 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties @@ -464,3 +464,17 @@ previousCrop=Previous crop tillageMethod=Tillage method cropSusceptibility=Crop susceptibility organizationsArchiveUser=The organization's standard archive user +organizations=Organizations +editOrganization=Edit organization +newOrganization=New organization +address=Address +postalCode=Postal code +defaultLocale=Default language +city=City +defaultTimeZone=Default time zone +vipswebUrl=VIPSWeb URL +defaultVipsCoreUserId=Default VIPSCore user ID +archiveUserId=Archive user +defaultMapZoom=Default map zoom +defaultMapCenter=Default map center +organizationStored=Organization was stored diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_zh_CN.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_zh_CN.properties index 8d0b2432cd17f59fcefc088d0b145751f2c48897..bb7cb6054e91a132ef91d5e4f0c3f4e0cbbba986 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_zh_CN.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_zh_CN.properties @@ -461,3 +461,17 @@ previousCrop=Previous crop tillageMethod=Tillage method cropSusceptibility=Crop susceptibility organizationsArchiveUser=The organization's standard archive user +organizations=Organizations +editOrganization=Edit organization +newOrganization=New organization +address=Address +postalCode=Postal code +defaultLocale=Default language +city=City +defaultTimeZone=Default time zone +vipswebUrl=VIPSWeb URL +defaultVipsCoreUserId=Default VIPSCore user ID +archiveUserId=Archive user +defaultMapZoom=Default map zoom +defaultMapCenter=Default map center +organizationStored=Organization was stored diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index dff81c3e22c4d0c8dcb561b45e9d68fd4dcf373a..9bd85db2c3822cdeb262ba5a2ff5828c2ecbe903 100755 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -83,6 +83,10 @@ <servlet-name>JSEnvironment</servlet-name> <servlet-class>no.nibio.vips.logic.web.js.JSEnvironment</servlet-class> </servlet> + <servlet> + <servlet-name>OrganizationController</servlet-name> + <servlet-class>no.nibio.vips.logic.controller.servlet.OrganizationController</servlet-class> + </servlet> <servlet-mapping> <servlet-name>PointOfInterestController</servlet-name> <url-pattern>/poi/*</url-pattern> @@ -153,6 +157,10 @@ <servlet-name>JSEnvironment</servlet-name> <url-pattern>/js/environment.js</url-pattern> </servlet-mapping> + <servlet-mapping> + <servlet-name>OrganizationController</servlet-name> + <url-pattern>/organization</url-pattern> + </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> @@ -189,7 +197,7 @@ <filter-name>AuthenticationFilter</filter-name> <filter-class>no.nibio.vips.logic.authenticate.AuthenticationFilter</filter-class> </filter> - <filter> + <filter> <description>Sets config values for FreeMarker</description> <filter-name>TemplateConfigFilter</filter-name> <filter-class>no.nibio.vips.logic.web.TemplateConfigFilter</filter-class> @@ -299,4 +307,4 @@ <error-code>404</error-code> <location>/error/404</location> </error-page> -</web-app> \ No newline at end of file +</web-app> diff --git a/src/main/webapp/formdefinitions/organizationForm.json b/src/main/webapp/formdefinitions/organizationForm.json new file mode 100644 index 0000000000000000000000000000000000000000..cf1de2562347f7e057554f8b8bbd7d0e6fd4a35e --- /dev/null +++ b/src/main/webapp/formdefinitions/organizationForm.json @@ -0,0 +1,100 @@ +{ + "_licenseNote": [ + "Copyright (c) 2019 NIBIO <http://www.nibio.no/>. ", + "", + "This file is part of VIPSLogic. ", + "VIPSLogic is free software: you can redistribute it and/or modify ", + "it under the terms of the NIBIO Open Source License as published by ", + "NIBIO, either version 1 of the License, or (at your option) any ", + "later version. ", + "", + "VIPSLogic 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 ", + "NIBIO Open Source License for more details. ", + "", + "You should have received a copy of the NIBIO Open Source License ", + "along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>. " + ], + "_comment" : "Structure of the organizationForm and how to validate it", + "fields": [ + { + "name" : "organizationId", + "dataType" : "INTEGER", + "required" : true + }, + { + "name" : "organizationName", + "dataType" : "STRING", + "required" : true + }, + { + "name" : "address1", + "dataType" : "STRING", + "required" : false + }, + { + "name" : "address2", + "dataType" : "STRING", + "required" : false + }, + { + "name" : "postalCode", + "dataType" : "STRING", + "required" : false + }, + { + "name" : "city", + "dataType" : "STRING", + "required" : false + }, + { + "name" : "vipswebUrl", + "dataType" : "STRING", + "required" : false + }, + { + "name" : "countryCode", + "dataType" : "STRING", + "fieldType" : "SELECT_SINGLE", + "required" : true, + "nullValue" : "" + }, + { + "name" : "defaultLocale", + "dataType" : "STRING", + "fieldType" : "SELECT_SINGLE", + "required" : true, + "nullValue" : "" + }, + { + "name" : "defaultTimeZone", + "dataType" : "STRING", + "fieldType" : "SELECT_SINGLE", + "required" : true, + "nullValue" : "" + }, + { + "name" : "archiveUserId", + "dataType" : "INTEGER", + "fieldType" : "SELECT_SINGLE", + "required" : false, + "nullValue" : -1 + },{ + "name" : "defaultVipsCoreUserId", + "dataType" : "INTEGER", + "required" : false + }, + { + "name" : "defaultMapZoom", + "dataType" : "INTEGER", + "required" : false + }, + { + "name" : "defaultMapCenter", + "dataType" : "STRING", + "required" : false + } + + ] +} diff --git a/src/main/webapp/templates/master.ftl b/src/main/webapp/templates/master.ftl index 933e4144967e526bbc10a43b876128165242b086..0f2b3f9b50f55ace97c7f2147b76067ea0ac94ea 100755 --- a/src/main/webapp/templates/master.ftl +++ b/src/main/webapp/templates/master.ftl @@ -48,6 +48,9 @@ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Admin<b class="caret"></b></a> <ul class="dropdown-menu"> <#if user.isOrganizationAdmin() || user.isSuperUser() > + <#if user.isSuperUser() > + <li><a href="/organization">${i18nBundle.organizations}</a></li> + </#if> <li><a href="/user">${i18nBundle.users}</a></li> <li><a href="/organizationgroup">${i18nBundle.organizationGroupList}</a></li> <li><a href="/scheduling">${i18nBundle.scheduling}</a></li> diff --git a/src/main/webapp/templates/organizationForm.ftl b/src/main/webapp/templates/organizationForm.ftl new file mode 100644 index 0000000000000000000000000000000000000000..78fa94ded9ba695ffc662de0b22d216c0f059054 --- /dev/null +++ b/src/main/webapp/templates/organizationForm.ftl @@ -0,0 +1,158 @@ +<#-- + Copyright (c) 2016 NIBIO <http://www.nibio.no/>. + + This file is part of VIPSLogic. + VIPSLogic is free software: you can redistribute it and/or modify + it under the terms of the NIBIO Open Source License as published by + NIBIO, either version 1 of the License, or (at your option) any + later version. + + VIPSLogic 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 + NIBIO Open Source License for more details. + + You should have received a copy of the NIBIO Open Source License + along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>. +--><#include "master.ftl"> +<#macro page_head> + <title><#if organization.organizationId?has_content>${i18nBundle.editOrganization} ${organization.organizationName}<#else>${i18nBundle.newOrganization}</#if></title> +</#macro> +<#macro custom_css> + <link rel="stylesheet" type="text/css" href="/css/3rdparty/ol.css"/ > +</#macro> +<#macro custom_js> + <script type="text/javascript" src="/js/constants.js"></script> + <script type="text/javascript" src="/js/resourcebundle.js"></script> + <script type="text/javascript" src="/js/validateForm.js"></script> + <script type="text/javascript"> + $(document).ready(function() { + // Load main form definition (for validation) + loadFormDefinition("organizationForm"); + + }); + + + </script> +</#macro> +<#macro page_contents> +<div class="singleBlockContainer"> + <#if user.isSuperUser() > + <p><a href="/organization" class="btn btn-default back" role="button">${i18nBundle.back}</a></p> + </#if> + <h1><#if organization.organizationId?has_content>${i18nBundle.editOrganization} ${organization.organizationName}<#else>${i18nBundle.newOrganization}</#if></h1> + <div id="errorMsgEl" class="alert alert-danger" <#if !formValidation?has_content> style="display:none;"</#if>> + <#if formValidation?has_content>${formValidation.validationMessages?replace("\n", "<br>")}</#if> + </div> + <#if messageKey?has_content> + <div class="alert alert-success">${i18nBundle(messageKey)}</div> + </#if> + <div class="row"> + <div class="col-md-12"> + <#assign formId = "organizationForm"> + <form id="${formId}" role="form" action="/organization?action=organizationFormSubmit" method="POST" onsubmit="return validateForm(this);"> + + <input type="hidden" name="organizationId" value="${organization.organizationId!"-1"}"/> + <div class="form-group"> + <label for="organizationName">${i18nBundle.name}</label> + <input type="text" class="form-control" name="organizationName" placeholder="${i18nBundle.name}" value="${(organization.organizationName)!""}" onblur="validateField(this); "/> + <span class="help-block" id="${formId}_organizationName_validation"></span> + </div> + <div class="form-group"> + <label for="address1">${i18nBundle.address} 1</label> + <input type="text" class="form-control" name="address1" placeholder="${i18nBundle.address} 1" value="${(organization.address1)!""}" onblur="validateField(this); "/> + <span class="help-block" id="${formId}_address1_validation"></span> + </div> + <div class="form-group"> + <label for="address2">${i18nBundle.address} 2</label> + <input type="text" class="form-control" name="address2" placeholder="${i18nBundle.address} 2" value="${(organization.address2)!""}" onblur="validateField(this); "/> + <span class="help-block" id="${formId}_address2_validation"></span> + </div> + <div class="form-group"> + <label for="postalCode">${i18nBundle.postalCode}</label> + <input type="text" class="form-control" name="postalCode" placeholder="${i18nBundle.postalCode}" value="${(organization.postalCode)!""}" onblur="validateField(this); "/> + <span class="help-block" id="${formId}_postalCode_validation"></span> + </div> + <div class="form-group"> + <label for="city">${i18nBundle.city}</label> + <input type="text" class="form-control" name="city" placeholder="${i18nBundle.city}" value="${(organization.city)!""}" onblur="validateField(this); "/> + <span class="help-block" id="${formId}_city_validation"></span> + </div> + <div class="form-group"> + <label for="countryCode">${i18nBundle.country}</label> + <select class="form-control" name="countryCode" onblur="validateField(this);"> + <option value="">${i18nBundle.pleaseSelect} ${i18nBundle.country?lower_case} + <#list countries as country> + <option value="${country.countryCode}" + <#if organization.countryCode?has_content && organization.countryCode.countryCode == country.countryCode>selected="selected"</#if> + >${country.getCountryName(currentLocale.language)}</option> + </#list> + </select> + <span class="help-block" id="${formId}_countryCode_validation"></span> + </div> + <div class="form-group"> + <label for="defaultLocale">${i18nBundle.defaultLocale}</label> + <select class="form-control" name="defaultLocale" onblur="validateField(this);"> + <option value="">${i18nBundle.pleaseSelect} ${i18nBundle.defaultLocale?lower_case} + <#list currentLocale.getAvailableLocales() as locale> + <option value="${locale.language}" + <#if organization.defaultLocale?has_content && organization.defaultLocale == locale.language && organization.countryCode.countryCode == locale.country>selected="selected"</#if> + >${locale.getDisplayLanguage(currentLocale)} / ${locale.getDisplayCountry(currentLocale)}</option> + </#list> + </select> + <span class="help-block" id="${formId}_defaultLocale_validation"></span> + </div> + <div class="form-group"> + <label for="defaultTimeZone">${i18nBundle.defaultTimeZone}</label> + <select class="form-control" name="defaultTimeZone" onblur="validateField(this);"> + <option value="">${i18nBundle.pleaseSelect} ${i18nBundle.defaultTimeZone?lower_case} + <#list timeZones as timeZone> + <option value="${timeZone}" + <#if organization.defaultTimeZone?has_content && organization.defaultTimeZone == timeZone>selected="selected"</#if> + >${timeZone}</option> + </#list> + </select> + <span class="help-block" id="${formId}_defaultTimeZone_validation"></span> + </div> + <div class="form-group"> + <label for="vipswebUrl">${i18nBundle.vipswebUrl}</label> + <input type="text" class="form-control" name="vipswebUrl" placeholder="${i18nBundle.vipswebUrl}" value="${(organization.vipswebUrl)!""}" onblur="validateField(this); "/> + <span class="help-block" id="${formId}_vipswebUrl_validation"></span> + </div> + <div class="form-group"> + <label for="archiveUserId">${i18nBundle.archiveUserId}</label> + <select class="form-control" name="archiveUserId" onblur="validateField(this);"> + <option value="-1">${i18nBundle.pleaseSelect} ${i18nBundle.archiveUserId?lower_case} + <#list organizationUsers as oUser> + <option value="${oUser.userId}" + <#if organization.archiveUser?has_content && organization.archiveUser.userId == oUser.userId>selected="selected"</#if> + >${oUser.lastName}, ${oUser.firstName}</option> + </#list> + </select> + <span class="help-block" id="${formId}_archiveUserId_validation"></span> + </div> + <div class="form-group"> + <label for="defaultVipsCoreUserId">${i18nBundle.defaultVipsCoreUserId}</label> + <input type="number" class="form-control" name="defaultVipsCoreUserId" placeholder="${i18nBundle.defaultVipsCoreUserId}" value="${(organization.defaultVipsCoreUserId)!""}" onblur="validateField(this); "/> + <span class="help-block" id="${formId}_defaultVipsCoreUserId_validation"></span> + </div> + <div class="form-group"> + <label for="defaultMapZoom">${i18nBundle.defaultMapZoom}</label> + <input type="number" class="form-control" name="defaultMapZoom" placeholder="${i18nBundle.defaultMapZoom}" value="${(organization.defaultMapZoom)!""}" onblur="validateField(this); "/> + <span class="help-block" id="${formId}_defaultMapZoom_validation"></span> + </div> + <div class="form-group"> + <label for="defaultMapCenter">${i18nBundle.defaultMapCenter} (WGS84 longitude,latitude)</label> + <input type="text" class="form-control" name="defaultMapCenter" placeholder="${i18nBundle.defaultMapCenter}" value="${(defaultMapCenterLon?c)!""},${(defaultMapCenterLat?c)!""}" onblur="validateField(this); "/> + <span class="help-block" id="${formId}_defaultMapCenter_validation"></span> + </div> + <button type="submit" class="btn btn-default">${i18nBundle.submit}</button> + <#if organization.organizationId?has_content> + <button type="button" class="btn btn-danger" onclick="if(confirm('${i18nBundle.confirmDelete}')){alert('Sorry, but this functionality has not yet been implemented');}">${i18nBundle.delete}</button> + </#if> + </form> + </div> + </div> +</div> +</#macro> +<@page_html/> diff --git a/src/main/webapp/templates/organizationList.ftl b/src/main/webapp/templates/organizationList.ftl new file mode 100644 index 0000000000000000000000000000000000000000..917b85a675008e22e8fd5475c52e2ce4fe59bf09 --- /dev/null +++ b/src/main/webapp/templates/organizationList.ftl @@ -0,0 +1,39 @@ +<#-- + Copyright (c) 2019 NIBIO <http://www.nibio.no/>. + + This file is part of VIPSLogic. + VIPSLogic is free software: you can redistribute it and/or modify + it under the terms of the NIBIO Open Source License as published by + NIBIO, either version 1 of the License, or (at your option) any + later version. + + VIPSLogic 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 + NIBIO Open Source License for more details. + + You should have received a copy of the NIBIO Open Source License + along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>. +--><#include "master.ftl"> +<#macro page_head> + <title>${i18nBundle.organizations}</title> +</#macro> +<#macro custom_css> +</#macro> +<#macro custom_js> +</#macro> +<#macro page_contents> +<div class="singleBlockContainer"> +<h1>${i18nBundle.organizations}</h1> +<#if messageKey?has_content> + <div class="alert alert-success">${i18nBundle(messageKey)}</div> +</#if> +<ul> +<#list organizations as organization> +<li><a href="/organization?action=editOrganization&organizationId=${organization.organizationId}">${organization.organizationName}</a></li> +</#list> +</ul> +<p><a href="/organization?action=newOrganization" class="btn btn-default back" role="button">${i18nBundle.newOrganization}</a></p> +</div> +</#macro> +<@page_html/>