Skip to content

Commit

Permalink
馃専 2165 recent contacts UI (#2212)
Browse files Browse the repository at this point in the history
* recent

* recent contacts

* recent everything

* FileUploadAPIClient.mimeToType() to get the filetype
+ document to FileUploadAPIClient.mimeToType()

removed unnecessary comments

images recreated as svg and moved out of code

Co-authored-by: Romaric Mourgues <rmourgues@linagora.com>
  • Loading branch information
romanesko and RomaricMourgues committed Jun 2, 2022
1 parent f60f2fc commit 009257b
Show file tree
Hide file tree
Showing 36 changed files with 1,384 additions and 588 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ export function Column(
options: ColumnDefinition["options"] = { order: "ASC" },
): PropertyDecorator {
// eslint-disable-next-line @typescript-eslint/ban-types
return function (target: Object, key: string): void {
return function (target: Object, key: string | symbol) {
target.constructor.prototype._columns = target.constructor.prototype._columns || {};
const colDefinition: ColumnDefinition = { type: type, options: options, nodename: key };
const colDefinition: ColumnDefinition = {
type: type,
options: options,
nodename: key.toString(),
};
target.constructor.prototype._columns[name] = colDefinition;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ export class ChannelCrudController
);

return {
resources: userIncludedChannels,
resources: userIncludedChannels.slice(0, request.query.limit),
};
}
}
Expand Down
3 changes: 3 additions & 0 deletions twake/frontend/public/public/icons/copy.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions twake/frontend/public/public/icons/delete.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions twake/frontend/public/public/icons/dismiss.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions twake/frontend/public/public/icons/download.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions twake/frontend/public/public/icons/eye.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions twake/frontend/public/public/icons/file-type-archive.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions twake/frontend/public/public/icons/file-type-document.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions twake/frontend/public/public/icons/file-type-pdf.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions twake/frontend/public/public/icons/file-type-spreadsheet.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions twake/frontend/public/public/icons/file-type-unknown.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions twake/frontend/public/public/icons/input-clear.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions twake/frontend/public/public/icons/share.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@


.component-channel-avatar {

display: inline-flex;
flex-direction: column;



.channel-icon-container{
display: flex;
flex-direction: row;

}

$iconWidth: 64px;

.channel-icon-wrapper {
height: $iconWidth;
width: $iconWidth;
border-radius: 50%;
box-shadow: 1px 1px 3px #ccc;
margin-bottom:2px;
align-items: center;
text-align: center;
display: flex;

.channel-icon-text {
line-height: 64px;
width:100%;
font-size: 24px;
color:white;
font-weight: 700;
}

.channel-icon-img {
width:$iconWidth;
height:$iconWidth;
object-fit: cover;
object-position: 50% 15%;
border-radius: 50%;

}
}

.channel-icon-wrapper:not(:first-child){
margin-left:calc($iconWidth*2/5*-1);
}


.channel-label {
text-align: center;
font-size:10px;
line-height: 1.2em;
padding-top:4px;
padding-bottom:4px;
width:$iconWidth;
}

.channel-icon-wrapper.style0{
background: var(--messagebubblelight);
}

.channel-icon-wrapper.style1 {background: linear-gradient(129.62deg, #9F2EF4 15.98%, #F97D64 50.17%, #F6C533 82.97%);}
.channel-icon-wrapper.style2 {background: linear-gradient(124.19deg, #0099C0 12.87%, #0099C0 49.65%, #3DD5A8 84.94%);}
.channel-icon-wrapper.style3 {background: linear-gradient(137.24deg, #D3A6FF 15.1%, #B966B5 50.52%, #7E72C6 85.13%);}
.channel-icon-wrapper.style4 {background: linear-gradient(124.08deg, #E2EF54 14.56%, #FF5C66 47.57%, #6248D5 83.84%);}
.channel-icon-wrapper.style5 {background: linear-gradient(120.32deg, #FF5CF1 14.48%, #B38ADE 51.66%, #56CDDF 84.61%);}
.channel-icon-wrapper.style6 {background: linear-gradient(120.32deg, #75C192 14.48%, #70BDA0 51.66%, #21B59C 84.61%);}
.channel-icon-wrapper.style7 {background: linear-gradient(136.93deg, #FFA6AF 14.87%, #E62E40 50.07%, #AA0909 84.36%);}
.channel-icon-wrapper.style8 {background: linear-gradient(136.93deg, #335F50 14.87%, #47888C 50.07%, #08C992 84.36%);}
.channel-icon-wrapper.style9 {background: linear-gradient(135.32deg, #6CD97E 15.23%, #12B312 56.97%, #117600 84.49%);}
.channel-icon-wrapper.style10 {background: linear-gradient(135deg, #7DF1FA 14.84%, #2BB4D6 49.93%, #008AA2 82.63%);}
.channel-icon-wrapper.style11 {background: linear-gradient(136.26deg, #FFBF80 13.66%, #E66B2E 51.13%, #A64300 84.79%);}
}

105 changes: 105 additions & 0 deletions twake/frontend/src/app/components/channel-avatar/channel-avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { ChannelType } from 'features/channels/types/channel';
import React from 'react';
import './channel-avatar.scss';
import UsersService from 'features/users/services/current-user-service';
import UserService from 'features/users/services/current-user-service';
import { UserType } from 'features/users/types/user';
import { getUser } from 'features/users/hooks/use-user-list';
import { addApiUrlIfNeeded } from 'features/global/utils/URLUtils';

const emoji = require('emoji-name-map');

type PropsType = {
channel: ChannelType;
showLabel: boolean;
};

export default ({ channel, showLabel }: PropsType): JSX.Element => {
if (channel.visibility === 'direct') {
let channelMembers = (channel.members || []).filter(e => e !== UsersService.getCurrentUserId());
channelMembers = channelMembers.filter((e, i) => channelMembers.indexOf(e) === i);

let channelName: string[] = [];

let users: UserType[] = [];

channelMembers.forEach(userId => users.push(getUser(userId)));

const icons = [] as JSX.Element[];

users.forEach(member => {
channelName.push(UserService.getFullName(member));
icons.push(getThumbnail(member));
});

let width = 64;

if (channelMembers.length > 1) {
const shift = 64 - (64 * 2) / 5;
width = 64 + (channelMembers.length - 1) * shift;
}

return (
<div className="component-channel-avatar">
<div className="channel-icon-container">{icons.map(icon => icon)}</div>
{showLabel && (
<div className="channel-label" style={{ width: width }}>
{channelName.join(', ')}
</div>
)}
</div>
);
}

let thumbnail;
let label = channel?.name;

if (channel.icon) {
thumbnail = emoji.get(channel.icon);
}

if (!thumbnail && channel.name) {
thumbnail = '';
const channelName =
channel.name.indexOf(' ') < 0 ? channel.name.replace('_', ' ') : channel.name;
const split = channelName.toUpperCase().split(' ');
thumbnail += (split?.[0]?.[0] || '') + (split?.[1]?.[0] || '');
}

const style = getStyle(channel.id);

return (
<div className="component-channel-avatar">
<div className={'channel-icon-wrapper' + style}>
<div className="channel-icon-text">{thumbnail}</div>
</div>
{showLabel && <div className="channel-label">{label}</div>}
</div>
);
};

const getStyle = (id?: string) => {
if (!id) return '';
let output = 0;
for (let i = 0; i < id.length; i++) {
output += id[i].charCodeAt(0);
}
const i = (output % 10) + 1;
return ` style${i}`;
};

const getThumbnail = (user: UserType) => {
let inner;
let style = '';
if (user && (user.thumbnail || user.picture)) {
const thumbnail = addApiUrlIfNeeded(user.picture || user.thumbnail || '');
inner = <img alt={user.first_name} className="channel-icon-img" src={thumbnail} />;
} else {
const fullName = UserService.getFullName(user).toUpperCase().split(' ');
let letters = (fullName?.[0]?.[0] || '?') + (fullName?.[1]?.[0] || '');
inner = <div className="channel-icon-text">{letters}</div>;
style = getStyle(user.id);
}

return <div className={`channel-icon-wrapper${style}`}>{inner}</div>;
};
Loading

0 comments on commit 009257b

Please sign in to comment.