forms seem to work now
This commit is contained in:
+16
-5
@@ -558,10 +558,23 @@ table.permission-editor td.checkbox {
|
||||
min-width: 8rem;
|
||||
}
|
||||
.bot-form.hlist {
|
||||
flex-direction: column;
|
||||
flex-direction: row;
|
||||
}
|
||||
.bot-form div {
|
||||
min-height: 2rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
/* Nested bot forms should have not border */
|
||||
.bot-form .bot-form {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.bot-form div {
|
||||
/*
|
||||
Form element with non-interactive content
|
||||
needs padding.
|
||||
*/
|
||||
.bot-form div.dft {
|
||||
padding: 0.25rem 1rem;
|
||||
min-height: 2rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@@ -664,7 +677,7 @@ i.search {
|
||||
.alert-box.info {
|
||||
display: flex;
|
||||
background-color: #e1f5fe;
|
||||
border-bottom: 1px solid #4fc3f7;
|
||||
border-bottom: 1px solid #b3e5fc;
|
||||
color: #0288d1;
|
||||
}
|
||||
.alert-box .cancel .material-icons {
|
||||
@@ -1155,7 +1168,6 @@ i.search {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
align-items: flex-end;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chat-box .right {
|
||||
@@ -1171,7 +1183,6 @@ i.search {
|
||||
padding: 0.75rem 0.5rem 0.75rem 1.25rem;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -7,6 +7,7 @@ import Tinode from 'tinode-sdk';
|
||||
import AvatarUpload from '../widgets/avatar-upload.jsx';
|
||||
import CheckBox from '../widgets/checkbox.jsx';
|
||||
import ContactList from '../widgets/contact-list.jsx';
|
||||
import ErrorPanel from '../widgets/error-panel.jsx';
|
||||
import GroupManager from '../widgets/group-manager.jsx';
|
||||
import InPlaceEdit from '../widgets/in-place-edit.jsx';
|
||||
import MenuCancel from '../widgets/menu-cancel.jsx';
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
||||
|
||||
import Tinode from 'tinode-sdk';
|
||||
const Drafty = Tinode.Drafty;
|
||||
|
||||
import ChatMessage from '../widgets/chat-message.jsx';
|
||||
import ErrorPanel from '../widgets/error-panel.jsx';
|
||||
@@ -62,6 +63,7 @@ class MessagesView extends React.Component {
|
||||
this.handleInfoReceipt = this.handleInfoReceipt.bind(this);
|
||||
this.handleImagePreview = this.handleImagePreview.bind(this);
|
||||
this.handleCloseImagePreview = this.handleCloseImagePreview.bind(this);
|
||||
this.handleFormResponse = this.handleFormResponse.bind(this);
|
||||
this.handleContextClick = this.handleContextClick.bind(this);
|
||||
this.handleShowContextMenuMessage = this.handleShowContextMenuMessage.bind(this);
|
||||
this.handleBackNavigation = this.handleBackNavigation.bind(this);
|
||||
@@ -349,6 +351,30 @@ class MessagesView extends React.Component {
|
||||
this.setState({ imagePreview: null });
|
||||
}
|
||||
|
||||
handleFormResponse(action, text, data) {
|
||||
if (action == 'pub') {
|
||||
this.props.sendMessage(Drafty.attachJSON(Drafty.parse(text), data));
|
||||
} else if (action == 'url') {
|
||||
const url = new URL(data.ref);
|
||||
let params = url.searchParams;
|
||||
for (let key in data.resp) {
|
||||
if (data.resp.hasOwnProperty(key)) {
|
||||
params.set(key, data.resp[key]);
|
||||
}
|
||||
}
|
||||
['name', 'seq'].map(function(key) {
|
||||
if (data[key]) {
|
||||
params.set(key, data[key]);
|
||||
}
|
||||
});
|
||||
params.set('uid', this.props.myUserId);
|
||||
url.search = params;
|
||||
window.open(url, '_blank');
|
||||
} else {
|
||||
console.log("Unknown action in form", action);
|
||||
}
|
||||
}
|
||||
|
||||
handleContextClick(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -376,11 +402,10 @@ class MessagesView extends React.Component {
|
||||
const {formatMessage} = this.props.intl;
|
||||
|
||||
let component;
|
||||
|
||||
if (this.state.topic) {
|
||||
const topic = this.props.tinode.getTopic(this.state.topic);
|
||||
const groupTopic = topic.getType() == 'grp';
|
||||
let messageNodes = [];
|
||||
let topic = this.props.tinode.getTopic(this.state.topic);
|
||||
let groupTopic = topic.getType() == 'grp';
|
||||
let previousFrom = null;
|
||||
let chatBoxClass = null;
|
||||
for (let i=0; i<this.state.messages.length; i++) {
|
||||
@@ -403,12 +428,12 @@ class MessagesView extends React.Component {
|
||||
}
|
||||
previousFrom = msg.from;
|
||||
|
||||
let isReply = !(msg.from == this.props.myUserId);
|
||||
let deliveryStatus = topic.msgStatus(msg);
|
||||
const isReply = !(msg.from == this.props.myUserId);
|
||||
const deliveryStatus = topic.msgStatus(msg);
|
||||
|
||||
let userName, userAvatar, userFrom;
|
||||
if (groupTopic) {
|
||||
let user = topic.userDesc(msg.from);
|
||||
const user = topic.userDesc(msg.from);
|
||||
if (user && user.public) {
|
||||
userName = user.public.fn;
|
||||
userAvatar = makeImageUrl(user.public.photo);
|
||||
@@ -430,6 +455,7 @@ class MessagesView extends React.Component {
|
||||
viewportWidth={this.props.viewportWidth}
|
||||
showContextMenu={this.handleShowContextMenuMessage}
|
||||
onImagePreview={this.handleImagePreview}
|
||||
onFormResponse={this.handleFormResponse}
|
||||
onError={this.props.onError}
|
||||
key={msg.seq} />
|
||||
);
|
||||
|
||||
@@ -77,7 +77,7 @@ class SidepanelView extends React.Component {
|
||||
}
|
||||
|
||||
let onCancel;
|
||||
if (view != 'login') {
|
||||
if (['login', 'contacts'].indexOf(view) == -1) {
|
||||
onCancel = this.props.onCancel;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
import FileProgress from './file-progress.jsx';
|
||||
import { bytesToHumanSize } from '../lib/strformat.js';
|
||||
|
||||
export default class Attachment extends React.Component {
|
||||
constructor(props) {
|
||||
|
||||
@@ -39,7 +39,22 @@ export default class ChatMessage extends React.Component {
|
||||
|
||||
handleFormButtonClick(e) {
|
||||
e.preventDefault();
|
||||
console.log(e.target);
|
||||
const data = {
|
||||
seq: this.props.seq
|
||||
};
|
||||
data.resp = {};
|
||||
if (e.target.dataset.name) {
|
||||
data.resp[e.target.dataset.name] = e.target.dataset.val ? e.target.dataset.val :
|
||||
e.target.dataset.val === undefined ? 1 : '' + e.target.dataset.val;
|
||||
}
|
||||
if (e.target.dataset.act == 'url') {
|
||||
data.ref = '' + e.target.dataset.ref;
|
||||
}
|
||||
if (e.target.dataset.formname) {
|
||||
data.name = '' + e.target.dataset.formname;
|
||||
}
|
||||
const text = e.target.dataset.title || 'unknown';
|
||||
this.props.onFormResponse(e.target.dataset.act, text, data);
|
||||
}
|
||||
|
||||
handleContextClick(e) {
|
||||
@@ -68,6 +83,11 @@ export default class ChatMessage extends React.Component {
|
||||
const attachments = [];
|
||||
if (this.props.mimeType == Drafty.getContentType()) {
|
||||
Drafty.attachments(content, function(att, i) {
|
||||
if (att.mime == 'application/json') {
|
||||
// Don't show json objects as attachments.
|
||||
// They are not meant for users.
|
||||
return;
|
||||
}
|
||||
attachments.push(<Attachment
|
||||
tinode={this.props.tinode}
|
||||
downloadUrl={Drafty.getDownloadUrl(att)}
|
||||
@@ -147,6 +167,11 @@ function draftyFormatter(style, data, values, key) {
|
||||
case 'FM':
|
||||
// Form
|
||||
attr.className = 'bot-form' + ((data && data.layout) ? ' ' + data.layout : '');
|
||||
// console.log(data, attr);
|
||||
break;
|
||||
case 'FE':
|
||||
// Form element formatting is dependent on element content.
|
||||
attr.className = data && data.dftp ? data.dftp : '';
|
||||
break;
|
||||
}
|
||||
return React.createElement(el, attr, values);
|
||||
|
||||
@@ -87,9 +87,8 @@ class ContactList extends React.Component {
|
||||
{contactNodes}
|
||||
</ul>
|
||||
:
|
||||
<div className="center-medium-text">
|
||||
{this.props.emptyListMessage}
|
||||
</div>}
|
||||
<div className="center-medium-text" dangerouslySetInnerHTML={{__html: this.props.emptyListMessage}} />
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { Drafty } from 'tinode-sdk';
|
||||
|
||||
import { KEYPRESS_DELAY, MAX_EXTERN_ATTACHMENT_SIZE, MAX_IMAGE_DIM, MAX_INBAND_ATTACHMENT_SIZE } from '../config.js';
|
||||
import { SUPPORTED_IMAGE_FORMATS, filePasted, imageFileToBase64, imageFileScaledToBase64 } from '../lib/blob-helpers.js';
|
||||
import { SUPPORTED_IMAGE_FORMATS, filePasted, fileToBase64, imageFileToBase64, imageFileScaledToBase64 } from '../lib/blob-helpers.js';
|
||||
import { bytesToHumanSize } from '../lib/strformat.js';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
||||
+87
-24
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user