NIFI-4436:

- Clearing bucket/flow/versions when changing the selected registry/bucket.
- Using the versioned flow to get the group name when importing.
- Adding menu items for viewing local changes.
- Showing local changes during revert request.
This commit is contained in:
Matt Gilman 2017-11-16 14:41:41 -05:00 committed by Bryan Bende
parent f6cc5b6cdc
commit 3d8b1e4890
No known key found for this signature in database
GPG Key ID: A0DDA9ED50711C39
13 changed files with 1008 additions and 321 deletions

View File

@ -17,12 +17,11 @@
package org.apache.nifi.web.api.dto;
import java.util.List;
import java.util.Objects;
import io.swagger.annotations.ApiModelProperty;
import javax.xml.bind.annotation.XmlType;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
import java.util.Objects;
@XmlType(name = "componentDifference")
public class ComponentDifferenceDTO {
@ -30,7 +29,7 @@ public class ComponentDifferenceDTO {
private String componentId;
private String componentName;
private String processGroupId;
private List<String> differences;
private List<DifferenceDTO> differences;
@ApiModelProperty("The type of component")
public String getComponentType() {
@ -69,11 +68,11 @@ public class ComponentDifferenceDTO {
}
@ApiModelProperty("The differences in the component between the two flows")
public List<String> getDifferences() {
public List<DifferenceDTO> getDifferences() {
return differences;
}
public void setDifferences(List<String> differences) {
public void setDifferences(List<DifferenceDTO> differences) {
this.differences = differences;
}

View File

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.web.api.dto;
import io.swagger.annotations.ApiModelProperty;
import javax.xml.bind.annotation.XmlType;
@XmlType(name = "difference")
public class DifferenceDTO {
private String differenceType;
private String difference;
@ApiModelProperty("The type of difference")
public String getDifferenceType() {
return differenceType;
}
public void setDifferenceType(String differenceType) {
this.differenceType = differenceType;
}
@ApiModelProperty("Description of the difference")
public String getDifference() {
return difference;
}
public void setDifference(String difference) {
this.difference = difference;
}
}

View File

@ -16,57 +16,12 @@
*/
package org.apache.nifi.web.api;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLStreamReader;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.authorization.AuthorizableLookup;
import org.apache.nifi.authorization.AuthorizeAccess;
@ -156,12 +111,55 @@ import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* RESTful endpoint for managing a Group.
@ -341,9 +339,7 @@ public class ProcessGroupResource extends ApplicationResource {
// authorize access
serviceFacade.authorizeAccess(lookup -> {
final ProcessGroupAuthorizable groupAuthorizable = lookup.getProcessGroup(groupId);
final Authorizable processGroup = groupAuthorizable.getAuthorizable();
processGroup.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
super.authorizeProcessGroup(groupAuthorizable, authorizer, lookup, RequestAction.READ, false, false, true, false);
authorizeProcessGroup(groupAuthorizable, authorizer, lookup, RequestAction.READ, false, false, true, false);
});
final FlowComparisonEntity entity = serviceFacade.getLocalModifications(groupId);
@ -1625,6 +1621,11 @@ public class ProcessGroupResource extends ApplicationResource {
}
}
// if the group name isn't specified, ensure the group is being imported from version control
if (StringUtils.isBlank(requestProcessGroupEntity.getComponent().getName()) && requestProcessGroupEntity.getComponent().getVersionControlInformation() == null) {
throw new IllegalArgumentException("The group name is required when the group is not imported from version control.");
}
if (requestProcessGroupEntity.getComponent().getParentGroupId() != null && !groupId.equals(requestProcessGroupEntity.getComponent().getParentGroupId())) {
throw new IllegalArgumentException(String.format("If specified, the parent process group id %s must be the same as specified in the URI %s",
requestProcessGroupEntity.getComponent().getParentGroupId(), groupId));
@ -1688,15 +1689,22 @@ public class ProcessGroupResource extends ApplicationResource {
serviceFacade.verifyComponentTypes(versionedFlowSnapshot.getFlowContents());
}
},
processGroupGroupEntity -> {
processGroupEntity -> {
final ProcessGroupDTO processGroup = processGroupEntity.getComponent();
// set the processor id as appropriate
processGroupGroupEntity.getComponent().setId(generateUuid());
processGroup.setId(generateUuid());
// ensure the group name comes from the versioned flow
final VersionedFlowSnapshot flowSnapshot = processGroupEntity.getVersionedFlowSnapshot();
if (flowSnapshot != null && StringUtils.isNotBlank(flowSnapshot.getFlowContents().getName()) && StringUtils.isBlank(processGroup.getName())) {
processGroup.setName(flowSnapshot.getFlowContents().getName());
}
// create the process group contents
final Revision revision = getRevision(processGroupGroupEntity, processGroupGroupEntity.getComponent().getId());
ProcessGroupEntity entity = serviceFacade.createProcessGroup(revision, groupId, processGroupGroupEntity.getComponent());
final Revision revision = getRevision(processGroupEntity, processGroup.getId());
ProcessGroupEntity entity = serviceFacade.createProcessGroup(revision, groupId, processGroup);
final VersionedFlowSnapshot flowSnapshot = requestProcessGroupEntity.getVersionedFlowSnapshot();
if (flowSnapshot != null) {
final RevisionDTO revisionDto = entity.getRevision();
final String newGroupId = entity.getComponent().getId();

View File

@ -16,33 +16,6 @@
*/
package org.apache.nifi.web.api.dto;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.ws.rs.WebApplicationException;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.action.Action;
@ -215,6 +188,32 @@ import org.apache.nifi.web.api.entity.VariableEntity;
import org.apache.nifi.web.controller.ControllerFacade;
import org.apache.nifi.web.revision.RevisionManager;
import javax.ws.rs.WebApplicationException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public final class DtoFactory {
@SuppressWarnings("rawtypes")
@ -2181,15 +2180,20 @@ public final class DtoFactory {
public Set<ComponentDifferenceDTO> createComponentDifferenceDtos(final FlowComparison comparison) {
final Map<ComponentDifferenceDTO, List<String>> differencesByComponent = new HashMap<>();
final Map<ComponentDifferenceDTO, List<DifferenceDTO>> differencesByComponent = new HashMap<>();
for (final FlowDifference difference : comparison.getDifferences()) {
final ComponentDifferenceDTO componentDiff = createComponentDifference(difference);
final List<String> differences = differencesByComponent.computeIfAbsent(componentDiff, key -> new ArrayList<>());
differences.add(difference.getDescription());
final List<DifferenceDTO> differences = differencesByComponent.computeIfAbsent(componentDiff, key -> new ArrayList<>());
final DifferenceDTO dto = new DifferenceDTO();
dto.setDifferenceType(difference.getDifferenceType().getDescription());
dto.setDifference(difference.getDescription());
differences.add(dto);
}
for (final Map.Entry<ComponentDifferenceDTO, List<String>> entry : differencesByComponent.entrySet()) {
for (final Map.Entry<ComponentDifferenceDTO, List<DifferenceDTO>> entry : differencesByComponent.entrySet()) {
entry.getKey().setDifferences(entry.getValue());
}

View File

@ -61,7 +61,9 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
// create the process group
ProcessGroup group = flowController.createProcessGroup(processGroup.getId());
if (processGroup.getName() != null) {
group.setName(processGroup.getName());
}
if (processGroup.getPosition() != null) {
group.setPosition(new Position(processGroup.getPosition().getX(), processGroup.getPosition().getY()));
}

View File

@ -117,6 +117,8 @@
<jsp:include page="/WEB-INF/partials/canvas/connections-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/save-flow-version-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/import-flow-version-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/revert-local-changes-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/show-local-changes-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/registry-configuration-dialog.jsp"/>
<div id="canvas-container" class="unselectable"></div>
<div id="canvas-tooltips">

View File

@ -0,0 +1,36 @@
<%--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--%>
<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
<div id="revert-local-changes-dialog" layout="column" class="hidden large-dialog">
<div class="dialog-content">
<div class="setting">
<div class="setting-field">
Are you sure you want to revert changes? All flow configuration changes detailed below will be reverted to the last version.
</div>
</div>
<span id="revert-local-changes-process-group-id" class="hidden"></span>
<div id="revert-local-changes-filter-controls">
<div id="revert-local-changes-filter-status" class="filter-status">
Displaying&nbsp;<span id="displayed-revert-local-changes-entries"></span>&nbsp;of&nbsp;<span id="total-revert-local-changes-entries"></span>
</div>
<div id="revert-local-changes-filter-container">
<input type="text" id="revert-local-changes-filter" placeholder="Filter"/>
</div>
</div>
<div id="revert-local-changes-table"></div>
</div>
</div>

View File

@ -0,0 +1,35 @@
<%--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--%>
<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
<div id="show-local-changes-dialog" layout="column" class="hidden large-dialog">
<div class="dialog-content">
<div class="setting">
<div class="setting-field">
The following changes have been made to the flow since the last version.
</div>
</div>
<div id="show-local-changes-filter-controls">
<div id="show-local-changes-filter-status" class="filter-status">
Displaying&nbsp;<span id="displayed-show-local-changes-entries"></span>&nbsp;of&nbsp;<span id="total-show-local-changes-entries"></span>
</div>
<div id="show-local-changes-filter-container">
<input type="text" id="show-local-changes-filter" placeholder="Filter"/>
</div>
</div>
<div id="show-local-changes-table"></div>
</div>
</div>

View File

@ -263,6 +263,23 @@ div.progress-label {
border-radius: 0;
}
/*
Local changes
*/
#revert-local-changes-table, #show-local-changes-table {
position: absolute;
top: 80px;
left: 0px;
right: 0px;
bottom: 0px;
height: 225px;
}
#revert-local-changes-filter, #show-local-changes-filter {
width: 173px;
}
/*
Variable Registry
*/

View File

@ -25,9 +25,10 @@
'nf.Graph',
'nf.CanvasUtils',
'nf.ErrorHandler',
'nf.Common'],
function ($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfCommon) {
return (nf.ng.GroupComponent = factory($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfCommon));
'nf.Common',
'nf.Dialog'],
function ($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfCommon, nfDialog) {
return (nf.ng.GroupComponent = factory($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfCommon, nfDialog));
});
} else if (typeof exports === 'object' && typeof module === 'object') {
module.exports = (nf.ng.GroupComponent =
@ -37,7 +38,8 @@
require('nf.Graph'),
require('nf.CanvasUtils'),
require('nf.ErrorHandler'),
require('nf.Common')));
require('nf.Common'),
require('nf.Dialog')));
} else {
nf.ng.GroupComponent = factory(root.$,
root.nf.Client,
@ -45,9 +47,10 @@
root.nf.Graph,
root.nf.CanvasUtils,
root.nf.ErrorHandler,
root.nf.Common);
root.nf.Common,
root.nf.Dialog);
}
}(this, function ($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfCommon) {
}(this, function ($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfCommon, nfDialog) {
'use strict';
return function (serviceProvider) {
@ -236,12 +239,22 @@
// hide the dialog
groupComponent.modal.hide();
// ensure the group name is specified
if (nfCommon.isBlank(groupName)) {
nfDialog.showOkDialog({
headerText: 'Create Process Group',
dialogContent: 'The group name is required.'
});
deferred.reject();
} else {
// create the group and resolve the deferred accordingly
createGroup(groupName, pt).done(function (response) {
deferred.resolve(response.component);
}).fail(function () {
deferred.reject();
});
}
};
groupComponent.modal.update('setButtonModel', [{

View File

@ -1265,6 +1265,18 @@
}
},
/**
* Shows local changes.
*/
showLocalChanges: function (selection) {
if (selection.empty()) {
nfFlowVersion.showLocalChanges(nfCanvasUtils.getGroupId());
} else if (selection.size() === 1) {
var selectionData = selection.datum();
nfFlowVersion.showLocalChanges(selectionData.id)
}
},
/**
* Changes the flow version.
*/

View File

@ -427,6 +427,123 @@
return nfCommon.isUndefinedOrNull(processGroupData.component.versionControlInformation);
};
/**
* Returns whether the process group support supports commit.
*
* @param selection
* @returns {boolean}
*/
var supportsCommitFlowVersion = function (selection) {
// ensure this selection supports flow versioning above
if (supportsFlowVersioning(selection) === false) {
return false;
}
var versionControlInformation;
if (selection.empty()) {
// check bread crumbs for version control information in the current group
var breadcrumbEntities = nfNgBridge.injector.get('breadcrumbsCtrl').getBreadcrumbs();
if (breadcrumbEntities.length > 0) {
var breadcrumbEntity = breadcrumbEntities[breadcrumbEntities.length - 1];
if (breadcrumbEntity.permissions.canRead) {
versionControlInformation = breadcrumbEntity.breadcrumb.versionControlInformation;
} else {
return false;
}
} else {
return false;
}
} else {
var processGroupData = selection.datum();
versionControlInformation = processGroupData.component.versionControlInformation;
}
if (nfCommon.isUndefinedOrNull(versionControlInformation)) {
return false;
}
// check the selection for version control information
return versionControlInformation.current === true && versionControlInformation.modified === true;
};
/**
* Returns whether the process group supports revert local changes.
*
* @param selection
* @returns {boolean}
*/
var hasLocalChanges = function (selection) {
// ensure this selection supports flow versioning above
if (supportsFlowVersioning(selection) === false) {
return false;
}
var versionControlInformation;
if (selection.empty()) {
// check bread crumbs for version control information in the current group
var breadcrumbEntities = nfNgBridge.injector.get('breadcrumbsCtrl').getBreadcrumbs();
if (breadcrumbEntities.length > 0) {
var breadcrumbEntity = breadcrumbEntities[breadcrumbEntities.length - 1];
if (breadcrumbEntity.permissions.canRead) {
versionControlInformation = breadcrumbEntity.breadcrumb.versionControlInformation;
} else {
return false;
}
} else {
return false;
}
} else {
var processGroupData = selection.datum();
versionControlInformation = processGroupData.component.versionControlInformation;
}
if (nfCommon.isUndefinedOrNull(versionControlInformation)) {
return false;
}
// check the selection for version control information
return versionControlInformation.modified === true;
};
/**
* Returns whether the process group supports changing the flow version.
*
* @param selection
* @returns {boolean}
*/
var supportsChangeFlowVersion = function (selection) {
// ensure this selection supports flow versioning above
if (supportsFlowVersioning(selection) === false) {
return false;
}
var versionControlInformation;
if (selection.empty()) {
// check bread crumbs for version control information in the current group
var breadcrumbEntities = nfNgBridge.injector.get('breadcrumbsCtrl').getBreadcrumbs();
if (breadcrumbEntities.length > 0) {
var breadcrumbEntity = breadcrumbEntities[breadcrumbEntities.length - 1];
if (breadcrumbEntity.permissions.canRead) {
versionControlInformation = breadcrumbEntity.breadcrumb.versionControlInformation;
} else {
return false;
}
} else {
return false;
}
} else {
var processGroupData = selection.datum();
versionControlInformation = processGroupData.component.versionControlInformation;
}
if (nfCommon.isUndefinedOrNull(versionControlInformation)) {
return false;
}
// check the selection for version control information
return versionControlInformation.modified === false;
};
/**
* Determines whether the current selection supports stopping flow versioning.
*
@ -640,9 +757,10 @@
{id: 'version-menu-item', groupMenuItem: {clazz: 'fa', text: 'Version'}, menuItems: [
{id: 'start-version-control-menu-item', condition: supportsStartFlowVersioning, menuItem: {clazz: 'fa fa-upload', text: 'Start version control', action: 'saveFlowVersion'}},
{separator: true},
{id: 'commit-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa fa-upload', text: 'Commit local changes', action: 'saveFlowVersion'}},
{id: 'revert-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa fa-undo', text: 'Revert local changes', action: 'revertLocalChanges'}},
{id: 'change-version-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa', text: 'Change version', action: 'changeFlowVersion'}},
{id: 'commit-menu-item', condition: supportsCommitFlowVersion, menuItem: {clazz: 'fa fa-upload', text: 'Commit local changes', action: 'saveFlowVersion'}},
{id: 'local-changes-menu-item', condition: hasLocalChanges, menuItem: {clazz: 'fa', text: 'Show local changes', action: 'showLocalChanges'}},
{id: 'revert-menu-item', condition: hasLocalChanges, menuItem: {clazz: 'fa fa-undo', text: 'Revert local changes', action: 'revertLocalChanges'}},
{id: 'change-version-menu-item', condition: supportsChangeFlowVersion, menuItem: {clazz: 'fa', text: 'Change version', action: 'changeFlowVersion'}},
{separator: true},
{id: 'stop-version-control-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa', text: 'Stop version control', action: 'stopVersionControl'}}
]},

View File

@ -30,10 +30,11 @@
'nf.Client',
'nf.CanvasUtils',
'nf.ProcessGroup',
'nf.ProcessGroupConfiguration',
'nf.Graph',
'nf.Birdseye'],
function ($, nfNgBridge, nfErrorHandler, nfDialog, nfCommon, nfClient, nfCanvasUtils, nfProcessGroup, nfGraph, nfBirdseye) {
return (nf.FlowVersion = factory($, nfNgBridge, nfErrorHandler, nfDialog, nfCommon, nfClient, nfCanvasUtils, nfProcessGroup, nfGraph, nfBirdseye));
function ($, nfNgBridge, nfErrorHandler, nfDialog, nfCommon, nfClient, nfCanvasUtils, nfProcessGroup, nfProcessGroupConfiguration, nfGraph, nfBirdseye) {
return (nf.FlowVersion = factory($, nfNgBridge, nfErrorHandler, nfDialog, nfCommon, nfClient, nfCanvasUtils, nfProcessGroup, nfProcessGroupConfiguration, nfGraph, nfBirdseye));
});
} else if (typeof exports === 'object' && typeof module === 'object') {
module.exports = (nf.FlowVerison =
@ -45,6 +46,7 @@
require('nf.Client'),
require('nf.CanvasUtils'),
require('nf.ProcessGroup'),
require('nf.ProcessGroupConfiguration'),
require('nf.Graph'),
require('nf.Birdseye')));
} else {
@ -56,10 +58,11 @@
root.nf.Client,
root.nf.CanvasUtils,
root.nf.ProcessGroup,
root.nf.ProcessGroupConfiguration,
root.nf.Graph,
root.nf.Birdseye);
}
}(this, function ($, nfNgBridge, nfErrorHandler, nfDialog, nfCommon, nfClient, nfCanvasUtils, nfProcessGroup, nfGraph, nfBirdseye) {
}(this, function ($, nfNgBridge, nfErrorHandler, nfDialog, nfCommon, nfClient, nfCanvasUtils, nfProcessGroup, nfProcessGroupConfiguration, nfGraph, nfBirdseye) {
'use strict';
var serverTimeOffset = null;
@ -96,6 +99,55 @@
$('#save-flow-version-process-group-id').removeData('versionControlInformation').removeData('revision').text('');
};
/**
* Reset the revert local changes dialog.
*/
var resetRevertLocalChangesDialog = function () {
$('#revert-local-changes-process-group-id').text('');
clearLocalChangesGrid($('#revert-local-changes-table'), $('#revert-local-changes-filter'), $('#displayed-revert-local-changes-entries'), $('#total-revert-local-changes-entries'));
};
/**
* Reset the show local changes dialog.
*/
var resetShowLocalChangesDialog = function () {
clearLocalChangesGrid($('#show-local-changes-table'), $('#show-local-changes-filter'), $('#displayed-show-local-changes-entries'), $('#total-show-local-changes-entries'));
};
/**
* Clears the local changes grid.
*/
var clearLocalChangesGrid = function (localChangesTable, filterInput, displayedLabel, totalLabel) {
var localChangesGrid = localChangesTable.data('gridInstance');
if (nfCommon.isDefinedAndNotNull(localChangesGrid)) {
localChangesGrid.setSelectedRows([]);
localChangesGrid.resetActiveCell();
var localChangesData = localChangesGrid.getData();
localChangesData.setItems([]);
}
filterInput.val('');
displayedLabel.text('0');
totalLabel.text('0');
}
/**
* Clears the version grid
*/
var clearFlowVersionsGrid = function () {
var importFlowVersionGrid = $('#import-flow-version-table').data('gridInstance');
if (nfCommon.isDefinedAndNotNull(importFlowVersionGrid)) {
importFlowVersionGrid.setSelectedRows([]);
importFlowVersionGrid.resetActiveCell();
var importFlowVersionData = importFlowVersionGrid.getData();
importFlowVersionData.setItems([]);
}
};
/**
* Reset the import flow version dialog.
*/
@ -110,14 +162,7 @@
$('#import-flow-version-bucket').text('').hide();
$('#import-flow-version-name').text('').hide();
var importFlowVersionGrid = $('#import-flow-version-table').data('gridInstance');
if (nfCommon.isDefinedAndNotNull(importFlowVersionGrid)) {
importFlowVersionGrid.setSelectedRows([]);
importFlowVersionGrid.resetActiveCell();
var importFlowVersionData = importFlowVersionGrid.getData();
importFlowVersionData.setItems([]);
}
clearFlowVersionsGrid();
$('#import-flow-version-process-group-id').removeData('versionControlInformation').removeData('revision').text('');
@ -131,9 +176,10 @@
* @param dialog
* @param registryCombo
* @param bucketCombo
* @param flowCombo
* @returns {deferred}
*/
var loadRegistries = function (dialog, registryCombo, bucketCombo, selectBucket) {
var loadRegistries = function (dialog, registryCombo, bucketCombo, flowCombo, selectBucket) {
return $.ajax({
type: 'GET',
url: '../nifi-api/flow/registries',
@ -167,7 +213,7 @@
registryCombo.combo({
options: registries,
select: function (selectedOption) {
selectRegistry(dialog, selectedOption, bucketCombo, selectBucket)
selectRegistry(dialog, selectedOption, bucketCombo, flowCombo, selectBucket)
}
});
}).fail(nfErrorHandler.handleAjaxError);
@ -178,6 +224,7 @@
*
* @param registryIdentifier
* @param bucketCombo
* @param selectBucket
* @returns {*}
*/
var loadBuckets = function (registryIdentifier, bucketCombo, selectBucket) {
@ -224,9 +271,10 @@
* @param dialog
* @param selectedOption
* @param bucketCombo
* @param flowCombo
* @param selectBucket
*/
var selectRegistry = function (dialog, selectedOption, bucketCombo, selectBucket) {
var selectRegistry = function (dialog, selectedOption, bucketCombo, flowCombo, selectBucket) {
var showNoBucketsAvailable = function () {
bucketCombo.combo('destroy').combo({
options: [{
@ -243,6 +291,28 @@
if (selectedOption.disabled === true) {
showNoBucketsAvailable();
} else {
bucketCombo.combo('destroy').combo({
options: [{
text: 'Loading buckets...',
value: null,
optionClass: 'unset',
disabled: true
}]
});
if (nfCommon.isDefinedAndNotNull(flowCombo)) {
flowCombo.combo('destroy').combo({
options: [{
text: 'Loading flows...',
value: null,
optionClass: 'unset',
disabled: true
}]
});
clearFlowVersionsGrid();
}
loadBuckets(selectedOption.value, bucketCombo, selectBucket).fail(function () {
showNoBucketsAvailable();
});
@ -344,7 +414,7 @@
return nfCommon.formatDateTime(date);
};
// define the column model for the controller services table
// define the column model for flow versions
var importFlowVersionColumns = [
{
id: 'version',
@ -426,6 +496,185 @@
importFlowVersionTable.data('gridInstance', importFlowVersionGrid);
};
/**
* Initializes the specified local changes table.
*
* @param localChangesTable
* @param filterInput
* @param displayedLabel
* @param totalLabel
*/
var initLocalChangesTable = function (localChangesTable, filterInput, displayedLabel, totalLabel) {
var getFilterText = function () {
return filterInput.val();
};
var applyFilter = function () {
// get the dataview
var localChangesGrid = localChangesTable.data('gridInstance');
// ensure the grid has been initialized
if (nfCommon.isDefinedAndNotNull(localChangesGrid)) {
var localChangesData = localChangesGrid.getData();
// update the search criteria
localChangesData.setFilterArgs({
searchString: getFilterText()
});
localChangesData.refresh();
}
};
var filter = function (item, args) {
if (args.searchString === '') {
return true;
}
try {
// perform the row filtering
var filterExp = new RegExp(args.searchString, 'i');
} catch (e) {
// invalid regex
return false;
}
// determine if the item matches the filter
var matchesId = item['componentId'].search(filterExp) >= 0;
var matchesComponent = item['componentName'].search(filterExp) >= 0;
var matchesDifferenceType = item['differenceType'].search(filterExp) >= 0;
var matchesDifference = item['difference'].search(filterExp) >= 0;
return matchesId || matchesComponent || matchesDifferenceType || matchesDifference;
};
// initialize the component state filter
filterInput.on('keyup', function () {
applyFilter();
});
var valueFormatter = function (row, cell, value, columnDef, dataContext) {
return nfCommon.escapeHtml(value);
};
var actionsFormatter = function (row, cell, value, columnDef, dataContext) {
var markup = '';
if (dataContext.differenceType !== 'Component Removed' && nfCommon.isDefinedAndNotNull(dataContext.processGroupId)) {
markup += '<div class="pointer go-to-component fa fa-long-arrow-right" title="Go To" style="margin-top: 2px" ></div>';
}
return markup;
};
// define the column model for local changes
var localChangesColumns = [
{
id: 'component',
name: 'Component Name',
field: 'componentName',
formatter: valueFormatter,
sortable: true,
resizable: true
},
{
id: 'differenceType',
name: 'Type',
field: 'differenceType',
formatter: valueFormatter,
sortable: true,
resizable: true
},
{
id: 'difference',
name: 'Difference',
field: 'difference',
formatter: valueFormatter,
sortable: true,
resizable: true,
minWidth: 300
},
{
id: 'actions',
name: '&nbsp;',
formatter: actionsFormatter,
sortable: false,
resizable: false,
width: 25
}
];
// initialize the dataview
var localChangesData = new Slick.Data.DataView({
inlineFilters: false
});
localChangesData.setFilterArgs({
searchString: '',
property: 'component'
});
localChangesData.setFilter(filter);
// initialize the sort
sort({
columnId: 'version',
sortAsc: false
}, localChangesData);
// initialize the grid
var localChangesGrid = new Slick.Grid(localChangesTable, localChangesData, localChangesColumns, gridOptions);
localChangesGrid.setSelectionModel(new Slick.RowSelectionModel());
localChangesGrid.registerPlugin(new Slick.AutoTooltips());
localChangesGrid.setSortColumn('version', false);
localChangesGrid.onSort.subscribe(function (e, args) {
sort({
columnId: args.sortCol.id,
sortAsc: args.sortAsc
}, localChangesData);
});
// configure a click listener
localChangesGrid.onClick.subscribe(function (e, args) {
var target = $(e.target);
// get the node at this row
var componentDifference = localChangesData.getItem(args.row);
// determine the desired action
if (localChangesGrid.getColumns()[args.cell].id === 'actions') {
if (target.hasClass('go-to-component')) {
if (componentDifference.componentType === 'Controller Service') {
nfProcessGroupConfiguration.showConfiguration(componentDifference.processGroupId).done(function () {
nfProcessGroupConfiguration.selectControllerService(componentDifference.componentId);
});
} else {
nfCanvasUtils.showComponent(componentDifference.processGroupId, componentDifference.componentId);
}
}
}
});
// wire up the dataview to the grid
localChangesData.onRowCountChanged.subscribe(function (e, args) {
localChangesGrid.updateRowCount();
localChangesGrid.render();
// update the total number of displayed items
displayedLabel.text(nfCommon.formatInteger(args.current));
});
localChangesData.onRowsChanged.subscribe(function (e, args) {
localChangesGrid.invalidateRows(args.rows);
localChangesGrid.render();
});
localChangesData.syncGridSelection(localChangesGrid, true);
// hold onto an instance of the grid
localChangesTable.data('gridInstance', localChangesGrid);
// initialize the number of display items
displayedLabel.text('0');
totalLabel.text('0');
};
/**
* Shows the import flow version dialog.
*/
@ -450,7 +699,7 @@
disabled: true
}]
}).show();
$('#import-flow-version-name-combo').combo('destroy').combo({
var flowCombo = $('#import-flow-version-name-combo').combo('destroy').combo({
options: [{
text: 'Loading flows...',
value: null,
@ -459,7 +708,7 @@
}]
}).show();
loadRegistries($('#import-flow-version-dialog'), registryCombo, bucketCombo, selectBucketImportVersion).done(function () {
loadRegistries($('#import-flow-version-dialog'), registryCombo, bucketCombo, flowCombo, selectBucketImportVersion).done(function () {
// show the import dialog
$('#import-flow-version-dialog').modal('setHeaderText', 'Import Version').modal('setButtonModel', [{
buttonText: 'Import',
@ -619,6 +868,19 @@
* @param selectedBucket
*/
var selectBucketImportVersion = function (selectedBucket) {
// mark the flows as loading
$('#import-flow-version-name-combo').combo('destroy').combo({
options: [{
text: 'Loading flows...',
value: null,
optionClass: 'unset',
disabled: true
}]
});
// clear the flow versions grid
clearFlowVersionsGrid();
var selectedRegistry = $('#import-flow-version-registry-combo').combo('getSelectedOption');
// load the flows for the currently selected registry and bucket
@ -646,7 +908,6 @@
}
}),
'component': {
'name': selectedFlow.text, // TODO - name from versioned PG?
'position': {
'x': pt.x,
'y': pt.y
@ -966,193 +1227,70 @@
progressBar.append(label);
};
return {
init: function (timeOffset) {
serverTimeOffset = timeOffset;
// initialize the flow version dialog
$('#save-flow-version-dialog').modal({
scrollableContentStyle: 'scrollable',
headerText: 'Save Flow Version',
buttons: [{
buttonText: 'Save',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
disabled: function () {
if ($('#save-flow-version-registry-combo').is(':visible')) {
var selectedRegistry = $('#save-flow-version-registry-combo').combo('getSelectedOption');
var selectedBucket = $('#save-flow-version-bucket-combo').combo('getSelectedOption');
if (nfCommon.isDefinedAndNotNull(selectedRegistry) && nfCommon.isDefinedAndNotNull(selectedBucket)) {
return selectedRegistry.disabled === true || selectedBucket.disabled === true;
} else {
return true;
}
} else {
return false;
}
},
handler: {
click: function () {
var processGroupId = $('#save-flow-version-process-group-id').text();
saveFlowVersion().done(function (response) {
updateVersionControlInformation(processGroupId, response.versionControlInformation);
// close the dialog
$('#save-flow-version-dialog').modal('hide');
});
}
}
}, {
buttonText: 'Cancel',
color: {
base: '#E3E8EB',
hover: '#C7D2D7',
text: '#004849'
},
handler: {
click: function () {
$(this).modal('hide');
}
}
}],
handler: {
close: function () {
resetSaveFlowVersionDialog();
}
}
});
// initialize the import flow version dialog
$('#import-flow-version-dialog').modal({
scrollableContentStyle: 'scrollable',
handler: {
close: function () {
resetImportFlowVersionDialog();
}
}
});
// configure the drop request status dialog
$('#change-version-status-dialog').modal({
scrollableContentStyle: 'scrollable',
headerText: 'Change Flow Version',
handler: {
close: function () {
// clear the current button model
$('#change-version-status-dialog').modal('setButtonModel', []);
}
}
});
// handle the click for the process group import
$('#import-process-group-link').on('click', function() {
showImportFlowVersionDialog();
});
// initialize the import flow version table
initImportFlowVersionTable();
},
/**
* Shows the flow version dialog.
* Shows local changes for the specified process group.
*
* @param processGroupId
* @param localChangesTable
* @param totalLabel
*/
showFlowVersionDialog: function (processGroupId) {
var focusName = true;
var loadLocalChanges = function (processGroupId, localChangesTable, totalLabel) {
var localChangesGrid = localChangesTable.data('gridInstance');
var localChangesData = localChangesGrid.getData();
return $.Deferred(function (deferred) {
getVersionControlInformation(processGroupId).done(function (groupVersionControlInformation) {
// record the revision
$('#save-flow-version-process-group-id').data('revision', groupVersionControlInformation.processGroupRevision).text(processGroupId);
// begin the update
localChangesData.beginUpdate();
if (nfCommon.isDefinedAndNotNull(groupVersionControlInformation.versionControlInformation)) {
var versionControlInformation = groupVersionControlInformation.versionControlInformation;
// remove the current versions
localChangesGrid.setSelectedRows([]);
localChangesGrid.resetActiveCell();
localChangesData.setItems([]);
// update the registry and bucket visibility
$('#save-flow-version-registry').text(versionControlInformation.registryName).show();
$('#save-flow-version-bucket').text(versionControlInformation.bucketName).show();
$('#save-flow-version-label').text(versionControlInformation.version + 1);
return $.ajax({
type: 'GET',
url: '../nifi-api/process-groups/' + encodeURIComponent(processGroupId) + '/local-modifications',
dataType: 'json'
}).done(function (response) {
if (nfCommon.isDefinedAndNotNull(response.componentDifferences) && response.componentDifferences.length > 0) {
var totalDifferences = 0;
$.each(response.componentDifferences, function (_, componentDifference) {
$.each(componentDifference.differences, function (_, difference) {
localChangesData.addItem({
id: totalDifferences++,
componentId: componentDifference.componentId,
componentName: componentDifference.componentName,
componentType: componentDifference.componentType,
processGroupId: componentDifference.processGroupId,
differenceType: difference.differenceType,
difference: difference.difference
});
});
});
$('#save-flow-version-name').text(versionControlInformation.flowName).show();
$('#save-flow-version-description').text(versionControlInformation.flowDescription).show();
// end the update
localChangesData.endUpdate();
// record the versionControlInformation
$('#save-flow-version-process-group-id').data('versionControlInformation', versionControlInformation);
// resort
localChangesData.reSort();
localChangesGrid.invalidate();
// reposition the version label
$('#save-flow-version-label').css('margin-top', '-15px');
focusName = false;
deferred.resolve();
// update the total displayed
totalLabel.text(nfCommon.formatInteger(totalDifferences));
} else {
// update the registry and bucket visibility
var registryCombo = $('#save-flow-version-registry-combo').combo('destroy').combo({
options: [{
text: 'Loading registries...',
value: null,
optionClass: 'unset',
disabled: true
}]
}).show();
var bucketCombo = $('#save-flow-version-bucket-combo').combo('destroy').combo({
options: [{
text: 'Loading buckets...',
value: null,
optionClass: 'unset',
disabled: true
}]
}).show();
// set the initial version
$('#save-flow-version-label').text(1);
$('#save-flow-version-name-field').show();
$('#save-flow-version-description-field').show();
// reposition the version label
$('#save-flow-version-label').css('margin-top', '0');
loadRegistries($('#save-flow-version-dialog'), registryCombo, bucketCombo, selectBucketSaveFlowVersion).done(function () {
deferred.resolve();
}).fail(function () {
deferred.reject();
nfDialog.showOkDialog({
headerText: 'Local Changes',
dialogContent: 'This Process Group does not have any local changes.'
});
}
}).fail(nfErrorHandler.handleAjaxError);
}).done(function () {
$('#save-flow-version-dialog').modal('show');
if (focusName) {
$('#save-flow-version-name-field').focus();
} else {
$('#save-flow-version-change-comments').focus();
}
}).fail(function () {
$('#save-flow-version-dialog').modal('refreshButtons');
}).promise();
},
};
/**
* Reverts local changes for the specified Process Group.
* Revert local changes for the specified process group.
*
* @param processGroupId
*/
revertLocalChanges: function (processGroupId) {
// TODO update to show user the ramifications of reverting for confirmation
// prompt the user before reverting
nfDialog.showYesNoDialog({
headerText: 'Revert Changes',
dialogContent: 'Are you sure you want to revert changes? All flow configuration changes will be reverted to the last version.',
noText: 'Cancel',
yesText: 'Revert',
yesHandler: function () {
var revertLocalChanges = function (processGroupId) {
getVersionControlInformation(processGroupId).done(function (response) {
if (nfCommon.isDefinedAndNotNull(response.versionControlInformation)) {
var revertTimer = null;
@ -1321,7 +1459,263 @@
});
}
}).fail(nfErrorHandler.handleAjaxError);
};
return {
init: function (timeOffset) {
serverTimeOffset = timeOffset;
// initialize the flow version dialog
$('#save-flow-version-dialog').modal({
scrollableContentStyle: 'scrollable',
headerText: 'Save Flow Version',
buttons: [{
buttonText: 'Save',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
disabled: function () {
if ($('#save-flow-version-registry-combo').is(':visible')) {
var selectedRegistry = $('#save-flow-version-registry-combo').combo('getSelectedOption');
var selectedBucket = $('#save-flow-version-bucket-combo').combo('getSelectedOption');
if (nfCommon.isDefinedAndNotNull(selectedRegistry) && nfCommon.isDefinedAndNotNull(selectedBucket)) {
return selectedRegistry.disabled === true || selectedBucket.disabled === true;
} else {
return true;
}
} else {
return false;
}
},
handler: {
click: function () {
var processGroupId = $('#save-flow-version-process-group-id').text();
saveFlowVersion().done(function (response) {
updateVersionControlInformation(processGroupId, response.versionControlInformation);
});
$(this).modal('hide');
}
}
}, {
buttonText: 'Cancel',
color: {
base: '#E3E8EB',
hover: '#C7D2D7',
text: '#004849'
},
handler: {
click: function () {
$(this).modal('hide');
}
}
}],
handler: {
close: function () {
resetSaveFlowVersionDialog();
}
}
});
// initialize the import flow version dialog
$('#import-flow-version-dialog').modal({
scrollableContentStyle: 'scrollable',
handler: {
close: function () {
resetImportFlowVersionDialog();
}
}
});
// configure the drop request status dialog
$('#change-version-status-dialog').modal({
scrollableContentStyle: 'scrollable',
headerText: 'Change Flow Version',
handler: {
close: function () {
// clear the current button model
$('#change-version-status-dialog').modal('setButtonModel', []);
}
}
});
// init the revert local changes dialog
$('#revert-local-changes-dialog').modal({
scrollableContentStyle: 'scrollable',
headerText: 'Revert Local Changes',
buttons: [{
buttonText: 'Revert',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
handler: {
click: function () {
var processGroupId = $('#revert-local-changes-process-group-id').text();
revertLocalChanges(processGroupId);
$(this).modal('hide');
}
}
}, {
buttonText: 'Cancel',
color: {
base: '#E3E8EB',
hover: '#C7D2D7',
text: '#004849'
},
handler: {
click: function () {
$(this).modal('hide');
}
}
}],
handler: {
close: function () {
resetRevertLocalChangesDialog();
}
}
});
// init the show local changes dialog
$('#show-local-changes-dialog').modal({
scrollableContentStyle: 'scrollable',
headerText: 'Local Changes',
buttons: [{
buttonText: 'Close',
color: {
base: '#728E9B',
hover: '#004849',
text: '#ffffff'
},
handler: {
click: function () {
$(this).modal('hide');
}
}
}],
handler: {
close: function () {
resetShowLocalChangesDialog();
}
}
});
// handle the click for the process group import
$('#import-process-group-link').on('click', function() {
showImportFlowVersionDialog();
});
// initialize the import flow version table
initImportFlowVersionTable();
initLocalChangesTable($('#revert-local-changes-table'), $('#revert-local-changes-filter'), $('#displayed-revert-local-changes-entries'), $('#total-revert-local-changes-entries'));
initLocalChangesTable($('#show-local-changes-table'), $('#show-local-changes-filter'), $('#displayed-show-local-changes-entries'), $('#total-show-local-changes-entries'));
},
/**
* Shows the flow version dialog.
*
* @param processGroupId
*/
showFlowVersionDialog: function (processGroupId) {
var focusName = true;
return $.Deferred(function (deferred) {
getVersionControlInformation(processGroupId).done(function (groupVersionControlInformation) {
// record the revision
$('#save-flow-version-process-group-id').data('revision', groupVersionControlInformation.processGroupRevision).text(processGroupId);
if (nfCommon.isDefinedAndNotNull(groupVersionControlInformation.versionControlInformation)) {
var versionControlInformation = groupVersionControlInformation.versionControlInformation;
// update the registry and bucket visibility
$('#save-flow-version-registry').text(versionControlInformation.registryName).show();
$('#save-flow-version-bucket').text(versionControlInformation.bucketName).show();
$('#save-flow-version-label').text(versionControlInformation.version + 1);
$('#save-flow-version-name').text(versionControlInformation.flowName).show();
$('#save-flow-version-description').text(versionControlInformation.flowDescription).show();
// record the versionControlInformation
$('#save-flow-version-process-group-id').data('versionControlInformation', versionControlInformation);
// reposition the version label
$('#save-flow-version-label').css('margin-top', '-15px');
focusName = false;
deferred.resolve();
} else {
// update the registry and bucket visibility
var registryCombo = $('#save-flow-version-registry-combo').combo('destroy').combo({
options: [{
text: 'Loading registries...',
value: null,
optionClass: 'unset',
disabled: true
}]
}).show();
var bucketCombo = $('#save-flow-version-bucket-combo').combo('destroy').combo({
options: [{
text: 'Loading buckets...',
value: null,
optionClass: 'unset',
disabled: true
}]
}).show();
// set the initial version
$('#save-flow-version-label').text(1);
$('#save-flow-version-name-field').show();
$('#save-flow-version-description-field').show();
// reposition the version label
$('#save-flow-version-label').css('margin-top', '0');
loadRegistries($('#save-flow-version-dialog'), registryCombo, bucketCombo, null, selectBucketSaveFlowVersion).done(function () {
deferred.resolve();
}).fail(function () {
deferred.reject();
});
}
}).fail(nfErrorHandler.handleAjaxError);
}).done(function () {
$('#save-flow-version-dialog').modal('show');
if (focusName) {
$('#save-flow-version-name-field').focus();
} else {
$('#save-flow-version-change-comments').focus();
}
}).fail(function () {
$('#save-flow-version-dialog').modal('refreshButtons');
}).promise();
},
/**
* Reverts local changes for the specified Process Group.
*
* @param processGroupId
*/
revertLocalChanges: function (processGroupId) {
loadLocalChanges(processGroupId, $('#revert-local-changes-table'), $('#total-revert-local-changes-entries')).done(function () {
$('#revert-local-changes-process-group-id').text(processGroupId);
$('#revert-local-changes-dialog').modal('show');
});
},
/**
* Shows local changes for the specified process group.
*
* @param processGroupId
*/
showLocalChanges: function (processGroupId) {
loadLocalChanges(processGroupId, $('#show-local-changes-table'), $('#total-show-local-changes-entries')).done(function () {
$('#show-local-changes-dialog').modal('show');
});
},
@ -1407,8 +1801,8 @@
stopVersionControl: function (processGroupId) {
// prompt the user before disconnecting
nfDialog.showYesNoDialog({
headerText: 'Disconnect',
dialogContent: 'Are you sure you want to disconnect?',
headerText: 'Stop Version Control',
dialogContent: 'Are you sure you want to stop version control?',
noText: 'Cancel',
yesText: 'Disconnect',
yesHandler: function () {
@ -1434,7 +1828,7 @@
nfDialog.showOkDialog({
headerText: 'Disconnect',
dialogContent: 'This Process Group has been disconnected.'
dialogContent: 'This Process Group is no longer under version control.'
});
}).fail(nfErrorHandler.handleAjaxError);
} else {