This commit is contained in:
		
							parent
							
								
									5921c8874d
								
							
						
					
					
						commit
						ab4454320a
					
				
							
								
								
									
										2021
									
								
								logs/app.log
								
								
								
								
							
							
						
						
									
										2021
									
								
								logs/app.log
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										25
									
								
								main.py
								
								
								
								
							
							
						
						
									
										25
									
								
								main.py
								
								
								
								
							|  | @ -3,7 +3,7 @@ from fastapi.responses import RedirectResponse | |||
| from fastapi.templating import Jinja2Templates | ||||
| from fastapi.staticfiles import StaticFiles | ||||
| from model.database import init_db | ||||
| from routers import index, logins, users, product, profile, jobs | ||||
| from routers import index, logins, users, product, profile, jobs, client | ||||
| 
 | ||||
| import logging | ||||
| 
 | ||||
|  | @ -12,7 +12,16 @@ import logging | |||
| init_db() | ||||
| 
 | ||||
| # Инициализация приложения | ||||
| app = FastAPI() | ||||
| app = FastAPI(title="API для turboapply", | ||||
|               description="🚀 Это кастомное описание для Swagger UI",  # ✅ Описание | ||||
|               version="1.0.3",                     # ✅ Версия API | ||||
|             #   docs_url="/api/v1/documentation/", | ||||
|               redoc_url=None, | ||||
|             #   docs_url=None,  # Отключаем дефолтный Swagger | ||||
|               openapi_url="/openapi.json",  | ||||
|               swagger_ui_parameters={"filter": True}, | ||||
|             #   on_startup=[start_workers] | ||||
|             ) | ||||
| 
 | ||||
| # Настройка шаблонов | ||||
| templates = Jinja2Templates(directory="templates") | ||||
|  | @ -21,14 +30,16 @@ templates = Jinja2Templates(directory="templates") | |||
| app.mount("/static", StaticFiles(directory="static"), name="static") | ||||
| 
 | ||||
| # Подключение маршрутов | ||||
| app.include_router(index.router, tags=["callback"]) | ||||
| app.include_router(logins.router, tags=["login"]) | ||||
| app.include_router(users.router, tags=["users"]) | ||||
| app.include_router(product.router, tags=["product"]) | ||||
| app.include_router(index.router, tags=["callback"], include_in_schema=False) | ||||
| app.include_router(logins.router, tags=["login"], include_in_schema=False) | ||||
| app.include_router(users.router, tags=["users"], include_in_schema=False) | ||||
| app.include_router(product.router, tags=["product"], include_in_schema=False) | ||||
| app.include_router(client.router, tags=["client"]) | ||||
| 
 | ||||
| 
 | ||||
| # Подключение роутеров | ||||
| app.include_router(profile.router, tags=["Profile"]) | ||||
| app.include_router(jobs.router, tags=["Jobs"]) | ||||
| app.include_router(jobs.router, tags=["Jobs"], include_in_schema=False) | ||||
| 
 | ||||
| # Обработка 404 | ||||
| @app.exception_handler(404) | ||||
|  |  | |||
|  | @ -126,16 +126,33 @@ class Client(Base): | |||
|     __tablename__ = "client" | ||||
| 
 | ||||
|     id = Column(Integer, primary_key=True, index=True) | ||||
|     username = Column(String(55), unique=True, index=True, nullable=False)  # ✅ Правильно | ||||
|     phone = Column(String(55), unique=True, index=True, nullable=True)  # ✅ Правильно | ||||
|     email = Column(String(55), unique=True, index=True, nullable=True)  # ✅ Правильно | ||||
|     link = Column(String(2083), nullable=True)  # URL вакансии | ||||
|     is_active = Column(Boolean, default=True) | ||||
|     user_login = Column(String(55), unique=True, index=True, nullable=False)  # ✅ Правильно | ||||
|     user_nicename = Column(String(55), unique=True, index=True, nullable=True)  # ✅ Правильно | ||||
|     user_email = Column(String(55), unique=True, index=True, nullable=True)  # ✅ Правильно | ||||
|     # user_registered = Column(String(2083), nullable=True)  # URL вакансии | ||||
|     user_status = Column(Boolean, default=True) | ||||
|      | ||||
|     # Связь с AppliedJobs (заявки на вакансии) | ||||
|     applications = relationship("AppliedJob", back_populates="client") | ||||
|      | ||||
| class MetaClient(Base): | ||||
|     __tablename__ = "meta_client" | ||||
| 
 | ||||
|     id = Column(Integer, primary_key=True, index=True) | ||||
|     user_id = Column(Integer, ForeignKey("client.id"), nullable=False) | ||||
|     meta_key = Column(String(255), nullable=False) | ||||
|     meta_value = Column(Text, nullable=True) | ||||
| 
 | ||||
|     # Связь с Client | ||||
|     client = relationship("Client", back_populates="meta") | ||||
| 
 | ||||
| # Добавляем обратную связь в Client | ||||
| Client.meta = relationship("MetaClient", back_populates="client", cascade="all, delete-orphan") | ||||
| 
 | ||||
|      | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| class AppliedJob(Base): | ||||
|     __tablename__ = "applied_jobs" | ||||
| 
 | ||||
|  | @ -151,3 +168,6 @@ class AppliedJob(Base): | |||
|     job = relationship("Job", back_populates="applications") | ||||
|     users = relationship("User", back_populates="applications") | ||||
|      | ||||
|      | ||||
| 
 | ||||
|      | ||||
|  |  | |||
|  | @ -0,0 +1,38 @@ | |||
| from fastapi import FastAPI, HTTPException, APIRouter, Request, Header | ||||
| from fastapi.responses import JSONResponse | ||||
| from fastapi.templating import Jinja2Templates | ||||
| from typing import Dict | ||||
| from pydantic import BaseModel | ||||
| import json | ||||
| 
 | ||||
| router = APIRouter() | ||||
| templates = Jinja2Templates(directory="templates") | ||||
| API_KEY = "4545454" | ||||
| 
 | ||||
| # Пример данных | ||||
| clients = { | ||||
|     27: {"username": "John Doe", "email": "john@example.com", "phone": "+123456781"}, | ||||
|     44: {"username": "Jane Smith", "email": "jane@example.com", "phone": "+987654321"} | ||||
| } | ||||
| @router.get("/get_client/{client_id}", include_in_schema=False) | ||||
| async def get_client_modal(client_id: int): | ||||
|     client = clients.get(client_id)  # Используй clients вместо clients_db | ||||
|     if not client: | ||||
|         raise HTTPException(status_code=404, detail="Client not found") | ||||
|     return JSONResponse(content=client) | ||||
| 
 | ||||
| class JsonData(BaseModel): | ||||
|     json_data: str | ||||
| 
 | ||||
| @router.post("/client/") | ||||
| async def client(data: JsonData, x_api_key: str = Header(None)): | ||||
|     # Проверяем API-ключ | ||||
|     if x_api_key != "4545454": | ||||
|         raise HTTPException(status_code=403, detail="Invalid API Key") | ||||
|      | ||||
|     try: | ||||
|         parsed_data = json.loads(data.json_data)  # Декодируем JSON | ||||
|         print("Полученные данные:", parsed_data) | ||||
|         return {"message": "JSON получен", "data": parsed_data} | ||||
|     except json.JSONDecodeError as e: | ||||
|         raise HTTPException(status_code=400, detail=f"Invalid JSON: {str(e)}") | ||||
|  | @ -0,0 +1,48 @@ | |||
| 
 | ||||
| function updateStatus(selectElement, jobId) { | ||||
|     let selectedStatus = selectElement.value; | ||||
| 
 | ||||
|     fetch('/update_status/', { | ||||
|         method: 'POST', | ||||
|         headers: { | ||||
|             'Content-Type': 'application/json', | ||||
|         }, | ||||
|         body: JSON.stringify({ | ||||
|             job_id: jobId, | ||||
|             status: selectedStatus | ||||
|         }) | ||||
|     }) | ||||
|     .then(response => response.json()) | ||||
|     .then(data => { | ||||
|         console.log('Успешно обновлено:', data); | ||||
|     }) | ||||
|     .catch(error => { | ||||
|         console.error('Ошибка:', error); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| function updateAssignee(selectElement, jobId) { | ||||
|     let selectedUserId = selectElement.value; | ||||
| 
 | ||||
|     fetch('/update_assignee/', { | ||||
|         method: 'POST', | ||||
|         headers: { | ||||
|             'Content-Type': 'application/json', | ||||
|         }, | ||||
|         body: JSON.stringify({ | ||||
|             job_id: jobId, | ||||
|             assignee_id: selectedUserId | ||||
|         }) | ||||
|     }) | ||||
|     .then(response => response.json()) | ||||
|     .then(data => { | ||||
|         console.log('Успешно обновлено:', data); | ||||
|     }) | ||||
|     .catch(error => { | ||||
|         console.error('Ошибка:', error); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -0,0 +1,101 @@ | |||
| 
 | ||||
| <!-- Модальное окно ×--> | ||||
| 
 | ||||
| 
 | ||||
| <!-- Модальное окно ×--> | ||||
| <div id="client-modal" class="fixed inset-0 hidden bg-gray-800 bg-opacity-75 flex items-center justify-center z-50"> | ||||
|     <div class="bg-white rounded-lg p-6 w-1/3 relative shadow-2xl"> | ||||
|         <span id="close-modal" class="absolute top-2 right-4 text-xl cursor-pointer"></span> | ||||
|         <h2 class="modal__content">Client Details</h2> | ||||
| <div class="post intro-y overflow-hidden box mt-5"> | ||||
|                             <div class="post__tabs nav-tabs flex flex-col sm:flex-row bg-gray-200 text-gray-600"> | ||||
|                                 <a title="Main" data-toggle="tab" data-target="#content" href="javascript:;" class="tooltip w-full sm:w-40 py-4 text-center flex justify-center items-center active"> <i data-feather="file-text" class="w-4 h-4 mr-2"></i> Main </a> | ||||
|                                 <a title="Profile" data-toggle="tab" data-target="#prom" href="javascript:;" class="tooltip w-full sm:w-40 py-4 text-center flex justify-center items-center"> <i data-feather="code" class="w-4 h-4 mr-2"></i> Profile </a> | ||||
|                                 <a title="Knowledge Base" data-toggle="tab" data-target="#rozetka" href="javascript:;" class="tooltip w-full sm:w-40 py-4 text-center flex justify-center items-center"> <i data-feather="align-left" class="w-4 h-4 mr-2"></i> Knowledge Base </a> | ||||
|                                  | ||||
| 
 | ||||
|                             </div> | ||||
|                             <div class="post__content tab-content"> | ||||
|                                                     <div class="tab-content__pane p-5 active" id="content"> | ||||
|                                                     <div class="border border-gray-200 rounded-md p-5 mt-5"> | ||||
|                          | ||||
|                                                     <p><strong>Name:</strong> <span id="client-name"></span></p> | ||||
|                                                     <p><strong>Email:</strong> <span id="client-email"></span></p> | ||||
|                                                     <p><strong>Phone:</strong> <span id="client-phone"></span></p> | ||||
|                                                              | ||||
|                                                      | ||||
|                                                     </div> | ||||
| 
 | ||||
|                              | ||||
|                                                     </div> | ||||
| 
 | ||||
|                                                     <div class="tab-content__pane p-5 " id="prom"> | ||||
|                                                     <div class="border border-gray-200 rounded-md p-5 mt-5"> | ||||
|                                                          | ||||
|                                                      | ||||
|                                                      | ||||
|                                                      | ||||
|                                                         </div> | ||||
|                                                          | ||||
|                                                     </div> | ||||
|                                                      | ||||
|                                                     <div class="tab-content__pane p-5" id="rozetka"> | ||||
|                                                         <div class="border border-gray-200 rounded-md p-5 mt-5"> | ||||
|                                                              | ||||
|                                                      | ||||
|                                                      | ||||
|                                                         </div> | ||||
|                                                     </div> | ||||
|                                                      | ||||
|                                                      | ||||
|                                                      | ||||
|                                                      | ||||
|                             </div> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     <!-- END: Post Content --> | ||||
|                     <!-- BEGIN: Post Info --> | ||||
|                      | ||||
|     </div> | ||||
|     </div> | ||||
| 
 | ||||
| </div> | ||||
| 
 | ||||
| 
 | ||||
| <!-- JS только для модалки --> | ||||
| <script> | ||||
| document.addEventListener("DOMContentLoaded", () => { | ||||
|     const modal = document.getElementById("client-modal"); | ||||
|     const closeModal = document.getElementById("close-modal"); | ||||
| 
 | ||||
|     // Открытие модалки по клику на имя клиента | ||||
|     document.querySelectorAll(".client-link").forEach(link => { | ||||
|         link.addEventListener("click", (e) => { | ||||
|             e.preventDefault(); | ||||
|             const clientId = link.getAttribute("data-client-id"); | ||||
| 
 | ||||
|             fetch(`/get_client/${clientId}`) | ||||
|                 .then(response => response.json()) | ||||
|                 .then(data => { | ||||
|                     document.getElementById("client-name").textContent = data.username; | ||||
|                     document.getElementById("client-email").textContent = data.email; | ||||
|                     document.getElementById("client-phone").textContent = data.phone; | ||||
|                     modal.classList.remove("hidden"); | ||||
|                 }) | ||||
|                 .catch(err => console.error("Error fetching client data:", err)); | ||||
|         }); | ||||
|     }); | ||||
| 
 | ||||
|     // Закрытие модалки | ||||
|     closeModal.addEventListener("click", () => { | ||||
|         modal.classList.add("hidden"); | ||||
|     }); | ||||
| 
 | ||||
|     // Закрытие по клику вне модалки | ||||
|     modal.addEventListener("click", (e) => { | ||||
|         if (e.target === modal) { | ||||
|             modal.classList.add("hidden"); | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
| </script> | ||||
|  | @ -35,7 +35,12 @@ | |||
|                                     <div class="text-gray-600 text-xs whitespace-no-wrap">{{ job.job.job_id  }}</div> | ||||
|                                 </td> | ||||
|                                 <td class="text-center border-b">Company</td> | ||||
|                                 <td class="text-center border-b">{{job.client.username}}</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">Requested on</td> | ||||
|                                 <td class="text-center border-b">Posted on</td> | ||||
|                                 <td class="text-center border-b"> | ||||
|  | @ -66,52 +71,9 @@ | |||
|                     </table> | ||||
|                 </div> | ||||
|                 <!-- END: Datatable --> | ||||
| <!-- Включаем модалку --> | ||||
| <!-- Модальное окно --> | ||||
| {% include "modal.html" %} | ||||
| <script src="/static/dist/js/prod.js"></script> | ||||
| 
 | ||||
| 
 | ||||
| <script> | ||||
| function updateStatus(selectElement, jobId) { | ||||
|     let selectedStatus = selectElement.value; | ||||
| 
 | ||||
|     fetch('/update_status/', { | ||||
|         method: 'POST', | ||||
|         headers: { | ||||
|             'Content-Type': 'application/json', | ||||
|         }, | ||||
|         body: JSON.stringify({ | ||||
|             job_id: jobId, | ||||
|             status: selectedStatus | ||||
|         }) | ||||
|     }) | ||||
|     .then(response => response.json()) | ||||
|     .then(data => { | ||||
|         console.log('Успешно обновлено:', data); | ||||
|     }) | ||||
|     .catch(error => { | ||||
|         console.error('Ошибка:', error); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| function updateAssignee(selectElement, jobId) { | ||||
|     let selectedUserId = selectElement.value; | ||||
| 
 | ||||
|     fetch('/update_assignee/', { | ||||
|         method: 'POST', | ||||
|         headers: { | ||||
|             'Content-Type': 'application/json', | ||||
|         }, | ||||
|         body: JSON.stringify({ | ||||
|             job_id: jobId, | ||||
|             assignee_id: selectedUserId | ||||
|         }) | ||||
|     }) | ||||
|     .then(response => response.json()) | ||||
|     .then(data => { | ||||
|         console.log('Успешно обновлено:', data); | ||||
|     }) | ||||
|     .catch(error => { | ||||
|         console.error('Ошибка:', error); | ||||
|     }); | ||||
| } | ||||
| </script> | ||||
| {% endblock %} | ||||
		Loading…
	
		Reference in New Issue