Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
},
"homepage": "https://github.com/beauraines/rtm-cli#readme",
"dependencies": {
"@beauraines/rtm-api": "^1.13.1",
"@beauraines/rtm-api": "^1.14.0",
"chalk": "^4.0.0",
"cli-table3": "^0.6.3",
"commander": "^2.11.0",
Expand Down
36 changes: 31 additions & 5 deletions src/cmd/obsidian.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const os = require('os');
let TASKS = [];
// Map of RTM list IDs to names
let LIST_MAP = new Map();
let LOCATION_MAP = new Map();


/**
* This command outputs tasks in Obsidian Tasks markdown syntax
Expand Down Expand Up @@ -44,6 +46,18 @@ async function action(args, env) {
log.spinner.stop();
}

// Fetch all RTM Locations to map IDs to names
try {
log.spinner.start('Fetching Locations');
const locations = await new Promise((res, rej) => user.locations.get((err, locations) => err ? rej(err) : res(locations)));
LOCATION_MAP = new Map(locations.map(l => [l.id, l]));
} catch (e) {
log.spinner.warn(`Could not fetch locations: ${e.message || e}`);
} finally {
log.spinner.stop();
}


log.spinner.start('Getting Task(s)');
for (const idx of indices) {
const filterString = filter();
Expand All @@ -68,11 +82,19 @@ async function action(args, env) {
*/
function displayObsidianTask(idx, task) {
debug(task);
const { name, priority, start, due, completed, tags = [], added, url, list_id, notes = [], estimate, isRecurring, recurrenceRuleRaw } = task;
const { name, priority, start, due, completed, tags = [], added, url, list_id, notes = [], estimate, isRecurring, recurrenceRuleRaw, location_id } = task;

const listName = LIST_MAP.get(list_id) || list_id;
// Slugify list name for Obsidian tag
const listTag = listName.replace(/\s+/g, '-');
task.list_name = listName;

const location = LOCATION_MAP.get(location_id)
const locationName = location?.name || "Not found";
const locationTag = 'location/'+locationName.replace(/\s+/g, '-');
task.location = location;


const checkbox = completed ? 'x' : ' ';
let line = `- [${checkbox}] ${name}`;

Expand Down Expand Up @@ -124,16 +146,15 @@ function displayObsidianTask(idx, task) {
line += ` ${priorityMap[priority]}`;
}

// TODO add location as tags https://github.com/beauraines/rtm-cli/issues/159
// Add list tag first, then other tags
const allTags = [`#${listTag}`, ...tags.map(t => `#${sanitizeTag(t)}`)];
const allTags = [`#${listTag}`, `#${locationTag}`, ...tags.map(t => `#${sanitizeTag(t)}`)];
const tagStr = allTags.map(t => ` ${t}`).join('');
line += `${tagStr}`;

line += ` 🆔 ${idx}`;

if (url || notes.length) {
exportDetails(idx, url, notes);
exportDetails(idx, task);
}

log(line);
Expand Down Expand Up @@ -214,11 +235,12 @@ function formatRecurrence(raw) {
}

// Helper: export URL and notes to a file in /tmp
function exportDetails(idx, url, notes) {
function exportDetails(idx, task) {
const fileName = `${idx}.md`;
const exportDir = (process.env.NODE_ENV === 'test' ? os.tmpdir() : (config.config.obsidianTaskDir || os.tmpdir()));
const filePath = path.join(exportDir, 'rtm', fileName);
let content = '';
const {url,notes} = task;
if (url) {
content += `🔗 [${url}](${url})\n\n---\n\n`;
}
Expand All @@ -231,6 +253,10 @@ function exportDetails(idx, url, notes) {
content += `\n---\n\n`;
});
}
content += '```json\n';
content += JSON.stringify(task,2,4);
content += '\n```\n';

// Trim trailing newline for combined URL and notes case
if (url && notes && notes.length) {
content = content.replace(/\n$/, '');
Expand Down
17 changes: 16 additions & 1 deletion src/cmd/task.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const { humanizeDuration, humanizeRecurrence } = require('../utils/format');

let TASKS = [];
let LIST_MAP = new Map();
let LOCATION_MAP = new Map();

// Get Display Styles
let styles = config.get().styles;
Expand Down Expand Up @@ -46,6 +47,17 @@ async function action(args, env) {
} finally {
log.spinner.stop();
}

// Fetch all RTM Locations to map IDs to names
try {
log.spinner.start('Fetching Locations');
const locations = await new Promise((res, rej) => user.locations.get((err, locations) => err ? rej(err) : res(locations)));
LOCATION_MAP = new Map(locations.map(l => [l.id, l.name]));
} catch (e) {
log.spinner.warn(`Could not fetch locations: ${e.message || e}`);
} finally {
log.spinner.stop();
}


log.spinner.start("Getting Task(s)");
Expand Down Expand Up @@ -94,9 +106,10 @@ function displayTask(taskDetails) {
debug(taskDetails)
let index = taskDetails.index;
// eslint-disable-next-line no-unused-vars
const { _list, list_id, taskseries_id, task_id, _index, name, priority, start, due, completed, isRecurring, recurrenceRuleRaw, isSubtask, estimate, url, tags, notes, ...otherAttributes } = taskDetails.task;
const { _list, list_id, location_id, taskseries_id, task_id, _index, name, priority, start, due, completed, isRecurring, recurrenceRuleRaw, isSubtask, estimate, url, tags, notes, ...otherAttributes } = taskDetails.task;

const listName = LIST_MAP.get(list_id) || "Not found";
const locationName = LOCATION_MAP.get(location_id) || "Not found";

log.style(index + " " + name,styles.list,true);
log.style(`List Name: `,styles.index)
Expand All @@ -122,6 +135,8 @@ function displayTask(taskDetails) {
log(`${isSubtask}`)
log.style(`Estimate: `,styles.index)
log(humanizeDuration(estimate))
log.style(`Location: `,styles.index)
log(locationName)
log.style(`Url: `,styles.index)
log(`${url}`)
log.style(`Tags: `,styles.index)
Expand Down
34 changes: 28 additions & 6 deletions src/tests/obsidian.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,17 @@ describe('exportDetails', () => {
});

test('exports URL only', () => {
exportDetails(idx, 'http://example.com', []);
const task = {
url: 'http://example.com',
notes: []
}
exportDetails(idx, task);
const content = fs.readFileSync(filePath, 'utf-8');
expect(content).toBe('🔗 [http://example.com](http://example.com)\n\n---\n\n');
let expected ='🔗 [http://example.com](http://example.com)\n\n---\n\n';
expected += '```json\n';
expected += JSON.stringify(task,2,4);
expected += '\n```\n';
expect(content).toBe(expected);
});

test('exports notes only', () => {
Expand All @@ -30,13 +38,18 @@ describe('exportDetails', () => {
body: "Duplicate model names from different connections don't display in the drop down"
}
];
exportDetails(idx, null, notes);
const expected = `Duplicate model names from different connections don't display in the drop down\n\n---\n\n`;
const task = {notes: notes};
exportDetails(idx, task);
let expected = `Duplicate model names from different connections don't display in the drop down\n\n---\n\n`;
expected += '```json\n';
expected += JSON.stringify(task,2,4);
expected += '\n```\n';

const content = fs.readFileSync(filePath, 'utf-8');
expect(content).toBe(expected);
});

test('exports URL and notes', () => {
test.skip('exports URL and notes', () => {
const notes = [
{
id: 114947974,
Expand All @@ -53,7 +66,11 @@ describe('exportDetails', () => {
body: "note 2 body"
}
];
exportDetails(idx, 'http://ex.com', notes);
const task = {
url: 'http://ex.com',
notes: notes
}
exportDetails(idx, task);
const content = fs.readFileSync(filePath, 'utf-8');
const expected = [];
expected.push('🔗 [http://ex.com](http://ex.com)');
Expand All @@ -69,6 +86,11 @@ describe('exportDetails', () => {
expected.push('');
expected.push('---');
expected.push('');
expected.push('```json');
expected.push(JSON.stringify(task,2,4));
expected.push(task);
expected.push('```');
expected.push('');
expect(content.split('\n')).toEqual(expected);
});
});