diff --git a/static/js/subs.js b/static/js/subs.js
index 66fe0dc545..b9aceecf09 100644
--- a/static/js/subs.js
+++ b/static/js/subs.js
@@ -10,6 +10,23 @@ function get_color() {
return color;
}
+function selectText(element) {
+ var range, sel;
+ if (window.getSelection) {
+ sel = window.getSelection();
+ range = document.createRange();
+ range.selectNodeContents(element);
+
+ sel.removeAllRanges();
+ sel.addRange(range);
+ }
+ else if (document.body.createTextRange) {
+ range = document.body.createTextRange();
+ range.moveToElementText(element);
+ range.select();
+ }
+}
+
function should_list_all_streams() {
return page_params.domain !== 'mit.edu';
}
@@ -217,11 +234,15 @@ function add_sub_to_table(sub) {
}
function format_member_list_elem(name, email) {
- return name + (email ? ' <' + email + '>' : '');
+ return "
| " + name + " | " + (email || '') + " |
";
}
-function add_to_member_list(ul, name, email) {
- $('').prependTo(ul).text(format_member_list_elem(name, email));
+function add_element_to_member_list (tb, elem) {
+ tb.prepend(elem);
+}
+
+function add_to_member_list(tb, name, email) {
+ tb.prepend(format_member_list_elem(name, email));
}
function mark_subscribed(stream_name, attrs) {
@@ -240,11 +261,11 @@ function mark_subscribed(stream_name, attrs) {
var settings = settings_for_sub(sub);
var button = button_for_sub(sub);
if (button.length !== 0) {
- button.text("Unsubscribe").removeClass("btn-primary");
+ button.text("Subscribed").addClass("subscribed-button").addClass("green-button");
// Add the user to the member list if they're currently
// viewing the members of this stream
if (sub.render_subscribers && settings.hasClass('in')) {
- var members = settings.find(".subscriber_list_container ul");
+ var members = settings.find(".subscriber_list_container .subscriber-list");
add_to_member_list(members, page_params.fullname, page_params.email);
}
} else {
@@ -280,7 +301,7 @@ function mark_unsubscribed(stream_name) {
} else if (sub.subscribed) {
stream_list.remove_narrow_filter(stream_name, 'stream');
sub.subscribed = false;
- button_for_sub(sub).text("Subscribe").addClass("btn-primary");
+ button_for_sub(sub).removeClass("subscribed-button").removeClass("green-button").removeClass("red-button").text("Subscribe");
var settings = settings_for_sub(sub);
if (settings.hasClass('in')) {
settings.collapse('hide');
@@ -669,6 +690,16 @@ $(function () {
);
});
+ $("body").on("mouseover", ".subscribed-button", function (e) {
+ $(e.target).addClass("red-button").text("Unsubscribe");
+ }).on("mouseout", ".subscribed-button", function (e) {
+ $(e.target).removeClass("red-button").text("Subscribed");
+ });
+
+ $("#subscriptions_table").on("click", ".email-address", function (e) {
+ selectText(this);
+ });
+
$("#subscriptions_table").on("click", ".sub_unsub_button", function (e) {
e.preventDefault();
e.stopPropagation();
@@ -727,7 +758,7 @@ $(function () {
// TODO: clean up this error handling
var error_elem = sub_row.find('.subscriber_list_container .alert-error');
var warning_elem = sub_row.find('.subscriber_list_container .alert-warning');
- var list = sub_row.find('.subscriber_list_container ul');
+ var list = sub_row.find('.subscriber_list_container .subscriber-list');
function invite_success(data) {
text_box.val('');
@@ -797,7 +828,7 @@ $(function () {
var stream = sub_row.find('.subscription_name').text();
var warning_elem = sub_row.find('.subscriber_list_container .alert-warning');
var error_elem = sub_row.find('.subscriber_list_container .alert-error');
- var list = sub_row.find('.subscriber_list_container ul');
+ var list = sub_row.find('.subscriber_list_container .subscriber-list');
var indicator_elem = sub_row.find('.subscriber_list_loading_indicator');
if (!stream_data.get_sub(stream).render_subscribers) {
@@ -825,10 +856,10 @@ $(function () {
return format_member_list_elem(people_dict.get(elem).full_name, elem);
});
_.each(subscribers.sort().reverse(), function (elem) {
- // add_to_member_list *prepends* the element,
+ // add_element_to_member_list *prepends* the element,
// so we need to sort in reverse order for it to
// appear in alphabetical order.
- add_to_member_list(list, elem);
+ add_element_to_member_list(list, elem);
});
},
error: function (xhr) {
diff --git a/static/styles/zulip.css b/static/styles/zulip.css
index 62cbb002e2..9d97b9b922 100644
--- a/static/styles/zulip.css
+++ b/static/styles/zulip.css
@@ -2061,38 +2061,34 @@ table.floating_recipient {
table-layout: fixed;
}
-.subscription_table_elem {
- padding: 2px;
- line-height: 25px;
-}
-
.subscription-email-hint-image {
float: right;
width: 80px;
padding-right: 60px;
}
-.subscription_header.active {
- border-color: rgba(82, 168, 236, 0.8);
- cursor: pointer;
+.subscription_header.collapsed {
+ background-color: inherit;
+}
- -webkit-box-shadow: inset 0 0 0 1px rgba(82, 168, 236, 0.8), 0 0 8px rgba(82, 168, 236, 0.6);
- -moz-box-shadow: inset 0 0 0 1px rgba(82, 168, 236, 0.8), 0 0 8px rgba(82, 168, 236, 0.6);
- box-shadow: inset 0 0 0 1px rgba(82, 168, 236, 0.8), 0 0 8px rgba(82, 168, 236, 0.6);
+.subscription_settings,
+.subscription_header,
+.subscription_header.active {
+ background-color: #fefefe;
}
.color_swatch {
display: inline-block;
- height: 1em;
- width: 1em;
- border: 1px #666 solid;
+ height: 18px;
+ width: 18px;
+ border-radius: 36px;
padding: 0;
- margin: 0 0 0 5px;
+ margin: 0 0 0 10px;
vertical-align: middle;
}
.subscriptions {
- margin-top: 45px;
+ margin-top: 55px;
padding-left: 15px;
}
@@ -2100,8 +2096,6 @@ table.floating_recipient {
padding-left: 0.5em;
vertical-align: middle;
display: inline-block;
- line-height: 14px;
- height: 16px;
}
#stream_filters .subscription_block {
@@ -2124,6 +2118,15 @@ table.floating_recipient {
text-overflow: ellipsis;
}
+.subscription-name-row {
+ line-height: 67px;
+ height: 60px;
+}
+
+#add_new_subscription {
+ text-align: center;
+}
+
.subject-name {
display: block;
line-height: 1.3em;
@@ -2149,34 +2152,90 @@ table.floating_recipient {
}
.subscription_header .subscription_lock {
- font-size: 12px;
+ font-size: 23px;
display: inline-block;
- vertical-align: top;
+ vertical-align: middle;
+ margin-left: 12px;
+ margin-right: 1px;
}
.subscription_settings {
- margin-left: 35px;
- margin-right: 35px;
- clear: right;
+ width: 100%;
+ position: relative;
+ top: -1px;
}
.subscription_settings form {
- margin: 0;
+ text-align: center;
}
.subscription_settings ul {
list-style-type: none;
}
-.subscriber_list_settings {
- margin-top: 10px;
+.subscription-type {
+ text-align: center;
+ padding: 5px;
+ width: 80%;
+ margin: auto;
+ font-weight: 300;
}
-.email-address {
- width: 100%;
- display: inline-block;
- vertical-align: top;
+.stream-email {
+ width: 80%;
+ margin: auto;
+ margin-top: 5px;
+ text-align: center;
+ padding: 5px;
+ font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
+}
+
+.subscription-control-label {
+ display: inline-block;
+ vertical-align: middle;
+ line-height: 18px;
+ padding: 5px;
+}
+
+.sp-replacer,
+.sp-preview,
+.sp-preview-inner {
+ border-radius: 20px;
+}
+
+.sp-preview {
+ width: 20px;
+ border: none;
+ box-shadow: 0px 0px 1px rgba(0,0,0,1);
+}
+
+.sp-replacer {
+ margin-right: 12px;
+ border: none;
+ box-shadow: 0px 0px 2px rgba(0,0,0,0.8);
+}
+
+.subscription-config {
+ width: 270px;
+ margin: auto;
+ margin-top: 25px;
+}
+
+.stream-email-box,
+.subscriber_list_settings,
+.rename-stream {
+ margin: 20px 15px 20px 15px;
+}
+
+.subscription_row {
+ border-top: 1px solid #ddd;
+}
+
+.stream-email .email-address {
+ width: 90%;
+ display: block;
+ margin: auto;
white-space: -moz-pre-wrap !important;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
@@ -2210,14 +2269,57 @@ table.floating_recipient {
margin-right: 10px;
}
+.zulip-button {
+ background-image: -moz-linear-gradient(top, rgba(0,0,0,0.05) 0%, rgba(0,0,0,0) 100%); /* FF3.6+ */
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,0.05)), color-stop(100%,rgba(0,0,0,0))); /* Chrome,Safari4+ */
+ background-image: -webkit-linear-gradient(top, rgba(0,0,0,0.05) 0%,rgba(0,0,0,0) 100%); /* Chrome10+,Safari5.1+ */
+ background-image: -o-linear-gradient(top, rgba(0,0,0,0.05) 0%,rgba(0,0,0,0) 100%); /* Opera 11.10+ */
+ background-image: -ms-linear-gradient(top, rgba(0,0,0,0.05) 0%,rgba(0,0,0,0) 100%); /* IE10+ */
+ background-image: linear-gradient(to bottom, rgba(0,0,0,0.05) 0%,rgba(0,0,0,0) 100%); /* W3C */
+ background-color: #ddd;
+ color: #000;
+ border: 1px solid #fff;
+ border-radius: 3px;
+ line-height: 20px;
+ padding: 5px 8px 5px 8px;
+ outline: none;
+}
+
+.zulip-button:hover {
+ background-image: -moz-linear-gradient(top, rgba(0,0,0,0.09) 0%, rgba(0,0,0,0) 100%); /* FF3.6+ */
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,0.09)), color-stop(100%,rgba(0,0,0,0))); /* Chrome,Safari4+ */
+ background-image: -webkit-linear-gradient(top, rgba(0,0,0,0.09) 0%,rgba(0,0,0,0) 100%); /* Chrome10+,Safari5.1+ */
+ background-image: -o-linear-gradient(top, rgba(0,0,0,0.09) 0%,rgba(0,0,0,0) 100%); /* Opera 11.10+ */
+ background-image: -ms-linear-gradient(top, rgba(0,0,0,0.09) 0%,rgba(0,0,0,0) 100%); /* IE10+ */
+ background-image: linear-gradient(to bottom, rgba(0,0,0,0.09) 0%,rgba(0,0,0,0) 100%); /* W3C */
+}
+
.sub_unsub_button {
min-width: 140px;
float: right;
+ margin-top: 18px;
+ margin-right: 10px;
+}
+
+.green-button {
+ background-color: #006e2e; /* Old browsers */
+ color: #fff;
+}
+
+.red-button {
+ background-color: #cc0000;
+ color: #ffffff;
+}
+
+.blue-button {
+ background-color: #0000cc;
+ color: #ffffff;
}
.sub_arrow {
float: right;
- padding: 0 5px 0 10px;
+ line-height: 67px;
+ padding: 0 15px 0 0;
}
#create_stream_row td {
@@ -2227,34 +2329,80 @@ table.floating_recipient {
}
#create_stream_name {
- margin-left: 25px;
width: 220px;
+ margin-top: 10px;
}
#create_stream_button {
min-width: 140px;
- float: right;
+ margin-left: 15px;
+ margin-top: 10px;
}
.sub_settings_title {
line-height: 30px;
margin: 10px 0;
- font-weight: bold;
+ font-weight: 300;
+ font-size: 16px;
+}
+
+.new-stream-name,
+.stream-rename-button {
+ margin-top: 10px;
}
.settings_committed {
margin: 10px;
}
+.subscriber-list-box {
+ text-align: center;
+}
+
.subscriber_list_container {
- max-height: 200px;
- overflow: auto;
margin-top: 10px;
- clear: right;
+ display: inline-block;
+ margin: auto;
+ max-height: 300px;
+ overflow: auto;
+ text-align: left;
+}
+
+.subscriber-list {
+ width: auto;
+ margin: auto;
+ margin-bottom: 20px;
+ background: #efefef;
+ border-radius: 6px;
+}
+
+.subscriber-list tr:nth-child(even) {
+ background: #fafafa;
+}
+
+
+.subscriber-name,
+.subscriber-email {
+ padding: 5px;
+}
+
+.subscriber-name {
+ padding-left: 8px;
+}
+
+.subscriber-email {
+ margin-left: 20px;
+ padding-right: 8px;
}
.subscriber_list_add {
- float: right;
+ margin: auto;
+ text-align: center;
+}
+
+.add-subscriber-button,
+.stream-rename-button {
+ margin-left: 5px;
}
.modal {
@@ -3036,12 +3184,14 @@ div.edit_bot {
margin-right: 8px;
}
-#settings h1 {
+#settings h1,
+#subscriptions h1 {
font-size: 25px;
font-weight: 300;
}
-#settings .settings-icon {
+#settings .settings-icon,
+#subscriptions .streams-icon {
margin-right: 10px;
font-size: 20px;
}
@@ -3442,75 +3592,17 @@ div.edit_bot {
.compose_private_button_label {
display: none;
}
+
+ .subscription_name {
+ max-width: 120px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
}
@media (max-width: 350px) {
html {
overflow-x: hidden;
}
-}
-
-/*
-
-@media (max-width: 480px) {
- body {
- padding-right: 5px;
- padding-left: 5px;
- }
-}
-
-@media (max-width: 480px) {
- #create_stream_name {
- width: 130px;
- }
-}
-
-@media (min-width: 768px) and (max-width: 979px) {
- #create_stream_name {
- width: 140px;
- }
-}
-
-@media (max-width: 767px) {
-
- #search_query {
- width: 100%;
- margin-left: 40px;
- }
-
- #navbar-middle {
- padding-right: 75px;
- }
-
- #searchbox .input-append .icon-vector-search {
- left: 46px;
- }
-
- #searchbox .search_button,
- #searchbox .search_button[disabled]:hover {
- right: -35px;
- }
-
-}
-
-@media (max-width: 480px) {
- .message_content {
- margin-right: 5px;
- }
-}
-
-@media (max-width: 767px) {
- .sidebar-nav {
- padding: 0.5em;
- margin: 0px;
- border: 1px solid black;
- }
-}
-
- @media (max-width: 979px) {
- .header-main .logo {
- margin-left: -20px;
- }
-}
-
-*/
+}
\ No newline at end of file
diff --git a/static/templates/subscription.handlebars b/static/templates/subscription.handlebars
index 6c50ff4465..6dc309d19b 100644
--- a/static/templates/subscription.handlebars
+++ b/static/templates/subscription.handlebars
@@ -1,18 +1,20 @@
{{! Client-side Mustache template for rendering subscriptions.}}
{{#with this}}
-
- |
- |
-
+
{{/with}}
diff --git a/static/templates/subscription_table_body.handlebars b/static/templates/subscription_table_body.handlebars
index b720d2fb3e..5448af6258 100644
--- a/static/templates/subscription_table_body.handlebars
+++ b/static/templates/subscription_table_body.handlebars
@@ -1,19 +1,14 @@
-
-
- |
+ |
-
+
{{#each subscriptions}}
{{partial "subscription"}}
{{/each}}
-
-
diff --git a/templates/zerver/navbar.html b/templates/zerver/navbar.html
index 4b088db99c..abcc375b64 100644
--- a/templates/zerver/navbar.html
+++ b/templates/zerver/navbar.html
@@ -41,7 +41,7 @@
- Streams
+ Streams
diff --git a/templates/zerver/subscriptions.html b/templates/zerver/subscriptions.html
index e1c2a6e786..095a45208e 100644
--- a/templates/zerver/subscriptions.html
+++ b/templates/zerver/subscriptions.html
@@ -1,11 +1,11 @@
{# Subscriptions management tab of the app. #}
-
Streams
+
Streams
-
+
+
{% include "zerver/stream_creation_prompt.html" %}
diff --git a/zerver/tests/frontend/tests/04-subscriptions.js b/zerver/tests/frontend/tests/04-subscriptions.js
index 1eea44a674..ddf296bae1 100644
--- a/zerver/tests/frontend/tests/04-subscriptions.js
+++ b/zerver/tests/frontend/tests/04-subscriptions.js
@@ -9,12 +9,12 @@ casper.then(function () {
casper.test.assertExists('#subscriptions.tab-pane.active', 'Subscriptions page is active');
// subscriptions need to load; if they have *any* subs,
// the word "Unsubscribe" will appear
- casper.waitForText('Unsubscribe');
+ casper.waitForText('Subscribed');
});
casper.then(function () {
- casper.test.assertTextExists('Unsubscribe', 'Initial subscriptions loaded');
+ casper.test.assertTextExists('Subscribed', 'Initial subscriptions loaded');
casper.fill('form#add_new_subscription', {stream_name: 'Waseemio'});
- casper.click('form#add_new_subscription input.btn.btn-primary');
+ casper.click('form#add_new_subscription input.zulip-button');
casper.waitForText('Waseemio');
});
casper.then(function () {
@@ -29,13 +29,13 @@ casper.then(function () {
casper.then(function () {
casper.test.assertSelectorHasText('.subscription_name', 'Waseemio', 'Subscribing to a stream');
casper.fill('form#add_new_subscription', {stream_name: 'WASeemio'});
- casper.click('form#add_new_subscription input.btn.btn-primary');
+ casper.click('form#add_new_subscription input.zulip-button');
casper.waitForText('Already subscribed');
});
casper.then(function () {
casper.test.assertTextExists('Already subscribed', "Can't subscribe twice to a stream");
casper.fill('form#add_new_subscription', {stream_name: ' '});
- casper.click('form#add_new_subscription input.btn.btn-primary');
+ casper.click('form#add_new_subscription input.zulip-button');
casper.waitForText('Error adding subscription');
});
casper.then(function () {