-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add generator to create web admin ui
- Loading branch information
Showing
31 changed files
with
732 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
libs/tools/src/generators/web-feature/web-feature-generator.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Tree } from '@nx/devkit' | ||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing' | ||
import { createMockWebApp } from '../../lib/web/create-mock-web-app' | ||
|
||
import { webFeatureGenerator } from './web-feature-generator' | ||
import { WebFeatureGeneratorSchema } from './web-feature-schema' | ||
|
||
describe('web-feature generator', () => { | ||
let tree: Tree | ||
const rawOptions: WebFeatureGeneratorSchema = { app: 'web', name: 'test' } | ||
|
||
beforeEach(() => { | ||
tree = createTreeWithEmptyWorkspace() | ||
}) | ||
|
||
it('should run successfully', async () => { | ||
await createMockWebApp(tree, rawOptions.app) | ||
await webFeatureGenerator(tree, rawOptions) | ||
|
||
expect(true).toBeTruthy() | ||
}) | ||
}) |
13 changes: 13 additions & 0 deletions
13
libs/tools/src/generators/web-feature/web-feature-generator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { formatFiles, Tree } from '@nx/devkit' | ||
import { ensureNxProjectExists } from '../../lib/utils/ensure-nx-project-exists' | ||
import { generateWebFeature, normalizeWebFeatureSchema } from '../../lib/web' | ||
import { WebFeatureGeneratorSchema } from './web-feature-schema' | ||
|
||
export async function webFeatureGenerator(tree: Tree, rawOptions: WebFeatureGeneratorSchema) { | ||
const options = normalizeWebFeatureSchema(rawOptions) | ||
ensureNxProjectExists(tree, options.app) | ||
await generateWebFeature(tree, options) | ||
await formatFiles(tree) | ||
} | ||
|
||
export default webFeatureGenerator |
13 changes: 13 additions & 0 deletions
13
libs/tools/src/generators/web-feature/web-feature-schema.d.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export type WebFeatureGeneratorSchema = Partial<NormalizedWebFeatureSchema> | ||
|
||
export interface NormalizedWebFeatureSchema { | ||
app: string | ||
name: string | ||
label: string | ||
modelName: string | ||
pluralModelName: string | ||
skipAdminCrud: boolean | ||
skipDataAccess: boolean | ||
skipFeature: boolean | ||
skipUi: boolean | ||
} |
43 changes: 43 additions & 0 deletions
43
libs/tools/src/generators/web-feature/web-feature-schema.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
{ | ||
"$schema": "http://json-schema.org/schema", | ||
"$id": "WebFeature", | ||
"title": "", | ||
"type": "object", | ||
"properties": { | ||
"name": { | ||
"type": "string", | ||
"description": "", | ||
"$default": { | ||
"$source": "argv", | ||
"index": 0 | ||
}, | ||
"x-prompt": "What name would you like to use?" | ||
}, | ||
"app": { | ||
"type": "string", | ||
"description": "The name of the application you are adding the feature to.", | ||
"default": "web" | ||
}, | ||
"skipAdminCrud": { | ||
"type": "boolean", | ||
"description": "Do not create an admin crud library for this feature.", | ||
"default": false | ||
}, | ||
"skipDataAccess": { | ||
"type": "boolean", | ||
"description": "Do not create a data access library for this feature.", | ||
"default": false | ||
}, | ||
"skipFeature": { | ||
"type": "boolean", | ||
"description": "Do not create a feature library for this feature.", | ||
"default": false | ||
}, | ||
"skipUi": { | ||
"type": "boolean", | ||
"description": "Do not create a ui library for this feature.", | ||
"default": false | ||
} | ||
}, | ||
"required": ["name"] | ||
} |
2 changes: 1 addition & 1 deletion
2
libs/tools/src/lib/api/create-mock-api.ts → .../tools/src/lib/api/create-mock-api-app.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export type WebLibType = 'data-access' | 'feature' | 'ui' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { Tree } from '@nx/devkit' | ||
import { Linter } from '@nx/linter' | ||
import { applicationGenerator, componentGenerator, libraryGenerator } from '@nx/react' | ||
|
||
export async function createMockWebApp(tree: Tree, app: string) { | ||
// Build the mock app and shell libs | ||
await applicationGenerator(tree, { | ||
directory: 'apps', | ||
e2eTestRunner: 'none', | ||
linter: Linter.EsLint, | ||
name: app, | ||
routing: true, | ||
skipFormat: true, | ||
style: 'css', | ||
}) | ||
// Create the shell data access lib | ||
await libraryGenerator(tree, { | ||
linter: Linter.EsLint, | ||
style: 'css', | ||
name: `data-access`, | ||
directory: `libs/${app}/shell`, | ||
skipFormat: true, | ||
}) | ||
|
||
// Create the shell feature lib | ||
await libraryGenerator(tree, { | ||
directory: `libs/${app}/shell`, | ||
linter: Linter.EsLint, | ||
name: `feature`, | ||
skipFormat: true, | ||
style: 'css', | ||
}) | ||
|
||
// Create the shell feature lib | ||
await createMockComponent(tree, `${app}-shell-feature`, `${app}-shell-feature`) | ||
|
||
// Create the shell routes libs | ||
await createMockComponent(tree, `${app}-shell-feature`, `${app}-shell.routes`) | ||
await createMockComponent(tree, `${app}-shell-feature`, `${app}-admin.routes`) | ||
} | ||
|
||
function createMockComponent(tree: Tree, project: string, name: string) { | ||
return componentGenerator(tree, { | ||
name, | ||
project, | ||
style: 'none', | ||
flat: true, | ||
skipTests: true, | ||
}) | ||
} |
51 changes: 51 additions & 0 deletions
51
...ools/src/lib/web/files/data-access/lib/use-admin-find-many-__modelFileName__.tsx.template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { AdminCreate<%= modelClassName %>Input, AdminFindMany<%= modelClassName %>Input } from '@<%= npmScope %>/sdk' | ||
import { useWebSdk } from '@<%= npmScope %>/<%= app %>/shell/data-access' | ||
|
||
import { useUiPagination } from '@<%= npmScope %>/<%= app %>/ui/core' | ||
import { showNotificationError, showNotificationSuccess } from '@<%= npmScope %>/<%= app %>/ui/notifications' | ||
import { useQuery } from '@tanstack/react-query' | ||
import { useState } from 'react' | ||
|
||
export function useAdminFindMany<%= modelClassName %>(props?: Partial<AdminFindMany<%= modelClassName %>Input>) { | ||
const sdk = useWebSdk() | ||
const [take, setTake] = useState(props?.take ?? 10) | ||
const [skip, setSkip] = useState(props?.skip ?? 0) | ||
const [search, setSearch] = useState<string>(props?.search ?? '') | ||
|
||
const input: AdminFindMany<%= modelClassName %>Input = { skip, take, search } | ||
const query = useQuery(['admin', '<%= modelPropertyName %>s', 'find', input], () => sdk.adminFindMany<%= modelClassName %>s({ input }).then((res) => res.data)) | ||
const total = query.data?.count?.total ?? 0 | ||
|
||
return { | ||
create<%= modelClassName %>: (input: AdminCreate<%= modelClassName %>Input) => | ||
sdk | ||
.adminCreate<%= modelClassName %>({ input }) | ||
.then((res) => res.data) | ||
.then((res) => { | ||
if (res.created) { | ||
showNotificationSuccess(`<%= modelClassName %> created`) | ||
} else { | ||
showNotificationError(`<%= modelClassName %> not created`) | ||
} | ||
return res.created | ||
}) | ||
.catch((err) => { | ||
showNotificationError(err.message) | ||
return undefined | ||
}), | ||
delete<%= modelClassName %>: (<%= modelPropertyName %>Id: string) => | ||
sdk.adminDelete<%= modelClassName %>({ <%= modelPropertyName %>Id }).then(() => { | ||
showNotificationSuccess('<%= modelClassName %> deleted') | ||
return query.refetch() | ||
}), | ||
query, | ||
setSearch, | ||
pagination: useUiPagination({ | ||
skip, | ||
setSkip, | ||
take, | ||
setTake, | ||
total, | ||
}), | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
...tools/src/lib/web/files/data-access/lib/use-admin-find-one-__modelFileName__.tsx.template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { AdminUpdate<%= modelClassName %>Input } from '@<%= npmScope %>/sdk' | ||
import { useWebSdk } from '@<%= npmScope %>/<%= app %>/shell/data-access' | ||
import { showNotificationError, showNotificationSuccess } from '@<%= npmScope %>/<%= app %>/ui/notifications' | ||
import { useQuery } from '@tanstack/react-query' | ||
|
||
export function useAdminFindOne<%= modelClassName %>(<%= modelPropertyName %>Id: string) { | ||
const sdk = useWebSdk() | ||
const query = useQuery( | ||
['admin', '<%= modelPropertyName %>s', 'get', <%= modelPropertyName %>Id], | ||
() => sdk.adminFindOne<%= modelClassName %>({ <%= modelPropertyName %>Id }).then((res) => res.data), | ||
{ retry: 0 }, | ||
) | ||
const <%= modelPropertyName %> = query.data?.item ?? undefined | ||
|
||
return { | ||
<%= modelPropertyName %>, | ||
query, | ||
update<%= modelClassName %>: async (input: AdminUpdate<%= modelClassName %>Input) => | ||
sdk | ||
.adminUpdate<%= modelClassName %>({ <%= modelPropertyName %>Id, input }) | ||
.then((res) => res.data) | ||
.then(async (res) => { | ||
if (res) { | ||
showNotificationSuccess('<%= modelClassName %> updated') | ||
await query.refetch() | ||
return true | ||
} | ||
showNotificationError('<%= modelClassName %> not updated') | ||
return false | ||
}) | ||
.catch((err) => { | ||
showNotificationError(err.message) | ||
return false | ||
}), | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
...ols/src/lib/web/files/feature/lib/web-admin-__modelFileName__-create.feature.tsx.template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { Button, Group } from '@mantine/core' | ||
import { AdminCreate<%= modelClassName %>Input } from '@<%= npmScope %>/sdk' | ||
import { UiBack, UiAdminPage, UiCard } from '@<%= npmScope %>/<%= app %>/ui/core' | ||
import { showNotificationError } from '@<%= npmScope %>/<%= app %>/ui/notifications' | ||
import { useAdminFindMany<%= modelClassName %> } from '@<%= npmScope %>/<%= app %>/<%= modelFileName %>/data-access' | ||
import { AdminUiCreate<%= modelClassName %>Form } from '@<%= npmScope %>/<%= app %>/<%= modelFileName %>/ui' | ||
import { useNavigate } from 'react-router-dom' | ||
|
||
export function WebAdmin<%= modelClassName %>CreateFeature() { | ||
const navigate = useNavigate() | ||
const { create<%= modelClassName %> } = useAdminFindMany<%= modelClassName %>() | ||
|
||
const submit = async (input: AdminCreate<%= modelClassName %>Input) => | ||
create<%= modelClassName %>(input) | ||
.then((res) => navigate(`/admin/<%= modelFileName %>s/${res?.id}`)) | ||
.then(() => true) | ||
.catch((err) => { | ||
showNotificationError(err.message) | ||
return false | ||
}) | ||
|
||
return ( | ||
<UiAdminPage leftAction={<UiBack />} title="Create <%= modelClassName %>"> | ||
<UiCard> | ||
<AdminUiCreate<%= modelClassName %>Form submit={submit}> | ||
<Group position="right"> | ||
<Button type="submit">Create</Button> | ||
</Group> | ||
</AdminUiCreate<%= modelClassName %>Form> | ||
</UiCard> | ||
</UiAdminPage> | ||
) | ||
} |
13 changes: 13 additions & 0 deletions
13
...rc/lib/web/files/feature/lib/web-admin-__modelFileName__-detail-settings.tab.tsx.template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { UiAlert, UiCard } from '@<%= npmScope %>/<%= app %>/ui/core' | ||
import { useAdminFindOne<%= modelClassName %> } from '@<%= npmScope %>/<%= app %>/<%= modelFileName %>/data-access' | ||
import { AdminUiUpdate<%= modelClassName %>Form } from '@<%= npmScope %>/<%= app %>/<%= modelFileName %>/ui' | ||
|
||
export function WebAdmin<%= modelClassName %>DetailSettingsTab({ <%= modelPropertyName %>Id }: { <%= modelPropertyName %>Id: string }) { | ||
const { <%= modelPropertyName %>, update<%= modelClassName %> } = useAdminFindOne<%= modelClassName %>(<%= modelPropertyName %>Id) | ||
|
||
return ( | ||
<UiCard> | ||
{<%= modelPropertyName %> ? <AdminUiUpdate<%= modelClassName %>Form <%= modelPropertyName %>={<%= modelPropertyName %>} submit={update<%= modelClassName %>} /> : <UiAlert message="<%= modelClassName %> not found." />} | ||
</UiCard> | ||
) | ||
} |
Oops, something went wrong.