Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
9bdf50f
upcoming: [M3-7753] - Tag custom analytics events for account switchi…
mjac0bs Feb 15, 2024
a099b8e
refactor: [M3-7585] - Upgrade to React 18 (#10169)
bnussman-akamai Feb 15, 2024
455f09b
fix: [M3-7758] - Linode Network Graph Tooltip - Incorrect Units (#10197)
bnussman-akamai Feb 16, 2024
42137a0
upcoming: [M3-7618] - Delete Placement Group Modal (#10162)
abailly-akamai Feb 16, 2024
8e5bb02
upcoming: [M3-7694] - OBJ Multi Cluster Copy updates (#10188)
cpathipa Feb 16, 2024
9e03e40
upcoming: [M3-7775] - Disable ability to edit or delete a proxy user …
mjac0bs Feb 20, 2024
ef6dbfb
change: [M3-7598] - Update developer docs on components (#10198)
mjac0bs Feb 20, 2024
2fd5742
Merge branch 'master' into develop
DevDW Feb 20, 2024
f5bd65f
refactor: [M3-7786] - Convert `isRestrictedGlobalGrantType` to Hook (…
jaalah-akamai Feb 20, 2024
a4bbe2a
feat: [M3-7687] - Refactor & Improve `LinodeActionMenu` Restricted Us…
jaalah-akamai Feb 20, 2024
65a84e9
upcoming: [M3-7615] - Add placement group to payload (#10195)
carrillo-erik Feb 20, 2024
b9819bb
upcoming: [M3-7743] - Handle errors gracefully when FF enabled withou…
cpathipa Feb 21, 2024
a2be175
chore: Update Storybook to latest to resolve `CVE-2023-42282` (#10212)
bnussman-akamai Feb 21, 2024
046e5ce
test: [M3-7434]: Add a Cypress test for OBJ Multicluster Bucket creat…
jdamore-linode Feb 22, 2024
5518871
upcoming: [M3-7733] - Access key "Permissions" drawer ARIA label need…
cpathipa Feb 22, 2024
2173f45
fix: [M3-7059] - Stop resetting count and disabling Add button when a…
mjac0bs Feb 22, 2024
f08b57c
test: [M3-7516] - Cypress tests for Parent → Child account switching …
jdamore-linode Feb 22, 2024
232dd2c
poc: [M3-7799] - Improve Docs Site Sidebar (#10214)
bnussman-akamai Feb 22, 2024
c1457a8
change: [UIE-7292] - Rename DBaaS "Scale Up" to "Resize" (#10193)
mpolotsk-akamai Feb 23, 2024
cbd2e1a
change: [M3-7802] - Remove API caching (#10219)
bnussman-akamai Feb 23, 2024
cdd0fa4
chore: [M3-7803] - Clean up `Chip` component (#10223)
bnussman-akamai Feb 26, 2024
9c88cb1
change: [M3-7785] - Improve Dev Tools (#10220)
abailly-akamai Feb 26, 2024
02bdf6d
upcoming: [M3-7702] - Update Region Select for edge sites (#10194)
hana-akamai Feb 26, 2024
ca52738
refactor: [M3-7800] - Clean up `new QueryClient()` pattern in unit te…
bnussman-akamai Feb 26, 2024
1ceb91c
upcoming: [M3-7777, M3-7778] - Improve Billing & Account Restricted U…
jaalah-akamai Feb 26, 2024
d9b5b92
upcoming: [M3-7580] - Add list view for Linode Clone/Backup (#10182)
hkhalil-akamai Feb 26, 2024
fd9617d
fix: [M3-7811] - Fix Users & Grants query filtering on user_type (#10…
mjac0bs Feb 27, 2024
f08d42c
fix: [M3-7812] Textfield input disabled styles (#10231)
abailly-akamai Feb 27, 2024
f5f53de
upcoming: [M3-7779]: Placement Groups types update, part 2 (#10200)
abailly-akamai Feb 27, 2024
d53f3f5
feat: [M3-7801] - Reintroduce NVMe Volume Upgrades (#10229)
bnussman-akamai Feb 27, 2024
e255d5b
upcoming: [M3-7814, M3-7819] - Fix Account Switching (#10234)
jaalah-akamai Feb 27, 2024
632b454
fix: [M3-7804] - Volume Create Drawer Crash (Linode detail) (#10225)
abailly-akamai Feb 28, 2024
a482b21
fix: [M3-7804] - LinodeVolumeCreateForm crash (for real this time) (#…
abailly-akamai Feb 28, 2024
231e4ff
change: [M3-7815] - Change ACLB Beta Regions (#10232)
bnussman-akamai Feb 28, 2024
525aed0
test: [M3-7820] - Suppress Cypress "MODULE_LEVEL_DIRECTIVE" and "SOUR…
jdamore-linode Feb 29, 2024
04d2fed
fix: [M3-7796] - Correct Default VPC Scope and Adjust PAT Creation Be…
mjac0bs Feb 29, 2024
b584a4d
Cloud version 1.114.0, API v4 version 0.111.0, and Validation version…
carrillo-erik Mar 1, 2024
e07d8c7
Add the release date and version number for Validation package that w…
carrillo-erik Mar 4, 2024
9902757
Merge pull request #10246 from linode/release-v1.114.0
carrillo-erik Mar 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
13 changes: 5 additions & 8 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { guides } from "./plugins/sidebar";
import { generateSidebar } from "./plugins/sidebar";

export const DOCS_SRC_DIR = new URL("./../", import.meta.url).pathname;

export default {
title: "Cloud Manager Docs",
description: "Akamai Cloud Manger Documentation",
srcDir: "./",
srcDir: DOCS_SRC_DIR,
base: "/manager/",
themeConfig: {
logo: "/akamai-wave.svg",
Expand All @@ -15,12 +17,7 @@ export default {
search: {
provider: "local",
},
sidebar: [
{
text: "Development Guide",
items: guides,
},
],
sidebar: generateSidebar(DOCS_SRC_DIR),
socialLinks: [
{ icon: "github", link: "https://github.com/linode/manager" },
],
Expand Down
103 changes: 77 additions & 26 deletions docs/.vitepress/plugins/sidebar.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,89 @@
import * as fs from "fs";
import * as path from "path";
import { readdirSync } from "fs";
import { join } from "path";
import { DOCS_SRC_DIR } from "../config";

const DEVELOPMENT_GUIDE_PATH = "./docs/development-guide";
type LinkItem = { text: string; link: string };

interface MarkdownInfo {
text: string;
link: string;
type SidebarItem =
| {
text: string;
collapsed?: boolean;
items: SidebarItem[] | LinkItem[];
}
| LinkItem;

const exclude = [
"cache",
"public",
"PULL_REQUEST_TEMPLATE.md",
".vitepress",
"index.md",
];

const replacements = [
["-", " "],
["_", " "],
[".md", ""],
];

function isPathIgnored(path: string) {
for (const item of exclude) {
if (path.includes(item)) {
return true;
}
}
return false;
}

function capitalize(s: string) {
return (
s.substring(0, 1).toUpperCase() + s.substring(1, s.length).toLowerCase()
);
}

/**
* Aggregates the pages in the development-guide and populates the left sidebar.
* Given a file name, this function returns a formatted title.
*/
const scanDirectory = (directoryPath: string): MarkdownInfo[] => {
const markdownFiles = fs
.readdirSync(directoryPath)
.filter((file) => file.endsWith(".md"));
const markdownInfoArray: MarkdownInfo[] = [];
function formatSidebarItemText(fileName: string) {
// removes -, _, and .md from files names to generate the title
for (const [from, to] of replacements) {
fileName = fileName.replaceAll(from, to);
}
// Removes any number prefix. This allows us to order things by putting numbers in file names.
fileName = fileName.replace(/^[0-9]*/, "");
// Capitalizes each word in the file name
fileName = fileName.split(" ").map(capitalize).join(" ");
return fileName;
}

markdownFiles.forEach((file) => {
const filePath = path.join(directoryPath, file);
const fileContent = fs.readFileSync(filePath, "utf-8");
/**
* Generates a VitePress sidebar by recursively traversing the given directory.
*/
export function generateSidebar(dir: string) {
const files = readdirSync(dir, { withFileTypes: true });

const titleMatch = fileContent.match(/^#\s+(.*)/m);
const title = titleMatch ? titleMatch[1] : "Untitled";
const sidebar: SidebarItem[] = [];

const markdownInfo: MarkdownInfo = {
text: title,
link: `/development-guide/${file}`,
};
for (const file of files) {
const filepath = join(dir, file.name);

markdownInfoArray.push(markdownInfo);
});
if (isPathIgnored(filepath)) {
continue;
}

return markdownInfoArray;
};
if (file.isDirectory()) {
sidebar.push({
text: formatSidebarItemText(file.name),
collapsed: false,
items: generateSidebar(filepath),
});
} else {
sidebar.push({
text: formatSidebarItemText(file.name),
link: filepath.split(DOCS_SRC_DIR)[1],
});
}
}

export const guides = scanDirectory(DEVELOPMENT_GUIDE_PATH);
return sidebar;
}
6 changes: 6 additions & 0 deletions docs/.vitepress/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"compilerOptions": {
"lib": ["ESNext"],
"module": "ESNext",
}
}
6 changes: 5 additions & 1 deletion docs/development-guide/02-component-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ export const capitalize = (s: string) => {

#### Composition

When building a large component, it is recommended to break it down and avoid writing several components within the same file. It improves readability and testability. Components should, in most cases, come with their own unit test, although they can be skipped if an e2e suite is covering the functionality.
When building a large component, it is recommended to break it down and avoid writing several components within the same file. It improves readability and testability. It is also best to avoid same-file render functions (e.g. `renderTableBody`), in favor of extracting the JSX into its own component. In addition to improved readability and testability, this practice makes components less brittle and more extensible.

Components should, in most cases, come with their own unit test, although they can be skipped if an e2e suite is covering the functionality.
Utilities should almost always feature a unit test.

#### Styles
Expand All @@ -85,6 +87,8 @@ export const interface MyComponentProps {
const MyComponent = (props: MyComponentProps) { ... }
```
- When it comes to components located in the `src/features/` directory, you can use the name `Props` for their types or interfaces, unless exporting is necessary. In such cases, name the type or interface after the component name.
- Define props as required, rather than optional, as often as possible for data relying on API responses (which can be `undefined`). In the case of `undefined` props, error handling - such as early return statements - can be done in the HOC. This allows all child components to expect data, avoiding extra conditionals or convoluted logic.

#### Function Component Definition

- Prefer function components over class components.
Expand Down
10 changes: 4 additions & 6 deletions docs/development-guide/04-component-library.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Material-UI

We use [Material-UI](https://mui.com/material-ui/getting-started/overview/) as the primary component library for Cloud Manager. The library contains many UI primitives like `<Typography />` and `<Button />` as well as a layout system with the `<Grid />` component.
We use [Material-UI](https://mui.com/material-ui/getting-started/overview/) as the primary component library for Cloud Manager. The library contains many UI primitives like `<Typography />` and `<Button />`, as well as a layout system with the `<Grid />` component.

All MUI components have abstractions in the Cloud Manager codebase, meaning you will use relative imports to use them instead of importing from MUI directly:

Expand Down Expand Up @@ -37,18 +37,16 @@ A color, font, svg icon, or other simple styling convention.

##### Element

A basic HTML element wrapped in a react component, or a small component that is not normally used on its own.
A basic HTML element wrapped in a React component, or a small component that is not normally used on its own.

##### Component

A composition of Core Styles and Elements. Normally with some code that defines behavior. An example of a Component is a Dialog which is a composition of Typography and Buttons.

##### Feature

A Composition of Core Styles, Elements, and Components that defines a verticle slice of functionality. An example of a Feature is the Payment Method Row it combines Components, Elements, and Core Styles like Buttons, Action Menus, Icons, Typography, etc.
A Composition of Core Styles, Elements, and Components that defines a vertical slice of functionality. An example of a Feature is the Payment Method Row; it combines Components, Elements, and Core Styles like Buttons, Action Menus, Icons, Typography, etc.

#### Best Practices
Our stories are in the process of being updated to the latest Storybook 7.0 format.
We currently use MDX both for documentation and for defining stories in the same `.stories.mdx` file. However, Storybook has deprecated this functionality and they plan to remove it in a future version of Storybook.

As we begin to move away from the MDX format, please refer to Storybook's [documentation](https://storybook.js.org/docs/react/writing-docs/introduction) for how to write stories in the CSF format.
Please refer to Storybook's [documentation](https://storybook.js.org/docs/react/writing-docs/introduction) for how to write stories in the CSF format.
18 changes: 16 additions & 2 deletions docs/development-guide/10-local-dev-tools.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
# Local Dev Tools

To facilitate development and debugging, Cloud Manager includes a "Dev Tools" mode. Currently this mode is used for feature flag toggling, data mocking, and environment switching.
To facilitate development and debugging, Cloud Manager includes a "Dev Tools" mode. Currently this mode is used for feature flag toggling, data mocking, and theme & environment switching.

In order to access the dev tools, hover or click (mobile) on the 🛠 icon in the lower left corner of your browser window. The icon will be colored green if MSW is enabled.

This mode is enabled by default while running the development server. To disable it, add `?dev-tools=false` to the URL, or write `dev-tools: false` to local storage.

This mode is disabled by default in production builds, but can be enabled by adding `?dev-tools=true` to the URL, or `dev-tools: true` to local storage.
This mode is disabled by default in production builds.

## Feature Flags

The display of the Flags in dev tools is defined in the `options` array in `FeatureFlagTool.tsx`. While it is convenient to add those switches to the dev tools, it is not always necessary as they can clutter the UI. Additionally, it is important to clean them up once the feature has been battle tested in production.

The flags on/off values are stored in local storage for convenience and will be remembered on reload or app restart.

By default, the boolean flags checkboxes represent their true values as returned by Launch Darkly (dev environment). Hitting the reset button will bring them back to those default values and clear local storage.

## Theme Select

The theme select in dev tools is a convenient way to store the theme choice while MSW is enabled (it won't affect your actual Application settings/preferences). The default is "system".

## Writing a new tool

Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"coverage": "yarn workspace linode-manager coverage",
"coverage:summary": "yarn workspace linode-manager coverage:summary",
"junit:summary": "ts-node scripts/junit-summary/index.ts",
"docs": "bunx vitepress@1.0.0-rc.35 dev docs"
"docs": "bunx vitepress@1.0.0-rc.44 dev docs"
},
"resolutions": {
"@babel/traverse": "^7.23.3",
Expand All @@ -58,11 +58,11 @@
"lodash": "^4.17.21",
"glob-parent": "^5.1.2",
"hosted-git-info": "^5.0.0",
"@types/react": "^17",
"yaml": "^2.3.0",
"word-wrap": "^1.2.4",
"semver": "^7.5.2",
"tough-cookie": "^4.1.3"
"tough-cookie": "^4.1.3",
"jackspeak": "2.1.1"
},
"workspaces": {
"packages": [
Expand Down
10 changes: 10 additions & 0 deletions packages/api-v4/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## [2024-03-04] - v0.111.0

### Changed:

- Rename `database_scale` type to `database_resize` ([#10193](https://github.com/linode/manager/pull/10193))

### Upcoming Features:

- Accept placement group in Linode create payload ([#10195](https://github.com/linode/manager/pull/10195))

## [2024-02-20] - v0.110.0

### Upcoming Features:
Expand Down
2 changes: 1 addition & 1 deletion packages/api-v4/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@linode/api-v4",
"version": "0.110.0",
"version": "0.111.0",
"homepage": "https://github.com/linode/manager/tree/develop/packages/api-v4",
"bugs": {
"url": "https://github.com/linode/manager/issues"
Expand Down
2 changes: 1 addition & 1 deletion packages/api-v4/src/account/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ export type EventAction =
| 'community_question_reply'
| 'credit_card_updated'
| 'database_low_disk_space'
| 'database_scale'
| 'database_resize'
| 'database_backup_restore'
| 'database_create'
| 'database_credentials_reset'
Expand Down
22 changes: 17 additions & 5 deletions packages/api-v4/src/linodes/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Region } from '../regions';
import type { IPAddress, IPRange } from '../networking/types';
import type { SSHKey } from '../profile/types';
import type { PlacementGroup } from '../placement-groups/types';
import type { PlacementGroupPayload } from '../placement-groups/types';

export type Hypervisor = 'kvm' | 'zen';

Expand All @@ -24,9 +24,7 @@ export interface Linode {
ipv4: string[];
ipv6: string | null;
label: string;
placement_groups:
| [Pick<PlacementGroup, 'id' | 'label' | 'affinity_type'>] // While the API returns an array of PlacementGroup objects for future proofing, we only support one PlacementGroup per Linode at this time, hence the tuple.
| [];
placement_group?: PlacementGroupPayload; // If not in a placement group, this will be excluded from the response.
type: string | null;
status: LinodeStatus;
updated: string;
Expand Down Expand Up @@ -230,10 +228,13 @@ export interface Kernel {
label: string;
version: string;
kvm: boolean;
xen: boolean;
architecture: KernelArchitecture;
pvops: boolean;
deprecated: boolean;
/**
* @example 2009-10-26T04:00:00
*/
built: string;
}

export interface NetStats {
Expand Down Expand Up @@ -338,6 +339,16 @@ export interface UserData {
user_data: string | null;
}

export interface CreateLinodePlacementGroupPayload {
id: number;
/**
* This parameter is silent in Cloud Manager, but still needs to be represented in the API types.
*
* @default false
*/
compliant_only?: boolean;
}

export interface CreateLinodeRequest {
type?: string;
region?: string;
Expand All @@ -357,6 +368,7 @@ export interface CreateLinodeRequest {
interfaces?: InterfacePayload[];
metadata?: UserData;
firewall_id?: number;
placement_group?: CreateLinodePlacementGroupPayload;
}

export type RescueRequestObject = Pick<
Expand Down
4 changes: 2 additions & 2 deletions packages/api-v4/src/placement-groups/placement-groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type {
CreatePlacementGroupPayload,
PlacementGroup,
UnassignLinodesFromPlacementGroupPayload,
RenamePlacementGroupPayload,
UpdatePlacementGroupPayload,
} from './types';

/**
Expand Down Expand Up @@ -72,7 +72,7 @@ export const createPlacementGroup = (data: CreatePlacementGroupPayload) =>
*/
export const renamePlacementGroup = (
placementGroupId: number,
data: RenamePlacementGroupPayload
data: UpdatePlacementGroupPayload
) =>
Request<PlacementGroup>(
setURL(
Expand Down
Loading