294 lines
8.7 KiB
Python
294 lines
8.7 KiB
Python
from typing import TYPE_CHECKING, List, Optional, Iterable, Any
|
|
from .base_object import BaseObject
|
|
from ..util.api_call_decorator import api_call
|
|
from ..util.text_enum import TextEnum
|
|
|
|
if TYPE_CHECKING:
|
|
from boxsdk.session.session import Session
|
|
|
|
|
|
class MetadataTemplateUpdate:
|
|
"""Represents a set of update operations to a metadata template."""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._ops = []
|
|
|
|
def json(self) -> list:
|
|
return self._ops
|
|
|
|
def add_enum_option(self, field_key: str, option_key: str) -> None:
|
|
"""
|
|
Adds a new option to an enum field.
|
|
|
|
:param field_key:
|
|
The key of the template field to add the option to
|
|
:param option_key:
|
|
The option to add
|
|
"""
|
|
self.add_operation({
|
|
'op': 'addEnumOption',
|
|
'fieldKey': field_key,
|
|
'data': {
|
|
'key': option_key,
|
|
},
|
|
})
|
|
|
|
def add_field(self, field: 'MetadataField') -> None:
|
|
"""
|
|
Add a new field to the template.
|
|
|
|
:param field:
|
|
The new field to add
|
|
"""
|
|
self.add_operation({
|
|
'op': 'addField',
|
|
'data': field.json(),
|
|
})
|
|
|
|
def edit_template(self, data: dict) -> None:
|
|
"""
|
|
Edit top-level template properties.
|
|
|
|
:param data:
|
|
The properties to modify
|
|
"""
|
|
self.add_operation({
|
|
'op': 'editTemplate',
|
|
'data': data,
|
|
})
|
|
|
|
def reorder_enum_options(self, field_key: str, option_keys: List[str]) -> None:
|
|
"""
|
|
Reorders the options in an enum field, which affects their display in UI.
|
|
|
|
:param field_key:
|
|
The key of the enum field to reorder
|
|
:param option_keys:
|
|
The option keys in the desired order
|
|
"""
|
|
self.add_operation({
|
|
'op': 'reorderEnumOptions',
|
|
'fieldKey': field_key,
|
|
'enumOptionKeys': option_keys,
|
|
})
|
|
|
|
def reorder_fields(self, field_keys: List[str]) -> None:
|
|
"""
|
|
Reorders the fields in a metadata template, which affects their display in UI.
|
|
|
|
:param field_keys:
|
|
The field keys in the desired order
|
|
"""
|
|
self.add_operation({
|
|
'op': 'reorderFields',
|
|
'fieldKeys': field_keys,
|
|
})
|
|
|
|
def edit_field(self, field_key: str, field: 'MetadataField') -> None:
|
|
"""
|
|
Edits a field in the template.
|
|
|
|
:param field_key:
|
|
The key of the field to update
|
|
:param field:
|
|
The updated field values
|
|
"""
|
|
self.add_operation({
|
|
'op': 'editField',
|
|
'fieldKey': field_key,
|
|
'data': field.json(),
|
|
})
|
|
|
|
def edit_enum_option_key(self, field_key: str, old_option_key: str, new_option_key: str) -> None:
|
|
"""
|
|
Change the key of an enum field option.
|
|
|
|
:param field_key:
|
|
The key of the template field in which the option appears
|
|
:param old_option_key:
|
|
The old option key
|
|
:param new_option_key:
|
|
The new option key
|
|
"""
|
|
self.add_operation({
|
|
'op': 'editEnumOption',
|
|
'fieldKey': field_key,
|
|
'enumOptionKey': old_option_key,
|
|
'data': {
|
|
'key': new_option_key,
|
|
},
|
|
})
|
|
|
|
def remove_enum_option(self, field_key: str, option_key: str) -> None:
|
|
"""
|
|
Remove an option from an enum field.
|
|
|
|
:param field_key:
|
|
The key of the template field in which the option appears
|
|
:param option_key:
|
|
The key of the enum option to remove
|
|
"""
|
|
self.add_operation({
|
|
'op': 'removeEnumOption',
|
|
'fieldKey': field_key,
|
|
'enumOptionKey': option_key,
|
|
})
|
|
|
|
def remove_field(self, field_key: str) -> None:
|
|
"""
|
|
Remove a field from the metadata template.
|
|
|
|
:param field_key:
|
|
The key of the field to remove
|
|
"""
|
|
self.add_operation({
|
|
'op': 'removeField',
|
|
'fieldKey': field_key,
|
|
})
|
|
|
|
def add_operation(self, operation: dict) -> None:
|
|
"""
|
|
Adds an update operation.
|
|
|
|
:param operation:
|
|
The operation to add.
|
|
"""
|
|
self._ops.append(operation)
|
|
|
|
|
|
class MetadataFieldType(TextEnum):
|
|
STRING = 'string'
|
|
DATE = 'date'
|
|
ENUM = 'enum'
|
|
MULTISELECT = 'multiSelect'
|
|
FLOAT = 'float'
|
|
|
|
|
|
class MetadataField:
|
|
"""Represents a metadata field when creating or updating a metadata template."""
|
|
|
|
def __init__(
|
|
self,
|
|
field_type: MetadataFieldType,
|
|
display_name: str,
|
|
key: Optional[str] = None,
|
|
options: Iterable[str] = None,
|
|
description: Optional[str] = None,
|
|
hidden: Optional[bool] = None
|
|
):
|
|
"""
|
|
:param field_type:
|
|
The type of the metadata field
|
|
:param display_name:
|
|
The human-readable name of the metadata field
|
|
:param key:
|
|
The machine-readable key for the metadata field
|
|
:param options:
|
|
For 'enum' or 'multiSelect' fields, the selectable options
|
|
:param description:
|
|
A description of the field
|
|
:param hidden:
|
|
Whether this field is hidden in the UI for the user and can only be set through the API instead
|
|
"""
|
|
super().__init__()
|
|
self.type = field_type
|
|
self.name = display_name
|
|
self.key = key
|
|
self.options = options
|
|
self.description = description
|
|
self.hidden = hidden
|
|
|
|
def json(self) -> dict:
|
|
"""
|
|
Returns the correct representation of the template field for the API.
|
|
"""
|
|
values = {}
|
|
|
|
if self.type is not None:
|
|
values['type'] = self.type
|
|
|
|
if self.name is not None:
|
|
values['displayName'] = self.name
|
|
|
|
if self.key is not None:
|
|
values['key'] = self.key
|
|
|
|
if self.type in ['enum', 'multiSelect']:
|
|
values['options'] = [{'key': opt} for opt in self.options or ()]
|
|
|
|
if self.description is not None:
|
|
values['description'] = self.description
|
|
|
|
if self.hidden is not None:
|
|
values['hidden'] = self.hidden
|
|
|
|
return values
|
|
|
|
|
|
class MetadataTemplate(BaseObject):
|
|
"""Represents a metadata template, which contains the the type information for associated metadata fields."""
|
|
|
|
_item_type = 'metadata_template'
|
|
_untranslated_fields = ('fields',)
|
|
_scope = None
|
|
_template_key = None
|
|
|
|
def __init__(self, session: 'Session', object_id: Optional[str], response_object: Optional[dict] = None):
|
|
"""
|
|
:param session:
|
|
The Box session used to make requests.
|
|
:param object_id:
|
|
The primary GUID key for the metadata template
|
|
:param response_object:
|
|
A JSON object representing the object returned from a Box API request. This should
|
|
contain 'scope' and 'templateKey' properties if the instance is being constructed without
|
|
a primary GUID object_id.
|
|
"""
|
|
super().__init__(session, object_id, response_object)
|
|
if response_object:
|
|
self._scope = response_object.get('scope', None)
|
|
self._template_key = response_object.get('templateKey', None)
|
|
elif not object_id:
|
|
raise ValueError('Metadata template must be constructed with an ID or scope and templateKey')
|
|
|
|
@property
|
|
def scope(self) -> Optional[str]:
|
|
return self._scope
|
|
|
|
@property
|
|
def template_key(self) -> Optional[str]:
|
|
return self._template_key
|
|
|
|
def get_url(self, *args: Any) -> str:
|
|
"""
|
|
Base class override, since metadata templates have a weird compound ID and non-standard URL format
|
|
"""
|
|
if self._scope and self._template_key:
|
|
return self._session.get_url('metadata_templates', self._scope, self._template_key, 'schema', *args)
|
|
|
|
return super().get_url(*args)
|
|
|
|
@staticmethod
|
|
def start_update() -> MetadataTemplateUpdate:
|
|
"""
|
|
Start an update operation on the template.
|
|
|
|
:returns:
|
|
An update object to collect the desired update operations.
|
|
"""
|
|
return MetadataTemplateUpdate()
|
|
|
|
@api_call
|
|
def update_info(self, *, updates: MetadataTemplateUpdate, **kwargs) -> 'MetadataTemplate':
|
|
# pylint: disable=arguments-differ
|
|
"""
|
|
Update a metadata template with a set of update operations.
|
|
|
|
:param updates:
|
|
The update operations to apply to the template
|
|
:returns:
|
|
The updated metadata template object
|
|
"""
|
|
# pylint: disable=arguments-differ
|
|
return super().update_info(data=updates.json(), **kwargs)
|