packages/article-feedback/widgets/feedback-statistics/app.tsx (86 lines of code) (raw):

import React, {memo} from 'react'; import type {FC} from 'react'; import {format} from 'date-fns'; import {ControlsHeightContext, ControlsHeight} from '@jetbrains/ring-ui-built/components/global/controls-height'; import Link from '@jetbrains/ring-ui-built/components/link/link'; import Badge from '@jetbrains/ring-ui-built/components/badge/badge'; import API, {YTUser} from '../api'; const host = await YTApp.register(); const api = new API(host); const [stat, config, profile] = await Promise.all([ api.getStat(), api.getYtConfig(), api.getYtUserProfile(), api.loadProject(), api.loadPermissions() ]); const dateTimePattern = profile.profiles.general.dateFieldFormat.pattern; const usersIds = [...new Set(stat.messages.map(it => it.userId))]; const users = await api.getYtUsers(usersIds); const messages = [...stat.messages, ...stat.guestMessages].sort((a, b) => b.timestamp - a.timestamp); const likesTotal = stat.likes + stat.guestLikes; const canReadUser = api.canReadUser(); function getYouTrackUrl(path: string) { if (config.contextPath) { return `/${config.contextPath}/${path}`; } return `/${path}`; } function renderUser(user?: YTUser, guest?: {name: string}) { if (user) { if (canReadUser) { return <Link href={getYouTrackUrl(`users/${user.ringId}`)} target="_blank">{user.fullName}</Link>; } else { return <span>{user.fullName}</span>; } } if (guest) { return <span>{guest.name}</span>; } return <span>{'Deleted User'}</span>; } const AppComponent: FC = () => { return ( <ControlsHeightContext.Provider value={ControlsHeight.S}> <article className="widget"> {stat && ( <> <div data-test="likes"> <strong>{'Helpful'}</strong>{': '}{likesTotal} {likesTotal > 0 && ` (${stat.likes} from registered users)`} </div> <div data-test="dislikes" className="dislikes"> <strong>{'Not helpful'}</strong>{': '}{stat.dislikes} </div> {messages.length > 0 && ( <> <div className="separator"/> <div className="messages"> {messages.map(message => { const user = 'userId' in message ? users.find(it => it.ringId === message.userId) : undefined; const guest = 'name' in message ? {name: message.name, email: message.email} : undefined; return ( <section key={message.message}> <header className="messageHeader"> <strong> {renderUser(user, guest)} </strong> {guest && ( <Badge>{'guest'}</Badge> )} <span className="datetime">{format(message.timestamp, dateTimePattern)}</span> </header> {guest && ( <div className="messageSubHeader">{guest.email}</div> )} <div className="messageText" data-test="feedback-text">{message.message}</div> </section> ); })} </div> </> )} </> )} </article> </ControlsHeightContext.Provider> ); }; export const App = memo(AppComponent);