diff --git a/pom.xml b/pom.xml index 3796e2feb12a70dff5686e464c23702286ba374d..8a88d2705fa3bdea596ae6d7457588ad411ae4c6 100644 --- a/pom.xml +++ b/pom.xml @@ -82,7 +82,7 @@ <dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> - <version>0.9.9-RC1</version> + <version>0.9.9</version> <type>jar</type> </dependency> <dependency> diff --git a/src/main/java/no/nibio/vips/logic/VIPSLogicApplication.java b/src/main/java/no/nibio/vips/logic/VIPSLogicApplication.java index add6f3ca1a78108657c6c94ce1391f987293633e..24176ef0d6f804807c66f19479c850c63146c883 100644 --- a/src/main/java/no/nibio/vips/logic/VIPSLogicApplication.java +++ b/src/main/java/no/nibio/vips/logic/VIPSLogicApplication.java @@ -25,7 +25,7 @@ import javax.ws.rs.core.Application; /** * Responsible for adding REST resources - * @copyright 2015 {@link http://www.nibio.no NIBIO} + * @copyright 2016 {@link http://www.nibio.no NIBIO} * @author Tor-Einar Skog <tor-einar.skog@nibio.no> */ @ApplicationPath("/rest/") diff --git a/src/main/java/no/nibio/vips/logic/controller/servlet/CropCategoryController.java b/src/main/java/no/nibio/vips/logic/controller/servlet/CropCategoryController.java new file mode 100644 index 0000000000000000000000000000000000000000..89fbeb060c842437cc9323e073966053c7c4c9cc --- /dev/null +++ b/src/main/java/no/nibio/vips/logic/controller/servlet/CropCategoryController.java @@ -0,0 +1,150 @@ +/* + * 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/>. + * + */ + +package no.nibio.vips.logic.controller.servlet; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import no.nibio.vips.logic.entity.CropCategory; +import no.nibio.vips.logic.entity.Organism; +import no.nibio.vips.logic.entity.Organization; +import no.nibio.vips.logic.entity.VipsLogicUser; +import no.nibio.vips.logic.util.SessionControllerGetter; +import no.nibio.vips.util.ServletUtil; +import no.nibio.web.forms.FormUtil; +import no.nibio.web.forms.FormValidation; +import no.nibio.web.forms.FormValidationException; +import no.nibio.web.forms.FormValidator; + +/** + * @copyright 2016 <a href="http://www.bioforsk.no/">Bioforsk</a> + * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no> + */ +public class CropCategoryController 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"); + String action = request.getParameter("action"); + VipsLogicUser user = (VipsLogicUser) request.getSession().getAttribute("user"); + // Default: View crop category list + // for everyone + if(action == null) + { + Organization currentOrganization = user.isSuperUser() && request.getParameter("organizationId") != null ? + SessionControllerGetter.getUserBean().getOrganization(Integer.valueOf(request.getParameter("organizationId"))) + : user.getOrganizationId(); + if(user.isSuperUser()) + { + List<Organization> allOrganizations = SessionControllerGetter.getUserBean().getTopLevelOrganizations(); + request.setAttribute("allOrganizations", allOrganizations); + } + + List<CropCategory> cropCategories = SessionControllerGetter.getOrganismBean().getCropCategories(currentOrganization.getOrganizationId()); + + request.setAttribute("organization", currentOrganization); + request.setAttribute("cropCategories", cropCategories); + List<Organism> cropList = SessionControllerGetter.getOrganismBean().getAllCrops(); + Map<String, Organism> allCrops = new HashMap<>(); + for(Organism crop:cropList) + { + allCrops.put(String.valueOf(crop.getOrganismId()), crop); + } + request.setAttribute("allCrops", allCrops); + request.getRequestDispatcher("/cropCategoryList.ftl").forward(request, response); + } + else if(action.equals("submit")) + { + try + { + + FormValidation formValidation = FormValidator.validateForm("cropCategoryCropForm",request,getServletContext()); + if(formValidation.isValid()) + { + Integer cropCategoryId = formValidation.getFormField("cropCategoryId").getValueAsInteger(); + List<Integer> cropCategoryCropOrganismIds = FormUtil.getIdsFromMultipleSelect(formValidation.getFormField("cropCategoryCropOrganismIds").getWebValues()); + CropCategory cropCategory = SessionControllerGetter.getOrganismBean().getCropCategory(cropCategoryId); + cropCategory.setCropOrganismIds(cropCategoryCropOrganismIds.toArray(new Integer[cropCategoryCropOrganismIds.size()])); + SessionControllerGetter.getOrganismBean().storeCropCategory(cropCategory); + + response.sendRedirect(new StringBuilder("http://").append(ServletUtil.getServerName(request)).append("/organism/cropcategory?messageKey=cropCategoryUpdated").toString()); + } + else + { + System.out.println("Form didn't validate"); + } + } + catch(NullPointerException | NumberFormatException | FormValidationException ex) + { + ex.printStackTrace(); + } + } + } + + // <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/OrganismBean.java b/src/main/java/no/nibio/vips/logic/controller/session/OrganismBean.java index beafe6aaba2ef56402649275dd16d80b7d0bc73a..c9a710f2ad3c8e76c4e8af545d2b9be0a7a43617 100644 --- a/src/main/java/no/nibio/vips/logic/controller/session/OrganismBean.java +++ b/src/main/java/no/nibio/vips/logic/controller/session/OrganismBean.java @@ -259,6 +259,17 @@ public class OrganismBean { { return em.createNamedQuery("Organism.findAllCrops").getResultList(); } + + public Map<Integer, Organism> getAllCropsMapped() + { + List<Organism> cropList = this.getAllCrops(); + Map<Integer, Organism> cropMap = new HashMap<>(); + for(Organism crop:cropList) + { + cropMap.put(crop.getOrganismId(), crop); + } + return cropMap; + } public CropPest getCropPest(Integer cropOrganismId) { try @@ -391,4 +402,12 @@ public class OrganismBean { } } } + + public CropCategory getCropCategory(Integer cropCategoryId) { + return em.find(CropCategory.class, cropCategoryId); + } + + public void storeCropCategory(CropCategory cropCategory) { + em.merge(cropCategory); + } } diff --git a/src/main/java/no/nibio/vips/logic/service/LogicService.java b/src/main/java/no/nibio/vips/logic/service/LogicService.java index b2fde2b2953f4ad7ce9f64dbbcc76ace43d2f040..2f83d85cd3d9bb59f27b26a7fc09df026bb8237e 100644 --- a/src/main/java/no/nibio/vips/logic/service/LogicService.java +++ b/src/main/java/no/nibio/vips/logic/service/LogicService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 NIBIO <http://www.nibio.no/>. + * 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 @@ -77,7 +77,7 @@ import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; import org.jboss.resteasy.spi.HttpRequest; /** - * @copyright 2013-2015 <a href="http://www.nibio.no/">NIBIO</a> + * @copyright 2013-2016 <a href="http://www.nibio.no/">NIBIO</a> * @author Tor-Einar Skog <tor-einar.skog@nibio.no> */ @Path("rest") diff --git a/src/main/resources/no/nibio/vips/logic/i18n/passay_zh_CN.properties b/src/main/resources/no/nibio/vips/logic/i18n/passay_zh_CN.properties new file mode 100644 index 0000000000000000000000000000000000000000..5d364fe65d744c84c4282e91f515509334eb7ad6 --- /dev/null +++ b/src/main/resources/no/nibio/vips/logic/i18n/passay_zh_CN.properties @@ -0,0 +1,42 @@ +# + # 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/>. + # + +# This (and and corresponding localized) property file(s) +# Localizes the error messages given from the passay properties files +# @see UserBean.isPasswordValid() and http://www.passay.org/reference/ +# for usage +HISTORY_VIOLATION=Password matches one of %1$s previous passwords. +ILLEGAL_WORD=Password contains the dictionary word '%1$s'. +ILLEGAL_WORD_REVERSED=Password contains the reversed dictionary word '%1$s'. +ILLEGAL_MATCH=Password matches the illegal pattern '%1$s'. +ALLOWED_MATCH=Password must match pattern '%1$s'. +ILLEGAL_CHAR=Password contains the illegal character '%1$s'. +ALLOWED_CHAR=Password contains the illegal character '%1$s'. +ILLEGAL_SEQUENCE=Password contains the illegal sequence '%1$s'. +ILLEGAL_USERNAME=Password contains the user id '%1$s'. +ILLEGAL_USERNAME_REVERSED=Password contains the user id '%1$s' in reverse. +ILLEGAL_WHITESPACE=Password cannot contain whitespace characters. +INSUFFICIENT_UPPERCASE=Password must contain at least %1$s uppercase characters. +INSUFFICIENT_LOWERCASE=Password must contain at least %1$s lowercase characters. +INSUFFICIENT_ALPHABETICAL=Password must contain at least %1$s alphabetical characters. +INSUFFICIENT_DIGIT=Password must contain at least %1$s digit characters. +INSUFFICIENT_SPECIAL=Password must contain at least %1$s special characters. +INSUFFICIENT_CHARACTERISTICS=Password matches %1$s of %3$s character rules, but %2$s are required. +SOURCE_VIOLATION=Password cannot be the same as your %1$s password. +TOO_LONG=Password must be no more than %2$s characters in length. +TOO_SHORT=Password must be at least %1$s characters in length. \ No newline at end of file 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 907fde2e5c42431f02162fa24e627f4f6d756576..319c9a0dc9d04bbeea90775c762a3aedb86d67d5 100644 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties @@ -426,3 +426,5 @@ digit=Digit lowercase=Lower case uppercase=Upper case allSystems=All systems +cropCategoriesFor=Crop categories for +cropCategoryUpdated=Crop category was updated 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 7c870bff5cced8a7bc2cab2238eee81957488622..d88dd091035e7a6408cb505eaf8b773eaaad9d3a 100644 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties @@ -426,3 +426,5 @@ digit=Digit lowercase=Lower case uppercase=Upper case allSystems=All systems +cropCategoriesFor=Crop categories for +cropCategoryUpdated=Crop category was updated 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 977d9be4079296df4e6ed15d6ab56b78414cf570..bcdf18e97b76948fdc4ab87608f445e6b5ae3baa 100644 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties @@ -425,3 +425,5 @@ digit=Digit lowercase=Lower case uppercase=Upper case allSystems=All systems +cropCategoriesFor=Crop categories for +cropCategoryUpdated=Crop category was updated 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 bf97bb55b7a44a2930f44df5f84408e5f4e8b3dc..305abc4f611bbb1190e449b59084aecff27d1994 100644 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties @@ -426,3 +426,5 @@ digit=Tall lowercase=Liten bokstav uppercase=STOR bokstav allSystems=Alle system +cropCategoriesFor=Kulturkategorier for +cropCategoryUpdated=Kulturkategorien ble oppdatert 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 20f75283c06e5ccfa6d050e6f7fffa1f1e1d5856..dacbfef7cc8e04b6ae2ba30282ef7979af8d2093 100644 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties @@ -426,3 +426,5 @@ digit=Digit lowercase=Lower case uppercase=Upper case allSystems=All systems +cropCategoriesFor=Crop categories for +cropCategoryUpdated=Crop category was updated 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 new file mode 100644 index 0000000000000000000000000000000000000000..319c9a0dc9d04bbeea90775c762a3aedb86d67d5 --- /dev/null +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_zh_CN.properties @@ -0,0 +1,430 @@ +# + # Copyright (c) 2014 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/>. + # +invalidcredentials=Invalid username and/or password +greeting=Welcome to +logoutsuccess=You are now logged out. Welcome back! +pleaselogin=Please log in +login=Log in +username=User name +password=Password +loggedinas=Logged in as +logout=Log out +weatherStations=Weather stations +position=Position +dataSource=Data source +name=Name +dataSourceMissing=Data source is missing +weatherStationRemoteIdMissing=Remote Id for weather station is missing +weatherStationRemoteId=Remote Id for weather station +latitude=Latitude +longitude=Longitude +missing=Missing +altitude=Altitude +test=Test +logInterval1h=1 hour +logInterval1d=1 day +elementMeasurementTypes=Measurement types +logInterval=Log interval +startTime=Start time +endTime=End time +timeZone=Time zone +viewFullScreen=Full screen view +edit=Edit +remoteloginfailed=Remote login failed +your=Your +or=Or +signInWith=Sign in with +registerNewUser=Register new user +registerNewUserExplanation=Please fill out the form to apply for a user account. +password2=Repeat password +email=Email +firstName=First name +lastName=Last name +approvalApplication=Role description +pleaseSelect=Please select +passwordsDoNotMatch=Passwords do not match +missingValues=Missing values +fieldIsRequired=Field is required +exceedsMaxLengthOf=Exceeds max length of {0} +invalidFormat=Invalid format +organizationId=VIPS system +numberRequired=A number is required +lowerThanMinimum=Lower than the minimum ({0}) +higherThanMaximum=Higher than the maximum ({0}) +xIsNotEqualToY={0} is not equal to {1} +warning_fieldNotFoundInFormDefinition=WARNING: field {0} not found in form definition. The system does not know how to validate it. Continue anyway? +emailAddressIsAlreadyInUse=Email address is already in use +registerNewUserReceipt=Thanks. You should receive an email requesting you to validate your email address. After following the instructions there, the organization admin will hopefully approve your application shortly. +users=Users +user=User +userStatus_1=Awaiting email validation +userStatus_2=Awaiting approval +userStatus_3=Rejected +userStatus_4=Approved +userStatus_5=Disabled +submit=Submit +remarks=Remarks +userStatusId=Approval status +vipsLogicRole_1=Superuser +vipsLogicRole_2=Organization administrator +vipsLogicRoles=User roles +userUpdated=User was updated +delete=Delete +confirmDelete=Do you really want to delete? +userDeleted=User was deleted +forecasts=Forecasts +dateStart=Date start +dateEnd=Date end +poi=Point of interest +viewForecastConfiguration=View forecast configuration +forecastConfigurationUpdated=Forecast configuration was updated +forecastConfigurationId=Forecast configuration +vipsLogicUserId=User +doesNotMatchDateFormat=Does not match format {0} +modelId=Forecasting model +APPLESCABM=Apple scab model +NAERSTADMO=N\u00e6rstad's model +locationPointOfInterestId=Location +weatherStationPointOfInterestId=Weather station +addNew=Add new +xIsNotAfterY={0} is not after {1} +calculationStart=Calculation start +calculationEnd=Calculation end +startDateAscosporeMaturity=Start date for ascospore maturation +specificFieldsForX=Specific fields for {0} +doesNotMatchFormatX=Does not match format {0} +forecastConfigurationDeleted=Forecast configuration was deleted +cancel=Cancel +confirmCancel=Do you really want to cancel? +leaveForm=Leave form +confirmLeaveForm=Do you really want to leave this form? All changes are left behind. +noDescriptionFound=No description found +task_RunAllForecastConfigurationsTask_name=Run all forecast configurations +tasks=Tasks +description=Description +task_RunAllForecastConfigurationsTask_description=Runs all current forecasts for all organizations +configureAndRunManually=Configure and run manually +scheduling=Scheduling +runTask=Run task +taskXWasLaunched=Task "{0}" was launched +factoryId=Factory id +schedulingOverview=Scheduling overview +runningTasks=Running tasks +scheduledTasks=Scheduled tasks +timestamp=Timestamp +progress=Progress +viewAllTasks=View all tasks +schedulingStopped=Scheduling was stopped +schedulingStarted=Scheduling started +stopScheduling=Stop scheduling +startScheduling=Start scheduling +schedulingStoppedExplanation=The scheduling system is stopped. None of the tasks in the list below will be run, unless scheduling is started again. +noTasksRunning=No tasks running +taskHistory=Task history +status=Status +taskHistoryDate=Date for task history +changeDate=Change date +taskHistoryStatusOK=OK +taskHistoryStatusFailedPartly=Failed partly +details=Details +taskHistoryDetails=Task history details +completenessAtFinish=Completeness at finish +back=Back +systemTime=System time +organisms=Organisms +up=Up +children=Children +latinName=Latin name +localName=Local name +tradeName=Trade name +userRegistrationEmailVerificationMessageBody=We have received a request to register a new user at VIPSLogic (http://{0}/). Please confirm your email by clicking this link: {1}\n\nThank you +userRegistrationEmailVerificationMessageSubject=Email verification needed +attachIdToExistingUser=Add this login to my existing user +confirmEmailReceipt=Your email was successfully confirmed. You will be notified as soon as the organization administrator approves your application. +confirmEmailFailure=Your email address was not confirmed. Please contact the system administrator. +attachIdToExistingUserReceipt=The id was successfully connected to the user. You may now log in with it +externalResources=External resources +externalResourceIdentifier=External resource identifier +organismId=Organism id +parentOrganismId=Parent organism +newOrganism=New organism +hierarchyCategoryId=Hierarchy category +organismUpdated=Organism was updated +organismRegistered=Organism was registered +organismDeleted=Organism was deleted +organismNotDeleted=Organism was not deleted +messages=Messages +editMessage=Edit message +newMessage=New message +language=Language +heading=Heading +leadParagraph=Lead paragraph +body=Body +datePub=Date published +dateValidTo=Valid to date +messageUpdated=Message was updated +newIllustration=New illustration +illustration=Illustration +browse=Browse +replaceIllustration=Replace illustration +deleteIllustration=Delete illustration +messageIllustrationCaptionLocale=Caption +messageTags=Message tags +confirmReloadForm=Do you really want to reload this form. All unsaved changes will be lost. +observationMethodTitle_NOT_REGISTERED=Not registered +observationMethodDescription_NOT_REGISTERED=The observation method is not registered +observationMethodTitle_KNOCKING=Knocking +observationMethodDescription_KNOCKING=Knocking description (TODO) +observationMethodTitle_HARVESTING=Harvesting +observationMethodTitle_COUNTING=Counting +observationMethodTitle_VISUAL=Visual +observations=Observations +newObservation=New observation +observedValue=Observed value +location=Location +denominator=Denominator +observationMethodId=Observation method +timeOfObservation=Time of observation +vipsLogicRole_3=Observer +missingSeparatorComma=Missing separator comma +tooManySeparatorCommas=Too many separator commas +observationStored=Observation was stored +editObservation=Edit observation +organism=Organism +observationDeleted=Observation was deleted +informAdminOfConfirmedEmailSubject=New user has confirmed email and is now ready for approval +informAdminOfConfirmedEmailBody=The user''s last name is {0}. The approval information is as follows: {1}. \\nFollow this link to edit this user: {2} \\n Follow this link to approve automatically: {3} +sendUserApprovalConfirmationSubject=Your user account has been approved +sendUserApprovalConfirmationBody=We are happy to confirm that your user account for VIPSLogic has been approved. Please log in here: {0} +dataSourceName=Data source name +newWeatherStation=New weather station +meter=Meter +country=Country +editWeatherStation=Edit weather station +toTheTop=To the top +newUser=New user +newUserCredentialsHelpText=Please enter a user name for the new user. An auto generated password will be sent to the user's email address. +usernameExists=Username {0} exists +sendUsernameAndPasswordToUserSubject=Username and password for VIPSLogic +sendUsernameAndPasswordToUserBody=Here is your username and password for logging in to VIPSLogic (http://{2}):\nUsername: {0}\nPassword: {1} +userCreatedAndInformed=User was created. An email with username and password was sent to the user's email +forgottenPassword=Forgotten password +resetPasswordRequest=Request to reset password +resetPasswordRequestFormExplanation=An email will be sent to the address you enter here, with a link to reset your current password and enter a new one. +resetPasswordRequestAccepted=Your request has been accepted. An email with further instructions have been sent to the registered email address. +emailNotRegistered=The email address is not registered +emailNotUnique=The email address is not unique. Please contact the VIPSLogic administrator to sort this out. +createPasswordResetCodeAndSendToUserSubject=Create new password in VIPSLogic +createPasswordResetCodeAndSendToUserBody=You have requested to reset your current password for username {0} in VIPSLogic, and create a new one. Please follow this link to proceed: {1} +missingUsernameAndPassword=Missing username and password +passwordResetCodeExpired=The password reset code has expired. +passwordResetCodeNotFound=The password reset code was not found +resetPassword =Reset and create new password +resetPasswordFormExplanation=Please enter your new password +passwordResetSuccess=Password was successfully created. Please log in. +task_UpdateModelInformationTask_name=Update model information +task_UpdateModelInformationTask_description=Fetches information about models from VIPSCoreManager and stores in VIPSLogic +filter=Filter +filterMessages=Filter messages +datePubPeriod=Period of publication +from=From +to=To +reset=Reset +messageDeleted=Message was deleted +taskHistoryStatusFailedCompletely=Failed completely +weatherStationStored=Weather station information was stored +cropOrganismId=Crop +task_UpdateForecastResultCacheTableTask_name=Update forecast result cache table +task_UpdateForecastResultCacheTableTask_description=To speed up certain tasks, for instance aggregating warnings for today, the table forecast_result_cache should contain only today's forecast results. Today = SystemTime. +task_UpdateForecastSummaryTableTask_name=Update table of forecast summaries +task_UpdateForecastSummaryTableTask_description=This task updates the table for summaries +pestOrganismId=Pest +weatherForecastProvider=Weather forecast service +none=None +allOrganizations=All organizations +isPest=Is pest +isCrop=Is crop +externalForecastProviders=External forecast providers +help=Help +active=Active +activeWeatherStations=Active weather stations +inactiveWeatherStations=Inactive weather stations +weatherStationDeleted=Weather station was deleted +deleteWeatherStation=Delete weather station +weatherStationForecastConfigurations=Forecasts connected to the weather station +deleteWeatherStationPreviewExplanation=The weather station that you want to delete has the resources below connected to it. When you delete the weather station, you also delete these resources. +deleteUser=Delete user +deleteUserDescription=You must transfer the user's resouces to another user before deleting is possible +userResources=User resources +transferResources=Transfer resources +select=Select +transferAndDelete=Transfer and delete +weatherStationPointOfInterestIds=Weather stations +multipleForecastConfigurationsCreated=The forecast configurations were successfully created +addMultipleNew=Add multiple new +availableTranslations=Available translations +reference=Reference +observedDateOfFirstCatch=Observed date of first catch +CYDIAPOMON=Cydia pomonella model +cropOrganismIds=Crops +allCrops=All crops +rememberLogin=Remember login +task_DeleteAllExpiredUserUuidsTask_name=Delete all expired user UUIDs +task_DeleteAllExpiredUserUuidsTask_description=Cleaning up the database of UUIDs, which is used for remembering client logins +mapDataIsRequired=Map data is required +showMeWhereIAm=Show me where I am +unknownTranslationKey=Unknown translation key: {0} +mapDrawTypeLabel=What do you want to draw +point=Point +polygon=Polygon +clearAll=Clear all +clearOne=Clear one +phone=Telephone +notificationSubscriptions=Notification subscriptions +userAccountInformation=User account information +notificationSubscriptionsUpdated=Notification subscriptions was successfully updated +messageNotifications=Message notifications +forecastNotifications=Forecast notifications +notificationSubscriptionDescription=You can subscribe to different kinds of notifications below. Choose the format for notification, for instance email or SMS. To receive notifications on SMS, you must accept the billing costs for this in your user account settings. +messageFormat=Message format +Mail=Email +Sms=SMS +forecastNotificationMessageBodyTpl_1=This is for {0} in {1} at location {2} at date {3}. Details: {4} +forecastNotificationMessageBodyTpl_2=This is for {0} in {1} at location {2} at date {3}.Read more: {4} +forecastNotificationMessageHeadingTpl_1=High risk of infection +forecastNotificationMessageHeadingTpl_2=Moderate infection risk +task_SendForecastEventNotificationsTask_name=Send forecast event notifications +task_SendForecastEventNotificationsTask_description=Checks to see if there has been changes in forecasts to YELLOW or RED status. If so, finds subscribers to such events and sends notifications +preferredLocale=Preferred locale +VIPSLogicTitle=Administration system +indexText=VIPSLogic is the common administration system for VIPS. This is where you configure users, weather stations and forecasts, and where you report observations and write messages, and more. Use the top menu to get started. +observationHeading=Observation heading +observationText=Observation text +statusTypeId=Status +statusRemarks=Status remarks +vipsLogicRole_4=Observation authority +statusTypeIdTitle_1=Pending +statusTypeIdTitle_2=Rejected +statusTypeIdTitle_3=Approved +observationDataField_counting1=Counting 1 +observationDataField_counting2=Counting 2 +allCategories=All categories +pending=Pending +approved=Approved +rejected=Rejected +isQuantified=Is quantified +missingInDatabase=Missing in database +broadcastMessage=Broadcast the message +approvesSmsBilling=Approves billing for SMS messages +approvesSmsBillingDescription=By checking this option, you confirm that you accept the billing costs for receiving SMS messages from our subscription services. The price in Norway is 1 NOK/message. This consent can be terminated at any time, either by unchecking this checkbox or by sending VIPS STOP to the service number for your country. The number for Norway is 1963. To configure which notifications to receive and on which format, please select the notification subscriptions button at the top of this page. +observationNotifications=Observation notifications +editCropPests=Edit pests for crop +includeAllChildCrops=Include all child crops +pestOrganismIds=Pests +cropPestUpdated=Crop pest was updated +surveillanceMessageInformation=If you want to create a message about an observation, please use the observation registration form +isPrivate=Is private +privateForecasts=Private forecasts +privateForecastsForOtherUser=Private forecasts for other user +noPrivateForecastsFoundForUser=No private forecasts found for user +listCrops=List all crops +listPests=List all pests +allPests=All pests +cropCategoryIds=Crop categories +vipsLogicRole_5=Message author +approvalApplicationHelp=Describe what role you will have as a VIPS user. +suggestedUserRole=Suggested user role +farmer=Farmer +advisor=Advisor +researcher=Researcher +other=Other +pleaseSpecifyOther=If other, please specify +myAccount=My account +emailNotVerified=You must verify your email address before the user approval process can proceed +pleaseAwaitApproval=Please await your user approval +userApproved=The user was approved +freeSms=Free SMS +LYGUSRUGUL=Lygus rugulipennis model +DELIARADIC=Delia radicum model +OATFLOWERM=Oat flowering model +GRASSDRYMO=Grass drying model +BARLEYNETB=Barley net blotch model +PLASMOVITI=Downy Mildew model +startDateDayDegreeAccumulation=Start date for day degree accumulation +PSILARTEMP=Psila rosae Temperature Model +vipsLogicRole_6=Apple Fruit Moth Administrator +observationSiteName=Observation site name +newObservationSite=New observation site +season=Season +warningStatus_0=No forecast available +warningStatus_1=Missing data +warningStatus_2=No risk of infection +warningStatus_3=Medium risk of infection +warningStatus_4=High risk of infection +warningStatus=Warning status +thousandBerrySample=Thousand berry sample +degreeOfParasitation=Degree of parasitation +observationSitePoints=Observation site points +newObservationSitePoint=New observation site point +observationSitePointName=Observation site point name +appleFruitMothChangeSeasonConfirm=Are you sure you want to change season? All unsaved data for the current season will be lost. +observationSiteStored=Observation site was successfully updated +appleFruitMoth=Apple fruit moth +MAMESTRABR=Mamestra brassicae model +pois=Points Of Interest +type=Type +pointOfInterestType_1=Weather station +pointOfInterestType_2=Farm +pointOfInterestType_3=Field +editPoi=Edit Point Of Interest +newPoi=New Point Of Interest +pointOfInterestType=Point of Interest Type +poiStored=Poi was stored +pointOfInterestType_0=General +noMapDataEntered=No map data entered +DELIARFOBS=Delia radicum/floralis observation model +DELIARFOBY=Delia radicum/floralis observation model for young crops +DELIARFOBO=Delia radicum/floralis observation model for old crops +startDateGrowth=Start date for growth +PSILAROBSE=Psila rosae observation model +NEGPROGMOD=Negative prognosis model +poiDeleted=Point of interest was deleted +organizationGroupList=Organization groups +groupMembers=Group members +organizationGroupStored=Organization group was stored +newGroup=New group +organizationGroupDeleted=The organization group was deleted +availableFor=Available for +userOrganizationGroupsListDescription=Organization groups can be used to share resources like points of interest +cropCategory=Crop category +listSelectedCropCategoryOnTop=List crops from selected category on top +observer=Observer +SEPAPIICOL=Septoria apiicola model +BREMIALACT=Bremia lactucae model +DOWNCASTMO=DOWNCAST model +noResultsFoundForCriteria=No results were found for the given search criteria +noWhitespaceAllowed=No whitespace allowed +general=General +genericPlaces=Generic places +helpMessageFormCropCategoryIds=No crop selection means visibility regardless of user's crop preferences +digit=Digit +lowercase=Lower case +uppercase=Upper case +allSystems=All systems +cropCategoriesFor=Crop categories for +cropCategoryUpdated=Crop category was updated diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 4cc372119e4756947514ccfd8eb85ef1daa2ffb3..a4e31cf71311cf06637080417e944cd3bba7e0a7 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -75,6 +75,10 @@ <servlet-name>OrganizationGroupController</servlet-name> <servlet-class>no.nibio.vips.logic.controller.servlet.OrganizationGroupController</servlet-class> </servlet> + <servlet> + <servlet-name>CropCategoryController</servlet-name> + <servlet-class>no.nibio.vips.logic.controller.servlet.CropCategoryController</servlet-class> + </servlet> <servlet-mapping> <servlet-name>PointOfInterestController</servlet-name> <url-pattern>/poi/*</url-pattern> @@ -135,6 +139,10 @@ <servlet-name>OrganizationGroupController</servlet-name> <url-pattern>/organizationgroup</url-pattern> </servlet-mapping> + <servlet-mapping> + <servlet-name>CropCategoryController</servlet-name> + <url-pattern>/organism/cropcategory</url-pattern> + </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> diff --git a/src/main/webapp/formdefinitions/cropCategoryCropForm.json b/src/main/webapp/formdefinitions/cropCategoryCropForm.json new file mode 100644 index 0000000000000000000000000000000000000000..621429ac22dc34982608de0b525dea2571020511 --- /dev/null +++ b/src/main/webapp/formdefinitions/cropCategoryCropForm.json @@ -0,0 +1,33 @@ +{ + "_licenseNote": [ + "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/>. " + ], + "_comment" : "Structure of the organismForm and how to validate it", + "fields": [ + { + "name" : "cropCategoryId", + "dataType" : "INTEGER", + "required" : true + }, + { + "name" : "cropCategoryCropOrganismIds", + "dataType" : "INTEGER", + "fieldType" : "SELECT_MULTIPLE", + "required" : false + } + ] +} diff --git a/src/main/webapp/templates/cropCategoryList.ftl b/src/main/webapp/templates/cropCategoryList.ftl new file mode 100644 index 0000000000000000000000000000000000000000..c5efd649c4c80b7658b44a3801ac9be235791154 --- /dev/null +++ b/src/main/webapp/templates/cropCategoryList.ftl @@ -0,0 +1,144 @@ +<#-- + 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>${i18nBundle.cropCategoriesFor} ${organization.organizationName}</title> +</#macro> +<#macro custom_css> + <link href="/css/3rdparty/chosen.min.css" rel="stylesheet" /> +</#macro> +<#macro custom_js> + <script src="http://code.jquery.com/ui/1.10.3/jquery-ui.min.js"></script> + <script type="text/javascript" src="/js/3rdparty/chosen.jquery.min.js"></script> + <script type="text/javascript"> + $(document).ready( function() { + // Activating chosen plugin + $(".chosen-select").chosen(); + }); + + var allCrops = [ + <#list allCrops?keys as cropId> + new Option("${allCrops[cropId?string].getLocalName(currentLocale.language)!""} (${allCrops[cropId?string].latinName})", "${cropId}"), + </#list> + ]; + + function prepareEdit(cropCategoryId) + { + var theForm = document.getElementById("form_" + cropCategoryId); + // Disable all other edit buttons + var allForms = document.querySelectorAll('[id^="form_"]') + for(var i=0;i<allForms.length;i++) + { + var aForm = allForms[i]; + var formId = aForm.id.split("_")[1]; + if(formId != cropCategoryId) + { + document.getElementById("editButton_" + formId).disabled = true; + } + else + { + document.getElementById("editButton_" + formId).style.display = "none"; + document.getElementById("cancelButton_" + formId).style.display = "inline"; + document.getElementById("submitButton_" + formId).style.display = "inline"; + aForm.cropCategoryCropOrganismIds.disabled = false; + addUnselectedCrops(aForm.cropCategoryCropOrganismIds); + + $(aForm.cropCategoryCropOrganismIds).trigger("chosen:updated"); + } + } + } + + function addUnselectedCrops(theSelect) + { + // Make a set of the options currently in the list + var selOpts = theSelect.options; + var selOptIds = []; + for(var i=0;i<selOpts.length;i++) + { + selOptIds.push(selOpts[i].value); + } + + for(var i=0;i<allCrops.length;i++) + { + if(selOptIds.indexOf(allCrops[i].id) < 0) + { + selOpts[selOpts.length] = allCrops[i]; + } + } + } + + function cancelEdit() + { + if(!confirm("Are you sure you want to cancel?")) + { + return; + } + location.reload(); + } + </script> +</#macro> +<#macro page_contents> +<div class="singleBlockContainer"> + <h1>${i18nBundle.cropCategoriesFor} ${organization.organizationName}</h1> + <#if user.isSuperUser()> + <div class="form-group"> + <label for="organizationId">${i18nBundle.organizationId}</label> + <select class="form-control chosen-select" name="organizationId" onchange="window.location.href='/organism/cropcategory?organizationId=' + this.options[this.options.selectedIndex].value;"> + <option value="-1">${i18nBundle.pleaseSelect} ${i18nBundle.organizationId?lower_case}</option> + <#list allOrganizations?sort_by("organizationName") as oneOrg> + <option value="${oneOrg.organizationId}" + <#if (organization?has_content && organization.organizationId == oneOrg.organizationId)>selected="selected"</#if> + >${oneOrg.organizationName}</option> + </#list> + </select> + </div> + </#if> + <div class="table-responsive"> + <table class="table table-striped"> + <thead> + <th>${i18nBundle.name}</th> + <th>${i18nBundle.cropOrganismIds}</th> + <th></th> + </thead> + <tbody> + <#list cropCategories as cropCategory> + <tr> + <form id="form_${cropCategory.cropCategoryId}" action="/organism/cropcategory" method="post"> + <input type="hidden" name="action" value="submit"/> + <input type="hidden" name="cropCategoryId" value="${cropCategory.cropCategoryId}"/> + <td>${(cropCategory.getLocalName(currentLocale))!cropCategory.defaultName}</td> + <td> + <select class="form-control chosen-select" name="cropCategoryCropOrganismIds" multiple="multiple" disabled="disabled"> + <#list cropCategory.cropOrganismIds as cropId> + <option value="${cropId}" selected="selected">${allCrops[cropId?string].getLocalName(currentLocale.language)!""} (${allCrops[cropId?string].latinName})</option> + </#list> + </select> + </td> + <td> + <button id="editButton_${cropCategory.cropCategoryId}" type="button" onclick="prepareEdit(${cropCategory.cropCategoryId});">Edit</button> + <button id="cancelButton_${cropCategory.cropCategoryId}" type="button" onclick="cancelEdit(${cropCategory.cropCategoryId});" style="display: none;">Cancel</button> + <input id="submitButton_${cropCategory.cropCategoryId}" type="submit" value="Submit" style="display: none;"/> + </td> + </form> + </tr> + </#list> + </tbody> + </table> +</div> +</#macro> +<@page_html/> \ No newline at end of file diff --git a/src/main/webapp/templates/master.ftl b/src/main/webapp/templates/master.ftl index 1bada82280d21bff7ccc65eb5c852acbae259ab2..cee1fe5e079a72be9a8aec24968e2dd94ff8748a 100644 --- a/src/main/webapp/templates/master.ftl +++ b/src/main/webapp/templates/master.ftl @@ -1,5 +1,5 @@ <#-- - Copyright (c) 2014 NIBIO <http://www.nibio.no/>. + 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 @@ -53,6 +53,7 @@ <li><a href="/scheduling">${i18nBundle.scheduling}</a></li> <li><a href="/weatherStation">${i18nBundle.weatherStations}</a></li> <li><a href="/organism">${i18nBundle.organisms}</a></li> + <li><a href="/organism/cropcategory">${i18nBundle.cropCategoryIds}</a></li> <#else> <li><a href="/user?action=viewUser&userId=${user.userId}">${i18nBundle.myAccount}</a></li> </#if>