Compare commits
7 Commits
Author | SHA1 | Date |
---|---|---|
mpabi | 63085c2d32 | |
mpabi | d5d251a738 | |
mpabi | 0b77052943 | |
mpabi | ef2db25b0b | |
mpabi | 0363e941b1 | |
mpabi | 5a45abc524 | |
mpabi | 2ed560f13a |
|
@ -0,0 +1,110 @@
|
||||||
|
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,3 +161,165 @@ 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,3 +24,11 @@ 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,21 +1,28 @@
|
||||||
# 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 app.database import SessionLocal
|
from typing import List, Optional
|
||||||
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")
|
||||||
|
|
||||||
# Dependency to get DB session
|
models.Base.metadata.create_all(bind=engine)
|
||||||
|
|
||||||
def get_db():
|
def get_db():
|
||||||
db = SessionLocal()
|
db = SessionLocal()
|
||||||
try:
|
try:
|
||||||
|
@ -23,24 +30,18 @@ def get_db():
|
||||||
finally:
|
finally:
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
class PassportDataRequest(BaseModel):
|
@app.post("/passport/", response_model=schemas.PassportData)
|
||||||
number: str
|
def create_passport_data(passport_data: schemas.PassportDataCreate, db: Session = Depends(get_db)):
|
||||||
name: str
|
db_passport_data = models.PassportData(**passport_data.dict())
|
||||||
surname: str
|
db.add(db_passport_data)
|
||||||
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)
|
db.refresh(db_passport_data)
|
||||||
return db_passport
|
return db_passport_data
|
||||||
|
|
||||||
@app.get("/passport_data/{passport_number}")
|
@app.get("/passport/{passport_number}", response_model=schemas.PassportData)
|
||||||
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 = db.query(PassportData).filter(PassportData.number == passport_number).first()
|
db_passport_data = db.query(models.PassportData).filter(models.PassportData.number == passport_number).first()
|
||||||
if db_passport is None:
|
if db_passport_data is None:
|
||||||
raise HTTPException(status_code=404, detail="Passport data not found")
|
raise HTTPException(status_code=404, detail="Passport data not found")
|
||||||
return db_passport
|
return schemas.PassportData.from_orm(db_passport_data)
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
# app/models.py
|
# app/models.py
|
||||||
from sqlalchemy import Column, Integer, String, ForeignKey
|
from sqlalchemy import Column, Integer, String
|
||||||
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=False)
|
name = Column(String(255), nullable=True)
|
||||||
surname = Column(String(255), nullable=False)
|
surname = Column(String(255), nullable=True)
|
||||||
gender = Column(String(255), nullable=False)
|
gender = Column(String(255), nullable=True)
|
||||||
|
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
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# 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,25 +1,76 @@
|
||||||
from app.database import engine
|
# entrypoint.py
|
||||||
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):
|
#%%
|
||||||
# Create the database
|
def load_data_from_directory(directory_path: str, db_session):
|
||||||
|
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.")
|
||||||
|
|
||||||
# Run the FastAPI app using uvicorn
|
db_session = SessionLocal()
|
||||||
|
try:
|
||||||
|
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)
|
# 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")
|
||||||
# Parse arguments
|
parser.add_argument("--data-dir", type=str, default="data", help="Directory containing passport data files")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
main(args.port)
|
main(args.port, args.data_dir)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
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.
After Width: | Height: | Size: 41 KiB |
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
After Width: | Height: | Size: 50 KiB |
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
|
@ -3,38 +3,14 @@
|
||||||
<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>Library Management</title>
|
<title>Passport Form App</title>
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="./style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>Library Management</header>
|
|
||||||
<div class="container">
|
<div id="app"></div>
|
||||||
<aside class="sidebar">
|
<script src="./js/axios.min.js"></script>
|
||||||
<h2>Add Author</h2>
|
<script type="module" src="./script.js"></script>
|
||||||
<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,69 +1,16 @@
|
||||||
const BASE_URL = 'http://qstack.pl:1111'; // Zaktualizuj zgodnie z konfiguracją Twojego serwera
|
import { createApp } from './js/vue.esm-browser.js';
|
||||||
|
import PassportForm from './components/Tabs.js';
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
const App = {
|
||||||
loadAuthors();
|
name: 'App',
|
||||||
loadBooks();
|
components: {
|
||||||
});
|
PassportForm
|
||||||
|
},
|
||||||
document.getElementById('addAuthorForm').addEventListener('submit', function(e) {
|
template: `
|
||||||
e.preventDefault();
|
<div id="app">
|
||||||
const authorName = document.getElementById('authorName').value;
|
<PassportForm />
|
||||||
fetch(`${BASE_URL}/authors/`, {
|
</div>
|
||||||
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,43 +1,33 @@
|
||||||
body, html {
|
.passport-form {
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
header, footer {
|
|
||||||
background-color: #333;
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
padding: 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
min-height: calc(100vh - 100px); /* Adjust based on header/footer height */
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.form-container {
|
||||||
width: 30%;
|
display: flex;
|
||||||
padding: 20px;
|
flex-direction: column;
|
||||||
background-color: #f4f4f4;
|
align-items: flex-start;
|
||||||
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.form-field {
|
||||||
flex-grow: 1;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
form > * {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
.form-field label {
|
||||||
cursor: pointer;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
.images-container {
|
||||||
list-style-type: none;
|
display: flex;
|
||||||
padding-left: 0;
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.images-container img {
|
||||||
|
max-width: 200px;
|
||||||
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue