Hi All,
I have created a python tool that allows multiple users to create a storymap based on a template. I have manually grouped these together to create a collection. However, I would like to implement an instruction that will programatically add the newly created storymap to the collection.
I have inspected the collection and all I can see is a dictionary of a single Collection-UI node. Is there a way to do this noting that I am using arcgis 2.2.0?
** UPDATE - I can access the json file and can see I need to add another resourceId node defining type and specifying the item id of the portal item. So my question now is: how do I add a resourceId node to the json file?
Solved! Go to Solution.
Hi @atmosfairy You have made a lot of progress.
Unfortunately the python API does not currently support StoryMap Collections. But that will be fixed with the April 2.3.0 release.
You are on the right track. We will need to update the json file for the collection programmatically. And possibly do a few things to the Collection metadata depending on your use case. I just have a couple questions in order to understand the workflow better:
1. Are you creating a brand new Collections, or planning to add to an existing Collection?
2. Do you plan to verify the Collection after running your script before publishing the changes?
In the end you will probably need to use a combination of the the following methods/packages to get this working:
ResourceManager.add (esri python api)
Item.update (esri python api)
json (built in python package)
We always recommend QA on items generated programmatically.
Here is some code to get you started. Updating the itemKeywords will be important in order to point your story to the newly created draft. You might need to modify as needed
#Get collection Item
target_collection = Item(itemid="COLLECTION_ITEM_ID")
target_collection_json = draft_data = draft_data =
#This draft will be modified with new information
draft_data = target_collection.resources.get("published_data.json", try_json=True)
#Generate a new draft_filename
draft_file_name = f"draft_{unix_timestamp}.json"
#Get the node that will get the new items
root_id = draft_data['root']
ui_child_id = draft_data['nodes']['root_id']['children'][0]
collention_ui_node = draft_data['nodes']['ui_child_id']
for storyID in storymap_list:
#generate new resourceID
generated_resource_id = f"r-{uuid4()[:6]}"
#Add StoryMap Id as new Item
draft_data['resources'][generated_resource_id] = {
"type": "portal-item",
"data": {
"itemId": storyID
}
}
#Update Itemrefs
collection_ui_node['data'['items'].append({"resourceId":generated_resource_id})
#Remove existing Keywords
keywords = target_collection.typeKeywords
if 'smstatuspublished'in keywords:
keywords.pop('smstatuspublished')
if 'smstatusunpublishedchanges' in keywords:
keywords.pop('smstatusunpublishedchanges')
#Append Editor App, unpublished and Draft pointer keyword
keywords.append('smeditorapp:python')
keywords.append('unpublished')
keywords.append(f'smdraftresourceid:{draft_file_name}.json')
#update keywords on the item
target_collection.update(item_properties={"typeKeywords":keywords})
#add the new Draft as a resource
target_collection.resources.add(file_name=draft_file_name, text=json.dumps(data, indent=4))
Hi @atmosfairy You have made a lot of progress.
Unfortunately the python API does not currently support StoryMap Collections. But that will be fixed with the April 2.3.0 release.
You are on the right track. We will need to update the json file for the collection programmatically. And possibly do a few things to the Collection metadata depending on your use case. I just have a couple questions in order to understand the workflow better:
1. Are you creating a brand new Collections, or planning to add to an existing Collection?
2. Do you plan to verify the Collection after running your script before publishing the changes?
In the end you will probably need to use a combination of the the following methods/packages to get this working:
ResourceManager.add (esri python api)
Item.update (esri python api)
json (built in python package)
Hi @ThePreatorian,
In 99% of cases, I will be adding new storymaps to an existing collection; however, there may be the need to create a new collection from time-to-time.
Haven't thought about verifying the Collection after running script, but before publishing changes - is this the recommended workflow?
And thanks for getting back to me - good to know that this functionality is just around the corner
We always recommend QA on items generated programmatically.
Here is some code to get you started. Updating the itemKeywords will be important in order to point your story to the newly created draft. You might need to modify as needed
#Get collection Item
target_collection = Item(itemid="COLLECTION_ITEM_ID")
target_collection_json = draft_data = draft_data =
#This draft will be modified with new information
draft_data = target_collection.resources.get("published_data.json", try_json=True)
#Generate a new draft_filename
draft_file_name = f"draft_{unix_timestamp}.json"
#Get the node that will get the new items
root_id = draft_data['root']
ui_child_id = draft_data['nodes']['root_id']['children'][0]
collention_ui_node = draft_data['nodes']['ui_child_id']
for storyID in storymap_list:
#generate new resourceID
generated_resource_id = f"r-{uuid4()[:6]}"
#Add StoryMap Id as new Item
draft_data['resources'][generated_resource_id] = {
"type": "portal-item",
"data": {
"itemId": storyID
}
}
#Update Itemrefs
collection_ui_node['data'['items'].append({"resourceId":generated_resource_id})
#Remove existing Keywords
keywords = target_collection.typeKeywords
if 'smstatuspublished'in keywords:
keywords.pop('smstatuspublished')
if 'smstatusunpublishedchanges' in keywords:
keywords.pop('smstatusunpublishedchanges')
#Append Editor App, unpublished and Draft pointer keyword
keywords.append('smeditorapp:python')
keywords.append('unpublished')
keywords.append(f'smdraftresourceid:{draft_file_name}.json')
#update keywords on the item
target_collection.update(item_properties={"typeKeywords":keywords})
#add the new Draft as a resource
target_collection.resources.add(file_name=draft_file_name, text=json.dumps(data, indent=4))
Love that! Thanks @ThePreatorian. Will get back to you if I have any further questions.
Noticed A couple of naming/syntax issues with the previous code. Cleaned up a bit here:
#Get collection Item
target_collection = Item(itemid="COLLECTION_ITEM_ID")
#This draft will be modified with new information
draft_data = target_collection.resources.get("published_data.json", try_json=True)
#Generate a new draft_filename
draft_file_name = f"draft_{unix_timestamp}.json"
#Get the node that will get the new items
root_id = draft_data['root']
ui_child_id = draft_data['nodes']['root_id']['children'][0]
collention_ui_node = draft_data['nodes']['ui_child_id']
for storyID in storymap_list:
#generate new resourceID
generated_resource_id = f"r-{uuid4()[:6]}"
#Add StoryMap Id as new Item
draft_data['resources'][generated_resource_id] = {
"type": "portal-item",
"data": {
"itemId": storyID
}
}
#Update Itemrefs
collection_ui_node['data'['items'].append({"resourceId":generated_resource_id})
#Remove existing Keywords
keywords = target_collection.typeKeywords
if 'smstatuspublished'in keywords:
keywords.pop('smstatuspublished')
if 'smstatusunpublishedchanges' in keywords:
keywords.pop('smstatusunpublishedchanges')
#Append Editor App, unpublished and Draft pointer keyword
keywords.append('smeditorapp:python')
keywords.append('unpublished')
keywords.append(f'smdraftresourceid:{draft_file_name}.json')
#update keywords on the item
target_collection.update(item_properties={"typeKeywords":keywords})
#add the new Draft as a resource
target_collection.resources.add(file_name=draft_file_name, text=json.dumps(draft_data, indent=4))
@ThePreatorian that is helpful advice to QA programmatically created content. Do you know where one can find a definition of the StoryMap model to check against, such as what keywords are required, optional, etc.?
At this time, we have not published developer documentation for ArcGIS StoryMaps. However, you can use the StoryMap , Briefing , and Collection classes in the Python API to create ArcGIS StoryMap items. These classes manage keywords, and we do not recommend editing them manually. If you need to query keywords for your scripts, you can use the {Class}._item.typeKeywords property.
Please note the above advice of manually manipulating everything is only applicable until Python v2.3.0 is released around April 2024. After that release, Collections and Briefings will be supported in the API, so the recommended way to manipulate the Collection would be to use the class-specific methods.
If you have any further questions or need more information, feel free to ask!