markdown-timestamp: Show flatpickr using typeaheads.

We leverage the composebox typeaheads to show flatpickr to pick dates
and times for the !time syntax.

We use moment.js to try and parse the time from current token. If we
are successful, we initialize flatpickr with the parsed time, else we
default to using the current time.
This commit is contained in:
Rohitt Vashishtha 2019-08-02 00:35:50 +05:30 committed by Tim Abbott
parent 890cafac11
commit 6ba8fb518b
2 changed files with 81 additions and 1 deletions

View File

@ -1126,6 +1126,7 @@ run_test('begins_typeahead', () => {
stream: true,
syntax: true,
topic: true,
timestamp: true,
}}};
function get_values(input, rest) {
@ -1302,6 +1303,16 @@ run_test('begins_typeahead', () => {
sweden_topics_to_show.push('totally new topic');
assert_typeahead_equals("#**Sweden>totally new topic", sweden_topics_to_show);
// time_jump
assert_typeahead_equals("!tim", false);
assert_typeahead_equals("!timerandom", false);
assert_typeahead_equals("!time", ['translated: Mention a timezone-aware time']);
assert_typeahead_equals("!time(", ['translated: Mention a timezone-aware time']);
assert_typeahead_equals("!time(something", ['translated: Mention a timezone-aware time']);
assert_typeahead_equals("!time(something", ") ", ['translated: Mention a timezone-aware time']);
assert_typeahead_equals("!time(something)", false);
assert_typeahead_equals("!time(something) ", false); // Already completed the mention
// Following tests place the cursor before the second string
assert_typeahead_equals("#test", "ing", false);
assert_typeahead_equals("@test", "ing", false);

View File

@ -2,6 +2,7 @@ const pygments_data = require("../generated/pygments_data.json");
const typeahead = require("../shared/js/typeahead");
const autosize = require('autosize');
const settings_data = require("./settings_data");
const confirmDatePlugin = require("flatpickr/dist/plugins/confirmDate/confirmDate.js");
//************************************
// AN IMPORTANT NOTE ABOUT TYPEAHEADS
@ -330,6 +331,11 @@ exports.tokenize_compose_str = function (s) {
}
}
const timestamp_index = s.indexOf('!time');
if (timestamp_index >= 0) {
return s.slice(timestamp_index);
}
return '';
};
@ -733,6 +739,14 @@ exports.get_candidates = function (query) {
}
}
}
if (this.options.completions.timestamp) {
const time_jump_regex = /!time(\(([^\)]*?))?$/;
if (time_jump_regex.test(split[0])) {
this.completing = 'time_jump';
return [i18n.t('Mention a timezone-aware time')];
}
}
return false;
};
@ -753,6 +767,8 @@ exports.content_highlighter = function (item) {
return typeahead_helper.render_typeahead_item({ primary: item });
} else if (this.completing === 'topic_list') {
return typeahead_helper.render_typeahead_item({ primary: item });
} else if (this.completing === 'time_jump') {
return typeahead_helper.render_typeahead_item({ primary: item });
}
};
@ -841,6 +857,56 @@ exports.content_typeahead_selected = function (item, event) {
// with the topic and the final **.
const start = beginning.length - this.token.length;
beginning = beginning.substring(0, start) + item + '** ';
} else if (this.completing === 'time_jump') {
const flatpickr_input = $("<input id='#timestamp_flatpickr'>");
let timeobject;
let timestring = beginning.substring(beginning.lastIndexOf('!time'));
if (timestring.startsWith('!time(') && timestring.endsWith(')')) {
timestring = timestring.substring(6, timestring.length - 1);
moment.suppressDeprecationWarnings = true;
try {
// If there's already a time in the compose box here,
// we use it to initialize the flatpickr instance.
timeobject = moment(timestring).toDate();
} catch {
// Otherwise, default to showing the current time.
}
}
const instance = flatpickr_input.flatpickr({
mode: 'single',
enableTime: true,
clickOpens: false,
defaultDate: timeobject || moment().format(),
plugins: [new confirmDatePlugin({})], // eslint-disable-line new-cap, no-undef
positionElement: this.$element[0],
dateFormat: 'Z',
formatDate: (date) => {
const dt = moment(date);
return dt.local().format();
},
});
const container = $($(instance.innerContainer).parent());
container.on('click', '.flatpickr-calendar', (e) => {
e.stopPropagation();
e.preventDefault();
});
container.on('click', '.flatpickr-confirm', () => {
const datestr = flatpickr_input.val();
beginning = beginning.substring(0, beginning.lastIndexOf('!time')) + `!time(${datestr}) `;
if (rest.startsWith(')')) {
rest = rest.slice(1);
}
textbox.val(beginning + rest);
textbox.caret(beginning.length, beginning.length);
compose_ui.autosize_textarea();
instance.close();
instance.destroy();
});
instance.open();
container.find('.flatpickr-monthDropdown-months').focus();
return beginning + rest;
}
// Keep the cursor after the newly inserted text, as Bootstrap will call textbox.change() to
@ -870,7 +936,8 @@ exports.compose_content_matcher = function (completing, token) {
return function () {
switch (completing) {
case 'topic_jump':
// topic_jump doesn't actually have a typeahead popover, so we return quickly here.
case 'time_jump':
// these don't actually have a typeahead popover, so we return quickly here.
return true;
}
};
@ -887,6 +954,7 @@ exports.sort_results = function (completing, matches, token) {
case 'syntax':
return typeahead_helper.sort_languages(matches, token);
case 'topic_jump':
case 'time_jump':
// topic_jump doesn't actually have a typeahead popover, so we return quickly here.
return matches;
case 'topic_list':
@ -942,6 +1010,7 @@ exports.initialize_compose_typeahead = function (selector) {
stream: true,
syntax: true,
topic: true,
timestamp: true,
};
$(selector).typeahead({