DEV: Modernize admin emoji JavaScript (#29714)
app/assets/javascripts/admin/addon/templates/emojis.hbs
This commit is contained in:
parent
01a160d8af
commit
d96b8d1001
|
@ -0,0 +1,98 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { fn } from "@ember/helper";
|
||||
import { service } from "@ember/service";
|
||||
import DButton from "discourse/components/d-button";
|
||||
import i18n from "discourse-common/helpers/i18n";
|
||||
import AdminConfigAreaEmptyList from "admin/components/admin-config-area-empty-list";
|
||||
import ComboBox from "select-kit/components/combo-box";
|
||||
|
||||
export default class AdminConfigAreasEmojisList extends Component {
|
||||
@service dialog;
|
||||
@service adminEmojis;
|
||||
|
||||
get emojis() {
|
||||
return this.adminEmojis.emojis;
|
||||
}
|
||||
|
||||
get sortedEmojis() {
|
||||
return this.adminEmojis.sortedEmojis;
|
||||
}
|
||||
|
||||
get filteringGroups() {
|
||||
return this.adminEmojis.filteringGroups;
|
||||
}
|
||||
|
||||
<template>
|
||||
<div class="form-horizontal">
|
||||
<div class="inline-form">
|
||||
<ComboBox
|
||||
@value={{this.adminEmojis.filter}}
|
||||
@content={{this.filteringGroups}}
|
||||
@nameProperty={{null}}
|
||||
@valueProperty={{null}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if this.emojis}}
|
||||
<table id="custom_emoji" class="d-admin-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{i18n "admin.emoji.image"}}</th>
|
||||
<th>{{i18n "admin.emoji.name"}}</th>
|
||||
<th>{{i18n "admin.emoji.group"}}</th>
|
||||
<th colspan="3">{{i18n "admin.emoji.created_by"}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{{#if this.sortedEmojis}}
|
||||
<tbody>
|
||||
{{#each this.sortedEmojis as |emoji|}}
|
||||
<tr class="d-admin-row__content">
|
||||
<td class="d-admin-row__overview">
|
||||
<img
|
||||
class="emoji emoji-custom"
|
||||
src={{emoji.url}}
|
||||
title={{emoji.name}}
|
||||
alt={{i18n "admin.emoji.alt"}}
|
||||
/>
|
||||
</td>
|
||||
<td class="d-admin-row__detail">
|
||||
<div class="d-admin-row__mobile-label">
|
||||
{{i18n "admin.emoji.name"}}
|
||||
</div>
|
||||
:{{emoji.name}}:
|
||||
</td>
|
||||
<td class="d-admin-row__detail">
|
||||
<div class="d-admin-row__mobile-label">
|
||||
{{i18n "admin.emoji.group"}}
|
||||
</div>
|
||||
{{emoji.group}}
|
||||
</td>
|
||||
<td class="d-admin-row__detail">
|
||||
<div class="d-admin-row__mobile-label">
|
||||
{{i18n "admin.emoji.created_by"}}
|
||||
</div>
|
||||
{{emoji.created_by}}
|
||||
</td>
|
||||
<td class="d-admin-row__controls action">
|
||||
<DButton
|
||||
@action={{fn this.adminEmojis.destroyEmoji emoji}}
|
||||
@icon="trash-can"
|
||||
class="btn-small"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
{{/if}}
|
||||
</table>
|
||||
{{else}}
|
||||
<AdminConfigAreaEmptyList
|
||||
@ctaLabel="admin.emoji.add"
|
||||
@ctaRoute="adminEmojis.new"
|
||||
@ctaClass="admin-emojis__add-emoji"
|
||||
@emptyLabel="admin.emoji.no_emoji"
|
||||
/>
|
||||
{{/if}}
|
||||
</template>
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
import Component from "@glimmer/component";
|
||||
import EmberObject, { action } from "@ember/object";
|
||||
import { service } from "@ember/service";
|
||||
import BackButton from "discourse/components/back-button";
|
||||
import AdminConfigAreaCard from "admin/components/admin-config-area-card";
|
||||
import EmojiUploader from "admin/components/emoji-uploader";
|
||||
|
||||
export default class AdminConfigAreasEmojisNew extends Component {
|
||||
@service router;
|
||||
@service currentUser;
|
||||
@service adminEmojis;
|
||||
|
||||
get emojiGroups() {
|
||||
return this.adminEmojis.emojiGroups;
|
||||
}
|
||||
|
||||
@action
|
||||
emojiUploaded(emoji, group) {
|
||||
emoji.url += "?t=" + new Date().getTime();
|
||||
emoji.group = group;
|
||||
emoji.created_by = this.currentUser.username;
|
||||
this.adminEmojis.emojis = [
|
||||
...this.adminEmojis.emojis,
|
||||
EmberObject.create(emoji),
|
||||
];
|
||||
this.router.transitionTo("adminEmojis.index");
|
||||
}
|
||||
|
||||
<template>
|
||||
<BackButton @route="adminEmojis.index" @label="admin.emoji.back" />
|
||||
<div class="admin-config-area">
|
||||
<div class="admin-config-area__primary-content admin-emojis-form">
|
||||
<AdminConfigAreaCard @heading="admin.emoji.add">
|
||||
<:content>
|
||||
<EmojiUploader
|
||||
@emojiGroups={{this.emojiGroups}}
|
||||
@done={{this.emojiUploaded}}
|
||||
/>
|
||||
</:content>
|
||||
</AdminConfigAreaCard>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
|
||||
import { service } from "@ember/service";
|
||||
import DBreadcrumbsItem from "discourse/components/d-breadcrumbs-item";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import i18n from "discourse-common/helpers/i18n";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
import AdminFilteredSiteSettings from "admin/components/admin-filtered-site-settings";
|
||||
import SiteSetting from "admin/models/site-setting";
|
||||
|
||||
export default class AdminConfigAreasEmojisSettings extends Component {
|
||||
@service siteSettings;
|
||||
@tracked settings;
|
||||
|
||||
@bind
|
||||
loadSettings() {
|
||||
ajax("/admin/config/site_settings.json", {
|
||||
data: {
|
||||
filter_area: "emojis",
|
||||
},
|
||||
}).then((result) => {
|
||||
this.settings = [
|
||||
{
|
||||
name: "All",
|
||||
nameKey: "all_results",
|
||||
siteSettings: result.site_settings.map((setting) =>
|
||||
SiteSetting.create(setting)
|
||||
),
|
||||
},
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
<template>
|
||||
<DBreadcrumbsItem
|
||||
@path="/admin/config/emojis/settings"
|
||||
@label={{i18n "settings"}}
|
||||
/>
|
||||
|
||||
<div
|
||||
class="content-body admin-config-area__settings admin-detail pull-left"
|
||||
{{didInsert this.loadSettings}}
|
||||
>
|
||||
{{#if this.settings}}
|
||||
<AdminFilteredSiteSettings
|
||||
@initialFilter={{@initialFilter}}
|
||||
@onFilterChanged={{@onFilterChanged}}
|
||||
@settings={{this.settings}}
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
}
|
|
@ -1,33 +1,39 @@
|
|||
<div class="emoji-uploader form-horizontal">
|
||||
<div class="control-group">
|
||||
<span class="label">
|
||||
<div class="form-kit">
|
||||
<div class="form-kit__container form-kit__field form-kit__field-input-text">
|
||||
<label class="form-kit__container-title">
|
||||
{{i18n "admin.emoji.name"}}
|
||||
</span>
|
||||
<div class="input">
|
||||
<Input
|
||||
id="emoji-name"
|
||||
name="name"
|
||||
placeholder={{i18n "admin.emoji.name"}}
|
||||
@value={{readonly this.name}}
|
||||
{{on "input" (with-event-value (fn (mut this.name)))}}
|
||||
/>
|
||||
</label>
|
||||
<div class="form-kit__container-content --large">
|
||||
<div class="form-kit__control-input-wrapper">
|
||||
<Input
|
||||
id="emoji-name"
|
||||
class="form-kit__control-input"
|
||||
name="name"
|
||||
@value={{readonly this.name}}
|
||||
{{on "input" (with-event-value (fn (mut this.name)))}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<span class="label">
|
||||
<div
|
||||
class="form-kit__container form-kit__field form-kit__field-input-combo-box"
|
||||
>
|
||||
<label class="form-kit__container-title">
|
||||
{{i18n "admin.emoji.group"}}
|
||||
</span>
|
||||
<div class="input">
|
||||
<ComboBox
|
||||
@name="group"
|
||||
@id="emoji-group-selector"
|
||||
@value={{this.group}}
|
||||
@content={{this.newEmojiGroups}}
|
||||
@onChange={{action "createEmojiGroup"}}
|
||||
@valueProperty={{null}}
|
||||
@nameProperty={{null}}
|
||||
@options={{hash allowAny=true}}
|
||||
/>
|
||||
</label>
|
||||
<div class="form-kit__container-content --large">
|
||||
<div class="form-kit__control-input-wrapper">
|
||||
<ComboBox
|
||||
@name="group"
|
||||
@id="emoji-group-selector"
|
||||
@value={{this.group}}
|
||||
@content={{this.newEmojiGroups}}
|
||||
@onChange={{action "createEmojiGroup"}}
|
||||
@valueProperty={{null}}
|
||||
@nameProperty={{null}}
|
||||
@options={{hash allowAny=true}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
|
@ -44,7 +50,7 @@
|
|||
@translatedLabel={{this.buttonLabel}}
|
||||
@action={{this.chooseFiles}}
|
||||
@disabled={{this.uppyUpload.uploading}}
|
||||
class="btn-default"
|
||||
class="btn-primary"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -76,7 +76,7 @@ export default class EmojiUploader extends Component {
|
|||
if (uploading) {
|
||||
return `${I18n.t("admin.emoji.uploading")} ${uploadProgress}%`;
|
||||
} else {
|
||||
return I18n.t("admin.emoji.add");
|
||||
return I18n.t("admin.emoji.choose_files");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
import Controller from "@ember/controller";
|
||||
import { action, computed } from "@ember/object";
|
||||
import { sort } from "@ember/object/computed";
|
||||
import { service } from "@ember/service";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
const ALL_FILTER = "all";
|
||||
|
||||
export default class AdminEmojisIndexController extends Controller {
|
||||
@service dialog;
|
||||
|
||||
filter = null;
|
||||
sorting = null;
|
||||
|
||||
@sort("filteredEmojis.[]", "sorting") sortedEmojis;
|
||||
|
||||
init() {
|
||||
super.init(...arguments);
|
||||
|
||||
this.setProperties({
|
||||
filter: ALL_FILTER,
|
||||
sorting: ["group", "name"],
|
||||
});
|
||||
}
|
||||
|
||||
@computed("model.[]", "filter")
|
||||
get filteredEmojis() {
|
||||
if (!this.filter || this.filter === ALL_FILTER) {
|
||||
return this.model;
|
||||
} else {
|
||||
return this.model.filterBy("group", this.filter);
|
||||
}
|
||||
}
|
||||
|
||||
@computed("model.[]")
|
||||
get emojiGroups() {
|
||||
return this.model.mapBy("group").uniq();
|
||||
}
|
||||
|
||||
@computed("emojiGroups.[]")
|
||||
get sortingGroups() {
|
||||
return [ALL_FILTER].concat(this.emojiGroups);
|
||||
}
|
||||
|
||||
@action
|
||||
filterGroups(value) {
|
||||
this.set("filter", value);
|
||||
}
|
||||
|
||||
@action
|
||||
destroyEmoji(emoji) {
|
||||
this.dialog.yesNoConfirm({
|
||||
message: I18n.t("admin.emoji.delete_confirm", {
|
||||
name: emoji.get("name"),
|
||||
}),
|
||||
didConfirm: () => this.#destroyEmoji(emoji),
|
||||
});
|
||||
}
|
||||
|
||||
async #destroyEmoji(emoji) {
|
||||
try {
|
||||
await ajax("/admin/customize/emojis/" + emoji.get("name"), {
|
||||
type: "DELETE",
|
||||
});
|
||||
this.model.removeObject(emoji);
|
||||
} catch (err) {
|
||||
popupAjaxError(err);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
import Controller from "@ember/controller";
|
||||
import EmberObject, { action, computed } from "@ember/object";
|
||||
import { service } from "@ember/service";
|
||||
|
||||
const ALL_FILTER = "all";
|
||||
|
||||
export default class AdminEmojisNewController extends Controller {
|
||||
@service router;
|
||||
@service currentUser;
|
||||
|
||||
@computed("model")
|
||||
get emojiGroups() {
|
||||
return this.model.mapBy("group").uniq();
|
||||
}
|
||||
|
||||
@computed("emojiGroups.[]")
|
||||
get sortingGroups() {
|
||||
return [ALL_FILTER].concat(this.emojiGroups);
|
||||
}
|
||||
|
||||
@action
|
||||
emojiUploaded(emoji, group) {
|
||||
emoji.url += "?t=" + new Date().getTime();
|
||||
emoji.group = group;
|
||||
emoji.created_by = this.currentUser.username;
|
||||
this.model.pushObject(EmberObject.create(emoji));
|
||||
this.router.transitionTo("adminEmojis.index");
|
||||
}
|
||||
}
|
|
@ -3,9 +3,10 @@ import { action } from "@ember/object";
|
|||
|
||||
export default class AdminEmojisSettingsController extends Controller {
|
||||
filter = "";
|
||||
queryParams = ["filter"];
|
||||
|
||||
@action
|
||||
filterChanged(filterData) {
|
||||
filterChangedCallback(filterData) {
|
||||
this.set("filter", filterData.filter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
import Controller from "@ember/controller";
|
||||
import { service } from "@ember/service";
|
||||
|
||||
export default class AdminEmojisController extends Controller {}
|
||||
export default class AdminEmojisController extends Controller {
|
||||
@service router;
|
||||
|
||||
get hideTabs() {
|
||||
return ["adminEmojis.new"].includes(this.router.currentRouteName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
import I18n from "discourse-i18n";
|
||||
import SiteSetting from "admin/models/site-setting";
|
||||
|
||||
export default class AdminEmojisSettingsRoute extends DiscourseRoute {
|
||||
queryParams = {
|
||||
|
@ -10,11 +9,4 @@ export default class AdminEmojisSettingsRoute extends DiscourseRoute {
|
|||
titleToken() {
|
||||
return I18n.t("settings");
|
||||
}
|
||||
|
||||
async model() {
|
||||
return {
|
||||
settings: await SiteSetting.findAll(),
|
||||
initialFilter: "emoji",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import EmberObject from "@ember/object";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
|
@ -7,9 +5,4 @@ export default class AdminEmojisRoute extends DiscourseRoute {
|
|||
titleToken() {
|
||||
return I18n.t("admin.emoji.title");
|
||||
}
|
||||
|
||||
async model() {
|
||||
const emojis = await ajax("/admin/customize/emojis.json");
|
||||
return emojis.map((emoji) => EmberObject.create(emoji));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
import { tracked } from "@glimmer/tracking";
|
||||
import EmberObject, { action } from "@ember/object";
|
||||
import Service, { service } from "@ember/service";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
const ALL_FILTER = "all";
|
||||
const DEFAULT_GROUP = "default";
|
||||
|
||||
export default class AdminEmojis extends Service {
|
||||
@service dialog;
|
||||
|
||||
@tracked emojis = [];
|
||||
|
||||
@tracked filter = ALL_FILTER;
|
||||
@tracked sorting = ["group", "name"];
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
this.#fetchEmojis();
|
||||
}
|
||||
|
||||
get filteredEmojis() {
|
||||
if (!this.filter || this.filter === ALL_FILTER) {
|
||||
return this.emojis;
|
||||
} else {
|
||||
return this.emojis.filter((e) => e.group === this.filter);
|
||||
}
|
||||
}
|
||||
|
||||
get sortedEmojis() {
|
||||
return this.filteredEmojis.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
|
||||
get emojiGroups() {
|
||||
return [DEFAULT_GROUP].concat(this.emojis.map((e) => e.group)).uniq();
|
||||
}
|
||||
|
||||
get filteringGroups() {
|
||||
return [ALL_FILTER].concat(this.emojiGroups);
|
||||
}
|
||||
|
||||
async #fetchEmojis() {
|
||||
try {
|
||||
const data = await ajax("/admin/customize/emojis.json");
|
||||
this.emojis = data.map((emoji) => EmberObject.create(emoji));
|
||||
} catch (err) {
|
||||
popupAjaxError(err);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
destroyEmoji(emoji) {
|
||||
this.dialog.yesNoConfirm({
|
||||
message: I18n.t("admin.emoji.delete_confirm", {
|
||||
name: emoji.get("name"),
|
||||
}),
|
||||
didConfirm: () => this.#destroyEmoji(emoji),
|
||||
});
|
||||
}
|
||||
|
||||
async #destroyEmoji(emoji) {
|
||||
try {
|
||||
await ajax("/admin/customize/emojis/" + emoji.get("name"), {
|
||||
type: "DELETE",
|
||||
});
|
||||
this.emojis.removeObject(emoji);
|
||||
} catch (err) {
|
||||
popupAjaxError(err);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +1 @@
|
|||
<div class="form-horizontal">
|
||||
<div class="inline-form">
|
||||
<ComboBox
|
||||
@value={{this.filter}}
|
||||
@content={{this.sortingGroups}}
|
||||
@nameProperty={{null}}
|
||||
@valueProperty={{null}}
|
||||
@onChange={{action "filterGroups"}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if this.sortedEmojis}}
|
||||
<table id="custom_emoji" class="d-admin-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{i18n "admin.emoji.image"}}</th>
|
||||
<th>{{i18n "admin.emoji.name"}}</th>
|
||||
<th>{{i18n "admin.emoji.group"}}</th>
|
||||
<th colspan="3">{{i18n "admin.emoji.created_by"}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each this.sortedEmojis as |emoji|}}
|
||||
<tr class="d-admin-row__content">
|
||||
<td class="d-admin-row__overview">
|
||||
<img
|
||||
class="emoji emoji-custom"
|
||||
src={{emoji.url}}
|
||||
title={{emoji.name}}
|
||||
alt={{i18n "admin.emoji.alt"}}
|
||||
/>
|
||||
</td>
|
||||
<td class="d-admin-row__detail">
|
||||
<div class="d-admin-row__mobile-label">
|
||||
{{i18n "admin.emoji.name"}}
|
||||
</div>
|
||||
:{{emoji.name}}:
|
||||
</td>
|
||||
<td class="d-admin-row__detail">
|
||||
<div class="d-admin-row__mobile-label">
|
||||
{{i18n "admin.emoji.group"}}
|
||||
</div>
|
||||
{{emoji.group}}
|
||||
</td>
|
||||
<td class="d-admin-row__detail">
|
||||
<div class="d-admin-row__mobile-label">
|
||||
{{i18n "admin.emoji.created_by"}}
|
||||
</div>
|
||||
{{emoji.created_by}}
|
||||
</td>
|
||||
<td class="d-admin-row__controls action">
|
||||
<DButton
|
||||
@action={{fn this.destroyEmoji emoji}}
|
||||
@icon="trash-can"
|
||||
class="btn-small"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{/if}}
|
||||
<AdminConfigAreas::EmojisList />
|
|
@ -1,4 +1 @@
|
|||
<EmojiUploader
|
||||
@emojiGroups={{this.emojiGroups}}
|
||||
@done={{action "emojiUploaded"}}
|
||||
/>
|
||||
<AdminConfigAreas::EmojisNew />
|
|
@ -1,9 +1,4 @@
|
|||
<DBreadcrumbsItem @path="/admin/emojis/settings" @label={{i18n "settings"}} />
|
||||
|
||||
<div class="content-body admin-config-area__settings admin-detail pull-left">
|
||||
<AdminFilteredSiteSettings
|
||||
@initialFilter={{@model.initialFilter}}
|
||||
@settings={{@model.settings}}
|
||||
@onFilterChanged={{this.filterChanged}}
|
||||
/>
|
||||
</div>
|
||||
<AdminConfigAreas::EmojisSettings
|
||||
@onFilterChanged={{this.filterChangedCallback}}
|
||||
@initialFilter={{this.filter}}
|
||||
/>
|
|
@ -2,6 +2,7 @@
|
|||
<AdminPageHeader
|
||||
@titleLabel="admin.emoji.title"
|
||||
@descriptionLabel="admin.emoji.description"
|
||||
@hideTabs={{this.hideTabs}}
|
||||
>
|
||||
<:breadcrumbs>
|
||||
<DBreadcrumbsItem
|
||||
|
@ -10,7 +11,7 @@
|
|||
/>
|
||||
</:breadcrumbs>
|
||||
<:actions as |actions|>
|
||||
<actions.Primary @route="adminEmojis.new" @label="admin.emoji.new" />
|
||||
<actions.Primary @route="adminEmojis.new" @label="admin.emoji.add" />
|
||||
</:actions>
|
||||
<:tabs>
|
||||
<NavItem
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
#custom_emoji td.action {
|
||||
text-align: right;
|
||||
}
|
||||
#emoji-uploader {
|
||||
transition: box-shadow ease-in-out 0.25s;
|
||||
}
|
||||
#custom_emoji.highlighted {
|
||||
background: var(--tertiary-very-low);
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
|
@ -15,31 +12,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.emoji-uploader.form-horizontal {
|
||||
padding: var(--space-3);
|
||||
margin-top: var(--space-2);
|
||||
background: var(--primary-very-low);
|
||||
display: flex;
|
||||
gap: var(--space-3);
|
||||
flex-direction: row;
|
||||
align-items: end;
|
||||
|
||||
@include breakpoint("tablet") {
|
||||
flex-direction: column;
|
||||
align-items: normal;
|
||||
}
|
||||
|
||||
.control-group {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-weight: bold;
|
||||
margin-right: var(--space-2);
|
||||
color: var(--primary-high);
|
||||
}
|
||||
}
|
||||
|
||||
.d-admin-table {
|
||||
.d-admin-row__content td {
|
||||
vertical-align: middle;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class SiteSetting < ActiveRecord::Base
|
||||
VALID_AREAS = %w[flags about]
|
||||
VALID_AREAS = %w[flags about emojis]
|
||||
|
||||
extend GlobalPath
|
||||
extend SiteSettingExtension
|
||||
|
|
|
@ -7218,10 +7218,11 @@ en:
|
|||
|
||||
emoji:
|
||||
title: "Emoji"
|
||||
description: "Add new emoji that will be available to everyone. Drag and drop multiple files at once without entering a name to create emojis using their file names. The selected group will be used for all files that are added at the same time. You can also click 'Add New Emoji' to open the file picker."
|
||||
new: "Add emoji"
|
||||
add: "Add New Emoji"
|
||||
choose_files: "Choose Files"
|
||||
description: "Add new emoji that will be available to everyone. Select multiple files to create emojis using their file names. The selected group will be used for all files that are added at the same time."
|
||||
no_emoji: "You don't have any custom emoji yet."
|
||||
add: "Add emoji"
|
||||
back: "Back to emoji"
|
||||
choose_files: "Choose files"
|
||||
uploading: "Uploading…"
|
||||
name: "Name"
|
||||
group: "Group"
|
||||
|
|
|
@ -909,7 +909,9 @@ posting:
|
|||
client: true
|
||||
default: 2
|
||||
min: 1
|
||||
max_emojis_in_title: 1
|
||||
max_emojis_in_title:
|
||||
default: 1
|
||||
area: "emojis"
|
||||
allow_uncategorized_topics:
|
||||
client: true
|
||||
default: false
|
||||
|
@ -1097,18 +1099,22 @@ posting:
|
|||
enable_emoji:
|
||||
default: true
|
||||
client: true
|
||||
area: "emojis"
|
||||
enable_emoji_shortcuts:
|
||||
default: true
|
||||
client: true
|
||||
area: "emojis"
|
||||
emoji_set:
|
||||
default: "twitter"
|
||||
client: true
|
||||
enum: "EmojiSetSiteSetting"
|
||||
area: "emojis"
|
||||
emoji_autocomplete_min_chars:
|
||||
client: true
|
||||
default: 0
|
||||
locale_default:
|
||||
fr: 1
|
||||
area: "emojis"
|
||||
enable_inline_emoji_translation:
|
||||
client: true
|
||||
default: false
|
||||
|
@ -1117,11 +1123,13 @@ posting:
|
|||
zh_TW: true
|
||||
ja: true
|
||||
ko: true
|
||||
area: "emojis"
|
||||
emoji_deny_list:
|
||||
type: emoji_list
|
||||
default: ""
|
||||
client: true
|
||||
refresh: true
|
||||
area: "emojis"
|
||||
approve_post_count:
|
||||
default: 0
|
||||
approve_unless_trust_level:
|
||||
|
@ -1674,6 +1682,7 @@ files:
|
|||
external_emoji_url:
|
||||
default: ""
|
||||
client: true
|
||||
area: "emojis"
|
||||
restrict_letter_avatar_colors:
|
||||
default: ""
|
||||
type: list
|
||||
|
|
Loading…
Reference in New Issue