Calling an action after setTemplateTag (bug with app.queueAction)

I have a script that sets a template tag then queues up multiple actions. On macOS, the tag is unset when the last action is run, and on iOS, the tag does not seem to set at all.

Action 1:

draft.setTemplateTag("Test","Hello World");

// Using draft.update() appears to makes no difference.
//draft.update();

// My original code
var actions = ["Action 2","Action 2","Action 2"]
for (var i in actions) {
  		action = Action.find(actions[i]);
  		app.queueAction(action, draft);
}

// Same problem using this code
/*
action = Action.find("Action 2");
app.queueAction(action, draft);
action = Action.find("Action 2");
app.queueAction(action, draft);
action = Action.find("Action 2");
app.queueAction(action, draft);
*/

Action 2

var tag = draft.getTemplateTag("Test");
if ( tag ) {
	alert("Template tag set to: " + tag);
} else {
	alert("Template tag is not set.");
}

Template tags are not intended to persist between actions. This is referenced explicitly in the custom template tag docs.

Note that queued actions are separate actions that are run after the original action and so should not be able to access such tags.

Forgive me, maybe I’m just having a dyslexic moment here, but where does it say that tags do are not intended to persist between actions? I don’t see it.

In addition to the predefined tags always available, scripts in an action can create custom tags which become available to action steps run after the script in the same action. This is useful if a scripted action step processes text to create a value that then needs to be inserted in a later step that shares that text. The below example shows a simple script with creates a tag.

If that is the intended behavior then I’ll find a different way to pass information between the scripts. Not a problem. However, I’m still getting a bug running the following code on iOS and macOS.

draft.setTemplateTag("Test","Hello World");
action = Action.find("Action 2");
app.queueAction(action, draft);

Action 2 reports that no tag has been set.

I think @sylumer’s description is correct. As stated in the quote you inserted, “custom tags which become available to action steps run after the script in the same action”. This is definitely not a bug.

Queuing an action is setting it up to run after the current action, but it is not part of the same action, so has a different context. Perhaps that could be clarified more in the scripting docs…current text, “Queues an action to run on a draft after the current action is complete.”

There are many other ways to pass data between actions, if that is your desired outcome…which is best might depend on what you are trying to pass. Do you have a more concrete explanation of what you are trying to accomplish?

1 Like

Thanks for the clarification.

I’m trying to set a template tag in one action that can be used in the callback URL of a second action, specifically the name of a journal in DayOne.

For example, my first action adds a template tag of “journal” with the value “Memories.” Then, my second action checks to see if the journal tag is set. If not, it prompts me to pick one, and if it is, it opens the DayOne callback URL using the predefined template tag.

Maybe I’m misusing tags because I’ve been chaining actions together this way for months. The only difference is that I have been using Step Types instead of a script. With Step Types, you can have a “Define Template Tag” step followed by an “Include Action” step, and the template tag will persist. This is why I thought it was a scripting bug.

Am I using tags wrong, or is there a difference between the way Step Types and app.queueAction are processed?

Steps are within a single action and a single context for the custom template tags.

Queueing of actions are all separate actions and so have separate contexts. The custom tags are unique to the context of each queued* separat* action.

1 Like

Got it! Thank you so much.

So then there is no equivalent “Insert Action” that can be used with scripting?

There is not scripting equivalent of the Include Action step. The action name field in the Include Action step is a dynamic template, however…so, you can use a template tag to define the action used…so, if your script does:

draft.setTemplateTag("actionName", "Action 2");

And there is an Include Action step after that script with the action name defined as [[actionName]], it will roll in the steps from “Action 2”.

1 Like

hi @dewittn looks like a nice nut of automation you have set to crack yourself.

Would you be willing to share your working action here or via the action directory?

I would be highly interested

Thanks
Andreas

HI @Andreas_Haberle, yeah absolutely!

The basic idea is that I want to have a global action that handles the creation of DayOne entries.

Every morning I start the day with a “morning pages” exercise where I clear my head and write down any tasks I need to do for the day. When I’m done writing, I have a Complete Morning Pages action that marks the task complete in Streaks, creates a new draft from selected text, and sends all To-do’s to things. Once all of those steps have been completed the draft is passed off to the DayOne action which files it away.

I could combine all of these actions into a single script but I’d like to keep the morning pages routine separate from the DayOne export. This not only makes my DayOne action reusable with other actions, but makes it easier to manage if I ever want to make changes to the way I export to DayOne.

Here is the code for the two related actions.

Action: Complete Morning Pages

Step 1: Script

// If running on an iPhone or iPad, open streaks.
const baseURL = "streaks://x-callback-url/completed/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
if (device.model != "Mac") { openCallback(baseURL); }
  
draft.setTemplateTag("journal","Morning Pages");

// Que actions to run 
var actions = ["New from selection","Send To-do’s to things","DayOne"]
  for (var i in actions) {
  		action = Action.find(actions[i]);
  		app.queueAction(action, draft);
 }

Action: DayOne

Step 1: Script

var journals = [
	"Journal",
	"Morning Pages",
	"Memories",
	"Frisbee Scores"
	];
var templateTag = "journal";

if (!draft.getTemplateTag(templateTag)) {
  var p = Prompt.create();
  p.title = "Choose A Journal";
  p.message = "Which Journal would you like to use?";
  p.addButton("OK");
  p.addSelect(templateTag, "Journals", journals);

  if (p.show()) { 
   draft.setTemplateTag(templateTag,p.fieldValues[templateTag]);
  } else {
    context.cancel();
  }
}

Step 2: URL

dayone2://post?entry=[[draft]]&tags=[[tags]]&journal=[[journal]]

I like passing Template tags between scripts because it can drop right into the URL schema. I’ve been running it this way for months using the Include Action Step Type but I wanted to see if I could replicate this behavior with code.

Another possible solution could be to save the journey name as a tag or append it as text to the end of the draft. I don’t like those solutions as much because then I’m adding something to a draft only to remove it in the next action.

After some more testing, the code below works and sets a template tag for a queued action, but I have a feeling it might be more of a hack than an actual solution. :sweat_smile:

var d = Draft.find(draft.uuid);
var action = Action.find("DayOne");

d.setTemplateTag("journal","Morning Pages");
app.queueAction(action, d);
1 Like

You could store them as metadata using the functions I wrote into the TADpoLe library. They store the data outside of the draft so as not to pollute the existing content or meta data (e.g. tags).

Once you include the library (including the TAD action from the ThoughtAsylum Action group (download it and run the refresh action as per the instructions to get the latest library file on your devices) you can then call the meta data functions.

draft.TA_metaRead() will initialise the current draft with any persistent data held on file.

draft.TA_metaWrite() will write the current draft meta data to be persistently held to file.

Then in action #1 you could write something like this:

draft.TA_metaRead();
draft.meta.test = "hello world";
draft.TA_metaWrite();

In action 2, you could read the value of the test property back like this:

draft.TA_metaRead();
alert(draft.meta.test);

Examples:

Hope that helps.

2 Likes

@sylumer This is great! I had no idea that library existed. I’ll definitely check it out! Thank you!