Skip to content

Commit

Permalink
Fix bugs
Browse files Browse the repository at this point in the history
- Lists not scrolling completely
- Create type failing when adding can grant allowlist
- Edit type copying create allowlist into grant allowlist
- New emojis
- Load custom emojis
- Growing user profile popover getting out of view
- List rerender when setting up badge as custom attribute
  • Loading branch information
larkox committed Jul 30, 2021
1 parent 0f16d23 commit e5cce6a
Show file tree
Hide file tree
Showing 18 changed files with 182 additions and 56 deletions.
58 changes: 27 additions & 31 deletions server/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ func (p *Plugin) dialogCreateType(w http.ResponseWriter, r *http.Request, userID
}

if grantAllowList != "" {
toCreate.CanCreate.AllowList = map[string]bool{}
toCreate.CanGrant.AllowList = map[string]bool{}
usernames := strings.Split(createAllowList, ",")
for _, username := range usernames {
username = strings.TrimSpace(username)
Expand Down Expand Up @@ -339,40 +339,36 @@ func (p *Plugin) dialogEditType(w http.ResponseWriter, r *http.Request, userID s
createAllowList, _ := req.Submission[DialogFieldTypeAllowlistCanCreate].(string)
grantAllowList, _ := req.Submission[DialogFieldTypeAllowlistCanGrant].(string)

if createAllowList != "" {
originalType.CanCreate.AllowList = map[string]bool{}
usernames := strings.Split(createAllowList, ",")
for _, username := range usernames {
username = strings.TrimSpace(username)
if username == "" {
continue
}
var allowedUser *model.User
allowedUser, err = p.mm.User.GetByUsername(username)
if err != nil {
dialogError(w, "Cannot find user", map[string]string{DialogFieldTypeAllowlistCanCreate: fmt.Sprintf("Error getting user %s. Error: %v", username, err)})
return
}
originalType.CanCreate.AllowList[allowedUser.Id] = true
originalType.CanCreate.AllowList = map[string]bool{}
usernames := strings.Split(createAllowList, ",")
for _, username := range usernames {
username = strings.TrimSpace(username)
if username == "" {
continue
}
var allowedUser *model.User
allowedUser, err = p.mm.User.GetByUsername(username)
if err != nil {
dialogError(w, "Cannot find user", map[string]string{DialogFieldTypeAllowlistCanCreate: fmt.Sprintf("Error getting user %s. Error: %v", username, err)})
return
}
originalType.CanCreate.AllowList[allowedUser.Id] = true
}

if grantAllowList != "" {
originalType.CanGrant.AllowList = map[string]bool{}
usernames := strings.Split(createAllowList, ",")
for _, username := range usernames {
username = strings.TrimSpace(username)
if username == "" {
continue
}
var allowedUser *model.User
allowedUser, err = p.mm.User.GetByUsername(username)
if err != nil {
dialogError(w, "Cannot find user", map[string]string{DialogFieldTypeAllowlistCanGrant: fmt.Sprintf("Error getting user %s. Error: %v", username, err)})
return
}
originalType.CanGrant.AllowList[allowedUser.Id] = true
originalType.CanGrant.AllowList = map[string]bool{}
usernames = strings.Split(grantAllowList, ",")
for _, username := range usernames {
username = strings.TrimSpace(username)
if username == "" {
continue
}
var allowedUser *model.User
allowedUser, err = p.mm.User.GetByUsername(username)
if err != nil {
dialogError(w, "Cannot find user", map[string]string{DialogFieldTypeAllowlistCanGrant: fmt.Sprintf("Error getting user %s. Error: %v", username, err)})
return
}
originalType.CanGrant.AllowList[allowedUser.Id] = true
}

err = p.store.UpdateType(originalType)
Expand Down
2 changes: 2 additions & 0 deletions webapp/src/components/rhs/all_badges.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.AllBadges {
display: flex;
flex-flow: column;
height: 100%;
padding: 10px;
}
15 changes: 14 additions & 1 deletion webapp/src/components/rhs/all_badges.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {BadgeID, AllBadgesBadge} from '../../types/badges';
import Client from '../../client/api';

import {RHSState} from '../../types/general';
import {RHS_STATE_DETAIL} from '../../constants';
import {IMAGE_TYPE_EMOJI, RHS_STATE_DETAIL} from '../../constants';

import AllBadgesRow from './all_badges_row';
import RHSScrollbars from './rhs_scrollbars';
Expand All @@ -15,6 +15,7 @@ type Props = {
actions: {
setRHSView: (view: RHSState) => void;
setRHSBadge: (badge: BadgeID | null) => void;
getCustomEmojisByName: (names: string[]) => void;
};
}

Expand All @@ -39,6 +40,18 @@ class AllBadges extends React.PureComponent<Props, State> {
});
}

componentDidUpdate(prevProps: Props, prevState: State) {
if (this.state.badges !== prevState.badges) {
const names: string[] = [];
this.state.badges?.forEach((badge) => {
if (badge.image_type === IMAGE_TYPE_EMOJI) {
names.push(badge.image);
}
});
this.props.actions.getCustomEmojisByName(names);
}
}

onBadgeClick = (badge: AllBadgesBadge) => {
this.props.actions.setRHSBadge(badge.id);
this.props.actions.setRHSView(RHS_STATE_DETAIL);
Expand Down
2 changes: 2 additions & 0 deletions webapp/src/components/rhs/badge_details.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.BadgeDetails {
display: flex;
flex-flow: column;
height: 100%;
padding: 10px;
.badge-info {
Expand Down
8 changes: 6 additions & 2 deletions webapp/src/components/rhs/badge_details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type Props = {
actions: {
setRHSView: (view: RHSState) => void;
setRHSUser: (user: string | null) => void;
getCustomEmojiByName: (names: string) => void;
};
}

Expand Down Expand Up @@ -48,8 +49,11 @@ class BadgeDetailsComponent extends React.PureComponent<Props, State> {
});
}

componentDidUpdate(prevProps: Props) {
// Typical usage (don't forget to compare props):
componentDidUpdate(prevProps: Props, prevState: State) {
if (this.state.badge !== prevState.badge && this.state.badge) {
this.props.actions.getCustomEmojiByName(this.state.badge!.name);
}

if (this.props.badgeID === prevProps.badgeID) {
return;
}
Expand Down
6 changes: 6 additions & 0 deletions webapp/src/components/rhs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {getUser} from 'mattermost-redux/selectors/entities/users';

import {GlobalState} from 'mattermost-redux/types/store';

import {getCustomEmojiByName, getCustomEmojisByName} from 'mattermost-redux/actions/emojis';

import {getRHSBadge, getRHSUser, getRHSView} from 'selectors';
import {RHS_STATE_ALL, RHS_STATE_DETAIL, RHS_STATE_OTHER, RHS_STATE_MY} from '../../constants';
import {RHSState} from 'types/general';
Expand All @@ -36,6 +38,7 @@ const RHS: React.FC = () => {
actions={{
setRHSView: (view: RHSState) => dispatch(setRHSView(view)),
setRHSBadge: (badge: BadgeID | null) => dispatch(setRHSBadge(badge)),
getCustomEmojisByName: (names: string[]) => dispatch(getCustomEmojisByName(names)),
}}
/>
);
Expand All @@ -47,6 +50,7 @@ const RHS: React.FC = () => {
actions={{
setRHSView: (view: RHSState) => dispatch(setRHSView(view)),
setRHSUser: (user: string | null) => dispatch(setRHSUser(user)),
getCustomEmojiByName: (names: string) => dispatch(getCustomEmojiByName(names)),
}}
/>
);
Expand All @@ -58,6 +62,7 @@ const RHS: React.FC = () => {
actions={{
setRHSView: (view: RHSState) => dispatch(setRHSView(view)),
setRHSBadge: (badge: BadgeID | null) => dispatch(setRHSBadge(badge)),
getCustomEmojisByName: (names: string[]) => dispatch(getCustomEmojisByName(names)),
}}
/>
);
Expand All @@ -70,6 +75,7 @@ const RHS: React.FC = () => {
actions={{
setRHSView: (view: RHSState) => dispatch(setRHSView(view)),
setRHSBadge: (badge: BadgeID | null) => dispatch(setRHSBadge(badge)),
getCustomEmojisByName: (names: string[]) => dispatch(getCustomEmojisByName(names)),
}}
/>
);
Expand Down
1 change: 1 addition & 0 deletions webapp/src/components/rhs/rhs_scrollbars.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const RHSScrollbars = ({children}: {children: React.ReactNode[]}) => {
renderThumbHorizontal={renderThumbHorizontal}
renderThumbVertical={renderThumbVertical}
renderView={renderView}
style={{flex: '1 1 auto', height: ''}}
>
{children}
</Scrollbars>
Expand Down
8 changes: 6 additions & 2 deletions webapp/src/components/rhs/user_badge_row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@ const UserBadgeRow: React.FC<Props> = ({badge, onClick, isCurrentUser}: Props) =
reason = (<div className='badge-user-reason'>{'Why? ' + badge.reason}</div>);
}
let setStatus = null;
const c = new Client4();
if (isCurrentUser && badge.image_type === 'emoji') {
setStatus = (
<div className='user-badge-set-status'>
<a onClick={() => c.updateCustomStatus({emoji: badge.image, text: badge.name})}>
<a
onClick={() => {
const c = new Client4();
c.updateCustomStatus({emoji: badge.image, text: badge.name});
}}
>
{'Set status to this badge'}
</a>
</div>
Expand Down
2 changes: 2 additions & 0 deletions webapp/src/components/rhs/user_badges.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.UserBadges {
display: flex;
flex-flow: column;
height: 100%;
padding: 10px;
}
16 changes: 13 additions & 3 deletions webapp/src/components/rhs/user_badges.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {BadgeID, UserBadge} from '../../types/badges';
import Client from '../../client/api';

import {RHSState} from 'types/general';
import {RHS_STATE_DETAIL} from '../../constants';
import {IMAGE_TYPE_EMOJI, RHS_STATE_DETAIL} from '../../constants';

import UserBadgeRow from './user_badge_row';
import RHSScrollbars from './rhs_scrollbars';
Expand All @@ -18,6 +18,7 @@ type Props = {
actions: {
setRHSView: (view: RHSState) => void;
setRHSBadge: (badge: BadgeID | null) => void;
getCustomEmojisByName: (names: string[]) => void;
};
}

Expand Down Expand Up @@ -45,8 +46,17 @@ class UserBadges extends React.PureComponent<Props, State> {
});
}

componentDidUpdate(prevProps: Props) {
if (this.props.user === prevProps.user) {
componentDidUpdate(prevProps: Props, prevState: State) {
if (this.state.badges !== prevState.badges) {
const names: string[] = [];
this.state.badges?.forEach((badge) => {
if (badge.image_type === IMAGE_TYPE_EMOJI) {
names.push(badge.image);
}
});
this.props.actions.getCustomEmojisByName(names);
}
if (this.props.user?.id === prevProps.user?.id) {
return;
}

Expand Down
30 changes: 28 additions & 2 deletions webapp/src/components/user_popover/badge_list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {BadgeID, UserBadge} from 'types/badges';
import Client from 'client/api';
import BadgeImage from '../utils/badge_image';
import {RHSState} from 'types/general';
import {RHS_STATE_DETAIL, RHS_STATE_MY, RHS_STATE_OTHER} from '../../constants';
import {IMAGE_TYPE_EMOJI, RHS_STATE_DETAIL, RHS_STATE_MY, RHS_STATE_OTHER} from '../../constants';
import {markdown} from 'utils/markdown';

type Props = {
Expand All @@ -24,11 +24,13 @@ type Props = {
setRHSBadge: (id: BadgeID | null) => Promise<void>;
setRHSUser: (id: string | null) => Promise<void>;
openGrant: (user?: string, badge?: string) => Promise<void>;
getCustomEmojisByName: (names: string[]) => Promise<unknown>;
};
}

type State = {
badges?: UserBadge[];
loaded?: Boolean;
}

const MAX_BADGES = 20;
Expand All @@ -44,10 +46,25 @@ class BadgeList extends React.PureComponent<Props, State> {
componentDidMount() {
const c = new Client();
c.getUserBadges(this.props.user.id).then((badges) => {
this.setState({badges});
this.setState({badges, loaded: true});
});
}

componentDidUpdate(prevProps: Props, prevState: State) {
if (this.state.badges !== prevState.badges) {
const nBadges = this.state.badges?.length || 0;
const toShow = nBadges < MAX_BADGES ? nBadges : MAX_BADGES;
const names: string[] = [];
for (let i = 0; i < toShow; i++) {
const badge = this.state.badges![i];
if (badge.image_type === IMAGE_TYPE_EMOJI) {
names.push(badge.image);
}
}
this.props.actions.getCustomEmojisByName(names);
}
}

onMoreClick = () => {
if (!this.props.openRHS) {
return;
Expand Down Expand Up @@ -130,11 +147,20 @@ class BadgeList extends React.PureComponent<Props, State> {
</a>
);
}
let loading: React.ReactNode = null;
if (!this.state.loaded) {
loading = (

// Reserve enough height for two rows of badges and the "and more" link
<div style={{height: 64}}>{'Loading...'}</div>
);
}
return (
<div>
<div><b>{'Badges'}</b></div>
{content}
{andMore}
{loading}
<a onClick={this.onGrantClick}>
<div>{'Grant badge'}</div>
</a>
Expand Down
4 changes: 4 additions & 0 deletions webapp/src/components/user_popover/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {GlobalState} from 'mattermost-redux/types/store';

import {getCurrentUserId} from 'mattermost-redux/selectors/entities/common';

import {getCustomEmojisByName} from 'mattermost-redux/actions/emojis';

import {setRHSView, setRHSBadge, setRHSUser, openGrant} from '../../actions/actions';

import {getShowRHS} from 'selectors';
Expand All @@ -29,6 +31,7 @@ type Actions = {
setRHSBadge: (id: BadgeID | null) => Promise<void>;
setRHSUser: (id: string | null) => Promise<void>;
openGrant: (user?: string, badge?: string) => Promise<void>;
getCustomEmojisByName: (names: string[]) => Promise<unknown>;
}

function mapDispatchToProps(dispatch: Dispatch) {
Expand All @@ -38,6 +41,7 @@ function mapDispatchToProps(dispatch: Dispatch) {
setRHSBadge,
setRHSUser,
openGrant,
getCustomEmojisByName,
}, dispatch),
};
}
Expand Down
2 changes: 1 addition & 1 deletion webapp/src/components/utils/emoji.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import React from 'react';
import {useSelector} from 'react-redux';

import {getEmojiImageUrl} from 'mattermost-redux/utils/emoji_utils';
import {GlobalState} from 'mattermost-redux/types/store';

import {getEmojiMap} from 'selectors';
import {getEmojiImageUrl} from 'utils/emoji';

interface ComponentProps {
emojiName: string;
Expand Down
Binary file added webapp/src/utils/apple-sheet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion webapp/src/utils/emoji.json

Large diffs are not rendered by default.

57 changes: 49 additions & 8 deletions webapp/src/utils/emoji.tsx

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions webapp/src/utils/emoji_map.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import {CustomEmoji, SystemEmoji} from 'mattermost-redux/types/emojis';
import {CustomEmoji} from 'mattermost-redux/types/emojis';

import * as Emoji from './emoji';

Expand Down Expand Up @@ -52,15 +52,15 @@ export default class EmojiMap {

this.systemIndex += 1;

return {value: [(emoji as SystemEmoji).aliases[0], emoji]};
return {value: [(emoji as any).short_names[0], emoji]};
}

if (this.customIndex < customEmojisArray.length) {
const emoji = customEmojisArray[this.customIndex][1];
const emoji = customEmojisArray[this.customIndex][1] as any;

this.customIndex += 1;

return {value: [emoji.name, emoji]};
const name = emoji.short_name || emoji.name;
return {value: [name, emoji]};
}

return {done: true};
Expand Down
Loading

0 comments on commit e5cce6a

Please sign in to comment.