Projekt

Obecné

Profil

« Předchozí | Další » 

Revize b73954d1

Přidáno uživatelem Václav Honzík před více než 2 roky(ů)

re #9196

Zobrazit rozdíly:

frontend/package.json
16 16
    "@types/react-dom": "^17.0.9",
17 17
    "axios": "^0.26.0",
18 18
    "dotenv": "^16.0.0",
19
    "formik": "^2.2.9",
19 20
    "react": "^17.0.2",
20 21
    "react-dom": "^17.0.2",
21 22
    "react-router-dom": "^6.2.2",
frontend/src/api/ApiClient.ts
1
import axios from 'axios'
2
import Config from '../config/Config'
3

  
4
const ApiClient = axios.create({
5
    baseURL: Config.baseUrl
6
})
frontend/src/api/axios.ts
1
import axios from 'axios'
2
import Config from '../config/Config'
3

  
4
export default axios.create({
5
    baseURL: Config.baseUrl,
6

  
7
})
8

  
frontend/src/components/StubComponent.tsx
1
// Example component that connects to the backend API and fetches dummy data
2

  
3
import { useState } from 'react'
4
import AxiosClient from '../services/AxiosClient'
5

  
6
const StubComponent = () => {
7

  
8
    const [text, setText] = useState<string>('')
9

  
10
    // Sends swagger request to the backend
11
    const fetchStub = async () => {
12
        try {
13
            const { data } = await AxiosClient.get('/stub')
14
            if (!!data && data.success) {
15
                setText(data.message as string)
16
            }
17
        }
18
        catch (err) {
19
            console.log(`An error has occurred: ${err}`)
20
        }
21
    }
22

  
23
    return (
24
        <>
25
            <h1>Welcome to the internet</h1>
26
            <p>Click the button to fetch the message</p>
27
            <p>The message: {text}</p>
28
            <button onClick={fetchStub}>Fetch the message</button>
29
        </>
30
    )
31

  
32
}
33

  
34
export default StubComponent
frontend/src/features/Auth/AuthService.ts
1
import axios from "../../api/axios"
2
import { UserDto } from "../../swagger/data-contracts"
3
import ApiCallError from "../../utils/ApiCallError"
1 4

  
2
export default  {}
5
export const getAccessToken = () => localStorage.getItem('accessToken') as string | null
6
export const getRefreshToken = () => localStorage.getItem('refreshToken') as string | null
7

  
8
export const setAccessToken = (accessToken: string) => localStorage.setItem('accessToken', accessToken)
9
export const setRefreshToken = (refreshToken: string) => localStorage.setItem('refreshToken', refreshToken)
10

  
11

  
12
export const sendRegisterRequest = (userDto: UserDto) => {
13
    
14
}
15

  
16
export const sendLoginRequest = async (username: string, password: string, setLoggedInState: (loggedIn: boolean) => void) => {
17
    try {
18
        const { data } = await axios.post('/login', {username, password})
19

  
20
        if (!data) {
21
            throw new ApiCallError("An authentication error has occurred. Please try again later")
22
        }
23

  
24
        // TODO - set state as logged in
25
        const { accessToken, refreshToken } = data
26
        setAccessToken(accessToken)
27
        setRefreshToken(refreshToken)
28
        setLoggedInState(true)
29
    }
30
    catch (err) {
31

  
32
    }
33
}
frontend/src/features/Auth/Login.tsx
1

  
2
const Login = () => {
3

  
4
    return (
5
        <>
6

  
7
        </>
8
    )
9
}
10

  
11
export default Login
frontend/src/features/Catalog/CatalogService.ts
1
import axios from "../../api/axios"
2
import { CatalogDto } from "../../swagger/data-contracts"
3

  
4
export const getCatalogItems = async (componentMounted: boolean, setCatalog: (catalogItems: CatalogDto[]) => void, ) => {
5
    try {
6
        const { data } = await axios.get('/catalog')
7
    }
8
    catch (err: any) {
9

  
10
    }
11
}
12

  
13
export const getCatalogItem = (id: string) => {
14

  
15
}
frontend/src/scripts/GenerateDtosFromSwagger.ts
1
import { generateApi } from 'swagger-typescript-api'
2
import Config from '../config/Config'
3

  
4
await generateApi({
5
    name: 'apiDefinitions.ts',
6
    output: '../swagger',
7
    generateUnionEnums: true,
8
    url: Config.baseUrl,
9
    prettier: {
10
        printWidth: 100,
11
        trailingComma: "es5",
12
        singleQuote: true,
13
        semi: true,
14
        arrowParens: "avoid",
15
        tabWidth: 2,
16
        parser: "typescript",
17
    }
18
})
frontend/src/services/AxiosClient.ts
1
import axios from 'axios'
2
import Config from '../config/Config'
3

  
4
export default axios.create({
5
    baseURL: Config.baseUrl,
6
})
frontend/src/swagger/Catalog.ts
1
/* eslint-disable */
2
/* tslint:disable */
3
/*
4
 * ---------------------------------------------------------------
5
 * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API        ##
6
 * ##                                                           ##
7
 * ## AUTHOR: acacode                                           ##
8
 * ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
9
 * ---------------------------------------------------------------
10
 */
11

  
12
import { CatalogDto } from "./data-contracts";
13
import { ContentType, HttpClient, RequestParams } from "./http-client";
14

  
15
export class Catalog<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
16
  /**
17
   * No description
18
   *
19
   * @tags catalog-controller
20
   * @name UpdateCatalogEntry
21
   * @request PUT:/catalog/{id}
22
   */
23
  updateCatalogEntry = (id: string, data: CatalogDto, params: RequestParams = {}) =>
24
    this.request<void, any>({
25
      path: `/catalog/${id}`,
26
      method: "PUT",
27
      body: data,
28
      type: ContentType.Json,
29
      ...params,
30
    });
31
  /**
32
   * No description
33
   *
34
   * @tags catalog-controller
35
   * @name DeleteCatalogEntry
36
   * @request DELETE:/catalog/{id}
37
   */
38
  deleteCatalogEntry = (id: string, params: RequestParams = {}) =>
39
    this.request<void, any>({
40
      path: `/catalog/${id}`,
41
      method: "DELETE",
42
      ...params,
43
    });
44
  /**
45
   * No description
46
   *
47
   * @tags catalog-controller
48
   * @name GetAllUsers1
49
   * @request GET:/catalog
50
   */
51
  getAllUsers1 = (params: RequestParams = {}) =>
52
    this.request<CatalogDto[], any>({
53
      path: `/catalog`,
54
      method: "GET",
55
      ...params,
56
    });
57
  /**
58
   * No description
59
   *
60
   * @tags catalog-controller
61
   * @name AddCatalogEntry
62
   * @request POST:/catalog
63
   */
64
  addCatalogEntry = (data: CatalogDto, params: RequestParams = {}) =>
65
    this.request<void, any>({
66
      path: `/catalog`,
67
      method: "POST",
68
      body: data,
69
      type: ContentType.Json,
70
      ...params,
71
    });
72
}
frontend/src/swagger/Register.ts
1
/* eslint-disable */
2
/* tslint:disable */
3
/*
4
 * ---------------------------------------------------------------
5
 * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API        ##
6
 * ##                                                           ##
7
 * ## AUTHOR: acacode                                           ##
8
 * ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
9
 * ---------------------------------------------------------------
10
 */
11

  
12
import { UserDto } from "./data-contracts";
13
import { ContentType, HttpClient, RequestParams } from "./http-client";
14

  
15
export class Register<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
16
  /**
17
   * No description
18
   *
19
   * @tags user-controller
20
   * @name RegisterNewUser
21
   * @request POST:/register
22
   */
23
  registerNewUser = (data: UserDto, params: RequestParams = {}) =>
24
    this.request<void, any>({
25
      path: `/register`,
26
      method: "POST",
27
      body: data,
28
      type: ContentType.Json,
29
      ...params,
30
    });
31
}
frontend/src/swagger/Token.ts
1
/* eslint-disable */
2
/* tslint:disable */
3
/*
4
 * ---------------------------------------------------------------
5
 * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API        ##
6
 * ##                                                           ##
7
 * ## AUTHOR: acacode                                           ##
8
 * ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
9
 * ---------------------------------------------------------------
10
 */
11

  
12
import { HttpClient, RequestParams } from "./http-client";
13

  
14
export class Token<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
15
  /**
16
   * No description
17
   *
18
   * @tags user-controller
19
   * @name RefreshToken
20
   * @request GET:/token/refresh
21
   */
22
  refreshToken = (params: RequestParams = {}) =>
23
    this.request<void, any>({
24
      path: `/token/refresh`,
25
      method: "GET",
26
      ...params,
27
    });
28
}
frontend/src/swagger/User.ts
1
/* eslint-disable */
2
/* tslint:disable */
3
/*
4
 * ---------------------------------------------------------------
5
 * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API        ##
6
 * ##                                                           ##
7
 * ## AUTHOR: acacode                                           ##
8
 * ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
9
 * ---------------------------------------------------------------
10
 */
11

  
12
import { UserDto } from "./data-contracts";
13
import { ContentType, HttpClient, RequestParams } from "./http-client";
14

  
15
export class User<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
16
  /**
17
   * No description
18
   *
19
   * @tags user-controller
20
   * @name UpdateUser
21
   * @request PUT:/user/{username}
22
   */
23
  updateUser = (username: string, data: UserDto, params: RequestParams = {}) =>
24
    this.request<void, any>({
25
      path: `/user/${username}`,
26
      method: "PUT",
27
      body: data,
28
      type: ContentType.Json,
29
      ...params,
30
    });
31
  /**
32
   * No description
33
   *
34
   * @tags user-controller
35
   * @name DeleteUser
36
   * @request DELETE:/user/{username}
37
   */
38
  deleteUser = (username: string, params: RequestParams = {}) =>
39
    this.request<void, any>({
40
      path: `/user/${username}`,
41
      method: "DELETE",
42
      ...params,
43
    });
44
}
frontend/src/swagger/Users.ts
1
/* eslint-disable */
2
/* tslint:disable */
3
/*
4
 * ---------------------------------------------------------------
5
 * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API        ##
6
 * ##                                                           ##
7
 * ## AUTHOR: acacode                                           ##
8
 * ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
9
 * ---------------------------------------------------------------
10
 */
11

  
12
import { UserDto } from "./data-contracts";
13
import { HttpClient, RequestParams } from "./http-client";
14

  
15
export class Users<SecurityDataType = unknown> extends HttpClient<SecurityDataType> {
16
  /**
17
   * No description
18
   *
19
   * @tags user-controller
20
   * @name GetAllUsers
21
   * @request GET:/users
22
   */
23
  getAllUsers = (params: RequestParams = {}) =>
24
    this.request<UserDto[], any>({
25
      path: `/users`,
26
      method: "GET",
27
      ...params,
28
    });
29
}
frontend/src/swagger/data-contracts.ts
1
/* eslint-disable */
2
/* tslint:disable */
3
/*
4
 * ---------------------------------------------------------------
5
 * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API        ##
6
 * ##                                                           ##
7
 * ## AUTHOR: acacode                                           ##
8
 * ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
9
 * ---------------------------------------------------------------
10
 */
11

  
12
export interface UserDto {
13
  name?: string;
14
  email: string;
15
  canRead?: boolean;
16
  canWrite?: boolean;
17
  canDelete?: boolean;
18
}
19

  
20
export interface CatalogDto {
21
  /** @format uuid */
22
  id?: string;
23
  name?: string;
24

  
25
  /** @format int32 */
26
  certainty?: number;
27

  
28
  /** @format double */
29
  longitude?: number;
30

  
31
  /** @format double */
32
  latitude?: number;
33
  bibliography?: string[];
34
  countries?: string[];
35
  writtenForms?: string[];
36
  alternativeNames?: string[];
37
  types?: string[];
38
}
frontend/src/swagger/http-client.ts
1
/* eslint-disable */
2
/* tslint:disable */
3
/*
4
 * ---------------------------------------------------------------
5
 * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API        ##
6
 * ##                                                           ##
7
 * ## AUTHOR: acacode                                           ##
8
 * ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
9
 * ---------------------------------------------------------------
10
 */
11

  
12
export type QueryParamsType = Record<string | number, any>;
13
export type ResponseFormat = keyof Omit<Body, "body" | "bodyUsed">;
14

  
15
export interface FullRequestParams extends Omit<RequestInit, "body"> {
16
  /** set parameter to `true` for call `securityWorker` for this request */
17
  secure?: boolean;
18
  /** request path */
19
  path: string;
20
  /** content type of request body */
21
  type?: ContentType;
22
  /** query params */
23
  query?: QueryParamsType;
24
  /** format of response (i.e. response.json() -> format: "json") */
25
  format?: ResponseFormat;
26
  /** request body */
27
  body?: unknown;
28
  /** base url */
29
  baseUrl?: string;
30
  /** request cancellation token */
31
  cancelToken?: CancelToken;
32
}
33

  
34
export type RequestParams = Omit<FullRequestParams, "body" | "method" | "query" | "path">;
35

  
36
export interface ApiConfig<SecurityDataType = unknown> {
37
  baseUrl?: string;
38
  baseApiParams?: Omit<RequestParams, "baseUrl" | "cancelToken" | "signal">;
39
  securityWorker?: (securityData: SecurityDataType | null) => Promise<RequestParams | void> | RequestParams | void;
40
  customFetch?: typeof fetch;
41
}
42

  
43
export interface HttpResponse<D extends unknown, E extends unknown = unknown> extends Response {
44
  data: D;
45
  error: E;
46
}
47

  
48
type CancelToken = Symbol | string | number;
49

  
50
export enum ContentType {
51
  Json = "application/json",
52
  FormData = "multipart/form-data",
53
  UrlEncoded = "application/x-www-form-urlencoded",
54
}
55

  
56
export class HttpClient<SecurityDataType = unknown> {
57
  public baseUrl: string = "http://localhost:8080";
58
  private securityData: SecurityDataType | null = null;
59
  private securityWorker?: ApiConfig<SecurityDataType>["securityWorker"];
60
  private abortControllers = new Map<CancelToken, AbortController>();
61
  private customFetch = (...fetchParams: Parameters<typeof fetch>) => fetch(...fetchParams);
62

  
63
  private baseApiParams: RequestParams = {
64
    credentials: "same-origin",
65
    headers: {},
66
    redirect: "follow",
67
    referrerPolicy: "no-referrer",
68
  };
69

  
70
  constructor(apiConfig: ApiConfig<SecurityDataType> = {}) {
71
    Object.assign(this, apiConfig);
72
  }
73

  
74
  public setSecurityData = (data: SecurityDataType | null) => {
75
    this.securityData = data;
76
  };
77

  
78
  private encodeQueryParam(key: string, value: any) {
79
    const encodedKey = encodeURIComponent(key);
80
    return `${encodedKey}=${encodeURIComponent(typeof value === "number" ? value : `${value}`)}`;
81
  }
82

  
83
  private addQueryParam(query: QueryParamsType, key: string) {
84
    return this.encodeQueryParam(key, query[key]);
85
  }
86

  
87
  private addArrayQueryParam(query: QueryParamsType, key: string) {
88
    const value = query[key];
89
    return value.map((v: any) => this.encodeQueryParam(key, v)).join("&");
90
  }
91

  
92
  protected toQueryString(rawQuery?: QueryParamsType): string {
93
    const query = rawQuery || {};
94
    const keys = Object.keys(query).filter((key) => "undefined" !== typeof query[key]);
95
    return keys
96
      .map((key) => (Array.isArray(query[key]) ? this.addArrayQueryParam(query, key) : this.addQueryParam(query, key)))
97
      .join("&");
98
  }
99

  
100
  protected addQueryParams(rawQuery?: QueryParamsType): string {
101
    const queryString = this.toQueryString(rawQuery);
102
    return queryString ? `?${queryString}` : "";
103
  }
104

  
105
  private contentFormatters: Record<ContentType, (input: any) => any> = {
106
    [ContentType.Json]: (input: any) =>
107
      input !== null && (typeof input === "object" || typeof input === "string") ? JSON.stringify(input) : input,
108
    [ContentType.FormData]: (input: any) =>
109
      Object.keys(input || {}).reduce((formData, key) => {
110
        const property = input[key];
111
        formData.append(
112
          key,
113
          property instanceof Blob
114
            ? property
115
            : typeof property === "object" && property !== null
116
            ? JSON.stringify(property)
117
            : `${property}`,
118
        );
119
        return formData;
120
      }, new FormData()),
121
    [ContentType.UrlEncoded]: (input: any) => this.toQueryString(input),
122
  };
123

  
124
  private mergeRequestParams(params1: RequestParams, params2?: RequestParams): RequestParams {
125
    return {
126
      ...this.baseApiParams,
127
      ...params1,
128
      ...(params2 || {}),
129
      headers: {
130
        ...(this.baseApiParams.headers || {}),
131
        ...(params1.headers || {}),
132
        ...((params2 && params2.headers) || {}),
133
      },
134
    };
135
  }
136

  
137
  private createAbortSignal = (cancelToken: CancelToken): AbortSignal | undefined => {
138
    if (this.abortControllers.has(cancelToken)) {
139
      const abortController = this.abortControllers.get(cancelToken);
140
      if (abortController) {
141
        return abortController.signal;
142
      }
143
      return void 0;
144
    }
145

  
146
    const abortController = new AbortController();
147
    this.abortControllers.set(cancelToken, abortController);
148
    return abortController.signal;
149
  };
150

  
151
  public abortRequest = (cancelToken: CancelToken) => {
152
    const abortController = this.abortControllers.get(cancelToken);
153

  
154
    if (abortController) {
155
      abortController.abort();
156
      this.abortControllers.delete(cancelToken);
157
    }
158
  };
159

  
160
  public request = async <T = any, E = any>({
161
    body,
162
    secure,
163
    path,
164
    type,
165
    query,
166
    format,
167
    baseUrl,
168
    cancelToken,
169
    ...params
170
  }: FullRequestParams): Promise<HttpResponse<T, E>> => {
171
    const secureParams =
172
      ((typeof secure === "boolean" ? secure : this.baseApiParams.secure) &&
173
        this.securityWorker &&
174
        (await this.securityWorker(this.securityData))) ||
175
      {};
176
    const requestParams = this.mergeRequestParams(params, secureParams);
177
    const queryString = query && this.toQueryString(query);
178
    const payloadFormatter = this.contentFormatters[type || ContentType.Json];
179
    const responseFormat = format || requestParams.format;
180

  
181
    return this.customFetch(`${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, {
182
      ...requestParams,
183
      headers: {
184
        ...(type && type !== ContentType.FormData ? { "Content-Type": type } : {}),
185
        ...(requestParams.headers || {}),
186
      },
187
      signal: cancelToken ? this.createAbortSignal(cancelToken) : void 0,
188
      body: typeof body === "undefined" || body === null ? null : payloadFormatter(body),
189
    }).then(async (response) => {
190
      const r = response as HttpResponse<T, E>;
191
      r.data = null as unknown as T;
192
      r.error = null as unknown as E;
193

  
194
      const data = !responseFormat
195
        ? r
196
        : await response[responseFormat]()
197
            .then((data) => {
198
              if (r.ok) {
199
                r.data = data;
200
              } else {
201
                r.error = data;
202
              }
203
              return r;
204
            })
205
            .catch((e) => {
206
              r.error = e;
207
              return r;
208
            });
209

  
210
      if (cancelToken) {
211
        this.abortControllers.delete(cancelToken);
212
      }
213

  
214
      if (!response.ok) throw data;
215
      return data;
216
    });
217
  };
218
}
frontend/src/utils/ApiCallError.ts
1
export default class ApiCallError extends Error {}

Také k dispozici: Unified diff