Compare commits

..

No commits in common. "step4" and "api" have entirely different histories.
step4 ... api

17 changed files with 184 additions and 461 deletions

View File

@ -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())

View File

@ -161,165 +161,3 @@ xmap <c-c><c-c> <Plug>SlimeRegionSend
nmap <c-c><c-c> :<c-u>call SendCell('^#%%')<cr>
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>

View File

@ -24,11 +24,3 @@ from sqlalchemy import text
with engine.connect() as conn:
result = conn.execute(text("select 'hello world'"))
print(result.all())
#%%
with engine.connect() as conn:
result = conn.execute(text("show tables;"))
#%%
for row in result.fetchall():
print(row)

View File

@ -1,28 +1,21 @@
# app/main.py
# ---
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
from sqlalchemy.orm import Session
from app.database import SessionLocal, engine
from app import models, schemas
from typing import List, Optional
# 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 app.database import SessionLocal
from app.models import PassportData
from fastapi.staticfiles import StaticFiles
from typing import List, Optional
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
models.Base.metadata.create_all(bind=engine)
# Dependency to get DB session
def get_db():
db = SessionLocal()
try:
@ -30,18 +23,24 @@ def get_db():
finally:
db.close()
@app.post("/passport/", response_model=schemas.PassportData)
def create_passport_data(passport_data: schemas.PassportDataCreate, db: Session = Depends(get_db)):
db_passport_data = models.PassportData(**passport_data.dict())
db.add(db_passport_data)
class PassportDataRequest(BaseModel):
number: str
name: str
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.refresh(db_passport_data)
return db_passport_data
db.refresh(db_passport)
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)):
db_passport_data = db.query(models.PassportData).filter(models.PassportData.number == passport_number).first()
if db_passport_data is None:
db_passport = db.query(PassportData).filter(PassportData.number == passport_number).first()
if db_passport is None:
raise HTTPException(status_code=404, detail="Passport data not found")
return schemas.PassportData.from_orm(db_passport_data)
return db_passport

View File

@ -1,13 +1,13 @@
# 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
class PassportData(Base):
__tablename__ = 'passport_data'
id = Column(Integer, primary_key=True, autoincrement=True)
number = Column(String(255), unique=True, nullable=False)
name = Column(String(255), nullable=True)
surname = Column(String(255), nullable=True)
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
name = Column(String(255), nullable=False)
surname = Column(String(255), nullable=False)
gender = Column(String(255), nullable=False)

View File

@ -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

View File

@ -1,76 +1,25 @@
# entrypoint.py
#%%
from app.database import engine, SessionLocal
from app.models import Base, PassportData
from app.database import engine
from app.models import Base
import argparse
import uvicorn
import os
#%%
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):
def main(port):
# Create the database
print("Creating database tables...")
Base.metadata.create_all(bind=engine)
print("Database tables created.")
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()
# Run the FastAPI app using uvicorn
# uvicorn.run("app.main:app", host="0.0.0.0", port=port, reload=True)
#%% main(9999,"data")
#%%
if __name__ == "__main__":
# Create argument parser
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("--data-dir", type=str, default="data", help="Directory containing passport data files")
# Parse arguments
args = parser.parse_args()
main(args.port, args.data_dir)
main(args.port)

View File

@ -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

View File

@ -3,14 +3,38 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Passport Form App</title>
<link rel="stylesheet" href="./style.css">
<title>Library Management</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="app"></div>
<script src="./js/axios.min.js"></script>
<script type="module" src="./script.js"></script>
<header>Library Management</header>
<div class="container">
<aside class="sidebar">
<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>
</html>

View File

@ -1,16 +1,69 @@
import { createApp } from './js/vue.esm-browser.js';
import PassportForm from './components/Tabs.js';
const BASE_URL = 'http://qstack.pl:1111'; // Zaktualizuj zgodnie z konfiguracją Twojego serwera
const App = {
name: 'App',
components: {
PassportForm
},
template: `
<div id="app">
<PassportForm />
</div>
`,
};
document.addEventListener('DOMContentLoaded', function() {
loadAuthors();
loadBooks();
});
document.getElementById('addAuthorForm').addEventListener('submit', function(e) {
e.preventDefault();
const authorName = document.getElementById('authorName').value;
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');

View File

@ -1,33 +1,43 @@
.passport-form {
display: flex;
justify-content: center;
align-items: flex-start;
margin-top: 20px;
body, html {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
.form-container {
display: flex;
flex-direction: column;
align-items: flex-start;
margin-right: 20px;
header, footer {
background-color: #333;
color: #fff;
text-align: center;
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;
}
.form-field label {
margin-right: 10px;
button {
cursor: pointer;
}
.images-container {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.images-container img {
max-width: 200px;
margin-bottom: 10px;
ul {
list-style-type: none;
padding-left: 0;
}