Skip to content

Commit

Permalink
Add tags (#511)
Browse files Browse the repository at this point in the history
* Add tags

* Fixes
  • Loading branch information
LanternNassi authored Jul 2, 2024
1 parent 9786287 commit 060a447
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 1 deletion.
112 changes: 112 additions & 0 deletions api_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3641,6 +3641,118 @@ paths:
500:
description: "Internal Server Error"

"/projects/tags/{tag_id}":
get:
tags:
- projects
consumes:
- application/json
produces:
- application/json
parameters:
- in: header
name: Authorization
required: true
description: "Bearer [token]"
- in: path
name: tag_id
required: true
type: string
responses:
200:
description: "Success"
404:
description: "Tag not found"
400:
description: "Bad request"
500:
description: "Internal Server Error"

delete:
tags:
- projects
consumes:
- application/json
produces:
- application/json
parameters:
- in: header
name: Authorization
required: true
description: "Bearer [token]"
- in: path
name: tag_id
required: true
type: string

responses:
200:
description: "Success"
404:
description: "User not found"
400:
description: "Bad request"
500:
description: "Internal Server Error"


"/projects/tags":
post:
tags:
- projects
consumes:
- application/json
parameters:
- in: header
name: Authorization
required: true
description: "Bearer [token]"
type: string
- in: body
name: tag
schema:
type: array
required:
- name
items:
type: string

produces:
- application/json
responses:
201:
description: "Success"
400:
description: "Bad request"
500:
description: "Internal Server Error"

get:
tags:
- projects
consumes:
- application/json
produces:
- application/json
parameters:
- in: header
name: Authorization
required: true
description: "Bearer [token]"
type: string
- in: query
name: keywords
type: string
description: Enter keywords if searching
responses:
200:
description: "Success"
400:
description: "Bad request"
500:
description: "Internal Server Error"


components:
securitySchemes:
bearerAuth:
Expand Down
1 change: 1 addition & 0 deletions app/controllers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@
from .system_status import SystemSummaryView
from .project_users import ProjectUsersView, ProjectUsersTransferView, ProjectUsersHandleInviteView, ProjectFollowingView
from .activity_feed import ActivityFeedView
from .project_tags import ProjectTagsView, ProjectTagsDetailView
88 changes: 88 additions & 0 deletions app/controllers/project_tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@

from flask_restful import Resource, request
from flask_jwt_extended import jwt_required, get_jwt_identity, get_jwt_claims
from app.schemas.project_tags import ProjectTagSchema
from app.models.project_tag import ProjectTag
from app.helpers.decorators import admin_required




class ProjectTagsView(Resource):

@jwt_required
def post(self):
tags_data = request.get_json()

project_tag_schema = ProjectTagSchema()

for _tag in tags_data:
validated_tag_data , errors = project_tag_schema.load({'name' : _tag})
if not ProjectTag.find_first(name=validated_tag_data['name']):
tag = ProjectTag(**validated_tag_data)
tag.save()

return dict(
status='success',
message='Tags saved successfully'
) , 201

def get(self):
keywords = request.args.get('keywords', None)

project_tag_schema = ProjectTagSchema(many=True)

project_tags = ProjectTag.find_all()

if keywords :
project_tags = ProjectTag.query.filter(ProjectTag.name.ilike(f'%{keywords}%'))

tags_data = project_tag_schema.dump(project_tags)

return dict(
status="success",
data=tags_data.data
) , 200

class ProjectTagsDetailView(Resource):
def get(self, tag_id):

project_tag_id_schema = ProjectTagSchema()

project_tag = ProjectTag.get_by_id(tag_id)

tags_data = project_tag_id_schema.dump(project_tag)

return dict(
status="success",
data=tags_data.data
) , 200

@admin_required
def delete(self, tag_id):

current_user_roles = get_jwt_claims()['roles']

tag = ProjectTag.get_by_id(tag_id)

deleted = tag.soft_delete()

if not deleted:
return dict(
status='fail',
message='An error occured during deletion'
) , 500

return dict(
status='success',
message=f"Tag {tag_id} successfully deleted"
) , 200









1 change: 1 addition & 0 deletions app/models/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ class Project(ModelMixin):

def is_followed_by(self, user):
return any(follower.user_id == user.id for follower in self.followers)

19 changes: 19 additions & 0 deletions app/models/project_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from sqlalchemy.dialects.postgresql import UUID
from app.models import db
from app.models.model_mixin import ModelMixin, SoftDeleteQuery
from sqlalchemy import text as sa_text



class ProjectTag(ModelMixin):
__tablename__ = "project_tags"
query_class = SoftDeleteQuery

id = db.Column(UUID(as_uuid=True), primary_key=True,
server_default=sa_text("uuid_generate_v4()"))
name = db.Column(db.String)
deleted = db.Column(db.Boolean, default=False)
date_created = db.Column(db.DateTime, default=db.func.current_timestamp())



4 changes: 3 additions & 1 deletion app/routes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
UserAdminUpdateView, AppRevertView, ProjectGetCostsView, TransactionRecordView, CreditTransactionRecordView, CreditPurchaseTransactionRecordView,
BillingInvoiceView, BillingInvoiceNotificationView, SystemSummaryView, CreditDetailView, ProjectUsersView, ProjectUsersTransferView, AppReviseView,
ProjectUsersHandleInviteView, ClusterProjectsView, ProjectDisableView, ProjectEnableView, AppRedeployView, AppDisableView, AppEnableView,
ProjectTagsView,ProjectTagsDetailView,
UserDisableView, UserEnableView, AppDockerWebhookListenerView, UserFollowersView, UserFollowView, ProjectFollowingView, ActivityFeedView)
from app.controllers.app import AppRevisionsView
from app.controllers.billing_invoice import BillingInvoiceDetailView
Expand Down Expand Up @@ -149,7 +150,8 @@
api.add_resource(ProjectPinView, '/projects/<string:project_id>/pin')
# User Project routes
api.add_resource(UserProjectsView, '/users/<string:user_id>/projects')

api.add_resource(ProjectTagsView, '/projects/tags')
api.add_resource(ProjectTagsDetailView, '/projects/tags/<string:tag_id>')
# App routes
api.add_resource(AppsView, '/apps')
api.add_resource(AppDetailView, '/apps/<string:app_id>')
Expand Down
15 changes: 15 additions & 0 deletions app/schemas/project_tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from marshmallow import Schema, fields, validate, pre_load


class ProjectTagSchema(Schema):

id = fields.UUID(dump_only=True)
name = fields.String(required=True, error_message={
"required": "name is required"},
validate=[
validate.Regexp(
regex=r'^(?!\s*$)', error='name should be a valid string'
),
])
date_created = fields.Date(dump_only=True)

35 changes: 35 additions & 0 deletions migrations/versions/2f06b8e0c98b_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""empty message
Revision ID: 2f06b8e0c98b
Revises: 5f6dfc8f1b35
Create Date: 2024-06-27 20:02:34.415744
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = '2f06b8e0c98b'
down_revision = '5f6dfc8f1b35'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('project_tags',
sa.Column('id', postgresql.UUID(as_uuid=True), server_default=sa.text('uuid_generate_v4()'), nullable=False),
sa.Column('name', sa.String(), nullable=True),
sa.Column('deleted', sa.Boolean(), nullable=True),
sa.Column('date_created', sa.DateTime(), nullable=True),

sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('project_tags')
# ### end Alembic commands ###

0 comments on commit 060a447

Please sign in to comment.