1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
from typing import List
from collections import defaultdict
from sqlalchemy.orm import Session
from girok.server.src.database import get_db
import girok.server.src.category.schemas as schemas
import girok.server.src.category.service as service
import girok.server.src.category.exceptions as exceptions
import girok.server.src.category.constants as category_constants
def get_all_categories():
db = next(get_db())
resp = defaultdict(dict)
cats = service.get_subcategories_by_parent_id(db, pid=None)
for cat in cats:
resp[cat.name]["subcategories"] = service.build_category_tree(db, cat.task_category_id)
resp[cat.name]["color"] = cat.color
resp['No Category'] = {
"color": "grey",
"subcategories": {}
}
return resp
def create_category(category: schemas.CategoryCreateIn):
db = next(get_db())
''' Example
category = {
names: ['HKU', 'COMP3230', 'Assignment']
color: yellow
}
'''
names = category['names']
color = category['color']
if color and color not in category_constants.CATEGORY_COLORS:
return {"success": False, "detail": exceptions.CategoryColorNotExistException(color).detail}
try:
pid_of_second_last_cat, cumul_path = service.get_last_cat_id(db, names[:-1])
except Exception as e:
return {"success": False, "detail": e.detail}
# If given, check if the subdirectory color is equal to the parent's color,
if color is None:
if pid_of_second_last_cat is not None:
color = service.get_category_color_by_id(db, pid_of_second_last_cat) # set to parent's color
else:
# Select non-overlapping colors
existing_colors = set(service.get_all_category_colors(db).values())
for c in category_constants.CATEGORY_COLORS: # Assign color (lower index higher priority)
if c in existing_colors:
continue
color = c
break
if color is None: # If no available non-overlapping color, assign the default color
color = category_constants.DEFAULT_CATEGORY_COLOR
else:
if pid_of_second_last_cat is not None:
parent_color = service.get_category_color_by_id(db, pid_of_second_last_cat)
if color != parent_color:
return {"success": False, "detail": exceptions.CategoryColorException(names[-1], color, '/'.join(names[:-1]), parent_color).detail}
new_cat_name = names[-1]
dup_cat_id = service.get_category_id_by_name_and_parent_id(db, new_cat_name, pid_of_second_last_cat)
if dup_cat_id:
return {"success": False, "detail": exceptions.CategoryAlreadyExistsException(cumul_path, new_cat_name).detail}
new_cat_data = {
"name": new_cat_name,
"super_task_category_id": pid_of_second_last_cat,
"color": color
}
new_cat = service.create_category(db, new_cat_data)
return {"success": True, "data": new_cat}
def delete_category(category: schemas.CategoryDeleteIn):
db = next(get_db())
cats = category['cats']
try:
cat_id, _ = service.get_last_cat_id(db, cats)
except Exception as e:
return {"success": False, "detail": e.detail}
service.delete_category(db, cat_id)
return {"success": True}
def rename_category(category: schemas.CategoryRenameIn):
db = next(get_db())
cats, new_name, = category['cats'], category['new_name']
# Get cat_id of the original category
try:
cat_id, _ = service.get_last_cat_id(db, cats)
except Exception as e:
return {"success": False, "detail": e.detail}
# Check if new_cats exists (ex. cats[:-1] + /new_cat)
new_cats = cats[:-1] + [new_name]
if service.check_exist_category(db, new_cats):
return {"success": False, "detail": exceptions.CategoryAlreadyExistsException('/'.join(new_cats[:-1]), new_name)}
service.rename_category(db, cat_id, new_name)
return {"success": True}
def move_category(category: schemas.CategoryMoveIn):
"""
cats: ['HKU', 'COMP3230']
new_parent_cats: ['Dev', 'Git']
Then, we want to move the entire HKU/COMP3230 category into under Dev/Git category.
"""
db = next(get_db())
cats, new_parent_cats = category['cats'], category['new_parent_cats']
if not cats:
return {"success": False, "detail": exceptions.CannotMoveRootDirectoryException().detail}
new_cat = new_parent_cats + [cats[-1]]
if service.check_exist_category(db, new_parent_cats + [cats[-1]]):
raise exceptions.CategoryAlreadyExistsException('/'.join(new_parent_cats), cats[-1])
try:
cat_id, _ = service.get_last_cat_id(db, cats)
new_pid, _ = service.get_last_cat_id(db, new_parent_cats)
except Exception as e:
return {"success": False, "detail": e.detail}
if cat_id == new_pid:
return {"success": False, "detail": exceptions.CannotMoveToSameLocation().detail}
service.move_category(db, cat_id, new_pid)
return {"success": True}
def get_last_cat_id(cat_data: schemas.LastCategoryIdIn):
db = next(get_db())
try:
cat_id, _ = service.get_last_cat_id(db, cat_data['cats'])
return {"success": True, "cat_id": cat_id}
except Exception as e:
return {"success": False, "detail": e.detail}
def get_category_color(cat_id: int):
db = next(get_db())
try:
color = service.get_category_color_by_id(db, cat_id)
return {"success": True, "color": color}
except Exception as e:
return {"success": False, "detail": e.detail}
def get_category_colors_dict():
db = next(get_db())
try:
colors = service.get_all_category_colors(db)
colors['No Category'] = "grey"
return {"success": True, "colors": colors}
except Exception as e:
return {"success": False, "detail": e.detail}
|