Filter
This commit is contained in:
parent
41e390ac45
commit
ed8b3068fc
38793
logs/app.log
38793
logs/app.log
File diff suppressed because it is too large
Load Diff
47797
logs/app.log.1
47797
logs/app.log.1
File diff suppressed because it is too large
Load Diff
60036
logs/app.log.2
60036
logs/app.log.2
File diff suppressed because it is too large
Load Diff
|
@ -1,16 +1,20 @@
|
||||||
from fastapi import FastAPI, APIRouter, Depends, Request, HTTPException, Form
|
from fastapi import FastAPI, APIRouter, Depends, Request, HTTPException, Form
|
||||||
|
from fastapi import Request, Query
|
||||||
|
from typing import List, Optional
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
from fastapi.responses import RedirectResponse, HTMLResponse
|
from fastapi.responses import RedirectResponse, HTMLResponse
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
import jwt
|
import jwt
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from sqlalchemy.future import select
|
from sqlalchemy.future import select
|
||||||
from sqlalchemy.orm import joinedload
|
from sqlalchemy.orm import joinedload, selectinload
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
from sqlalchemy import and_, between
|
||||||
|
from sqlalchemy.sql import func
|
||||||
from sqlalchemy import or_, and_, select
|
from sqlalchemy import or_, and_, select
|
||||||
|
|
||||||
from sqlalchemy import null
|
from sqlalchemy import null
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from routers.auth import get_current_user
|
from routers.auth import get_current_user
|
||||||
from model.database import get_async_session, Job, Client, AppliedJob, User
|
from model.database import get_async_session, Job, Client, AppliedJob, User
|
||||||
|
@ -35,7 +39,7 @@ async def product(request: Request,
|
||||||
)
|
)
|
||||||
|
|
||||||
applied_jobs = result.scalars().all()
|
applied_jobs = result.scalars().all()
|
||||||
|
selected_client_ids = list({job.client.id for job in applied_jobs if job.client})
|
||||||
|
|
||||||
result1 = await session.execute(select(User))
|
result1 = await session.execute(select(User))
|
||||||
users = result1.scalars().all()
|
users = result1.scalars().all()
|
||||||
|
@ -47,6 +51,7 @@ async def product(request: Request,
|
||||||
|
|
||||||
return templates.TemplateResponse("product.html", {"request": request, "size": size,
|
return templates.TemplateResponse("product.html", {"request": request, "size": size,
|
||||||
"jobs": applied_jobs, "role": username["role"],
|
"jobs": applied_jobs, "role": username["role"],
|
||||||
|
"selected_client_ids": selected_client_ids,
|
||||||
"username": username['username'], "users": users,
|
"username": username['username'], "users": users,
|
||||||
"current_path": request.url.path })#
|
"current_path": request.url.path })#
|
||||||
|
|
||||||
|
@ -185,6 +190,177 @@ async def productoj(request: Request,
|
||||||
"username": username['username'], "users": users,
|
"username": username['username'], "users": users,
|
||||||
"current_path": request.url.path })#
|
"current_path": request.url.path })#
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/productf")
|
||||||
|
async def product_filtered(
|
||||||
|
request: Request,
|
||||||
|
|
||||||
|
username: str = Depends(get_current_user),
|
||||||
|
session: AsyncSession = Depends(get_async_session)
|
||||||
|
):
|
||||||
|
# Преобразуем строки в списки
|
||||||
|
|
||||||
|
size = "Work"
|
||||||
|
username = username
|
||||||
|
|
||||||
|
form_data = await request.form()
|
||||||
|
# Преобразуем FormData в словарь, где ключи - имена полей, значения - списки значений
|
||||||
|
form_dict = {}
|
||||||
|
for key, value in form_data.multi_items():
|
||||||
|
if key not in form_dict:
|
||||||
|
form_dict[key] = []
|
||||||
|
form_dict[key].append(value)
|
||||||
|
|
||||||
|
# Получаем значения для каждого поля
|
||||||
|
date_requested = form_dict.get('date_requested', [''])[0]
|
||||||
|
date_requested_from = form_dict.get('date_requested_from', [''])[0]
|
||||||
|
date_requested_to = form_dict.get('date_requested_to', [''])[0]
|
||||||
|
|
||||||
|
date_posted = form_dict.get('date_posted', [''])[0] # Обратите внимание на возможную опечатку в ключе ('date_posted' vs 'date_posted')
|
||||||
|
date_posted_from = form_dict.get('date_posted_from', [''])[0]
|
||||||
|
date_posted_to = form_dict.get('date_posted_to', [''])[0]
|
||||||
|
|
||||||
|
date_applied = form_dict.get('date_applied', [''])[0]
|
||||||
|
date_applied_from = form_dict.get('date_applied_from', [''])[0]
|
||||||
|
date_applied_to = form_dict.get('date_applied_to', [''])[0]
|
||||||
|
|
||||||
|
client = form_dict.get('client', [''])
|
||||||
|
assignees = form_dict.get('assignee', []) # Это будет список всех выбранных assignees
|
||||||
|
status = form_dict.get('status', [''])
|
||||||
|
|
||||||
|
# Теперь у вас есть все значения в отдельных переменных
|
||||||
|
print(f"Date requested: {date_requested}, from: {date_requested_from}, to: {date_requested_to}")
|
||||||
|
print(f"Date posted: {date_posted}, from: {date_posted_from}, to: {date_posted_to}")
|
||||||
|
print(f"Date applied: {date_applied}, from: {date_applied_from}, to: {date_applied_to}")
|
||||||
|
print(f"Client: {client}")
|
||||||
|
print(f"Assignees: {assignees}")
|
||||||
|
print(f"Status: {status}")
|
||||||
|
# Строим базовый запрос с join таблиц
|
||||||
|
# Строим базовый запрос
|
||||||
|
|
||||||
|
|
||||||
|
# Получаем все выбранные значения
|
||||||
|
filters = {
|
||||||
|
'date_requested': form_dict.get('date_requested', [''])[0],
|
||||||
|
'date_requested_from': form_dict.get('date_requested_from', [''])[0],
|
||||||
|
'date_requested_to': form_dict.get('date_requested_to', [''])[0],
|
||||||
|
'date_posted': form_dict.get('date_posted', [''])[0],
|
||||||
|
'date_posted_from': form_dict.get('date_posted_from', [''])[0],
|
||||||
|
'date_posted_to': form_dict.get('date_posted_to', [''])[0],
|
||||||
|
'date_applied': form_dict.get('date_applied', [''])[0],
|
||||||
|
'date_applied_from': form_dict.get('date_applied_from', [''])[0],
|
||||||
|
'date_applied_to': form_dict.get('date_applied_to', [''])[0],
|
||||||
|
'client': form_dict.get('client', []), # Список всех выбранных клиентов
|
||||||
|
'assignees': form_dict.get('assignee', []), # Список всех выбранных assignees
|
||||||
|
'status': form_dict.get('status', []), # Список всех выбранных статусов
|
||||||
|
}
|
||||||
|
# Строим базовый запрос с загрузкой связанных данных
|
||||||
|
stmt = select(AppliedJob).options(
|
||||||
|
selectinload(AppliedJob.job),
|
||||||
|
selectinload(AppliedJob.client),
|
||||||
|
selectinload(AppliedJob.users)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Добавляем условия фильтрации
|
||||||
|
conditions = []
|
||||||
|
|
||||||
|
# Фильтр по дате requested
|
||||||
|
if date_requested == 'custom_date_requested' and date_requested_from and date_requested_to:
|
||||||
|
start = datetime.strptime(date_requested_from, '%Y-%m-%d')
|
||||||
|
end = datetime.strptime(date_requested_to, '%Y-%m-%d')
|
||||||
|
conditions.append(Job.data_requested.between(start, end))
|
||||||
|
elif date_requested == 'Today':
|
||||||
|
conditions.append(func.date(Job.data_requested) == func.current_date())
|
||||||
|
elif date_requested == 'Yesterday':
|
||||||
|
conditions.append(func.date(Job.data_requested) == func.date_sub(func.current_date(), 1))
|
||||||
|
elif date_requested == 'Last 7 days':
|
||||||
|
conditions.append(Job.data_requested >= func.date_sub(func.current_date(), 7))
|
||||||
|
|
||||||
|
# Фильтр по дате posted
|
||||||
|
if date_posted == 'custom_date_posted' and date_posted_from and date_posted_to:
|
||||||
|
start = datetime.strptime(date_posted_from, '%Y-%m-%d')
|
||||||
|
end = datetime.strptime(date_posted_to, '%Y-%m-%d')
|
||||||
|
conditions.append(Job.date_posted.between(start, end))
|
||||||
|
elif date_posted == 'Today':
|
||||||
|
conditions.append(func.date(Job.date_posted) == func.current_date())
|
||||||
|
elif date_posted == 'Yesterday':
|
||||||
|
conditions.append(func.date(Job.date_posted) == func.date_sub(func.current_date(), 1))
|
||||||
|
elif date_posted == 'Last 7 days':
|
||||||
|
conditions.append(Job.date_posted >= func.date_sub(func.current_date(), 7))
|
||||||
|
|
||||||
|
# Фильтр по дате applied
|
||||||
|
if date_applied == 'custom_date_applied' and date_applied_from and date_applied_to:
|
||||||
|
start = datetime.strptime(date_applied_from, '%Y-%m-%d')
|
||||||
|
end = datetime.strptime(date_applied_to, '%Y-%m-%d')
|
||||||
|
conditions.append(AppliedJob.applied_on.between(start, end))
|
||||||
|
elif date_applied == 'Today':
|
||||||
|
conditions.append(func.date(AppliedJob.applied_on) == func.current_date())
|
||||||
|
elif date_applied == 'Yesterday':
|
||||||
|
conditions.append(func.date(AppliedJob.applied_on) == func.date_sub(func.current_date(), 1))
|
||||||
|
elif date_applied == 'Last 7 days':
|
||||||
|
conditions.append(AppliedJob.applied_on >= func.date_sub(func.current_date(), 7))
|
||||||
|
|
||||||
|
# Фильтр по клиенту
|
||||||
|
if client and client[0]:
|
||||||
|
conditions.append(AppliedJob.client_id.in_([int(c) for c in client]))
|
||||||
|
|
||||||
|
# Фильтр по assignees
|
||||||
|
if assignees:
|
||||||
|
conditions.append(AppliedJob.assignee.in_([int(a) for a in assignees]))
|
||||||
|
|
||||||
|
# Фильтр по статусу
|
||||||
|
if status and status[0]:
|
||||||
|
conditions.append(AppliedJob.status.in_(status))
|
||||||
|
|
||||||
|
# Применяем все условия
|
||||||
|
if conditions:
|
||||||
|
stmt = stmt.join(Job).where(and_(*conditions))
|
||||||
|
|
||||||
|
# Выполняем запрос
|
||||||
|
try:
|
||||||
|
result = await session.execute(stmt)
|
||||||
|
applied_jobs = result.scalars().all()
|
||||||
|
|
||||||
|
# # Форматируем результат
|
||||||
|
# response_data = []
|
||||||
|
# for job in applied_jobs:
|
||||||
|
# response_data.append({
|
||||||
|
# "id": job.id,
|
||||||
|
# "client_id": job.client_id,
|
||||||
|
# "job_id": job.job_id,
|
||||||
|
# "applied_on": job.applied_on.isoformat() if job.applied_on else None,
|
||||||
|
# "status": job.status,
|
||||||
|
# "assignee": job.assignee,
|
||||||
|
# "priority": job.priority,
|
||||||
|
# "job": {
|
||||||
|
# "job_title": job.job.job_title,
|
||||||
|
# "company": job.job.job_company,
|
||||||
|
# "date_posted": job.job.date_posted.isoformat() if job.job.date_posted else None
|
||||||
|
# } if job.job else None
|
||||||
|
# })
|
||||||
|
|
||||||
|
# print(f'{"status": "success", "data": response_data}')
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
await session.rollback()
|
||||||
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return templates.TemplateResponse(
|
||||||
|
"productf.html",
|
||||||
|
{
|
||||||
|
"request": request, "size": size,
|
||||||
|
"jobs": applied_jobs, "role": username["role"],
|
||||||
|
"username": username['username'],# "users": users,
|
||||||
|
"role": username["role"],
|
||||||
|
|
||||||
|
"current_path": request.url.path
|
||||||
|
}
|
||||||
|
)
|
||||||
# Pydantic модель запроса
|
# Pydantic модель запроса
|
||||||
class StatusUpdate(BaseModel):
|
class StatusUpdate(BaseModel):
|
||||||
job_id: int
|
job_id: int
|
||||||
|
|
6938
search_jobes2.json
6938
search_jobes2.json
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,150 @@
|
||||||
|
<!-- BEGIN: Inbox Filter -->
|
||||||
|
<div class="intro-y flex flex-col-reverse sm:flex-row items-center">
|
||||||
|
<div class="w-full sm:w-auto relative mr-auto mt-3 sm:mt-0">
|
||||||
|
<i class="w-4 h-4 absolute my-auto inset-y-0 ml-3 left-0 z-10 text-gray-700" data-feather="search"></i>
|
||||||
|
<input type="text" class="input w-full sm:w-64 box px-10 text-gray-700 placeholder-theme-13" placeholder="Filter">
|
||||||
|
<div class="inbox-filter dropdown absolute inset-y-0 mr-3 right-0 flex items-center">
|
||||||
|
<i class="dropdown-toggle w-4 h-4 cursor-pointer text-gray-700" data-feather="chevron-down"></i>
|
||||||
|
<div class="inbox-filter__dropdown-box dropdown-box mt-10 absolute top-0 left-0 z-20">
|
||||||
|
<div class="dropdown-box__content box p-5">
|
||||||
|
<div class="grid grid-cols-12 gap-4 row-gap-3">
|
||||||
|
<div class="col-span-6">
|
||||||
|
<div class="text-xs">Requested o</div>
|
||||||
|
<select id="" class="input w-full border mt-2 flex-1">
|
||||||
|
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="date_range1">from date to date</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-span-6">
|
||||||
|
<div class="text-xs">Posted on</div>
|
||||||
|
<select data-placeholder="Select Posted on" id="" class="input w-full border mt-2 flex-1">
|
||||||
|
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="date_range">from date to date</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-span-6">
|
||||||
|
<div class="text-xs">Applied on</div>
|
||||||
|
<select id="applied-select" class="input w-full border mt-2 flex-1">
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="date_applied">from date to date</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- обёртка для диапазона дат (по умолчанию скрыта) -->
|
||||||
|
<div id="date-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input id="date-from" class="datepicker input w-full border mt-2">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input id="date-to" class="datepicker input w-full border mt-2">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const select = document.getElementById('applied-select');
|
||||||
|
const dateRangeWrapper = document.getElementById('date-range-wrapper');
|
||||||
|
const dateFrom = document.getElementById('date-from');
|
||||||
|
const dateTo = document.getElementById('date-to');
|
||||||
|
|
||||||
|
select.addEventListener('change', function () {
|
||||||
|
if (this.value === 'date_applied') {
|
||||||
|
dateRangeWrapper.style.display = 'grid';
|
||||||
|
} else {
|
||||||
|
dateRangeWrapper.style.display = 'none';
|
||||||
|
dateFrom.value = '';
|
||||||
|
dateTo.value = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Если хочешь — можно сохранить даты как data-атрибут или передать их куда нужно
|
||||||
|
dateFrom.addEventListener('change', function () {
|
||||||
|
select.setAttribute('data-date-from', this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
dateTo.addEventListener('change', function () {
|
||||||
|
select.setAttribute('data-date-to', this.value);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="col-span-6">
|
||||||
|
|
||||||
|
<div class="mt-3">
|
||||||
|
<label>Clients</label>
|
||||||
|
<div class="mt-2">
|
||||||
|
<select data-placeholder="Select Clients" id="clients-multiselect" class="select2 w-full" multiple="multiple">
|
||||||
|
{% set seen_ids = [] %}
|
||||||
|
{% for job in jobs %}
|
||||||
|
{% if job.client.id not in seen_ids %}
|
||||||
|
<option value="{{ job.client.id }}">{{ job.client.user_nicename }}</option>
|
||||||
|
{% set _ = seen_ids.append(job.client.id) %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-span-6">
|
||||||
|
<div class="mt-3">
|
||||||
|
<label>Assignee</label>
|
||||||
|
<div class="mt-2">
|
||||||
|
<select data-placeholder="Select Assignee" class="select2 w-full" multiple="multiple" name="assignee">
|
||||||
|
<option value="">— Not selected —</option>
|
||||||
|
{% for user in users %}
|
||||||
|
<option value="{{ user.id }}"
|
||||||
|
{% if user.id in assigned_users_ids %}selected{% endif %}>
|
||||||
|
{{ user.username }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-span-6">
|
||||||
|
|
||||||
|
<div class="mt-3">
|
||||||
|
<label>Status</label>
|
||||||
|
<div class="mt-2">
|
||||||
|
<select data-placeholder="Select Status" class="select2 w-full" multiple>
|
||||||
|
<option value="Scheduled" >Scheduled</option>
|
||||||
|
<option value="Requested">Requested</option>
|
||||||
|
<option value="In-Progress">In-Progress</option>
|
||||||
|
<option value="Applied">Applied</option>
|
||||||
|
<option value="Issues Applying">Issues Applying</option>
|
||||||
|
<option value="Cancelled">Cancelled</option>
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 flex items-center mt-3">
|
||||||
|
|
||||||
|
<button class="button w-32 justify-center block bg-theme-1 text-white ml-2">Search</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="w-full sm:w-auto flex">
|
||||||
|
|
||||||
|
<div class="dropdown relative">
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- END: Inbox Filter -->
|
|
@ -3,106 +3,206 @@
|
||||||
{% block title %}Главная{% endblock %}
|
{% block title %}Главная{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<style>
|
||||||
|
.select2-container {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
.filter-link {
|
||||||
|
font-size: 18px; /* Увеличиваем размер шрифта */
|
||||||
|
font-weight: bold; /* Делаем текст жирным */
|
||||||
|
padding: 10px 20px; /* Добавляем отступы для лучшего кликабельности */
|
||||||
|
background-color: #7a61fe; /* Добавляем зелёный фон */
|
||||||
|
color: white; /* Текст белый */
|
||||||
|
border-radius: 5px; /* Слегка скругляем углы */
|
||||||
|
text-align: center; /* Выравнивание по центру */
|
||||||
|
cursor: pointer; /* Курсор в виде указателя при наведении */
|
||||||
|
transition: background-color 0.3s ease, transform 0.2s ease; /* Плавные анимации */
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-link:hover {
|
||||||
|
background-color: #7a61fe; /* Темнее при наведении */
|
||||||
|
transform: scale(1.002); /* Немного увеличиваем размер при наведении */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
|
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
|
||||||
<h2 class="text-lg font-medium mr-auto">
|
<h2 class="text-lg font-medium mr-auto">
|
||||||
Tasks
|
Tasks
|
||||||
</h2>
|
</h2>
|
||||||
<!-- BEGIN: Inbox Filter -->
|
|
||||||
<div class="intro-y flex flex-col-reverse sm:flex-row items-center">
|
|
||||||
<div class="w-full sm:w-auto relative mr-auto mt-3 sm:mt-0">
|
|
||||||
<i class="w-4 h-4 absolute my-auto inset-y-0 ml-3 left-0 z-10 text-gray-700" data-feather="search"></i>
|
|
||||||
<input type="text" class="input w-full sm:w-64 box px-10 text-gray-700 placeholder-theme-13" placeholder="Filter">
|
|
||||||
<div class="inbox-filter dropdown absolute inset-y-0 mr-3 right-0 flex items-center">
|
|
||||||
<i class="dropdown-toggle w-4 h-4 cursor-pointer text-gray-700" data-feather="chevron-down"></i>
|
|
||||||
<div class="inbox-filter__dropdown-box dropdown-box mt-10 absolute top-0 left-0 z-20">
|
|
||||||
<div class="dropdown-box__content box p-5">
|
|
||||||
<div class="grid grid-cols-12 gap-4 row-gap-3">
|
|
||||||
<div class="col-span-6">
|
|
||||||
<div class="text-xs">Requested o</div>
|
|
||||||
<select class="input w-full border mt-2 flex-1">
|
|
||||||
<option value="" selected disabled>Выберите</option>
|
|
||||||
<option>Сегодня</option>
|
|
||||||
<option>Последние 7 дней</option>
|
|
||||||
<option>За все время</option>
|
|
||||||
<option>От даты - до даты.</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-6">
|
|
||||||
<div class="text-xs">Posted on</div>
|
|
||||||
<select class="input w-full border mt-2 flex-1">
|
|
||||||
<option value="" selected disabled>Выберите</option>
|
|
||||||
<option>Сегодня</option>
|
|
||||||
<option>Последние 7 дней</option>
|
|
||||||
<option>За все время</option>
|
|
||||||
<option>От даты - до даты.</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-6">
|
|
||||||
<div class="text-xs">Applied on</div>
|
|
||||||
<select class="input w-full border mt-2 flex-1">
|
|
||||||
<option value="" selected disabled>Выберите</option>
|
|
||||||
<option>Сегодня</option>
|
|
||||||
<option>Последние 7 дней</option>
|
|
||||||
<option>За все время</option>
|
|
||||||
<option>От даты - до даты.</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-6">
|
|
||||||
<div class="text-xs">Client</div>
|
|
||||||
<select class="input w-full border mt-2 flex-1">
|
|
||||||
<option value="" selected disabled>Выберите</option>
|
|
||||||
<option>-</option>
|
|
||||||
<option>-</option>
|
|
||||||
<option>-</option>
|
|
||||||
<option>-</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-6">
|
|
||||||
<div class="text-xs">Assignee</div>
|
|
||||||
<select class="select2 w-full" multiple>
|
|
||||||
<option value="" selected disabled>Выберите</option>
|
|
||||||
<option>-</option>
|
|
||||||
<option>-</option>
|
|
||||||
<option>-</option>
|
|
||||||
<option>-</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-6">
|
|
||||||
<div class="text-xs">Status</div>
|
|
||||||
<select class="select2 w-full" multiple>
|
|
||||||
|
|
||||||
<option>Scheduled</option>
|
|
||||||
<option>Requested</option>
|
|
||||||
<option>Applying</option>
|
|
||||||
<option>Applied</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-12 flex items-center mt-3">
|
|
||||||
|
|
||||||
<button class="button w-32 justify-center block bg-theme-1 text-white ml-2">Search</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="w-full sm:w-auto flex">
|
|
||||||
|
|
||||||
<div class="dropdown relative">
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- END: Inbox Filter -->
|
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
|
||||||
|
|
||||||
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
|
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="p-5" id="boxed-accordion">
|
||||||
|
<div class="preview">
|
||||||
|
<div class="accordion">
|
||||||
|
<div class="accordion__pane border border-gray-200 p-4 mt-3">
|
||||||
|
<a href="javascript:;" class="accordion__pane__toggle filter-link font-medium block">Filter</a>
|
||||||
|
|
||||||
|
<div class="accordion__pane__content mt-3 text-gray-800 leading-relaxed">
|
||||||
|
<div class="dropdown-box__content box p-5">
|
||||||
|
<form method="POST" action="/productf">
|
||||||
|
<!-- Дата-фильтры (Requested, Posted, Applied) -->
|
||||||
|
<div class="flex gap-4">
|
||||||
|
<!-- Requested on -->
|
||||||
|
<div class="w-1/2">
|
||||||
|
<div class="text-xs">Requested on</div>
|
||||||
|
<select id="date_requested" class="input w-full border mt-2 flex-1" name="date_requested">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_requested">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-requested-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-requested-from" class="input w-full border mt-2" name="date_requested_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-requested-to" class="input w-full border mt-2" name="date_requested_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Posted on -->
|
||||||
|
<div class="w-1/2">
|
||||||
|
<div class="text-xs">Posted on</div>
|
||||||
|
<select id="date_posted" class="input w-full border mt-2 flex-1" name="date_posted">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_posted">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-posted-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-posted-from" class="input w-full border mt-2" name="date_posted_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-posted-to" class="input w-full border mt-2" name="date_posted_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Applied on -->
|
||||||
|
<div class="col-span-6 mt-4">
|
||||||
|
<div class="text-xs">Applied on</div>
|
||||||
|
<select id="date_applied" class="input w-full border mt-2 flex-1" name="date_applied">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_applied">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-applied-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-applied-from" class="input w-full border mt-2" name="date_applied_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-applied-to" class="input w-full border mt-2" name="date_applied_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-nowrap gap-4 mt-4"> <!-- flex-nowrap запрещает перенос на новую строку -->
|
||||||
|
<!-- Clients (50% ширины) -->
|
||||||
|
<div class="flex-1 min-w-0"> <!-- flex-1 + min-w-0 предотвращает "расползание" -->
|
||||||
|
<label class="block mb-1 text-sm">Clients</label>
|
||||||
|
<select id="clients-multiselect1" class="select2 w-full" multiple="multiple" data-placeholder="Select Clients" name="client">
|
||||||
|
{% set seen_ids = [] %}
|
||||||
|
{% for job in jobs %}
|
||||||
|
{% if job.client.id not in seen_ids %}
|
||||||
|
<option value="{{ job.client.id }}">{{ job.client.user_nicename }}</option>
|
||||||
|
{% set _ = seen_ids.append(job.client.id) %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Assignee (50% ширины) -->
|
||||||
|
<div class="flex-1 min-w-0"> <!-- flex-1 дает равную ширину -->
|
||||||
|
<label class="block mb-1 text-sm">Assignee</label>
|
||||||
|
<select id="assignee-multiselect" class="select2 w-full" multiple="multiple" data-placeholder="Select Assignee" name="assignee">
|
||||||
|
<option value="">— Not selected —</option>
|
||||||
|
{% for user in users %}
|
||||||
|
<option value="{{ user.id }}" {% if user.id in assigned_users_ids %}selected{% endif %}>{{ user.username }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Status и кнопка Apply Filters -->
|
||||||
|
<div class="col-span-6 mt-4">
|
||||||
|
<label>Status</label>
|
||||||
|
<div class="mt-2">
|
||||||
|
<select data-placeholder="Select Status" class="select2 w-full" multiple name="status">
|
||||||
|
<option value="Scheduled">Scheduled</option>
|
||||||
|
<option value="Requested">Requested</option>
|
||||||
|
<option value="In-Progress">In-Progress</option>
|
||||||
|
<option value="Applied">Applied</option>
|
||||||
|
<option value="Issues Applying">Issues Applying</option>
|
||||||
|
<option value="Cancelled">Cancelled</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="button bg-theme-1 text-white mt-5">Apply Filters</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Функция для настройки обработчиков событий для каждого селекта
|
||||||
|
function setupDateSelect(selectId, wrapperId, customValue) {
|
||||||
|
const select = document.getElementById(selectId);
|
||||||
|
const dateRangeWrapper = document.getElementById(wrapperId);
|
||||||
|
|
||||||
|
select.addEventListener('change', function() {
|
||||||
|
if (this.value === customValue) {
|
||||||
|
dateRangeWrapper.style.display = 'grid';
|
||||||
|
} else {
|
||||||
|
dateRangeWrapper.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Инициализация при загрузке страницы
|
||||||
|
if (select.value === customValue) {
|
||||||
|
dateRangeWrapper.style.display = 'grid';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Настройка всех трех селектов
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
setupDateSelect('date_requested', 'date-requested-range-wrapper', 'custom_date_requested');
|
||||||
|
setupDateSelect('date_posted', 'date-posted-range-wrapper', 'custom_date_posted');
|
||||||
|
setupDateSelect('date_applied', 'date-applied-range-wrapper', 'custom_date_applied');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
<!-- BEGIN: Datatable -->
|
<!-- BEGIN: Datatable -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="intro-y datatable-wrapper box p-5 mt-5">
|
<div class="intro-y datatable-wrapper box p-5 mt-5">
|
||||||
<table class="table table-report table-report--bordered display datatable w-full">
|
<table class="table table-report table-report--bordered display datatable w-full">
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -163,10 +263,70 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- END: Datatable -->
|
<!-- END: Datatable -->
|
||||||
<!-- Включаем модалку -->
|
<!-- Включаем модалку -->
|
||||||
<!-- Модальное окно -->
|
<!-- Модальное окно -->
|
||||||
{% include "modal.html" %}
|
{% include "modal.html" %}
|
||||||
<script src="/static/dist/js/prod.js"></script>
|
<script src="/static/dist/js/prod.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Инициализация Select2
|
||||||
|
$('#clients-multiselect').select2();
|
||||||
|
|
||||||
|
// Получение выбранных ID при изменении
|
||||||
|
$('#clients-multiselect').on('change', function() {
|
||||||
|
const selectedIds = $(this).val(); // Массив выбранных ID
|
||||||
|
console.log("Selected Client IDs:", selectedIds);
|
||||||
|
|
||||||
|
// Отправка на сервер (пример)
|
||||||
|
fetch('/update-selected-clients', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRFToken': '{{ csrf_token }}'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({client_ids: selectedIds})
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => console.log(data));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Инициализация всех select2
|
||||||
|
$('.select2').select2();
|
||||||
|
|
||||||
|
// Обработчик кнопки Search
|
||||||
|
$('.button.bg-theme-1').on('click', function() {
|
||||||
|
// Собираем все данные фильтров
|
||||||
|
const filters = {
|
||||||
|
clients: $('#clients-multiselect').val() || [],
|
||||||
|
assignees: $('select[name="assignee"]').val() || [],
|
||||||
|
statuses: $('select[placeholder="Select categories"]').val() || [],
|
||||||
|
requested: $('#applied-select:eq(0)').val(),
|
||||||
|
posted: $('#applied-select:eq(1)').val(),
|
||||||
|
applied: $('#applied-select:eq(2)').val(),
|
||||||
|
date_range: $('#date-range-input').val()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Переходим на /productf с параметрами
|
||||||
|
const queryString = new URLSearchParams();
|
||||||
|
|
||||||
|
if (filters.clients.length) queryString.append('clients', filters.clients.join(','));
|
||||||
|
if (filters.assignees.length) queryString.append('assignees', filters.assignees.join(','));
|
||||||
|
if (filters.statuses.length) queryString.append('statuses', filters.statuses.join(','));
|
||||||
|
if (filters.requested) queryString.append('requested', filters.requested);
|
||||||
|
if (filters.posted) queryString.append('posted', filters.posted);
|
||||||
|
if (filters.applied) queryString.append('applied', filters.applied);
|
||||||
|
if (filters.date_range) queryString.append('date_range', filters.date_range);
|
||||||
|
|
||||||
|
window.location.href = `/productf?${queryString.toString()}`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -0,0 +1,85 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Главная{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
|
||||||
|
<h2 class="text-lg font-medium mr-auto">
|
||||||
|
Tasks
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
|
||||||
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
|
||||||
|
|
||||||
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
|
||||||
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
|
||||||
|
</div>
|
||||||
|
<!-- BEGIN: Datatable -->
|
||||||
|
<div class="intro-y datatable-wrapper box p-5 mt-5">
|
||||||
|
<table class="table table-report table-report--bordered display datatable w-full">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="border-b-2 whitespace-no-wrap">TITLE ⨈</th>
|
||||||
|
<th class="border-b-2 text-center whitespace-no-wrap">COMPANY ⨈</th>
|
||||||
|
<th class="border-b-2 text-center whitespace-no-wrap">CLIENT ⨈</th>
|
||||||
|
<th class="border-b-2 text-center whitespace-no-wrap">Requested on ⨈</th>
|
||||||
|
<th class="border-b-2 text-center whitespace-no-wrap">Posted on ⨈</th>
|
||||||
|
<th class="border-b-2 text-center whitespace-no-wrap">STATUS</th>
|
||||||
|
<th class="border-b-2 text-center whitespace-no-wrap">Assignee</th>
|
||||||
|
|
||||||
|
|
||||||
|
<th class="border-b-2 text-center whitespace-no-wrap">Applied on</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for job in jobs %}
|
||||||
|
<tr>
|
||||||
|
<td class="border-b">
|
||||||
|
<a href="{{ job.job.link }}" target="_blank" class="font-medium whitespace-no-wrap">{{ job.job.job_title [:50] }}</a>
|
||||||
|
<div class="text-gray-600 text-xs whitespace-no-wrap">{{ job.job.job_id }}</div>
|
||||||
|
</td>
|
||||||
|
<td class="text-center border-b">{{job.job.job_company}}</td>
|
||||||
|
<td class="text-center border-b">
|
||||||
|
|
||||||
|
<a href="#" class="client-link text-blue-500" data-client-id="{{ job.client.id }}">{{ job.client.user_nicename }}</a>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td class="text-center border-b">{{job.job.data_requested}}</td>
|
||||||
|
<td class="text-center border-b">{{job.job.date_posted}}</td>
|
||||||
|
<td class="text-center border-b">
|
||||||
|
<select class="select2" onchange="updateStatus(this, '{{ job.id }}')">
|
||||||
|
<option value="" {% if job.status is none %}selected{% endif %}>— Not selected —</option>
|
||||||
|
<option value="Scheduled" {% if job.status == "Scheduled" %}selected{% endif %}>Scheduled</option>
|
||||||
|
<option value="Requested" {% if job.status == "Requested" %}selected{% endif %}>Requested</option>
|
||||||
|
<option value="In-Progress" {% if job.status == "In-Progress" %}selected{% endif %}>In-Progress</option>
|
||||||
|
<option value="Applied" {% if job.status == "Applied" %}selected{% endif %}>Applied</option>
|
||||||
|
<option value="Issues Applying" {% if job.status == "Issues Applying" %}selected{% endif %}>Issues Applying</option>
|
||||||
|
<option value="Cancelled" {% if job.status == "Cancelled" %}selected{% endif %}>Cancelled</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td class="text-center border-b">
|
||||||
|
<select class="select2" onchange="updateAssignee(this, '{{ job.id }}')">
|
||||||
|
<option value="" {% if job.assignee is none %}selected{% endif %}>— Not selected —</option>
|
||||||
|
{% for user in users %}
|
||||||
|
<option value="{{ user.id }}" {% if job.assignee == user.id %}selected{% endif %}>
|
||||||
|
{{ user.username }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td class="text-center border-b">-</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!-- END: Datatable -->
|
||||||
|
<!-- Включаем модалку -->
|
||||||
|
<!-- Модальное окно -->
|
||||||
|
{% include "modal.html" %}
|
||||||
|
<script src="/static/dist/js/prod.js"></script>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -3,17 +3,202 @@
|
||||||
{% block title %}Главная{% endblock %}
|
{% block title %}Главная{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<style>
|
||||||
|
.select2-container {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
.filter-link {
|
||||||
|
font-size: 18px; /* Увеличиваем размер шрифта */
|
||||||
|
font-weight: bold; /* Делаем текст жирным */
|
||||||
|
padding: 10px 20px; /* Добавляем отступы для лучшего кликабельности */
|
||||||
|
background-color: #7a61fe; /* Добавляем зелёный фон */
|
||||||
|
color: white; /* Текст белый */
|
||||||
|
border-radius: 5px; /* Слегка скругляем углы */
|
||||||
|
text-align: center; /* Выравнивание по центру */
|
||||||
|
cursor: pointer; /* Курсор в виде указателя при наведении */
|
||||||
|
transition: background-color 0.3s ease, transform 0.2s ease; /* Плавные анимации */
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-link:hover {
|
||||||
|
background-color: #7a61fe; /* Темнее при наведении */
|
||||||
|
transform: scale(1.002); /* Немного увеличиваем размер при наведении */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
|
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
|
||||||
<h2 class="text-lg font-medium mr-auto">
|
<h2 class="text-lg font-medium mr-auto">
|
||||||
Tasks
|
Tasks
|
||||||
</h2>
|
</h2>
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
|
|
||||||
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
|
|
||||||
|
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
|
|
||||||
|
|
||||||
|
|
||||||
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
|
||||||
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
|
||||||
|
|
||||||
|
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="p-5" id="boxed-accordion">
|
||||||
|
<div class="preview">
|
||||||
|
<div class="accordion">
|
||||||
|
<div class="accordion__pane border border-gray-200 p-4 mt-3">
|
||||||
|
<a href="javascript:;" class="accordion__pane__toggle filter-link font-medium block">Filter</a>
|
||||||
|
|
||||||
|
<div class="accordion__pane__content mt-3 text-gray-800 leading-relaxed">
|
||||||
|
<div class="dropdown-box__content box p-5">
|
||||||
|
<form method="POST" action="/productf">
|
||||||
|
<!-- Дата-фильтры (Requested, Posted, Applied) -->
|
||||||
|
<div class="flex gap-4">
|
||||||
|
<!-- Requested on -->
|
||||||
|
<div class="w-1/2">
|
||||||
|
<div class="text-xs">Requested on</div>
|
||||||
|
<select id="date_requested" class="input w-full border mt-2 flex-1" name="date_requested">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_requested">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-requested-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-requested-from" class="input w-full border mt-2" name="date_requested_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-requested-to" class="input w-full border mt-2" name="date_requested_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Posted on -->
|
||||||
|
<div class="w-1/2">
|
||||||
|
<div class="text-xs">Posted on</div>
|
||||||
|
<select id="date_posted" class="input w-full border mt-2 flex-1" name="date_posted">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_posted">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-posted-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-posted-from" class="input w-full border mt-2" name="date_posted_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-posted-to" class="input w-full border mt-2" name="date_posted_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Applied on -->
|
||||||
|
<div class="col-span-6 mt-4">
|
||||||
|
<div class="text-xs">Applied on</div>
|
||||||
|
<select id="date_applied" class="input w-full border mt-2 flex-1" name="date_applied">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_applied">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-applied-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-applied-from" class="input w-full border mt-2" name="date_applied_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-applied-to" class="input w-full border mt-2" name="date_applied_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-nowrap gap-4 mt-4"> <!-- flex-nowrap запрещает перенос на новую строку -->
|
||||||
|
<!-- Clients (50% ширины) -->
|
||||||
|
<div class="flex-1 min-w-0"> <!-- flex-1 + min-w-0 предотвращает "расползание" -->
|
||||||
|
<label class="block mb-1 text-sm">Clients</label>
|
||||||
|
<select id="clients-multiselect1" class="select2 w-full" multiple="multiple" data-placeholder="Select Clients" name="client">
|
||||||
|
{% set seen_ids = [] %}
|
||||||
|
{% for job in jobs %}
|
||||||
|
{% if job.client.id not in seen_ids %}
|
||||||
|
<option value="{{ job.client.id }}">{{ job.client.user_nicename }}</option>
|
||||||
|
{% set _ = seen_ids.append(job.client.id) %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Assignee (50% ширины) -->
|
||||||
|
<div class="flex-1 min-w-0"> <!-- flex-1 дает равную ширину -->
|
||||||
|
<label class="block mb-1 text-sm">Assignee</label>
|
||||||
|
<select id="assignee-multiselect" class="select2 w-full" multiple="multiple" data-placeholder="Select Assignee" name="assignee">
|
||||||
|
<option value="">— Not selected —</option>
|
||||||
|
{% for user in users %}
|
||||||
|
<option value="{{ user.id }}" {% if user.id in assigned_users_ids %}selected{% endif %}>{{ user.username }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Status и кнопка Apply Filters -->
|
||||||
|
<div class="col-span-6 mt-4">
|
||||||
|
<label>Status</label>
|
||||||
|
<div class="mt-2">
|
||||||
|
<select data-placeholder="Select Status" class="select2 w-full" multiple name="status">
|
||||||
|
<option value="Scheduled">Scheduled</option>
|
||||||
|
<option value="Requested">Requested</option>
|
||||||
|
<option value="In-Progress">In-Progress</option>
|
||||||
|
<option value="Applied">Applied</option>
|
||||||
|
<option value="Issues Applying">Issues Applying</option>
|
||||||
|
<option value="Cancelled">Cancelled</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="button bg-theme-1 text-white mt-5">Apply Filters</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Функция для настройки обработчиков событий для каждого селекта
|
||||||
|
function setupDateSelect(selectId, wrapperId, customValue) {
|
||||||
|
const select = document.getElementById(selectId);
|
||||||
|
const dateRangeWrapper = document.getElementById(wrapperId);
|
||||||
|
|
||||||
|
select.addEventListener('change', function() {
|
||||||
|
if (this.value === customValue) {
|
||||||
|
dateRangeWrapper.style.display = 'grid';
|
||||||
|
} else {
|
||||||
|
dateRangeWrapper.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Инициализация при загрузке страницы
|
||||||
|
if (select.value === customValue) {
|
||||||
|
dateRangeWrapper.style.display = 'grid';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Настройка всех трех селектов
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
setupDateSelect('date_requested', 'date-requested-range-wrapper', 'custom_date_requested');
|
||||||
|
setupDateSelect('date_posted', 'date-posted-range-wrapper', 'custom_date_posted');
|
||||||
|
setupDateSelect('date_applied', 'date-applied-range-wrapper', 'custom_date_applied');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
<!-- BEGIN: Datatable -->
|
<!-- BEGIN: Datatable -->
|
||||||
<div class="intro-y datatable-wrapper box p-5 mt-5">
|
<div class="intro-y datatable-wrapper box p-5 mt-5">
|
||||||
<table class="table table-report table-report--bordered display datatable w-full">
|
<table class="table table-report table-report--bordered display datatable w-full">
|
||||||
|
|
|
@ -3,18 +3,202 @@
|
||||||
{% block title %}Главная{% endblock %}
|
{% block title %}Главная{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<style>
|
||||||
|
.select2-container {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
.filter-link {
|
||||||
|
font-size: 18px; /* Увеличиваем размер шрифта */
|
||||||
|
font-weight: bold; /* Делаем текст жирным */
|
||||||
|
padding: 10px 20px; /* Добавляем отступы для лучшего кликабельности */
|
||||||
|
background-color: #7a61fe; /* Добавляем зелёный фон */
|
||||||
|
color: white; /* Текст белый */
|
||||||
|
border-radius: 5px; /* Слегка скругляем углы */
|
||||||
|
text-align: center; /* Выравнивание по центру */
|
||||||
|
cursor: pointer; /* Курсор в виде указателя при наведении */
|
||||||
|
transition: background-color 0.3s ease, transform 0.2s ease; /* Плавные анимации */
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-link:hover {
|
||||||
|
background-color: #7a61fe; /* Темнее при наведении */
|
||||||
|
transform: scale(1.002); /* Немного увеличиваем размер при наведении */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
|
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
|
||||||
<h2 class="text-lg font-medium mr-auto">
|
<h2 class="text-lg font-medium mr-auto">
|
||||||
Tasks
|
Tasks
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
|
||||||
|
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
|
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
|
||||||
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
|
||||||
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="p-5" id="boxed-accordion">
|
||||||
|
<div class="preview">
|
||||||
|
<div class="accordion">
|
||||||
|
<div class="accordion__pane border border-gray-200 p-4 mt-3">
|
||||||
|
<a href="javascript:;" class="accordion__pane__toggle filter-link font-medium block">Filter</a>
|
||||||
|
|
||||||
|
<div class="accordion__pane__content mt-3 text-gray-800 leading-relaxed">
|
||||||
|
<div class="dropdown-box__content box p-5">
|
||||||
|
<form method="POST" action="/productf">
|
||||||
|
<!-- Дата-фильтры (Requested, Posted, Applied) -->
|
||||||
|
<div class="flex gap-4">
|
||||||
|
<!-- Requested on -->
|
||||||
|
<div class="w-1/2">
|
||||||
|
<div class="text-xs">Requested on</div>
|
||||||
|
<select id="date_requested" class="input w-full border mt-2 flex-1" name="date_requested">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_requested">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-requested-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-requested-from" class="input w-full border mt-2" name="date_requested_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-requested-to" class="input w-full border mt-2" name="date_requested_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Posted on -->
|
||||||
|
<div class="w-1/2">
|
||||||
|
<div class="text-xs">Posted on</div>
|
||||||
|
<select id="date_posted" class="input w-full border mt-2 flex-1" name="date_posted">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_posted">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-posted-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-posted-from" class="input w-full border mt-2" name="date_posted_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-posted-to" class="input w-full border mt-2" name="date_posted_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Applied on -->
|
||||||
|
<div class="col-span-6 mt-4">
|
||||||
|
<div class="text-xs">Applied on</div>
|
||||||
|
<select id="date_applied" class="input w-full border mt-2 flex-1" name="date_applied">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_applied">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-applied-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-applied-from" class="input w-full border mt-2" name="date_applied_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-applied-to" class="input w-full border mt-2" name="date_applied_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-nowrap gap-4 mt-4"> <!-- flex-nowrap запрещает перенос на новую строку -->
|
||||||
|
<!-- Clients (50% ширины) -->
|
||||||
|
<div class="flex-1 min-w-0"> <!-- flex-1 + min-w-0 предотвращает "расползание" -->
|
||||||
|
<label class="block mb-1 text-sm">Clients</label>
|
||||||
|
<select id="clients-multiselect1" class="select2 w-full" multiple="multiple" data-placeholder="Select Clients" name="client">
|
||||||
|
{% set seen_ids = [] %}
|
||||||
|
{% for job in jobs %}
|
||||||
|
{% if job.client.id not in seen_ids %}
|
||||||
|
<option value="{{ job.client.id }}">{{ job.client.user_nicename }}</option>
|
||||||
|
{% set _ = seen_ids.append(job.client.id) %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Assignee (50% ширины) -->
|
||||||
|
<div class="flex-1 min-w-0"> <!-- flex-1 дает равную ширину -->
|
||||||
|
<label class="block mb-1 text-sm">Assignee</label>
|
||||||
|
<select id="assignee-multiselect" class="select2 w-full" multiple="multiple" data-placeholder="Select Assignee" name="assignee">
|
||||||
|
<option value="">— Not selected —</option>
|
||||||
|
{% for user in users %}
|
||||||
|
<option value="{{ user.id }}" {% if user.id in assigned_users_ids %}selected{% endif %}>{{ user.username }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Status и кнопка Apply Filters -->
|
||||||
|
<div class="col-span-6 mt-4">
|
||||||
|
<label>Status</label>
|
||||||
|
<div class="mt-2">
|
||||||
|
<select data-placeholder="Select Status" class="select2 w-full" multiple name="status">
|
||||||
|
<option value="Scheduled">Scheduled</option>
|
||||||
|
<option value="Requested">Requested</option>
|
||||||
|
<option value="In-Progress">In-Progress</option>
|
||||||
|
<option value="Applied">Applied</option>
|
||||||
|
<option value="Issues Applying">Issues Applying</option>
|
||||||
|
<option value="Cancelled">Cancelled</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="button bg-theme-1 text-white mt-5">Apply Filters</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Функция для настройки обработчиков событий для каждого селекта
|
||||||
|
function setupDateSelect(selectId, wrapperId, customValue) {
|
||||||
|
const select = document.getElementById(selectId);
|
||||||
|
const dateRangeWrapper = document.getElementById(wrapperId);
|
||||||
|
|
||||||
|
select.addEventListener('change', function() {
|
||||||
|
if (this.value === customValue) {
|
||||||
|
dateRangeWrapper.style.display = 'grid';
|
||||||
|
} else {
|
||||||
|
dateRangeWrapper.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Инициализация при загрузке страницы
|
||||||
|
if (select.value === customValue) {
|
||||||
|
dateRangeWrapper.style.display = 'grid';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Настройка всех трех селектов
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
setupDateSelect('date_requested', 'date-requested-range-wrapper', 'custom_date_requested');
|
||||||
|
setupDateSelect('date_posted', 'date-posted-range-wrapper', 'custom_date_posted');
|
||||||
|
setupDateSelect('date_applied', 'date-applied-range-wrapper', 'custom_date_applied');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
<!-- BEGIN: Datatable -->
|
<!-- BEGIN: Datatable -->
|
||||||
<div class="intro-y datatable-wrapper box p-5 mt-5">
|
<div class="intro-y datatable-wrapper box p-5 mt-5">
|
||||||
<table class="table table-report table-report--bordered display datatable w-full">
|
<table class="table table-report table-report--bordered display datatable w-full">
|
||||||
|
|
|
@ -4,104 +4,202 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.select2-container {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
.filter-link {
|
||||||
|
font-size: 18px; /* Увеличиваем размер шрифта */
|
||||||
|
font-weight: bold; /* Делаем текст жирным */
|
||||||
|
padding: 10px 20px; /* Добавляем отступы для лучшего кликабельности */
|
||||||
|
background-color: #7a61fe; /* Добавляем зелёный фон */
|
||||||
|
color: white; /* Текст белый */
|
||||||
|
border-radius: 5px; /* Слегка скругляем углы */
|
||||||
|
text-align: center; /* Выравнивание по центру */
|
||||||
|
cursor: pointer; /* Курсор в виде указателя при наведении */
|
||||||
|
transition: background-color 0.3s ease, transform 0.2s ease; /* Плавные анимации */
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-link:hover {
|
||||||
|
background-color: #7a61fe; /* Темнее при наведении */
|
||||||
|
transform: scale(1.002); /* Немного увеличиваем размер при наведении */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
|
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
|
||||||
<h2 class="text-lg font-medium mr-auto">
|
<h2 class="text-lg font-medium mr-auto">
|
||||||
Tasks
|
Tasks
|
||||||
</h2>
|
</h2>
|
||||||
<!-- BEGIN: Inbox Filter
|
|
||||||
<div class="intro-y flex flex-col-reverse sm:flex-row items-center">
|
|
||||||
<div class="w-full sm:w-auto relative mr-auto mt-3 sm:mt-0">
|
|
||||||
<i class="w-4 h-4 absolute my-auto inset-y-0 ml-3 left-0 z-10 text-gray-700" data-feather="search"></i>
|
|
||||||
<input type="text" class="input w-full sm:w-64 box px-10 text-gray-700 placeholder-theme-13" placeholder="Filter">
|
|
||||||
<div class="inbox-filter dropdown absolute inset-y-0 mr-3 right-0 flex items-center">
|
|
||||||
<i class="dropdown-toggle w-4 h-4 cursor-pointer text-gray-700" data-feather="chevron-down"></i>
|
|
||||||
<div class="inbox-filter__dropdown-box dropdown-box mt-10 absolute top-0 left-0 z-20">
|
|
||||||
<div class="dropdown-box__content box p-5">
|
|
||||||
<div class="grid grid-cols-12 gap-4 row-gap-3">
|
|
||||||
<div class="col-span-6">
|
|
||||||
<div class="text-xs">Requested o</div>
|
|
||||||
<select class="input w-full border mt-2 flex-1">
|
|
||||||
<option value="" selected disabled>Выберите</option>
|
|
||||||
<option>Сегодня</option>
|
|
||||||
<option>Последние 7 дней</option>
|
|
||||||
<option>За все время</option>
|
|
||||||
<option>От даты - до даты.</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-6">
|
|
||||||
<div class="text-xs">Posted on</div>
|
|
||||||
<select class="input w-full border mt-2 flex-1">
|
|
||||||
<option value="" selected disabled>Выберите</option>
|
|
||||||
<option>Сегодня</option>
|
|
||||||
<option>Последние 7 дней</option>
|
|
||||||
<option>За все время</option>
|
|
||||||
<option>От даты - до даты.</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-6">
|
|
||||||
<div class="text-xs">Applied on</div>
|
|
||||||
<select class="input w-full border mt-2 flex-1">
|
|
||||||
<option value="" selected disabled>Выберите</option>
|
|
||||||
<option>Сегодня</option>
|
|
||||||
<option>Последние 7 дней</option>
|
|
||||||
<option>За все время</option>
|
|
||||||
<option>От даты - до даты.</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-6">
|
|
||||||
<div class="text-xs">Client</div>
|
|
||||||
<select class="input w-full border mt-2 flex-1">
|
|
||||||
<option value="" selected disabled>Выберите</option>
|
|
||||||
<option>-</option>
|
|
||||||
<option>-</option>
|
|
||||||
<option>-</option>
|
|
||||||
<option>-</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-6">
|
|
||||||
<div class="text-xs">Assignee</div>
|
|
||||||
<select class="select2 w-full" multiple>
|
|
||||||
<option value="" selected disabled>Выберите</option>
|
|
||||||
<option>-</option>
|
|
||||||
<option>-</option>
|
|
||||||
<option>-</option>
|
|
||||||
<option>-</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-6">
|
|
||||||
<div class="text-xs">Status</div>
|
|
||||||
<select class="select2 w-full" multiple>
|
|
||||||
|
|
||||||
<option>Scheduled</option>
|
|
||||||
<option>Requested</option>
|
|
||||||
<option>Applying</option>
|
|
||||||
<option>Applied</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-12 flex items-center mt-3">
|
|
||||||
|
|
||||||
<button class="button w-32 justify-center block bg-theme-1 text-white ml-2">Search</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="w-full sm:w-auto flex">
|
|
||||||
|
|
||||||
<div class="dropdown relative">
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
END: Inbox Filter -->
|
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
|
||||||
|
|
||||||
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
|
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="p-5" id="boxed-accordion">
|
||||||
|
<div class="preview">
|
||||||
|
<div class="accordion">
|
||||||
|
<div class="accordion__pane border border-gray-200 p-4 mt-3">
|
||||||
|
<a href="javascript:;" class="accordion__pane__toggle filter-link font-medium block">Filter</a>
|
||||||
|
|
||||||
|
<div class="accordion__pane__content mt-3 text-gray-800 leading-relaxed">
|
||||||
|
<div class="dropdown-box__content box p-5">
|
||||||
|
<form method="POST" action="/productf">
|
||||||
|
<!-- Дата-фильтры (Requested, Posted, Applied) -->
|
||||||
|
<div class="flex gap-4">
|
||||||
|
<!-- Requested on -->
|
||||||
|
<div class="w-1/2">
|
||||||
|
<div class="text-xs">Requested on</div>
|
||||||
|
<select id="date_requested" class="input w-full border mt-2 flex-1" name="date_requested">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_requested">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-requested-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-requested-from" class="input w-full border mt-2" name="date_requested_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-requested-to" class="input w-full border mt-2" name="date_requested_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Posted on -->
|
||||||
|
<div class="w-1/2">
|
||||||
|
<div class="text-xs">Posted on</div>
|
||||||
|
<select id="date_posted" class="input w-full border mt-2 flex-1" name="date_posted">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_posted">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-posted-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-posted-from" class="input w-full border mt-2" name="date_posted_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-posted-to" class="input w-full border mt-2" name="date_posted_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Applied on -->
|
||||||
|
<div class="col-span-6 mt-4">
|
||||||
|
<div class="text-xs">Applied on</div>
|
||||||
|
<select id="date_applied" class="input w-full border mt-2 flex-1" name="date_applied">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_applied">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-applied-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-applied-from" class="input w-full border mt-2" name="date_applied_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-applied-to" class="input w-full border mt-2" name="date_applied_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-nowrap gap-4 mt-4"> <!-- flex-nowrap запрещает перенос на новую строку -->
|
||||||
|
<!-- Clients (50% ширины) -->
|
||||||
|
<div class="flex-1 min-w-0"> <!-- flex-1 + min-w-0 предотвращает "расползание" -->
|
||||||
|
<label class="block mb-1 text-sm">Clients</label>
|
||||||
|
<select id="clients-multiselect1" class="select2 w-full" multiple="multiple" data-placeholder="Select Clients" name="client">
|
||||||
|
{% set seen_ids = [] %}
|
||||||
|
{% for job in jobs %}
|
||||||
|
{% if job.client.id not in seen_ids %}
|
||||||
|
<option value="{{ job.client.id }}">{{ job.client.user_nicename }}</option>
|
||||||
|
{% set _ = seen_ids.append(job.client.id) %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Assignee (50% ширины) -->
|
||||||
|
<div class="flex-1 min-w-0"> <!-- flex-1 дает равную ширину -->
|
||||||
|
<label class="block mb-1 text-sm">Assignee</label>
|
||||||
|
<select id="assignee-multiselect" class="select2 w-full" multiple="multiple" data-placeholder="Select Assignee" name="assignee">
|
||||||
|
<option value="">— Not selected —</option>
|
||||||
|
{% for user in users %}
|
||||||
|
<option value="{{ user.id }}" {% if user.id in assigned_users_ids %}selected{% endif %}>{{ user.username }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Status и кнопка Apply Filters -->
|
||||||
|
<div class="col-span-6 mt-4">
|
||||||
|
<label>Status</label>
|
||||||
|
<div class="mt-2">
|
||||||
|
<select data-placeholder="Select Status" class="select2 w-full" multiple name="status">
|
||||||
|
<option value="Scheduled">Scheduled</option>
|
||||||
|
<option value="Requested">Requested</option>
|
||||||
|
<option value="In-Progress">In-Progress</option>
|
||||||
|
<option value="Applied">Applied</option>
|
||||||
|
<option value="Issues Applying">Issues Applying</option>
|
||||||
|
<option value="Cancelled">Cancelled</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="button bg-theme-1 text-white mt-5">Apply Filters</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Функция для настройки обработчиков событий для каждого селекта
|
||||||
|
function setupDateSelect(selectId, wrapperId, customValue) {
|
||||||
|
const select = document.getElementById(selectId);
|
||||||
|
const dateRangeWrapper = document.getElementById(wrapperId);
|
||||||
|
|
||||||
|
select.addEventListener('change', function() {
|
||||||
|
if (this.value === customValue) {
|
||||||
|
dateRangeWrapper.style.display = 'grid';
|
||||||
|
} else {
|
||||||
|
dateRangeWrapper.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Инициализация при загрузке страницы
|
||||||
|
if (select.value === customValue) {
|
||||||
|
dateRangeWrapper.style.display = 'grid';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Настройка всех трех селектов
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
setupDateSelect('date_requested', 'date-requested-range-wrapper', 'custom_date_requested');
|
||||||
|
setupDateSelect('date_posted', 'date-posted-range-wrapper', 'custom_date_posted');
|
||||||
|
setupDateSelect('date_applied', 'date-applied-range-wrapper', 'custom_date_applied');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
<!-- BEGIN: Datatable -->
|
<!-- BEGIN: Datatable -->
|
||||||
<div class="intro-y datatable-wrapper box p-5 mt-5">
|
<div class="intro-y datatable-wrapper box p-5 mt-5">
|
||||||
<table class="table table-report table-report--bordered display datatable w-full">
|
<table class="table table-report table-report--bordered display datatable w-full">
|
||||||
|
|
|
@ -4,16 +4,202 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.select2-container {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
.filter-link {
|
||||||
|
font-size: 18px; /* Увеличиваем размер шрифта */
|
||||||
|
font-weight: bold; /* Делаем текст жирным */
|
||||||
|
padding: 10px 20px; /* Добавляем отступы для лучшего кликабельности */
|
||||||
|
background-color: #7a61fe; /* Добавляем зелёный фон */
|
||||||
|
color: white; /* Текст белый */
|
||||||
|
border-radius: 5px; /* Слегка скругляем углы */
|
||||||
|
text-align: center; /* Выравнивание по центру */
|
||||||
|
cursor: pointer; /* Курсор в виде указателя при наведении */
|
||||||
|
transition: background-color 0.3s ease, transform 0.2s ease; /* Плавные анимации */
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-link:hover {
|
||||||
|
background-color: #7a61fe; /* Темнее при наведении */
|
||||||
|
transform: scale(1.002); /* Немного увеличиваем размер при наведении */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
|
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
|
||||||
<h2 class="text-lg font-medium mr-auto">
|
<h2 class="text-lg font-medium mr-auto">
|
||||||
Tasks
|
Tasks
|
||||||
</h2>
|
</h2>
|
||||||
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
|
||||||
|
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
|
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
|
||||||
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
|
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="p-5" id="boxed-accordion">
|
||||||
|
<div class="preview">
|
||||||
|
<div class="accordion">
|
||||||
|
<div class="accordion__pane border border-gray-200 p-4 mt-3">
|
||||||
|
<a href="javascript:;" class="accordion__pane__toggle filter-link font-medium block">Filter</a>
|
||||||
|
|
||||||
|
<div class="accordion__pane__content mt-3 text-gray-800 leading-relaxed">
|
||||||
|
<div class="dropdown-box__content box p-5">
|
||||||
|
<form method="POST" action="/productf">
|
||||||
|
<!-- Дата-фильтры (Requested, Posted, Applied) -->
|
||||||
|
<div class="flex gap-4">
|
||||||
|
<!-- Requested on -->
|
||||||
|
<div class="w-1/2">
|
||||||
|
<div class="text-xs">Requested on</div>
|
||||||
|
<select id="date_requested" class="input w-full border mt-2 flex-1" name="date_requested">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_requested">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-requested-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-requested-from" class="input w-full border mt-2" name="date_requested_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-requested-to" class="input w-full border mt-2" name="date_requested_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Posted on -->
|
||||||
|
<div class="w-1/2">
|
||||||
|
<div class="text-xs">Posted on</div>
|
||||||
|
<select id="date_posted" class="input w-full border mt-2 flex-1" name="date_posted">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_posted">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-posted-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-posted-from" class="input w-full border mt-2" name="date_posted_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-posted-to" class="input w-full border mt-2" name="date_posted_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Applied on -->
|
||||||
|
<div class="col-span-6 mt-4">
|
||||||
|
<div class="text-xs">Applied on</div>
|
||||||
|
<select id="date_applied" class="input w-full border mt-2 flex-1" name="date_applied">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Today">Today</option>
|
||||||
|
<option value="Last 7 days">Last 7 days</option>
|
||||||
|
<option value="For all time">For all time</option>
|
||||||
|
<option value="custom_date_applied">from date to date</option>
|
||||||
|
</select>
|
||||||
|
<div id="date-applied-range-wrapper" class="p-5 grid grid-cols-12 gap-4 row-gap-3 mt-4" style="display: none;">
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>From</label>
|
||||||
|
<input type="date" id="date-applied-from" class="input w-full border mt-2" name="date_applied_from">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-12 sm:col-span-6">
|
||||||
|
<label>To</label>
|
||||||
|
<input type="date" id="date-applied-to" class="input w-full border mt-2" name="date_applied_to">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-nowrap gap-4 mt-4"> <!-- flex-nowrap запрещает перенос на новую строку -->
|
||||||
|
<!-- Clients (50% ширины) -->
|
||||||
|
<div class="flex-1 min-w-0"> <!-- flex-1 + min-w-0 предотвращает "расползание" -->
|
||||||
|
<label class="block mb-1 text-sm">Clients</label>
|
||||||
|
<select id="clients-multiselect1" class="select2 w-full" multiple="multiple" data-placeholder="Select Clients" name="client">
|
||||||
|
{% set seen_ids = [] %}
|
||||||
|
{% for job in jobs %}
|
||||||
|
{% if job.client.id not in seen_ids %}
|
||||||
|
<option value="{{ job.client.id }}">{{ job.client.user_nicename }}</option>
|
||||||
|
{% set _ = seen_ids.append(job.client.id) %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Assignee (50% ширины) -->
|
||||||
|
<div class="flex-1 min-w-0"> <!-- flex-1 дает равную ширину -->
|
||||||
|
<label class="block mb-1 text-sm">Assignee</label>
|
||||||
|
<select id="assignee-multiselect" class="select2 w-full" multiple="multiple" data-placeholder="Select Assignee" name="assignee">
|
||||||
|
<option value="">— Not selected —</option>
|
||||||
|
{% for user in users %}
|
||||||
|
<option value="{{ user.id }}" {% if user.id in assigned_users_ids %}selected{% endif %}>{{ user.username }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Status и кнопка Apply Filters -->
|
||||||
|
<div class="col-span-6 mt-4">
|
||||||
|
<label>Status</label>
|
||||||
|
<div class="mt-2">
|
||||||
|
<select data-placeholder="Select Status" class="select2 w-full" multiple name="status">
|
||||||
|
<option value="Scheduled">Scheduled</option>
|
||||||
|
<option value="Requested">Requested</option>
|
||||||
|
<option value="In-Progress">In-Progress</option>
|
||||||
|
<option value="Applied">Applied</option>
|
||||||
|
<option value="Issues Applying">Issues Applying</option>
|
||||||
|
<option value="Cancelled">Cancelled</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="button bg-theme-1 text-white mt-5">Apply Filters</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Функция для настройки обработчиков событий для каждого селекта
|
||||||
|
function setupDateSelect(selectId, wrapperId, customValue) {
|
||||||
|
const select = document.getElementById(selectId);
|
||||||
|
const dateRangeWrapper = document.getElementById(wrapperId);
|
||||||
|
|
||||||
|
select.addEventListener('change', function() {
|
||||||
|
if (this.value === customValue) {
|
||||||
|
dateRangeWrapper.style.display = 'grid';
|
||||||
|
} else {
|
||||||
|
dateRangeWrapper.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Инициализация при загрузке страницы
|
||||||
|
if (select.value === customValue) {
|
||||||
|
dateRangeWrapper.style.display = 'grid';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Настройка всех трех селектов
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
setupDateSelect('date_requested', 'date-requested-range-wrapper', 'custom_date_requested');
|
||||||
|
setupDateSelect('date_posted', 'date-posted-range-wrapper', 'custom_date_posted');
|
||||||
|
setupDateSelect('date_applied', 'date-applied-range-wrapper', 'custom_date_applied');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
<!-- BEGIN: Datatable -->
|
<!-- BEGIN: Datatable -->
|
||||||
<div class="intro-y datatable-wrapper box p-5 mt-5">
|
<div class="intro-y datatable-wrapper box p-5 mt-5">
|
||||||
<table class="table table-report table-report--bordered display datatable w-full">
|
<table class="table table-report table-report--bordered display datatable w-full">
|
||||||
|
|
Loading…
Reference in New Issue