Skip to content
Open
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
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ jobs:
./cc-test-reporter before-build
. venv/bin/activate
coverage combine parallel-coverage/
coverage xml
coverage xml -i
coverage report
./cc-test-reporter format-coverage -o ./.coverage -t coverage.py
./cc-test-reporter upload-coverage -i .coverage
Expand Down
5 changes: 4 additions & 1 deletion .codeclimate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ version: "2"
exclude_patterns:
- "helpers/auth/authentication.py"
- "helpers/calendar/events.py"
- "alembic/"
- "alembic/"
- "admin_notifications/__init__.py"
- "admin_notifications/helpers/__init__.py"
- "admin_notifications/helpers/notification_templates.py"
2 changes: 0 additions & 2 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,3 @@ omit =

[html]
directory=html_coverage_report


2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ html_coverage_report/
.tox/
.coverage
.coverage.*
.coveragerc
setup.cfg
.cache
nosetests.xml
coverage.xml
Expand Down
Empty file added admin_notifications/__init__.py
Empty file.
Empty file.
34 changes: 34 additions & 0 deletions admin_notifications/helpers/create_notification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from admin_notifications.models import AdminNotification
from api.location.models import Location
from datetime import datetime
import celery


def update_notification(notification_id):
notification = AdminNotification.query.filter_by(id=notification_id).first()
notification.date_received = datetime.now()
notification.save()


@celery.task
def create_notification(title, message, location_id):
"""
Create notifications in the database and emit them to the client
"""
from manage import socketio
location = Location.query.filter_by(id=location_id).first()
location_name = location.name
notification = AdminNotification(
title=title,
message=message,
location_id=location_id,
status="unread"
)
notification.save()
new_notification = {"title": title, "message": message}
return socketio.emit(
f"notifications-{location_name}",
{'notification': new_notification},
broadcast=True,
callback=update_notification(notification.id)
)
6 changes: 6 additions & 0 deletions admin_notifications/helpers/notification_templates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
def event_auto_cancelled_notification(event_name, room_name):
return {
"title": "Event Auto cancelled.",
"message": f"An event {event_name} in {room_name} \
has been auto cancelled."
}
19 changes: 19 additions & 0 deletions admin_notifications/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from sqlalchemy import (Column, String, Enum, Integer, ForeignKey)
from helpers.database import Base
from utilities.utility import Utility, StatusType


class AdminNotification(Base, Utility):
__tablename__ = 'admin_notifications'

id = Column(Integer, primary_key=True) # noqa
title = Column(String, nullable=True)
message = Column(String, nullable=True)
date_received = Column(String, nullable=True)
date_read = Column(String, nullable=True)
status = Column(Enum(StatusType), default="unread")
location_id = Column(
Integer,
ForeignKey('locations.id', ondelete="CASCADE"),
nullable=True
)
67 changes: 67 additions & 0 deletions admin_notifications/schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import graphene
from graphene_sqlalchemy import SQLAlchemyObjectType
from graphql import GraphQLError
from helpers.auth.authentication import Auth
from datetime import datetime
from admin_notifications.models import AdminNotification as \
AdminNotificationModel


class AdminNotifications(SQLAlchemyObjectType):
"""
Returns the admin_notificationspayload
"""
class Meta:
model = AdminNotificationModel


class NotificationsList(graphene.ObjectType):
"""
Class to return the types for Admin notifications
\n- rooms: The rooms data
"""
notifications = graphene.List(AdminNotifications)


class Query(graphene.ObjectType):
all_unread_notifications = graphene.Field(
NotificationsList,
description="Returns a list of admin notifications"
)

@Auth.user_roles('Admin')
def resolve_all_unread_notifications(self, info):
query = AdminNotifications.get_query(info)
notifications = query.filter(
AdminNotificationModel.status == "unread").all()
return NotificationsList(notifications=notifications)


class UpdateNotificationStatus(graphene.Mutation):
"""
Class to update the status of a notification
"""

class Arguments:
notification_id = graphene.Int(required=True)
notification = graphene.Field(AdminNotifications)

@Auth.user_roles('Admin')
def mutate(self, info, notification_id):
query = AdminNotifications.get_query(info)
unread_notifications = query.filter(
AdminNotificationModel.status == "unread")
notification = unread_notifications.filter(
AdminNotificationModel.id == notification_id).first()
if not notification:
raise GraphQLError("Notification is already read or not found.")
notification.status = "read"
notification.date_read = datetime.now()
notification.save()
return UpdateNotificationStatus(notification=notification)


class Mutation(graphene.ObjectType):
update_notification_status = UpdateNotificationStatus.Field(
description="Updates the status of a notification and takes the argument\
\n- notification_id: The name of the room[required]")
2 changes: 1 addition & 1 deletion alembic/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
from api.response.models import Response
from api.tag.models import Tag
from api.structure.models import Structure

from admin_notifications.models import AdminNotification

target_metadata = Base.metadata

Expand Down
39 changes: 39 additions & 0 deletions alembic/versions/f0873fb8edb3_add_admin_notifications_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""add admin notifications table

Revision ID: f0873fb8edb3
Revises: 50173cb0491f
Create Date: 2019-06-27 13:31:19.694650

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'f0873fb8edb3'
down_revision = '50173cb0491f'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.execute('DROP TYPE statustype;')
op.create_table('admin_notifications',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('title', sa.String(), nullable=True),
sa.Column('message', sa.String(), nullable=True),
sa.Column('date_received', sa.String(), nullable=True),
sa.Column('date_read', sa.String(), nullable=True),
sa.Column('status', sa.Enum('read', 'unread', name='statustype'), nullable=True),
sa.Column('location_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['location_id'], ['locations.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('admin_notifications')
# ### end Alembic commands ###
2 changes: 1 addition & 1 deletion api/devices/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

class Devices(Base, Utility):
__tablename__ = 'devices'
id = Column(Integer, Sequence('devices_id_seq', start=1, increment=1), primary_key=True) # noqa
id = Column(Integer, Sequence('devices_id_seq', start=1, increment=1), primary_key=True) # noqa
name = Column(String, nullable=False)
device_type = Column(String, nullable=False)
date_added = Column(DateTime, nullable=False)
Expand Down
1 change: 0 additions & 1 deletion app.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from healthcheck_schema import healthcheck_schema
from helpers.auth.authentication import Auth
from api.analytics.analytics_request import AnalyticsRequest

mail = Mail()


Expand Down
16 changes: 13 additions & 3 deletions cworker.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import os

from celery import Celery
from app import create_app


app = create_app(os.getenv('APP_SETTINGS') or 'default')
app.app_context().push()


app.config.update(
CELERY_BROKER_URL=os.getenv('CELERY_BROKER_URL'),
CELERY_RESULT_BACKEND=os.getenv('CELERY_RESULT_BACKEND'),
CELERY_ACCEPT_CONTENT=['pickle']
)


def make_celery(app):
celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'], include=['admin_notifications.helpers.create_notification'], # noqa 501
backend=app.config['CELERY_BROKER_URL'])

celery.conf.update(app.config)
celery.conf.enable_utc = False
TaskBase = celery.Task

class ContextTask(TaskBase):
Expand All @@ -24,3 +32,5 @@ def __call__(self, *args, **kwargs):


celery = make_celery(app)
celery_scheduler = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery_scheduler.conf.update(app.config)
Empty file.
53 changes: 53 additions & 0 deletions fixtures/admin_notification/admin_notification_fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
null = None

get_all_unread_notifications = '''
query {
allUnreadNotifications{
notifications {
title
message
id
}
}
}
'''

get_all_unread_notifications_response = {
"data": {
"allUnreadNotifications": {
"notifications": []
}
}
}

change_notification_status_unexistent_id = '''
mutation {
updateNotificationStatus(notificationId: 260){
notification {
id
title
message
}
}
}
'''

change_notification_status_unexistent_id_response = {
"errors": [
{
"message": "Notification is already read or not found.",
"locations": [
{
"line": 3,
"column": 3
}
],
"path": [
"updateNotificationStatus"
]
}
],
"data": {
"updateNotificationStatus": null
}
}
2 changes: 1 addition & 1 deletion helpers/email/email_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def __init__(
html=self.template,
sender=self.sender)

@celery.task
@celery.task(name='asynchronous-email-notifications')
def send_async_email(msg_dict):
mail = Mail()
msg = Message()
Expand Down
11 changes: 9 additions & 2 deletions manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import bugsnag
from flask_script import Manager, Shell
from bugsnag.flask import handle_exceptions

from flask_socketio import SocketIO

# Configure bugnsag
bugsnag.configure(
Expand All @@ -18,16 +18,23 @@
app = create_app(os.getenv('APP_SETTINGS') or 'default')
handle_exceptions(app)
manager = Manager(app)
socketio = SocketIO(app)


def make_shell_context():
return dict(app=app)


@socketio.on('message')
def hanldleMessage(msg):
from admin_notifications.socket_handler import send_notifications
return send_notifications()


manager.add_command(
"shell", Shell(
make_context=make_shell_context))


if __name__ == '__main__':
socketio.run(app, debug=True)
manager.run()
Loading