Skip to content

Commit

Permalink
Merge pull request #453 from oaknational/rc-20241216-2
Browse files Browse the repository at this point in the history
build: release candidate
  • Loading branch information
mikeritson-oak authored Dec 16, 2024
2 parents 09646c7 + 35e25fc commit 125a274
Show file tree
Hide file tree
Showing 83 changed files with 1,657 additions and 459 deletions.
407 changes: 407 additions & 0 deletions .dependency-cruiser.cjs

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,6 @@ yarn-error.log*
.vscode/*.settings.json

.sonar
.sonar/**/*
.sonar/**/*

dependency-graph.svg
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"bradlc.vscode-tailwindcss",
"Prisma.prisma",
"orta.vscode-jest",
"ms-playwright.playwright"
"ms-playwright.playwright",
"sonarsource.sonarlint-vscode"
]
}
72 changes: 72 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ Oak AI Lesson Assistant is a project focused on experimenting with AI models and
- [End-to-end tests](#end-to-end-tests)
- [Playwright tags](#playwright-tags)
- [Testing in VSCode](#testing-in-vscode)
- [Standards](#standards)
- [Typescript](#typescript)
- [ES Modules](#esmodules)
- [CommonJS](#commonjs)
- [Code quality](#quality)
- [Sonar](#sonar)
- [ESLint](#eslint)
- [Prettier](#prettier)
- [Tsconfig]("#tsconfig)
- [Dependency cruiser](#dependency-cruiser)
- [Release process](#release-process)
- [PNPM / dependency problems](#pnpm--dependency-problems)
- [External contributions](#external-contributions)
Expand Down Expand Up @@ -176,6 +186,68 @@ Our Playwright tests are organised with tags:

Install the Jest and Playwright extensions recommended in the workspace config. Testing icons should appear in the gutter to the left of each test when viewing a test file. Clicking the icon will run the test. The testing tab in the VSCode nav bar provides an overview.

## Standards

### Typescript

By default, we develop in Typescript and aim to be up to date with the latest version. New code should default to being written in Typescript unless it is not possible.

### ES Modules

All packages are configured to be ES Modules.

### CommonJS

Currently NextJS, Tailwind and some other tools has some code which needs to be CommonJS. For these files, you should use the .cjs extension so that the correct linting rules are applied.

## Code quality

We use several tools to ensure code quality in the codebase and for checks during development. These checks run on each PR in Github to ensure we maintain good code quality. You can also run many of these checks locally before making a PR.

### Sonar

If you are using VS Code or Cursor, consider installing the SonarQube for IDE extension. This will give you feedback while you were as to any code quality or security issues that it has detected.

If you would like to run a Sonar scan locally, use the following command:

```shell
pnpm sonar
```

You will need to log in to Sonar when prompted the first time. This will generate a full report for you of your local development environment. Usually it is easier to make a PR and have this run for you automatically.

### ESLint

We have a single ESLint config for the whole monorepo. You will find it in packages/eslint-config.

This is using the latest version of ESLint and you should note that the config file format has changed to the "Flat file" config in version 9.

Each package does not have its own ESLint config by default. Instead we have a single config file, with regex path matchers to turn on/off rules that are specific for each package. This can be overridden and you can see an example of that in the logger package.

Each package specifies in its package.json file that it should use this shared config and there is a root ESLint config file for the whole mono repo which specifies that it should do the same.

To check for linting errors, run the following command:

```shell
pnpm lint
```

If you want to check for linting errors in an individual package, cd into that package and run the same command.

### Prettier

We also have a single Prettier config, which is located in packages/prettier-config. In general there should be no need to change this on a per-package basis.

### Tsconfig

We have an overall tsconfig.json file which specifies the overall Typescript configuration for the project. Then each package extends from it.

You can check the codebase for any Typescript issues by running the following command:

```shell
pnpm type-check
```

## Release process

The current release process is fully documented [in Notion](https://www.notion.so/oaknationalacademy/Branch-Strategy-and-Release-Process-ceeb32937af0426ba495565288e18844?pvs=4), but broadly works as follows:
Expand Down
91 changes: 91 additions & 0 deletions apps/nextjs/.storybook/chromatic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import "@storybook/csf";

type ChromaticModes = "mobile" | "mobile-wide" | "desktop" | "desktop-wide";

export function chromaticParams(modes: ChromaticModes[]) {
return {
chromatic: {
modes: {
...(modes.includes("mobile") && {
mobile: { viewport: "mobile" },
}),
...(modes.includes("mobile-wide") && {
mobile: { viewport: "mobile-wide" },
}),
...(modes.includes("desktop") && {
desktop: { viewport: "desktop" },
}),
...(modes.includes("desktop-wide") && {
"desktop-wide": { viewport: "desktopWide" },
}),
},
},
};
}

declare module "@storybook/csf" {
interface Parameters {
/**
* Parameters for chromatic
*/
chromatic?: {
/**
* Delay capture for a fixed time (in milliseconds) to allow your story to get into
* the intended state
*
* @see [delaying snapshots chromatic documentation](https://www.chromatic.com/docs/delay)
*/
delay?: number;
/**
* Override this behavior in instances where a single pixel change is not flagged by
* Chromatic but should be
*
* * @see [anti-aliasing chromatic documentation](https://www.chromatic.com/docs/threshold#anti-aliasing)
*
* @default false
*/
diffIncludeAntiAliasing?: boolean;
/**
* The diffThreshold parameter allows you to fine tune the threshold for visual change
* between snapshots before they're flagged by Chromatic. Sometimes you need assurance
* to the sub-pixel and other times you want to skip visual noise generated by
* non-deterministic rendering such as anti-aliasing.
*
* 0 is the most accurate. 1 is the least accurate.
*
* @default 0.063
*/
diffThreshold?: number;
/**
* You can omit stories entirely from Chromatic testing using the disable story parameter.
*
* @see [ignoring elements chromatic documentation](https://www.chromatic.com/docs/ignoring-elements)
*/
disable?: boolean;
/**
* Modes
*
* @see [modes chromatic documentation](https://www.chromatic.com/docs/modes)
*/
modes?: Record<
string,
{
viewport?: string | number;
theme?: "light" | "dark";
backgrounds?: { value: string };
}
>;
/**
* Define one or more viewport sizes to capture. Note, units are considered in pixels
*/
viewports?: number[];
/**
* To specify that Chromatic should pause the animation at the end instead of reseting
* them to their beginning state.
*
* @see [animations chromatic documentation](https://www.chromatic.com/docs/animations)
*/
pauseAnimationAtEnd?: boolean;
};
}
}
35 changes: 35 additions & 0 deletions apps/nextjs/.storybook/decorators/AnalyticsDecorator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";

import type { Decorator } from "@storybook/react";
import { fn } from "@storybook/test";

import {
analyticsContext,
type AnalyticsContext,
} from "../../src/components/ContextProviders/AnalyticsProvider";

declare module "@storybook/csf" {
interface Parameters {
analyticsContext?: Partial<AnalyticsContext>;
}
}

export const AnalyticsDecorator: Decorator = (Story, { parameters }) => {
return (
<analyticsContext.Provider
value={
{
track: fn(),
trackEvent: fn(),
identify: fn(),
reset: fn(),
page: fn(),
posthogAiBetaClient: {},
...parameters.analyticsContext,
} as unknown as AnalyticsContext
}
>
<Story />
</analyticsContext.Provider>
);
};
20 changes: 20 additions & 0 deletions apps/nextjs/.storybook/decorators/ChatDecorator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";

import type { Decorator } from "@storybook/react";

import {
ChatContext,
type ChatContextProps,
} from "../../src/components/ContextProviders/ChatProvider";

declare module "@storybook/csf" {
interface Parameters {
chatContext?: Partial<ChatContextProps>;
}
}

export const ChatDecorator: Decorator = (Story, { parameters }) => (
<ChatContext.Provider value={parameters.chatContext as ChatContextProps}>
<Story />
</ChatContext.Provider>
);
62 changes: 62 additions & 0 deletions apps/nextjs/.storybook/decorators/DemoDecorator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from "react";

import type { Decorator } from "@storybook/react";
import invariant from "tiny-invariant";

import {
DemoContext,
type DemoContextProps,
} from "@/components/ContextProviders/Demo";

declare module "@storybook/csf" {
interface Parameters {
demoContext?: DemoContextProps;
}
}

export const DemoDecorator: Decorator = (Story, { parameters }) => {
const value = parameters.demoContext;
invariant(
value,
"DemoDecorator requires a DemoContext. Please call ...demoParams() in the parameters",
);

return (
<DemoContext.Provider value={value}>
<Story />
</DemoContext.Provider>
);
};

const demoBase: DemoContextProps["demo"] = {
appSessionsRemaining: 2,
appSessionsPerMonth: 3,
contactHref: "https://share.hsforms.com/1R9ulYSNPQgqElEHde3KdhAbvumd",
};

type DemoParams = {
isDemoUser: boolean;
demo?: Partial<DemoContextProps["demo"]>;
isSharingEnabled?: boolean;
};
export const demoParams = (
args: DemoParams,
): { demoContext: DemoContextProps } => {
const isSharingEnabled = args.isSharingEnabled ?? true;

const context: DemoContextProps = args.isDemoUser
? {
isDemoUser: true,
demo: { ...demoBase, ...args.demo },
isSharingEnabled,
}
: {
isDemoUser: false,
demo: undefined,
isSharingEnabled,
};

return {
demoContext: context,
};
};
30 changes: 30 additions & 0 deletions apps/nextjs/.storybook/decorators/DialogContentDecorator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";

import type { Decorator } from "@storybook/react";
import { fn } from "@storybook/test";

import type { DialogTypes } from "../../src/components/AppComponents/Chat/Chat/types";
import { DialogContext } from "../../src/components/AppComponents/DialogContext";

declare module "@storybook/csf" {
interface Parameters {
dialogWindow?: DialogTypes;
}
}

export const DialogContentDecorator: Decorator = (Story, { parameters }) => {
return (
<DialogContext.Provider
value={{
dialogWindow: parameters.dialogWindow ?? "",
setDialogWindow: fn(),
dialogProps: {},
setDialogProps: fn(),
openSidebar: false,
setOpenSidebar: fn(),
}}
>
<Story />
</DialogContext.Provider>
);
};
21 changes: 21 additions & 0 deletions apps/nextjs/.storybook/decorators/LessonPlanTrackingDecorator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";

import type { Decorator } from "@storybook/react";
import { fn } from "@storybook/test";

import { LessonPlanTrackingContext } from "../../src/lib/analytics/lessonPlanTrackingContext";

export const LessonPlanTrackingDecorator: Decorator = (Story) => (
<LessonPlanTrackingContext.Provider
value={{
onClickContinue: fn(),
onClickRetry: fn(),
onClickStartFromExample: fn(),
onClickStartFromFreeText: fn(),
onStreamFinished: fn(),
onSubmitText: fn(),
}}
>
<Story />
</LessonPlanTrackingContext.Provider>
);
3 changes: 2 additions & 1 deletion apps/nextjs/.storybook/decorators/RadixThemeDecorator.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React from "react";

import { Theme } from "@radix-ui/themes";
import { Decorator } from "@storybook/react";

export const RadixThemeDecorator = (Story: React.ComponentType) => (
export const RadixThemeDecorator: Decorator = (Story) => (
<Theme>
<Story />
</Theme>
Expand Down
Loading

0 comments on commit 125a274

Please sign in to comment.