diff --git a/css/base.css b/css/base.css
index 75bfc322..e76698da 100644
--- a/css/base.css
+++ b/css/base.css
@@ -505,17 +505,52 @@ table.permission-editor td.checkbox {
/* Area which displays an error message */
-#alert-box {
- background-color: transparent;
- height: 0;
+.alert-box {
+ position: relative;
+ display: none;
overflow: hidden;
+ padding: 1rem 1.5rem 1rem 0.5rem;
}
-#alert-box.error-alert {
- padding: 0.5rem;
+.alert-box .cancel {
+ position: absolute;
+ right: 0.25rem;
+ top: 0.5rem;
+}
+
+.alert-box.error {
+ display: block;
background-color: #ffcdd2;
- border-color: #d32f2f;
+ border-bottom: 1px solid #ffbfc8;
color: #b71c1c;
- height: auto;
+}
+.alert-box.warning {
+ display: block;
+ background-color: #fff9c4;
+ border-bottom: 1px solid #fff59d;
+ color: #607d8b;
+}
+.alert-box .cancel .material-icons {
+ font-size: 1rem;
+}
+.alert-box.error .cancel .material-icons {
+ color: #b71c1c;
+}
+.alert-box.warning .cancel .material-icons {
+ color: #757575;
+}
+.alert-box .icon {
+ display: inline-block;
+ vertical-align: middle;
+ margin-right: 0.5rem;
+}
+.alert-box .icon .material-icons {
+ font-size: 1.5rem;
+}
+.alert-box.warning .icon .material-icons {
+ color: #fbc02d;
+}
+.alert-box.error .icon .material-icons {
+ color: #ef5350;
}
/* List of contacts */
@@ -1488,7 +1523,6 @@ ul.tabbar li.active > a:after {
border-top: 0.35rem solid #1e88e5;
width: 2rem;
height: 2rem;
- -webkit-animation: spin 1.5s linear infinite;
animation: spin 1.5s linear infinite;
}
diff --git a/drafty.js b/drafty.js
index b845c3ea..cb30fa56 100644
--- a/drafty.js
+++ b/drafty.js
@@ -521,8 +521,6 @@ Sample JSON representation of the text above:
return a.at - b.at;
});
- console.log(spans);
-
// Denormalize entities into spans. Create a copy of the objects to leave
// original Drafty object unchanged.
spans = spans.map(function(s) {
@@ -536,8 +534,6 @@ Sample JSON representation of the text above:
return {tp: tp, data: data, at: s.at, len: s.len};
});
- console.log(spans);
-
return forEach(txt, 0, txt.length, spans, formatter, context);
},
diff --git a/index.html b/index.html
index 83c8b517..69cecf43 100644
--- a/index.html
+++ b/index.html
@@ -15,9 +15,9 @@
-
-
-
+
+
+
@@ -133,7 +133,7 @@
/* BEGIN Context Menu: popup/dropdown menu */
// Function is used by context menu to set permissions.
- function topicPermissionSetter(mode, topicName, uid) {
+ function topicPermissionSetter(mode, topicName, uid, errorHandler) {
var topic = Tinode.getTopic(topicName);
if (!topic) {
console.log("Topic not found: " + topicName);
@@ -151,7 +151,14 @@
} else {
am = topic.getAccessMode().updateWant(mode).getWant();
}
- topic.setMeta({sub: {user: uid, mode: am}});
+ var instance = this;
+ topic.setMeta({sub: {user: uid, mode: am}}).catch(function(err) {
+ if (errorHandler) {
+ errorHandler(err.message, "err");
+ } else {
+ console.log(err);
+ }
+ });
}
// Context menu items.
@@ -164,6 +171,7 @@
console.log("Topic not found: " + topicName);
return;
}
+
topic.delMessagesAll(false).then(function(){
console.log("refresh message list");
});
@@ -232,7 +240,7 @@
e.stopPropagation();
this.props.hide();
var item = this.props.items[e.currentTarget.dataset.id];
- item.handler(this.props.topic, this.props.user);
+ item.handler(this.props.topic, this.props.user, this.props.onError);
},
render: function() {
@@ -280,13 +288,17 @@
/* END Popup/dropdown menu */
/* The X menu to be displayed in title bars */
- var MenuCancel = React.createClass({
- render: function() {
+ class MenuCancel extends React.PureComponent {
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
return (
close
);
}
- });
+ }
class LoadSpinner extends React.PureComponent {
render() {
@@ -714,31 +726,20 @@
login: this.props.login,
password: '',
hostName: this.props.serverAddress,
- errorCleared: false
};
},
- clearError: function() {
- if (!this.state.errorCleared) {
- this.props.onClearError();
- this.setState({errorCleared: true});
- }
- },
handleLoginChange: function(e) {
- this.clearError();
this.setState({login: e.target.value});
},
handlePasswordChange: function(e) {
- this.clearError();
this.setState({password: e.target.value});
},
handleServerAddressChange: function(name) {
- this.clearError();
this.setState({hostName: name});
this.props.onServerAddressChange(name);
},
handleSubmit: function(e) {
e.preventDefault();
- this.setState({errorCleared: false});
this.props.onLogin(this.state.login.trim(), this.state.password.trim());
},
@@ -1000,20 +1001,11 @@
);
}
- })
+ });
var SidepanelView = React.createClass({
- getInitialState: function() {
- return {
- showErrorText: true
- };
- },
- handleClearErrorText: function() {
- this.setState({showErrorText: false});
- },
handleLoginRequested: function(login, password) {
this.props.onLoginRequest(login, password);
- this.setState({showErrorText: true});
},
render: function() {
var title = null;
@@ -1046,17 +1038,16 @@
onNewTopic={this.props.onNewTopic}
onCancel={this.props.onCancel} />
-
+
{this.props.state === 'login' ?
:
+ onServerAddressChange={this.props.onConnectionSettings} /> :
this.props.state === 'register' ?
{errorText}
+
+
{icon}
+ {this.props.text}
+
+
);
}
});
@@ -1891,8 +1897,6 @@
resetDesc: function(topic) {
var defacs = topic.getDefaultAccess() || {};
var acs = topic.getAccessMode();
- console.log("InfoView: reset desc");
- console.log(topic.public);
this.setState({
owner: acs && acs.isOwner(),
admin: acs && acs.isAdmin(),
@@ -2104,6 +2108,10 @@
+ {this.props.displayMobile ?
+ : null}
{this.state.showMemberPanel ?
+ {this.props.displayMobile ?
+ : null}