diff --git a/team-checkin-app/.gitignore b/team-checkin-app/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/team-checkin-app/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/team-checkin-app/LICENSE b/team-checkin-app/LICENSE new file mode 100644 index 0000000..77a8049 --- /dev/null +++ b/team-checkin-app/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 pavan-elisetty + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/team-checkin-app/Procfile b/team-checkin-app/Procfile new file mode 100644 index 0000000..645733f --- /dev/null +++ b/team-checkin-app/Procfile @@ -0,0 +1 @@ +web: sh setup.sh && streamlit run app.py \ No newline at end of file diff --git a/team-checkin-app/README.md b/team-checkin-app/README.md new file mode 100644 index 0000000..f206b70 --- /dev/null +++ b/team-checkin-app/README.md @@ -0,0 +1,50 @@ +# A *simple* team attendence/checkin application + +- This repository consists the python code that is used to build. +- It is developed with streamlit. +- Hosted on heroku for temp deployment + +## Application description : + - Application is used to enter and maintain the log of the team members. + - This also produce a general stats for that week + - Every team member is assigned a unique passphrase (just like password) , only with that particular passphrase , the member can checkin. + - This makes it difficult for doing proxy + +## Functionality : + - The `record.csv` is used to maintain the entire log of team members + - `week_log.csv` is used to maintain log of a particular week and will be recycled for every weekend. + - `app.py` is the main functional app + - `data.csv` contains the user details and pass phrases . (*this can be hidden or make the repo private*) + - `Procfile`,`setup.sh` is used for the deployment + - *all the remaining files are support files* + +## ScreenShots : +LightMode +![lightmode](https://github.com/pavan-elisetty/team-checkin-app/blob/main/images/1.jpg) +DarkMode +![DarkMode](https://github.com/pavan-elisetty/team-checkin-app/blob/main/images/2.jpg) + +## Deployment : +[app](https://team-checkin-application.herokuapp.com/) + +### Steps to Run the app: + +1. Create a python virtual environment and activate it: + ``` + python3 -m venv app + source app/bin/activate + ``` +2. Install the required libraries: + ``` + pip install -r requirements.txt + ``` +3. Run the app: + ``` + streamlit run app.py + ``` + *app runs on the local server* + +4. Enter `CTRL+C` once you are done. + + +[MIT License](https://github.com/pavan-elisetty/team-checkin-app/blob/main/LICENSE) diff --git a/team-checkin-app/app.py b/team-checkin-app/app.py new file mode 100644 index 0000000..30f4221 --- /dev/null +++ b/team-checkin-app/app.py @@ -0,0 +1,190 @@ +import streamlit as st +import pandas as pd +import base64 +import os +import datetime +import sqlalchemy as sa +from pathlib import Path +import psycopg2 + +#creating sql alchemy engine +engine = sa.create_engine('',echo=False) #add your heroku postgres url +def check_if_weekend(today): + try: + isinstance(today, datetime.datetime) + upper_limit = today + datetime.timedelta(days=(6 - today.weekday())) + lower_limit = today + datetime.timedelta(days=(5 - today.weekday())) + if today >= lower_limit <= upper_limit: + return True + else: + return False + except ValueError: + pass + + +today_date = datetime.datetime.today() +weekend = check_if_weekend(today_date) + + +if weekend==True: + os.remove('week_log.csv') + try: + engine.execute('DROP TABLE table2') + except: + pass + new_week_log = pd.DataFrame(columns=['Name', 'Time', 'Days', 'Hours', 'Reason', 'Team'],index=None) + new_week_log.to_csv('week_log.csv', mode='w', header=True,index=None) + new_week_log.to_sql('table2',con=engine,index=False,index_label=None,if_exists='replace') +else: + try: + new_week_log=pd.read_sql('table2',con=engine,index_col=None) + except: + new_week_log = pd.DataFrame(columns=['Name', 'Time', 'Days', 'Hours', 'Reason', 'Team']) + new_week_log.to_sql('table2', con=engine, index=False, index_label=None, if_exists='replace') + new_week_log = pd.read_sql('table2', con=engine, index_col=None) + + +st.title('Work Checkin System') + +st.sidebar.image('logo.jpg') +st.sidebar.markdown(""" + ***XYZ Team*** +""") + +data=pd.read_csv('data.csv',header=[0]) +if os.path.exists('record.csv'): + try: + record=pd.read_sql('table1',con=engine,index_col=None) + except: + record=pd.read_csv('record.csv',index_col=None) + record.to_sql('table1',con=engine,index=False,index_label=None,if_exists='append') +else: + record = pd.DataFrame(columns=['Name', 'Time', 'Days', 'Hours', 'Reason', 'Team'],index=None) + record.to_csv('record.csv', mode='w', header=True,index=None) + record.to_sql('table1',con=engine,index=False,index_label=None,if_exists='replace') +st.write(record) +#st.write(pd.read_sql('table1',con=engine,index_col=None)) + +days=['mon','tue','wed','thurs','fri','sat','sun'] +teams=['Development','PR','management'] +st.warning('Avoid duplication, ignore if not applicable') +st.error('During the time of weekend it will reset itself and you wont be able to do any changes , dont checkin during the weekends') + + +def input_values(): + data2 = pd.read_csv('data.csv', header=[0]) + + if st.sidebar.checkbox('Work for this week'): + selected_name = st.sidebar.selectbox('Name', options=data['Members']) + days_selected=st.sidebar.multiselect('Days free to work',options=days) + hours=st.sidebar.slider('No.of hours per week will be able to work',1.0,1.0,8.0) + team_willing=st.sidebar.multiselect('Team willing to work in',options=teams) + password=str(st.sidebar.text_input('enter the passphrase')).lower() + + if st.sidebar.button('Submit details'): + y=data2.loc[data2.Members == str(selected_name)] + z=y.iloc[:,-1].values + if password==str(z[0]): + st.balloons() + input_data={ + 'Name':[str(selected_name)], + 'Time':[str(datetime.datetime.today())], + 'Days':[str(days_selected)], + 'Hours':[str(hours)], + 'Reason':['None'], + 'Team':[str(team_willing)] + } + input_df=pd.DataFrame(input_data) + input_df.to_csv('record.csv', mode='a', header=False,index=None) + input_df.to_sql('table1',if_exists='append',con=engine,index=False,index_label=None) + record_changed = pd.read_sql('table1',con=engine,index_col=None) + record_reverse = record_changed.iloc[::-1] + st.subheader('Continous Log') + st.write(record_reverse.head()) + input_df.to_csv('week_log.csv', mode='a', header=False,index=None) + input_df.to_sql('table2', if_exists='append', con=engine, index=False, index_label=None) + record_changed_wl = pd.read_sql('table2',con=engine,index_col=None) + record_reverse_wl = record_changed_wl.iloc[::-1] + st.subheader('Weekly Log') + st.write(record_reverse_wl.head()) + else: + st.sidebar.warning('Wrong passphrase') + elif st.sidebar.checkbox('Cannot Work this week'): + selected_name = st.sidebar.selectbox('Name', options=data['Members']) + reason=st.sidebar.text_input('Reason') + password = str(st.sidebar.text_input('enter the passphrase')).lower() + if st.sidebar.button('Submit details'): + y = data2.loc[data2.Members == str(selected_name)] + z = y.iloc[:, -1].values + if password == str(z[0]): + st.balloons() + input_data={ + 'Name':[str(selected_name)], + 'Time':[str(datetime.datetime.today())], + 'Days':['None'], + 'Hours':0, + 'Reason':[str(reason)], + 'Team':['None'] + } + input_df=pd.DataFrame(input_data) + input_df.to_csv('record.csv', mode='a', header=False,index=None) + input_df.to_sql('table1', if_exists='append', con=engine, index=False, index_label=None) + record_changed = pd.read_sql('table1',con=engine,index_col=None) + record_reverse=record_changed.iloc[::-1] + st.subheader('Continous Log') + st.write(record_reverse.head()) + input_df.to_csv('week_log.csv', mode='a', header=False,index=None) + input_df.to_sql('table2', if_exists='append', con=engine, index=False, index_label=None) + record_changed_wl = pd.read_sql('table2',con=engine,index_col=None) + record_reverse_wl = record_changed_wl.iloc[::-1] + st.subheader('Weekly Log') + st.write(record_reverse_wl.head()) + else: + st.sidebar.warning('Wrong passphrase') + +input_values() # input values function + +def filedownload(): + log=pd.read_sql('table1',con=engine,index_col=None) + csv = log.to_csv(index=False) + b64 = base64.b64encode(csv.encode()).decode() # strings <-> bytes conversions + href = f'Download Team entire Log File' + return href + +def filedownload_week(): + log=pd.read_sql('table2',con=engine,index_col=None) + csv = log.to_csv(index=False) + b64 = base64.b64encode(csv.encode()).decode() # strings <-> bytes conversions + href = f'Download Team week Log File' + return href + +new_log_df=pd.read_sql('table2',con=engine,index_col=None) +people_data=data.copy() + + +st.write('Total no.of work hours reported {}'.format(new_log_df['Hours'].sum())) + +col1,col2,col3=st.beta_columns(3) +with col1: + st.header('Team updated') + unique_names=new_log_df['Name'].unique() + st.write(unique_names) +with col2: + st.header('Team Not updated') + name1 = set(new_log_df['Name']) + name2 = set(people_data['Members']) + diff = sorted(name2 - name1) + st.write(pd.DataFrame(diff)) +with col3: + data={ + 'Updated':new_log_df['Name'].nunique(), + 'Not-Updated':people_data['Members'].nunique()-new_log_df['Name'].nunique() + } + st.header('Comparision between updation for current week') + st.bar_chart(data=pd.DataFrame(data,index=[0]),use_container_width=True) + bar_df=pd.DataFrame(data,index=[0]) + + +st.markdown(filedownload_week(), unsafe_allow_html=True) + +st.markdown(filedownload(), unsafe_allow_html=True) diff --git a/team-checkin-app/data.csv b/team-checkin-app/data.csv new file mode 100644 index 0000000..e1f0442 --- /dev/null +++ b/team-checkin-app/data.csv @@ -0,0 +1,5 @@ +Members,Phrase +one,charlie +two,gamma +three,beta +four,delta diff --git a/team-checkin-app/images/1.jpg b/team-checkin-app/images/1.jpg new file mode 100644 index 0000000..5c8c696 Binary files /dev/null and b/team-checkin-app/images/1.jpg differ diff --git a/team-checkin-app/images/2.jpg b/team-checkin-app/images/2.jpg new file mode 100644 index 0000000..8d0bd63 Binary files /dev/null and b/team-checkin-app/images/2.jpg differ diff --git a/team-checkin-app/logo.jpg b/team-checkin-app/logo.jpg new file mode 100644 index 0000000..214f2c5 Binary files /dev/null and b/team-checkin-app/logo.jpg differ diff --git a/team-checkin-app/record.csv b/team-checkin-app/record.csv new file mode 100644 index 0000000..60e452c --- /dev/null +++ b/team-checkin-app/record.csv @@ -0,0 +1 @@ +Name,Time,Days,Hours,Reason,Team diff --git a/team-checkin-app/requirements.txt b/team-checkin-app/requirements.txt new file mode 100644 index 0000000..27772af --- /dev/null +++ b/team-checkin-app/requirements.txt @@ -0,0 +1,6 @@ +streamlit +pandas +base58 +datetime +psycopg2 +SQLAlchemy diff --git a/team-checkin-app/setup.sh b/team-checkin-app/setup.sh new file mode 100644 index 0000000..d39033d --- /dev/null +++ b/team-checkin-app/setup.sh @@ -0,0 +1,9 @@ +mkdir -p ~/.streamlit/ + +echo "\ +[server]\n\ +port = $PORT\n\ +enableCORS = false\n\ +headless = true\n\ +\n\ +" > ~/.streamlit/config.toml \ No newline at end of file diff --git a/team-checkin-app/week_log.csv b/team-checkin-app/week_log.csv new file mode 100644 index 0000000..60e452c --- /dev/null +++ b/team-checkin-app/week_log.csv @@ -0,0 +1 @@ +Name,Time,Days,Hours,Reason,Team