Skip to content

Commit

Permalink
[v12] Connect: Allow config customization (#23197)
Browse files Browse the repository at this point in the history
* Connect: Prepare keyboard shortcuts configuration (#22193)

* Make naming around keyboard shortcuts more consistent

Previously, we used words like: "key", "type", "shortcut" which were really confusing (and I wrote this code), because it was hard to tell what exactly they describe.
From now, we will use only "accelerator" (borrowed from Electron) and "action" words.
For example, in a shortcut "Command+1": "tab-1":
- "Command+1" is "accelerator"
- "tab-1" is "action"

* Use "+" instead of "-" as a separator

With "-" we are not able to use this symbol as a valid key code.

* Rename some config keys to follow the same naming pattern

* Rename keyboard shortcuts to match config keys

* Extract `mapAcceleratorsToActions` to a function

* Rename other "keyboard shortcuts" to "accelerators" and "actions"

(cherry picked from commit 717c4fa)

* Connect: Enable keyboard shortcuts configuration (#22194)

* Use event.code for non A-z keys

Without this fix, shortcuts like "Shift+1" can't work, because the reported character is "!".

* Add Zod schema to validate keyboard shortcuts

* Render better formatted error notification, add a link to docs

* Notify about duplicated accelerators

* Improve the error message for re-parsing failure (it can happen when a default value does not pass validation)

* A bunch of renames

* Allow spaces in accelerators

* Rename `isContentAnObject`

* Allow `Notification` to render links and lists

* Split by optional whitespace and "+"

* Allow lowercase letters

* Require a modifier for non-function keys

* Move VALID_SHORTCUT_MESSAGE to `initUi`

* Always return from `getDuplicateAccelerators`

* Use 'Cmd' and 'Ctrl' for mac

* Add comments

* Fix notification not rendering content

* Add more comments, rename `getKeyCode` to `getKeyName`

* Fix incorrect size of <Link> text

* Remove "expected" prefix

* Revert `typeof content === 'object'` in `Notification`

* Remove a comment about disabled keys in `ConfigService`, add a note about `keymap.` prefix

* Improve `getKeyName` comment

* Extract an inline object to a variable in `getKeyName`

* Fix notification list padding

* Change text for doc link & description for config error

* Improve comment for `getKeyName`

* Remove special formatting for list === 1 in `Notification`

* Print valid modifiers

* Call `getKeyboardShortcutSchema()` once

* Collect issues from all validations, run `invalidModifiers` through a set

* Change error message for `missingModifierIssue`

* Convert duplicates warning to error

* Define ALLOWED_KEY_CODES in a more concise way

* Support both `IntlBackslash` and `Backquote`

* Restore modifiers for mac to full spelling, sort them in order recommended by platform guidelines

* Fix old comment about the shortcuts order

---------

Co-authored-by: Rafał Cieślak <[email protected]>
(cherry picked from commit 4830ea1)

* Connect: Generate json schema for app config (#22538)

* Rename `putAllSync` to `writeSync`

* Extend `FileStorage` with functions to replace an entire state and return file path used to create it

* Add `updateJsonSchema` function

* Generate schema for the app config

* Always return a string from `createMockFileStorage().getFilePath()`

* Add missing license headers

* Rename 'teleport_connect_config_schema.json' to 'schema_app_config.json'

* Rename `getKeyboardShortcutDescription` to `getShortcutDesc`

* Rename `keyboardShortcutSchema` to `shortcutSchema`

* Update a valid shortcut message

* Rename `configJsonSchemaFile` to `jsonSchema`

* Simplify `updateJsonSchema`

* Set `$refStrategy` to none

* Add missing description for `usageReporting.enabled`

* Bump zod to the latest (improves TS performance)

* Move `configService` implementation to `configStore`

* Rename `configStore` to `configService`

* Move `updateJsonSchema` to `createConfigService`

* Move `validateStoredConfig` outside `createConfigService`

* Rename `createAppConfigSchema.ts` to `appConfigSchema.ts`, `getKeyboardShortcutSchema.ts` to `keyboardShortcutSchema.ts`

* Export `createKeyboardShortcutSchema`

* Add license header

(cherry picked from commit 9967149)

* Connect: Show config file errors (#22728)

* Add a function that returns error that might happen during loading the file

* Return validation and file loading errors from `ConfigService`

* Discard file storage updates when the file was not loaded correctly

* Do not show usage reporting dialog when the file was not loaded correctly

* Make title of notifications a little bit smaller, so longer titles do not look weird

* Get rid of sync fs functions wherever possible in file storage

* Move error handling code to `createFileStorage`

* Improve `getConfigError` comment

* Rename `discardUpdatesWhenLoadingFileFailed` to `discardUpdatesOnLoadError`

* Fix the error message in `notifyAboutConfigErrors`

* Revert "Make title of notifications a little bit smaller, so longer titles do not look weird"

* Make `writeSync` async too

* Return `unknown` from `FileStorage.get`

* Add a TODO comment about createFileStorage type

* Add "the" to "Using default config instead"

* Remove `toString()`

---------

Co-authored-by: Rafał Cieślak <[email protected]>

(cherry picked from commit 17ff6d6)

* Connect: Add "Open Config File" item to menu (#22730)

* Expose `openConfigFile` IPC

* Add "Open Config File" to `NavigationMenu`

* Make `NavigationMenu` more concise

* Remove unused imports

* Call "three dots" menu "More Options" to make it easier to refer to in the docs

* Show a notification with a config file path

* Render the icon component only in `NavigationItem`

* Render the separator only with access request items

* Use just `separator` string instead of an object

* Render `StyledListItem` as a button

* Shorten the notification

Co-authored-by: Rafał Cieślak <[email protected]>

---------

Co-authored-by: Rafał Cieślak <[email protected]>
(cherry picked from commit af9e0ed)

* Add docs for Connect config  (#22898)

* Rename old "quick input" to the current "command bar" feature name

* Remove 'Droid Sans Fallback' from Linux fonts

* Add docs for config

* Link to the proper documentation section

* Apply suggestions from @ravicious and @ibeckermayer

Co-authored-by: Rafał Cieślak <[email protected]>
Co-authored-by: Isaiah Becker-Mayer <[email protected]>

* Adjust property descriptions with the names used in User Interface

* Drop `Courier New`

* Simplify `$schema` description

* Fix lint issues

* Add a break line after each heading

Co-authored-by: Paul Gottschling <[email protected]>

* Schema should not be modified

* Config file is created on first launch

---------

Co-authored-by: Rafał Cieślak <[email protected]>
Co-authored-by: Isaiah Becker-Mayer <[email protected]>
Co-authored-by: Paul Gottschling <[email protected]>
(cherry picked from commit 2d387e1)
  • Loading branch information
gzdunek authored Mar 17, 2023
1 parent fe5bff3 commit 221a413
Show file tree
Hide file tree
Showing 49 changed files with 1,685 additions and 703 deletions.
71 changes: 59 additions & 12 deletions docs/pages/connect-your-client/teleport-connect.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -158,27 +158,74 @@ installation directory to the `Path` user environment variable.
</TabItem>
</Tabs>

## Configuration

Teleport Connect can be configured by editing the `app_config.json` file, which it creates on first launch.
To open it, click the More Options icon `` -> Open Config File.
The file will open in your default editor.

<Admonition
type="note"
title="Note"
>
Any changes to the config file will take effect at the next launch.
</Admonition>

Below is the list of the supported config properties.


| Property | Default | Description |
|-------------------------------|----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------|
| `usageReporting.enabled` | `false` | Enables collecting anonymous usage data (see [Telemetry](#telemetry)). |
| `keymap.tab1` - `keymap.tab9` | `Command+1` - `Command+9` on macOS <br/> `Ctrl+1` - `Ctrl+9` on Windows<br/>`Alt+1` - `Alt+9` on Linux | Shortcut to open tab 1–9. |
| `keymap.closeTab` | `Command+W` on macOS<br/>`Ctrl+W` on Windows/Linux | Shortcut to close a tab. |
| `keymap.newTab` | `Command+T` on macOS<br/>`Ctrl+T` on Windows/Linux | Shortcut to open a new tab. |
| `keymap.previousTab` | `Shift+Command+Tab` on macOS<br/>`Ctrl+Shift+Tab` on Windows/Linux | Shortcut to go to the previous tab. |
| `keymap.nextTab` | `Command+Tab` on macOS<br/>`Ctrl+Tab` on Windows/Linux | Shortcut to go to the next tab. |
| `keymap.openConnections` | `Command+P` on macOS<br/>`Ctrl+P` on Windows/Linux | Shortcut to open the connection list. |
| `keymap.openClusters` | `Command+E` on macOS<br/>`Ctrl+E` on Windows/Linux | Shortcut to open the cluster selector. |
| `keymap.openProfiles` | `Command+I` on macOS<br/>`Ctrl+I` on Windows/Linux | Shortcut to open the profile selector. |
| `keymap.openCommandBar` | `Command+K` on macOS<br/>`Ctrl+K` on Windows/Linux | Shortcut to open the command bar. |
| `terminal.fontFamily` | `Menlo, Monaco, monospace` on macOS<br/>`Consolas, monospace` on Windows<br/>`'Droid Sans Mono', monospace` on Linux | Font family for the terminal. |
| `terminal.fontSize` | 15 | Font size for the terminal. |

<Admonition
type="note"
title="Note"
>
The additional `$schema` property present in the config file allows text editors to provide autocompletion.
It should not be modified.
</Admonition>

### Configuring keyboard shortcuts

A valid shortcut contains at least one modifier and a single key code, for example `Shift+Tab`.
Function keys such as `F1` do not require a modifier.
Modifiers and a key code must be combined by the `+` character.

Available modifiers:

- `Control`, `Option`, `Shift`, `Command` on macOS.
- `Ctrl`, `Alt`, `Shift` on Windows and Linux.

Available key codes:
- `0` to `9`
- `A` to `Z`
- `F1` to `F24`
- `,`, `.`, `/`, `\`, `` ` ``, `-`, `=`, `;`, `'`, `[`, `]`
- `Space`, `Tab`, `CapsLock`, `NumLock`, `ScrollLock`, `Backspace`, `Delete`, `Insert`, `Enter`, `Up`, `Down`, `Left`, `Right`, `Home`, `End`, `PageUp`, `PageDown`, `Escape`, `IntlBackslash`


## Telemetry

(!docs/pages/includes/teleport-connect-telemetry.mdx!)

### Disabling telemetry

If you initially agreed to share telemetry data, but now want to opt out, you need to update the `app_config.json` file:
If you initially agreed to share telemetry data, but now want to opt out, you need to set `usageReporting.enabled` in the config to `false` (see [Configuration](#configuration)):
```json
"usageReporting.enabled": false
```
<Tabs>
<TabItem label="macOS">
The Teleport Connect configuration file is located at `~/Library/Application Support/Teleport Connect/app_config.json`.
</TabItem>
<TabItem label="Linux">
The Teleport Connect configuration file is located at `~/.config/Teleport Connect/app_config.json`.
</TabItem>
<TabItem label="Windows">
The Teleport Connect configuration file is located at `C:\Users\%UserName%\AppData\Roaming\Teleport Connect\app_config.json`.
</TabItem>
</Tabs>

The changes will take effect at the next launch.

Expand Down
112 changes: 110 additions & 2 deletions web/packages/shared/components/Notification/Notification.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ export default {

export const Notifications = () => {
return (
<Flex gap={8}>
<div
css={`
display: grid;
grid-gap: ${props => props.theme.space[8]}px;
grid-template-columns: auto auto auto;
`}
>
<Flex flexDirection="column" gap={4}>
<Notification
item={{
Expand Down Expand Up @@ -149,7 +155,109 @@ export const Notifications = () => {
isAutoRemovable={false}
/>
</Flex>
</Flex>

<Flex flexDirection="column" gap={4}>
<Notification
item={{
id: crypto.randomUUID(),
severity: 'info',
content: {
title: 'Info with link',
description: loremIpsum,
link: {
href: 'https://goteleport.com',
text: 'goteleport.com',
},
},
}}
Icon={Info}
getColor={theme => theme.colors.info}
onRemove={() => {}}
isAutoRemovable={false}
/>
<Notification
item={{
id: crypto.randomUUID(),
severity: 'warn',
content: {
title: 'Warning with link',
description: loremIpsum,
link: {
href: 'https://goteleport.com',
text: 'goteleport.com',
},
},
}}
Icon={Warning}
getColor={theme => theme.colors.warning}
onRemove={() => {}}
isAutoRemovable={false}
/>
<Notification
item={{
id: crypto.randomUUID(),
severity: 'error',
content: {
title: 'Error with link',
description: loremIpsum,
link: {
href: 'https://goteleport.com',
text: 'goteleport.com',
},
},
}}
Icon={Warning}
getColor={theme => theme.colors.danger}
onRemove={() => {}}
isAutoRemovable={false}
/>
</Flex>

<Flex flexDirection="column" gap={4}>
<Notification
item={{
id: crypto.randomUUID(),
severity: 'info',
content: {
title: 'Info with list',
list: [loremIpsum, loremIpsum],
},
}}
Icon={Info}
getColor={theme => theme.colors.info}
onRemove={() => {}}
isAutoRemovable={false}
/>
<Notification
item={{
id: crypto.randomUUID(),
severity: 'warn',
content: {
title: 'Warning with list',
list: [loremIpsum, loremIpsum],
},
}}
Icon={Warning}
getColor={theme => theme.colors.warning}
onRemove={() => {}}
isAutoRemovable={false}
/>
<Notification
item={{
id: crypto.randomUUID(),
severity: 'error',
content: {
title: 'Error with list',
list: [loremIpsum, loremIpsum],
},
}}
Icon={Warning}
getColor={theme => theme.colors.danger}
onRemove={() => {}}
isAutoRemovable={false}
/>
</Flex>
</div>
);
};

Expand Down
39 changes: 38 additions & 1 deletion web/packages/shared/components/Notification/Notification.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,20 @@ limitations under the License.

import React, { useEffect, useRef, useState } from 'react';
import styled, { css, useTheme } from 'styled-components';
import { ButtonIcon, Flex, Text } from 'design';
import { ButtonIcon, Flex, Link, Text } from 'design';
import { Close } from 'design/Icon';

import type { NotificationItem, NotificationItemContent } from './types';

interface NotificationProps {
item: NotificationItem;

onRemove(): void;

Icon: React.ElementType;

getColor(theme): string;

isAutoRemovable: boolean;
autoRemoveDurationMs?: number;
// Workaround until `styled` gets types.
Expand Down Expand Up @@ -171,13 +175,46 @@ function getRenderedContent(
color="text.secondary"
css={longerTextCss}
>
{content.list && <List items={content.list} />}
{content.description}
{content.link && (
<Link
css={`
display: block;
`}
href={content.link.href}
target="_blank"
>
{content.link.text}
</Link>
)}
</Text>
</Flex>
);
}
}

function List(props: { items: string[] }) {
return (
<ul
// Ideally we'd align the bullet point to the left without using list-style-position: inside
// (because it looks bad when the list item spans multiple lines).
//
// However, it seems impossible to use padding-inline-start for that because the result looks
// different on Retina vs non-Retina screens, the bullet point looks cut off on the latter if
// padding-inline-start is set to 1em. So instead we just set it to 2em.
css={`
margin: 0;
padding-inline-start: 2em;
`}
>
{props.items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}

const textCss = css`
line-height: 20px;
overflow-wrap: break-word;
Expand Down
14 changes: 11 additions & 3 deletions web/packages/shared/components/Notification/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ export interface NotificationItem {
id: string;
}

export type NotificationItemContent =
| string
| { title: string; description: string };
export type NotificationItemContent = string | NotificationItemObjectContent;

export type NotificationItemObjectContent = {
title: string;
list?: string[];
description?: string;
link?: {
href: string;
text: string;
};
};
3 changes: 2 additions & 1 deletion web/packages/teleterm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@
"winston": "^3.3.3",
"xterm": "^5.0.0",
"xterm-addon-fit": "^0.7.0",
"zod": "^3.20.0"
"zod": "^3.21.2",
"zod-to-json-schema": "^3.20.4"
},
"productName": "Teleport Connect"
}
Loading

0 comments on commit 221a413

Please sign in to comment.