# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 """ This file contains helper functions related to layout. """ import os from urllib.parse import unquote import chalicelib.settings as msam_settings import boto3 from boto3.dynamodb.conditions import Key from botocore.config import Config from botocore.exceptions import ClientError # table names generated by CloudFormation LAYOUT_TABLE_NAME = os.environ["LAYOUT_TABLE_NAME"] # user-agent config SOLUTION_ID = os.environ['SOLUTION_ID'] USER_AGENT_EXTRA = {"user_agent_extra": SOLUTION_ID} MSAM_BOTO3_CONFIG = Config(**USER_AGENT_EXTRA) # DynamoDB DYNAMO_RESOURCE = boto3.resource("dynamodb", config=MSAM_BOTO3_CONFIG) def get_view_layout(view): """ API entry point for retrieving all item positions in a view. """ view = unquote(view) items = [] table_name = LAYOUT_TABLE_NAME try: table = DYNAMO_RESOURCE.Table(table_name) try: # get the settings object response = table.query(KeyConditionExpression=Key('view').eq(view)) print(response) # return the response or an empty object if "Items" in response: items = response["Items"] print("retrieved") except ClientError: print("not found") except ClientError as error_out: # send the exception back in the object print(error_out) items = {"exception": str(error_out)} return items def set_node_layout(layout_items): """ API entry point for setting nodes in a view. This adds new nodes and overwrites existing nodes. It does not replace the entire set. """ settings = {} table_name = LAYOUT_TABLE_NAME try: table = DYNAMO_RESOURCE.Table(table_name) # print(request.json_body) # layout_items = request.json_body # write to the database in batch for item in layout_items: table.put_item(Item=item) settings = {"message": "saved"} print(settings) except ClientError as error: # send the exception back in the object print(error) settings = {"exception": str(error)} return settings def delete_node_layout(view, node_id): """ API entry point for removing nodes from a view. """ view = unquote(view) node_id = unquote(node_id) settings = {} table_name = LAYOUT_TABLE_NAME try: print(view, node_id) table = DYNAMO_RESOURCE.Table(table_name) table.delete_item(Key={"view": view, "id": node_id}) settings = {"message": "deleted"} print(settings) except ClientError as error: # send the exception back in the object print(error) settings = {"exception": str(error)} return settings def has_node(view, node_id): """ API entry point to check presence of nodes in a view. """ view = unquote(view) node_id = unquote(node_id) table_name = LAYOUT_TABLE_NAME try: table = DYNAMO_RESOURCE.Table(table_name) response = table.get_item(Key={"view": view, "id": node_id}) # True or False return "Item" in response except ClientError as error: print(error) return False def remove_all_diagrams(): """ Delete all diagrams from the database """ try: table = DYNAMO_RESOURCE.Table(LAYOUT_TABLE_NAME) # empty the value in settings msam_settings.put_setting("diagrams", []) # empty the channels table response = table.scan(ExpressionAttributeNames={ "#v": "view", "#i": "id" }, ProjectionExpression="#v,#i") items = response.get("Items", []) while "LastEvaluatedKey" in response: response = table.scan( ExpressionAttributeNames={ "#v": "view", "#i": "id" }, ProjectionExpression="#v,#i", ExclusiveStartKey=response["LastEvaluatedKey"]) items = items + response.get("Items", []) for item in items: table.delete_item(Key={"view": item["view"], "id": item["id"]}) response = {"message": "done"} except ClientError as client_error: print(client_error) response = {"message": str(client_error)} return response