mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 16:34:53 +01:00
Merge pull request #1321 from pypeclub/feature/prepare_project_prep
Prepare project Ftrack action in Pype 3
This commit is contained in:
commit
138ad21aba
4 changed files with 475 additions and 175 deletions
|
|
@ -0,0 +1,365 @@
|
||||||
|
import json
|
||||||
|
|
||||||
|
from openpype.api import ProjectSettings
|
||||||
|
|
||||||
|
from openpype.modules.ftrack.lib import ServerAction
|
||||||
|
from openpype.modules.ftrack.lib.avalon_sync import (
|
||||||
|
get_pype_attr,
|
||||||
|
CUST_ATTR_AUTO_SYNC
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class PrepareProjectServer(ServerAction):
|
||||||
|
"""Prepare project attributes in Anatomy."""
|
||||||
|
|
||||||
|
identifier = "prepare.project.server"
|
||||||
|
label = "OpenPype Admin"
|
||||||
|
variant = "- Prepare Project (Server)"
|
||||||
|
description = "Set basic attributes on the project"
|
||||||
|
|
||||||
|
settings_key = "prepare_project"
|
||||||
|
|
||||||
|
role_list = ["Pypeclub", "Administrator", "Project Manager"]
|
||||||
|
|
||||||
|
# Key to store info about trigerring create folder structure
|
||||||
|
item_splitter = {"type": "label", "value": "---"}
|
||||||
|
|
||||||
|
def discover(self, session, entities, event):
|
||||||
|
"""Show only on project."""
|
||||||
|
if (
|
||||||
|
len(entities) != 1
|
||||||
|
or entities[0].entity_type.lower() != "project"
|
||||||
|
):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return self.valid_roles(session, entities, event)
|
||||||
|
|
||||||
|
def interface(self, session, entities, event):
|
||||||
|
if event['data'].get('values', {}):
|
||||||
|
return
|
||||||
|
|
||||||
|
# Inform user that this may take a while
|
||||||
|
self.show_message(event, "Preparing data... Please wait", True)
|
||||||
|
self.log.debug("Preparing data which will be shown")
|
||||||
|
|
||||||
|
self.log.debug("Loading custom attributes")
|
||||||
|
|
||||||
|
project_entity = entities[0]
|
||||||
|
project_name = project_entity["full_name"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
project_settings = ProjectSettings(project_name)
|
||||||
|
except ValueError:
|
||||||
|
return {
|
||||||
|
"message": "Project is not synchronized yet",
|
||||||
|
"success": False
|
||||||
|
}
|
||||||
|
|
||||||
|
project_anatom_settings = project_settings["project_anatomy"]
|
||||||
|
root_items = self.prepare_root_items(project_anatom_settings)
|
||||||
|
|
||||||
|
ca_items, multiselect_enumerators = (
|
||||||
|
self.prepare_custom_attribute_items(project_anatom_settings)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.log.debug("Heavy items are ready. Preparing last items group.")
|
||||||
|
|
||||||
|
title = "Prepare Project"
|
||||||
|
items = []
|
||||||
|
|
||||||
|
# Add root items
|
||||||
|
items.extend(root_items)
|
||||||
|
|
||||||
|
items.append(self.item_splitter)
|
||||||
|
items.append({
|
||||||
|
"type": "label",
|
||||||
|
"value": "<h3>Set basic Attributes:</h3>"
|
||||||
|
})
|
||||||
|
|
||||||
|
items.extend(ca_items)
|
||||||
|
|
||||||
|
# This item will be last (before enumerators)
|
||||||
|
# - sets value of auto synchronization
|
||||||
|
auto_sync_name = "avalon_auto_sync"
|
||||||
|
auto_sync_value = project_entity["custom_attributes"].get(
|
||||||
|
CUST_ATTR_AUTO_SYNC, False
|
||||||
|
)
|
||||||
|
auto_sync_item = {
|
||||||
|
"name": auto_sync_name,
|
||||||
|
"type": "boolean",
|
||||||
|
"value": auto_sync_value,
|
||||||
|
"label": "AutoSync to Avalon"
|
||||||
|
}
|
||||||
|
# Add autosync attribute
|
||||||
|
items.append(auto_sync_item)
|
||||||
|
|
||||||
|
# Add enumerator items at the end
|
||||||
|
for item in multiselect_enumerators:
|
||||||
|
items.append(item)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"items": items,
|
||||||
|
"title": title
|
||||||
|
}
|
||||||
|
|
||||||
|
def prepare_root_items(self, project_anatom_settings):
|
||||||
|
self.log.debug("Root items preparation begins.")
|
||||||
|
|
||||||
|
root_items = []
|
||||||
|
root_items.append({
|
||||||
|
"type": "label",
|
||||||
|
"value": "<h3>Check your Project root settings</h3>"
|
||||||
|
})
|
||||||
|
root_items.append({
|
||||||
|
"type": "label",
|
||||||
|
"value": (
|
||||||
|
"<p><i>NOTE: Roots are <b>crutial</b> for path filling"
|
||||||
|
" (and creating folder structure).</i></p>"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
root_items.append({
|
||||||
|
"type": "label",
|
||||||
|
"value": (
|
||||||
|
"<p><i>WARNING: Do not change roots on running project,"
|
||||||
|
" that <b>will cause workflow issues</b>.</i></p>"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
empty_text = "Enter root path here..."
|
||||||
|
|
||||||
|
roots_entity = project_anatom_settings["roots"]
|
||||||
|
for root_name, root_entity in roots_entity.items():
|
||||||
|
root_items.append(self.item_splitter)
|
||||||
|
root_items.append({
|
||||||
|
"type": "label",
|
||||||
|
"value": "Root: \"{}\"".format(root_name)
|
||||||
|
})
|
||||||
|
for platform_name, value_entity in root_entity.items():
|
||||||
|
root_items.append({
|
||||||
|
"label": platform_name,
|
||||||
|
"name": "__root__{}__{}".format(root_name, platform_name),
|
||||||
|
"type": "text",
|
||||||
|
"value": value_entity.value,
|
||||||
|
"empty_text": empty_text
|
||||||
|
})
|
||||||
|
|
||||||
|
root_items.append({
|
||||||
|
"type": "hidden",
|
||||||
|
"name": "__rootnames__",
|
||||||
|
"value": json.dumps(list(roots_entity.keys()))
|
||||||
|
})
|
||||||
|
|
||||||
|
self.log.debug("Root items preparation ended.")
|
||||||
|
return root_items
|
||||||
|
|
||||||
|
def _attributes_to_set(self, project_anatom_settings):
|
||||||
|
attributes_to_set = {}
|
||||||
|
|
||||||
|
attribute_values_by_key = {}
|
||||||
|
for key, entity in project_anatom_settings["attributes"].items():
|
||||||
|
attribute_values_by_key[key] = entity.value
|
||||||
|
|
||||||
|
cust_attrs, hier_cust_attrs = get_pype_attr(self.session, True)
|
||||||
|
|
||||||
|
for attr in hier_cust_attrs:
|
||||||
|
key = attr["key"]
|
||||||
|
if key.startswith("avalon_"):
|
||||||
|
continue
|
||||||
|
attributes_to_set[key] = {
|
||||||
|
"label": attr["label"],
|
||||||
|
"object": attr,
|
||||||
|
"default": attribute_values_by_key.get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
for attr in cust_attrs:
|
||||||
|
if attr["entity_type"].lower() != "show":
|
||||||
|
continue
|
||||||
|
key = attr["key"]
|
||||||
|
if key.startswith("avalon_"):
|
||||||
|
continue
|
||||||
|
attributes_to_set[key] = {
|
||||||
|
"label": attr["label"],
|
||||||
|
"object": attr,
|
||||||
|
"default": attribute_values_by_key.get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Sort by label
|
||||||
|
attributes_to_set = dict(sorted(
|
||||||
|
attributes_to_set.items(),
|
||||||
|
key=lambda x: x[1]["label"]
|
||||||
|
))
|
||||||
|
return attributes_to_set
|
||||||
|
|
||||||
|
def prepare_custom_attribute_items(self, project_anatom_settings):
|
||||||
|
items = []
|
||||||
|
multiselect_enumerators = []
|
||||||
|
attributes_to_set = self._attributes_to_set(project_anatom_settings)
|
||||||
|
|
||||||
|
self.log.debug("Preparing interface for keys: \"{}\"".format(
|
||||||
|
str([key for key in attributes_to_set])
|
||||||
|
))
|
||||||
|
|
||||||
|
for key, in_data in attributes_to_set.items():
|
||||||
|
attr = in_data["object"]
|
||||||
|
|
||||||
|
# initial item definition
|
||||||
|
item = {
|
||||||
|
"name": key,
|
||||||
|
"label": in_data["label"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# cust attr type - may have different visualization
|
||||||
|
type_name = attr["type"]["name"].lower()
|
||||||
|
easy_types = ["text", "boolean", "date", "number"]
|
||||||
|
|
||||||
|
easy_type = False
|
||||||
|
if type_name in easy_types:
|
||||||
|
easy_type = True
|
||||||
|
|
||||||
|
elif type_name == "enumerator":
|
||||||
|
|
||||||
|
attr_config = json.loads(attr["config"])
|
||||||
|
attr_config_data = json.loads(attr_config["data"])
|
||||||
|
|
||||||
|
if attr_config["multiSelect"] is True:
|
||||||
|
multiselect_enumerators.append(self.item_splitter)
|
||||||
|
multiselect_enumerators.append({
|
||||||
|
"type": "label",
|
||||||
|
"value": in_data["label"]
|
||||||
|
})
|
||||||
|
|
||||||
|
default = in_data["default"]
|
||||||
|
names = []
|
||||||
|
for option in sorted(
|
||||||
|
attr_config_data, key=lambda x: x["menu"]
|
||||||
|
):
|
||||||
|
name = option["value"]
|
||||||
|
new_name = "__{}__{}".format(key, name)
|
||||||
|
names.append(new_name)
|
||||||
|
item = {
|
||||||
|
"name": new_name,
|
||||||
|
"type": "boolean",
|
||||||
|
"label": "- {}".format(option["menu"])
|
||||||
|
}
|
||||||
|
if default:
|
||||||
|
if isinstance(default, (list, tuple)):
|
||||||
|
if name in default:
|
||||||
|
item["value"] = True
|
||||||
|
else:
|
||||||
|
if name == default:
|
||||||
|
item["value"] = True
|
||||||
|
|
||||||
|
multiselect_enumerators.append(item)
|
||||||
|
|
||||||
|
multiselect_enumerators.append({
|
||||||
|
"type": "hidden",
|
||||||
|
"name": "__hidden__{}".format(key),
|
||||||
|
"value": json.dumps(names)
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
easy_type = True
|
||||||
|
item["data"] = attr_config_data
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.log.warning((
|
||||||
|
"Custom attribute \"{}\" has type \"{}\"."
|
||||||
|
" I don't know how to handle"
|
||||||
|
).format(key, type_name))
|
||||||
|
items.append({
|
||||||
|
"type": "label",
|
||||||
|
"value": (
|
||||||
|
"!!! Can't handle Custom attritubte type \"{}\""
|
||||||
|
" (key: \"{}\")"
|
||||||
|
).format(type_name, key)
|
||||||
|
})
|
||||||
|
|
||||||
|
if easy_type:
|
||||||
|
item["type"] = type_name
|
||||||
|
|
||||||
|
# default value in interface
|
||||||
|
default = in_data["default"]
|
||||||
|
if default is not None:
|
||||||
|
item["value"] = default
|
||||||
|
|
||||||
|
items.append(item)
|
||||||
|
|
||||||
|
return items, multiselect_enumerators
|
||||||
|
|
||||||
|
def launch(self, session, entities, event):
|
||||||
|
if not event['data'].get('values', {}):
|
||||||
|
return
|
||||||
|
|
||||||
|
in_data = event['data']['values']
|
||||||
|
|
||||||
|
root_values = {}
|
||||||
|
root_key = "__root__"
|
||||||
|
for key in tuple(in_data.keys()):
|
||||||
|
if key.startswith(root_key):
|
||||||
|
_key = key[len(root_key):]
|
||||||
|
root_values[_key] = in_data.pop(key)
|
||||||
|
|
||||||
|
root_names = in_data.pop("__rootnames__", None)
|
||||||
|
root_data = {}
|
||||||
|
for root_name in json.loads(root_names):
|
||||||
|
root_data[root_name] = {}
|
||||||
|
for key, value in tuple(root_values.items()):
|
||||||
|
prefix = "{}__".format(root_name)
|
||||||
|
if not key.startswith(prefix):
|
||||||
|
continue
|
||||||
|
|
||||||
|
_key = key[len(prefix):]
|
||||||
|
root_data[root_name][_key] = value
|
||||||
|
|
||||||
|
# Find hidden items for multiselect enumerators
|
||||||
|
keys_to_process = []
|
||||||
|
for key in in_data:
|
||||||
|
if key.startswith("__hidden__"):
|
||||||
|
keys_to_process.append(key)
|
||||||
|
|
||||||
|
self.log.debug("Preparing data for Multiselect Enumerators")
|
||||||
|
enumerators = {}
|
||||||
|
for key in keys_to_process:
|
||||||
|
new_key = key.replace("__hidden__", "")
|
||||||
|
enumerator_items = in_data.pop(key)
|
||||||
|
enumerators[new_key] = json.loads(enumerator_items)
|
||||||
|
|
||||||
|
# find values set for multiselect enumerator
|
||||||
|
for key, enumerator_items in enumerators.items():
|
||||||
|
in_data[key] = []
|
||||||
|
|
||||||
|
name = "__{}__".format(key)
|
||||||
|
|
||||||
|
for item in enumerator_items:
|
||||||
|
value = in_data.pop(item)
|
||||||
|
if value is True:
|
||||||
|
new_key = item.replace(name, "")
|
||||||
|
in_data[key].append(new_key)
|
||||||
|
|
||||||
|
self.log.debug("Setting Custom Attribute values")
|
||||||
|
|
||||||
|
project_name = entities[0]["full_name"]
|
||||||
|
project_settings = ProjectSettings(project_name)
|
||||||
|
project_anatomy_settings = project_settings["project_anatomy"]
|
||||||
|
project_anatomy_settings["roots"] = root_data
|
||||||
|
|
||||||
|
custom_attribute_values = {}
|
||||||
|
attributes_entity = project_anatomy_settings["attributes"]
|
||||||
|
for key, value in in_data.items():
|
||||||
|
if key not in attributes_entity:
|
||||||
|
custom_attribute_values[key] = value
|
||||||
|
else:
|
||||||
|
attributes_entity[key] = value
|
||||||
|
|
||||||
|
project_settings.save()
|
||||||
|
|
||||||
|
entity = entities[0]
|
||||||
|
for key, value in custom_attribute_values.items():
|
||||||
|
entity["custom_attributes"][key] = value
|
||||||
|
self.log.debug("- Key \"{}\" set to \"{}\"".format(key, value))
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def register(session):
|
||||||
|
'''Register plugin. Called when used as an plugin.'''
|
||||||
|
PrepareProjectServer(session).register()
|
||||||
|
|
@ -1,31 +1,34 @@
|
||||||
import os
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from openpype.modules.ftrack.lib import BaseAction, statics_icon
|
from openpype.api import ProjectSettings
|
||||||
from openpype.api import config, Anatomy
|
|
||||||
from openpype.modules.ftrack.lib.avalon_sync import get_pype_attr
|
from openpype.modules.ftrack.lib import (
|
||||||
|
BaseAction,
|
||||||
|
statics_icon
|
||||||
|
)
|
||||||
|
from openpype.modules.ftrack.lib.avalon_sync import (
|
||||||
|
get_pype_attr,
|
||||||
|
CUST_ATTR_AUTO_SYNC
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class PrepareProject(BaseAction):
|
class PrepareProjectLocal(BaseAction):
|
||||||
'''Edit meta data action.'''
|
"""Prepare project attributes in Anatomy."""
|
||||||
|
|
||||||
#: Action identifier.
|
identifier = "prepare.project.local"
|
||||||
identifier = 'prepare.project'
|
label = "Prepare Project"
|
||||||
#: Action label.
|
description = "Set basic attributes on the project"
|
||||||
label = 'Prepare Project'
|
|
||||||
#: Action description.
|
|
||||||
description = 'Set basic attributes on the project'
|
|
||||||
#: roles that are allowed to register this action
|
|
||||||
icon = statics_icon("ftrack", "action_icons", "PrepareProject.svg")
|
icon = statics_icon("ftrack", "action_icons", "PrepareProject.svg")
|
||||||
|
|
||||||
|
role_list = ["Pypeclub", "Administrator", "Project Manager"]
|
||||||
|
|
||||||
settings_key = "prepare_project"
|
settings_key = "prepare_project"
|
||||||
|
|
||||||
# Key to store info about trigerring create folder structure
|
# Key to store info about trigerring create folder structure
|
||||||
create_project_structure_key = "create_folder_structure"
|
item_splitter = {"type": "label", "value": "---"}
|
||||||
item_splitter = {'type': 'label', 'value': '---'}
|
|
||||||
|
|
||||||
def discover(self, session, entities, event):
|
def discover(self, session, entities, event):
|
||||||
''' Validation '''
|
"""Show only on project."""
|
||||||
if (
|
if (
|
||||||
len(entities) != 1
|
len(entities) != 1
|
||||||
or entities[0].entity_type.lower() != "project"
|
or entities[0].entity_type.lower() != "project"
|
||||||
|
|
@ -44,27 +47,22 @@ class PrepareProject(BaseAction):
|
||||||
|
|
||||||
self.log.debug("Loading custom attributes")
|
self.log.debug("Loading custom attributes")
|
||||||
|
|
||||||
project_name = entities[0]["full_name"]
|
project_entity = entities[0]
|
||||||
|
project_name = project_entity["full_name"]
|
||||||
|
|
||||||
project_defaults = (
|
try:
|
||||||
config.get_presets(project_name)
|
project_settings = ProjectSettings(project_name)
|
||||||
.get("ftrack", {})
|
except ValueError:
|
||||||
.get("project_defaults", {})
|
|
||||||
)
|
|
||||||
|
|
||||||
anatomy = Anatomy(project_name)
|
|
||||||
if not anatomy.roots:
|
|
||||||
return {
|
return {
|
||||||
"success": False,
|
"message": "Project is not synchronized yet",
|
||||||
"message": (
|
"success": False
|
||||||
"Have issues with loading Roots for project \"{}\"."
|
|
||||||
).format(anatomy.project_name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
root_items = self.prepare_root_items(anatomy)
|
project_anatom_settings = project_settings["project_anatomy"]
|
||||||
|
root_items = self.prepare_root_items(project_anatom_settings)
|
||||||
|
|
||||||
ca_items, multiselect_enumerators = (
|
ca_items, multiselect_enumerators = (
|
||||||
self.prepare_custom_attribute_items(project_defaults)
|
self.prepare_custom_attribute_items(project_anatom_settings)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.log.debug("Heavy items are ready. Preparing last items group.")
|
self.log.debug("Heavy items are ready. Preparing last items group.")
|
||||||
|
|
@ -74,19 +72,6 @@ class PrepareProject(BaseAction):
|
||||||
|
|
||||||
# Add root items
|
# Add root items
|
||||||
items.extend(root_items)
|
items.extend(root_items)
|
||||||
items.append(self.item_splitter)
|
|
||||||
|
|
||||||
# Ask if want to trigger Action Create Folder Structure
|
|
||||||
items.append({
|
|
||||||
"type": "label",
|
|
||||||
"value": "<h3>Want to create basic Folder Structure?</h3>"
|
|
||||||
})
|
|
||||||
items.append({
|
|
||||||
"name": self.create_project_structure_key,
|
|
||||||
"type": "boolean",
|
|
||||||
"value": False,
|
|
||||||
"label": "Check if Yes"
|
|
||||||
})
|
|
||||||
|
|
||||||
items.append(self.item_splitter)
|
items.append(self.item_splitter)
|
||||||
items.append({
|
items.append({
|
||||||
|
|
@ -99,10 +84,13 @@ class PrepareProject(BaseAction):
|
||||||
# This item will be last (before enumerators)
|
# This item will be last (before enumerators)
|
||||||
# - sets value of auto synchronization
|
# - sets value of auto synchronization
|
||||||
auto_sync_name = "avalon_auto_sync"
|
auto_sync_name = "avalon_auto_sync"
|
||||||
|
auto_sync_value = project_entity["custom_attributes"].get(
|
||||||
|
CUST_ATTR_AUTO_SYNC, False
|
||||||
|
)
|
||||||
auto_sync_item = {
|
auto_sync_item = {
|
||||||
"name": auto_sync_name,
|
"name": auto_sync_name,
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"value": project_defaults.get(auto_sync_name, False),
|
"value": auto_sync_value,
|
||||||
"label": "AutoSync to Avalon"
|
"label": "AutoSync to Avalon"
|
||||||
}
|
}
|
||||||
# Add autosync attribute
|
# Add autosync attribute
|
||||||
|
|
@ -117,13 +105,10 @@ class PrepareProject(BaseAction):
|
||||||
"title": title
|
"title": title
|
||||||
}
|
}
|
||||||
|
|
||||||
def prepare_root_items(self, anatomy):
|
def prepare_root_items(self, project_anatom_settings):
|
||||||
root_items = []
|
|
||||||
self.log.debug("Root items preparation begins.")
|
self.log.debug("Root items preparation begins.")
|
||||||
|
|
||||||
root_names = anatomy.root_names()
|
root_items = []
|
||||||
roots = anatomy.roots
|
|
||||||
|
|
||||||
root_items.append({
|
root_items.append({
|
||||||
"type": "label",
|
"type": "label",
|
||||||
"value": "<h3>Check your Project root settings</h3>"
|
"value": "<h3>Check your Project root settings</h3>"
|
||||||
|
|
@ -143,85 +128,40 @@ class PrepareProject(BaseAction):
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
default_roots = anatomy.roots
|
|
||||||
while isinstance(default_roots, dict):
|
|
||||||
key = tuple(default_roots.keys())[0]
|
|
||||||
default_roots = default_roots[key]
|
|
||||||
|
|
||||||
empty_text = "Enter root path here..."
|
empty_text = "Enter root path here..."
|
||||||
|
|
||||||
# Root names is None when anatomy templates contain "{root}"
|
roots_entity = project_anatom_settings["roots"]
|
||||||
all_platforms = ["windows", "linux", "darwin"]
|
for root_name, root_entity in roots_entity.items():
|
||||||
if root_names is None:
|
|
||||||
root_items.append(self.item_splitter)
|
|
||||||
# find first possible key
|
|
||||||
for platform in all_platforms:
|
|
||||||
value = default_roots.raw_data.get(platform) or ""
|
|
||||||
root_items.append({
|
|
||||||
"label": platform,
|
|
||||||
"name": "__root__{}".format(platform),
|
|
||||||
"type": "text",
|
|
||||||
"value": value,
|
|
||||||
"empty_text": empty_text
|
|
||||||
})
|
|
||||||
return root_items
|
|
||||||
|
|
||||||
root_name_data = {}
|
|
||||||
missing_roots = []
|
|
||||||
for root_name in root_names:
|
|
||||||
root_name_data[root_name] = {}
|
|
||||||
if not isinstance(roots, dict):
|
|
||||||
missing_roots.append(root_name)
|
|
||||||
continue
|
|
||||||
|
|
||||||
root_item = roots.get(root_name)
|
|
||||||
if not root_item:
|
|
||||||
missing_roots.append(root_name)
|
|
||||||
continue
|
|
||||||
|
|
||||||
for platform in all_platforms:
|
|
||||||
root_name_data[root_name][platform] = (
|
|
||||||
root_item.raw_data.get(platform) or ""
|
|
||||||
)
|
|
||||||
|
|
||||||
if missing_roots:
|
|
||||||
default_values = {}
|
|
||||||
for platform in all_platforms:
|
|
||||||
default_values[platform] = (
|
|
||||||
default_roots.raw_data.get(platform) or ""
|
|
||||||
)
|
|
||||||
|
|
||||||
for root_name in missing_roots:
|
|
||||||
root_name_data[root_name] = default_values
|
|
||||||
|
|
||||||
root_names = list(root_name_data.keys())
|
|
||||||
root_items.append({
|
|
||||||
"type": "hidden",
|
|
||||||
"name": "__rootnames__",
|
|
||||||
"value": json.dumps(root_names)
|
|
||||||
})
|
|
||||||
|
|
||||||
for root_name, values in root_name_data.items():
|
|
||||||
root_items.append(self.item_splitter)
|
root_items.append(self.item_splitter)
|
||||||
root_items.append({
|
root_items.append({
|
||||||
"type": "label",
|
"type": "label",
|
||||||
"value": "Root: \"{}\"".format(root_name)
|
"value": "Root: \"{}\"".format(root_name)
|
||||||
})
|
})
|
||||||
for platform, value in values.items():
|
for platform_name, value_entity in root_entity.items():
|
||||||
root_items.append({
|
root_items.append({
|
||||||
"label": platform,
|
"label": platform_name,
|
||||||
"name": "__root__{}{}".format(root_name, platform),
|
"name": "__root__{}__{}".format(root_name, platform_name),
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": value,
|
"value": value_entity.value,
|
||||||
"empty_text": empty_text
|
"empty_text": empty_text
|
||||||
})
|
})
|
||||||
|
|
||||||
|
root_items.append({
|
||||||
|
"type": "hidden",
|
||||||
|
"name": "__rootnames__",
|
||||||
|
"value": json.dumps(list(roots_entity.keys()))
|
||||||
|
})
|
||||||
|
|
||||||
self.log.debug("Root items preparation ended.")
|
self.log.debug("Root items preparation ended.")
|
||||||
return root_items
|
return root_items
|
||||||
|
|
||||||
def _attributes_to_set(self, project_defaults):
|
def _attributes_to_set(self, project_anatom_settings):
|
||||||
attributes_to_set = {}
|
attributes_to_set = {}
|
||||||
|
|
||||||
|
attribute_values_by_key = {}
|
||||||
|
for key, entity in project_anatom_settings["attributes"].items():
|
||||||
|
attribute_values_by_key[key] = entity.value
|
||||||
|
|
||||||
cust_attrs, hier_cust_attrs = get_pype_attr(self.session, True)
|
cust_attrs, hier_cust_attrs = get_pype_attr(self.session, True)
|
||||||
|
|
||||||
for attr in hier_cust_attrs:
|
for attr in hier_cust_attrs:
|
||||||
|
|
@ -231,7 +171,7 @@ class PrepareProject(BaseAction):
|
||||||
attributes_to_set[key] = {
|
attributes_to_set[key] = {
|
||||||
"label": attr["label"],
|
"label": attr["label"],
|
||||||
"object": attr,
|
"object": attr,
|
||||||
"default": project_defaults.get(key)
|
"default": attribute_values_by_key.get(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
for attr in cust_attrs:
|
for attr in cust_attrs:
|
||||||
|
|
@ -243,7 +183,7 @@ class PrepareProject(BaseAction):
|
||||||
attributes_to_set[key] = {
|
attributes_to_set[key] = {
|
||||||
"label": attr["label"],
|
"label": attr["label"],
|
||||||
"object": attr,
|
"object": attr,
|
||||||
"default": project_defaults.get(key)
|
"default": attribute_values_by_key.get(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Sort by label
|
# Sort by label
|
||||||
|
|
@ -253,10 +193,10 @@ class PrepareProject(BaseAction):
|
||||||
))
|
))
|
||||||
return attributes_to_set
|
return attributes_to_set
|
||||||
|
|
||||||
def prepare_custom_attribute_items(self, project_defaults):
|
def prepare_custom_attribute_items(self, project_anatom_settings):
|
||||||
items = []
|
items = []
|
||||||
multiselect_enumerators = []
|
multiselect_enumerators = []
|
||||||
attributes_to_set = self._attributes_to_set(project_defaults)
|
attributes_to_set = self._attributes_to_set(project_anatom_settings)
|
||||||
|
|
||||||
self.log.debug("Preparing interface for keys: \"{}\"".format(
|
self.log.debug("Preparing interface for keys: \"{}\"".format(
|
||||||
str([key for key in attributes_to_set])
|
str([key for key in attributes_to_set])
|
||||||
|
|
@ -363,24 +303,15 @@ class PrepareProject(BaseAction):
|
||||||
|
|
||||||
root_names = in_data.pop("__rootnames__", None)
|
root_names = in_data.pop("__rootnames__", None)
|
||||||
root_data = {}
|
root_data = {}
|
||||||
if root_names:
|
for root_name in json.loads(root_names):
|
||||||
for root_name in json.loads(root_names):
|
root_data[root_name] = {}
|
||||||
root_data[root_name] = {}
|
for key, value in tuple(root_values.items()):
|
||||||
for key, value in tuple(root_values.items()):
|
prefix = "{}__".format(root_name)
|
||||||
if key.startswith(root_name):
|
if not key.startswith(prefix):
|
||||||
_key = key[len(root_name):]
|
continue
|
||||||
root_data[root_name][_key] = value
|
|
||||||
|
|
||||||
else:
|
_key = key[len(prefix):]
|
||||||
for key, value in root_values.items():
|
root_data[root_name][_key] = value
|
||||||
root_data[key] = value
|
|
||||||
|
|
||||||
# TODO implement creating of anatomy for new projects
|
|
||||||
# project_name = entities[0]["full_name"]
|
|
||||||
# anatomy = Anatomy(project_name)
|
|
||||||
|
|
||||||
# pop out info about creating project structure
|
|
||||||
create_proj_struct = in_data.pop(self.create_project_structure_key)
|
|
||||||
|
|
||||||
# Find hidden items for multiselect enumerators
|
# Find hidden items for multiselect enumerators
|
||||||
keys_to_process = []
|
keys_to_process = []
|
||||||
|
|
@ -407,54 +338,31 @@ class PrepareProject(BaseAction):
|
||||||
new_key = item.replace(name, "")
|
new_key = item.replace(name, "")
|
||||||
in_data[key].append(new_key)
|
in_data[key].append(new_key)
|
||||||
|
|
||||||
self.log.debug("Setting Custom Attribute values:")
|
self.log.debug("Setting Custom Attribute values")
|
||||||
entity = entities[0]
|
|
||||||
|
project_name = entities[0]["full_name"]
|
||||||
|
project_settings = ProjectSettings(project_name)
|
||||||
|
project_anatomy_settings = project_settings["project_anatomy"]
|
||||||
|
project_anatomy_settings["roots"] = root_data
|
||||||
|
|
||||||
|
custom_attribute_values = {}
|
||||||
|
attributes_entity = project_anatomy_settings["attributes"]
|
||||||
for key, value in in_data.items():
|
for key, value in in_data.items():
|
||||||
|
if key not in attributes_entity:
|
||||||
|
custom_attribute_values[key] = value
|
||||||
|
else:
|
||||||
|
attributes_entity[key] = value
|
||||||
|
|
||||||
|
project_settings.save()
|
||||||
|
|
||||||
|
entity = entities[0]
|
||||||
|
for key, value in custom_attribute_values.items():
|
||||||
entity["custom_attributes"][key] = value
|
entity["custom_attributes"][key] = value
|
||||||
self.log.debug("- Key \"{}\" set to \"{}\"".format(key, value))
|
self.log.debug("- Key \"{}\" set to \"{}\"".format(key, value))
|
||||||
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
# Create project structure
|
|
||||||
self.create_project_specific_config(entities[0]["full_name"], in_data)
|
|
||||||
|
|
||||||
# Trigger Create Project Structure action
|
|
||||||
if create_proj_struct is True:
|
|
||||||
self.trigger_action("create.project.structure", event)
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def create_project_specific_config(self, project_name, json_data):
|
|
||||||
self.log.debug("*** Creating project specifig configs ***")
|
|
||||||
project_specific_path = project_overrides_dir_path(project_name)
|
|
||||||
if not os.path.exists(project_specific_path):
|
|
||||||
os.makedirs(project_specific_path)
|
|
||||||
self.log.debug((
|
|
||||||
"Project specific config folder for project \"{}\" created."
|
|
||||||
).format(project_name))
|
|
||||||
|
|
||||||
# Presets ####################################
|
|
||||||
self.log.debug("--- Processing Presets Begins: ---")
|
|
||||||
|
|
||||||
project_defaults_dir = os.path.normpath(os.path.join(
|
|
||||||
project_specific_path, "presets", "ftrack"
|
|
||||||
))
|
|
||||||
project_defaults_path = os.path.normpath(os.path.join(
|
|
||||||
project_defaults_dir, "project_defaults.json"
|
|
||||||
))
|
|
||||||
# Create folder if not exist
|
|
||||||
if not os.path.exists(project_defaults_dir):
|
|
||||||
self.log.debug("Creating Ftrack Presets folder: \"{}\"".format(
|
|
||||||
project_defaults_dir
|
|
||||||
))
|
|
||||||
os.makedirs(project_defaults_dir)
|
|
||||||
|
|
||||||
with open(project_defaults_path, 'w') as file_stream:
|
|
||||||
json.dump(json_data, file_stream, indent=4)
|
|
||||||
|
|
||||||
self.log.debug("*** Creating project specifig configs Finished ***")
|
|
||||||
|
|
||||||
|
|
||||||
def register(session):
|
def register(session):
|
||||||
'''Register plugin. Called when used as an plugin.'''
|
'''Register plugin. Called when used as an plugin.'''
|
||||||
PrepareProject(session).register()
|
PrepareProjectLocal(session).register()
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,14 @@
|
||||||
"not ready"
|
"not ready"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"prepare_project": {
|
||||||
|
"enabled": true,
|
||||||
|
"role_list": [
|
||||||
|
"Pypeclub",
|
||||||
|
"Administrator",
|
||||||
|
"Project manager"
|
||||||
|
]
|
||||||
|
},
|
||||||
"sync_hier_entity_attributes": {
|
"sync_hier_entity_attributes": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"interest_entity_types": [
|
"interest_entity_types": [
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,25 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "dict",
|
||||||
|
"key": "prepare_project",
|
||||||
|
"label": "Prepare Project",
|
||||||
|
"checkbox_key": "enabled",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"key": "enabled",
|
||||||
|
"label": "Enabled"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "list",
|
||||||
|
"key": "role_list",
|
||||||
|
"label": "Roles",
|
||||||
|
"object_type": "text"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "dict",
|
"type": "dict",
|
||||||
"key": "sync_hier_entity_attributes",
|
"key": "sync_hier_entity_attributes",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue