Browse Source

HUE-8155 [metadata] Make it possible to remove custom metadata entries in the Table Browser

Johan Ahlen 7 years ago
parent
commit
e5ae685b8c

+ 11 - 11
desktop/core/src/desktop/static/desktop/js/apiHelper.js

@@ -1669,18 +1669,18 @@ var ApiHelper = (function () {
 
   ApiHelper.prototype.updateNavigatorProperties = function (options) {
     var self = this;
-    return self.simplePost(NAV_URLS.UPDATE_PROPERTIES, {
-      id: ko.mapping.toJSON(options.identity),
-      properties: ko.mapping.toJSON(options.properties)
-    }, options)
-  };
+    var data = { id: ko.mapping.toJSON(options.identity) };
 
-  ApiHelper.prototype.updateNavigatorCustomProperties = function (options) {
-    var self = this;
-    return self.simplePost(NAV_URLS.UPDATE_PROPERTIES, {
-      id: ko.mapping.toJSON(options.identity),
-      metadata: ko.mapping.toJSON(options.customProperties)
-    }, options)
+    if (options.properties) {
+      data.properties = ko.mapping.toJSON(options.properties);
+    }
+    if (options.customMetadata) {
+      data.customMetadata = ko.mapping.toJSON(options.customMetadata);
+    }
+    if (options.deletedCustomMetadataKeys) {
+      data.deletedCustomMetadataKeys = ko.mapping.toJSON(options.deletedCustomMetadataKeys);
+    }
+    return self.simplePost(NAV_URLS.UPDATE_PROPERTIES, data, options)
   };
 
   /**

+ 10 - 9
desktop/core/src/desktop/static/desktop/js/dataCatalog.js

@@ -1115,7 +1115,7 @@ var DataCatalog = (function () {
       return applyCancellable(new CancellablePromise(deferred, undefined, cancellablePromises), options);
     };
 
-    DataCatalogEntry.prototype.setNavigatorCustomProperties = function (customProperties, apiOptions) {
+    DataCatalogEntry.prototype.updateNavigatorCustomMetadata = function (customMetadata, deletedCustomMetadataKeys, apiOptions) {
       var self = this;
       var deferred = $.Deferred();
 
@@ -1128,12 +1128,13 @@ var DataCatalog = (function () {
         }
         self.getNavigatorMeta(apiOptions).done(function (navigatorMeta) {
           if (navigatorMeta) {
-            ApiHelper.getInstance().updateNavigatorCustomProperties({
+            ApiHelper.getInstance().updateNavigatorProperties({
               identity: navigatorMeta.identity,
-              customProperties: customProperties
-            }).done(function (updateResponse) {
-              if (updateResponse.entity) {
-                self.navigatorMeta = updateResponse.entity;
+              customMetadata: customMetadata,
+              deletedCustomMetadataKeys: deletedCustomMetadataKeys
+            }).done(function (entity) {
+              if (entity) {
+                self.navigatorMeta = entity;
                 self.navigatorMetaPromise = $.Deferred().resolve(self.navigatorMeta).promise();
                 self.saveLater();
                 deferred.resolve(self.navigatorMeta);
@@ -1178,9 +1179,9 @@ var DataCatalog = (function () {
               properties: {
                 description: comment
               }
-            }).done(function (updateResponse) {
-              if (updateResponse.entity) {
-                self.navigatorMeta = updateResponse.entity;
+            }).done(function (entity) {
+              if (entity) {
+                self.navigatorMeta = entity;
                 self.navigatorMetaPromise = $.Deferred().resolve(self.navigatorMeta).promise();
                 self.saveLater();
               }

+ 11 - 4
desktop/core/src/desktop/templates/ko_components/ko_nav_properties.mako

@@ -182,12 +182,19 @@ from django.utils.translation import ugettext as _
         $(document).off('click.navProperties');
         self.editMode(false);
         if (ko.mapping.toJSON(self.editProperties()) !== ko.mapping.toJSON(self.properties())) {
-          var newProperties = {};
-          self.editProperties().forEach(function(property) {
-            newProperties[property.key()] = property.value();
+          var customMetadata = {};
+          self.editProperties().forEach(function (property) {
+            customMetadata[property.key()] = property.value();
           });
+          var deletedCustomMetadataKeys = [];
+          self.properties().forEach(function (property) {
+            if (!customMetadata[property.key()]) {
+              deletedCustomMetadataKeys.push(property.key());
+            }
+          });
+
           self.loading(true);
-          self.catalogEntry.setNavigatorCustomProperties(newProperties).always(function () {
+          self.catalogEntry.updateNavigatorCustomMetadata(customMetadata, deletedCustomMetadataKeys).always(function () {
             self.loadProperties();
           });
         }

+ 13 - 10
desktop/libs/metadata/src/metadata/navigator_api.py

@@ -72,6 +72,7 @@ def error_handler(view_fn):
         response['message'] = force_unicode(e.message)
     except Exception, e:
       message = force_unicode(e)
+      response['message'] = message
       LOG.exception(message)
 
     return JsonResponse(response, status=status)
@@ -451,28 +452,30 @@ def delete_tags(request):
 @require_POST
 @error_handler
 def update_properties(request):
-  response = {'status': -1}
-
   api = NavigatorApi(request.user)
   entity_id = json.loads(request.POST.get('id', '""'))
   properties = json.loads(request.POST.get('properties', '{}')) # Entity properties
-  metadata = json.loads(request.POST.get('metadata', '{}')) # Aka "Custom Metadata"
+  custom_metadata = json.loads(request.POST.get('customMetadata', '{}')) # Aka "Custom Metadata"
+  deleted_custom_metadata_keys = json.loads(request.POST.get('deletedCustomMetadataKeys', '[]'))
 
   is_allowed = request.user.has_hue_permission(action='write', app='metadata')
 
   request.audit = {
     'allowed': is_allowed,
     'operation': 'NAVIGATOR_UPDATE_PROPERTIES',
-    'operationText': 'Updating metadata %s properties %s of entity %s' % (metadata, properties, entity_id)
+    'operationText': 'Updating custom metadata %s, deleted custom metadata keys %s and properties %s of entity %s' % (custom_metadata, deleted_custom_metadata_keys, properties, entity_id)
   }
 
-  if not entity_id or (not properties and not metadata) or not is_allowed:
-    response['error'] = _("update_properties requires an 'id' parameter and 'properties' or 'metadata' parameters that are non-empty dicts")
-  else:
-    response['entity'] = api.update_properties(entity_id, properties, metadata)
-    response['status'] = 0
+  if not entity_id:
+    # TODO: raise HueApiException(message="Missing required parameter 'id' for update_properties", source="Hue")
+    # source so the user knows which service that failed right away, in UI: "[source] responded with error: [message]"
+    raise Exception("Missing required parameter 'id' for the Hue update_properties API.")
 
-  return JsonResponse(response)
+  if not is_allowed:
+    # TODO: HueAuthException?
+    raise Exception("The user does not have proper Hue permissions to update Navigator properties.")
+
+  return JsonResponse(api.update_properties(entity_id, properties, custom_metadata, deleted_custom_metadata_keys))
 
 
 @require_POST

+ 8 - 3
desktop/libs/metadata/src/metadata/navigator_client.py

@@ -473,11 +473,16 @@ class NavigatorApi(object):
     return self.update_entity(entity, tags=new_tags)
 
 
-  def update_properties(self, entity_id, properties, metadata=None):
+  def update_properties(self, entity_id, properties, custom_properties=None, deleted_custom_properties=None):
     entity = self.get_entity(entity_id)
-    if metadata:
+    if custom_properties:
       properties['properties'] = entity['properties'] or {}
-      properties['properties'].update(metadata)
+      properties['properties'].update(custom_properties)
+    if deleted_custom_properties:
+      properties['properties'] = entity['properties'] or {}
+      for key in deleted_custom_properties:
+        if key in properties['properties']:
+          del properties['properties'][key]
     return self.update_entity(entity, **properties)