@shipfox/client-projects 21.0.0 → 22.0.1

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.
Files changed (30) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +31 -0
  3. package/dist/components/source-strip.d.ts.map +1 -1
  4. package/dist/components/source-strip.js +49 -45
  5. package/dist/components/source-strip.js.map +1 -1
  6. package/dist/pages/create-project-page.d.ts.map +1 -1
  7. package/dist/pages/create-project-page.js +161 -175
  8. package/dist/pages/create-project-page.js.map +1 -1
  9. package/dist/pages/project-settings-page.d.ts.map +1 -1
  10. package/dist/pages/project-settings-page.js +82 -84
  11. package/dist/pages/project-settings-page.js.map +1 -1
  12. package/dist/pages/projects-hub-page.d.ts.map +1 -1
  13. package/dist/pages/projects-hub-page.js +160 -159
  14. package/dist/pages/projects-hub-page.js.map +1 -1
  15. package/dist/pages/projects-hub-page.stories.d.ts +22 -0
  16. package/dist/pages/projects-hub-page.stories.d.ts.map +1 -0
  17. package/dist/pages/projects-hub-page.stories.js +214 -0
  18. package/dist/pages/projects-hub-page.stories.js.map +1 -0
  19. package/dist/tsconfig.test.tsbuildinfo +1 -1
  20. package/package.json +7 -7
  21. package/src/components/source-strip.tsx +29 -26
  22. package/src/pages/create-project-page.test.tsx +85 -1
  23. package/src/pages/create-project-page.tsx +165 -153
  24. package/src/pages/home-router.test.tsx +2 -1
  25. package/src/pages/project-settings-page.test.tsx +10 -1
  26. package/src/pages/project-settings-page.tsx +88 -76
  27. package/src/pages/projects-hub-page.stories.tsx +203 -0
  28. package/src/pages/projects-hub-page.test.tsx +90 -10
  29. package/src/pages/projects-hub-page.tsx +136 -125
  30. package/tsconfig.build.tsbuildinfo +1 -1
@@ -0,0 +1,214 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { configureApiClient } from '@shipfox/client-api';
3
+ import { authStateAtom } from '@shipfox/client-auth';
4
+ import { Toaster } from '@shipfox/react-ui/toast';
5
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
6
+ import { createMemoryHistory, createRootRoute, createRoute, createRouter, Outlet, RouterProvider } from '@tanstack/react-router';
7
+ import { createStore, Provider as JotaiProvider } from 'jotai';
8
+ import { useMemo } from 'react';
9
+ import { ProjectsHubPage } from './projects-hub-page.js';
10
+ const WORKSPACE_ID = '11111111-1111-4111-8111-111111111111';
11
+ const CONNECTION_ID = '33333333-3333-4333-8333-333333333333';
12
+ const authState = {
13
+ status: 'authenticated',
14
+ token: 'token',
15
+ user: {
16
+ id: '22222222-2222-4222-8222-222222222222',
17
+ email: 'platform@example.com',
18
+ name: 'Platform Engineer',
19
+ emailVerifiedAt: '2026-01-01T00:00:00.000Z'
20
+ },
21
+ workspaces: [
22
+ {
23
+ id: WORKSPACE_ID,
24
+ name: 'Acme',
25
+ slug: 'acme',
26
+ membershipId: 'membership-1'
27
+ }
28
+ ]
29
+ };
30
+ function ProjectsHubPageStory({ scenario }) {
31
+ configureApiClient({
32
+ baseUrl: 'https://api.example.test',
33
+ fetchImpl: fetchForScenario(scenario)
34
+ });
35
+ const queryClient = useMemo(()=>new QueryClient({
36
+ defaultOptions: {
37
+ queries: {
38
+ retry: false
39
+ }
40
+ }
41
+ }), []);
42
+ const store = useMemo(()=>{
43
+ const nextStore = createStore();
44
+ nextStore.set(authStateAtom, authState);
45
+ return nextStore;
46
+ }, []);
47
+ const router = useMemo(()=>createStoryRouter(), []);
48
+ return /*#__PURE__*/ _jsx(QueryClientProvider, {
49
+ client: queryClient,
50
+ children: /*#__PURE__*/ _jsxs(JotaiProvider, {
51
+ store: store,
52
+ children: [
53
+ /*#__PURE__*/ _jsx("div", {
54
+ className: "min-h-screen bg-background-subtle-base px-24 py-32",
55
+ children: /*#__PURE__*/ _jsx("div", {
56
+ className: "mx-auto w-full max-w-[1120px]",
57
+ children: /*#__PURE__*/ _jsx(RouterProvider, {
58
+ router: router
59
+ })
60
+ })
61
+ }),
62
+ /*#__PURE__*/ _jsx(Toaster, {})
63
+ ]
64
+ })
65
+ });
66
+ }
67
+ const meta = {
68
+ title: 'Projects/ProjectsHubPage',
69
+ component: ProjectsHubPageStory,
70
+ parameters: {
71
+ layout: 'fullscreen'
72
+ },
73
+ args: {
74
+ scenario: 'list'
75
+ }
76
+ };
77
+ export default meta;
78
+ export const Playground = {};
79
+ export const Empty = {
80
+ args: {
81
+ scenario: 'empty'
82
+ }
83
+ };
84
+ export const Loading = {
85
+ args: {
86
+ scenario: 'loading'
87
+ }
88
+ };
89
+ export const ErrorState = {
90
+ args: {
91
+ scenario: 'error'
92
+ }
93
+ };
94
+ function createStoryRouter() {
95
+ const rootRoute = createRootRoute({
96
+ component: Outlet
97
+ });
98
+ const workspaceRoute = createRoute({
99
+ getParentRoute: ()=>rootRoute,
100
+ path: '/w/$workspaceSlug',
101
+ component: ProjectsHubPage
102
+ });
103
+ return createRouter({
104
+ history: createMemoryHistory({
105
+ initialEntries: [
106
+ '/w/acme'
107
+ ]
108
+ }),
109
+ routeTree: rootRoute.addChildren([
110
+ workspaceRoute
111
+ ])
112
+ });
113
+ }
114
+ function fetchForScenario(scenario) {
115
+ return (input)=>{
116
+ const url = requestUrl(input);
117
+ if (url.pathname.endsWith('/agent/model-providers')) {
118
+ return Promise.resolve(jsonResponse({
119
+ configs: [
120
+ {
121
+ kind: 'builtin',
122
+ provider_id: 'anthropic',
123
+ default_model: null,
124
+ created_at: '2026-01-01T00:00:00.000Z',
125
+ updated_at: '2026-01-01T00:00:00.000Z'
126
+ }
127
+ ],
128
+ default_provider_id: 'anthropic',
129
+ default_harness_id: null
130
+ }));
131
+ }
132
+ if (url.pathname === '/integration-connections') {
133
+ return Promise.resolve(jsonResponse({
134
+ connections: [
135
+ {
136
+ id: CONNECTION_ID,
137
+ workspace_id: WORKSPACE_ID,
138
+ provider: 'github',
139
+ external_account_id: 'octo',
140
+ slug: 'github_octo',
141
+ display_name: 'Acme GitHub',
142
+ lifecycle_status: 'active',
143
+ capabilities: [
144
+ 'source_control'
145
+ ],
146
+ created_at: '2026-01-01T00:00:00.000Z',
147
+ updated_at: '2026-01-01T00:00:00.000Z'
148
+ }
149
+ ]
150
+ }));
151
+ }
152
+ if (url.pathname === '/projects') {
153
+ if (scenario === 'loading') {
154
+ return new Promise(()=>{
155
+ // Keep the request pending to show the initial skeleton.
156
+ });
157
+ }
158
+ if (scenario === 'error') {
159
+ return Promise.resolve(jsonResponse({
160
+ code: 'server-error'
161
+ }, {
162
+ status: 500
163
+ }));
164
+ }
165
+ if (scenario === 'empty') {
166
+ return Promise.resolve(jsonResponse({
167
+ projects: [],
168
+ next_cursor: null
169
+ }));
170
+ }
171
+ return Promise.resolve(jsonResponse({
172
+ projects: [
173
+ projectForStory('Platform', '11111111-1111-4111-8111-111111111112'),
174
+ projectForStory('Agent', '11111111-1111-4111-8111-111111111113'),
175
+ projectForStory('Workflows', '11111111-1111-4111-8111-111111111114')
176
+ ],
177
+ next_cursor: null
178
+ }));
179
+ }
180
+ return Promise.resolve(jsonResponse({}, {
181
+ status: 404
182
+ }));
183
+ };
184
+ }
185
+ function projectForStory(name, id) {
186
+ return {
187
+ id,
188
+ workspace_id: WORKSPACE_ID,
189
+ name,
190
+ slug: name.toLowerCase(),
191
+ source: {
192
+ connection_id: CONNECTION_ID,
193
+ external_repository_id: `github:octo/${name.toLowerCase()}`
194
+ },
195
+ created_at: '2026-01-01T00:00:00.000Z',
196
+ updated_at: '2026-01-01T00:00:00.000Z'
197
+ };
198
+ }
199
+ function requestUrl(input) {
200
+ if (input instanceof Request) return new URL(input.url);
201
+ if (input instanceof URL) return input;
202
+ return new URL(input, 'https://api.example.test');
203
+ }
204
+ function jsonResponse(body, init = {}) {
205
+ return new Response(JSON.stringify(body), {
206
+ status: 200,
207
+ headers: {
208
+ 'content-type': 'application/json'
209
+ },
210
+ ...init
211
+ });
212
+ }
213
+
214
+ //# sourceMappingURL=projects-hub-page.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/pages/projects-hub-page.stories.tsx"],"sourcesContent":["import {configureApiClient} from '@shipfox/client-api';\nimport {type AuthState, authStateAtom} from '@shipfox/client-auth';\nimport {Toaster} from '@shipfox/react-ui/toast';\nimport type {Meta, StoryObj} from '@storybook/react';\nimport {QueryClient, QueryClientProvider} from '@tanstack/react-query';\nimport {\n createMemoryHistory,\n createRootRoute,\n createRoute,\n createRouter,\n Outlet,\n RouterProvider,\n} from '@tanstack/react-router';\nimport {createStore, Provider as JotaiProvider} from 'jotai';\nimport {useMemo} from 'react';\nimport {ProjectsHubPage} from './projects-hub-page.js';\n\nconst WORKSPACE_ID = '11111111-1111-4111-8111-111111111111';\nconst CONNECTION_ID = '33333333-3333-4333-8333-333333333333';\n\ntype Scenario = 'list' | 'empty' | 'loading' | 'error';\n\nconst authState: AuthState = {\n status: 'authenticated',\n token: 'token',\n user: {\n id: '22222222-2222-4222-8222-222222222222',\n email: 'platform@example.com',\n name: 'Platform Engineer',\n emailVerifiedAt: '2026-01-01T00:00:00.000Z',\n },\n workspaces: [{id: WORKSPACE_ID, name: 'Acme', slug: 'acme', membershipId: 'membership-1'}],\n};\n\nfunction ProjectsHubPageStory({scenario}: {scenario: Scenario}) {\n configureApiClient({\n baseUrl: 'https://api.example.test',\n fetchImpl: fetchForScenario(scenario),\n });\n\n const queryClient = useMemo(\n () => new QueryClient({defaultOptions: {queries: {retry: false}}}),\n [],\n );\n const store = useMemo(() => {\n const nextStore = createStore();\n nextStore.set(authStateAtom, authState);\n return nextStore;\n }, []);\n const router = useMemo(() => createStoryRouter(), []);\n\n return (\n <QueryClientProvider client={queryClient}>\n <JotaiProvider store={store}>\n <div className=\"min-h-screen bg-background-subtle-base px-24 py-32\">\n <div className=\"mx-auto w-full max-w-[1120px]\">\n <RouterProvider router={router} />\n </div>\n </div>\n <Toaster />\n </JotaiProvider>\n </QueryClientProvider>\n );\n}\n\nconst meta = {\n title: 'Projects/ProjectsHubPage',\n component: ProjectsHubPageStory,\n parameters: {layout: 'fullscreen'},\n args: {scenario: 'list'},\n} satisfies Meta<typeof ProjectsHubPageStory>;\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Playground: Story = {};\n\nexport const Empty: Story = {\n args: {scenario: 'empty'},\n};\n\nexport const Loading: Story = {\n args: {scenario: 'loading'},\n};\n\nexport const ErrorState: Story = {\n args: {scenario: 'error'},\n};\n\nfunction createStoryRouter() {\n const rootRoute = createRootRoute({component: Outlet});\n const workspaceRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: '/w/$workspaceSlug',\n component: ProjectsHubPage,\n });\n\n return createRouter({\n history: createMemoryHistory({initialEntries: ['/w/acme']}),\n routeTree: rootRoute.addChildren([workspaceRoute]),\n });\n}\n\nfunction fetchForScenario(scenario: Scenario): typeof fetch {\n return (input) => {\n const url = requestUrl(input);\n\n if (url.pathname.endsWith('/agent/model-providers')) {\n return Promise.resolve(\n jsonResponse({\n configs: [\n {\n kind: 'builtin',\n provider_id: 'anthropic',\n default_model: null,\n created_at: '2026-01-01T00:00:00.000Z',\n updated_at: '2026-01-01T00:00:00.000Z',\n },\n ],\n default_provider_id: 'anthropic',\n default_harness_id: null,\n }),\n );\n }\n\n if (url.pathname === '/integration-connections') {\n return Promise.resolve(\n jsonResponse({\n connections: [\n {\n id: CONNECTION_ID,\n workspace_id: WORKSPACE_ID,\n provider: 'github',\n external_account_id: 'octo',\n slug: 'github_octo',\n display_name: 'Acme GitHub',\n lifecycle_status: 'active',\n capabilities: ['source_control'],\n created_at: '2026-01-01T00:00:00.000Z',\n updated_at: '2026-01-01T00:00:00.000Z',\n },\n ],\n }),\n );\n }\n\n if (url.pathname === '/projects') {\n if (scenario === 'loading') {\n return new Promise<Response>(() => {\n // Keep the request pending to show the initial skeleton.\n });\n }\n if (scenario === 'error') {\n return Promise.resolve(jsonResponse({code: 'server-error'}, {status: 500}));\n }\n if (scenario === 'empty') {\n return Promise.resolve(jsonResponse({projects: [], next_cursor: null}));\n }\n\n return Promise.resolve(\n jsonResponse({\n projects: [\n projectForStory('Platform', '11111111-1111-4111-8111-111111111112'),\n projectForStory('Agent', '11111111-1111-4111-8111-111111111113'),\n projectForStory('Workflows', '11111111-1111-4111-8111-111111111114'),\n ],\n next_cursor: null,\n }),\n );\n }\n\n return Promise.resolve(jsonResponse({}, {status: 404}));\n };\n}\n\nfunction projectForStory(name: string, id: string) {\n return {\n id,\n workspace_id: WORKSPACE_ID,\n name,\n slug: name.toLowerCase(),\n source: {\n connection_id: CONNECTION_ID,\n external_repository_id: `github:octo/${name.toLowerCase()}`,\n },\n created_at: '2026-01-01T00:00:00.000Z',\n updated_at: '2026-01-01T00:00:00.000Z',\n };\n}\n\nfunction requestUrl(input: RequestInfo | URL): URL {\n if (input instanceof Request) return new URL(input.url);\n if (input instanceof URL) return input;\n return new URL(input, 'https://api.example.test');\n}\n\nfunction jsonResponse(body: unknown, init: ResponseInit = {}) {\n return new Response(JSON.stringify(body), {\n status: 200,\n headers: {'content-type': 'application/json'},\n ...init,\n });\n}\n"],"names":["configureApiClient","authStateAtom","Toaster","QueryClient","QueryClientProvider","createMemoryHistory","createRootRoute","createRoute","createRouter","Outlet","RouterProvider","createStore","Provider","JotaiProvider","useMemo","ProjectsHubPage","WORKSPACE_ID","CONNECTION_ID","authState","status","token","user","id","email","name","emailVerifiedAt","workspaces","slug","membershipId","ProjectsHubPageStory","scenario","baseUrl","fetchImpl","fetchForScenario","queryClient","defaultOptions","queries","retry","store","nextStore","set","router","createStoryRouter","client","div","className","meta","title","component","parameters","layout","args","Playground","Empty","Loading","ErrorState","rootRoute","workspaceRoute","getParentRoute","path","history","initialEntries","routeTree","addChildren","input","url","requestUrl","pathname","endsWith","Promise","resolve","jsonResponse","configs","kind","provider_id","default_model","created_at","updated_at","default_provider_id","default_harness_id","connections","workspace_id","provider","external_account_id","display_name","lifecycle_status","capabilities","code","projects","next_cursor","projectForStory","toLowerCase","source","connection_id","external_repository_id","Request","URL","body","init","Response","JSON","stringify","headers"],"mappings":"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"}