mirror of https://github.com/zulip/zulip.git
settings: Add support for uploading logo for night mode.
This adds a new field named realm_night_logo which is used for displaying the organization logo when the user is in night mode. Fixes #11176.
This commit is contained in:
parent
e67cf30dfd
commit
7157edf4af
|
@ -121,6 +121,7 @@
|
|||
"reactions": false,
|
||||
"realm_icon": false,
|
||||
"realm_logo": false,
|
||||
"realm_night_logo": false,
|
||||
"recent_senders": false,
|
||||
"reload": false,
|
||||
"reload_state": false,
|
||||
|
|
|
@ -296,6 +296,16 @@ var event_fixtures = {
|
|||
},
|
||||
},
|
||||
|
||||
realm__update_dict__night_logo: {
|
||||
type: 'realm',
|
||||
op: 'update_dict',
|
||||
property: 'night_logo',
|
||||
data: {
|
||||
night_logo_url: 'night_logo.png',
|
||||
night_logo_source: 'U',
|
||||
},
|
||||
},
|
||||
|
||||
realm__deactivated: {
|
||||
type: 'realm',
|
||||
op: 'deactivated',
|
||||
|
@ -940,6 +950,12 @@ with_overrides(function (override) {
|
|||
assert_same(page_params.realm_logo_url, 'logo.png');
|
||||
assert_same(page_params.realm_logo_source, 'U');
|
||||
|
||||
event = event_fixtures.realm__update_dict__night_logo;
|
||||
override('realm_logo.rerender', noop);
|
||||
dispatch(event);
|
||||
assert_same(page_params.realm_night_logo_url, 'night_logo.png');
|
||||
assert_same(page_params.realm_night_logo_source, 'U');
|
||||
|
||||
event = event_fixtures.realm__deactivated;
|
||||
window.location = {};
|
||||
dispatch(event);
|
||||
|
@ -1336,6 +1352,7 @@ with_overrides(function (override) {
|
|||
event = event_fixtures.update_display_settings__night_mode;
|
||||
page_params.night_mode = false;
|
||||
override('night_mode.enable', stub.f); // automatically checks if called
|
||||
override('realm_logo.rerender', noop);
|
||||
dispatch(event);
|
||||
assert_same(page_params.night_mode, true);
|
||||
});
|
||||
|
|
|
@ -57,6 +57,7 @@ const _ui_report = {
|
|||
|
||||
const _realm_logo = {
|
||||
build_realm_logo_widget: noop,
|
||||
build_realm_night_logo_widget: noop,
|
||||
};
|
||||
|
||||
set_global('channel', _channel);
|
||||
|
|
|
@ -53,6 +53,8 @@ exports.build_page = function () {
|
|||
realm_icon_url: page_params.realm_icon_url,
|
||||
realm_logo_source: page_params.realm_logo_source,
|
||||
realm_logo_url: page_params.realm_logo_url,
|
||||
realm_night_logo_source: page_params.realm_night_logo_source,
|
||||
realm_night_logo_url: page_params.realm_night_logo_url,
|
||||
realm_mandatory_topics: page_params.realm_mandatory_topics,
|
||||
realm_send_welcome_emails: page_params.realm_send_welcome_emails,
|
||||
realm_message_content_allowed_in_email_notifications:
|
||||
|
|
|
@ -2,22 +2,22 @@
|
|||
var realm_logo = (function () {
|
||||
|
||||
var exports = {};
|
||||
|
||||
exports.build_realm_logo_widget = function (upload_function) {
|
||||
var get_file_input = function () {
|
||||
return $('#realm_logo_file_input').expectOne();
|
||||
};
|
||||
|
||||
if (page_params.realm_logo_source === 'D') {
|
||||
$("#realm_logo_delete_button").hide();
|
||||
} else {
|
||||
$("#realm_logo_delete_button").show();
|
||||
}
|
||||
var data = {night: JSON.stringify(false)};
|
||||
$("#realm_logo_delete_button").on('click', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
channel.del({
|
||||
url: '/json/realm/logo',
|
||||
data: data,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -30,18 +30,61 @@ var realm_logo = (function () {
|
|||
);
|
||||
};
|
||||
|
||||
exports.build_realm_night_logo_widget = function (upload_function) {
|
||||
var get_file_input = function () {
|
||||
return $('#realm_night_logo_file_input').expectOne();
|
||||
};
|
||||
if (page_params.realm_night_logo_source === 'D') {
|
||||
$("#realm_night_logo_delete_button").hide();
|
||||
} else {
|
||||
$("#realm_night_logo_delete_button").show();
|
||||
}
|
||||
var data = {night: JSON.stringify(true)};
|
||||
$("#realm_night_logo_delete_button").on('click', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
channel.del({
|
||||
url: '/json/realm/logo',
|
||||
data: data,
|
||||
});
|
||||
});
|
||||
|
||||
return upload_widget.build_direct_upload_widget(
|
||||
get_file_input,
|
||||
$("#realm_night_logo_file_input_error").expectOne(),
|
||||
$("#realm_night_logo_upload_button").expectOne(),
|
||||
upload_function,
|
||||
page_params.max_logo_file_size
|
||||
);
|
||||
};
|
||||
|
||||
exports.rerender = function () {
|
||||
var file_input = $("#realm_logo_file_input");
|
||||
var night_file_input = $("#realm_night_logo_file_input");
|
||||
$("#realm-settings-logo").attr("src", page_params.realm_logo_url);
|
||||
$("#realm-settings-night-logo").attr("src", page_params.realm_night_logo_url);
|
||||
if (page_params.night_mode) {
|
||||
$("#realm-logo").attr("src", page_params.realm_night_logo_url);
|
||||
} else {
|
||||
$("#realm-logo").attr("src", page_params.realm_logo_url);
|
||||
}
|
||||
if (page_params.realm_logo_source === 'U') {
|
||||
$("#realm_logo_delete_button").show();
|
||||
} else {
|
||||
$("#realm_logo_delete_button").hide();
|
||||
// Need to clear input because of a small edge case
|
||||
// where you try to upload the same image you just deleted.
|
||||
var file_input = $("#realm_logo_file_input");
|
||||
file_input.val('');
|
||||
}
|
||||
if (page_params.realm_night_logo_source === 'U') {
|
||||
$("#realm_night_logo_delete_button").show();
|
||||
} else {
|
||||
$("#realm_night_logo_delete_button").hide();
|
||||
// Need to clear input because of a small edge case
|
||||
// where you try to upload the same image you just deleted.
|
||||
night_file_input.val('');
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return exports;
|
||||
|
|
|
@ -165,6 +165,10 @@ exports.dispatch_normal_event = function dispatch_normal_event(event) {
|
|||
page_params.realm_logo_url = event.data.logo_url;
|
||||
page_params.realm_logo_source = event.data.logo_source;
|
||||
realm_logo.rerender();
|
||||
} else if (event.op === 'update_dict' && event.property === 'night_logo') {
|
||||
page_params.realm_night_logo_url = event.data.night_logo_url;
|
||||
page_params.realm_night_logo_source = event.data.night_logo_source;
|
||||
realm_logo.rerender();
|
||||
} else if (event.op === 'deactivated') {
|
||||
window.location.href = "/accounts/deactivated/";
|
||||
}
|
||||
|
@ -392,8 +396,10 @@ exports.dispatch_normal_event = function dispatch_normal_event(event) {
|
|||
setTimeout(function () {
|
||||
if (event.setting === true) {
|
||||
night_mode.enable();
|
||||
realm_logo.rerender();
|
||||
} else {
|
||||
night_mode.disable();
|
||||
realm_logo.rerender();
|
||||
}
|
||||
$("body").fadeIn(300);
|
||||
}, 300);
|
||||
|
|
|
@ -1116,20 +1116,30 @@ exports.build_page = function () {
|
|||
}
|
||||
realm_icon.build_realm_icon_widget(upload_realm_icon);
|
||||
|
||||
function upload_realm_logo(file_input) {
|
||||
function upload_realm_logo(file_input, night) {
|
||||
var form_data = new FormData();
|
||||
var spinner;
|
||||
var error_field;
|
||||
var button_text;
|
||||
|
||||
form_data.append('csrfmiddlewaretoken', csrf_token);
|
||||
jQuery.each(file_input[0].files, function (i, file) {
|
||||
form_data.append('file-' + i, file);
|
||||
});
|
||||
|
||||
var error_field = $("#realm_logo_file_input_error");
|
||||
if (night) {
|
||||
error_field = $("#realm_night_logo_file_input_error");
|
||||
spinner = $("#upload_night_logo_spinner");
|
||||
button_text = $("#upload_night_logo_button_text");
|
||||
} else {
|
||||
error_field = $("#realm_logo_file_input_error");
|
||||
spinner = $("#upload_logo_spinner");
|
||||
button_text = $("#upload_logo_button_text");
|
||||
}
|
||||
spinner.expectOne();
|
||||
error_field.hide();
|
||||
var spinner = $("#upload_logo_spinner").expectOne();
|
||||
button_text.expectOne().hide();
|
||||
loading.make_indicator(spinner, {text: i18n.t("Uploading logo.")});
|
||||
$("#upload_logo_button_text").expectOne().hide();
|
||||
|
||||
form_data.append('night', JSON.stringify(night));
|
||||
channel.post({
|
||||
url: '/json/realm/logo',
|
||||
data: form_data,
|
||||
|
@ -1137,17 +1147,18 @@ exports.build_page = function () {
|
|||
processData: false,
|
||||
contentType: false,
|
||||
success: function () {
|
||||
loading.destroy_indicator($("#upload_logo_spinner"));
|
||||
$("#upload_logo_button_text").expectOne().show();
|
||||
loading.destroy_indicator(spinner);
|
||||
button_text.expectOne().show();
|
||||
},
|
||||
error: function (xhr) {
|
||||
loading.destroy_indicator($("#upload_logo_spinner"));
|
||||
$("#upload_logo_button_text").expectOne().show();
|
||||
loading.destroy_indicator(spinner);
|
||||
button_text.expectOne().show();
|
||||
ui_report.error("", xhr, error_field);
|
||||
},
|
||||
});
|
||||
|
||||
}
|
||||
realm_logo.build_realm_night_logo_widget(upload_realm_logo);
|
||||
realm_logo.build_realm_logo_widget(upload_realm_logo);
|
||||
|
||||
$('#deactivate_realm_button').on('click', function (e) {
|
||||
|
|
|
@ -116,11 +116,16 @@ var upload_widget = (function () {
|
|||
) {
|
||||
// default value of max upladed file size
|
||||
max_file_upload_size = max_file_upload_size || default_max_file_size;
|
||||
|
||||
function accept() {
|
||||
input_error.hide();
|
||||
if (upload_button[0].id === "realm_night_logo_upload_button") {
|
||||
upload_function(get_file_input(), true);
|
||||
} else if (upload_button[0].id === "realm_logo_upload_button") {
|
||||
upload_function(get_file_input(), false);
|
||||
} else {
|
||||
upload_function(get_file_input());
|
||||
}
|
||||
}
|
||||
|
||||
function clear() {
|
||||
var control = get_file_input();
|
||||
|
|
|
@ -970,7 +970,8 @@ input[type=checkbox].inline-block {
|
|||
|
||||
#upload_avatar_spinner,
|
||||
#upload_logo_spinner,
|
||||
#upload_icon_spinner {
|
||||
#upload_icon_spinner,
|
||||
#upload_night_logo_spinner {
|
||||
font-size: 14px;
|
||||
margin: auto;
|
||||
}
|
||||
|
@ -1113,7 +1114,8 @@ input[type=checkbox].inline-block {
|
|||
height: 100px;
|
||||
}
|
||||
|
||||
#realm-settings-logo {
|
||||
#realm-settings-logo,
|
||||
#realm-settings-night-logo {
|
||||
border-radius: 5px;
|
||||
box-shadow: 0px 0px 10px hsla(0, 0%, 0%, 0.2);
|
||||
/* We allow actual images up to 800x100 in the main display, but the
|
||||
|
@ -1690,7 +1692,8 @@ input[type=text]#settings_search {
|
|||
}
|
||||
|
||||
@media (max-width: 1023px) {
|
||||
#realm-settings-logo {
|
||||
#realm-settings-logo,
|
||||
#realm-settings-night-logo {
|
||||
max-width: 600px;
|
||||
height: 75px;
|
||||
}
|
||||
|
@ -1716,7 +1719,8 @@ input[type=text]#settings_search {
|
|||
margin: 5px 0 0 0;
|
||||
}
|
||||
|
||||
#realm-settings-logo {
|
||||
#realm-settings-logo,
|
||||
#realm-settings-night-logo {
|
||||
max-width: 400px;
|
||||
height: 50px;
|
||||
}
|
||||
|
|
|
@ -66,6 +66,27 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<h3>{{t "Organization logo for night mode" }}</h3>
|
||||
<p>{{t "Like Organization Logo, but for the night theme." }}</p>
|
||||
|
||||
<div class="realm-logo-section realm-night-logo-section">
|
||||
<div class="block realm-logo-block">
|
||||
<img id="realm-settings-night-logo" src="{{ realm_night_logo_url }}">
|
||||
<input type="file" name="realm_night_logo_file_input" class="notvisible"
|
||||
id="realm_night_logo_file_input" value="{{t 'Upload logo' }}"/>
|
||||
</div>
|
||||
<div class="block avatar-controls">
|
||||
<div id="realm_night_logo_file_input_error" class="alert text-error"></div>
|
||||
<button class="button rounded sea-green w-200 block input-size"
|
||||
id="realm_night_logo_upload_button">
|
||||
<span id="upload_night_logo_button_text">{{t 'Upload new logo' }}</span>
|
||||
<span id="upload_night_logo_spinner"></span>
|
||||
</button>
|
||||
<button class="button rounded btn-danger w-200 m-t-10 block input-size"
|
||||
id="realm_night_logo_delete_button">{{t 'Delete logo' }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="light">{{t "Deactivate organization" }}</h3>
|
||||
<div class="deactivate-realm-section">
|
||||
<div class="input-group">
|
||||
|
|
|
@ -56,6 +56,9 @@ curl {{ api_url }}/v1/server_settings \
|
|||
* `realm_logo`: the URI of the organization's logo as a horizontal
|
||||
format image (displayed in the top-left corner of the logged-in
|
||||
webapp).
|
||||
* `realm_night_logo`: the URI of the organization's logo in the night mode as a
|
||||
horizontal format image (dispalyed in the top-left corner of the logged-in
|
||||
webapp).
|
||||
* `realm_description`: HTML description of the organization, as configured by
|
||||
the [organization profile](/help/create-your-organization-profile).
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<nav class="header-main rightside-userlist" id="top_navbar">
|
||||
<div class="column-left">
|
||||
<a class="brand no-style" href="#">
|
||||
<img id="realm-logo" src="{{ realm_logo }}" alt="" class="nav-logo no-drag">
|
||||
<img id="realm-logo" src="{% if night_mode %} {{ realm_night_logo }}{% else %} {{ realm_logo }} {% endif %}" alt="" class="nav-logo no-drag"/>
|
||||
</a>
|
||||
</div>
|
||||
<div class="column-middle" id="navbar-middle">
|
||||
|
|
|
@ -55,6 +55,7 @@ def zulip_default_context(request: HttpRequest) -> Dict[str, Any]:
|
|||
realm_name = None
|
||||
realm_icon = None
|
||||
realm_logo = None
|
||||
realm_night_logo = None
|
||||
realm_description = None
|
||||
realm_invite_required = False
|
||||
realm_plan_type = 0
|
||||
|
@ -62,7 +63,8 @@ def zulip_default_context(request: HttpRequest) -> Dict[str, Any]:
|
|||
realm_uri = realm.uri
|
||||
realm_name = realm.name
|
||||
realm_icon = get_realm_icon_url(realm)
|
||||
realm_logo = get_realm_logo_url(realm)
|
||||
realm_logo = get_realm_logo_url(realm, night = False)
|
||||
realm_night_logo = get_realm_logo_url(realm, night = True)
|
||||
realm_description_raw = realm.description or "The coolest place in the universe."
|
||||
realm_description = bugdown_convert(realm_description_raw, message_realm=realm)
|
||||
realm_invite_required = realm.invite_required
|
||||
|
@ -118,6 +120,7 @@ def zulip_default_context(request: HttpRequest) -> Dict[str, Any]:
|
|||
'realm_name': realm_name,
|
||||
'realm_icon': realm_icon,
|
||||
'realm_logo': realm_logo,
|
||||
'realm_night_logo': realm_night_logo,
|
||||
'realm_description': realm_description,
|
||||
'realm_plan_type': realm_plan_type,
|
||||
'root_domain_uri': settings.ROOT_DOMAIN_URI,
|
||||
|
|
|
@ -3266,22 +3266,39 @@ def do_change_icon_source(realm: Realm, icon_source: str, log: bool=True) -> Non
|
|||
icon_url=realm_icon_url(realm))),
|
||||
active_user_ids(realm.id))
|
||||
|
||||
def do_change_logo_source(realm: Realm, logo_source: str) -> None:
|
||||
def do_change_logo_source(realm: Realm, logo_source: str, night: bool) -> None:
|
||||
if not night:
|
||||
realm.logo_source = logo_source
|
||||
realm.logo_version += 1
|
||||
realm.save(update_fields=["logo_source", "logo_version"])
|
||||
|
||||
else:
|
||||
realm.night_logo_source = logo_source
|
||||
realm.night_logo_version += 1
|
||||
realm.save(update_fields=["night_logo_source", "night_logo_version"])
|
||||
|
||||
RealmAuditLog.objects.create(event_type=RealmAuditLog.REALM_LOGO_CHANGED,
|
||||
realm=realm, event_time=timezone_now())
|
||||
|
||||
if not night:
|
||||
send_event(realm,
|
||||
dict(type='realm',
|
||||
op='update_dict',
|
||||
property="logo",
|
||||
data=dict(logo_source=realm.logo_source,
|
||||
logo_url=realm_logo_url(realm))),
|
||||
logo_url=realm_logo_url(realm, night))),
|
||||
active_user_ids(realm.id))
|
||||
|
||||
else:
|
||||
send_event(realm,
|
||||
dict(type='realm',
|
||||
op='update_dict',
|
||||
property="night_logo",
|
||||
data=dict(night_logo_source=realm.night_logo_source,
|
||||
night_logo_url=realm_logo_url(realm, night))),
|
||||
active_user_ids(realm.id))
|
||||
|
||||
|
||||
def do_change_plan_type(realm: Realm, plan_type: int) -> None:
|
||||
old_value = realm.plan_type
|
||||
realm.plan_type = plan_type
|
||||
|
|
|
@ -180,8 +180,10 @@ def fetch_initial_state_data(user_profile: UserProfile,
|
|||
state['realm_icon_url'] = realm_icon_url(realm)
|
||||
state['realm_icon_source'] = realm.icon_source
|
||||
state['max_icon_file_size'] = settings.MAX_ICON_FILE_SIZE
|
||||
state['realm_logo_url'] = realm_logo_url(realm)
|
||||
state['realm_logo_url'] = realm_logo_url(realm, night = False)
|
||||
state['realm_logo_source'] = realm.logo_source
|
||||
state['realm_night_logo_url'] = realm_logo_url(realm, night = True)
|
||||
state['realm_night_logo_source'] = realm.night_logo_source
|
||||
state['max_logo_file_size'] = settings.MAX_LOGO_FILE_SIZE
|
||||
state['realm_bot_domain'] = realm.get_bot_domain()
|
||||
state['realm_uri'] = realm.uri
|
||||
|
|
|
@ -3,11 +3,17 @@ from django.conf import settings
|
|||
from zerver.lib.upload import upload_backend
|
||||
from zerver.models import Realm
|
||||
|
||||
def realm_logo_url(realm: Realm) -> str:
|
||||
return get_realm_logo_url(realm)
|
||||
def realm_logo_url(realm: Realm, night: bool) -> str:
|
||||
return get_realm_logo_url(realm, night)
|
||||
|
||||
def get_realm_logo_url(realm: Realm) -> str:
|
||||
def get_realm_logo_url(realm: Realm, night: bool) -> str:
|
||||
if not night:
|
||||
if realm.logo_source == 'U':
|
||||
return upload_backend.get_realm_logo_url(realm.id, realm.logo_version)
|
||||
return upload_backend.get_realm_logo_url(realm.id, realm.logo_version, night)
|
||||
else:
|
||||
return settings.DEFAULT_LOGO_URI+'?version=0'
|
||||
else:
|
||||
if realm.night_logo_source == 'U':
|
||||
return upload_backend.get_realm_logo_url(realm.id, realm.night_logo_version, night)
|
||||
else:
|
||||
return settings.DEFAULT_LOGO_URI+'?version=0'
|
||||
|
|
|
@ -225,10 +225,11 @@ class ZulipUploadBackend:
|
|||
def get_realm_icon_url(self, realm_id: int, version: int) -> str:
|
||||
raise NotImplementedError()
|
||||
|
||||
def upload_realm_logo_image(self, logo_file: File, user_profile: UserProfile) -> None:
|
||||
def upload_realm_logo_image(self, logo_file: File, user_profile: UserProfile,
|
||||
night: bool) -> None:
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_realm_logo_url(self, realm_id: int, version: int) -> str:
|
||||
def get_realm_logo_url(self, realm_id: int, version: int, night: bool) -> str:
|
||||
raise NotImplementedError()
|
||||
|
||||
def upload_emoji_image(self, emoji_file: File, emoji_file_name: str, user_profile: UserProfile) -> None:
|
||||
|
@ -467,10 +468,15 @@ class S3UploadBackend(ZulipUploadBackend):
|
|||
# ?x=x allows templates to append additional parameters with &s
|
||||
return "https://%s.s3.amazonaws.com/%s/realm/icon.png?version=%s" % (bucket, realm_id, version)
|
||||
|
||||
def upload_realm_logo_image(self, logo_file: File, user_profile: UserProfile) -> None:
|
||||
def upload_realm_logo_image(self, logo_file: File, user_profile: UserProfile,
|
||||
night: bool) -> None:
|
||||
content_type = guess_type(logo_file.name)[0]
|
||||
bucket_name = settings.S3_AVATAR_BUCKET
|
||||
s3_file_name = os.path.join(str(user_profile.realm.id), 'realm', 'logo')
|
||||
if night:
|
||||
basename = 'night_logo'
|
||||
else:
|
||||
basename = 'logo'
|
||||
s3_file_name = os.path.join(str(user_profile.realm.id), 'realm', basename)
|
||||
|
||||
image_data = logo_file.read()
|
||||
upload_image_to_s3(
|
||||
|
@ -492,10 +498,14 @@ class S3UploadBackend(ZulipUploadBackend):
|
|||
# See avatar_url in avatar.py for URL. (That code also handles the case
|
||||
# that users use gravatar.)
|
||||
|
||||
def get_realm_logo_url(self, realm_id: int, version: int) -> str:
|
||||
def get_realm_logo_url(self, realm_id: int, version: int, night: bool) -> str:
|
||||
bucket = settings.S3_AVATAR_BUCKET
|
||||
# ?x=x allows templates to append additional parameters with &s
|
||||
return "https://%s.s3.amazonaws.com/%s/realm/logo.png?version=%s" % (bucket, realm_id, version)
|
||||
if not night:
|
||||
file_name = 'logo.png'
|
||||
else:
|
||||
file_name = 'night_logo.png'
|
||||
return "https://%s.s3.amazonaws.com/%s/realm/%s?version=%s" % (bucket, realm_id, file_name, version)
|
||||
|
||||
def ensure_medium_avatar_image(self, user_profile: UserProfile) -> None:
|
||||
file_path = user_avatar_path(user_profile)
|
||||
|
@ -671,21 +681,31 @@ class LocalUploadBackend(ZulipUploadBackend):
|
|||
# ?x=x allows templates to append additional parameters with &s
|
||||
return "/user_avatars/%s/realm/icon.png?version=%s" % (realm_id, version)
|
||||
|
||||
def upload_realm_logo_image(self, logo_file: File, user_profile: UserProfile) -> None:
|
||||
def upload_realm_logo_image(self, logo_file: File, user_profile: UserProfile,
|
||||
night: bool) -> None:
|
||||
upload_path = os.path.join('avatars', str(user_profile.realm.id), 'realm')
|
||||
|
||||
if night:
|
||||
original_file = 'night_logo.original'
|
||||
resized_file = 'night_logo.png'
|
||||
else:
|
||||
original_file = 'logo.original'
|
||||
resized_file = 'logo.png'
|
||||
image_data = logo_file.read()
|
||||
write_local_file(
|
||||
upload_path,
|
||||
'logo.original',
|
||||
original_file,
|
||||
image_data)
|
||||
|
||||
resized_data = resize_logo(image_data)
|
||||
write_local_file(upload_path, 'logo.png', resized_data)
|
||||
write_local_file(upload_path, resized_file, resized_data)
|
||||
|
||||
def get_realm_logo_url(self, realm_id: int, version: int) -> str:
|
||||
def get_realm_logo_url(self, realm_id: int, version: int, night: bool) -> str:
|
||||
# ?x=x allows templates to append additional parameters with &s
|
||||
return "/user_avatars/%s/realm/logo.png?version=%s" % (realm_id, version)
|
||||
if night:
|
||||
file_name = 'night_logo.png'
|
||||
else:
|
||||
file_name = 'logo.png'
|
||||
return "/user_avatars/%s/realm/%s?version=%s" % (realm_id, file_name, version)
|
||||
|
||||
def ensure_medium_avatar_image(self, user_profile: UserProfile) -> None:
|
||||
file_path = user_avatar_path(user_profile)
|
||||
|
@ -757,8 +777,8 @@ def copy_avatar(source_profile: UserProfile, target_profile: UserProfile) -> Non
|
|||
def upload_icon_image(user_file: File, user_profile: UserProfile) -> None:
|
||||
upload_backend.upload_realm_icon_image(user_file, user_profile)
|
||||
|
||||
def upload_logo_image(user_file: File, user_profile: UserProfile) -> None:
|
||||
upload_backend.upload_realm_logo_image(user_file, user_profile)
|
||||
def upload_logo_image(user_file: File, user_profile: UserProfile, night: bool) -> None:
|
||||
upload_backend.upload_realm_logo_image(user_file, user_profile, night)
|
||||
|
||||
def upload_emoji_image(emoji_file: File, emoji_file_name: str, user_profile: UserProfile) -> None:
|
||||
upload_backend.upload_emoji_image(emoji_file, emoji_file_name, user_profile)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.18 on 2019-01-15 16:07
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('zerver', '0207_multiuseinvite_invited_as'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='realm',
|
||||
name='night_logo_source',
|
||||
field=models.CharField(choices=[('D', 'Default to Zulip'), ('U', 'Uploaded by administrator')], default='D', max_length=1),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='realm',
|
||||
name='night_logo_version',
|
||||
field=models.PositiveSmallIntegerField(default=1),
|
||||
),
|
||||
]
|
|
@ -316,6 +316,10 @@ class Realm(models.Model):
|
|||
max_length=1) # type: str
|
||||
logo_version = models.PositiveSmallIntegerField(default=1) # type: int
|
||||
|
||||
night_logo_source = models.CharField(default=LOGO_DEFAULT, choices=LOGO_SOURCES,
|
||||
max_length=1) # type: str
|
||||
night_logo_version = models.PositiveSmallIntegerField(default=1) # type: int
|
||||
|
||||
BOT_CREATION_POLICY_TYPES = [
|
||||
BOT_CREATION_EVERYONE,
|
||||
BOT_CREATION_LIMIT_GENERIC_BOTS,
|
||||
|
|
|
@ -1759,6 +1759,10 @@ paths:
|
|||
type: string
|
||||
description: The URI of the organization's top-left navbar logo
|
||||
(usually a wide rectangular version of the logo).
|
||||
realm_night_logo:
|
||||
type: string
|
||||
description: The URI of the organization's top-left navbar logo in night_mode
|
||||
(usually a wide rectangular version of the logo).
|
||||
realm_description:
|
||||
type: string
|
||||
description: HTML description of the organization, as
|
||||
|
@ -1771,6 +1775,7 @@ paths:
|
|||
"msg": "",
|
||||
"realm_icon": "https://secure.gravatar.com/avatar/62429d594b6ffc712f54aee976a18b44?d=identicon",
|
||||
"realm_logo": "/static/images/logo/zulip-org-logo.png",
|
||||
"realm_night_logo": "static/images/logo/zulip-org-logo.png",
|
||||
"realm_description": "<p>The Zulip development environment default organization. It's great for testing!</p>",
|
||||
"email_auth_enabled": true,
|
||||
"zulip_version": "1.9.0-rc1+git",
|
||||
|
|
|
@ -1719,6 +1719,7 @@ class FetchAuthBackends(ZulipTestCase):
|
|||
('realm_description', check_string),
|
||||
('realm_icon', check_string),
|
||||
('realm_logo', check_string),
|
||||
('realm_night_logo', check_string),
|
||||
])
|
||||
|
||||
def test_fetch_auth_backend_format(self) -> None:
|
||||
|
|
|
@ -157,6 +157,8 @@ class HomeTest(ZulipTestCase):
|
|||
"realm_name",
|
||||
"realm_name_changes_disabled",
|
||||
"realm_name_in_notifications",
|
||||
"realm_night_logo_source",
|
||||
"realm_night_logo_url",
|
||||
"realm_non_active_users",
|
||||
"realm_notifications_stream_id",
|
||||
"realm_password_auth_enabled",
|
||||
|
|
|
@ -40,6 +40,7 @@ from zerver.lib.users import get_api_key
|
|||
from zerver.views.upload import upload_file_backend
|
||||
|
||||
import urllib
|
||||
import ujson
|
||||
from PIL import Image
|
||||
|
||||
from io import StringIO
|
||||
|
@ -799,8 +800,10 @@ class AvatarTest(UploadSerializeMixin, ZulipTestCase):
|
|||
"/user_avatars/hash-medium.png?x=x")
|
||||
self.assertEqual(backend.get_realm_icon_url(15, 1),
|
||||
"/user_avatars/15/realm/icon.png?version=1")
|
||||
self.assertEqual(backend.get_realm_logo_url(15, 1),
|
||||
self.assertEqual(backend.get_realm_logo_url(15, 1, False),
|
||||
"/user_avatars/15/realm/logo.png?version=1")
|
||||
self.assertEqual(backend.get_realm_logo_url(15, 1, True),
|
||||
"/user_avatars/15/realm/night_logo.png?version=1")
|
||||
|
||||
with self.settings(S3_AVATAR_BUCKET="bucket"):
|
||||
backend = S3UploadBackend()
|
||||
|
@ -810,8 +813,10 @@ class AvatarTest(UploadSerializeMixin, ZulipTestCase):
|
|||
"https://bucket.s3.amazonaws.com/hash-medium.png?x=x")
|
||||
self.assertEqual(backend.get_realm_icon_url(15, 1),
|
||||
"https://bucket.s3.amazonaws.com/15/realm/icon.png?version=1")
|
||||
self.assertEqual(backend.get_realm_logo_url(15, 1),
|
||||
self.assertEqual(backend.get_realm_logo_url(15, 1, False),
|
||||
"https://bucket.s3.amazonaws.com/15/realm/logo.png?version=1")
|
||||
self.assertEqual(backend.get_realm_logo_url(15, 1, True),
|
||||
"https://bucket.s3.amazonaws.com/15/realm/night_logo.png?version=1")
|
||||
|
||||
def test_multiple_upload_failure(self) -> None:
|
||||
"""
|
||||
|
@ -1250,6 +1255,7 @@ class RealmIconTest(UploadSerializeMixin, ZulipTestCase):
|
|||
destroy_uploads()
|
||||
|
||||
class RealmLogoTest(UploadSerializeMixin, ZulipTestCase):
|
||||
night = False
|
||||
|
||||
def test_multiple_upload_failure(self) -> None:
|
||||
"""
|
||||
|
@ -1259,7 +1265,8 @@ class RealmLogoTest(UploadSerializeMixin, ZulipTestCase):
|
|||
self.login(self.example_email("iago"))
|
||||
with get_test_image_file('img.png') as fp1, \
|
||||
get_test_image_file('img.png') as fp2:
|
||||
result = self.client_post("/json/realm/logo", {'f1': fp1, 'f2': fp2})
|
||||
result = self.client_post("/json/realm/logo", {'f1': fp1, 'f2': fp2,
|
||||
'night': ujson.dumps(self.night)})
|
||||
self.assert_json_error(result, "You must upload exactly one logo.")
|
||||
|
||||
def test_no_file_upload_failure(self) -> None:
|
||||
|
@ -1268,7 +1275,7 @@ class RealmLogoTest(UploadSerializeMixin, ZulipTestCase):
|
|||
"""
|
||||
self.login(self.example_email("iago"))
|
||||
|
||||
result = self.client_post("/json/realm/logo")
|
||||
result = self.client_post("/json/realm/logo", {'night': ujson.dumps(self.night)})
|
||||
self.assert_json_error(result, "You must upload exactly one logo.")
|
||||
|
||||
correct_files = [
|
||||
|
@ -1283,7 +1290,7 @@ class RealmLogoTest(UploadSerializeMixin, ZulipTestCase):
|
|||
def test_no_admin_user_upload(self) -> None:
|
||||
self.login(self.example_email("hamlet"))
|
||||
with get_test_image_file(self.correct_files[0][0]) as fp:
|
||||
result = self.client_post("/json/realm/logo", {'file': fp})
|
||||
result = self.client_post("/json/realm/logo", {'file': fp, 'night': ujson.dumps(self.night)})
|
||||
self.assert_json_error(result, 'Must be an organization administrator')
|
||||
|
||||
def test_upload_limited_plan_type(self) -> None:
|
||||
|
@ -1291,45 +1298,53 @@ class RealmLogoTest(UploadSerializeMixin, ZulipTestCase):
|
|||
do_change_plan_type(user_profile.realm, Realm.LIMITED)
|
||||
self.login(user_profile.email)
|
||||
with get_test_image_file(self.correct_files[0][0]) as fp:
|
||||
result = self.client_post("/json/realm/logo", {'file': fp})
|
||||
result = self.client_post("/json/realm/logo", {'file': fp, 'night': ujson.dumps(self.night)})
|
||||
self.assert_json_error(result, 'Feature unavailable on your current plan.')
|
||||
|
||||
def test_get_default_logo(self) -> None:
|
||||
self.login(self.example_email("hamlet"))
|
||||
realm = get_realm('zulip')
|
||||
realm.logo_source = Realm.LOGO_DEFAULT
|
||||
realm.night_logo_source = Realm.LOGO_DEFAULT
|
||||
realm.save()
|
||||
|
||||
response = self.client_get("/json/realm/logo?foo=bar")
|
||||
response = self.client_get("/json/realm/logo", {'night': ujson.dumps(self.night)})
|
||||
redirect_url = response['Location']
|
||||
self.assertEqual(redirect_url, realm_logo_url(realm) + '&foo=bar')
|
||||
self.assertEqual(redirect_url, realm_logo_url(realm, self.night) +
|
||||
'&night=%s' % (str(self.night).lower()))
|
||||
|
||||
def test_get_realm_logo(self) -> None:
|
||||
self.login(self.example_email("hamlet"))
|
||||
|
||||
realm = get_realm('zulip')
|
||||
realm.logo_source = Realm.LOGO_UPLOADED
|
||||
realm.night_logo_source = Realm.LOGO_UPLOADED
|
||||
realm.save()
|
||||
response = self.client_get("/json/realm/logo?foo=bar")
|
||||
response = self.client_get("/json/realm/logo", {'night': ujson.dumps(self.night)})
|
||||
redirect_url = response['Location']
|
||||
self.assertTrue(redirect_url.endswith(realm_logo_url(realm) + '&foo=bar'))
|
||||
self.assertTrue(redirect_url.endswith(realm_logo_url(realm, self.night) +
|
||||
'&night=%s' % (str(self.night).lower())))
|
||||
|
||||
def test_valid_logos(self) -> None:
|
||||
"""
|
||||
A PUT request to /json/realm/logo with a valid file should return a url
|
||||
and actually create an realm logo.
|
||||
"""
|
||||
if self.night:
|
||||
field_name = 'night_logo_url'
|
||||
file_name = 'night_logo.png'
|
||||
else:
|
||||
field_name = 'logo_url'
|
||||
file_name = 'logo.png'
|
||||
for fname, rfname in self.correct_files:
|
||||
# TODO: use self.subTest once we're exclusively on python 3 by uncommenting the line below.
|
||||
# with self.subTest(fname=fname):
|
||||
self.login(self.example_email("iago"))
|
||||
with get_test_image_file(fname) as fp:
|
||||
result = self.client_post("/json/realm/logo", {'file': fp})
|
||||
result = self.client_post("/json/realm/logo", {'file': fp, 'night': ujson.dumps(self.night)})
|
||||
realm = get_realm('zulip')
|
||||
self.assert_json_success(result)
|
||||
self.assertIn("logo_url", result.json())
|
||||
base = '/user_avatars/%s/realm/logo.png' % (realm.id,)
|
||||
url = result.json()['logo_url']
|
||||
self.assertIn(field_name, result.json())
|
||||
base = '/user_avatars/%s/realm/%s' % (realm.id, file_name)
|
||||
url = result.json()[field_name]
|
||||
self.assertEqual(base, url[:len(base)])
|
||||
|
||||
if rfname is not None:
|
||||
|
@ -1339,7 +1354,7 @@ class RealmLogoTest(UploadSerializeMixin, ZulipTestCase):
|
|||
# while trying to fit in a 800 x 100 box without losing part of the image
|
||||
self.assertEqual(Image.open(io.BytesIO(data)).size, (100, 100))
|
||||
|
||||
def test_invalid_logos(self) -> None:
|
||||
def test_invalid_logo_upload(self) -> None:
|
||||
"""
|
||||
A PUT request to /json/realm/logo with an invalid file should fail.
|
||||
"""
|
||||
|
@ -1347,7 +1362,7 @@ class RealmLogoTest(UploadSerializeMixin, ZulipTestCase):
|
|||
# with self.subTest(fname=fname):
|
||||
self.login(self.example_email("iago"))
|
||||
with get_test_image_file(fname) as fp:
|
||||
result = self.client_post("/json/realm/logo", {'file': fp})
|
||||
result = self.client_post("/json/realm/logo", {'file': fp, 'night': ujson.dumps(self.night)})
|
||||
|
||||
self.assert_json_error(result, "Could not decode image; did you upload an image file?")
|
||||
|
||||
|
@ -1355,39 +1370,57 @@ class RealmLogoTest(UploadSerializeMixin, ZulipTestCase):
|
|||
"""
|
||||
A DELETE request to /json/realm/logo should delete the realm logo and return gravatar URL
|
||||
"""
|
||||
if self.night:
|
||||
field_name = 'night_logo_url'
|
||||
else:
|
||||
field_name = 'logo_url'
|
||||
|
||||
self.login(self.example_email("iago"))
|
||||
realm = get_realm('zulip')
|
||||
realm.logo_source = Realm.LOGO_UPLOADED
|
||||
realm.night_logo_source = Realm.LOGO_UPLOADED
|
||||
realm.save()
|
||||
|
||||
result = self.client_delete("/json/realm/logo")
|
||||
|
||||
result = self.client_delete("/json/realm/logo", {'night': ujson.dumps(self.night)})
|
||||
self.assert_json_success(result)
|
||||
self.assertIn("logo_url", result.json())
|
||||
self.assertIn(field_name, result.json())
|
||||
realm = get_realm('zulip')
|
||||
self.assertEqual(result.json()["logo_url"], realm_logo_url(realm))
|
||||
self.assertEqual(result.json()[field_name], realm_logo_url(realm, self.night))
|
||||
if self.night:
|
||||
self.assertEqual(realm.night_logo_source, Realm.LOGO_DEFAULT)
|
||||
else:
|
||||
self.assertEqual(realm.logo_source, Realm.LOGO_DEFAULT)
|
||||
|
||||
def test_realm_logo_version(self) -> None:
|
||||
def test_logo_version(self) -> None:
|
||||
self.login(self.example_email("iago"))
|
||||
realm = get_realm('zulip')
|
||||
logo_version = realm.logo_version
|
||||
self.assertEqual(logo_version, 1)
|
||||
if self.night:
|
||||
version = realm.night_logo_version
|
||||
else:
|
||||
version = realm.logo_version
|
||||
self.assertEqual(version, 1)
|
||||
with get_test_image_file(self.correct_files[0][0]) as fp:
|
||||
self.client_post("/json/realm/logo", {'file': fp})
|
||||
self.client_post("/json/realm/logo", {'file': fp, 'night': ujson.dumps(self.night)})
|
||||
realm = get_realm('zulip')
|
||||
self.assertEqual(realm.logo_version, logo_version + 1)
|
||||
if self.night:
|
||||
self.assertEqual(realm.night_logo_version, version + 1)
|
||||
else:
|
||||
self.assertEqual(realm.logo_version, version + 1)
|
||||
|
||||
def test_realm_logo_upload_file_size_error(self) -> None:
|
||||
def test_logo_upload_file_size_error(self) -> None:
|
||||
self.login(self.example_email("iago"))
|
||||
with get_test_image_file(self.correct_files[0][0]) as fp:
|
||||
with self.settings(MAX_LOGO_FILE_SIZE=0):
|
||||
result = self.client_post("/json/realm/logo", {'file': fp})
|
||||
result = self.client_post("/json/realm/logo", {'file': fp, 'night':
|
||||
ujson.dumps(self.night)})
|
||||
self.assert_json_error(result, "Uploaded file is larger than the allowed limit of 0 MB")
|
||||
|
||||
def tearDown(self) -> None:
|
||||
destroy_uploads()
|
||||
|
||||
class RealmNightLogoTest(RealmLogoTest):
|
||||
# Run the same tests as for RealmLogoTest, just with night mode enabled
|
||||
night = True
|
||||
|
||||
class LocalStorageTest(UploadSerializeMixin, ZulipTestCase):
|
||||
|
||||
def test_file_upload_local(self) -> None:
|
||||
|
@ -1662,23 +1695,29 @@ class S3Test(ZulipTestCase):
|
|||
self.assertEqual(resized_image, (DEFAULT_AVATAR_SIZE, DEFAULT_AVATAR_SIZE))
|
||||
|
||||
@use_s3_backend
|
||||
def test_upload_realm_logo_image(self) -> None:
|
||||
def _test_upload_logo_image(self, night: bool, file_name: str) -> None:
|
||||
bucket = create_s3_buckets(settings.S3_AVATAR_BUCKET)[0]
|
||||
|
||||
user_profile = self.example_user("hamlet")
|
||||
image_file = get_test_image_file("img.png")
|
||||
zerver.lib.upload.upload_backend.upload_realm_logo_image(image_file, user_profile)
|
||||
zerver.lib.upload.upload_backend.upload_realm_logo_image(image_file, user_profile, night)
|
||||
|
||||
original_path_id = os.path.join(str(user_profile.realm.id), "realm", "logo.original")
|
||||
original_path_id = os.path.join(str(user_profile.realm.id), "realm", "%s.original" % (file_name))
|
||||
print(original_path_id)
|
||||
original_key = bucket.get_key(original_path_id)
|
||||
print(original_key)
|
||||
image_file.seek(0)
|
||||
self.assertEqual(image_file.read(), original_key.get_contents_as_string())
|
||||
|
||||
resized_path_id = os.path.join(str(user_profile.realm.id), "realm", "logo.png")
|
||||
resized_path_id = os.path.join(str(user_profile.realm.id), "realm", "%s.png" % (file_name))
|
||||
resized_data = bucket.get_key(resized_path_id).read()
|
||||
resized_image = Image.open(io.BytesIO(resized_data)).size
|
||||
self.assertEqual(resized_image, (DEFAULT_AVATAR_SIZE, DEFAULT_AVATAR_SIZE))
|
||||
|
||||
def test_upload_realm_logo_image(self) -> None:
|
||||
self._test_upload_logo_image(night = False, file_name = 'logo')
|
||||
self._test_upload_logo_image(night = True, file_name = 'night_logo')
|
||||
|
||||
@use_s3_backend
|
||||
def test_upload_emoji_image(self) -> None:
|
||||
bucket = create_s3_buckets(settings.S3_AVATAR_BUCKET)[0]
|
||||
|
@ -1802,5 +1841,8 @@ class DecompressionBombTests(ZulipTestCase):
|
|||
with get_test_image_file("bomb.png") as fp:
|
||||
for url, error_string in self.test_urls.items():
|
||||
fp.seek(0, 0)
|
||||
if (url == "/json/realm/logo"):
|
||||
result = self.client_post(url, {'f1': fp, 'night': ujson.dumps(False)})
|
||||
else:
|
||||
result = self.client_post(url, {'f1': fp})
|
||||
self.assert_json_error(result, error_string)
|
||||
|
|
|
@ -872,6 +872,7 @@ def api_get_server_settings(request: HttpRequest) -> HttpResponse:
|
|||
"realm_name",
|
||||
"realm_icon",
|
||||
"realm_logo",
|
||||
"realm_night_logo",
|
||||
"realm_description"]:
|
||||
if context[settings_item] is not None:
|
||||
result[settings_item] = context[settings_item]
|
||||
|
|
|
@ -285,6 +285,7 @@ def home_real(request: HttpRequest) -> HttpResponse:
|
|||
'show_plans': show_plans,
|
||||
'is_admin': user_profile.is_realm_admin,
|
||||
'is_guest': user_profile.is_guest,
|
||||
'night_mode': user_profile.night_mode,
|
||||
'show_webathena': user_profile.realm.webathena_enabled,
|
||||
'enable_feedback': settings.ENABLE_FEEDBACK,
|
||||
'embedded': narrow_stream is not None,
|
||||
|
|
|
@ -2,7 +2,11 @@ from django.conf import settings
|
|||
from django.shortcuts import redirect
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.http import HttpResponse, HttpRequest
|
||||
from typing import Optional, Callable, Any
|
||||
|
||||
from zerver.lib.validator import check_string, check_int, check_list, check_dict, \
|
||||
check_bool, check_variable_type, check_capped_string, check_color
|
||||
from zerver.lib.request import REQ, has_request_variables
|
||||
from zerver.decorator import require_realm_admin
|
||||
from zerver.lib.actions import do_change_logo_source
|
||||
from zerver.lib.realm_logo import realm_logo_url
|
||||
|
@ -12,42 +16,54 @@ from zerver.models import Realm, UserProfile
|
|||
|
||||
|
||||
@require_realm_admin
|
||||
def upload_logo(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
|
||||
@has_request_variables
|
||||
def upload_logo(request: HttpRequest, user_profile: UserProfile,
|
||||
night: bool=REQ(validator=check_bool)) -> HttpResponse:
|
||||
if user_profile.realm.plan_type == Realm.LIMITED:
|
||||
return json_error(_("Feature unavailable on your current plan."))
|
||||
|
||||
if len(request.FILES) != 1:
|
||||
return json_error(_("You must upload exactly one logo."))
|
||||
|
||||
logo_file = list(request.FILES.values())[0]
|
||||
if ((settings.MAX_LOGO_FILE_SIZE * 1024 * 1024) < logo_file.size):
|
||||
return json_error(_("Uploaded file is larger than the allowed limit of %s MB") % (
|
||||
settings.MAX_LOGO_FILE_SIZE))
|
||||
upload_logo_image(logo_file, user_profile)
|
||||
do_change_logo_source(user_profile.realm, user_profile.realm.LOGO_UPLOADED)
|
||||
logo_url = realm_logo_url(user_profile.realm)
|
||||
|
||||
upload_logo_image(logo_file, user_profile, night)
|
||||
do_change_logo_source(user_profile.realm, user_profile.realm.LOGO_UPLOADED, night)
|
||||
logo_url = realm_logo_url(user_profile.realm, night)
|
||||
if night:
|
||||
json_result = dict(
|
||||
night_logo_url=logo_url
|
||||
)
|
||||
else:
|
||||
json_result = dict(
|
||||
logo_url=logo_url
|
||||
)
|
||||
return json_success(json_result)
|
||||
|
||||
|
||||
@require_realm_admin
|
||||
def delete_logo_backend(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
|
||||
@has_request_variables
|
||||
def delete_logo_backend(request: HttpRequest, user_profile: UserProfile,
|
||||
night: bool=REQ(validator=check_bool)) -> HttpResponse:
|
||||
# We don't actually delete the logo because it might still
|
||||
# be needed if the URL was cached and it is rewrited
|
||||
# in any case after next update.
|
||||
do_change_logo_source(user_profile.realm, user_profile.realm.LOGO_DEFAULT)
|
||||
default_url = realm_logo_url(user_profile.realm)
|
||||
do_change_logo_source(user_profile.realm, user_profile.realm.LOGO_DEFAULT, night)
|
||||
default_url = realm_logo_url(user_profile.realm, night)
|
||||
if night:
|
||||
json_result = dict(
|
||||
night_logo_url=default_url
|
||||
)
|
||||
else:
|
||||
json_result = dict(
|
||||
logo_url=default_url
|
||||
)
|
||||
return json_success(json_result)
|
||||
|
||||
|
||||
def get_logo_backend(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
|
||||
url = realm_logo_url(user_profile.realm)
|
||||
@has_request_variables
|
||||
def get_logo_backend(request: HttpRequest, user_profile: UserProfile,
|
||||
night: bool=REQ(validator=check_bool)) -> HttpResponse:
|
||||
url = realm_logo_url(user_profile.realm, night)
|
||||
|
||||
# We can rely on the url already having query parameters. Because
|
||||
# our templates depend on being able to use the ampersand to
|
||||
|
|
|
@ -98,7 +98,7 @@ v1_api_and_json_patterns = [
|
|||
'DELETE': 'zerver.views.realm_icon.delete_icon_backend',
|
||||
'GET': 'zerver.views.realm_icon.get_icon_backend'}),
|
||||
|
||||
# realm/logo -> zerver.views.realm_logo_
|
||||
# realm/logo -> zerver.views.realm_logo
|
||||
url(r'^realm/logo$', rest_dispatch,
|
||||
{'POST': 'zerver.views.realm_logo.upload_logo',
|
||||
'DELETE': 'zerver.views.realm_logo.delete_logo_backend',
|
||||
|
|
Loading…
Reference in New Issue