Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #1

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
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
99 changes: 99 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# IT Team Task Manager

## How to install

1) Open Terminal and open folder to clone project in.

2) Clone repository into a desirable folder:

```
git clone https://github.com/mykolamateichuk/it-company-task-manager.git
```

3) Open cloned folder in terminal

4) If you don't have **pip** installed [install it here](https://pip.pypa.io/en/stable/installation/#).

5) Create and activate **Virtual environment**:

**Windows**
```
python -m venv venv
```

```
venv\Scripts\activate
```

**MacOS**
```
python3 -m venv venv
```

```
source venv/bin/activate
```

6) Open cloned folder and install needed requirements using:

```
pip install -r requirements.txt
```

7) Make migrations and migrate:

```
python manage.py makemigrations
```
```
python manage.py migrate
```

8) Install database fixture:

```
python manage.py loaddata db_fixture.json
```

9) Run server:

```
python manage.py runserver
```

10) Go to [http://127.0.0.1:8000/](http://127.0.0.1:8000/)


## How does it work

This task manager is built for _a small team of developers who want to manage
their workflow properly_.

To access the page first you want to [register](http://127.0.0.1:8000/create-account/) yourself.

Then you will be redirected onto the [main page](http://127.0.0.1:8000/), where
you will see all of your **tasks**.

Tasks that have not been completed yet have a red border, tasks that have been - green.
Tasks have a detailed view that is accessible by clicking on the specific task card.
In this detailed view you can see all information about the task and also **Update** it,
**Delete** it, or **Mark as Done**.

Any member of the team can create tasks and assign them to other members or themselves.
To create a task click on the green button in the top part of the screen, and
you will be redirected to the [task creation form](http://127.0.0.1:8000/create-task/).

On the left of the page you will see a sidebar that can redirect you to
[Team](http://127.0.0.1:8000/worker-list/) page that has information about everyone
on your team. To see their progress in solving tasks you can click on the username
of a specific user and see how many tasks are still due for them.

Also you can filter the list of your teammates by their **position**.

The second page where sidebar can take you to, is [Deadlines](http://127.0.0.1:8000/deadlines/).
Deadlines is a page that has a compact view on all of your tasks and can help you
with deciding whick task to do next.

## Database Schema

![db_schema.png](db_schema.png)
1 change: 1 addition & 0 deletions db_fixture.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"model": "auth.permission", "pk": 1, "fields": {"name": "Can add log entry", "content_type": 1, "codename": "add_logentry"}}, {"model": "auth.permission", "pk": 2, "fields": {"name": "Can change log entry", "content_type": 1, "codename": "change_logentry"}}, {"model": "auth.permission", "pk": 3, "fields": {"name": "Can delete log entry", "content_type": 1, "codename": "delete_logentry"}}, {"model": "auth.permission", "pk": 4, "fields": {"name": "Can view log entry", "content_type": 1, "codename": "view_logentry"}}, {"model": "auth.permission", "pk": 5, "fields": {"name": "Can add permission", "content_type": 2, "codename": "add_permission"}}, {"model": "auth.permission", "pk": 6, "fields": {"name": "Can change permission", "content_type": 2, "codename": "change_permission"}}, {"model": "auth.permission", "pk": 7, "fields": {"name": "Can delete permission", "content_type": 2, "codename": "delete_permission"}}, {"model": "auth.permission", "pk": 8, "fields": {"name": "Can view permission", "content_type": 2, "codename": "view_permission"}}, {"model": "auth.permission", "pk": 9, "fields": {"name": "Can add group", "content_type": 3, "codename": "add_group"}}, {"model": "auth.permission", "pk": 10, "fields": {"name": "Can change group", "content_type": 3, "codename": "change_group"}}, {"model": "auth.permission", "pk": 11, "fields": {"name": "Can delete group", "content_type": 3, "codename": "delete_group"}}, {"model": "auth.permission", "pk": 12, "fields": {"name": "Can view group", "content_type": 3, "codename": "view_group"}}, {"model": "auth.permission", "pk": 13, "fields": {"name": "Can add content type", "content_type": 4, "codename": "add_contenttype"}}, {"model": "auth.permission", "pk": 14, "fields": {"name": "Can change content type", "content_type": 4, "codename": "change_contenttype"}}, {"model": "auth.permission", "pk": 15, "fields": {"name": "Can delete content type", "content_type": 4, "codename": "delete_contenttype"}}, {"model": "auth.permission", "pk": 16, "fields": {"name": "Can view content type", "content_type": 4, "codename": "view_contenttype"}}, {"model": "auth.permission", "pk": 17, "fields": {"name": "Can add session", "content_type": 5, "codename": "add_session"}}, {"model": "auth.permission", "pk": 18, "fields": {"name": "Can change session", "content_type": 5, "codename": "change_session"}}, {"model": "auth.permission", "pk": 19, "fields": {"name": "Can delete session", "content_type": 5, "codename": "delete_session"}}, {"model": "auth.permission", "pk": 20, "fields": {"name": "Can view session", "content_type": 5, "codename": "view_session"}}, {"model": "auth.permission", "pk": 21, "fields": {"name": "Can add worker", "content_type": 6, "codename": "add_worker"}}, {"model": "auth.permission", "pk": 22, "fields": {"name": "Can change worker", "content_type": 6, "codename": "change_worker"}}, {"model": "auth.permission", "pk": 23, "fields": {"name": "Can delete worker", "content_type": 6, "codename": "delete_worker"}}, {"model": "auth.permission", "pk": 24, "fields": {"name": "Can view worker", "content_type": 6, "codename": "view_worker"}}, {"model": "auth.permission", "pk": 25, "fields": {"name": "Can add position", "content_type": 7, "codename": "add_position"}}, {"model": "auth.permission", "pk": 26, "fields": {"name": "Can change position", "content_type": 7, "codename": "change_position"}}, {"model": "auth.permission", "pk": 27, "fields": {"name": "Can delete position", "content_type": 7, "codename": "delete_position"}}, {"model": "auth.permission", "pk": 28, "fields": {"name": "Can view position", "content_type": 7, "codename": "view_position"}}, {"model": "auth.permission", "pk": 29, "fields": {"name": "Can add task type", "content_type": 8, "codename": "add_tasktype"}}, {"model": "auth.permission", "pk": 30, "fields": {"name": "Can change task type", "content_type": 8, "codename": "change_tasktype"}}, {"model": "auth.permission", "pk": 31, "fields": {"name": "Can delete task type", "content_type": 8, "codename": "delete_tasktype"}}, {"model": "auth.permission", "pk": 32, "fields": {"name": "Can view task type", "content_type": 8, "codename": "view_tasktype"}}, {"model": "auth.permission", "pk": 33, "fields": {"name": "Can add task", "content_type": 9, "codename": "add_task"}}, {"model": "auth.permission", "pk": 34, "fields": {"name": "Can change task", "content_type": 9, "codename": "change_task"}}, {"model": "auth.permission", "pk": 35, "fields": {"name": "Can delete task", "content_type": 9, "codename": "delete_task"}}, {"model": "auth.permission", "pk": 36, "fields": {"name": "Can view task", "content_type": 9, "codename": "view_task"}}, {"model": "contenttypes.contenttype", "pk": 1, "fields": {"app_label": "admin", "model": "logentry"}}, {"model": "contenttypes.contenttype", "pk": 2, "fields": {"app_label": "auth", "model": "permission"}}, {"model": "contenttypes.contenttype", "pk": 3, "fields": {"app_label": "auth", "model": "group"}}, {"model": "contenttypes.contenttype", "pk": 4, "fields": {"app_label": "contenttypes", "model": "contenttype"}}, {"model": "contenttypes.contenttype", "pk": 5, "fields": {"app_label": "sessions", "model": "session"}}, {"model": "contenttypes.contenttype", "pk": 6, "fields": {"app_label": "task_manager", "model": "worker"}}, {"model": "contenttypes.contenttype", "pk": 7, "fields": {"app_label": "task_manager", "model": "position"}}, {"model": "contenttypes.contenttype", "pk": 8, "fields": {"app_label": "task_manager", "model": "tasktype"}}, {"model": "contenttypes.contenttype", "pk": 9, "fields": {"app_label": "task_manager", "model": "task"}}, {"model": "sessions.session", "pk": "kdjpenlxno7hu4c1jxzllzbk3ecibpje", "fields": {"session_data": ".eJxVjDsOwyAQBe9CHSHM3ynT-wxoYZfgJALJ2FWUu0dILpL2zcx7swDHXsLRaQsrsisz7PK7RUhPqgPgA-q98dTqvq2RD4WftPOlIb1up_t3UKCXUWcxK7IaDSnMJH1MymYPQCZJT17RlJ1N4N3kdYw4EwpnHWgwUUsp2OcLEB84oQ:1r6DrM:pIKUlXuUvimsRPEcdA_qP_lE_ZmPzH3Ad8JxZUnME3k", "expire_date": "2023-12-07T17:51:28.138Z"}}, {"model": "task_manager.tasktype", "pk": 1, "fields": {"name": "New Feature"}}, {"model": "task_manager.tasktype", "pk": 2, "fields": {"name": "Bug"}}, {"model": "task_manager.tasktype", "pk": 3, "fields": {"name": "Breaking change"}}, {"model": "task_manager.tasktype", "pk": 4, "fields": {"name": "Refactoring"}}, {"model": "task_manager.tasktype", "pk": 5, "fields": {"name": "QA"}}, {"model": "task_manager.position", "pk": 1, "fields": {"name": "Project Manager"}}, {"model": "task_manager.position", "pk": 2, "fields": {"name": "Developer"}}, {"model": "task_manager.position", "pk": 3, "fields": {"name": "Designer"}}, {"model": "task_manager.position", "pk": 4, "fields": {"name": "QA"}}, {"model": "task_manager.position", "pk": 5, "fields": {"name": "DevOps"}}, {"model": "task_manager.worker", "pk": 1, "fields": {"password": "pbkdf2_sha256$600000$HlTpCznvkkqF7eOx2CGKbg$X48bwwOrP3eU97t9gD5DCU4jmhtzf1FfkYRANKi197k=", "last_login": "2023-11-22T17:37:26.183Z", "is_superuser": false, "username": "mykolamateichuk", "first_name": "Mykola", "last_name": "Mateichuk", "email": "", "is_staff": false, "is_active": true, "date_joined": "2023-11-22T11:02:46.893Z", "position": 1, "groups": [], "user_permissions": []}}, {"model": "task_manager.worker", "pk": 2, "fields": {"password": "pbkdf2_sha256$600000$kQbnLMBlpcpZXYIfaNLPbj$dfDEAeIrhuBbgBA24yRHcF75+0KVtrGtRn22ZcTSwLI=", "last_login": "2023-11-23T17:49:22.626Z", "is_superuser": false, "username": "vasyapetrenko", "first_name": "Vasya", "last_name": "Petrenko", "email": "", "is_staff": false, "is_active": true, "date_joined": "2023-11-22T16:23:47.033Z", "position": 2, "groups": [], "user_permissions": []}}, {"model": "task_manager.worker", "pk": 3, "fields": {"password": "pbkdf2_sha256$600000$BCylJf8VlXgoGFCmqSvHPS$m3QwV7zjEybXXEz1+DvaPFuUeNyWVjLuUWANPvZ/gqY=", "last_login": null, "is_superuser": false, "username": "petrovasylenko", "first_name": "Petro", "last_name": "Vasylenko", "email": "", "is_staff": false, "is_active": true, "date_joined": "2023-11-22T16:30:12.788Z", "position": 3, "groups": [], "user_permissions": []}}, {"model": "task_manager.worker", "pk": 4, "fields": {"password": "pbkdf2_sha256$600000$0cJhhDTuviGb2Ze4V0tvVq$4wr2Sv+wGwDFfwJgmx0IXV1bzMIbMt6yEb07lEbx4Y8=", "last_login": "2023-11-23T17:50:37.009Z", "is_superuser": false, "username": "sanyaivaniuta", "first_name": "Sanya", "last_name": "Ivaniuta", "email": "", "is_staff": false, "is_active": true, "date_joined": "2023-11-22T16:32:01.580Z", "position": 4, "groups": [], "user_permissions": []}}, {"model": "task_manager.worker", "pk": 5, "fields": {"password": "pbkdf2_sha256$600000$cQ8GJL97nMJ435DHtRpWtV$NUyNgCHhVkERqH9BJcHo2uYp7goADKkTkvDlDxBCYFQ=", "last_login": "2023-11-23T17:51:28.133Z", "is_superuser": false, "username": "ivankazan", "first_name": "Ivan", "last_name": "Kazantsev", "email": "", "is_staff": false, "is_active": true, "date_joined": "2023-11-22T16:32:43.119Z", "position": 5, "groups": [], "user_permissions": []}}, {"model": "task_manager.task", "pk": 9, "fields": {"name": "Design a website header", "description": "Make a really nice and beautiful design of a website header.", "deadline": "2023-11-26", "is_completed": false, "task_type": 1, "assignees": [3]}}, {"model": "task_manager.task", "pk": 10, "fields": {"name": "Make an entire project from scratch", "description": "In crafting a revolutionary project, the team must first define a visionary goal, weaving together creativity and feasibility. Collaborative brainstorming should spawn innovative ideas, each member contributing unique perspectives. Rigorous planning, with an emphasis on adaptability, charts the course, ensuring milestones align with the overarching vision. Assembling a diverse team with complementary skills fosters a dynamic environment, fueling the project's evolution. Effective communication becomes the project's lifeblood, fostering cohesion and agility. Iterative development, fueled by feedback loops, hones the project's edge. Rigorous testing guarantees robustness, while continuous refinement ensures relevance. The team's commitment to excellence propels the project towards realization, as each member contributes their expertise, passion, and resilience to sculpt a transformative masterpiece.", "deadline": "2024-01-01", "is_completed": false, "task_type": 3, "assignees": [1, 2, 3, 4, 5]}}, {"model": "task_manager.task", "pk": 11, "fields": {"name": "Make a website header", "description": "Make website header exactly like designer designed it.", "deadline": "2023-11-27", "is_completed": false, "task_type": 1, "assignees": [2, 4]}}, {"model": "task_manager.task", "pk": 12, "fields": {"name": "Deploy project", "description": "Deploy entire project!", "deadline": "2023-11-24", "is_completed": false, "task_type": 3, "assignees": [1, 4, 5]}}, {"model": "task_manager.task", "pk": 13, "fields": {"name": "Fix some bugs", "description": "You know, as always... Bugs - unhappy, no bugs - impossible.", "deadline": "2023-11-26", "is_completed": false, "task_type": 2, "assignees": [1, 2, 4]}}]
Binary file added db_schema.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file added it_task_manager/__init__.py
Empty file.
16 changes: 16 additions & 0 deletions it_task_manager/asgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
ASGI config for it_task_manager project.

It exposes the ASGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "it_task_manager.settings")

application = get_asgi_application()
108 changes: 108 additions & 0 deletions it_task_manager/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import os
import dj_database_url

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY", "django-insecure-9jim!(&m3s(4a)y&ca)x-^rxqz578ixt61-)nx&gt0@t7jy4)r")

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.environ.get("DJANGO_DEBUG", "") != "False"

ALLOWED_HOSTS = ["127.0.0.1"]

INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"task_manager",
"crispy_forms",
"crispy_bootstrap4"
]

CRISPY_TEMPLATE_PACK = "bootstrap4"

MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]

ROOT_URLCONF = "it_task_manager.urls"

TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / "templates"],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]

WSGI_APPLICATION = "it_task_manager.wsgi.application"

DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}

db_from_env = dj_database_url.config(conn_max_age=500)
DATABASES["default"].update(db_from_env)

DATABASE_URL = "postgres://plzcduol:[email protected]/plzcduol"

AUTH_USER_MODEL = "task_manager.Worker"

LOGIN_REDIRECT_URL = "/"

AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]

LANGUAGE_CODE = "en-us"

TIME_ZONE = "Europe/Kiev"

USE_I18N = True

USE_TZ = True

STATIC_URL = "static/"
STATIC_ROOT = "staticfiles/"

STATICFILES_DIRS = (BASE_DIR / "static",)

STATIC_ROOT = BASE_DIR / "staticfiles"

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
10 changes: 10 additions & 0 deletions it_task_manager/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path("admin/", admin.site.urls),
path("", include("task_manager.urls", namespace="task_manager")),
path("accounts/", include("django.contrib.auth.urls"))
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
16 changes: 16 additions & 0 deletions it_task_manager/wsgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
WSGI config for it_task_manager project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "it_task_manager.settings")

application = get_wsgi_application()
22 changes: 22 additions & 0 deletions manage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys


def main():
"""Run administrative tasks."""
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "it_task_manager.settings")
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)


if __name__ == "__main__":
main()
24 changes: 24 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
asgiref==3.7.2
black==23.11.0
certifi==2023.11.17
charset-normalizer==3.3.2
click==8.1.7
crispy-bootstrap4==2023.1
dj-database-url==2.1.0
Django==4.2.7
django-crispy-forms==2.1
flake8==6.1.0
idna==3.4
mccabe==0.7.0
mypy-extensions==1.0.0
packaging==23.2
pathspec==0.11.2
platformdirs==4.0.0
psycopg2-binary==2.9.9
pycodestyle==2.11.1
pyflakes==3.1.0
requests==2.31.0
sqlparse==0.4.4
typing_extensions==4.8.0
urllib3==2.1.0
whitenoise==6.6.0
3 changes: 3 additions & 0 deletions static/css/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
body {
margin: 10px;
}
13 changes: 13 additions & 0 deletions static/js/update_clock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function updateClock() {
var currentTime = new Date();
var hours = currentTime.getHours();
var minutes = currentTime.getMinutes();

minutes = (minutes < 10 ? "0" : "") + minutes;

var timeString = hours + ':' + minutes;

document.getElementById('clock').innerHTML = timeString;
}

setInterval(updateClock, 5000);
Empty file added staticfiles/.gitkeep
Empty file.
Empty file added task_manager/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions task_manager/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class TaskManagerConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "task_manager"
Loading