mirror of
https://github.com/zulip/zulip.git
synced 2025-11-06 23:13:25 +00:00
uploads: Show used upload space in attachments UI.
This commit is contained in:
@@ -1410,6 +1410,24 @@ run_test('typing_notifications', () => {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
run_test('upload_space_stats', () => {
|
||||||
|
var args = {
|
||||||
|
show_upgrade_message: true,
|
||||||
|
percent_used: 50,
|
||||||
|
upload_quota: "1 GB",
|
||||||
|
};
|
||||||
|
var html = render('upload-space-stats', args);
|
||||||
|
assert.equal($(html).text().trim(), "translated: Organization using 50% of 1 GB.\n translated: Upgrade for more space.");
|
||||||
|
|
||||||
|
args = {
|
||||||
|
show_upgrade_message: false,
|
||||||
|
percent_used: 10,
|
||||||
|
upload_quota: "5 GB",
|
||||||
|
};
|
||||||
|
html = render('upload-space-stats', args);
|
||||||
|
assert.equal($(html).text().trim(), "translated: Organization using 10% of 5 GB.");
|
||||||
|
});
|
||||||
|
|
||||||
run_test('user_group_info_popover', () => {
|
run_test('user_group_info_popover', () => {
|
||||||
var html = render('user_group_info_popover');
|
var html = render('user_group_info_popover');
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ var attachments_ui = (function () {
|
|||||||
var exports = {};
|
var exports = {};
|
||||||
|
|
||||||
var attachments;
|
var attachments;
|
||||||
|
var upload_space_used;
|
||||||
|
|
||||||
exports.bytes_to_size = function (bytes, kb_with_1024_bytes) {
|
exports.bytes_to_size = function (bytes, kb_with_1024_bytes) {
|
||||||
if (kb_with_1024_bytes === undefined) {
|
if (kb_with_1024_bytes === undefined) {
|
||||||
@@ -21,6 +22,26 @@ exports.bytes_to_size = function (bytes, kb_with_1024_bytes) {
|
|||||||
return size + ' ' + sizes[i];
|
return size + ' ' + sizes[i];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.percentage_used_space = function (uploads_size) {
|
||||||
|
if (page_params.realm_upload_quota === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (100 * uploads_size / page_params.realm_upload_quota).toFixed(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
function set_upload_space_stats() {
|
||||||
|
if (page_params.realm_upload_quota === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var args = {
|
||||||
|
show_upgrade_message: page_params.realm_plan_type === 2,
|
||||||
|
percent_used: exports.percentage_used_space(upload_space_used),
|
||||||
|
upload_quota: attachments_ui.bytes_to_size(page_params.realm_upload_quota, true),
|
||||||
|
};
|
||||||
|
var rendered_upload_stats_html = templates.render("upload-space-stats", args);
|
||||||
|
$("#attachment-stats-holder").html(rendered_upload_stats_html);
|
||||||
|
}
|
||||||
|
|
||||||
function delete_attachments(attachment) {
|
function delete_attachments(attachment) {
|
||||||
var status = $('#delete-upload-status');
|
var status = $('#delete-upload-status');
|
||||||
channel.del({
|
channel.del({
|
||||||
@@ -36,6 +57,8 @@ function delete_attachments(attachment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function render_attachments_ui() {
|
function render_attachments_ui() {
|
||||||
|
set_upload_space_stats();
|
||||||
|
|
||||||
var uploaded_files_table = $("#uploaded_files_table").expectOne();
|
var uploaded_files_table = $("#uploaded_files_table").expectOne();
|
||||||
var $search_input = $("#upload_file_search");
|
var $search_input = $("#upload_file_search");
|
||||||
|
|
||||||
@@ -99,7 +122,7 @@ exports.update_attachments = function (event) {
|
|||||||
format_attachment_data([event.attachment]);
|
format_attachment_data([event.attachment]);
|
||||||
attachments.push(event.attachment);
|
attachments.push(event.attachment);
|
||||||
}
|
}
|
||||||
|
upload_space_used = event.upload_space_used;
|
||||||
// TODO: This is inefficient and we should be able to do some sort
|
// TODO: This is inefficient and we should be able to do some sort
|
||||||
// of incremental list_render update instead.
|
// of incremental list_render update instead.
|
||||||
render_attachments_ui();
|
render_attachments_ui();
|
||||||
@@ -125,6 +148,7 @@ exports.set_up_attachments = function () {
|
|||||||
loading.destroy_indicator($('#attachments_loading_indicator'));
|
loading.destroy_indicator($('#attachments_loading_indicator'));
|
||||||
format_attachment_data(data.attachments);
|
format_attachment_data(data.attachments);
|
||||||
attachments = data.attachments;
|
attachments = data.attachments;
|
||||||
|
upload_space_used = data.upload_space_used;
|
||||||
render_attachments_ui();
|
render_attachments_ui();
|
||||||
},
|
},
|
||||||
error: function (xhr) {
|
error: function (xhr) {
|
||||||
|
|||||||
@@ -1911,3 +1911,9 @@ thead .actions {
|
|||||||
#get_api_key_button {
|
#get_api_key_button {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#attachment-stats-holder {
|
||||||
|
position: relative;
|
||||||
|
margin-top: 13px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<div id="attachments-settings" class="settings-section" data-name="uploaded-files">
|
<div id="attachments-settings" class="settings-section" data-name="uploaded-files">
|
||||||
|
<div id="attachment-stats-holder"></div>
|
||||||
<input id="upload_file_search" class="search" type="text" placeholder="{{t 'Search uploads...' }}" aria-label="{{t 'Search uploads...' }}"/>
|
<input id="upload_file_search" class="search" type="text" placeholder="{{t 'Search uploads...' }}" aria-label="{{t 'Search uploads...' }}"/>
|
||||||
<div class="clear-float"></div>
|
<div class="clear-float"></div>
|
||||||
<div class="alert" id="delete-upload-status"></div>
|
<div class="alert" id="delete-upload-status"></div>
|
||||||
|
|||||||
4
static/templates/settings/upload-space-stats.handlebars
Normal file
4
static/templates/settings/upload-space-stats.handlebars
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<span>
|
||||||
|
{{#tr this}}Organization using __percent_used__% of __upload_quota__.{{/tr}}
|
||||||
|
{{#if show_upgrade_message}}{{#tr this}}<a href="/upgrade" target="_blank">Upgrade</a> for more space.{{/tr}}{{/if}}
|
||||||
|
</span>
|
||||||
@@ -5221,6 +5221,7 @@ def notify_attachment_update(user_profile: UserProfile, op: str,
|
|||||||
'type': 'attachment',
|
'type': 'attachment',
|
||||||
'op': op,
|
'op': op,
|
||||||
'attachment': attachment_dict,
|
'attachment': attachment_dict,
|
||||||
|
"upload_space_used": user_profile.realm.currently_used_upload_space_bytes(),
|
||||||
}
|
}
|
||||||
send_event(user_profile.realm, event, [user_profile.id])
|
send_event(user_profile.realm, event, [user_profile.id])
|
||||||
|
|
||||||
|
|||||||
@@ -2525,6 +2525,7 @@ class EventsRegisterTest(ZulipTestCase):
|
|||||||
('name', check_float),
|
('name', check_float),
|
||||||
]))),
|
]))),
|
||||||
])),
|
])),
|
||||||
|
('upload_space_used', equals(6)),
|
||||||
])
|
])
|
||||||
|
|
||||||
self.login(self.example_email("hamlet"))
|
self.login(self.example_email("hamlet"))
|
||||||
@@ -2567,6 +2568,7 @@ class EventsRegisterTest(ZulipTestCase):
|
|||||||
('name', check_float),
|
('name', check_float),
|
||||||
]))),
|
]))),
|
||||||
])),
|
])),
|
||||||
|
('upload_space_used', equals(6)),
|
||||||
])
|
])
|
||||||
|
|
||||||
self.subscribe(self.example_user("hamlet"), "Denmark")
|
self.subscribe(self.example_user("hamlet"), "Denmark")
|
||||||
@@ -2584,6 +2586,7 @@ class EventsRegisterTest(ZulipTestCase):
|
|||||||
('attachment', check_dict_only([
|
('attachment', check_dict_only([
|
||||||
('id', check_int),
|
('id', check_int),
|
||||||
])),
|
])),
|
||||||
|
('upload_space_used', equals(0)),
|
||||||
])
|
])
|
||||||
|
|
||||||
events = self.do_test(
|
events = self.do_test(
|
||||||
|
|||||||
@@ -1762,15 +1762,15 @@ class UploadSpaceTests(UploadSerializeMixin, ZulipTestCase):
|
|||||||
|
|
||||||
data = b'zulip!'
|
data = b'zulip!'
|
||||||
upload_message_file(u'dummy.txt', len(data), u'text/plain', data, self.user_profile)
|
upload_message_file(u'dummy.txt', len(data), u'text/plain', data, self.user_profile)
|
||||||
self.assertEqual(None, cache_get(get_realm_used_upload_space_cache_key(self.realm)))
|
# notify_attachment_update function calls currently_used_upload_space_bytes which
|
||||||
self.assertEqual(len(data), self.realm.currently_used_upload_space_bytes())
|
# updates the cache.
|
||||||
self.assertEqual(len(data), cache_get(get_realm_used_upload_space_cache_key(self.realm))[0])
|
self.assertEqual(len(data), cache_get(get_realm_used_upload_space_cache_key(self.realm))[0])
|
||||||
|
self.assertEqual(len(data), self.realm.currently_used_upload_space_bytes())
|
||||||
|
|
||||||
data2 = b'more-data!'
|
data2 = b'more-data!'
|
||||||
upload_message_file(u'dummy2.txt', len(data2), u'text/plain', data2, self.user_profile)
|
upload_message_file(u'dummy2.txt', len(data2), u'text/plain', data2, self.user_profile)
|
||||||
self.assertEqual(None, cache_get(get_realm_used_upload_space_cache_key(self.realm)))
|
|
||||||
self.assertEqual(len(data) + len(data2), self.realm.currently_used_upload_space_bytes())
|
|
||||||
self.assertEqual(len(data) + len(data2), cache_get(get_realm_used_upload_space_cache_key(self.realm))[0])
|
self.assertEqual(len(data) + len(data2), cache_get(get_realm_used_upload_space_cache_key(self.realm))[0])
|
||||||
|
self.assertEqual(len(data) + len(data2), self.realm.currently_used_upload_space_bytes())
|
||||||
|
|
||||||
attachment = Attachment.objects.get(file_name="dummy.txt")
|
attachment = Attachment.objects.get(file_name="dummy.txt")
|
||||||
attachment.file_name = "dummy1.txt"
|
attachment.file_name = "dummy1.txt"
|
||||||
@@ -1781,17 +1781,6 @@ class UploadSpaceTests(UploadSerializeMixin, ZulipTestCase):
|
|||||||
attachment.delete()
|
attachment.delete()
|
||||||
self.assertEqual(None, cache_get(get_realm_used_upload_space_cache_key(self.realm)))
|
self.assertEqual(None, cache_get(get_realm_used_upload_space_cache_key(self.realm)))
|
||||||
self.assertEqual(len(data2), self.realm.currently_used_upload_space_bytes())
|
self.assertEqual(len(data2), self.realm.currently_used_upload_space_bytes())
|
||||||
self.assertEqual(len(data2), cache_get(get_realm_used_upload_space_cache_key(self.realm))[0])
|
|
||||||
|
|
||||||
def test_upload_space_used_api(self) -> None:
|
|
||||||
self.login(self.user_profile.email)
|
|
||||||
response = self.client_get("/json/realm/upload_space_used")
|
|
||||||
self.assert_in_success_response(["0"], response)
|
|
||||||
|
|
||||||
data = b'zulip!'
|
|
||||||
upload_message_file(u'dummy.txt', len(data), u'text/plain', data, self.user_profile)
|
|
||||||
response = self.client_get("/json/realm/upload_space_used")
|
|
||||||
self.assert_in_success_response([str(len(data))], response)
|
|
||||||
|
|
||||||
class ExifRotateTests(TestCase):
|
class ExifRotateTests(TestCase):
|
||||||
def test_image_do_not_rotate(self) -> None:
|
def test_image_do_not_rotate(self) -> None:
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ from zerver.lib.attachments import user_attachments, remove_attachment, \
|
|||||||
|
|
||||||
|
|
||||||
def list_by_user(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
|
def list_by_user(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
|
||||||
return json_success({"attachments": user_attachments(user_profile)})
|
return json_success({
|
||||||
|
"attachments": user_attachments(user_profile),
|
||||||
|
"upload_space_used": user_profile.realm.currently_used_upload_space_bytes(),
|
||||||
|
})
|
||||||
|
|
||||||
def remove(request: HttpRequest, user_profile: UserProfile, attachment_id: str) -> HttpResponse:
|
def remove(request: HttpRequest, user_profile: UserProfile, attachment_id: str) -> HttpResponse:
|
||||||
attachment = access_attachment_by_id(user_profile, int(attachment_id),
|
attachment = access_attachment_by_id(user_profile, int(attachment_id),
|
||||||
@@ -17,6 +19,3 @@ def remove(request: HttpRequest, user_profile: UserProfile, attachment_id: str)
|
|||||||
remove_attachment(user_profile, attachment)
|
remove_attachment(user_profile, attachment)
|
||||||
notify_attachment_update(user_profile, "remove", {"id": int(attachment_id)})
|
notify_attachment_update(user_profile, "remove", {"id": int(attachment_id)})
|
||||||
return json_success()
|
return json_success()
|
||||||
|
|
||||||
def upload_space_used(request: HttpRequest, user_profile: UserProfile) -> HttpResponse:
|
|
||||||
return json_success({"upload_space_used": user_profile.realm.currently_used_upload_space_bytes()})
|
|
||||||
|
|||||||
@@ -127,9 +127,6 @@ v1_api_and_json_patterns = [
|
|||||||
url(r'^realm/presence$', rest_dispatch,
|
url(r'^realm/presence$', rest_dispatch,
|
||||||
{'GET': 'zerver.views.presence.get_statuses_for_realm'}),
|
{'GET': 'zerver.views.presence.get_statuses_for_realm'}),
|
||||||
|
|
||||||
url(r'^realm/upload_space_used$', rest_dispatch,
|
|
||||||
{'GET': 'zerver.views.attachments.upload_space_used'}),
|
|
||||||
|
|
||||||
# users -> zerver.views.users
|
# users -> zerver.views.users
|
||||||
#
|
#
|
||||||
# Since some of these endpoints do something different if used on
|
# Since some of these endpoints do something different if used on
|
||||||
|
|||||||
Reference in New Issue
Block a user