Skip to content

Commit

Permalink
create directories
Browse files Browse the repository at this point in the history
  • Loading branch information
maxime-urbanski committed Jun 5, 2024
1 parent cb47c8b commit e57f0c5
Show file tree
Hide file tree
Showing 43 changed files with 1,143 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/generators.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import TypescriptInterfaceGenerator from "./generators/TypescriptInterfaceGenera
import VueGenerator from "./generators/VueGenerator.js";
import VuetifyGenerator from "./generators/VuetifyGenerator.js";
import QuasarGenerator from "./generators/QuasarGenerator.js";
import AngularGenerator from "./generators/AngularGenerator.js";

function wrap(cl) {
return ({ hydraPrefix, templateDirectory }) =>
Expand Down Expand Up @@ -36,5 +37,7 @@ export default async function generators(generator = "react") {
return wrap(VuetifyGenerator);
case "quasar":
return wrap(QuasarGenerator);
case "angular":
return wrap(AngularGenerator);
}
}
157 changes: 157 additions & 0 deletions src/generators/AngularGenerator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import BaseGenerator from "./BaseGenerator.js";
import handlebars from "handlebars";
import hbhComparison from "handlebars-helpers/lib/comparison.js";
import hbhString from "handlebars-helpers/lib/string.js";

export default class extends BaseGenerator {
constructor(params) {
super(params);

this.registerTemplates("angular/", [
// COMMON COMPONENTS
"app/components/common/delete/delete.component.html",
"app/components/common/delete/delete.component.ts",
"app/components/common/form/form.component.html",
"app/components/common/form/form.component.ts",
"app/components/common/header/header.component.html",
"app/components/common/header/header.component.ts",
"app/components/common/sidebar/sidebar.component.html",
"app/components/common/sidebar/sidebar.component.ts",
"app/components/common/table/table.component.html",
"app/components/common/table/table.component.ts",

// COMPONENTS
"app/components/foo/create/create.component.html",
"app/components/foo/create/create.component.ts",
"app/components/foo/edit/edit.component.html",
"app/components/foo/edit/edit.component.ts",
"app/components/foo/list/list.component.html",
"app/components/foo/list/list.component.ts",
"app/components/foo/show/show.component.html",
"app/components/foo/show/show.component.ts",
"app/app.component.html",
"app/app.component.ts",

//SVG COMPONENT
"app/components/svg/list-svg/list-svg.component.svg",
"app/components/svg/list-svg/list-svg.component.ts",
"app/components/svg/menu/menu.component.svg",
"app/components/svg/menu/menu.component.ts",

//INTERFACE
"app/interface/api.ts",
"app/interface/foo.model.ts",
"app/interface/hero.model.ts",
"app/interface/list.model.ts",
"app/interface/show.model.ts",
"app/interface/update.model.ts",

// ROUTER
"app/router/foo.ts",
"app/app.routes.ts",

//SERVICE
"app/service/hero.service.ts",
]);

handlebars.registerHelper("compare", hbhComparison.compare);
handlebars.registerHelper("lowercase", hbhString.lowercase);
}

generate(api, resource, dir) {
const lc = resource.title.toLowerCase();
const titleUcFirst =
resource.title.charAt(0).toUpperCase() + resource.title.slice(1);
const fields = this.parseFields(resource);
const hasIsRelation = fields.some((field) => field.isRelation);
const hasIsRelations = fields.some((field) => field.isRelations);
const hasDateField = fields.some((field) => field.type === "dateTime");

const context = {
title: resource.title,
name: resource.name,
lc,
uc: resource.title.toUpperCase(),
fields,
formFields: this.buildFields(fields),
hydraPrefix: this.hydraPrefix,
titleUcFirst,
hasIsRelation,
hasIsRelations,
hasRelations: hasIsRelation || hasIsRelations,
hasDateField,
};

//CREATE DIRECTORIES - These directories may already exist
[
`${dir}/assets`,
`${dir}/utils`,
`${dir}/app/components/${lc}`,
`${dir}/app/components/common`,
`${dir}/app/components/svg`,
`${dir}/app/interface`,
`${dir}/app/router`,
`${dir}/app/service`,
].forEach((dir) => this.createDir(dir, false));

//CREATE FILE
[
`${dir}/app/components/svg/list-svg/list-svg.component.svg`,
`${dir}/app/components/svg/list-svg/list-svg.component.ts`,
`${dir}/app/components/svg/menu/menu.component.svg`,
`${dir}/app/components/svg/menu/menu.component.ts`,
`${dir}/app/components/common/delete/delete.component.html`,
`${dir}/app/components/common/delete/delete.component.ts`,
`${dir}/app/components/common/form/form.component.html`,
`${dir}/app/components/common/form/form.component.ts`,
`${dir}/app/components/common/header/header.component.html`,
`${dir}/app/components/common/header/header.component.ts`,
`${dir}/app/components/common/sidebar/sidebar.component.html`,
`${dir}/app/components/common/sidebar/sidebar.component.ts`,
`${dir}/app/components/common/table/table.component.html`,
`${dir}/app/app.component.html`,
`${dir}/app/app.component.ts`,
`${dir}/app/app.routes.ts`,
].forEach((file) => this.createFile(file, file, context, false));

[
`app/components/%s/create/create.component.html",
"app/components/%s/create/create.component.ts",
"app/components/%s/edit/edit.component.html",
"app/components/%s/edit/edit.component.ts",
"app/components/%s/list/list.component.html",
"app/components/%s/list/list.component.ts",
"app/components/%s/show/show.component.html",
"app/components/%s/show/show.component.ts",`,
].forEach((file) => this.createFileFromPattern(file, dir, [lc], context));
}

parseFields(resource) {
const fields = [
...resource.writableFields,
...resource.readableFields,
].reduce((list, field) => {
if (list[field.name]) {
return list;
}

const isReferences = Boolean(
field.reference && field.maxCardinality !== 1
);
const isEmbeddeds = Boolean(field.embedded && field.maxCardinality !== 1);

return {
...list,
[field.name]: {
...field,
isReferences,
isEmbeddeds,
isRelation: field.reference || field.embedded,
isRelations: isEmbeddeds || isReferences,
},
};
}, {});

return Object.values(fields);
}
}
75 changes: 75 additions & 0 deletions src/generators/AngularGenerator.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Api, Resource, Field } from "@api-platform/api-doc-parser";
import path from "path";
import { fileURLToPath } from "url";
import fs from "fs";
import tmp from "tmp";
import AngularGenerator from "./AngularGenerator.js";

const dirname = path.dirname(fileURLToPath(import.meta.url));

test("Generate a React app", () => {
const generator = new AngularGenerator({
hydraPrefix: "hydra:",
templateDirectory: `${dirname}/../../templates`,
});
const tmpobj = tmp.dirSync({ unsafeCleanup: true });

const fields = [
new Field("bar", {
id: "http://schema.org/url",
range: "http://www.w3.org/2001/XMLSchema#string",
reference: null,
required: true,
description: "An URL",
}),
];
const resource = new Resource("abc", "http://example.com/foos", {
id: "abc",
title: "abc",
readableFields: fields,
writableFields: fields,
});
const api = new Api("http://example.com", {
entrypoint: "http://example.com:8080",
title: "My API",
resources: [resource],
});
generator.generate(api, resource, tmpobj.name);

[
"app/components/common/delete/delete.component.html",
"app/components/common/delete/delete.component.ts",
"app/components/common/form/form.component.html",
"app/components/common/form/form.component.ts",
"app/components/common/header/header.component.html",
"app/components/common/header/header.component.ts",
"app/components/common/sidebar/sidebar.component.html",
"app/components/common/sidebar/sidebar.component.ts",
"app/components/common/table /table.component.html",
"app/components/common/table/table.component.ts",
"app/components/svg/list-svg/list-svg.component.svg",
"app/components/svg/list-svg/list-svg.component.ts",
"app/components/svg/menu/menu.component.svg",
"app/components/svg/menu/menu.component.ts",
"app/interface/api.ts",
"app/interface/foo.model.ts",
"app/interface/hero.model.ts",
"app/interface/list.model.ts",
"app/interface/show.model.ts",
"app/interface/update.model.ts",
"app/router/foo.ts",
"app/service/hero.service.ts",
].forEach((file) => expect(fs.existsSync(tmpobj.name + file)).toBe(true));

[
"/components/abc/Form.tsx",
"/components/abc/List.tsx",
"/components/abc/Show.tsx",
"/interfaces/Abc.ts",
].forEach((file) => {
expect(fs.existsSync(tmpobj.name + file)).toBe(true);
expect(fs.readFileSync(tmpobj.name + file, "utf8")).toMatch(/bar/);
});

tmpobj.removeCallback();
});
1 change: 1 addition & 0 deletions src/generators/BaseGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default class {
context,
templateValues = ["foo", "Foo"]
) {
console.log(dir);
this.createFile(
vsprintf(pattern, templateValues),
vsprintf(`${dir}/${pattern}`, values),
Expand Down
9 changes: 9 additions & 0 deletions templates/angular/app/app.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<app-header></app-header>
<div class="flex">
<div class="w-1/6 h-100">
<app-sidebar></app-sidebar>
</div>
<div class="w-5/6 ">
<router-outlet></router-outlet>
</div>
</div>
17 changes: 17 additions & 0 deletions templates/angular/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {Component} from '@angular/core';
import {RouterOutlet} from '@angular/router';
import {AsyncPipe} from "@angular/common";
import {HttpClientModule} from "@angular/common/http";
import {SidebarComponent} from "./components/common/sidebar/sidebar.component";
import {HeaderComponent} from "./components/common/header/header.component";

@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, AsyncPipe, HttpClientModule, SidebarComponent, HeaderComponent],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent {
title = 'Api Platform Angular Admin';
}
24 changes: 24 additions & 0 deletions templates/angular/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {Routes} from '@angular/router';
import {ListComponent} from "./components/foo/list/list.component";
import {ShowComponent} from "./components/foo/show/show.component";
import {EditComponent} from "./components/foo/edit/edit.component";
import {CreateComponent} from "./components/foo/create/create.component";

export const routes: Routes = [
{
path: 'heroes',
component: ListComponent
},
{
path: 'heroes/add',
component: CreateComponent
},
{
path: 'heroes/:id',
component: ShowComponent,
},
{
path: 'heroes/:id/edit',
component: EditComponent
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<button
(click)="deleteAction()"
[className]="!disabled ?
'py-2 px-4 bg-red-600 text-white text-sm rounded shadow-md hover:bg-red-700' :
'py-2 px-4 bg-red-600 text-white text-sm rounded shadow-md opacity-25'"
[disabled]="disabled">
Delete
</button>
23 changes: 23 additions & 0 deletions templates/angular/app/components/common/delete/delete.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {Component, EventEmitter, Input, Output} from '@angular/core';
import {HeroService} from "../../../service/hero.service";
import {Location} from "@angular/common";

@Component({
selector: 'app-delete',
standalone: true,
imports: [],
templateUrl: './delete.component.html',
})
export class DeleteComponent {
@Input() disabled!: boolean
@Output() delete: EventEmitter<Function> = new EventEmitter<Function>()
constructor(
private heroService: HeroService,
private location: Location
) {
}

deleteAction () {
return this.delete.emit()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>form works!</p>
11 changes: 11 additions & 0 deletions templates/angular/app/components/common/form/form.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Component } from '@angular/core';

@Component({
selector: 'app-form',
standalone: true,
imports: [],
templateUrl: './form.component.html',
})
export class FormComponent {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.header {
background-color: #288690;
width: 100%;
padding: 0 8px;
box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2),
0 4px 5px 0 rgba(0, 0, 0, 0.14),
0 1px 10px 0 rgba(0, 0, 0, 0.12);
}

.menu {
padding: 8px;
cursor: pointer;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<header class="header">
<div class="menu">
<app-menu />
</div>
</header>
Loading

0 comments on commit e57f0c5

Please sign in to comment.