mirror of
https://github.com/zulip/zulip.git
synced 2025-11-13 10:26:28 +00:00
Remove the onboarding checklist.
Looking at the historical data, fewer than 50% of active users have completed the checklist, which means that it is just persistent clutter. We also have other better ways of encouraging people to send traffic and get the apps now. This commit removes both the frontend UI and backend work but leaves the db row for now for the historical data. (imported from commit e8f5780be37bbc75f794fb118e4dd41d8811f2bf)
This commit is contained in:
@@ -394,11 +394,7 @@ function send_message(request) {
|
||||
$("#new_message_content").val('').focus();
|
||||
autosize_textarea();
|
||||
$("#send-status").hide(0);
|
||||
if (request.type === "private") {
|
||||
onboarding.mark_checklist_step("sent_private_message");
|
||||
} else {
|
||||
onboarding.mark_checklist_step("sent_stream_message");
|
||||
}
|
||||
|
||||
clear_message_snapshot();
|
||||
$("#compose-send-button").removeAttr('disabled');
|
||||
$("#sending-indicator").hide();
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
var onboarding = (function () {
|
||||
|
||||
var exports = {};
|
||||
|
||||
// The ordered list of onboarding steps we want new users to complete. If the
|
||||
// steps are changed here, they must also be changed in create_user.py.
|
||||
var steps = ["sent_stream_message", "sent_private_message", "made_app_sticky", "set_up_integration"];
|
||||
// N.B. user_message is **unescaped HTML**, so please use caution
|
||||
var step_info = {sent_stream_message: {"user_message": "Send a stream message"},
|
||||
sent_private_message: {"user_message": "Send a private message"},
|
||||
made_app_sticky: {"user_message": 'Get our <a id="get-the-app" href="/apps" target="_blank">apps</a>'},
|
||||
set_up_integration: {"user_message": 'Set up an <a id="set-up-integration" href="/integrations" target="_blank">integration</a>'}};
|
||||
|
||||
var onboarding = false;
|
||||
|
||||
function update_onboarding_steps() {
|
||||
var step_statuses = _.map(steps, function (step) {
|
||||
return [step, step_info[step].status];
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/json/update_onboarding_steps',
|
||||
dataType: 'json',
|
||||
data: {"onboarding_steps": JSON.stringify(step_statuses)}
|
||||
});
|
||||
}
|
||||
|
||||
function all_steps_completed() {
|
||||
return steps.filter(function (step) {
|
||||
return step_info[step].status === false;
|
||||
}).length === 0;
|
||||
}
|
||||
|
||||
|
||||
function finish_onboarding() {
|
||||
var checklist = $('#onboarding-checklist');
|
||||
checklist.empty();
|
||||
checklist.html("<i class='icon-vector-check onboarding_success'>Done");
|
||||
$('#onboarding').fadeOut(5000, function () {
|
||||
$(this).hide();
|
||||
});
|
||||
}
|
||||
|
||||
function update_checklist_ui(step) {
|
||||
var checklist_item = $($('#onboarding-checklist').find("i")[steps.indexOf(step)]);
|
||||
checklist_item.removeClass("icon-vector-check-empty").addClass("icon-vector-check");
|
||||
if (all_steps_completed()) {
|
||||
finish_onboarding();
|
||||
}
|
||||
}
|
||||
|
||||
exports.set_step_info = function (steps) {
|
||||
_.each(steps, function (step) {
|
||||
var step_name = step[0];
|
||||
var status = step[1];
|
||||
step_info[step_name].status = status;
|
||||
if (status) {
|
||||
update_checklist_ui(step_name);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.mark_checklist_step = function (step) {
|
||||
if (!onboarding || step_info[step].status) {
|
||||
return;
|
||||
}
|
||||
|
||||
step_info[step].status = true;
|
||||
update_checklist_ui(step);
|
||||
update_onboarding_steps();
|
||||
};
|
||||
|
||||
function set_up_checklist() {
|
||||
var onboarding_checklist = $('#onboarding-checklist').empty();
|
||||
if (all_steps_completed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_.each(steps, function (step) {
|
||||
var entry = $('<div>');
|
||||
if (step_info[step].status) {
|
||||
entry.append($("<i class='icon-vector-check'>"));
|
||||
} else {
|
||||
entry.append($("<i class='icon-vector-check-empty'>"));
|
||||
}
|
||||
entry.append($('<span>').html(step_info[step].user_message)).attr("id", step);
|
||||
onboarding_checklist.append(entry);
|
||||
|
||||
var register_action = step_info[step].register;
|
||||
if (register_action !== undefined) {
|
||||
register_action(step_info[step].status);
|
||||
}
|
||||
});
|
||||
|
||||
$(document.body).one('click', 'a[href="/apps"]', function (e) {
|
||||
exports.mark_checklist_step("made_app_sticky");
|
||||
});
|
||||
$(document.body).one('click', "#set-up-integration", function (e) {
|
||||
exports.mark_checklist_step("set_up_integration");
|
||||
});
|
||||
|
||||
$("#onboarding").show();
|
||||
}
|
||||
|
||||
exports.initialize = function () {
|
||||
onboarding = true;
|
||||
exports.set_step_info(page_params.onboarding_steps);
|
||||
set_up_checklist();
|
||||
};
|
||||
|
||||
return exports;
|
||||
}());
|
||||
@@ -1563,7 +1563,6 @@ $(function () {
|
||||
invite.initialize();
|
||||
activity.initialize();
|
||||
tutorial.initialize();
|
||||
onboarding.initialize();
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -779,9 +779,6 @@ function get_updates_success(data) {
|
||||
case 'restart':
|
||||
reload.initiate({message: "The application has been updated; reloading!"});
|
||||
break;
|
||||
case 'onboarding_steps':
|
||||
onboarding.set_step_info(event.steps);
|
||||
break;
|
||||
case 'update_message':
|
||||
messages_to_update.push(event);
|
||||
break;
|
||||
|
||||
@@ -2713,42 +2713,6 @@ div.edit_bot {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
#onboarding-header {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
#onboarding-checklist {
|
||||
font-size: 14px;
|
||||
border: 1px solid #ddd;
|
||||
background-color: #F7F7F7;
|
||||
padding: 10px 0px 10px 10px;
|
||||
width: 175px;
|
||||
}
|
||||
|
||||
#onboarding {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.onboarding_success {
|
||||
font-size: 40px;
|
||||
color: #00CC00;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#sticky-popover h1 {
|
||||
text-align: center;
|
||||
}
|
||||
.done-button {
|
||||
text-align: center;
|
||||
}
|
||||
.sticky-popover-inner {
|
||||
max-width: 300px;
|
||||
}
|
||||
.sticky-popover-inner p {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
#feedback_section {
|
||||
text-align: left;
|
||||
padding-bottom: 10px;
|
||||
@@ -3195,10 +3159,6 @@ div.edit_bot {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#onboarding-checklist i {
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
|
||||
#share-the-love {
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
{{! Contents of the "make the app sticky" onboarding popup }}
|
||||
|
||||
<div id="sticky-popover">
|
||||
<h1>Get our app!</h1>
|
||||
|
||||
<p>Zulip works best when it's always open, which is why we also
|
||||
have apps!</p>
|
||||
|
||||
<p>Visit <a target="_blank" href="/apps">our apps page</a> for
|
||||
Mac, Linux, Windows, Android, and iPhone/iPad instructions.</p>
|
||||
|
||||
<div class="done-button">
|
||||
<input type="submit" id="sticky_done" value="Done" class="btn btn-big btn-primary" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -26,11 +26,6 @@
|
||||
<i class="icon-vector-comment"></i> Send feedback
|
||||
</button>
|
||||
</div>
|
||||
<div id="onboarding">
|
||||
<p id="onboarding-header">Get started with Zulip!</p>
|
||||
<div id="onboarding-checklist">
|
||||
</div>
|
||||
</div>
|
||||
<div id="user-list">
|
||||
<div id="userlist-header">
|
||||
<h4 class='sidebar-title' id='userlist-title'>USERS</h4>
|
||||
|
||||
@@ -25,7 +25,7 @@ var globals =
|
||||
+ ' compose compose_fade rows hotkeys narrow reload notifications_bar search subs'
|
||||
+ ' composebox_typeahead typeahead_helper notifications hashchange'
|
||||
+ ' invite ui util activity timerender MessageList MessageListView blueslip unread stream_list'
|
||||
+ ' onboarding message_edit tab_bar emoji popovers navigate message_tour'
|
||||
+ ' message_edit tab_bar emoji popovers navigate message_tour'
|
||||
+ ' avatar feature_flags search_suggestion referral stream_color Dict'
|
||||
+ ' Filter summary admin stream_data muting WinChan muting_ui Socket'
|
||||
|
||||
|
||||
@@ -87,10 +87,6 @@ class ZulipSession extends Session
|
||||
content
|
||||
}, message_send_time.cbTimer()
|
||||
|
||||
@post '/json/update_onboarding_steps', {
|
||||
onboarding_steps: '[["sent_stream_message",true],["sent_private_message",true],["made_app_sticky",true]]'
|
||||
}, update_onboarding_steps_time.cbTimer()
|
||||
|
||||
send_private_message: (recipients, content) ->
|
||||
@post '/json/send_message', {
|
||||
client: 'website'
|
||||
@@ -161,7 +157,6 @@ stats = [
|
||||
message_latency = new Stat("Message Latency")
|
||||
message_send_time = new Stat("Message Send Time")
|
||||
update_status_time = new Stat("/json/update_status_time Time")
|
||||
update_onboarding_steps_time = new Stat("/json/update_onboarding_steps Time")
|
||||
total_reload_time = new Stat("Total reload time")
|
||||
get_old_messages_time = new Stat("/json/get_old_messages Time")
|
||||
]
|
||||
|
||||
@@ -1407,18 +1407,6 @@ def subscribed_to_stream(user_profile, stream):
|
||||
except Subscription.DoesNotExist:
|
||||
return False
|
||||
|
||||
def do_update_onboarding_steps(user_profile, steps):
|
||||
user_profile.onboarding_steps = ujson.dumps(steps)
|
||||
user_profile.save(update_fields=["onboarding_steps"])
|
||||
|
||||
log_event({'type': 'update_onboarding',
|
||||
'user': user_profile.email,
|
||||
'steps': steps})
|
||||
|
||||
notice = dict(event=dict(type="onboarding_steps", steps=steps),
|
||||
users=[user_profile.id])
|
||||
tornado_callbacks.send_notification(notice)
|
||||
|
||||
def do_update_message(user_profile, message_id, subject, propagate_mode, content):
|
||||
try:
|
||||
message = Message.objects.select_related().get(id=message_id)
|
||||
@@ -1674,9 +1662,6 @@ def do_events_register(user_profile, user_client, apply_markdown=True,
|
||||
'is_bot' : userdict['is_bot'],
|
||||
'full_name' : userdict['full_name']}
|
||||
for userdict in get_active_user_dicts_in_realm(user_profile.realm)]
|
||||
if event_types is None or "onboarding_steps" in event_types:
|
||||
ret['onboarding_steps'] = {'email' : user_profile.email,
|
||||
'steps' : user_profile.onboarding_steps}
|
||||
if event_types is None or "subscription" in event_types:
|
||||
subscriptions, unsubscribed, email_dict = gather_subscriptions_helper(user_profile)
|
||||
ret['subscriptions'] = subscriptions
|
||||
@@ -1705,8 +1690,6 @@ def do_events_register(user_profile, user_client, apply_markdown=True,
|
||||
ret['max_message_id'] = max(ret['max_message_id'], event['message']['id'])
|
||||
elif event['type'] == "pointer":
|
||||
ret['pointer'] = max(ret['pointer'], event['pointer'])
|
||||
elif event['type'] == "onboarding_steps":
|
||||
ret['onboarding_steps'] = event['steps']
|
||||
elif event['type'] == "realm_user":
|
||||
# We handle update by just removing the old value and
|
||||
# adding the new one.
|
||||
|
||||
@@ -8,13 +8,6 @@ import ujson
|
||||
import os
|
||||
import string
|
||||
|
||||
# The ordered list of onboarding steps we want new users to complete. If the
|
||||
# steps are changed here, they must also be changed in onboarding.js.
|
||||
onboarding_steps = ["sent_stream_message", "sent_private_message", "made_app_sticky", "set_up_integration"]
|
||||
|
||||
def create_onboarding_steps_blob():
|
||||
return ujson.dumps([(step, False) for step in onboarding_steps])
|
||||
|
||||
def random_api_key():
|
||||
choices = string.ascii_letters + string.digits
|
||||
altchars = ''.join([choices[ord(os.urandom(1)) % 62] for _ in range(2)])
|
||||
@@ -34,7 +27,7 @@ def create_user_profile(realm, email, password, active, bot, full_name, short_na
|
||||
full_name=full_name, short_name=short_name,
|
||||
last_login=now, date_joined=now, realm=realm,
|
||||
pointer=-1, is_bot=bot, bot_owner=bot_owner,
|
||||
onboarding_steps=create_onboarding_steps_blob())
|
||||
onboarding_steps=ujson.dumps([]))
|
||||
|
||||
if bot or not active:
|
||||
user_profile.set_unusable_password()
|
||||
|
||||
@@ -35,7 +35,7 @@ from zerver.lib.actions import do_remove_subscription, bulk_remove_subscriptions
|
||||
update_user_presence, bulk_add_subscriptions, do_update_message_flags, \
|
||||
recipient_for_emails, extract_recipients, do_events_register, \
|
||||
get_status_dict, do_change_enable_offline_email_notifications, \
|
||||
do_update_onboarding_steps, do_update_message, internal_prep_message, \
|
||||
do_update_message, internal_prep_message, \
|
||||
do_send_messages, do_add_subscription, get_default_subs, do_deactivate, \
|
||||
user_email_is_unique, do_invite_users, do_refer_friend, compute_mit_user_fullname, \
|
||||
do_add_alert_words, do_remove_alert_words, do_set_alert_words, get_subscriber_emails, \
|
||||
@@ -681,7 +681,6 @@ def home(request):
|
||||
max_message_id = register_ret['max_message_id'],
|
||||
unread_count = approximate_unread_count(user_profile),
|
||||
furthest_read_time = sent_time_in_epoch_seconds(latest_read),
|
||||
onboarding_steps = ujson.loads(user_profile.onboarding_steps),
|
||||
staging = settings.STAGING_DEPLOYED or not settings.DEPLOYED,
|
||||
alert_words = register_ret['alert_words'],
|
||||
muted_topics = register_ret['muted_topics'],
|
||||
@@ -1178,14 +1177,6 @@ def json_change_enter_sends(request, user_profile,
|
||||
do_change_enter_sends(user_profile, enter_sends)
|
||||
return json_success()
|
||||
|
||||
@authenticated_json_post_view
|
||||
@has_request_variables
|
||||
def json_update_onboarding_steps(request, user_profile,
|
||||
onboarding_steps=REQ(converter=json_to_list,
|
||||
default=[])):
|
||||
do_update_onboarding_steps(user_profile, onboarding_steps)
|
||||
return json_success()
|
||||
|
||||
def is_super_user_api(request):
|
||||
return request.user.is_authenticated() and is_super_user(request.user)
|
||||
|
||||
|
||||
@@ -435,7 +435,6 @@ JS_SPECS = {
|
||||
'js/invite.js',
|
||||
'js/message_list_view.js',
|
||||
'js/message_list.js',
|
||||
'js/onboarding.js',
|
||||
'js/alert_words.js',
|
||||
'js/alert_words_ui.js',
|
||||
'js/zulip.js',
|
||||
|
||||
@@ -130,7 +130,6 @@ urlpatterns += patterns('zerver.views',
|
||||
url(r'^json/messages_in_narrow$', 'json_messages_in_narrow'),
|
||||
url(r'^json/create_bot$', 'json_create_bot'),
|
||||
url(r'^json/get_bots$', 'json_get_bots'),
|
||||
url(r'^json/update_onboarding_steps$', 'json_update_onboarding_steps'),
|
||||
url(r'^json/update_message$', 'json_update_message'),
|
||||
url(r'^json/fetch_raw_message$', 'json_fetch_raw_message'),
|
||||
url(r'^json/refer_friend$', 'json_refer_friend'),
|
||||
|
||||
Reference in New Issue
Block a user