gealogiuya
5
.dockerignore
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
venv/
|
||||||
|
assets/staticfiles/*
|
||||||
|
assets/staticfiles/
|
||||||
|
assets/media/*
|
||||||
|
assets/media/
|
||||||
44
.env.example
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#######################
|
||||||
|
# SECRET KEY
|
||||||
|
#######################
|
||||||
|
SECRET_KEY=ti5#4-7%vows!c)n(k#g*q$xg5aq4q$5=k!5@b3hhcf3h)6+5g
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# POSTGRES DB
|
||||||
|
#######################
|
||||||
|
POSTGRES_DB=djangodefault
|
||||||
|
POSTGRES_USER=postgres
|
||||||
|
POSTGRES_PASSWORD=1253
|
||||||
|
POSTGRES_HOST=db
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# DEBUG
|
||||||
|
#######################
|
||||||
|
DEBUG=False
|
||||||
|
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# HOSTS
|
||||||
|
#######################
|
||||||
|
ALLOWED_HOSTS=127.0.0.1,localhost,web
|
||||||
|
CSRF_TRUSTED_ORIGINS=http://127.0.0.1,http://localhost
|
||||||
|
|
||||||
|
|
||||||
|
######################
|
||||||
|
# PORTS
|
||||||
|
######################
|
||||||
|
PORT=8028
|
||||||
|
RABBITMQ_PORT=15672
|
||||||
|
CELERY_FLOWER=5555
|
||||||
|
|
||||||
|
|
||||||
|
######################
|
||||||
|
# Cache
|
||||||
|
######################
|
||||||
|
CACHE_BACKEND=django.core.cache.backends.redis.RedisCache
|
||||||
|
REDIS_CACHE_URL=redis://redis:6379
|
||||||
|
CACHE_ENABLED=False
|
||||||
|
CACHE_TIMEOUT=120
|
||||||
|
CELERY_BROKER=redis://redis:6379/0
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
27
.github/workflows/deploy.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
name: Deploy Django Application to Server
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main # Bu yerda kodni qaysi branch'dan push qilganda deploy ishga tushishini ko'rsatasiz
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Repositoryni GitHub'dan olish
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Serverga SSH orqali ulanish
|
||||||
|
uses: appleboy/ssh-action@v1.0.3
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.SSH_HOST }}
|
||||||
|
username: ${{ secrets.SSH_USER }}
|
||||||
|
port: ${{ secrets.SSH_PORT }}
|
||||||
|
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
|
script: |
|
||||||
|
cd ${{ secrets.DEPLOY_PATH }}
|
||||||
|
git pull origin main
|
||||||
|
docker compose up --build -d
|
||||||
|
docker image prune -f
|
||||||
|
echo "Deploy jarayoni muvaffaqiyatli yakunlandi!"
|
||||||
26
.github/workflows/notify.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: Telegram Notifications
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
[opened, closed, edited, ready_for_review, review_requested, reopened]
|
||||||
|
pull_request_review_comment:
|
||||||
|
types: [created]
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- dev
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Telegram Gate
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Notifier
|
||||||
|
uses: ethyaan/tgate-action@v1.0.0
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.TOKEN }}
|
||||||
|
to: ${{ secrets.CHAT_ID }}
|
||||||
|
disable_web_page_preview: true
|
||||||
|
disable_notification: false
|
||||||
21
.gitignore
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
.idea
|
||||||
|
venv/
|
||||||
|
.idea/
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*.pyd
|
||||||
|
.env
|
||||||
|
qodana.yaml
|
||||||
|
db.sqlite3/
|
||||||
|
db.sqlite3
|
||||||
|
.venv/
|
||||||
|
backups/
|
||||||
|
backups/*
|
||||||
|
backups
|
||||||
|
*.sql
|
||||||
|
*.dump
|
||||||
|
assets/media/*
|
||||||
|
assets/media/
|
||||||
|
assets/staticfiles/*
|
||||||
|
assets/staticfiles/
|
||||||
25
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.6.0
|
||||||
|
hooks:
|
||||||
|
- id: check-case-conflict
|
||||||
|
- id: check-json
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- id: check-symlinks
|
||||||
|
- id: check-toml
|
||||||
|
exclude: CHANGELOG.md
|
||||||
|
- id: trailing-whitespace
|
||||||
|
exclude: CHANGELOG.md
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
rev: v0.5.0
|
||||||
|
hooks:
|
||||||
|
- id: ruff
|
||||||
|
args:
|
||||||
|
- --fix
|
||||||
|
- id: ruff-format
|
||||||
|
- repo: https://github.com/compilerla/conventional-pre-commit
|
||||||
|
rev: v3.2.0
|
||||||
|
hooks:
|
||||||
|
- id: conventional-pre-commit
|
||||||
|
stages: [commit-msg]
|
||||||
|
args: []
|
||||||
94
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
# Citizen Code of Conduct
|
||||||
|
|
||||||
|
## 1. Purpose
|
||||||
|
|
||||||
|
A primary goal of Django Default is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof).
|
||||||
|
|
||||||
|
This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior.
|
||||||
|
|
||||||
|
We invite all those who participate in Django Default to help us create safe and positive experiences for everyone.
|
||||||
|
|
||||||
|
## 2. Open [Source/Culture/Tech] Citizenship
|
||||||
|
|
||||||
|
A supplemental goal of this Code of Conduct is to increase open [source/culture/tech] citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community.
|
||||||
|
|
||||||
|
Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society.
|
||||||
|
|
||||||
|
If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know.
|
||||||
|
|
||||||
|
## 3. Expected Behavior
|
||||||
|
|
||||||
|
The following behaviors are expected and requested of all community members:
|
||||||
|
|
||||||
|
* Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community.
|
||||||
|
* Exercise consideration and respect in your speech and actions.
|
||||||
|
* Attempt collaboration before conflict.
|
||||||
|
* Refrain from demeaning, discriminatory, or harassing behavior and speech.
|
||||||
|
* Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential.
|
||||||
|
* Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations.
|
||||||
|
|
||||||
|
## 4. Unacceptable Behavior
|
||||||
|
|
||||||
|
The following behaviors are considered harassment and are unacceptable within our community:
|
||||||
|
|
||||||
|
* Violence, threats of violence or violent language directed against another person.
|
||||||
|
* Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language.
|
||||||
|
* Posting or displaying sexually explicit or violent material.
|
||||||
|
* Posting or threatening to post other people's personally identifying information ("doxing").
|
||||||
|
* Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability.
|
||||||
|
* Inappropriate photography or recording.
|
||||||
|
* Inappropriate physical contact. You should have someone's consent before touching them.
|
||||||
|
* Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances.
|
||||||
|
* Deliberate intimidation, stalking or following (online or in person).
|
||||||
|
* Advocating for, or encouraging, any of the above behavior.
|
||||||
|
* Sustained disruption of community events, including talks and presentations.
|
||||||
|
|
||||||
|
## 5. Weapons Policy
|
||||||
|
|
||||||
|
No weapons will be allowed at Django Default events, community spaces, or in other spaces covered by the scope of this Code of Conduct. Weapons include but are not limited to guns, explosives (including fireworks), and large knives such as those used for hunting or display, as well as any other item used for the purpose of causing injury or harm to others. Anyone seen in possession of one of these items will be asked to leave immediately, and will only be allowed to return without the weapon. Community members are further expected to comply with all state and local laws on this matter.
|
||||||
|
|
||||||
|
## 6. Consequences of Unacceptable Behavior
|
||||||
|
|
||||||
|
Unacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated.
|
||||||
|
|
||||||
|
Anyone asked to stop unacceptable behavior is expected to comply immediately.
|
||||||
|
|
||||||
|
If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event).
|
||||||
|
|
||||||
|
## 7. Reporting Guidelines
|
||||||
|
|
||||||
|
If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. jahongirhakimjonov@gmail.com.
|
||||||
|
|
||||||
|
[Reporting guidelines](https://jahongirhakimjonov.github.io/DjangoDefault/)
|
||||||
|
|
||||||
|
Additionally, community organizers are available to help community members engage with local law enforcement or to otherwise help those experiencing unacceptable behavior feel safe. In the context of in-person events, organizers will also provide escorts as desired by the person experiencing distress.
|
||||||
|
|
||||||
|
## 8. Addressing Grievances
|
||||||
|
|
||||||
|
If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify Jahongir Hakimjonov with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies. [Policy](https://jahongirhakimjonov.github.io/DjangoDefault/)
|
||||||
|
|
||||||
|
Django Default
|
||||||
|
|
||||||
|
## 9. Scope
|
||||||
|
|
||||||
|
We expect all community participants (contributors, paid or otherwise; sponsors; and other guests) to abide by this Code of Conduct in all community venues--online and in-person--as well as in all one-on-one communications pertaining to community business.
|
||||||
|
|
||||||
|
This code of conduct and its related procedures also applies to unacceptable behavior occurring outside the scope of community activities when such behavior has the potential to adversely affect the safety and well-being of community members.
|
||||||
|
|
||||||
|
## 10. Contact info
|
||||||
|
|
||||||
|
jahongirhakimjonov@gmail.com
|
||||||
|
|
||||||
|
## 11. License and attribution
|
||||||
|
|
||||||
|
The Citizen Code of Conduct is distributed by [Stumptown Syndicate](http://stumptownsyndicate.org) under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/).
|
||||||
|
|
||||||
|
Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy).
|
||||||
|
|
||||||
|
_Revision 2.3. Posted 6 March 2017._
|
||||||
|
|
||||||
|
_Revision 2.2. Posted 4 February 2016._
|
||||||
|
|
||||||
|
_Revision 2.1. Posted 23 June 2014._
|
||||||
|
|
||||||
|
_Revision 2.0, adopted by the [Stumptown Syndicate](http://stumptownsyndicate.org) board on 10 January 2013. Posted 17 March 2013._
|
||||||
38
CONTRIBUTING.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# Contributing to Django Default
|
||||||
|
|
||||||
|
Thank you for your interest in contributing to Django Default! We welcome contributions from everyone, and we are grateful for every contribution made to the project. This document provides guidelines for contributing to Django Default.
|
||||||
|
|
||||||
|
## How to Contribute
|
||||||
|
|
||||||
|
There are many ways to contribute to our project:
|
||||||
|
|
||||||
|
- **Reporting Bugs**: If you find a bug, please report it by opening a new issue. We appreciate detailed reports that help us understand and replicate the issue.
|
||||||
|
- **Suggesting Enhancements**: Have an idea to make Django Default better? Open an issue to suggest enhancements. Please provide as much detail and context as possible.
|
||||||
|
- **Pull Requests**: Contributions via pull requests are the best way to propose changes. This could include fixing bugs, adding new features, or updating documentation.
|
||||||
|
|
||||||
|
## Pull Request Process
|
||||||
|
|
||||||
|
1. Ensure any install or build dependencies are removed before the end of the layer when doing a build.
|
||||||
|
2. Update the README.md with details of changes to the interface, this includes new environment variables, exposed ports, useful file locations, and container parameters.
|
||||||
|
3. Increase the version numbers in any examples files and the README.md to the new version that this Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
|
||||||
|
4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you do not have permission to do that, you may request the second reviewer to merge it for you.
|
||||||
|
|
||||||
|
## Code of Conduct
|
||||||
|
|
||||||
|
Our project adheres to a Code of Conduct that we expect all contributors to follow. Please read [Code of Conduct](CODE_OF_CONDUCT.md) before contributing so that you understand what actions will and will not be tolerated.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
- Fork the repository on GitHub
|
||||||
|
- Clone your fork to your local machine
|
||||||
|
- Create a new branch for your fix or feature
|
||||||
|
- Commit your changes with a clear description of the change
|
||||||
|
- Push your branch to your fork
|
||||||
|
- Submit a pull request from your fork back to the main repository
|
||||||
|
- Await feedback from the project maintainers
|
||||||
|
|
||||||
|
## Questions?
|
||||||
|
|
||||||
|
If you have any questions or need further clarification about contributing, please open an issue, and we will be happy to help.
|
||||||
|
|
||||||
|
Thank you for contributing to Django Default, and we look forward to your contribution!
|
||||||
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Django Default
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
205
README.md
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
# Django Default
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Django Default is a Django project structure generator that simplifies the process of setting up new Django projects. It automates the cloning of a predefined Django project structure from a GitHub repository, enabling developers to start their projects with a solid foundation.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Automates the cloning of a Django project structure.
|
||||||
|
- Customizable to fit specific project needs.
|
||||||
|
- Streamlines the initial setup process for Django projects.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Install Django Default using pip:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install django-default
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To generate a new Django project structure, execute the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bankai
|
||||||
|
```
|
||||||
|
|
||||||
|
This command clones the predefined Django project structure into your current working directory.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
After generating your project structure, configure it by setting up the database and adjusting the settings in `settings.py` to match your environment. Ensure to include the third-party apps listed in `core/config/apps.py`:
|
||||||
|
|
||||||
|
- jazzmin
|
||||||
|
- modeltranslation
|
||||||
|
- django_ckeditor_5
|
||||||
|
- corsheaders
|
||||||
|
- rosetta
|
||||||
|
- rest_framework
|
||||||
|
- drf_spectacular
|
||||||
|
- drf_spectacular_sidecar
|
||||||
|
- celery beat
|
||||||
|
- celery worker
|
||||||
|
- flower
|
||||||
|
- RabbitMQ
|
||||||
|
- Redis
|
||||||
|
- black
|
||||||
|
- pre-commit
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
To contribute to Django Default, set up a development environment by cloning the project and installing its dependencies. Run tests to ensure your changes don't break existing functionality and follow the project's contribution guidelines when submitting pull requests.
|
||||||
|
|
||||||
|
## API Documentation
|
||||||
|
|
||||||
|
If your project uses Django REST Framework, use `drf_spectacular` to auto-generate API documentation. Document your API endpoints, including information on request methods, parameters, and example responses.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Django Default is released under the MIT License. See the LICENSE file in the project repository for more information.
|
||||||
|
|
||||||
|
## Acknowledgments
|
||||||
|
|
||||||
|
- Thanks to all contributors who have helped to improve Django Default.
|
||||||
|
- Special thanks to Jahongir Hakimjonov for creating and maintaining this project.
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
Please contact Jahongir Hakimjonov with any questions or concerns regarding this project.
|
||||||
|
|
||||||
|
- [GitHub](https://github.com/JahongirHakimjonov)
|
||||||
|
- [Instagram](https://www.instagram.com/ja_kahn_gir/)
|
||||||
|
- [Telegram](https://t.me/jakhangir_blog)
|
||||||
|
|
||||||
|
<a href="https://pypi.org/project/django-default/">
|
||||||
|
<img src="https://i0.wp.com/securityaffairs.com/wp-content/uploads/2021/08/PyPI.png?ssl=1" width="200" height="90" alt="pypi">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
# Donate
|
||||||
|
- [Buy Me Coffee](https://buymeacoffee.com/ja_khan_gir)
|
||||||
|
|
||||||
|
- [Tirikchilik](https://tirikchilik.uz/ja_khan_gir)
|
||||||
|
|
||||||
|
|
||||||
|
<a href="https://buymeacoffee.com/ja_khan_gir">
|
||||||
|
<img src="https://i.postimg.cc/cLwdq9pL/bmc-qr-2.png" width="200" height="200" alt="pypi">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
# Management Commands Documentation
|
||||||
|
|
||||||
|
This document provides an overview and usage instructions for custom management commands included in the Django project.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
### createadmin
|
||||||
|
|
||||||
|
- **Description**: Creates superuser accounts with predefined credentials. Useful for quickly setting up admin users during development.
|
||||||
|
- **Usage**: `python manage.py createadmin`
|
||||||
|
|
||||||
|
### makeapp
|
||||||
|
|
||||||
|
- **Description**: Automates the creation of a new Django app within the `apps` directory. It also modifies the app's `apps.py` to correctly reference the app's location and removes unnecessary files.
|
||||||
|
- **Usage**: `python manage.py makeapp <app_name>`
|
||||||
|
- `<app_name>`: The name of the app you want to create.
|
||||||
|
|
||||||
|
### nginx
|
||||||
|
|
||||||
|
- **Description**: Generates a new nginx configuration file based on user input for domain name, project name, and project port. The command simplifies the process of preparing nginx for new projects.
|
||||||
|
- **Usage**: `python manage.py nginx`
|
||||||
|
- Follow the prompts to enter the domain name, project name, and project port.
|
||||||
|
|
||||||
|
### secret_key
|
||||||
|
|
||||||
|
- **Description**: Generates a new Django secret key. This is particularly useful when setting up a new project or when you need to regenerate the secret key for security reasons.
|
||||||
|
- **Usage**: `python manage.py secret_key`
|
||||||
|
|
||||||
|
# Project Dependencies and Tools
|
||||||
|
|
||||||
|
This project utilizes a combination of powerful tools and technologies to manage background tasks, message queuing, and real-time monitoring. Below is an overview of the key components:
|
||||||
|
|
||||||
|
## Celery
|
||||||
|
|
||||||
|
Celery is an asynchronous task queue/job queue based on distributed message passing. It is focused on real-time operation but supports scheduling as well. The execution units, called tasks, are executed concurrently on one or more worker nodes using multiprocessing, Eventlet, or gevent. Celery is used in this project for handling background tasks efficiently.
|
||||||
|
|
||||||
|
### Key Components:
|
||||||
|
|
||||||
|
- **Celery Beat**: A scheduler for Celery. It kicks off tasks at regular intervals, which are then executed by available Celery workers. It's used for periodic tasks like cleaning up databases, sending emails, or gathering data from various sources.
|
||||||
|
- **Celery Worker**: These are the processes that run the actual tasks. A Celery system can have multiple workers, which can be located on the same machine or across a distributed network.
|
||||||
|
|
||||||
|
## RabbitMQ
|
||||||
|
|
||||||
|
RabbitMQ is an open-source message broker software that originally implemented the Advanced Message Queuing Protocol (AMQP). It facilitates the efficient delivery of messages in complex routing scenarios and ensures that messages are processed only once, in the order they are sent. In this project, RabbitMQ is used as the message broker for Celery, managing the queue of tasks to be processed by the workers.
|
||||||
|
|
||||||
|
## Redis
|
||||||
|
|
||||||
|
Redis is an in-memory data structure store, used as a database, cache, and message broker. In this project, Redis is used in two main roles:
|
||||||
|
- As a message broker, similar to RabbitMQ, offering support for fast, transient storage scenarios.
|
||||||
|
- For storing the task results (Celery supports using Redis as a result backend).
|
||||||
|
|
||||||
|
## Flower
|
||||||
|
|
||||||
|
Flower is a web-based tool for monitoring and administrating Celery clusters. It provides detailed real-time information about task queues, workers, and tasks, with the ability to control them directly through the web interface. Flower is an essential tool for managing and troubleshooting Celery tasks and workers in this project.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
To set up these components for your development environment, refer to the respective official documentation for installation and configuration guidelines.
|
||||||
|
|
||||||
|
## General Information
|
||||||
|
|
||||||
|
These commands are designed to streamline common tasks in Django development and deployment. Ensure you have the necessary permissions and environment setup before running these commands.
|
||||||
|
|
||||||
|
|
||||||
|
## Pre-commit for Code Quality Assurance
|
||||||
|
|
||||||
|
Pre-commit is an essential tool in modern development workflows, ensuring that code committed to the repository adheres to defined quality standards. It automates the process of checking code for common issues before it is committed, helping to maintain a clean and error-free codebase.
|
||||||
|
|
||||||
|
### Features and Benefits:
|
||||||
|
|
||||||
|
- **Automated Code Review**: Runs a series of checks on code before it is committed, catching issues early in the development cycle.
|
||||||
|
- **Customizable Hooks**: Supports a wide range of hooks for different languages and frameworks, including Python and JavaScript, making it versatile for projects with diverse tech stacks.
|
||||||
|
- **Easy Integration**: Can be easily integrated into existing projects with minimal setup, enhancing the development process without significant overhead.
|
||||||
|
|
||||||
|
### Setting Up Pre-commit in Your Project:
|
||||||
|
|
||||||
|
1. **Installation**: Install pre-commit using pip:
|
||||||
|
```bash
|
||||||
|
pip install pre-commit
|
||||||
|
```
|
||||||
|
2. **Configuration**: Create a `.pre-commit-config.yaml` file in your project root directory. Define the hooks you want to use, as shown in the project's current configuration.
|
||||||
|
3. **Install Git Hook Scripts**: Run the following command to set up pre-commit with your git hooks:
|
||||||
|
```bash
|
||||||
|
pre-commit install
|
||||||
|
```
|
||||||
|
This step ensures that pre-commit runs automatically on every commit attempt.
|
||||||
|
|
||||||
|
4. **Optional: Commit Message Hooks**: For projects requiring commit message standards, pre-commit can enforce this through commit message hooks:
|
||||||
|
```bash
|
||||||
|
pre-commit install --hook-type commit-msg
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Manual Run**: To manually run pre-commit on all files in the project, use:
|
||||||
|
```bash
|
||||||
|
pre-commit run --all-files
|
||||||
|
```
|
||||||
|
This is useful for initial setup or periodic checks across the entire codebase.
|
||||||
|
|
||||||
|
### Example Configuration:
|
||||||
|
|
||||||
|
The project's `.pre-commit-config.yaml` includes hooks for checking JSON, TOML, and ensuring no merge conflicts, among others. It also utilizes `ruff` for fast Python linting and formatting, demonstrating the flexibility and power of pre-commit in maintaining code quality.
|
||||||
|
|
||||||
|
For detailed information and advanced configurations, refer to the [official pre-commit documentation](https://pre-commit.com/).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Development
|
||||||
|
### Pre-commit
|
||||||
|
Before adding any source code, it is recommended to have pre-commit installed on your local computer to check for all potential issues when comitting the code.
|
||||||
|
```bash
|
||||||
|
black . # Format the code
|
||||||
|
pip install pre-commit
|
||||||
|
pre-commit install
|
||||||
|
pre-commit install --hook-type commit-msg
|
||||||
|
pre-commit run --all-files # Check if everything is okay
|
||||||
|
```
|
||||||
43
SECURITY.md
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This document outlines the security processes and policies for the Django Default project. Our goal is to keep the project as secure as possible and to deal promptly with any security issues that arise.
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
The following versions of Django Default are currently being supported with security updates:
|
||||||
|
|
||||||
|
| Version | Supported |
|
||||||
|
| ------- | ------------------ |
|
||||||
|
| 1.0.x | :white_check_mark: |
|
||||||
|
| < 1.0 | :x: |
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
If you believe you have found a security vulnerability in Django Default, please report it to us as soon as possible. Do not report security vulnerabilities through public GitHub issues.
|
||||||
|
|
||||||
|
Please send your report to: jahongirhakimjonov@gmail.com
|
||||||
|
|
||||||
|
Include the following information with your report:
|
||||||
|
|
||||||
|
- A description of the vulnerability
|
||||||
|
- Steps to reproduce the issue
|
||||||
|
- Potential impact of the vulnerability
|
||||||
|
|
||||||
|
We take all security reports seriously and will respond swiftly to fix verifiable security issues. We ask that you follow responsible disclosure, not disclosing the vulnerability until we have had a chance to address it.
|
||||||
|
|
||||||
|
## Security Update Policy
|
||||||
|
|
||||||
|
Once a security issue is reported, we will assess the impact and develop a fix. Security updates will be released as part of our regular update cycle or as an immediate patch, depending on the severity of the issue.
|
||||||
|
|
||||||
|
We will notify users of security updates through:
|
||||||
|
|
||||||
|
- [Project's Update Mechanism]
|
||||||
|
- [Mailing List, Blog, etc.]
|
||||||
|
|
||||||
|
## Acknowledgments
|
||||||
|
|
||||||
|
We would like to thank those who have contributed to the security of the [Project Name] project by reporting vulnerabilities.
|
||||||
|
|
||||||
|
Thank you for helping us keep Django Default secure.
|
||||||
0
apps/__init__.py
Normal file
0
apps/geology/__init__.py
Normal file
4
apps/geology/admin/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from .category import * # noqa
|
||||||
|
from .gallery import * # noqa
|
||||||
|
from .geology import * # noqa
|
||||||
|
from .photo import * # noqa
|
||||||
12
apps/geology/admin/category.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
from unfold.admin import ModelAdmin # noqa
|
||||||
|
|
||||||
|
from apps.geology.models import Category
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Category)
|
||||||
|
class CategoryAdmin(ModelAdmin):
|
||||||
|
list_display = ("name", "created_at", "updated_at")
|
||||||
|
search_fields = ("name",)
|
||||||
|
list_filter = ("created_at", "updated_at")
|
||||||
|
readonly_fields = ("created_at", "updated_at")
|
||||||
21
apps/geology/admin/gallery.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
from unfold.admin import ModelAdmin
|
||||||
|
|
||||||
|
from apps.geology.models import GalleryCategory, Gallery
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(GalleryCategory)
|
||||||
|
class GalleryCategoryAdmin(ModelAdmin):
|
||||||
|
list_display = ("id", "name", "created_at", "updated_at")
|
||||||
|
search_fields = ("name",)
|
||||||
|
filter_horizontal = ("gallery",)
|
||||||
|
list_filter = ("created_at", "updated_at")
|
||||||
|
exclude = ("count",)
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Gallery)
|
||||||
|
class GalleryAdmin(ModelAdmin):
|
||||||
|
list_display = ("id", "name", "created_at", "updated_at")
|
||||||
|
search_fields = ("name",)
|
||||||
|
list_filter = ("created_at", "updated_at")
|
||||||
|
exclude = ("type", "created_at", "updated_at", "name", "size")
|
||||||
48
apps/geology/admin/geology.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
from unfold.admin import ModelAdmin # noqa
|
||||||
|
|
||||||
|
from apps.geology.models import Geology
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Geology)
|
||||||
|
class GeologyAdmin(ModelAdmin):
|
||||||
|
list_display = ("name", "category", "created_at", "updated_at")
|
||||||
|
search_fields = ("name", "title", "body1", "body2", "body3")
|
||||||
|
list_filter = ("category", "created_at", "updated_at")
|
||||||
|
filter_horizontal = ("photos1", "photos2")
|
||||||
|
readonly_fields = ("created_at", "updated_at")
|
||||||
|
autocomplete_fields = ("category",)
|
||||||
|
fieldsets = (
|
||||||
|
(
|
||||||
|
"Asosiy ma'lumotlar",
|
||||||
|
{
|
||||||
|
"fields": (
|
||||||
|
"category",
|
||||||
|
"banner_title",
|
||||||
|
"banner",
|
||||||
|
"name",
|
||||||
|
"title",
|
||||||
|
"body1",
|
||||||
|
"address",
|
||||||
|
"image",
|
||||||
|
"location",
|
||||||
|
"composition",
|
||||||
|
"isp",
|
||||||
|
"analysis",
|
||||||
|
"body2",
|
||||||
|
"photos1",
|
||||||
|
"body3",
|
||||||
|
"photos2",
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Qo'shimcha ma'lumotlar",
|
||||||
|
{
|
||||||
|
"fields": (
|
||||||
|
"created_at",
|
||||||
|
"updated_at",
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
12
apps/geology/admin/photo.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
from unfold.admin import ModelAdmin # noqa
|
||||||
|
|
||||||
|
from apps.geology.models import Photo
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Photo)
|
||||||
|
class PhotoAdmin(ModelAdmin):
|
||||||
|
list_display = ("name", "description", "type", "size", "image", "created_at")
|
||||||
|
search_fields = ("name", "description", "type", "size", "image")
|
||||||
|
list_filter = ("type",)
|
||||||
|
exclude = ("created_at", "updated_at", "type", "size", "name")
|
||||||
9
apps/geology/apps.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class GeologyConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "apps.geology"
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
import apps.geology.signals # noqa
|
||||||
143
apps/geology/migrations/0001_initial.py
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
# Generated by Django 5.0.8 on 2024-10-22 12:10
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = []
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Category",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||||
|
("updated_at", models.DateTimeField(auto_now=True)),
|
||||||
|
("name", models.CharField(max_length=255, verbose_name="Nomi")),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Kategoriya",
|
||||||
|
"verbose_name_plural": "Kategoriyalar",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Photo",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||||
|
("updated_at", models.DateTimeField(auto_now=True)),
|
||||||
|
(
|
||||||
|
"name",
|
||||||
|
models.CharField(
|
||||||
|
blank=True, max_length=255, null=True, verbose_name="Nomi"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"description",
|
||||||
|
models.TextField(blank=True, null=True, verbose_name="Tavsif"),
|
||||||
|
),
|
||||||
|
("image", models.FileField(upload_to="media/", verbose_name="Fayl")),
|
||||||
|
(
|
||||||
|
"type",
|
||||||
|
models.CharField(
|
||||||
|
blank=True, max_length=255, null=True, verbose_name="Fayl turi"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"size",
|
||||||
|
models.BigIntegerField(
|
||||||
|
blank=True, default=0, null=True, verbose_name="Hajmi"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Foto",
|
||||||
|
"verbose_name_plural": "Fotolar",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Geology",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||||
|
("updated_at", models.DateTimeField(auto_now=True)),
|
||||||
|
("name", models.CharField(max_length=255, verbose_name="Nomi")),
|
||||||
|
("title", models.CharField(max_length=255, verbose_name="Sarlavha")),
|
||||||
|
("body1", models.TextField(verbose_name="Tavsif1")),
|
||||||
|
("body2", models.TextField(verbose_name="Tavsif2")),
|
||||||
|
("body3", models.TextField(verbose_name="Tavsif3")),
|
||||||
|
(
|
||||||
|
"banner",
|
||||||
|
models.ImageField(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
upload_to="banners/",
|
||||||
|
verbose_name="Banner",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("address", models.CharField(max_length=255, verbose_name="Manzil")),
|
||||||
|
("longitude", models.FloatField(verbose_name="Boylam")),
|
||||||
|
("latitude", models.FloatField(verbose_name="Kenglik")),
|
||||||
|
("composition", models.TextField(verbose_name="Tarkib")),
|
||||||
|
("isp", models.TextField(verbose_name="ISP")),
|
||||||
|
("analysis", models.TextField(verbose_name="Analiz")),
|
||||||
|
(
|
||||||
|
"category",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="cultures",
|
||||||
|
to="geology.category",
|
||||||
|
verbose_name="Kategoriya",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"photos1",
|
||||||
|
models.ManyToManyField(
|
||||||
|
related_name="geology_photos1",
|
||||||
|
to="geology.photo",
|
||||||
|
verbose_name="Fotolavhalar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"photos2",
|
||||||
|
models.ManyToManyField(
|
||||||
|
related_name="geology_photos2",
|
||||||
|
to="geology.photo",
|
||||||
|
verbose_name="Fotolavhalar",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Madan",
|
||||||
|
"verbose_name_plural": "Madanlar",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# Generated by Django 5.0.8 on 2024-10-26 07:31
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("geology", "0001_initial"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="category",
|
||||||
|
options={
|
||||||
|
"ordering": ["-created_at"],
|
||||||
|
"verbose_name": "Kategoriya",
|
||||||
|
"verbose_name_plural": "Kategoriyalar",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="geology",
|
||||||
|
options={
|
||||||
|
"ordering": ["-created_at"],
|
||||||
|
"verbose_name": "Madan",
|
||||||
|
"verbose_name_plural": "Madanlar",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="photo",
|
||||||
|
options={
|
||||||
|
"ordering": ["-created_at"],
|
||||||
|
"verbose_name": "Foto",
|
||||||
|
"verbose_name_plural": "Fotolar",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="photo",
|
||||||
|
name="image",
|
||||||
|
field=models.ImageField(upload_to="media/", verbose_name="Fayl"),
|
||||||
|
),
|
||||||
|
]
|
||||||
20
apps/geology/migrations/0003_geology_banner_title.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Generated by Django 5.0.8 on 2024-10-26 07:49
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("geology", "0002_alter_category_options_alter_geology_options_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="geology",
|
||||||
|
name="banner_title",
|
||||||
|
field=models.CharField(
|
||||||
|
blank=True, max_length=255, null=True, verbose_name="Banner sarlavhasi"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
87
apps/geology/migrations/0004_gallery_gallerycategory.py
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
# Generated by Django 5.0.8 on 2024-10-26 10:31
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("geology", "0003_geology_banner_title"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Gallery",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||||
|
("updated_at", models.DateTimeField(auto_now=True)),
|
||||||
|
(
|
||||||
|
"name",
|
||||||
|
models.CharField(
|
||||||
|
blank=True, max_length=255, null=True, verbose_name="Nomi"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"description",
|
||||||
|
models.TextField(blank=True, null=True, verbose_name="Tavsif"),
|
||||||
|
),
|
||||||
|
("image", models.ImageField(upload_to="media/", verbose_name="Fayl")),
|
||||||
|
(
|
||||||
|
"type",
|
||||||
|
models.CharField(
|
||||||
|
blank=True, max_length=255, null=True, verbose_name="Fayl turi"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"size",
|
||||||
|
models.BigIntegerField(
|
||||||
|
blank=True, default=0, null=True, verbose_name="Hajmi"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Galereya",
|
||||||
|
"verbose_name_plural": "Galereya",
|
||||||
|
"ordering": ["-created_at"],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="GalleryCategory",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||||
|
("updated_at", models.DateTimeField(auto_now=True)),
|
||||||
|
("name", models.CharField(max_length=255, verbose_name="Nomi")),
|
||||||
|
(
|
||||||
|
"gallery",
|
||||||
|
models.ManyToManyField(
|
||||||
|
related_name="gallery_category",
|
||||||
|
to="geology.gallery",
|
||||||
|
verbose_name="Galereya",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Galereya kategoriya",
|
||||||
|
"verbose_name_plural": "Galereya kategoriyalar",
|
||||||
|
"ordering": ["-created_at"],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
18
apps/geology/migrations/0005_gallerycategory_count.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.0.8 on 2024-10-26 10:47
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("geology", "0004_gallery_gallerycategory"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="gallerycategory",
|
||||||
|
name="count",
|
||||||
|
field=models.BigIntegerField(default=0, verbose_name="Soni"),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
# Generated by Django 5.0.8 on 2024-11-02 04:41
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("geology", "0005_gallerycategory_count"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="address",
|
||||||
|
field=models.CharField(max_length=255, verbose_name="Олинган жойи"),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="analysis",
|
||||||
|
field=models.TextField(
|
||||||
|
verbose_name="Тоғ жинсининг спектрал тахлил натижаси (%)"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="body1",
|
||||||
|
field=models.TextField(verbose_name="Tavsif"),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="body2",
|
||||||
|
field=models.TextField(
|
||||||
|
verbose_name="Тоғ жинсининг шаффоф шакилда кўриниши"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="body3",
|
||||||
|
field=models.TextField(verbose_name="Тоғ жинсининг аншлифда кўриниши"),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="composition",
|
||||||
|
field=models.TextField(verbose_name="Тог жинсининг кимёвий таркиби (%)"),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="isp",
|
||||||
|
field=models.TextField(
|
||||||
|
verbose_name="Тоғ жинсининг ISP - масс-спектрометрик"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="latitude",
|
||||||
|
field=models.FloatField(verbose_name="Kenglik (Координаталари)"),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="longitude",
|
||||||
|
field=models.FloatField(verbose_name="Boylam (Координаталари)"),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="name",
|
||||||
|
field=models.CharField(
|
||||||
|
max_length=255, verbose_name="Nomi (Пироксенли скарн)"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="photos1",
|
||||||
|
field=models.ManyToManyField(
|
||||||
|
related_name="geology_photos1",
|
||||||
|
to="geology.photo",
|
||||||
|
verbose_name="Барча кўрнишлар",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="photos2",
|
||||||
|
field=models.ManyToManyField(
|
||||||
|
related_name="geology_photos2",
|
||||||
|
to="geology.photo",
|
||||||
|
verbose_name="Барча кўрнишлар",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="title",
|
||||||
|
field=models.CharField(max_length=255, verbose_name="Sarlavha (Dr-1)"),
|
||||||
|
),
|
||||||
|
]
|
||||||
21
apps/geology/migrations/0007_alter_photo_options.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Generated by Django 5.0.8 on 2024-11-02 04:51
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("geology", "0006_alter_geology_address_alter_geology_analysis_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="photo",
|
||||||
|
options={
|
||||||
|
"ordering": ["-created_at"],
|
||||||
|
"verbose_name": "Барча кўрнишлар",
|
||||||
|
"verbose_name_plural": "Барча кўрнишлар",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
23
apps/geology/migrations/0008_geology_image.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 5.0.8 on 2024-11-02 05:07
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("geology", "0007_alter_photo_options"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="geology",
|
||||||
|
name="image",
|
||||||
|
field=models.ImageField(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
upload_to="images/",
|
||||||
|
verbose_name="Олинган жойи сурати",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
# Generated by Django 5.0.8 on 2024-11-06 12:18
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("geology", "0008_geology_image"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="geology",
|
||||||
|
name="latitude",
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="geology",
|
||||||
|
name="longitude",
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="geology",
|
||||||
|
name="location",
|
||||||
|
field=models.CharField(
|
||||||
|
blank=True, max_length=255, null=True, verbose_name="Кординаталар"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="address",
|
||||||
|
field=models.CharField(
|
||||||
|
blank=True, max_length=255, null=True, verbose_name="Олинган жойи"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="analysis",
|
||||||
|
field=models.TextField(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
verbose_name="Тоғ жинсининг спектрал тахлил натижаси (%)",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="body1",
|
||||||
|
field=models.TextField(
|
||||||
|
blank=True, null=True, verbose_name="Тог жинсининг макроскопик таснифи"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="body2",
|
||||||
|
field=models.TextField(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
verbose_name="Тоғ жинсининг шаффоф шлифда кўриниши",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="body3",
|
||||||
|
field=models.TextField(
|
||||||
|
blank=True, null=True, verbose_name="Тоғ жинсининг аншлифда кўриниши"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="composition",
|
||||||
|
field=models.TextField(
|
||||||
|
blank=True, null=True, verbose_name="Тог жинсининг кимёвий таркиби (%)"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="isp",
|
||||||
|
field=models.TextField(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
verbose_name="Тоғ жинсининг ISP - масс-спектрометрик тахлил натижаси (г/т)",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="name",
|
||||||
|
field=models.CharField(max_length=255, verbose_name="Тог жинси номи"),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="title",
|
||||||
|
field=models.CharField(
|
||||||
|
max_length=255, verbose_name="Тог жинсининг геологик раками"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Generated by Django 5.0.8 on 2024-11-20 07:05
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("geology", "0009_remove_geology_latitude_remove_geology_longitude_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="photos1",
|
||||||
|
field=models.ManyToManyField(
|
||||||
|
blank=True,
|
||||||
|
related_name="geology_photos1",
|
||||||
|
to="geology.photo",
|
||||||
|
verbose_name="Барча кўрнишлар",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="geology",
|
||||||
|
name="photos2",
|
||||||
|
field=models.ManyToManyField(
|
||||||
|
blank=True,
|
||||||
|
related_name="geology_photos2",
|
||||||
|
to="geology.photo",
|
||||||
|
verbose_name="Барча кўрнишлар",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
0
apps/geology/migrations/__init__.py
Normal file
4
apps/geology/models/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from .category import * # noqa
|
||||||
|
from .gallery import * # noqa
|
||||||
|
from .geology import * # noqa
|
||||||
|
from .photo import * # noqa
|
||||||
16
apps/geology/models/category.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from django.db import models
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from apps.shared.models import AbstractBaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class Category(AbstractBaseModel):
|
||||||
|
name = models.CharField(max_length=255, verbose_name=_("Nomi"))
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("Kategoriya")
|
||||||
|
verbose_name_plural = _("Kategoriyalar")
|
||||||
|
ordering = ["-created_at"]
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.name
|
||||||
20
apps/geology/models/gallery.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from django.db import models
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from apps.shared.models import AbstractBaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class GalleryCategory(AbstractBaseModel):
|
||||||
|
name = models.CharField(max_length=255, verbose_name=_("Nomi"))
|
||||||
|
count = models.BigIntegerField(default=0, verbose_name=_("Soni"))
|
||||||
|
gallery = models.ManyToManyField(
|
||||||
|
"Gallery", related_name="gallery_category", verbose_name=_("Galereya")
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("Galereya kategoriya")
|
||||||
|
verbose_name_plural = _("Galereya kategoriyalar")
|
||||||
|
ordering = ["-created_at"]
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.name
|
||||||
47
apps/geology/models/geology.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
from django.db import models
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from apps.shared.models import AbstractBaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class Geology(AbstractBaseModel):
|
||||||
|
category = models.ForeignKey(
|
||||||
|
"Category",
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
related_name="cultures",
|
||||||
|
verbose_name=_("Kategoriya"),
|
||||||
|
)
|
||||||
|
banner_title = models.CharField(
|
||||||
|
max_length=255, verbose_name=_("Banner sarlavhasi"), null=True, blank=True
|
||||||
|
)
|
||||||
|
banner = models.ImageField(
|
||||||
|
upload_to="banners/", verbose_name=_("Banner"), null=True, blank=True
|
||||||
|
)
|
||||||
|
name = models.CharField(max_length=255, verbose_name=_("Тог жинси номи"))
|
||||||
|
title = models.CharField(max_length=255, verbose_name=_("Тог жинсининг геологик раками"))
|
||||||
|
body1 = models.TextField(verbose_name=_("Тог жинсининг макроскопик таснифи"), null=True, blank=True)
|
||||||
|
address = models.CharField(max_length=255, verbose_name=_("Олинган жойи"), null=True, blank=True)
|
||||||
|
image = models.ImageField(upload_to="images/", verbose_name=_("Олинган жойи сурати"), null=True, blank=True)
|
||||||
|
location = models.CharField(max_length=255, verbose_name=_("Кординаталар"), null=True, blank=True)
|
||||||
|
composition = models.TextField(verbose_name=_("Тог жинсининг кимёвий таркиби (%)"), null=True, blank=True)
|
||||||
|
isp = models.TextField(verbose_name=_("Тоғ жинсининг ISP - масс-спектрометрик тахлил натижаси (г/т)"), null=True,
|
||||||
|
blank=True)
|
||||||
|
analysis = models.TextField(
|
||||||
|
verbose_name=_("Тоғ жинсининг спектрал тахлил натижаси (%)"), null=True, blank=True
|
||||||
|
)
|
||||||
|
body2 = models.TextField(verbose_name=_("Тоғ жинсининг шаффоф шлифда кўриниши"), null=True, blank=True)
|
||||||
|
photos1 = models.ManyToManyField(
|
||||||
|
"Photo", verbose_name=_("Барча кўрнишлар"), related_name="geology_photos1", blank=True
|
||||||
|
)
|
||||||
|
body3 = models.TextField(verbose_name=_("Тоғ жинсининг аншлифда кўриниши"), null=True, blank=True)
|
||||||
|
photos2 = models.ManyToManyField(
|
||||||
|
"Photo", verbose_name=_("Барча кўрнишлар"), related_name="geology_photos2", blank=True
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("Madan")
|
||||||
|
verbose_name_plural = _("Madanlar")
|
||||||
|
ordering = ["-created_at"]
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.name
|
||||||
66
apps/geology/models/photo.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
from django.db import models
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from apps.shared.models import AbstractBaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class Photo(AbstractBaseModel):
|
||||||
|
name = models.CharField(
|
||||||
|
max_length=255, blank=True, null=True, verbose_name=_("Nomi")
|
||||||
|
)
|
||||||
|
description = models.TextField(blank=True, null=True, verbose_name=_("Tavsif"))
|
||||||
|
image = models.ImageField(upload_to="media/", verbose_name=_("Fayl"))
|
||||||
|
type = models.CharField(
|
||||||
|
max_length=255, blank=True, null=True, verbose_name=_("Fayl turi")
|
||||||
|
)
|
||||||
|
size = models.BigIntegerField(
|
||||||
|
blank=True, null=True, default=0, verbose_name=_("Hajmi")
|
||||||
|
)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
self.type = self.image.name.split(".")[-1]
|
||||||
|
self.size = self.image.size
|
||||||
|
if self.name is None:
|
||||||
|
self.name = (
|
||||||
|
self.image.name if self.image.name is not None else f"Media {self.id}"
|
||||||
|
)
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("Барча кўрнишлар")
|
||||||
|
verbose_name_plural = _("Барча кўрнишлар")
|
||||||
|
ordering = ["-created_at"]
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return str(self.description) if str(self.description) else f"Photo {self.id}"
|
||||||
|
|
||||||
|
|
||||||
|
class Gallery(AbstractBaseModel):
|
||||||
|
name = models.CharField(
|
||||||
|
max_length=255, blank=True, null=True, verbose_name=_("Nomi")
|
||||||
|
)
|
||||||
|
description = models.TextField(blank=True, null=True, verbose_name=_("Tavsif"))
|
||||||
|
image = models.ImageField(upload_to="media/", verbose_name=_("Fayl"))
|
||||||
|
type = models.CharField(
|
||||||
|
max_length=255, blank=True, null=True, verbose_name=_("Fayl turi")
|
||||||
|
)
|
||||||
|
size = models.BigIntegerField(
|
||||||
|
blank=True, null=True, default=0, verbose_name=_("Hajmi")
|
||||||
|
)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
self.type = self.image.name.split(".")[-1]
|
||||||
|
self.size = self.image.size
|
||||||
|
if self.name is None:
|
||||||
|
self.name = (
|
||||||
|
self.image.name if self.image.name is not None else f"Media {self.id}"
|
||||||
|
)
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("Galereya")
|
||||||
|
verbose_name_plural = _("Galereya")
|
||||||
|
ordering = ["-created_at"]
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return str(self.description) if str(self.description) else f"Gallery {self.id}"
|
||||||
4
apps/geology/serializers/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from .category import * # noqa
|
||||||
|
from .gallery import * # noqa
|
||||||
|
from .geology import * # noqa
|
||||||
|
from .photo import * # noqa
|
||||||
16
apps/geology/serializers/category.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from typing import Type
|
||||||
|
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from apps.geology.models import Category, Geology
|
||||||
|
|
||||||
|
|
||||||
|
class CategorySerializer(serializers.ModelSerializer):
|
||||||
|
count = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model: Type[Category] = Category
|
||||||
|
fields: str = ("id", "count", "name", "created_at", "updated_at")
|
||||||
|
|
||||||
|
def get_count(self, obj):
|
||||||
|
return Geology.objects.filter(category=obj).count()
|
||||||
17
apps/geology/serializers/gallery.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from apps.geology.models import Gallery, GalleryCategory
|
||||||
|
|
||||||
|
|
||||||
|
class GallerySerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Gallery
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
|
class GalleryCategorySerializer(serializers.ModelSerializer):
|
||||||
|
gallery = GallerySerializer(many=True, read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = GalleryCategory
|
||||||
|
fields = ("id", "name", "count", "gallery", "created_at", "updated_at")
|
||||||
161
apps/geology/serializers/geology.py
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
import logging
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
from drf_spectacular.utils import extend_schema_field
|
||||||
|
from rest_framework import exceptions, status
|
||||||
|
from rest_framework import serializers
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from apps.geology.models import Geology, Photo
|
||||||
|
|
||||||
|
|
||||||
|
class GeologySerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Geology
|
||||||
|
fields = (
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"title",
|
||||||
|
"body1",
|
||||||
|
"body2",
|
||||||
|
"body3",
|
||||||
|
"banner_title",
|
||||||
|
"banner",
|
||||||
|
"address",
|
||||||
|
"image",
|
||||||
|
"location",
|
||||||
|
"composition",
|
||||||
|
"isp",
|
||||||
|
"analysis",
|
||||||
|
"category",
|
||||||
|
"created_at",
|
||||||
|
"updated_at",
|
||||||
|
)
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
try:
|
||||||
|
request = self.context.get("request")
|
||||||
|
photo_data1 = []
|
||||||
|
photo_data2 = []
|
||||||
|
|
||||||
|
for key in request.data:
|
||||||
|
if key.startswith("description1[") and key.endswith("]"):
|
||||||
|
index = key[len("description1[") : -1]
|
||||||
|
file_key = f"image1[{index}]"
|
||||||
|
photo_desc = request.data.get(key)
|
||||||
|
photo_file = request.FILES.get(file_key)
|
||||||
|
|
||||||
|
if not photo_file:
|
||||||
|
return Response(
|
||||||
|
{
|
||||||
|
"error": f"File is required for photo item {index} in photos1"
|
||||||
|
},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
||||||
|
if not photo_desc:
|
||||||
|
photo_desc = photo_file.name
|
||||||
|
photo_data1.append({"image": photo_file, "description": photo_desc})
|
||||||
|
|
||||||
|
if key.startswith("description2[") and key.endswith("]"):
|
||||||
|
index = key[len("description2[") : -1]
|
||||||
|
file_key = f"image2[{index}]"
|
||||||
|
photo_desc = request.data.get(key)
|
||||||
|
photo_file = request.FILES.get(file_key)
|
||||||
|
|
||||||
|
if not photo_file:
|
||||||
|
return Response(
|
||||||
|
{
|
||||||
|
"error": f"File is required for photo item {index} in photos2"
|
||||||
|
},
|
||||||
|
status=status.HTTP_400_BAD_REQUEST,
|
||||||
|
)
|
||||||
|
if not photo_desc:
|
||||||
|
photo_desc = photo_file.name
|
||||||
|
photo_data2.append({"image": photo_file, "description": photo_desc})
|
||||||
|
|
||||||
|
geology = Geology.objects.create(
|
||||||
|
name=validated_data.get("name"),
|
||||||
|
title=validated_data.get("title"),
|
||||||
|
body1=validated_data.get("body1"),
|
||||||
|
body2=validated_data.get("body2"),
|
||||||
|
body3=validated_data.get("body3"),
|
||||||
|
banner_title=validated_data.get("banner_title"),
|
||||||
|
banner=validated_data.get("banner"),
|
||||||
|
address=validated_data.get("address"),
|
||||||
|
location=validated_data.get("location"),
|
||||||
|
composition=validated_data.get("composition"),
|
||||||
|
isp=validated_data.get("isp"),
|
||||||
|
analysis=validated_data.get("analysis"),
|
||||||
|
category=validated_data.get("category"),
|
||||||
|
)
|
||||||
|
|
||||||
|
for photo in photo_data1:
|
||||||
|
photo_instance = Photo.objects.create(
|
||||||
|
image=photo["image"], description=photo["description"]
|
||||||
|
)
|
||||||
|
geology.photos1.add(photo_instance)
|
||||||
|
|
||||||
|
for photo in photo_data2:
|
||||||
|
photo_instance = Photo.objects.create(
|
||||||
|
image=photo["image"], description=photo["description"]
|
||||||
|
)
|
||||||
|
geology.photos2.add(photo_instance)
|
||||||
|
return geology
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Error in create method: {str(e)}")
|
||||||
|
raise exceptions.ValidationError({"detail": str(e)})
|
||||||
|
|
||||||
|
|
||||||
|
class GeologyDetailSerializer(serializers.ModelSerializer):
|
||||||
|
category = serializers.SerializerMethodField()
|
||||||
|
photos1 = serializers.SerializerMethodField()
|
||||||
|
photos2 = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Geology
|
||||||
|
fields = (
|
||||||
|
"id",
|
||||||
|
"category",
|
||||||
|
"banner_title",
|
||||||
|
"banner",
|
||||||
|
"name",
|
||||||
|
"title",
|
||||||
|
"body1",
|
||||||
|
"address",
|
||||||
|
"image",
|
||||||
|
"location",
|
||||||
|
"composition",
|
||||||
|
"isp",
|
||||||
|
"analysis",
|
||||||
|
"body2",
|
||||||
|
"photos1",
|
||||||
|
"body3",
|
||||||
|
"photos2",
|
||||||
|
"created_at",
|
||||||
|
"updated_at",
|
||||||
|
)
|
||||||
|
|
||||||
|
def to_representation(self, instance):
|
||||||
|
representation = super().to_representation(instance)
|
||||||
|
if representation.get("banner"):
|
||||||
|
parsed_url = urlparse(representation["banner"])
|
||||||
|
representation["banner"] = parsed_url.path
|
||||||
|
return representation
|
||||||
|
|
||||||
|
@extend_schema_field(serializers.DictField())
|
||||||
|
def get_category(self, obj):
|
||||||
|
from apps.geology.serializers.category import CategorySerializer
|
||||||
|
|
||||||
|
return CategorySerializer(obj.category).data
|
||||||
|
|
||||||
|
@extend_schema_field(serializers.ListField(child=serializers.DictField()))
|
||||||
|
def get_photos1(self, obj):
|
||||||
|
from apps.geology.serializers.photo import PhotoSerializer
|
||||||
|
|
||||||
|
return PhotoSerializer(obj.photos1.all(), many=True).data
|
||||||
|
|
||||||
|
@extend_schema_field(serializers.ListField(child=serializers.DictField()))
|
||||||
|
def get_photos2(self, obj):
|
||||||
|
from apps.geology.serializers.photo import PhotoSerializer
|
||||||
|
|
||||||
|
return PhotoSerializer(obj.photos2.all(), many=True).data
|
||||||
11
apps/geology/serializers/photo.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from typing import Type
|
||||||
|
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from apps.geology.models import Photo
|
||||||
|
|
||||||
|
|
||||||
|
class PhotoSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model: Type[Photo] = Photo
|
||||||
|
fields: str = "__all__"
|
||||||
1
apps/geology/signals/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from .gallery import * # noqa
|
||||||
12
apps/geology/signals/gallery.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from django.db.models.signals import m2m_changed
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
|
from apps.geology.models import GalleryCategory
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(m2m_changed, sender=GalleryCategory.gallery.through)
|
||||||
|
def gallery_category_m2m_changed(sender, instance, action, **kwargs):
|
||||||
|
if action in ["post_add", "post_remove", "post_clear"]:
|
||||||
|
instance.count = instance.gallery.count()
|
||||||
|
print(instance.count)
|
||||||
|
instance.save()
|
||||||
0
apps/geology/tests/__init__.py
Normal file
12
apps/geology/urls.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
from django.urls import path
|
||||||
|
from django.urls.resolvers import URLPattern
|
||||||
|
|
||||||
|
from apps.geology.views import GeologyView, CategoryView, GalleryCategoryView
|
||||||
|
|
||||||
|
urlpatterns: List[URLPattern] = [
|
||||||
|
path("geology/", GeologyView.as_view(), name="geology"),
|
||||||
|
path("category/", CategoryView.as_view(), name="category"),
|
||||||
|
path("gallery/", GalleryCategoryView.as_view(), name="gallery"),
|
||||||
|
]
|
||||||
3
apps/geology/views/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from .category import * # noqa
|
||||||
|
from .gallery import * # noqa
|
||||||
|
from .geology import * # noqa
|
||||||
24
apps/geology/views/category.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
from typing import Type
|
||||||
|
|
||||||
|
from django.db.models import QuerySet
|
||||||
|
from rest_framework.generics import GenericAPIView
|
||||||
|
from rest_framework.permissions import AllowAny
|
||||||
|
from rest_framework.request import Request
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.serializers import Serializer
|
||||||
|
|
||||||
|
from apps.geology.models import Category
|
||||||
|
from apps.geology.serializers import CategorySerializer
|
||||||
|
|
||||||
|
|
||||||
|
class CategoryView(GenericAPIView):
|
||||||
|
permission_classes = [AllowAny]
|
||||||
|
serializer_class: Type[Serializer] = CategorySerializer
|
||||||
|
|
||||||
|
def get_queryset(self) -> QuerySet[Category]:
|
||||||
|
return Category.objects.all()
|
||||||
|
|
||||||
|
def get(self, request: Request) -> Response:
|
||||||
|
categories = self.get_queryset()
|
||||||
|
serializer = self.serializer_class(categories, many=True)
|
||||||
|
return Response(serializer.data)
|
||||||
24
apps/geology/views/gallery.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
from typing import Type
|
||||||
|
|
||||||
|
from django.db.models import QuerySet
|
||||||
|
from rest_framework.generics import GenericAPIView
|
||||||
|
from rest_framework.permissions import AllowAny
|
||||||
|
from rest_framework.request import Request
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.serializers import Serializer
|
||||||
|
|
||||||
|
from apps.geology.models import GalleryCategory
|
||||||
|
from apps.geology.serializers import GalleryCategorySerializer
|
||||||
|
|
||||||
|
|
||||||
|
class GalleryCategoryView(GenericAPIView):
|
||||||
|
permission_classes = [AllowAny]
|
||||||
|
serializer_class: Type[Serializer] = GalleryCategorySerializer
|
||||||
|
|
||||||
|
def get_queryset(self) -> QuerySet[GalleryCategory]:
|
||||||
|
return GalleryCategory.objects.all()
|
||||||
|
|
||||||
|
def get(self, request: Request) -> Response:
|
||||||
|
categories = self.get_queryset()
|
||||||
|
serializer = self.serializer_class(categories, many=True)
|
||||||
|
return Response(serializer.data)
|
||||||
45
apps/geology/views/geology.py
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
from typing import Type
|
||||||
|
|
||||||
|
from django.db.models import QuerySet
|
||||||
|
from rest_framework import status
|
||||||
|
from rest_framework.generics import GenericAPIView
|
||||||
|
from rest_framework.permissions import AllowAny
|
||||||
|
from rest_framework.request import Request
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.serializers import Serializer
|
||||||
|
|
||||||
|
from apps.geology.models import Geology
|
||||||
|
from apps.geology.serializers import GeologySerializer, GeologyDetailSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class GeologyView(GenericAPIView):
|
||||||
|
permission_classes = [AllowAny]
|
||||||
|
|
||||||
|
def get_serializer_class(self) -> Type[Serializer]:
|
||||||
|
if self.request.method == "POST":
|
||||||
|
return GeologySerializer
|
||||||
|
return GeologyDetailSerializer
|
||||||
|
|
||||||
|
def get_queryset(self) -> QuerySet[Geology]:
|
||||||
|
return Geology.objects.all().select_related()
|
||||||
|
|
||||||
|
def get(self, request: Request) -> Response:
|
||||||
|
geology_id = request.query_params.get("id")
|
||||||
|
category_id = request.query_params.get("category")
|
||||||
|
if geology_id:
|
||||||
|
geologies = Geology.objects.filter(id=geology_id)
|
||||||
|
elif category_id:
|
||||||
|
geologies = Geology.objects.filter(category_id=category_id)
|
||||||
|
else:
|
||||||
|
geologies = self.get_queryset()
|
||||||
|
serializer = self.get_serializer(geologies, many=True)
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
def post(self, request: Request) -> Response:
|
||||||
|
serializer = self.get_serializer(
|
||||||
|
data=request.data, context={"request": request}
|
||||||
|
)
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save()
|
||||||
|
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||||
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
0
apps/shared/__init__.py
Normal file
33
apps/shared/admin.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin
|
||||||
|
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
||||||
|
from django.contrib.auth.models import Group, User
|
||||||
|
from unfold.admin import ModelAdmin # noqa
|
||||||
|
from unfold.forms import (
|
||||||
|
UserChangeForm,
|
||||||
|
UserCreationForm,
|
||||||
|
AdminPasswordChangeForm,
|
||||||
|
) # noqa
|
||||||
|
|
||||||
|
admin.site.unregister(Group)
|
||||||
|
admin.site.unregister(User)
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Group)
|
||||||
|
class GroupAdmin(BaseGroupAdmin, ModelAdmin):
|
||||||
|
list_display = ("name",)
|
||||||
|
search_fields = ("name",)
|
||||||
|
filter_vertical = ("permissions",)
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(User)
|
||||||
|
class UserAdmin(BaseUserAdmin, ModelAdmin):
|
||||||
|
change_password_form = AdminPasswordChangeForm
|
||||||
|
add_form = UserCreationForm
|
||||||
|
form = UserChangeForm
|
||||||
|
list_display = ("username", "email", "is_active", "is_staff", "is_superuser")
|
||||||
|
list_filter = ("is_active", "is_staff", "is_superuser")
|
||||||
|
search_fields = ("username", "email")
|
||||||
|
ordering = ("username",)
|
||||||
|
list_editable = ("is_active", "is_staff", "is_superuser")
|
||||||
|
filter_vertical = ("groups", "user_permissions")
|
||||||
6
apps/shared/apps.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class SharedConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "apps.shared"
|
||||||
0
apps/shared/management/__init__.py
Normal file
0
apps/shared/management/commands/__init__.py
Normal file
25
apps/shared/management/commands/createadmin.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
user = get_user_model()
|
||||||
|
self.create_superuser(user, "jahongir", "jahongirhakimjonov@gmail.com", "1253")
|
||||||
|
self.create_superuser(
|
||||||
|
user, "Jahongir", "jahongirhakimjonov@gmail.com", "20030307mart"
|
||||||
|
)
|
||||||
|
self.create_superuser(
|
||||||
|
user, "998330078587", "jahongirhakimjonov@gmail.com", "20030307mart"
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_superuser(self, user, username, email, password):
|
||||||
|
if not user.objects.filter(username=username).exists():
|
||||||
|
user.objects.create_superuser(username, email, password)
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.SUCCESS(f"Superuser {username} created successfully.")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.SUCCESS(f"Superuser {username} already exists.")
|
||||||
|
)
|
||||||
52
apps/shared/management/commands/makeapp.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.management import call_command
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = (
|
||||||
|
"Creates a new Django app inside the apps folder and sets the name in apps.py"
|
||||||
|
)
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument("app_name", type=str, help="The name of the app to create")
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
app_name = options["app_name"]
|
||||||
|
app_directory = os.path.join("apps", app_name)
|
||||||
|
|
||||||
|
os.makedirs(app_directory, exist_ok=True)
|
||||||
|
|
||||||
|
init_file_path = os.path.join("apps", "__init__.py")
|
||||||
|
|
||||||
|
if not os.path.exists(init_file_path):
|
||||||
|
open(init_file_path, "w").close()
|
||||||
|
|
||||||
|
call_command("startapp", app_name, app_directory)
|
||||||
|
|
||||||
|
apps_file_path = os.path.join(app_directory, "apps.py")
|
||||||
|
with open(apps_file_path, "r") as file:
|
||||||
|
filedata = file.read()
|
||||||
|
|
||||||
|
filedata = filedata.replace(f'name = "{app_name}"', f'name = "apps.{app_name}"')
|
||||||
|
|
||||||
|
with open(apps_file_path, "w") as file:
|
||||||
|
file.write(filedata)
|
||||||
|
|
||||||
|
for file_name in ["admin.py", "models.py", "views.py", "tests.py"]:
|
||||||
|
os.remove(os.path.join(app_directory, file_name))
|
||||||
|
|
||||||
|
urls_file_path = os.path.join(app_directory, "urls.py")
|
||||||
|
with open(urls_file_path, "w") as file:
|
||||||
|
file.write("from django.urls import path\n\nurlpatterns = []\n")
|
||||||
|
|
||||||
|
def create_package(package_name): # noqa
|
||||||
|
os.makedirs(package_name, exist_ok=True)
|
||||||
|
with open(os.path.join(package_name, "__init__.py"), "w"):
|
||||||
|
pass
|
||||||
|
|
||||||
|
for package_name in ["models", "views", "admin", "serializers", "tests"]:
|
||||||
|
create_package(os.path.join(app_directory, package_name))
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS(f"App {app_name} created successfully!"))
|
||||||
43
apps/shared/management/commands/nginx.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from colorama import Fore, Style
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Generates a new nginx config file with custom domain and project path"
|
||||||
|
|
||||||
|
def handle(self, *args, **kwargs):
|
||||||
|
domain_name = input(
|
||||||
|
Fore.LIGHTCYAN_EX + "Please enter the domain name: " + Style.RESET_ALL
|
||||||
|
)
|
||||||
|
project_name = input(
|
||||||
|
Fore.LIGHTMAGENTA_EX + "\nPlease enter the project name: " + Style.RESET_ALL
|
||||||
|
)
|
||||||
|
project_port = input(
|
||||||
|
Fore.LIGHTBLUE_EX + "\nPlease enter the project port: " + Style.RESET_ALL
|
||||||
|
)
|
||||||
|
|
||||||
|
source_file_path = "./deployments/compose/nginx/nginx.conf"
|
||||||
|
target_dir_path = "./deployments/nginx"
|
||||||
|
target_file_path = f"{target_dir_path}/{domain_name}.conf"
|
||||||
|
|
||||||
|
with open(source_file_path, "r") as file:
|
||||||
|
file_contents = file.read()
|
||||||
|
|
||||||
|
file_contents = file_contents.replace("yourdomain.uz", domain_name)
|
||||||
|
file_contents = file_contents.replace("/path/project", project_name)
|
||||||
|
file_contents = file_contents.replace("PROJECT_PORT", project_port)
|
||||||
|
|
||||||
|
os.makedirs(target_dir_path, exist_ok=True)
|
||||||
|
|
||||||
|
with open(target_file_path, "w") as file:
|
||||||
|
file.write(file_contents)
|
||||||
|
|
||||||
|
self.stdout.write(
|
||||||
|
self.style.SUCCESS(
|
||||||
|
Fore.LIGHTGREEN_EX
|
||||||
|
+ f"\n\n\nSuccessfully created {target_file_path}\n\n"
|
||||||
|
+ Style.RESET_ALL
|
||||||
|
)
|
||||||
|
)
|
||||||
21
apps/shared/management/commands/secret_key.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
from colorama import Fore, Style
|
||||||
|
from django.core.management import utils
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Generates a new Django secret key"
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
print(
|
||||||
|
Fore.LIGHTCYAN_EX
|
||||||
|
+ "<======================================================>"
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
"<=" + Style.RESET_ALL,
|
||||||
|
Fore.LIGHTMAGENTA_EX + utils.get_random_secret_key() + Style.RESET_ALL,
|
||||||
|
Fore.LIGHTCYAN_EX + "=>",
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
"<======================================================>" + Style.RESET_ALL
|
||||||
|
)
|
||||||
0
apps/shared/migrations/__init__.py
Normal file
9
apps/shared/models.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractBaseModel(models.Model):
|
||||||
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
1
apps/shared/tests.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# Create your tests here.
|
||||||
6
apps/shared/urls.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.urls import path
|
||||||
|
from .views import HomeView
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("", HomeView.as_view(), name="home"),
|
||||||
|
]
|
||||||
5
apps/shared/views.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
|
|
||||||
|
class HomeView(TemplateView):
|
||||||
|
template_name = "index.html"
|
||||||
10038
assets/static/css/bootstrap.css
vendored
Normal file
4
assets/static/css/font-awesome.min.css
vendored
Normal file
5
assets/static/css/jazzmin.css
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.login-logo img {
|
||||||
|
border-radius: 100%;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
107
assets/static/css/responsive.css
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
@media (max-width: 1300px) {}
|
||||||
|
|
||||||
|
@media (max-width: 1120px) {}
|
||||||
|
|
||||||
|
@media (max-width: 992px) {
|
||||||
|
.hero_area {
|
||||||
|
min-height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero_area {
|
||||||
|
background: linear-gradient(130deg, #231a6f, #0f054c);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero_area .hero_bg_box {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section {
|
||||||
|
padding: 45px 0 75px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-nav {
|
||||||
|
padding-top: 15px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-nav .nav-item .nav-link {
|
||||||
|
padding: 5px 25px;
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.about_section .img-box {
|
||||||
|
margin-bottom: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
.header_section .header_top .contact_nav a span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.client_section .client_container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client_section .box {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.owl-nav {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client_section .owl-carousel .owl-nav .owl-prev,
|
||||||
|
.client_section .owl-carousel .owl-nav .owl-next {
|
||||||
|
position: unset;
|
||||||
|
margin: 0 2.5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.slider_section .detail-box h1 {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track_section form {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track_section form input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track_section form button {
|
||||||
|
padding: 10px 60px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 420px) {
|
||||||
|
.service_section .box {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service_section .box .img-box {
|
||||||
|
justify-content: flex-start;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 376px) {}
|
||||||
|
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
.container {
|
||||||
|
max-width: 1170px;
|
||||||
|
}
|
||||||
|
}
|
||||||
944
assets/static/css/style.css
Normal file
@@ -0,0 +1,944 @@
|
|||||||
|
@import url("https://fonts.googleapis.com/css2?family=Lato:wght@400;700&family=Open+Sans:wght@300;400;600;700&display=swap");
|
||||||
|
@import url("https://fonts.googleapis.com/css2?family=Lato:wght@400;700&family=Open+Sans:wght@300;400;600;700&display=swap");
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: "Open Sans", sans-serif;
|
||||||
|
color: #0c0c0c;
|
||||||
|
background-color: #ffffff;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout_padding {
|
||||||
|
padding: 90px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout_padding2 {
|
||||||
|
padding: 75px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout_padding2-top {
|
||||||
|
padding-top: 75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout_padding2-bottom {
|
||||||
|
padding-bottom: 75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout_padding-top {
|
||||||
|
padding-top: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout_padding-bottom {
|
||||||
|
padding-bottom: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading_container {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
-webkit-box-align: start;
|
||||||
|
-ms-flex-align: start;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading_container h2 {
|
||||||
|
position: relative;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading_container h2 span {
|
||||||
|
color: #00bbf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading_container p {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading_container.heading_center {
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
a,
|
||||||
|
a:hover,
|
||||||
|
a:focus {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover,
|
||||||
|
a:focus {
|
||||||
|
color: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn,
|
||||||
|
.btn:focus {
|
||||||
|
outline: none !important;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*header section*/
|
||||||
|
.hero_area {
|
||||||
|
position: relative;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero_area .hero_bg_box {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
-webkit-box-align: end;
|
||||||
|
-ms-flex-align: end;
|
||||||
|
align-items: flex-end;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero_area .hero_bg_box .bg_img_box {
|
||||||
|
min-width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero_area .hero_bg_box img {
|
||||||
|
min-width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_page .hero_area {
|
||||||
|
min-height: auto;
|
||||||
|
background: linear-gradient(130deg, #231a6f, #0f054c);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_page .hero_area .hero_bg_box {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_section {
|
||||||
|
padding: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_section .container-fluid {
|
||||||
|
padding-right: 25px;
|
||||||
|
padding-left: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-brand span {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 24px;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-nav {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-nav .nav-item .nav-link {
|
||||||
|
padding: 5px 20px;
|
||||||
|
color: #ffffff;
|
||||||
|
text-align: center;
|
||||||
|
text-transform: uppercase;
|
||||||
|
border-radius: 5px;
|
||||||
|
-webkit-transition: all 0.3s;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-nav .nav-item:hover .nav-link, .custom_nav-container .navbar-nav .nav-item.active .nav-link {
|
||||||
|
color: #00bbf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-nav .nav-item.active .nav-link {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .nav_search-btn {
|
||||||
|
width: 35px;
|
||||||
|
height: 35px;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .nav_search-btn:hover {
|
||||||
|
color: #00bbf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-toggler {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-toggler {
|
||||||
|
padding: 0;
|
||||||
|
width: 37px;
|
||||||
|
height: 42px;
|
||||||
|
-webkit-transition: all 0.3s;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-toggler span {
|
||||||
|
display: block;
|
||||||
|
width: 35px;
|
||||||
|
height: 4px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
margin: 7px 0;
|
||||||
|
-webkit-transition: all 0.3s;
|
||||||
|
transition: all 0.3s;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-toggler span::before, .custom_nav-container .navbar-toggler span::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
top: -10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
-webkit-transition: all 0.3s;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-toggler span::after {
|
||||||
|
top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-toggler[aria-expanded="true"] {
|
||||||
|
-webkit-transform: rotate(360deg);
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-toggler[aria-expanded="true"] span {
|
||||||
|
-webkit-transform: rotate(45deg);
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-toggler[aria-expanded="true"] span::before, .custom_nav-container .navbar-toggler[aria-expanded="true"] span::after {
|
||||||
|
-webkit-transform: rotate(90deg);
|
||||||
|
transform: rotate(90deg);
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*end header section*/
|
||||||
|
/* slider section */
|
||||||
|
.slider_section {
|
||||||
|
-webkit-box-flex: 1;
|
||||||
|
-ms-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
padding: 45px 0 145px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .row {
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section #customCarousel1 {
|
||||||
|
width: 100%;
|
||||||
|
position: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .detail-box {
|
||||||
|
color: #00204a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .detail-box h1 {
|
||||||
|
font-size: 3rem;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .detail-box p {
|
||||||
|
color: #fefefe;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .detail-box .btn-box {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
margin: 0 -5px;
|
||||||
|
margin-top: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .detail-box .btn-box a {
|
||||||
|
margin: 5px;
|
||||||
|
text-align: center;
|
||||||
|
width: 165px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .detail-box .btn-box .btn1 {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 10px 15px;
|
||||||
|
background-color: #00bbf0;
|
||||||
|
color: #ffffff;
|
||||||
|
border-radius: 25px;
|
||||||
|
-webkit-transition: all 0.3s;
|
||||||
|
transition: all 0.5s;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn1:hover {
|
||||||
|
background-color: #00bbf0;
|
||||||
|
box-shadow: 0 0 5px #00bbf0, 0 0 25px #00bbf0, 0 0 50px #00bbf0, 0 0 200px #00bbf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link:hover {
|
||||||
|
background-color: #002b64;
|
||||||
|
box-shadow: 0 0 5px #00bbf0, 0 0 25px #00bbf0, 0 0 50px #00bbf0, 0 0 200px #00bbf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .detail-box .btn-box .btn1:hover {
|
||||||
|
background-color: #007fa4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .detail-box .btn-box .btn2 {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 10px 15px;
|
||||||
|
background-color: #000000;
|
||||||
|
color: #ffffff;
|
||||||
|
border-radius: 0;
|
||||||
|
-webkit-transition: all 0.3s;
|
||||||
|
transition: all 0.3s;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .detail-box .btn-box .btn2:hover {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .img-box {
|
||||||
|
margin: 45px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .img-box img {
|
||||||
|
width: 100%;
|
||||||
|
-webkit-animation: upDown 5s infinite;
|
||||||
|
animation: upDown 5s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes upDown {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: translateY(-45px);
|
||||||
|
transform: translateY(-45px);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
-webkit-transform: translateY(45px);
|
||||||
|
transform: translateY(45px);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: translateY(-45px);
|
||||||
|
transform: translateY(-45px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes upDown {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: translateY(-45px);
|
||||||
|
transform: translateY(-45px);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
-webkit-transform: translateY(45px);
|
||||||
|
transform: translateY(45px);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: translateY(-45px);
|
||||||
|
transform: translateY(-45px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .carousel-indicators {
|
||||||
|
position: unset;
|
||||||
|
margin: 0;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .carousel-indicators li {
|
||||||
|
background-color: #ffffff;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border-radius: 100%;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider_section .carousel-indicators li.active {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background-color: #00bbf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service_section {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service_section .box {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 45px;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service_section .box .img-box {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
-webkit-box-align: start;
|
||||||
|
-ms-flex-align: start;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 125px;
|
||||||
|
min-width: 75px;
|
||||||
|
height: 75px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service_section .box .img-box img {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
-webkit-transition: all 0.3s;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service_section .box .detail-box h5 {
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service_section .box .detail-box a {
|
||||||
|
color: #00204a;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service_section .box .detail-box a:hover {
|
||||||
|
color: #00bbf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service_section .btn-box {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service_section .btn-box a {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 10px 45px;
|
||||||
|
background-color: #00bbf0;
|
||||||
|
color: #ffffff;
|
||||||
|
border-radius: 0;
|
||||||
|
-webkit-transition: all 0.3s;
|
||||||
|
transition: all 0.3s;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service_section .btn-box a:hover {
|
||||||
|
background-color: #007fa4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about_section {
|
||||||
|
background-color: #00204a;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about_section .heading_container {
|
||||||
|
margin-bottom: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about_section .row {
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about_section .img-box img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about_section .detail-box h3 {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about_section .detail-box p {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about_section .detail-box a {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 10px 45px;
|
||||||
|
background-color: #00bbf0;
|
||||||
|
color: #ffffff;
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-transition: all 0.3s;
|
||||||
|
transition: all 0.3s;
|
||||||
|
border: none;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about_section .detail-box a:hover {
|
||||||
|
background-color: #007fa4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.why_section .box {
|
||||||
|
margin-top: 45px;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.why_section .box .img-box {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
width: 120px;
|
||||||
|
height: 120px;
|
||||||
|
min-width: 120px;
|
||||||
|
min-height: 120px;
|
||||||
|
border-radius: 100%;
|
||||||
|
border: 5px solid #00204a;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.why_section .box .img-box img {
|
||||||
|
width: 55px;
|
||||||
|
height: auto;
|
||||||
|
fill: #00204a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.why_section .box h5 {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.why_section .box p {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.why_section .btn-box {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.why_section .btn-box a {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 10px 45px;
|
||||||
|
background-color: #00bbf0;
|
||||||
|
color: #ffffff;
|
||||||
|
border-radius: 0;
|
||||||
|
-webkit-transition: all 0.3s;
|
||||||
|
transition: all 0.3s;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.why_section .btn-box a:hover {
|
||||||
|
background-color: #007fa4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*team section */
|
||||||
|
.team_section {
|
||||||
|
text-align: center;
|
||||||
|
background-color: #00204a;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team_section .heading_container {
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team_section .team_container {
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.team_section .team_container .box {
|
||||||
|
padding: 35px 0 0 0;
|
||||||
|
border-radius: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-transition: all .1s;
|
||||||
|
transition: all .1s;
|
||||||
|
margin-top: 45px;
|
||||||
|
background: linear-gradient(to bottom, #002759, #002b64);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.team_section .team_container .box .img-box {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team_section .team_container .box .img-box img {
|
||||||
|
width: 120px;
|
||||||
|
border-radius: 100%;
|
||||||
|
border: 5px solid #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team_section .team_container .box .detail-box {
|
||||||
|
margin: 25px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team_section .team_container .box .detail-box h5 {
|
||||||
|
color: #00bbf0;
|
||||||
|
font-weight: 600;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team_section .team_container .box .social_box {
|
||||||
|
padding: 10px 45px 20px 45px;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-pack: justify;
|
||||||
|
-ms-flex-pack: justify;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team_section .team_container .box .social_box a {
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team_section .team_container .box .social_box a:hover {
|
||||||
|
color: #00bbf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*team section end*/
|
||||||
|
/* client section start */
|
||||||
|
.client_section .heading_container {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client_section .box {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
margin: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client_section .box .img-box {
|
||||||
|
position: relative;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100px;
|
||||||
|
margin-bottom: -50px;
|
||||||
|
margin-left: 25px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client_section .box .img-box img {
|
||||||
|
border-radius: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client_section .box .client_id {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-pack: justify;
|
||||||
|
-ms-flex-pack: justify;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client_section .box .client_id .client_info h6 {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client_section .box .client_id .client_info p {
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-size: 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client_section .box .detail-box {
|
||||||
|
background-color: #ffffff;
|
||||||
|
-webkit-box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.15);
|
||||||
|
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.15);
|
||||||
|
padding: 75px 25px 25px 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client_section .box .detail-box i {
|
||||||
|
color: #00204a;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client_section .owl-carousel .owl-nav {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client_section .owl-carousel .owl-nav .owl-prev,
|
||||||
|
.client_section .owl-carousel .owl-nav .owl-next {
|
||||||
|
width: 55px;
|
||||||
|
height: 55px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #000000;
|
||||||
|
outline: none;
|
||||||
|
bottom: 0px;
|
||||||
|
font-size: 24px;
|
||||||
|
-webkit-box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.25);
|
||||||
|
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.client_section .owl-carousel .owl-nav .owl-prev:hover,
|
||||||
|
.client_section .owl-carousel .owl-nav .owl-next:hover {
|
||||||
|
color: #00204a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* client section end */
|
||||||
|
.info_section {
|
||||||
|
background-color: #00204a;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 45px 0 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section h4 {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section .info_col {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section .info_contact .contact_link_box {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section .info_contact .contact_link_box a {
|
||||||
|
margin: 5px 0;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section .info_contact .contact_link_box a i {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section .info_contact .contact_link_box a:hover {
|
||||||
|
color: #00bbf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section .info_social {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section .info_social a {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
color: #ffffff;
|
||||||
|
border-radius: 100%;
|
||||||
|
margin-right: 10px;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section .info_social a:hover {
|
||||||
|
color: #00bbf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section .info_links {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
-ms-flex-wrap: wrap;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section .info_links a {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section .info_links a:hover {
|
||||||
|
color: #00bbf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section form input {
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid #ffffff;
|
||||||
|
background-color: transparent;
|
||||||
|
width: 100%;
|
||||||
|
height: 45px;
|
||||||
|
color: #ffffff;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section form input::-webkit-input-placeholder {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section form input:-ms-input-placeholder {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section form input::-ms-input-placeholder {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section form input::placeholder {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section form button {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 10px 55px;
|
||||||
|
background-color: #00bbf0;
|
||||||
|
color: #ffffff;
|
||||||
|
border-radius: 0;
|
||||||
|
-webkit-transition: all 0.3s;
|
||||||
|
transition: all 0.3s;
|
||||||
|
border: none;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_section form button:hover {
|
||||||
|
background-color: #007fa4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* footer section*/
|
||||||
|
.footer_section {
|
||||||
|
position: relative;
|
||||||
|
background-color: #ffffff;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_section p {
|
||||||
|
color: #00204a;
|
||||||
|
padding: 25px 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_section p a {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*# sourceMappingURL=style.css.map */
|
||||||
9
assets/static/css/style.css.map
Normal file
798
assets/static/css/style.scss
Normal file
@@ -0,0 +1,798 @@
|
|||||||
|
$white: #ffffff;
|
||||||
|
$black: #000000;
|
||||||
|
// $primary1: #0cb1a8;
|
||||||
|
$primary1: #00bbf0;
|
||||||
|
$primary2: #00204a;
|
||||||
|
$textCol: #1f1f1f;
|
||||||
|
|
||||||
|
// import fonts - font-family: 'Open Sans', sans-serif;
|
||||||
|
@import url("https://fonts.googleapis.com/css2?family=Lato:wght@400;700&family=Open+Sans:wght@300;400;600;700&display=swap");
|
||||||
|
|
||||||
|
@mixin main-font {
|
||||||
|
font-family: "Open Sans", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin hero_btn($col1, $col2, $pad1, $pad2, $bRadius) {
|
||||||
|
display: inline-block;
|
||||||
|
padding: $pad1 $pad2;
|
||||||
|
background-color: $col1;
|
||||||
|
color: $col2;
|
||||||
|
border-radius: $bRadius;
|
||||||
|
transition: all 0.3s;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: darken($color: $col1, $amount: 15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin upperBold {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
@include main-font;
|
||||||
|
color: #0c0c0c;
|
||||||
|
background-color: #ffffff;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout_padding {
|
||||||
|
padding: 90px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout_padding2 {
|
||||||
|
padding: 75px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout_padding2-top {
|
||||||
|
padding-top: 75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout_padding2-bottom {
|
||||||
|
padding-bottom: 75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout_padding-top {
|
||||||
|
padding-top: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout_padding-bottom {
|
||||||
|
padding-bottom: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading_container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
position: relative;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: $primary1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.heading_center {
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a,
|
||||||
|
a:hover,
|
||||||
|
a:focus {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover,
|
||||||
|
a:focus {
|
||||||
|
color: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn,
|
||||||
|
.btn:focus {
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*header section*/
|
||||||
|
.hero_area {
|
||||||
|
position: relative;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.hero_bg_box {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-end;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: -1;
|
||||||
|
|
||||||
|
.bg_img_box {
|
||||||
|
min-width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
min-width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub_page {
|
||||||
|
.hero_area {
|
||||||
|
min-height: auto;
|
||||||
|
background: linear-gradient(130deg, #231a6f, #0f054c);
|
||||||
|
|
||||||
|
.hero_bg_box {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_section {
|
||||||
|
padding: 15px 0;
|
||||||
|
|
||||||
|
.container-fluid {
|
||||||
|
padding-right: 25px;
|
||||||
|
padding-left: 25px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-brand {
|
||||||
|
span {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 24px;
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.navbar-nav {
|
||||||
|
margin-left: auto;
|
||||||
|
|
||||||
|
.nav-item {
|
||||||
|
.nav-link {
|
||||||
|
padding: 5px 20px;
|
||||||
|
color: $white;
|
||||||
|
text-align: center;
|
||||||
|
text-transform: uppercase;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&.active {
|
||||||
|
.nav-link {
|
||||||
|
color: $primary1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
.nav-link {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .nav_search-btn {
|
||||||
|
width: 35px;
|
||||||
|
height: 35px;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
color: $white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $primary1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-toggler {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom_nav-container .navbar-toggler {
|
||||||
|
padding: 0;
|
||||||
|
width: 37px;
|
||||||
|
height: 42px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
width: 35px;
|
||||||
|
height: 4px;
|
||||||
|
background-color: $white;
|
||||||
|
margin: 7px 0;
|
||||||
|
transition: all 0.3s;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background-color: $white;
|
||||||
|
top: -10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[aria-expanded="true"] {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
|
||||||
|
span {
|
||||||
|
transform: rotate(45deg);
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*end header section*/
|
||||||
|
|
||||||
|
/* slider section */
|
||||||
|
.slider_section {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
padding: 45px 0 145px 0;
|
||||||
|
|
||||||
|
.row {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#customCarousel1 {
|
||||||
|
width: 100%;
|
||||||
|
position: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-box {
|
||||||
|
color: $primary2;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 3rem;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #fefefe;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-box {
|
||||||
|
display: flex;
|
||||||
|
margin: 0 -5px;
|
||||||
|
margin-top: 25px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
margin: 5px;
|
||||||
|
text-align: center;
|
||||||
|
width: 165px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn1 {
|
||||||
|
@include hero_btn($primary1, $white, 10px, 15px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn2 {
|
||||||
|
@include hero_btn($black, $white, 10px, 15px, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-box {
|
||||||
|
margin: 45px 0;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
animation: upDown 5s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes upDown {
|
||||||
|
0% {
|
||||||
|
transform: translateY(-45px);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: translateY(45px);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateY(-45px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-indicators {
|
||||||
|
position: unset;
|
||||||
|
margin: 0;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
li {
|
||||||
|
background-color: $white;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border-radius: 100%;
|
||||||
|
opacity: 1;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background-color: $primary1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// end slider section
|
||||||
|
|
||||||
|
// service section
|
||||||
|
|
||||||
|
.service_section {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.box {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 45px;
|
||||||
|
background-color: #f8f8f9;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
|
.img-box {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 125px;
|
||||||
|
min-width: 75px;
|
||||||
|
height: 75px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-box {
|
||||||
|
h5 {
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $primary2;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $primary1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-box {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 45px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
@include hero_btn($primary1, $white, 10px, 45px, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// end service section
|
||||||
|
|
||||||
|
// about section
|
||||||
|
.about_section {
|
||||||
|
background-color: $primary2;
|
||||||
|
color: $white;
|
||||||
|
|
||||||
|
.heading_container {
|
||||||
|
margin-bottom: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-box {
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-box {
|
||||||
|
h3 {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
@include hero_btn($primary1, $white, 10px, 45px, 0px);
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// end about section
|
||||||
|
|
||||||
|
// why section
|
||||||
|
|
||||||
|
.why_section {
|
||||||
|
|
||||||
|
.box {
|
||||||
|
margin-top: 45px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.img-box {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
width: 120px;
|
||||||
|
height: 120px;
|
||||||
|
min-width: 120px;
|
||||||
|
min-height: 120px;
|
||||||
|
border-radius: 100%;
|
||||||
|
border: 5px solid $primary2;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 55px;
|
||||||
|
height: auto;
|
||||||
|
fill: $primary2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-box {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 45px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
@include hero_btn($primary1, $white, 10px, 45px, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// end why section
|
||||||
|
|
||||||
|
/*team section */
|
||||||
|
|
||||||
|
.team_section {
|
||||||
|
text-align: center;
|
||||||
|
background-color: $primary2;
|
||||||
|
color: $white;
|
||||||
|
|
||||||
|
.heading_container {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team_container {
|
||||||
|
padding: 0 15px;
|
||||||
|
|
||||||
|
.box {
|
||||||
|
padding: 35px 0 0 0;
|
||||||
|
border-radius: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: all .1s;
|
||||||
|
margin-top: 45px;
|
||||||
|
// background-color: #053068;
|
||||||
|
background: linear-gradient(to bottom, lighten($color: $primary2, $amount: 3), lighten($color: $primary2, $amount: 5));
|
||||||
|
|
||||||
|
.img-box {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 120px;
|
||||||
|
border-radius: 100%;
|
||||||
|
border: 5px solid $white;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-box {
|
||||||
|
margin: 25px 0;
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
color: $primary1;
|
||||||
|
font-weight: 600;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.social_box {
|
||||||
|
padding: 10px 45px 20px 45px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $white;
|
||||||
|
font-size: 22px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $primary1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*team section end*/
|
||||||
|
|
||||||
|
/* client section start */
|
||||||
|
|
||||||
|
.client_section {
|
||||||
|
.heading_container {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin: 15px;
|
||||||
|
|
||||||
|
.img-box {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100px;
|
||||||
|
margin-bottom: -50px;
|
||||||
|
margin-left: 25px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-radius: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.client_id {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.client_info {
|
||||||
|
h6 {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-size: 15px;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-box {
|
||||||
|
background-color: $white;
|
||||||
|
box-shadow: 0 0 15px 0 rgba($color: #000000, $alpha: 0.15);
|
||||||
|
padding: 75px 25px 25px 25px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: $primary2;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.owl-carousel {
|
||||||
|
.owl-nav {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 45px;
|
||||||
|
|
||||||
|
.owl-prev,
|
||||||
|
.owl-next {
|
||||||
|
width: 55px;
|
||||||
|
height: 55px;
|
||||||
|
background-color: $white;
|
||||||
|
color: $black;
|
||||||
|
outline: none;
|
||||||
|
bottom: 0px;
|
||||||
|
font-size: 24px;
|
||||||
|
box-shadow: 0 0 5px 0 rgba($color: #000000, $alpha: 0.25);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $primary2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* client section end */
|
||||||
|
|
||||||
|
// info section
|
||||||
|
.info_section {
|
||||||
|
background-color: $primary2;
|
||||||
|
color: $white;
|
||||||
|
padding: 45px 0 15px 0;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_col {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_contact {
|
||||||
|
.contact_link_box {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
a {
|
||||||
|
margin: 5px 0;
|
||||||
|
color: $white;
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $primary1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_social {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
color: $white;
|
||||||
|
border-radius: 100%;
|
||||||
|
margin-right: 10px;
|
||||||
|
font-size: 24px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $primary1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_links {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
color: $white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $primary1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
input {
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid $white;
|
||||||
|
background-color: transparent;
|
||||||
|
width: 100%;
|
||||||
|
height: 45px;
|
||||||
|
color: $white;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
@include hero_btn($primary1, $white, 10px, 55px, 0);
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// end info section
|
||||||
|
|
||||||
|
/* footer section*/
|
||||||
|
|
||||||
|
.footer_section {
|
||||||
|
position: relative;
|
||||||
|
background-color: $white;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: $primary2;
|
||||||
|
padding: 25px 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// end footer section
|
||||||
945
assets/static/css/tailwind.css
Normal file
@@ -0,0 +1,945 @@
|
|||||||
|
/*! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/
|
||||||
|
*, :after, :before {
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 0 solid #e5e7eb
|
||||||
|
}
|
||||||
|
|
||||||
|
:after, :before {
|
||||||
|
--tw-content: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
:host, html {
|
||||||
|
line-height: 1.5;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
-o-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
font-family: ui-sans-serif, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
||||||
|
font-feature-settings: normal;
|
||||||
|
font-variation-settings: normal;
|
||||||
|
-webkit-tap-highlight-color: transparent
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
line-height: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
height: 0;
|
||||||
|
color: inherit;
|
||||||
|
border-top-width: 1px
|
||||||
|
}
|
||||||
|
|
||||||
|
abbr:where([title]) {
|
||||||
|
-webkit-text-decoration: underline dotted;
|
||||||
|
text-decoration: underline dotted
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-size: inherit;
|
||||||
|
font-weight: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
b, strong {
|
||||||
|
font-weight: bolder
|
||||||
|
}
|
||||||
|
|
||||||
|
code, kbd, pre, samp {
|
||||||
|
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
|
||||||
|
font-feature-settings: normal;
|
||||||
|
font-variation-settings: normal;
|
||||||
|
font-size: 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%
|
||||||
|
}
|
||||||
|
|
||||||
|
sub, sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: initial
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -.25em
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -.5em
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
text-indent: 0;
|
||||||
|
border-color: inherit;
|
||||||
|
border-collapse: collapse
|
||||||
|
}
|
||||||
|
|
||||||
|
button, input, optgroup, select, textarea {
|
||||||
|
font-family: inherit;
|
||||||
|
font-feature-settings: inherit;
|
||||||
|
font-variation-settings: inherit;
|
||||||
|
font-size: 100%;
|
||||||
|
font-weight: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
letter-spacing: inherit;
|
||||||
|
color: inherit;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
button, select {
|
||||||
|
text-transform: none
|
||||||
|
}
|
||||||
|
|
||||||
|
button, input:where([type=button]), input:where([type=reset]), input:where([type=submit]) {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
background-color: initial;
|
||||||
|
background-image: none
|
||||||
|
}
|
||||||
|
|
||||||
|
:-moz-focusring {
|
||||||
|
outline: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
:-moz-ui-invalid {
|
||||||
|
box-shadow: none
|
||||||
|
}
|
||||||
|
|
||||||
|
progress {
|
||||||
|
vertical-align: initial
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
|
||||||
|
height: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
[type=search] {
|
||||||
|
-webkit-appearance: textfield;
|
||||||
|
outline-offset: -2px
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
font: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
summary {
|
||||||
|
display: list-item
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote, dd, dl, figure, h1, h2, h3, h4, h5, h6, hr, p, pre {
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset, legend {
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
menu, ol, ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog {
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
resize: vertical
|
||||||
|
}
|
||||||
|
|
||||||
|
input::-moz-placeholder, textarea::-moz-placeholder {
|
||||||
|
opacity: 1;
|
||||||
|
color: #9ca3af
|
||||||
|
}
|
||||||
|
|
||||||
|
input::placeholder, textarea::placeholder {
|
||||||
|
opacity: 1;
|
||||||
|
color: #9ca3af
|
||||||
|
}
|
||||||
|
|
||||||
|
[role=button], button {
|
||||||
|
cursor: pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
:disabled {
|
||||||
|
cursor: default
|
||||||
|
}
|
||||||
|
|
||||||
|
audio, canvas, embed, iframe, img, object, svg, video {
|
||||||
|
display: block;
|
||||||
|
vertical-align: middle
|
||||||
|
}
|
||||||
|
|
||||||
|
img, video {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
*, ::backdrop, :after, :before {
|
||||||
|
--tw-border-spacing-x: 0;
|
||||||
|
--tw-border-spacing-y: 0;
|
||||||
|
--tw-translate-x: 0;
|
||||||
|
--tw-translate-y: 0;
|
||||||
|
--tw-rotate: 0;
|
||||||
|
--tw-skew-x: 0;
|
||||||
|
--tw-skew-y: 0;
|
||||||
|
--tw-scale-x: 1;
|
||||||
|
--tw-scale-y: 1;
|
||||||
|
--tw-pan-x: ;
|
||||||
|
--tw-pan-y: ;
|
||||||
|
--tw-pinch-zoom: ;
|
||||||
|
--tw-scroll-snap-strictness: proximity;
|
||||||
|
--tw-gradient-from-position: ;
|
||||||
|
--tw-gradient-via-position: ;
|
||||||
|
--tw-gradient-to-position: ;
|
||||||
|
--tw-ordinal: ;
|
||||||
|
--tw-slashed-zero: ;
|
||||||
|
--tw-numeric-figure: ;
|
||||||
|
--tw-numeric-spacing: ;
|
||||||
|
--tw-numeric-fraction: ;
|
||||||
|
--tw-ring-inset: ;
|
||||||
|
--tw-ring-offset-width: 0px;
|
||||||
|
--tw-ring-offset-color: #fff;
|
||||||
|
--tw-ring-color: #3b82f680;
|
||||||
|
--tw-ring-offset-shadow: 0 0 #0000;
|
||||||
|
--tw-ring-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow-colored: 0 0 #0000;
|
||||||
|
--tw-blur: ;
|
||||||
|
--tw-brightness: ;
|
||||||
|
--tw-contrast: ;
|
||||||
|
--tw-grayscale: ;
|
||||||
|
--tw-hue-rotate: ;
|
||||||
|
--tw-invert: ;
|
||||||
|
--tw-saturate: ;
|
||||||
|
--tw-sepia: ;
|
||||||
|
--tw-drop-shadow: ;
|
||||||
|
--tw-backdrop-blur: ;
|
||||||
|
--tw-backdrop-brightness: ;
|
||||||
|
--tw-backdrop-contrast: ;
|
||||||
|
--tw-backdrop-grayscale: ;
|
||||||
|
--tw-backdrop-hue-rotate: ;
|
||||||
|
--tw-backdrop-invert: ;
|
||||||
|
--tw-backdrop-opacity: ;
|
||||||
|
--tw-backdrop-saturate: ;
|
||||||
|
--tw-backdrop-sepia: ;
|
||||||
|
--tw-contain-size: ;
|
||||||
|
--tw-contain-layout: ;
|
||||||
|
--tw-contain-paint: ;
|
||||||
|
--tw-contain-style:
|
||||||
|
}
|
||||||
|
|
||||||
|
.\!container {
|
||||||
|
width: 100% !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.\!container {
|
||||||
|
max-width: 640px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 640px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.\!container {
|
||||||
|
max-width: 768px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 768px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.\!container {
|
||||||
|
max-width: 1024px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 1024px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1280px) {
|
||||||
|
.\!container {
|
||||||
|
max-width: 1280px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 1280px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1536px) {
|
||||||
|
.\!container {
|
||||||
|
max-width: 1536px !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 1536px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.visible {
|
||||||
|
visibility: visible
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse {
|
||||||
|
visibility: collapse
|
||||||
|
}
|
||||||
|
|
||||||
|
.static {
|
||||||
|
position: static
|
||||||
|
}
|
||||||
|
|
||||||
|
.\!fixed {
|
||||||
|
position: fixed !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed {
|
||||||
|
position: fixed
|
||||||
|
}
|
||||||
|
|
||||||
|
.absolute {
|
||||||
|
position: absolute
|
||||||
|
}
|
||||||
|
|
||||||
|
.relative {
|
||||||
|
position: relative
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticky {
|
||||||
|
position: sticky
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-0 {
|
||||||
|
left: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-5 {
|
||||||
|
left: 1.25rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-0 {
|
||||||
|
top: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-\[99\] {
|
||||||
|
z-index: 99
|
||||||
|
}
|
||||||
|
|
||||||
|
.float-right {
|
||||||
|
float: right
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-2 {
|
||||||
|
margin: .5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx-4 {
|
||||||
|
margin-left: 1rem;
|
||||||
|
margin-right: 1rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-1 {
|
||||||
|
margin-bottom: .25rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-3 {
|
||||||
|
margin-bottom: .75rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-5 {
|
||||||
|
margin-bottom: 1.25rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-2 {
|
||||||
|
margin-left: .5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-auto {
|
||||||
|
margin-left: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr-2 {
|
||||||
|
margin-right: .5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr-auto {
|
||||||
|
margin-right: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-10 {
|
||||||
|
margin-top: 2.5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-3 {
|
||||||
|
margin-top: .75rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-4 {
|
||||||
|
margin-top: 1rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-5 {
|
||||||
|
margin-top: 1.25rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-10 {
|
||||||
|
margin-bottom: 2.5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-2 {
|
||||||
|
margin-top: .5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-block {
|
||||||
|
display: inline-block
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline {
|
||||||
|
display: inline
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex {
|
||||||
|
display: flex
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-flex {
|
||||||
|
display: inline-flex
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
display: table
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-caption {
|
||||||
|
display: table-caption
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-cell {
|
||||||
|
display: table-cell
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid
|
||||||
|
}
|
||||||
|
|
||||||
|
.contents {
|
||||||
|
display: contents
|
||||||
|
}
|
||||||
|
|
||||||
|
.\!hidden {
|
||||||
|
display: none !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.size-2 {
|
||||||
|
width: .5rem;
|
||||||
|
height: .5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-1 {
|
||||||
|
height: .25rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-14 {
|
||||||
|
height: 3.5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-16 {
|
||||||
|
height: 4rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-3 {
|
||||||
|
height: .75rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-8 {
|
||||||
|
height: 2rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-\[100vh\] {
|
||||||
|
height: 100vh
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-h-\[400px\] {
|
||||||
|
max-height: 400px
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-\[100vw\] {
|
||||||
|
width: 100vw
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-\[90\%\] {
|
||||||
|
width: 90%
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-full {
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-\[500px\] {
|
||||||
|
max-width: 500px
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-\[90vw\] {
|
||||||
|
max-width: 90vw
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-\[20px\] {
|
||||||
|
max-width: 20px
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-\[300px\] {
|
||||||
|
max-width: 300px
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-shrink, .shrink {
|
||||||
|
flex-shrink: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-grow, .grow {
|
||||||
|
flex-grow: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-collapse {
|
||||||
|
border-collapse: collapse
|
||||||
|
}
|
||||||
|
|
||||||
|
.transform {
|
||||||
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))
|
||||||
|
}
|
||||||
|
|
||||||
|
.cursor-pointer {
|
||||||
|
cursor: pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
.resize {
|
||||||
|
resize: both
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-cols-1 {
|
||||||
|
grid-template-columns:repeat(1, minmax(0, 1fr))
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-cols-2 {
|
||||||
|
grid-template-columns:repeat(2, minmax(0, 1fr))
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-col {
|
||||||
|
flex-direction: column
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-wrap {
|
||||||
|
flex-wrap: wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-center {
|
||||||
|
align-items: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-end {
|
||||||
|
justify-content: flex-end
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-center {
|
||||||
|
justify-content: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-10 {
|
||||||
|
gap: 2.5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-8 {
|
||||||
|
gap: 2rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-2 {
|
||||||
|
gap: .5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-5 {
|
||||||
|
gap: 1.25rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-x-3 {
|
||||||
|
-moz-column-gap: .75rem;
|
||||||
|
column-gap: .75rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.truncate {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded {
|
||||||
|
border-radius: .25rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-xl {
|
||||||
|
border-radius: .75rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.border {
|
||||||
|
border-width: 1px
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-black {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(0 0 0/var(--tw-border-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-blue-500 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(59 130 246/var(--tw-bg-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-gray-200 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(229 231 235/var(--tw-bg-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-orange-500 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(249 115 22/var(--tw-bg-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-white {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(255 255 255/var(--tw-bg-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-red-500 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(239 68 68/var(--tw-bg-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-gray-400 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(156 163 175/var(--tw-bg-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-gray-700 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(55 65 81/var(--tw-bg-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-blue-400 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(96 165 250/var(--tw-bg-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-green-400 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(74 222 128/var(--tw-bg-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.\!bg-gray-700 {
|
||||||
|
--tw-bg-opacity: 1 !important;
|
||||||
|
background-color: rgb(55 65 81/var(--tw-bg-opacity)) !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.\!bg-orange-500 {
|
||||||
|
--tw-bg-opacity: 1 !important;
|
||||||
|
background-color: rgb(249 115 22/var(--tw-bg-opacity)) !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.\!bg-red-500 {
|
||||||
|
--tw-bg-opacity: 1 !important;
|
||||||
|
background-color: rgb(239 68 68/var(--tw-bg-opacity)) !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-1 {
|
||||||
|
padding: .25rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-14 {
|
||||||
|
padding: 3.5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-16 {
|
||||||
|
padding: 4rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-2 {
|
||||||
|
padding: .5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-3 {
|
||||||
|
padding: .75rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-4 {
|
||||||
|
padding: 1rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-5 {
|
||||||
|
padding: 1.25rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-8 {
|
||||||
|
padding: 2rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-\[40px\] {
|
||||||
|
padding-left: 40px;
|
||||||
|
padding-right: 40px
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-3 {
|
||||||
|
padding-top: .75rem;
|
||||||
|
padding-bottom: .75rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-2 {
|
||||||
|
padding-top: .5rem;
|
||||||
|
padding-bottom: .5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-3 {
|
||||||
|
padding-left: .75rem;
|
||||||
|
padding-right: .75rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.indent-1 {
|
||||||
|
text-indent: .25rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[20px\] {
|
||||||
|
font-size: 20px
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[25px\] {
|
||||||
|
font-size: 25px
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[30px\] {
|
||||||
|
font-size: 30px
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[40px\] {
|
||||||
|
font-size: 40px
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-sm {
|
||||||
|
font-size: .875rem;
|
||||||
|
line-height: 1.25rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[27px\] {
|
||||||
|
font-size: 27px
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-\[400\] {
|
||||||
|
font-weight: 400
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-\[500\] {
|
||||||
|
font-weight: 500
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-\[600\] {
|
||||||
|
font-weight: 600
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-bold {
|
||||||
|
font-weight: 700
|
||||||
|
}
|
||||||
|
|
||||||
|
.uppercase {
|
||||||
|
text-transform: uppercase
|
||||||
|
}
|
||||||
|
|
||||||
|
.lowercase {
|
||||||
|
text-transform: lowercase
|
||||||
|
}
|
||||||
|
|
||||||
|
.capitalize {
|
||||||
|
text-transform: capitalize
|
||||||
|
}
|
||||||
|
|
||||||
|
.italic {
|
||||||
|
font-style: italic
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-black {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(0 0 0/var(--tw-text-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-blue-500 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(59 130 246/var(--tw-text-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-red-500 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(239 68 68/var(--tw-text-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-white {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(255 255 255/var(--tw-text-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.\!text-white {
|
||||||
|
--tw-text-opacity: 1 !important;
|
||||||
|
color: rgb(255 255 255/var(--tw-text-opacity)) !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[px\] {
|
||||||
|
color: px
|
||||||
|
}
|
||||||
|
|
||||||
|
.underline {
|
||||||
|
text-decoration-line: underline
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-through {
|
||||||
|
text-decoration-line: line-through
|
||||||
|
}
|
||||||
|
|
||||||
|
.antialiased {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow {
|
||||||
|
--tw-shadow: 0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a;
|
||||||
|
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color)
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow, .shadow-md {
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow-md {
|
||||||
|
--tw-shadow: 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;
|
||||||
|
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color)
|
||||||
|
}
|
||||||
|
|
||||||
|
.outline {
|
||||||
|
outline-style: solid
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring {
|
||||||
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||||
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)
|
||||||
|
}
|
||||||
|
|
||||||
|
.blur {
|
||||||
|
--tw-blur: blur(8px)
|
||||||
|
}
|
||||||
|
|
||||||
|
.blur, .grayscale {
|
||||||
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)
|
||||||
|
}
|
||||||
|
|
||||||
|
.grayscale {
|
||||||
|
--tw-grayscale: grayscale(100%)
|
||||||
|
}
|
||||||
|
|
||||||
|
.\!invert {
|
||||||
|
--tw-invert: invert(100%) !important;
|
||||||
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow) !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.invert {
|
||||||
|
--tw-invert: invert(100%);
|
||||||
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)
|
||||||
|
}
|
||||||
|
|
||||||
|
.\!filter {
|
||||||
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow) !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter {
|
||||||
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)
|
||||||
|
}
|
||||||
|
|
||||||
|
.backdrop-blur-sm {
|
||||||
|
--tw-backdrop-blur: blur(4px);
|
||||||
|
-webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
|
||||||
|
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)
|
||||||
|
}
|
||||||
|
|
||||||
|
.transition {
|
||||||
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
|
||||||
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
|
||||||
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
|
||||||
|
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
|
||||||
|
transition-duration: .15s
|
||||||
|
}
|
||||||
|
|
||||||
|
.ease-out {
|
||||||
|
transition-timing-function: cubic-bezier(0, 0, .2, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
.\[a-zA-Z\:\\-\] {
|
||||||
|
a-z-a--z: \-
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.sm\:grid-cols-2 {
|
||||||
|
grid-template-columns:repeat(2, minmax(0, 1fr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.md\:grid-cols-2 {
|
||||||
|
grid-template-columns:repeat(2, minmax(0, 1fr))
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:grid-cols-3 {
|
||||||
|
grid-template-columns:repeat(3, minmax(0, 1fr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.lg\:grid-cols-4 {
|
||||||
|
grid-template-columns:repeat(4, minmax(0, 1fr))
|
||||||
|
}
|
||||||
|
}
|
||||||
13250
assets/static/data/chemistry_table.pdf
Normal file
BIN
assets/static/data/klark.pdf
Normal file
BIN
assets/static/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
assets/static/fonts/fontawesome-webfont.ttf
Normal file
BIN
assets/static/fonts/fontawesome-webfont.woff
Normal file
BIN
assets/static/fonts/fontawesome-webfont.woff2
Normal file
BIN
assets/static/images/django-logo.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
assets/static/images/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
assets/static/images/hero-bg.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
assets/static/images/login.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
assets/static/images/logo.jpg
Normal file
|
After Width: | Height: | Size: 358 KiB |
BIN
assets/static/images/slider-img.png
Normal file
|
After Width: | Height: | Size: 201 KiB |
4442
assets/static/js/bootstrap.js
vendored
Normal file
46
assets/static/js/custom.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// to get current year
|
||||||
|
function getYear() {
|
||||||
|
var currentDate = new Date();
|
||||||
|
var currentYear = currentDate.getFullYear();
|
||||||
|
document.querySelector("#displayYear").innerHTML = currentYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
getYear();
|
||||||
|
|
||||||
|
|
||||||
|
// client section owl carousel
|
||||||
|
$(".client_owl-carousel").owlCarousel({
|
||||||
|
loop: true,
|
||||||
|
margin: 20,
|
||||||
|
dots: false,
|
||||||
|
nav: true,
|
||||||
|
navText: [],
|
||||||
|
autoplay: true,
|
||||||
|
autoplayHoverPause: true,
|
||||||
|
navText: [
|
||||||
|
'<i class="fa fa-angle-left" aria-hidden="true"></i>',
|
||||||
|
'<i class="fa fa-angle-right" aria-hidden="true"></i>'
|
||||||
|
],
|
||||||
|
responsive: {
|
||||||
|
0: {
|
||||||
|
items: 1
|
||||||
|
},
|
||||||
|
600: {
|
||||||
|
items: 2
|
||||||
|
},
|
||||||
|
1000: {
|
||||||
|
items: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** google_map js **/
|
||||||
|
function myMap() {
|
||||||
|
var mapProp = {
|
||||||
|
center: new google.maps.LatLng(40.712775, -74.005973),
|
||||||
|
zoom: 18,
|
||||||
|
};
|
||||||
|
var map = new google.maps.Map(document.getElementById("googleMap"), mapProp);
|
||||||
|
}
|
||||||
2
assets/static/js/jquery-3.4.1.min.js
vendored
Normal file
296
assets/templates/index.html
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="description"
|
||||||
|
content="Django Default is a Django project structure generator that simplifies the process of setting up new Django projects. It automates the cloning of a predefined Django project structure from a GitHub repository, enabling developers to start their projects with a solid foundation.">
|
||||||
|
<meta name="keywords" content="Django Default is a Django project structure generator by @ja_khan_gir">
|
||||||
|
<meta name="author" content="https://pypi.org/project/django-default/">
|
||||||
|
<meta name="robots" content="index, follow">
|
||||||
|
<link rel="shortcut icon" href="{% static 'images/favicon.ico' %}" type="image/x-icon">
|
||||||
|
<link rel="icon" href="{% static 'images/favicon.ico' %}" type="image/x-icon">
|
||||||
|
<link rel="shortcut icon" href="{% static 'images/favicon.ico' %}" type="image/x-icon">
|
||||||
|
|
||||||
|
<!-- Open Graph Meta Tags -->
|
||||||
|
<meta property="og:title" content="A Django project structure generator by @ja_khan_gir">
|
||||||
|
<meta property="og:description"
|
||||||
|
content="Django Default is a Django project structure generator that simplifies the process of setting up new Django projects.">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:url" content="https://pypi.org/project/django-default/">
|
||||||
|
<meta property="og:image" content="https://i.postimg.cc/WzS3fs9f/Pics-Art-24-07-08-01-10-45-321.png">
|
||||||
|
<meta property="og:site_name" content="https://pypi.org/project/django-default/">
|
||||||
|
|
||||||
|
<!-- Twitter Card Meta Tags -->
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<meta name="twitter:title" content="Django Default">
|
||||||
|
<meta name="twitter:description"
|
||||||
|
content="Django Default is a Django project structure generator that simplifies the process of setting up new Django projects.">
|
||||||
|
<meta name="twitter:image" content="https://i.postimg.cc/WzS3fs9f/Pics-Art-24-07-08-01-10-45-321.png">
|
||||||
|
<meta name="twitter:site" content="@ja_khan_gir">
|
||||||
|
<meta name="twitter:creator" content="@ja_khan_gir">
|
||||||
|
|
||||||
|
<!-- Canonical Link -->
|
||||||
|
<link rel="canonical" href="https://pypi.org/project/django-default/">
|
||||||
|
|
||||||
|
<!-- Schema Markup -->
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "SoftwareApplication",
|
||||||
|
"name": "Django Default",
|
||||||
|
"url": "https://pypi.org/project/django-default/",
|
||||||
|
"logo": "https://i.postimg.cc/WzS3fs9f/Pics-Art-24-07-08-01-10-45-321.png",
|
||||||
|
"sameAs": [
|
||||||
|
"https://t.me/ja_khan_gir",
|
||||||
|
"https://www.twitter.com/ja_khan_gir",
|
||||||
|
"https://www.instagram.com/ja_khan_gir",
|
||||||
|
],
|
||||||
|
"contactPoint": {
|
||||||
|
"@type": "ContactPoint",
|
||||||
|
"telephone": "+998-33-007-85-87",
|
||||||
|
"contactType": "customer service"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<title>Django Default</title>
|
||||||
|
|
||||||
|
<!-- bootstrap core css -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.css' %}"/>
|
||||||
|
|
||||||
|
<!-- fonts style -->
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700;900&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
|
<!--owl slider stylesheet -->
|
||||||
|
<link rel="stylesheet" type="text/css"
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/assets/owl.carousel.min.css"/>
|
||||||
|
|
||||||
|
<!-- font awesome style -->
|
||||||
|
<link href="{% static 'css/font-awesome.min.css' %}" rel="stylesheet"/>
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="{% static 'css/style.css' %}" rel="stylesheet"/>
|
||||||
|
<!-- responsive style -->
|
||||||
|
<link href="{% static 'css/responsive.css' %}" rel="stylesheet"/>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="hero_area">
|
||||||
|
|
||||||
|
<div class="hero_bg_box">
|
||||||
|
<div class="bg_img_box">
|
||||||
|
<img src="{% static 'images/hero-bg.png' %}" alt="">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- header section strats -->
|
||||||
|
<header class="header_section">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<nav class="navbar navbar-expand-lg custom_nav-container ">
|
||||||
|
<a class="navbar-brand" href="/">
|
||||||
|
<span>
|
||||||
|
Django Default
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse"
|
||||||
|
data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
|
||||||
|
aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class=""> </span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
|
<ul class="navbar-nav ">
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="admin/"> <i class="fa fa-user"
|
||||||
|
aria-hidden="true"></i>
|
||||||
|
Admin</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="api/schema/swagger-ui/"> <i class="fas fa-cogs"
|
||||||
|
aria-hidden="true"></i>
|
||||||
|
Swagger</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="api/schema/redoc/"> <i class="fas fa-book"
|
||||||
|
aria-hidden="true"></i> Redoc</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="rosetta/"> <i class="fas fa-globe" aria-hidden="true"></i>
|
||||||
|
Rosetta</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<!-- end header section -->
|
||||||
|
<!-- slider section -->
|
||||||
|
<section class="slider_section ">
|
||||||
|
<div id="customCarousel1" class="carousel slide" data-ride="carousel">
|
||||||
|
<div class="carousel-inner">
|
||||||
|
{# <div class="carousel-item active">#}
|
||||||
|
<div class="container ">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 ">
|
||||||
|
<div class="detail-box">
|
||||||
|
<h1>
|
||||||
|
Django Default
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
Hello, guys! This is a Django Template. You can use this template for your
|
||||||
|
</p>
|
||||||
|
<div class="btn-box">
|
||||||
|
<a href="{% url 'admin:index' %}" class="btn1">
|
||||||
|
SignIn
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="img-box">
|
||||||
|
<img src="{% static 'images/slider-img.png' %}" alt="">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- end slider section -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- info section -->
|
||||||
|
|
||||||
|
<section class="info_section layout_padding2">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 col-lg-3 info_col">
|
||||||
|
<div class="info_contact">
|
||||||
|
<h4>
|
||||||
|
Contacts
|
||||||
|
</h4>
|
||||||
|
<div class="contact_link_box">
|
||||||
|
<a href="">
|
||||||
|
<i class="fa fa-map-marker" aria-hidden="true"></i>
|
||||||
|
<span>
|
||||||
|
Archa mahalla, Orqa ko'cha 1-uy
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<a href="">
|
||||||
|
<i class="fa fa-phone" aria-hidden="true"></i>
|
||||||
|
<span>
|
||||||
|
+998 33 007 85 87
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<a href="">
|
||||||
|
<i class="fa fa-envelope" aria-hidden="true"></i>
|
||||||
|
<span>
|
||||||
|
jahongir_kh@tiiame.uz
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info_social">
|
||||||
|
<a href="https://www.facebook.com/ja_khan_gir">
|
||||||
|
<i class="fa fa-facebook" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
<a href="https://twitter.com/ja_khan_gir">
|
||||||
|
<i class="fa fa-twitter" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
<a href="https://www.linkedin.com/in/jahongir-hakimjonov/">
|
||||||
|
<i class="fa fa-linkedin" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
<a href="https://instagram.com/ja_khan_gir">
|
||||||
|
<i class="fa fa-instagram" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/JahongirHakimjonov">
|
||||||
|
<i class="fa fa-github" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
<a href="https://t.me/ja_khan_gir">
|
||||||
|
<i class="fa fa-telegram" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 col-lg-3 info_col">
|
||||||
|
<div class="info_detail">
|
||||||
|
<h4>
|
||||||
|
Info
|
||||||
|
</h4>
|
||||||
|
<p>
|
||||||
|
Hello, guys! This is a Django Template. You can use this template for your
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 col-lg-2 mx-auto info_col">
|
||||||
|
<div class="info_link_box">
|
||||||
|
<h4>
|
||||||
|
Links
|
||||||
|
</h4>
|
||||||
|
<div class="info_links">
|
||||||
|
<a class="active"
|
||||||
|
href="https://www.canva.com/design/DAGDHdnRcII/oMWsmW8fRmSDq_asvn2Kiw/edit?utm_content=DAGDHdnRcII&utm_campaign=designshare&utm_medium=link2&utm_source=sharebutton">
|
||||||
|
Resume
|
||||||
|
</a>
|
||||||
|
<a class="" href="https://github.com/JahongirHakimjonov">
|
||||||
|
GitHub
|
||||||
|
</a>
|
||||||
|
<a class="" href="https://t.me/ja_khan_gir">
|
||||||
|
Telegram
|
||||||
|
</a>
|
||||||
|
<a class="" href="https://www.instagram.com/ja_khan_gir">
|
||||||
|
Instagram
|
||||||
|
</a>
|
||||||
|
<a class="" href="https://jahongirhakimjonov.github.io/portfolio/">
|
||||||
|
PORTFOLIO
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- end info section -->
|
||||||
|
|
||||||
|
<!-- footer section -->
|
||||||
|
<section class="footer_section">
|
||||||
|
<div class="container">
|
||||||
|
<p>
|
||||||
|
© <span id="displayYear"></span> All Rights Reserved By
|
||||||
|
<a href="https://pypi.org/project/django-default/">Django Default</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- footer section -->
|
||||||
|
|
||||||
|
<!-- jQery -->
|
||||||
|
<script type="text/javascript" src="{% static 'js/jquery-3.4.1.min.js' %}"></script>
|
||||||
|
<!-- popper js -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
|
||||||
|
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous">
|
||||||
|
</script>
|
||||||
|
<!-- bootstrap js -->
|
||||||
|
<script type="text/javascript" src="{% static 'js/bootstrap.js' %}"></script>
|
||||||
|
<!-- owl slider -->
|
||||||
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/owl.carousel.min.js">
|
||||||
|
</script>
|
||||||
|
<!-- custom js -->
|
||||||
|
<script type="text/javascript" src="{% static 'js/custom.js' %}"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
{% endblock %}
|
||||||
BIN
celerybeat-schedule
Normal file
3
core/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from .celery import app
|
||||||
|
|
||||||
|
__all__ = ["app"]
|
||||||
16
core/asgi.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
ASGI config for core project.
|
||||||
|
|
||||||
|
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings")
|
||||||
|
|
||||||
|
application = get_asgi_application()
|
||||||
14
core/celery.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from celery import Celery
|
||||||
|
|
||||||
|
# from celery.schedules import crontab
|
||||||
|
|
||||||
|
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings")
|
||||||
|
|
||||||
|
app = Celery("core")
|
||||||
|
|
||||||
|
app.config_from_object("django.conf:settings", namespace="CELERY")
|
||||||
|
|
||||||
|
app.autodiscover_tasks()
|
||||||
9
core/config/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from .apps import * # noqa
|
||||||
|
|
||||||
|
# from .cache import * # noqa
|
||||||
|
# from .ckeditor5 import * # noqa
|
||||||
|
# from .jazzmin import * # noqa
|
||||||
|
from .jwt import * # noqa
|
||||||
|
from .rest_framework import * # noqa
|
||||||
|
from .unfold import * # noqa
|
||||||
|
from .unfold_navigation import * # noqa
|
||||||
30
core/config/apps.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
THIRD_PARTY_APPS = [
|
||||||
|
# "jazzmin",
|
||||||
|
"unfold",
|
||||||
|
"unfold.contrib.filters",
|
||||||
|
"unfold.contrib.forms",
|
||||||
|
"unfold.contrib.import_export",
|
||||||
|
"unfold.contrib.guardian",
|
||||||
|
"unfold.contrib.simple_history",
|
||||||
|
"modeltranslation",
|
||||||
|
"django_ckeditor_5",
|
||||||
|
"corsheaders",
|
||||||
|
"rosetta",
|
||||||
|
"rest_framework",
|
||||||
|
"drf_spectacular",
|
||||||
|
"drf_spectacular_sidecar",
|
||||||
|
]
|
||||||
|
|
||||||
|
DEFAULT_APPS = [
|
||||||
|
"django.contrib.admin",
|
||||||
|
"django.contrib.auth",
|
||||||
|
"django.contrib.contenttypes",
|
||||||
|
"django.contrib.sessions",
|
||||||
|
"django.contrib.messages",
|
||||||
|
"django.contrib.staticfiles",
|
||||||
|
]
|
||||||
|
|
||||||
|
PROJECT_APPS = [
|
||||||
|
"apps.shared.apps.SharedConfig",
|
||||||
|
"apps.geology.apps.GeologyConfig",
|
||||||
|
]
|
||||||
17
core/config/cache.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
CACHES = {
|
||||||
|
"default": {
|
||||||
|
"BACKEND": "django_redis.cache.RedisCache",
|
||||||
|
"LOCATION": os.getenv("REDIS_CACHE_URL"),
|
||||||
|
"OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
|
||||||
|
"KEY_PREFIX": "core",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CACHE_MIDDLEWARE_SECONDS = os.getenv("CACHE_TIMEOUT")
|
||||||
|
|
||||||
|
# In your Django settings.py or a dedicated Celery configuration module
|
||||||
|
|
||||||
|
CELERY_BROKER_URL = os.getenv("CELERY_BROKER", "redis://redis:6379/0")
|
||||||
|
CELERY_RESULT_BACKEND = os.getenv("RABBITMQ_RESULT_BACKEND")
|
||||||
140
core/config/ckeditor5.py
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
customColorPalette = [
|
||||||
|
{"color": "hsl(4, 90%, 58%)", "label": "Red"},
|
||||||
|
{"color": "hsl(340, 82%, 52%)", "label": "Pink"},
|
||||||
|
{"color": "hsl(291, 64%, 42%)", "label": "Purple"},
|
||||||
|
{"color": "hsl(262, 52%, 47%)", "label": "Deep Purple"},
|
||||||
|
{"color": "hsl(231, 48%, 48%)", "label": "Indigo"},
|
||||||
|
{"color": "hsl(207, 90%, 54%)", "label": "Blue"},
|
||||||
|
]
|
||||||
|
|
||||||
|
CKEDITOR_5_CONFIGS = {
|
||||||
|
"default": {
|
||||||
|
"toolbar": [
|
||||||
|
"heading",
|
||||||
|
"|",
|
||||||
|
"bold",
|
||||||
|
"italic",
|
||||||
|
"link",
|
||||||
|
"bulletedList",
|
||||||
|
"numberedList",
|
||||||
|
"blockQuote",
|
||||||
|
"imageUpload",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"extends": {
|
||||||
|
"blockToolbar": [
|
||||||
|
"paragraph",
|
||||||
|
"heading1",
|
||||||
|
"heading2",
|
||||||
|
"heading3",
|
||||||
|
"|",
|
||||||
|
"bulletedList",
|
||||||
|
"numberedList",
|
||||||
|
"|",
|
||||||
|
"blockQuote",
|
||||||
|
],
|
||||||
|
"toolbar": [
|
||||||
|
"heading",
|
||||||
|
"|",
|
||||||
|
"outdent",
|
||||||
|
"indent",
|
||||||
|
"|",
|
||||||
|
"bold",
|
||||||
|
"italic",
|
||||||
|
"link",
|
||||||
|
"underline",
|
||||||
|
"strikethrough",
|
||||||
|
"code",
|
||||||
|
"subscript",
|
||||||
|
"superscript",
|
||||||
|
"highlight",
|
||||||
|
"|",
|
||||||
|
"codeBlock",
|
||||||
|
"sourceEditing",
|
||||||
|
"insertImage",
|
||||||
|
"bulletedList",
|
||||||
|
"numberedList",
|
||||||
|
"todoList",
|
||||||
|
"|",
|
||||||
|
"blockQuote",
|
||||||
|
"imageUpload",
|
||||||
|
"|",
|
||||||
|
"fontSize",
|
||||||
|
"fontFamily",
|
||||||
|
"fontColor",
|
||||||
|
"fontBackgroundColor",
|
||||||
|
"mediaEmbed",
|
||||||
|
"removeFormat",
|
||||||
|
"insertTable",
|
||||||
|
],
|
||||||
|
"image": {
|
||||||
|
"toolbar": [
|
||||||
|
"imageTextAlternative",
|
||||||
|
"|",
|
||||||
|
"imageStyle:alignLeft",
|
||||||
|
"imageStyle:alignRight",
|
||||||
|
"imageStyle:alignCenter",
|
||||||
|
"imageStyle:side",
|
||||||
|
"|",
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
"full",
|
||||||
|
"side",
|
||||||
|
"alignLeft",
|
||||||
|
"alignRight",
|
||||||
|
"alignCenter",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"table": {
|
||||||
|
"contentToolbar": [
|
||||||
|
"tableColumn",
|
||||||
|
"tableRow",
|
||||||
|
"mergeTableCells",
|
||||||
|
"tableProperties",
|
||||||
|
"tableCellProperties",
|
||||||
|
],
|
||||||
|
"tableProperties": {
|
||||||
|
"borderColors": customColorPalette,
|
||||||
|
"backgroundColors": customColorPalette,
|
||||||
|
},
|
||||||
|
"tableCellProperties": {
|
||||||
|
"borderColors": customColorPalette,
|
||||||
|
"backgroundColors": customColorPalette,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"heading": {
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"model": "paragraph",
|
||||||
|
"title": "Paragraph",
|
||||||
|
"class": "ck-heading_paragraph",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "heading1",
|
||||||
|
"view": "h1",
|
||||||
|
"title": "Heading 1",
|
||||||
|
"class": "ck-heading_heading1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "heading2",
|
||||||
|
"view": "h2",
|
||||||
|
"title": "Heading 2",
|
||||||
|
"class": "ck-heading_heading2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "heading3",
|
||||||
|
"view": "h3",
|
||||||
|
"title": "Heading 3",
|
||||||
|
"class": "ck-heading_heading3",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"list": {
|
||||||
|
"properties": {
|
||||||
|
"styles": "true",
|
||||||
|
"startIndex": "true",
|
||||||
|
"reversed": "true",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
69
core/config/jazzmin.py
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
JAZZMIN_SETTINGS = {
|
||||||
|
"site_title": "Django Admin",
|
||||||
|
"site_header": "Django Admin",
|
||||||
|
"site_brand": "Django Admin",
|
||||||
|
"welcome_sign": "Django Admin",
|
||||||
|
"site_title_short": "Django Admin",
|
||||||
|
"login_logo": "image/logo.png",
|
||||||
|
"site_icon": "image/logo.png",
|
||||||
|
"site_logo": "image/logo.png",
|
||||||
|
"login_logo_dark": "image/logo.png",
|
||||||
|
"user_avatar": None,
|
||||||
|
"show_sidebar": True,
|
||||||
|
"navigation_expanded": True,
|
||||||
|
"icons": {
|
||||||
|
"auth": "fas fa-users-cog",
|
||||||
|
"auth.user": "fas fa-user",
|
||||||
|
"auth.Group": "fas fa-users",
|
||||||
|
},
|
||||||
|
"topmenu_links": [
|
||||||
|
{"name": "Home", "url": "/", "new_window": False},
|
||||||
|
],
|
||||||
|
"copyright": "University Admin",
|
||||||
|
"default_icon_parents": "fas fa-chevron-circle-right",
|
||||||
|
"default_icon_children": "fas fa-circle",
|
||||||
|
"related_modal_active": False,
|
||||||
|
"custom_js": None,
|
||||||
|
"custom_css": "css/jazzmin.css",
|
||||||
|
"use_google_fonts_cdn": True,
|
||||||
|
"changeform_format": "horizontal_tabs",
|
||||||
|
"changeform_format_overrides": {
|
||||||
|
"auth.user": "collapsible",
|
||||||
|
"auth.group": "vertical_tabs",
|
||||||
|
},
|
||||||
|
"site_logo_classes": "img-circle",
|
||||||
|
"language_chooser": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
JAZZMIN_UI_TWEAKS = {
|
||||||
|
"navbar_small_text": False,
|
||||||
|
"footer_small_text": False,
|
||||||
|
"body_small_text": True,
|
||||||
|
"brand_small_text": False,
|
||||||
|
"brand_colour": "navbar-navy",
|
||||||
|
"accent": "accent-primary",
|
||||||
|
"navbar": "navbar-navy navbar-dark",
|
||||||
|
"no_navbar_border": False,
|
||||||
|
"navbar_fixed": False,
|
||||||
|
"layout_boxed": False,
|
||||||
|
"footer_fixed": False,
|
||||||
|
"sidebar_fixed": True,
|
||||||
|
"sidebar": "sidebar-dark-navy",
|
||||||
|
"sidebar_nav_small_text": False,
|
||||||
|
"sidebar_disable_expand": False,
|
||||||
|
"sidebar_nav_child_indent": False,
|
||||||
|
"sidebar_nav_compact_style": True,
|
||||||
|
"sidebar_nav_legacy_style": False,
|
||||||
|
"sidebar_nav_flat_style": False,
|
||||||
|
"theme": "minty",
|
||||||
|
"dark_mode_theme": None,
|
||||||
|
"button_classes": {
|
||||||
|
"primary": "btn-outline-primary",
|
||||||
|
"secondary": "btn-outline-secondary",
|
||||||
|
"info": "btn-outline-info",
|
||||||
|
"warning": "btn-warning",
|
||||||
|
"danger": "btn-danger",
|
||||||
|
"success": "btn-success",
|
||||||
|
},
|
||||||
|
"actions_sticky_top": False,
|
||||||
|
}
|
||||||
36
core/config/jwt.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import os
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
SIMPLE_JWT = {
|
||||||
|
"ACCESS_TOKEN_LIFETIME": timedelta(days=1),
|
||||||
|
"REFRESH_TOKEN_LIFETIME": timedelta(days=7),
|
||||||
|
"ROTATE_REFRESH_TOKENS": False,
|
||||||
|
"BLACKLIST_AFTER_ROTATION": False,
|
||||||
|
"UPDATE_LAST_LOGIN": False,
|
||||||
|
"ALGORITHM": "HS256",
|
||||||
|
"SIGNING_KEY": os.getenv("SECRET_KEY"),
|
||||||
|
"VERIFYING_KEY": "",
|
||||||
|
"AUDIENCE": None,
|
||||||
|
"ISSUER": None,
|
||||||
|
"JSON_ENCODER": None,
|
||||||
|
"JWK_URL": None,
|
||||||
|
"LEEWAY": 0,
|
||||||
|
"AUTH_HEADER_TYPES": ("Bearer",),
|
||||||
|
"AUTH_HEADER_NAME": "HTTP_AUTHORIZATION",
|
||||||
|
"USER_ID_FIELD": "id",
|
||||||
|
"USER_ID_CLAIM": "user_id",
|
||||||
|
"USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",
|
||||||
|
"AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
|
||||||
|
"TOKEN_TYPE_CLAIM": "token_type",
|
||||||
|
"TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",
|
||||||
|
"JTI_CLAIM": "jti",
|
||||||
|
"SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
|
||||||
|
"SLIDING_TOKEN_LIFETIME": timedelta(minutes=60),
|
||||||
|
"SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
|
||||||
|
"TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainPairSerializer",
|
||||||
|
"TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer",
|
||||||
|
"TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer",
|
||||||
|
"TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer",
|
||||||
|
"SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer",
|
||||||
|
"SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer",
|
||||||
|
}
|
||||||
20
core/config/rest_framework.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
REST_FRAMEWORK = {
|
||||||
|
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
|
||||||
|
"DEFAULT_AUTHENTICATION_CLASSES": (
|
||||||
|
"rest_framework_simplejwt.authentication.JWTAuthentication",
|
||||||
|
),
|
||||||
|
"DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
|
||||||
|
"DEFAULT_THROTTLE_RATE": {
|
||||||
|
"anon": "1000/day",
|
||||||
|
"user": "1000/day",
|
||||||
|
"user_create": "1000/day",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
SPECTACULAR_SETTINGS = {
|
||||||
|
"SWAGGER_UI_DIST": "SIDECAR",
|
||||||
|
"SWAGGER_UI_FAVICON_HREF": "SIDECAR",
|
||||||
|
"REDOC_DIST": "SIDECAR",
|
||||||
|
"TITLE": "Django Rest API",
|
||||||
|
"DESCRIPTION": "Django Rest API",
|
||||||
|
}
|
||||||
29
core/config/swagger.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.urls import path
|
||||||
|
from drf_spectacular.views import (
|
||||||
|
SpectacularAPIView,
|
||||||
|
SpectacularRedocView,
|
||||||
|
SpectacularSwaggerView,
|
||||||
|
)
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path(
|
||||||
|
"schema/",
|
||||||
|
login_required(SpectacularAPIView.as_view(), login_url="/admin/"),
|
||||||
|
name="schema",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"api/schema/swagger-ui/",
|
||||||
|
login_required(
|
||||||
|
SpectacularSwaggerView.as_view(url_name="schema"), login_url="/admin/"
|
||||||
|
),
|
||||||
|
name="swagger-ui",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"api/schema/redoc/",
|
||||||
|
login_required(
|
||||||
|
SpectacularRedocView.as_view(url_name="schema"), login_url="/admin/"
|
||||||
|
),
|
||||||
|
name="redoc",
|
||||||
|
),
|
||||||
|
]
|
||||||
107
core/config/unfold.py
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
from django.templatetags.static import static
|
||||||
|
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.urls import reverse_lazy
|
||||||
|
from . import unfold_navigation as navigation
|
||||||
|
|
||||||
|
UNFOLD = {
|
||||||
|
"SITE_TITLE": "Django Default",
|
||||||
|
"SITE_HEADER": "Django Default",
|
||||||
|
"SITE_URL": "/",
|
||||||
|
"SITE_ICON": {
|
||||||
|
"light": lambda request: static("images/django-logo.png"),
|
||||||
|
"dark": lambda request: static("images/django-logo.png"),
|
||||||
|
},
|
||||||
|
"SITE_FAVICONS": [
|
||||||
|
{
|
||||||
|
"rel": "icon",
|
||||||
|
"sizes": "32x32",
|
||||||
|
"type": "image/svg+xml",
|
||||||
|
"href": lambda request: static("images/django-logo.png"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"SITE_SYMBOL": "speed",
|
||||||
|
"SHOW_HISTORY": True,
|
||||||
|
"SHOW_VIEW_ON_SITE": True,
|
||||||
|
"LOGIN": {
|
||||||
|
"image": lambda request: static("images/login.jpg"),
|
||||||
|
},
|
||||||
|
"STYLES": [
|
||||||
|
lambda request: static("css/tailwind.css"),
|
||||||
|
],
|
||||||
|
"COLORS": {
|
||||||
|
"font": {
|
||||||
|
"subtle-light": "107 114 128",
|
||||||
|
"subtle-dark": "156 163 175",
|
||||||
|
"default-light": "75 85 99",
|
||||||
|
"default-dark": "209 213 219",
|
||||||
|
"important-light": "17 24 39",
|
||||||
|
"important-dark": "243 244 246",
|
||||||
|
},
|
||||||
|
"primary": {
|
||||||
|
"50": "65 144 176",
|
||||||
|
"100": "65 144 176",
|
||||||
|
"200": "65 144 176",
|
||||||
|
"300": "65 144 176",
|
||||||
|
"400": "65 144 176",
|
||||||
|
"500": "65 144 176",
|
||||||
|
"600": "65 144 176",
|
||||||
|
"700": "65 144 176",
|
||||||
|
"800": "65 144 176",
|
||||||
|
"900": "65 144 176",
|
||||||
|
"950": "65 144 176",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"EXTENSIONS": {
|
||||||
|
"modeltranslation": {
|
||||||
|
"flags": {
|
||||||
|
"uz": "🇺🇿",
|
||||||
|
"ru": "🇷🇺",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"SIDEBAR": {
|
||||||
|
"show_search": True,
|
||||||
|
"show_all_applications": True,
|
||||||
|
"navigation": navigation.PAGES,
|
||||||
|
},
|
||||||
|
"TABS": [
|
||||||
|
{
|
||||||
|
"models": [
|
||||||
|
"geology.geology",
|
||||||
|
"geology.photo",
|
||||||
|
"geology.category",
|
||||||
|
],
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"title": _("Madanlar"),
|
||||||
|
"link": reverse_lazy("admin:geology_geology_changelist"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": _("Fotolar"),
|
||||||
|
"link": reverse_lazy("admin:geology_photo_changelist"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": _("Kategoriyalar"),
|
||||||
|
"link": reverse_lazy("admin:geology_category_changelist"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"models": [
|
||||||
|
"geology.gallerycategory",
|
||||||
|
"geology.gallery",
|
||||||
|
],
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"title": _("Galereya kategoriyalari"),
|
||||||
|
"link": reverse_lazy("admin:geology_gallerycategory_changelist"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": _("Galereya"),
|
||||||
|
"link": reverse_lazy("admin:geology_gallery_changelist"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||