Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(ai): add explanation of conversation route design #7927

Draft
wants to merge 3 commits into
base: next-release/main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/check_for_broken_links.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
role-to-assume: arn:aws:iam::464149486631:role/github_action_read_slack_webhook_url
aws-region: us-west-2
- name: Read secrets from AWS Secrets Manager into environment variables
uses: aws-actions/aws-secretsmanager-get-secrets@ff26a0aa6bd4dd5e51326b5afb3f5f6874c958c7 # v2.0.3
uses: aws-actions/aws-secretsmanager-get-secrets@98c2d6bf1dd67c2575fa2bb14294aa64103d426c # v2.0.5
with:
secret-ids: |
SLACK_WEBHOOK_URL
Expand Down
58 changes: 58 additions & 0 deletions .github/workflows/scripts/validate-redirects.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
module.exports = {
invalidRedirects: () => {
const Ajv = require('ajv');
const redirects = require('../../../redirects.json');
const ajv = new Ajv();

const schema = {
type: 'array',
items: {
type: 'object',
required: ['source', 'target', 'status'],
properties: {
source: {
description: 'The address the user requested.',
type: 'string',
pattern: '^/'
},
target: {
description:
'The address that actually serves the content that the user sees',
type: 'string',
pattern: '^[(https)(/)]'
},
status: {
description:
'Types include a permanent redirect (301), a temporary redirect (302), a rewrite (200), or not found (404).',
type: 'string',
pattern: '^[0-5-]+$'
}
}
}
};

const errors = [];
const validate = ajv.compile(schema);

const validateEntries = (redirects) => {
const valid = validate(redirects);

if (!valid) {
const error = validate.errors[0];
const invalidEntry =
JSON.stringify(redirects[error.instancePath.slice(1, -7)]);
const loc = error.schemaPath.slice(error.schemaPath.indexOf('properties') + 11, -8);
const errorMessage = '\n\n' + 'INVALID ENTRY: Please correct the error in the "' + loc +'" property of the following entry: \n' + invalidEntry + '\n' + 'ERROR MESSAGE: ' + error.message;
errors.push(errorMessage);

validateEntries(redirects.splice(parseInt(error.instancePath.slice(1, -7)) + 1));

}
}
validateEntries(redirects);

return errors;
}
}


32 changes: 32 additions & 0 deletions .github/workflows/validate_redirects.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Validate Redirects
on:
pull_request:
branches: [main]
types: [opened, synchronize]
env:
BUILD_DIR: 'client/www/next-build'
permissions:
contents: read
jobs:
ValidateRedirects:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- name: Setup Node.js 20.x
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: 20.x
- name: Install Dependencies
run: yarn
- name: Validate redirects
id: redirects
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
result-encoding: string
script: |
const { invalidRedirects } = require('./.github/workflows/scripts/validate-redirects.js');
return await invalidRedirects();
- name: Fail if any invalid redirects have been found
if: ${{ steps.redirects.outputs.result }}
run: exit 1 && echo ${{ steps.redirects.outputs.result }}
2 changes: 2 additions & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -532,10 +532,12 @@
"Didfinishlaunchingwithoptions",
"displayMode",
"displayOrder",
"dists",
"DocSet",
"DocSets",
"Donef",
"Dont",
"dotenvx",
"downcasting",
"dropdown",
"dynamoDB",
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
"license": "Apache-2.0",
"private": true,
"dependencies": {
"@aws-amplify/amplify-cli-core": "^4.3.8",
"@aws-amplify/amplify-cli-core": "^4.3.9",
"@aws-amplify/ui-react": "^6.1.12",
"@docsearch/react": "3",
"ajv": "^8.16.0",
"aws-amplify": "^6.0.9",
"next": "^14.2.3",
"next-image-export-optimizer": "^1.8.3",
Expand Down
2 changes: 1 addition & 1 deletion redirects.json
Original file line number Diff line number Diff line change
Expand Up @@ -3011,7 +3011,7 @@
},
{
"source": "/lib/client-configuration/configuring-amplify-categories/q/platform/react-native/",
"target": "react-native/tools/libraries/configure-categories/",
"target": "/react-native/tools/libraries/configure-categories/",
"status": "301"
},
{
Expand Down
2 changes: 2 additions & 0 deletions src/components/Accordion/Accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,12 @@ export const Accordion: React.FC<AccordionProps> = ({

const closeAccordion = () => {
const details = detailsRef.current;
const summary = summaryRef.current;
if (details) {
const scrollToLoc = details.offsetTop - 48 - 70 - 10; // account for nav heights and 10px buffer
setDetailsOpen(false);
details.animate(collapse, animationTiming);
summary?.focus();
window.scrollTo({
left: 0,
top: scrollToLoc,
Expand Down
5 changes: 4 additions & 1 deletion src/components/Accordion/__tests__/Accordion.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,13 @@ describe('Accordion', () => {
});
});

it('should collapse Accordion when close button is clicked', async () => {
it('should collapse Accordion and refocus on Accordion element when close button is clicked', async () => {
render(component);
const accordionHeading = screen.getByText('Accordion component example');
userEvent.click(accordionHeading);
const detailsEl = await screen.getByRole('group');
const summaryEl = detailsEl.firstChild;

expect(detailsEl).toHaveAttribute('open');

const text = await screen.getByText(content);
Expand All @@ -79,6 +81,7 @@ describe('Accordion', () => {
await waitFor(() => {
expect(text).not.toBeVisible();
expect(detailsEl).not.toHaveAttribute('open');
expect(summaryEl).toHaveFocus();
});
});

Expand Down
13 changes: 11 additions & 2 deletions src/components/Callout/Callout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,21 @@ import { Message, View } from '@aws-amplify/ui-react';
interface CalloutProps {
info?: boolean;
warning?: boolean;
backgroundColor?: string;
children?: React.ReactNode;
}

export const Callout = ({ warning, children }: CalloutProps) => {
export const Callout = ({
warning,
backgroundColor,
children
}: CalloutProps) => {
return (
<Message variation="filled" colorTheme={warning ? 'warning' : 'info'}>
<Message
variation="filled"
colorTheme={warning ? 'warning' : 'info'}
backgroundColor={backgroundColor}
>
<View>{children}</View>
</Message>
);
Expand Down
13 changes: 13 additions & 0 deletions src/components/Callout/__tests__/Callout.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,17 @@ describe('Callout', () => {

consoleErrorFn.mockRestore();
});

it('should pass the backgroundColor through to the Message component', async () => {
const child = <div>Callout Child</div>;
const ele = render(
<Callout info={true} backgroundColor={'red'}>
{child}
</Callout>
);

const styles = getComputedStyle(ele.container.children[0]);
console.log(styles);
expect(styles.backgroundColor).toBe('red');
});
});
20 changes: 20 additions & 0 deletions src/components/FeatureFlags/feature-flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,26 @@
"defaultExistingProject": false
}
]
},
"subscriptionsInheritPrimaryAuth": {
"description": "Toggles whether subscriptions will inherit related authorization when relational fields are set as required",
"type": "Feature",
"valueType": "Boolean",
"versionAdded": "12.12.4",
"values": [
{
"value": "true",
"description": "Subscriptions will inherit the primary model authorization rules for the relational fields",
"defaultNewProject": false,
"defaultExistingProject": false
},
{
"value": "false",
"description": "Relational fields will be redacted in mutation response when there is a difference between auth rules between primary and related models.",
"defaultNewProject": true,
"defaultExistingProject": true
}
]
}
}
},
Expand Down
7 changes: 6 additions & 1 deletion src/components/Feedback/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,12 @@ const Feedback = function Feedback(router) {

return (
<Flex className="feedback" key={router?.router?.asPath}>
<div id="start-state" aria-labelledby="feedbackGroupTitle" role="group">
<div
id="start-state"
aria-labelledby="feedbackGroupTitle"
role="group"
aria-live="polite"
>
<Text className="feedback-text" id="feedbackGroupTitle">
{c.feedbackQuestion}
</Text>
Expand Down
20 changes: 20 additions & 0 deletions src/components/Gen1Banner/Gen1Banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Callout } from '@/components/Callout';
import Link from 'next/link';
import classNames from 'classnames';

export const Gen1Banner = ({ currentPlatform }) => {
return (
<Callout backgroundColor="background.error">
For new Amplify apps, we recommend using Amplify Gen 2. You can learn more
in our{' '}
<Link
href={`/${currentPlatform}/start/quickstart`}
passHref
className={classNames('amplify-link')}
>
Gen 2 Docs
</Link>
.
</Callout>
);
};
1 change: 1 addition & 0 deletions src/components/Gen1Banner/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Gen1Banner } from './Gen1Banner';
11 changes: 11 additions & 0 deletions src/components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
NEXT_PREVIOUS_SECTIONS
} from '@/components/NextPrevious';
import { Modal } from '@/components/Modal';
import { Gen1Banner } from '@/components/Gen1Banner';

export const Layout = ({
children,
Expand Down Expand Up @@ -127,6 +128,13 @@ export const Layout = ({
}
}, 20);

const isGen1GettingStarted = /\/gen1\/\w+\/start\/getting-started\//.test(
asPathWithNoHash
);
const isGen1HowAmplifyWorks = /\/gen1\/\w+\/how-amplify-works\//.test(
asPathWithNoHash
);

useEffect(() => {
const headings: HeadingInterface[] = [];

Expand Down Expand Up @@ -254,6 +262,9 @@ export const Layout = ({
{useCustomTitle ? null : (
<Heading level={1}>{pageTitle}</Heading>
)}
{(isGen1GettingStarted || isGen1HowAmplifyWorks) && (
<Gen1Banner currentPlatform={currentPlatform} />
)}
{children}
{showNextPrev && <NextPrevious />}
</Flex>
Expand Down
3 changes: 1 addition & 2 deletions src/components/MDXComponents/MDXCopyCodeButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,9 @@ export const MDXCopyCodeButton = ({
<Button
size="small"
variation="link"
disabled={copied}
className="code-copy"
testId={testId}
aria-describedby={title ? undefined : codeId}
aria-describedby={codeId}
>
<IconClipboard /> {copied ? 'Copied!' : 'Copy'}
<VisuallyHidden>
Expand Down
2 changes: 1 addition & 1 deletion src/components/MDXComponents/MDXHeading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const MDXHeading = (props) => {
const { level, children, id } = props;

return (
<Heading level={level} id={id}>
<Heading level={level} id={id} tabIndex={-1}>
{/* Only output heading links for h2 and h3 \ */}
{level == 2 || level == 3 ? (
<Link href={`#${id}`}>{children}</Link>
Expand Down
1 change: 0 additions & 1 deletion src/components/MDXComponents/MDXTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export const MDXTable: React.FC<MDXTableProps> = ({ children, ...props }) => {
return (
<ScrollView
tabIndex={0}
role="region"
aria-label="Scrollable table"
className="scrollview"
>
Expand Down
26 changes: 26 additions & 0 deletions src/components/MDXComponents/__tests__/MDXHeading.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { render, screen } from '@testing-library/react';
import { MDXHeading } from '../MDXHeading';
import { TableOfContents } from '../../TableOfContents/index';
import userEvent from '@testing-library/user-event';

describe('MDXHeading', () => {
it('should render H2 with string and anchor link', () => {
Expand Down Expand Up @@ -53,4 +55,28 @@ describe('MDXHeading', () => {
expect(heading).toHaveTextContent(props.children);
expect(link).not.toBeInTheDocument();
});

it('should shift focus to in-content heading on TOC click', async () => {
const props = {
level: 2,
children: 'Test heading',
id: 'test-heading'
};
render(<MDXHeading {...props} />);

const heading = screen.queryByRole('heading', { level: 2 });
const tocHeadings = [
{ linkText: 'Test heading', hash: 'test-heading', level: 'h2' }
];

const tableOfContents = <TableOfContents headers={tocHeadings} />;
render(tableOfContents);

const tocEntry = await screen.findByRole('heading', {
name: 'Test heading'
});

userEvent.click(tocEntry);
expect(heading).toHaveFocus();
});
});
6 changes: 3 additions & 3 deletions src/components/Overview/Overview.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PageNode } from '@/directory/directory';
import { Card, Flex, View, Text } from '@aws-amplify/ui-react';
import { Card, Flex, View, Heading } from '@aws-amplify/ui-react';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { Platform } from '@/data/platforms';
Expand Down Expand Up @@ -40,9 +40,9 @@ export function Overview({ childPageNodes }: OverviewProps) {
>
<Card className="overview__link__card" variation="outlined">
<Flex direction="column" gap="xs">
<Text className="overview__link__card__title">
<Heading level={2} className="overview__link__card__title">
{node.title}
</Text>
</Heading>
<View className="overview__link__card__description">
{node.description}
</View>
Expand Down
Loading