Skip to content

Commit

Permalink
feat: refactor tolgee UI
Browse files Browse the repository at this point in the history
  • Loading branch information
stepan662 committed Apr 5, 2024
1 parent 46546a1 commit b4c3c7d
Show file tree
Hide file tree
Showing 16 changed files with 149 additions and 172 deletions.
1 change: 1 addition & 0 deletions packages/core/src/Controller/Controller.ts
Expand Up @@ -207,6 +207,7 @@ export function Controller({ options }: StateServiceProps) {
changeTranslation: changeTranslation,
getTranslationNs: getTranslationNs,
getDefaultAndFallbackNs: getDefaultAndFallbackNs,
findPositions: pluginService.findPositions,
async changeLanguage(language: string) {
if (
state.getPendingLanguage() === language &&
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/Controller/Plugins/Plugins.ts
Expand Up @@ -57,7 +57,7 @@ export function Plugins(
languageStorage: undefined as LanguageStorageMiddleware | undefined,
};

const onClick: TranslationOnClick = async ({ keysAndDefaults, event }) => {
const onClick: TranslationOnClick = async ({ keysAndDefaults, target }) => {
const withNs: UiKeyOption[] = keysAndDefaults.map(
({ key, ns, defaultValue }) => {
return {
Expand All @@ -72,7 +72,7 @@ export function Plugins(
};
}
);
instances.ui?.handleElementClick(withNs, event);
instances.ui?.handleElementClick(withNs, target);
};

const findPositions: FindPositionsInterface = (key, ns) => {
Expand Down Expand Up @@ -185,7 +185,7 @@ export function Plugins(

const self = Object.freeze({
addPlugin,

findPositions: findPositions,
run() {
const { apiKey, apiUrl, projectId, observerOptions } =
getInitialOptions();
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/TolgeeCore.ts
Expand Up @@ -171,6 +171,11 @@ function createTolgee(options: TolgeeOptions) {
*/
highlight: controller.highlight,

/**
* Find positions of keys in the DOM.
*/
findPositions: controller.findPositions,

/**
* @return current Tolgee options.
*/
Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/types/plugin.ts
Expand Up @@ -129,7 +129,7 @@ export type FormatterMiddleware = {

export type TranslationOnClick = (data: {
keysAndDefaults: KeyAndParams[];
event: any;
target: HTMLElement;
}) => void;

export type Highlighter = {
Expand Down Expand Up @@ -172,7 +172,10 @@ export type UiKeyOption = {
export type UiMiddleware = (props: UiProps) => UiInterface;

export interface UiInterface {
handleElementClick(keysAndDefaults: UiKeyOption[], event: any): Promise<void>;
handleElementClick(
keysAndDefaults: UiKeyOption[],
target: HTMLElement
): Promise<void>;
}

export type PluginTools = Readonly<{
Expand Down
29 changes: 27 additions & 2 deletions packages/web/src/app/App.tsx
@@ -1,12 +1,37 @@
import { useEffect } from 'react';
import { useTolgee } from './basicTolgee';
import { secrets, tolgee, useTolgee } from './basicTolgee';
import { styled } from '@mui/material';
import { UI } from '../package/ui';

const StyledContainer = styled('div')`
margin: 100px auto;
max-width: 300px;
`;

const ui = new UI({
...secrets,
projectId: undefined,
highlight: tolgee.highlight,
findPositions: tolgee.findPositions,
changeTranslation: tolgee.changeTranslation,
onPermanentChange: undefined,
});

export const App = () => {
const tolgee = useTolgee(['update', 'language']);

useEffect(() => {
tolgee.run();
ui.renderViewer('on-the-road-title', 'Default value', [''], '');
}, []);

return <div>{tolgee.t('on-the-road-title')}</div>;
return (
<StyledContainer>
<div>{tolgee.t('on-the-road-title')}</div>
<div>
{tolgee.t('on-the-road-title')}
{tolgee.t('on-the-road-subtitle')}
</div>
</StyledContainer>
);
};
10 changes: 7 additions & 3 deletions packages/web/src/app/basicTolgee.ts
Expand Up @@ -2,13 +2,17 @@ import { TolgeeEvent, TolgeeInstance } from '@tolgee/core';
import { useCallback, useEffect, useState } from 'react';
import { BackendFetch, DevTools, Tolgee } from '../package/entry-development';

const tolgee = Tolgee()
export const secrets = {
apiUrl: import.meta.env.VITE_APP_TOLGEE_API_URL,
apiKey: import.meta.env.VITE_APP_TOLGEE_API_KEY,
};

export const tolgee = Tolgee()
.use(DevTools())
.use(BackendFetch())
.init({
...secrets,
availableLanguages: ['en', 'cs', 'fr', 'de'],
apiUrl: import.meta.env.VITE_APP_TOLGEE_API_URL,
apiKey: import.meta.env.VITE_APP_TOLGEE_API_KEY,
defaultLanguage: 'en',
});

Expand Down
4 changes: 2 additions & 2 deletions packages/web/src/package/observers/general/ElementRegistry.ts
Expand Up @@ -25,10 +25,10 @@ export function ElementRegistry(
const eventHandler = MouseEventHandler({
highlightKeys: options.highlightKeys,
elementStore,
onClick(event, el) {
onClick(el) {
const meta = elementStore.get(el)!;
onClick({
event,
target: el as HTMLElement,
keysAndDefaults: getKeysAndDefaults(meta),
});
},
Expand Down
Expand Up @@ -20,7 +20,7 @@ type Coordinates = {
type Props = {
highlightKeys: ModifierKey[];
elementStore: ElementStoreType;
onClick: (event: MouseEvent, el: TolgeeElement) => void;
onClick: (el: TolgeeElement) => void;
options: ObserverOptionsInternal;
};

Expand Down Expand Up @@ -136,7 +136,7 @@ export function MouseEventHandler({
updateModifiers(e);
updateCursorPosition({ x: e.clientX, y: e.clientY });
if (areKeysDown() && highlighted) {
onClick(e, highlighted);
onClick(highlighted);
unhighlight();
}
}
Expand Down
Expand Up @@ -21,19 +21,13 @@ test('it selects the key', async () => {
findPositions: () => [],
onPermanentChange: () => {},
});
const mouseEvent = new MouseEvent('click');

Object.defineProperty(mouseEvent, 'target', {
writable: false,
value: document.body,
});

const keys = new Map([
['key 1', 'Key 1'],
['key 2', 'Key 2'],
]);
// open context menu and wait for select
const resultPromise = ui.getKey({ openEvent: mouseEvent, keys: keys });
const resultPromise = ui.getKey({ target: document.body, keys: keys });

await sleep(10);

Expand Down
24 changes: 16 additions & 8 deletions packages/web/src/package/ui/KeyContextMenu/KeyContextMenu.tsx
Expand Up @@ -27,23 +27,31 @@ const ScKey = styled('div')`
font-family: Monospace, 'Courier New', Courier;
`;

export interface KeyContextMenuParams {
openEvent: MouseEvent;
export interface KeyContextMenuProps {
target: HTMLElement;
keys: Map<string, string | undefined>;
onSelect: (key: string | undefined) => void;
}

export type KeyContextMenuState = Partial<KeyContextMenuParams> & {
export type KeyContextMenuState = Partial<KeyContextMenuProps> & {
opened: boolean;
};

export class KeyContextMenu extends React.Component {
state: KeyContextMenuState & { opened: boolean } = {
type Props = {
initialState: KeyContextMenuProps;
};

export class KeyContextMenu extends React.Component<
Props,
KeyContextMenuState
> {
state: KeyContextMenuState = {
opened: false,
};

async show(params: KeyContextMenuParams) {
this.setState({ ...params, opened: true });
constructor(props: Props) {
super(props);
this.state = { ...props.initialState, opened: true };
}

keyDown = (e: KeyboardEvent) => {
Expand All @@ -68,7 +76,7 @@ export class KeyContextMenu extends React.Component {
<Menu
disablePortal
disableEnforceFocus
anchorEl={this.state.openEvent?.target as Element}
anchorEl={this.state.target}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
Expand Down
92 changes: 34 additions & 58 deletions packages/web/src/package/ui/KeyDialog/KeyDialog.tsx
@@ -1,77 +1,53 @@
import * as React from 'react';
import type { UiProps } from '@tolgee/core';

import { BodyEnd } from '../common/BodyEnd';
import { useEffect, useState } from 'react';
import { QueryProvider } from '../client/QueryProvider';
import { DialogProvider } from './dialogContext';
import { TranslationDialog } from './TranslationDialog';
import { QueryProvider } from '../../ui/client/QueryProvider';

export type ComponentDependencies = UiProps;

export type Props = UiProps;

type State = {
type KeyData = {
key: null | string;
defaultValue: undefined | string;
dialogOpened: boolean;
fallbackNamespaces: string[];
namespace: string;
};

export class KeyDialog extends React.Component<Props, State> {
state = {
key: null,
defaultValue: undefined,
dialogOpened: false,
fallbackNamespaces: [],
namespace: '',
};
export type Props = {
uiProps: UiProps;
keyData: KeyData;
};

constructor(props: Props) {
super(props);
}
export const KeyDialog = ({ uiProps, keyData }: Props) => {
const [open, setOpen] = useState(true);
useEffect(() => {
setOpen(true);
}, [keyData]);

public translationEdit(
key: string,
defaultValue: string | undefined,
fallbackNamespaces: string[],
namespace: string
) {
this.setState({
...this.state,
dialogOpened: true,
defaultValue: defaultValue,
key,
fallbackNamespaces,
namespace,
});
function handleClose() {
setOpen(false);
}

public render = () => (
<BodyEnd>
<QueryProvider
apiUrl={this.props.apiUrl}
apiKey={this.props.apiKey}
projectId={this.props.projectId}
>
{this.state.dialogOpened && (
<DialogProvider
uiProps={this.props}
defaultValue={this.state.defaultValue || ''}
open={this.state.dialogOpened}
keyName={this.state.key!}
fallbackNamespaces={this.state.fallbackNamespaces}
namespace={this.state.namespace}
onClose={this.onClose}
>
<TranslationDialog />
</DialogProvider>
)}
</QueryProvider>
</BodyEnd>
return (
<QueryProvider
apiUrl={uiProps.apiUrl}
apiKey={uiProps.apiKey}
projectId={uiProps.projectId}
>
{open && (
<DialogProvider
uiProps={uiProps}
defaultValue={keyData.defaultValue || ''}
keyName={keyData.key!}
fallbackNamespaces={keyData.fallbackNamespaces}
namespace={keyData.namespace}
onClose={handleClose}
>
<TranslationDialog />
</DialogProvider>
)}
</QueryProvider>
);

private onClose = () => {
this.setState({ ...this.state, dialogOpened: false });
};
}
};
Expand Up @@ -33,7 +33,7 @@ export const ControlsButton: React.FC<Props> = function ControlsButton({
</StyledIconButton>
);

return tooltip ? (
return tooltip && !props.disabled ? (
<Tooltip
disableInteractive
title={tooltip}
Expand Down
Expand Up @@ -10,7 +10,6 @@ export const TranslationDialogWrapper = ({
}: React.PropsWithChildren) => {
const { onClose } = useDialogActions();
const useBrowserWindow = useDialogContext((c) => c.useBrowserWindow);
const open = useDialogContext((c) => c.open);
const takingScreenshot = useDialogContext((c) => c.takingScreenshot);

return (
Expand All @@ -20,9 +19,9 @@ export const TranslationDialogWrapper = ({
) : (
<Dialog
disableRestoreFocus
disablePortal
disableEnforceFocus
open={open}
disablePortal
open={true}
onClose={onClose}
aria-labelledby="form-dialog-title"
maxWidth="lg"
Expand Down

0 comments on commit b4c3c7d

Please sign in to comment.