mirror of
https://github.com/grafana/grafana.git
synced 2025-02-13 00:55:47 -06:00
Chore: Mark up User Profile page for translation (#43874)
* Mark up User profile page for translation * Extract new messages * updated selectors * update selectors * wip TestProvider * update tests * fix field labels * extract new messages * don't store date objects in redux state * don't store date objects in redux state
This commit is contained in:
parent
6d072ad84d
commit
36983d8d3b
@ -2,7 +2,8 @@
|
|||||||
"locales": [
|
"locales": [
|
||||||
"en",
|
"en",
|
||||||
"fr",
|
"fr",
|
||||||
"es"
|
"es",
|
||||||
|
"pseudo-LOCALE"
|
||||||
],
|
],
|
||||||
"catalogs": [
|
"catalogs": [
|
||||||
{
|
{
|
||||||
@ -11,14 +12,18 @@
|
|||||||
"public/app"
|
"public/app"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
"**/*.d.ts",
|
||||||
|
"**/*.test.ts",
|
||||||
"**/node_modules/**",
|
"**/node_modules/**",
|
||||||
"public/app/plugins"
|
"public/app/plugins"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fallbackLocales": {
|
"fallbackLocales": {
|
||||||
|
"pseudo-LOCALE": "en",
|
||||||
"default": "en"
|
"default": "en"
|
||||||
},
|
},
|
||||||
|
"pseudoLocale": "pseudo-LOCALE",
|
||||||
"sourceLocale": "en",
|
"sourceLocale": "en",
|
||||||
"format": "po",
|
"format": "po",
|
||||||
"formatOptions": {
|
"formatOptions": {
|
||||||
|
@ -322,4 +322,10 @@ export const Components = {
|
|||||||
DashboardRow: {
|
DashboardRow: {
|
||||||
title: (title: string) => `data-testid dashboard-row-title-${title}`,
|
title: (title: string) => `data-testid dashboard-row-title-${title}`,
|
||||||
},
|
},
|
||||||
|
UserProfile: {
|
||||||
|
profileSaveButton: 'data-testid-user-profile-save',
|
||||||
|
preferencesSaveButton: 'data-testid-shared-prefs-save',
|
||||||
|
orgsTable: 'data-testid-user-orgs-table',
|
||||||
|
sessionsTable: 'data-testid-user-sessions-table',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -21,6 +21,7 @@ import { selectors } from '@grafana/e2e-selectors';
|
|||||||
import { DashboardSearchHit, DashboardSearchItemType } from 'app/features/search/types';
|
import { DashboardSearchHit, DashboardSearchItemType } from 'app/features/search/types';
|
||||||
import { backendSrv } from 'app/core/services/backend_srv';
|
import { backendSrv } from 'app/core/services/backend_srv';
|
||||||
import { PreferencesService } from 'app/core/services/PreferencesService';
|
import { PreferencesService } from 'app/core/services/PreferencesService';
|
||||||
|
import { t, Trans } from '@lingui/macro';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
resourceUri: string;
|
resourceUri: string;
|
||||||
@ -36,9 +37,9 @@ export interface State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const themes: SelectableValue[] = [
|
const themes: SelectableValue[] = [
|
||||||
{ value: '', label: 'Default' },
|
{ value: '', label: t({ id: 'shared-preferences.theme.default-label', message: 'Default' }) },
|
||||||
{ value: 'dark', label: 'Dark' },
|
{ value: 'dark', label: t({ id: 'shared-preferences.theme.dark-label', message: 'Dark' }) },
|
||||||
{ value: 'light', label: 'Light' },
|
{ value: 'light', label: t({ id: 'shared-preferences.theme.light-label', message: 'Light' }) },
|
||||||
];
|
];
|
||||||
|
|
||||||
export class SharedPreferences extends PureComponent<Props, State> {
|
export class SharedPreferences extends PureComponent<Props, State> {
|
||||||
@ -130,12 +131,24 @@ export class SharedPreferences extends PureComponent<Props, State> {
|
|||||||
const { disabled } = this.props;
|
const { disabled } = this.props;
|
||||||
const styles = getStyles();
|
const styles = getStyles();
|
||||||
|
|
||||||
|
const homeDashboardTooltip = (
|
||||||
|
<Tooltip
|
||||||
|
content={
|
||||||
|
<Trans id="shared-preferences.fields.home-dashboard-tooltip">
|
||||||
|
Not finding the dashboard you want? Star it first, then it should appear in this select box.
|
||||||
|
</Trans>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Icon name="info-circle" />
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form onSubmit={this.onSubmitForm}>
|
<Form onSubmit={this.onSubmitForm}>
|
||||||
{() => {
|
{() => {
|
||||||
return (
|
return (
|
||||||
<FieldSet label="Preferences" disabled={disabled}>
|
<FieldSet label={<Trans id="shared-preferences.title">Preferences</Trans>} disabled={disabled}>
|
||||||
<Field label="UI Theme">
|
<Field label={t({ id: 'shared-preferences.fields.theme-label', message: 'UI Theme' })}>
|
||||||
<RadioButtonGroup
|
<RadioButtonGroup
|
||||||
options={themes}
|
options={themes}
|
||||||
value={themes.find((item) => item.value === theme)?.value}
|
value={themes.find((item) => item.value === theme)?.value}
|
||||||
@ -146,10 +159,11 @@ export class SharedPreferences extends PureComponent<Props, State> {
|
|||||||
<Field
|
<Field
|
||||||
label={
|
label={
|
||||||
<Label htmlFor="home-dashboard-select">
|
<Label htmlFor="home-dashboard-select">
|
||||||
<span className={styles.labelText}>Home Dashboard</span>
|
<span className={styles.labelText}>
|
||||||
<Tooltip content="Not finding the dashboard you want? Star it first, then it should appear in this select box.">
|
<Trans id="shared-preferences.fields.home-dashboard-label">Home Dashboard</Trans>
|
||||||
<Icon name="info-circle" />
|
</span>
|
||||||
</Tooltip>
|
|
||||||
|
{homeDashboardTooltip}
|
||||||
</Label>
|
</Label>
|
||||||
}
|
}
|
||||||
data-testid="User preferences home dashboard drop down"
|
data-testid="User preferences home dashboard drop down"
|
||||||
@ -163,30 +177,40 @@ export class SharedPreferences extends PureComponent<Props, State> {
|
|||||||
this.onHomeDashboardChanged(dashboard.id)
|
this.onHomeDashboardChanged(dashboard.id)
|
||||||
}
|
}
|
||||||
options={dashboards}
|
options={dashboards}
|
||||||
placeholder="Choose default dashboard"
|
placeholder={t({
|
||||||
|
id: 'shared-preferences.fields.home-dashboard-placeholder',
|
||||||
|
message: 'Choose default dashboard',
|
||||||
|
})}
|
||||||
inputId="home-dashboard-select"
|
inputId="home-dashboard-select"
|
||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
<Field label="Timezone" data-testid={selectors.components.TimeZonePicker.containerV2}>
|
<Field
|
||||||
|
label={t({ id: 'shared-dashboard.fields.timezone-label', message: 'Timezone' })}
|
||||||
|
data-testid={selectors.components.TimeZonePicker.containerV2}
|
||||||
|
>
|
||||||
<TimeZonePicker
|
<TimeZonePicker
|
||||||
includeInternal={true}
|
includeInternal={true}
|
||||||
value={timezone}
|
value={timezone}
|
||||||
onChange={this.onTimeZoneChanged}
|
onChange={this.onTimeZoneChanged}
|
||||||
inputId={'shared-preferences-timezone-picker'}
|
inputId="shared-preferences-timezone-picker"
|
||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
<Field label="Week start" data-testid={selectors.components.WeekStartPicker.containerV2}>
|
<Field
|
||||||
|
label={t({ id: 'shared-preferences.fields.week-start-label', message: 'Week start' })}
|
||||||
|
data-testid={selectors.components.WeekStartPicker.containerV2}
|
||||||
|
>
|
||||||
<WeekStartPicker
|
<WeekStartPicker
|
||||||
value={weekStart}
|
value={weekStart}
|
||||||
onChange={this.onWeekStartChanged}
|
onChange={this.onWeekStartChanged}
|
||||||
inputId={'shared-preferences-week-start-picker'}
|
inputId={'shared-preferences-week-start-picker'}
|
||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
<div className="gf-form-button-row">
|
<div className="gf-form-button-row">
|
||||||
<Button variant="primary" aria-label="User preferences save button">
|
<Button variant="primary" data-testid={selectors.components.UserProfile.preferencesSaveButton}>
|
||||||
Save
|
<Trans id="common.save">Save</Trans>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</FieldSet>
|
</FieldSet>
|
||||||
|
@ -3,8 +3,9 @@ import { css } from '@emotion/css';
|
|||||||
import { ConfirmButton, ConfirmModal, Button } from '@grafana/ui';
|
import { ConfirmButton, ConfirmModal, Button } from '@grafana/ui';
|
||||||
import { AccessControlAction, UserSession } from 'app/types';
|
import { AccessControlAction, UserSession } from 'app/types';
|
||||||
import { contextSrv } from 'app/core/core';
|
import { contextSrv } from 'app/core/core';
|
||||||
|
import { withI18n, withI18nProps } from '@lingui/react';
|
||||||
|
|
||||||
interface Props {
|
interface Props extends withI18nProps {
|
||||||
sessions: UserSession[];
|
sessions: UserSession[];
|
||||||
|
|
||||||
onSessionRevoke: (id: number) => void;
|
onSessionRevoke: (id: number) => void;
|
||||||
@ -15,7 +16,7 @@ interface State {
|
|||||||
showLogoutModal: boolean;
|
showLogoutModal: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UserSessions extends PureComponent<Props, State> {
|
class BaseUserSessions extends PureComponent<Props, State> {
|
||||||
forceAllLogoutButton = React.createRef<HTMLButtonElement>();
|
forceAllLogoutButton = React.createRef<HTMLButtonElement>();
|
||||||
state: State = {
|
state: State = {
|
||||||
showLogoutModal: false,
|
showLogoutModal: false,
|
||||||
@ -43,7 +44,7 @@ export class UserSessions extends PureComponent<Props, State> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { sessions } = this.props;
|
const { sessions, i18n } = this.props;
|
||||||
const { showLogoutModal } = this.state;
|
const { showLogoutModal } = this.state;
|
||||||
|
|
||||||
const logoutFromAllDevicesClass = css`
|
const logoutFromAllDevicesClass = css`
|
||||||
@ -71,7 +72,7 @@ export class UserSessions extends PureComponent<Props, State> {
|
|||||||
sessions.map((session, index) => (
|
sessions.map((session, index) => (
|
||||||
<tr key={`${session.id}-${index}`}>
|
<tr key={`${session.id}-${index}`}>
|
||||||
<td>{session.isActive ? 'Now' : session.seenAt}</td>
|
<td>{session.isActive ? 'Now' : session.seenAt}</td>
|
||||||
<td>{session.createdAt}</td>
|
<td>{i18n.date(session.createdAt, { dateStyle: 'long' })}</td>
|
||||||
<td>{session.clientIp}</td>
|
<td>{session.clientIp}</td>
|
||||||
<td>{`${session.browser} on ${session.os} ${session.osVersion}`}</td>
|
<td>{`${session.browser} on ${session.os} ${session.osVersion}`}</td>
|
||||||
<td>
|
<td>
|
||||||
@ -113,3 +114,5 @@ export class UserSessions extends PureComponent<Props, State> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const UserSessions = withI18n()(BaseUserSessions);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
import { dateTimeFormat, dateTimeFormatTimeAgo } from '@grafana/data';
|
import { dateTimeFormatTimeAgo } from '@grafana/data';
|
||||||
import { featureEnabled, getBackendSrv, locationService } from '@grafana/runtime';
|
import { featureEnabled, getBackendSrv, locationService } from '@grafana/runtime';
|
||||||
import { ThunkResult, LdapUser, UserSession, UserDTO, AccessControlAction, UserFilter } from 'app/types';
|
import { ThunkResult, LdapUser, UserSession, UserDTO, AccessControlAction, UserFilter } from 'app/types';
|
||||||
|
|
||||||
@ -144,12 +144,13 @@ export function loadUserSessions(userId: number): ThunkResult<void> {
|
|||||||
|
|
||||||
const tokens = await getBackendSrv().get(`/api/admin/users/${userId}/auth-tokens`);
|
const tokens = await getBackendSrv().get(`/api/admin/users/${userId}/auth-tokens`);
|
||||||
tokens.reverse();
|
tokens.reverse();
|
||||||
|
|
||||||
const sessions = tokens.map((session: UserSession) => {
|
const sessions = tokens.map((session: UserSession) => {
|
||||||
return {
|
return {
|
||||||
id: session.id,
|
id: session.id,
|
||||||
isActive: session.isActive,
|
isActive: session.isActive,
|
||||||
seenAt: dateTimeFormatTimeAgo(session.seenAt),
|
seenAt: dateTimeFormatTimeAgo(session.seenAt),
|
||||||
createdAt: dateTimeFormat(session.createdAt, { format: 'MMMM DD, YYYY' }),
|
createdAt: session.createdAt,
|
||||||
clientIp: session.clientIp,
|
clientIp: session.clientIp,
|
||||||
browser: session.browser,
|
browser: session.browser,
|
||||||
browserVersion: session.browserVersion,
|
browserVersion: session.browserVersion,
|
||||||
@ -158,6 +159,7 @@ export function loadUserSessions(userId: number): ThunkResult<void> {
|
|||||||
device: session.device,
|
device: session.device,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
dispatch(userSessionsLoadedAction(sessions));
|
dispatch(userSessionsLoadedAction(sessions));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { UserDTO, UserOrg } from 'app/types';
|
import { UserDTO, UserOrg } from 'app/types';
|
||||||
import { Button, LoadingPlaceholder } from '@grafana/ui';
|
import { Button, LoadingPlaceholder } from '@grafana/ui';
|
||||||
|
import { Trans } from '@lingui/macro';
|
||||||
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
user: UserDTO | null;
|
user: UserDTO | null;
|
||||||
@ -23,13 +25,20 @@ export class UserOrganizations extends PureComponent<Props> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h3 className="page-sub-heading">Organizations</h3>
|
<h3 className="page-sub-heading">
|
||||||
|
<Trans id="user-orgs.title">Organizations</Trans>
|
||||||
|
</h3>
|
||||||
|
|
||||||
<div className="gf-form-group">
|
<div className="gf-form-group">
|
||||||
<table className="filter-table form-inline" aria-label="User organizations table">
|
<table className="filter-table form-inline" data-testid={selectors.components.UserProfile.orgsTable}>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>
|
||||||
<th>Role</th>
|
<Trans id="user-orgs.name-column">Name</Trans>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Trans id="user-orgs.role-column">Role</Trans>
|
||||||
|
</th>
|
||||||
<th />
|
<th />
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -42,7 +51,7 @@ export class UserOrganizations extends PureComponent<Props> {
|
|||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
{org.orgId === user?.orgId ? (
|
{org.orgId === user?.orgId ? (
|
||||||
<Button variant="secondary" size="sm" disabled>
|
<Button variant="secondary" size="sm" disabled>
|
||||||
Current
|
<Trans id="user-orgs.current-org-button">Current</Trans>
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
@ -51,9 +60,8 @@ export class UserOrganizations extends PureComponent<Props> {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
this.props.setUserOrg(org);
|
this.props.setUserOrg(org);
|
||||||
}}
|
}}
|
||||||
aria-label={`Switch to the organization named ${org.name}`}
|
|
||||||
>
|
>
|
||||||
Select
|
<Trans id="user-orgs.select-org-button">Select organisation</Trans>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { Trans } from '@lingui/macro';
|
import { Trans, t } from '@lingui/macro';
|
||||||
import { Button, Field, FieldSet, Form, Icon, Input, Tooltip } from '@grafana/ui';
|
import { Button, Field, FieldSet, Form, Icon, Input, Tooltip } from '@grafana/ui';
|
||||||
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
import { UserDTO } from 'app/types';
|
import { UserDTO } from 'app/types';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
import { ProfileUpdateFields } from './types';
|
import { ProfileUpdateFields } from './types';
|
||||||
@ -22,37 +23,57 @@ export const UserProfileEditForm: FC<Props> = ({ user, isSavingUser, updateProfi
|
|||||||
<Form onSubmit={onSubmitProfileUpdate} validateOn="onBlur">
|
<Form onSubmit={onSubmitProfileUpdate} validateOn="onBlur">
|
||||||
{({ register, errors }) => {
|
{({ register, errors }) => {
|
||||||
return (
|
return (
|
||||||
<FieldSet label={<Trans id="edit-user-profile.title">Edit profile</Trans>}>
|
<FieldSet label={<Trans id="user-profile.title">Edit profile</Trans>}>
|
||||||
<Field label="Name" invalid={!!errors.name} error="Name is required" disabled={disableLoginForm}>
|
<Field
|
||||||
|
label={t({ id: 'user-profile.fields.name-label', message: 'Name' })}
|
||||||
|
invalid={!!errors.name}
|
||||||
|
error={<Trans id="user-profile.fields.name-error">Name is required</Trans>}
|
||||||
|
disabled={disableLoginForm}
|
||||||
|
>
|
||||||
<Input
|
<Input
|
||||||
{...register('name', { required: true })}
|
{...register('name', { required: true })}
|
||||||
id="edit-user-profile-name"
|
id="edit-user-profile-name"
|
||||||
placeholder="Name"
|
placeholder={t({ id: 'user-profile.fields.name-label', message: 'Name' })}
|
||||||
defaultValue={user?.name ?? ''}
|
defaultValue={user?.name ?? ''}
|
||||||
suffix={<InputSuffix />}
|
suffix={<InputSuffix />}
|
||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
<Field label="Email" invalid={!!errors.email} error="Email is required" disabled={disableLoginForm}>
|
|
||||||
|
<Field
|
||||||
|
label={t({ id: 'user-profile.fields.email-label', message: 'Email' })}
|
||||||
|
invalid={!!errors.email}
|
||||||
|
error={<Trans id="user-profile.fields.email-error">Email is required</Trans>}
|
||||||
|
disabled={disableLoginForm}
|
||||||
|
>
|
||||||
<Input
|
<Input
|
||||||
{...register('email', { required: true })}
|
{...register('email', { required: true })}
|
||||||
id="edit-user-profile-email"
|
id="edit-user-profile-email"
|
||||||
placeholder="Email"
|
placeholder={t({ id: 'user-profile.fields.email-label', message: 'Email' })}
|
||||||
defaultValue={user?.email ?? ''}
|
defaultValue={user?.email ?? ''}
|
||||||
suffix={<InputSuffix />}
|
suffix={<InputSuffix />}
|
||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
<Field label="Username" disabled={disableLoginForm}>
|
|
||||||
|
<Field
|
||||||
|
label={t({ id: 'user-profile.fields.username-label', message: 'Username' })}
|
||||||
|
disabled={disableLoginForm}
|
||||||
|
>
|
||||||
<Input
|
<Input
|
||||||
{...register('login')}
|
{...register('login')}
|
||||||
id="edit-user-profile-username"
|
id="edit-user-profile-username"
|
||||||
defaultValue={user?.login ?? ''}
|
defaultValue={user?.login ?? ''}
|
||||||
placeholder="Username"
|
placeholder={t({ id: 'user-profile.fields.username-label', message: 'Username' })}
|
||||||
suffix={<InputSuffix />}
|
suffix={<InputSuffix />}
|
||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
<div className="gf-form-button-row">
|
<div className="gf-form-button-row">
|
||||||
<Button variant="primary" disabled={isSavingUser} aria-label="Edit user profile save button">
|
<Button
|
||||||
Save
|
variant="primary"
|
||||||
|
disabled={isSavingUser}
|
||||||
|
data-testid={selectors.components.UserProfile.profileSaveButton}
|
||||||
|
>
|
||||||
|
<Trans id="common.save">Save</Trans>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</FieldSet>
|
</FieldSet>
|
||||||
|
@ -4,6 +4,7 @@ import userEvent from '@testing-library/user-event';
|
|||||||
import { within } from '@testing-library/dom';
|
import { within } from '@testing-library/dom';
|
||||||
import { OrgRole } from '@grafana/data';
|
import { OrgRole } from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
import TestProvider from '../../../test/helpers/TestProvider';
|
||||||
|
|
||||||
import { Props, UserProfileEditPage } from './UserProfileEditPage';
|
import { Props, UserProfileEditPage } from './UserProfileEditPage';
|
||||||
import { initialUserState } from './state/reducers';
|
import { initialUserState } from './state/reducers';
|
||||||
@ -90,28 +91,28 @@ function getSelectors() {
|
|||||||
const dashboardSelect = () => screen.getByTestId('User preferences home dashboard drop down');
|
const dashboardSelect = () => screen.getByTestId('User preferences home dashboard drop down');
|
||||||
const timepickerSelect = () => screen.getByTestId(selectors.components.TimeZonePicker.containerV2);
|
const timepickerSelect = () => screen.getByTestId(selectors.components.TimeZonePicker.containerV2);
|
||||||
const teamsTable = () => screen.getByRole('table', { name: /user teams table/i });
|
const teamsTable = () => screen.getByRole('table', { name: /user teams table/i });
|
||||||
const orgsTable = () => screen.getByRole('table', { name: /user organizations table/i });
|
const orgsTable = () => screen.getByTestId(selectors.components.UserProfile.orgsTable);
|
||||||
const sessionsTable = () => screen.getByRole('table', { name: /user sessions table/i });
|
const sessionsTable = () => screen.getByTestId(selectors.components.UserProfile.sessionsTable);
|
||||||
return {
|
return {
|
||||||
name: () => screen.getByRole('textbox', { name: /^name$/i }),
|
name: () => screen.getByRole('textbox', { name: /^name$/i }),
|
||||||
email: () => screen.getByRole('textbox', { name: /email/i }),
|
email: () => screen.getByRole('textbox', { name: /email/i }),
|
||||||
username: () => screen.getByRole('textbox', { name: /username/i }),
|
username: () => screen.getByRole('textbox', { name: /username/i }),
|
||||||
saveProfile: () => screen.getByRole('button', { name: /edit user profile save button/i }),
|
saveProfile: () => screen.getByTestId(selectors.components.UserProfile.profileSaveButton),
|
||||||
dashboardSelect,
|
dashboardSelect,
|
||||||
dashboardValue: () => within(dashboardSelect()).getByText(/default/i),
|
dashboardValue: () => within(dashboardSelect()).getByText(/default/i),
|
||||||
timepickerSelect,
|
timepickerSelect,
|
||||||
timepickerValue: () => within(timepickerSelect()).getByText(/coordinated universal time/i),
|
timepickerValue: () => within(timepickerSelect()).getByText(/coordinated universal time/i),
|
||||||
savePreferences: () => screen.getByRole('button', { name: /user preferences save button/i }),
|
savePreferences: () => screen.getByTestId(selectors.components.UserProfile.preferencesSaveButton),
|
||||||
teamsTable,
|
teamsTable,
|
||||||
teamsRow: () => within(teamsTable()).getByRole('row', { name: /team one team.one@test\.com 2000/i }),
|
teamsRow: () => within(teamsTable()).getByRole('row', { name: /team one team.one@test\.com 2000/i }),
|
||||||
orgsTable,
|
orgsTable,
|
||||||
orgsEditorRow: () => within(orgsTable()).getByRole('row', { name: /main editor current/i }),
|
orgsEditorRow: () => within(orgsTable()).getByRole('row', { name: /main editor current/i }),
|
||||||
orgsViewerRow: () => within(orgsTable()).getByRole('row', { name: /second viewer select/i }),
|
orgsViewerRow: () => within(orgsTable()).getByRole('row', { name: /second viewer select organisation/i }),
|
||||||
orgsAdminRow: () => within(orgsTable()).getByRole('row', { name: /third admin select/i }),
|
orgsAdminRow: () => within(orgsTable()).getByRole('row', { name: /third admin select organisation/i }),
|
||||||
sessionsTable,
|
sessionsTable,
|
||||||
sessionsRow: () =>
|
sessionsRow: () =>
|
||||||
within(sessionsTable()).getByRole('row', {
|
within(sessionsTable()).getByRole('row', {
|
||||||
name: /now 2021-01-01 04:00:00 localhost chrome on mac os x 11/i,
|
name: /now January 1, 2021 localhost chrome on mac os x 11/i,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -125,7 +126,11 @@ async function getTestContext(overrides: Partial<Props> = {}) {
|
|||||||
const searchSpy = jest.spyOn(backendSrv, 'search').mockResolvedValue([]);
|
const searchSpy = jest.spyOn(backendSrv, 'search').mockResolvedValue([]);
|
||||||
|
|
||||||
const props = { ...defaultProps, ...overrides };
|
const props = { ...defaultProps, ...overrides };
|
||||||
const { rerender } = render(<UserProfileEditPage {...props} />);
|
const { rerender } = render(
|
||||||
|
<TestProvider>
|
||||||
|
<UserProfileEditPage {...props} />
|
||||||
|
</TestProvider>
|
||||||
|
);
|
||||||
|
|
||||||
await waitFor(() => expect(props.initUserProfilePage).toHaveBeenCalledTimes(1));
|
await waitFor(() => expect(props.initUserProfilePage).toHaveBeenCalledTimes(1));
|
||||||
|
|
||||||
@ -253,7 +258,7 @@ describe('UserProfileEditPage', () => {
|
|||||||
const { props } = await getTestContext();
|
const { props } = await getTestContext();
|
||||||
const orgsAdminSelectButton = () =>
|
const orgsAdminSelectButton = () =>
|
||||||
within(getSelectors().orgsAdminRow()).getByRole('button', {
|
within(getSelectors().orgsAdminRow()).getByRole('button', {
|
||||||
name: /switch to the organization named Third/i,
|
name: /select organisation/i,
|
||||||
});
|
});
|
||||||
|
|
||||||
userEvent.click(orgsAdminSelectButton());
|
userEvent.click(orgsAdminSelectButton());
|
||||||
|
@ -1,19 +1,22 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { UserSession } from 'app/types';
|
import { UserSession } from 'app/types';
|
||||||
import { Button, Icon, LoadingPlaceholder } from '@grafana/ui';
|
import { Button, Icon, LoadingPlaceholder } from '@grafana/ui';
|
||||||
|
import { withI18n, withI18nProps } from '@lingui/react';
|
||||||
|
import { t, Trans } from '@lingui/macro';
|
||||||
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
export interface Props {
|
interface Props extends withI18nProps {
|
||||||
sessions: UserSession[];
|
sessions: UserSession[];
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
revokeUserSession: (tokenId: number) => void;
|
revokeUserSession: (tokenId: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UserSessions extends PureComponent<Props> {
|
class UserSessions extends PureComponent<Props> {
|
||||||
render() {
|
render() {
|
||||||
const { isLoading, sessions, revokeUserSession } = this.props;
|
const { isLoading, sessions, revokeUserSession, i18n } = this.props;
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <LoadingPlaceholder text="Loading sessions..." />;
|
return <LoadingPlaceholder text={<Trans id="user-sessions.loading">Loading sessions...</Trans>} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -22,13 +25,21 @@ export class UserSessions extends PureComponent<Props> {
|
|||||||
<>
|
<>
|
||||||
<h3 className="page-sub-heading">Sessions</h3>
|
<h3 className="page-sub-heading">Sessions</h3>
|
||||||
<div className="gf-form-group">
|
<div className="gf-form-group">
|
||||||
<table className="filter-table form-inline" aria-label="User sessions table">
|
<table className="filter-table form-inline" data-testid={selectors.components.UserProfile.sessionsTable}>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Last seen</th>
|
<th>
|
||||||
<th>Logged on</th>
|
<Trans id="user-session.seen-at-column">Last seen</Trans>
|
||||||
<th>IP address</th>
|
</th>
|
||||||
<th>Browser & OS</th>
|
<th>
|
||||||
|
<Trans id="user-session.created-at-column">Logged on</Trans>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Trans id="user-session.ip-column">IP address</Trans>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Trans id="user-session.browser-column">Browser & OS</Trans>
|
||||||
|
</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -36,7 +47,7 @@ export class UserSessions extends PureComponent<Props> {
|
|||||||
{sessions.map((session: UserSession, index) => (
|
{sessions.map((session: UserSession, index) => (
|
||||||
<tr key={index}>
|
<tr key={index}>
|
||||||
{session.isActive ? <td>Now</td> : <td>{session.seenAt}</td>}
|
{session.isActive ? <td>Now</td> : <td>{session.seenAt}</td>}
|
||||||
<td>{session.createdAt}</td>
|
<td>{i18n.date(session.createdAt, { dateStyle: 'long' })}</td>
|
||||||
<td>{session.clientIp}</td>
|
<td>{session.clientIp}</td>
|
||||||
<td>
|
<td>
|
||||||
{session.browser} on {session.os} {session.osVersion}
|
{session.browser} on {session.os} {session.osVersion}
|
||||||
@ -46,7 +57,7 @@ export class UserSessions extends PureComponent<Props> {
|
|||||||
size="sm"
|
size="sm"
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
onClick={() => revokeUserSession(session.id)}
|
onClick={() => revokeUserSession(session.id)}
|
||||||
aria-label="Revoke user session"
|
aria-label={t({ id: 'user-session.revoke', message: 'Revoke user session' })}
|
||||||
>
|
>
|
||||||
<Icon name="power" />
|
<Icon name="power" />
|
||||||
</Button>
|
</Button>
|
||||||
@ -63,4 +74,4 @@ export class UserSessions extends PureComponent<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default UserSessions;
|
export default withI18n()(UserSessions);
|
||||||
|
@ -166,7 +166,7 @@ describe('userReducer', () => {
|
|||||||
browserVersion: '90',
|
browserVersion: '90',
|
||||||
osVersion: '95',
|
osVersion: '95',
|
||||||
clientIp: '192.168.1.1',
|
clientIp: '192.168.1.1',
|
||||||
createdAt: 'December 31, 2020',
|
createdAt: '2021-01-01 04:00:00',
|
||||||
device: 'Computer',
|
device: 'Computer',
|
||||||
os: 'Windows',
|
os: 'Windows',
|
||||||
isActive: false,
|
isActive: false,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { isEmpty, isString, set } from 'lodash';
|
import { isEmpty, isString, set } from 'lodash';
|
||||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||||
import { dateTimeFormat, dateTimeFormatTimeAgo, setWeekStart, TimeZone } from '@grafana/data';
|
import { dateTimeFormatTimeAgo, setWeekStart, TimeZone } from '@grafana/data';
|
||||||
|
|
||||||
import { Team, ThunkResult, UserDTO, UserOrg, UserSession } from 'app/types';
|
import { Team, ThunkResult, UserDTO, UserOrg, UserSession } from 'app/types';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
@ -78,7 +78,7 @@ export const slice = createSlice({
|
|||||||
id: session.id,
|
id: session.id,
|
||||||
isActive: session.isActive,
|
isActive: session.isActive,
|
||||||
seenAt: dateTimeFormatTimeAgo(session.seenAt),
|
seenAt: dateTimeFormatTimeAgo(session.seenAt),
|
||||||
createdAt: dateTimeFormat(session.createdAt, { format: 'MMMM DD, YYYY' }),
|
createdAt: session.createdAt,
|
||||||
clientIp: session.clientIp,
|
clientIp: session.clientIp,
|
||||||
browser: session.browser,
|
browser: session.browser,
|
||||||
browserVersion: session.browserVersion,
|
browserVersion: session.browserVersion,
|
||||||
|
@ -13,6 +13,118 @@ msgstr ""
|
|||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Plural-Forms: \n"
|
"Plural-Forms: \n"
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
#: public/app/features/profile/UserProfileEditForm.tsx
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
msgid "edit-user-profile.title"
|
msgid "common.save"
|
||||||
|
msgstr "Save"
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-dashboard.fields.timezone-label"
|
||||||
|
msgstr "Timezone"
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.home-dashboard-label"
|
||||||
|
msgstr "Home Dashboard"
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.home-dashboard-placeholder"
|
||||||
|
msgstr "Choose default dashboard"
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.home-dashboard-tooltip"
|
||||||
|
msgstr "Not finding the dashboard you want? Star it first, then it should appear in this select box."
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.theme-label"
|
||||||
|
msgstr "UI Theme"
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.week-start-label"
|
||||||
|
msgstr "Week start"
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.theme.dark-label"
|
||||||
|
msgstr "Dark"
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.theme.default-label"
|
||||||
|
msgstr "Default"
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.theme.light-label"
|
||||||
|
msgstr "Light"
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.title"
|
||||||
|
msgstr "Preferences"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.current-org-button"
|
||||||
|
msgstr "Current"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.name-column"
|
||||||
|
msgstr "Name"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.role-column"
|
||||||
|
msgstr "Role"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.select-org-button"
|
||||||
|
msgstr "Select"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.title"
|
||||||
|
msgstr "Organizations"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.email-error"
|
||||||
|
msgstr "Email is required"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.email-label"
|
||||||
|
msgstr "Email"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.name-error"
|
||||||
|
msgstr "Name is required"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.name-label"
|
||||||
|
msgstr "Name"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.username-label"
|
||||||
|
msgstr "Username"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.title"
|
||||||
msgstr "Edit profile"
|
msgstr "Edit profile"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.browser-column"
|
||||||
|
msgstr "Browser & OS"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.created-at-column"
|
||||||
|
msgstr "Logged on"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.ip-column"
|
||||||
|
msgstr "IP address"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.revoke"
|
||||||
|
msgstr "Revoke user session"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.seen-at-column"
|
||||||
|
msgstr "Last seen"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-sessions.loading"
|
||||||
|
msgstr "Loading sessions..."
|
||||||
|
@ -13,6 +13,118 @@ msgstr ""
|
|||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Plural-Forms: \n"
|
"Plural-Forms: \n"
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
#: public/app/features/profile/UserProfileEditForm.tsx
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
msgid "edit-user-profile.title"
|
msgid "common.save"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-dashboard.fields.timezone-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.home-dashboard-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.home-dashboard-placeholder"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.home-dashboard-tooltip"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.theme-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.week-start-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.theme.dark-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.theme.default-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.theme.light-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.current-org-button"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.name-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.role-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.select-org-button"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.email-error"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.email-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.name-error"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.name-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.username-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.title"
|
||||||
msgstr "Editar perfil"
|
msgstr "Editar perfil"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.browser-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.created-at-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.ip-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.revoke"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.seen-at-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-sessions.loading"
|
||||||
|
msgstr ""
|
||||||
|
@ -13,6 +13,118 @@ msgstr ""
|
|||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Plural-Forms: \n"
|
"Plural-Forms: \n"
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
#: public/app/features/profile/UserProfileEditForm.tsx
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
msgid "edit-user-profile.title"
|
msgid "common.save"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-dashboard.fields.timezone-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.home-dashboard-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.home-dashboard-placeholder"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.home-dashboard-tooltip"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.theme-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.week-start-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.theme.dark-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.theme.default-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.theme.light-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.current-org-button"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.name-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.role-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.select-org-button"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.email-error"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.email-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.name-error"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.name-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.username-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.title"
|
||||||
msgstr "Editer le profil"
|
msgstr "Editer le profil"
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.browser-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.created-at-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.ip-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.revoke"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.seen-at-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-sessions.loading"
|
||||||
|
msgstr ""
|
||||||
|
130
public/locales/pseudo-LOCALE/messages.po
Normal file
130
public/locales/pseudo-LOCALE/messages.po
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"POT-Creation-Date: 2022-01-10 10:42+0000\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Generator: @lingui/cli\n"
|
||||||
|
"Language: pseudo-LOCALE\n"
|
||||||
|
"Project-Id-Version: \n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"PO-Revision-Date: \n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: \n"
|
||||||
|
"Plural-Forms: \n"
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "common.save"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-dashboard.fields.timezone-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.home-dashboard-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.home-dashboard-placeholder"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.home-dashboard-tooltip"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.theme-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.fields.week-start-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.theme.dark-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.theme.default-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.theme.light-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/core/components/SharedPreferences/SharedPreferences.tsx
|
||||||
|
msgid "shared-preferences.title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.current-org-button"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.name-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.role-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.select-org-button"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserOrganizations.tsx
|
||||||
|
msgid "user-orgs.title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.email-error"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.email-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.name-error"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.name-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.fields.username-label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserProfileEditForm.tsx
|
||||||
|
msgid "user-profile.title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.browser-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.created-at-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.ip-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.revoke"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-session.seen-at-column"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: public/app/features/profile/UserSessions.tsx
|
||||||
|
msgid "user-sessions.loading"
|
||||||
|
msgstr ""
|
8
public/test/helpers/TestProvider.tsx
Normal file
8
public/test/helpers/TestProvider.tsx
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { I18nProvider } from '../../app/core/localisation';
|
||||||
|
|
||||||
|
const TestProvider: React.FC = ({ children }) => {
|
||||||
|
return <I18nProvider>{children}</I18nProvider>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TestProvider;
|
@ -15,3 +15,7 @@ export const Select: React.FC = () => {
|
|||||||
export const SelectOrdinal: React.FC = () => {
|
export const SelectOrdinal: React.FC = () => {
|
||||||
throw new Error('SelectOrdinal mock not implemented yet');
|
throw new Error('SelectOrdinal mock not implemented yet');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const t = (msg: string | { message: string }) => {
|
||||||
|
return typeof msg === 'string' ? msg : msg.message;
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user