├── wms
├── pages
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── admin.py
│ ├── tests.py
│ ├── apps.py
│ ├── urls.py
│ ├── static
│ │ └── events
│ │ │ └── dashboard
│ │ │ ├── img
│ │ │ ├── mglogo.png
│ │ │ ├── avatars
│ │ │ │ ├── profiles
│ │ │ │ │ ├── avatar-1.jpg
│ │ │ │ │ ├── avatar-2.jpg
│ │ │ │ │ ├── avatar-3.jpg
│ │ │ │ │ ├── avatar-4.jpg
│ │ │ │ │ ├── avatar-5.jpg
│ │ │ │ │ ├── avatar-6.jpg
│ │ │ │ │ ├── avatar-7.jpg
│ │ │ │ │ └── avatar-8.jpg
│ │ │ │ ├── projects
│ │ │ │ │ ├── project-1.jpg
│ │ │ │ │ ├── project-2.jpg
│ │ │ │ │ ├── project-3.jpg
│ │ │ │ │ └── project-5.jpg
│ │ │ │ └── teams
│ │ │ │ │ ├── team-logo-1.jpg
│ │ │ │ │ └── team-logo-2.jpg
│ │ │ ├── svg
│ │ │ │ ├── clipboard.svg
│ │ │ │ ├── share2.svg
│ │ │ │ ├── location-pin.svg
│ │ │ │ ├── messenger.svg
│ │ │ │ ├── fb.svg
│ │ │ │ ├── calendar.svg
│ │ │ │ ├── twitter.svg
│ │ │ │ ├── share.svg
│ │ │ │ └── whatsapp.svg
│ │ │ └── logo.svg
│ │ │ ├── fonts
│ │ │ ├── feather
│ │ │ │ ├── fonts
│ │ │ │ │ └── Feather.ttf
│ │ │ │ └── feather.min.css
│ │ │ └── cerebrisans
│ │ │ │ ├── cerebrisans-medium.woff
│ │ │ │ ├── cerebrisans-regular.woff
│ │ │ │ └── cerebrisans-semibold.woff
│ │ │ └── libs
│ │ │ ├── chart.js
│ │ │ └── Chart.extension.min.js
│ │ │ ├── highlightjs
│ │ │ └── styles
│ │ │ │ └── vs2015.css
│ │ │ └── magnific
│ │ │ └── magnific.min.css
│ ├── api_v1_urls.py
│ ├── views.py
│ ├── api_v1_views.py
│ └── templates
│ │ └── pages
│ │ └── index.html
├── stock
│ ├── __init__.py
│ ├── migrations
│ │ ├── __init__.py
│ │ ├── 0003_auto_20200215_1536.py
│ │ ├── 0004_auto_20200215_1558.py
│ │ ├── 0007_product_price.py
│ │ ├── 0006_auto_20200216_1708.py
│ │ ├── 0002_auto_20200215_1038.py
│ │ ├── 0005_auto_20200216_1442.py
│ │ └── 0001_initial.py
│ ├── tests.py
│ ├── apps.py
│ ├── admin.py
│ ├── forms.py
│ ├── templates
│ │ └── stock
│ │ │ ├── ProductDelete.html
│ │ │ ├── CustomerDelete.html
│ │ │ ├── ShipmentDelete.html
│ │ │ ├── CustomerCreation.html
│ │ │ ├── customer_update_form.html
│ │ │ ├── customer_list.html
│ │ │ ├── product_list.html
│ │ │ ├── product_update_form.html
│ │ │ ├── ProductCreation.html
│ │ │ ├── shipment_update_form.html
│ │ │ ├── shipment_list.html
│ │ │ └── ShipmentCreation.html
│ ├── serializers.py
│ ├── urls.py
│ ├── models.py
│ └── views.py
├── users
│ ├── __init__.py
│ ├── migrations
│ │ ├── __init__.py
│ │ ├── 0003_remove_profile_photo.py
│ │ ├── 0002_profile_is_approved.py
│ │ └── 0001_initial.py
│ ├── templates
│ │ ├── users
│ │ │ └── login.html
│ │ ├── account
│ │ │ ├── base.html
│ │ │ ├── messages
│ │ │ │ ├── logged_out.txt
│ │ │ │ ├── password_set.txt
│ │ │ │ ├── email_confirmed.txt
│ │ │ │ ├── email_deleted.txt
│ │ │ │ ├── password_changed.txt
│ │ │ │ ├── primary_email_set.txt
│ │ │ │ ├── email_confirmation_sent.txt
│ │ │ │ ├── unverified_primary_email.txt
│ │ │ │ ├── cannot_delete_primary_email.txt
│ │ │ │ └── logged_in.txt
│ │ │ ├── email
│ │ │ │ ├── email_confirmation_signup_message.txt
│ │ │ │ ├── email_confirmation_signup_subject.txt
│ │ │ │ ├── password_reset_key_subject.txt
│ │ │ │ ├── email_confirmation_subject.txt
│ │ │ │ ├── email_confirmation_message.txt
│ │ │ │ └── password_reset_key_message.txt
│ │ │ ├── snippets
│ │ │ │ └── already_logged_in.html
│ │ │ ├── account_inactive.html
│ │ │ ├── signup_closed.html
│ │ │ ├── password_reset_from_key_done.html
│ │ │ ├── password_set.html
│ │ │ ├── verification_sent.html
│ │ │ ├── password_reset_done.html
│ │ │ ├── verified_email_required.html
│ │ │ ├── logout.html
│ │ │ ├── email_confirm.html
│ │ │ ├── password_reset.html
│ │ │ ├── password_change.html
│ │ │ ├── signup.html
│ │ │ ├── password_reset_from_key.html
│ │ │ ├── email.html
│ │ │ └── login.html
│ │ ├── socialaccount
│ │ │ ├── base.html
│ │ │ ├── snippets
│ │ │ │ ├── login_extra.html
│ │ │ │ └── provider_list.html
│ │ │ ├── messages
│ │ │ │ ├── account_connected_updated.txt
│ │ │ │ ├── account_connected.txt
│ │ │ │ ├── account_disconnected.txt
│ │ │ │ └── account_connected_other.txt
│ │ │ ├── authentication_error.html
│ │ │ ├── login_cancelled.html
│ │ │ ├── signup.html
│ │ │ └── connections.html
│ │ └── base.html
│ ├── tests.py
│ ├── apps.py
│ ├── admin.py
│ ├── api_v1_views.py
│ ├── views.py
│ ├── serializers.py
│ ├── managers.py
│ └── models.py
├── wms
│ ├── __init__.py
│ ├── asgi.py
│ ├── wsgi.py
│ ├── middleware
│ │ └── HelloMiddleWare.py
│ ├── urls.py
│ └── settings.py
├── WMS WORKSPACE.code-workspace
├── .travisss.yml
├── Dockerfile
├── manage.py
├── requirements.txt
└── Readme.md
├── wms-frontend
├── .vscode
│ └── last.sql
├── public
│ ├── robots.txt
│ ├── favicon.ico
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── index.html
├── src
│ ├── auth-context.js
│ ├── fonts
│ │ └── feather
│ │ │ ├── fonts
│ │ │ └── Feather.ttf
│ │ │ └── feather.min.css
│ ├── setupTests.js
│ ├── index.css
│ ├── common
│ │ ├── InputElement.js
│ │ ├── Header.js
│ │ └── Table.js
│ ├── index.js
│ ├── Pages
│ │ ├── Customers.js
│ │ ├── ProductsPage.js
│ │ ├── ShipmentsPage.js
│ │ ├── CreateCustomerPage.js
│ │ ├── CreateProductPage.js
│ │ ├── LoginPage.js
│ │ ├── CreateShipmentPage.js
│ │ └── Homepage.js
│ ├── axiosInstance.js
│ ├── App.js
│ ├── logo.svg
│ └── serviceWorker.js
├── .gitignore
├── package.json
└── README.md
├── .vscode
└── settings.json
├── Readme.md
└── .gitignore
/wms/pages/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/stock/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/users/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/wms/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms-frontend/.vscode/last.sql:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/pages/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/stock/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/users/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/users/templates/users/login.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/users/templates/account/base.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
--------------------------------------------------------------------------------
/wms/users/templates/socialaccount/base.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
--------------------------------------------------------------------------------
/wms/pages/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/wms/pages/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/wms/pages/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/wms/stock/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/wms/users/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/wms-frontend/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/wms-frontend/src/auth-context.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 |
4 | const AuthContext = React.createContext()
--------------------------------------------------------------------------------
/wms/pages/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class PagesConfig(AppConfig):
5 | name = 'pages'
6 |
--------------------------------------------------------------------------------
/wms/stock/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class StockConfig(AppConfig):
5 | name = 'stock'
6 |
--------------------------------------------------------------------------------
/wms/users/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class UsersConfig(AppConfig):
5 | name = 'users'
6 |
--------------------------------------------------------------------------------
/wms/users/templates/socialaccount/snippets/login_extra.html:
--------------------------------------------------------------------------------
1 | {% load socialaccount %}
2 |
3 | {% providers_media_js %}
4 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "python.pythonPath": "env\\Scripts\\python.exe",
3 | "python.formatting.provider": "black"
4 | }
--------------------------------------------------------------------------------
/wms/users/templates/account/messages/logged_out.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% blocktrans %}You have signed out.{% endblocktrans %}
3 |
--------------------------------------------------------------------------------
/wms/users/templates/account/email/email_confirmation_signup_message.txt:
--------------------------------------------------------------------------------
1 | {% include "account/email/email_confirmation_message.txt" %}
2 |
--------------------------------------------------------------------------------
/wms/users/templates/account/email/email_confirmation_signup_subject.txt:
--------------------------------------------------------------------------------
1 | {% include "account/email/email_confirmation_subject.txt" %}
2 |
--------------------------------------------------------------------------------
/wms/users/templates/socialaccount/messages/account_connected_updated.txt:
--------------------------------------------------------------------------------
1 | {% extends "socialaccount/messages/account_connected.txt" %}
2 |
--------------------------------------------------------------------------------
/wms/users/templates/account/messages/password_set.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% blocktrans %}Password successfully set.{% endblocktrans %}
3 |
--------------------------------------------------------------------------------
/wms-frontend/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms-frontend/public/favicon.ico
--------------------------------------------------------------------------------
/wms-frontend/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms-frontend/public/logo192.png
--------------------------------------------------------------------------------
/wms-frontend/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms-frontend/public/logo512.png
--------------------------------------------------------------------------------
/wms/users/templates/account/messages/email_confirmed.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% blocktrans %}You have confirmed {{email}}.{% endblocktrans %}
3 |
--------------------------------------------------------------------------------
/wms/users/templates/account/messages/email_deleted.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% blocktrans %}Removed e-mail address {{email}}.{% endblocktrans %}
3 |
--------------------------------------------------------------------------------
/wms/users/templates/account/messages/password_changed.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% blocktrans %}Password successfully changed.{% endblocktrans %}
3 |
--------------------------------------------------------------------------------
/wms/users/templates/account/messages/primary_email_set.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% blocktrans %}Primary e-mail address set.{% endblocktrans %}
3 |
--------------------------------------------------------------------------------
/wms/pages/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 | from . import views
3 |
4 |
5 | urlpatterns = [
6 | path('', views.index, name='home'),
7 | ]
--------------------------------------------------------------------------------
/wms/users/templates/account/messages/email_confirmation_sent.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% blocktrans %}Confirmation e-mail sent to {{email}}.{% endblocktrans %}
3 |
--------------------------------------------------------------------------------
/wms/users/templates/socialaccount/messages/account_connected.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% blocktrans %}The social account has been connected.{% endblocktrans %}
3 |
--------------------------------------------------------------------------------
/wms/users/templates/socialaccount/messages/account_disconnected.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% blocktrans %}The social account has been disconnected.{% endblocktrans %}
3 |
--------------------------------------------------------------------------------
/wms/users/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from .models import stockUser , Profile
3 |
4 | admin.site.register(stockUser)
5 | admin.site.register(Profile)
6 |
--------------------------------------------------------------------------------
/wms/users/templates/account/messages/unverified_primary_email.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% blocktrans %}Your primary e-mail address must be verified.{% endblocktrans %}
3 |
--------------------------------------------------------------------------------
/wms-frontend/src/fonts/feather/fonts/Feather.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms-frontend/src/fonts/feather/fonts/Feather.ttf
--------------------------------------------------------------------------------
/wms/WMS WORKSPACE.code-workspace:
--------------------------------------------------------------------------------
1 | {
2 | "folders": [
3 | {
4 | "path": "."
5 | },
6 | {
7 | "path": "..\\wms-frontend"
8 | }
9 | ],
10 | "settings": {}
11 | }
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/mglogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/mglogo.png
--------------------------------------------------------------------------------
/wms/users/templates/account/messages/cannot_delete_primary_email.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% blocktrans %}You cannot remove your primary e-mail address ({{email}}).{% endblocktrans %}
3 |
--------------------------------------------------------------------------------
/wms/users/templates/socialaccount/messages/account_connected_other.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% blocktrans %}The social account is already connected to a different account.{% endblocktrans %}
3 |
--------------------------------------------------------------------------------
/wms/users/templates/account/email/password_reset_key_subject.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% autoescape off %}
3 | {% blocktrans %}Password Reset E-mail{% endblocktrans %}
4 | {% endautoescape %}
5 |
--------------------------------------------------------------------------------
/wms/users/templates/account/email/email_confirmation_subject.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% autoescape off %}
3 | {% blocktrans %}Please Confirm Your E-mail Address{% endblocktrans %}
4 | {% endautoescape %}
5 |
--------------------------------------------------------------------------------
/wms/users/templates/account/messages/logged_in.txt:
--------------------------------------------------------------------------------
1 | {% load account %}
2 | {% load i18n %}
3 | {% user_display user as name %}
4 | {% blocktrans %}Successfully signed in as {{user}}.{% endblocktrans %}
5 |
--------------------------------------------------------------------------------
/wms/users/api_v1_views.py:
--------------------------------------------------------------------------------
1 | from restframework.views import APIView
2 | from restframework.authentication import
3 |
4 | class AuthView(APIView):
5 | authentication_classes = [TokenAuthentication]
6 | pass
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/fonts/feather/fonts/Feather.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/fonts/feather/fonts/Feather.ttf
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-1.jpg
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-2.jpg
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-3.jpg
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-4.jpg
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-5.jpg
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-6.jpg
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-7.jpg
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/avatars/profiles/avatar-8.jpg
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/avatars/projects/project-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/avatars/projects/project-1.jpg
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/avatars/projects/project-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/avatars/projects/project-2.jpg
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/avatars/projects/project-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/avatars/projects/project-3.jpg
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/avatars/projects/project-5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/avatars/projects/project-5.jpg
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/avatars/teams/team-logo-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/avatars/teams/team-logo-1.jpg
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/avatars/teams/team-logo-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/img/avatars/teams/team-logo-2.jpg
--------------------------------------------------------------------------------
/wms/stock/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from .models import *
3 |
4 | admin.site.register(Warehouse)
5 | admin.site.register(Product)
6 | admin.site.register(Customer)
7 | admin.site.register(Shipment)
8 |
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/fonts/cerebrisans/cerebrisans-medium.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/fonts/cerebrisans/cerebrisans-medium.woff
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/fonts/cerebrisans/cerebrisans-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/fonts/cerebrisans/cerebrisans-regular.woff
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/fonts/cerebrisans/cerebrisans-semibold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nyamador/Django-React-Warehouse-Management-System/HEAD/wms/pages/static/events/dashboard/fonts/cerebrisans/cerebrisans-semibold.woff
--------------------------------------------------------------------------------
/wms/.travisss.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | python:
3 | - "3.7"
4 | branches:
5 | only:
6 | - master
7 | install:
8 | - pip install -r requirements.txt
9 | script:
10 | - python manage.py test --settings=velocity.local
--------------------------------------------------------------------------------
/wms/users/templates/account/snippets/already_logged_in.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% load account %}
3 |
4 | {% user_display user as user_display %}
5 |
{% trans "Note" %}: {% blocktrans %}you are already logged in as {{ user_display }}.{% endblocktrans %}
6 |
--------------------------------------------------------------------------------
/wms-frontend/src/setupTests.js:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect';
6 |
--------------------------------------------------------------------------------
/wms/users/templates/account/account_inactive.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Account Inactive" %}{% endblock %}
6 |
7 | {% block content %}
8 | {% trans "Account Inactive" %}
9 |
10 | {% trans "This account is inactive." %}
11 | {% endblock %}
12 |
--------------------------------------------------------------------------------
/wms/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.8-alpine3.10
2 |
3 | WORKDIR /code
4 |
5 | COPY requirements.txt /code
6 |
7 |
8 | RUN pip install -r requirements.txt
9 |
10 | COPY . /code
11 |
12 | RUN python manage.py makemigrations && python manage.py migrate
13 |
14 | EXPOSE 8000
15 |
16 | ENTRYPOINT ["python", "manage.py"]
17 | CMD ["runserver", "0.0.0.0:8000"]
--------------------------------------------------------------------------------
/wms/users/templates/account/signup_closed.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Sign Up Closed" %}{% endblock %}
6 |
7 | {% block content %}
8 | {% trans "Sign Up Closed" %}
9 |
10 | {% trans "We are sorry, but the sign up is currently closed." %}
11 | {% endblock %}
12 |
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/svg/clipboard.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/svg/share2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/svg/location-pin.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/users/templates/socialaccount/authentication_error.html:
--------------------------------------------------------------------------------
1 | {% extends "socialaccount/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Social Network Login Failure" %}{% endblock %}
6 |
7 | {% block content %}
8 | {% trans "Social Network Login Failure" %}
9 |
10 | {% trans "An error occurred while attempting to login via your social network account." %}
11 | {% endblock %}
12 |
--------------------------------------------------------------------------------
/wms-frontend/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/wms-frontend/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/wms/users/migrations/0003_remove_profile_photo.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.3 on 2020-03-20 17:12
2 |
3 | from django.db import migrations
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('users', '0002_profile_is_approved'),
10 | ]
11 |
12 | operations = [
13 | migrations.RemoveField(
14 | model_name='profile',
15 | name='photo',
16 | ),
17 | ]
18 |
--------------------------------------------------------------------------------
/wms/wms/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for wms project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'wms.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/wms/wms/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for wms project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'wms.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/wms-frontend/src/common/InputElement.js:
--------------------------------------------------------------------------------
1 | import React, {useState} from 'react';
2 |
3 |
4 | const InputElement = (props) => {
5 |
6 | const [value, setValue] = useState();
7 |
8 | return (
9 | setValue(e.target.value)}/>
11 | )
12 | }
13 |
14 | export default InputElement;
--------------------------------------------------------------------------------
/wms/users/templates/account/password_reset_from_key_done.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 | {% block head_title %}{% trans "Change Password" %}{% endblock %}
5 |
6 | {% block content %}
7 | {% trans "Change Password" %}
8 | {% trans 'Your password has been changed successfully.' %}
9 |
10 | Home
11 |
12 | {% endblock %}
13 |
--------------------------------------------------------------------------------
/wms/users/views.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.db.models.signals import post_save
3 | from django.dispatch import receiver
4 | from rest_framework.authtoken.models import Token
5 | from django.shortcuts import render
6 |
7 | # Create your views here.
8 | @receiver(post_save, sender=settings.AUTH_USER_MODEL)
9 | def create_auth_token(sender, instance, created=False, **kwargs):
10 | if created:
11 | Token.objects.create(user=instance)
12 |
--------------------------------------------------------------------------------
/wms/stock/migrations/0003_auto_20200215_1536.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.3 on 2020-02-15 15:36
2 |
3 | from django.db import migrations
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('stock', '0002_auto_20200215_1038'),
10 | ]
11 |
12 | operations = [
13 | migrations.RenameField(
14 | model_name='product',
15 | old_name='created_by',
16 | new_name='user',
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/wms/users/templates/account/password_set.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Set Password" %}{% endblock %}
6 |
7 | {% block content %}
8 | {% trans "Set Password" %}
9 |
10 |
15 | {% endblock %}
16 |
--------------------------------------------------------------------------------
/wms/users/templates/account/verification_sent.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Verify Your E-mail Address" %}{% endblock %}
6 |
7 | {% block content %}
8 | {% trans "Verify Your E-mail Address" %}
9 |
10 | {% blocktrans %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}
11 |
12 | {% endblock %}
13 |
--------------------------------------------------------------------------------
/wms/users/migrations/0002_profile_is_approved.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.3 on 2020-02-17 14:11
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('users', '0001_initial'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='profile',
15 | name='is_approved',
16 | field=models.BooleanField(default=False, verbose_name='Approved user'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/svg/messenger.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/stock/migrations/0004_auto_20200215_1558.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.3 on 2020-02-15 15:58
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('stock', '0003_auto_20200215_1536'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='product',
15 | name='sku',
16 | field=models.CharField(max_length=50, unique=True, verbose_name='Stock Keeping Unit'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/wms/users/templates/socialaccount/login_cancelled.html:
--------------------------------------------------------------------------------
1 | {% extends "socialaccount/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Login Cancelled" %}{% endblock %}
6 |
7 | {% block content %}
8 |
9 | {% trans "Login Cancelled" %}
10 |
11 | {% url 'account_login' as login_url %}
12 |
13 | {% blocktrans %}You decided to cancel logging in to our site using one of your existing accounts. If this was a mistake, please proceed to sign in .{% endblocktrans %}
14 |
15 | {% endblock %}
16 |
--------------------------------------------------------------------------------
/wms/stock/forms.py:
--------------------------------------------------------------------------------
1 | from django.forms import ModelForm
2 | from .models import Product, Customer, Shipment
3 |
4 | class ProductCreationForm(ModelForm):
5 | class Meta:
6 | model = Product
7 | fields = ('name', 'quantity', 'price', 'sku')
8 |
9 | class CustomerCreationForm(ModelForm):
10 | class Meta:
11 | model = Customer
12 | fields = ('firstname', 'lastname', 'email')
13 |
14 | class ShipmentCreationForm(ModelForm):
15 | class Meta:
16 | model = Shipment
17 | fields = ('customer', 'destination', 'product','quantity')
--------------------------------------------------------------------------------
/wms-frontend/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import * as serviceWorker from './serviceWorker';
6 |
7 | ReactDOM.render(
8 |
9 |
10 | ,
11 | document.getElementById('root')
12 | );
13 |
14 | // If you want your app to work offline and load faster, you can change
15 | // unregister() to register() below. Note this comes with some pitfalls.
16 | // Learn more about service workers: https://bit.ly/CRA-PWA
17 | serviceWorker.unregister();
18 |
--------------------------------------------------------------------------------
/wms/stock/migrations/0007_product_price.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.3 on 2020-02-17 08:10
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('stock', '0006_auto_20200216_1708'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='product',
15 | name='price',
16 | field=models.DecimalField(decimal_places=2, default=2.0, max_digits=10, verbose_name='Unit Price'),
17 | preserve_default=False,
18 | ),
19 | ]
20 |
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/svg/fb.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms-frontend/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/wms/users/templates/account/email/email_confirmation_message.txt:
--------------------------------------------------------------------------------
1 | {% load account %}{% user_display user as user_display %}{% load i18n %}{% autoescape off %}{% blocktrans with site_name=current_site.name site_domain=current_site.domain %}Hello from {{ site_name }}!
2 |
3 | You're receiving this e-mail because user {{ user_display }} has given yours as an e-mail address to connect their account.
4 |
5 | To confirm this is correct, go to {{ activate_url }}
6 | {% endblocktrans %}
7 | {% blocktrans with site_name=current_site.name site_domain=current_site.domain %}Thank you from {{ site_name }}!
8 | {{ site_domain }}{% endblocktrans %}
9 | {% endautoescape %}
10 |
--------------------------------------------------------------------------------
/wms/stock/templates/stock/ProductDelete.html:
--------------------------------------------------------------------------------
1 | {% extends 'pages/_base.html' %}
2 |
3 |
4 | {% block content %}
5 |
6 |
7 |
8 |
9 | Do you want to delete {{ product }}
10 |
11 |
12 |
13 |
14 |
24 |
25 |
26 | {% endblock content %}
--------------------------------------------------------------------------------
/wms/users/templates/account/password_reset_done.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 | {% load account %}
5 |
6 | {% block head_title %}{% trans "Password Reset" %}{% endblock %}
7 |
8 | {% block content %}
9 | {% trans "Password Reset" %}
10 |
11 | {% if user.is_authenticated %}
12 | {% include "account/snippets/already_logged_in.html" %}
13 | {% endif %}
14 |
15 | {% blocktrans %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}
16 |
17 | Go Home
18 |
19 | {% endblock %}
20 |
--------------------------------------------------------------------------------
/wms/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'wms.settings')
9 | try:
10 | from django.core.management import execute_from_command_line
11 | except ImportError as exc:
12 | raise ImportError(
13 | "Couldn't import Django. Are you sure it's installed and "
14 | "available on your PYTHONPATH environment variable? Did you "
15 | "forget to activate a virtual environment?"
16 | ) from exc
17 | execute_from_command_line(sys.argv)
18 |
19 |
20 | if __name__ == '__main__':
21 | main()
22 |
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/wms/stock/templates/stock/CustomerDelete.html:
--------------------------------------------------------------------------------
1 | {% extends 'pages/_base.html' %}
2 |
3 |
4 | {% block content %}
5 |
6 |
7 |
8 |
9 | Do you want to delete {{ customer }}
10 |
11 |
12 |
13 |
14 |
15 |
25 |
26 |
27 | {% endblock content %}
--------------------------------------------------------------------------------
/wms/stock/templates/stock/ShipmentDelete.html:
--------------------------------------------------------------------------------
1 | {% extends 'pages/_base.html' %}
2 |
3 |
4 | {% block content %}
5 |
6 |
7 |
8 |
9 | Do you want to delete {{ shipment }}
10 |
11 |
12 |
13 |
14 |
15 |
25 |
26 |
27 | {% endblock content %}
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/svg/calendar.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/users/templates/account/email/password_reset_key_message.txt:
--------------------------------------------------------------------------------
1 | {% load i18n %}{% autoescape off %}{% blocktrans with site_name=current_site.name site_domain=current_site.domain %}Hello from {{ site_name }}!
2 |
3 | You're receiving this e-mail because you or someone else has requested a password for your user account.
4 | It can be safely ignored if you did not request a password reset. Click the link below to reset your password.{% endblocktrans %}
5 |
6 | {{ password_reset_url }}
7 |
8 | {% if username %}{% blocktrans %}In case you forgot, your username is {{ username }}.{% endblocktrans %}
9 |
10 | {% endif %}{% blocktrans with site_name=current_site.name site_domain=current_site.domain %}Thank you for using {{ site_name }}!
11 | {{ site_domain }}{% endblocktrans %}
12 | {% endautoescape %}
13 |
--------------------------------------------------------------------------------
/wms/users/templates/socialaccount/snippets/provider_list.html:
--------------------------------------------------------------------------------
1 | {% load socialaccount %}
2 |
3 | {% get_providers as socialaccount_providers %}
4 |
5 | {% for provider in socialaccount_providers %}
6 | {% if provider.id == "openid" %}
7 | {% for brand in provider.get_brands %}
8 |
9 | {{brand.name}}
13 |
14 | {% endfor %}
15 | {% endif %}
16 |
17 | {{provider.name}}
19 |
20 | {% endfor %}
21 |
--------------------------------------------------------------------------------
/wms/pages/api_v1_urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 |
3 | # from rest_framework.authtoken import views as authtokenviews
4 | from . import api_v1_views
5 |
6 |
7 | urlpatterns = [
8 | # List Routes
9 | path("products/all", api_v1_views.Products.as_view(), name="api_product_list"),
10 | path(
11 | "products/create",
12 | api_v1_views.ProductCreateAPIView.as_view(),
13 | name="api_product_create",
14 | ),
15 | path("customers/all", api_v1_views.Customers.as_view(), name="api_customer_list"),
16 | path(
17 | "warehouses/all", api_v1_views.Warehouses.as_view(), name="api_warehouse_list"
18 | ),
19 | path("shipments/all", api_v1_views.Shipments.as_view(), name="api_shipment_list"),
20 | # TOKENAUTH
21 | # path('api-token-auth', authtokenviews.obtain_auth_token),
22 | ]
23 |
--------------------------------------------------------------------------------
/wms/stock/migrations/0006_auto_20200216_1708.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.3 on 2020-02-16 17:08
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('stock', '0005_auto_20200216_1442'),
10 | ]
11 |
12 | operations = [
13 | migrations.AddField(
14 | model_name='shipment',
15 | name='destination',
16 | field=models.CharField(default=1, max_length=100, verbose_name='Destination of Shipment'),
17 | preserve_default=False,
18 | ),
19 | migrations.AddField(
20 | model_name='shipment',
21 | name='quantity',
22 | field=models.PositiveIntegerField(default=1, verbose_name='Product Quantity'),
23 | preserve_default=False,
24 | ),
25 | ]
26 |
--------------------------------------------------------------------------------
/wms/stock/serializers.py:
--------------------------------------------------------------------------------
1 | from rest_framework import serializers
2 |
3 | from .models import Product, Customer, Warehouse, Shipment
4 |
5 |
6 | class ProductSerializer(serializers.ModelSerializer):
7 | class Meta:
8 | model = Product
9 | fields = ["user", "warehouse", "name", "price", "quantity", "sku", "date"]
10 |
11 |
12 | class CustomerSerializer(serializers.ModelSerializer):
13 | class Meta:
14 | model = Customer
15 | fields = ["firstname", "lastname", "email"]
16 |
17 |
18 | class WarehouseSerializer(serializers.ModelSerializer):
19 | class Meta:
20 | model = Warehouse
21 | fields = ["id", "name", "location"]
22 |
23 |
24 | class ShipmentSerializer(serializers.ModelSerializer):
25 | class Meta:
26 | model = Shipment
27 | fields = ["user", "customer", "destination", "product", "quantity"]
28 |
29 |
--------------------------------------------------------------------------------
/wms/users/templates/socialaccount/signup.html:
--------------------------------------------------------------------------------
1 | {% extends "socialaccount/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Signup" %}{% endblock %}
6 |
7 | {% block content %}
8 | {% trans "Sign Up" %}
9 |
10 | {% blocktrans with provider_name=account.get_provider.name site_name=site.name %}You are about to use your {{provider_name}} account to login to
11 | {{site_name}}. As a final step, please complete the following form:{% endblocktrans %}
12 |
13 |
21 |
22 | {% endblock %}
23 |
--------------------------------------------------------------------------------
/wms/users/serializers.py:
--------------------------------------------------------------------------------
1 | from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
2 | from rest_framework import serializers
3 | from .models import stockUser
4 |
5 |
6 | class CustomUserSerializer(serializers.ModelSerializer):
7 | email = serializers.EmailField(required=True)
8 | password = serializers.CharField(min_length=8, write_only=True)
9 |
10 | class Meta:
11 | model = stockUser
12 | field = ('email', 'password')
13 | extra_kwargs = {'password': {'write_only': True}}
14 |
15 | def create(self, validated_data):
16 | password = validated_data.pop('password', None)
17 | instance = self.Meta.model(**validated_data) # as long as the fields are the same, we can just use this
18 | if password is not None:
19 | instance.set_password(password)
20 | instance.save()
21 | return instance
22 |
--------------------------------------------------------------------------------
/wms/users/templates/account/verified_email_required.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Verify Your E-mail Address" %}{% endblock %}
6 |
7 | {% block content %}
8 | {% trans "Verify Your E-mail Address" %}
9 |
10 | {% url 'account_email' as email_url %}
11 |
12 | {% blocktrans %}This part of the site requires us to verify that
13 | you are who you claim to be. For this purpose, we require that you
14 | verify ownership of your e-mail address. {% endblocktrans %}
15 |
16 | {% blocktrans %}We have sent an e-mail to you for
17 | verification. Please click on the link inside this e-mail. Please
18 | contact us if you do not receive it within a few minutes.{% endblocktrans %}
19 |
20 | {% blocktrans %}Note: you can still change your e-mail address .{% endblocktrans %}
21 |
22 |
23 | {% endblock %}
24 |
--------------------------------------------------------------------------------
/wms/stock/migrations/0002_auto_20200215_1038.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.3 on 2020-02-15 10:38
2 |
3 | from django.conf import settings
4 | from django.db import migrations, models
5 | import django.db.models.deletion
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | initial = True
11 |
12 | dependencies = [
13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
14 | ('stock', '0001_initial'),
15 | ]
16 |
17 | operations = [
18 | migrations.AddField(
19 | model_name='product',
20 | name='created_by',
21 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
22 | ),
23 | migrations.AddField(
24 | model_name='product',
25 | name='warehouse',
26 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='stock.Warehouse'),
27 | ),
28 | ]
29 |
--------------------------------------------------------------------------------
/wms-frontend/src/Pages/Customers.js:
--------------------------------------------------------------------------------
1 | import React, {useState, useEffect} from 'react';
2 | import Header from '../common/Header';
3 | import Table from '../common/Table';
4 |
5 | const Customers = () => {
6 | const [dataList, setdataList] = useState([]);
7 | const [isLoading, setisLoading] = useState(true);
8 |
9 | const dataHeadings = ['Firstname', 'Lastname', 'Email'];
10 |
11 |
12 | useEffect( () => {
13 | fetch('http://127.0.0.1:8000/api/v1/customers/all')
14 | .then( res => res.json())
15 | .then( data => setdataList([...data]) )
16 | .then(setisLoading(false))
17 | .catch(err => setisLoading(true));
18 | }, [])
19 |
20 | return (
21 | <>
22 |
23 |
24 | { isLoading ? Loading...
25 | : }
26 | >
27 | );
28 | };
29 |
30 | export default Customers;
31 |
--------------------------------------------------------------------------------
/wms/users/templates/account/logout.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Sign Out" %}{% endblock %}
6 |
7 |
8 | {% if messages %}
9 | {% for message in messages %}
10 |
11 | {{message}}
12 |
13 | {% endfor %}
14 | {% endif %}
15 |
16 | {% block content %}
17 | {% trans "Sign Out" %}
18 |
19 | {% trans 'Are you sure you want to sign out?' %}
20 |
21 |
28 |
29 |
30 | {% endblock %}
31 |
--------------------------------------------------------------------------------
/wms-frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wms-frontend",
3 | "version": "0.1.0",
4 | "private": true,
5 | "license": "BSD",
6 | "dependencies": {
7 | "@testing-library/jest-dom": "^4.2.4",
8 | "@testing-library/react": "^9.3.2",
9 | "@testing-library/user-event": "^7.1.2",
10 | "react": "^16.13.1",
11 | "react-dom": "^16.13.1",
12 | "react-router-dom": "^5.2.0",
13 | "react-scripts": "3.4.1"
14 | },
15 | "scripts": {
16 | "start": "react-scripts start",
17 | "build": "react-scripts build",
18 | "test": "react-scripts test",
19 | "eject": "react-scripts eject"
20 | },
21 | "eslintConfig": {
22 | "extends": "react-app"
23 | },
24 | "browserslist": {
25 | "production": [
26 | ">0.2%",
27 | "not dead",
28 | "not op_mini all"
29 | ],
30 | "development": [
31 | "last 1 chrome version",
32 | "last 1 firefox version",
33 | "last 1 safari version"
34 | ]
35 | },
36 | "devDependencies": {
37 | "axios": "^0.19.2"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/wms-frontend/src/Pages/ProductsPage.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import Header from '../common/Header';
3 | import Table from '../common/Table';
4 |
5 | const ProductsPage = () => {
6 | const [productsList, setProductsList] = useState([]);
7 | const [isLoading, setisLoading] = useState(true);
8 |
9 | const dataHeadings = ['Name', 'Quantity', 'Sku'];
10 | useEffect(() => {
11 | fetch('http://127.0.0.1:8000/api/v1/products/all')
12 | .then((res) => res.json())
13 | .then((data) => setProductsList([...data]))
14 | .then(setisLoading(false));
15 | }, []);
16 |
17 | return (
18 | <>
19 |
20 | {isLoading ? (
21 |
22 | {' '}
23 | Loading... {' '}
24 |
25 | ) : (
26 |
27 | )}
28 | >
29 | );
30 | };
31 |
32 | export default ProductsPage;
33 |
--------------------------------------------------------------------------------
/wms/pages/views.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.core.cache.backends.base import DEFAULT_TIMEOUT
3 | from django.views.decorators.cache import cache_page
4 | from django.shortcuts import render
5 | from django.contrib.auth.decorators import login_required
6 | from django.db.models import Sum
7 | from stock.models import (Product, Customer)
8 |
9 | CACHE_TTL = getattr(settings, 'CACHE_TTL', DEFAULT_TIMEOUT)
10 |
11 | @cache_page(CACHE_TTL)
12 | @login_required()
13 | def index(request):
14 |
15 | product_count = Product.objects.count()
16 | customer_count = Customer.objects.count()
17 | total_stock_price = Product.objects.all().aggregate(Sum('price'))
18 |
19 | print("Desmond", request.META['Desmond'])
20 | print("Seller", request.META['seller_subdomain'])
21 |
22 | context = {
23 | 'product_count' :product_count,
24 | "customer_count" : customer_count,
25 | "total_stock_price": abs(total_stock_price['price__sum'])
26 | }
27 | return render(request, 'pages/index.html', context)
28 |
--------------------------------------------------------------------------------
/wms-frontend/src/Pages/ShipmentsPage.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import Header from '../common/Header';
3 | import Table from '../common/Table';
4 |
5 | const ShipmentsPage = () => {
6 | const [shipmentsList, setshipmentsList] = useState([]);
7 | const [isLoading, setisLoading] = useState(true);
8 |
9 | const dataHeadings = ['Destination', 'Quantity', 'Product'];
10 | useEffect(() => {
11 | fetch('http://127.0.0.1:8000/api/v1/shipments/all')
12 | .then((res) => res.json())
13 | .then((data) => setshipmentsList([...data]))
14 | .then(setisLoading(false));
15 | }, []);
16 |
17 | return (
18 | <>
19 |
20 | {isLoading ? (
21 |
22 | {' '}
23 | Loading... {' '}
24 |
25 | ) : (
26 |
27 | )}
28 | >
29 | );
30 | };
31 |
32 | export default ShipmentsPage;
33 |
--------------------------------------------------------------------------------
/wms/pages/api_v1_views.py:
--------------------------------------------------------------------------------
1 | from rest_framework import generics
2 | from rest_framework.authentication import TokenAuthentication
3 | from rest_framework.permissions import IsAuthenticated
4 | from stock.models import Product, Customer, Warehouse, Shipment
5 | from stock.serializers import ProductSerializer, CustomerSerializer, WarehouseSerializer, ShipmentSerializer
6 |
7 |
8 | #LIST API VIEWS
9 | class Products(generics.ListAPIView):
10 |
11 | queryset = Product.objects.all()
12 | serializer_class = ProductSerializer
13 |
14 |
15 | class ProductCreateAPIView(generics.CreateAPIView):
16 |
17 | serializer_class = ProductSerializer
18 |
19 |
20 | class Customers(generics.ListAPIView):
21 |
22 | queryset = Customer.objects.all()
23 | serializer_class = CustomerSerializer
24 |
25 |
26 | class Warehouses(generics.ListAPIView):
27 | queryset = Warehouse.objects.all()
28 | serializer_class = WarehouseSerializer
29 |
30 |
31 | class Shipments(generics.ListAPIView):
32 | queryset = Shipment.objects.all()
33 | serializer_class = ShipmentSerializer
--------------------------------------------------------------------------------
/wms/users/templates/account/email_confirm.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 |
3 | {% load i18n %}
4 | {% load account %}
5 |
6 | {% block head_title %}{% trans "Confirm E-mail Address" %}{% endblock %}
7 |
8 |
9 | {% block content %}
10 | {% trans "Confirm E-mail Address" %}
11 |
12 | {% if confirmation %}
13 |
14 | {% user_display confirmation.email_address.user as user_display %}
15 |
16 | {% blocktrans with confirmation.email_address.email as email %}Please confirm that {{ email }} is an e-mail address for user {{ user_display }}.{% endblocktrans %}
17 |
18 |
22 |
23 | {% else %}
24 |
25 | {% url 'account_email' as email_url %}
26 |
27 | {% blocktrans %}This e-mail confirmation link expired or is invalid. Please issue a new e-mail confirmation request .{% endblocktrans %}
28 |
29 | {% endif %}
30 |
31 | {% endblock %}
32 |
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/svg/twitter.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/wms/middleware/HelloMiddleWare.py:
--------------------------------------------------------------------------------
1 | from django.http import HttpResponse
2 |
3 | class SimpleMiddleware:
4 | def __init__(self, get_response):
5 | self.get_response = get_response
6 | # One-time configuration and initialization.
7 |
8 | def __call__(self, request):
9 | # Code to be executed for each request before
10 | # the view (and later middleware) are called.
11 |
12 | request.META['Desmond'] = "Selasi"
13 |
14 |
15 | uri = request.build_absolute_uri() #https://foo.myvelocity.tech
16 | link_without_slashes = uri.split('/')[2] # foo.myvelocity.tech
17 | seller_subdomain = link_without_slashes.split('.')[0] #foo
18 |
19 | request.META['seller_subdomain'] = seller_subdomain
20 |
21 |
22 | response = self.get_response(request)
23 |
24 | # Code to be executed for each request/response after
25 | # the view is called.
26 |
27 |
28 | return response
29 |
30 | # def process_view(request, view_func, view_args, view_kwargs):
31 | # # view_kwargs['name'] = "Hello"
32 | # response = HttpResponse()
33 | # response['Desmond'] = 120
34 | # return response
--------------------------------------------------------------------------------
/wms/wms/urls.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from django.conf import settings
3 | from django.conf.urls.static import static
4 | from django.urls import path, include
5 | from rest_framework_simplejwt.views import (
6 | TokenObtainPairView, TokenRefreshView, TokenVerifyView)
7 | from rest_framework.authtoken import views as TokenViews
8 | from stock import views as stock_views
9 |
10 | urlpatterns = [
11 | path('admin/', admin.site.urls),
12 | path('accounts/', include('allauth.urls')),
13 | path('stock/', include('stock.urls')),
14 | path('customers/new', stock_views.CustomerCreationView.as_view(),name='add-customer'),
15 | path('', include('pages.urls')),
16 | path('api-auth/', include('rest_framework.urls')),
17 | path('api/v1/', include('pages.api_v1_urls')),
18 | # path('api-token-auth/', TokenViews.obtain_auth_token),
19 |
20 | # JWT Authentication Views
21 | path('api/token', TokenObtainPairView.as_view(), name='token_obtain_pair'),
22 | path('api/token/refresh', TokenRefreshView.as_view(), name='token_refresh'),
23 | path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'),
24 | ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
25 |
--------------------------------------------------------------------------------
/wms/stock/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 | from . import views
3 |
4 | urlpatterns = [
5 | #Customers
6 | path('customers', views.CustomerListView.as_view(), name="all-customers"),
7 | path('customers//delete', views.CustomerDeleteView.as_view(), name="delete-customer"),
8 | path('customers//edit', views.CustomerUpdateView.as_view(), name="edit-customer"),
9 | # Products
10 | path('/products', views.ProductListView.as_view(), name="all-products"),
11 | path('products/all', views.CachedProductListView, name='cached'),
12 | path('/products/new', views.ProductCreationView, name="add-product"),
13 | path('products//delete', views.ProductDeleteView.as_view(), name="delete-product"),
14 | path('products//edit', views.ProductUpdateView.as_view(), name="edit-product"),
15 | #Shipments
16 | path('/shipments/new', views.ShipmentCreationView.as_view(), name="add-shipment"),
17 | path('/shipments', views.ShipmentListView.as_view(), name="all-shipment"),
18 | path('shipments//delete', views.ShipmentDeleteView.as_view(), name="delete-shipment"),
19 | path('shipments//edit', views.ShipmentUpdateView.as_view(), name="edit-shipment"),
20 | ]
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/libs/chart.js/Chart.extension.min.js:
--------------------------------------------------------------------------------
1 | Chart.elements.Rectangle.prototype.draw=function(){var t,e,i,r,h,o,d,a=this._chart.ctx,n=this._view,l=n.borderWidth;if(d=n.horizontal?(t=n.base,e=n.x,i=n.y-n.height/2,r=n.y+n.height/2,h=theight/2&&(m=height/2),m>width/2&&(m=width/2),a.moveTo(x+m,y),a.lineTo(x+width-m,y),a.quadraticCurveTo(x+width,y,x+width,y+m),a.lineTo(x+width,y+height-m),a.quadraticCurveTo(x+width,y+height,x+width-m,y+height),a.lineTo(x+m,y+height),a.quadraticCurveTo(x,y+height,x,y+height-m),a.lineTo(x,y+m),a.quadraticCurveTo(x,y,x+m,y)}a.fill(),l&&a.stroke()};
--------------------------------------------------------------------------------
/wms-frontend/src/axiosInstance.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | const axiosInstance = axios.create({
4 | baseURL: 'http://127.0.0.1:8000',
5 | timeout: 5000,
6 | headers:{
7 | 'Authorization': 'JWT' + localStorage.getItem('access_token'),
8 | 'Content-Type': 'application/json',
9 | 'Accept': 'application/json'
10 | }
11 | })
12 |
13 | axiosInstance.interceptors.response.use(response => response,
14 | error => {
15 | const originalRequest = error.config;
16 | if (error.response.status === 401 && error.response.statusText === "Unauthorized"){
17 | const refresh_token = localStorage.getItem('refresh_token');
18 |
19 | return axiosInstance.post('/api/token', {refresh: refresh_token})
20 | .then(response => {
21 | localStorage.setItem('access_token', response.data.access);
22 | localStorage.setItem('refresh_token', response.data.refresh);
23 |
24 | axiosInstance.defaults['Authorization'] = "JWT" + response.data.access;
25 | originalRequest.headers['Authorization'] = "JWT" + response.data.access;
26 |
27 | return axiosInstance(originalRequest);
28 | })
29 | .catch(err => console.error(err));
30 | }
31 | return Promise.reject(error)
32 | }
33 | )
34 |
35 | export default axiosInstance;
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/svg/share.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/users/managers.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.base_user import BaseUserManager
2 | from django.utils.translation import ugettext_lazy as _
3 | from django.db import models
4 |
5 |
6 | class stockUserManager(BaseUserManager):
7 | """
8 | Custom user model manager
9 | """
10 | def create_user(self, email, password, **extra_fields):
11 | """
12 | Create and save a User with the given email and password.
13 | """
14 | if not email:
15 | raise ValueError(_('The Email must be set'))
16 | email = self.normalize_email(email)
17 | user = self.model(email=email, **extra_fields)
18 | user.set_password(password)
19 | user.save()
20 | return user
21 |
22 | def create_superuser(self, email, password, **extra_fields):
23 | """
24 | Create and save a SuperUser with the given email and password.
25 | """
26 | extra_fields.setdefault('is_staff', True)
27 | extra_fields.setdefault('is_superuser', True)
28 | extra_fields.setdefault('is_active', True)
29 |
30 | if extra_fields.get('is_staff') is not True:
31 | raise ValueError(_('Superuser must have is_staff=True.'))
32 | if extra_fields.get('is_superuser') is not True:
33 | raise ValueError(_('Superuser must have is_superuser=True.'))
34 | return self.create_user(email, password, **extra_fields)
--------------------------------------------------------------------------------
/wms/stock/migrations/0005_auto_20200216_1442.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.3 on 2020-02-16 14:42
2 |
3 | from django.conf import settings
4 | from django.db import migrations, models
5 | import django.db.models.deletion
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | dependencies = [
11 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12 | ('stock', '0004_auto_20200215_1558'),
13 | ]
14 |
15 | operations = [
16 | migrations.AlterField(
17 | model_name='customer',
18 | name='firstname',
19 | field=models.CharField(max_length=50, verbose_name='Firstname'),
20 | ),
21 | migrations.AlterField(
22 | model_name='customer',
23 | name='lastname',
24 | field=models.CharField(max_length=50, verbose_name='Lastname'),
25 | ),
26 | migrations.CreateModel(
27 | name='Shipment',
28 | fields=[
29 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
30 | ('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='stock.Customer')),
31 | ('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='stock.Product')),
32 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
33 | ],
34 | ),
35 | ]
36 |
--------------------------------------------------------------------------------
/wms/requirements.txt:
--------------------------------------------------------------------------------
1 | algoliasearch==2.2.0
2 | aniso8601==7.0.0
3 | asgiref==3.2.3
4 | astroid==2.3.3
5 | autopep8==1.4.4
6 | awsebcli==3.18.0
7 | beautifulsoup4==4.8.1
8 | boto3==1.11.15
9 | botocore==1.15.41
10 | cement==2.8.2
11 | certifi==2019.11.28
12 | cffi==1.13.2
13 | chardet==3.0.4
14 | colorama==0.4.3
15 | cryptography==2.8
16 | Django==3.0
17 | django-filter==2.2.0
18 | django-graphql-jwt==0.3.1
19 | djangorestframework==3.10.3
20 | docutils==0.15.2
21 | elasticsearch==7.5.1
22 | elasticsearch-dsl==7.1.0
23 | et-xmlfile==1.0.1
24 | future==0.16.0
25 | graphene==2.1.8
26 | graphene-django==2.10.0
27 | graphql-core==2.3.1
28 | graphql-relay==2.0.1
29 | gunicorn==20.0.4
30 | idna==2.7
31 | isort==4.3.21
32 | jdcal==1.4.1
33 | jmespath==0.9.4
34 | jwcrypto==0.6.0
35 | KalturaApiClient==15.14.0
36 | lazy-object-proxy==1.4.3
37 | lxml==4.4.1
38 | mccabe==0.6.1
39 | numpy==1.18.1
40 | openpyxl==3.0.3
41 | pandas==1.0.1
42 | pathspec==0.5.9
43 | Pillow==7.1.2
44 | promise==2.3
45 | pycodestyle==2.5.0
46 | pycparser==2.19
47 | PyJWT==1.7.1
48 | pylint==2.4.4
49 | pyperclip==1.7.0
50 | pypiwin32==223
51 | python-dateutil==2.8.0
52 | pytz==2019.3
53 | pywin32==227
54 | PyYAML==5.3.1
55 | requests==2.20.1
56 | requests-toolbelt==0.9.1
57 | Rx==1.6.1
58 | s3transfer==0.3.3
59 | selenium==3.141.0
60 | semantic-version==2.5.0
61 | singledispatch==3.4.0.3
62 | six==1.14.0
63 | soupsieve==1.9.5
64 | sqlparse==0.3.0
65 | termcolor==1.1.0
66 | urllib3==1.24.3
67 | virtualenv==16.7.7
68 | wcwidth==0.1.9
69 | wrapt==1.11.2
70 |
--------------------------------------------------------------------------------
/wms-frontend/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './App.css';
3 | import HomePage from './Pages/Homepage';
4 | import ProductsPage from './Pages/ProductsPage';
5 | import ShipmentsPage from './Pages/ShipmentsPage';
6 | import LoginPage from './Pages/LoginPage';
7 | import Customers from './Pages/Customers';
8 | import CreateShipmentPage from './Pages/CreateShipmentPage';
9 | import CreateProductPage from './Pages/CreateProductPage';
10 | import CreateCustomerPage from './Pages/CreateCustomerPage';
11 | import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
12 |
13 | function App() {
14 | return (
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | );
51 | }
52 |
53 | export default App;
54 |
--------------------------------------------------------------------------------
/wms-frontend/src/common/Header.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router-dom';
3 |
4 |
5 | const Header = () => {
6 | return (
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
46 |
47 |
48 |
49 |
50 |
51 | )
52 | }
53 |
54 |
55 | export default Header;
--------------------------------------------------------------------------------
/wms/users/models.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.contrib.auth.models import AbstractUser
3 | from django.db import models
4 | from .managers import stockUserManager
5 | from stock.models import Warehouse
6 |
7 |
8 | class stockUser(AbstractUser):
9 |
10 | email = models.EmailField(verbose_name="Email Adddress", max_length=255, unique=True)
11 |
12 | USERNAME_FIELD = 'email'
13 | REQUIRED_FIELDS = []
14 |
15 | objects = stockUserManager()
16 |
17 | def __str__(self):
18 | return self.email
19 |
20 |
21 | class Profile(models.Model):
22 | prefix_list = (
23 | ('Mr', 'Mr.'),
24 | ('Mrs', 'Mrs.'),
25 | ('Ms', 'Ms.'),
26 | ('Mis', 'Miss.'),
27 | ('Mx', 'Mx.'),
28 | ('Dr', 'Dr.'),
29 | ('Prf', 'Prof.'),
30 | ('Rv', 'Rev.'),
31 | )
32 |
33 | user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
34 | prefix = models.CharField(verbose_name="Prefix", choices=prefix_list , max_length=5)
35 | firstname = models.CharField(verbose_name="First Name", max_length=100)
36 | lastname = models.CharField(verbose_name="Last Name", max_length=100)
37 | cellphone = models.CharField(verbose_name="Mobile Number", max_length=20)
38 | warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
39 | is_approved = models.BooleanField(verbose_name="Approved user", default=False)
40 |
41 | def __str__(self):
42 | return f'{self.prefix} {self.firstname} {self.lastname}'
43 |
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/img/svg/whatsapp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/wms/users/templates/base.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 |
5 |
6 |
7 | {% block head_title %}{% endblock %}
8 |
9 |
10 |
11 |
12 | {% block extra_head %}
13 | {% endblock %}
14 |
15 |
16 |
17 | {% block body %}
18 |
19 |
20 |
21 | {% block content %}
22 | {% endblock %}
23 | {% endblock %}
24 |
25 |
26 |
27 | {% block extra_body %}
28 | {% endblock %}
29 |
30 |
31 |
32 | {% block extra_js %}
33 | {% endblock extra_js %}
34 |
35 |
36 |
--------------------------------------------------------------------------------
/wms/users/templates/socialaccount/connections.html:
--------------------------------------------------------------------------------
1 | {% extends "socialaccount/base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head_title %}{% trans "Account Connections" %}{% endblock %}
6 |
7 | {% block content %}
8 | {% trans "Account Connections" %}
9 |
10 | {% if form.accounts %}
11 | {% blocktrans %}You can sign in to your account using any of the following third party accounts:{% endblocktrans %}
12 |
13 |
14 |
41 |
42 | {% else %}
43 | {% trans 'You currently have no social network accounts connected to this account.' %}
44 | {% endif %}
45 |
46 | {% trans 'Add a 3rd Party Account' %}
47 |
48 |
49 | {% include "socialaccount/snippets/provider_list.html" with process="connect" %}
50 |
51 |
52 | {% include "socialaccount/snippets/login_extra.html" %}
53 |
54 | {% endblock %}
55 |
--------------------------------------------------------------------------------
/wms/Readme.md:
--------------------------------------------------------------------------------
1 | ###### Warehouse Management Software Built With React and Django
2 |
3 | **Backend - Django**
4 |
5 | 1. Clone this repository
6 | 2. `git clone https://github.com/Nyamador/wms`
7 | 3. Create a virtual environment with virtualenv `virtual {your-virtual-environment-name}`
8 | 4. Activate your virtual environment , from your virtual environment root `.\Scripts\activate`
9 | 5. Go back to your project root where the `requirements.txt` lives
10 | 6. Install dependencies `pip install -r requirements.txt`
11 | 7. `cd wms`
12 | 8. Run your migrations => `manage.py makemigrations` then `manage.py migrate`
13 | 9. Run the project `python manage.py runserver`
14 |
15 |
16 | **Frontend - Reaact**
17 | 1. cd `wms-frontend`
18 | 2. If you prefer using `npm` -> Run `npm i` or `yarn add` for Yarn
19 |
20 | **Redis - Caching**
21 | 1. Download Redis From The Official Website ( You need Redis > 3.x.x )
22 | 2. If you run windows download the Binary (Not Official) from this link [Redis Windows Binary 3.2.100](https://github-production-release-asset-2e65be.s3.amazonaws.com/3402186/bb47f4a2-3fac-11e6-9e71-9a4261699bd5?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20200609%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20200609T073851Z&X-Amz-Expires=300&X-Amz-Signature=46ff45abdcac77c3992179d4f5e4d8af73a988638f04fa93d5c4e40f456506fe&X-Amz-SignedHeaders=host&actor_id=48738520&repo_id=3402186&response-content-disposition=attachment%3B%20filename%3DRedis-x64-3.2.100.zip&response-content-type=application%2Foctet-stream)
23 | 3. If you want be able to run the Redis-Server with `redis-server` without having to open the \bin directory of the binary everytime, add it to your path. You should be able to start the server with `redis-server`.
24 | 4. To verify the server is running open another terminal window and run `redis-cli`, then enter `PING`. You should see `PONG` on your screen.
--------------------------------------------------------------------------------
/wms-frontend/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 | You need to enable JavaScript to run this app.
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/wms/stock/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.3 on 2020-02-15 10:38
2 |
3 | from django.db import migrations, models
4 | import uuid
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | initial = True
10 |
11 | dependencies = [
12 | ]
13 |
14 | operations = [
15 | migrations.CreateModel(
16 | name='Customer',
17 | fields=[
18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19 | ('firstname', models.CharField(max_length=50, verbose_name='Customer Name')),
20 | ('lastname', models.CharField(max_length=50, verbose_name='Customer Name')),
21 | ('email', models.EmailField(max_length=100, verbose_name='Email Address')),
22 | ],
23 | ),
24 | migrations.CreateModel(
25 | name='Product',
26 | fields=[
27 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
28 | ('name', models.CharField(max_length=300, verbose_name='Product Name')),
29 | ('quantity', models.PositiveIntegerField(verbose_name='Product Quantity')),
30 | ('sku', models.CharField(max_length=50, verbose_name='Stock Keeping Unit')),
31 | ('date', models.DateField(auto_now_add=True, verbose_name='Date Created')),
32 | ],
33 | ),
34 | migrations.CreateModel(
35 | name='Warehouse',
36 | fields=[
37 | ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
38 | ('name', models.CharField(max_length=300, verbose_name='Warehouse name')),
39 | ('location', models.CharField(max_length=300, verbose_name='Warehouse Location')),
40 | ],
41 | ),
42 | ]
43 |
--------------------------------------------------------------------------------
/wms/stock/templates/stock/CustomerCreation.html:
--------------------------------------------------------------------------------
1 | {% extends 'pages/_base.html' %}
2 | {% load widget_tweaks %}
3 |
4 |
5 |
6 | {% block content %}
7 |
23 |
24 |
55 | {% endblock content %}
--------------------------------------------------------------------------------
/wms/stock/templates/stock/customer_update_form.html:
--------------------------------------------------------------------------------
1 | {% extends 'pages/_base.html' %}
2 | {% load widget_tweaks %}
3 |
4 | {% block content %}
5 |
6 |
7 |
23 |
24 |
25 |
58 | {% endblock content %}
59 |
--------------------------------------------------------------------------------
/wms/users/templates/account/password_reset.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load widget_tweaks %}
3 | {% load i18n %}
4 | {% load account %}
5 |
6 | {% block head_title %}{% trans "Password Reset" %}{% endblock %}
7 |
8 | {% block content %}
9 |
10 | {% trans "Password Reset" %}
11 | {% if user.is_authenticated %}
12 | {% include "account/snippets/already_logged_in.html" %}
13 | {% endif %}
14 |
15 | {% trans "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}
16 |
17 |
40 |
41 | {% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %}
42 | {% endblock %}
43 |
--------------------------------------------------------------------------------
/wms-frontend/src/common/Table.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Table = ({data, editable, list}) => {
4 | return (
5 |
6 |
7 |
8 |
14 |
15 |
16 |
17 | { data.map( item =>
18 | (
19 |
20 |
21 | {item}
22 |
23 |
24 | )
25 | )
26 | }
27 |
28 |
29 |
30 |
31 | {
32 | list.map(
33 | datapoint =>
34 |
35 |
36 | {datapoint.firstname || datapoint.name || datapoint.destination}
37 |
38 |
39 | {datapoint.lastname || datapoint.quantity }
40 |
41 |
42 | {datapoint.email || datapoint.sku || datapoint.product}
43 |
44 |
45 | )
46 | }
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | );
55 | };
56 |
57 | export default Table;
58 |
--------------------------------------------------------------------------------
/wms/users/templates/account/password_change.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load widget_tweaks %}
3 |
4 | {% load i18n %}
5 |
6 | {% block head_title %}{% trans "Change Password" %}{% endblock %}
7 | {% if messages %}
8 | {% for message in messages %}
9 |
10 | {{message}}
11 |
12 | {% endfor %}
13 | {% endif %}
14 |
15 |
16 | {% block content %}
17 | {% trans "Change Password" %}
18 |
19 |
59 | {% endblock %}
60 |
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/libs/highlightjs/styles/vs2015.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Visual Studio 2015 dark style
3 | * Author: Nicolas LLOBERA
4 | */
5 |
6 | .hljs {
7 | display: block;
8 | overflow-x: auto;
9 | padding: 0.5em;
10 | background: #1E1E1E;
11 | color: #DCDCDC;
12 | }
13 |
14 | .hljs-keyword,
15 | .hljs-literal,
16 | .hljs-symbol,
17 | .hljs-name {
18 | color: #569CD6;
19 | }
20 | .hljs-link {
21 | color: #569CD6;
22 | text-decoration: underline;
23 | }
24 |
25 | .hljs-built_in,
26 | .hljs-type {
27 | color: #4EC9B0;
28 | }
29 |
30 | .hljs-number,
31 | .hljs-class {
32 | color: #B8D7A3;
33 | }
34 |
35 | .hljs-string,
36 | .hljs-meta-string {
37 | color: #D69D85;
38 | }
39 |
40 | .hljs-regexp,
41 | .hljs-template-tag {
42 | color: #9A5334;
43 | }
44 |
45 | .hljs-subst,
46 | .hljs-function,
47 | .hljs-title,
48 | .hljs-params,
49 | .hljs-formula {
50 | color: #DCDCDC;
51 | }
52 |
53 | .hljs-comment,
54 | .hljs-quote {
55 | color: #57A64A;
56 | font-style: italic;
57 | }
58 |
59 | .hljs-doctag {
60 | color: #608B4E;
61 | }
62 |
63 | .hljs-meta,
64 | .hljs-meta-keyword,
65 | .hljs-tag {
66 | color: #9B9B9B;
67 | }
68 |
69 | .hljs-variable,
70 | .hljs-template-variable {
71 | color: #BD63C5;
72 | }
73 |
74 | .hljs-attr,
75 | .hljs-attribute,
76 | .hljs-builtin-name {
77 | color: #9CDCFE;
78 | }
79 |
80 | .hljs-section {
81 | color: gold;
82 | }
83 |
84 | .hljs-emphasis {
85 | font-style: italic;
86 | }
87 |
88 | .hljs-strong {
89 | font-weight: bold;
90 | }
91 |
92 | /*.hljs-code {
93 | font-family:'Monospace';
94 | }*/
95 |
96 | .hljs-bullet,
97 | .hljs-selector-tag,
98 | .hljs-selector-id,
99 | .hljs-selector-class,
100 | .hljs-selector-attr,
101 | .hljs-selector-pseudo {
102 | color: #D7BA7D;
103 | }
104 |
105 | .hljs-addition {
106 | background-color: #144212;
107 | display: inline-block;
108 | width: 100%;
109 | }
110 |
111 | .hljs-deletion {
112 | background-color: #600;
113 | display: inline-block;
114 | width: 100%;
115 | }
116 |
--------------------------------------------------------------------------------
/wms/stock/models.py:
--------------------------------------------------------------------------------
1 | import uuid
2 | from django.db import models
3 | from django.conf import settings
4 |
5 | class Warehouse(models.Model):
6 | id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
7 | name = models.CharField(verbose_name="Warehouse name", blank=False, null=False, max_length=300)
8 | location = models.CharField(verbose_name="Warehouse Location",max_length=300, null=False, blank=False)
9 |
10 | def __str__(self):
11 | return self.name
12 |
13 | # class Warehous(models.Model):
14 |
15 |
16 | class Product(models.Model):
17 | user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
18 | warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
19 | name = models.CharField(verbose_name="Product Name", max_length=300)
20 | price = models.DecimalField(verbose_name="Unit Price", max_digits=10, decimal_places=2)
21 | quantity = models.PositiveIntegerField(verbose_name="Product Quantity")
22 | sku = models.CharField(verbose_name="Stock Keeping Unit", max_length=50, null=False, blank=False, unique=True)
23 | date = models.DateField(verbose_name="Date Created", auto_now_add=True)
24 |
25 |
26 | def __str__(self):
27 | return self.name
28 |
29 |
30 | class Customer(models.Model):
31 | firstname = models.CharField("Firstname", max_length=50)
32 | lastname = models.CharField("Lastname", max_length=50)
33 | email = models.EmailField(verbose_name="Email Address", max_length=100)
34 |
35 | def __str__(self):
36 | return f'{self.firstname} {self.lastname}'
37 |
38 |
39 | class Shipment(models.Model):
40 | user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
41 | customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
42 | destination = models.CharField(verbose_name="Destination of Shipment", max_length=100, null=False, blank=False)
43 | product = models.ForeignKey(Product, on_delete=models.CASCADE)
44 | quantity = models.PositiveIntegerField(verbose_name="Product Quantity")
45 |
46 |
47 | def __str__(self):
48 | return f'Shipment #{self.id}'
--------------------------------------------------------------------------------
/wms-frontend/src/Pages/CreateCustomerPage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Header from '../common/Header';
3 |
4 |
5 | const CreateCustomerPage = () => {
6 | return(
7 | <>
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | Add a Customer
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
61 |
62 |
63 |
64 |
65 | >
66 | )
67 | }
68 |
69 |
70 | export default CreateCustomerPage;
--------------------------------------------------------------------------------
/wms/stock/templates/stock/customer_list.html:
--------------------------------------------------------------------------------
1 | {% extends 'pages/_base.html' %}
2 |
3 | {% block content %}
4 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | #
26 |
27 |
28 | Firstname
29 |
30 |
31 | Lastname
32 |
33 |
34 | Email
35 |
36 |
37 | Delete
38 |
39 |
40 | Edit
41 |
42 |
43 |
44 |
45 | {% for customer in customers %}
46 |
47 | {{ customer.id }}
48 | {{ customer.firstname }}
49 | {{ customer.lastname }}
50 | {{ customer.email }}
51 |
52 |
53 |
54 | {% endfor %}
55 |
56 |
57 |
58 |
59 |
60 | {% endblock content %}
--------------------------------------------------------------------------------
/wms/stock/templates/stock/product_list.html:
--------------------------------------------------------------------------------
1 | {% extends 'pages/_base.html' %}
2 |
3 | {% block content %}
4 |
19 |
20 |
22 |
23 |
24 |
25 |
26 | #
27 |
28 |
29 | Name
30 |
31 |
32 | Quantity
33 |
34 |
35 | SKU
36 |
37 |
38 | Delete
39 |
40 |
41 | Edit
42 |
43 |
44 |
45 |
46 | {% for product in products %}
47 |
48 | {{ product.id }}
49 | {{ product.name }}
50 | {{ product.quantity }}
51 | {{ product.sku }}
52 |
53 |
54 |
55 | {% endfor %}
56 |
57 |
58 |
59 |
60 |
61 | {% endblock content %}
--------------------------------------------------------------------------------
/wms/stock/templates/stock/product_update_form.html:
--------------------------------------------------------------------------------
1 | {% extends 'pages/_base.html' %}
2 | {% load widget_tweaks %}
3 |
4 | {% block content %}
5 |
6 |
7 |
23 |
24 |
25 |
65 | {% endblock content %}
66 |
--------------------------------------------------------------------------------
/wms/stock/templates/stock/ProductCreation.html:
--------------------------------------------------------------------------------
1 | {% extends 'pages/_base.html' %}
2 | {% load widget_tweaks %}
3 |
4 | {% block content %}
5 |
21 |
22 |
23 |
63 |
64 | {% endblock content %}
65 |
--------------------------------------------------------------------------------
/wms/stock/templates/stock/shipment_update_form.html:
--------------------------------------------------------------------------------
1 | {% extends 'pages/_base.html' %}
2 | {% load widget_tweaks %}
3 |
4 | {% block content %}
5 |
6 |
7 |
23 |
24 |
25 |
65 | {% endblock content %}
66 |
--------------------------------------------------------------------------------
/wms/stock/templates/stock/shipment_list.html:
--------------------------------------------------------------------------------
1 | {% extends 'pages/_base.html' %}
2 |
3 | {% block content %}
4 |
19 |
20 |
22 |
23 |
24 |
25 |
26 | #
27 |
28 |
29 | Customer
30 |
31 |
32 | Product
33 |
34 |
35 | Quantity
36 |
37 |
38 | Destination
39 |
40 |
41 | Delete
42 |
43 |
44 | Update
45 |
46 |
47 |
48 |
49 | {% for shipment in shipments %}
50 |
51 | {{ shipment.id }}
52 | {{ shipment.customer }}
53 | {{ shipment.product }}
54 | {{ shipment.quantity }}
55 | {{ shipment.destination }}
56 |
57 |
58 |
59 | {% endfor %}
60 |
61 |
62 |
63 |
64 |
65 | {% endblock content %}
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | ###### Warehouse Management Software Built With React and Django
2 |
3 |
4 |
5 | ### Dashboard Homepage
6 | 
7 |
8 | ### Shipment Creation Page
9 | 
10 |
11 | 
12 |
13 | **Backend - Django**
14 |
15 | 1. Clone this repository
16 | 2. `git clone https://github.com/Nyamador/wms`
17 | 3. Create a virtual environment with virtualenv `virtual {your-virtual-environment-name}`
18 | 4. Activate your virtual environment , from your virtual environment root `.\Scripts\activate`
19 | 5. Go back to your project root where the `requirements.txt` lives
20 | 6. Install dependencies `pip install -r requirements.txt`
21 | 7. `cd wms`
22 | 8. Run your migrations => `manage.py makemigrations` then `manage.py migrate`
23 | 9. Run the project `python manage.py runserver`
24 |
25 |
26 | **Frontend - Reaact**
27 | 1. cd `wms-frontend`
28 | 2. If you prefer using `npm` -> Run `npm i` or `yarn add` for Yarn
29 |
30 | **Redis - Caching**
31 | 1. Download Redis From The Official Website ( You need Redis > 3.x.x )
32 | 2. If you run windows download the Binary (Not Official) from this link [Redis Windows Binary 3.2.100](https://github-production-release-asset-2e65be.s3.amazonaws.com/3402186/bb47f4a2-3fac-11e6-9e71-9a4261699bd5?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20200609%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20200609T073851Z&X-Amz-Expires=300&X-Amz-Signature=46ff45abdcac77c3992179d4f5e4d8af73a988638f04fa93d5c4e40f456506fe&X-Amz-SignedHeaders=host&actor_id=48738520&repo_id=3402186&response-content-disposition=attachment%3B%20filename%3DRedis-x64-3.2.100.zip&response-content-type=application%2Foctet-stream)
33 | 3. If you want be able to run the Redis-Server with `redis-server` without having to open the \bin directory of the binary everytime, add it to your path. You should be able to start the server with `redis-server`.
34 | 4. To verify the server is running open another terminal window and run `redis-cli`, then enter `PING`. You should see `PONG` on your screen.
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # virtualenv
10 | env/
11 | .env/
12 |
13 | # Distribution / packaging
14 | .Python
15 | build/
16 | develop-eggs/
17 | dist/
18 | downloads/
19 | eggs/
20 | .eggs/
21 | lib/
22 | lib64/
23 | parts/
24 | sdist/
25 | var/
26 | wheels/
27 | pip-wheel-metadata/
28 | share/python-wheels/
29 | *.egg-info/
30 | .installed.cfg
31 | *.egg
32 | MANIFEST
33 |
34 | # PyInstaller
35 | # Usually these files are written by a python script from a template
36 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
37 | *.manifest
38 | *.spec
39 |
40 | # Installer logs
41 | pip-log.txt
42 | pip-delete-this-directory.txt
43 |
44 | # Unit test / coverage reports
45 | htmlcov/
46 | .tox/
47 | .nox/
48 | .coverage
49 | .coverage.*
50 | .cache
51 | nosetests.xml
52 | coverage.xml
53 | *.cover
54 | *.py,cover
55 | .hypothesis/
56 | .pytest_cache/
57 |
58 | # Translations
59 | *.mo
60 | *.pot
61 |
62 | # Django stuff:
63 | *.log
64 | local_settings.py
65 | db.sqlite3
66 | db.sqlite3-journal
67 |
68 | # Flask stuff:
69 | instance/
70 | .webassets-cache
71 |
72 | # Scrapy stuff:
73 | .scrapy
74 |
75 | # Sphinx documentation
76 | docs/_build/
77 |
78 | # PyBuilder
79 | target/
80 |
81 | # Jupyter Notebook
82 | .ipynb_checkpoints
83 |
84 | # IPython
85 | profile_default/
86 | ipython_config.py
87 |
88 | # pyenv
89 | .python-version
90 |
91 | # pipenv
92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
95 | # install all needed dependencies.
96 | #Pipfile.lock
97 |
98 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
99 | __pypackages__/
100 |
101 | # Celery stuff
102 | celerybeat-schedule
103 | celerybeat.pid
104 |
105 | # SageMath parsed files
106 | *.sage.py
107 |
108 | # Environments
109 | .env
110 | .venv
111 | env/
112 | venv/
113 | ENV/
114 | env.bak/
115 | venv.bak/
116 |
117 | # Spyder project settings
118 | .spyderproject
119 | .spyproject
120 |
121 | # Rope project settings
122 | .ropeproject
123 |
124 | # mkdocs documentation
125 | /site
126 |
127 | # mypy
128 | .mypy_cache/
129 | .dmypy.json
130 | dmypy.json
131 |
132 | # Pyre type checker
133 | .pyre/
134 |
--------------------------------------------------------------------------------
/wms-frontend/src/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/wms-frontend/src/Pages/CreateProductPage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Header from '../common/Header';
3 | import InputElement from '../common/InputElement';
4 |
5 |
6 |
7 | const CreateProductPage = () => {
8 |
9 | return (
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | Add a product
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | )
81 | }
82 |
83 |
84 | export default CreateProductPage;
--------------------------------------------------------------------------------
/wms/users/templates/account/signup.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load widget_tweaks %}
3 | {% load static %}
4 |
5 | {% load i18n %}
6 |
7 | {% block head_title %}{% trans "Signup" %}{% endblock %}
8 | {% block extra_head %}
9 |
10 | {% endblock extra_head %}
11 |
12 |
13 | {% block content %}
14 | {% trans "Sign Up" %}
15 |
16 | {% if form.non_field_errors %}
17 | {% for error in form.non_field_errors %}
18 |
19 | {{ error }}
20 |
21 | ×
22 |
23 |
24 | {% endfor %}
25 | {% endif %}
26 |
54 |
55 | {% endblock %}
56 |
57 |
58 | {% block extra_js %}
59 |
60 | {% endblock extra_js %}
--------------------------------------------------------------------------------
/wms/users/templates/account/password_reset_from_key.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load widget_tweaks %}
3 |
4 | {% load i18n %}
5 | {% block head_title %}{% trans "Change Password" %}{% endblock %}
6 |
7 | {% block content %}
8 | {% if token_fail %}{% trans "Bad Token" %}{% else %}{% trans "Change Password" %}{% endif %}
9 |
10 | {% if token_fail %}
11 | {% url 'account_reset_password' as passwd_reset_url %}
12 | {% blocktrans %}The password reset link was invalid, possibly because it has already been used. Please request a new password reset .{% endblocktrans %}
13 | {% else %}
14 | {% if form %}
15 |
46 | {% else %}
47 | {% trans 'Your password is now changed.' %}
48 | {% endif %}
49 | {% endif %}
50 | {% endblock %}
51 |
--------------------------------------------------------------------------------
/wms-frontend/README.md:
--------------------------------------------------------------------------------
1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
2 |
3 | ## Available Scripts
4 |
5 | In the project directory, you can run:
6 |
7 | ### `yarn start`
8 |
9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
11 |
12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console.
14 |
15 | ### `yarn test`
16 |
17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
19 |
20 | ### `yarn build`
21 |
22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance.
24 |
25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed!
27 |
28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
29 |
30 | ### `yarn eject`
31 |
32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
33 |
34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
35 |
36 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
37 |
38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
39 |
40 | ## Learn More
41 |
42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
43 |
44 | To learn React, check out the [React documentation](https://reactjs.org/).
45 |
46 | ### Code Splitting
47 |
48 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
49 |
50 | ### Analyzing the Bundle Size
51 |
52 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
53 |
54 | ### Making a Progressive Web App
55 |
56 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
57 |
58 | ### Advanced Configuration
59 |
60 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
61 |
62 | ### Deployment
63 |
64 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
65 |
66 | ### `yarn build` fails to minify
67 |
68 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
69 |
--------------------------------------------------------------------------------
/wms/users/templates/account/email.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load widget_tweaks %}
3 |
4 |
5 | {% load i18n %}
6 |
7 | {% block head_title %}{% trans "Account" %}{% endblock %}
8 |
9 | {% block content %}
10 | {% trans "E-mail Addresses" %}
11 | {% if user.emailaddress_set.all %}
12 | {% trans 'The following e-mail addresses are associated with your account:' %}
13 |
14 |
43 |
44 | {% else %}
45 | {% trans 'Warning:'%} {% trans "You currently do not have any e-mail address set up. You should really add an e-mail address so you can receive notifications, reset your password, etc." %}
46 |
47 | {% endif %}
48 |
49 |
50 | {% trans "Add E-mail Address" %}
51 |
52 |
65 |
66 | {% endblock %}
67 |
68 |
69 | {% block extra_body %}
70 |
83 | {% endblock %}
84 |
--------------------------------------------------------------------------------
/wms/stock/templates/stock/ShipmentCreation.html:
--------------------------------------------------------------------------------
1 | {% extends 'pages/_base.html' %}
2 | {% load widget_tweaks %}
3 |
4 |
5 | {% block content %}
6 |
22 |
23 |
69 |
70 |
71 | {% endblock content %}
--------------------------------------------------------------------------------
/wms-frontend/src/Pages/LoginPage.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import {Redirect} from 'react-router-dom'
3 | import axiosInstance from '../axiosInstance';
4 |
5 | const LoginPage = () => {
6 | const [email, setEmail] = useState('');
7 | const [password, setPassword] = useState('');
8 | const [isLoggedIn, setisLoggedIn] = useState(false)
9 |
10 | useEffect(() => {
11 |
12 | });
13 |
14 | const handleEmailChange = (event) => {
15 | setEmail(event.target.value);
16 | };
17 |
18 | const handlePasswordChange = (event) => {
19 | setPassword(event.target.value);
20 | };
21 |
22 | const handleSubmit = async (event) => {
23 | event.preventDefault();
24 | try{
25 | const response = await axiosInstance.post('/api/token',{
26 | email: email,
27 | password: password
28 | });
29 | axiosInstance.defaults.headers['Authorization'] = "JWT" + response.data.access;
30 | localStorage.setItem('access_token', response.data.access);
31 | localStorage.setItem('refresh_token', response.data.refresh);
32 | setisLoggedIn(true);
33 | }catch(error){
34 | setisLoggedIn(false);
35 | throw error;
36 | }
37 | };
38 |
39 | return isLoggedIn ? : (
40 |
41 |
42 |
43 |
Sign In
44 |
45 |
107 |
108 |
109 |
110 | );
111 | };
112 |
113 | export default LoginPage;
114 |
--------------------------------------------------------------------------------
/wms/users/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.0.3 on 2020-02-15 10:38
2 |
3 | from django.conf import settings
4 | import django.contrib.auth.validators
5 | from django.db import migrations, models
6 | import django.db.models.deletion
7 | import django.utils.timezone
8 |
9 |
10 | class Migration(migrations.Migration):
11 |
12 | initial = True
13 |
14 | dependencies = [
15 | ('auth', '0011_update_proxy_permissions'),
16 | ('stock', '0001_initial'),
17 | ]
18 |
19 | operations = [
20 | migrations.CreateModel(
21 | name='stockUser',
22 | fields=[
23 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
24 | ('password', models.CharField(max_length=128, verbose_name='password')),
25 | ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
26 | ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
27 | ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
28 | ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
29 | ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
30 | ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
31 | ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
32 | ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
33 | ('email', models.EmailField(max_length=255, unique=True, verbose_name='Email Adddress')),
34 | ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
35 | ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
36 | ],
37 | options={
38 | 'verbose_name': 'user',
39 | 'verbose_name_plural': 'users',
40 | 'abstract': False,
41 | },
42 | ),
43 | migrations.CreateModel(
44 | name='Profile',
45 | fields=[
46 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
47 | ('photo', models.ImageField(default='profilep.jpg', max_length=200, upload_to='profile/%Y/%m/%d/', verbose_name='Profile Photo')),
48 | ('prefix', models.CharField(choices=[('Mr', 'Mr.'), ('Mrs', 'Mrs.'), ('Ms', 'Ms.'), ('Mis', 'Miss.'), ('Mx', 'Mx.'), ('Dr', 'Dr.'), ('Prf', 'Prof.'), ('Rv', 'Rev.')], max_length=5, verbose_name='Prefix')),
49 | ('firstname', models.CharField(max_length=100, verbose_name='First Name')),
50 | ('lastname', models.CharField(max_length=100, verbose_name='Last Name')),
51 | ('cellphone', models.CharField(max_length=20, verbose_name='Mobile Number')),
52 | ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
53 | ('warehouse', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='stock.Warehouse')),
54 | ],
55 | ),
56 | ]
57 |
--------------------------------------------------------------------------------
/wms-frontend/src/Pages/CreateShipmentPage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Header from '../common/Header';
3 |
4 |
5 | const CreateShipmentPage = () => {
6 | return (
7 | <>
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Create A New Shipment
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | >
108 |
109 | );
110 | }
111 |
112 | export default CreateShipmentPage;
--------------------------------------------------------------------------------
/wms/stock/views.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | # from django.core.cache.backends.base import DEFAULT_TIMEOUT
3 | from django.shortcuts import render,reverse,redirect
4 | from django.views.generic.edit import CreateView, DeleteView, UpdateView
5 | from django.views.generic import ListView
6 | from django.contrib.auth.mixins import LoginRequiredMixin
7 | from django.contrib.auth.decorators import login_required
8 | from django.contrib.messages.views import SuccessMessageMixin
9 | from django.contrib import messages
10 | from django.views.decorators.cache import cache_page
11 |
12 | from .forms import ProductCreationForm, CustomerCreationForm, ShipmentCreationForm
13 | from .models import Product, Customer, Shipment
14 |
15 |
16 | # CACHE_TTL = getattr(settings, 'CACHE_TTL', DEFAULT_TIMEOUT)
17 |
18 | @login_required()
19 | def ProductCreationView(request, uuid):
20 | # Form processing
21 | if request.method == 'POST':
22 | # Create an instance of the form
23 | form = ProductCreationForm(request.POST)
24 | if form.is_valid():
25 | product = form.save(commit=False)
26 | product.user = request.user
27 | product.warehouse = request.user.profile.warehouse
28 | product.save()
29 | messages.success(request, f'{product.name} was created successfully')
30 | # return redirect(reverse('home'))
31 | form = ProductCreationForm()
32 |
33 | context = {
34 | 'form' : form,
35 | }
36 |
37 | return render(request, 'stock/ProductCreation.html', context)
38 |
39 |
40 | class CustomerCreationView(SuccessMessageMixin, LoginRequiredMixin, CreateView):
41 | template_name = 'stock/CustomerCreation.html'
42 | form_class = CustomerCreationForm
43 | success_url = '/'
44 | success_message = "%(firstname)s was created successfully"
45 |
46 |
47 | class ShipmentCreationView(SuccessMessageMixin, LoginRequiredMixin, CreateView):
48 | template_name = 'stock/ShipmentCreation.html'
49 | form_class = ShipmentCreationForm
50 | success_url = '/'
51 | success_message = "%(id)s was created successfully"
52 |
53 |
54 | # List Views
55 | # @cache_page(CACHE_TTL)
56 | def CachedProductListView(request):
57 | products = Product.objects.all()
58 | context = {
59 | 'products': products
60 | }
61 | return render(request, 'stock/product_list.html', context)
62 |
63 | class ProductListView(ListView, LoginRequiredMixin):
64 | template_name = "stock/ProductListView"
65 | queryset = Product.objects.all()
66 | context_object_name = "products"
67 |
68 | class CustomerListView(ListView, LoginRequiredMixin):
69 | template_name = "stock/CustomerListView"
70 | queryset = Customer.objects.all()
71 | context_object_name = "customers"
72 |
73 | class ShipmentListView(ListView, LoginRequiredMixin):
74 | template_name = "stock/shipment_list.html"
75 | queryset = Shipment.objects.all()
76 | context_object_name = "shipments"
77 |
78 |
79 | #Delete Views
80 | class ProductDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView):
81 | model = Product
82 | context_object_name = "product"
83 | pk_url_kwarg = 'id'
84 | success_url = '/'
85 | template_name = 'stock/ProductDelete.html'
86 | success_message = "%(product)s was deleted successfully"
87 |
88 | class CustomerDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView):
89 | model = Customer
90 | context_object_name = "customer"
91 | pk_url_kwarg = 'id'
92 | success_url = '/'
93 | template_name = 'stock/CustomerDelete.html'
94 | success_message = "%(customer)s was deleted successfully"
95 |
96 | class ShipmentDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView):
97 | model = Shipment
98 | context_object_name = "shipment"
99 | pk_url_kwarg = 'id'
100 | success_url = '/'
101 | template_name = 'stock/ShipmentDelete.html'
102 | success_message = "%(shipment)s was deleted successfully"
103 |
104 |
105 | #Update Views
106 | class ProductUpdateView(SuccessMessageMixin, UpdateView):
107 | model = Product
108 | pk_url_kwarg = 'id'
109 | template_name_suffix = '_update_form'
110 | fields = ['name', 'price', 'sku', 'quantity']
111 | success_url = '/'
112 | success_message = "%(name)s was edited successfully"
113 |
114 | class CustomerUpdateView(SuccessMessageMixin, UpdateView):
115 | model = Customer
116 | pk_url_kwarg = 'id'
117 | template_name_suffix = '_update_form'
118 | fields = ['firstname', 'lastname', 'email']
119 | success_url = '/'
120 | success_message = "%(name)s was edited successfully"
121 |
122 | class ShipmentUpdateView(SuccessMessageMixin, UpdateView):
123 | model = Shipment
124 | pk_url_kwarg = 'id'
125 | template_name_suffix = '_update_form'
126 | fields = ['customer', 'destination', 'product', 'quantity']
127 | success_url = '/'
128 | success_message = "%(name)s was edited successfully"
129 |
--------------------------------------------------------------------------------
/wms/users/templates/account/login.html:
--------------------------------------------------------------------------------
1 | {% extends "account/base.html" %}
2 | {% load widget_tweaks %}
3 |
4 | {% load i18n %}
5 | {% load account socialaccount %}
6 |
7 | {% block head_title %}{% trans "Sign In" %}{% endblock %}
8 |
9 |
10 | {% if messages %}
11 | {% for message in messages %}
12 |
13 | {{message}}
14 |
15 | {% endfor %}
16 | {% endif %}
17 | {% block content %}
18 |
19 |
20 | {% trans "Sign In" %}
21 |
22 | {% get_providers as socialaccount_providers %}
23 |
24 | {% if socialaccount_providers %}
25 | {% blocktrans with site.name as site_name %}Please sign in with one
26 | of your existing third party accounts. Or, sign up
27 | for a {{ site_name }} account and sign in below:{% endblocktrans %}
28 |
29 |
30 |
31 |
32 | {% include "socialaccount/snippets/provider_list.html" with process="login" %}
33 |
34 |
35 |
{% trans 'or' %}
36 |
37 |
38 |
39 | {% include "socialaccount/snippets/login_extra.html" %}
40 |
41 | {% else %}
42 | {% endif %}
43 | {% if form.non_field_errors %}
44 | {% for error in form.non_field_errors %}
45 |
46 | {{ error }}
47 |
48 | ×
49 |
50 |
51 | {% endfor %}
52 | {% endif %}
53 |
54 |
120 | {% endblock %}
121 |
--------------------------------------------------------------------------------
/wms-frontend/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read https://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.0/8 are considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return;
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config);
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA'
47 | );
48 | });
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config);
52 | }
53 | });
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing;
63 | if (installingWorker == null) {
64 | return;
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
75 | );
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration);
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.');
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration);
90 | }
91 | }
92 | }
93 | };
94 | };
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error);
98 | });
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl, {
104 | headers: { 'Service-Worker': 'script' },
105 | })
106 | .then(response => {
107 | // Ensure service worker exists, and that we really are getting a JS file.
108 | const contentType = response.headers.get('content-type');
109 | if (
110 | response.status === 404 ||
111 | (contentType != null && contentType.indexOf('javascript') === -1)
112 | ) {
113 | // No service worker found. Probably a different app. Reload the page.
114 | navigator.serviceWorker.ready.then(registration => {
115 | registration.unregister().then(() => {
116 | window.location.reload();
117 | });
118 | });
119 | } else {
120 | // Service worker found. Proceed as normal.
121 | registerValidSW(swUrl, config);
122 | }
123 | })
124 | .catch(() => {
125 | console.log(
126 | 'No internet connection found. App is running in offline mode.'
127 | );
128 | });
129 | }
130 |
131 | export function unregister() {
132 | if ('serviceWorker' in navigator) {
133 | navigator.serviceWorker.ready
134 | .then(registration => {
135 | registration.unregister();
136 | })
137 | .catch(error => {
138 | console.error(error.message);
139 | });
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/wms/wms/settings.py:
--------------------------------------------------------------------------------
1 | import os
2 | from datetime import timedelta
3 |
4 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
5 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
6 |
7 |
8 | # Quick-start development settings - unsuitable for production
9 | # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
10 |
11 | # SECURITY WARNING: keep the secret key used in production secret!
12 | SECRET_KEY = "%@(mp@w9bs7e7=!n)x88nk)$cc^!m62)ca()6+5r6-f9y$ax6n"
13 |
14 | # SECURITY WARNING: don't run with debug turned on in production!
15 | DEBUG = True
16 |
17 | ALLOWED_HOSTS = ["*"]
18 |
19 |
20 | # Application definition
21 |
22 | INSTALLED_APPS = [
23 | "django.contrib.admin",
24 | "django.contrib.auth",
25 | "django.contrib.contenttypes",
26 | "django.contrib.sessions",
27 | "django.contrib.messages",
28 | "django.contrib.staticfiles",
29 | "django.contrib.sites",
30 | "stock.apps.StockConfig",
31 | "users.apps.UsersConfig",
32 | "pages.apps.PagesConfig",
33 | # 3rd party
34 | "allauth",
35 | "allauth.account",
36 | "allauth.socialaccount",
37 | "widget_tweaks",
38 | "rest_framework",
39 | # 'rest_framework.authtoken',
40 | "corsheaders",
41 | ]
42 |
43 | MIDDLEWARE = [
44 | "corsheaders.middleware.CorsMiddleware",
45 | "django.middleware.security.SecurityMiddleware",
46 | "django.contrib.sessions.middleware.SessionMiddleware",
47 | "django.middleware.common.CommonMiddleware",
48 | "django.middleware.csrf.CsrfViewMiddleware",
49 | "django.contrib.auth.middleware.AuthenticationMiddleware",
50 | "django.contrib.messages.middleware.MessageMiddleware",
51 | "django.middleware.clickjacking.XFrameOptionsMiddleware",
52 | "wms.middleware.HelloMiddleWare.SimpleMiddleware",
53 | ]
54 |
55 | ROOT_URLCONF = "wms.urls"
56 |
57 | TEMPLATES = [
58 | {
59 | "BACKEND": "django.template.backends.django.DjangoTemplates",
60 | "DIRS": [],
61 | "APP_DIRS": True,
62 | "OPTIONS": {
63 | "context_processors": [
64 | "django.template.context_processors.debug",
65 | "django.template.context_processors.request",
66 | "django.contrib.auth.context_processors.auth",
67 | "django.contrib.messages.context_processors.messages",
68 | ],
69 | },
70 | },
71 | ]
72 |
73 | WSGI_APPLICATION = "wms.wsgi.application"
74 |
75 |
76 | # Database
77 | # https://docs.djangoproject.com/en/3.0/ref/settings/#databases
78 |
79 | DATABASES = {
80 | "default": {
81 | "ENGINE": "django.db.backends.sqlite3",
82 | "NAME": os.path.join(BASE_DIR, "db.sqlite3"),
83 | }
84 | }
85 |
86 |
87 | # Password validation
88 | # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
89 |
90 | AUTH_PASSWORD_VALIDATORS = [
91 | {
92 | "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
93 | },
94 | {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",},
95 | {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",},
96 | {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",},
97 | ]
98 |
99 |
100 | # Internationalization
101 | # https://docs.djangoproject.com/en/3.0/topics/i18n/
102 |
103 | LANGUAGE_CODE = "en-us"
104 |
105 | TIME_ZONE = "UTC"
106 |
107 | USE_I18N = True
108 |
109 | USE_L10N = True
110 |
111 | USE_TZ = True
112 |
113 |
114 | # Static files (CSS, JavaScript, Images)
115 | # https://docs.djangoproject.com/en/3.0/howto/static-files/
116 |
117 | STATIC_URL = "/static/"
118 |
119 | MEDIA_URL = "/media/"
120 |
121 | STATIC_ROOT = os.path.join(BASE_DIR, "static_root")
122 |
123 | MEDIA_ROOT = os.path.join(BASE_DIR, "media_root")
124 |
125 |
126 | # AllAuth
127 | AUTHENTICATION_BACKENDS = (
128 | # Needed to login by username in Django admin, regardless of `allauth`
129 | "django.contrib.auth.backends.ModelBackend",
130 | # `allauth` specific authentication methods, such as login by e-mail
131 | "allauth.account.auth_backends.AuthenticationBackend",
132 | )
133 |
134 | SITE_ID = 1
135 |
136 | AUTH_USER_MODEL = "users.stockUser"
137 |
138 | ACCOUNT_USERNAME_REQUIRED = False
139 |
140 | ACCOUNT_AUTHENTICATION_METHOD = "email"
141 |
142 | ACCOUNT_EMAIL_REQUIRED = True
143 |
144 | ACCOUNT_UNIQUE_EMAIL = True
145 |
146 | ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE = False
147 |
148 | if DEBUG:
149 | EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
150 |
151 | # EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
152 |
153 | # EMAIL_HOST = 'smtp.sendgrid.net'
154 |
155 | # EMAIL_PORT = 587
156 |
157 | # EMAIL_SUBJECT_PREFIX = 'Magtickets'
158 |
159 | LOGIN_REDIRECT_URL = "home"
160 |
161 | LOGOUT_REDIRECT_URL = "home"
162 |
163 |
164 | # CORS HEADERS
165 | # CORS_ORIGIN_WHITELIST = ()
166 |
167 | CACHES = {
168 | "default": {
169 | "BACKEND": "django_redis.cache.RedisCache",
170 | "LOCATION": "redis://127.0.0.1:6379/1",
171 | "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
172 | "KEY_PREFIX": "wms",
173 | }
174 | }
175 |
176 | CACHE_TTL = 60 * 15
177 |
178 | CORS_ORIGIN_ALLOW_ALL = True
179 |
180 | # CORS_ORIGIN_ALLOW_ALL = False
181 | CORS_ORIGIN_WHITELIST = ("http://127.0.0.1:3000",)
182 |
183 | REST_FRAMEWORK = {
184 | "DEFAULT_AUTHENTICATION_CLASSES": (
185 | "rest_framework_simplejwt.authentication.JWTAuthentication",
186 | ),
187 | "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.NamespaceVersioning",
188 | }
189 |
190 | SIMPLE_JWT = {
191 | "ACCESS_TOKEN_LIFETIME": timedelta(minutes=5),
192 | "REFRESH_TOKEN_LIFETIME": timedelta(days=14),
193 | "ROTATE_REFRESH_TOKENS": True,
194 | "BLACKLIST_AFTER_ROTATION": False,
195 | "ALGORITHM": "HS256",
196 | "SIGNING_KEY": SECRET_KEY,
197 | "VERIFYING_KEY": None,
198 | "AUTH_HEADER_TYPES": ("JWT",),
199 | "USER_ID_FIELD": "id",
200 | "USER_ID_CLAIM": "user_id",
201 | "AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
202 | "TOKEN_TYPE_CLAIM": "token_type",
203 | }
204 |
205 |
--------------------------------------------------------------------------------
/wms-frontend/src/Pages/Homepage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import '../fonts/feather/feather.min.css';
3 | import Header from '../common/Header';
4 | import {Link} from 'react-router-dom';
5 |
6 |
7 | const Homepage = () => {
8 | return (
9 | <>
10 |
11 |
12 |
13 |
14 |
15 |
16 |
Warehouse Name
17 |
18 |
Welcome - Desmond
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Total Orders
30 |
31 |
32 | GHS 200
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | Total Products
49 |
50 |
51 | 100
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | Customers
67 |
68 |
69 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | Shipments
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | Add New
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | All Shipments
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | Products
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | Add New
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | All Products
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 | Customers
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 | Add New
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 | All Customers
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 | >
170 | );
171 | };
172 |
173 | export default Homepage;
174 |
--------------------------------------------------------------------------------
/wms/pages/templates/pages/index.html:
--------------------------------------------------------------------------------
1 | {% extends 'pages/_base.html' %}
2 | {% load cache %}
3 |
4 |
5 | {% block content %}
6 |
7 |
8 | {% if user.profile.is_approved %}
9 | {% cache 500 username %}
10 |
25 | {% endcache %}
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | Total Orders
39 |
40 |
41 |
42 |
43 | GHS {{ total_stock_price | floatformat }}
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Total Products
70 |
71 |
72 |
73 |
74 | {{ product_count }}
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | Customers
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | {{ customer_count }}
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
141 |
142 |
143 |
151 |
152 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
173 |
174 |
182 |
183 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
206 |
207 |
208 |
216 |
217 |
225 |
226 |
227 |
228 |
229 | {% else %}
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 | Aproval error
239 |
240 |
241 |
242 |
243 | Your account has not been approved.💔
244 |
245 |
246 |
247 |
248 | You might have to contact your administrator.
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 | {% endif %}
262 | {% endblock content %}
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/libs/magnific/magnific.min.css:
--------------------------------------------------------------------------------
1 | /* Magnific Popup CSS */
2 | .mfp-bg {
3 | top: 0;
4 | left: 0;
5 | width: 100%;
6 | height: 100%;
7 | z-index: 1042;
8 | overflow: hidden;
9 | position: fixed;
10 | background: #0b0b0b;
11 | opacity: 0.8; }
12 |
13 | .mfp-wrap {
14 | top: 0;
15 | left: 0;
16 | width: 100%;
17 | height: 100%;
18 | z-index: 1043;
19 | position: fixed;
20 | outline: none !important;
21 | -webkit-backface-visibility: hidden; }
22 |
23 | .mfp-container {
24 | text-align: center;
25 | position: absolute;
26 | width: 100%;
27 | height: 100%;
28 | left: 0;
29 | top: 0;
30 | padding: 0 8px;
31 | box-sizing: border-box; }
32 |
33 | .mfp-container:before {
34 | content: '';
35 | display: inline-block;
36 | height: 100%;
37 | vertical-align: middle; }
38 |
39 | .mfp-align-top .mfp-container:before {
40 | display: none; }
41 |
42 | .mfp-content {
43 | position: relative;
44 | display: inline-block;
45 | vertical-align: middle;
46 | margin: 0 auto;
47 | text-align: left;
48 | z-index: 1045; }
49 |
50 | .mfp-inline-holder .mfp-content,
51 | .mfp-ajax-holder .mfp-content {
52 | width: 100%;
53 | cursor: auto; }
54 |
55 | .mfp-ajax-cur {
56 | cursor: progress; }
57 |
58 | .mfp-zoom-out-cur, .mfp-zoom-out-cur .mfp-image-holder .mfp-close {
59 | cursor: -moz-zoom-out;
60 | cursor: -webkit-zoom-out;
61 | cursor: zoom-out; }
62 |
63 | .mfp-zoom {
64 | cursor: pointer;
65 | cursor: -webkit-zoom-in;
66 | cursor: -moz-zoom-in;
67 | cursor: zoom-in; }
68 |
69 | .mfp-auto-cursor .mfp-content {
70 | cursor: auto; }
71 |
72 | .mfp-close,
73 | .mfp-arrow,
74 | .mfp-preloader,
75 | .mfp-counter {
76 | -webkit-user-select: none;
77 | -moz-user-select: none;
78 | user-select: none; }
79 |
80 | .mfp-loading.mfp-figure {
81 | display: none; }
82 |
83 | .mfp-hide {
84 | display: none !important; }
85 |
86 | .mfp-preloader {
87 | color: #CCC;
88 | position: absolute;
89 | top: 50%;
90 | width: auto;
91 | text-align: center;
92 | margin-top: -0.8em;
93 | left: 8px;
94 | right: 8px;
95 | z-index: 1044; }
96 | .mfp-preloader a {
97 | color: #CCC; }
98 | .mfp-preloader a:hover {
99 | color: #FFF; }
100 |
101 | .mfp-s-ready .mfp-preloader {
102 | display: none; }
103 |
104 | .mfp-s-error .mfp-content {
105 | display: none; }
106 |
107 | button.mfp-close,
108 | button.mfp-arrow {
109 | overflow: visible;
110 | cursor: pointer;
111 | background: transparent;
112 | border: 0;
113 | -webkit-appearance: none;
114 | display: block;
115 | outline: none;
116 | padding: 0;
117 | z-index: 1046;
118 | box-shadow: none;
119 | touch-action: manipulation; }
120 |
121 | button::-moz-focus-inner {
122 | padding: 0;
123 | border: 0; }
124 |
125 | .mfp-close {
126 | width: 44px;
127 | height: 44px;
128 | line-height: 44px;
129 | position: absolute;
130 | right: 0;
131 | top: 0;
132 | text-decoration: none;
133 | text-align: center;
134 | opacity: 0.65;
135 | padding: 0 0 18px 10px;
136 | color: #FFF;
137 | font-style: normal;
138 | font-size: 28px;
139 | font-family: Arial, Baskerville, monospace; }
140 | .mfp-close:hover,
141 | .mfp-close:focus {
142 | opacity: 1; }
143 | .mfp-close:active {
144 | top: 1px; }
145 |
146 | .mfp-close-btn-in .mfp-close {
147 | color: #333; }
148 |
149 | .mfp-image-holder .mfp-close,
150 | .mfp-iframe-holder .mfp-close {
151 | color: #FFF;
152 | right: -6px;
153 | text-align: right;
154 | padding-right: 6px;
155 | width: 100%; }
156 |
157 | .mfp-counter {
158 | position: absolute;
159 | top: 0;
160 | right: 0;
161 | color: #CCC;
162 | font-size: 12px;
163 | line-height: 18px;
164 | white-space: nowrap; }
165 |
166 | .mfp-arrow {
167 | position: absolute;
168 | opacity: 0.65;
169 | margin: 0;
170 | top: 50%;
171 | margin-top: -55px;
172 | padding: 0;
173 | width: 90px;
174 | height: 110px;
175 | -webkit-tap-highlight-color: transparent; }
176 | .mfp-arrow:active {
177 | margin-top: -54px; }
178 | .mfp-arrow:hover,
179 | .mfp-arrow:focus {
180 | opacity: 1; }
181 | .mfp-arrow:before,
182 | .mfp-arrow:after {
183 | content: '';
184 | display: block;
185 | width: 0;
186 | height: 0;
187 | position: absolute;
188 | left: 0;
189 | top: 0;
190 | margin-top: 35px;
191 | margin-left: 35px;
192 | border: medium inset transparent; }
193 | .mfp-arrow:after {
194 | border-top-width: 13px;
195 | border-bottom-width: 13px;
196 | top: 8px; }
197 | .mfp-arrow:before {
198 | border-top-width: 21px;
199 | border-bottom-width: 21px;
200 | opacity: 0.7; }
201 |
202 | .mfp-arrow-left {
203 | left: 0; }
204 | .mfp-arrow-left:after {
205 | border-right: 17px solid #FFF;
206 | margin-left: 31px; }
207 | .mfp-arrow-left:before {
208 | margin-left: 25px;
209 | border-right: 27px solid #3F3F3F; }
210 |
211 | .mfp-arrow-right {
212 | right: 0; }
213 | .mfp-arrow-right:after {
214 | border-left: 17px solid #FFF;
215 | margin-left: 39px; }
216 | .mfp-arrow-right:before {
217 | border-left: 27px solid #3F3F3F; }
218 |
219 | .mfp-iframe-holder {
220 | padding-top: 40px;
221 | padding-bottom: 40px; }
222 | .mfp-iframe-holder .mfp-content {
223 | line-height: 0;
224 | width: 100%;
225 | max-width: 900px; }
226 | .mfp-iframe-holder .mfp-close {
227 | top: -40px; }
228 |
229 | .mfp-iframe-scaler {
230 | width: 100%;
231 | height: 0;
232 | overflow: hidden;
233 | padding-top: 56.25%; }
234 | .mfp-iframe-scaler iframe {
235 | position: absolute;
236 | display: block;
237 | top: 0;
238 | left: 0;
239 | width: 100%;
240 | height: 100%;
241 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
242 | background: #000; }
243 |
244 | /* Main image in popup */
245 | img.mfp-img {
246 | width: auto;
247 | max-width: 100%;
248 | height: auto;
249 | display: block;
250 | line-height: 0;
251 | box-sizing: border-box;
252 | padding: 40px 0 40px;
253 | margin: 0 auto; }
254 |
255 | /* The shadow behind the image */
256 | .mfp-figure {
257 | line-height: 0; }
258 | .mfp-figure:after {
259 | content: '';
260 | position: absolute;
261 | left: 0;
262 | top: 40px;
263 | bottom: 40px;
264 | display: block;
265 | right: 0;
266 | width: auto;
267 | height: auto;
268 | z-index: -1;
269 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
270 | background: #444; }
271 | .mfp-figure small {
272 | color: #BDBDBD;
273 | display: block;
274 | font-size: 12px;
275 | line-height: 14px; }
276 | .mfp-figure figure {
277 | margin: 0; }
278 |
279 | .mfp-bottom-bar {
280 | margin-top: -36px;
281 | position: absolute;
282 | top: 100%;
283 | left: 0;
284 | width: 100%;
285 | cursor: auto; }
286 |
287 | .mfp-title {
288 | text-align: left;
289 | line-height: 18px;
290 | color: #F3F3F3;
291 | word-wrap: break-word;
292 | padding-right: 36px; }
293 |
294 | .mfp-image-holder .mfp-content {
295 | max-width: 100%; }
296 |
297 | .mfp-gallery .mfp-image-holder .mfp-figure {
298 | cursor: pointer; }
299 |
300 | @media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px) {
301 | /**
302 | * Remove all paddings around the image on small screen
303 | */
304 | .mfp-img-mobile .mfp-image-holder {
305 | padding-left: 0;
306 | padding-right: 0; }
307 | .mfp-img-mobile img.mfp-img {
308 | padding: 0; }
309 | .mfp-img-mobile .mfp-figure:after {
310 | top: 0;
311 | bottom: 0; }
312 | .mfp-img-mobile .mfp-figure small {
313 | display: inline;
314 | margin-left: 5px; }
315 | .mfp-img-mobile .mfp-bottom-bar {
316 | background: rgba(0, 0, 0, 0.6);
317 | bottom: 0;
318 | margin: 0;
319 | top: auto;
320 | padding: 3px 5px;
321 | position: fixed;
322 | box-sizing: border-box; }
323 | .mfp-img-mobile .mfp-bottom-bar:empty {
324 | padding: 0; }
325 | .mfp-img-mobile .mfp-counter {
326 | right: 5px;
327 | top: 3px; }
328 | .mfp-img-mobile .mfp-close {
329 | top: 0;
330 | right: 0;
331 | width: 35px;
332 | height: 35px;
333 | line-height: 35px;
334 | background: rgba(0, 0, 0, 0.6);
335 | position: fixed;
336 | text-align: center;
337 | padding: 0; } }
338 |
339 | @media all and (max-width: 900px) {
340 | .mfp-arrow {
341 | -webkit-transform: scale(0.75);
342 | transform: scale(0.75); }
343 | .mfp-arrow-left {
344 | -webkit-transform-origin: 0;
345 | transform-origin: 0; }
346 | .mfp-arrow-right {
347 | -webkit-transform-origin: 100%;
348 | transform-origin: 100%; }
349 | .mfp-container {
350 | padding-left: 6px;
351 | padding-right: 6px; } }
--------------------------------------------------------------------------------
/wms-frontend/src/fonts/feather/feather.min.css:
--------------------------------------------------------------------------------
1 | @font-face{font-family:Feather;src:url(fonts/Feather.ttf?sdxovp) format("truetype");font-weight:400;font-style:normal}.fe{font-family:Feather!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fe-activity:before{content:"\e900"}.fe-airplay:before{content:"\e901"}.fe-alert-circle:before{content:"\e902"}.fe-alert-octagon:before{content:"\e903"}.fe-alert-triangle:before{content:"\e904"}.fe-align-center:before{content:"\e905"}.fe-align-justify:before{content:"\e906"}.fe-align-left:before{content:"\e907"}.fe-align-right:before{content:"\e908"}.fe-anchor:before{content:"\e909"}.fe-aperture:before{content:"\e90a"}.fe-archive:before{content:"\e90b"}.fe-arrow-down:before{content:"\e90c"}.fe-arrow-down-circle:before{content:"\e90d"}.fe-arrow-down-left:before{content:"\e90e"}.fe-arrow-down-right:before{content:"\e90f"}.fe-arrow-left:before{content:"\e910"}.fe-arrow-left-circle:before{content:"\e911"}.fe-arrow-right:before{content:"\e912"}.fe-arrow-right-circle:before{content:"\e913"}.fe-arrow-up:before{content:"\e914"}.fe-arrow-up-circle:before{content:"\e915"}.fe-arrow-up-left:before{content:"\e916"}.fe-arrow-up-right:before{content:"\e917"}.fe-at-sign:before{content:"\e918"}.fe-award:before{content:"\e919"}.fe-bar-chart:before{content:"\e91a"}.fe-bar-chart-2:before{content:"\e91b"}.fe-battery:before{content:"\e91c"}.fe-battery-charging:before{content:"\e91d"}.fe-bell:before{content:"\e91e"}.fe-bell-off:before{content:"\e91f"}.fe-bluetooth:before{content:"\e920"}.fe-bold:before{content:"\e921"}.fe-book:before{content:"\e922"}.fe-book-open:before{content:"\e923"}.fe-bookmark:before{content:"\e924"}.fe-box:before{content:"\e925"}.fe-briefcase:before{content:"\e926"}.fe-calendar:before{content:"\e927"}.fe-camera:before{content:"\e928"}.fe-camera-off:before{content:"\e929"}.fe-cast:before{content:"\e92a"}.fe-check:before{content:"\e92b"}.fe-check-circle:before{content:"\e92c"}.fe-check-square:before{content:"\e92d"}.fe-chevron-down:before{content:"\e92e"}.fe-chevron-left:before{content:"\e92f"}.fe-chevron-right:before{content:"\e930"}.fe-chevron-up:before{content:"\e931"}.fe-chevrons-down:before{content:"\e932"}.fe-chevrons-left:before{content:"\e933"}.fe-chevrons-right:before{content:"\e934"}.fe-chevrons-up:before{content:"\e935"}.fe-chrome:before{content:"\e936"}.fe-circle:before{content:"\e937"}.fe-clipboard:before{content:"\e938"}.fe-clock:before{content:"\e939"}.fe-cloud:before{content:"\e93a"}.fe-cloud-drizzle:before{content:"\e93b"}.fe-cloud-lightning:before{content:"\e93c"}.fe-cloud-off:before{content:"\e93d"}.fe-cloud-rain:before{content:"\e93e"}.fe-cloud-snow:before{content:"\e93f"}.fe-code:before{content:"\e940"}.fe-codepen:before{content:"\e941"}.fe-command:before{content:"\e942"}.fe-compass:before{content:"\e943"}.fe-copy:before{content:"\e944"}.fe-corner-down-left:before{content:"\e945"}.fe-corner-down-right:before{content:"\e946"}.fe-corner-left-down:before{content:"\e947"}.fe-corner-left-up:before{content:"\e948"}.fe-corner-right-down:before{content:"\e949"}.fe-corner-right-up:before{content:"\e94a"}.fe-corner-up-left:before{content:"\e94b"}.fe-corner-up-right:before{content:"\e94c"}.fe-cpu:before{content:"\e94d"}.fe-credit-card:before{content:"\e94e"}.fe-crop:before{content:"\e94f"}.fe-crosshair:before{content:"\e950"}.fe-database:before{content:"\e951"}.fe-delete:before{content:"\e952"}.fe-disc:before{content:"\e953"}.fe-dollar-sign:before{content:"\e954"}.fe-download:before{content:"\e955"}.fe-download-cloud:before{content:"\e956"}.fe-droplet:before{content:"\e957"}.fe-edit:before{content:"\e958"}.fe-edit-2:before{content:"\e959"}.fe-edit-3:before{content:"\e95a"}.fe-external-link:before{content:"\e95b"}.fe-eye:before{content:"\e95c"}.fe-eye-off:before{content:"\e95d"}.fe-facebook:before{content:"\e95e"}.fe-fast-forward:before{content:"\e95f"}.fe-feather:before{content:"\e960"}.fe-file:before{content:"\e961"}.fe-file-minus:before{content:"\e962"}.fe-file-plus:before{content:"\e963"}.fe-file-text:before{content:"\e964"}.fe-film:before{content:"\e965"}.fe-filter:before{content:"\e966"}.fe-flag:before{content:"\e967"}.fe-folder:before{content:"\e968"}.fe-folder-minus:before{content:"\e969"}.fe-folder-plus:before{content:"\e96a"}.fe-gift:before{content:"\e96b"}.fe-git-branch:before{content:"\e96c"}.fe-git-commit:before{content:"\e96d"}.fe-git-merge:before{content:"\e96e"}.fe-git-pull-request:before{content:"\e96f"}.fe-github:before{content:"\e970"}.fe-gitlab:before{content:"\e971"}.fe-globe:before{content:"\e972"}.fe-grid:before{content:"\e973"}.fe-hard-drive:before{content:"\e974"}.fe-hash:before{content:"\e975"}.fe-headphones:before{content:"\e976"}.fe-heart:before{content:"\e977"}.fe-help-circle:before{content:"\e978"}.fe-home:before{content:"\e979"}.fe-image:before{content:"\e97a"}.fe-inbox:before{content:"\e97b"}.fe-info:before{content:"\e97c"}.fe-instagram:before{content:"\e97d"}.fe-italic:before{content:"\e97e"}.fe-layers:before{content:"\e97f"}.fe-layout:before{content:"\e980"}.fe-life-buoy:before{content:"\e981"}.fe-link:before{content:"\e982"}.fe-link-2:before{content:"\e983"}.fe-linkedin:before{content:"\e984"}.fe-list:before{content:"\e985"}.fe-loader:before{content:"\e986"}.fe-lock:before{content:"\e987"}.fe-log-in:before{content:"\e988"}.fe-log-out:before{content:"\e989"}.fe-mail:before{content:"\e98a"}.fe-map:before{content:"\e98b"}.fe-map-pin:before{content:"\e98c"}.fe-maximize:before{content:"\e98d"}.fe-maximize-2:before{content:"\e98e"}.fe-menu:before{content:"\e98f"}.fe-message-circle:before{content:"\e990"}.fe-message-square:before{content:"\e991"}.fe-mic:before{content:"\e992"}.fe-mic-off:before{content:"\e993"}.fe-minimize:before{content:"\e994"}.fe-minimize-2:before{content:"\e995"}.fe-minus:before{content:"\e996"}.fe-minus-circle:before{content:"\e997"}.fe-minus-square:before{content:"\e998"}.fe-monitor:before{content:"\e999"}.fe-moon:before{content:"\e99a"}.fe-more-horizontal:before{content:"\e99b"}.fe-more-vertical:before{content:"\e99c"}.fe-move:before{content:"\e99d"}.fe-music:before{content:"\e99e"}.fe-navigation:before{content:"\e99f"}.fe-navigation-2:before{content:"\e9a0"}.fe-octagon:before{content:"\e9a1"}.fe-package:before{content:"\e9a2"}.fe-paperclip:before{content:"\e9a3"}.fe-pause:before{content:"\e9a4"}.fe-pause-circle:before{content:"\e9a5"}.fe-percent:before{content:"\e9a6"}.fe-phone:before{content:"\e9a7"}.fe-phone-call:before{content:"\e9a8"}.fe-phone-forwarded:before{content:"\e9a9"}.fe-phone-incoming:before{content:"\e9aa"}.fe-phone-missed:before{content:"\e9ab"}.fe-phone-off:before{content:"\e9ac"}.fe-phone-outgoing:before{content:"\e9ad"}.fe-pie-chart:before{content:"\e9ae"}.fe-play:before{content:"\e9af"}.fe-play-circle:before{content:"\e9b0"}.fe-plus:before{content:"\e9b1"}.fe-plus-circle:before{content:"\e9b2"}.fe-plus-square:before{content:"\e9b3"}.fe-pocket:before{content:"\e9b4"}.fe-power:before{content:"\e9b5"}.fe-printer:before{content:"\e9b6"}.fe-radio:before{content:"\e9b7"}.fe-refresh-ccw:before{content:"\e9b8"}.fe-refresh-cw:before{content:"\e9b9"}.fe-repeat:before{content:"\e9ba"}.fe-rewind:before{content:"\e9bb"}.fe-rotate-ccw:before{content:"\e9bc"}.fe-rotate-cw:before{content:"\e9bd"}.fe-rss:before{content:"\e9be"}.fe-save:before{content:"\e9bf"}.fe-scissors:before{content:"\e9c0"}.fe-search:before{content:"\e9c1"}.fe-send:before{content:"\e9c2"}.fe-server:before{content:"\e9c3"}.fe-settings:before{content:"\e9c4"}.fe-share:before{content:"\e9c5"}.fe-share-2:before{content:"\e9c6"}.fe-shield:before{content:"\e9c7"}.fe-shield-off:before{content:"\e9c8"}.fe-shopping-bag:before{content:"\e9c9"}.fe-shopping-cart:before{content:"\e9ca"}.fe-shuffle:before{content:"\e9cb"}.fe-sidebar:before{content:"\e9cc"}.fe-skip-back:before{content:"\e9cd"}.fe-skip-forward:before{content:"\e9ce"}.fe-slack:before{content:"\e9cf"}.fe-slash:before{content:"\e9d0"}.fe-sliders:before{content:"\e9d1"}.fe-smartphone:before{content:"\e9d2"}.fe-speaker:before{content:"\e9d3"}.fe-square:before{content:"\e9d4"}.fe-star:before{content:"\e9d5"}.fe-stop-circle:before{content:"\e9d6"}.fe-sun:before{content:"\e9d7"}.fe-sunrise:before{content:"\e9d8"}.fe-sunset:before{content:"\e9d9"}.fe-tablet:before{content:"\e9da"}.fe-tag:before{content:"\e9db"}.fe-target:before{content:"\e9dc"}.fe-terminal:before{content:"\e9dd"}.fe-thermometer:before{content:"\e9de"}.fe-thumbs-down:before{content:"\e9df"}.fe-thumbs-up:before{content:"\e9e0"}.fe-toggle-left:before{content:"\e9e1"}.fe-toggle-right:before{content:"\e9e2"}.fe-trash:before{content:"\e9e3"}.fe-trash-2:before{content:"\e9e4"}.fe-trending-down:before{content:"\e9e5"}.fe-trending-up:before{content:"\e9e6"}.fe-triangle:before{content:"\e9e7"}.fe-truck:before{content:"\e9e8"}.fe-tv:before{content:"\e9e9"}.fe-twitter:before{content:"\e9ea"}.fe-type:before{content:"\e9eb"}.fe-umbrella:before{content:"\e9ec"}.fe-underline:before{content:"\e9ed"}.fe-unlock:before{content:"\e9ee"}.fe-upload:before{content:"\e9ef"}.fe-upload-cloud:before{content:"\e9f0"}.fe-user:before{content:"\e9f1"}.fe-user-check:before{content:"\e9f2"}.fe-user-minus:before{content:"\e9f3"}.fe-user-plus:before{content:"\e9f4"}.fe-user-x:before{content:"\e9f5"}.fe-users:before{content:"\e9f6"}.fe-video:before{content:"\e9f7"}.fe-video-off:before{content:"\e9f8"}.fe-voicemail:before{content:"\e9f9"}.fe-volume:before{content:"\e9fa"}.fe-volume-1:before{content:"\e9fb"}.fe-volume-2:before{content:"\e9fc"}.fe-volume-x:before{content:"\e9fd"}.fe-watch:before{content:"\e9fe"}.fe-wifi:before{content:"\e9ff"}.fe-wifi-off:before{content:"\ea00"}.fe-wind:before{content:"\ea01"}.fe-x:before{content:"\ea02"}.fe-x-circle:before{content:"\ea03"}.fe-x-square:before{content:"\ea04"}.fe-youtube:before{content:"\ea05"}.fe-zap:before{content:"\ea06"}.fe-zap-off:before{content:"\ea07"}.fe-zoom-in:before{content:"\ea08"}.fe-zoom-out:before{content:"\ea09"}
--------------------------------------------------------------------------------
/wms/pages/static/events/dashboard/fonts/feather/feather.min.css:
--------------------------------------------------------------------------------
1 | @font-face{font-family:Feather;src:url(fonts/Feather.ttf?sdxovp) format("truetype"),url(fonts/Feather.woff?sdxovp) format("woff"),url(fonts/Feather.svg?sdxovp#Feather) format("svg");font-weight:400;font-style:normal}.fe{font-family:Feather!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fe-activity:before{content:"\e900"}.fe-airplay:before{content:"\e901"}.fe-alert-circle:before{content:"\e902"}.fe-alert-octagon:before{content:"\e903"}.fe-alert-triangle:before{content:"\e904"}.fe-align-center:before{content:"\e905"}.fe-align-justify:before{content:"\e906"}.fe-align-left:before{content:"\e907"}.fe-align-right:before{content:"\e908"}.fe-anchor:before{content:"\e909"}.fe-aperture:before{content:"\e90a"}.fe-archive:before{content:"\e90b"}.fe-arrow-down:before{content:"\e90c"}.fe-arrow-down-circle:before{content:"\e90d"}.fe-arrow-down-left:before{content:"\e90e"}.fe-arrow-down-right:before{content:"\e90f"}.fe-arrow-left:before{content:"\e910"}.fe-arrow-left-circle:before{content:"\e911"}.fe-arrow-right:before{content:"\e912"}.fe-arrow-right-circle:before{content:"\e913"}.fe-arrow-up:before{content:"\e914"}.fe-arrow-up-circle:before{content:"\e915"}.fe-arrow-up-left:before{content:"\e916"}.fe-arrow-up-right:before{content:"\e917"}.fe-at-sign:before{content:"\e918"}.fe-award:before{content:"\e919"}.fe-bar-chart:before{content:"\e91a"}.fe-bar-chart-2:before{content:"\e91b"}.fe-battery:before{content:"\e91c"}.fe-battery-charging:before{content:"\e91d"}.fe-bell:before{content:"\e91e"}.fe-bell-off:before{content:"\e91f"}.fe-bluetooth:before{content:"\e920"}.fe-bold:before{content:"\e921"}.fe-book:before{content:"\e922"}.fe-book-open:before{content:"\e923"}.fe-bookmark:before{content:"\e924"}.fe-box:before{content:"\e925"}.fe-briefcase:before{content:"\e926"}.fe-calendar:before{content:"\e927"}.fe-camera:before{content:"\e928"}.fe-camera-off:before{content:"\e929"}.fe-cast:before{content:"\e92a"}.fe-check:before{content:"\e92b"}.fe-check-circle:before{content:"\e92c"}.fe-check-square:before{content:"\e92d"}.fe-chevron-down:before{content:"\e92e"}.fe-chevron-left:before{content:"\e92f"}.fe-chevron-right:before{content:"\e930"}.fe-chevron-up:before{content:"\e931"}.fe-chevrons-down:before{content:"\e932"}.fe-chevrons-left:before{content:"\e933"}.fe-chevrons-right:before{content:"\e934"}.fe-chevrons-up:before{content:"\e935"}.fe-chrome:before{content:"\e936"}.fe-circle:before{content:"\e937"}.fe-clipboard:before{content:"\e938"}.fe-clock:before{content:"\e939"}.fe-cloud:before{content:"\e93a"}.fe-cloud-drizzle:before{content:"\e93b"}.fe-cloud-lightning:before{content:"\e93c"}.fe-cloud-off:before{content:"\e93d"}.fe-cloud-rain:before{content:"\e93e"}.fe-cloud-snow:before{content:"\e93f"}.fe-code:before{content:"\e940"}.fe-codepen:before{content:"\e941"}.fe-command:before{content:"\e942"}.fe-compass:before{content:"\e943"}.fe-copy:before{content:"\e944"}.fe-corner-down-left:before{content:"\e945"}.fe-corner-down-right:before{content:"\e946"}.fe-corner-left-down:before{content:"\e947"}.fe-corner-left-up:before{content:"\e948"}.fe-corner-right-down:before{content:"\e949"}.fe-corner-right-up:before{content:"\e94a"}.fe-corner-up-left:before{content:"\e94b"}.fe-corner-up-right:before{content:"\e94c"}.fe-cpu:before{content:"\e94d"}.fe-credit-card:before{content:"\e94e"}.fe-crop:before{content:"\e94f"}.fe-crosshair:before{content:"\e950"}.fe-database:before{content:"\e951"}.fe-delete:before{content:"\e952"}.fe-disc:before{content:"\e953"}.fe-dollar-sign:before{content:"\e954"}.fe-download:before{content:"\e955"}.fe-download-cloud:before{content:"\e956"}.fe-droplet:before{content:"\e957"}.fe-edit:before{content:"\e958"}.fe-edit-2:before{content:"\e959"}.fe-edit-3:before{content:"\e95a"}.fe-external-link:before{content:"\e95b"}.fe-eye:before{content:"\e95c"}.fe-eye-off:before{content:"\e95d"}.fe-facebook:before{content:"\e95e"}.fe-fast-forward:before{content:"\e95f"}.fe-feather:before{content:"\e960"}.fe-file:before{content:"\e961"}.fe-file-minus:before{content:"\e962"}.fe-file-plus:before{content:"\e963"}.fe-file-text:before{content:"\e964"}.fe-film:before{content:"\e965"}.fe-filter:before{content:"\e966"}.fe-flag:before{content:"\e967"}.fe-folder:before{content:"\e968"}.fe-folder-minus:before{content:"\e969"}.fe-folder-plus:before{content:"\e96a"}.fe-gift:before{content:"\e96b"}.fe-git-branch:before{content:"\e96c"}.fe-git-commit:before{content:"\e96d"}.fe-git-merge:before{content:"\e96e"}.fe-git-pull-request:before{content:"\e96f"}.fe-github:before{content:"\e970"}.fe-gitlab:before{content:"\e971"}.fe-globe:before{content:"\e972"}.fe-grid:before{content:"\e973"}.fe-hard-drive:before{content:"\e974"}.fe-hash:before{content:"\e975"}.fe-headphones:before{content:"\e976"}.fe-heart:before{content:"\e977"}.fe-help-circle:before{content:"\e978"}.fe-home:before{content:"\e979"}.fe-image:before{content:"\e97a"}.fe-inbox:before{content:"\e97b"}.fe-info:before{content:"\e97c"}.fe-instagram:before{content:"\e97d"}.fe-italic:before{content:"\e97e"}.fe-layers:before{content:"\e97f"}.fe-layout:before{content:"\e980"}.fe-life-buoy:before{content:"\e981"}.fe-link:before{content:"\e982"}.fe-link-2:before{content:"\e983"}.fe-linkedin:before{content:"\e984"}.fe-list:before{content:"\e985"}.fe-loader:before{content:"\e986"}.fe-lock:before{content:"\e987"}.fe-log-in:before{content:"\e988"}.fe-log-out:before{content:"\e989"}.fe-mail:before{content:"\e98a"}.fe-map:before{content:"\e98b"}.fe-map-pin:before{content:"\e98c"}.fe-maximize:before{content:"\e98d"}.fe-maximize-2:before{content:"\e98e"}.fe-menu:before{content:"\e98f"}.fe-message-circle:before{content:"\e990"}.fe-message-square:before{content:"\e991"}.fe-mic:before{content:"\e992"}.fe-mic-off:before{content:"\e993"}.fe-minimize:before{content:"\e994"}.fe-minimize-2:before{content:"\e995"}.fe-minus:before{content:"\e996"}.fe-minus-circle:before{content:"\e997"}.fe-minus-square:before{content:"\e998"}.fe-monitor:before{content:"\e999"}.fe-moon:before{content:"\e99a"}.fe-more-horizontal:before{content:"\e99b"}.fe-more-vertical:before{content:"\e99c"}.fe-move:before{content:"\e99d"}.fe-music:before{content:"\e99e"}.fe-navigation:before{content:"\e99f"}.fe-navigation-2:before{content:"\e9a0"}.fe-octagon:before{content:"\e9a1"}.fe-package:before{content:"\e9a2"}.fe-paperclip:before{content:"\e9a3"}.fe-pause:before{content:"\e9a4"}.fe-pause-circle:before{content:"\e9a5"}.fe-percent:before{content:"\e9a6"}.fe-phone:before{content:"\e9a7"}.fe-phone-call:before{content:"\e9a8"}.fe-phone-forwarded:before{content:"\e9a9"}.fe-phone-incoming:before{content:"\e9aa"}.fe-phone-missed:before{content:"\e9ab"}.fe-phone-off:before{content:"\e9ac"}.fe-phone-outgoing:before{content:"\e9ad"}.fe-pie-chart:before{content:"\e9ae"}.fe-play:before{content:"\e9af"}.fe-play-circle:before{content:"\e9b0"}.fe-plus:before{content:"\e9b1"}.fe-plus-circle:before{content:"\e9b2"}.fe-plus-square:before{content:"\e9b3"}.fe-pocket:before{content:"\e9b4"}.fe-power:before{content:"\e9b5"}.fe-printer:before{content:"\e9b6"}.fe-radio:before{content:"\e9b7"}.fe-refresh-ccw:before{content:"\e9b8"}.fe-refresh-cw:before{content:"\e9b9"}.fe-repeat:before{content:"\e9ba"}.fe-rewind:before{content:"\e9bb"}.fe-rotate-ccw:before{content:"\e9bc"}.fe-rotate-cw:before{content:"\e9bd"}.fe-rss:before{content:"\e9be"}.fe-save:before{content:"\e9bf"}.fe-scissors:before{content:"\e9c0"}.fe-search:before{content:"\e9c1"}.fe-send:before{content:"\e9c2"}.fe-server:before{content:"\e9c3"}.fe-settings:before{content:"\e9c4"}.fe-share:before{content:"\e9c5"}.fe-share-2:before{content:"\e9c6"}.fe-shield:before{content:"\e9c7"}.fe-shield-off:before{content:"\e9c8"}.fe-shopping-bag:before{content:"\e9c9"}.fe-shopping-cart:before{content:"\e9ca"}.fe-shuffle:before{content:"\e9cb"}.fe-sidebar:before{content:"\e9cc"}.fe-skip-back:before{content:"\e9cd"}.fe-skip-forward:before{content:"\e9ce"}.fe-slack:before{content:"\e9cf"}.fe-slash:before{content:"\e9d0"}.fe-sliders:before{content:"\e9d1"}.fe-smartphone:before{content:"\e9d2"}.fe-speaker:before{content:"\e9d3"}.fe-square:before{content:"\e9d4"}.fe-star:before{content:"\e9d5"}.fe-stop-circle:before{content:"\e9d6"}.fe-sun:before{content:"\e9d7"}.fe-sunrise:before{content:"\e9d8"}.fe-sunset:before{content:"\e9d9"}.fe-tablet:before{content:"\e9da"}.fe-tag:before{content:"\e9db"}.fe-target:before{content:"\e9dc"}.fe-terminal:before{content:"\e9dd"}.fe-thermometer:before{content:"\e9de"}.fe-thumbs-down:before{content:"\e9df"}.fe-thumbs-up:before{content:"\e9e0"}.fe-toggle-left:before{content:"\e9e1"}.fe-toggle-right:before{content:"\e9e2"}.fe-trash:before{content:"\e9e3"}.fe-trash-2:before{content:"\e9e4"}.fe-trending-down:before{content:"\e9e5"}.fe-trending-up:before{content:"\e9e6"}.fe-triangle:before{content:"\e9e7"}.fe-truck:before{content:"\e9e8"}.fe-tv:before{content:"\e9e9"}.fe-twitter:before{content:"\e9ea"}.fe-type:before{content:"\e9eb"}.fe-umbrella:before{content:"\e9ec"}.fe-underline:before{content:"\e9ed"}.fe-unlock:before{content:"\e9ee"}.fe-upload:before{content:"\e9ef"}.fe-upload-cloud:before{content:"\e9f0"}.fe-user:before{content:"\e9f1"}.fe-user-check:before{content:"\e9f2"}.fe-user-minus:before{content:"\e9f3"}.fe-user-plus:before{content:"\e9f4"}.fe-user-x:before{content:"\e9f5"}.fe-users:before{content:"\e9f6"}.fe-video:before{content:"\e9f7"}.fe-video-off:before{content:"\e9f8"}.fe-voicemail:before{content:"\e9f9"}.fe-volume:before{content:"\e9fa"}.fe-volume-1:before{content:"\e9fb"}.fe-volume-2:before{content:"\e9fc"}.fe-volume-x:before{content:"\e9fd"}.fe-watch:before{content:"\e9fe"}.fe-wifi:before{content:"\e9ff"}.fe-wifi-off:before{content:"\ea00"}.fe-wind:before{content:"\ea01"}.fe-x:before{content:"\ea02"}.fe-x-circle:before{content:"\ea03"}.fe-x-square:before{content:"\ea04"}.fe-youtube:before{content:"\ea05"}.fe-zap:before{content:"\ea06"}.fe-zap-off:before{content:"\ea07"}.fe-zoom-in:before{content:"\ea08"}.fe-zoom-out:before{content:"\ea09"}
--------------------------------------------------------------------------------