Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added backend/community/__init__.py
Empty file.
54 changes: 54 additions & 0 deletions backend/community/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Generated by Django 3.2.25 on 2025-08-11 05:58

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import utils.models


class Migration(migrations.Migration):

initial = True

dependencies = [
('contest', '0001_initial'),
('problem', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='Post',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=200)),
('content', utils.models.RichTextField()),
('community_type', models.CharField(choices=[('GENERAL', '일반'), ('PROBLEM', '문제'), ('CONTEST', '대회')], default='GENERAL', max_length=20)),
('post_type', models.CharField(choices=[('QUESTION', '질문'), ('ARTICLE', '글'), ('ANNOUNCEMENT', '공지')], default='ARTICLE', max_length=20)),
('question_status', models.CharField(choices=[('OPEN', '진행중'), ('CLOSED', '해결됨')], default='OPEN', max_length=20)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('contest', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='contest.contest')),
('problem', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='problem.problem')),
],
options={
'ordering': ['-created_at'],
},
),
migrations.CreateModel(
name='Comment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('content', utils.models.RichTextField()),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('parent_comment', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='replies', to='community.comment')),
('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='community.post')),
],
options={
'ordering': ['created_at'],
},
),
]
Empty file.
93 changes: 93 additions & 0 deletions backend/community/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
from django.db import models

from account.models import User
from contest.models import Contest
from problem.models import Problem
from utils.models import RichTextField


class Post(models.Model):
"""커뮤니티 게시글 모델

Attributes:
title (CharField): 게시글 제목 (최대 200자)
content (RichTextField): 게시글 내용
author (ForeignKey): 작성자 (User 모델 외래 키)
problem (ForeignKey): 연관된 문제 (Problem 모델 외래 키, community_type이 'PROBLEM'일 경우)
contest (ForeignKey): 연관된 대회 (Contest 모델 외래 키, community_type이 'CONTEST'일 경우)
community_type (CharField): 커뮤니티 종류 (일반, 문제, 대회)
post_type (CharField): 게시글 종류 (질문, 글, 공지)
question_status (CharField): 질문 상태 (진행중, 해결됨), post_type이 'QUESTION'일 경우
created_at (DateTimeField): 생성 일시 (자동 생성)
updated_at (DateTimeField): 수정 일시 (자동 업데이트)
"""

class CommunityType(models.TextChoices):
"""게시글의 커뮤니티 종류"""
GENERAL = 'GENERAL', '일반'
PROBLEM = 'PROBLEM', '문제'
CONTEST = 'CONTEST', '대회'

class PostType(models.TextChoices):
"""게시글의 종류"""
QUESTION = 'QUESTION', '질문'
ARTICLE = 'ARTICLE', '글'
ANNOUNCEMENT = 'ANNOUNCEMENT', '공지'

class QuestionStatus(models.TextChoices):
"""질문 게시글의 상태"""
OPEN = 'OPEN', '진행중'
CLOSED = 'CLOSED', '해결됨'

title = models.CharField(max_length=200)
content = RichTextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)

problem = models.ForeignKey(Problem, null=True, blank=True, on_delete=models.CASCADE)
contest = models.ForeignKey(Contest, null=True, blank=True, on_delete=models.CASCADE)

community_type = models.CharField(
max_length=20,
choices=CommunityType.choices,
default=CommunityType.GENERAL,
)

post_type = models.CharField(
max_length=20,
choices=PostType.choices,
default=PostType.ARTICLE,
)

question_status = models.CharField(
max_length=20,
choices=QuestionStatus.choices,
default=QuestionStatus.OPEN,
)

created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Meta:
ordering = ['-created_at']


class Comment(models.Model):
"""게시글 댓글 모델

Attributes:
post (ForeignKey): 댓글이 달린 게시글 (Post 모델 외래 키)
author (ForeignKey): 댓글 작성자 (User 모델 외래 키)
content (RichTextField): 댓글 내용
parent_comment (ForeignKey): 부모 댓글 (대댓글의 경우)
created_at (DateTimeField): 생성 일시 (자동 생성)
updated_at (DateTimeField): 수정 일시 (자동 업데이트)
"""
post = models.ForeignKey(Post, related_name='comments', on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.CASCADE)
content = RichTextField()
parent_comment = models.ForeignKey('self', null=True, blank=True, related_name='replies', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Meta:
ordering = ['created_at'] # 댓글은 오래된 순서대로 정렬
1 change: 1 addition & 0 deletions backend/oj/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
LOCAL_APPS = [
'account',
'announcement',
'community',
'conf',
'problem',
'contest',
Expand Down
14 changes: 7 additions & 7 deletions deployment/docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,28 @@ version: "3.9"

services:
frontend:
image: registry.copl-dev.site/code-place-dev/frontend:latest
image: registry.code-place-dev.site/code-place-dev/frontend:latest
ports:
- "8001:8000"
- "1444:1443"
volumes:
- /etc/letsencrypt/live/copl-dev.site/fullchain.pem:/etc/letsencrypt/live/copl-dev.site/fullchain.pem:ro
- /etc/letsencrypt/live/copl-dev.site/privkey.pem:/etc/letsencrypt/live/copl-dev.site/privkey.pem:ro
- /etc/letsencrypt/live/code-place-dev.site/fullchain.pem:/etc/letsencrypt/live/code-place-dev.site/fullchain.pem:ro
- /etc/letsencrypt/live/code-place-dev.site/privkey.pem:/etc/letsencrypt/live/code-place-dev.site/privkey.pem:ro
- data_volume:/data:ro

backend:
image: registry.copl-dev.site/code-place-dev/backend:latest
image: registry.code-place-dev.site/code-place-dev/backend:latest
volumes:
- data_volume:/data:rw

celery-beat:
image: registry.copl-dev.site/code-place-dev/backend:latest
image: registry.code-place-dev.site/code-place-dev/backend:latest

celery-worker:
image: registry.copl-dev.site/code-place-dev/backend:latest
image: registry.code-place-dev.site/code-place-dev/backend:latest

oj-judge:
image: registry.copl-dev.site/code-place-dev/judge-server:1.0.0-beta
image: registry.code-place-dev.site/code-place-dev/judge-server:1.0.0-beta

oj-postgres:
ports:
Expand Down
2 changes: 1 addition & 1 deletion deployment/docker-compose.hub.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: "3.9"

services:
auth-server:
image: registry.copl-dev.site/code-place-hub/auth-server:latest
image: registry.code-place-dev.site/code-place-hub/auth-server:latest
ports:
- "3444:80"
env_file:
Expand Down
61 changes: 61 additions & 0 deletions deployment/docker-compose.monitoring.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
version: "3.9"

networks:
monitoring:
driver: overlay
attachable: true

volumes:
prometheus-data:
grafana-data:

services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.52.0
networks:
- monitoring
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
deploy:
mode: global
restart_policy:
condition: on-failure

prometheus:
image: prom/prometheus:v3.5.0
networks:
- monitoring
volumes:
- ${PWD}/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
deploy:
replicas: 1
placement:
constraints:
- node.role == manager
restart_policy:
condition: on-failure
depends_on:
- cadvisor

grafana:
image: grafana/grafana:11.6.3
networks:
- monitoring
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
deploy:
replicas: 1
placement:
constraints:
- node.role == manager
restart_policy:
condition: on-failure
depends_on:
- prometheus
10 changes: 5 additions & 5 deletions deployment/docker-compose.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: "3.9"

services:
frontend:
image: registry.copl-dev.site/code-place-prod/frontend:latest
image: registry.code-place-dev.site/code-place-prod/frontend:latest
ports:
- "8000:8000"
- "1443:1443"
Expand All @@ -20,7 +20,7 @@ services:
order: start-first

backend:
image: registry.copl-dev.site/code-place-prod/backend:latest
image: registry.code-place-dev.site/code-place-prod/backend:latest
volumes:
- data_volume:/data:rw
deploy:
Expand All @@ -32,7 +32,7 @@ services:
condition: on-failure

celery-beat:
image: registry.copl-dev.site/code-place-prod/backend:latest
image: registry.code-place-dev.site/code-place-prod/backend:latest
deploy:
replicas: 1
update_config:
Expand All @@ -42,7 +42,7 @@ services:
condition: on-failure

celery-worker:
image: registry.copl-dev.site/code-place-prod/backend:latest
image: registry.code-place-dev.site/code-place-prod/backend:latest
deploy:
replicas: 3 # NOTE: This should be adjusted based on the workloads
update_config:
Expand All @@ -52,7 +52,7 @@ services:
condition: on-failure

oj-judge:
image: registry.copl-dev.site/code-place-prod/judge-server:1.0.0-beta
image: registry.code-place-dev.site/code-place-prod/judge-server:1.0.0-beta
deploy:
replicas: 6
update_config:
Expand Down
14 changes: 14 additions & 0 deletions deployment/prometheus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
global:
scrape_interval: 15s

scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]

- job_name: "cadvisor"
dns_sd_configs:
- names:
- "tasks.cadvisor"
type: "A"
port: 8080
31 changes: 16 additions & 15 deletions frontend/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
module.exports = {
root: true,
parser: "babel-eslint",
parser: 'babel-eslint',
parserOptions: {
sourceType: "module"
sourceType: 'module',
},
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
extends: "standard",
extends: ['standard', 'prettier'],
lintOnSave: false,
// required to lint *.vue files
plugins: ["html"],
plugins: ['html'],
// add your custom rules here
rules: {
'prettier/prettier': 'error',
// allow paren-less arrow functions
"arrow-parens": 0,
'arrow-parens': 0,
// allow async-await
"generator-star-spacing": 0,
'generator-star-spacing': 0,
// allow debugger during development
"no-debugger": process.env.NODE_ENV === "production" ? 2 : 0,
"no-irregular-whitespace": [
"error",
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'no-irregular-whitespace': [
'error',
{
skipComments: true,
skipTemplates: true
}
skipTemplates: true,
},
],
"no-unused-vars": ["warn"],
quotes: ["off", "single"]
}
};
'no-unused-vars': ['warn'],
quotes: ['off', 'single'],
},
}
7 changes: 7 additions & 0 deletions frontend/.prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
semi: false,
tabWidth: 2,
trailingComma: 'all',
printWidth: 80,
endOfLine: 'lf',
}
8 changes: 4 additions & 4 deletions frontend/deploy/swarm/web-frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ services:
- data_volume:/data:ro
- /etc/letsencrypt/live/code.pusan.ac.kr/fullchain.pem:/etc/letsencrypt/live/code.pusan.ac.kr/fullchain.pem:ro
- /etc/letsencrypt/live/code.pusan.ac.kr/privkey.pem:/etc/letsencrypt/live/code.pusan.ac.kr/privkey.pem:ro
- /etc/letsencrypt/live/copl-dev.site/fullchain.pem:/etc/letsencrypt/live/copl-dev.site/fullchain.pem:ro
- /etc/letsencrypt/live/copl-dev.site/privkey.pem:/etc/letsencrypt/live/copl-dev.site/privkey.pem:ro
- /etc/letsencrypt/live/registry.copl-dev.site/fullchain.pem:/etc/letsencrypt/live/registry.copl-dev.site/fullchain.pem:ro
- /etc/letsencrypt/live/registry.copl-dev.site/privkey.pem:/etc/letsencrypt/live/registry.copl-dev.site/privkey.pem:ro
- /etc/letsencrypt/live/code-place-dev.site/fullchain.pem:/etc/letsencrypt/live/code-place-dev.site/fullchain.pem:ro
- /etc/letsencrypt/live/code-place-dev.site/privkey.pem:/etc/letsencrypt/live/code-place-dev.site/privkey.pem:ro
- /etc/letsencrypt/live/registry.code-place-dev.site/fullchain.pem:/etc/letsencrypt/live/registry.code-place-dev.site/fullchain.pem:ro
- /etc/letsencrypt/live/registry.code-place-dev.site/privkey.pem:/etc/letsencrypt/live/registry.code-place-dev.site/privkey.pem:ro
networks:
- prod-network

Expand Down
Loading
Loading