diff --git a/CHANGELOG.md b/CHANGELOG.md index f7b95317..c591a343 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Support in Contributions BB to upload an icon for Talents and Capabilities. [#945](https://github.com/rokwire/rokwire-building-blocks-api/issues/945) - Added error message when the Contributions are not retrieved from the Contributions BB [#923](https://github.com/rokwire/rokwire-building-blocks-api/issues/923) - Delete contribution button. [#944](https://github.com/rokwire/rokwire-building-blocks-api/issues/944) +- Upload image icons for Talents and Capabilities from the Catalog. [#952](https://github.com/rokwire/rokwire-building-blocks-api/issues/952) +- Editing image icons for Talents and Capabilities from the Catalog. [#959](https://github.com/rokwire/rokwire-building-blocks-api/issues/959) - Add support for hybrid events in Events BB. [#955](https://github.com/rokwire/rokwire-building-blocks-api/issues/955) ### Changed diff --git a/contributions/catalog/controllers/config.py b/contributions/catalog/controllers/config.py index 6362333e..71ce0975 100644 --- a/contributions/catalog/controllers/config.py +++ b/contributions/catalog/controllers/config.py @@ -41,3 +41,4 @@ class Config(object): CORS_ENABLED = bool(os.getenv('CORS_ENABLED', 'False') == 'True') ADMIN_USERS = os.getenv('ADMIN_USERS', '') CATALOG_PORT = int(os.getenv('CATALOG_PORT', '5000')) + CONTENT_BB_IMAGE_ENDPOINT_URL = os.getenv('CONTENT_BB_IMAGE_ENDPOINT_URL', 'https://api-dev.rokwire.illinois.edu/content/image') diff --git a/contributions/catalog/controllers/contribute.py b/contributions/catalog/controllers/contribute.py index 2858c08e..43fdd072 100644 --- a/contributions/catalog/controllers/contribute.py +++ b/contributions/catalog/controllers/contribute.py @@ -17,7 +17,9 @@ import traceback import requests import datetime +import tempfile +from operator import itemgetter from flask import ( Blueprint, render_template, request, session, redirect, url_for ) @@ -199,6 +201,31 @@ def contribution_edit(contribution_id): contribution = jsonutil.add_contribution_admins(contribution, is_edit=True) # remove id from json_data del contribution["id"] + + # when it is put, since icon doesn't belong to the regular request, + # it has to be from the actual database if there is the icon value is there. + existing_contribution = get_contribution(contribution_id) + + # insert icon information into request contribution + existing_capabilities = existing_contribution["capabilities"] + existing_talents = existing_contribution["talents"] + + # match the capability and talent id and insert icon url to contribution + for existing_cap in existing_capabilities: + for i, cap in enumerate(contribution["capabilities"]): + if existing_cap["id"] == cap["id"]: + contribution["capabilities"][i]["icon"] = existing_cap["icon"] + for existing_tal in existing_talents: + for i, tal in enumerate(contribution["talents"]): + if existing_tal["id"] == tal["id"]: + contribution["talents"][i]["icon"] = existing_tal["icon"] + + # upload and update icon if there is icon image + contribution = check_and_post_image(request, contribution) + if contribution is None: + s = "Failed to upload icon image." + return render_template('contribute/error.html', error_msg=s) + json_contribution = json.dumps(contribution, indent=4) response, s = put_contribution(json_contribution, contribution_id) @@ -456,6 +483,13 @@ def create(): # add contributionAdmins to the json_contribution contribution = jsonutil.add_contribution_admins(contribution) contribution["status"] = "Submitted" + + contribution = check_and_post_image(request, contribution) + + if contribution is None: + s = "Failed to upload icon image." + return render_template('contribute/error.html', error_msg=s) + json_contribution = json.dumps(contribution, indent=4) response, s, post_json = post_contribution(json_contribution) @@ -781,3 +815,75 @@ def parse_response_error(response): err_json = json.loads(err_content) return err_json + +""" +check if there is image and post +""" +def check_and_post_image(request, in_dict): + temp_dir = tempfile.gettempdir() + del_files = [] # list for holding the path for files to be deleted + # grab file information from request. + # currently, it is only icon for either capability or talent + # if there are other file contents added in the catalog, this should be updated + for i in range(len(in_dict["capabilities"])): + file = request.files["capability_icon_" + str(i)] + if file.filename != "": + # save the file to temp folder + tmp_filename = os.path.join(temp_dir, file.filename) + file.save(tmp_filename) + del_files.append(tmp_filename) + # upload to content building block + uploaded_url = upload_image_to_content_bb(tmp_filename) + if uploaded_url != "": + # record to the contribution + in_dict["capabilities"][i]["icon"] = uploaded_url + else: + return None + for i in range(len(in_dict["talents"])): + file = request.files["talent_icon_" + str(i)] + if file.filename != "": + # save the file to temp folder + tmp_filename = os.path.join(temp_dir, file.filename) + file.save(tmp_filename) + del_files.append(tmp_filename) + # upload to content building block + uploaded_url = upload_image_to_content_bb(tmp_filename) + if uploaded_url != "": + # record to the contribution + in_dict["talents"][i]["icon"] = uploaded_url + else: + return None + + # delete tmp files + for file in del_files: + try: + os.remove(file) + except: + print("failed to delete " + file) + return in_dict + +""" +upload image to content building block +""" +def upload_image_to_content_bb(tmp_filename): + # TODO the method for gettincg access token should be developed. + # Then the toke should be inserted in the following line + access_token = "Bearer " + headers = {"Authorization": access_token} + + files = { + 'path': (None, '"/tmp/tmp_folder"'), + 'fileName': open(tmp_filename, 'rb'), + } + + response = requests.post(cfg.CONTENT_BB_IMAGE_ENDPOINT_URL, headers=headers, files=files) + + if response.status_code == 200: + url_json = json.loads(response.content.decode("utf-8")) + return url_json["url"] + else: + return "" + + # for testing purpose + # url_str = '{"url":"https://rokwire-images.s3.us-east-2.amazonaws.com/%22/tmp/tmp_folder%22/d35ce75c-f3fd-11ec-afd0-0a58a9feac02.webp"}' + # url_json = json.loads(url_str) diff --git a/contributions/catalog/models/capability_utilities.py b/contributions/catalog/models/capability_utilities.py index 3cfcce20..bb7773cb 100644 --- a/contributions/catalog/models/capability_utilities.py +++ b/contributions/catalog/models/capability_utilities.py @@ -65,8 +65,6 @@ def to_capability(d): for _ in range(num_cap): capability_list.append(init_capability()) for i, capability in enumerate(capability_list): - cap_id = str(uuid.uuid4()) - capability['id'] = cap_id # get environment key value pairs by pattern matching. # filter by matching with pattern environmentVariables_key_{{env_num}}_{{cap_num}} key_pattern = re.compile('environmentVariables_key_[0-9]+' + '_' + str(i)) @@ -105,4 +103,8 @@ def to_capability(d): else: capability_list[i][name] = v[0] + # if the request is post, id should be generated + if capability_list[i]["id"] == "": + capability['id'] = str(uuid.uuid4()) + return capability_list diff --git a/contributions/catalog/models/talent_utilities.py b/contributions/catalog/models/talent_utilities.py index 38bfafc2..8d284695 100644 --- a/contributions/catalog/models/talent_utilities.py +++ b/contributions/catalog/models/talent_utilities.py @@ -58,9 +58,6 @@ def to_talent(d): talent_list.append(init_talent()) for i, talent in enumerate(talent_list): - tal_id = str(uuid.uuid4()) - talent['id'] = tal_id - for k, v in d.items(): if "minUserPrivacyLevel_" in k: if len(str(v[0])) > 0: @@ -94,6 +91,11 @@ def to_talent(d): talent_list[i]["selfCertification"] = to_self_certification(d, i) + # if the request is post, id should be generated + if talent_list[i]["id"] == "": + tal_id = str(uuid.uuid4()) + talent['id'] = tal_id + return talent_list def init_self_certification(): diff --git a/contributions/catalog/webapps/templates/contribute/capability_details.html b/contributions/catalog/webapps/templates/contribute/capability_details.html index 7e6a89eb..f1b0c04f 100644 --- a/contributions/catalog/webapps/templates/contribute/capability_details.html +++ b/contributions/catalog/webapps/templates/contribute/capability_details.html @@ -38,6 +38,15 @@
{{post.description}}
+ {% if post.icon %} +{{post.icon}}
+