SEBSERV-160 fixed "In Use" for selection
This commit is contained in:
		
							parent
							
								
									8b9eebfe5b
								
							
						
					
					
						commit
						6396afa53b
					
				
					 7 changed files with 65 additions and 9 deletions
				
			
		|  | @ -26,12 +26,15 @@ import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM_CONFIGURATION_MAP; | import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM_CONFIGURATION_MAP; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.Entity; | import ch.ethz.seb.sebserver.gbl.model.Entity; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.GrantEntity; | import ch.ethz.seb.sebserver.gbl.model.GrantEntity; | ||||||
|  | import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType; | import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus; | import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus; | ||||||
| 
 | 
 | ||||||
| @JsonIgnoreProperties(ignoreUnknown = true) | @JsonIgnoreProperties(ignoreUnknown = true) | ||||||
| public final class ExamConfigurationMap implements GrantEntity { | public final class ExamConfigurationMap implements GrantEntity { | ||||||
| 
 | 
 | ||||||
|  |     private static final String ARR_EXAM_STATUS = "examStatus"; | ||||||
|  | 
 | ||||||
|     public static final String ATTR_CONFIRM_ENCRYPT_SECRET = "confirm_encrypt_secret"; |     public static final String ATTR_CONFIRM_ENCRYPT_SECRET = "confirm_encrypt_secret"; | ||||||
| 
 | 
 | ||||||
|     public static final String FILTER_ATTR_EXAM_ID = "examId"; |     public static final String FILTER_ATTR_EXAM_ID = "examId"; | ||||||
|  | @ -60,6 +63,9 @@ public final class ExamConfigurationMap implements GrantEntity { | ||||||
|     @JsonProperty(EXAM.ATTR_TYPE) |     @JsonProperty(EXAM.ATTR_TYPE) | ||||||
|     public final ExamType examType; |     public final ExamType examType; | ||||||
| 
 | 
 | ||||||
|  |     @JsonProperty(ARR_EXAM_STATUS) | ||||||
|  |     public final ExamStatus examStatus; | ||||||
|  | 
 | ||||||
|     @NotNull(message = "examConfigurationMap:configurationNodeId:notNull") |     @NotNull(message = "examConfigurationMap:configurationNodeId:notNull") | ||||||
|     @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID) |     @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID) | ||||||
|     public final Long configurationNodeId; |     public final Long configurationNodeId; | ||||||
|  | @ -91,6 +97,7 @@ public final class ExamConfigurationMap implements GrantEntity { | ||||||
|             @JsonProperty(QuizData.QUIZ_ATTR_DESCRIPTION) final String examDescription, |             @JsonProperty(QuizData.QUIZ_ATTR_DESCRIPTION) final String examDescription, | ||||||
|             @JsonProperty(QuizData.QUIZ_ATTR_START_TIME) final DateTime examStartTime, |             @JsonProperty(QuizData.QUIZ_ATTR_START_TIME) final DateTime examStartTime, | ||||||
|             @JsonProperty(EXAM.ATTR_TYPE) final ExamType examType, |             @JsonProperty(EXAM.ATTR_TYPE) final ExamType examType, | ||||||
|  |             @JsonProperty(ARR_EXAM_STATUS) final ExamStatus examStatus, | ||||||
|             @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID) final Long configurationNodeId, |             @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID) final Long configurationNodeId, | ||||||
|             @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_USER_NAMES) final String userNames, |             @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_USER_NAMES) final String userNames, | ||||||
|             @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_ENCRYPT_SECRET) final CharSequence encryptSecret, |             @JsonProperty(EXAM_CONFIGURATION_MAP.ATTR_ENCRYPT_SECRET) final CharSequence encryptSecret, | ||||||
|  | @ -106,6 +113,7 @@ public final class ExamConfigurationMap implements GrantEntity { | ||||||
|         this.examDescription = examDescription; |         this.examDescription = examDescription; | ||||||
|         this.examStartTime = examStartTime; |         this.examStartTime = examStartTime; | ||||||
|         this.examType = examType; |         this.examType = examType; | ||||||
|  |         this.examStatus = examStatus; | ||||||
|         this.configurationNodeId = configurationNodeId; |         this.configurationNodeId = configurationNodeId; | ||||||
|         this.userNames = userNames; |         this.userNames = userNames; | ||||||
|         this.encryptSecret = encryptSecret; |         this.encryptSecret = encryptSecret; | ||||||
|  | @ -125,6 +133,7 @@ public final class ExamConfigurationMap implements GrantEntity { | ||||||
|         this.examDescription = postParams.getString(QuizData.QUIZ_ATTR_DESCRIPTION); |         this.examDescription = postParams.getString(QuizData.QUIZ_ATTR_DESCRIPTION); | ||||||
|         this.examStartTime = postParams.getDateTime(QuizData.QUIZ_ATTR_START_TIME); |         this.examStartTime = postParams.getDateTime(QuizData.QUIZ_ATTR_START_TIME); | ||||||
|         this.examType = postParams.getEnum(EXAM.ATTR_TYPE, ExamType.class); |         this.examType = postParams.getEnum(EXAM.ATTR_TYPE, ExamType.class); | ||||||
|  |         this.examStatus = postParams.getEnum(ARR_EXAM_STATUS, ExamStatus.class); | ||||||
| 
 | 
 | ||||||
|         this.configurationNodeId = postParams.getLong(Domain.EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID); |         this.configurationNodeId = postParams.getLong(Domain.EXAM_CONFIGURATION_MAP.ATTR_CONFIGURATION_NODE_ID); | ||||||
|         this.userNames = postParams.getString(Domain.EXAM_CONFIGURATION_MAP.ATTR_USER_NAMES); |         this.userNames = postParams.getString(Domain.EXAM_CONFIGURATION_MAP.ATTR_USER_NAMES); | ||||||
|  | @ -149,6 +158,7 @@ public final class ExamConfigurationMap implements GrantEntity { | ||||||
|         this.examDescription = null; |         this.examDescription = null; | ||||||
|         this.examStartTime = null; |         this.examStartTime = null; | ||||||
|         this.examType = null; |         this.examType = null; | ||||||
|  |         this.examStatus = null; | ||||||
|         this.configurationNodeId = configurationNodeId; |         this.configurationNodeId = configurationNodeId; | ||||||
|         this.userNames = userNames; |         this.userNames = userNames; | ||||||
|         this.encryptSecret = null; |         this.encryptSecret = null; | ||||||
|  | @ -205,6 +215,10 @@ public final class ExamConfigurationMap implements GrantEntity { | ||||||
|         return this.examType; |         return this.examType; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public ExamStatus getExamStatus() { | ||||||
|  |         return this.examStatus; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public Long getConfigurationNodeId() { |     public Long getConfigurationNodeId() { | ||||||
|         return this.configurationNodeId; |         return this.configurationNodeId; | ||||||
|     } |     } | ||||||
|  | @ -250,6 +264,7 @@ public final class ExamConfigurationMap implements GrantEntity { | ||||||
|                 this.examDescription, |                 this.examDescription, | ||||||
|                 this.examStartTime, |                 this.examStartTime, | ||||||
|                 this.examType, |                 this.examType, | ||||||
|  |                 this.examStatus, | ||||||
|                 this.configurationNodeId, |                 this.configurationNodeId, | ||||||
|                 this.userNames, |                 this.userNames, | ||||||
|                 Constants.EMPTY_NOTE, |                 Constants.EMPTY_NOTE, | ||||||
|  | @ -296,7 +311,7 @@ public final class ExamConfigurationMap implements GrantEntity { | ||||||
| 
 | 
 | ||||||
|     public static ExamConfigurationMap createNew(final Exam exam) { |     public static ExamConfigurationMap createNew(final Exam exam) { | ||||||
|         return new ExamConfigurationMap( |         return new ExamConfigurationMap( | ||||||
|                 null, exam.institutionId, exam.id, exam.name, exam.description, exam.startTime, exam.type, |                 null, exam.institutionId, exam.id, exam.name, exam.description, exam.startTime, exam.type, exam.status, | ||||||
|                 null, null, null, null, null, null, null); |                 null, null, null, null, null, null, null); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -87,7 +87,7 @@ public class SEBExamConfigBatchStateChangePopup extends AbstractBatchActionWizar | ||||||
|                 FORM_STATUS_TEXT_KEY, |                 FORM_STATUS_TEXT_KEY, | ||||||
|                 targetStateName, |                 targetStateName, | ||||||
|                 () -> this.pageService.getResourceService() |                 () -> this.pageService.getResourceService() | ||||||
|                         .examConfigStatusResources(false)) |                         .examConfigStatusResourcesAll()) | ||||||
|                 .readonly(readonly)); |                 .readonly(readonly)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.Domain; | import ch.ethz.seb.sebserver.gbl.model.Domain; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.EntityKey; | import ch.ethz.seb.sebserver.gbl.model.EntityKey; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport; | import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport; | ||||||
|  | import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap; | import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; | import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigKey; | import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigKey; | ||||||
|  | @ -173,6 +174,16 @@ public class SEBExamConfigForm implements TemplateComposer { | ||||||
|                 .call() |                 .call() | ||||||
|                 .map(names -> names != null && !names.isEmpty()) |                 .map(names -> names != null && !names.isEmpty()) | ||||||
|                 .getOr(Boolean.FALSE); |                 .getOr(Boolean.FALSE); | ||||||
|  |         final boolean hasRunningExam = isAttachedToExam && this.restService | ||||||
|  |                 .getBuilder(GetExamConfigMappingsPage.class) | ||||||
|  |                 .withQueryParam(ExamConfigurationMap.FILTER_ATTR_CONFIG_ID, examConfig.getModelId()) | ||||||
|  |                 .call() | ||||||
|  |                 .map(res -> res.content | ||||||
|  |                         .stream() | ||||||
|  |                         .filter(map -> map.examStatus == ExamStatus.RUNNING) | ||||||
|  |                         .findAny() | ||||||
|  |                         .isPresent()) | ||||||
|  |                 .getOr(false); | ||||||
| 
 | 
 | ||||||
|         // new PageContext with actual EntityKey |         // new PageContext with actual EntityKey | ||||||
|         final PageContext formContext = pageContext.withEntityKey(examConfig.getEntityKey()); |         final PageContext formContext = pageContext.withEntityKey(examConfig.getEntityKey()); | ||||||
|  | @ -223,7 +234,7 @@ public class SEBExamConfigForm implements TemplateComposer { | ||||||
|                         Domain.CONFIGURATION_NODE.ATTR_STATUS, |                         Domain.CONFIGURATION_NODE.ATTR_STATUS, | ||||||
|                         FORM_STATUS_TEXT_KEY, |                         FORM_STATUS_TEXT_KEY, | ||||||
|                         examConfig.status.name(), |                         examConfig.status.name(), | ||||||
|                         () -> resourceService.examConfigStatusResources(isAttachedToExam)) |                         () -> resourceService.examConfigStatusResources(isAttachedToExam, hasRunningExam)) | ||||||
|                         .withEmptyCellSeparation(!isReadonly)) |                         .withEmptyCellSeparation(!isReadonly)) | ||||||
|                 .buildFor((isNew) |                 .buildFor((isNew) | ||||||
|                         ? this.restService.getRestCall(NewExamConfig.class) |                         ? this.restService.getRestCall(NewExamConfig.class) | ||||||
|  | @ -297,7 +308,7 @@ public class SEBExamConfigForm implements TemplateComposer { | ||||||
|                 .withEntityKey(entityKey) |                 .withEntityKey(entityKey) | ||||||
|                 .withExec(formHandle::processFormSave) |                 .withExec(formHandle::processFormSave) | ||||||
|                 .ignoreMoveAwayFromEdit() |                 .ignoreMoveAwayFromEdit() | ||||||
|                 .withConfirm(() -> stateChangeConfirm(isAttachedToExam, formHandle)) |                 .withConfirm(() -> stateChangeConfirm(hasRunningExam, formHandle)) | ||||||
|                 .publishIf(() -> !isReadonly) |                 .publishIf(() -> !isReadonly) | ||||||
| 
 | 
 | ||||||
|                 .newAction(ActionDefinition.SEB_EXAM_CONFIG_PROP_CANCEL_MODIFY) |                 .newAction(ActionDefinition.SEB_EXAM_CONFIG_PROP_CANCEL_MODIFY) | ||||||
|  | @ -436,17 +447,17 @@ public class SEBExamConfigForm implements TemplateComposer { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private LocTextKey stateChangeConfirm( |     private LocTextKey stateChangeConfirm( | ||||||
|             final boolean isAttachedToExam, |             final boolean hasRunningExam, | ||||||
|             final FormHandle<ConfigurationNode> formHandle) { |             final FormHandle<ConfigurationNode> formHandle) { | ||||||
| 
 | 
 | ||||||
|         if (isAttachedToExam) { |         if (hasRunningExam) { | ||||||
|             final String fieldValue = formHandle |             final String fieldValue = formHandle | ||||||
|                     .getForm() |                     .getForm() | ||||||
|                     .getFieldValue(Domain.CONFIGURATION_NODE.ATTR_STATUS); |                     .getFieldValue(Domain.CONFIGURATION_NODE.ATTR_STATUS); | ||||||
| 
 | 
 | ||||||
|             if (fieldValue != null) { |             if (fieldValue != null) { | ||||||
|                 final ConfigurationStatus state = ConfigurationStatus.valueOf(fieldValue); |                 final ConfigurationStatus state = ConfigurationStatus.valueOf(fieldValue); | ||||||
|                 if (state != ConfigurationStatus.IN_USE) { |                 if (state != ConfigurationStatus.IN_USE && state != ConfigurationStatus.ARCHIVED) { | ||||||
|                     return SAVE_CONFIRM_STATE_CHANGE_WHILE_ATTACHED; |                     return SAVE_CONFIRM_STATE_CHANGE_WHILE_ATTACHED; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -471,7 +471,20 @@ public class ResourceService { | ||||||
|                 .collect(Collectors.toList()); |                 .collect(Collectors.toList()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public List<Tuple<String>> examConfigStatusResources(final boolean isAttachedToExam) { |     public List<Tuple<String>> examConfigStatusResourcesAll() { | ||||||
|  |         return Arrays.stream(ConfigurationStatus.values()) | ||||||
|  |                 .map(type -> new Tuple3<>( | ||||||
|  |                         type.name(), | ||||||
|  |                         this.i18nSupport.getText(EXAMCONFIG_STATUS_PREFIX + type.name()), | ||||||
|  |                         Utils.formatLineBreaks(this.i18nSupport.getText( | ||||||
|  |                                 this.i18nSupport.getText(EXAMCONFIG_STATUS_PREFIX + type.name()) | ||||||
|  |                                         + Constants.TOOLTIP_TEXT_KEY_SUFFIX, | ||||||
|  |                                 StringUtils.EMPTY)))) | ||||||
|  |                 .sorted(RESOURCE_COMPARATOR) | ||||||
|  |                 .collect(Collectors.toList()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public List<Tuple<String>> examConfigStatusResources(final boolean isAttachedToExam, final boolean hasRunningExam) { | ||||||
|         return Arrays.stream(ConfigurationStatus.values()) |         return Arrays.stream(ConfigurationStatus.values()) | ||||||
|                 .filter(status -> { |                 .filter(status -> { | ||||||
|                     if (isAttachedToExam) { |                     if (isAttachedToExam) { | ||||||
|  | @ -480,6 +493,7 @@ public class ResourceService { | ||||||
|                         return status != ConfigurationStatus.IN_USE; |                         return status != ConfigurationStatus.IN_USE; | ||||||
|                     } |                     } | ||||||
|                 }) |                 }) | ||||||
|  |                 .filter(status -> !hasRunningExam || status != ConfigurationStatus.ARCHIVED) | ||||||
|                 .map(type -> new Tuple3<>( |                 .map(type -> new Tuple3<>( | ||||||
|                         type.name(), |                         type.name(), | ||||||
|                         this.i18nSupport.getText(EXAMCONFIG_STATUS_PREFIX + type.name()), |                         this.i18nSupport.getText(EXAMCONFIG_STATUS_PREFIX + type.name()), | ||||||
|  |  | ||||||
|  | @ -442,6 +442,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO { | ||||||
|                     (exam != null) ? exam.description : null, |                     (exam != null) ? exam.description : null, | ||||||
|                     (exam != null) ? exam.startTime : null, |                     (exam != null) ? exam.startTime : null, | ||||||
|                     (exam != null) ? exam.type : ExamType.UNDEFINED, |                     (exam != null) ? exam.type : ExamType.UNDEFINED, | ||||||
|  |                     (exam != null) ? exam.status : null, | ||||||
|                     record.getConfigurationNodeId(), |                     record.getConfigurationNodeId(), | ||||||
|                     record.getUserNames(), |                     record.getUserNames(), | ||||||
|                     record.getEncryptSecret(), |                     record.getEncryptSecret(), | ||||||
|  |  | ||||||
|  | @ -136,6 +136,7 @@ public class ExamConfigServiceImpl implements ExamConfigService { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|     public Result<Long> getFollowupConfigurationId(final Long examConfigNodeId) { |     public Result<Long> getFollowupConfigurationId(final Long examConfigNodeId) { | ||||||
|         return this.configurationDAO.getFollowupConfigurationId(examConfigNodeId); |         return this.configurationDAO.getFollowupConfigurationId(examConfigNodeId); | ||||||
|     } |     } | ||||||
|  | @ -443,6 +444,20 @@ public class ExamConfigServiceImpl implements ExamConfigService { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |             // if changing to "In Use" check config is mapped for at least one exam | ||||||
|  |             if (configurationNode.status == ConfigurationStatus.IN_USE && | ||||||
|  |                     existingNode.status != ConfigurationStatus.IN_USE) { | ||||||
|  | 
 | ||||||
|  |                 if (this.examConfigurationMapDAO | ||||||
|  |                         .getExamIdsForConfigNodeId(configurationNode.id) | ||||||
|  |                         .getOr(Collections.emptyList()) | ||||||
|  |                         .isEmpty()) { | ||||||
|  |                     throw new APIMessageException( | ||||||
|  |                             APIMessage.ErrorMessage.INTEGRITY_VALIDATION | ||||||
|  |                                     .of("Exam configuration has no reference to any exam.")); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             return configurationNode; |             return configurationNode; | ||||||
| 
 | 
 | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|  | @ -209,7 +209,7 @@ public class ModelObjectJSONGenerator { | ||||||
|         System.out.println(writerWithDefaultPrettyPrinter.writeValueAsString(domainObject)); |         System.out.println(writerWithDefaultPrettyPrinter.writeValueAsString(domainObject)); | ||||||
| 
 | 
 | ||||||
|         domainObject = new ExamConfigurationMap( |         domainObject = new ExamConfigurationMap( | ||||||
|                 1L, 1L, 1L, "examName", "examDescription", DateTime.now(), ExamType.BYOD, |                 1L, 1L, 1L, "examName", "examDescription", DateTime.now(), ExamType.BYOD, ExamStatus.RUNNING, | ||||||
|                 1L, "userNames", "encryptSecret", "confirmEncryptSecret", "configName", "configDescription", |                 1L, "userNames", "encryptSecret", "confirmEncryptSecret", "configName", "configDescription", | ||||||
|                 ConfigurationStatus.IN_USE); |                 ConfigurationStatus.IN_USE); | ||||||
|         System.out.println(domainObject.getClass().getSimpleName() + ":"); |         System.out.println(domainObject.getClass().getSimpleName() + ":"); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 anhefti
						anhefti