Compare commits
No commits in common. "step4" and "api" have entirely different histories.
110
py6/app.py
110
py6/app.py
|
@ -1,110 +0,0 @@
|
||||||
import sys
|
|
||||||
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QFormLayout, QLineEdit, QPushButton, QLabel, QMessageBox, QFileDialog)
|
|
||||||
from PySide6.QtCore import Qt
|
|
||||||
from PySide6.QtGui import QPixmap
|
|
||||||
import requests
|
|
||||||
|
|
||||||
class PassportForm(QWidget):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
self.setWindowTitle("PAssportForms")
|
|
||||||
|
|
||||||
self.main_layout = QHBoxLayout()
|
|
||||||
self.form_layout = QVBoxLayout()
|
|
||||||
self.data_layout = QFormLayout()
|
|
||||||
|
|
||||||
self.number_input = QLineEdit()
|
|
||||||
self.name_input = QLineEdit()
|
|
||||||
self.surname_input = QLineEdit()
|
|
||||||
self.gender_input = QLineEdit()
|
|
||||||
self.fingerprint_url_input = QLineEdit()
|
|
||||||
self.photo_url_input = QLineEdit()
|
|
||||||
|
|
||||||
self.data_layout.addRow("Passport Number", self.number_input)
|
|
||||||
self.data_layout.addRow("Name", self.name_input)
|
|
||||||
self.data_layout.addRow("Surname", self.surname_input)
|
|
||||||
self.data_layout.addRow("Gender", self.gender_input)
|
|
||||||
self.data_layout.addRow("Fingerprint URL", self.fingerprint_url_input)
|
|
||||||
self.data_layout.addRow("Photo URL", self.photo_url_input)
|
|
||||||
|
|
||||||
self.load_button = QPushButton("Load Data")
|
|
||||||
self.load_button.clicked.connect(self.load_data)
|
|
||||||
|
|
||||||
self.submit_button = QPushButton("Submit")
|
|
||||||
self.submit_button.clicked.connect(self.submit_form)
|
|
||||||
|
|
||||||
self.form_layout.addLayout(self.data_layout)
|
|
||||||
self.form_layout.addWidget(self.load_button)
|
|
||||||
self.form_layout.addWidget(self.submit_button)
|
|
||||||
|
|
||||||
self.image_layout = QVBoxLayout()
|
|
||||||
|
|
||||||
self.photo_label = QLabel("Photo")
|
|
||||||
self.photo_label.setFixedSize(200, 200)
|
|
||||||
self.photo_label.setStyleSheet("border: 1px solid black;")
|
|
||||||
self.photo_label.setAlignment(Qt.AlignCenter)
|
|
||||||
|
|
||||||
self.fingerprint_label = QLabel("Fingerprint")
|
|
||||||
self.fingerprint_label.setFixedSize(200, 200)
|
|
||||||
self.fingerprint_label.setStyleSheet("border: 1px solid black;")
|
|
||||||
self.fingerprint_label.setAlignment(Qt.AlignCenter)
|
|
||||||
|
|
||||||
self.image_layout.addWidget(self.photo_label)
|
|
||||||
self.image_layout.addWidget(self.fingerprint_label)
|
|
||||||
|
|
||||||
self.main_layout.addLayout(self.form_layout)
|
|
||||||
self.main_layout.addLayout(self.image_layout)
|
|
||||||
|
|
||||||
self.setLayout(self.main_layout)
|
|
||||||
|
|
||||||
def load_data(self):
|
|
||||||
passport_number = self.number_input.text()
|
|
||||||
response = requests.get(f"http://localhost:9999/passport/{passport_number}")
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
data = response.json()
|
|
||||||
self.name_input.setText(data['name'])
|
|
||||||
self.surname_input.setText(data['surname'])
|
|
||||||
self.gender_input.setText(data['gender'])
|
|
||||||
self.fingerprint_url_input.setText(data['fingerprint_url'])
|
|
||||||
self.photo_url_input.setText(data['photo_url'])
|
|
||||||
|
|
||||||
self.load_image(self.photo_label, f"http://localhost:9999/static/imgs/data/{passport_number}-zdjecie.jpg")
|
|
||||||
self.load_image(self.fingerprint_label, f"http://localhost:9999/static/imgs/data/{passport_number}-odcisk.jpg")
|
|
||||||
else:
|
|
||||||
QMessageBox.critical(self, "Error", "Failed to load passport data")
|
|
||||||
|
|
||||||
def load_image(self, label, url):
|
|
||||||
response = requests.get(url)
|
|
||||||
if response.status_code == 200:
|
|
||||||
pixmap = QPixmap()
|
|
||||||
pixmap.loadFromData(response.content)
|
|
||||||
label.setPixmap(pixmap.scaled(label.size(), Qt.KeepAspectRatio))
|
|
||||||
else:
|
|
||||||
label.setText("Image not found")
|
|
||||||
|
|
||||||
def submit_form(self):
|
|
||||||
passport_data = {
|
|
||||||
"number": self.number_input.text(),
|
|
||||||
"name": self.name_input.text(),
|
|
||||||
"surname": self.surname_input.text(),
|
|
||||||
"gender": self.gender_input.text(),
|
|
||||||
"fingerprint_url": self.fingerprint_url_input.text(),
|
|
||||||
"photo_url": self.photo_url_input.text()
|
|
||||||
}
|
|
||||||
|
|
||||||
response = requests.post("http://localhost:9999/passport/", json=passport_data)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
QMessageBox.information(self, "Success", "Passport data submitted successfully")
|
|
||||||
else:
|
|
||||||
QMessageBox.critical(self, "Error", "Failed to submit passport data")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app = QApplication(sys.argv)
|
|
||||||
window = PassportForm()
|
|
||||||
window.show()
|
|
||||||
sys.exit(app.exec())
|
|
||||||
|
|
|
@ -161,165 +161,3 @@ xmap <c-c><c-c> <Plug>SlimeRegionSend
|
||||||
nmap <c-c><c-c> :<c-u>call SendCell('^#%%')<cr>
|
nmap <c-c><c-c> :<c-u>call SendCell('^#%%')<cr>
|
||||||
nmap <c-c>v <Plug>SlimeConfig
|
nmap <c-c>v <Plug>SlimeConfig
|
||||||
|
|
||||||
" https://raw.githubusercontent.com/neoclide/coc.nvim/master/doc/coc-example-config.vim
|
|
||||||
|
|
||||||
" May need for Vim (not Neovim) since coc.nvim calculates byte offset by count
|
|
||||||
" utf-8 byte sequence
|
|
||||||
set encoding=utf-8
|
|
||||||
" Some servers have issues with backup files, see #649
|
|
||||||
set nobackup
|
|
||||||
set nowritebackup
|
|
||||||
|
|
||||||
" Having longer updatetime (default is 4000 ms = 4s) leads to noticeable
|
|
||||||
" delays and poor user experience
|
|
||||||
set updatetime=300
|
|
||||||
|
|
||||||
" Always show the signcolumn, otherwise it would shift the text each time
|
|
||||||
" diagnostics appear/become resolved
|
|
||||||
set signcolumn=yes
|
|
||||||
|
|
||||||
" Use tab for trigger completion with characters ahead and navigate
|
|
||||||
" NOTE: There's always complete item selected by default, you may want to enable
|
|
||||||
" no select by `"suggest.noselect": true` in your configuration file
|
|
||||||
" NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
|
|
||||||
" other plugin before putting this into your config
|
|
||||||
inoremap <silent><expr> <TAB>
|
|
||||||
\ coc#pum#visible() ? coc#pum#next(1) :
|
|
||||||
\ CheckBackspace() ? "\<Tab>" :
|
|
||||||
\ coc#refresh()
|
|
||||||
inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"
|
|
||||||
|
|
||||||
" Make <CR> to accept selected completion item or notify coc.nvim to format
|
|
||||||
" <C-g>u breaks current undo, please make your own choice
|
|
||||||
inoremap <silent><expr> <CR> coc#pum#visible() ? coc#pum#confirm()
|
|
||||||
\: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
|
|
||||||
|
|
||||||
function! CheckBackspace() abort
|
|
||||||
let col = col('.') - 1
|
|
||||||
return !col || getline('.')[col - 1] =~# '\s'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Use <c-space> to trigger completion
|
|
||||||
if has('nvim')
|
|
||||||
inoremap <silent><expr> <c-space> coc#refresh()
|
|
||||||
else
|
|
||||||
inoremap <silent><expr> <c-@> coc#refresh()
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Use `[g` and `]g` to navigate diagnostics
|
|
||||||
" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list
|
|
||||||
nmap <silent> [g <Plug>(coc-diagnostic-prev)
|
|
||||||
nmap <silent> ]g <Plug>(coc-diagnostic-next)
|
|
||||||
|
|
||||||
" GoTo code navigation
|
|
||||||
nmap <silent> gd <Plug>(coc-definition)
|
|
||||||
nmap <silent> gy <Plug>(coc-type-definition)
|
|
||||||
nmap <silent> gi <Plug>(coc-implementation)
|
|
||||||
nmap <silent> gr <Plug>(coc-references)
|
|
||||||
|
|
||||||
" Use K to show documentation in preview window
|
|
||||||
nnoremap <silent> K :call ShowDocumentation()<CR>
|
|
||||||
|
|
||||||
function! ShowDocumentation()
|
|
||||||
if CocAction('hasProvider', 'hover')
|
|
||||||
call CocActionAsync('doHover')
|
|
||||||
else
|
|
||||||
call feedkeys('K', 'in')
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Highlight the symbol and its references when holding the cursor
|
|
||||||
autocmd CursorHold * silent call CocActionAsync('highlight')
|
|
||||||
|
|
||||||
" Symbol renaming
|
|
||||||
nmap <leader>rn <Plug>(coc-rename)
|
|
||||||
|
|
||||||
" Formatting selected code
|
|
||||||
xmap <leader>f <Plug>(coc-format-selected)
|
|
||||||
nmap <leader>f <Plug>(coc-format-selected)
|
|
||||||
|
|
||||||
augroup mygroup
|
|
||||||
autocmd!
|
|
||||||
" Setup formatexpr specified filetype(s)
|
|
||||||
autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
|
|
||||||
" Update signature help on jump placeholder
|
|
||||||
autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
|
|
||||||
augroup end
|
|
||||||
|
|
||||||
" Applying code actions to the selected code block
|
|
||||||
" Example: `<leader>aap` for current paragraph
|
|
||||||
xmap <leader>a <Plug>(coc-codeaction-selected)
|
|
||||||
nmap <leader>a <Plug>(coc-codeaction-selected)
|
|
||||||
|
|
||||||
" Remap keys for applying code actions at the cursor position
|
|
||||||
nmap <leader>ac <Plug>(coc-codeaction-cursor)
|
|
||||||
" Remap keys for apply code actions affect whole buffer
|
|
||||||
nmap <leader>as <Plug>(coc-codeaction-source)
|
|
||||||
" Apply the most preferred quickfix action to fix diagnostic on the current line
|
|
||||||
nmap <leader>qf <Plug>(coc-fix-current)
|
|
||||||
|
|
||||||
" Remap keys for applying refactor code actions
|
|
||||||
nmap <silent> <leader>re <Plug>(coc-codeaction-refactor)
|
|
||||||
xmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)
|
|
||||||
nmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)
|
|
||||||
|
|
||||||
" Run the Code Lens action on the current line
|
|
||||||
nmap <leader>cl <Plug>(coc-codelens-action)
|
|
||||||
|
|
||||||
" Map function and class text objects
|
|
||||||
" NOTE: Requires 'textDocument.documentSymbol' support from the language server
|
|
||||||
xmap if <Plug>(coc-funcobj-i)
|
|
||||||
omap if <Plug>(coc-funcobj-i)
|
|
||||||
xmap af <Plug>(coc-funcobj-a)
|
|
||||||
omap af <Plug>(coc-funcobj-a)
|
|
||||||
xmap ic <Plug>(coc-classobj-i)
|
|
||||||
omap ic <Plug>(coc-classobj-i)
|
|
||||||
xmap ac <Plug>(coc-classobj-a)
|
|
||||||
omap ac <Plug>(coc-classobj-a)
|
|
||||||
|
|
||||||
" Remap <C-f> and <C-b> to scroll float windows/popups
|
|
||||||
if has('nvim-0.4.0') || has('patch-8.2.0750')
|
|
||||||
nnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
|
|
||||||
nnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
|
|
||||||
inoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(1)\<cr>" : "\<Right>"
|
|
||||||
inoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(0)\<cr>" : "\<Left>"
|
|
||||||
vnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
|
|
||||||
vnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Use CTRL-S for selections ranges
|
|
||||||
" Requires 'textDocument/selectionRange' support of language server
|
|
||||||
nmap <silent> <C-s> <Plug>(coc-range-select)
|
|
||||||
xmap <silent> <C-s> <Plug>(coc-range-select)
|
|
||||||
|
|
||||||
" Add `:Format` command to format current buffer
|
|
||||||
command! -nargs=0 Format :call CocActionAsync('format')
|
|
||||||
|
|
||||||
" Add `:Fold` command to fold current buffer
|
|
||||||
command! -nargs=? Fold :call CocAction('fold', <f-args>)
|
|
||||||
|
|
||||||
" Add `:OR` command for organize imports of the current buffer
|
|
||||||
command! -nargs=0 OR :call CocActionAsync('runCommand', 'editor.action.organizeImport')
|
|
||||||
|
|
||||||
" Add (Neo)Vim's native statusline support
|
|
||||||
" NOTE: Please see `:h coc-status` for integrations with external plugins that
|
|
||||||
" provide custom statusline: lightline.vim, vim-airline
|
|
||||||
set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}
|
|
||||||
|
|
||||||
" Mappings for CoCList
|
|
||||||
" Show all diagnostics
|
|
||||||
nnoremap <silent><nowait> <space>a :<C-u>CocList diagnostics<cr>
|
|
||||||
" Manage extensions
|
|
||||||
nnoremap <silent><nowait> <space>e :<C-u>CocList extensions<cr>
|
|
||||||
" Show commands
|
|
||||||
nnoremap <silent><nowait> <space>c :<C-u>CocList commands<cr>
|
|
||||||
" Find symbol of current document
|
|
||||||
nnoremap <silent><nowait> <space>o :<C-u>CocList outline<cr>
|
|
||||||
" Search workspace symbols
|
|
||||||
nnoremap <silent><nowait> <space>s :<C-u>CocList -I symbols<cr>
|
|
||||||
" Do default action for next item
|
|
||||||
nnoremap <silent><nowait> <space>j :<C-u>CocNext<CR>
|
|
||||||
" Do default action for previous item
|
|
||||||
nnoremap <silent><nowait> <space>k :<C-u>CocPrev<CR>
|
|
||||||
" Resume latest coc list
|
|
||||||
nnoremap <silent><nowait> <space>p :<C-u>CocListResume<CR>
|
|
||||||
|
|
|
@ -24,11 +24,3 @@ from sqlalchemy import text
|
||||||
with engine.connect() as conn:
|
with engine.connect() as conn:
|
||||||
result = conn.execute(text("select 'hello world'"))
|
result = conn.execute(text("select 'hello world'"))
|
||||||
print(result.all())
|
print(result.all())
|
||||||
|
|
||||||
#%%
|
|
||||||
with engine.connect() as conn:
|
|
||||||
result = conn.execute(text("show tables;"))
|
|
||||||
#%%
|
|
||||||
for row in result.fetchall():
|
|
||||||
print(row)
|
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,21 @@
|
||||||
# app/main.py
|
# app/main.py
|
||||||
|
|
||||||
|
# ---
|
||||||
|
|
||||||
from fastapi import FastAPI, HTTPException, Depends
|
from fastapi import FastAPI, HTTPException, Depends
|
||||||
|
from pydantic import BaseModel
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from app.database import SessionLocal, engine
|
|
||||||
from app import models, schemas
|
|
||||||
|
|
||||||
from typing import List, Optional
|
from app.database import SessionLocal
|
||||||
|
from app.models import PassportData
|
||||||
# ddfrom starlette.middleware.base import BaseHTTPMiddleware
|
|
||||||
# from starlette.responses import Response
|
|
||||||
|
|
||||||
# class CustomMIMEMiddleware(BaseHTTPMiddleware):
|
|
||||||
# async def dispatch(self, request, call_next):
|
|
||||||
# response = await call_next(request)
|
|
||||||
# if request.url.path.endswith('.vue'):
|
|
||||||
# response.headers['Content-Type'] = 'application/javascript'
|
|
||||||
# return response
|
|
||||||
|
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
app.mount("/static", StaticFiles(directory="static"), name="static")
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||||
|
|
||||||
models.Base.metadata.create_all(bind=engine)
|
# Dependency to get DB session
|
||||||
|
|
||||||
def get_db():
|
def get_db():
|
||||||
db = SessionLocal()
|
db = SessionLocal()
|
||||||
try:
|
try:
|
||||||
|
@ -30,18 +23,24 @@ def get_db():
|
||||||
finally:
|
finally:
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
@app.post("/passport/", response_model=schemas.PassportData)
|
class PassportDataRequest(BaseModel):
|
||||||
def create_passport_data(passport_data: schemas.PassportDataCreate, db: Session = Depends(get_db)):
|
number: str
|
||||||
db_passport_data = models.PassportData(**passport_data.dict())
|
name: str
|
||||||
db.add(db_passport_data)
|
surname: str
|
||||||
|
gender: str
|
||||||
|
|
||||||
|
@app.post("/passport_data/")
|
||||||
|
def create_passport_data(request: PassportDataRequest, db: Session = Depends(get_db)):
|
||||||
|
db_passport = PassportData(number=request.number, name=request.name, surname=request.surname, gender=request.gender)
|
||||||
|
db.add(db_passport)
|
||||||
db.commit()
|
db.commit()
|
||||||
db.refresh(db_passport_data)
|
db.refresh(db_passport)
|
||||||
return db_passport_data
|
return db_passport
|
||||||
|
|
||||||
@app.get("/passport/{passport_number}", response_model=schemas.PassportData)
|
@app.get("/passport_data/{passport_number}")
|
||||||
def read_passport_data(passport_number: str, db: Session = Depends(get_db)):
|
def read_passport_data(passport_number: str, db: Session = Depends(get_db)):
|
||||||
db_passport_data = db.query(models.PassportData).filter(models.PassportData.number == passport_number).first()
|
db_passport = db.query(PassportData).filter(PassportData.number == passport_number).first()
|
||||||
if db_passport_data is None:
|
if db_passport is None:
|
||||||
raise HTTPException(status_code=404, detail="Passport data not found")
|
raise HTTPException(status_code=404, detail="Passport data not found")
|
||||||
return schemas.PassportData.from_orm(db_passport_data)
|
return db_passport
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
# app/models.py
|
# app/models.py
|
||||||
from sqlalchemy import Column, Integer, String
|
from sqlalchemy import Column, Integer, String, ForeignKey
|
||||||
|
from sqlalchemy.orm import relationship
|
||||||
from app.database import Base
|
from app.database import Base
|
||||||
|
|
||||||
class PassportData(Base):
|
class PassportData(Base):
|
||||||
__tablename__ = 'passport_data'
|
__tablename__ = 'passport_data'
|
||||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
number = Column(String(255), unique=True, nullable=False)
|
number = Column(String(255), unique=True, nullable=False)
|
||||||
name = Column(String(255), nullable=True)
|
name = Column(String(255), nullable=False)
|
||||||
surname = Column(String(255), nullable=True)
|
surname = Column(String(255), nullable=False)
|
||||||
gender = Column(String(255), nullable=True)
|
gender = Column(String(255), nullable=False)
|
||||||
fingerprint_url = Column(String(255), nullable=True) # New field for fingerprint image URL
|
|
||||||
photo_url = Column(String(255), nullable=True) # New field for photo image URL
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
# app/schemas.py
|
|
||||||
from pydantic import BaseModel
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
class PassportDataBase(BaseModel):
|
|
||||||
number: str
|
|
||||||
name: Optional[str] = None
|
|
||||||
surname: Optional[str] = None
|
|
||||||
gender: Optional[str] = None
|
|
||||||
fingerprint_url: Optional[str] = None
|
|
||||||
photo_url: Optional[str] = None
|
|
||||||
|
|
||||||
class PassportDataCreate(PassportDataBase):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class PassportData(PassportDataBase):
|
|
||||||
id: int
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
orm_mode = True # Poprawne przypisanie
|
|
||||||
|
|
|
@ -1,76 +1,25 @@
|
||||||
# entrypoint.py
|
from app.database import engine
|
||||||
#%%
|
from app.models import Base
|
||||||
from app.database import engine, SessionLocal
|
|
||||||
from app.models import Base, PassportData
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
import uvicorn
|
import uvicorn
|
||||||
import os
|
|
||||||
|
|
||||||
#%%
|
def main(port):
|
||||||
def load_data_from_directory(directory_path: str, db_session):
|
# Create the database
|
||||||
files = os.listdir(directory_path)
|
|
||||||
passport_data = {}
|
|
||||||
|
|
||||||
for file in files:
|
|
||||||
file_parts = file.split('-')
|
|
||||||
if len(file_parts) != 2:
|
|
||||||
continue
|
|
||||||
|
|
||||||
passport_number = file_parts[0]
|
|
||||||
file_type = file_parts[1].split('.')[0]
|
|
||||||
|
|
||||||
if passport_number not in passport_data:
|
|
||||||
passport_data[passport_number] = {
|
|
||||||
"fingerprint_url": None,
|
|
||||||
"photo_url": None
|
|
||||||
}
|
|
||||||
|
|
||||||
file_path = os.path.join(directory_path, file)
|
|
||||||
if file_type == 'odcisk':
|
|
||||||
passport_data[passport_number]["fingerprint_url"] = file_path
|
|
||||||
elif file_type == 'zdjecie':
|
|
||||||
passport_data[passport_number]["photo_url"] = file_path
|
|
||||||
|
|
||||||
for number, data in passport_data.items():
|
|
||||||
passport_entry = PassportData(
|
|
||||||
number=number,
|
|
||||||
name=None,
|
|
||||||
surname=None,
|
|
||||||
gender=None,
|
|
||||||
fingerprint_url=data["fingerprint_url"],
|
|
||||||
photo_url=data["photo_url"]
|
|
||||||
)
|
|
||||||
db_session.add(passport_entry)
|
|
||||||
print (passport_entry)
|
|
||||||
db_session.commit()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#%%
|
|
||||||
def main(port, data_dir):
|
|
||||||
print("Creating database tables...")
|
print("Creating database tables...")
|
||||||
Base.metadata.create_all(bind=engine)
|
Base.metadata.create_all(bind=engine)
|
||||||
print("Database tables created.")
|
print("Database tables created.")
|
||||||
|
|
||||||
db_session = SessionLocal()
|
# Run the FastAPI app using uvicorn
|
||||||
try:
|
# uvicorn.run("app.main:app", host="0.0.0.0", port=port, reload=True)
|
||||||
print(f"Loading data from directory: {data_dir}")
|
|
||||||
load_data_from_directory(data_dir, db_session)
|
|
||||||
print("Data loaded into database.")
|
|
||||||
finally:
|
|
||||||
db_session.close()
|
|
||||||
|
|
||||||
# uvicorn.run("app.main:app", host="0.0.0.0", port=port, reload=True)
|
|
||||||
|
|
||||||
#%% main(9999,"data")
|
|
||||||
|
|
||||||
|
|
||||||
#%%
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
# Create argument parser
|
||||||
parser = argparse.ArgumentParser(description="Run the FastAPI app")
|
parser = argparse.ArgumentParser(description="Run the FastAPI app")
|
||||||
|
# Add port argument, default is 9999
|
||||||
parser.add_argument("--port", type=int, default=9999, help="Port to run the FastAPI app on")
|
parser.add_argument("--port", type=int, default=9999, help="Port to run the FastAPI app on")
|
||||||
parser.add_argument("--data-dir", type=str, default="data", help="Directory containing passport data files")
|
# Parse arguments
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
main(args.port, args.data_dir)
|
main(args.port)
|
||||||
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
curl -X POST "http://localhost:9999/passport/" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"number": "444",
|
|
||||||
"name": null,
|
|
||||||
"surname": null,
|
|
||||||
"gender": null,
|
|
||||||
"fingerprint_url": "data/444-odcisk.jpg",
|
|
||||||
"photo_url": "data/444-zdjecie.jpg"
|
|
||||||
}'
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 41 KiB |
Binary file not shown.
Before Width: | Height: | Size: 18 KiB |
Binary file not shown.
Before Width: | Height: | Size: 46 KiB |
Binary file not shown.
Before Width: | Height: | Size: 18 KiB |
Binary file not shown.
Before Width: | Height: | Size: 50 KiB |
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
|
@ -3,14 +3,38 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Passport Form App</title>
|
<title>Library Management</title>
|
||||||
<link rel="stylesheet" href="./style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<header>Library Management</header>
|
||||||
<div id="app"></div>
|
<div class="container">
|
||||||
<script src="./js/axios.min.js"></script>
|
<aside class="sidebar">
|
||||||
<script type="module" src="./script.js"></script>
|
<h2>Add Author</h2>
|
||||||
|
<form id="addAuthorForm">
|
||||||
|
<input type="text" id="authorName" placeholder="Author Name" required>
|
||||||
|
<button type="submit">Add Author</button>
|
||||||
|
</form>
|
||||||
|
<h2>Add Book</h2>
|
||||||
|
<form id="addBookForm">
|
||||||
|
<input type="text" id="bookTitle" placeholder="Book Title" required>
|
||||||
|
<select id="bookAuthorId">
|
||||||
|
<!-- Autorzy będą dodawani tutaj dynamicznie -->
|
||||||
|
</select>
|
||||||
|
<button type="submit">Add Book</button>
|
||||||
|
</form>
|
||||||
|
</aside>
|
||||||
|
<main class="content">
|
||||||
|
<h2>Authors</h2>
|
||||||
|
<ul id="authorsList"></ul>
|
||||||
|
<h2>Books</h2>
|
||||||
|
<ul id="booksList"></ul>
|
||||||
|
<button id="loadBooksWithAuthors">Load Books with Authors</button>
|
||||||
|
<ul id="booksWithAuthorsList"></ul>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
<footer>2024 Library Management System</footer>
|
||||||
|
<script src="script.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,69 @@
|
||||||
import { createApp } from './js/vue.esm-browser.js';
|
const BASE_URL = 'http://qstack.pl:1111'; // Zaktualizuj zgodnie z konfiguracją Twojego serwera
|
||||||
import PassportForm from './components/Tabs.js';
|
|
||||||
|
|
||||||
const App = {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
name: 'App',
|
loadAuthors();
|
||||||
components: {
|
loadBooks();
|
||||||
PassportForm
|
});
|
||||||
},
|
|
||||||
template: `
|
document.getElementById('addAuthorForm').addEventListener('submit', function(e) {
|
||||||
<div id="app">
|
e.preventDefault();
|
||||||
<PassportForm />
|
const authorName = document.getElementById('authorName').value;
|
||||||
</div>
|
fetch(`${BASE_URL}/authors/`, {
|
||||||
`,
|
method: 'POST',
|
||||||
};
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ name: authorName }),
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(() => {
|
||||||
|
loadAuthors(); // Ponowne ładowanie listy autorów po dodaniu nowego autora
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error:', error));
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('addBookForm').addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const bookTitle = document.getElementById('bookTitle').value;
|
||||||
|
const bookAuthorId = document.getElementById('bookAuthorId').value;
|
||||||
|
fetch(`${BASE_URL}/books/`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ title: bookTitle, author_id: parseInt(bookAuthorId, 10) }),
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(() => {
|
||||||
|
loadBooks(); // Ponowne ładowanie listy książek po dodaniu nowej książki
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error:', error));
|
||||||
|
});
|
||||||
|
|
||||||
|
function loadAuthors() {
|
||||||
|
fetch(`${BASE_URL}/authors/`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
const authorsSelect = document.getElementById('bookAuthorId');
|
||||||
|
authorsSelect.innerHTML = '<option value="">Select an Author</option>'; // Dodaj domyślną opcję
|
||||||
|
data.forEach(author => {
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.value = author.id;
|
||||||
|
option.textContent = author.name;
|
||||||
|
authorsSelect.appendChild(option);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadBooks() {
|
||||||
|
fetch(`${BASE_URL}/books/`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
const booksList = document.getElementById('booksList');
|
||||||
|
booksList.innerHTML = '';
|
||||||
|
data.forEach(book => {
|
||||||
|
const listItem = document.createElement('li');
|
||||||
|
listItem.textContent = `${book.title} - Author ID: ${book.author_id}`;
|
||||||
|
booksList.appendChild(listItem);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error:', error));
|
||||||
|
}
|
||||||
|
|
||||||
createApp(App).mount('#app');
|
|
||||||
|
|
|
@ -1,33 +1,43 @@
|
||||||
.passport-form {
|
body, html {
|
||||||
display: flex;
|
margin: 0;
|
||||||
justify-content: center;
|
padding: 0;
|
||||||
align-items: flex-start;
|
font-family: Arial, sans-serif;
|
||||||
margin-top: 20px;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.form-container {
|
header, footer {
|
||||||
display: flex;
|
background-color: #333;
|
||||||
flex-direction: column;
|
color: #fff;
|
||||||
align-items: flex-start;
|
text-align: center;
|
||||||
margin-right: 20px;
|
padding: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-field {
|
.container {
|
||||||
|
display: flex;
|
||||||
|
min-height: calc(100vh - 100px); /* Adjust based on header/footer height */
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
width: 30%;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
flex-grow: 1;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form > * {
|
||||||
|
display: block;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-field label {
|
button {
|
||||||
margin-right: 10px;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.images-container {
|
ul {
|
||||||
display: flex;
|
list-style-type: none;
|
||||||
flex-direction: column;
|
padding-left: 0;
|
||||||
align-items: flex-start;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.images-container img {
|
|
||||||
max-width: 200px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue