Skip to content

Commit

Permalink
Polishing design for User tooltip in Schedules (#1290)
Browse files Browse the repository at this point in the history
# What this PR does
Design polishing for Schedules User tooltip and Incident action icons

## Which issue(s) this PR fixes

## Checklist

- [ ] Tests updated
- [ ] Documentation added
- [x] `CHANGELOG.md` updated
  • Loading branch information
Ukochka authored Feb 6, 2023
1 parent cd3a357 commit 89f2220
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 78 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## v1.1.24 (2023-02-06)

### Fixed

- Design polishing ([1290](https://github.com/grafana/oncall/pull/1290))
- Not showing contact details in User tooltip if User does not have edit/admin access

## v1.1.23 (2023-02-06)

### Fixed
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.root {
width: 220px;
padding: 10px;
width: 210px;
padding: 8px 4px;
}

.oncall-badge {
Expand All @@ -25,7 +25,7 @@

.line-break {
width: 100vw;
margin: -4px -18px -4px -18px;
margin: 8px -14px 8px -14px;
}

.times {
Expand All @@ -37,21 +37,40 @@
color: #ccccdc;
}

.username {
word-break: break-all;
}

.timezone-wrapper {
display: flex;
flex-grow: 1;
}

.timezone-icon {
width: 10%;
margin-right: 8px;
}

.contact-icon {
margin-right: 8px;
}

.timezone-info {
width: 50%;
overflow-wrap: anywhere;
margin-left: 4px;
margin-right: 8px;
}

.contact-details {
display: flex;
}

.contact-details a {
text-decoration-line: none;
word-break: break-all;
}

.user-timezones {
margin-top: 4px;
display: flex;
width: 100%;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,117 +5,142 @@ import cn from 'classnames/bind';
import dayjs from 'dayjs';

import Avatar from 'components/Avatar/Avatar';
import ScheduleBorderedAvatar from 'components/ScheduleBorderedAvatar/ScheduleBorderedAvatar';
import Text from 'components/Text/Text';
import { isInWorkingHours } from 'components/WorkingHours/WorkingHours.helpers';
import { getTzOffsetString } from 'models/timezone/timezone.helpers';
import { User } from 'models/user/user.types';
import { getColorSchemeMappingForUsers } from 'pages/schedule/Schedule.helpers';
import { useStore } from 'state/useStore';
import { isUserActionAllowed, UserActions } from 'utils/authorization';

import styles from './ScheduleUserDetails.module.css';

interface ScheduleUserDetailsProps {
currentMoment: dayjs.Dayjs;
user: User;
isOncall: boolean;
scheduleId: string;
startMoment: dayjs.Dayjs;
}

const cx = cn.bind(styles);

const ScheduleUserDetails: FC<ScheduleUserDetailsProps> = (props) => {
const { user, currentMoment, isOncall } = props;
const { user, currentMoment, isOncall, scheduleId, startMoment } = props;
const userMoment = currentMoment.tz(user.timezone);
const userOffsetHoursStr = getTzOffsetString(userMoment);
const isInWH = isInWorkingHours(currentMoment, user.working_hours, user.timezone);

const store = useStore();
const colorSchemeMapping = getColorSchemeMappingForUsers(store, scheduleId, startMoment);
const colorSchemeList = Array.from(colorSchemeMapping[user.pk] || []);

const { teamStore } = store;

const slackWorkspaceName = teamStore.currentTeam.slack_team_identity?.cached_name?.replace(/[^0-9a-z]/gi, '') || '';
return (
<div className={cx('root')}>
<VerticalGroup spacing="md">
<HorizontalGroup justify="space-between">
<Avatar src={user.avatar} size="large" />
</HorizontalGroup>
<VerticalGroup spacing="sm">
<Text type="primary">{user.username}</Text>
{isOncall && <Badge text="OnCall now" color="green" />}
{isInWH ? (
<Badge text="Inside working hours" color="blue" />
) : (
<Badge text="Outside working hours" color="orange" />
)}
<HorizontalGroup align="flex-start">
<VerticalGroup spacing="xs">
<ScheduleBorderedAvatar
colors={colorSchemeList}
width={35}
height={35}
renderAvatar={() => <Avatar src={user.avatar} size="large" />}
renderIcon={() => null}
></ScheduleBorderedAvatar>

<VerticalGroup spacing="xs" width="100%">
<div className={cx('username')}>
<Text type="primary">{user.username}</Text>
</div>
<HorizontalGroup spacing="xs">
{isOncall && <Badge text="OnCall" color="green" />}
{isInWH ? (
<Badge text="Inside working hours" color="blue" />
) : (
<Badge text="Outside working hours" color="orange" />
)}
</HorizontalGroup>
<div className={cx('user-timezones')}>
<div className={cx('timezone-icon')}>
<Text type="secondary">
<Icon name="clock-nine" />
</Text>
</div>
<div className={cx('timezone-wrapper')}>
<div className={cx('timezone-info')}>
<VerticalGroup>
<VerticalGroup spacing="none">
<Text type="secondary">Local time</Text>
<Text type="secondary">{currentMoment.tz().format('DD MMM, HH:mm')}</Text>
<Text type="secondary">({getTzOffsetString(currentMoment)})</Text>
</VerticalGroup>
</div>

<div className={cx('timezone-info')}>
<VerticalGroup className={cx('timezone-info')}>
<Text>{user.username}'s time</Text>
<VerticalGroup className={cx('timezone-info')} spacing="none">
<Text>User's time</Text>
<Text>{`${userMoment.tz(user.timezone).format('DD MMM, HH:mm')}`}</Text>
<Text>({userOffsetHoursStr})</Text>
</VerticalGroup>
</div>
</div>
</HorizontalGroup>
</div>
</VerticalGroup>

<hr className={cx('line-break')} />
<VerticalGroup spacing="sm">
<Text>Contacts</Text>
{isUserActionAllowed(UserActions.UserSettingsAdmin) && (
<VerticalGroup spacing="xs">
<hr className={cx('line-break')} />
<VerticalGroup spacing="xs">
<Text>Contacts</Text>

<div className={cx('contact-details')}>
<Text type="secondary">
<Icon name="envelope" />{' '}
<a href={`mailto:${user.email}`} target="_blank" rel="noreferrer">
<Text type="link">{user.email}</Text>
</a>{' '}
</Text>
</div>
{user.slack_user_identity && (
<div className={cx('contact-details')}>
<Text type="secondary">
<Icon name="slack" />{' '}
<a
href={`https://${slackWorkspaceName}.slack.com/team/${user.slack_user_identity.slack_id}`}
target="_blank"
rel="noreferrer"
>
<Text type="link">{user.slack_user_identity.slack_login}</Text>
</a>{' '}
</Text>
</div>
)}
{user.telegram_configuration && (
<div className={cx('contact-details')}>
<Text type="secondary">
<Icon name="message" />{' '}
<a
href={`https://t.me/${user.telegram_configuration.telegram_nick_name}`}
target="_blank"
rel="noreferrer"
>
<Text type="link">{user.telegram_configuration.telegram_nick_name}</Text>
</a>{' '}
</Text>
</div>
)}
{!user.hide_phone_number && user.verified_phone_number && (
<Text type="secondary">Phone: {user.verified_phone_number}</Text>
)}
</VerticalGroup>
<div className={cx('contact-details')}>
<Text type="secondary">
<Icon name="envelope" className={cx('contact-icon')} />
</Text>
<a href={`mailto:${user.email}`} target="_blank" rel="noreferrer">
<Text type="link">{user.email}</Text>
</a>
</div>
{user.slack_user_identity && (
<div className={cx('contact-details')}>
<Text type="secondary">
<Icon name="slack" className={cx('contact-icon')} />
</Text>
<a
href={`https://${slackWorkspaceName}.slack.com/team/${user.slack_user_identity.slack_id}`}
target="_blank"
rel="noreferrer"
>
<Text type="link">{user.slack_user_identity.slack_login}</Text>
</a>
</div>
)}
{user.telegram_configuration && (
<div className={cx('contact-details')}>
<Text type="secondary">
<Icon name="message" className={cx('contact-icon')} />
</Text>
<a
href={`https://t.me/${user.telegram_configuration.telegram_nick_name}`}
target="_blank"
rel="noreferrer"
>
<Text type="link">{user.telegram_configuration.telegram_nick_name}</Text>
</a>
</div>
)}
{!user.hide_phone_number && user.verified_phone_number && (
<div className={cx('contact-details')}>
<Text type="secondary">
<Icon name="document-info" className={cx('contact-icon')} />
</Text>
<Text type="secondary">{user.verified_phone_number}</Text>
</div>
)}
</VerticalGroup>
</VerticalGroup>
)}
</VerticalGroup>
</div>
);
Expand Down
10 changes: 9 additions & 1 deletion grafana-plugin/src/containers/UsersTimezones/UsersTimezones.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,15 @@ const AvatarGroup = (props: AvatarGroupProps) => {
placement="top"
interactive
key={index}
content={<ScheduleUserDetails currentMoment={currentMoment} user={user} isOncall={isOncall} />}
content={
<ScheduleUserDetails
currentMoment={currentMoment}
user={user}
isOncall={isOncall}
scheduleId={scheduleId}
startMoment={startMoment}
/>
}
>
<div
className={cx('avatar')}
Expand Down
1 change: 1 addition & 0 deletions grafana-plugin/src/pages/incident/Incident.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,5 @@

.title-icon {
color: var(--secondary-text-color);
margin-left: 4px;
}
22 changes: 11 additions & 11 deletions grafana-plugin/src/pages/incident/Incident.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,17 +246,6 @@ class IncidentPage extends React.Component<IncidentPageProps, IncidentPageState>
</HorizontalGroup>
<HorizontalGroup align="center">
<Text>
<CopyToClipboard
text={window.location.href}
onCopy={() => {
openNotification('Link copied');
}}
>
<IconButton name="code-branch" tooltip="Copy link" className={cx('title-icon')} />
</CopyToClipboard>
<a href={incident.slack_permalink} target="_blank" rel="noreferrer">
<IconButton name="slack" tooltip="View in Slack" className={cx('title-icon')} />
</a>
{showLinkTo && (
<IconButton
name="share-alt"
Expand All @@ -265,6 +254,17 @@ class IncidentPage extends React.Component<IncidentPageProps, IncidentPageState>
className={cx('title-icon')}
/>
)}
<a href={incident.slack_permalink} target="_blank" rel="noreferrer">
<IconButton name="slack" tooltip="View in Slack" className={cx('title-icon')} />
</a>
<CopyToClipboard
text={window.location.href}
onCopy={() => {
openNotification('Link copied');
}}
>
<IconButton name="copy" tooltip="Copy link" className={cx('title-icon')} />
</CopyToClipboard>
</Text>
</HorizontalGroup>
</HorizontalGroup>
Expand Down

0 comments on commit 89f2220

Please sign in to comment.