r1846 - in trunk: wao-services/src/main/java/fr/ifremer/wao/services/service wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer wao-web/src/main/java/fr/ifremer/wao/web/converter wao-web/src/main/resources/i18n wao-web/src/main/webapp/WEB-INF/content/obsmer wao-web/src/main/webapp/WEB-INF/decorators wao-web/src/main/webapp/bootstrap-2.3.1
Author: tchemit Date: 2014-04-06 19:00:34 +0200 (Sun, 06 Apr 2014) New Revision: 1846 Url: http://forge.codelutin.com/projects/wao/repository/revisions/1846 Log: refs #4487 begin of update contact code Added: trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/ContactNotUpdatableException.java trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/UpdateContactCommand.java trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/EditContactAction.java trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/ValidateContactJsonAction.java trunk/wao-web/src/main/webapp/WEB-INF/content/obsmer/edit-contact-input.jsp Removed: trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/ValidateContact.java Modified: trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/ObsMerContactsService.java trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/DeleteContactAction.java trunk/wao-web/src/main/java/fr/ifremer/wao/web/converter/BooleanSetConverter.java trunk/wao-web/src/main/resources/i18n/wao-web_en_GB.properties trunk/wao-web/src/main/resources/i18n/wao-web_fr_FR.properties trunk/wao-web/src/main/webapp/WEB-INF/content/obsmer/contacts.jsp trunk/wao-web/src/main/webapp/WEB-INF/decorators/layout.jsp trunk/wao-web/src/main/webapp/bootstrap-2.3.1/bootstrap-popover.js Added: trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/ContactNotUpdatableException.java =================================================================== --- trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/ContactNotUpdatableException.java (rev 0) +++ trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/ContactNotUpdatableException.java 2014-04-06 17:00:34 UTC (rev 1846) @@ -0,0 +1,15 @@ +package fr.ifremer.wao.services.service; + +import fr.ifremer.wao.WaoException; + +/** + * When a user try to update a contact with not enough rights. + * <p/> + * Created on 4/6/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 4.0 + */ +public class ContactNotUpdatableException extends WaoException { + private static final long serialVersionUID = 1L; +} Property changes on: trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/ContactNotUpdatableException.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/ObsMerContactsService.java =================================================================== --- trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/ObsMerContactsService.java 2014-04-06 10:01:28 UTC (rev 1845) +++ trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/ObsMerContactsService.java 2014-04-06 17:00:34 UTC (rev 1846) @@ -22,11 +22,14 @@ */ import com.google.common.base.Charsets; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import fr.ifremer.wao.ContactsFilter; import fr.ifremer.wao.WaoTechnicalException; import fr.ifremer.wao.entity.Boat; import fr.ifremer.wao.entity.Contact; +import fr.ifremer.wao.entity.ContactImpl; import fr.ifremer.wao.entity.ContactState; import fr.ifremer.wao.entity.ContactStateMotif; import fr.ifremer.wao.entity.ContactTopiaDao; @@ -46,21 +49,18 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.commons.mail.EmailException; import org.nuiton.csv.Export; import org.nuiton.csv.ExportModel; import org.nuiton.csv.Import; import org.nuiton.csv.ImportModel; import org.nuiton.csv.ImportRuntimeException; +import org.nuiton.topia.persistence.TopiaEntity; import org.nuiton.topia.persistence.pager.TopiaPagerBean; import org.nuiton.util.DateUtil; -import org.nuiton.util.beans.Binder; -import org.nuiton.util.beans.BinderFactory; import java.io.InputStream; import java.util.Calendar; @@ -69,6 +69,7 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Map; import static org.nuiton.i18n.I18n.l; @@ -166,6 +167,45 @@ } + public UpdateContactCommand newUpdateContactCommand(AuthenticatedWaoUser authenticatedWaoUser, Optional<String> optionalContactId) { + + //FIXME Should we apply some security rules (can create, update, import) ? + //Preconditions.checkState(authenticatedWaoUser.isAuthorizedToCreateSampleRow()); + + UpdateContactCommand updateContactCommand = new UpdateContactCommand(); + + updateContactCommand.setAdmin(authenticatedWaoUser.isAdmin()); + + if (optionalContactId.isPresent()) { + + String contactId = optionalContactId.get(); + + Contact contact = getContact(contactId); + + updateContactCommand.setContact(contact); + + updateContactCommand.setCreation(false); + + } else { + + //TODO + Contact contact = new ContactImpl(); + + contact.setObsProgram(ObsProgram.OBSMER); + contact.setDataReliability(DataReliability.UNKNOWN); + + updateContactCommand.setContact(contact); + + updateContactCommand.setCreation(true); + } + + return updateContactCommand; + } + + public Contact getContact(String contactId) { + return getContactDao().forTopiaIdEquals(contactId).findUnique(); + } + public InputStream exportContacts(ContactsFilter filter) { ContactTopiaDao dao = getContactDao(); @@ -214,7 +254,25 @@ for (Contact contact : contactImport) { - createOrUpdateContact(authenticatedWaoUser, contact); + String contactId = contact.getTopiaId(); + + Optional<String> optionalContactId = Optional.fromNullable(contactId); + UpdateContactCommand updateContactCommand = newUpdateContactCommand(authenticatedWaoUser, + optionalContactId); + + //FIXME Apply imported contact... +// updateContactCommand.setContact(contact); + + try { + preValidate(authenticatedWaoUser, updateContactCommand, false); + } catch (ContactNotUpdatableException e) { + if (log.isWarnEnabled()) { + log.warn("Can't update contact: " + contactId); + } + continue; + } + + save0(updateContactCommand); } } catch (ImportRuntimeException e) { @@ -228,136 +286,269 @@ commit(); } - public void save(AuthenticatedWaoUser authenticatedWaoUser, Contact contact) - throws EmailException, ContactNotValidException, NullSampleMonthException { + public void preValidate(AuthenticatedWaoUser authenticatedWaoUser, + UpdateContactCommand updateContactCommand, + boolean needUpdate) throws ContactNotUpdatableException, ContactNotValidException { - ContactTopiaDao dao = getContactDao(); - Contact contactFound = dao.findByTopiaId(contact.getTopiaId()); + if (needUpdate) { + Preconditions.checkState(!updateContactCommand.isCreation()); + } - notifyUsersForMammalsObservation(contactFound, contact); + //FIXME Do some security checks about authenticatedWaoUser - // createOrUpdateContact(transaction, contactFound, contact, true); - createOrUpdateContact(authenticatedWaoUser, contact); + // Check if contact can be updated + boolean canUpdateContact = updateContactCommand.canUpdateContact(authenticatedWaoUser); + if (!canUpdateContact) { + throw new ContactNotUpdatableException(); + } - commit(); - } + // Check if a validation controls are required + boolean mustValidateContact = updateContactCommand.mustValidateContact(); - public void delete(Contact contact) throws NullSampleMonthException { + if (mustValidateContact) { - ContactTopiaDao dao = getContactDao(); - Contact contactFound = dao.findByTopiaId(contact.getTopiaId()); + // Pass validation controls + Contact contact = updateContactCommand.getContact(); - // Need to decrement estimated value if contactFound has - // OBSERVATION_DONE state and may be real value (normally not allowed) - updateSampleMonthTidesValue(contactFound, null, true); + Locale l = serviceContext.getLocale(); - // Execute delete - dao.delete(contactFound); + if (contact.getMainObserver() == null) { + throw new ContactNotValidException(l(l, "wao.import.contact.failure.missing.main.observer")); + } - commit(); - } + if (contact.isSecondaryObserversNotEmpty() && contact.getSecondaryObservers().contains(contact.getMainObserver())) { + throw new ContactNotValidException(l(l, "wao.import.contact.failure.mainObserver.cant.be.secondaryObserver")); + } - /** - * The goal of this method is to put in common code that will be executed - * while updating a single contact (from UI) and while updating multiple - * contacts (from import). - * - * @param connectedUser user who is modifying the contact - * @param contact the contact to save or create - * @return true if the contact was successfully updated, false if contact - * was not updated due to insufficient right (modifying data as - * observer after a validation by administrator) - */ - protected boolean createOrUpdateContact(AuthenticatedWaoUser connectedUser, - Contact contact) throws ContactNotValidException, NullSampleMonthException { + for (WaoUser observer : contact.getAllObservers()) { + boolean observerWorksForCompanyInSampleRow = observer.getCompany().equals(contact.getSampleRow().getCompany()); + if (!observerWorksForCompanyInSampleRow) { + throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.company.for.observer", + observer.getLogin(), contact.getSampleRow().getCompany().getName())); + } + } - validateContact(contact); + // Validation for saving contact depends on contactState + ContactState contactState = contact.getContactState(); + Date observationBeginDate = contact.getObservationBeginDate(); + if (log.isDebugEnabled()) { + log.debug("For state : " + contactState + " and observation begin date " + observationBeginDate); + } - ContactTopiaDao dao = getContactDao(); - Contact contactFound = null; - if (contact.getTopiaId() != null) { - contactFound = dao.findByTopiaId(contact.getTopiaId()); - } + // need the sample months to be loaded, it's never the case :-( + // boolean operationBeginDateIsValid = contact.getSampleRow().isValid(observationBeginDate); - // Prevent that someone who is not admin change data that only admin - // must be able to modify - if (!connectedUser.isAdmin()) { - if (contactFound == null) { - contact.setCommentAdmin(null); - contact.setValidationProgram(null); - contact.setDataReliability(DataReliability.UNKNOWN); - } else { - contact.setCommentAdmin(contactFound.getCommentAdmin()); - contact.setValidationProgram(contactFound.getValidationProgram()); - contact.setDataReliability(contactFound.getDataReliability()); + String sampleRowCode = contact.getSampleRow().getCode(); + SampleRow sampleRow = getSampleRowDao().forCodeEquals(sampleRowCode).findAny(); + + SampleMonth month = sampleRow.getSampleMonth(observationBeginDate); + boolean operationBeginDateIsValid = month != null; + + if (log.isDebugEnabled()) { + log.debug("operation begin data is valid : " + operationBeginDateIsValid); } - } - boolean contactCanBeUpdated = true; - if (contactFound != null && connectedUser.isCoordinatorOrObserver()) { - contactCanBeUpdated = contactFound.getValidationProgram() == null; - } + if (observationBeginDate != null && !operationBeginDateIsValid) { + throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.trip.beginDate", + contact.getSampleRow().getCode())); + } - if (contactCanBeUpdated) { + Date observationEndDate = contact.getObservationEndDate(); + if (observationBeginDate != null && observationEndDate != null + && observationEndDate.before(observationBeginDate)) { + throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.observation.endDate")); + } - updateElligibleBoatForContact(contact); - updateSampleMonthTidesValue(contactFound, contact, true); + Date dataInputDate = contact.getDataInputDate(); + // Here, we check that the date input date is after the end of the + // observation. Since the first is a day (at 00:00) and the second + // is date-time, there may be a bug if the data input day is the same + // as the end of observation + boolean observationEndDateIsBeforeDataInputDate = + observationEndDate == null + || dataInputDate == null + || observationEndDate.before(DateUtil.setMaxTimeOfDay(dataInputDate)); - if (contactFound == null) { - if (contact.getCreationDate() == null) { - contact.setCreationDate(serviceContext.getNow()); + if (log.isDebugEnabled()) { + log.debug("observationEndDate = " + observationEndDate + + ", dateInputDate = " + dataInputDate + ", observationEndDateIsBeforeDataInputDate = " + + observationEndDateIsBeforeDataInputDate); + } + if (!observationEndDateIsBeforeDataInputDate) { + throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.observation.end")); + } + + Date currentDate = serviceContext.getNow(); + if (observationEndDate != null && observationEndDate.after(currentDate)) { + throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.trip.endDate")); + } + + if (dataInputDate != null && dataInputDate.after(currentDate)) { + throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.observation.end2")); + } + + // Non abouti + if (contactState == ContactState.OBSERVATION_CANCELLED && StringUtils.isBlank(contact.getComment())) { + throw new ContactNotValidException(l(l, "wao.business.contact.validation.commentMissingForState", + contact.getContactState().toString())); + // Observation réalisée + } else if (contactState.equals(ContactState.OBSERVATION_DONE)) { + + if (observationBeginDate == null) { + throw new ContactNotValidException(l(l, "wao.import.contact.failure.missing.trip.beginDate", contactState)); } - dao.create(contact); - } else { - Binder<Contact, Contact> contactBinder = BinderFactory.newBinder(Contact.class); - contactBinder.copyExcluding(contact, contactFound, - Contact.PROPERTY_TOPIA_ID, - Contact.PROPERTY_TOPIA_VERSION, - Contact.PROPERTY_TOPIA_CREATE_DATE, - Contact.PROPERTY_SAMPLE_ROW); -// contactFound.clearSecondaryObservers(); -// if (contact.getSecondaryObservers() != null) { -// contactFound.addAllSecondaryObservers(contact.getSecondaryObservers()); -// } - dao.update(contactFound); + if (observationEndDate == null) { + throw new ContactNotValidException(l(l, "wao.import.contact.failure.missing.observation.endDate", contactState)); + } + if (contact.getNbObservants() == 0) { + throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.observer.state", contactState)); + } + if (contact.getObsProgram() == ObsProgram.OBSVENTE) { + if (contact.getTerrestrialLocation() == null) { + throw new ContactNotValidException(l(l, "wao.import.contact.failure.missing.observationArea")); + } + } } - } - return contactCanBeUpdated; - } + boolean contactMustHaveAMotif = contact.getObsProgram() == ObsProgram.OBSMER + && (contactState == ContactState.CONTACT_REFUSED + || contactState == ContactState.CONTACT_DEFINITELY_REFUSED); + if (contactMustHaveAMotif && contact.getContactStateMotif() == null) { + throw new ContactNotValidException(l(l, "wao.business.contact.validation.contactStateMotifMissing")); + } - protected void notifyUsersForMammalsObservation(Contact contactFound, Contact contact) { + if (!contactMustHaveAMotif && contact.getContactStateMotif() != null) { + throw new ContactNotValidException(l(l, "wao.business.contact.validation.contactStateMotifUnwanted")); + } - boolean sendNotification = false; + if (log.isDebugEnabled()) { + log.debug("validationProgram = " + contact.getValidationProgram()); + } - // we send notifications if there is mammals Capture and - // we prevent re-send of multiple identical messages - if (contact.isMammalsCapture()) { - String oldMessage = null; - if (contactFound != null) { - oldMessage = contactFound.getMammalsInfo(); + if (BooleanUtils.isTrue(contact.getValidationCompany())) { + // Pour valider un contact société, il faut que le contact aie une date de transmission + if (contact.getContactState() == ContactState.OBSERVATION_DONE && contact.getObservedDataControl() == null) { + throw new ContactNotValidException(l(l, "wao.business.contact.validation.observedDataControlMissingForValidation")); + } + if (contact.getObservedDataControl() == ObservedDataControl.ACCEPTED && contact.getRestitution() == null) { + throw new ContactNotValidException(l(l, "wao.business.contact.validation.restitutionMissingForValidation")); + } + if (contact.getDataInputDate() == null && contact.getRestitution() != null) { + throw new ContactNotValidException(l(l, "wao.import.contact.failure.missing.observationDate")); + } + if (contact.getDataInputDate() != null && contact.getRestitution() != null && contact.getRestitution().before(contact.getDataInputDate())) { + throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.transmissionDate")); + } } - boolean messageChanged = ObjectUtils.notEqual(contact.getMammalsInfo(), oldMessage); - if (messageChanged) { - sendNotification = true; + + if (BooleanUtils.isTrue(contact.getValidationProgram())) { + // it's an admin validation, data-reliability field must be filled + if (log.isDebugEnabled()) { + log.debug("field data reliability is " + contact.getDataReliability()); + } + + if (contact.getDataReliability() == null || + contact.getDataReliability() == DataReliability.UNKNOWN) { + throw new ContactNotValidException(l(l, "wao.business.contact.validation.dataReliabilityMissingForValidation")); + } else if (contact.getDataReliability() != DataReliability.RELIABLE + && StringUtils.isEmpty(contact.getCommentAdmin())) { + throw new ContactNotValidException(l(l, "wao.business.contact.validation.commentAdminNecessaryForDataReliability", + contact.getDataReliability().toString())); + } } } + } - if (sendNotification) { + public void save(UpdateContactCommand updateContactCommand, + boolean needUpdate) throws ContactNotValidException, ContactNotUpdatableException, NullSampleMonthException { - MammalsObservationEmail email = new MammalsObservationEmail(getLocale()); - email.setContact(contact); + if (needUpdate) { + Preconditions.checkState(!updateContactCommand.isCreation()); + } - // now trying to find to what user we need to send the mail - WaoUserTopiaDao userDao = getWaoUserDao(); - // users contains all the user we need to notify for the capture - List<WaoUser> waoUsers = userDao.forMammalsNotificationsEquals(true).findAll(); + save0(updateContactCommand); - for (WaoUser waoUser : waoUsers) { - email.addTo(waoUser); + commit(); + } + + public void delete(String contactId) throws IllegalDeletionException { + + Contact contact = getContact(contactId); + + // Execute delete + ContactTopiaDao dao = getContactDao(); + + Map<Class<? extends TopiaEntity>, List<? extends TopiaEntity>> allUsages = dao.findAllUsages(contact); + + if (!allUsages.isEmpty()) { + throw new IllegalDeletionException(allUsages); + } + + //FIXME +// updateSampleMonthTidesValue(contact, null, true); + + dao.delete(contact); + + commit(); + } + + protected void save0(UpdateContactCommand updateContactCommand) throws NullSampleMonthException { + + // Get contact to validate (must exist) + Contact contact = updateContactCommand.getContact(); + + ContactTopiaDao dao = getContactDao(); + + if (updateContactCommand.isCreation()) { + + //Update the elligible boat depends on contact creation. The + //{@code contact} reference can only be created for a sampleRow and a + //boat if both are linked with an elligibleBoat. So this method is + //used to create the link if needed during contacts import. This + //elligibleBoat is needed for the contact owned by a company, so + //the companyActive property of ElligibleBoat will be set to TRUE. No + //admin has decided to explicitly create this link. + + ElligibleBoatTopiaDao elligibleDAO = getElligibleBoatDao(); + ElligibleBoat elligible = elligibleDAO.findUniqueOrNull(contact); + + if (elligible == null) { + // Create new elligible boat not active in a global way + elligible = elligibleDAO.create(contact); } + elligible.setCompanyActive(Boolean.TRUE); - getEmailService().send(email); + //FIXME Recompute for the hole sample row? +// updateSampleMonthTidesValue(null, contact, true); + + if (contact.getCreationDate() == null) { + contact.setCreationDate(serviceContext.getNow()); + } + + dao.create(contact); + + } else { + + //FIXME Recompute for the hole sample row? +// updateSampleMonthTidesValue(contactFound, contact, true); + + if (updateContactCommand.isMammalsInfosChanged()) { + + MammalsObservationEmail email = new MammalsObservationEmail(getLocale()); + email.setContact(contact); + + // now trying to find to what user we need to send the mail + WaoUserTopiaDao userDao = getWaoUserDao(); + // users contains all the user we need to notify for the capture + List<WaoUser> waoUsers = userDao.forMammalsNotificationsEquals(true).findAll(); + + for (WaoUser waoUser : waoUsers) { + email.addTo(waoUser); + } + + getEmailService().send(email); + } + dao.update(contact); } } @@ -486,197 +677,4 @@ } } } - - protected void validateContact(Contact contact) throws ContactNotValidException { - - Locale l = serviceContext.getLocale(); - - Contact oldContact = null; - if (contact.getTopiaId() != null) { - oldContact = getContactDao().findByTopiaId(contact.getTopiaId()); - } - - // S'il s'agit de dé-valider pour le coordinateur ou l'administrateur - // on ne fait aucun contrôle - boolean skip = oldContact != null - && oldContact.getValidationProgram() != null && - contact.getValidationProgram() == null; - - if (skip) { - return; - } - - if (contact.getMainObserver() == null) { - throw new ContactNotValidException(l(l, "wao.import.contact.failure.missing.main.observer")); - } - - if (contact.getSecondaryObservers() != null && - contact.getSecondaryObservers().contains(contact.getMainObserver())) { - throw new ContactNotValidException(l(l, "wao.import.contact.failure.mainObserver.cant.be.secondaryObserver")); - } - - for (WaoUser observer : contact.getAllObservers()) { - boolean observerWorksForCompanyInSampleRow = observer.getCompany().equals(contact.getSampleRow().getCompany()); - if (!observerWorksForCompanyInSampleRow) { - throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.company.for.observer", - observer.getLogin(), contact.getSampleRow().getCompany().getName())); - } - } - - // Validation for saving contact depends on contactState - ContactState contactState = contact.getContactState(); - Date observationBeginDate = contact.getObservationBeginDate(); - if (log.isDebugEnabled()) { - log.debug("For state : " + contactState + " and observation begin date " + observationBeginDate); - } - - // need the sample months to be loaded, it's never the case :-( - // boolean operationBeginDateIsValid = contact.getSampleRow().isValid(observationBeginDate); - - String sampleRowCode = contact.getSampleRow().getCode(); - SampleRow sampleRow = getSampleRowDao().forCodeEquals(sampleRowCode).findAny(); - - SampleMonth month = sampleRow.getSampleMonth(observationBeginDate); - boolean operationBeginDateIsValid = month != null; - - if (log.isDebugEnabled()) { - log.debug("operation begin data is valid : " + operationBeginDateIsValid); - } - - if (observationBeginDate != null && !operationBeginDateIsValid) { - throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.trip.beginDate", - contact.getSampleRow().getCode())); - } - - Date observationEndDate = contact.getObservationEndDate(); - if (observationBeginDate != null && observationEndDate != null - && observationEndDate.before(observationBeginDate)) { - throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.observation.endDate")); - } - - Date dataInputDate = contact.getDataInputDate(); - // Here, we check that the date input date is after the end of the - // observation. Since the first is a day (at 00:00) and the second - // is date-time, there may be a bug if the data input day is the same - // as the end of observation - boolean observationEndDateIsBeforeDataInputDate = - observationEndDate == null - || dataInputDate == null - || observationEndDate.before(DateUtil.setMaxTimeOfDay(dataInputDate)); - - if (log.isDebugEnabled()) { - log.debug("observationEndDate = " + observationEndDate + - ", dateInputDate = " + dataInputDate + ", observationEndDateIsBeforeDataInputDate = " - + observationEndDateIsBeforeDataInputDate); - } - if (!observationEndDateIsBeforeDataInputDate) { - throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.observation.end")); - } - - Date currentDate = serviceContext.getNow(); - if (observationEndDate != null && observationEndDate.after(currentDate)) { - throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.trip.endDate")); - } - - if (dataInputDate != null && dataInputDate.after(currentDate)) { - throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.observation.end2")); - } - - // Non abouti - if (contactState == ContactState.OBSERVATION_CANCELLED && StringUtils.isBlank(contact.getComment())) { - throw new ContactNotValidException(l(l, "wao.business.contact.validation.commentMissingForState", - contact.getContactState().toString())); - // Observation réalisée - } else if (contactState.equals(ContactState.OBSERVATION_DONE)) { - - if (observationBeginDate == null) { - throw new ContactNotValidException(l(l, "wao.import.contact.failure.missing.trip.beginDate", contactState)); - } - if (observationEndDate == null) { - throw new ContactNotValidException(l(l, "wao.import.contact.failure.missing.observation.endDate", contactState)); - } - if (contact.getNbObservants() == 0) { - throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.observer.state", contactState)); - } - if (contact.getObsProgram() == ObsProgram.OBSVENTE) { - if (contact.getTerrestrialLocation() == null) { - throw new ContactNotValidException(l(l, "wao.import.contact.failure.missing.observationArea")); - } - } - } - - // Ici, les contrôle spécifique à ObsMer - if (contact.getObsProgram() == ObsProgram.OBSMER) { - - boolean contactMustHaveAMotif = contact.getObsProgram() == ObsProgram.OBSMER - && (contactState == ContactState.CONTACT_REFUSED - || contactState == ContactState.CONTACT_DEFINITELY_REFUSED); - if (contactMustHaveAMotif && contact.getContactStateMotif() == null) { - throw new ContactNotValidException(l(l, "wao.business.contact.validation.contactStateMotifMissing")); - } - - if (!contactMustHaveAMotif && contact.getContactStateMotif() != null) { - throw new ContactNotValidException(l(l, "wao.business.contact.validation.contactStateMotifUnwanted")); - } - - if (log.isDebugEnabled()) { - log.debug("validationProgram = " + contact.getValidationProgram()); - } - - if (BooleanUtils.isTrue(contact.getValidationCompany())) { - // Pour valider un contact société, il faut que le contact aie une date de transmission - if (contact.getContactState() == ContactState.OBSERVATION_DONE && contact.getObservedDataControl() == null) { - throw new ContactNotValidException(l(l, "wao.business.contact.validation.observedDataControlMissingForValidation")); - } - if (contact.getObservedDataControl() == ObservedDataControl.ACCEPTED && contact.getRestitution() == null) { - throw new ContactNotValidException(l(l, "wao.business.contact.validation.restitutionMissingForValidation")); - } - if (contact.getDataInputDate() == null && contact.getRestitution() != null) { - throw new ContactNotValidException(l(l, "wao.import.contact.failure.missing.observationDate")); - } - if (contact.getDataInputDate() != null && contact.getRestitution() != null && contact.getRestitution().before(contact.getDataInputDate())) { - throw new ContactNotValidException(l(l, "wao.import.contact.failure.invalid.transmissionDate")); - } - } - - if (BooleanUtils.isTrue(contact.getValidationProgram())) { - // it's an admin validation, data-reliability field must be filled - if (log.isDebugEnabled()) { - log.debug("field data reliability is " + contact.getDataReliability()); - } - - if (contact.getDataReliability() == null || - contact.getDataReliability() == DataReliability.UNKNOWN) { - throw new ContactNotValidException(l(l, "wao.business.contact.validation.dataReliabilityMissingForValidation")); - } else if (contact.getDataReliability() != DataReliability.RELIABLE - && StringUtils.isEmpty(contact.getCommentAdmin())) { - throw new ContactNotValidException(l(l, "wao.business.contact.validation.commentAdminNecessaryForDataReliability", - contact.getDataReliability().toString())); - } - } - } - } - - /** - * Update the elligible boat depends on contact creation. The - * {@code contact} reference can only be created for a sampleRow and a - * boat if both are linked with an elligibleBoat. So this method is - * used to create the link if needed during contacts import. This - * elligibleBoat is needed for the contact owned by a company, so - * the companyActive property of ElligibleBoat will be set to TRUE. No - * admin has decided to explicitly create this link. - * - * @param contact which contains sampleRow and boat to link - */ - protected void updateElligibleBoatForContact(Contact contact) { - - ElligibleBoatTopiaDao elligibleDAO = getElligibleBoatDao(); - ElligibleBoat elligible = elligibleDAO.findUniqueOrNull(contact); - - if (elligible == null) { - // Create new elligible boat not active in a global way - elligible = elligibleDAO.create(contact); - } - elligible.setCompanyActive(Boolean.TRUE); - } } Added: trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/UpdateContactCommand.java =================================================================== --- trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/UpdateContactCommand.java (rev 0) +++ trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/UpdateContactCommand.java 2014-04-06 17:00:34 UTC (rev 1846) @@ -0,0 +1,140 @@ +package fr.ifremer.wao.services.service; + +import com.google.common.base.Preconditions; +import fr.ifremer.wao.entity.Contact; +import fr.ifremer.wao.entity.DataReliability; +import fr.ifremer.wao.services.AuthenticatedWaoUser; +import org.apache.commons.lang3.ObjectUtils; + +import java.io.Serializable; + +/** + * Created on 4/6/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 4.0 + */ +public class UpdateContactCommand implements Serializable { + + private static final long serialVersionUID = 1L; + + protected boolean admin; + + protected boolean creation; + + protected Contact contact; + + protected Boolean oldValidationCompany; + + protected Boolean oldValidationProgram; + + protected String oldMammalsInfo; + + public boolean isCreation() { + return creation; + } + + public void setCreation(boolean creation) { + this.creation = creation; + } + + public boolean isAdmin() { + return admin; + } + + public void setAdmin(boolean admin) { + this.admin = admin; + } + + public Contact getContact() { + return contact; + } + + public void setContact(Contact contact) { + this.contact = contact; + this.oldValidationCompany = contact.getValidationCompany(); + this.oldValidationProgram = contact.getValidationProgram(); + this.oldMammalsInfo = contact.getMammalsInfo(); + } + + public Boolean getValidationCompany() { + return contact.getValidationCompany(); + } + + public void setValidationCompany(Boolean validationCompany) { + contact.setValidationCompany(validationCompany); + } + + public Boolean getValidationProgram() { + return contact.getValidationProgram(); + } + + public void setValidationProgram(Boolean validationProgram) { + Preconditions.checkState(isAdmin(), "cannot change 'validationProgram' if you are not admin"); + contact.setValidationProgram(validationProgram); + } + + public void setCommentAdmin(String commentAdmin) { + Preconditions.checkState(isAdmin(), "cannot change 'commentAdmin' if you are not admin"); + contact.setCommentAdmin(commentAdmin); + } + + public void setDataReliability(DataReliability dataReliability) { + Preconditions.checkState(isAdmin(), "cannot change 'dataReliability' if you are not admin"); + contact.setDataReliability(dataReliability); + } + + public void setMammalsInfo(String mammalsInfo) { + contact.setMammalsInfo(mammalsInfo); + } + + /** + * Check if the contact can be updated by the given connected user. + * + * @param authenticatedWaoUser the user who want to update the contact + * @return {@code true} if contact can be updated + */ + public boolean canUpdateContact(AuthenticatedWaoUser authenticatedWaoUser) { + boolean contactCanBeUpdated = true; + if (!isCreation() && authenticatedWaoUser.isCoordinatorOrObserver()) { + contactCanBeUpdated = oldValidationProgram == null; + } + return contactCanBeUpdated; + } + + /** + * Check if the contact need to pass validation controls. + * + * @return {@code true} if the contact must be validated + */ + public boolean mustValidateContact() { + boolean needValidation = isCreation() || // new contact + oldValidationProgram == null || // want to unvalidate a contact + getValidationProgram() != null; // want to validate a contact + return needValidation; + } + + /** + * Check if mammals informations has changed. + * + * @return {@code true} if mammal informations changed + */ + public boolean isMammalsInfosChanged() { + + boolean mammalsInfosChanged = false; + + // we send notifications if there is mammals Capture and + // we prevent re-send of multiple identical messages + if (contact.isMammalsCapture()) { + String oldMessage = null; + if (!isCreation()) { + oldMessage = oldMammalsInfo; + } + boolean messageChanged = ObjectUtils.notEqual(contact.getMammalsInfo(), oldMessage); + if (messageChanged) { + mammalsInfosChanged = true; + } + } + return mammalsInfosChanged; + } +} Property changes on: trunk/wao-services/src/main/java/fr/ifremer/wao/services/service/UpdateContactCommand.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/DeleteContactAction.java =================================================================== --- trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/DeleteContactAction.java 2014-04-06 10:01:28 UTC (rev 1845) +++ trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/DeleteContactAction.java 2014-04-06 17:00:34 UTC (rev 1846) @@ -21,8 +21,12 @@ * #L% */ -import fr.ifremer.wao.services.service.ObsMerSamplingPlanService; +import fr.ifremer.wao.entity.Contact; +import fr.ifremer.wao.services.service.IllegalDeletionException; +import fr.ifremer.wao.services.service.ObsMerContactsService; import fr.ifremer.wao.web.WaoJspActionSupport; +import org.apache.struts2.convention.annotation.Result; +import org.apache.struts2.convention.annotation.Results; /** * Created on 4/3/14. @@ -30,15 +34,19 @@ * @author Tony Chemit <chemit@codelutin.com> * @since 4.0 */ +@Results({ + @Result(name = "error", type = "redirectAction", params = {"actionName", "edit-contact!input", "contactId", "%{contactId}"}), + @Result(name = "success", type = "redirectAction", params = {"actionName", "contacts"}) + }) public class DeleteContactAction extends WaoJspActionSupport { private static final long serialVersionUID = 1L; protected String contactId; - protected transient ObsMerSamplingPlanService service; + protected transient ObsMerContactsService service; - public void setService(ObsMerSamplingPlanService service) { + public void setService(ObsMerContactsService service) { this.service = service; } @@ -46,6 +54,31 @@ this.contactId = contactId; } - //TODO + public String getContactId() { + return contactId; + } + @Override + public String execute() throws Exception { + + Contact contact = service.getContact(contactId); + String contactCode = contact.getMainObserver().getFullName(); + + String result; + try { + service.delete(contactId); + + session.addMessage(t("wao.ui.action.deleteContact.success", contactCode)); + + result = SUCCESS; + + } catch (IllegalDeletionException e) { + + session.addErrorMessages(t("wao.ui.action.deleteContact.failure", contactCode)); + session.addErrorMessages(e.getExplanation(getLocale())); + + result = ERROR; + } + return result; + } } Added: trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/EditContactAction.java =================================================================== --- trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/EditContactAction.java (rev 0) +++ trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/EditContactAction.java 2014-04-06 17:00:34 UTC (rev 1846) @@ -0,0 +1,83 @@ +package fr.ifremer.wao.web.action.obsmer; + +import com.google.common.base.Optional; +import com.google.common.base.Strings; +import com.opensymphony.xwork2.Preparable; +import fr.ifremer.wao.services.AuthenticatedWaoUser; +import fr.ifremer.wao.services.service.ContactNotUpdatableException; +import fr.ifremer.wao.services.service.ContactNotValidException; +import fr.ifremer.wao.services.service.ObsMerContactsService; +import fr.ifremer.wao.services.service.UpdateContactCommand; +import fr.ifremer.wao.web.WaoJspActionSupport; +import org.apache.struts2.convention.annotation.Result; +import org.apache.struts2.convention.annotation.Results; + +/** + * Created on 4/6/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 4.0 + */ +@Results({@Result(name = "success", type = "redirectAction", params = {"actionName", "contacts"})}) +public class EditContactAction extends WaoJspActionSupport implements Preparable { + + private static final long serialVersionUID = 1L; + + /** + * Id of contact to edit. + */ + protected Optional<String> optionalContactId = Optional.absent(); + + protected transient ObsMerContactsService service; + + protected UpdateContactCommand updateContactCommand; + + public void setService(ObsMerContactsService service) { + this.service = service; + } + + public void setContactId(String contactId) { + this.optionalContactId = Optional.fromNullable(Strings.emptyToNull(contactId)); + } + + public String getContactId() { + return optionalContactId.orNull(); + } + + public UpdateContactCommand getUpdateContactCommand() { + if (updateContactCommand == null) { + prepare(); + } + return updateContactCommand; + } + + @Override + public void prepare() { + + updateContactCommand = service.newUpdateContactCommand(getAuthenticatedWaoUser(), optionalContactId); + } + + @Override + public void validate() { + + AuthenticatedWaoUser authenticatedWaoUser = session.getAuthenticatedWaoUser(); + + try { + service.preValidate(authenticatedWaoUser, updateContactCommand, true); + } catch (ContactNotUpdatableException e) { + addActionError(t("wao.ui.contacts.validation.failure.not.updatable", e.getMessage())); + } catch (ContactNotValidException e) { + addActionError(t("wao.ui.contacts.validation.failure.not.valid", e.getMessage())); + } + } + + @Override + public String execute() throws Exception { + + service.save(updateContactCommand, false); + + session.addMessage(t("wao.ui.form.updateContactCommand.success", + updateContactCommand.getContact().getMainObserver().getFullName())); + return SUCCESS; + } +} \ No newline at end of file Property changes on: trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/EditContactAction.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Deleted: trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/ValidateContact.java =================================================================== --- trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/ValidateContact.java 2014-04-06 10:01:28 UTC (rev 1845) +++ trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/ValidateContact.java 2014-04-06 17:00:34 UTC (rev 1846) @@ -1,54 +0,0 @@ -package fr.ifremer.wao.web.action.obsmer; - -/* - * #%L - * Wao :: Web - * %% - * Copyright (C) 2009 - 2014 Ifremer - * %% - * 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% - */ - -import fr.ifremer.wao.services.service.ObsMerSamplingPlanService; -import fr.ifremer.wao.web.WaoJspActionSupport; - -/** - * Created on 4/3/14. - * - * @author Tony Chemit <chemit@codelutin.com> - * @since 4.0 - */ -public class ValidateContact extends WaoJspActionSupport { - - private static final long serialVersionUID = 1L; - - protected String contactId; - - protected Boolean validationState; - - protected transient ObsMerSamplingPlanService service; - - public void setService(ObsMerSamplingPlanService service) { - this.service = service; - } - - public void setContactId(String contactId) { - this.contactId = contactId; - } - - public void setValidationState(Boolean validationState) { - this.validationState = validationState; - } -} Copied: trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/ValidateContactJsonAction.java (from rev 1840, trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/ValidateContact.java) =================================================================== --- trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/ValidateContactJsonAction.java (rev 0) +++ trunk/wao-web/src/main/java/fr/ifremer/wao/web/action/obsmer/ValidateContactJsonAction.java 2014-04-06 17:00:34 UTC (rev 1846) @@ -0,0 +1,178 @@ +package fr.ifremer.wao.web.action.obsmer; + +/* + * #%L + * Wao :: Web + * %% + * Copyright (C) 2009 - 2014 Ifremer + * %% + * 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% + */ + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.opensymphony.xwork2.Preparable; +import fr.ifremer.wao.services.AuthenticatedWaoUser; +import fr.ifremer.wao.services.service.ContactNotUpdatableException; +import fr.ifremer.wao.services.service.ContactNotValidException; +import fr.ifremer.wao.services.service.ObsMerContactsService; +import fr.ifremer.wao.services.service.UpdateContactCommand; +import fr.ifremer.wao.web.WaoJsonActionSupport; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Created on 4/3/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 4.0 + */ +public class ValidateContactJsonAction extends WaoJsonActionSupport implements Preparable { + + private static final long serialVersionUID = 1L; + + /** Logger. */ + private static final Log log = LogFactory.getLog(ValidateContactJsonAction.class); + + /** + * Id of contact to treat. + */ + protected String contactId; + + /** + * New validation state. + */ + protected Boolean validationState; + + /** + * Success message + */ + protected String successMessage; + + /** + * Error message if validation, or any was wrong while update. + */ + protected String errorMessage; + + /** + * To update contact validation actions. + */ + protected boolean canValidateContact; + + /** + * To update contact validation actions. + */ + protected boolean canUnvalidateContact; + + protected transient ObsMerContactsService service; + + protected UpdateContactCommand updateContactCommand; + + public void setService(ObsMerContactsService service) { + this.service = service; + } + + public void setContactId(String contactId) { + this.contactId = contactId; + } + + public void setValidationState(Boolean validationState) { + this.validationState = validationState; + } + + public String getContactId() { + return contactId; + } + + public Boolean getValidationState() { + return validationState; + } + + public String getSuccessMessage() { + return successMessage; + } + + public String getErrorMessage() { + return errorMessage; + } + + public boolean isCanValidateContact() { + return canValidateContact; + } + + public boolean isCanUnvalidateContact() { + return canUnvalidateContact; + } + + public boolean isSuccessful() { + return errorMessage == null; + } + + @Override + public void prepare() { + + Preconditions.checkState(StringUtils.isNotEmpty(contactId)); + + AuthenticatedWaoUser authenticatedWaoUser = session.getAuthenticatedWaoUser(); + + updateContactCommand = service.newUpdateContactCommand( + session.getAuthenticatedWaoUser(), + Optional.of(contactId)); + + if (authenticatedWaoUser.isAdmin()) { + updateContactCommand.setValidationProgram(validationState); + } else { + updateContactCommand.setValidationCompany(validationState); + } + } + + @Override + public String execute() throws Exception { + + AuthenticatedWaoUser authenticatedWaoUser = session.getAuthenticatedWaoUser(); + + try { + service.preValidate(authenticatedWaoUser, updateContactCommand, true); + } catch (ContactNotUpdatableException e) { + errorMessage = t("wao.ui.contacts.validation.failure.not.updatable", e.getMessage()); + } catch (ContactNotValidException e) { + errorMessage = t("wao.ui.contacts.validation.failure.not.valid", e.getMessage()); + } catch (Exception e) { + if (log.isErrorEnabled()) { + log.error(e); + } + errorMessage = t("wao.ui.contacts.validation.failure", e.getMessage()); + } + + if (isSuccessful()) { + + service.save(updateContactCommand, true); + if (validationState == null) { + successMessage = t("wao.ui.contacts.validation.to.unvalidate.state.success"); + } else if (validationState) { + successMessage = t("wao.ui.contacts.validation.to.accept.state.success"); + } else { + successMessage = t("wao.ui.contacts.validation.to.reject.state.success"); + } + + canValidateContact = authenticatedWaoUser.isAuthorizedToValidateContact(updateContactCommand.getContact()); + + canUnvalidateContact = authenticatedWaoUser.isAuthorizedToUnvalidateContact(updateContactCommand.getContact()); + } + + return SUCCESS; + } +} Modified: trunk/wao-web/src/main/java/fr/ifremer/wao/web/converter/BooleanSetConverter.java =================================================================== --- trunk/wao-web/src/main/java/fr/ifremer/wao/web/converter/BooleanSetConverter.java 2014-04-06 10:01:28 UTC (rev 1845) +++ trunk/wao-web/src/main/java/fr/ifremer/wao/web/converter/BooleanSetConverter.java 2014-04-06 17:00:34 UTC (rev 1846) @@ -49,7 +49,7 @@ for (String string : strings) { Boolean aBoolean; - if (StringUtils.isEmpty(string)) { + if (StringUtils.isEmpty(string) || "null".equals(string)) { aBoolean = null; } else { aBoolean = Boolean.valueOf(string); Modified: trunk/wao-web/src/main/resources/i18n/wao-web_en_GB.properties =================================================================== --- trunk/wao-web/src/main/resources/i18n/wao-web_en_GB.properties 2014-04-06 10:01:28 UTC (rev 1845) +++ trunk/wao-web/src/main/resources/i18n/wao-web_en_GB.properties 2014-04-06 17:00:34 UTC (rev 1846) @@ -40,6 +40,8 @@ wao.ui.action.deleteCompany.success=Company deleted successfully wao.ui.action.deleteContact=Delete contact wao.ui.action.deleteContact.confirm=Are you sure you want to delete this contact ? +wao.ui.action.deleteContact.failure=The contact cannot be deleted +wao.ui.action.deleteContact.success=Contact deleted successfully wao.ui.action.deleteNews=Delete this news wao.ui.action.deleteNews.confirm=Are you sure you want to delete this news ? wao.ui.action.deleteSampleRow=Delete this sample row @@ -51,6 +53,7 @@ wao.ui.action.deleteWaoUser.failure=The user cannot be deleted wao.ui.action.deleteWaoUser.success=User deleted successfully wao.ui.action.edit=Edit +wao.ui.action.editOrDeleteContact=Edit or delete contact wao.ui.action.editOrDeleteSampleRow=Edit or delete sample row wao.ui.action.enlargeView=Enlarge view wao.ui.action.exportBoats=Export boats with private infos @@ -110,15 +113,30 @@ wao.ui.chart.numberObservations=No. observations wao.ui.chart.numberOfBoatsWithBoardings=Number of boats with x observations wao.ui.chooseUserProfile=Choose your user profile +wao.ui.contact.creation=Creation of a contact +wao.ui.contact.edition=Edtion of contact %s wao.ui.contact.lastContact=Last observation with this boat for your company +wao.ui.contacts.FishingZone.facadeName=Fishing zone Facade +wao.ui.contacts.FishingZone.sectorName=Fishing zone Sector +wao.ui.contacts.Profession.libelle=Profession Libelle +wao.ui.contacts.Profession.species=Profession species +wao.ui.contacts.boatName=Boat wao.ui.contacts.createFromBoat=Create a new contact for this boat and this sample row wao.ui.contacts.createFromBoat.fail=Contact creation failed wao.ui.contacts.createFromBoat.warn=Warning \:this sample-row is out of date, are your sure you want to create a new contact ? -wao.ui.contacts.division=Division -wao.ui.contacts.observations=Accidental catches and observations -wao.ui.contacts.observers=Observers +wao.ui.contacts.district=Boat District Code +wao.ui.contacts.division=Fishing Zone Division +wao.ui.contacts.immatriculation=Boat Immatriculation +wao.ui.contacts.observations=Mammals +wao.ui.contacts.observers=Main observer wao.ui.contacts.title=%s contacts found wao.ui.contacts.validation=Validation +wao.ui.contacts.validation.failure=An error occurs %s +wao.ui.contacts.validation.failure.not.updatable=You can not modify this contact\: %s +wao.ui.contacts.validation.failure.not.valid=Contact is not valid\: %s +wao.ui.contacts.validation.to.accept.state.success=Contact was accepted successful +wao.ui.contacts.validation.to.reject.state.success=Contact was rejected successful +wao.ui.contacts.validation.to.unvalidate.state.success=Contact was unvalidated successful wao.ui.disclaimer=The website "SUIVI DU REALISE DU PLAN D'ECHANTILLONNAGE DES OBSERVATIONS A LA MER" is declared to the CNIL with the number \: 1414476 wao.ui.disclaimer.boats=Data your provide remains property of your company.Outside your company, only an administrator may access to your data for maintenance purpose. The administrator is someone from Ifremer. wao.ui.email=e-mail address @@ -161,30 +179,30 @@ wao.ui.field.Company.name=Name wao.ui.field.Company.phoneNumber=Phone number wao.ui.field.Company.postalCode=Post code -wao.ui.field.Contact.beginDate=Observation start +wao.ui.field.Contact.beginDate=Observation Begin Date wao.ui.field.Contact.boat=Boat -wao.ui.field.Contact.comment=Observer comment -wao.ui.field.Contact.commentAdmin=Program comment -wao.ui.field.Contact.commentCompany=Company Comment +wao.ui.field.Contact.comment=Comment +wao.ui.field.Contact.commentAdmin=Comment Admin +wao.ui.field.Contact.commentCompany=Comment Coordinator wao.ui.field.Contact.commentCoordinator=Coordinator comment wao.ui.field.Contact.completeSampling=Complete sampling -wao.ui.field.Contact.contactState=Contact state -wao.ui.field.Contact.contactStateMotif=Refusal motif +wao.ui.field.Contact.contactState=State +wao.ui.field.Contact.contactStateMotif=Contact State Motif wao.ui.field.Contact.contactStateMotifs=Refusal motives -wao.ui.field.Contact.creationDate=Contact creation date +wao.ui.field.Contact.creationDate=Creation date wao.ui.field.Contact.dataInputDate=Data input date -wao.ui.field.Contact.dataReliability=Data reliability -wao.ui.field.Contact.endDate=Observation end +wao.ui.field.Contact.dataReliability=Data Reliability +wao.ui.field.Contact.endDate=Observation Begin Date wao.ui.field.Contact.landingDate=Landing date and time wao.ui.field.Contact.mainObserver=Main observer wao.ui.field.Contact.mammalsCapture=Accidental capture wao.ui.field.Contact.mammalsInfo=Scientific names and number of captured species wao.ui.field.Contact.mammalsObservation=Exceptional observation -wao.ui.field.Contact.nbObservants=Observers number +wao.ui.field.Contact.nbObservants=Nb Observants wao.ui.field.Contact.obsDebCode=Profession wao.ui.field.Contact.observationType=Observation type -wao.ui.field.Contact.observedDataControl=Observed data control -wao.ui.field.Contact.restitution=Restitution forwarding date +wao.ui.field.Contact.observedDataControl=Observed Data control +wao.ui.field.Contact.restitution=Restitution wao.ui.field.Contact.sampleRow=Sample row wao.ui.field.Contact.samplingStrategy=Sampling strategy followed wao.ui.field.Contact.secondaryObservers=Observers @@ -193,7 +211,6 @@ wao.ui.field.Contact.validationProgram=Program validation wao.ui.field.FishingZone.facadeName=Facade wao.ui.field.FishingZone.sectorName=Sector -wao.ui.field.Profression.libelle=Libellé métier wao.ui.field.SampleRow.appliedCoverageRate=Applied coverage rate wao.ui.field.SampleRow.averageTideTime=Average tide time wao.ui.field.SampleRow.boat=Boat @@ -305,6 +322,7 @@ wao.ui.form.repeatPassword=Repeat password wao.ui.form.roles=Roles wao.ui.form.sortByTideBegin=Sort by observation begin date +wao.ui.form.updateContactCommand.success=Modifications about contact successfully saved wao.ui.form.updateSampleRowCommand.success=Modifications about sample row %s successfully saved wao.ui.form.updateWaoUserCommand.admin=Administrator wao.ui.form.updateWaoUserCommand.adminReadOnly=Administrator (read-only) @@ -487,3 +505,4 @@ wao.ui.userList=Users list wao.ui.userMustAcceptCgu=You must accept the terms of use wao.ui.validLogin=Valid identifier +wao.ui.validation.validation.contacts.failure.not.valid=Could not validate contact\: %s Modified: trunk/wao-web/src/main/resources/i18n/wao-web_fr_FR.properties =================================================================== --- trunk/wao-web/src/main/resources/i18n/wao-web_fr_FR.properties 2014-04-06 10:01:28 UTC (rev 1845) +++ trunk/wao-web/src/main/resources/i18n/wao-web_fr_FR.properties 2014-04-06 17:00:34 UTC (rev 1846) @@ -40,6 +40,8 @@ wao.ui.action.deleteCompany.success=La société a bien été supprimée wao.ui.action.deleteContact=Supprimer le contact wao.ui.action.deleteContact.confirm=Êtes-vous sûr de vouloir supprimer définitivement ce contact ? +wao.ui.action.deleteContact.failure=La suppression du contact a échoué +wao.ui.action.deleteContact.success=Le contact a bien été supprimé wao.ui.action.deleteNews=Supprimer la nouvelle wao.ui.action.deleteNews.confirm=Êtes-vous sûr de vouloir supprimer définitivement cette nouvelle ? wao.ui.action.deleteSampleRow=Supprimer la ligne du plan @@ -51,6 +53,7 @@ wao.ui.action.deleteWaoUser.failure=La suppression de l'utilisateur a échoué wao.ui.action.deleteWaoUser.success=L'utilisateur a bien été supprimé wao.ui.action.edit=Modifier +wao.ui.action.editOrDeleteContact=Modifier ou supprimer le contact wao.ui.action.editOrDeleteSampleRow=Modifier ou supprimer la ligne wao.ui.action.enlargeView=Agrandir la vue wao.ui.action.exportBoats=Exporter les $s navires avec leurs informations privées @@ -110,15 +113,30 @@ wao.ui.chart.numberObservations=Nb observations wao.ui.chart.numberOfBoatsWithBoardings=Nombre de navires avec x embarquements wao.ui.chooseUserProfile=Choisissez votre rôle +wao.ui.contact.creation=Création d'u contact +wao.ui.contact.edition=Modification du contact %s wao.ui.contact.lastContact=Dernière observation concernant ce navire pour votre société (tous programmes confondus) +wao.ui.contacts.FishingZone.facadeName=Façade +wao.ui.contacts.FishingZone.sectorName=Zone +wao.ui.contacts.Profession.libelle=Libellé métier +wao.ui.contacts.Profession.species=Espèces cibles +wao.ui.contacts.boatName=Navire wao.ui.contacts.createFromBoat=Créer un nouveau contact pour ce navire et cette ligne du plan wao.ui.contacts.createFromBoat.fail=Création d'un nouveau contact impossible wao.ui.contacts.createFromBoat.warn=Attention \: cette ligne du plan est arrivée à échéance, êtes-vous sûr de vouloir créer un nouveau contact ? +wao.ui.contacts.district=CQ wao.ui.contacts.division=Division +wao.ui.contacts.immatriculation=N° wao.ui.contacts.observations=Observations et captures accidentelles wao.ui.contacts.observers=Observateurs wao.ui.contacts.title=%s contacts trouvés -wao.ui.contacts.validation=Validation +wao.ui.contacts.validation=Validations +wao.ui.contacts.validation.failure=Une erreur est survenue %s +wao.ui.contacts.validation.failure.not.updatable=Vous n'avez pas les droits pour modifier ce contact \: %s +wao.ui.contacts.validation.failure.not.valid=Le contact n'a pas pu être validé pour la raison suivante \: %s +wao.ui.contacts.validation.to.accept.state.success=Le contact a été accepté avec succès +wao.ui.contacts.validation.to.reject.state.success=Le contact a été rejeté avec succès +wao.ui.contacts.validation.to.unvalidate.state.success=Le contact a été invalidé avec succès wao.ui.disclaimer=Le site de « SUIVI DU REALISE DU PLAN D'ECHANTILLONNAGE DES OBSERVATIONS A LA MER » a fait l'objet d'une déclaration à la CNIL sous le numéro suivant \: 1414476 wao.ui.disclaimer.boats=Les données saisies dans cette page sont la propriété exclusive de la société. En dehors de la société, seul l'administrateur peut les consulter pour des questions de maintenance sur le site. L'administrateur est une personne de l'Ifremer. wao.ui.email=Adresse e-mail @@ -161,26 +179,26 @@ wao.ui.field.Company.name=Nom wao.ui.field.Company.phoneNumber=N° de téléphone wao.ui.field.Company.postalCode=Code postal -wao.ui.field.Contact.beginDate=Début d'observation +wao.ui.field.Contact.beginDate=Début de l'observation wao.ui.field.Contact.boat=Navire wao.ui.field.Contact.comment=Commentaire observateur wao.ui.field.Contact.commentAdmin=Commentaire programme wao.ui.field.Contact.commentCompany=Commentaire société wao.ui.field.Contact.commentCoordinator=Commentaire coordinateur wao.ui.field.Contact.completeSampling=Échantillonnage complet -wao.ui.field.Contact.contactState=État du contact -wao.ui.field.Contact.contactStateMotif=Motif du refus +wao.ui.field.Contact.contactState=État +wao.ui.field.Contact.contactStateMotif=Motif de refus wao.ui.field.Contact.contactStateMotifs=Motifs de refus -wao.ui.field.Contact.creationDate=Date de création du contact -wao.ui.field.Contact.dataInputDate=Saisie des données -wao.ui.field.Contact.dataReliability=Qualité des données -wao.ui.field.Contact.endDate=Fin d'observation +wao.ui.field.Contact.creationDate=Création +wao.ui.field.Contact.dataInputDate=Saisie des données observées +wao.ui.field.Contact.dataReliability=Qualité de la donnée +wao.ui.field.Contact.endDate=Fin de l'observation wao.ui.field.Contact.landingDate=Date et heure de débarquement wao.ui.field.Contact.mainObserver=Observateur référent wao.ui.field.Contact.mammalsCapture=Capture accidentelle wao.ui.field.Contact.mammalsInfo=Noms scientifiques et nombres d'individus des espèces capturées wao.ui.field.Contact.mammalsObservation=Observation exceptionnelle -wao.ui.field.Contact.nbObservants=Nombre d'observateurs +wao.ui.field.Contact.nbObservants=Nb obs. wao.ui.field.Contact.obsDebCode=Métier wao.ui.field.Contact.observationType=Type d'observation wao.ui.field.Contact.observedDataControl=Contrôle des données observées @@ -193,7 +211,6 @@ wao.ui.field.Contact.validationProgram=Validation programme wao.ui.field.FishingZone.facadeName=Façade wao.ui.field.FishingZone.sectorName=Zone -wao.ui.field.Profression.libelle=Libellé métier wao.ui.field.SampleRow.appliedCoverageRate=Taux de couverture appliqué wao.ui.field.SampleRow.averageTideTime=Durée moyenne d'une marée wao.ui.field.SampleRow.boat=Navire @@ -305,6 +322,7 @@ wao.ui.form.repeatPassword=Répéter le mot de passe wao.ui.form.roles=Rôles wao.ui.form.sortByTideBegin=Trier par date de début d'observation (du plus récent au plus ancien) +wao.ui.form.updateContactCommand.success=Les informations concernant le contact ont bien été enregistrées wao.ui.form.updateSampleRowCommand.success=Les informations concernant la ligne %s ont bien été enregistrées wao.ui.form.updateWaoUserCommand.admin=Administrateur wao.ui.form.updateWaoUserCommand.adminReadOnly=Administrateur (lecture seule) Modified: trunk/wao-web/src/main/webapp/WEB-INF/content/obsmer/contacts.jsp =================================================================== --- trunk/wao-web/src/main/webapp/WEB-INF/content/obsmer/contacts.jsp 2014-04-06 10:01:28 UTC (rev 1845) +++ trunk/wao-web/src/main/webapp/WEB-INF/content/obsmer/contacts.jsp 2014-04-06 17:00:34 UTC (rev 1846) @@ -44,6 +44,26 @@ contactsFilterController.reset(); }); + $('.validation-action').click(function() { + var $action = $(this); + var url = $action.attr('data'); + var successCallback = function (data) { + var succesful = data['successful']; + + if (!succesful) { + var error = data['errorMessage']; + WAO.notifications.error(error); + } else { + var success = data['successMessage']; + WAO.notifications.success(success); + //TODO Update line and data actions + } + }; + WAO.get(url, null, successCallback); + }); + + // Do not expose any struts internal input fields + $('input[type="hidden"][id^="__"]').prop('disabled', true); }); </script> @@ -71,7 +91,7 @@ <fieldset> <s:select name="filter.boatFilter.boatIds" - label="%{getText('wao.ui.field.Boat.name')}" + label="%{getText('wao.ui.contacts.boatName')}" list="filterValues.boatNames" listKey="value" listValue="label" @@ -116,7 +136,7 @@ listKey="value" listValue="label" multiple="true" - dataBinding="programNames"/> + dataBinding="sampleRowsFilterValues.programNames"/> </fieldset> @@ -211,7 +231,6 @@ <s:checkbox name="filter.mammalsCaptureOnly" label="%{getText('wao.ui.field.Contact.mammalsCapture')}"/> - <br/> <s:checkbox name="filter.commentDefinedOnly" label="%{getText('wao.ui.field.Contact.comment')}"/> @@ -318,19 +337,19 @@ <thead> <tr> <th><s:text name="wao.ui.field.Contact.creationDate"/></th> - <th class="only-in-full-view"><s:text name="wao.ui.contacts.observers"/></th> + <th><s:text name="wao.ui.contacts.observers"/></th> <th class="only-in-full-view"><s:text name="wao.ui.field.SampleRow.company"/></th> <th><s:text name="wao.ui.field.Contact.sampleRow"/></th> <th class="only-in-full-view"><s:text name="wao.ui.field.SampleRow.programName"/></th> <th class="only-in-full-view"><s:text name="wao.ui.field.SampleRow.professionCode"/></th> - <th class="only-in-full-view"><s:text name="wao.ui.field.Profression.libelle"/></th> - <th class="only-in-full-view"><s:text name="wao.ui.field.SampleRow.species"/></th> - <th class="only-in-full-view"><s:text name="wao.ui.field.FishingZone.facadeName"/></th> - <th class="only-in-full-view"><s:text name="wao.ui.field.FishingZone.sectorName"/></th> + <th class="only-in-full-view"><s:text name="wao.ui.contacts.Profession.libelle"/></th> + <th class="only-in-full-view"><s:text name="wao.ui.contacts.Profession.species"/></th> + <th class="only-in-full-view"><s:text name="wao.ui.contacts.FishingZone.facadeName"/></th> + <th class="only-in-full-view"><s:text name="wao.ui.contacts.FishingZone.sectorName"/></th> <th class="only-in-full-view"><s:text name="wao.ui.contacts.division"/></th> - <th class="only-in-full-view"><s:text name="wao.ui.field.Boat.name"/></th> - <th class="only-in-full-view"><s:text name="wao.ui.field.Boat.immatriculation"/></th> - <th class="only-in-full-view"><s:text name="wao.ui.field.Boat.district"/></th> + <th><s:text name="wao.ui.contacts.boatName"/></th> + <th class="only-in-full-view"><s:text name="wao.ui.contacts.immatriculation"/></th> + <th class="only-in-full-view"><s:text name="wao.ui.contacts.district"/></th> <th><s:text name="wao.ui.field.Contact.contactState"/></th> <th><s:text name="wao.ui.field.Contact.contactStateMotif"/></th> <th><s:text name="wao.ui.field.Contact.beginDate"/></th> @@ -355,7 +374,7 @@ <td> <s:property value="%{formatDate(creationDate)}"/> </td> -<td class="only-in-full-view"> +<td> <s:if test="secondaryObserversEmpty"> <s:property value="mainObserver.fullName"/> </s:if> @@ -504,53 +523,43 @@ <b class="caret"></b> </a> <ul class="dropdown-menu"> - <s:if test="authenticatedWaoUser.isAuthorizedToEditContact(#contact)"> + <s:if test="authenticatedWaoUser.isAuthorizedToEditContact(#contact) || authenticatedWaoUser.isAuthorizedToDeleteContact(#contact)"> <li> <s:url action="edit-contact!input" id="editContactUrl"> <s:param name="contactId" value="topiaId"/> </s:url> <s:a href="%{editContactUrl}"> - <i class="icon-edit"></i> <s:text name="wao.ui.action.edit"/> + <i class="icon-edit"></i> <s:text name="wao.ui.action.editOrDeleteContact"/> </s:a> </li> </s:if> - <s:if test="authenticatedWaoUser.isAuthorizedToDeleteContact(#contact)"> - <li> - <s:url action="delete-contact!input" id="deleteContactUrl"> - <s:param name="contactId" value="topiaId"/> - </s:url> - <s:a href="%{deleteContactUrl}"> - <i class="icon-delete"></i> <s:text name="wao.ui.action.delete"/> - </s:a> - </li> - </s:if> <s:if test="authenticatedWaoUser.authorizedToValidateContacts"> <s:if test="authenticatedWaoUser.isAuthorizedToValidateContact(#contact)"> <li> - <s:url action="validate-contact!input" id="acceptContactUrl"> + <s:url action="validate-contact-json" id="acceptContactUrl" escapeAmp="false"> <s:param name="contactId" value="topiaId"/> - <s:param name="validateState" value="true"/> + <s:param name="validationState">true</s:param> </s:url> - <s:a href="%{acceptContactUrl}"> + <s:a cssClass='validation-action' href="#notifications" data="%{acceptContactUrl}"> <s:text name="wao.ui.action.acceptContact"/> </s:a> </li> <li> - <s:url action="validate-contact!input" id="refuseContactUrl"> + <s:url action="validate-contact-json" id="refuseContactUrl" escapeAmp="false"> <s:param name="contactId" value="topiaId"/> - <s:param name="validateState" value="false"/> + <s:param name="validationState">false</s:param> </s:url> - <s:a href="%{refuseContactUrl}"> + <s:a cssClass='validation-action' href="#notifications" data="%{refuseContactUrl}"> <s:text name="wao.ui.action.refuseContact"/> </s:a> </li> </s:if> <s:if test="authenticatedWaoUser.isAuthorizedToUnvalidateContact(#contact)"> <li> - <s:url action="validate-contact!input" id="unvalidateContactUrl"> + <s:url action="validate-contact-json" id="unvalidateContactUrl"> <s:param name="contactId" value="topiaId"/> </s:url> - <s:a href="%{unvalidateContactUrl}"> + <s:a cssClass='validation-action' href="#notifications" data="%{unvalidateContactUrl}"> <s:text name="wao.ui.action.unvalidateContact"/> </s:a> </li> Added: trunk/wao-web/src/main/webapp/WEB-INF/content/obsmer/edit-contact-input.jsp =================================================================== --- trunk/wao-web/src/main/webapp/WEB-INF/content/obsmer/edit-contact-input.jsp (rev 0) +++ trunk/wao-web/src/main/webapp/WEB-INF/content/obsmer/edit-contact-input.jsp 2014-04-06 17:00:34 UTC (rev 1846) @@ -0,0 +1,112 @@ +<%-- + #%L + Wao :: Web + %% + Copyright (C) 2009 - 2014 Ifremer + %% + 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 language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@taglib uri="/struts-tags" prefix="s" %> + +<html> +<head> + <title> + <s:if test="updateContactCommand.creation"> + <s:text name="wao.ui.sampleRow.creation" /> + </s:if> + <s:else> + <s:text name="wao.ui.contact.edition"> + <s:param value="updateContactCommand.contact.mainObserver.fullName"/> + </s:text> + </s:else> + </title> + <script> + + $(document).ready(function() { + + }); + + </script> +</head> + + +<h1> + <s:if test="updateContactCommand.creation"> + <s:text name="wao.ui.contact.creation" /> + </s:if> + <s:else> + <s:text name="wao.ui.contact.edition"> + <s:param value="updateContactCommand.contact.mainObserver.fullName"/> + </s:text> + </s:else> +</h1> + +<s:if test="updateContactCommand.observationAlreadyStarted"> + <div class="alert"> + <s:text name="wao.ui.form.SampleRow.warn.observationAlreadyStarted" /> + </div> +</s:if> + +<s:form> + + <s:hidden name="sampleRowId" value="%{sampleRowId}" /> + + <fieldset> + + <legend><s:text name="wao.ui.field.SampleRow.profession" /></legend> + + + </fieldset> + + <s:if test=" ! updateContactCommand.creation"> + + <fieldset> + + <legend><s:text name="wao.ui.form.editComment" /></legend> + + <s:text name="wao.ui.form.editionAuthor" /> <s:property value="updateContactCommand.sampleRowLog.author.fullName" /> + + <s:textarea name="updateContactCommand.contact.comment" label="%{getText('wao.ui.form.editComment')}" requiredLabel="true" /> + + </fieldset> + + </s:if> + + <div class="form-actions"> + <s:url action="contacts" id="contactsUrl" /> + <s:a href="%{contactsUrl}" cssClass="btn"> + <i class="icon-chevron-left"></i> <s:text name="wao.ui.action.cancel" /> + </s:a> + <s:if test=" authenticatedWaoUser.isAuthorizedToEditContact(updateContactCommand.contact)"> + <s:submit type="button" cssClass="btn"> + <i class="icon-hdd"></i> <s:text name="wao.ui.action.save" /> + </s:submit> + </s:if> + + <s:if test=" ! updateContactCommand.creation && authenticatedWaoUser.isAuthorizedToDeleteContact(updateContactCommand.contact)"> + <s:url action="delete-contact" id="deleteContactUrl"> + <s:param name="contactId" value="contactId" /> + </s:url> + <s:a href="%{deleteContactUrl}" cssClass="btn pull-right"> + <i class="icon-trash"></i> <s:text name="wao.ui.action.deleteContact" /> + </s:a> + </s:if> + </div> + +</s:form> + +</html> + Property changes on: trunk/wao-web/src/main/webapp/WEB-INF/content/obsmer/edit-contact-input.jsp ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/wao-web/src/main/webapp/WEB-INF/decorators/layout.jsp =================================================================== --- trunk/wao-web/src/main/webapp/WEB-INF/decorators/layout.jsp 2014-04-06 10:01:28 UTC (rev 1845) +++ trunk/wao-web/src/main/webapp/WEB-INF/decorators/layout.jsp 2014-04-06 17:00:34 UTC (rev 1846) @@ -178,7 +178,7 @@ <s:actionerror theme="bootstrap" /> <s:actionmessage theme="bootstrap" /> <s:fielderror theme="bootstrap" /> - <div id="notifications"></div> + <div id="notifications"><a href="#notifications"></a></div> <decorator:body /> </main> @@ -194,13 +194,13 @@ <%@include file="version.jsp" %> </a> </li> - <t:if test="obsMer"> + <s:if test="obsMer"> <li> <a href="mailto:harmonie@ifremer.fr" title="Contacter un responsable Obsmer"> Obsmer </a> </li> - </t:if> + </s:if> <li> <a href="http://sih.ifremer.fr/" title="Page d'accueil du SIH" target="_blank"> Ifremer SIH Modified: trunk/wao-web/src/main/webapp/bootstrap-2.3.1/bootstrap-popover.js =================================================================== --- trunk/wao-web/src/main/webapp/bootstrap-2.3.1/bootstrap-popover.js 2014-04-06 10:01:28 UTC (rev 1845) +++ trunk/wao-web/src/main/webapp/bootstrap-2.3.1/bootstrap-popover.js 2014-04-06 17:00:34 UTC (rev 1846) @@ -1,5 +1,5 @@ /* =========================================================== - * bootstrap-popover.js v2.3.1 + * bootstrap-popover.js v2.3.1 %%Ignore-License * http://twitter.github.com/bootstrap/javascript.html#popovers * =========================================================== * Copyright 2012 Twitter, Inc.
participants (1)
-
tchemit@users.forge.codelutin.com