@shipfox/client-projects 22.0.3 → 24.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +45 -0
- package/dist/core/definition.d.ts +4 -2
- package/dist/core/definition.d.ts.map +1 -1
- package/dist/core/definition.js.map +1 -1
- package/dist/hooks/api/mappers.d.ts.map +1 -1
- package/dist/hooks/api/mappers.js +9 -5
- package/dist/hooks/api/mappers.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pages/projects-hub-page.d.ts.map +1 -1
- package/dist/pages/projects-hub-page.js +3 -0
- package/dist/pages/projects-hub-page.js.map +1 -1
- package/dist/pages/projects-hub-page.stories.d.ts.map +1 -1
- package/dist/pages/projects-hub-page.stories.js +22 -15
- package/dist/pages/projects-hub-page.stories.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/core/definition.ts +4 -2
- package/src/hooks/api/mappers.test.ts +22 -4
- package/src/hooks/api/mappers.ts +6 -4
- package/src/index.ts +6 -1
- package/src/pages/projects-hub-page.stories.tsx +17 -9
- package/src/pages/projects-hub-page.test.tsx +25 -0
- package/src/pages/projects-hub-page.tsx +3 -0
- package/test/pages.tsx +15 -6
- package/tsconfig.build.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shipfox/client-projects",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "24.0.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/ShipfoxHQ/shipfox.git",
|
|
@@ -27,16 +27,16 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@swc/helpers": "^0.5.17",
|
|
29
29
|
"@tanstack/react-form": "^1.32.0",
|
|
30
|
-
"@shipfox/api-common-dto": "
|
|
31
|
-
"@shipfox/api-definitions-dto": "
|
|
32
|
-
"@shipfox/api-integration-core-dto": "
|
|
33
|
-
"@shipfox/api-projects-dto": "
|
|
34
|
-
"@shipfox/client-agent": "
|
|
30
|
+
"@shipfox/api-common-dto": "15.0.0",
|
|
31
|
+
"@shipfox/api-definitions-dto": "15.0.0",
|
|
32
|
+
"@shipfox/api-integration-core-dto": "15.0.0",
|
|
33
|
+
"@shipfox/api-projects-dto": "15.0.0",
|
|
34
|
+
"@shipfox/client-agent": "24.0.0",
|
|
35
35
|
"@shipfox/client-api": "6.0.1",
|
|
36
|
-
"@shipfox/client-auth": "
|
|
37
|
-
"@shipfox/client-integrations": "
|
|
38
|
-
"@shipfox/client-shell": "
|
|
39
|
-
"@shipfox/client-ui": "
|
|
36
|
+
"@shipfox/client-auth": "24.0.0",
|
|
37
|
+
"@shipfox/client-integrations": "24.0.0",
|
|
38
|
+
"@shipfox/client-shell": "24.0.0",
|
|
39
|
+
"@shipfox/client-ui": "24.0.0",
|
|
40
40
|
"@shipfox/react-ui": "2.2.0"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
package/src/core/definition.ts
CHANGED
|
@@ -22,13 +22,15 @@ export interface DefinitionSyncSummary {
|
|
|
22
22
|
finishedAt: string | null;
|
|
23
23
|
lastErrorCode: string | null;
|
|
24
24
|
lastErrorMessage: string | null;
|
|
25
|
-
|
|
25
|
+
diagnostics: DefinitionSyncDiagnostic[];
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export interface
|
|
28
|
+
export interface DefinitionSyncDiagnostic {
|
|
29
29
|
code: string;
|
|
30
30
|
message: string;
|
|
31
31
|
path?: string | undefined;
|
|
32
|
+
filePath?: string | undefined;
|
|
33
|
+
severity: 'error' | 'warning';
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
export interface DefinitionList {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {toDefinitionSyncSummary} from './mappers.js';
|
|
2
2
|
|
|
3
3
|
describe('toDefinitionSyncSummary', () => {
|
|
4
|
-
it('
|
|
4
|
+
it('maps diagnostics with severity and file path while preserving an absent path', () => {
|
|
5
5
|
const summary = toDefinitionSyncSummary({
|
|
6
6
|
ref: 'main',
|
|
7
7
|
status: 'succeeded',
|
|
@@ -10,10 +10,28 @@ describe('toDefinitionSyncSummary', () => {
|
|
|
10
10
|
finished_at: '2026-05-07T01:00:00.000Z',
|
|
11
11
|
last_error_code: null,
|
|
12
12
|
last_error_message: null,
|
|
13
|
-
|
|
13
|
+
diagnostics: [
|
|
14
|
+
{code: 'warning-code', message: 'Warning without a path', severity: 'warning'},
|
|
15
|
+
{
|
|
16
|
+
code: 'error-code',
|
|
17
|
+
message: 'Trigger error with a path',
|
|
18
|
+
path: 'triggers.on_demand',
|
|
19
|
+
file_path: '.shipfox/workflows/deploy.yml',
|
|
20
|
+
severity: 'error',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
14
23
|
});
|
|
15
24
|
|
|
16
|
-
expect(summary.
|
|
17
|
-
|
|
25
|
+
expect(summary.diagnostics).toEqual([
|
|
26
|
+
{code: 'warning-code', message: 'Warning without a path', severity: 'warning'},
|
|
27
|
+
{
|
|
28
|
+
code: 'error-code',
|
|
29
|
+
message: 'Trigger error with a path',
|
|
30
|
+
path: 'triggers.on_demand',
|
|
31
|
+
filePath: '.shipfox/workflows/deploy.yml',
|
|
32
|
+
severity: 'error',
|
|
33
|
+
},
|
|
34
|
+
]);
|
|
35
|
+
expect(summary.diagnostics[0]).not.toHaveProperty('path');
|
|
18
36
|
});
|
|
19
37
|
});
|
package/src/hooks/api/mappers.ts
CHANGED
|
@@ -52,10 +52,12 @@ export function toDefinitionSyncSummary(dto: DefinitionSyncSummaryDto): Definiti
|
|
|
52
52
|
finishedAt: dto.finished_at,
|
|
53
53
|
lastErrorCode: dto.last_error_code,
|
|
54
54
|
lastErrorMessage: dto.last_error_message,
|
|
55
|
-
|
|
56
|
-
code:
|
|
57
|
-
message:
|
|
58
|
-
|
|
55
|
+
diagnostics: dto.diagnostics.map((diagnostic) => ({
|
|
56
|
+
code: diagnostic.code,
|
|
57
|
+
message: diagnostic.message,
|
|
58
|
+
severity: diagnostic.severity,
|
|
59
|
+
...(diagnostic.path === undefined ? {} : {path: diagnostic.path}),
|
|
60
|
+
...(diagnostic.file_path === undefined ? {} : {filePath: diagnostic.file_path}),
|
|
59
61
|
})),
|
|
60
62
|
};
|
|
61
63
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
export type {
|
|
1
|
+
export type {
|
|
2
|
+
Definition,
|
|
3
|
+
DefinitionList,
|
|
4
|
+
DefinitionSyncDiagnostic,
|
|
5
|
+
DefinitionSyncSummary,
|
|
6
|
+
} from '#core/definition.js';
|
|
2
7
|
export {
|
|
3
8
|
type CreateProjectCommand,
|
|
4
9
|
type Project,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {configureApiClient} from '@shipfox/client-api';
|
|
2
2
|
import {type AuthState, authStateAtom} from '@shipfox/client-auth';
|
|
3
|
+
import {ChromeProvider} from '@shipfox/client-shell/runtime';
|
|
3
4
|
import {Toaster} from '@shipfox/react-ui/toast';
|
|
4
5
|
import type {Meta, StoryObj} from '@storybook/react';
|
|
5
6
|
import {QueryClient, QueryClientProvider} from '@tanstack/react-query';
|
|
@@ -50,16 +51,23 @@ function ProjectsHubPageStory({scenario}: {scenario: Scenario}) {
|
|
|
50
51
|
const router = useMemo(() => createStoryRouter(), []);
|
|
51
52
|
|
|
52
53
|
return (
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
<ChromeProvider
|
|
55
|
+
chrome={{
|
|
56
|
+
ProjectBreadcrumb: () => null,
|
|
57
|
+
projectSlugResolver: async () => undefined,
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
<QueryClientProvider client={queryClient}>
|
|
61
|
+
<JotaiProvider store={store}>
|
|
62
|
+
<div className="min-h-screen bg-background-subtle-base px-24 py-32">
|
|
63
|
+
<div className="mx-auto w-full max-w-[1120px]">
|
|
64
|
+
<RouterProvider router={router} />
|
|
65
|
+
</div>
|
|
58
66
|
</div>
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
</
|
|
62
|
-
</
|
|
67
|
+
<Toaster />
|
|
68
|
+
</JotaiProvider>
|
|
69
|
+
</QueryClientProvider>
|
|
70
|
+
</ChromeProvider>
|
|
63
71
|
);
|
|
64
72
|
}
|
|
65
73
|
|
|
@@ -12,11 +12,36 @@ const NEW_PROJECT_REGEX = /New project/i;
|
|
|
12
12
|
const WORKSPACE_PROJECTS_NEW_HREF = `/w/${PROJECT_TEST_WSLUG}/projects/new`;
|
|
13
13
|
const CONNECTION_ID = '33333333-3333-4333-8333-333333333333';
|
|
14
14
|
|
|
15
|
+
function StubWorkspaceSetupChecklist() {
|
|
16
|
+
return <section aria-label="Workspace setup checklist">Workspace setup checklist</section>;
|
|
17
|
+
}
|
|
18
|
+
|
|
15
19
|
describe('ProjectsHubPage', () => {
|
|
16
20
|
beforeEach(() => {
|
|
17
21
|
window.sessionStorage.clear();
|
|
18
22
|
});
|
|
19
23
|
|
|
24
|
+
test('renders the workspace setup checklist before the projects panel', async () => {
|
|
25
|
+
configureApiClient({
|
|
26
|
+
fetchImpl: createHubFetch({
|
|
27
|
+
projects: jsonResponse({projects: [], next_cursor: null}),
|
|
28
|
+
modelProviders: jsonResponse(modelProviderConfigsDto()),
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
renderProjectPage(`/w/${PROJECT_TEST_WSLUG}`, <ProjectsHubPage />, undefined, {
|
|
33
|
+
WorkspaceSetupChecklist: StubWorkspaceSetupChecklist,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(await screen.findByText('Create your first project')).toBeInTheDocument();
|
|
37
|
+
const checklist = screen.getByRole('region', {name: 'Workspace setup checklist'});
|
|
38
|
+
const projects = screen.getByRole('region', {name: 'Projects'});
|
|
39
|
+
|
|
40
|
+
expect(checklist.compareDocumentPosition(projects) & Node.DOCUMENT_POSITION_FOLLOWING).toBe(
|
|
41
|
+
Node.DOCUMENT_POSITION_FOLLOWING,
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
20
45
|
test('renders the Projects panel controls and empty state with create CTA', async () => {
|
|
21
46
|
configureApiClient({
|
|
22
47
|
fetchImpl: createHubFetch({
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
IntegrationIcon,
|
|
6
6
|
useIntegrationConnectionsQuery,
|
|
7
7
|
} from '@shipfox/client-integrations';
|
|
8
|
+
import {useChrome} from '@shipfox/client-shell/runtime';
|
|
8
9
|
import {QueryLoadError} from '@shipfox/client-ui';
|
|
9
10
|
import {Button} from '@shipfox/react-ui/button';
|
|
10
11
|
import {Callout} from '@shipfox/react-ui/callout';
|
|
@@ -29,6 +30,7 @@ import {useProjectsInfiniteQuery} from '#hooks/api/projects.js';
|
|
|
29
30
|
|
|
30
31
|
export function ProjectsHubPage({search = ''}: {search?: string}) {
|
|
31
32
|
const workspace = useActiveWorkspace();
|
|
33
|
+
const {WorkspaceSetupChecklist} = useChrome();
|
|
32
34
|
const navigate = useNavigate();
|
|
33
35
|
const query = useProjectsInfiniteQuery(workspace.id, search || undefined);
|
|
34
36
|
const projects = query.data?.pages.flatMap((page) => page.projects) ?? [];
|
|
@@ -49,6 +51,7 @@ export function ProjectsHubPage({search = ''}: {search?: string}) {
|
|
|
49
51
|
|
|
50
52
|
return (
|
|
51
53
|
<div className="flex w-full flex-col gap-section">
|
|
54
|
+
{WorkspaceSetupChecklist ? <WorkspaceSetupChecklist /> : null}
|
|
52
55
|
<ModelProviderReminderBanner workspaceId={workspace.id} />
|
|
53
56
|
|
|
54
57
|
<section aria-label="Projects">
|
package/test/pages.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {configureApiClient} from '@shipfox/client-api';
|
|
2
2
|
import {type AuthState, authStateAtom} from '@shipfox/client-auth';
|
|
3
|
+
import {ChromeProvider, type ChromeSlots} from '@shipfox/client-shell/runtime';
|
|
3
4
|
import {Toaster} from '@shipfox/react-ui/toast';
|
|
4
5
|
import {QueryClient, QueryClientProvider} from '@tanstack/react-query';
|
|
5
6
|
import {
|
|
@@ -122,19 +123,27 @@ export function renderProjectPage(
|
|
|
122
123
|
path: string,
|
|
123
124
|
element: ReactElement,
|
|
124
125
|
queryClient = new QueryClient({defaultOptions: {queries: {retry: false}}}),
|
|
126
|
+
chromeOverrides: Partial<ChromeSlots> = {},
|
|
125
127
|
): RenderResult {
|
|
126
128
|
const router = createTestRouter(path, element);
|
|
127
129
|
const store = createStore();
|
|
128
130
|
store.set(authStateAtom, authState);
|
|
131
|
+
const chrome: ChromeSlots = {
|
|
132
|
+
ProjectBreadcrumb: () => null,
|
|
133
|
+
projectSlugResolver: async () => undefined,
|
|
134
|
+
...chromeOverrides,
|
|
135
|
+
};
|
|
129
136
|
|
|
130
137
|
configureApiClient({baseUrl: 'https://api.example.test'});
|
|
131
138
|
|
|
132
139
|
return render(
|
|
133
|
-
<
|
|
134
|
-
<
|
|
135
|
-
<
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
140
|
+
<ChromeProvider chrome={chrome}>
|
|
141
|
+
<QueryClientProvider client={queryClient}>
|
|
142
|
+
<JotaiProvider store={store}>
|
|
143
|
+
<RouterProvider router={router} />
|
|
144
|
+
<Toaster />
|
|
145
|
+
</JotaiProvider>
|
|
146
|
+
</QueryClientProvider>
|
|
147
|
+
</ChromeProvider>,
|
|
139
148
|
);
|
|
140
149
|
}
|