NIFI-475: - Adding support to create controller services inline when editing a components properties.
NIFI-475: - Adding support to create controller services inline when editing a components properties. NIFI-475: - Prompting the user to save changes before navigating to the controller service definition. NIFI-475: - Adding support to create controller services inline when editing a components properties. NIFI-475: - Adding support to create controller services inline when editing a components properties. NIFI-475: - Prompting the user to save changes before navigating to the controller service definition. NIFI-475: - Prompting the user to save changes before navigating to the controller service definition. NIFI-475: - Prompting the user to save changes before navigating to the controller service definition. NIFI-475: - Only providing the option to go to the service if the dialog is originating from the canvas (not for instance the summary page). NIFI-475: - Removing the children from the documented types. This prevents conveying the documented type hierarchies but that isn't necessary given the support for creating instances inline when editing properties. NIFI-475: - Removing the type hierarchies from the new controller service dialog. NIFI-475: - Including the controller service description in the inline controller service dialog. Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/2154b822 Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/2154b822 Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/2154b822 Branch: refs/heads/NIFI-271 Commit: 2154b822bf32b661c80bb41d96d569ee3491a41b Parents: e456ea3 Author: Matt Gilman <matt.c.gil...@gmail.com> Authored: Mon Apr 6 16:29:07 2015 -0400 Committer: Matt Gilman <matt.c.gil...@gmail.com> Committed: Wed Apr 8 12:25:48 2015 -0400 ---------------------------------------------------------------------- .../nifi/web/api/dto/DocumentedTypeDTO.java | 14 - .../nifi/web/api/dto/PropertyDescriptorDTO.java | 9 +- .../org/apache/nifi/web/NiFiServiceFacade.java | 3 +- .../nifi/web/StandardNiFiServiceFacade.java | 4 +- .../apache/nifi/web/api/ControllerResource.java | 7 +- .../org/apache/nifi/web/api/dto/DtoFactory.java | 135 +-------- .../nifi/web/controller/ControllerFacade.java | 43 ++- .../org/apache/nifi/web/util/SnippetUtils.java | 6 +- .../src/main/webapp/css/settings.css | 15 - .../propertytable/jquery.propertytable.css | 43 +++ .../propertytable/jquery.propertytable.js | 289 +++++++++++++++++-- .../js/nf/canvas/nf-controller-service.js | 186 ++++++------ .../js/nf/canvas/nf-processor-configuration.js | 136 +++++---- .../webapp/js/nf/canvas/nf-reporting-task.js | 135 +++++---- .../src/main/webapp/js/nf/canvas/nf-settings.js | 227 ++------------- 15 files changed, 657 insertions(+), 595 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/2154b822/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java index 7cf1b84..6e4aeb9 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/DocumentedTypeDTO.java @@ -26,7 +26,6 @@ import javax.xml.bind.annotation.XmlType; public class DocumentedTypeDTO { private String type; - private Set<DocumentedTypeDTO> childTypes; private String description; private Set<String> tags; @@ -69,17 +68,4 @@ public class DocumentedTypeDTO { this.tags = tags; } - /** - * Child types for this type. - * - * @return - */ - public Set<DocumentedTypeDTO> getChildTypes() { - return childTypes; - } - - public void setChildTypes(Set<DocumentedTypeDTO> childTypes) { - this.childTypes = childTypes; - } - } http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/2154b822/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/PropertyDescriptorDTO.java ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/PropertyDescriptorDTO.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/PropertyDescriptorDTO.java index d10a324..ecde255 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/PropertyDescriptorDTO.java +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/PropertyDescriptorDTO.java @@ -34,7 +34,7 @@ public class PropertyDescriptorDTO { private boolean sensitive; private boolean dynamic; private boolean supportsEl; - private boolean identifiesControllerService; + private String identifiesControllerService; /** * The set of allowable values for this property. If empty then the @@ -158,15 +158,16 @@ public class PropertyDescriptorDTO { } /** - * Whether this descriptor represents a controller service. + * If this property identifies a controller service, this returns the + * fully qualified type, null otherwise. * * @return */ - public boolean isIdentifiesControllerService() { + public String getIdentifiesControllerService() { return identifiesControllerService; } - public void setIdentifiesControllerService(boolean identifiesControllerService) { + public void setIdentifiesControllerService(String identifiesControllerService) { this.identifiesControllerService = identifiesControllerService; } http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/2154b822/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java index e3afbf9..8d9dade 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java @@ -252,9 +252,10 @@ public interface NiFiServiceFacade { /** * Returns the list of controller service types. * + * @param serviceType Filters only service types that implement this type * @return The list of available controller types */ - Set<DocumentedTypeDTO> getControllerServiceTypes(); + Set<DocumentedTypeDTO> getControllerServiceTypes(String serviceType); /** * Returns the list of reporting task types. http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/2154b822/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java index 086c46b..88637b4 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java @@ -1718,8 +1718,8 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { } @Override - public Set<DocumentedTypeDTO> getControllerServiceTypes() { - return controllerFacade.getControllerServiceTypes(); + public Set<DocumentedTypeDTO> getControllerServiceTypes(final String serviceType) { + return controllerFacade.getControllerServiceTypes(serviceType); } @Override http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/2154b822/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java index 98f17d5..c0b4cd7 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java @@ -737,6 +737,7 @@ public class ControllerResource extends ApplicationResource { * @param clientId Optional client id. If the client id is not specified, a * new one will be generated. This value (whether specified or generated) is * included in the response. + * @param serviceType Returns only services that implement this type * @return A controllerServicesTypesEntity. */ @GET @@ -744,7 +745,9 @@ public class ControllerResource extends ApplicationResource { @Path("/controller-service-types") @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')") @TypeHint(ControllerServiceTypesEntity.class) - public Response getControllerServiceTypes(@QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId) { + public Response getControllerServiceTypes( + @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, + @QueryParam("serviceType") String serviceType) { // replicate if cluster manager if (properties.isClusterManager()) { @@ -758,7 +761,7 @@ public class ControllerResource extends ApplicationResource { // create response entity final ControllerServiceTypesEntity entity = new ControllerServiceTypesEntity(); entity.setRevision(revision); - entity.setControllerServiceTypes(serviceFacade.getControllerServiceTypes()); + entity.setControllerServiceTypes(serviceFacade.getControllerServiceTypes(serviceType)); // generate the response return clusterContext(generateOkResponse(entity)).build(); http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/2154b822/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java index 7fe76ad..4e83ac5 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java @@ -1384,135 +1384,6 @@ public final class DtoFactory { } /** - * Identifies all baseTypes for the specified type that are assignable to the specified baseType. - * - * @param baseType - * @param type - * @param baseTypes - */ - private void identifyBaseTypes(final Class baseType, final Class type, final Set<Class> baseTypes, final boolean recurse) { - final Class[] interfaces = type.getInterfaces(); - for (final Class i : interfaces) { - if (baseType.isAssignableFrom(i) && !baseType.equals(i)) { - baseTypes.add(i); - } - } - - if (recurse) { - if (type.getSuperclass() != null) { - identifyBaseTypes(baseType, type.getSuperclass(), baseTypes, recurse); - } - } - } - - /** - * Gets the DocumentedTypeDTOs from the specified classes for the specified baseClass. - * - * @param baseClass - * @param classes - * @return - */ - public Set<DocumentedTypeDTO> fromDocumentedTypes(final Class baseClass, final Set<Class> classes) { - final Set<DocumentedTypeDTO> types = new LinkedHashSet<>(); - final Set<Class> sortedClasses = new TreeSet<>(CLASS_NAME_COMPARATOR); - sortedClasses.addAll(classes); - - // identify all interfaces that extend baseClass for all classes - final Set<Class> interfaces = new HashSet<>(); - for (final Class<?> cls : sortedClasses) { - identifyBaseTypes(baseClass, cls, interfaces, true); - } - - // build a lookup of all interfaces - final Map<Class, DocumentedTypeDTO> lookup = new HashMap<>(); - - // convert the interfaces to DTO form - for (final Class<?> i : interfaces) { - final DocumentedTypeDTO type = new DocumentedTypeDTO(); - type.setType(i.getName()); - type.setDescription(getCapabilityDescription(i)); - type.setTags(getTags(i)); - type.setChildTypes(new LinkedHashSet<DocumentedTypeDTO>()); - lookup.put(i, type); - } - - // move the interfaces into the appropriate hierarchy - final Collection<Class> rootTypes = new ArrayList<>(); - for (final Class<?> i : interfaces) { - rootTypes.add(i); - - // identify the base types - final Set<Class> baseTypes = new LinkedHashSet<>(); - identifyBaseTypes(baseClass, i, baseTypes, false); - - // move this interfaces into the hierarchy where appropriate - if (!baseTypes.isEmpty()) { - // get the DTO for each base type - for (final Class baseType : baseTypes) { - final DocumentedTypeDTO parentInteface = lookup.get(baseType); - final DocumentedTypeDTO childInterface = lookup.get(i); - - // include all parent tags in the respective children - childInterface.getTags().addAll(parentInteface.getTags()); - - // update the hierarchy - parentInteface.getChildTypes().add(childInterface); - } - - // remove this interface from the lookup (this will only - // leave the interfaces that are ancestor roots) - rootTypes.remove(i); - } - } - - // include the interfaces - sortedClasses.addAll(rootTypes); - - // get the DTO form for all interfaces and classes - for (final Class<?> cls : sortedClasses) { - boolean add = false; - - final DocumentedTypeDTO type; - if (rootTypes.contains(cls)) { - type = lookup.get(cls); - add = true; - } else { - type = new DocumentedTypeDTO(); - type.setType(cls.getName()); - type.setDescription(getCapabilityDescription(cls)); - type.setTags(getTags(cls)); - } - - // identify the base types - final Set<Class> baseTypes = new LinkedHashSet<>(); - identifyBaseTypes(baseClass, cls, baseTypes, false); - - // include this type if it doesn't belong to another hierarchy - if (baseTypes.isEmpty()) { - add = true; - } else { - // get the DTO for each base type - for (final Class baseType : baseTypes) { - final DocumentedTypeDTO parentInterface = lookup.get(baseType); - - // include all parent tags in the respective children - type.getTags().addAll(parentInterface.getTags()); - - // update the hierarchy - parentInterface.getChildTypes().add(type); - } - } - - // add if appropriate - if (add) { - types.add(type); - } - } - - return types; - } - - /** * Creates a ProcessorDTO from the specified ProcessorNode. * * @param node @@ -1958,7 +1829,11 @@ public final class DtoFactory { dto.setDescription(propertyDescriptor.getDescription()); dto.setDefaultValue(propertyDescriptor.getDefaultValue()); dto.setSupportsEl(propertyDescriptor.isExpressionLanguageSupported()); - dto.setIdentifiesControllerService(propertyDescriptor.getControllerServiceDefinition() != null); + + // set the identifies controller service is applicable + if (propertyDescriptor.getControllerServiceDefinition() != null) { + dto.setIdentifiesControllerService(propertyDescriptor.getControllerServiceDefinition().getName()); + } final Class<? extends ControllerService> serviceDefinition = propertyDescriptor.getControllerServiceDefinition(); if (propertyDescriptor.getAllowableValues() == null) { http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/2154b822/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java index a373f05..b5e6f7e 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java @@ -108,6 +108,7 @@ import org.apache.nifi.web.api.dto.status.ProcessGroupStatusDTO; import org.apache.nifi.web.api.dto.status.StatusHistoryDTO; import org.apache.nifi.web.DownloadableContent; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.admin.service.UserService; import org.apache.nifi.authorization.DownloadAuthorization; @@ -348,12 +349,48 @@ public class ControllerFacade { } /** + * Returns whether the specified type implements the specified serviceType. + * + * @param baseType + * @param type + * @return + */ + private boolean implementsServiceType(final String serviceType, final Class type) { + final List<Class<?>> interfaces = ClassUtils.getAllInterfaces(type); + for (final Class i : interfaces) { + if (ControllerService.class.isAssignableFrom(i) && i.getName().equals(serviceType)) { + return true; + } + } + + return false; + } + + /** * Gets the ControllerService types that this controller supports. * + * @param serviceType * @return */ - public Set<DocumentedTypeDTO> getControllerServiceTypes() { - return dtoFactory.fromDocumentedTypes(ControllerService.class, ExtensionManager.getExtensions(ControllerService.class)); + public Set<DocumentedTypeDTO> getControllerServiceTypes(final String serviceType) { + final Set<Class> serviceImplementations = ExtensionManager.getExtensions(ControllerService.class); + + // identify the controller services that implement the specified serviceType if applicable + final Set<Class> matchingServiceImplementions; + if (serviceType != null) { + matchingServiceImplementions = new HashSet<>(); + + // check each type and remove those that aren't in the specified ancestry + for (final Class type : serviceImplementations) { + if (implementsServiceType(serviceType, type)) { + matchingServiceImplementions.add(type); + } + } + } else { + matchingServiceImplementions = serviceImplementations; + } + + return dtoFactory.fromDocumentedTypes(matchingServiceImplementions); } /** @@ -362,7 +399,7 @@ public class ControllerFacade { * @return */ public Set<DocumentedTypeDTO> getReportingTaskTypes() { - return dtoFactory.fromDocumentedTypes(ReportingTask.class, ExtensionManager.getExtensions(ReportingTask.class)); + return dtoFactory.fromDocumentedTypes(ExtensionManager.getExtensions(ReportingTask.class)); } /** http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/2154b822/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java index fa9bc41..40e5730 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java @@ -222,7 +222,7 @@ public final class SnippetUtils { } final PropertyDescriptorDTO propertyDescriptorDto = descriptors.get(propName); - if ( propertyDescriptorDto != null && propertyDescriptorDto.isIdentifiesControllerService() ) { + if ( propertyDescriptorDto != null && propertyDescriptorDto.getIdentifiesControllerService() != null ) { final ControllerServiceNode serviceNode = flowController.getControllerServiceNode(propValue); if ( serviceNode != null ) { addControllerServicesToSnippet(snippet, serviceNode); @@ -363,7 +363,7 @@ public final class SnippetUtils { final Map<String, PropertyDescriptorDTO> descriptors = serviceDTO.getDescriptors(); if ( properties != null && descriptors != null ) { for ( final PropertyDescriptorDTO descriptor : descriptors.values() ) { - if ( descriptor.isIdentifiesControllerService() ) { + if ( descriptor.getIdentifiesControllerService() != null ) { final String currentServiceId = properties.get(descriptor.getName()); if ( currentServiceId == null ) { continue; @@ -558,7 +558,7 @@ public final class SnippetUtils { final Map<String, PropertyDescriptorDTO> descriptors = configDto.getDescriptors(); if ( properties != null && descriptors != null ) { for ( final PropertyDescriptorDTO descriptor : descriptors.values() ) { - if ( descriptor.isIdentifiesControllerService() ) { + if ( descriptor.getIdentifiesControllerService() != null ) { final String currentServiceId = properties.get(descriptor.getName()); if ( currentServiceId == null ) { continue; http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/2154b822/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/settings.css ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/settings.css b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/settings.css index 91805e1..ae93bcc 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/settings.css +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/settings.css @@ -43,21 +43,6 @@ cursor: pointer; } -span.expansion-button { - width: 10px; - height: 10px; - float: left; -} - -span.ancestor-type { - font-weight: bold; -} - -span.ancestor-type-rollup { - margin-left: 3px; - color: #aaa; -} - /* settings tabs */ #settings-tabs-container { http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/2154b822/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/propertytable/jquery.propertytable.css ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/propertytable/jquery.propertytable.css b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/propertytable/jquery.propertytable.css index 74b6f4c..d1f22b2 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/propertytable/jquery.propertytable.css +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/propertytable/jquery.propertytable.css @@ -104,6 +104,49 @@ div.new-property-button-container { } /* + New inline controller service dialog +*/ + +div.new-inline-controller-service-dialog { + z-index: 1301; + display: none; + padding: 10px; + border: 3px solid #365C6A; + box-shadow: 4px 4px 6px rgba(0, 0, 0, 0.9); + cursor: move; + width: 350px; + height: 250px; +} + +div.new-inline-controller-service-combo { + height: 18px; + width: 340px; + margin-bottom: 10px; +} + +div.new-inline-controller-service-tags { + height: 18px; + width: 340px; + margin-bottom: 10px; + overflow: hidden; + white-space: nowrap; +} + +div.new-inline-controller-service-description { + height: 115px; + width: 340px; + overflow: auto; +} + +div.new-inline-controller-service-button-container { + position: absolute; + left: 0; + bottom: 0; + right: 0; + padding: 0 8px 10px; +} + +/* Styles for the property editor. */ http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/2154b822/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/propertytable/jquery.propertytable.js ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/propertytable/jquery.propertytable.js b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/propertytable/jquery.propertytable.js index bbafc60..c0b8884 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/propertytable/jquery.propertytable.js +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/propertytable/jquery.propertytable.js @@ -23,7 +23,17 @@ * * { * readOnly: true, - * newPropertyDialogContainer: 'body' + * dialogContainer: 'body', + * descriptorDeferred: function () { + * return $.Deferred(function (deferred) { + * deferred.resolve(); + * }).promise; + * }, + * goToServiceDeferred: function () { + * return $.Deferred(function (deferred) { + * deferred.resolve(); + * }).promise; + * } * } */ @@ -443,6 +453,10 @@ var gridContainer = $(args.grid.getContainerNode()); var descriptors = gridContainer.data('descriptors'); propertyDescriptor = descriptors[args.item.property]; + + // get the options + var propertyContainer = gridContainer.closest('.property-container'); + var configurationOptions = propertyContainer.data('options'); // create the wrapper wrapper = $('<div></div>').css({ @@ -490,6 +504,15 @@ disabled: true }); } + + // if this descriptor identifies a controller service, provide a way to create one + if (nf.Common.isDefinedAndNotNull(propertyDescriptor.identifiesControllerService)) { + options.push({ + text: 'Create new service...', + value: undefined, + optionClass: 'unset' + }); + } // determine the max height var position = args.position; @@ -499,7 +522,16 @@ // build the combo field combo = $('<div class="value-combo combo"></div>').combo({ options: options, - maxHeight: maxHeight + maxHeight: maxHeight, + select: function (option) { + if (typeof option.value === 'undefined') { + // cancel the current edit + scope.cancel(); + + // prompt for the new service type + promptForNewControllerService(gridContainer, args.grid, args.item, propertyDescriptor.identifiesControllerService, configurationOptions); + } + } }).width(position.width - 16).appendTo(wrapper); // add buttons for handling user input @@ -744,6 +776,154 @@ } } }; + + /** + * Gets the available controller services that implement the specified type and + * prompts the user to create one. + * + * @param {jQuery} gridContainer The grid container + * @param {slickgrid} grid The grid + * @param {object} item The item + * @param {type} serviceType The type of service to create + * @param {object} configurationOptions The configuration options + */ + var promptForNewControllerService = function (gridContainer, grid, item, serviceType, configurationOptions) { + $.ajax({ + type: 'GET', + url: '../nifi-api/controller/controller-service-types', + data: { + serviceType: serviceType + }, + dataType: 'json' + }).done(function (response) { + var options = []; + $.each(response.controllerServiceTypes, function (i, controllerServiceType) { + options.push({ + text: nf.Common.substringAfterLast(controllerServiceType.type, '.'), + value: controllerServiceType.type, + description: nf.Common.escapeHtml(controllerServiceType.description) + }); + }); + + // ensure there are some applicable controller services + if (options.length === 0) { + nf.Dialog.showOkDialog({ + dialogContent: 'No controller service types found that are applicable for this property.', + overlayBackground: false + }); + } else { + var newControllerServiceDialogMarkup = + '<div class="new-inline-controller-service-dialog dialog cancellable">' + + '<div>' + + '<div class="setting-name">Controller Service</div>' + + '<div class="setting-field">' + + '<div class="new-inline-controller-service-combo"></div>' + + '</div>' + + '</div>' + + '<div>' + + '<div class="setting-name">Tags</div>' + + '<div class="setting-field">' + + '<div class="new-inline-controller-service-tags"></div>' + + '</div>' + + '</div>' + + '<div>' + + '<div class="setting-name">Description</div>' + + '<div class="setting-field">' + + '<div class="new-inline-controller-service-description"></div>' + + '</div>' + + '</div>' + + '<div class="new-inline-controller-service-button-container">' + + '<div class="new-inline-controller-service-create button button-normal">Create</div>' + + '<div class="new-inline-controller-service-cancel button button-normal">Cancel</div>' + + '<div class="clear"></div>' + + '</div>' + + '</div>'; + + var newControllerServiceDialog = $(newControllerServiceDialogMarkup).appendTo(configurationOptions.dialogContainer); + var newControllerServiceCombo = newControllerServiceDialog.find('div.new-inline-controller-service-combo'); + var newControllerServiceTags = newControllerServiceDialog.find('div.new-inline-controller-service-tags'); + var newControllerServiceDescription = newControllerServiceDialog.find('div.new-inline-controller-service-description'); + + // build the combo field + newControllerServiceCombo.combo({ + options: options, + select: function (option) { + var service; + $.each(response.controllerServiceTypes, function (i, controllerServiceType) { + if (controllerServiceType.type === option.value) { + service = controllerServiceType; + return false; + } + }); + + // set the service details + newControllerServiceTags.text(service.tags.join(', ')).ellipsis(); + newControllerServiceDescription.text(service.description); + } + }); + + var create = function () { + var newControllerServiceType = newControllerServiceCombo.combo('getSelectedOption').value; + + // create service of the specified type + var revision = nf.Client.getRevision(); + + // add the new controller service + $.ajax({ + type: 'POST', + url: '../nifi-api/controller/controller-services/node', + data: { + version: revision.version, + clientId: revision.clientId, + type: newControllerServiceType + }, + dataType: 'json' + }).done(function (response) { + // update the revision + nf.Client.setRevision(response.revision); + + $.Deferred(function (deferred) { + // load the property descriptor if possible + if (typeof configurationOptions.descriptorDeferred === 'function') { + configurationOptions.descriptorDeferred(item.property).done(function(response) { + var descriptor = response.propertyDescriptor; + + // store the descriptor for use later + var descriptors = gridContainer.data('descriptors'); + if (!nf.Common.isUndefined(descriptors)) { + descriptors[descriptor.name] = descriptor; + } + + deferred.resolve(); + }); + } else { + deferred.resolve(); + } + }).done(function() { + // add a row for the new property + var data = grid.getData(); + data.updateItem(item.id, $.extend(item, { + value: response.controllerService.id + })); + + // close the dialog + newControllerServiceDialog.hide(); + }); + }).fail(nf.Common.handleAjaxError); + }; + + var cancel = function () { + newControllerServiceDialog.hide(); + }; + + // make the new property dialog draggable + newControllerServiceDialog.draggable({ + cancel: 'input, textarea, pre, .button, .' + editorClass, + containment: 'body' + }).on('click', 'div.new-inline-controller-service-create', create).on('click', 'div.new-inline-controller-service-cancel', cancel).modal('show'); + } + }).fail(nf.Common.handleAjaxError); + }; var initPropertiesTable = function (table, options) { // function for formatting the property name @@ -826,20 +1006,37 @@ {id: 'value', field: 'value', name: 'Value', sortable: false, resizable: true, cssClass: 'pointer', rerenderOnResize: true, formatter: valueFormatter} ]; - if (options.readOnly !== true) { - // custom formatter for the actions column - var actionFormatter = function (row, cell, value, columnDef, dataContext) { - var markup = ''; + // custom formatter for the actions column + var actionFormatter = function (row, cell, value, columnDef, dataContext) { + var markup = ''; - // allow user defined properties to be removed - if (dataContext.type === 'userDefined') { - markup = '<img src="images/iconDelete.png" title="Delete" class="delete-property pointer" style="margin-top: 2px" />'; - } + // get the property descriptor + var descriptors = table.data('descriptors'); + var propertyDescriptor = descriptors[dataContext.property]; + + var identifiesControllerService = nf.Common.isDefinedAndNotNull(propertyDescriptor.identifiesControllerService); + var isConfigured = nf.Common.isDefinedAndNotNull(dataContext.value); + var isOnCanvas = nf.Common.isDefinedAndNotNull(nf.Canvas); + + // check to see if we should provide a button for going to a controller service + if (identifiesControllerService && isConfigured && isOnCanvas) { + // ensure the configured value is referencing a valid service + $.each(propertyDescriptor.allowableValues, function (_, allowableValue) { + if (allowableValue.value === dataContext.value) { + markup = '<img src="images/iconGoTo.png" title="Go To" class="go-to-service pointer" style="margin-top: 2px" />'; + return false; + } + }); + } - return markup; - }; - propertyColumns.push({id: "actions", name: " ", minWidth: 20, width: 20, formatter: actionFormatter}); - } + // allow user defined properties to be removed + if (options.readOnly !== true && dataContext.type === 'userDefined') { + markup = '<img src="images/iconDelete.png" title="Delete" class="delete-property pointer" style="margin-top: 2px" />'; + } + + return markup; + }; + propertyColumns.push({id: "actions", name: " ", minWidth: 20, width: 20, formatter: actionFormatter}); var propertyConfigurationOptions = { forceFitColumns: true, @@ -899,6 +1096,39 @@ } } }; + + var goToControllerService = function (property) { + // close the dialog + var dialog = table.closest('.dialog'); + if (dialog.hasClass('modal')) { + dialog.modal('hide'); + } else { + dialog.hide(); + } + + $.Deferred(function (deferred) { + if ($('#settings').is(':visible')) { + deferred.resolve(); + } else { + // reload the settings and show + nf.Settings.loadSettings().done(function () { + nf.Settings.showSettings(); + deferred.resolve(); + }); + } + }).done(function () { + var controllerServiceGrid = $('#controller-services-table').data('gridInstance'); + var controllerServiceData = controllerServiceGrid.getData(); + + // select the desired service + var row = controllerServiceData.getRowById(property.value); + controllerServiceGrid.setSelectedRows([row]); + controllerServiceGrid.scrollRowIntoView(row); + + // select the controller services tab + $('#settings-tabs').find('li:eq(1)').click(); + }); + }; // initialize the grid var propertyGrid = new Slick.Grid(table, propertyData, propertyColumns, propertyConfigurationOptions); @@ -916,10 +1146,11 @@ // prevents standard edit logic e.stopImmediatePropagation(); } else if (propertyGrid.getColumns()[args.cell].id === 'actions') { + var property = propertyData.getItem(args.row); + var target = $(e.target); if (target.hasClass('delete-property')) { // mark the property in question for removal - var property = propertyData.getItem(args.row); property.hidden = true; // refresh the table @@ -927,6 +1158,17 @@ // prevents standard edit logic e.stopImmediatePropagation(); + } else if (target.hasClass('go-to-service')) { + if (options.readOnly === true) { + goToControllerService(property); + } else { + // load the property descriptor if possible + if (typeof options.goToServiceDeferred === 'function') { + options.goToServiceDeferred().done(function() { + goToControllerService(property); + }); + } + } } } }); @@ -1076,8 +1318,8 @@ nf.Common.removeAllPropertyDetailDialogs(); } else { // clear any existing new property dialogs - if (nf.Common.isDefinedAndNotNull(options.newPropertyDialogContainer)) { - $(options.newPropertyDialogContainer).children('div.new-property-dialog').hide(); + if (nf.Common.isDefinedAndNotNull(options.dialogContainer)) { + $(options.dialogContainer).children('div.new-property-dialog').hide(); } } @@ -1108,7 +1350,7 @@ var propertyTableContainer = $(this); // clear any current contents, remote events, and store options - propertyTableContainer.empty().unbind().data('options', options); + propertyTableContainer.empty().unbind().addClass('property-container').data('options', options); // build the component var header = $('<div class="properties-header"></div>').appendTo(propertyTableContainer); @@ -1118,7 +1360,7 @@ var table = $('<div class="property-table"></div>').appendTo(propertyTableContainer); // optionally add a add new property button - if (options.readOnly !== true && nf.Common.isDefinedAndNotNull(options.newPropertyDialogContainer)) { + if (options.readOnly !== true && nf.Common.isDefinedAndNotNull(options.dialogContainer)) { // build the new property dialog var newPropertyDialogMarkup = '<div class="new-property-dialog dialog cancellable">' + @@ -1135,7 +1377,7 @@ '</div>' + '</div>'; - var newPropertyDialog = $(newPropertyDialogMarkup).appendTo(options.newPropertyDialogContainer); + var newPropertyDialog = $(newPropertyDialogMarkup).appendTo(options.dialogContainer); var newPropertyNameField = newPropertyDialog.find('input.new-property-name'); var add = function () { @@ -1295,8 +1537,9 @@ clear(propertyTableContainer); // clear any existing new property dialogs - if (nf.Common.isDefinedAndNotNull(options.newPropertyDialogContainer)) { - $(options.newPropertyDialogContainer).children('div.new-property-dialog').remove(); + if (nf.Common.isDefinedAndNotNull(options.dialogContainer)) { + $(options.dialogContainer).children('div.new-property-dialog').remove(); + $(options.dialogContainer).children('div.new-inline-controller-service-dialog').remove(); } }); }, @@ -1372,4 +1615,4 @@ return methods.init.apply(this, arguments); } }; -})(jQuery); \ No newline at end of file +})(jQuery); http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/2154b822/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-service.js ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-service.js b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-service.js index 26b7253..39bbe64 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-service.js +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-service.js @@ -374,6 +374,7 @@ nf.ControllerService = (function () { // select the selected row var row = controllerServiceData.getRowById(referencingComponent.id); controllerServiceGrid.setSelectedRows([row]); + controllerServiceGrid.scrollRowIntoView(row); // close the dialog and shell referenceContainer.closest('.dialog').modal('hide'); @@ -419,6 +420,7 @@ nf.ControllerService = (function () { // select the selected row var row = reportingTaskData.getRowById(referencingComponent.id); reportingTaskGrid.setSelectedRows([row]); + reportingTaskGrid.scrollRowIntoView(row); // select the reporting task tab $('#settings-tabs').find('li:last').click(); @@ -1070,6 +1072,83 @@ nf.ControllerService = (function () { }; /** + * Goes to a service configuration from the property table. + */ + var goToServiceFromProperty = function () { + return $.Deferred(function (deferred) { + // close all fields currently being edited + $('#controller-service-properties').propertytable('saveRow'); + + // determine if changes have been made + if (isSaveRequired()) { + // see if those changes should be saved + nf.Dialog.showYesNoDialog({ + dialogContent: 'Save changes before going to this Controller Service?', + overlayBackground: false, + noHandler: function () { + deferred.resolve(); + }, + yesHandler: function () { + var controllerService = $('#controller-service-configuration').data('controllerServiceDetails'); + saveControllerService(controllerService).done(function () { + deferred.resolve(); + }).fail(function () { + deferred.reject(); + }); + } + }); + } else { + deferred.resolve(); + } + }).promise(); + }; + + var saveControllerService = function (controllerService) { + // marshal the settings and properties and update the controller service + var updatedControllerService = marshalDetails(); + + // ensure details are valid as far as we can tell + if (validateDetails(updatedControllerService)) { + var previouslyReferencedServiceIds = []; + $.each(identifyReferencedServiceDescriptors(controllerService), function (_, descriptor) { + var modifyingService = !nf.Common.isUndefined(updatedControllerService.controllerService.properties) && !nf.Common.isUndefined(updatedControllerService.controllerService.properties[descriptor.name]); + var isCurrentlyConfigured = nf.Common.isDefinedAndNotNull(controllerService.properties[descriptor.name]); + + // if we are attempting to update a controller service reference + if (modifyingService && isCurrentlyConfigured) { + + // record the current value if set + previouslyReferencedServiceIds.push(controllerService.properties[descriptor.name]); + } + }); + + // update the selected component + return $.ajax({ + type: 'PUT', + data: JSON.stringify(updatedControllerService), + url: controllerService.uri, + dataType: 'json', + processData: false, + contentType: 'application/json' + }).done(function (response) { + if (nf.Common.isDefinedAndNotNull(response.controllerService)) { + // update the revision + nf.Client.setRevision(response.revision); + + // reload all previously referenced controller services + $.each(previouslyReferencedServiceIds, function(_, oldServiceReferenceId) { + reloadControllerService(oldServiceReferenceId); + }); + } + }).fail(handleControllerServiceConfigurationError); + } else { + return $.Deferred(function (deferred) { + deferred.reject(); + }).promise(); + } + }; + + /** * Identifies the descriptors that identify controller services. * * @param {object} component @@ -1078,7 +1157,7 @@ nf.ControllerService = (function () { var referencedServiceDescriptors = []; $.each(component.descriptors, function(_, descriptor) { - if (descriptor.identifiesControllerService === true) { + if (nf.Common.isDefinedAndNotNull(descriptor.identifiesControllerService)) { referencedServiceDescriptors.push(descriptor); } }); @@ -1180,8 +1259,9 @@ nf.ControllerService = (function () { // initialize the property table $('#controller-service-properties').propertytable({ readOnly: false, - newPropertyDialogContainer: '#new-controller-service-property-container', - descriptorDeferred: getControllerServicePropertyDescriptor + dialogContainer: '#new-controller-service-property-container', + descriptorDeferred: getControllerServicePropertyDescriptor, + goToServiceDeferred: goToServiceFromProperty }); // initialize the disable service dialog @@ -1324,8 +1404,9 @@ nf.ControllerService = (function () { // initialize the property table $('#controller-service-properties').propertytable('destroy').propertytable({ readOnly: false, - newPropertyDialogContainer: '#new-controller-service-property-container', - descriptorDeferred: getControllerServicePropertyDescriptor + dialogContainer: '#new-controller-service-property-container', + descriptorDeferred: getControllerServicePropertyDescriptor, + goToServiceDeferred: goToServiceFromProperty }); // update the mode @@ -1392,49 +1473,15 @@ nf.ControllerService = (function () { // close all fields currently being edited $('#controller-service-properties').propertytable('saveRow'); - // marshal the settings and properties and update the controller service - var updatedControllerService = marshalDetails(); - - // ensure details are valid as far as we can tell - if (validateDetails(updatedControllerService)) { - var previouslyReferencedServiceIds = []; - $.each(identifyReferencedServiceDescriptors(controllerService), function (_, descriptor) { - var modifyingService = !nf.Common.isUndefined(updatedControllerService.controllerService.properties) && !nf.Common.isUndefined(updatedControllerService.controllerService.properties[descriptor.name]); - var isCurrentlyConfigured = nf.Common.isDefinedAndNotNull(controllerService.properties[descriptor.name]); - - // if we are attempting to update a controller service reference - if (modifyingService && isCurrentlyConfigured) { - // record the current value if set - previouslyReferencedServiceIds.push(controllerService.properties[descriptor.name]); - } - }); + // save the controller service + saveControllerService(controllerService).done(function (response) { + // reload the controller service + renderControllerService(response.controllerService); + reloadControllerServiceReferences(response.controllerService); - // update the selected component - $.ajax({ - type: 'PUT', - data: JSON.stringify(updatedControllerService), - url: controllerService.uri, - dataType: 'json', - processData: false, - contentType: 'application/json' - }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.controllerService)) { - nf.Client.setRevision(response.revision); - - // reload the controller service - renderControllerService(response.controllerService); - reloadControllerServiceReferences(response.controllerService); - - // reload all previously referenced controller services - $.each(previouslyReferencedServiceIds, function(_, oldServiceReferenceId) { - reloadControllerService(oldServiceReferenceId); - }); - - // close the details panel - controllerServiceDialog.modal('hide'); - } - }).fail(handleControllerServiceConfigurationError); - } + // close the details panel + controllerServiceDialog.modal('hide'); + }); } } }, { @@ -1480,47 +1527,10 @@ nf.ControllerService = (function () { overlayBackground: false, noHandler: openCustomUi, yesHandler: function () { - // marshal the settings and properties and update the controller service - var updatedControllerService = marshalDetails(); - - // ensure details are valid as far as we can tell - if (validateDetails(updatedControllerService)) { - var previouslyReferencedServiceIds = []; - $.each(identifyReferencedServiceDescriptors(controllerService), function (_, descriptor) { - var modifyingService = !nf.Common.isUndefined(updatedControllerService.controllerService.properties) && !nf.Common.isUndefined(updatedControllerService.controllerService.properties[descriptor.name]); - var isCurrentlyConfigured = nf.Common.isDefinedAndNotNull(controllerService.properties[descriptor.name]); - - // if we are attempting to update a controller service reference - if (modifyingService && isCurrentlyConfigured) { - - // record the current value if set - previouslyReferencedServiceIds.push(controllerService.properties[descriptor.name]); - } - }); - - // update the selected component - $.ajax({ - type: 'PUT', - data: JSON.stringify(updatedControllerService), - url: controllerService.uri, - dataType: 'json', - processData: false, - contentType: 'application/json' - }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.controllerService)) { - // update the revision - nf.Client.setRevision(response.revision); - - // reload all previously referenced controller services - $.each(previouslyReferencedServiceIds, function(_, oldServiceReferenceId) { - reloadControllerService(oldServiceReferenceId); - }); - - // open the custom ui - openCustomUi(); - } - }).fail(handleControllerServiceConfigurationError); - } + saveControllerService(controllerService).done(function () { + // open the custom ui + openCustomUi(); + }); } }); } else { http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/2154b822/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js index 4e828df..2e48579 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-processor-configuration.js @@ -380,6 +380,70 @@ nf.ProcessorConfiguration = (function () { } }); }; + + /** + * Goes to a service configuration from the property table. + */ + var goToServiceFromProperty = function () { + return $.Deferred(function (deferred) { + // close all fields currently being edited + $('#processor-properties').propertytable('saveRow'); + + // determine if changes have been made + if (isSaveRequired()) { + // see if those changes should be saved + nf.Dialog.showYesNoDialog({ + dialogContent: 'Save changes before going to this Controller Service?', + overlayBackground: false, + noHandler: function () { + deferred.resolve(); + }, + yesHandler: function () { + var processor = $('#processor-configuration').data('processorDetails'); + saveProcessor(processor).done(function () { + deferred.resolve(); + }).fail(function () { + deferred.reject(); + }); + } + }); + } else { + deferred.resolve(); + } + }).promise(); + }; + + /** + * + * @param {type} processor + * @returns {undefined} + */ + var saveProcessor = function (processor) { + // marshal the settings and properties and update the processor + var updatedProcessor = marshalDetails(); + + // ensure details are valid as far as we can tell + if (validateDetails(updatedProcessor)) { + // update the selected component + return $.ajax({ + type: 'PUT', + data: JSON.stringify(updatedProcessor), + url: processor.uri, + dataType: 'json', + processData: false, + contentType: 'application/json' + }).done(function (response) { + if (nf.Common.isDefinedAndNotNull(response.processor)) { + // update the revision + nf.Client.setRevision(response.revision); + } + }).fail(handleProcessorConfigurationError); + } else { + return $.Deferred(function (deferred) { + deferred.reject(); + }).promise(); + } + }; return { /** @@ -470,7 +534,7 @@ nf.ProcessorConfiguration = (function () { // initialize the property table $('#processor-properties').propertytable({ readOnly: false, - newPropertyDialogContainer: '#new-processor-property-container', + dialogContainer: '#new-processor-property-container', descriptorDeferred: function(propertyName) { var processor = $('#processor-configuration').data('processorDetails'); return $.ajax({ @@ -481,7 +545,8 @@ nf.ProcessorConfiguration = (function () { }, dataType: 'json' }).fail(nf.Common.handleAjaxError); - } + }, + goToServiceDeferred: goToServiceFromProperty }); }, @@ -625,35 +690,17 @@ nf.ProcessorConfiguration = (function () { // close all fields currently being edited $('#processor-properties').propertytable('saveRow'); - // marshal the settings and properties and update the processor - var updatedProcessor = marshalDetails(); - - // ensure details are valid as far as we can tell - if (validateDetails(updatedProcessor)) { - // update the selected component - $.ajax({ - type: 'PUT', - data: JSON.stringify(updatedProcessor), - url: processor.uri, - dataType: 'json', - processData: false, - contentType: 'application/json' - }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.processor)) { - // update the revision - nf.Client.setRevision(response.revision); - - // set the new processor state based on the response - nf.Processor.set(response.processor); - - // reload the processor's outgoing connections - reloadProcessorConnections(processor); - - // close the details panel - $('#processor-configuration').modal('hide'); - } - }).fail(handleProcessorConfigurationError); - } + // save the processor + saveProcessor(processor).done(function (response) { + // set the new processor state based on the response + nf.Processor.set(response.processor); + + // reload the processor's outgoing connections + reloadProcessorConnections(processor); + + // close the details panel + $('#processor-configuration').modal('hide'); + }); } } }, { @@ -696,29 +743,10 @@ nf.ProcessorConfiguration = (function () { overlayBackground: false, noHandler: openCustomUi, yesHandler: function () { - // marshal the settings and properties and update the processor - var updatedProcessor = marshalDetails(); - - // ensure details are valid as far as we can tell - if (validateDetails(updatedProcessor)) { - // update the selected component - $.ajax({ - type: 'PUT', - data: JSON.stringify(updatedProcessor), - url: processor.uri, - dataType: 'json', - processData: false, - contentType: 'application/json' - }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.processor)) { - // update the revision - nf.Client.setRevision(response.revision); - - // open the custom ui - openCustomUi(); - } - }).fail(handleProcessorConfigurationError); - } + saveProcessor(processor).done(function (deferred) { + // open the custom ui + openCustomUi(); + }); } }); } else { http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/2154b822/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-reporting-task.js ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-reporting-task.js b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-reporting-task.js index ed13f10..998213e 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-reporting-task.js +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-reporting-task.js @@ -207,6 +207,70 @@ nf.ReportingTask = (function () { }; /** + * Goes to a service configuration from the property table. + */ + var goToServiceFromProperty = function () { + return $.Deferred(function (deferred) { + // close all fields currently being edited + $('#reporting-task-properties').propertytable('saveRow'); + + // determine if changes have been made + if (isSaveRequired()) { + // see if those changes should be saved + nf.Dialog.showYesNoDialog({ + dialogContent: 'Save changes before going to this Controller Service?', + overlayBackground: false, + noHandler: function () { + deferred.resolve(); + }, + yesHandler: function () { + var reportingTask = $('#reporting-task-configuration').data('reportingTaskDetails'); + saveReportingTask(reportingTask).done(function () { + deferred.resolve(); + }).fail(function () { + deferred.reject(); + }); + } + }); + } else { + deferred.resolve(); + } + }).promise(); + }; + + /** + * Saves the specified reporting task. + * + * @param {type} reportingTask + */ + var saveReportingTask = function (reportingTask) { + // marshal the settings and properties and update the reporting task + var updatedReportingTask = marshalDetails(); + + // ensure details are valid as far as we can tell + if (validateDetails(updatedReportingTask)) { + // update the selected component + return $.ajax({ + type: 'PUT', + data: JSON.stringify(updatedReportingTask), + url: reportingTask.uri, + dataType: 'json', + processData: false, + contentType: 'application/json' + }).done(function (response) { + if (nf.Common.isDefinedAndNotNull(response.reportingTask)) { + // update the revision + nf.Client.setRevision(response.revision); + } + }).fail(handleReportingTaskConfigurationError); + } else { + return $.Deferred(function (deferred) { + deferred.reject(); + }).promise(); + } + }; + + /** * Gets a property descriptor for the controller service currently being configured. * * @param {type} propertyName @@ -288,8 +352,9 @@ nf.ReportingTask = (function () { // initialize the property table $('#reporting-task-properties').propertytable({ readOnly: false, - newPropertyDialogContainer: '#new-reporting-task-property-container', - deferredDescriptor: getReportingTaskPropertyDescriptor + dialogContainer: '#new-reporting-task-property-container', + deferredDescriptor: getReportingTaskPropertyDescriptor, + goToServiceDeferred: goToServiceFromProperty }); }, @@ -308,8 +373,9 @@ nf.ReportingTask = (function () { // initialize the property table $('#reporting-task-properties').propertytable('destroy').propertytable({ readOnly: false, - newPropertyDialogContainer: '#new-reporting-task-property-container', - deferredDescriptor: getReportingTaskPropertyDescriptor + dialogContainer: '#new-reporting-task-property-container', + deferredDescriptor: getReportingTaskPropertyDescriptor, + goToServiceDeferred: goToServiceFromProperty }); // update the mode @@ -407,33 +473,15 @@ nf.ReportingTask = (function () { // close all fields currently being edited $('#reporting-task-properties').propertytable('saveRow'); - // marshal the settings and properties and update the reporting task - var updatedReportingTask = marshalDetails(); - - // ensure details are valid as far as we can tell - if (validateDetails(updatedReportingTask)) { - // update the selected component - $.ajax({ - type: 'PUT', - data: JSON.stringify(updatedReportingTask), - url: reportingTask.uri, - dataType: 'json', - processData: false, - contentType: 'application/json' - }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.reportingTask)) { - // update the revision - nf.Client.setRevision(response.revision); - - // reload the reporting task - renderReportingTask(response.reportingTask); - nf.ControllerService.reloadReferencedServices(response.reportingTask); + // save the reporting task + saveReportingTask(reportingTask).done(function (response) { + // reload the reporting task + renderReportingTask(response.reportingTask); + nf.ControllerService.reloadReferencedServices(response.reportingTask); - // close the details panel - $('#reporting-task-configuration').modal('hide'); - } - }).fail(handleReportingTaskConfigurationError); - } + // close the details panel + $('#reporting-task-configuration').modal('hide'); + }); } } }, { @@ -481,29 +529,10 @@ nf.ReportingTask = (function () { overlayBackground: false, noHandler: openCustomUi, yesHandler: function () { - // marshal the settings and properties and update the reporting task - var updatedReportingTask = marshalDetails(); - - // ensure details are valid as far as we can tell - if (validateDetails(updatedReportingTask)) { - // update the selected component - $.ajax({ - type: 'PUT', - data: JSON.stringify(updatedReportingTask), - url: reportingTask.uri, - dataType: 'json', - processData: false, - contentType: 'application/json' - }).done(function (response) { - if (nf.Common.isDefinedAndNotNull(response.reportingTask)) { - // update the revision - nf.Client.setRevision(response.revision); - - // open the custom ui - openCustomUi(); - } - }).fail(handleReportingTaskConfigurationError); - } + saveReportingTask(reportingTask).done(function () { + // open the custom ui + openCustomUi(); + }); } }); } else {