Building a Monthly Archive

The goal: Write out every draft from the previous month to a text file according to a template.

I’ve hacked together a rough version of this based off of @drdrang’s Assemble Diary action, modified thusly:

// Start a new draft
editor.new();

// Get all the "diary" drafts in the inbox
var diaryDrafts = Draft.query("", "inbox");

// Assemble
var ds = draft.processTemplate("[[date|%Y-%m-%d %H:%M %z]]");
var diaryContent = "Diary as of " + ds + "\n\n";
for (var i=0; i<diaryDrafts.length; i++) {
	var stamp = diaryDrafts[i].processTemplate("[[created|%Y-%m-%d %H:%M %z]]") + "\n" + diaryDrafts[i].processTemplate("[[created_latitude]], [[created_longitude]]") + "\n" + diaryDrafts[i].processTemplate("[[tags]]") + "\n";
	diaryContent += stamp + diaryDrafts[i].content + "\n\n";
	diaryDrafts[i].isArchived = true;
	diaryDrafts[i].update();
}

// Make the diary
editor.setText(diaryContent);
editor.save();

As is likely obvious to someone with more JavaScript Kung Fu than I, I’ve built some of my template into the script itself. I’d much rather call out to a template file like:

#### [[title]]

[[body]]

###### [[created|%Y-%m-%dT%k-%M-%S-%z]] | [[created_latitude]], [[created_longitude]] | [[tags]]

****

I know I need two things:

  1. The JS necessary to accomplish Draft.query("[[created]] is last month", "inbox")
  2. To remove the templating from the JS itself.
1 Like
  1. You cannot specify a date range in a query…so you would have to handle it by filtering your results. The Inbox Sweeper example action demonstrates a way to do this, but roughly:
// define the cutoff date
let cutoffDate = Date.today().addDays(-31); // 31 days ago
// query all inbox drafts
let queriedDrafts = Draft.query("", "inbox", [], [], "created", false);
// filter out any older than cutoffDate
let filteredDrafts = queriedDrafts.filter(d => d.createdAt > cutoffDate);
// now use `filteredDrafts` in your loop...
  1. The Define Template Tag exists primarily for this need. Put one of these steps before your script step, put your template in it, and give it a name, like my-template. Then in your script, you can just make that change the line as follows:
var stamp = diaryDrafts[i].processTemplate("[[my-template]]");
1 Like

Thank you Greg for the quick response!!!

I apologize for asking some more rudimentary questions, but I’m unclear as to how to rewrite Drang’s script around calling out to that template. I wonder if you wouldn’t mind amending his script with the appropriate changes; to strip out the formatting from the script and house it? I’d love some comments to help me learn what each line is doing.

var date = draft.processTemplate("[[date|%Y-%m-%d]]");
var diaryContent = "# " + date + " -- Drafts Log" + "\n\n";
for (var i=0; i<diaryDrafts.length; i++) {
   var stamp = diaryDrafts[i].processTemplate("[[monthly-log]]");
	diaryContent += "### " + diaryDrafts[i].content + "\n" + stamp + "\n" + "****" + "\n\n";
	diaryDrafts[i].isArchived = true;
	diaryDrafts[i].update();
}

Something like this for the loop would work…assuming you setup the define template step as described:

for (var i=0; i<diaryDrafts.length; i++) {
    // create the new templatized version for this draft...
    let newContent = diaryDrafts[i].processTemplate("[[my-template]]");
    // add it to the complete content...
    diaryContent = diaryContent + newContent;

    diaryDrafts[i].isArchived = true;
    diaryDrafts[i].update();
}

Minor quibble, but I would rewrite the loop without the C-style index to make it more readable, like:

for (let d of diaryDrafts) {
    // create the new templatized version for this draft...
    let newContent = d.processTemplate("[[my-template]]");
    // add it to the complete content...
    diaryContent = diaryContent + newContent;

    d.isArchived = true;
    d.update();
}

Still hitting the wall :frowning_face:

I’ve got a Define Template Tag step called monthly-log that looks like this:

****

#### [[title]]

[[body]]

###### [[created|%Y-%m-%dT%k-%M-%S-%z]] | [[created_latitude]], [[created_longitude]] | [[tags]]

****

And then a Script step:

// Start a new draft
editor.new();

// Get all the "diary" drafts in the inbox
var diaryDrafts = Draft.query("", "inbox");

// Assemble
var date = draft.processTemplate("[[date|%Y-%m-%d]]");
var diaryContent = "# " + date + " -- Drafts Log" + "\n\n";
for (let d of diaryDrafts) {
    // create the new templatized version for this draft...
    let newContent = d.processTemplate("[[monthly-log]]");
    // add it to the complete content...
    diaryContent = diaryContent + newContent;

    d.isArchived = true;
    d.update();
}

// Make the diary
let fm = FileManager.createCloud();
fm.writeString(date+" -- Drafts Log"+".md", diaryContent);

I promise I’m not being intentionally dense :smile:

Are you getting an error in the log?

I’m not getting an error at this point, but I hope this will help shed some light on the problem:

I’m listening to you on MPU at the moment, btw. Nice to put a voice to your name :slight_smile:

Just a friendly nudge :slight_smile: Let me know what else I can provide to understand the state of play.

I had a similar problem that I couldn’t seem to get to work reliably, and after sending a test script to @agiletortoise , they discovered that the template tag functionality was struggling with nested tags, and said this would get fixed in a future update when this functionality was rewritten.

I avoided the problem by simply keeping the templates inside the js-script and it works perfectly. Use the new multiline strings with backticks to make it more readable and easier to maintain.

So in your case, I would just store the template at the top of the script for easy access like this:

let template = `****

#### [[title]]

[[body]]

###### [[created|%Y-%m-%dT%k-%M-%S-%z]] | [[created_latitude]], [[created_longitude]] | [[tags]]

****`

and then later in the script you can process it like before:

let diarycontent = d.processTemplate(template);

@steinar’s answer is the correct one. The “Define Template Tag” step is for defining a value to be inserted with a template. You are trying to use it to define a template. Tags inside that value will not necessarily be evaluated because the template engine is not recursive.

Basically, a template tag should not contain more template tags.

Thank you both for chiming in. The adjustment you recommended @steinar worked perfectly, though that naturally means I see one more change I’d like to make :stuck_out_tongue:

I’d like to adjust my final tag output, and so I’ve added something @agiletortoise helped me with previously. I’ve got the script set up thusly:

// Get all the "diary" drafts in the inbox
var diaryDrafts = Draft.query("", "inbox");

// Print tags with GitLab quick action syntax
let tags = draft.tags.map(t => `~${t}`).join(" ");
draft.setTemplateTag("formattedtags", tags);
// use [[formattedtags]] in subsequent action steps

// Declare the Final Template
let template = `#### [[title]]
[[body]]
###### [[created|%Y-%m-%dT%k-%M-%S-%z]] | [[created_latitude]],[[created_longitude]] | [[formattedtags]]

****

`
// Start a new draft
editor.new();

// Assemble
var date = draft.processTemplate("[[date|%Y-%m-%d]]");
var diaryContent = "## " + date + " -- Drafts Log" + "\n\n";
for (let d of diaryDrafts) {
    // create the new templatized version for this draft...
    let newContent = d.processTemplate(template);
    // add it to the complete content...
    diaryContent = diaryContent + newContent;

    d.isArchived = true;
    d.update();
}

// Make the diary
let fm = FileManager.createCloud();
fm.writeString(date+" -- Drafts Log"+".md", diaryContent);

and instead of the tags themselves, I’m getting [[formattedtags]] in my output.

Template tags are specific to a draft. You are setting the custom tag on the draft, but then processing the template on a different draft (the d variable). I think you actually want the tags to be derived from each individual draft you are looping over as well…so move that to the loop, like:

for (let d of diaryDrafts) {
    let tags = d.tags.map(t => `~${t}`).join(" ");
    d.setTemplateTag("formattedtags", tags);

    // create the new templatized version for this draft...
    let newContent = d.processTemplate(template);
    // add it to the complete content...
    diaryContent = diaryContent + newContent;

    d.isArchived = true;
    d.update();
}

Thank you sir! Y’all have got me quite a bit closer to having Drafts act as my front-end to GitLab Issues :smiley:

1 Like