exceptionfactory commented on a change in pull request #319:
URL: https://github.com/apache/nifi-registry/pull/319#discussion_r626113532



##########
File path: 
nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java
##########
@@ -291,6 +294,42 @@ public Response createFlowVersion(
         return 
Response.status(Response.Status.OK).entity(createdSnapshot).build();
     }
 
+    @POST
+    @Path("{flowId}/versions/import")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Upload flow version",

Review comment:
       Should this be changed to Import flow version?
   ```suggestion
               value = "Import flow version",
   ```

##########
File path: 
nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java
##########
@@ -291,6 +294,42 @@ public Response createFlowVersion(
         return 
Response.status(Response.Status.OK).entity(createdSnapshot).build();
     }
 
+    @POST
+    @Path("{flowId}/versions/import")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Upload flow version",
+            notes = "Uploads the next version of a flow. The version number of 
the object being created must be the " +
+                    "next available version integer. Flow versions are 
immutable after they are created.",

Review comment:
       The notes make it sound like the version number must be specified, as 
opposed to being generated.
   ```suggestion
               notes = "Import the next version of a flow. The version number 
of the object being created will be the " +
                       "next available version integer. Flow versions are 
immutable after they are created.",
   ```

##########
File path: 
nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/service/StandardServiceFacade.java
##########
@@ -360,6 +362,48 @@ public VersionedFlowSnapshot getLatestFlowSnapshot(final 
String flowIdentifier)
         return lastSnapshot;
     }
 
+    @Override
+    public VersionedFlowSnapshot 
importVersionedFlowSnapshot(VersionedFlowSnapshot versionedFlowSnapshot, String 
bucketIdentifier,
+                                                             String 
flowIdentifier, String comments) {
+        // set new snapshotMetadata
+        final VersionedFlowSnapshotMetadata metadata = new 
VersionedFlowSnapshotMetadata();
+        metadata.setBucketIdentifier(bucketIdentifier);
+        metadata.setFlowIdentifier(flowIdentifier);
+        metadata.setVersion(LATEST_VERSION);
+
+        // if there are new comments, then set it
+        // otherwise, keep the original comments
+        if (!StringUtils.isBlank(comments)) {
+            metadata.setComments(comments);
+        } else if (versionedFlowSnapshot.getSnapshotMetadata() != null && 
versionedFlowSnapshot.getSnapshotMetadata().getComments() != null) {

Review comment:
       Should this line check for blank comments?
   ```suggestion
           } else if (versionedFlowSnapshot.getSnapshotMetadata() != null && 
StringUtils.isNotBlank(versionedFlowSnapshot.getSnapshotMetadata().getComments()))
 {
   ```

##########
File path: 
nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/explorer/grid-list/dialogs/import-new-flow/nf-registry-import-new-flow.js
##########
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+import { Component } from '@angular/core';
+
+import NfRegistryApi from 'services/nf-registry.api';
+import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
+import { FdsSnackBarService } from '@nifi-fds/core';
+
+/**
+ * NfRegistryImportNewFlow constructor.
+ *
+ * @param nfRegistryApi         The api service.
+ * @param fdsSnackBarService    The FDS snack bar service module.
+ * @param matDialogRef          The angular material dialog ref.
+ * @param data                  The data passed into this component.
+ * @constructor
+ */
+function NfRegistryImportNewFlow(nfRegistryApi, fdsSnackBarService, 
matDialogRef, data) {
+    // Services
+    this.snackBarService = fdsSnackBarService;
+    this.nfRegistryApi = nfRegistryApi;
+    this.dialogRef = matDialogRef;
+    // local state
+    this.keepDialogOpen = false;
+    this.protocol = location.protocol;
+    this.buckets = data.buckets;
+    this.activeBucket = data.activeBucket.identifier;
+    this.writableBuckets = [];
+    this.fileToUpload = null;
+    this.fileName = null;
+    this.name = '';
+    this.description = '';
+    this.selectedBucket = {};
+    this.hoverValidity = '';
+    this.extensions = 'application/json';
+    this.multiple = false;
+}
+
+NfRegistryImportNewFlow.prototype = {
+    constructor: NfRegistryImportNewFlow,
+
+    ngOnInit: function () {
+        this.writableBuckets = this.filterWritableBuckets(this.buckets);
+
+        // if there's only 1 writable bucket, always set as the initial value 
in the bucket dropdown
+        // if opening the dialog from the explorer/grid-list, there is no 
active bucket
+        if (typeof this.activeBucket === 'undefined') {

Review comment:
       Can this be simplified to check against `undefined` without `typeof`?
   ```suggestion
           if (this.activeBucket === undefined) {
   ```

##########
File path: 
nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/BucketFlowResource.java
##########
@@ -291,6 +294,42 @@ public Response createFlowVersion(
         return 
Response.status(Response.Status.OK).entity(createdSnapshot).build();
     }
 
+    @POST
+    @Path("{flowId}/versions/import")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Upload flow version",
+            notes = "Uploads the next version of a flow. The version number of 
the object being created must be the " +
+                    "next available version integer. Flow versions are 
immutable after they are created.",
+            response = VersionedFlowSnapshot.class,
+            extensions = {
+                    @Extension(name = "access-policy", properties = {
+                            @ExtensionProperty(name = "action", value = 
"write"),
+                            @ExtensionProperty(name = "resource", value = 
"/buckets/{bucketId}") })
+            }
+    )
+    @ApiResponses({
+            @ApiResponse(code = 400, message = HttpStatusMessages.MESSAGE_400),
+            @ApiResponse(code = 401, message = HttpStatusMessages.MESSAGE_401),
+            @ApiResponse(code = 403, message = HttpStatusMessages.MESSAGE_403),
+            @ApiResponse(code = 404, message = HttpStatusMessages.MESSAGE_404),
+            @ApiResponse(code = 409, message = HttpStatusMessages.MESSAGE_409) 
})
+    public Response importVersionedFlow(
+            @PathParam("bucketId")
+            @ApiParam("The bucket identifier")
+            final String bucketId,
+            @PathParam("flowId")
+            @ApiParam(value = "The flow identifier")
+            final String flowId,
+            @ApiParam("file") final VersionedFlowSnapshot 
versionedFlowSnapshot,
+            @HeaderParam("comments") final String comments) {

Review comment:
       Recommend capitalizing this header to follow HTTP conventions:
   ```suggestion
               @HeaderParam("Comments") final String comments) {
   ```

##########
File path: 
nifi-registry-core/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/FlowsIT.java
##########
@@ -541,4 +544,171 @@ public void testFlowNameUniquePerBucket() throws 
Exception {
 
     }
 
+    @Test
+    public void testImportVersionedFlowSnapshot() {
+        final RevisionInfo initialRevision = new RevisionInfo("FlowsIT", 0L);
+
+        // Create a versionedFlowSnapshot to export
+        // Given: an empty Bucket "3" (see FlowsIT.sql) with a newly created 
flow
+
+        final String bucketId = "3";
+        final VersionedFlow flow = new VersionedFlow();
+        flow.setBucketIdentifier(bucketId);
+        flow.setName("Test Flow for creating snapshots");
+        flow.setDescription("This is a randomly named flow created by an 
integration test for the purpose of holding snapshots.");
+        flow.setRevision(initialRevision);
+
+        final VersionedFlow createdFlow = client
+                .target(createURL("buckets/{bucketId}/flows"))
+                .resolveTemplate("bucketId", bucketId)
+                .request()
+                .post(Entity.entity(flow, MediaType.APPLICATION_JSON), 
VersionedFlow.class);
+        final String flowId = createdFlow.getIdentifier();
+
+        // Create snapshotMetadata
+        final VersionedFlowSnapshotMetadata flowSnapshotMetadata = new 
VersionedFlowSnapshotMetadata();
+        flowSnapshotMetadata.setBucketIdentifier(bucketId);
+        flowSnapshotMetadata.setFlowIdentifier(flowId);
+        flowSnapshotMetadata.setComments("This is a snapshot created by an 
integration test.");
+
+        // Create a VersionedFlowSnapshot
+        final VersionedFlowSnapshot flowSnapshot = new VersionedFlowSnapshot();
+        flowSnapshot.setSnapshotMetadata(flowSnapshotMetadata);
+        flowSnapshot.setFlowContents(new VersionedProcessGroup()); // an empty 
root process group
+        flowSnapshot.getFlowContents().setName("Test Flow name");
+        flowSnapshot.getSnapshotMetadata().setVersion(-1);

Review comment:
       Recommend setting a private static final variable named LATEST_VERSION 
and reusing here and in the other test method.

##########
File path: 
nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/service/StandardServiceFacade.java
##########
@@ -360,6 +362,48 @@ public VersionedFlowSnapshot getLatestFlowSnapshot(final 
String flowIdentifier)
         return lastSnapshot;
     }
 
+    @Override
+    public VersionedFlowSnapshot 
importVersionedFlowSnapshot(VersionedFlowSnapshot versionedFlowSnapshot, String 
bucketIdentifier,
+                                                             String 
flowIdentifier, String comments) {
+        // set new snapshotMetadata
+        final VersionedFlowSnapshotMetadata metadata = new 
VersionedFlowSnapshotMetadata();
+        metadata.setBucketIdentifier(bucketIdentifier);
+        metadata.setFlowIdentifier(flowIdentifier);
+        metadata.setVersion(LATEST_VERSION);
+
+        // if there are new comments, then set it
+        // otherwise, keep the original comments
+        if (!StringUtils.isBlank(comments)) {

Review comment:
       This could be changed to `StringUtils.isNotBlank()`
   ```suggestion
           if (StringUtils.isNotBlank(comments)) {
   ```

##########
File path: 
nifi-registry-core/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.js
##########
@@ -75,6 +75,137 @@ NfRegistryApi.prototype = {
         );
     },
 
+    /**
+     * Retrieves the specified versioned flow snapshot for an existing droplet 
the registry has stored.
+     *
+     * @param {string}  dropletUri      The uri of the droplet to request.
+     * @param {number}  versionNumber   The version of the flow to request.
+     * @returns {*}
+     */
+    exportDropletVersionedSnapshot: function (dropletUri, versionNumber) {
+        var self = this;
+        var url = '../nifi-registry-api/' + dropletUri + '/versions/' + 
versionNumber + '/export';
+        var options = {
+            headers: headers,
+            observe: 'response'
+        };
+
+        return this.http.get(url, options).pipe(
+            map(function (response) {
+                // export the VersionedFlowSnapshot by creating a hidden 
anchor element
+                var stringSnapshot = 
encodeURIComponent(JSON.stringify(response.body, null, 2));

Review comment:
       Is it necessary to call `JSON.stringify()` or is it possible to just get 
the text content of response.body?  If `response.body` is already JSON, that 
means it went through an unnecessary serialization step, which would be great 
to avoid if possible.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to