* Reorganized Backstage code to use a view controller and separated it from integrations code

* Renamed InstalledIntegrations component to BackstageList

* Added EmojiList page

* Added AddEmoji page

* Added custom emoji to autocomplete and text formatter

* Moved system emoji to EmojiStore

* Stopped trying to get emoji before logging in

* Rerender posts when emojis change

* Fixed submit handler on backstage pages to properly support enter

* Removed debugging code

* Updated javascript driver

* Fixed unit tests

* Fixed backstage routes

* Added clientside validation to prevent users from creating an emoji with the same name as a system one

* Fixed AddEmoji page to properly redirect when an emoji is created successfully

* Fixed updating emoji list when an emoji is deleted

* Added type prop to BackstageList to properly support using a table for the list

* Added help text to EmojiList

* Fixed backstage on smaller screen sizes

* Disable custom emoji by default

* Improved restrictions on creating emojis

* Fixed non-admin users seeing the option to delete each other's emojis

* Fixing gofmt

* Fixed emoji unit tests

* Fixed trying to get emoji from the server when it's disabled
Этот коммит содержится в:
Harrison Healey
2016-07-05 11:58:18 -04:00
коммит произвёл Joram Wilander
родитель a65f1fc266
Коммит dc2f2a8001
56 изменённых файлов: 1697 добавлений и 8920 удалений

135
webapp/stores/emoji_store.jsx Обычный файл
Просмотреть файл

@@ -0,0 +1,135 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
import Constants from 'utils/constants.jsx';
import EventEmitter from 'events';
import EmojiJson from 'utils/emoji.json';
const ActionTypes = Constants.ActionTypes;
const CHANGE_EVENT = 'changed';
class EmojiStore extends EventEmitter {
constructor() {
super();
this.dispatchToken = AppDispatcher.register(this.handleEventPayload.bind(this));
this.emojis = new Map(EmojiJson);
this.systemEmojis = new Map(EmojiJson);
this.unicodeEmojis = new Map();
for (const [, emoji] of this.systemEmojis) {
if (emoji.unicode) {
this.unicodeEmojis.set(emoji.unicode, emoji);
}
}
this.receivedCustomEmojis = false;
this.customEmojis = new Map();
}
addChangeListener(callback) {
this.on(CHANGE_EVENT, callback);
}
removeChangeListener(callback) {
this.removeListener(CHANGE_EVENT, callback);
}
emitChange() {
this.emit(CHANGE_EVENT);
}
hasReceivedCustomEmojis() {
return this.receivedCustomEmojis;
}
setCustomEmojis(customEmojis) {
this.customEmojis = new Map();
for (const emoji of customEmojis) {
this.addCustomEmoji(emoji);
}
// add custom emojis to the map first so that they can't override system ones
this.emojis = new Map([...this.customEmojis, ...this.systemEmojis]);
}
addCustomEmoji(emoji) {
this.customEmojis.set(emoji.name, emoji);
}
removeCustomEmoji(id) {
for (const [name, emoji] of this.customEmojis) {
if (emoji.id === id) {
this.customEmojis.delete(name);
break;
}
}
}
getSystemEmojis() {
return this.systemEmojis;
}
getCustomEmojiMap() {
return this.customEmojis;
}
getEmojis() {
return this.emojis;
}
has(name) {
return this.emojis.has(name);
}
get(name) {
// prioritize system emojis so that custom ones can't override them
return this.emojis.get(name);
}
hasUnicode(codepoint) {
return this.unicodeEmojis.has(codepoint);
}
getUnicode(codepoint) {
return this.unicodeEmojis.get(codepoint);
}
getEmojiImageUrl(emoji) {
if (emoji.id) {
// must match Client.getCustomEmojiImageUrl
return `/api/v3/emoji/${emoji.id}`;
}
const filename = emoji.unicode || emoji.filename || emoji.name;
return Constants.EMOJI_PATH + '/' + filename + '.png';
}
handleEventPayload(payload) {
const action = payload.action;
switch (action.type) {
case ActionTypes.RECEIVED_CUSTOM_EMOJIS:
this.setCustomEmojis(action.emojis);
this.receivedCustomEmojis = true;
this.emitChange();
break;
case ActionTypes.RECEIVED_CUSTOM_EMOJI:
this.addCustomEmoji(action.emoji);
this.emitChange();
break;
case ActionTypes.REMOVED_CUSTOM_EMOJI:
this.removeCustomEmoji(action.id);
this.emitChange();
break;
}
}
}
export default new EmojiStore();

Просмотреть файл

@@ -160,13 +160,16 @@ class TeamStoreClass extends EventEmitter {
}
isTeamAdminForCurrentTeam() {
return this.isTeamAdmin(UserStore.getCurrentId(), this.getCurrentId());
}
isTeamAdmin(userId, teamId) {
if (!Utils) {
Utils = require('utils/utils.jsx'); //eslint-disable-line global-require
}
const userId = UserStore.getCurrentId();
var teamMembers = this.getTeamMembers();
const teamMember = teamMembers.find((m) => m.user_id === userId && m.team_id === this.getCurrentId());
const teamMember = teamMembers.find((m) => m.user_id === userId && m.team_id === teamId);
if (teamMember) {
return Utils.isAdmin(teamMember.roles);