import os
import json
import requests
import inflection
from .abstract_chart_deployer import AbstractChartDeployer
[docs]
class MiroChartDeployer (AbstractChartDeployer):
DEFAULT_IMAGE_WIDTH=2000
DEFAULT_IMAGE_X_POSITION=0
DEFAULT_IMAGE_Y_POSITION=0
DEFAULT_IMAGE_TITLE="Default Image Title"
DEFAULT_LAYOUT_COLUMNS=4
DEFAULT_LAYOUT_COLUMN_SPACING=150
DEFAULT_LAYOUT_ROW_SPACING=150
def __init__(
self,
board_id,
token,
layout_columns=None,
layout_x_position=None,
layout_y_position=None,
params=None
):
self.board_id = board_id
self.oauth_token = token
self.parent_id = params.get("parent_id") if params else None
self.layout_columns = layout_columns or self.DEFAULT_LAYOUT_COLUMNS
self.layout_x_position = layout_x_position or self.DEFAULT_IMAGE_X_POSITION
self.layout_y_position = layout_y_position or self.DEFAULT_IMAGE_Y_POSITION
self.image_title = params.get("image_title") if params else self.DEFAULT_IMAGE_TITLE
self.image_width = params.get("image_width") if params else self.DEFAULT_IMAGE_WIDTH
self.image_x_position = self.layout_x_position
self.image_y_position = self.layout_y_position
self.layout_column_spacing = params.get("layout_column_spacing") if params else self.DEFAULT_LAYOUT_COLUMN_SPACING
self.layout_row_spacing = params.get("layout_row_spacing") if params else self.DEFAULT_LAYOUT_ROW_SPACING
self.deployment_counter = 0
self.row_elements_height = []
self.last_widget_id = None
[docs]
def calc_position(self,last_widget_id=None):
if (self.deployment_counter == 0) or (last_widget_id == None):
return
if self.deployment_counter % self.layout_columns > 0:
self.image_x_position = self.image_x_position + self.image_width + self.layout_column_spacing
last_widget_height = self.get_widget_attribute(
widget_id=self.last_widget_id,
attribute_path=['geometry', 'height']
)
self.row_elements_height.append(last_widget_height)
else:
row_height = max(self.row_elements_height)
self.image_y_position = self.image_y_position + row_height + self.layout_row_spacing + self.layout_y_position
self.image_x_position = self.layout_x_position
self.row_elements_height = []
[docs]
def deploy(
self,
fp,
rotation=0,
**kwargs
):
if hasattr(fp, 'getvalue'):
content = fp.getvalue()
elif isinstance(fp, (str, bytes, os.PathLike)):
with open(fp, 'rb') as file:
content = file.read()
else:
raise TypeError("fp must be a file-like object or a file path")
self.calc_position(self.last_widget_id)
files_dict = dict(
resource=(
f"{inflection.underscore(self.image_title)}.svg",
content,
"image/svg",
),
data=(
None,
json.dumps(
{
"title": self.image_title,
"position": {
"x": self.image_x_position,
"y": self.image_y_position,
},
"geometry": {
"width": self.image_width,
"rotation": rotation,
},
"parent": {
"id": self.parent_id,
},
}
),
"application/json",
),
)
files_list = [(key, value) for key, value in files_dict.items()]
headers = {"Authorization": f"Bearer {self.oauth_token}"}
url = f"https://api.miro.com/v2/boards/{self.board_id}/images"
response = requests.post(url, headers=headers, data={}, files=files_list)
if response.status_code == 201:
self.deployment_counter += 1
self.last_widget_id = response.json()["id"]
else:
response.raise_for_status()