Skip to content

Commit

Permalink
Allow editing of fields for user page (#761)
Browse files Browse the repository at this point in the history
Co-authored-by: Lowell <[email protected]>
  • Loading branch information
nicolexxuu and lowtorola authored Apr 30, 2024
1 parent 160a3e3 commit 87e1dad
Show file tree
Hide file tree
Showing 12 changed files with 332 additions and 272 deletions.
2 changes: 1 addition & 1 deletion backend/siarnaq/api/user/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def update(self, *args, **kwargs):
class UserProfilePrivateSerializer(UserProfilePublicSerializer):
# Couuntry field requires special serialization.
# See https://github.com/SmileyChris/django-countries#django-rest-framework
country = CountryField(name_only=True)
country = CountryField()

class Meta:
model = UserProfile
Expand Down
22 changes: 21 additions & 1 deletion backend/siarnaq/api/user/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ def teams(self, request, pk=None):
teams_dict = {team["episode"]: team for team in serializer.data}
return Response(teams_dict)

@extend_schema(
request={
"multipart/form-data": {
"type": "object",
"properties": {
"resume": {"type": "string", "format": "binary"},
},
}
},
)
@action(
detail=False,
methods=["get", "put"],
Expand Down Expand Up @@ -144,7 +154,17 @@ def resume(self, request):
case _:
raise RuntimeError(f"Fallthrough! Was {request.method} implemented?")

@extend_schema(responses={status.HTTP_204_NO_CONTENT: None})
@extend_schema(
responses={status.HTTP_204_NO_CONTENT: None},
request={
"multipart/form-data": {
"type": "object",
"properties": {
"avatar": {"type": "string", "format": "binary"},
},
}
},
)
@action(
detail=False,
methods=["post"],
Expand Down
44 changes: 10 additions & 34 deletions frontend2/schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1678,16 +1678,13 @@ paths:
- user
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UserAvatarRequest'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/UserAvatarRequest'
multipart/form-data:
schema:
$ref: '#/components/schemas/UserAvatarRequest'
required: true
type: object
properties:
avatar:
type: string
format: binary
security:
- jwtAuth: []
responses:
Expand Down Expand Up @@ -1781,16 +1778,13 @@ paths:
- user
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UserResumeRequest'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/UserResumeRequest'
multipart/form-data:
schema:
$ref: '#/components/schemas/UserResumeRequest'
required: true
type: object
properties:
resume:
type: string
format: binary
security:
- jwtAuth: []
responses:
Expand Down Expand Up @@ -3165,15 +3159,6 @@ components:
- tournament
- user
- username
UserAvatarRequest:
type: object
properties:
avatar:
type: string
format: binary
writeOnly: true
required:
- avatar
UserCreate:
type: object
properties:
Expand Down Expand Up @@ -3462,15 +3447,6 @@ components:
- ready
- reason
- url
UserResumeRequest:
type: object
properties:
resume:
type: string
format: binary
writeOnly: true
required:
- resume
securitySchemes:
jwtAuth:
type: http
Expand Down
2 changes: 0 additions & 2 deletions frontend2/src/api/_autogen/.openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ models/TokenVerifyRequest.ts
models/Tournament.ts
models/TournamentRound.ts
models/TournamentSubmission.ts
models/UserAvatarRequest.ts
models/UserCreate.ts
models/UserCreateRequest.ts
models/UserPassed.ts
Expand All @@ -79,6 +78,5 @@ models/UserProfilePublicRequest.ts
models/UserPublic.ts
models/UserPublicRequest.ts
models/UserResume.ts
models/UserResumeRequest.ts
models/index.ts
runtime.ts
70 changes: 46 additions & 24 deletions frontend2/src/api/_autogen/apis/UserApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,12 @@ import type {
ResetToken,
ResetTokenRequest,
TeamPublic,
UserAvatarRequest,
UserCreate,
UserCreateRequest,
UserPrivate,
UserPrivateRequest,
UserPublic,
UserResume,
UserResumeRequest,
} from '../models';
import {
EmailFromJSON,
Expand All @@ -49,8 +47,6 @@ import {
ResetTokenRequestToJSON,
TeamPublicFromJSON,
TeamPublicToJSON,
UserAvatarRequestFromJSON,
UserAvatarRequestToJSON,
UserCreateFromJSON,
UserCreateToJSON,
UserCreateRequestFromJSON,
Expand All @@ -63,8 +59,6 @@ import {
UserPublicToJSON,
UserResumeFromJSON,
UserResumeToJSON,
UserResumeRequestFromJSON,
UserResumeRequestToJSON,
} from '../models';

export interface UserPasswordResetConfirmCreateRequest {
Expand All @@ -80,7 +74,7 @@ export interface UserPasswordResetValidateTokenCreateRequest {
}

export interface UserUAvatarCreateRequest {
userAvatarRequest: UserAvatarRequest;
avatar?: Blob;
}

export interface UserUCreateRequest {
Expand All @@ -96,7 +90,7 @@ export interface UserUMeUpdateRequest {
}

export interface UserUResumeUpdateRequest {
userResumeRequest: UserResumeRequest;
resume?: Blob;
}

export interface UserURetrieveRequest {
Expand Down Expand Up @@ -215,16 +209,10 @@ export class UserApi extends runtime.BaseAPI {
* Update uploaded avatar.
*/
async userUAvatarCreateRaw(requestParameters: UserUAvatarCreateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
if (requestParameters.userAvatarRequest === null || requestParameters.userAvatarRequest === undefined) {
throw new runtime.RequiredError('userAvatarRequest','Required parameter requestParameters.userAvatarRequest was null or undefined when calling userUAvatarCreate.');
}

const queryParameters: any = {};

const headerParameters: runtime.HTTPHeaders = {};

headerParameters['Content-Type'] = 'application/json';

if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("jwtAuth", []);
Expand All @@ -233,12 +221,32 @@ export class UserApi extends runtime.BaseAPI {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const consumes: runtime.Consume[] = [
{ contentType: 'multipart/form-data' },
];
// @ts-ignore: canConsumeForm may be unused
const canConsumeForm = runtime.canConsumeForm(consumes);

let formParams: { append(param: string, value: any): any };
let useForm = false;
// use FormData to transmit files using content-type "multipart/form-data"
useForm = canConsumeForm;
if (useForm) {
formParams = new FormData();
} else {
formParams = new URLSearchParams();
}

if (requestParameters.avatar !== undefined) {
formParams.append('avatar', requestParameters.avatar as any);
}

const response = await this.request({
path: `/api/user/u/avatar/`,
method: 'POST',
headers: headerParameters,
query: queryParameters,
body: UserAvatarRequestToJSON(requestParameters.userAvatarRequest),
body: formParams,
}, initOverrides);

return new runtime.VoidApiResponse(response);
Expand All @@ -247,7 +255,7 @@ export class UserApi extends runtime.BaseAPI {
/**
* Update uploaded avatar.
*/
async userUAvatarCreate(requestParameters: UserUAvatarCreateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
async userUAvatarCreate(requestParameters: UserUAvatarCreateRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
await this.userUAvatarCreateRaw(requestParameters, initOverrides);
}

Expand Down Expand Up @@ -442,16 +450,10 @@ export class UserApi extends runtime.BaseAPI {
* Retrieve or update the uploaded resume.
*/
async userUResumeUpdateRaw(requestParameters: UserUResumeUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<UserResume>> {
if (requestParameters.userResumeRequest === null || requestParameters.userResumeRequest === undefined) {
throw new runtime.RequiredError('userResumeRequest','Required parameter requestParameters.userResumeRequest was null or undefined when calling userUResumeUpdate.');
}

const queryParameters: any = {};

const headerParameters: runtime.HTTPHeaders = {};

headerParameters['Content-Type'] = 'application/json';

if (this.configuration && this.configuration.accessToken) {
const token = this.configuration.accessToken;
const tokenString = await token("jwtAuth", []);
Expand All @@ -460,12 +462,32 @@ export class UserApi extends runtime.BaseAPI {
headerParameters["Authorization"] = `Bearer ${tokenString}`;
}
}
const consumes: runtime.Consume[] = [
{ contentType: 'multipart/form-data' },
];
// @ts-ignore: canConsumeForm may be unused
const canConsumeForm = runtime.canConsumeForm(consumes);

let formParams: { append(param: string, value: any): any };
let useForm = false;
// use FormData to transmit files using content-type "multipart/form-data"
useForm = canConsumeForm;
if (useForm) {
formParams = new FormData();
} else {
formParams = new URLSearchParams();
}

if (requestParameters.resume !== undefined) {
formParams.append('resume', requestParameters.resume as any);
}

const response = await this.request({
path: `/api/user/u/resume/`,
method: 'PUT',
headers: headerParameters,
query: queryParameters,
body: UserResumeRequestToJSON(requestParameters.userResumeRequest),
body: formParams,
}, initOverrides);

return new runtime.JSONApiResponse(response, (jsonValue) => UserResumeFromJSON(jsonValue));
Expand All @@ -474,7 +496,7 @@ export class UserApi extends runtime.BaseAPI {
/**
* Retrieve or update the uploaded resume.
*/
async userUResumeUpdate(requestParameters: UserUResumeUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<UserResume> {
async userUResumeUpdate(requestParameters: UserUResumeUpdateRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<UserResume> {
const response = await this.userUResumeUpdateRaw(requestParameters, initOverrides);
return await response.value();
}
Expand Down
66 changes: 0 additions & 66 deletions frontend2/src/api/_autogen/models/UserAvatarRequest.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export function UserProfilePrivateRequestFromJSONTyped(json: any, ignoreDiscrimi
return json;
}
return {

'gender': GenderEnumFromJSON(json['gender']),
'gender_details': !exists(json, 'gender_details') ? undefined : json['gender_details'],
'school': !exists(json, 'school') ? undefined : json['school'],
Expand All @@ -108,7 +108,7 @@ export function UserProfilePrivateRequestToJSON(value?: UserProfilePrivateReques
return null;
}
return {

'gender': GenderEnumToJSON(value.gender),
'gender_details': value.gender_details,
'school': value.school,
Expand Down
Loading

0 comments on commit 87e1dad

Please sign in to comment.