Skip to content

Commit

Permalink
Update User Interface to support requests support (#205)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
4 people committed Jul 12, 2023
1 parent fd6a41a commit ec08db0
Show file tree
Hide file tree
Showing 11 changed files with 177 additions and 30 deletions.
8 changes: 8 additions & 0 deletions estela-api/api/serializers/project.py
Expand Up @@ -54,6 +54,7 @@ class Meta:
"pid",
"name",
"category",
"framework",
"container_image",
"users",
"data_status",
Expand Down Expand Up @@ -132,6 +133,12 @@ class ProjectUpdateSerializer(serializers.ModelSerializer):
required=False,
help_text="Performed action.",
)
framework = serializers.ChoiceField(
write_only=True,
choices=Project.FRAMEWORK_CHOICES,
required=False,
help_text="Set project framework.",
)
permission = serializers.ChoiceField(
write_only=True,
choices=PERMISSION_CHOICES,
Expand All @@ -158,6 +165,7 @@ class Meta:
"users",
"email",
"action",
"framework",
"permission",
"data_status",
"data_expiry_days",
Expand Down
6 changes: 6 additions & 0 deletions estela-api/api/views/project.py
Expand Up @@ -100,11 +100,17 @@ def update(self, request, *args, **kwargs):
data_status = serializer.validated_data.pop("data_status", "")
data_expiry_days = serializer.validated_data.pop("data_expiry_days", 0)
description = ""
framework = serializer.validated_data.pop("framework", "")

if name:
old_name = instance.name
instance.name = name
description = f"renamed project {old_name} ({instance.pid}) to {name}."

if framework and framework != instance.framework:
instance.framework = framework
description = f"changed the framework to {framework}."

user = request.user
is_superuser = user.is_superuser or user.is_staff
if user_email and (is_superuser or user_email != user.email):
Expand Down
23 changes: 23 additions & 0 deletions estela-api/core/migrations/0032_project_framework.py
@@ -0,0 +1,23 @@
# Generated by Django 3.1.14 on 2023-07-12 14:14

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("core", "0031_project_oder_by_name"),
]

operations = [
migrations.AddField(
model_name="project",
name="framework",
field=models.CharField(
choices=[("SCRAPY", "Scrapy"), ("REQUESTS", "Requests")],
default="SCRAPY",
help_text="Project's framework.",
max_length=20,
),
),
]
12 changes: 12 additions & 0 deletions estela-api/core/models.py
Expand Up @@ -23,6 +23,12 @@ class DataStatus:


class Project(models.Model):
SCRAPY = "SCRAPY"
REQUESTS = "REQUESTS"
FRAMEWORK_CHOICES = [
(SCRAPY, "Scrapy"),
(REQUESTS, "Requests"),
]
NOT_SPECIFIED = "NOT SPECIFIED"
E_COMMERCE = "E-COMMERCE"
LOGISTICS = "LOGISTICS"
Expand Down Expand Up @@ -59,6 +65,12 @@ class Project(models.Model):
users = models.ManyToManyField(
User, through="Permission", help_text="Users with permissions on this project."
)
framework = models.CharField(
max_length=20,
choices=FRAMEWORK_CHOICES,
default=SCRAPY,
help_text="Project's framework.",
)
data_status = models.CharField(
max_length=20,
choices=DataStatus.HIGH_LEVEL_OPTIONS,
Expand Down
14 changes: 14 additions & 0 deletions estela-api/docs/api.yaml
Expand Up @@ -1691,6 +1691,13 @@ definitions:
- EDUCATIONAL
- TECHNOLOGY
- OTHER_CATEGORY
framework:
title: Framework
description: Project's framework.
type: string
enum:
- SCRAPY
- REQUESTS
container_image:
title: Container image
description: Path of the project's container image.
Expand Down Expand Up @@ -1748,6 +1755,13 @@ definitions:
- remove
- add
- update
framework:
title: Framework
description: Set project framework.
type: string
enum:
- SCRAPY
- REQUESTS
permission:
title: Permission
description: New permission.
Expand Down
23 changes: 23 additions & 0 deletions estela-web/src/components/FrameworkTag/index.tsx
@@ -0,0 +1,23 @@
import React from "react";
import { Tag } from "antd";

export function RequestTag() {
return (
<div className="flex">
<Tag className="text-estela-blue-full font-semibold border-0 bg-estela-blue-low text-base rounded py-1">
REQUESTS
</Tag>
<Tag className="text-xs border-estela-blue-full text-estela-blue-full h-fit rounded">Beta</Tag>
</div>
);
}

export function ScrapyTag() {
return (
<div className="flex">
<Tag className="text-estela-blue-full font-semibold border-0 bg-estela-blue-low text-base rounded py-1">
SCRAPY
</Tag>
</div>
);
}
45 changes: 32 additions & 13 deletions estela-web/src/pages/ProjectListPage/index.tsx
Expand Up @@ -22,6 +22,7 @@ interface ProjectList {
category?: string;
pid: string | undefined;
role: string;
framework: string | undefined;
key: number;
}

Expand Down Expand Up @@ -65,7 +66,10 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
<Link
className="text-sm font-medium hover:text-estela"
to={`/projects/${project.pid}/dashboard`}
onClick={() => this.setUserRole(project.role)}
onClick={() => {
this.setUserRole(project.role);
AuthService.setFramework(String(project.framework));
}}
>
{name}
</Link>
Expand All @@ -77,6 +81,14 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
key: "pid",
render: (pid: string): ReactElement => <p className="font-courier">{pid}</p>,
},
{
title: "FRAMEWORK",
dataIndex: "framework",
key: "framework",
render: (framework: string): ReactElement => (
<Tag className="border-estela-blue-full rounded-md text-estela-blue-full p-1">{framework}</Tag>
),
},
{
title: "ROLE",
dataIndex: "role",
Expand All @@ -99,11 +111,13 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
async componentDidMount(): Promise<void> {
const { updateRole } = this.context as UserContextProps;
updateRole && updateRole("");
AuthService.removeFramework();
const data = await this.getProjects(1);
const projectData: ProjectList[] = data.data.map((project: Project, id: number) => {
return {
name: project.name,
category: project.category,
framework: project.framework,
pid: project.pid,
role:
project.users?.find((user) => user.user?.username === AuthService.getUserUsername())?.permission ||
Expand Down Expand Up @@ -142,6 +156,7 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
updateRole && updateRole(response.users[0].permission ?? "");
}
history.push(`/projects/${response.pid}/deploys`);
AuthService.setFramework(String(response.framework));
},
(error: unknown) => {
error;
Expand Down Expand Up @@ -174,6 +189,7 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
return {
name: project.name,
pid: project.pid,
framework: project.framework,
role:
project.users?.find((user) => user.user?.username === AuthService.getUserUsername())?.permission ||
"Admin",
Expand All @@ -196,7 +212,7 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
<>
{loaded ? (
<Fragment>
<Content className="mx-4">
<Content className="mx-auto w-full lg:px-10">
<Modal
open={modalWelcome}
footer={false}
Expand Down Expand Up @@ -237,7 +253,7 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
</Col>
</Row>
</Modal>
<Space direction="vertical" className="mx-8">
<Space direction="vertical" className="w-full">
<Content className="float-left">
<Text className="text-3xl">
Welcome home&nbsp;
Expand All @@ -250,34 +266,38 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
<Text className="text-silver text-base font-medium">RECENT PROJECTS</Text>
</Col>
</Row>
<Row className="grid grid-cols-3 gap-3 mt-4">
<Row className="flex-row gap-3 mt-4">
{projects.map((project: ProjectList, index) => {
return index < 3 ? (
<Button
key={project.key}
onClick={() => {
const { updateRole } = this.context as UserContextProps;
AuthService.setUserRole(project.role);
AuthService.setFramework(String(project.framework));
updateRole && updateRole(project.role);
history.push(`/projects/${project.pid}/dashboard`);
}}
className="bg-white rounded-md p-3 h-20 hover:border-none border-none hover:bg-estela-blue-low hover:text-estela-blue-full"
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"
>
<Row className="gap-3 m-1">
<Row className="gap-4">
<Text className="text-sm font-bold">{project.name}</Text>
{index === 0 && (
<Tag className="text-estela bg-estela-blue-low border-none font-medium rounded-md">
New
</Tag>
)}
</Row>
<Row className="flow-root rounded-md m-2">
<Text className="float-left text-xs font-courier">
{project.pid}
</Text>
<Tag className="float-right bg-white border-white rounded-md">
<Row className="rounded-md my-3">
<Text className="text-xs font-courier">{project.pid}</Text>
</Row>
<Row className="w-full justify-between">
<Tag className="bg-white border-white rounded-md">
{project.role}
</Tag>
<Tag className="border-estela-blue-full text-estela-blue-full rounded-md">
{project.framework}
</Tag>
</Row>
</Button>
) : (
Expand Down Expand Up @@ -412,10 +432,9 @@ export class ProjectListPage extends Component<unknown, ProjectsPageState> {
</Modal>
</Col>
</Row>
<Row>
<Row className="flex flex-col w-full">
<Table
showHeader={false}
tableLayout="fixed"
className="rounded-2xl"
columns={this.columns}
dataSource={projects}
Expand Down
15 changes: 15 additions & 0 deletions estela-web/src/services/api/generated-api/models/Project.ts
Expand Up @@ -44,6 +44,12 @@ export interface Project {
* @memberof Project
*/
category?: ProjectCategoryEnum;
/**
* Project's framework.
* @type {string}
* @memberof Project
*/
framework?: ProjectFrameworkEnum;
/**
* Path of the project's container image.
* @type {string}
Expand Down Expand Up @@ -86,6 +92,13 @@ export enum ProjectCategoryEnum {
* @export
* @enum {string}
*/
export enum ProjectFrameworkEnum {
Scrapy = 'SCRAPY',
Requests = 'REQUESTS'
}/**
* @export
* @enum {string}
*/
export enum ProjectDataStatusEnum {
Persistent = 'PERSISTENT',
Pending = 'PENDING'
Expand All @@ -104,6 +117,7 @@ export function ProjectFromJSONTyped(json: any, ignoreDiscriminator: boolean): P
'pid': !exists(json, 'pid') ? undefined : json['pid'],
'name': json['name'],
'category': !exists(json, 'category') ? undefined : json['category'],
'framework': !exists(json, 'framework') ? undefined : json['framework'],
'containerImage': !exists(json, 'container_image') ? undefined : json['container_image'],
'users': !exists(json, 'users') ? undefined : ((json['users'] as Array<any>).map(PermissionFromJSON)),
'dataStatus': !exists(json, 'data_status') ? undefined : json['data_status'],
Expand All @@ -122,6 +136,7 @@ export function ProjectToJSON(value?: Project | null): any {

'name': value.name,
'category': value.category,
'framework': value.framework,
'users': value.users === undefined ? undefined : ((value.users as Array<any>).map(PermissionToJSON)),
'data_status': value.dataStatus,
'data_expiry_days': value.dataExpiryDays,
Expand Down
15 changes: 15 additions & 0 deletions estela-web/src/services/api/generated-api/models/ProjectUpdate.ts
Expand Up @@ -56,6 +56,12 @@ export interface ProjectUpdate {
* @memberof ProjectUpdate
*/
action?: ProjectUpdateActionEnum;
/**
* Set project framework.
* @type {string}
* @memberof ProjectUpdate
*/
framework?: ProjectUpdateFrameworkEnum;
/**
* New permission.
* @type {string}
Expand Down Expand Up @@ -88,6 +94,13 @@ export enum ProjectUpdateActionEnum {
* @export
* @enum {string}
*/
export enum ProjectUpdateFrameworkEnum {
Scrapy = 'SCRAPY',
Requests = 'REQUESTS'
}/**
* @export
* @enum {string}
*/
export enum ProjectUpdatePermissionEnum {
Admin = 'ADMIN',
Developer = 'DEVELOPER',
Expand Down Expand Up @@ -116,6 +129,7 @@ export function ProjectUpdateFromJSONTyped(json: any, ignoreDiscriminator: boole
'users': !exists(json, 'users') ? undefined : ((json['users'] as Array<any>).map(UserDetailFromJSON)),
'email': !exists(json, 'email') ? undefined : json['email'],
'action': !exists(json, 'action') ? undefined : json['action'],
'framework': !exists(json, 'framework') ? undefined : json['framework'],
'permission': !exists(json, 'permission') ? undefined : json['permission'],
'dataStatus': !exists(json, 'data_status') ? undefined : json['data_status'],
'dataExpiryDays': !exists(json, 'data_expiry_days') ? undefined : json['data_expiry_days'],
Expand All @@ -135,6 +149,7 @@ export function ProjectUpdateToJSON(value?: ProjectUpdate | null): any {
'users': value.users === undefined ? undefined : ((value.users as Array<any>).map(UserDetailToJSON)),
'email': value.email,
'action': value.action,
'framework': value.framework,
'permission': value.permission,
'data_status': value.dataStatus,
'data_expiry_days': value.dataExpiryDays,
Expand Down

0 comments on commit ec08db0

Please sign in to comment.