Skip to content

Commit

Permalink
* Added a help page
Browse files Browse the repository at this point in the history
  • Loading branch information
korsakovs committed Jan 15, 2024
1 parent 3235c0b commit 94a3ef2
Show file tree
Hide file tree
Showing 18 changed files with 334 additions and 21 deletions.
6 changes: 3 additions & 3 deletions docker/docker-compose.common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ services:
volumes:
- "merci_bot_volume:/nginx_sockets"

pgadmin:
merci-pgadmin:
container_name: merci-pgadmin
depends_on:
- merci-postgres
Expand All @@ -67,8 +67,8 @@ services:
PGADMIN_DEFAULT_EMAIL: test@gmail.com
PGADMIN_DEFAULT_PASSWORD: postgres
PGADMIN_CONFIG_SERVER_MODE: "False"
ports:
- "5433:80"
# ports:
# - "5433:80"
networks:
- wwf_network

Expand Down
16 changes: 15 additions & 1 deletion docker/docker-compose.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,21 @@ services:
- merci-bot
restart: always

pgadmin:
merci-pgadmin:
environment:
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}

merci-pgadmin-nginx:
container_name: merci-pgadmin-nginx
image: pgadmin-nginx
build:
context: ..
dockerfile: docker/pgadmin-nginx/pgadmin-nginx.Dockerfile
# expose:
# - "5433"
depends_on:
- merci-pgadmin
restart: always
networks:
- wwf_network
1 change: 1 addition & 0 deletions docker/pgadmin-nginx/.htpasswd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
postgres:$apr1$bxjseg8r$v2qBpyoTODV/55oRc6CHV1
64 changes: 64 additions & 0 deletions docker/pgadmin-nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
##
# Basic Settings
##

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;

# server_names_hash_bucket_size 64;
# server_name_in_redirect off;

include /etc/nginx/mime.types;
default_type application/octet-stream;

##
# SSL Settings
##

ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;

##
# Logging Settings
##

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

##
# Gzip Settings
##

gzip on;

# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

##
# Virtual Host Configs
##

include /etc/nginx/sites-enabled/*;
}
13 changes: 13 additions & 0 deletions docker/pgadmin-nginx/pgadmin-nginx.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM nginx:latest

WORKDIR /usr/share/nginx/html
RUN rm -rf ./*

RUN mkdir -p /etc/nginx/sites-available
RUN mkdir -p /etc/nginx/sites-enabled
COPY ./docker/pgadmin-nginx/nginx.conf /etc/nginx/
COPY ./docker/pgadmin-nginx/.htpasswd /etc/nginx/
COPY ./docker/pgadmin-nginx/sites/pgadmin /etc/nginx/sites-available/
RUN ln -s /etc/nginx/sites-available/pgadmin /etc/nginx/sites-enabled/pgadmin

CMD ["nginx", "-g", "daemon off;"]
20 changes: 20 additions & 0 deletions docker/pgadmin-nginx/sites/pgadmin
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
server {
listen 5433;
server_name merci.emgbook.com;

# set DNS resolver as Docker internal DNS
resolver 127.0.0.11 valid=10s;
resolver_timeout 5s;

location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP ip_address;

auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;

client_body_buffer_size 32k;

proxy_pass http://merci-pgadmin:80;
}
}
10 changes: 10 additions & 0 deletions thankyou/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,13 @@ class ThankYouStats:
leader_slack_user_id: Slack_User_ID_Type
leader_slack_messages_num: int
total_messages_num: int


@dataclass
class Employee:
slack_user_id: Slack_User_ID_Type
company_uuid: UUID_Type

closed_welcome_message: bool = False

uuid: UUID_Type = field(default_factory=lambda: str(uuid.uuid4()))
10 changes: 9 additions & 1 deletion thankyou/dao/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

from typing import List, Optional, Tuple

from thankyou.core.models import Company, ThankYouMessage, ThankYouType, Slack_User_ID_Type, CompanyAdmin
from thankyou.core.models import Company, ThankYouMessage, ThankYouType, Slack_User_ID_Type, CompanyAdmin, Employee, \
UUID_Type


class Dao(ABC):
Expand Down Expand Up @@ -72,4 +73,11 @@ def get_thank_you_receiver_leaders(self, company_uuid: str, created_after: datet
created_before: datetime = None, thank_you_type: ThankYouType = None,
leaders_num: int = 3) -> List[Tuple[Slack_User_ID_Type, int]]: ...

def create_employee(self, employee: Employee): ...

def read_employee(self, company_uuid: UUID_Type, uuid: UUID_Type) -> Optional[Employee]: ...

def read_employee_by_slack_id(self, company_uuid: UUID_Type, slack_user_id: Slack_User_ID_Type) \
-> Optional[Employee]: ...

def on_app_error(self, error): ...
7 changes: 4 additions & 3 deletions thankyou/dao/postres.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from sqlalchemy import Engine, create_engine

from thankyou.core.config import get_env, Env
from thankyou.dao.sqlalchemy import SQLAlchemyDao


class PostgresDao(SQLAlchemyDao):
def __init__(self, host: str, database: str, user: str, password: str, port: int = 5432,
encryption_secret_key: str = None):
encryption_secret_key: str = None, echo: bool = False):
self.conn_string = f"postgresql://{user}:{password}@{host}:{port}/{database}"
super().__init__(encryption_secret_key=encryption_secret_key)
super().__init__(encryption_secret_key=encryption_secret_key, echo=echo)

def _create_engine(self) -> Engine:
return create_engine(self.conn_string)
return create_engine(self.conn_string, echo=self.echo, pool_recycle=3600, pool_timeout=20)
42 changes: 38 additions & 4 deletions thankyou/dao/sqlalchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
from typing import List, Optional, Generator, Tuple

from sqlalchemy import Engine, MetaData, Column, Table, String, ForeignKey, Boolean, Text, DateTime, or_, desc, \
and_, func, Integer, Enum, false
and_, func, Integer, Enum, false, UniqueConstraint
from sqlalchemy.exc import PendingRollbackError
from sqlalchemy.orm import registry, relationship, sessionmaker, Session
from sqlalchemy_utils import StringEncryptedType
from sqlalchemy_utils.types.encrypted.encrypted_type import AesEngine

from thankyou.core.models import ThankYouType, Company, ThankYouMessage, ThankYouReceiver, \
ThankYouMessageImage, Slack_User_ID_Type, CompanyAdmin, LeaderbordTimeSettings
ThankYouMessageImage, Slack_User_ID_Type, CompanyAdmin, LeaderbordTimeSettings, UUID_Type, Employee
from thankyou.dao.interface import Dao


Expand All @@ -23,6 +23,7 @@ class SQLAlchemyDao(Dao, ABC):
_THANK_YOU_TYPES_TABLE = "thank_you_types"
_THANK_YOU_RECEIVERS_TABLE = "thank_you_receivers"
_THANK_YOU_MESSAGE_IMAGES = "thank_you_message_images"
_EMPLOYEES_TABLE = "employees"

@abstractmethod
def _create_engine(self) -> Engine:
Expand All @@ -38,11 +39,13 @@ def encrypted_string_column(self, length: int):
return String(length)
return StringEncryptedType(String(length), key=self.secret_key, engine=AesEngine)

def __init__(self, encryption_secret_key: str = None):
def __init__(self, encryption_secret_key: str = None, echo: bool = False):
super().__init__(
encryption_secret_key=encryption_secret_key
)

self.echo = echo

self._mapper_registry = registry()
self._metadata_obj = MetaData()

Expand Down Expand Up @@ -119,6 +122,16 @@ def __init__(self, encryption_secret_key: str = None):
Column("ordering_key", Integer, nullable=False),
)

self._employees_table = Table(
self._EMPLOYEES_TABLE,
self._metadata_obj,
Column("uuid", String(256), primary_key=True, nullable=False),
Column("company_uuid", String(256), ForeignKey(f"{self._COMPANIES_TABLE}.uuid"), nullable=False),
Column("slack_user_id", String(256), nullable=False, index=True),
Column("closed_welcome_message", Boolean, nullable=False),
UniqueConstraint('company_uuid', 'slack_user_id', name='uix_employees__company__slack_user_id')
)

self._mapper_registry.map_imperatively(CompanyAdmin, self._company_admins_table)

self._mapper_registry.map_imperatively(Company, self._companies_table, properties={
Expand All @@ -142,6 +155,7 @@ def __init__(self, encryption_secret_key: str = None):

self._mapper_registry.map_imperatively(ThankYouReceiver, self._thank_you_receivers_table)
self._mapper_registry.map_imperatively(ThankYouMessageImage, self._thank_you_message_images_table)
self._mapper_registry.map_imperatively(Employee, self._employees_table)

self._engine = self._create_engine()
try:
Expand Down Expand Up @@ -374,12 +388,32 @@ def get_thank_you_receiver_leaders(self, company_uuid: str, created_after: datet

return result.all()

def create_employee(self, employee: Employee):
self._set_obj(employee)

def read_employee(self, company_uuid: UUID_Type, uuid: UUID_Type) -> Optional[Employee]:
employee: Employee = self._get_obj(Employee, uuid)
if employee and employee.company_uuid == company_uuid:
return employee

def read_employee_by_slack_id(self, company_uuid: UUID_Type, slack_user_id: Slack_User_ID_Type) \
-> Optional[Employee]:
with self._get_session() as session:
result: List[Employee] = session.query(Employee).filter(Employee.slack_user_id == slack_user_id).all()
if len(result) > 1:
raise ValueError("There are multiple companies with the same slack_user_id value")
try:
return result[0]
except IndexError:
pass

def on_app_error(self, error):
logging.error(f"An App error occurred: {error}")
if isinstance(error, PendingRollbackError) or isinstance(error, BrokenPipeError):
logging.info("Rolling back the session...")
try:
self._session.rollback()
# self._session.rollback()
pass
except Exception as e:
logging.error(f"Can not roll back the session: {e}")
else:
Expand Down
3 changes: 2 additions & 1 deletion thankyou/dao/sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from sqlalchemy import Engine, create_engine, NullPool

from thankyou.core.config import get_env, Env
from thankyou.dao.sqlalchemy import SQLAlchemyDao


Expand All @@ -22,4 +23,4 @@ def _db_file(self):
def _create_engine(self) -> Engine:
if not os.path.isdir(self._db_folder):
os.mkdir(self._db_folder)
return create_engine(f"sqlite:///{self._db_file}", echo=False, poolclass=NullPool)
return create_engine(f"sqlite:///{self._db_file}", echo=self.echo, poolclass=NullPool)
42 changes: 41 additions & 1 deletion thankyou/slackbot/blocks/homepage.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import List, Optional, Tuple

from slack_sdk.models.blocks import ButtonElement, ActionsBlock, SectionBlock, HeaderBlock, DividerBlock, TextObject, \
ContextBlock
ContextBlock, Block, ConfirmObject

from thankyou.core.models import ThankYouMessage, ThankYouType, Slack_User_ID_Type
from thankyou.slackbot.blocks.thank_you import thank_you_message_blocks
Expand All @@ -25,6 +25,11 @@ def home_page_actions_block(selected: str = "my_updates") -> ActionsBlock:
style="primary" if selected == "my_thank_yous" else None,
action_id="home_page_my_thank_you_button_clicked"
),
ButtonElement(
text="Help",
style="primary" if selected == "help" else None,
action_id="home_page_help_button_clicked"
),
ButtonElement(
text="Configuration",
style="primary" if selected == "configuration" else None,
Expand All @@ -35,6 +40,41 @@ def home_page_actions_block(selected: str = "my_updates") -> ActionsBlock:
return ActionsBlock(elements=elements)


def home_page_welcome_blocks() -> List[Block]:
return [
HeaderBlock(text="Welcome to the Merci! application"),
SectionBlock(
text="Recognizing and appreciating your team is a cornerstone of a motivated workforce. "
"The Merci! Slack application provides a seamless way for you and your colleagues to express "
"gratitude and foster a positive workplace culture."
),
SectionBlock(
text="Have you already tried sending a thank you message? If not, click on the \"Say Thank you!\" button "
"and send a couple of warm words to your colleague(s)!"
),
SectionBlock(
text=TextObject(
type="mrkdwn",
text="In case you want your message to appear in a a specific team channel, open this channel and "
"simpy send a `/merci` command"
),
),
ActionsBlock(
elements=[
ButtonElement(
text="Hide this message",
action_id="home_page_hide_welcome_message_button_clicked",
confirm=ConfirmObject(
title="Are you sure?",
text="Are you sure you want to hide this text? "
"If you need help, you can check the \"Help\" tab"
)
)
]
),
]


def home_page_show_leaders_button_block() -> ActionsBlock:
return ActionsBlock(
elements=[
Expand Down
Loading

0 comments on commit 94a3ef2

Please sign in to comment.