Compare commits
No commits in common. "be57bd32b8ac8e8fbbd7f3270f4c702340bd1b5f" and "31ba7bead17d151f9437b3ec32327d2f9248de2c" have entirely different histories.
be57bd32b8
...
31ba7bead1
|
|
@ -76,27 +76,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Notification": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"type": "integer",
|
|
||||||
"description": "Notification ID"
|
|
||||||
},
|
|
||||||
"message": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Notification message"
|
|
||||||
},
|
|
||||||
"timeStamp": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Notification creation date"
|
|
||||||
},
|
|
||||||
"seen": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Notification seen status"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"User": {
|
"User": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -149,24 +128,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
"UserWithRelationsAndNotifications": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/UserWithRelations"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"notifications": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/components/schemas/Notification"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -784,7 +745,7 @@
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/UserWithRelationsAndNotifications"
|
"$ref": "#/components/schemas/UserWithRelations"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -876,4 +837,4 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tags": []
|
"tags": []
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
|
|
||||||
"spaces": 2,
|
|
||||||
"generator-cli": {
|
|
||||||
"version": "7.3.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
7.3.0
|
7.2.0
|
||||||
|
|
@ -186,37 +186,6 @@ export interface CreatePostRequest {
|
||||||
*/
|
*/
|
||||||
'content'?: string;
|
'content'?: string;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @interface Notification
|
|
||||||
*/
|
|
||||||
export interface Notification {
|
|
||||||
/**
|
|
||||||
* Notification ID
|
|
||||||
* @type {number}
|
|
||||||
* @memberof Notification
|
|
||||||
*/
|
|
||||||
'id'?: number;
|
|
||||||
/**
|
|
||||||
* Notification message
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Notification
|
|
||||||
*/
|
|
||||||
'message'?: string;
|
|
||||||
/**
|
|
||||||
* Notification creation date
|
|
||||||
* @type {string}
|
|
||||||
* @memberof Notification
|
|
||||||
*/
|
|
||||||
'timeStamp'?: string;
|
|
||||||
/**
|
|
||||||
* Notification seen status
|
|
||||||
* @type {boolean}
|
|
||||||
* @memberof Notification
|
|
||||||
*/
|
|
||||||
'seen'?: boolean;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
|
|
@ -340,61 +309,6 @@ export interface UserWithRelations {
|
||||||
*/
|
*/
|
||||||
'followers'?: Array<User>;
|
'followers'?: Array<User>;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @interface UserWithRelationsAndNotifications
|
|
||||||
*/
|
|
||||||
export interface UserWithRelationsAndNotifications {
|
|
||||||
/**
|
|
||||||
* User ID
|
|
||||||
* @type {number}
|
|
||||||
* @memberof UserWithRelationsAndNotifications
|
|
||||||
*/
|
|
||||||
'id'?: number;
|
|
||||||
/**
|
|
||||||
* User first name
|
|
||||||
* @type {string}
|
|
||||||
* @memberof UserWithRelationsAndNotifications
|
|
||||||
*/
|
|
||||||
'firstName'?: string;
|
|
||||||
/**
|
|
||||||
* User last name
|
|
||||||
* @type {string}
|
|
||||||
* @memberof UserWithRelationsAndNotifications
|
|
||||||
*/
|
|
||||||
'lastName'?: string;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {Array<Post>}
|
|
||||||
* @memberof UserWithRelationsAndNotifications
|
|
||||||
*/
|
|
||||||
'posts'?: Array<Post>;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {Array<Comment>}
|
|
||||||
* @memberof UserWithRelationsAndNotifications
|
|
||||||
*/
|
|
||||||
'comments'?: Array<Comment>;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {Array<User>}
|
|
||||||
* @memberof UserWithRelationsAndNotifications
|
|
||||||
*/
|
|
||||||
'followed'?: Array<User>;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {Array<User>}
|
|
||||||
* @memberof UserWithRelationsAndNotifications
|
|
||||||
*/
|
|
||||||
'followers'?: Array<User>;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @type {Array<Notification>}
|
|
||||||
* @memberof UserWithRelationsAndNotifications
|
|
||||||
*/
|
|
||||||
'notifications'?: Array<Notification>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AuthenticationApi - axios parameter creator
|
* AuthenticationApi - axios parameter creator
|
||||||
|
|
@ -527,9 +441,9 @@ export const AuthenticationApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async authLoginPost(authLoginPostRequest: AuthLoginPostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<AuthLoginPost200Response>> {
|
async authLoginPost(authLoginPostRequest: AuthLoginPostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<AuthLoginPost200Response>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.authLoginPost(authLoginPostRequest, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.authLoginPost(authLoginPostRequest, options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['AuthenticationApi.authLoginPost']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['AuthenticationApi.authLoginPost']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -539,9 +453,9 @@ export const AuthenticationApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async authLogoutGet(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<AuthLogoutGet200Response>> {
|
async authLogoutGet(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<AuthLogoutGet200Response>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.authLogoutGet(options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.authLogoutGet(options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['AuthenticationApi.authLogoutGet']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['AuthenticationApi.authLogoutGet']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -552,9 +466,9 @@ export const AuthenticationApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async authSignupPost(authSignupPostRequest: AuthSignupPostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<User>> {
|
async authSignupPost(authSignupPostRequest: AuthSignupPostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<User>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.authSignupPost(authSignupPostRequest, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.authSignupPost(authSignupPostRequest, options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['AuthenticationApi.authSignupPost']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['AuthenticationApi.authSignupPost']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1017,9 +931,9 @@ export const PostsApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async commentPost(id: number, commentPostRequest: CommentPostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Comment>> {
|
async commentPost(id: number, commentPostRequest: CommentPostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Comment>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.commentPost(id, commentPostRequest, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.commentPost(id, commentPostRequest, options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['PostsApi.commentPost']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['PostsApi.commentPost']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -1030,9 +944,9 @@ export const PostsApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async createPost(createPostRequest: CreatePostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Post>> {
|
async createPost(createPostRequest: CreatePostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Post>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.createPost(createPostRequest, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.createPost(createPostRequest, options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['PostsApi.createPost']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['PostsApi.createPost']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -1043,9 +957,9 @@ export const PostsApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async deletePost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
|
async deletePost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.deletePost(id, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.deletePost(id, options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['PostsApi.deletePost']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['PostsApi.deletePost']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -1055,9 +969,9 @@ export const PostsApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async getAllPosts(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<Post>>> {
|
async getAllPosts(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<Post>>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.getAllPosts(options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.getAllPosts(options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['PostsApi.getAllPosts']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['PostsApi.getAllPosts']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -1067,9 +981,9 @@ export const PostsApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async getFollowedPosts(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<Post>>> {
|
async getFollowedPosts(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<Post>>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.getFollowedPosts(options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.getFollowedPosts(options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['PostsApi.getFollowedPosts']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['PostsApi.getFollowedPosts']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -1080,9 +994,9 @@ export const PostsApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async getPost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Post>> {
|
async getPost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Post>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.getPost(id, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.getPost(id, options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['PostsApi.getPost']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['PostsApi.getPost']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -1093,9 +1007,9 @@ export const PostsApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async likePost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Post>> {
|
async likePost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Post>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.likePost(id, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.likePost(id, options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['PostsApi.likePost']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['PostsApi.likePost']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -1106,9 +1020,9 @@ export const PostsApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async unlikePost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Post>> {
|
async unlikePost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Post>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.unlikePost(id, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.unlikePost(id, options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['PostsApi.unlikePost']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['PostsApi.unlikePost']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -1120,9 +1034,9 @@ export const PostsApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async updatePost(id: number, createPostRequest: CreatePostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Post>> {
|
async updatePost(id: number, createPostRequest: CreatePostRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Post>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.updatePost(id, createPostRequest, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.updatePost(id, createPostRequest, options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['PostsApi.updatePost']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['PostsApi.updatePost']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1551,9 +1465,9 @@ export const UsersApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async usersGet(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<User>>> {
|
async usersGet(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<User>>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.usersGet(options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.usersGet(options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['UsersApi.usersGet']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['UsersApi.usersGet']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -1564,9 +1478,9 @@ export const UsersApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async usersIdFollowDelete(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<UserWithRelations>> {
|
async usersIdFollowDelete(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<UserWithRelations>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.usersIdFollowDelete(id, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.usersIdFollowDelete(id, options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['UsersApi.usersIdFollowDelete']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['UsersApi.usersIdFollowDelete']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -1577,9 +1491,9 @@ export const UsersApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async usersIdFollowPost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<UserWithRelations>> {
|
async usersIdFollowPost(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<UserWithRelations>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.usersIdFollowPost(id, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.usersIdFollowPost(id, options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['UsersApi.usersIdFollowPost']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['UsersApi.usersIdFollowPost']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -1590,9 +1504,9 @@ export const UsersApiFp = function(configuration?: Configuration) {
|
||||||
*/
|
*/
|
||||||
async usersIdGet(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<UserWithRelations>> {
|
async usersIdGet(id: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<UserWithRelations>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.usersIdGet(id, options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.usersIdGet(id, options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['UsersApi.usersIdGet']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['UsersApi.usersIdGet']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -1600,11 +1514,11 @@ export const UsersApiFp = function(configuration?: Configuration) {
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
async usersMeGet(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<UserWithRelationsAndNotifications>> {
|
async usersMeGet(options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<UserWithRelations>> {
|
||||||
const localVarAxiosArgs = await localVarAxiosParamCreator.usersMeGet(options);
|
const localVarAxiosArgs = await localVarAxiosParamCreator.usersMeGet(options);
|
||||||
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
const index = configuration?.serverIndex ?? 0;
|
||||||
const localVarOperationServerBasePath = operationServerMap['UsersApi.usersMeGet']?.[localVarOperationServerIndex]?.url;
|
const operationBasePath = operationServerMap['UsersApi.usersMeGet']?.[index]?.url;
|
||||||
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1661,7 +1575,7 @@ export const UsersApiFactory = function (configuration?: Configuration, basePath
|
||||||
* @param {*} [options] Override http request option.
|
* @param {*} [options] Override http request option.
|
||||||
* @throws {RequiredError}
|
* @throws {RequiredError}
|
||||||
*/
|
*/
|
||||||
usersMeGet(options?: any): AxiosPromise<UserWithRelationsAndNotifications> {
|
usersMeGet(options?: any): AxiosPromise<UserWithRelations> {
|
||||||
return localVarFp.usersMeGet(options).then((request) => request(axios, basePath));
|
return localVarFp.usersMeGet(options).then((request) => request(axios, basePath));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ import {
|
||||||
AuthSignupPostRequest,
|
AuthSignupPostRequest,
|
||||||
AuthenticationApi,
|
AuthenticationApi,
|
||||||
Configuration,
|
Configuration,
|
||||||
UsersApi,
|
|
||||||
} from "../api";
|
} from "../api";
|
||||||
import { AppThunk } from "./store";
|
import { AppThunk } from "./store";
|
||||||
|
import { Axios, AxiosError } from "axios";
|
||||||
|
|
||||||
interface loginState {
|
interface loginState {
|
||||||
loggedIn: boolean;
|
loggedIn: boolean;
|
||||||
|
|
@ -15,7 +15,6 @@ interface loginState {
|
||||||
error: string | null;
|
error: string | null;
|
||||||
userInfo: {
|
userInfo: {
|
||||||
firstName: string;
|
firstName: string;
|
||||||
lastName: string;
|
|
||||||
jwt: string;
|
jwt: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +25,6 @@ const initialState: loginState = {
|
||||||
error: null,
|
error: null,
|
||||||
userInfo: {
|
userInfo: {
|
||||||
firstName: "",
|
firstName: "",
|
||||||
lastName: "",
|
|
||||||
jwt: "",
|
jwt: "",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -37,9 +35,7 @@ export const loginSlice = createSlice({
|
||||||
reducers: {
|
reducers: {
|
||||||
login: (state, action) => {
|
login: (state, action) => {
|
||||||
state.loggedIn = true;
|
state.loggedIn = true;
|
||||||
state.userInfo.jwt = action.payload.jwt;
|
state.userInfo.jwt = action.payload;
|
||||||
state.userInfo.firstName = action.payload.firstName;
|
|
||||||
state.userInfo.lastName = action.payload.lastName;
|
|
||||||
},
|
},
|
||||||
logoff: (state) => {
|
logoff: (state) => {
|
||||||
state.loggedIn = false;
|
state.loggedIn = false;
|
||||||
|
|
@ -54,7 +50,7 @@ export const loginSlice = createSlice({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const authApi = new AuthenticationApi(
|
const api = new AuthenticationApi(
|
||||||
new Configuration({
|
new Configuration({
|
||||||
basePath: process.env.REACT_APP_BACKEND_URL,
|
basePath: process.env.REACT_APP_BACKEND_URL,
|
||||||
})
|
})
|
||||||
|
|
@ -63,30 +59,15 @@ const authApi = new AuthenticationApi(
|
||||||
export const postLogin =
|
export const postLogin =
|
||||||
(params: AuthLoginPostRequest): AppThunk =>
|
(params: AuthLoginPostRequest): AppThunk =>
|
||||||
async (dispatch) => {
|
async (dispatch) => {
|
||||||
let response, userResponse;
|
let response;
|
||||||
try {
|
try {
|
||||||
dispatch(setStatus(Status.loading));
|
dispatch(setStatus(Status.loading));
|
||||||
response = await authApi.authLoginPost(params);
|
response = await api.authLoginPost(params);
|
||||||
|
|
||||||
|
dispatch(login(response.data.token));
|
||||||
await addJWT(response.data.token || "");
|
await addJWT(response.data.token || "");
|
||||||
|
|
||||||
// Get user info
|
dispatch(setError(""));
|
||||||
const userApi = new UsersApi(
|
|
||||||
new Configuration({
|
|
||||||
basePath: process.env.REACT_APP_BACKEND_URL,
|
|
||||||
accessToken: response.data.token,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
userResponse = await userApi.usersMeGet();
|
|
||||||
|
|
||||||
dispatch(
|
|
||||||
login({
|
|
||||||
jwt: response.data.token,
|
|
||||||
firstName: userResponse.data.firstName,
|
|
||||||
lastName: userResponse.data.lastName,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
dispatch(setStatus(Status.succeeded));
|
dispatch(setStatus(Status.succeeded));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch(setStatus(Status.failed));
|
dispatch(setStatus(Status.failed));
|
||||||
|
|
@ -102,7 +83,7 @@ export const postSignup =
|
||||||
console.log(params);
|
console.log(params);
|
||||||
try {
|
try {
|
||||||
dispatch(setStatus(Status.loading));
|
dispatch(setStatus(Status.loading));
|
||||||
response = await authApi.authSignupPost(params);
|
response = await api.authSignupPost(params);
|
||||||
|
|
||||||
dispatch(postLogin({ email: params.email, password: params.password }));
|
dispatch(postLogin({ email: params.email, password: params.password }));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -116,7 +97,7 @@ export const postLogout = (): AppThunk => async (dispatch) => {
|
||||||
localStorage.removeItem("jwt");
|
localStorage.removeItem("jwt");
|
||||||
sessionStorage.removeItem("jwt");
|
sessionStorage.removeItem("jwt");
|
||||||
dispatch(logoff());
|
dispatch(logoff());
|
||||||
await authApi.authLogoutGet();
|
await api.authLogoutGet();
|
||||||
};
|
};
|
||||||
|
|
||||||
const addJWT = async (token: string) => {
|
const addJWT = async (token: string) => {
|
||||||
|
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
import { Store, createSlice } from "@reduxjs/toolkit";
|
|
||||||
import { Configuration, Post, PostsApi } from "../api";
|
|
||||||
import { Status } from "../util/types";
|
|
||||||
import { AppThunk, store } from "./store";
|
|
||||||
|
|
||||||
interface postSliceInterface {
|
|
||||||
status: Status;
|
|
||||||
followedPosts: Post[];
|
|
||||||
globalPosts: Post[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialState: postSliceInterface = {
|
|
||||||
status: Status.idle,
|
|
||||||
followedPosts: [],
|
|
||||||
globalPosts: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const postSlice = createSlice({
|
|
||||||
name: "post",
|
|
||||||
initialState,
|
|
||||||
reducers: {
|
|
||||||
setStatus: (state, action) => {
|
|
||||||
state.status = action.payload;
|
|
||||||
},
|
|
||||||
setFollowedPosts: (state, action) => {
|
|
||||||
state.followedPosts = action.payload;
|
|
||||||
},
|
|
||||||
setGlobalPosts: (state, action) => {
|
|
||||||
state.globalPosts = action.payload;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchFollowedPosts = (): AppThunk => async (dispatch: any) => {
|
|
||||||
const postApi = createApi(store);
|
|
||||||
|
|
||||||
dispatch(setStatus(Status.loading));
|
|
||||||
const response = await postApi.getFollowedPosts();
|
|
||||||
dispatch(setFollowedPosts(response.data));
|
|
||||||
dispatch(setStatus(Status.idle));
|
|
||||||
};
|
|
||||||
|
|
||||||
export const fetchGlobalPosts = (): AppThunk => async (dispatch: any) => {
|
|
||||||
const postApi = createApi(store);
|
|
||||||
|
|
||||||
dispatch(setStatus(Status.loading));
|
|
||||||
const response = await postApi.getAllPosts();
|
|
||||||
dispatch(setGlobalPosts(response.data));
|
|
||||||
dispatch(setStatus(Status.idle));
|
|
||||||
};
|
|
||||||
|
|
||||||
export const likePost =
|
|
||||||
(postId: number): AppThunk =>
|
|
||||||
async (dispatch: any) => {
|
|
||||||
const postApi = createApi(store);
|
|
||||||
|
|
||||||
dispatch(setStatus(Status.loading));
|
|
||||||
await postApi.likePost(postId);
|
|
||||||
dispatch(setStatus(Status.idle));
|
|
||||||
};
|
|
||||||
|
|
||||||
export const unLikePost =
|
|
||||||
(postId: number): AppThunk =>
|
|
||||||
async (dispatch: any) => {
|
|
||||||
const postApi = createApi(store);
|
|
||||||
|
|
||||||
dispatch(setStatus(Status.loading));
|
|
||||||
await postApi.unlikePost(postId);
|
|
||||||
dispatch(setStatus(Status.idle));
|
|
||||||
};
|
|
||||||
|
|
||||||
export const { setFollowedPosts, setGlobalPosts, setStatus } =
|
|
||||||
postSlice.actions;
|
|
||||||
|
|
||||||
export default postSlice.reducer;
|
|
||||||
|
|
||||||
export const selectFollowedPosts = (state: any) => state.post.followedPosts;
|
|
||||||
export const selectAllPosts = (state: any) => state.post.globalPosts;
|
|
||||||
export const selectStatus = (state: any) => state.post.status;
|
|
||||||
|
|
||||||
function createApi(store: Store) {
|
|
||||||
return new PostsApi(
|
|
||||||
new Configuration({
|
|
||||||
basePath: process.env.REACT_APP_BACKEND_URL,
|
|
||||||
accessToken: store.getState().login.userInfo.jwt,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
import { Action, ThunkAction, configureStore } from "@reduxjs/toolkit";
|
import { Action, ThunkAction, configureStore } from "@reduxjs/toolkit";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import loginReducer from "./loginSlice";
|
import loginReducer from "./loginSlice";
|
||||||
import postReducer from "./postSlice";
|
|
||||||
|
|
||||||
export const store = configureStore({
|
export const store = configureStore({
|
||||||
reducer: {
|
reducer: {
|
||||||
login: loginReducer,
|
login: loginReducer,
|
||||||
post: postReducer,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,10 @@ import FeedIcon from "@mui/icons-material/Feed";
|
||||||
import GlobalIcon from "@mui/icons-material/Public";
|
import GlobalIcon from "@mui/icons-material/Public";
|
||||||
import AddIcon from "@mui/icons-material/Add";
|
import AddIcon from "@mui/icons-material/Add";
|
||||||
import SearchIcon from "@mui/icons-material/Search";
|
import SearchIcon from "@mui/icons-material/Search";
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
export default function BottomAppBar() {
|
export default function BottomAppBar() {
|
||||||
const [value, setValue] = useState(0);
|
const [value, setValue] = useState(0);
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const handleClick = (to: string) => () => {
|
|
||||||
navigate(to);
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<Paper
|
<Paper
|
||||||
sx={{ position: "fixed", bottom: 0, left: 0, right: 0 }}
|
sx={{ position: "fixed", bottom: 0, left: 0, right: 0 }}
|
||||||
|
|
@ -25,26 +20,10 @@ export default function BottomAppBar() {
|
||||||
setValue(newValue);
|
setValue(newValue);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<BottomNavigationAction
|
<BottomNavigationAction label="My Feed" icon={<FeedIcon />} />
|
||||||
label="My Feed"
|
<BottomNavigationAction label="Global Feed" icon={<GlobalIcon />} />
|
||||||
icon={<FeedIcon />}
|
<BottomNavigationAction label="New Post" icon={<AddIcon />} />
|
||||||
onClick={handleClick("feed")}
|
<BottomNavigationAction label="Search" icon={<SearchIcon />} />
|
||||||
/>
|
|
||||||
<BottomNavigationAction
|
|
||||||
label="Global Feed"
|
|
||||||
icon={<GlobalIcon />}
|
|
||||||
onClick={handleClick("global")}
|
|
||||||
/>
|
|
||||||
<BottomNavigationAction
|
|
||||||
label="New Post"
|
|
||||||
icon={<AddIcon />}
|
|
||||||
onClick={handleClick("newpost")}
|
|
||||||
/>
|
|
||||||
<BottomNavigationAction
|
|
||||||
label="Search"
|
|
||||||
icon={<SearchIcon />}
|
|
||||||
onClick={handleClick("search")}
|
|
||||||
/>
|
|
||||||
</BottomNavigation>
|
</BottomNavigation>
|
||||||
</Paper>
|
</Paper>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { Badge, Tooltip } from "@mui/material";
|
||||||
export default function NotificationBell() {
|
export default function NotificationBell() {
|
||||||
return (
|
return (
|
||||||
<Badge badgeContent={4} color="secondary">
|
<Badge badgeContent={4} color="secondary">
|
||||||
<Tooltip title="Notifications" >
|
<Tooltip title="Notifications">
|
||||||
<NotificationsIcon />
|
<NotificationsIcon />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Badge>
|
</Badge>
|
||||||
|
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Card,
|
|
||||||
CardActionArea,
|
|
||||||
CardContent,
|
|
||||||
Grid,
|
|
||||||
ListItem,
|
|
||||||
styled,
|
|
||||||
Typography,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { Post } from "../api";
|
|
||||||
import MessageIcon from "@mui/icons-material/Message";
|
|
||||||
import ThumbUpOffAltIcon from "@mui/icons-material/ThumbUpOffAlt";
|
|
||||||
import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
import { likePost, unLikePost } from "../app/postSlice";
|
|
||||||
import { useAppDispatch } from "../app/store";
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { useSelector } from "react-redux";
|
|
||||||
import { selectUserInfo } from "../app/loginSlice";
|
|
||||||
|
|
||||||
interface PostListItemProps {
|
|
||||||
post: Post;
|
|
||||||
postType: "all" | "user";
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function PostListItem(props: PostListItemProps) {
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const userInfo = useSelector(selectUserInfo);
|
|
||||||
const [liked, setLiked] = useState(false);
|
|
||||||
const [numberOfLikes, setNumberOfLikes] = useState(0);
|
|
||||||
|
|
||||||
// On component mount, set the number of likes
|
|
||||||
// and whether the user has liked the post
|
|
||||||
useEffect(() => {
|
|
||||||
setNumberOfLikes(props.post.likedBy?.length || 0);
|
|
||||||
setLiked(props.post.likedBy?.includes(userInfo) || false);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleLike = () => {
|
|
||||||
if (!liked) {
|
|
||||||
// Instant feedback to the user
|
|
||||||
setLiked(true);
|
|
||||||
setNumberOfLikes(numberOfLikes + 1);
|
|
||||||
// Dispatch the call to the API
|
|
||||||
dispatch(likePost(props.post.id as number));
|
|
||||||
}
|
|
||||||
// If the user has already liked the post, unlike it
|
|
||||||
else {
|
|
||||||
setLiked(false);
|
|
||||||
setNumberOfLikes(numberOfLikes - 1);
|
|
||||||
|
|
||||||
dispatch(unLikePost(props.post.id as number));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlePostClick = () => {
|
|
||||||
navigate(`/post/${props.post.id}`);
|
|
||||||
};
|
|
||||||
const handleUserClick = () => {
|
|
||||||
navigate(`/user/${props.post.createdBy?.id}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ListItem
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
mt: "1rem",
|
|
||||||
justifyContent: "start",
|
|
||||||
alignItems: "start",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Button onClick={handleUserClick} sx={{ textTransform: "none" }}>
|
|
||||||
<Typography
|
|
||||||
gutterBottom
|
|
||||||
sx={{ textAlign: "left", width: "100%" }}
|
|
||||||
variant="body2"
|
|
||||||
component="div"
|
|
||||||
color="text.secondary"
|
|
||||||
>
|
|
||||||
{props.post.createdBy?.firstName} {props.post.createdBy?.lastName}
|
|
||||||
</Typography>
|
|
||||||
</Button>
|
|
||||||
<Card sx={{ maxWidth: 400, width: "100%" }}>
|
|
||||||
<CardActionArea sx={{ mb: "0.8rem" }} onClick={handlePostClick}>
|
|
||||||
<CardContent>
|
|
||||||
<Typography gutterBottom variant="h5" component="div">
|
|
||||||
{props.post.title}
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="h6" color="text.secondary">
|
|
||||||
{props.post.content}
|
|
||||||
</Typography>
|
|
||||||
</CardContent>
|
|
||||||
</CardActionArea>
|
|
||||||
<Grid
|
|
||||||
container
|
|
||||||
spacing={1}
|
|
||||||
sx={{ display: "flex", justifyContent: "end" }}
|
|
||||||
>
|
|
||||||
<StyledGrid item>
|
|
||||||
<Button onClick={handleLike}>
|
|
||||||
<StyledTypography variant="body2" color="text.secondary">
|
|
||||||
{numberOfLikes}
|
|
||||||
</StyledTypography>
|
|
||||||
|
|
||||||
{liked ? <ThumbUpAltIcon /> : <ThumbUpOffAltIcon />}
|
|
||||||
</Button>
|
|
||||||
</StyledGrid>
|
|
||||||
<StyledGrid item>
|
|
||||||
<Button onClick={handlePostClick}>
|
|
||||||
<StyledTypography variant="body2" color="text.secondary">
|
|
||||||
{props.post.comments?.length || 0}
|
|
||||||
</StyledTypography>
|
|
||||||
<MessageIcon />
|
|
||||||
</Button>
|
|
||||||
</StyledGrid>
|
|
||||||
</Grid>
|
|
||||||
</Card>
|
|
||||||
</ListItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const StyledGrid = styled(Grid)({
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
padding: "auto",
|
|
||||||
marginBottom: "0.8rem",
|
|
||||||
marginRight: "0.8rem",
|
|
||||||
});
|
|
||||||
const StyledTypography = styled(Typography)({
|
|
||||||
padding: "0 0.5rem",
|
|
||||||
});
|
|
||||||
|
|
@ -13,7 +13,6 @@ import FeedIcon from "@mui/icons-material/Feed";
|
||||||
import GlobalIcon from "@mui/icons-material/Public";
|
import GlobalIcon from "@mui/icons-material/Public";
|
||||||
import AddIcon from "@mui/icons-material/Add";
|
import AddIcon from "@mui/icons-material/Add";
|
||||||
import SearchIcon from "@mui/icons-material/Search";
|
import SearchIcon from "@mui/icons-material/Search";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
export interface SideAppBarProps {
|
export interface SideAppBarProps {
|
||||||
drawerWidth: number;
|
drawerWidth: number;
|
||||||
|
|
@ -21,12 +20,6 @@ export interface SideAppBarProps {
|
||||||
|
|
||||||
export default function SideAppBar(props: SideAppBarProps) {
|
export default function SideAppBar(props: SideAppBarProps) {
|
||||||
const { drawerWidth } = props;
|
const { drawerWidth } = props;
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const handleClick = (to: string) => () => {
|
|
||||||
navigate(to);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Drawer
|
<Drawer
|
||||||
sx={{
|
sx={{
|
||||||
|
|
@ -44,7 +37,7 @@ export default function SideAppBar(props: SideAppBarProps) {
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<List>
|
<List>
|
||||||
<ListItem key={"myfeed"} disablePadding onClick={handleClick("feed")}>
|
<ListItem key={"myfeed"} disablePadding>
|
||||||
<ListItemButton>
|
<ListItemButton>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<FeedIcon />
|
<FeedIcon />
|
||||||
|
|
@ -53,11 +46,7 @@ export default function SideAppBar(props: SideAppBarProps) {
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem
|
<ListItem key={"globalfeed"} disablePadding>
|
||||||
key={"globalfeed"}
|
|
||||||
disablePadding
|
|
||||||
onClick={handleClick("global")}
|
|
||||||
>
|
|
||||||
<ListItemButton>
|
<ListItemButton>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<GlobalIcon />
|
<GlobalIcon />
|
||||||
|
|
@ -66,11 +55,7 @@ export default function SideAppBar(props: SideAppBarProps) {
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem
|
<ListItem key={"newpost"} disablePadding>
|
||||||
key={"newpost"}
|
|
||||||
disablePadding
|
|
||||||
onClick={handleClick("newpost")}
|
|
||||||
>
|
|
||||||
<ListItemButton>
|
<ListItemButton>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<AddIcon />
|
<AddIcon />
|
||||||
|
|
@ -79,7 +64,7 @@ export default function SideAppBar(props: SideAppBarProps) {
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem key={"search"} disablePadding onClick={handleClick("search")}>
|
<ListItem key={"search"} disablePadding>
|
||||||
<ListItemButton>
|
<ListItemButton>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<SearchIcon />
|
<SearchIcon />
|
||||||
|
|
@ -87,6 +72,7 @@ export default function SideAppBar(props: SideAppBarProps) {
|
||||||
<ListItemText primary={"Search"} />
|
<ListItemText primary={"Search"} />
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
</List>
|
</List>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -5,25 +5,24 @@ import Toolbar from "@mui/material/Toolbar";
|
||||||
import IconButton from "@mui/material/IconButton";
|
import IconButton from "@mui/material/IconButton";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Menu from "@mui/material/Menu";
|
import Menu from "@mui/material/Menu";
|
||||||
|
import Container from "@mui/material/Container";
|
||||||
import Avatar from "@mui/material/Avatar";
|
import Avatar from "@mui/material/Avatar";
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
import MenuItem from "@mui/material/MenuItem";
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
import NotificationBell from "./notificationBell";
|
import NotificationBell from "./notificationBell";
|
||||||
import {useSelector} from "react-redux";
|
import {useSelector} from "react-redux";
|
||||||
import { postLogout, selectUserInfo } from "../app/loginSlice";
|
import {selectUserInfo} from "../app/loginSlice";
|
||||||
import { useAppDispatch } from "../app/store";
|
|
||||||
|
|
||||||
interface TopAppBarProps {
|
const settings = ["Profile", "Account", "Dashboard", "Logout"];
|
||||||
height: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
function TopAppBar(props: TopAppBarProps) {
|
function TopAppBar() {
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const userInfo = useSelector(selectUserInfo);
|
const userInfo = useSelector(selectUserInfo);
|
||||||
const [anchorElUser, setAnchorElUser] = React.useState<null | HTMLElement>(
|
const [anchorElUser, setAnchorElUser] = React.useState<null | HTMLElement>(
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log(userInfo)
|
||||||
|
|
||||||
const handleOpenUserMenu = (event: React.MouseEvent<HTMLElement>) => {
|
const handleOpenUserMenu = (event: React.MouseEvent<HTMLElement>) => {
|
||||||
setAnchorElUser(event.currentTarget);
|
setAnchorElUser(event.currentTarget);
|
||||||
|
|
@ -33,20 +32,16 @@ function TopAppBar(props: TopAppBarProps) {
|
||||||
setAnchorElUser(null);
|
setAnchorElUser(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLogout = () => {
|
|
||||||
dispatch(postLogout());
|
|
||||||
setAnchorElUser(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppBar position="absolute" sx={{zIndex:1600, height: `${props.height}px` }}>
|
<AppBar position="static">
|
||||||
|
<Container maxWidth="xl" sx={{ zIndex: 2500 }}>
|
||||||
<Toolbar disableGutters>
|
<Toolbar disableGutters>
|
||||||
<Typography
|
<Typography
|
||||||
variant="h6"
|
variant="h6"
|
||||||
noWrap
|
noWrap
|
||||||
component="a"
|
component="a"
|
||||||
|
href="#app-bar-with-responsive-menu"
|
||||||
sx={{
|
sx={{
|
||||||
marginLeft: "1rem",
|
|
||||||
mr: 2,
|
mr: 2,
|
||||||
display: "flex",
|
display: "flex",
|
||||||
fontFamily: "monospace",
|
fontFamily: "monospace",
|
||||||
|
|
@ -69,13 +64,10 @@ function TopAppBar(props: TopAppBarProps) {
|
||||||
<NotificationBell />
|
<NotificationBell />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box sx={{ flexGrow: 0, mr:"2rem" }}>
|
<Box sx={{ flexGrow: 0 }}>
|
||||||
<Tooltip title="Open settings" >
|
<Tooltip title="Open settings">
|
||||||
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
|
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
|
||||||
<Avatar
|
<Avatar alt={userInfo.firstName} src="/static/images/avatar/2.jpg" />
|
||||||
alt={`${userInfo.firstName} ${userInfo.lastName}`}
|
|
||||||
src="/static/images/avatar/2.jpg"
|
|
||||||
/>
|
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Menu
|
<Menu
|
||||||
|
|
@ -94,18 +86,15 @@ function TopAppBar(props: TopAppBarProps) {
|
||||||
open={Boolean(anchorElUser)}
|
open={Boolean(anchorElUser)}
|
||||||
onClose={handleCloseUserMenu}
|
onClose={handleCloseUserMenu}
|
||||||
>
|
>
|
||||||
<MenuItem key={"profile"} onClick={handleCloseUserMenu}>
|
{settings.map((setting) => (
|
||||||
<Typography textAlign="center">{"Profile"}</Typography>
|
<MenuItem key={setting} onClick={handleCloseUserMenu}>
|
||||||
</MenuItem>
|
<Typography textAlign="center">{setting}</Typography>
|
||||||
<MenuItem key={"settings"} onClick={handleCloseUserMenu}>
|
</MenuItem>
|
||||||
<Typography textAlign="center">{"Settings"}</Typography>
|
))}
|
||||||
</MenuItem>
|
|
||||||
<MenuItem key={"logout"} onClick={handleLogout}>
|
|
||||||
<Typography textAlign="center">{"Logout"}</Typography>
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
</Menu>
|
||||||
</Box>
|
</Box>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
|
</Container>
|
||||||
</AppBar>
|
</AppBar>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,6 @@ import Register from "./routes/Auth/register";
|
||||||
import AuthRoot from "./routes/Auth/authRoot";
|
import AuthRoot from "./routes/Auth/authRoot";
|
||||||
import { Provider } from "react-redux";
|
import { Provider } from "react-redux";
|
||||||
import { store } from "./app/store";
|
import { store } from "./app/store";
|
||||||
import PostList from "./routes/postList";
|
|
||||||
import Profile from "./routes/profile";
|
|
||||||
import Post from "./routes/post";
|
|
||||||
import NewPost from "./routes/newPost";
|
|
||||||
import Search from "./routes/search";
|
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(
|
const root = ReactDOM.createRoot(
|
||||||
document.getElementById("root") as HTMLElement
|
document.getElementById("root") as HTMLElement
|
||||||
|
|
@ -33,36 +28,6 @@ const router = createBrowserRouter([
|
||||||
path: "/",
|
path: "/",
|
||||||
element: <Root />,
|
element: <Root />,
|
||||||
errorElement: <ErrorPage />,
|
errorElement: <ErrorPage />,
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: "feed",
|
|
||||||
element: <PostList type="user" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "global",
|
|
||||||
element: <PostList type="all" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "me",
|
|
||||||
element: <Profile selfProfile />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "user/:id",
|
|
||||||
element: <Profile />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "post/:id",
|
|
||||||
element: <Post />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "search",
|
|
||||||
element: <Search />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "newpost",
|
|
||||||
element: <NewPost />,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/auth",
|
path: "/auth",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Copyright } from "@mui/icons-material";
|
import { Copyright } from "@mui/icons-material";
|
||||||
import { Grid, Typography } from "@mui/material";
|
import { Grid, Paper, Typography } from "@mui/material";
|
||||||
import { Outlet, useNavigate } from "react-router-dom";
|
import { Outlet, useNavigate } from "react-router-dom";
|
||||||
import { StyledDivider } from "../../components/StyledComponents";
|
import { StyledDivider } from "../../components/StyledComponents";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
|
|
@ -12,7 +12,7 @@ export default function AuthRoot() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (loggedIn) {
|
if (loggedIn) {
|
||||||
return navigate("/feed");
|
return navigate("/");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
export default function NewPost() {
|
|
||||||
return <>New Post</>;
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
export default function Notification() {
|
|
||||||
return <>Notification</>;
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
export default function Post() {
|
|
||||||
return <>Post</>;
|
|
||||||
}
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
import { useSelector } from "react-redux";
|
|
||||||
import {
|
|
||||||
fetchFollowedPosts,
|
|
||||||
fetchGlobalPosts,
|
|
||||||
selectAllPosts,
|
|
||||||
selectFollowedPosts,
|
|
||||||
} from "../app/postSlice";
|
|
||||||
import { useAppDispatch } from "../app/store";
|
|
||||||
import { useEffect } from "react";
|
|
||||||
import { Box, List, Typography } from "@mui/material";
|
|
||||||
import { Post } from "../api";
|
|
||||||
import PostListItem from "../components/postListItem";
|
|
||||||
|
|
||||||
interface PostListProps {
|
|
||||||
type: "all" | "user";
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function PostList(props: PostListProps) {
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const followedPosts = useSelector(selectFollowedPosts);
|
|
||||||
const globalPosts = useSelector(selectAllPosts);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (props.type === "all") dispatch(fetchGlobalPosts());
|
|
||||||
if (props.type === "user") dispatch(fetchFollowedPosts());
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "100%",
|
|
||||||
alignContent: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
display: "flex",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{props.type === "all" && (
|
|
||||||
<List>
|
|
||||||
{globalPosts.map((post: Post) => (
|
|
||||||
<PostListItem post={post} postType="all" key={post.id} />
|
|
||||||
))}
|
|
||||||
</List>
|
|
||||||
)}
|
|
||||||
{props.type === "user" && (
|
|
||||||
<List>
|
|
||||||
{followedPosts.map((post: Post) => (
|
|
||||||
<PostListItem post={post} postType="user" key={post.id} />
|
|
||||||
))}
|
|
||||||
{followedPosts.length === 0 && (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography
|
|
||||||
variant="h3"
|
|
||||||
sx={{ color: "text.secondary", mb: "2rem" }}
|
|
||||||
>
|
|
||||||
Whops!
|
|
||||||
</Typography>
|
|
||||||
<Typography textAlign="center" sx={{ color: "text.secondary" }}>
|
|
||||||
There is no content here! Try following some users, or check the
|
|
||||||
global feed
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</List>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
import { useParams } from "react-router-dom";
|
|
||||||
|
|
||||||
export interface ProfileProps {
|
|
||||||
selfProfile?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Profile(props: ProfileProps) {
|
|
||||||
const { selfProfile } = props;
|
|
||||||
const userId = useParams<{ userId: string }>().userId;
|
|
||||||
|
|
||||||
return <>Profile</>;
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { Outlet, useNavigate } from "react-router-dom";
|
import { Outlet, useNavigate } from "react-router-dom";
|
||||||
import { Box } from "@mui/material";
|
import { Box } from "@mui/material";
|
||||||
import { selectLoggedIn } from "../app/loginSlice";
|
import { postLogout, selectLoggedIn, selectUserInfo } from "../app/loginSlice";
|
||||||
|
import { useAppDispatch } from "../app/store";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import useWindowDimensions from "../app/hooks/useWindowDimensions";
|
import useWindowDimensions from "../app/hooks/useWindowDimensions";
|
||||||
|
|
@ -9,10 +10,10 @@ import BottomAppBar from "../components/bottomAppBar";
|
||||||
import TopAppBar from "../components/topAppBar";
|
import TopAppBar from "../components/topAppBar";
|
||||||
|
|
||||||
const drawerWidth = 240;
|
const drawerWidth = 240;
|
||||||
const topAppBarHeight = 64;
|
|
||||||
|
|
||||||
export default function Root() {
|
export default function Root() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
const loggedIn = useSelector(selectLoggedIn);
|
const loggedIn = useSelector(selectLoggedIn);
|
||||||
const { width } = useWindowDimensions();
|
const { width } = useWindowDimensions();
|
||||||
|
|
||||||
|
|
@ -22,11 +23,14 @@ export default function Root() {
|
||||||
}
|
}
|
||||||
}, [loggedIn, navigate]);
|
}, [loggedIn, navigate]);
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
dispatch(postLogout());
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box>
|
<Box>
|
||||||
<TopAppBar height={topAppBarHeight} />
|
<TopAppBar />
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
|
|
@ -47,7 +51,6 @@ export default function Root() {
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
p: 3,
|
p: 3,
|
||||||
width: { sm: `calc(100% - ${width > 600 ? drawerWidth : 0}px)` },
|
width: { sm: `calc(100% - ${width > 600 ? drawerWidth : 0}px)` },
|
||||||
marginTop: { xs: `${topAppBarHeight}px`},
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
export default function Search() {
|
|
||||||
return <>Search</>;
|
|
||||||
}
|
|
||||||
|
|
@ -7,9 +7,10 @@ import {Notification} from "../entity/Notification";
|
||||||
import {catchAsync} from "../util/catchAsync";
|
import {catchAsync} from "../util/catchAsync";
|
||||||
|
|
||||||
export class UserController {
|
export class UserController {
|
||||||
private userRepository = AppDataSource.getRepository(User);
|
|
||||||
|
|
||||||
private notificationRepository = AppDataSource.getRepository(Notification);
|
private userRepository = AppDataSource.getRepository(User)
|
||||||
|
|
||||||
|
private notificationRepository = AppDataSource.getRepository(Notification)
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /users:
|
* /users:
|
||||||
|
|
@ -33,14 +34,13 @@ export class UserController {
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
const users = await this.userRepository.find();
|
const users = await this.userRepository.find();
|
||||||
|
|
||||||
// remove sensitive fields
|
// remove sensitive fields
|
||||||
users.forEach((user) => {
|
users.forEach(user => {
|
||||||
user.deleteSensitiveFields();
|
user.deleteSensitiveFields()
|
||||||
});
|
})
|
||||||
|
|
||||||
res.status(200).send(users);
|
res.status(200).send(users)
|
||||||
}
|
})
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
|
|
@ -73,28 +73,23 @@ export class UserController {
|
||||||
// Check if ID is a number
|
// Check if ID is a number
|
||||||
if (isNaN(parsedId)) return next(new AppError("Invalid ID", 400));
|
if (isNaN(parsedId)) return next(new AppError("Invalid ID", 400));
|
||||||
|
|
||||||
const user = await this.userRepository.findOne({
|
const user = await this.userRepository.findOne({where: {id: parsedId}, relations:{
|
||||||
where: { id: parsedId },
|
followed: true,
|
||||||
relations: {
|
followers: true,
|
||||||
followed: true,
|
posts: true,
|
||||||
followers: true,
|
comments: true,
|
||||||
posts: true,
|
}})
|
||||||
comments: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!user) return next(new AppError("No user found with that ID", 404));
|
|
||||||
|
|
||||||
// remove sensitive fields
|
if(!user) return next(new AppError('No user found with that ID', 404))
|
||||||
user.deleteSensitiveFields();
|
|
||||||
user.followed.forEach((followedUser) =>
|
|
||||||
followedUser.deleteSensitiveFields()
|
|
||||||
);
|
|
||||||
user.followers.forEach((follower) => follower.deleteSensitiveFields());
|
|
||||||
|
|
||||||
return res.send(user);
|
// remove sensitive fields
|
||||||
}
|
user.deleteSensitiveFields()
|
||||||
);
|
user.followed.forEach(followedUser => followedUser.deleteSensitiveFields())
|
||||||
|
user.followers.forEach(follower => follower.deleteSensitiveFields())
|
||||||
|
|
||||||
|
return res.send(user)
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
|
|
@ -111,7 +106,7 @@ export class UserController {
|
||||||
* content:
|
* content:
|
||||||
* application/json:
|
* application/json:
|
||||||
* schema:
|
* schema:
|
||||||
* $ref: '#/components/schemas/UserWithRelationsAndNotifications'
|
* $ref: '#/components/schemas/UserWithRelations'
|
||||||
*/
|
*/
|
||||||
public getMe = catchAsync(
|
public getMe = catchAsync(
|
||||||
async (req: AppRequest, res: Response, next: NextFunction) => {
|
async (req: AppRequest, res: Response, next: NextFunction) => {
|
||||||
|
|
@ -122,18 +117,14 @@ export class UserController {
|
||||||
followers: true,
|
followers: true,
|
||||||
posts: true,
|
posts: true,
|
||||||
comments: true,
|
comments: true,
|
||||||
notifications: true,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
user.followed.forEach((followedUser) =>
|
user.followed.forEach(followedUser => followedUser.deleteSensitiveFields())
|
||||||
followedUser.deleteSensitiveFields()
|
user.followers.forEach(follower => follower.deleteSensitiveFields())
|
||||||
);
|
|
||||||
user.followers.forEach((follower) => follower.deleteSensitiveFields());
|
|
||||||
|
|
||||||
return res.status(200).send(user);
|
return res.status(200).send(user)
|
||||||
}
|
})
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
|
|
@ -170,74 +161,69 @@ export class UserController {
|
||||||
// Check if ID is a number
|
// Check if ID is a number
|
||||||
if (isNaN(parsedId)) return next(new AppError("Invalid ID", 400));
|
if (isNaN(parsedId)) return next(new AppError("Invalid ID", 400));
|
||||||
|
|
||||||
const user = req.user;
|
const user = req.user
|
||||||
const userToFollow = await this.userRepository.findOne({
|
const userToFollow = await this.userRepository.findOne({
|
||||||
where: { id: parsedId },
|
where: {id: parsedId},
|
||||||
relations: { followed: true, followers: true, notifications: true },
|
relations:{followed: true, followers: true, notifications: true}}
|
||||||
});
|
|
||||||
|
|
||||||
if (!userToFollow)
|
|
||||||
return next(new AppError("No user found with that ID", 404));
|
|
||||||
|
|
||||||
// Check if user is already following
|
|
||||||
if (
|
|
||||||
user.followed.some(
|
|
||||||
(followedUser) => followedUser.id === userToFollow.id
|
|
||||||
)
|
)
|
||||||
) {
|
|
||||||
return next(new AppError("You are already following this user", 400));
|
|
||||||
}
|
|
||||||
// Follow the user
|
|
||||||
user.followed.push(userToFollow);
|
|
||||||
await this.userRepository.save(user);
|
|
||||||
// Add the requesting user to the followers of the user being followed
|
|
||||||
userToFollow.followers.push(user);
|
|
||||||
// Create a notification for the user being followed
|
|
||||||
const followNotification = Object.assign(new Notification(), {
|
|
||||||
seen: false,
|
|
||||||
message: `${user.firstName} is now following you`,
|
|
||||||
timeStamp: new Date(),
|
|
||||||
});
|
|
||||||
userToFollow.notifications.push(
|
|
||||||
await this.notificationRepository.save(followNotification)
|
|
||||||
);
|
|
||||||
await this.userRepository.save(userToFollow);
|
|
||||||
|
|
||||||
return res.status(200).send({
|
if(!userToFollow) return next(new AppError('No user found with that ID', 404))
|
||||||
status: "success",
|
|
||||||
message: `You are now following ${userToFollow.firstName}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
// Check if user is already following
|
||||||
* @swagger
|
if(user.followed.some(followedUser => followedUser.id === userToFollow.id)){
|
||||||
* /users/{id}/follow:
|
return next(new AppError('You are already following this user', 400))
|
||||||
* delete:
|
}
|
||||||
* security:
|
// Follow the user
|
||||||
* - bearerAuth: []
|
user.followed.push(userToFollow)
|
||||||
* tags:
|
await this.userRepository.save(user)
|
||||||
* - Users
|
// Add the requesting user to the followers of the user being followed
|
||||||
* summary: Unfollow a user
|
userToFollow.followers.push(user)
|
||||||
* parameters:
|
// Create a notification for the user being followed
|
||||||
* - in: path
|
const followNotification = Object.assign(new Notification(),{
|
||||||
* name: id
|
seen: false,
|
||||||
* required: true
|
message: `${user.firstName} is now following you`,
|
||||||
* schema:
|
timeStamp: new Date()
|
||||||
* type: integer
|
})
|
||||||
* description: The ID of the user to unfollow
|
userToFollow.notifications.push(
|
||||||
* responses:
|
await this.notificationRepository.save(followNotification)
|
||||||
* 200:
|
)
|
||||||
* description: Successfully unfollowed the user
|
await this.userRepository.save(userToFollow)
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
return res.status(200).send({
|
||||||
* $ref: '#/components/schemas/UserWithRelations'
|
status: 'success',
|
||||||
* 400:
|
message: `You are now following ${userToFollow.firstName}`
|
||||||
* description: Invalid ID
|
})
|
||||||
* 404:
|
})
|
||||||
* description: No user found with that ID
|
|
||||||
*/
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /users/{id}/follow:
|
||||||
|
* delete:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags:
|
||||||
|
* - Users
|
||||||
|
* summary: Unfollow a user
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: integer
|
||||||
|
* description: The ID of the user to unfollow
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Successfully unfollowed the user
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* $ref: '#/components/schemas/UserWithRelations'
|
||||||
|
* 400:
|
||||||
|
* description: Invalid ID
|
||||||
|
* 404:
|
||||||
|
* description: No user found with that ID
|
||||||
|
*/
|
||||||
public unfollowUser = catchAsync(
|
public unfollowUser = catchAsync(
|
||||||
async (req: AppRequest, res: Response, next: NextFunction) => {
|
async (req: AppRequest, res: Response, next: NextFunction) => {
|
||||||
const userToUnfollowId = req.params.id;
|
const userToUnfollowId = req.params.id;
|
||||||
|
|
@ -245,37 +231,28 @@ export class UserController {
|
||||||
// Check if ID is a number
|
// Check if ID is a number
|
||||||
if (isNaN(parsedId)) return next(new AppError("Invalid ID", 400));
|
if (isNaN(parsedId)) return next(new AppError("Invalid ID", 400));
|
||||||
|
|
||||||
const user = req.user;
|
const user = req.user
|
||||||
const userToUnfollow = await this.userRepository.findOne({
|
const userToUnfollow = await this.userRepository.findOne({
|
||||||
where: { id: parsedId },
|
where: {id: parsedId},
|
||||||
relations: { followed: true, followers: true },
|
relations: {followed: true, followers: true}
|
||||||
});
|
})
|
||||||
|
|
||||||
if (!userToUnfollow)
|
if(!userToUnfollow) return next(new AppError('No user found with that ID', 404))
|
||||||
return next(new AppError("No user found with that ID", 404));
|
// Check if user is following
|
||||||
// Check if user is following
|
if(!user.followed.some(followedUser => followedUser.id === userToUnfollow.id)){
|
||||||
if (
|
return next(new AppError('You are not following this user', 400))
|
||||||
!user.followed.some(
|
}
|
||||||
(followedUser) => followedUser.id === userToUnfollow.id
|
// Unfollow the user
|
||||||
)
|
user.followed = user.followed.filter(followedUser => followedUser.id !== userToUnfollow.id)
|
||||||
) {
|
await this.userRepository.save(user)
|
||||||
return next(new AppError("You are not following this user", 400));
|
|
||||||
}
|
|
||||||
// Unfollow the user
|
|
||||||
user.followed = user.followed.filter(
|
|
||||||
(followedUser) => followedUser.id !== userToUnfollow.id
|
|
||||||
);
|
|
||||||
await this.userRepository.save(user);
|
|
||||||
|
|
||||||
userToUnfollow.followers = userToUnfollow.followers.filter(
|
userToUnfollow.followers = userToUnfollow.followers.filter(follower => follower.id !== user.id)
|
||||||
(follower) => follower.id !== user.id
|
await this.userRepository.save(userToUnfollow)
|
||||||
);
|
|
||||||
await this.userRepository.save(userToUnfollow);
|
return res.status(200).send({
|
||||||
|
status: 'success',
|
||||||
|
message: `You are no longer following ${userToUnfollow.firstName}`
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
return res.status(200).send({
|
|
||||||
status: "success",
|
|
||||||
message: `You are no longer following ${userToUnfollow.firstName}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
@ -38,7 +38,7 @@ export class PostController {
|
||||||
*/
|
*/
|
||||||
public getAllPosts = catchAsync(async (_req, res, _next) => {
|
public getAllPosts = catchAsync(async (_req, res, _next) => {
|
||||||
const posts = await this.postRepository.find({
|
const posts = await this.postRepository.find({
|
||||||
relations: { createdBy: true, likedBy: true, comments: {createdBy: true} },
|
relations: { createdBy: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove sensitive fields
|
// Remove sensitive fields
|
||||||
|
|
@ -117,12 +117,8 @@ export class PostController {
|
||||||
|
|
||||||
public getFollowedPosts = catchAsync(async (req : AppRequest, res, _next) => {
|
public getFollowedPosts = catchAsync(async (req : AppRequest, res, _next) => {
|
||||||
const user = await this.userRepository.findOne({
|
const user = await this.userRepository.findOne({
|
||||||
where: { id: req.user.id },
|
where: {id: req.user.id},
|
||||||
relations: {
|
relations: {followed: true, posts: true}})
|
||||||
followed: true,
|
|
||||||
posts: { likedBy: true, comments: true },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const followedPosts = user.followed.map(followedUser => followedUser.posts).flat()
|
const followedPosts = user.followed.map(followedUser => followedUser.posts).flat()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,10 @@ export class Post {
|
||||||
|
|
||||||
public deleteSensitiveFields(){
|
public deleteSensitiveFields(){
|
||||||
this.createdBy.deleteSensitiveFields()
|
this.createdBy.deleteSensitiveFields()
|
||||||
if(this.likedBy.length > 0){
|
if(this.likedBy){
|
||||||
this.likedBy.forEach(user => user.deleteSensitiveFields())
|
this.likedBy.forEach(user => user.deleteSensitiveFields())
|
||||||
}
|
}
|
||||||
if(this.comments.length > 0){
|
if(this.comments){
|
||||||
this.comments.forEach(comment => comment.createdBy.deleteSensitiveFields())
|
this.comments.forEach(comment => comment.createdBy.deleteSensitiveFields())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,27 +83,6 @@ const swaggerOptions = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Notification: {
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
id: {
|
|
||||||
type: "integer",
|
|
||||||
description: "Notification ID",
|
|
||||||
},
|
|
||||||
message: {
|
|
||||||
type: "string",
|
|
||||||
description: "Notification message",
|
|
||||||
},
|
|
||||||
timeStamp: {
|
|
||||||
type: "string",
|
|
||||||
description: "Notification creation date",
|
|
||||||
},
|
|
||||||
seen: {
|
|
||||||
type: "boolean",
|
|
||||||
description: "Notification seen status",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
User: {
|
User: {
|
||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
|
|
@ -157,25 +136,10 @@ const swaggerOptions = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
UserWithRelationsAndNotifications: {
|
|
||||||
allOf: [
|
|
||||||
{ $ref: "#/components/schemas/UserWithRelations" },
|
|
||||||
{
|
|
||||||
type: "object",
|
|
||||||
properties: {
|
|
||||||
notifications: {
|
|
||||||
type: "array",
|
|
||||||
items: {
|
|
||||||
$ref: "#/components/schemas/Notification",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
apis: ["**/controller/*.ts"],
|
apis: ["**/controller/*.ts"],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue