Skip to content

Added ability to customize logo and title #9052

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog.d/20250205_141639_klakhov_setup_logo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Added

- Ability to customize `api/sever/about` endpoint via settings including: logo, subtitle, description
(<https://github.com/cvat-ai/cvat/pull/9052>)
2 changes: 2 additions & 0 deletions cvat-core/src/server-response-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ export interface SerializedAbout {
description: string;
name: string;
version: string;
logo: string;
subtitle: string;
}

export interface SerializedRemoteFile {
Expand Down
19 changes: 19 additions & 0 deletions cvat-ui/src/components/common/cvat-logo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (C) CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import React from 'react';
import { useSelector } from 'react-redux';
import { CombinedState } from 'reducers';

function CVATLogo(): JSX.Element {
const logo = useSelector((state: CombinedState) => state.about.server.logo);

return (
<div className='cvat-logo-icon'>
<img src={logo} alt='CVAT Logo' />
</div>
);
}

export default React.memo(CVATLogo);
9 changes: 5 additions & 4 deletions cvat-ui/src/components/cvat-app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,11 @@ class CVATApplication extends React.PureComponent<CVATAppProps & RouteComponentP
loadServerAPISchema();
}

if (!aboutInitialized && !aboutFetching) {
loadAbout();
return;
}

if (user == null || !user.isVerified || !user.id) {
return;
}
Expand All @@ -337,10 +342,6 @@ class CVATApplication extends React.PureComponent<CVATAppProps & RouteComponentP
loadFormats();
}

if (!aboutInitialized && !aboutFetching) {
loadAbout();
}

if (organizationInitialized && !requestsInitialized && !requestsFetching) {
initRequests();
}
Expand Down
6 changes: 3 additions & 3 deletions cvat-ui/src/components/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { connect } from 'react-redux';
import { useHistory, useLocation } from 'react-router';
import { Row, Col } from 'antd/lib/grid';
import { MenuProps } from 'antd/lib/menu';
import Icon, {
import {
SettingOutlined,
InfoCircleOutlined,
EditOutlined,
Expand All @@ -34,9 +34,9 @@ import notification from 'antd/lib/notification';
import config from 'config';

import { Organization, getCore } from 'cvat-core-wrapper';
import { CVATLogo } from 'icons';
import ChangePasswordDialog from 'components/change-password-modal/change-password-modal';
import CVATTooltip from 'components/common/cvat-tooltip';
import CVATLogo from 'components/common/cvat-logo';
import { switchSettingsModalVisible as switchSettingsModalVisibleAction } from 'actions/settings-actions';
import { logoutAsync, authActions } from 'actions/auth-actions';
import { shortcutsActions, registerComponentShortcuts } from 'actions/shortcuts-actions';
Expand Down Expand Up @@ -430,7 +430,7 @@ function HeaderComponent(props: Props): JSX.Element {
<Layout.Header className='cvat-header'>
<GlobalHotKeys keyMap={subKeyMap(componentShortcuts, keyMap)} handlers={handlers} />
<div className='cvat-left-header'>
<Icon className='cvat-logo-icon' component={CVATLogo} />
<CVATLogo />
<Button
className={getButtonClassName('projects')}
type='link'
Expand Down
19 changes: 17 additions & 2 deletions cvat-ui/src/components/header/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
line-height: 0;
height: $header-height;
background: $header-color;
justify-content: space-between;
}

.ant-btn.ant-btn-link.cvat-header-button {
Expand All @@ -23,6 +24,21 @@
}
}

.cvat-logo-icon {
width: $grid-unit-size * 8;
height: $grid-unit-size * 4;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;

img {
object-fit: contain;
width: 100%;
height: 100%;
}
}

.cvat-left-header {
.ant-btn.cvat-header-button {
opacity: 0.7;
Expand All @@ -33,11 +49,10 @@
}
}

.anticon.cvat-logo-icon {
.cvat-logo-icon {
margin: 0 $grid-unit-size * 2;
}

width: 50%;
display: flex;
justify-content: flex-start;
align-items: center;
Expand Down
14 changes: 8 additions & 6 deletions cvat-ui/src/components/signing-common/signing-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@

import './styles.scss';
import React from 'react';
import { useSelector } from 'react-redux';
import { CombinedState } from 'reducers';
import Layout from 'antd/lib/layout';
import { Col, Row } from 'antd/lib/grid';
import { CVATLogo } from 'icons';
import Icon from '@ant-design/icons';
import Title from 'antd/lib/typography/Title';
import CVATLogo from 'components/common/cvat-logo';
import SVGSigningBackground from '../../assets/signing-background.svg';

interface SignInLayoutComponentProps {
Expand Down Expand Up @@ -51,6 +52,8 @@ export const formSizes: FormSizes = {
function SignInLayout(props: SignInLayoutComponentProps): JSX.Element {
const { children } = props;
const { Content, Header } = Layout;
const subtitle = useSelector((state: CombinedState) => state.about.server.subtitle);

const titleSizes = {
xs: { span: 0 },
sm: { span: 0 },
Expand All @@ -71,18 +74,17 @@ function SignInLayout(props: SignInLayoutComponentProps): JSX.Element {
<Layout>
<SVGSigningBackground className='cvat-signing-background' />
<Header className='cvat-signing-header'>
<Row justify='center' align='middle'>
<Row className='cvat-signing-header-logo-wrapper' justify='center' align='middle'>
<Col {...logoSizes}>
<Icon className='cvat-logo-icon' component={CVATLogo} />
<CVATLogo />
</Col>
</Row>
</Header>
<Layout className='cvat-signing-layout'>
<Content>
<Row justify='center' align='middle' style={{ height: '100%' }}>
<Col {...titleSizes} className='cvat-signing-title'>
<Title>Open Data</Title>
<Title>Annotation Platform</Title>
<Title>{subtitle}</Title>
</Col>
{children}
</Row>
Expand Down
6 changes: 5 additions & 1 deletion cvat-ui/src/components/signing-common/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,18 @@ $social-google-background: #4286f5;
}
}

.cvat-signing-header-logo-wrapper {
height: 100%;
}

.cvat-signing-header {
background: transparent;
position: fixed;
padding: $grid-unit-size * 2 0 0 0;
width: 100%;

.cvat-logo-icon {
fill: white;
filter: brightness(0) invert(1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I understand it makes any logo on sign-in page white, however what if a color logo provided?
This approach will break such logo.

}
}

Expand Down
2 changes: 0 additions & 2 deletions cvat-ui/src/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import React from 'react';

import SVGCVATLogo from './assets/cvat-logo.svg';
import SVGCVATIcon from './assets/cvat-icon.svg';
import SVGCursorIcon from './assets/cursor-icon.svg';
import SVGMoveIcon from './assets/move-icon.svg';
Expand Down Expand Up @@ -72,7 +71,6 @@ import SVGShowGroundTruthIcon from './assets/show-gt-icon.svg';
import SVGJoinIcon from './assets/join-icon.svg';
import SVGSliceIcon from './assets/slice-icon.svg';

export const CVATLogo = React.memo((): JSX.Element => <SVGCVATLogo />);
export const CVATIcon = React.memo((): JSX.Element => <SVGCVATIcon />);
export const CursorIcon = React.memo((): JSX.Element => <SVGCursorIcon />);
export const MoveIcon = React.memo((): JSX.Element => <SVGMoveIcon />);
Expand Down
2 changes: 2 additions & 0 deletions cvat/apps/engine/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2627,6 +2627,8 @@ class AboutSerializer(serializers.Serializer):
name = serializers.CharField(max_length=128)
description = serializers.CharField(max_length=2048)
version = serializers.CharField(max_length=64)
logo = serializers.CharField()
subtitle = serializers.CharField(max_length=1024)

class FrameMetaSerializer(serializers.Serializer):
width = serializers.IntegerField()
Expand Down
File renamed without changes
15 changes: 7 additions & 8 deletions cvat/apps/engine/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@
_DATA_UPDATED_DATE_HEADER_NAME = 'X-Updated-Date'
_RETRY_AFTER_TIMEOUT = 10

def get_logo_uri(request) -> str:
return request.build_absolute_uri(f'{settings.STATIC_URL}{settings.LOGO_FILENAME}')

@extend_schema(tags=['server'])
class ServerViewSet(viewsets.ViewSet):
serializer_class = None
Expand All @@ -210,15 +213,11 @@ def get_serializer(self, *args, **kwargs):
def about(request):
from cvat import __version__ as cvat_version
about = {
"name": "Computer Vision Annotation Tool",
"name": settings.ABOUT_INFO["name"],
"subtitle": settings.ABOUT_INFO["subtitle"],
"description": settings.ABOUT_INFO["description"],
"version": cvat_version,
"description": "CVAT is completely re-designed and re-implemented " +
"version of Video Annotation Tool from Irvine, California " +
"tool. It is free, online, interactive video and image annotation " +
"tool for computer vision. It is being used by our team to " +
"annotate million of objects with different properties. Many UI " +
"and UX decisions are based on feedbacks from professional data " +
"annotation team."
"logo": get_logo_uri(request),
}
serializer = AboutSerializer(data=about)
if serializer.is_valid(raise_exception=True):
Expand Down
7 changes: 7 additions & 0 deletions cvat/schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6905,9 +6905,16 @@ components:
version:
type: string
maxLength: 64
logo:
type: string
subtitle:
type: string
maxLength: 1024
required:
- description
- logo
- name
- subtitle
- version
AcceptInvitationRead:
type: object
Expand Down
13 changes: 13 additions & 0 deletions cvat/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -769,3 +769,16 @@ class CVAT_QUEUES(Enum):

# Indicates the maximum number of days a file or directory is retained in the temporary directory
TMP_FILE_OR_DIR_RETENTION_DAYS = 3

LOGO_FILENAME = 'logo.png'
ABOUT_INFO = {
"name": "Computer Vision Annotation Tool",
"subtitle": "Open Data Annotation Platform",
"description": "CVAT is completely re-designed and re-implemented " +
"version of Video Annotation Tool from Irvine, California " +
"tool. It is free, online, interactive video and image annotation " +
"tool for computer vision. It is being used by our team to " +
"annotate million of objects with different properties. Many UI " +
"and UX decisions are based on feedbacks from professional data " +
"annotation team.",
}
Loading