mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 16:14:02 +00:00
Add "zform" functionality to the web client.
A "zform" knows how to render data that follows our schema for widget messages with form elements like buttons and choices. This code won't be triggered until a subsequent server-side commit takes widget_content from API callers such as the trivial chat bot and creates submessages for us.
This commit is contained in:
@@ -175,6 +175,7 @@
|
|||||||
"user_events": false,
|
"user_events": false,
|
||||||
"voting_widget": false,
|
"voting_widget": false,
|
||||||
"tictactoe_widget": false,
|
"tictactoe_widget": false,
|
||||||
|
"zform": false,
|
||||||
"widgetize": false,
|
"widgetize": false,
|
||||||
"submessage": false,
|
"submessage": false,
|
||||||
"Plotly": false,
|
"Plotly": false,
|
||||||
|
@@ -6,6 +6,7 @@ var widgets = {};
|
|||||||
|
|
||||||
widgets.poll = voting_widget;
|
widgets.poll = voting_widget;
|
||||||
widgets.tictactoe = tictactoe_widget;
|
widgets.tictactoe = tictactoe_widget;
|
||||||
|
widgets.zform = zform;
|
||||||
|
|
||||||
exports.activate = function (in_opts) {
|
exports.activate = function (in_opts) {
|
||||||
var widget_type = in_opts.widget_type;
|
var widget_type = in_opts.widget_type;
|
||||||
|
115
static/js/zform.js
Normal file
115
static/js/zform.js
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
var zform = (function () {
|
||||||
|
|
||||||
|
var exports = {};
|
||||||
|
|
||||||
|
exports.validate_extra_data = function (data) {
|
||||||
|
function check(data) {
|
||||||
|
function check_choice_data(data) {
|
||||||
|
function check_choice_item(field_name, val) {
|
||||||
|
return schema.check_record(field_name, val, {
|
||||||
|
short_name: schema.check_string,
|
||||||
|
long_name: schema.check_string,
|
||||||
|
reply: schema.check_string,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_choices(field_name, val) {
|
||||||
|
return schema.check_array(
|
||||||
|
field_name,
|
||||||
|
val,
|
||||||
|
check_choice_item
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema.check_record('zform data', data, {
|
||||||
|
heading: schema.check_string,
|
||||||
|
choices: check_choices,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.type === 'choices') {
|
||||||
|
return check_choice_data(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'unknown zform type: ' + data.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var msg = check(data);
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
|
blueslip.warn(msg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.activate = function (opts) {
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
var outer_elem = opts.elem;
|
||||||
|
var data = opts.extra_data;
|
||||||
|
|
||||||
|
if (!exports.validate_extra_data(data)) {
|
||||||
|
// callee will log reason we fail
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_choices(data) {
|
||||||
|
// Assign idx values to each of our choices so that
|
||||||
|
// our template can create data-idx values for our
|
||||||
|
// JS code to use later.
|
||||||
|
_.each(data.choices, function (choice, idx) {
|
||||||
|
choice.idx = idx;
|
||||||
|
});
|
||||||
|
|
||||||
|
var html = templates.render('zform-choices', data);
|
||||||
|
var elem = $(html);
|
||||||
|
|
||||||
|
elem.find('button').on('click', function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
// Grab our index from the markup.
|
||||||
|
var idx = $(e.target).attr('data-idx');
|
||||||
|
|
||||||
|
// Use the index from the markup to dereference our
|
||||||
|
// data structure.
|
||||||
|
var reply_content = data.choices[idx].reply;
|
||||||
|
|
||||||
|
transmit.reply_message({
|
||||||
|
message: opts.message,
|
||||||
|
content: reply_content,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
function render() {
|
||||||
|
var rendered_widget;
|
||||||
|
|
||||||
|
if (data.type === 'choices') {
|
||||||
|
rendered_widget = make_choices(data);
|
||||||
|
outer_elem.html(rendered_widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.handle_events = function (events) {
|
||||||
|
if (events) {
|
||||||
|
blueslip.info('unexpected');
|
||||||
|
}
|
||||||
|
render();
|
||||||
|
};
|
||||||
|
|
||||||
|
render();
|
||||||
|
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
return exports;
|
||||||
|
|
||||||
|
}());
|
||||||
|
if (typeof module !== 'undefined') {
|
||||||
|
module.exports = zform;
|
||||||
|
}
|
17
static/styles/widgets.scss
Normal file
17
static/styles/widgets.scss
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
.widget-choices ul {
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget-choices li {
|
||||||
|
padding: 2px;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget-choices button {
|
||||||
|
font-weight: 700;
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget-choices-heading {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
12
static/templates/widgets/zform-choices.handlebars
Normal file
12
static/templates/widgets/zform-choices.handlebars
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<div class="widget-choices">
|
||||||
|
<div class="widget-choices-heading">{{ heading }}</div>
|
||||||
|
<ul>
|
||||||
|
{{#each choices}}
|
||||||
|
<li>
|
||||||
|
<button data-idx="{{ this.idx }}">{{ this.short_name }}</button>
|
||||||
|
|
||||||
|
{{ this.long_name }}
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
</div>
|
@@ -79,7 +79,8 @@
|
|||||||
"./static/styles/media.scss",
|
"./static/styles/media.scss",
|
||||||
"./static/styles/typing_notifications.scss",
|
"./static/styles/typing_notifications.scss",
|
||||||
"./static/styles/hotspots.scss",
|
"./static/styles/hotspots.scss",
|
||||||
"./static/styles/night_mode.scss"
|
"./static/styles/night_mode.scss",
|
||||||
|
"./static/styles/widgets.scss"
|
||||||
],
|
],
|
||||||
"archive-styles": [
|
"archive-styles": [
|
||||||
"./node_modules/katex/dist/katex.css",
|
"./node_modules/katex/dist/katex.css",
|
||||||
|
@@ -964,6 +964,7 @@ JS_SPECS = {
|
|||||||
'js/filter.js',
|
'js/filter.js',
|
||||||
'js/voting_widget.js',
|
'js/voting_widget.js',
|
||||||
'js/tictactoe_widget.js',
|
'js/tictactoe_widget.js',
|
||||||
|
'js/zform.js',
|
||||||
'js/widgetize.js',
|
'js/widgetize.js',
|
||||||
'js/submessage.js',
|
'js/submessage.js',
|
||||||
'js/fetch_status.js',
|
'js/fetch_status.js',
|
||||||
|
Reference in New Issue
Block a user