Skip to content

Commit ec08db0

Browse files
raymond1242Raymond Negronjoaquingxmgonnav
authored
Update User Interface to support requests support (#205)
* Add framework field to the Project model * Update serializers and views to update the Project framework field --------- Co-authored-by: Raymond Negron <raymond1242@Raymonds-MacBook-Air.local> Co-authored-by: joaquin garmendia <joaquingc123@gmail.com> Co-authored-by: mgonnav <mateo@emegona.com>
1 parent fd6a41a commit ec08db0

File tree

11 files changed

+177
-30
lines changed

11 files changed

+177
-30
lines changed

estela-api/api/serializers/project.py

+8
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class Meta:
5454
"pid",
5555
"name",
5656
"category",
57+
"framework",
5758
"container_image",
5859
"users",
5960
"data_status",
@@ -132,6 +133,12 @@ class ProjectUpdateSerializer(serializers.ModelSerializer):
132133
required=False,
133134
help_text="Performed action.",
134135
)
136+
framework = serializers.ChoiceField(
137+
write_only=True,
138+
choices=Project.FRAMEWORK_CHOICES,
139+
required=False,
140+
help_text="Set project framework.",
141+
)
135142
permission = serializers.ChoiceField(
136143
write_only=True,
137144
choices=PERMISSION_CHOICES,
@@ -158,6 +165,7 @@ class Meta:
158165
"users",
159166
"email",
160167
"action",
168+
"framework",
161169
"permission",
162170
"data_status",
163171
"data_expiry_days",

estela-api/api/views/project.py

+6
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,17 @@ def update(self, request, *args, **kwargs):
100100
data_status = serializer.validated_data.pop("data_status", "")
101101
data_expiry_days = serializer.validated_data.pop("data_expiry_days", 0)
102102
description = ""
103+
framework = serializer.validated_data.pop("framework", "")
103104

104105
if name:
105106
old_name = instance.name
106107
instance.name = name
107108
description = f"renamed project {old_name} ({instance.pid}) to {name}."
109+
110+
if framework and framework != instance.framework:
111+
instance.framework = framework
112+
description = f"changed the framework to {framework}."
113+
108114
user = request.user
109115
is_superuser = user.is_superuser or user.is_staff
110116
if user_email and (is_superuser or user_email != user.email):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Generated by Django 3.1.14 on 2023-07-12 14:14
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("core", "0031_project_oder_by_name"),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name="project",
15+
name="framework",
16+
field=models.CharField(
17+
choices=[("SCRAPY", "Scrapy"), ("REQUESTS", "Requests")],
18+
default="SCRAPY",
19+
help_text="Project's framework.",
20+
max_length=20,
21+
),
22+
),
23+
]

estela-api/core/models.py

+12
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ class DataStatus:
2323

2424

2525
class Project(models.Model):
26+
SCRAPY = "SCRAPY"
27+
REQUESTS = "REQUESTS"
28+
FRAMEWORK_CHOICES = [
29+
(SCRAPY, "Scrapy"),
30+
(REQUESTS, "Requests"),
31+
]
2632
NOT_SPECIFIED = "NOT SPECIFIED"
2733
E_COMMERCE = "E-COMMERCE"
2834
LOGISTICS = "LOGISTICS"
@@ -59,6 +65,12 @@ class Project(models.Model):
5965
users = models.ManyToManyField(
6066
User, through="Permission", help_text="Users with permissions on this project."
6167
)
68+
framework = models.CharField(
69+
max_length=20,
70+
choices=FRAMEWORK_CHOICES,
71+
default=SCRAPY,
72+
help_text="Project's framework.",
73+
)
6274
data_status = models.CharField(
6375
max_length=20,
6476
choices=DataStatus.HIGH_LEVEL_OPTIONS,

estela-api/docs/api.yaml

+14
Original file line numberDiff line numberDiff line change
@@ -1691,6 +1691,13 @@ definitions:
16911691
- EDUCATIONAL
16921692
- TECHNOLOGY
16931693
- OTHER_CATEGORY
1694+
framework:
1695+
title: Framework
1696+
description: Project's framework.
1697+
type: string
1698+
enum:
1699+
- SCRAPY
1700+
- REQUESTS
16941701
container_image:
16951702
title: Container image
16961703
description: Path of the project's container image.
@@ -1748,6 +1755,13 @@ definitions:
17481755
- remove
17491756
- add
17501757
- update
1758+
framework:
1759+
title: Framework
1760+
description: Set project framework.
1761+
type: string
1762+
enum:
1763+
- SCRAPY
1764+
- REQUESTS
17511765
permission:
17521766
title: Permission
17531767
description: New permission.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from "react";
2+
import { Tag } from "antd";
3+
4+
export function RequestTag() {
5+
return (
6+
<div className="flex">
7+
<Tag className="text-estela-blue-full font-semibold border-0 bg-estela-blue-low text-base rounded py-1">
8+
REQUESTS
9+
</Tag>
10+
<Tag className="text-xs border-estela-blue-full text-estela-blue-full h-fit rounded">Beta</Tag>
11+
</div>
12+
);
13+
}
14+
15+
export function ScrapyTag() {
16+
return (
17+
<div className="flex">
18+
<Tag className="text-estela-blue-full font-semibold border-0 bg-estela-blue-low text-base rounded py-1">
19+
SCRAPY
20+
</Tag>
21+
</div>
22+
);
23+
}

estela-web/src/pages/ProjectListPage/index.tsx

+32-13
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ interface ProjectList {
2222
category?: string;
2323
pid: string | undefined;
2424
role: string;
25+
framework: string | undefined;
2526
key: number;
2627
}
2728

@@ -65,7 +66,10 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
6566
<Link
6667
className="text-sm font-medium hover:text-estela"
6768
to={`/projects/${project.pid}/dashboard`}
68-
onClick={() => this.setUserRole(project.role)}
69+
onClick={() => {
70+
this.setUserRole(project.role);
71+
AuthService.setFramework(String(project.framework));
72+
}}
6973
>
7074
{name}
7175
</Link>
@@ -77,6 +81,14 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
7781
key: "pid",
7882
render: (pid: string): ReactElement => <p className="font-courier">{pid}</p>,
7983
},
84+
{
85+
title: "FRAMEWORK",
86+
dataIndex: "framework",
87+
key: "framework",
88+
render: (framework: string): ReactElement => (
89+
<Tag className="border-estela-blue-full rounded-md text-estela-blue-full p-1">{framework}</Tag>
90+
),
91+
},
8092
{
8193
title: "ROLE",
8294
dataIndex: "role",
@@ -99,11 +111,13 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
99111
async componentDidMount(): Promise<void> {
100112
const { updateRole } = this.context as UserContextProps;
101113
updateRole && updateRole("");
114+
AuthService.removeFramework();
102115
const data = await this.getProjects(1);
103116
const projectData: ProjectList[] = data.data.map((project: Project, id: number) => {
104117
return {
105118
name: project.name,
106119
category: project.category,
120+
framework: project.framework,
107121
pid: project.pid,
108122
role:
109123
project.users?.find((user) => user.user?.username === AuthService.getUserUsername())?.permission ||
@@ -142,6 +156,7 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
142156
updateRole && updateRole(response.users[0].permission ?? "");
143157
}
144158
history.push(`/projects/${response.pid}/deploys`);
159+
AuthService.setFramework(String(response.framework));
145160
},
146161
(error: unknown) => {
147162
error;
@@ -174,6 +189,7 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
174189
return {
175190
name: project.name,
176191
pid: project.pid,
192+
framework: project.framework,
177193
role:
178194
project.users?.find((user) => user.user?.username === AuthService.getUserUsername())?.permission ||
179195
"Admin",
@@ -196,7 +212,7 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
196212
<>
197213
{loaded ? (
198214
<Fragment>
199-
<Content className="mx-4">
215+
<Content className="mx-auto w-full lg:px-10">
200216
<Modal
201217
open={modalWelcome}
202218
footer={false}
@@ -237,7 +253,7 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
237253
</Col>
238254
</Row>
239255
</Modal>
240-
<Space direction="vertical" className="mx-8">
256+
<Space direction="vertical" className="w-full">
241257
<Content className="float-left">
242258
<Text className="text-3xl">
243259
Welcome home&nbsp;
@@ -250,34 +266,38 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
250266
<Text className="text-silver text-base font-medium">RECENT PROJECTS</Text>
251267
</Col>
252268
</Row>
253-
<Row className="grid grid-cols-3 gap-3 mt-4">
269+
<Row className="flex-row gap-3 mt-4">
254270
{projects.map((project: ProjectList, index) => {
255271
return index < 3 ? (
256272
<Button
257273
key={project.key}
258274
onClick={() => {
259275
const { updateRole } = this.context as UserContextProps;
260276
AuthService.setUserRole(project.role);
277+
AuthService.setFramework(String(project.framework));
261278
updateRole && updateRole(project.role);
262279
history.push(`/projects/${project.pid}/dashboard`);
263280
}}
264-
className="bg-white rounded-md p-3 h-20 hover:border-none border-none hover:bg-estela-blue-low hover:text-estela-blue-full"
281+
className="bg-white rounded-md w-fit h-fit px-4 py-3 hover:border-none border-none hover:bg-estela-blue-low hover:text-estela-blue-full"
265282
>
266-
<Row className="gap-3 m-1">
283+
<Row className="gap-4">
267284
<Text className="text-sm font-bold">{project.name}</Text>
268285
{index === 0 && (
269286
<Tag className="text-estela bg-estela-blue-low border-none font-medium rounded-md">
270287
New
271288
</Tag>
272289
)}
273290
</Row>
274-
<Row className="flow-root rounded-md m-2">
275-
<Text className="float-left text-xs font-courier">
276-
{project.pid}
277-
</Text>
278-
<Tag className="float-right bg-white border-white rounded-md">
291+
<Row className="rounded-md my-3">
292+
<Text className="text-xs font-courier">{project.pid}</Text>
293+
</Row>
294+
<Row className="w-full justify-between">
295+
<Tag className="bg-white border-white rounded-md">
279296
{project.role}
280297
</Tag>
298+
<Tag className="border-estela-blue-full text-estela-blue-full rounded-md">
299+
{project.framework}
300+
</Tag>
281301
</Row>
282302
</Button>
283303
) : (
@@ -412,10 +432,9 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
412432
</Modal>
413433
</Col>
414434
</Row>
415-
<Row>
435+
<Row className="flex flex-col w-full">
416436
<Table
417437
showHeader={false}
418-
tableLayout="fixed"
419438
className="rounded-2xl"
420439
columns={this.columns}
421440
dataSource={projects}

estela-web/src/services/api/generated-api/models/Project.ts

+15
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ export interface Project {
4444
* @memberof Project
4545
*/
4646
category?: ProjectCategoryEnum;
47+
/**
48+
* Project's framework.
49+
* @type {string}
50+
* @memberof Project
51+
*/
52+
framework?: ProjectFrameworkEnum;
4753
/**
4854
* Path of the project's container image.
4955
* @type {string}
@@ -86,6 +92,13 @@ export enum ProjectCategoryEnum {
8692
* @export
8793
* @enum {string}
8894
*/
95+
export enum ProjectFrameworkEnum {
96+
Scrapy = 'SCRAPY',
97+
Requests = 'REQUESTS'
98+
}/**
99+
* @export
100+
* @enum {string}
101+
*/
89102
export enum ProjectDataStatusEnum {
90103
Persistent = 'PERSISTENT',
91104
Pending = 'PENDING'
@@ -104,6 +117,7 @@ export function ProjectFromJSONTyped(json: any, ignoreDiscriminator: boolean): P
104117
'pid': !exists(json, 'pid') ? undefined : json['pid'],
105118
'name': json['name'],
106119
'category': !exists(json, 'category') ? undefined : json['category'],
120+
'framework': !exists(json, 'framework') ? undefined : json['framework'],
107121
'containerImage': !exists(json, 'container_image') ? undefined : json['container_image'],
108122
'users': !exists(json, 'users') ? undefined : ((json['users'] as Array<any>).map(PermissionFromJSON)),
109123
'dataStatus': !exists(json, 'data_status') ? undefined : json['data_status'],
@@ -122,6 +136,7 @@ export function ProjectToJSON(value?: Project | null): any {
122136

123137
'name': value.name,
124138
'category': value.category,
139+
'framework': value.framework,
125140
'users': value.users === undefined ? undefined : ((value.users as Array<any>).map(PermissionToJSON)),
126141
'data_status': value.dataStatus,
127142
'data_expiry_days': value.dataExpiryDays,

estela-web/src/services/api/generated-api/models/ProjectUpdate.ts

+15
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ export interface ProjectUpdate {
5656
* @memberof ProjectUpdate
5757
*/
5858
action?: ProjectUpdateActionEnum;
59+
/**
60+
* Set project framework.
61+
* @type {string}
62+
* @memberof ProjectUpdate
63+
*/
64+
framework?: ProjectUpdateFrameworkEnum;
5965
/**
6066
* New permission.
6167
* @type {string}
@@ -88,6 +94,13 @@ export enum ProjectUpdateActionEnum {
8894
* @export
8995
* @enum {string}
9096
*/
97+
export enum ProjectUpdateFrameworkEnum {
98+
Scrapy = 'SCRAPY',
99+
Requests = 'REQUESTS'
100+
}/**
101+
* @export
102+
* @enum {string}
103+
*/
91104
export enum ProjectUpdatePermissionEnum {
92105
Admin = 'ADMIN',
93106
Developer = 'DEVELOPER',
@@ -116,6 +129,7 @@ export function ProjectUpdateFromJSONTyped(json: any, ignoreDiscriminator: boole
116129
'users': !exists(json, 'users') ? undefined : ((json['users'] as Array<any>).map(UserDetailFromJSON)),
117130
'email': !exists(json, 'email') ? undefined : json['email'],
118131
'action': !exists(json, 'action') ? undefined : json['action'],
132+
'framework': !exists(json, 'framework') ? undefined : json['framework'],
119133
'permission': !exists(json, 'permission') ? undefined : json['permission'],
120134
'dataStatus': !exists(json, 'data_status') ? undefined : json['data_status'],
121135
'dataExpiryDays': !exists(json, 'data_expiry_days') ? undefined : json['data_expiry_days'],
@@ -135,6 +149,7 @@ export function ProjectUpdateToJSON(value?: ProjectUpdate | null): any {
135149
'users': value.users === undefined ? undefined : ((value.users as Array<any>).map(UserDetailToJSON)),
136150
'email': value.email,
137151
'action': value.action,
152+
'framework': value.framework,
138153
'permission': value.permission,
139154
'data_status': value.dataStatus,
140155
'data_expiry_days': value.dataExpiryDays,

0 commit comments

Comments
 (0)