Skip to content

Commit 7f0a249

Browse files
committed
update admin_notifications setup
2 parents 8980de4 + eb9b082 commit 7f0a249

32 files changed

+891
-394
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ jobs:
191191
./cc-test-reporter before-build
192192
. venv/bin/activate
193193
coverage combine parallel-coverage/
194-
coverage xml
194+
coverage xml -i
195195
coverage report
196196
./cc-test-reporter format-coverage -o ./.coverage -t coverage.py
197197
./cc-test-reporter upload-coverage -i .coverage

.codeclimate.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ version: "2"
22
exclude_patterns:
33
- "helpers/auth/authentication.py"
44
- "helpers/calendar/events.py"
5-
- "alembic/"
5+
- "alembic/"
6+
- "admin_notifications/__init__.py"
7+
- "admin_notifications/helpers/__init__.py"
8+
- "admin_notifications/helpers/notification_templates.py"
Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,34 @@
1-
from flask_socketio import send
21
from admin_notifications.models import AdminNotification
3-
from manage import socketio
4-
5-
def create_notification(title, message, location_id):
6-
notification = AdminNotification(
7-
title=title,
8-
message=message,
9-
location_id=location_id,
10-
status="unread"
11-
)
12-
notification.save()
13-
14-
@socketio.on('notification')
15-
def send_notification():
16-
notification = { "title": title, "message": message }
17-
return send(notification, broadcast=True)
2+
from api.location.models import Location
3+
from datetime import datetime
4+
import celery
185

196

7+
def update_notification(notification_id):
8+
notification = AdminNotification.query.filter_by(id=notification_id).first()
9+
notification.date_received = datetime.now()
10+
notification.save()
2011

2112

22-
23-
def create_notif_lol():
24-
return create_notification(title="twre3r", message="rerf3ef3rf3rf", location_id=1)
13+
@celery.task
14+
def create_notification(title, message, location_id):
15+
"""
16+
Create notifications in the database and emit them to the client
17+
"""
18+
from manage import socketio
19+
location = Location.query.filter_by(id=location_id).first()
20+
location_name = location.name
21+
notification = AdminNotification(
22+
title=title,
23+
message=message,
24+
location_id=location_id,
25+
status="unread"
26+
)
27+
notification.save()
28+
new_notification = {"title": title, "message": message}
29+
return socketio.emit(
30+
f"notifications-{location_name}",
31+
{'notification': new_notification},
32+
broadcast=True,
33+
callback=update_notification(notification.id)
34+
)

admin_notifications/helpers/device_last_seen.py

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
def event_auto_cancelled_notification(event_name, room_name):
2+
return {
3+
"title": "Event Auto cancelled.",
4+
"message": f"An event {event_name} in {room_name} \
5+
has been auto cancelled."
6+
}

admin_notifications/helpers/queue_manager.py

Lines changed: 0 additions & 7 deletions
This file was deleted.

admin_notifications/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ class AdminNotification(Base, Utility):
1515
location_id = Column(
1616
Integer,
1717
ForeignKey('locations.id', ondelete="CASCADE"),
18-
nullable=True)
18+
nullable=True
19+
)

admin_notifications/schema.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import graphene
2+
from graphene_sqlalchemy import SQLAlchemyObjectType
3+
from graphql import GraphQLError
4+
from helpers.auth.authentication import Auth
5+
from datetime import datetime
6+
from admin_notifications.models import AdminNotification as \
7+
AdminNotificationModel
8+
9+
10+
class AdminNotifications(SQLAlchemyObjectType):
11+
"""
12+
Returns the admin_notificationspayload
13+
"""
14+
class Meta:
15+
model = AdminNotificationModel
16+
17+
18+
class NotificationsList(graphene.ObjectType):
19+
"""
20+
Class to return the types for Admin notifications
21+
\n- rooms: The rooms data
22+
"""
23+
notifications = graphene.List(AdminNotifications)
24+
25+
26+
class Query(graphene.ObjectType):
27+
all_unread_notifications = graphene.Field(
28+
NotificationsList,
29+
description="Returns a list of admin notifications"
30+
)
31+
32+
@Auth.user_roles('Admin')
33+
def resolve_all_unread_notifications(self, info):
34+
query = AdminNotifications.get_query(info)
35+
notifications = query.filter(
36+
AdminNotificationModel.status == "unread").all()
37+
return NotificationsList(notifications=notifications)
38+
39+
40+
class UpdateNotificationStatus(graphene.Mutation):
41+
"""
42+
Class to update the status of a notification
43+
"""
44+
45+
class Arguments:
46+
notification_id = graphene.Int(required=True)
47+
notification = graphene.Field(AdminNotifications)
48+
49+
@Auth.user_roles('Admin')
50+
def mutate(self, info, notification_id):
51+
query = AdminNotifications.get_query(info)
52+
unread_notifications = query.filter(
53+
AdminNotificationModel.status == "unread")
54+
notification = unread_notifications.filter(
55+
AdminNotificationModel.id == notification_id).first()
56+
if not notification:
57+
raise GraphQLError("Notification is already read or not found.")
58+
notification.status = "read"
59+
notification.date_read = datetime.now()
60+
notification.save()
61+
return UpdateNotificationStatus(notification=notification)
62+
63+
64+
class Mutation(graphene.ObjectType):
65+
update_notification_status = UpdateNotificationStatus.Field(
66+
description="Updates the status of a notification and takes the argument\
67+
\n- notification_id: The name of the room[required]")

admin_notifications/socket_handler.py

Lines changed: 0 additions & 19 deletions
This file was deleted.

alembic/versions/1b53553ddacf_add_activity_column_to_devices_table.py

Lines changed: 0 additions & 34 deletions
This file was deleted.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""Add CheckOptions column to Questions table
2+
3+
Revision ID: 50173cb0491f
4+
Revises: ac2686b45596
5+
Create Date: 2019-05-07 14:47:01.869751
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
from sqlalchemy.dialects import postgresql
11+
12+
# revision identifiers, used by Alembic.
13+
revision = '50173cb0491f'
14+
down_revision = 'a5a4841351d7'
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade():
20+
# ### commands auto generated by Alembic - please adjust! ###
21+
op.add_column('questions', sa.Column('check_options', postgresql.ARRAY(sa.String()), nullable=True))
22+
# ### end Alembic commands ###
23+
24+
25+
def downgrade():
26+
# ### commands auto generated by Alembic - please adjust! ###
27+
op.drop_column('questions', 'check_options')
28+
# ### end Alembic commands ###

alembic/versions/a5a4841351d7_refactor_response_model.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ def upgrade():
2323
'check', 'text_area', 'rate', name='questiontype')
2424
questiontype.create(op.get_bind())
2525
op.add_column('responses', sa.Column('question_type', sa.Enum(
26-
'rate', 'check', 'text_area', name='questiontype'), nullable=True))
26+
'rate', 'check', 'text_area', 'missing_items', name='questiontype'),
27+
nullable=True))
2728
op.add_column('responses', sa.Column(
28-
'response', sa.String(), nullable=True))
29+
'response', postgresql.ARRAY(sa.String()), nullable=True))
2930
op.drop_column('responses', 'text_area')
3031
op.drop_column('responses', 'check')
3132
op.drop_column('responses', 'rate')
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""add admin notifications table
2+
3+
Revision ID: f0873fb8edb3
4+
Revises: 50173cb0491f
5+
Create Date: 2019-06-27 13:31:19.694650
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
11+
12+
# revision identifiers, used by Alembic.
13+
revision = 'f0873fb8edb3'
14+
down_revision = '50173cb0491f'
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade():
20+
# ### commands auto generated by Alembic - please adjust! ###
21+
op.execute('DROP TYPE statustype;')
22+
op.create_table('admin_notifications',
23+
sa.Column('id', sa.Integer(), nullable=False),
24+
sa.Column('title', sa.String(), nullable=True),
25+
sa.Column('message', sa.String(), nullable=True),
26+
sa.Column('date_received', sa.String(), nullable=True),
27+
sa.Column('date_read', sa.String(), nullable=True),
28+
sa.Column('status', sa.Enum('read', 'unread', name='statustype'), nullable=True),
29+
sa.Column('location_id', sa.Integer(), nullable=True),
30+
sa.ForeignKeyConstraint(['location_id'], ['locations.id'], ondelete='CASCADE'),
31+
sa.PrimaryKeyConstraint('id')
32+
)
33+
# ### end Alembic commands ###
34+
35+
36+
def downgrade():
37+
# ### commands auto generated by Alembic - please adjust! ###
38+
op.drop_table('admin_notifications')
39+
# ### end Alembic commands ###

api/devices/models.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from helpers.database import Base
66
from utilities.validations import validate_empty_fields
7-
from utilities.utility import Utility, ActivityType
7+
from utilities.utility import Utility
88

99

1010
class Devices(Base, Utility):
@@ -17,7 +17,6 @@ class Devices(Base, Utility):
1717
location = Column(String, nullable=False)
1818
room_id = Column(Integer, ForeignKey('rooms.id', ondelete="CASCADE"))
1919
room = relationship('Room')
20-
activity = Column(Enum(ActivityType), default="active")
2120

2221
def __init__(self, **kwargs):
2322
validate_empty_fields(**kwargs)

api/question/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from sqlalchemy import (Column, String, Integer, Boolean, Enum, Index)
22
from sqlalchemy.orm import relationship, validates
3-
3+
from sqlalchemy.dialects import postgresql
44
from helpers.database import Base
55
from utilities.utility import Utility, StateType
66
import api.response.models
@@ -13,6 +13,7 @@ class Question(Base, Utility):
1313
question_type = Column(String, nullable=False)
1414
question = Column(String, nullable=False)
1515
start_date = Column(String, nullable=False)
16+
check_options = Column(postgresql.ARRAY(String))
1617
end_date = Column(String, nullable=False)
1718
total_views = Column(Integer, default=0)
1819
response = relationship('Response', cascade="all, delete-orphan")

api/question/schema.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,27 @@ class Arguments:
4141
question = graphene.String(required=True)
4242
start_date = graphene.DateTime(required=True)
4343
end_date = graphene.DateTime(required=True)
44+
check_options = graphene.List(graphene.String, required=False)
4445
question = graphene.Field(Question)
4546

4647
@Auth.user_roles('Admin')
4748
def mutate(self, info, **kwargs):
4849
validate_empty_fields(**kwargs)
4950
validate_question_type(**kwargs)
5051
validate_date_time_range(**kwargs)
51-
question = QuestionModel(**kwargs)
52+
question_type = kwargs['question_type']
53+
fields = kwargs
54+
if question_type == "check" and not kwargs.get('check_options'):
55+
return GraphQLError(
56+
"No check options supplied for question type check"
57+
)
58+
if question_type != "check":
59+
fields['check_options'] = None
5260
payload = {
5361
'model': QuestionModel, 'field': 'question',
5462
'value': kwargs['question']
5563
}
64+
question = QuestionModel(**fields)
5665
with SaveContextManager(question, 'Question', payload):
5766
return CreateQuestion(question=question)
5867

0 commit comments

Comments
 (0)