mirror of
https://github.com/Sudo-JHare/FhirPad.git
synced 2025-06-15 20:49:59 +00:00
Add files via upload
This commit is contained in:
parent
a2b827d02f
commit
bb7016cb8e
@ -8,4 +8,4 @@ COPY instance/ instance/
|
||||
COPY config.py .
|
||||
COPY .env .
|
||||
EXPOSE 5009
|
||||
CMD ["flask", "run", "--host=0.0.0.0" "--port=5009"]
|
||||
CMD ["flask", "run", "--host=0.0.0.0", "--port=5009"]
|
10
app/forms.py
10
app/forms.py
@ -1,5 +1,5 @@
|
||||
from flask_wtf import FlaskForm
|
||||
from flask_wtf.file import FileField, FileAllowed
|
||||
from flask_wtf.file import FileField, FileAllowed, MultipleFileField
|
||||
from wtforms import StringField, TextAreaField, SubmitField, PasswordField, SelectField, SelectMultipleField, BooleanField
|
||||
from wtforms.validators import DataRequired, Email, Length, EqualTo, Optional, ValidationError
|
||||
import re
|
||||
@ -9,10 +9,12 @@ from app import db
|
||||
def validate_url_or_path(form, field):
|
||||
if not field.data:
|
||||
return
|
||||
if field.data.startswith('/app/uploads/'):
|
||||
path_pattern = r'^/app/uploads/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}_[\w\-\.]+\.(jpg|png)$'
|
||||
# Allow upload paths like /uploads/<uuid>_<filename>.jpg|png
|
||||
if field.data.startswith('/uploads/'):
|
||||
path_pattern = r'^/uploads/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}_[\w\-\.]+\.(jpg|png)$'
|
||||
if re.match(path_pattern, field.data, re.I):
|
||||
return
|
||||
# Allow external URLs
|
||||
url_pattern = r'^(https?:\/\/)?([\w\-]+\.)+[\w\-]+(\/[\w\-\.]*)*\/?(\?[^\s]*)?(#[^\s]*)?$'
|
||||
if not re.match(url_pattern, field.data):
|
||||
raise ValidationError('Invalid URL or file path.')
|
||||
@ -44,7 +46,7 @@ class FHIRAppForm(FlaskForm):
|
||||
licensing_pricing = SelectField('Licensing & Pricing', coerce=int, validators=[DataRequired()])
|
||||
os_support = SelectMultipleField('OS Support', coerce=int, validators=[DataRequired()])
|
||||
app_image_urls = TextAreaField('App Image URLs (one per line)', validators=[Optional(), Length(max=1000)], render_kw={"placeholder": "e.g., https://example.com/image1.png"})
|
||||
app_image_uploads = FileField('Upload App Images', validators=[FileAllowed(['jpg', 'png'], 'Images only!')])
|
||||
app_image_uploads = MultipleFileField('Upload App Images', validators=[FileAllowed(['jpg', 'png'], 'Images only!')])
|
||||
submit = SubmitField('Register App')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -154,25 +154,24 @@ def register():
|
||||
if form.app_image_urls.data:
|
||||
app_images.extend([url.strip() for url in form.app_image_urls.data.splitlines() if url.strip().startswith(('http://', 'https://'))])
|
||||
if form.app_image_uploads.data:
|
||||
file = form.app_image_uploads.data
|
||||
if file and allowed_file(file.filename):
|
||||
filename = secure_filename(f"{uuid.uuid4()}_{file.filename}")
|
||||
(my apologies, I did not mean to interrupt you, please go ahead and continue.
|
||||
save_path = os.path.join(UPLOAD_FOLDER, filename)
|
||||
logger.debug(f"Attempting to save app image to {save_path}")
|
||||
try:
|
||||
file.save(save_path)
|
||||
if os.path.exists(save_path):
|
||||
logger.debug(f"Successfully saved app image to {save_path}")
|
||||
else:
|
||||
logger.error(f"Failed to save app image to {save_path}")
|
||||
flash('Failed to save app image.', 'danger')
|
||||
for file in form.app_image_uploads.data:
|
||||
if file and allowed_file(file.filename):
|
||||
filename = secure_filename(f"{uuid.uuid4()}_{file.filename}")
|
||||
save_path = os.path.join(UPLOAD_FOLDER, filename)
|
||||
logger.debug(f"Attempting to save app image to {save_path}")
|
||||
try:
|
||||
file.save(save_path)
|
||||
if os.path.exists(save_path):
|
||||
logger.debug(f"Successfully saved app image to {save_path}")
|
||||
else:
|
||||
logger.error(f"Failed to save app image to {save_path}")
|
||||
flash('Failed to save app image.', 'danger')
|
||||
return render_template('register.html', form=form)
|
||||
app_images.append(f"/uploads/{filename}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error saving app image to {save_path}: {e}")
|
||||
flash('Error saving app image.', 'danger')
|
||||
return render_template('register.html', form=form)
|
||||
app_images.append(f"/uploads/{filename}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error saving app image to {save_path}: {e}")
|
||||
flash('Error saving app image.', 'danger')
|
||||
return render_template('register.html', form=form)
|
||||
|
||||
app = FHIRApp(
|
||||
name=form.name.data,
|
||||
@ -258,24 +257,24 @@ def edit_app(app_id):
|
||||
|
||||
app_images = [url.strip() for url in form.app_image_urls.data.splitlines() if url.strip()]
|
||||
if form.app_image_uploads.data:
|
||||
file = form.app_image_uploads.data
|
||||
if file and allowed_file(file.filename):
|
||||
filename = secure_filename(f"{uuid.uuid4()}_{file.filename}")
|
||||
save_path = os.path.join(UPLOAD_FOLDER, filename)
|
||||
logger.debug(f"Attempting to save updated app image to {save_path}")
|
||||
try:
|
||||
file.save(save_path)
|
||||
if os.path.exists(save_path):
|
||||
logger.debug(f"Successfully saved updated app image to {save_path}")
|
||||
else:
|
||||
logger.error(f"Failed to save updated app image to {save_path}")
|
||||
flash('Failed to save app image.', 'danger')
|
||||
for file in form.app_image_uploads.data:
|
||||
if file and allowed_file(file.filename):
|
||||
filename = secure_filename(f"{uuid.uuid4()}_{file.filename}")
|
||||
save_path = os.path.join(UPLOAD_FOLDER, filename)
|
||||
logger.debug(f"Attempting to save updated app image to {save_path}")
|
||||
try:
|
||||
file.save(save_path)
|
||||
if os.path.exists(save_path):
|
||||
logger.debug(f"Successfully saved updated app image to {save_path}")
|
||||
else:
|
||||
logger.error(f"Failed to save updated app image to {save_path}")
|
||||
flash('Failed to save app image.', 'danger')
|
||||
return render_template('edit_app.html', form=form, app=app)
|
||||
app_images.append(f"/uploads/{filename}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error saving updated app image to {save_path}: {e}")
|
||||
flash('Error saving app image.', 'danger')
|
||||
return render_template('edit_app.html', form=form, app=app)
|
||||
app_images.append(f"/uploads/{filename}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error saving updated app image to {save_path}: {e}")
|
||||
flash('Error saving app image.', 'danger')
|
||||
return render_template('edit_app.html', form=form, app=app)
|
||||
|
||||
app.name = form.name.data
|
||||
app.description = form.description.data
|
||||
|
@ -114,7 +114,8 @@
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
{{ form.app_image_uploads.label(class="form-label") }}
|
||||
{{ form.app_image_uploads(class="form-control") }}
|
||||
{{ form.app_image_uploads(class="form-control", multiple=True) }}
|
||||
<small class="form-text text-muted">Select multiple images to upload.</small>
|
||||
{% for error in form.app_image_uploads.errors %}
|
||||
<span class="text-danger">{{ error }}</span>
|
||||
{% endfor %}
|
||||
|
@ -124,7 +124,7 @@
|
||||
<div class="app-item col-md-4 mb-3" style="animation: fadeIn 0.5s;">
|
||||
<div class="card app-card shadow-sm h-100">
|
||||
{% if app.logo_url %}
|
||||
<img src="{{ app.logo_url }}" class="card-img-top" alt="{{ app.name }} logo" style="max-height: 150px; object-fit: contain; padding: 1rem;" onerror="this.style.display='none';">
|
||||
<img src="{{ app.logo_url }}" class="card-img-top" alt="{{ app.name }} logo" style="max-height: 150px; object-fit: contain; padding: 1rem;" onerror="this.src='https://via.placeholder.com/150?text=No+Logo';">
|
||||
{% else %}
|
||||
<img src="https://via.placeholder.com/150?text=No+Logo" class="card-img-top" alt="No Logo" style="max-height: 150px; object-fit: contain; padding: 1rem;">
|
||||
{% endif %}
|
||||
@ -132,6 +132,14 @@
|
||||
<h5 class="card-title">{{ app.name }}</h5>
|
||||
<p class="card-text flex-grow-1">{{ app.description | truncate(100) }}</p>
|
||||
<p class="card-text"><small class="text-muted">By {{ app.developer }}</small></p>
|
||||
<div class="d-flex flex-wrap gap-2 mb-2">
|
||||
{% if app.website %}
|
||||
<a href="{{ app.website }}" class="btn btn-primary btn-sm" aria-label="Visit {{ app.name }} website">Website</a>
|
||||
{% endif %}
|
||||
{% if app.launch_url %}
|
||||
<a href="{{ app.launch_url }}" class="btn btn-outline-primary btn-sm" aria-label="Try {{ app.name }} with sandbox data">Try App</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<a href="{{ url_for('gallery.app_detail', app_id=app.id) }}" class="btn btn-primary mt-auto">View Details</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -18,7 +18,7 @@
|
||||
<div class="col-md-4 mb-3">
|
||||
<div class="card app-card shadow-sm h-100">
|
||||
{% if app.logo_url %}
|
||||
<img src="{{ app.logo_url }}" class="card-img-top" alt="{{ app.name }} logo" style="max-height: 150px; object-fit: contain; padding: 1rem;">
|
||||
<img src="{{ app.logo_url }}" class="card-img-top" alt="{{ app.name }} logo" style="max-height: 150px; object-fit: contain; padding: 1rem;" onerror="this.src='https://via.placeholder.com/150?text=No+Logo';">
|
||||
{% else %}
|
||||
<img src="https://via.placeholder.com/150?text=No+Logo" class="card-img-top" alt="No Logo" style="max-height: 150px; object-fit: contain; padding: 1rem;">
|
||||
{% endif %}
|
||||
@ -26,6 +26,14 @@
|
||||
<h5 class="card-title">{{ app.name }}</h5>
|
||||
<p class="card-text flex-grow-1">{{ app.description | truncate(100) }}</p>
|
||||
<p class="card-text"><small class="text-muted">By {{ app.developer }}</small></p>
|
||||
<div class="d-flex flex-wrap gap-2 mb-2">
|
||||
{% if app.website %}
|
||||
<a href="{{ app.website }}" class="btn btn-primary btn-sm" aria-label="Visit {{ app.name }} website">Website</a>
|
||||
{% endif %}
|
||||
{% if app.launch_url %}
|
||||
<a href="{{ app.launch_url }}" class="btn btn-outline-primary btn-sm" aria-label="Try {{ app.name }} with sandbox data">Try App</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<a href="{{ url_for('gallery.app_detail', app_id=app.id) }}" class="btn btn-primary mt-auto">View Details</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -10,4 +10,4 @@ services:
|
||||
environment:
|
||||
- FLASK_APP=app
|
||||
- FLASK_ENV=development
|
||||
command: ["flask", "run", "--host=0.0.0.0"]
|
||||
command: ["flask", "run", "--host=0.0.0.0", "--port=5009"]
|
Loading…
x
Reference in New Issue
Block a user