Rewrite edit blocs and themes

This commit is contained in:
2026-03-28 12:20:30 +01:00
parent 48c5c31818
commit cdf1d439f5
32 changed files with 627 additions and 373 deletions

View File

@@ -1,14 +0,0 @@
HOST="fd01::2"
PORT="8000"
SECRET_KEY = "CHANGE-ME"
STATIC_PATH = './app/static/'
JSON_FILE = './ident.json'
IMAGES_PATH = ['/static/img/portfolio/']
IMAGES_CACHE = STATIC_PATH+'/img/cache/'
#Dossier privé des utilisateurs
USERS_FOLDER = "/home/kitoy/prog/mapageperso/users"
# Le dossiers où sont exporté les sites générer
PUBLIC_FOLDER = "/home/kitoy/prog/mapageperso/public"
DEFAULT_SITE="default"

View File

@@ -1,56 +1,45 @@
import re import re
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField from wtforms import StringField, PasswordField, BooleanField, ColorField
from wtforms import SubmitField, TextAreaField, FileField from wtforms import SubmitField, TextAreaField, FileField
from flask_wtf.file import FileField, FileAllowed, FileRequired from flask_wtf.file import FileField, FileAllowed, FileRequired
from wtforms import validators from wtforms import validators
from wtforms.validators import DataRequired, Length from wtforms.validators import DataRequired, Length
class Accueil(FlaskForm): class FormBloc(FlaskForm):
title = StringField('Titre', validators=[DataRequired()]) title = StringField('Titre', validators=[DataRequired()])
name = StringField('Nom du bloc', validators=[DataRequired()])
bg_color = ColorField('Couleur de fond', validators=[])
fg_color = ColorField('Couleur du texte', validators=[])
text = TextAreaField('Présentation', validators=[Length(min=0, max=1000)]) text = TextAreaField('Présentation', validators=[Length(min=0, max=1000)])
text_button = StringField('Texte du bouton', validators=[]) text_button = StringField('Texte du bouton', validators=[])
link = StringField('Lien', validators=[]) link = StringField('Lien', validators=[])
image = FileField('image', validators=[FileAllowed(['jpg', 'png', 'gif'], 'Images only!')]) image = FileField('image', validators=[FileAllowed(['jpg', 'png', 'gif'], 'Images only!')])
submit = SubmitField('Valider') email = StringField('Email', validators=[])
phone = StringField('Téléphone', validators=[])
class Description(FlaskForm): address = StringField('Addresse', validators=[])
title = StringField('Titre', validators=[DataRequired()]) postal_code = StringField('Code Postal', validators=[])
text = TextAreaField('Texte', validators=[DataRequired()]) city = StringField('Ville', validators=[])
submit = SubmitField('Valider')
class ImageForm(FlaskForm): class ImageForm(FlaskForm):
title = StringField('Titre', validators=[DataRequired()]) title = StringField('Titre', validators=[DataRequired()])
name = StringField('Nom du bloc', validators=[])
subtitle = StringField('Sous-titre',validators=[]) subtitle = StringField('Sous-titre',validators=[])
category = StringField('Categories',validators=[]) category = StringField('Categories',validators=[])
description = StringField('Description', validators=[]) description = StringField('Description', validators=[])
class ImageUpload(FlaskForm): class ImageUpload(FlaskForm):
name = StringField('Nom du bloc', validators=[])
title = StringField('Titre', validators=[DataRequired()]) title = StringField('Titre', validators=[DataRequired()])
subtitle = StringField('Sous-titre',validators=[]) subtitle = StringField('Sous-titre',validators=[])
text = StringField('Une description de votre image', validators=[]) text = StringField('Une description de votre image', validators=[])
category = StringField('Categories',validators=[]) category = StringField('Categories',validators=[])
image = FileField('image', validators=[FileRequired(), image = FileField('image', validators=[FileRequired(),
FileAllowed(['jpg', 'png', 'gif'], 'Images only!')]) FileAllowed(['jpg', 'png', 'gif'], 'Images only!')])
submit = SubmitField('Valider')
class Lien(FlaskForm):
title = StringField('Titre', validators=[DataRequired()])
text = StringField('Texte', validators=[DataRequired()])
link = StringField('Lien', validators=[DataRequired()])
text_button = StringField('Texte du bouton', validators=[DataRequired()])
submit = SubmitField('Valider')
class Contact(FlaskForm):
title = StringField('Titre', validators=[])
text = TextAreaField('Texte contact', validators=[])
email = StringField('Email', validators=[])
phone = StringField('Téléphone', validators=[])
address = StringField('Adresse', validators=[])
postal_code = StringField('Code Postal', validators=[])
city = StringField('Ville', validators=[])
submit = SubmitField('Valider')
class Login(FlaskForm): class Login(FlaskForm):
passwd = PasswordField('Votre mot de passe', validators=[DataRequired()]) login = StringField('Votre identifiant', validators=[DataRequired()])
submit = SubmitField('Se connecter') passwd = PasswordField('Votre mot de passe', validators=[DataRequired()])
submit = SubmitField("Se connecter",validators=[])

View File

@@ -1,6 +1,7 @@
from app import app from app import app
from flask import render_template, url_for, request, flash, redirect, session, make_response from flask import render_template, url_for, request, flash, redirect, session, make_response
import json import json
from markupsafe import escape
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
import os import os
from app.forms import ImageForm, ImageUpload from app.forms import ImageForm, ImageUpload
@@ -12,121 +13,128 @@ from copy import deepcopy
from app.forms import Login from app.forms import Login
from functools import wraps from functools import wraps
from app.utils import login_required from app.utils import login_required
from flask_wtf.csrf import CSRFProtect
csrf = CSRFProtect(app)
app.secret_key = 'your_secret_key'
app.config.from_pyfile('config.py') app.config.from_pyfile('config.py')
DB = DataSite(app.config['JSON_FILE'], app.config['STATIC_PATH'])
DB.loadFile()
tmp = deepcopy(DB) USERS_FOLDER = app.config['USERS_FOLDER']
bcrypt = Bcrypt(app) bcrypt = Bcrypt(app)
EXT_IMG = {'.jpg', '.JPG', '.png', '.PNG', '.gif', '.GIF', '.bmp', '.BMP', '.jpeg', '.JPEG' } EXT_IMG = {'.jpg', '.JPG', '.png', '.PNG', '.gif', '.GIF', '.bmp', '.BMP', '.jpeg', '.JPEG' }
@app.route('/') @app.route('/', methods=['GET', 'POST'])
@app.route('/index.html') @app.route('/index.html', methods=['GET', 'POST'])
def index(): @app.route('/login', methods=['GET', 'POST'])
DB.loadFile() def login():
config = DB.datas['config'] form = Login()
menu = DB.datas['menu'] if 'username' in session :
myblocs = DB.datas['blocs'] resp = redirect(url_for('edit', _external=True))
return render_template('/index.html.tpl', else :
config=config, resp = redirect(url_for('login', _external=True))
menu=menu,
myblocs=myblocs) if request.method == 'POST' :
login = str(request.form['login'])
password = str(request.form['passwd'])
if login in os.listdir(USERS_FOLDER):
db = DataSite(login, USERS_FOLDER)
passwd_bcrypt = db.datas['config']['passwd']
if bcrypt.check_password_hash(passwd_bcrypt, password) is True:
session['username'] = login
resp = redirect(url_for('edit', _external=True))
else:
flash(u'Mauvais mot de passe', 'error')
else:
resp = render_template('/admin/login.html', form=form)
return resp
@app.route( '/logout/', methods=['GET'] )
@login_required
def logout():
session.pop('username', None) # Supprimer username de la session s'il s'y trouve
session.clear()
return redirect(url_for('login'))
@app.route('/edit/save') @app.route('/edit/save')
@login_required @login_required
def savefile(): def savefile():
DB.saveJson(tmp.datas) user = '%s'% escape(session['username'])
DB.loadFile() db = DataSite(user, USERS_FOLDER)
tmp.emptyTrash() db.saveJson(TMP.datas)
db.emptyTrash()
return redirect(url_for('edit')) return redirect(url_for('edit'))
@app.route('/edit') @app.route('/edit')
@login_required @login_required
def edit(): def edit():
theme = tmp.datas['config']['theme'] user = '%s'% escape(session['username'])
menu = DB.datas['menu'] db = DataSite(user, USERS_FOLDER)
print('edit_menu' + str(menu)) theme = db.datas['config']['theme']
myblocs = tmp.datas['blocs'] menu = db.datas['menu']
myblocs = db.datas['blocs']
return render_template('/edit.html.tpl', return render_template('/edit.html.tpl',
blocEdit="", blocEdit="",
config=DB.datas['config'], config=db.datas['config'],
menu=menu, menu=menu,
theme=theme,
myblocs=myblocs myblocs=myblocs
) )
@app.route('/edit/<page>')
@app.route('/edit/<bloc>', methods=['GET', 'POST'])
@login_required @login_required
def editBloc(bloc): def edit(page):
theme = tmp.datas['config']['theme'] user = '%s'% escape(session['username'])
menu= tmp.datas['menu'] db = DataSite(user, USERS_FOLDER)
myblocs = tmp.datas['blocs'] blocs_page = db.getpage()
form = MyBlocs.makeForm(tmp.datas['blocs'][bloc]) theme = db.datas['config']['theme']
bloc = tmp.datas['blocs'][bloc] menu = db.datas['menu']
if request.method == 'POST': myblocs = db.datas['blocs']
if form.validate_on_submit(): return render_template('/edit.html.tpl',
tmp.updateDatas(bloc, form) blocEdit="",
flash(u'Vos changements on été pris en compte', 'success') config=db.datas['config'],
menu=menu,
if "hx-request" in request.headers: theme=theme,
return render_template(theme+'/_'+bloc['type']+'.html', myblocs=myblocs
bloc=bloc) )
else:
return redirect(url_for('edit'))
if "hx-request" in request.headers:
return render_template(theme+'/_'+bloc['type']+'-edit.html',
bloc=bloc,
form=form)
else:
return render_template(theme+'/edit.html',
config=DB.datas['config'],
menu=menu,
myblocs=myblocs,
blocEdit=bloc['name'],
form=form)
@app.route('/view/<bloc>', methods=['GET'])
@login_required
def viewBloc(bloc):
theme = tmp.datas['config']['theme']
myblocs = tmp.datas['blocs']
form = MyBlocs.makeForm(tmp.datas['blocs'][bloc])
bloc = tmp.datas['blocs'][bloc]
return render_template(theme+'/_'+bloc['type']+'.html',
bloc=bloc)
@app.route('/edit/images/<bloc>/<image>', methods=['GET', 'POST']) @app.route('/edit/images/<bloc>/<image>', methods=['GET', 'POST'])
@login_required @login_required
def editPhoto(image, bloc): def editPhoto(image, bloc):
theme = tmp.datas['config']['theme'] user = '%s'% escape(session['username'])
db = DataSite(user, USERS_FOLDER)
theme = db.datas['config']['theme']
form = ImageForm() form = ImageForm()
mesimages = tmp.datas['blocs'][bloc] mesimages = db.datas['blocs'][bloc]
if form.validate_on_submit():
if request.method == 'POST': if request.method == 'POST':
if form.validate_on_submit(): db.updateImg(bloc, mesimages[image], form)
tmp.updateImg(bloc, mesimages[image], form) db.saveJson()
else: form = MyBlocs.makeForm(db.datas['blocs'][bloc])
flash(u'Image non modifier', error) if "hx-request" in request.headers:
return render_template(theme+'/blocs/edit/images_list.html',
theme=theme,
form = MyBlocs.makeForm(tmp.datas['blocs'][bloc]) bloc=mesimages,
if "hx-request" in request.headers: form=form)
return render_template(theme+'/_gallery-edit.html', else:
bloc=mesimages, return redirect ('/edit#'+bloc)
form=form)
else:
return redirect ('/edit#'+bloc)
else: else:
return render_template(theme+'/_image-edit'+'.html', form=form, image=mesimages[image], bloc=mesimages) return render_template(theme+'/blocs/edit/_image-edit'+'.html', form=form, image=mesimages[image], bloc=mesimages)
@app.route('/upload-gallery/<bloc>', methods=['POST']) @app.route('/upload-gallery/<bloc>', methods=['POST'])
@login_required @login_required
def drop_upload(bloc): def drop_upload(bloc):
user = '%s'% escape(session['username'])
db = DataSite(user, USERS_FOLDER)
file = request.files['file'] file = request.files['file']
filename = secure_filename(file.filename) filename = secure_filename(file.filename)
ext = os.path.splitext(filename)[-1] ext = os.path.splitext(filename)[-1]
@@ -157,64 +165,133 @@ def drop_upload(bloc):
with Image.open(os.path.join(save_path, 'fullsize', filename )) as img : with Image.open(os.path.join(save_path, 'fullsize', filename )) as img :
img.thumbnail((300,300)) img.thumbnail((300,300))
img.save(os.path.join(save_path, 'thumbnails', filename ) ) img.save(os.path.join(save_path, 'thumbnails', filename ) )
tmp.addImg(bloc, filename) db.addImg(bloc, filename)
db.saveJson()
return make_response(('Chunk upload succesfull', 200)) return make_response(('Chunk upload succesfull', 200))
@app.route('/edit/images/<bloc>/del/<image>', methods=['GET']) @app.route('/edit/images/<bloc>/del/<image>', methods=['GET'])
@login_required @login_required
def delImage(bloc, image): def delImage(bloc, image):
tmp.delImg(image) user = '%s'% escape(session['username'])
db = DataSite(user, USERS_FOLDER)
db.delImg(image)
db.saveJson()
return redirect ('/edit#'+bloc) return redirect ('/edit#'+bloc)
@app.route('/edit/<blocname>', methods=['GET', 'POST'])
@login_required
def editBloc(blocname):
user = '%s'% escape(session['username'])
db = DataSite(user, USERS_FOLDER)
theme = db.datas['config']['theme']
bloc = db.datas['blocs'][blocname]
form = MyBlocs.makeForm(bloc)
if request.method == 'POST':
if form.validate_on_submit():
print(form.name.data)
db.datas['blocs'][form.name.data]=DataSite.updateBloc(bloc, form)
db.saveJson()
flash(u'Vos changements on été pris en compte et enregistré', 'success')
else:
print(form.errors)
if "hx-request" in request.headers:
return render_template(theme+'/blocs/_'+bloc['type']+'.html',
theme=theme,
bloc=db.datas['blocs'][blocname])
else:
return redirect(url_for('edit'))
else:
if "hx-request" in request.headers:
return render_template(theme+'/blocs/edit/_'+bloc['type']+'.html',
theme=theme,
bloc=bloc,
form=form)
else:
return render_template('/edit.html.tpl',
config=db.datas['config'],
menu=db.datas['menu'],
myblocs=db.datas['blocs'],
theme=theme,
blocEdit=bloc['name'],
form=form)
@app.route('/view/<bloc>', methods=['GET'])
@login_required
def viewBloc(bloc):
user = '%s'% escape(session['username'])
db = DataSite(user, USERS_FOLDER)
theme = db.datas['config']['theme']
myblocs = db.datas['blocs']
form = MyBlocs.makeForm(db.datas['blocs'][bloc])
bloc = db.datas['blocs'][bloc]
return render_template(theme+'/blocs/_'+bloc['type']+'.html',
bloc=bloc)
@app.route('/addBloc', methods=['POST'])
@login_required
def addBloc():
user = '%s'% escape(session['username'])
db = DataSite(user, USERS_FOLDER)
for key in request.form:
print (key +':'+ request.form[key])
blocName = request.form['blocName']
blocType = request.form['blocType']
bloc = MyBlocs.new(blocName, blocType)
if bloc != None:
db.datas['blocs'][blocName] = { 'name': blocName, 'type': blocType}
flash (u'Bloc ajouté avec succès', 'succes');
else:
return make_response(('Invalid type of bloc ', 500))
db.saveJson()
if "hx-request" in request.headers:
return render_template('/admin/_blocs-list.html',
myblocs=db.datas['blocs'])
else:
return redirect(url_for('edit'))
@app.route('/sortblocs', methods=['POST'])
@login_required
def sortblocs():
user = '%s'% escape(session['username'])
db = DataSite(user, USERS_FOLDER)
config = db.datas['config']
menu = db.datas['menu']
myblocs = deepcopy(TMP.datas['blocs'])
db.datas['blocs']=dict()
for bloc in request.form:
if bloc != 'csrf_token':
bloc_name = bloc.replace("bloc-", "", 2)
db.datas['blocs'][bloc_name] = myblocs[bloc_name]
flash (u'Les blocs ont été réagencés', 'succes');
db.saveJson()
return redirect(url_for('edit'))
@app.route('/editmenu', methods=['POST']) @app.route('/editmenu', methods=['POST'])
@login_required @login_required
def editMenu(): def editMenu():
print (request.form) user = '%s'% escape(session['username'])
DB.datas['menu']=dict() db = DataSite(user, USERS_FOLDER)
db.datas['menu']=dict()
for menu in request.form: for menu in request.form:
if '§§' in menu: if '§§' in menu:
submenu = menu.split("§§") submenu = menu.split("§§")
if submenu[0] in DB.datas['menu'].keys(): if submenu[0] in db.datas['menu'].keys():
DB.datas['menu'][submenu[0]] = DB.datas['menu'][submenu[0]] | {submenu[1]: str(request.form[menu])} db.datas['menu'][submenu[0]] = db.datas['menu'][submenu[0]] | {submenu[1]: str(request.form[menu])}
else: else:
DB.datas['menu'][submenu[0]] = {submenu[1]: str(request.form[menu])} db.datas['menu'][submenu[0]] = {submenu[1]: str(request.form[menu])}
elif menu == 'csrf_token':
pass
else: else:
DB.datas['menu'][menu] = str(request.form[menu]) db.datas['menu'][menu] = str(request.form[menu])
print (DB.datas['menu'])
flash (u'Le menu a bien été modifier', 'succes');
return make_response(('Update menu succesfull', 200))
@app.route('/login', methods=['GET', 'POST'])
def login():
theme = DB.datas['config']['theme']
form = Login()
if 'username' in session :
resp = redirect(url_for('edit', _external=True))
else :
resp = redirect(url_for('login', _external=True))
if request.method == 'POST' :
password = str(request.form['passwd'])
passwd_bcrypt = DB.datas['config']['passwd']
if bcrypt.check_password_hash(passwd_bcrypt, password) is True: db.saveJson()
session['username'] = "logged" flash (u'Le menu a bien été modifier', 'success');
resp = redirect(url_for('edit', _external=True)) return redirect(url_for('edit'))
else:
flash(u'Mauvais mot de passe', 'error')
else:
resp = render_template(theme+'/login.html', form=form)
return resp
@app.route( '/logout/', methods=['GET'] )
@login_required
def logout():
session.pop('username', None) # Supprimer username de la session s'il s'y trouve
session.clear()
return redirect(url_for('index'))

View File

@@ -0,0 +1,48 @@
<div>
<form class="sortblocs" action="/sortblocs" method="POST" id="myblocs">
<input id="csrf_token" name="csrf_token" type="hidden" value="{{ csrf_token() }}">
{% include 'admin/_blocs-list.html' %}
</form>
<hr/>
<button class="btn btn-outline-success" onclick="printForm()">+</button>
<div class="formAddBloc" id="addBloc">
<form action="/addBloc" method="POST" class="" >
<input id="csrf_token" name="csrf_token" type="hidden" value="{{ csrf_token() }}">
<h3>Créé un nouveau bloc</H3>
<br>
<label for="nom"><b>Nom du bloc </b></label><br/>
<input type="text" name="blocName" placeholder="Nom" id="blocName" required="">
<br>
<label for="link"><b>Type de bloc</b></label>
<br/>
<select id="blocType" name="blocType" size="8">
<option value="presentation">Présentation</option>
<option value="text">Texte libre</option>
<option value="gallery">Galerie</option>
<option value="external_link">Lien externe</option>
<option value="contact">Contact</option>
</select>
<br/>
<button type="submit" class="btn btn-success"
hx-post="/addBloc"
hx-swap="outerHTML"
hx-target="#myblocs"> Créer le bloc </button>
</form>
</div>
<hr/>
<button class="btn btn-success" type="submit" form="myblocs"> Enregister </button>
</div>

View File

@@ -0,0 +1,33 @@
<form class="sortblocs" action="/sortblocs" method="POST" id="myblocs">
<div id="myblocs" class="myblocs">
{% for item in myblocs.keys() %}
<div class="bloc" id="bloc-{{ item }}" style="margin-top: 10px;">
<button class="btn"> {{ item }} - {{ myblocs[item]['type'] }} </button>
<input class="input-menu" id="bloc-{{ item }}" name="{{ item }}" value="" style="display:none;">
<button class="btn btn-danger" onclick="deleteItem(this)"> x </button>
</div>
{% endfor %}
</div>
</form>
<script src="/static/vendors/Sortable/Sortable.min.js"></script>
<script type="text/javascript">
var elements = document.getElementsByClassName('myblocs');
for (var i = 0; i < elements.length; i++) {
new Sortable(elements[i], {
group: 'shared',
animation: 150,
invertSwap: true,
fallbackOnBody: true,
swapThreshold: 0.65,
})};
</script>

View File

@@ -0,0 +1,9 @@
{% for item in myblocs.keys() %}
<div class="bloc" id="bloc-{{ item }}" style="margin-top: 10px;">
<button class="btn"> {{ item }} - {{ myblocs[item]['type'] }} </button>
<input class="input-menu" id="bloc-{{ item }}" name="{{ item }}" value="" style="display:none;">
<button class="btn btn-danger" onclick="deleteItem(this)"> x </button>
</div>
{% endfor %}

View File

@@ -1,4 +1,5 @@
<form class="sortable" action="/editmenu" method="POST" hx-post="/editmenu" hx-swap="none"> <form class="sortable" action="/editmenu" method="POST" id="menuEdit">
<input id="csrf_token" name="csrf_token" type="hidden" value="{{ csrf_token() }}">
<div id="Menu" class="list"> <div id="Menu" class="list">
{% for item in menu.keys() %} {% for item in menu.keys() %}
@@ -31,14 +32,14 @@
</div> </div>
<button class="btn btn-outline-success" onclick="openForm()">+</button> <button class="btn btn-outline-success" onclick="openForm()">+</button>
<hr> <hr>
<button class="btn btn-success" type="submit"> Enregistrer </button> <button class="btn btn-success" type="submit" form="menuEdit"> Enregistrer </button>
</form> </form>
<div class="form-popup" id="myForm" style="display: none;"> <div class="form-popup" id="myForm" style="display: none;">
<form action="/action_page.php" class="form-container"> <form class="form-container">
<h3>Nouvelle entrée</h3><br> <h3>Nouvelle entrée</h3><br>
<label for="nom"><b>Nom</b></label> <label for="nom"><b>Nom</b></label>

View File

@@ -0,0 +1,35 @@
<!--
<form class="sortblocs" action="/createpage" method="POST" id="mypages">
<div id="myblocs" class="myblocs">
{% for item in mypages %}
<div class="page" id="page" style="margin-top: 10px;">
<button class="btn"> {{ }} - {{ myblocs[item]['type'] }} </button>
<input class="input-menu" id="bloc-{{ item }}" name="{{ item }}" value="" style="display:none;">
<button class="btn btn-danger" onclick="deleteItem(this)"> x </button>
</div>
{% endfor %}
</div>
</form>
-->
<script src="/static/vendors/Sortable/Sortable.min.js"></script>
<script type="text/javascript">
var elements = document.getElementsByClassName('page');
for (var i = 0; i < elements.length; i++) {
new Sortable(elements[i], {
group: 'shared',
animation: 150,
invertSwap: true,
fallbackOnBody: true,
swapThreshold: 0.65,
})};
</script>

View File

@@ -0,0 +1,24 @@
<!--
<form class="sortblocs" action="/createpage" method="POST" id="mypages">
<div id="myblocs" class="myblocs">
</div>
</form>
-->
<script src="/static/vendors/Sortable/Sortable.min.js"></script>
<script type="text/javascript">
var elements = document.getElementsByClassName('page');
for (var i = 0; i < elements.length; i++) {
new Sortable(elements[i], {
group: 'shared',
animation: 150,
invertSwap: true,
fallbackOnBody: true,
swapThreshold: 0.65,
})};
</script>

View File

@@ -2,8 +2,9 @@
<div class="container text-center"> <div class="container text-center">
<form method='POST' action='/login'> <form method='POST' action='/login'>
{{ form.csrf_token }} {{ form.csrf_token }}
<h2 class="mb-4"> Entrez votre mot de passe : </h2> <h2 class="mb-4"> Entrez votre login et votre mot de passe : </h2>
{{ form.login(col=5, class="form-control form-control-lg text-center" ) }}
{{ form.passwd(col=5, class="form-control form-control-lg text-center" ) }} {{ form.passwd(col=5, class="form-control form-control-lg text-center" ) }}
<br /> <br />
{{ form.submit() }} {{ form.submit() }}

View File

@@ -1,61 +1,141 @@
<!-- Navigation --> <!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-light fixed-bottom navbar-skrink" id="toolNav"> <nav class="navbar navbar-expand-lg navbar-light fixed-bottom navbar-skrink" id="toolNav">
<div class="container"> <div class="container">
<button class="btn btn-secondary" type="button" data-toggle="modal" data-target="#parameters" > Paramètres de mon site </button> <button class="btn btn-primary"
<a class="btn btn-warning nav-brand js-scroll-trigger" href="/edit/save"> Publier mes modifications </a> type="button"
data-toggle="modal"
data-target="#addBloc">
Agencer es blocs
</button>
<button class="btn btn-info nav-brand js-scroll-trigger"
type="button"
data-toggle="modal"
data-target="#mymenu">
Editer le menu
</button>
<button class="btn btn-success nav-brand js-scroll-trigger"
type="button"
data-toggle="modal"
data-target="#mypages">
Gérer mes pages
</button>
<button class="btn btn-secondary"
type="button"
data-toggle="modal"
data-target="#parameters">
Paramètres de mon site
</button>
<a class="btn btn-warning nav-brand js-scroll-trigger" href="/edit/save">
Publier mes modifications
</a>
</div> </div>
</nav> </nav>
<div class="modal" id="parameters">
<div class="modal-dialog modal-lg"> <div class="modal" id="addBloc">
<div class="modal-content"> <div class="modal-dialog modal-lg">
<!-- Modal Header --> <div class="modal-content">
<div class="modal-header"> <!-- Modal Header -->
<h4 class="modal-title">Paramètres </h4> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button> <h4 class="modal-title"> Agencer mes blocs </h4>
</div> <button type="button" class="close" data-dismiss="modal">&times;</button>
</div>
<!-- Modal body --> <div class="modal-body text-center">
<div class="modal-body"> {% include 'admin/_bloc-edit.html' %}
<ul class="nav nav-pills nav-justified"> </div>
<li class="nav-item"> <div class="modal-footer mx-auto">
<a class="nav-link active" data-toggle="pill" href="#menu">Menu</a> <a class="btn btn-danger" href="/edit" > Annuler </a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#options"> Options </a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#publication">Publication</a>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div class="tab-pane container text-center active" id="menu">
<br/>
<h4> Organiser mes pages </h4>
{% include 'admin/_menu-edit.html' %}
</div>
<div class="tab-pane container text-center fade" id="options">
<br/>
<h4> Mes réseaux sociaux </h4>
</div>
<div class="tab-pane container fade text-center" id="publication">
<br/>
<h4> Serveur(s) où publier mon site </h4>
</div>
</div>
</div>
<!-- Modal footer -->
<div class="modal-footer mx-auto">
<button class="btn btn-success">Enregistrer </button>
<a class="btn btn-danger" href="/edit" > Annuler </a>
</div>
</div> </div>
</div> </div>
</div>
</div>
<div class="modal" id="mypages">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<h4 class="modal-title"> Mes pages </h4>
<button type="button" class="close" data-dismiss="modal">&times;</button>
</div>
<div class="modal-body text-center">
{% include 'admin/_pages-edit.html' %}
</div>
<div class="modal-footer mx-auto">
<a class="btn btn-danger" href="/edit" > Annuler </a>
</div>
</div>
</div>
</div>
<div class="modal" id="mymenu">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<h4 class="modal-title"> Mon menu </h4>
<button type="button" class="close" data-dismiss="modal">&times;</button>
</div>
<div class="modal-body text-center">
{% include 'admin/_menu-edit.html' %}
</div>
<div class="modal-footer mx-auto">
<a class="btn btn-danger" href="/edit" > Annuler </a>
</div>
</div>
</div>
</div>
<div class="modal" id="parameters">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<h4 class="modal-title">Paramètres </h4>
<button type="button" class="close" data-dismiss="modal">&times;</button>
</div>
<!-- Modal body -->
<div class="modal-body">
<ul class="nav nav-pills nav-justified">
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#options"> Options </a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#publication"> Publication </a>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div class="tab-pane container text-center fade" id="options">
<br/>
<h4> Mes réseaux sociaux </h4>
</div>
<div class="tab-pane container fade text-center" id="publication">
<br/>
<h4> Serveur(s) où publier mon site </h4>
</div>
</div>
</div>
<!-- Modal footer -->
<div class="modal-footer mx-auto">
<a class="btn btn-danger" href="/edit" > Annuler </a>
</div>
</div>
</div>
</div> </div>

View File

@@ -10,20 +10,20 @@
<div class="row"> <div class="row">
<div class="col-lg-4 ml-auto text-center"> <div class="col-lg-4 ml-auto text-center">
<i class="fa fa-phone fa-3x mb-3 sr-contact"></i> <i class="fa fa-phone fa-3x mb-3 sr-contact"></i>
<p>{{ bloc.phone }}</p> <p> {{ bloc.phone }} </p>
</div> </div>
<div class="col-lg-4 mr-auto text-center"> <div class="col-lg-4 mr-auto text-center">
<i class="fa fa-envelope-o fa-3x mb-3 sr-contact"></i> <i class="fa fa-envelope-o fa-3x mb-3 sr-contact"></i>
<p> <p>
<a href="{{ bloc.email }}" class="obfuscate" > {{bloc.email }}</a> <a href="{{ bloc.email }}" class="obfuscate" > {{ bloc.email }} </a>
</p> </p>
</div> </div>
<div class="col-lg-8 mx-auto text-center"> <div class="col-lg-8 mx-auto text-center">
<br/> <br/> <br/> <br/>
<p class="mb-2"> {{ bloc.address }} </p> <p class="mb-2"> {{ bloc.address }} </p>
<h3 class="section-heading"> <p>
{{ bloc.postal_code }} - {{ bloc.city }} <bold> {{ bloc.postal_code }} - {{ bloc.city }} </bold>
</h3> </p>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -9,8 +9,12 @@
</div> </div>
<div class="col-lg-8 mx-auto"> <div class="col-lg-8 mx-auto">
<p class="text-faded mb-5"> {{ bloc.text }} </p> <p class="text-faded mb-5"> {{ bloc.text }} </p>
<a class="btn btn-primary btn-xl js-scroll-trigger" href="{{bloc.link}}">{{ bloc.text_button }} </a> <a class="btn btn-primary btn-xl js-scroll-trigger" href="#">{{ bloc.text_button }}
</a>
</div> </div>
</div> </div>
</div> </div>
</header> </header>

View File

@@ -2,7 +2,7 @@
<div class="container" id="{{ bloc.name }}" hx_swap="beforeend"> <div class="container" id="{{ bloc.name }}" hx_swap="beforeend">
<form method='POST' action="/edit/{{ bloc.name }}" hx-post='/edit//{{ bloc.name }}' hx-swap="outerHTML" hx-target="#{{ bloc.name }}" > <form method='POST' action="/edit/{{ bloc.name }}" hx-post='/edit//{{ bloc.name }}' hx-swap="outerHTML" hx-target="#{{ bloc.name }}" >
{{ form.csrf_token }} {{ form.csrf_token }}
{% include 'edit-tools/_form-base.html' %}
<div class="row"> <div class="row">
<div class="col-lg-8 mx-auto text-center"> <div class="col-lg-8 mx-auto text-center">
{{ form.title(col=5, value=bloc.title, {{ form.title(col=5, value=bloc.title,
@@ -43,8 +43,8 @@
</div> </div>
</div> </div>
<br/> <br/>
{{ form.submit(class="btn") }} {% include 'edit-tools/_btn-save-cancel.html' %}
<button class="btn btn-danger" hx-get="/view/{{ bloc.name }}" hx-swap="outerHTML" hx-target="#{{ bloc.name }}" > Annuler </button>
</div> </div>
</div> </div>
</form> </form>

View File

@@ -2,7 +2,7 @@
<div class="container text-center"> <div class="container text-center">
<form method='POST' action='/edit/{{ bloc.name }}' hx-post='/edit//{{ bloc.name }}' hx-swap="outerHTML" hx-target="#{{ bloc.name }}"> <form method='POST' action='/edit/{{ bloc.name }}' hx-post='/edit//{{ bloc.name }}' hx-swap="outerHTML" hx-target="#{{ bloc.name }}">
{{ form.csrf_token }} {{ form.csrf_token }}
{% include 'edit-tools/_form-base.html' %}
<h2 class="mb-4"> Titre du lien </h2> <h2 class="mb-4"> Titre du lien </h2>
{{ form.title(value=bloc.title, {{ form.title(value=bloc.title,
class="form-control form-control-lg text-center") }} class="form-control form-control-lg text-center") }}
@@ -20,9 +20,7 @@
{{ error }}</span> {{ error }}</span>
{% endfor %} {% endfor %}
</div> </div>
{{ form.submit(class="btn") }} {% include 'edit-tools/_btn-save-cancel.html' %}
<button class="btn btn-danger" hx-get="/view/{{ bloc.name }}" hx-swap="outerHTML" hx-target="#{{ bloc.name }}" > Annuler </button>
</form> </form>
</div> </div>

View File

@@ -0,0 +1,6 @@
<form id="uploader" methods="POST" class="dropzone dz-clickable"></form>
{% include theme+'/blocs/edit/images_list.html' %}
{% include '_js_dropzone.html' %}

View File

@@ -0,0 +1,34 @@
<div class="container-fluid p-0">
<form method='POST' action='/edit/images/{{ bloc.name }}/{{ image.file }}' hx-swap="outerHTML" hx-target="#editImg">
{{ form.csrf_token }}
<div class="row">
<div class="col-lg-2 mx-auto my-4 text-center">
<img class="img-fluid" src="/static/img/portfolio/thumbnails/{{ image.file }}" alt="{{ image.description }}">
</div>
<div class="col-lg-4 mx-auto my-4 text-center">
<h3> Titre </h3>
{{ form.title(value=image.title,
class="form-control form-control-lg text-center") }}
<hr class="light my-4">
<h3>Sous-titre</h3>
{{ form.subtitle(value=image.subtitle, class="form-control text-center") }}
<br/>
<h3> Catégorie </h3>
{{ form.category(value=image.category, class="form-control text-center") }}
<hr class="light my-4">
<h3> Description de votre image </h3>
<p> Une description de l'image est utile pour les personnes mal-voyantes et au référecement de votre site </p>
{{ form.description(value=image.description, class="form-control text-center") }}
<br/>
<button class="btn btn-success" type="submit" data-dismiss="modal"
hx-post="/edit/images/{{ bloc.name }}/{{ image.file }}"
hx-swap="outerHTML"
hx-target="#editImg"> Valider </button>
<a class="btn btn-danger mx-auto" href="/edit/images/del/{{ image.nom_fichier }}">Supprimer l'image</a>
</div>
</div>
</form>
</div>

View File

@@ -2,8 +2,10 @@
<form method='POST' action='/edit/{{ bloc.name }}' hx-swap="outerHTML" hx-target="#{{ bloc.name }}" enctype="multipart/form-data"> <form method='POST' action='/edit/{{ bloc.name }}' hx-swap="outerHTML" hx-target="#{{ bloc.name }}" enctype="multipart/form-data">
{{ form.csrf_token }} {{ form.csrf_token }}
<div class="row"> <div class="row">
<div class="col-lg-10 form-group mx-auto"> <div class="col-lg-10 form-group mx-auto">
{{ form.title(value=bloc.title, {% include 'edit-tools/_form-base.html' %}
{{ form.title(value=bloc.title,
class="form-control form-control-lg text-center text-uppercase") class="form-control form-control-lg text-center text-uppercase")
}} }}
{% for error in form.title.errors %} {% for error in form.title.errors %}
@@ -32,9 +34,7 @@
<div class="col-lg-3 form-group mx-auto"> <div class="col-lg-3 form-group mx-auto">
{{ form.image(class="form-control" ) }} {{ form.image(class="form-control" ) }}
</div> </div>
{{ form.submit(class="btn") }} {% include 'edit-tools/_btn-save-cancel.html' %}
<button class="btn btn-danger" hx-get="/view/{{ bloc.name }}" hx-swap="outerHTML" hx-target="#{{ bloc.name }}" > Annuler </button>
</div> </div>
</div> </div>
</form> </form>

View File

@@ -1,19 +1,20 @@
<div class="container"> <div class="container">
<form method='POST' action='/edit//{{ bloc.name }}' hx-post='/edit//{{ bloc.name }}' hx-swap="outerHTML" hx-target="#{{ bloc.name }}"> <form method='POST' action='/edit/{{ bloc.name }}' >
{{ form.csrf_token }} {{ form.csrf_token }}
<div class="row"> <div class="row">
<div class="col-lg-8 mx-auto text-center"> <div class="col-lg-8 mx-auto text-center">
{{ form.title(col=5,value=bloc.title, {% include 'edit-tools/_form-base.html' %}
{{ form.title(col=5,value=bloc.title,
class="form-control form-control-lg text-center") }} class="form-control form-control-lg text-center") }}
<hr class="light my-4"> <hr class="light my-4">
<textarea class="form-control text-center" id="text" name="text"> {{ bloc.text }} </textarea> <textarea class="form-control text-center" id="text" name="text"> {{ bloc.text }} </textarea>
<br/> <br/>
{{ form.submit(class="btn") }} {% include 'edit-tools/_btn-save-cancel.html' %}
<button class="btn btn-danger" hx-get="/view/{{ bloc.name }}" hx-swap="outerHTML" hx-target="#{{ bloc.name }}" > Annuler </button>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
</section> </section>

View File

@@ -1,8 +1,5 @@
<section class="p-0">
<form id="uploader" methods="POST" class="dropzone dz-clickable"></form> <div class="container-fluid p-0" id="editImg">
<section class="p-0" id="{{ bloc.name }}">
<div class="container-fluid p-0">
<div class="row no-gutters "> <div class="row no-gutters ">
{% for image in bloc.values() %} {% for image in bloc.values() %}
{% if image.file %} {% if image.file %}
@@ -23,7 +20,7 @@
</a> </a>
<button type="button" class="btn btn-success m-4" <button type="button" class="btn btn-success m-4"
hx-get="/edit/images/{{ bloc.name }}/{{ image.file }}" hx-get="/edit/images/{{ bloc.name }}/{{ image.file }}"
hx-target="#{{bloc.name}}" hx-target="#editImg"
hw-swap="none"> hw-swap="none">
<i class="fa fa-pencil-square-o"></i> <i class="fa fa-pencil-square-o"></i>
</button> </button>
@@ -36,5 +33,3 @@
</section> </section>
{% include '_js_dropzone.html' %}

View File

@@ -2,17 +2,17 @@
{% block body %} {% block body %}
{% include 'creative/_nav.html' %} {% include theme+'/_nav.html' %}
{% include 'creative/_navtool.html' %} {% include theme+'/_navtool.html' %}
{% for bloc in myblocs.values() %} {% for bloc in myblocs.values() %}
{% if blocEdit == bloc.name %} {% if blocEdit == bloc.name %}
{% include 'creative/_'+bloc.type+'-edit.html' %} {% include theme+'/_'+bloc.type+'-edit.html' %}
{% else %} {% else %}
{% include 'creative/_'+bloc.type+'.html' %} {% include theme+'/_'+bloc.type+'.html' %}
<button class="btn btn-success btn-xl pull-right" <button class="btn btn-success btn-xl pull-right"
style="margin-top:-7rem; margin-right:1rem;" style="margin-top:-7rem; margin-right:1rem;"

View File

@@ -0,0 +1,10 @@
<button class="btn btn-success"
hx-post='/edit/{{ bloc.name }}'
hx-swap="outerHTML"
hx-target="#{{ bloc.name }}" > Enregistrer </button>
<button class="btn btn-danger"
hx-get="/view/{{ bloc.name }}"
hx-swap="outerHTML"
hx-target="#{{ bloc.name }}" > Annuler </button>

View File

@@ -0,0 +1,18 @@
<div class="row mx-md-5">
<div class="col-auto">
<label> Nom du bloc </label>
{{ form.name(col=4,value=bloc.name,
class="form-control text-center") }}
</div>
<div class="col-auto">
<label> Couleur de l'arrière plan </label>
{{ form.bg_color(col=4,
class="form-control form-control-color text-center") }}
</div>
<div class="col-auto">
<label> Couleur du texte</label>
{{ form.fg_color(col=4,
class="form-control form-control-color text-center") }}
</div>
</div>
<br/>

View File

@@ -1,18 +1,18 @@
<style> <style>
.msginfo
{
color: white;
font-weight:bold;
}
.msginfo .success .msginfo
{ {
background-color: green; color: white;
font-weight:bold;
} }
.msginfo .success
{
background-color: green;
}
.msginfo .error{ .msginfo .error{
background-color: red; background-color: red;
} }
</style> </style>

View File

@@ -2,6 +2,7 @@
{% block css %} {% block css %}
{% include 'edit-tools/css/dropzone' %} {% include 'edit-tools/css/dropzone' %}
<link href="/static/css/edit-toolbar.css" rel="stylesheet">
{% endblock %} {% endblock %}
@@ -13,16 +14,15 @@
{% for bloc in myblocs.values() %} {% for bloc in myblocs.values() %}
{% if blocEdit == bloc.name %} {% if blocEdit == bloc.name %}
{% include config.theme+'/_'+bloc.type+'-edit.html' %} {% include config.theme+'/blocs/edit/_'+bloc.type+'.html' %}
{% else %} {% else %}
{% include config.theme+'/_'+bloc.type+'.html' %} {% include config.theme+'/blocs/_'+bloc.type+'.html' %}
<button class="btn btn-success btn-xl pull-right" <button class="btn btn-success btn-xl pull-right"
style="margin-top:-7rem; margin-right:1rem;" style="margin-top:-7rem; margin-right:1rem;"
hx-get="/edit/{{ bloc.name }}" hx-get="/edit/{{ bloc.name }}"
hx-target="#{{bloc.name}}" hx-target="#{{bloc.name}}"
hw-swap="none" hx-swap="oob"> Modifier </button>
> Éditer </button>
{% endif %} {% endif %}
{% endfor %} {% endfor %}

View File

@@ -14,7 +14,7 @@
{% include config.theme+'/_nav.html' %} {% include config.theme+'/_nav.html' %}
{% for bloc in myblocs.values() %} {% for bloc in myblocs.values() %}
{% include config.theme+'/_'+bloc.type+'.html' %} {% include config.theme+'/blocs/_'+bloc.type+'.html' %}
{% endfor %} {% endfor %}

View File

@@ -1,95 +0,0 @@
{
"config": {
"theme": "creative",
"siteTitle": "Le titre de mon site",
"siteLang": "fr",
"siteDescription": "Une description du site",
"siteAuthor": "my name",
"passwd": "$2b$11$O5/ZTiiUG45cl7D5hJ9rMuzXmjAX2FeT5jwdBlS8ImOAoP1tpiv5G",
"lastLogins": {}
},
"menu": {
"A propos": "#bloc1",
"Galerie": "#bloc3",
"Sous-menu": {
"Un lien": "https://dede.Fr",
"Un autre truc": "https://example.fr"
},
"Contact": "#bloc5"
},
"blocs": {
"bloc0": {
"name": "bloc0",
"type": "presentation",
"title": "Mon Petit site pas \u00e0 Moi",
"text": "Mon petit site \u00e0 moi.\r\nJe suis tr\u00e8s content car \u00e7a marche toujours, et m\u00eame si j'ai mis \u00e0 jour les paquets c'est quand m\u00eame cool.",
"text_button": "En savoir plus",
"link": "mon_lien",
"bg_img": "bg.jpg"
},
"bloc1": {
"name": "bloc1",
"type": "text",
"title": "Salut c'est moi et ... voila quoi",
"text": "Ben je fais de la musique de la pierre s\u00e8che et \u00e7a me plait. Et de temps en temps je code des trucs qui marche :)."
},
"bloc2": {
"name": "bloc2",
"type": "external_link",
"title": "Titre de votre lien",
"text": "Un texte pour d\u00e9crire ce que l'on va trouver dans votre liens",
"text_button": "Mon lien",
"link": "http://exemple.com"
},
"bloc3": {
"name": "bloc3",
"type": "gallery",
"black.jpg": {
"title": "Guitare noire",
"subtitle": "Ma main sur ma gutiare",
"description": "Un main blanche sur une guitare noire",
"category": "",
"file": "black.jpg"
},
"tournesol.jpg": {
"title": "Tounesol",
"subtitle": "tournesol",
"description": "Une jolie photo de tournesol",
"category": "",
"file": "tournesol.jpg"
},
"173326.png": {
"title": "Flyer logiciel libre",
"subtitle": "Les LL",
"description": "explication c'est quoi le logiciel libre",
"category": "",
"file": "173326.png"
},
"logo_BIM.png": {
"title": "Le BIM",
"subtitle": "Le logo du BIM",
"description": "Le logo du bim : BIM \u00e9crit en orange sur le nuage bleu",
"file": "logo_BIM.png",
"category": "logo"
}
},
"bloc56": {
"name": "bloc56",
"type": "text",
"title": "Salut c'est moi et ... voila quoi",
"text": "Ben je fais de la musique de la pierre s\u00e8che et \u00e7a me plait. Et de temps en temps je code des trucs qui marche pas du tout et \u00e7a ma band\u00e9 ."
},
"bloc5": {
"name": "bloc5",
"type": "contact",
"title": " Pour me contacter ",
"text": "f,ldf,ldsm",
"schedules": "",
"email": "example__chez__mondomaine...tld",
"phone": "04040404040",
"address": "",
"postal_code": "34434",
"city": "34434"
}
}
}