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
4 changes: 2 additions & 2 deletions jgclark.DailyJournal/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
"plugin.icon": "",
"plugin.author": "Jonathan Clark",
"plugin.url": "https://github.com/NotePlan/plugins/blob/main/jgclark.DailyJournal/README.md",
"plugin.version": "0.6.2",
"plugin.version": "0.6.4",
"plugin.dependencies": [],
"plugin.script": "script.js",
"plugin.isRemote": "false",
"plugin.commands": [
{
"name": "dayStart",
"description": "Start today's daily note with a template, including local weather lookup (requires configuring)",
"description": "Start today's daily note with a template (requires configuring)",
"jsFunction": "dayStart",
"requested_interval": "24h"
},
Expand Down
237 changes: 115 additions & 122 deletions jgclark.DailyJournal/script.js

Large diffs are not rendered by default.

8 changes: 3 additions & 5 deletions jgclark.DailyJournal/src/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
// @flow

//-----------------------------------------------------------------------------
// Statistic commands for notes and projects
// Jonathan Clark & Eduard Metzger
// v0.6.0, 8.6.2021
// Daily Journal commands
// Jonathan Clark
// v0.6.4, 18.6.2021
//-----------------------------------------------------------------------------

// export { default as showNoteCount } from './showNoteCount'
export { dayStart, dayReview } from './script'
export { getWeatherSummary } from './weather'
3 changes: 0 additions & 3 deletions jgclark.DailyJournal/src/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,3 @@ export async function dayReview() {
true,
)
}

// globalThis.dayStart = dayStart
// globalThis.dayReview = dayReview
4 changes: 2 additions & 2 deletions nmn.Templates/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
"plugin.icon": "f120",
"plugin.author": "Naman Goel",
"plugin.repoUrl": "tbd",
"plugin.version": "0.0.1",
"plugin.version": "0.1.0",
"plugin.dependencies": [ ],
"plugin.script": "script.js",
"plugin.isRemote": "false",
"plugin.commands": [
{
"name": "it",
"description": "Choose a Template to apply to an existing Note",
"jsFunction": "addTemplate"
"jsFunction": "applyTemplate"
},
{
"name": "nn",
Expand Down
189 changes: 151 additions & 38 deletions nmn.Templates/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -9329,7 +9329,20 @@ The first code-block within the note will always be used. So edit the default co
// can be "short", "medium", "long" or "full"
dateStyle: 'short',
// optional key, can be "short", "medium", "long" or "full"
timeStyle: 'short,
timeStyle: 'short',
},

// configuration for weather data
weather: {
// API key for https://openweathermap.org/
// !!REQUIRED!!
openWeatherAPIKey: '... put your API key here ...',
// Default location for weather forcast
latPosition: 0.0,
longPosition: 0.0,
// Default units. Can be 'metric' (for Celsius), or 'metric' (for Fahrenheit)
openWeatherUnits: 'metric',
// When using a weather tag, you can customize these options.
},

// default values for custom tags.
Expand Down Expand Up @@ -9364,6 +9377,18 @@ date:
# can be null (to skip time), "short", "medium", "long" or "full"
timeStyle: short

# configuration for weather data lookups, if wanted
weather:
# API key for https://openweathermap.org/
# !!REQUIRED!!
openWeatherAPIKey: <put your API key here>
# Default location for weather forcast
latPosition: 0.0
longPosition: 0.0
# Default units. Can be 'metric' (for Celsius), or 'metric' (for Fahrenheit)
openWeatherUnits: metric
# When using a weather tag, you can customize these options.

# default values for custom tags.
# These tags cannot be functions, but you may choose to have nested objects.
# feel free to edit this value however you see fit.
Expand Down Expand Up @@ -9392,6 +9417,18 @@ dateStyle = "short"
# can be null (to skip time), "short", "medium", "long" or "full"
timeStyle = "short"

// configuration for weather data
[weather]
// API key for https://openweathermap.org/
# !!REQUIRED!!
openWeatherAPIKey = <put your API key here>
# Default location for weather forcast
latPosition = 0.0
longPosition = 0.0
# Default units. Can be 'metric' (for Celsius), or 'metric' (for Fahrenheit)
openWeatherUnits = 'metric'
# When using a weather tag, you can customize these options.

# default values for custom tags.
[tagValue]
# These tags cannot be functions, but you may choose to have nested objects.
Expand All @@ -9404,24 +9441,6 @@ firstName = "John"
lastName = "Doe"
\`\`\`
`;
/**
*
* The following should be added to the default configuration
* once the weather function works.
*
// configuration for weather data
weather: {
// API key for https://openweathermap.org/
// !!REQUIRED!!
apiKey: '... put your API key here ...',
// Default location for weather forcast
lattitude: 0,
longitude: 0,
// Default temperature unit. Can be "C" (Celcius), "K" (Kelvin) or "F" (Fahrenheit)
unit: 'C',
// When using a weather tag, you can customize these options.
},
*/

const ALLOWED_FORMATS = ['javascript', 'json', 'json5', 'yaml', 'toml', 'ini'];
const FORMAT_MAP = {
Expand Down Expand Up @@ -9529,7 +9548,59 @@ lastName = "Doe"
}
}

// Using https://openweathermap.org/api/one-call-api#data, for which you can get a free API key

async function getWeatherSummary(weatherParams, config) {
const weatherDescText = ['showers', 'rain', 'sunny intervals', 'partly sunny', 'sunny', 'cloud', 'snow ', 'thunderstorm', 'tornado'];
const weatherDescIcons = ["🌦️", "🌧️", "🌤", "⛅", "☀️", "☁️", "🌨️", "⛈", "🌪"]; // Get config settings from Template folder _configuration note

const weatherConfig = config.weather ?? null;

if (weatherConfig == null) {
await showMessage("Cannot find 'weather' settings in Templates/_configuration note");
return '';
}

const pref_openWeatherAPIKey = weatherConfig.openWeatherAPIKey;
const pref_latPosition = weatherConfig.latPosition;
const pref_longPosition = weatherConfig.longPosition;
const pref_openWeatherUnits = weatherConfig.openWeatherUnits;
console.log(`getWeatherSummary: Params: '${weatherParams}'`);
weatherParams.trim() ? await parseJSON5(weatherParams) : {}; // console.log(paramConfig)

const getWeatherURL = `https://api.openweathermap.org/data/2.5/onecall?lat=${pref_latPosition}&lon=${pref_longPosition}&exclude=current,hourly,minutely&units=${pref_openWeatherUnits}&appid=${pref_openWeatherAPIKey}`;
const jsonIn = await fetch(getWeatherURL);

if (jsonIn != null) {
const weatherTodayAll = JSON.parse(jsonIn).daily["0"];
const maxTemp = weatherTodayAll.feels_like.day.toFixed(0);
const minTemp = weatherTodayAll.feels_like.night.toFixed(0);
const weatherDesc = weatherTodayAll.weather["0"].description; // see if we can fix an icon for this as well, according to returned description. Main terms are:
// thunderstorm, drizzle, shower > rain, snow, sleet, clear sky, mist, fog, dust, tornado, overcast > clouds
// with 'light' modifier for rain and snow

let weatherIcon = '';

for (let i = 0; i < weatherDescText.length; i++) {
if (weatherDesc.match(weatherDescText[i])) {
weatherIcon = weatherDescIcons[i];
break;
}
} // TODO: Allow for more customisation of what is pulled out from the API's data structure
// using weatherParams


const summaryLine = `${maxTemp}/${minTemp} ${weatherIcon}${weatherDesc}`;
console.log(`\t${summaryLine}`);
return summaryLine;
} else {
await showMessage('Sorry; error in Weather lookup');
return 'sorry; error in Weather lookup';
}
}

async function processTemplate(content, config) {
console.log(`processTemplate: ${content}`);
const tagStart = content.indexOf('{{');
const tagEnd = content.indexOf('}}');
const hasTag = tagStart !== -1 && tagEnd !== -1 && tagStart < tagEnd;
Expand All @@ -9543,20 +9614,33 @@ lastName = "Doe"
const tag = content.slice(tagStart + 2, tagEnd);

try {
const tagProcessed = await processTag(tag, config);
const tagProcessed = await processTags(tag, config);
const restProcessed = await processTemplate(afterTag, config);
return beforeTag + tagProcessed + restProcessed;
} catch (e) {
console.log(e);
return content;
}
}
} // Apply any matching tag functions

async function processTags(tag, config) {
console.log(`processTag: ${tag}`);

async function processTag(tag, config) {
if (tag.startsWith('date(') && tag.endsWith(')')) {
return await processDate(tag.slice(5, tag.length - 1), config);
}

} else if (tag.startsWith('weather(') && tag.endsWith(')')) {
return await getWeatherSummary(tag.slice(8, tag.length - 1), config);
} // **Add other extension function calls here**
// Can call functions defined in other plugins, by appropriate use
// of imports at top of file (e.g. getWeatherSummary)
// Or declare below (e.g. processDate)
else {
// no matching funcs, so now attempt to match defined tag values instead
return processTagValues(tag, config);
}
} // Apply any matching tag values, asking user for value if not found in configuration

async function processTagValues(tag, config) {
const valueInConfig = tag // eslint-disable-next-line no-useless-escape
.split(/[\.\[\]]/).filter(Boolean).reduce((path, key) => path != null && typeof path === 'object' ? path[key] : null, config.tagValue);

Expand All @@ -9565,15 +9649,19 @@ lastName = "Doe"
}

return await getInput(`Value for ${tag}`);
}
} // ----------------------------------------------------------------
// Define new tag functions here ...

async function processDate(dateConfig, config) {

async function processDate(dateParams, config) {
console.log(`processDate: ${dateConfig}`);
const defaultConfig = config.date ?? {};
const paramConfig = dateConfig.trim() ? await parseJSON5(dateConfig) : {}; // console.log(`param config: ${dateConfig} as ${JSON.stringify(paramConfig)}`);
const paramConfig = dateParams.trim() ? await parseJSON5(dateParams) : {}; // console.log(`param config: ${dateParams} as ${JSON.stringify(paramConfig)}`);

const finalArguments = { ...defaultConfig,
...paramConfig
};
}; // ... = "gather the remaining parameters into an array"

const {
locale,
...otherParams
Expand All @@ -9587,11 +9675,35 @@ lastName = "Doe"
return new Intl.DateTimeFormat(localeParam, secondParam).format(new Date());
}

async function addTemplate(newNote) {
async function applyNamedTemplate(templateName) {
console.log(`applyNamedTemplate: for template '${templateName}'`);
const templateFolder = await getTemplateFolder();

if (templateFolder == null) {
console.log(`\twarning: templateFolder is null`);
await makeTemplateFolder();
await showMessage('Try using this command again to use a template');
return;
}

const selectedTemplate = DataStore.projectNoteByTitle(templateName, true, false)[0];
let templateContent = selectedTemplate?.content;

if (templateContent == null || templateContent.length === 0) {
console.log(`\twarning: template '${templateName}' is null or empty`);
return;
}

templateContent = templateContent.split('\n---\n').slice(1).join('\n---\n');
const config = (await getDefaultConfiguration()) ?? {};
const processedTemplateContent = await processTemplate(templateContent, config);
Editor.content = [Editor.content, processedTemplateContent].filter(Boolean).join('\n');
}
async function applyTemplate(newNote) {
const templateFolder = await getTemplateFolder();

if (templateFolder == null) {
console.log(`addTemplate: templateFolder is null`);
console.log(`applyTemplate: warning: templateFolder is null`);
await makeTemplateFolder();
await showMessage('Try using this command again to use a template');
return;
Expand All @@ -9601,8 +9713,8 @@ lastName = "Doe"
label: note.title,
value: note
}).filter(Boolean);
console.log(`addTemplate: found ${options.length} options`);
console.log(`addTemplate: asking user which template:`);
console.log(`applyTemplate: found ${options.length} options`); // console.log(`applyTemplate: asking user which template:`)

const selectedTemplate = await chooseOption('Choose Template', options);
let templateContent = selectedTemplate?.content;

Expand Down Expand Up @@ -9642,15 +9754,15 @@ lastName = "Doe"

if (!title) {
console.log('\tError: undefined or empty title');
await showMessage('Cannot create a not with an empty title');
await showMessage('Cannot create a note with an empty title');
return;
}

const templateFolder = await getTemplateFolder();
let shouldAddTemplate = false;
let shouldApplyTemplate = false;

if (templateFolder != null || templateFolder !== '') {
shouldAddTemplate = await chooseOption('Do you want to get started with a template?', [{
shouldApplyTemplate = await chooseOption('Do you want to get started with a template?', [{
label: 'Yes',
value: true
}, {
Expand All @@ -9659,8 +9771,8 @@ lastName = "Doe"
}], false);
}

if (shouldAddTemplate) {
await addTemplate([title, folder]);
if (shouldApplyTemplate) {
await applyTemplate([title, folder]);
return;
}

Expand All @@ -9675,7 +9787,8 @@ lastName = "Doe"
Editor.content = `# ${title}\n`;
}

exports.addTemplate = addTemplate;
exports.applyNamedTemplate = applyNamedTemplate;
exports.applyTemplate = applyTemplate;
exports.newNoteWithTemplate = newNoteWithTemplate;

Object.defineProperty(exports, '__esModule', { value: true });
Expand Down
Loading