FEATURE: upload an avatar option for uploading avatars with selectable avatars (#15878)

* FEATURE: upload an avatar option for uploading avatars with selectable avatars

Allow staff or users at or above a trust level to upload avatars even when the site
has selectable avatars enabled.

Everyone can still pick from the list of avatars. The option to upload is shown
below the selectable avatar list.

refactored boolean site setting into an enum with the following values:

disabled: No selectable avatars enabled (default)
everyone: Show selectable avatars, and allow everyone to upload custom avatars
tl1: Show selectable avatars, but require tl1+ and staff to upload custom avatars
tl2: Show selectable avatars, but require tl2+ and staff to upload custom avatars
tl3: Show selectable avatars, but require tl3+ and staff to upload custom avatars
tl4: Show selectable avatars, but require tl4 and staff to upload custom avatars
staff: Show selectable avatars, but only allow staff to upload custom avatars
no_one: Show selectable avatars. No users can upload custom avatars

Co-authored-by: Régis Hanol <regis@hanol.fr>
This commit is contained in:
Jeff Wong
2022-02-24 10:57:39 -10:00
committed by GitHub
parent 00bb5f3a9d
commit d1bdb6c65d
13 changed files with 250 additions and 18 deletions

View File

@@ -17,15 +17,43 @@ export default Controller.extend(ModalFunctionality, {
},
@discourseComputed(
"siteSettings.selectable_avatars_enabled",
"siteSettings.selectable_avatars_mode",
"siteSettings.selectable_avatars"
)
selectableAvatars(enabled, list) {
if (enabled) {
selectableAvatars(mode, list) {
if (mode !== "disabled") {
return list ? list.split("|") : [];
}
},
@discourseComputed("siteSettings.selectable_avatars_mode")
showSelectableAvatars(mode) {
return mode !== "disabled";
},
@discourseComputed("siteSettings.selectable_avatars_mode")
showAvatarUploader(mode) {
switch (mode) {
case "no_one":
return false;
case "tl1":
case "tl2":
case "tl3":
case "tl4":
const allowedTl = parseInt(mode.replace("tl", ""), 10);
return (
this.user.admin ||
this.user.moderator ||
this.user.trust_level >= allowedTl
);
case "staff":
return this.user.admin || this.user.moderator;
case "everyone":
default:
return true;
}
},
@discourseComputed(
"user.use_logo_small_as_avatar",
"user.avatar_template",

View File

@@ -1,5 +1,5 @@
{{#d-modal-body title="user.change_avatar.title" class="avatar-selector"}}
{{#if siteSettings.selectable_avatars_enabled}}
{{#if showSelectableAvatars}}
<div class="selectable-avatars">
{{#each selectableAvatars as |avatar|}}
<a href class="selectable-avatar" {{action "selectAvatar" avatar}}>
@@ -7,7 +7,11 @@
</a>
{{/each}}
</div>
{{else}}
{{#if showAvatarUploader}}
<h4>{{html-safe (i18n "user.change_avatar.use_custom")}}</h4>
{{/if}}
{{/if}}
{{#if showAvatarUploader}}
{{#if user.use_logo_small_as_avatar}}
<div class="avatar-choice">
{{radio-button id="logo-small" name="logo" value="logo" selection=selected}}
@@ -55,9 +59,9 @@
{{/if}}
{{/d-modal-body}}
{{#unless siteSettings.selectable_avatars_enabled}}
{{#if showAvatarUploader}}
<div class="modal-footer">
{{d-button action=(action "saveAvatarSelection") class="btn-primary" disabled=submitDisabled label="save"}}
{{d-modal-cancel close=(route-action "closeModal")}}
</div>
{{/unless}}
{{/if}}

View File

@@ -299,7 +299,7 @@ acceptance(
"Avatar selector when selectable avatars is enabled",
function (needs) {
needs.user();
needs.settings({ selectable_avatars_enabled: true });
needs.settings({ selectable_avatars_mode: "no_one" });
needs.pretender((server, helper) => {
server.get("/site/selectable-avatars.json", () =>
helper.response([
@@ -315,6 +315,134 @@ acceptance(
assert.ok(
exists(".selectable-avatars", "opens the avatar selection modal")
);
assert.notOk(
exists(
"#uploaded-avatar",
"avatar selection modal does not include option to upload"
)
);
});
}
);
acceptance(
"Avatar selector when selectable avatars allows staff to upload",
function (needs) {
needs.user();
needs.settings({ selectable_avatars_mode: "staff" });
needs.pretender((server, helper) => {
server.get("/site/selectable-avatars.json", () =>
helper.response([
"https://www.discourse.org",
"https://meta.discourse.org",
])
);
});
test("allows staff to upload", async function (assert) {
await updateCurrentUser({
trust_level: 3,
moderator: true,
admin: false,
});
await visit("/u/eviltrout/preferences");
await click(".pref-avatar .btn");
assert.ok(
exists(".selectable-avatars", "opens the avatar selection modal")
);
assert.ok(
exists(
"#uploaded-avatar",
"avatar selection modal includes option to upload"
)
);
});
test("disallow nonstaff", async function (assert) {
await visit("/u/eviltrout/preferences");
await updateCurrentUser({
trust_level: 3,
moderator: false,
admin: false,
});
await click(".pref-avatar .btn");
assert.ok(
exists(".selectable-avatars", "opens the avatar selection modal")
);
assert.notOk(
exists(
"#uploaded-avatar",
"avatar selection modal does not include option to upload"
)
);
});
}
);
acceptance(
"Avatar selector when selectable avatars allows trust level 3+ to upload",
function (needs) {
needs.user();
needs.settings({ selectable_avatars_mode: "tl3" });
needs.pretender((server, helper) => {
server.get("/site/selectable-avatars.json", () =>
helper.response([
"https://www.discourse.org",
"https://meta.discourse.org",
])
);
});
test("with a tl3 user", async function (assert) {
await visit("/u/eviltrout/preferences");
await updateCurrentUser({
trust_level: 3,
moderator: false,
admin: false,
});
await click(".pref-avatar .btn");
assert.ok(
exists(".selectable-avatars", "opens the avatar selection modal")
);
assert.ok(
exists(
"#uploaded-avatar",
"avatar selection modal does includes option to upload"
)
);
});
test("with a tl2 user", async function (assert) {
await visit("/u/eviltrout/preferences");
await updateCurrentUser({
trust_level: 2,
moderator: false,
admin: false,
});
await click(".pref-avatar .btn");
assert.ok(
exists(".selectable-avatars", "opens the avatar selection modal")
);
assert.notOk(
exists(
"#uploaded-avatar",
"avatar selection modal does not include option to upload"
)
);
});
test("always allow staff to upload", async function (assert) {
await visit("/u/eviltrout/preferences");
await updateCurrentUser({
trust_level: 2,
moderator: true,
admin: false,
});
await click(".pref-avatar .btn");
assert.ok(
exists(".selectable-avatars", "opens the avatar selection modal")
);
assert.ok(
exists(
"#uploaded-avatar",
"avatar selection modal includes option to upload"
)
);
});
}
);