Skip to content

Commit

Permalink
feat: add activity filter banner
Browse files Browse the repository at this point in the history
  • Loading branch information
stepan662 committed Apr 30, 2024
1 parent aaa15a1 commit c2fb46d
Show file tree
Hide file tree
Showing 10 changed files with 250 additions and 18 deletions.
1 change: 1 addition & 0 deletions webapp/src/ThemeProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ const getTheme = (mode: PaletteMode) => {
tokens: c.tokens,
placeholders: c.placeholders,
languageChips: c.languageChips,
revisionFilterBanner: c.revisionFilterBanner,
},
mixins: {
toolbar: {
Expand Down
13 changes: 13 additions & 0 deletions webapp/src/colors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ export type ExampleBanner = {
border: string;
};

export type RevisionFilterBanner = {
background: string;
highlightText: string;
};

export type TipsBanner = {
background: string;
};
Expand Down Expand Up @@ -197,6 +202,10 @@ export const colors = {
mainText: '#004437',
linkText: '#009B85',
},
revisionFilterBanner: {
background: '#00AF9A14',
highlightText: '#00AF9A',
} satisfies RevisionFilterBanner,
quickStart: {
highlight: '#F7F8FB',
circleNormal: '#E7EBF5',
Expand Down Expand Up @@ -321,6 +330,10 @@ export const colors = {
mainText: '#BEF4E9',
linkText: '#dddddd',
},
revisionFilterBanner: {
background: '#99E5D629',
highlightText: '#99E5D6',
} satisfies RevisionFilterBanner,
quickStart: {
highlight: '#233043',
circleNormal: '#2c3c52',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const ActivityDetail = ({ data, diffEnabled, activity }: Props) => {
const path = { projectId: project.id, revisionId: data.revisionId };
const query = { size: 40 };
const detailLoadable = useApiInfiniteQuery({
url: '/v2/projects/{projectId}/activity/revisions/{revisionId}',
url: '/v2/projects/{projectId}/activity/revisions/{revisionId}/modified-entities',
method: 'get',
path,
query,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const ActivityDetailDialog: React.FC<Props> = ({
size="medium"
href={`${LINKS.PROJECT_TRANSLATIONS.build({
[PARAMS.PROJECT_ID]: project.id,
})}?revision=${data.revisionId}`}
})}?activity=${data.revisionId}`}
endIcon={<OpenInNew fontSize="small" />}
target="_blank"
rel="noreferrer noopener"
Expand Down
3 changes: 3 additions & 0 deletions webapp/src/custom.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
TipsBanner,
TopBanner,
LanguageChips,
RevisionFilterBanner,
} from './colors';

declare module '*.svg' {
Expand Down Expand Up @@ -51,6 +52,7 @@ declare module '@mui/material/styles/createPalette' {
tokens: typeof all.tokens;
placeholders: Placeholders;
languageChips: LanguageChips;
revisionFilterBanner: RevisionFilterBanner;
}

interface PaletteOptions {
Expand All @@ -76,6 +78,7 @@ declare module '@mui/material/styles/createPalette' {
tokens: typeof all.tokens;
placeholders: Placeholders;
languageChips: LanguageChips;
revisionFilterBanner: RevisionFilterBanner;
}
}

Expand Down
65 changes: 54 additions & 11 deletions webapp/src/service/apiSchema.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -559,9 +559,12 @@ export interface paths {
"/v2/projects/{projectId}/all-keys": {
get: operations["getAllKeys"];
};
"/v2/projects/{projectId}/activity/revisions/{revisionId}": {
"/v2/projects/{projectId}/activity/revisions/{revisionId}/modified-entities": {
get: operations["getModifiedEntitiesByRevision"];
};
"/v2/projects/{projectId}/activity/revisions/{revisionId}": {
get: operations["getSingleRevision"];
};
"/v2/projects/{projectId}/activity": {
get: operations["getActivity"];
};
Expand Down Expand Up @@ -1774,9 +1777,9 @@ export interface components {
lastUsedAt?: number;
/** Format: int64 */
createdAt: number;
description: string;
/** Format: int64 */
updatedAt: number;
description: string;
};
SetOrganizationRoleDto: {
roleType: "MEMBER" | "OWNER";
Expand Down Expand Up @@ -1914,9 +1917,9 @@ export interface components {
/** Format: int64 */
id: number;
scopes: string[];
username?: string;
/** Format: int64 */
projectId: number;
username?: string;
/** Format: int64 */
expiresAt?: number;
/** Format: int64 */
Expand Down Expand Up @@ -3034,12 +3037,6 @@ export interface components {
old?: { [key: string]: unknown };
new?: { [key: string]: unknown };
};
PagedModelProjectActivityModel: {
_embedded?: {
activities?: components["schemas"]["ProjectActivityModel"][];
};
page?: components["schemas"]["PageMetadata"];
};
ProjectActivityAuthorModel: {
/** Format: int64 */
id: number;
Expand Down Expand Up @@ -3104,6 +3101,12 @@ export interface components {
counts?: { [key: string]: number };
params?: { [key: string]: unknown };
};
PagedModelProjectActivityModel: {
_embedded?: {
activities?: components["schemas"]["ProjectActivityModel"][];
};
page?: components["schemas"]["PageMetadata"];
};
PagedModelTagModel: {
_embedded?: {
tags?: components["schemas"]["TagModel"][];
Expand Down Expand Up @@ -3514,9 +3517,9 @@ export interface components {
lastUsedAt?: number;
/** Format: int64 */
createdAt: number;
description: string;
/** Format: int64 */
updatedAt: number;
description: string;
};
OrganizationRequestParamsDto: {
filterCurrentUserOwner: boolean;
Expand Down Expand Up @@ -3650,9 +3653,9 @@ export interface components {
/** Format: int64 */
id: number;
scopes: string[];
username?: string;
/** Format: int64 */
projectId: number;
username?: string;
/** Format: int64 */
expiresAt?: number;
/** Format: int64 */
Expand Down Expand Up @@ -11552,6 +11555,46 @@ export interface operations {
};
};
};
getSingleRevision: {
parameters: {
path: {
revisionId: number;
projectId: number;
};
};
responses: {
/** OK */
200: {
content: {
"application/hal+json": components["schemas"]["ProjectActivityModel"];
};
};
/** Bad Request */
400: {
content: {
"*/*": string;
};
};
/** Unauthorized */
401: {
content: {
"*/*": string;
};
};
/** Forbidden */
403: {
content: {
"*/*": string;
};
};
/** Not Found */
404: {
content: {
"*/*": string;
};
};
};
};
getActivity: {
parameters: {
query: {
Expand Down
145 changes: 145 additions & 0 deletions webapp/src/views/projects/translations/ActivityFilterIndicator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { FilterList } from '@mui/icons-material';
import { Box, Button, styled, useMediaQuery } from '@mui/material';
import { T } from '@tolgee/react';

import { ActivityTitle } from 'tg.component/activity/ActivityTitle';
import { buildActivity } from 'tg.component/activity/activityTools';
import { useProject } from 'tg.hooks/useProject';
import { useApiQuery } from 'tg.service/http/useQueryApi';
import { AvatarImg } from 'tg.component/common/avatar/AvatarImg';
import { UserName } from 'tg.component/common/UserName';

import { useActivityFilter } from './useActivityFilter';
import { useCurrentLanguage } from 'tg.hooks/useCurrentLanguage';
import { useGlobalContext } from 'tg.globalContext/GlobalContext';

const StyledContainer = styled('div')`
margin-top: -8px;
margin-bottom: 12px;
background: ${({ theme }) => theme.palette.revisionFilterBanner.background};
padding: 0px 4px 0px 14px;
border-radius: 4px;
height: 40px;
display: grid;
grid-template-columns: auto 1fr auto;
max-width: 100%;
align-items: center;
`;

const StyledDescription = styled('div')`
display: flex;
gap: 4px;
align-items: center;
overflow: hidden;
max-width: 100%;
`;

const StyledUser = styled(Box)`
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 500;
`;

const StyledLabel = styled('div')`
color: ${({ theme }) => theme.palette.revisionFilterBanner.highlightText};
display: flex;
align-items: center;
gap: 6px;
font-weight: 600;
margin-right: 16px;
flex-shrink: 1;
`;

const StyledTime = styled(Box)`
color: ${({ theme }) => theme.palette.text.secondary};
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex-shrink: 1;
`;

const StyledClear = styled('div')`
flex-grow: 1;
display: flex;
justify-content: flex-end;
white-space: nowrap;
`;

type Props = {
revisionId: number;
};

export const RevisionFilterIndicator = ({ revisionId }: Props) => {
const project = useProject();

const { clear } = useActivityFilter();

const { data } = useApiQuery({
url: '/v2/projects/{projectId}/activity/revisions/{revisionId}',
method: 'get',
path: { projectId: project.id, revisionId: revisionId },
});

const activity = data && buildActivity(data);
const lang = useCurrentLanguage();
const rightPanelWidth = useGlobalContext((c) => c.layout.rightPanelWidth);
const isSmall = useMediaQuery(
`@media(max-width: ${rightPanelWidth + 1000}px)`
);
if (!activity) {
return null;
}

const date = new Date(data.timestamp);

return (
<StyledContainer>
<StyledLabel>
<FilterList color="inherit" />
<span style={{ whiteSpace: 'nowrap' }}>
<T keyName="activity_filter_indicator_label" />
</span>
</StyledLabel>
{!isSmall && (
<StyledDescription>
{data.author && (
<Box gridArea="avatar">
<AvatarImg
size={24}
owner={{
type: 'USER',
id: data.author.id,
avatar: data.author.avatar,
deleted: data.author.deleted,
}}
/>
</Box>
)}
<StyledUser>
{data.author?.deleted ? (
<UserName {...data.author} />
) : (
data.author?.name
)}
</StyledUser>
<Box sx={{ marginLeft: '8px' }}>
<ActivityTitle activity={activity} />
</Box>
<StyledTime sx={{ marginLeft: '8px' }}>
{date.toLocaleDateString(lang) + ' '}
{date.toLocaleTimeString(lang, {
hour: 'numeric',
minute: 'numeric',
})}
</StyledTime>
</StyledDescription>
)}
<StyledClear>
<Button size="small" onClick={clear} color="inherit">
<T keyName="activity_filter_indicator_clear" />
</Button>
</StyledClear>
</StyledContainer>
);
};
10 changes: 9 additions & 1 deletion webapp/src/views/projects/translations/Translations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@ import { BaseProjectView } from '../BaseProjectView';
import { TranslationsToolbar } from './TranslationsToolbar';
import { BatchOperationsChangeIndicator } from './BatchOperations/BatchOperationsChangeIndicator';
import { FloatingToolsPanel } from './ToolsPanel/FloatingToolsPanel';
import { RevisionFilterIndicator } from './ActivityFilterIndicator';

const StyledContainer = styled('div')`
display: grid;
grid-template-columns: 1fr auto;
`;

export const Translations = () => {
type Props = {
revisionId: number | undefined;
};

export const Translations = (props: Props) => {
const { setQuickStartOpen, quickStartForceFloating } = useGlobalActions();
const quickStartEnabled = useGlobalContext((c) => c.quickStartGuide.enabled);
const isSmall = useMediaQuery(`@media (max-width: ${800}px)`);
Expand Down Expand Up @@ -148,6 +153,9 @@ export const Translations = () => {
wrapperProps={{ pb: 0 }}
>
<BatchOperationsChangeIndicator />
{props.revisionId !== undefined && (
<RevisionFilterIndicator revisionId={props.revisionId} />
)}
<TranslationsHeader />
<StyledContainer>
{translationsEmpty ? (
Expand Down
Loading

0 comments on commit c2fb46d

Please sign in to comment.