+ Pets with the status available from the Swagger Petstore
+
+
+
+
#
+
Name
+
Status
+
+
+
+ @for (pet of pets(); track pet.id; let index = $index) {
+
+
{{ index + 1 }}
+
{{ pet.name }}
+
{{ pet.status }}
+
+ }
+
+
diff --git a/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/exercise/app.component.ts b/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/exercise/app.component.ts
new file mode 100644
index 0000000000..34885cd76a
--- /dev/null
+++ b/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/exercise/app.component.ts
@@ -0,0 +1,33 @@
+import { Component, inject, signal } from '@angular/core';
+import { ApiFactoryService } from '@o3r/apis-manager';
+import { type Pet, PetApi, StoreApi } from 'sdk';
+
+@Component({
+ selector: 'app-root',
+ standalone: true,
+ imports: [],
+ templateUrl: './app.component.html',
+ styleUrl: './app.component.scss'
+})
+export class AppComponent {
+ /** Title of the application */
+ public title = 'tutorial-app';
+
+ /* Inject the ApiFactoryService and get the corresponding APIs */
+ private petApi;
+ private storeApi;
+
+ private readonly petsWritable = signal([]);
+ public readonly pets = this.petsWritable.asReadonly();
+
+ private readonly petsInventoryWritable = signal<{ [key: string]: number }>({});
+ public readonly petsInventory = this.petsInventoryWritable.asReadonly();
+
+ public async getAvailablePets() {
+ /* Get the pets whose status is 'available' */
+ }
+
+ public async getPetInventory() {
+ /* Get the pets inventory */
+ }
+}
diff --git a/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/exercise/app.config.ts b/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/exercise/app.config.ts
new file mode 100644
index 0000000000..8c5a84fd88
--- /dev/null
+++ b/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/exercise/app.config.ts
@@ -0,0 +1,33 @@
+import { ApiFetchClient } from '@ama-sdk/client-fetch';
+import { ApiClient, PluginRunner, RequestOptions, RequestPlugin } from '@ama-sdk/core';
+import { ApplicationConfig, importProvidersFrom, provideZoneChangeDetection } from '@angular/core';
+import { provideRouter } from '@angular/router';
+import { ApiManager, ApiManagerModule } from '@o3r/apis-manager';
+import { routes } from './app.routes';
+
+class RequestLogPlugin implements RequestPlugin {
+ public load(): PluginRunner {
+ return {
+ transform: (data: RequestOptions) => {
+ alert(JSON.stringify(data));
+ return data;
+ }
+ };
+ }
+}
+
+// Default configuration for all the APIs defined in the ApiManager
+const apiConfig: ApiClient = new ApiFetchClient(
+ // Properties of ApiFetchClient
+);
+const apiManager = new ApiManager(apiConfig, {
+ // Configuration override for a specific API
+});
+
+export const appConfig: ApplicationConfig = {
+ providers: [
+ provideZoneChangeDetection({ eventCoalescing: true }),
+ provideRouter(routes),
+ importProvidersFrom(ApiManagerModule.forRoot(apiManager))
+ ]
+};
diff --git a/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/instructions.md b/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/instructions.md
new file mode 100644
index 0000000000..a9136b70ea
--- /dev/null
+++ b/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/instructions.md
@@ -0,0 +1,40 @@
+When dealing with an Angular project, you need to ensure that your `ApiClient` will be shared accross
+your application. The Otter framework provides the `ApiManager` service to manage your API collection.
+
+### Objective
+- Leverage the `ApiManager` service to access two different clients to retrieve the list of available pets and submit an order for the first pet returned.
+- Add a plugin to the `OrderApi` to log each time a call is sent.
+
+### Prerequisite
+- The package `@o3r/apis-manager` needs to be installed in the project with `npm install @o3r/apis-manager` (which has already been done for you).
+
+### Exercise
+As you can see in the `app.config.ts` file, a plugin `RequestLogPlugin` has been created which displays an alert box when the API receives a request.
+
+Integrate the `ApiManagerModule` in your `ApplicationConfig` and configure it to use the `RequestLogPlugin` in the `StoreApi`.
+You can inspire yourself with the following lines:
+
+```typescript
+// Default configuration for all the APIs defined in the ApiManager
+const apiConfig: ApiClient = new ApiFetchClient(
+ {
+ // Properties of ApiFetchClient
+ }
+);
+const apiManager = new ApiManager(apiConfig, {
+ // Configuration override for a specific API
+ StoreApi: new ApiFetchClient({
+ // Properties of ApiFetchClient
+ })
+});
+
+export const appConfig: ApplicationConfig = {
+ providers: [importProvidersFrom(ApiManagerModule.forRoot(apiManager))]
+};
+```
+
+Now, checkout the `app.component.ts` file and inject the `ApiFactoryService` to use your unique instance of the `StoreApi` and `PetApi`.
+In the existing functions, update the `pets` signal with the result of a call to `findPetsByStatus` and the `petsInventory` signal with the the result of `getInventory`.
+
+Now, when clicking the **Get Available Pets** button, your table should be updated with the list of available pets (without the alert box).
+When clicking the **Get Inventory** button, you should see the request to the `StoreApi` logged in the alert box.
diff --git a/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/solution/app.component.ts b/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/solution/app.component.ts
new file mode 100644
index 0000000000..b8ef620814
--- /dev/null
+++ b/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/solution/app.component.ts
@@ -0,0 +1,37 @@
+import { Component, inject, signal } from '@angular/core';
+import { ApiFactoryService } from '@o3r/apis-manager';
+import { type Pet, PetApi, StoreApi } from 'sdk';
+
+@Component({
+ selector: 'app-root',
+ standalone: true,
+ imports: [],
+ templateUrl: './app.component.html',
+ styleUrl: './app.component.scss'
+})
+export class AppComponent {
+ /** Title of the application */
+ public title = 'tutorial-app';
+
+ /* Inject the ApiFactoryService and get the corresponding APIs */
+ private petApi = inject(ApiFactoryService).getApi(PetApi);
+ private storeApi = inject(ApiFactoryService).getApi(StoreApi);
+
+ private readonly petsWritable = signal([]);
+ public readonly pets = this.petsWritable.asReadonly();
+
+ private readonly petsInventoryWritable = signal<{ [key: string]: number }>({});
+ public readonly petsInventory = this.petsInventoryWritable.asReadonly();
+
+ public async getAvailablePets() {
+ /* Get the pets whose status is 'available' */
+ const availablePets = await this.petApi.findPetsByStatus({status: 'available'});
+ this.petsWritable.set(availablePets);
+ }
+
+ public async getPetInventory() {
+ /* Get the pets inventory */
+ const inventory = await this.storeApi.getInventory({});
+ this.petsInventoryWritable.set(inventory);
+ }
+}
diff --git a/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/solution/app.config.ts b/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/solution/app.config.ts
new file mode 100644
index 0000000000..d10d5c3f99
--- /dev/null
+++ b/apps/showcase/src/assets/trainings/sdk/steps/angular-integration/solution/app.config.ts
@@ -0,0 +1,42 @@
+import { ApiFetchClient } from '@ama-sdk/client-fetch';
+import { ApiClient, PluginRunner, RequestOptions, RequestPlugin } from '@ama-sdk/core';
+import { ApplicationConfig, importProvidersFrom, provideZoneChangeDetection } from '@angular/core';
+import { provideRouter } from '@angular/router';
+import { ApiManager, ApiManagerModule } from '@o3r/apis-manager';
+import { routes } from './app.routes';
+
+class RequestLogPlugin implements RequestPlugin {
+ public load(): PluginRunner {
+ return {
+ transform: (data: RequestOptions) => {
+ alert(JSON.stringify(data));
+ return data;
+ }
+ };
+ }
+}
+
+// Default configuration for all the APIs defined in the ApiManager
+const apiConfig: ApiClient = new ApiFetchClient(
+ {
+ basePath: 'https://petstore3.swagger.io/api/v3',
+ requestPlugins: [],
+ fetchPlugins: []
+ }
+);
+const apiManager = new ApiManager(apiConfig, {
+ // Configuration override for a specific API
+ StoreApi: new ApiFetchClient({
+ basePath: 'https://petstore3.swagger.io/api/v3',
+ requestPlugins: [new RequestLogPlugin()],
+ fetchPlugins: []
+ })
+});
+
+export const appConfig: ApplicationConfig = {
+ providers: [
+ provideZoneChangeDetection({ eventCoalescing: true }),
+ provideRouter(routes),
+ importProvidersFrom(ApiManagerModule.forRoot(apiManager))
+ ]
+};