Big commit i'm sorry ...
12
app/forms.py
@@ -7,14 +7,15 @@ from wtforms import validators
|
||||
from wtforms.validators import DataRequired, Length
|
||||
|
||||
class FormBloc(FlaskForm):
|
||||
title = StringField('Titre', validators=[DataRequired()])
|
||||
name = StringField('Nom du bloc', validators=[DataRequired()])
|
||||
title = StringField('Titre', validators=[])
|
||||
subtitle = StringField('Sous-titre', validators=[])
|
||||
property = StringField('Classes CSS', validators=[])
|
||||
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=30000)])
|
||||
text_button = StringField('Texte du bouton', validators=[])
|
||||
link = StringField('Lien', validators=[])
|
||||
image = FileField('image', validators=[FileAllowed(['jpg', 'png', 'gif'], 'Images only!')])
|
||||
image = FileField('image', validators=[FileAllowed(['jpg','jpeg','png'])])
|
||||
email = StringField('Email', validators=[])
|
||||
phone = StringField('Téléphone', validators=[])
|
||||
address = StringField('Addresse', validators=[])
|
||||
@@ -35,8 +36,7 @@ class ImageUpload(FlaskForm):
|
||||
subtitle = StringField('Sous-titre',validators=[])
|
||||
text = StringField('Une description de votre image', validators=[])
|
||||
category = StringField('Categories',validators=[])
|
||||
image = FileField('image', validators=[FileRequired(),
|
||||
FileAllowed(['jpg', 'png', 'gif'], 'Images only!')])
|
||||
image = FileField('image', validators=[FileAllowed(['jpg', 'png', 'gif'], 'Images only!')])
|
||||
|
||||
class Login(FlaskForm):
|
||||
login = StringField('Votre identifiant', validators=[DataRequired()])
|
||||
|
||||
@@ -4,13 +4,15 @@ from werkzeug.utils import secure_filename
|
||||
from app.forms import *
|
||||
from PIL import Image
|
||||
from os import remove, path
|
||||
from pathlib import Path, PurePath, PurePosixPath
|
||||
|
||||
|
||||
|
||||
class MyBlocs:
|
||||
|
||||
def new(blocName, blocType):
|
||||
def new(blocName, blocType, theme):
|
||||
mybloc = None
|
||||
if blocType in MyBlocs.listTypeBlocs():
|
||||
if blocType in MyBlocs.listTypeBlocs(theme):
|
||||
mybloc=dict()
|
||||
mybloc['name'] = str(blocName)
|
||||
mybloc['type'] = str(blocType)
|
||||
@@ -26,4 +28,13 @@ class MyBlocs:
|
||||
def newImgForm():
|
||||
return ImageUpload()
|
||||
|
||||
def listTypeBlocs(theme):
|
||||
typeBlocs = list()
|
||||
folders = Path(PurePosixPath('./app').joinpath('templates', theme, 'blocs'))
|
||||
for folder in folders.iterdir():
|
||||
if not(folder.is_dir()):
|
||||
typeBloc=folder.name.split('.')[0]
|
||||
typeBlocs.append(typeBloc[1:])
|
||||
|
||||
return typeBlocs
|
||||
|
||||
|
||||
@@ -3,105 +3,179 @@ import os
|
||||
from werkzeug.utils import secure_filename
|
||||
from app.forms import *
|
||||
from PIL import Image
|
||||
from os import remove, path
|
||||
|
||||
from pathlib import Path, PurePath, PurePosixPath
|
||||
|
||||
class DataSite:
|
||||
|
||||
datas = ""
|
||||
static_path = ""
|
||||
user_folder = None
|
||||
username = str()
|
||||
datas = str()
|
||||
static_path = None
|
||||
trash = list()
|
||||
filej= ""
|
||||
filej= None
|
||||
|
||||
def __init__(self, username, users_folder ):
|
||||
self.filej = os.path.join(users_folder, username,'ident.json')
|
||||
|
||||
with open(self.filej, 'r') as f:
|
||||
def __init__(self, username :str , users_folder :str ):
|
||||
self.username = username
|
||||
self.user_folder = PurePosixPath(users_folder).joinpath(username)
|
||||
self.filej = Path(PurePosixPath(self.user_folder).joinpath('ident.json'))
|
||||
|
||||
|
||||
with self.filej.open(newline='', mode='r', encoding='utf-8') as f:
|
||||
self.datas = json.load(f)
|
||||
self.static_path = os.path.join(users_folder, username, 'public')
|
||||
self.static_path = Path(PurePosixPath(self.user_folder.joinpath('public')))
|
||||
self.static_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def loadFile(self):
|
||||
with open(self.filej, 'r') as f:
|
||||
self.datas = json.load(f)
|
||||
|
||||
def loadFile_tmp(self):
|
||||
with open(self.filej_tmp, 'r') as f:
|
||||
self.datas = json.load(f)
|
||||
|
||||
|
||||
def updateBloc(bloc, form):
|
||||
bloc['name'] = form.name.data
|
||||
bloc['bg_color'] = form.bg_color.data
|
||||
bloc['fg_color']=form.fg_color.data
|
||||
bloc['title'] = form.title.data
|
||||
bloc['text'] = form.text.data
|
||||
bloc['text_button']=form.text_button.data
|
||||
bloc['link'] = form.link.data
|
||||
if form.image.data :
|
||||
f=form.image.data
|
||||
filename = secure_filename(f.filename)
|
||||
extension = filename.rsplit('.', 1)[1].lower()
|
||||
f.save(os.path.join(
|
||||
self.static_path, 'img','bg_custom.'+ extension))
|
||||
if not self.filej.isfile():
|
||||
raise FileNotFoundError(f"Le fichier ident.json n'existe pas : {self.filej}")
|
||||
|
||||
bloc['bg_img']='bg_custom.'+extension
|
||||
bloc['email'] = form.email.data
|
||||
bloc['address']=form.address.data
|
||||
bloc['phone'] = form.phone.data
|
||||
bloc['postal_code'] = form.postal_code.data
|
||||
bloc['city'] = form.city.data
|
||||
with self.filej.open(newline='', mode='r', encoding='utf-8') as f:
|
||||
self.datas = json.load(f)
|
||||
|
||||
|
||||
|
||||
|
||||
def getBlocs(self, page: str):
|
||||
|
||||
if page != '':
|
||||
page = Path(self.user_folder.joinpath(page, 'page.json'))
|
||||
datas = ""
|
||||
if not page.exists():
|
||||
raise FileNotFoundError(f"Le fichier page.json n'existe pas : {page}")
|
||||
|
||||
datas = json.loads(page.read_text())
|
||||
else:
|
||||
datas = self.datas
|
||||
|
||||
return datas
|
||||
|
||||
|
||||
def updateBloc(self, bloc, form, files=None):
|
||||
print (form)
|
||||
for field in form():
|
||||
print(field)
|
||||
|
||||
if files != None:
|
||||
f = files['image']
|
||||
filename = secure_filename(f.filename)
|
||||
extension = filename.rsplit('.', 1)[1].lower()
|
||||
bg_custom = 'bg_custom_'+bloc['name']+'.'+extension
|
||||
f.save(PurePath.joinpath(
|
||||
self.static_path, 'img', bg_custom))
|
||||
|
||||
bloc['bg_img'] = bg_custom
|
||||
|
||||
return bloc
|
||||
|
||||
def updateImg(self, bloc, img, form):
|
||||
filename = img['file']
|
||||
img['title'] = form.title.data
|
||||
img['subtitle'] = form.subtitle.data
|
||||
img['description'] = form.description.data
|
||||
img['category'] = form.category.data
|
||||
self.datas['blocs'][bloc][filename]=img
|
||||
|
||||
def updateImg_tmp(self, bloc, img, form):
|
||||
filename = img['file']
|
||||
img['title'] = form.title.data
|
||||
img['subtitle'] = form.subtitle.data
|
||||
img['description'] = form.description.data
|
||||
img['category'] = form.category.data
|
||||
self.datas['blocs'][bloc][filename]=img
|
||||
|
||||
|
||||
def addImg(self, bloc, image_uploaded):
|
||||
def updateImg(self, image, form):
|
||||
img = dict()
|
||||
img['title'] = ""
|
||||
img['subtitle']=""
|
||||
img['text'] = ""
|
||||
img['category'] = ""
|
||||
img['file']=image_uploaded
|
||||
self.datas['blocs'][bloc][image_uploaded]=img
|
||||
img['title'] = form.title.data
|
||||
img['subtitle'] = form.subtitle.data
|
||||
img['description'] = form.description.data
|
||||
img['category'] = form.category.data
|
||||
img['file'] = image
|
||||
return img
|
||||
|
||||
def addImg(self, image_uploaded):
|
||||
img = dict()
|
||||
|
||||
def addImg_tmp(self, bloc, image_uploaded):
|
||||
img = dict()
|
||||
img['title'] = ""
|
||||
img['subtitle']=""
|
||||
img['text'] = ""
|
||||
img['category'] = ""
|
||||
img['file']=image_uploaded
|
||||
self.datas_tmp['blocs'][bloc][image_uploaded]=img
|
||||
img['file'] = image_uploaded
|
||||
|
||||
return img
|
||||
|
||||
|
||||
def saveJson(self):
|
||||
remove(self.filej)
|
||||
with open (self.filej, 'w') as f:
|
||||
f.write(json.dumps(self.datas, indent=5))
|
||||
def delImg(self, bloc, img):
|
||||
|
||||
def delImg(self, img):
|
||||
try:
|
||||
images = self.datas['images']
|
||||
images.pop(img)
|
||||
except KeyError:
|
||||
print("Le fichier n'est pas dans la liste")
|
||||
if bloc['type'] == 'gallery':
|
||||
img_file = Path(PurePosixPath(self.user_folder).joinpath('public', 'img', bloc[img]['file'] ))
|
||||
img_thumb_file = Path(PurePosixPath(self.user_folder).joinpath('public','img', 'thumbnails', bloc[img]['file']))
|
||||
if img_file.exists():
|
||||
img_file.unlink()
|
||||
|
||||
if img_thumb_file.exists():
|
||||
img_thumb_file.unlink()
|
||||
|
||||
bloc.pop(img)
|
||||
else:
|
||||
self.trash.append(img)
|
||||
img_file = Path(PurePosixPath(self.user_folder).joinpath('public', 'img', img ))
|
||||
|
||||
return bloc
|
||||
|
||||
|
||||
def saveMenu(self, menu:dict):
|
||||
self.datas['menu'] = menu
|
||||
self.filej.write_text(json.dumps(self.datas, indent=5))
|
||||
|
||||
|
||||
def saveBlocs(self, page='', blocs=dict()):
|
||||
if page != '':
|
||||
datas = dict()
|
||||
datas['blocs'] = blocs
|
||||
|
||||
page_info = Path(PurePosixPath(self.user_folder).joinpath(page, 'page.json'))
|
||||
|
||||
if not page_info.exists():
|
||||
raise FileNotFoundError(f"Le fichier page.json n'existe pas : {page}")
|
||||
|
||||
page_info.write_text(json.dumps(datas, indent=3))
|
||||
else:
|
||||
self.datas['blocs']= blocs
|
||||
self.filej.write_text(json.dumps(self.datas, indent=5))
|
||||
|
||||
|
||||
def getPages(self):
|
||||
mypages = list()
|
||||
folders = Path(self.user_folder)
|
||||
for folder in folders.iterdir():
|
||||
if folder.name != 'public' and folder.is_dir():
|
||||
mypages.append(folder.name)
|
||||
|
||||
return mypages
|
||||
|
||||
def new_page(self, pageName:str, pageType:str):
|
||||
page_folder = Path(PurePosixPath(self.user_folder).joinpath(pageName))
|
||||
page = Path(PurePosixPath(self.user_folder).joinpath(pageName, 'page.json'))
|
||||
page_type = Path('./app/templates/themes/'+self.datas['config']['theme']+'/pages/'+pageType+'.json')
|
||||
|
||||
if not page_type.exists():
|
||||
raise FileNotFoundError(f"Le type de page n'existe pas : {page_type}")
|
||||
else:
|
||||
page_folder.mkdir()
|
||||
page.write_text(page_type.read_text())
|
||||
|
||||
if not page.exists():
|
||||
raise FileNotFoundError(f"La page n'a pas pu etre créé : {page}")
|
||||
|
||||
return True
|
||||
|
||||
def rm_page(self, pageName :str):
|
||||
page_folder = Path(PurePosixPath(self.user_folder).joinpath(pageName))
|
||||
page = Path(PurePosixPath(self.user_folder).joinpath(pageName, 'page.json'))
|
||||
|
||||
#First delete the json page
|
||||
try:
|
||||
page.unlink()
|
||||
print(f"Successfully deleted: {page}")
|
||||
except FileNotFoundError:
|
||||
print(f"File not found: {page}. Nothing to delete.")
|
||||
# Delete the empty directory
|
||||
if page_folder.is_dir():
|
||||
try:
|
||||
page_folder.rmdir()
|
||||
print(f"Successfully removed empty directory: {page_folder}")
|
||||
except OSError as e:
|
||||
print(f"Error removing directory (might not be empty): {e}")
|
||||
|
||||
|
||||
def writeHTML(self, pageName :str, htmlExport :str):
|
||||
public_folder = Path(PurePosixPath(self.user_folder).joinpath('public'))
|
||||
pageName = pageName+'.html'
|
||||
page = Path(PurePosixPath(self.user_folder).joinpath('public', pageName))
|
||||
page.write_text(htmlExport)
|
||||
|
||||
|
||||
def emptyTrash(self):
|
||||
for file in self.trash:
|
||||
|
||||
@@ -12,7 +12,7 @@ class Users:
|
||||
if auth_file != None:
|
||||
self.__auth_file = auth_file
|
||||
self.__auth_method = "file"
|
||||
|
||||
x
|
||||
def getPasswd(self, username):
|
||||
with open(self.auth_file, 'r') as f:
|
||||
users_info = f.readlines()
|
||||
|
||||
358
app/routes.py
@@ -1,9 +1,10 @@
|
||||
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, send_from_directory
|
||||
import json
|
||||
from markupsafe import escape
|
||||
from werkzeug.utils import secure_filename
|
||||
import os
|
||||
import re
|
||||
from app.forms import ImageForm, ImageUpload
|
||||
from app.models.sites import DataSite
|
||||
from app.models.blocs import MyBlocs
|
||||
@@ -17,20 +18,15 @@ from flask_wtf.csrf import CSRFProtect
|
||||
|
||||
csrf = CSRFProtect(app)
|
||||
|
||||
|
||||
app.secret_key = 'your_secret_key'
|
||||
|
||||
|
||||
app.config.from_pyfile('config.py')
|
||||
|
||||
|
||||
THEMES_FOLDER = './themes/'
|
||||
USERS_FOLDER = app.config['USERS_FOLDER']
|
||||
bcrypt = Bcrypt(app)
|
||||
|
||||
EXT_IMG = {'.jpg', '.JPG', '.png', '.PNG', '.gif', '.GIF', '.bmp', '.BMP', '.jpeg', '.JPEG' }
|
||||
|
||||
@app.route('/', methods=['GET', 'POST'])
|
||||
@app.route('/index.html', methods=['GET', 'POST'])
|
||||
@app.route('/login', methods=['GET', 'POST'])
|
||||
def login():
|
||||
form = Login()
|
||||
@@ -65,91 +61,79 @@ def logout():
|
||||
return redirect(url_for('login'))
|
||||
|
||||
|
||||
@app.route('/edit/save')
|
||||
@login_required
|
||||
def savefile():
|
||||
user = '%s'% escape(session['username'])
|
||||
db = DataSite(user, USERS_FOLDER)
|
||||
db.saveJson(TMP.datas)
|
||||
db.emptyTrash()
|
||||
return redirect(url_for('edit'))
|
||||
|
||||
@app.route('/edit')
|
||||
@login_required
|
||||
def edit():
|
||||
user = '%s'% escape(session['username'])
|
||||
db = DataSite(user, USERS_FOLDER)
|
||||
theme = db.datas['config']['theme']
|
||||
menu = db.datas['menu']
|
||||
myblocs = db.datas['blocs']
|
||||
return render_template('/edit.html.tpl',
|
||||
blocEdit="",
|
||||
config=db.datas['config'],
|
||||
menu=menu,
|
||||
theme=theme,
|
||||
myblocs=myblocs
|
||||
)
|
||||
@app.route('/edit/<page>')
|
||||
@app.route('/', methods=['GET'], defaults={'page': ''})
|
||||
@app.route('/<page>/', methods=['GET'])
|
||||
@login_required
|
||||
def edit(page):
|
||||
user = '%s'% escape(session['username'])
|
||||
page = '%s' % escape(page)
|
||||
db = DataSite(user, USERS_FOLDER)
|
||||
blocs_page = db.getpage()
|
||||
mypages = db.getPages()
|
||||
theme = db.datas['config']['theme']
|
||||
menu = db.datas['menu']
|
||||
myblocs = db.datas['blocs']
|
||||
myblocs = db.getBlocs(page)['blocs']
|
||||
|
||||
return render_template('/edit.html.tpl',
|
||||
blocEdit="",
|
||||
config=db.datas['config'],
|
||||
menu=menu,
|
||||
theme=theme,
|
||||
pagesList=mypages,
|
||||
page=page,
|
||||
myblocs=myblocs
|
||||
)
|
||||
|
||||
|
||||
@app.route('/edit/images/<bloc>/<image>', methods=['GET', 'POST'])
|
||||
@app.route('/edit/images/<bloc>/<image>', methods=['GET', 'POST'], defaults={'page': ''})
|
||||
@app.route('/<page>/edit/images/<bloc>/<image>', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def editPhoto(image, bloc):
|
||||
def editPhoto(page, image, bloc):
|
||||
user = '%s'% escape(session['username'])
|
||||
page = '%s' % escape(page)
|
||||
image = '%s' % escape(image)
|
||||
bloc = '%s' % escape(bloc)
|
||||
|
||||
db = DataSite(user, USERS_FOLDER)
|
||||
theme = db.datas['config']['theme']
|
||||
form = ImageForm()
|
||||
mesimages = db.datas['blocs'][bloc]
|
||||
myblocs = db.getBlocs(page)['blocs']
|
||||
|
||||
if form.validate_on_submit():
|
||||
if request.method == 'POST':
|
||||
db.updateImg(bloc, mesimages[image], form)
|
||||
db.saveJson()
|
||||
myblocs[bloc][image] = db.updateImg(image, form)
|
||||
db.saveBlocs(page, myblocs)
|
||||
form = MyBlocs.makeForm(db.datas['blocs'][bloc])
|
||||
if "hx-request" in request.headers:
|
||||
return render_template(theme+'/blocs/edit/images_list.html',
|
||||
theme=theme,
|
||||
bloc=mesimages,
|
||||
form=form)
|
||||
if "hx-request" in request.headers:
|
||||
return make_response(('Image modified', 200))
|
||||
else:
|
||||
return redirect ('/edit#'+bloc)
|
||||
return redirect ('/#'+bloc)
|
||||
else:
|
||||
return render_template(theme+'/blocs/edit/_image-edit'+'.html', form=form, image=mesimages[image], bloc=mesimages)
|
||||
return render_template(THEMES_FOLDER+theme+'/blocs/edit/_image-edit'+'.html', form=form, image=myblocs[bloc][image], bloc=myblocs[bloc])
|
||||
|
||||
@app.route('/upload-gallery/<bloc>', methods=['POST'])
|
||||
|
||||
@app.route('/upload-gallery/<bloc>', methods=['POST'], defaults={'page': ''})
|
||||
@app.route('/<page>/upload-gallery/<bloc>', methods=['POST'])
|
||||
@login_required
|
||||
def drop_upload(bloc):
|
||||
def drop_upload(page, bloc):
|
||||
user = '%s'% escape(session['username'])
|
||||
page = '%s' % escape(page)
|
||||
db = DataSite(user, USERS_FOLDER)
|
||||
datas = dict()
|
||||
file = request.files['file']
|
||||
filename = secure_filename(file.filename)
|
||||
myblocs = db.getBlocs(page)['blocs']
|
||||
ext = os.path.splitext(filename)[-1]
|
||||
save_path = "./app/static/img/portfolio"
|
||||
save_path = os.path.join(USERS_FOLDER, user, 'public', 'img' )
|
||||
if ext not in EXT_IMG :
|
||||
return make_response(('Le fichier n\'est pas une image', 400))
|
||||
|
||||
current_chunk = int(request.form['dzchunkindex'])
|
||||
print (current_chunk)
|
||||
|
||||
if (os.path.isfile(os.path.join(save_path, 'fullsize', filename ))) and current_chunk == 0:
|
||||
if (os.path.isfile(os.path.join(save_path, filename ))) and current_chunk == 0:
|
||||
return make_response(('Un fichier avec le même nom existe déjà', 400))
|
||||
|
||||
try:
|
||||
with open(os.path.join(save_path, 'fullsize', filename ), 'ab') as f:
|
||||
with open(os.path.join(save_path, filename ), 'ab') as f:
|
||||
f.seek(int(request.form['dzchunkbyteoffset']))
|
||||
f.write(file.stream.read())
|
||||
except OSError:
|
||||
@@ -159,117 +143,231 @@ def drop_upload(bloc):
|
||||
|
||||
if current_chunk + 1 == total_chunks:
|
||||
# This was the last chunk, the file should be complete and the size we expect
|
||||
if os.path.getsize(os.path.join(save_path, 'fullsize', filename )) != int(request.form['dztotalfilesize']):
|
||||
if os.path.getsize(os.path.join(save_path, filename )) != int(request.form['dztotalfilesize']):
|
||||
return make_response(('La taille du fichier source est différentes', 500))
|
||||
else:
|
||||
with Image.open(os.path.join(save_path, 'fullsize', filename )) as img :
|
||||
img.thumbnail((300,300))
|
||||
with Image.open(os.path.join(save_path, filename )) as img :
|
||||
img.thumbnail((640,480))
|
||||
img.save(os.path.join(save_path, 'thumbnails', filename ) )
|
||||
db.addImg(bloc, filename)
|
||||
db.saveJson()
|
||||
|
||||
myblocs[bloc][filename] = db.addImg(filename)
|
||||
db.saveBlocs(page, myblocs)
|
||||
return make_response(('Chunk upload succesfull', 200))
|
||||
|
||||
@app.route('/edit/images/<bloc>/del/<image>', methods=['GET'])
|
||||
@login_required
|
||||
def delImage(bloc, image):
|
||||
user = '%s'% escape(session['username'])
|
||||
db = DataSite(user, USERS_FOLDER)
|
||||
db.delImg(image)
|
||||
db.saveJson()
|
||||
return redirect ('/edit#'+bloc)
|
||||
|
||||
@app.route('/edit/<blocname>', methods=['GET', 'POST'])
|
||||
@app.route('/edit/images/<bloc>/del/<image>', methods=['GET'], defaults={'page': ''})
|
||||
@app.route('/<page>/edit/images/<bloc>/del/<image>', methods=['GET'])
|
||||
@login_required
|
||||
def editBloc(blocname):
|
||||
def delImage(page, bloc, image):
|
||||
user = '%s'% escape(session['username'])
|
||||
page = '%s' % escape(page)
|
||||
db = DataSite(user, USERS_FOLDER)
|
||||
myblocs = db.getBlocs(page)['blocs']
|
||||
|
||||
myblocs[bloc] = db.delImg(myblocs[bloc], image)
|
||||
db.saveBlocs(page, myblocs)
|
||||
|
||||
return make_response(('Image removed', 200))
|
||||
|
||||
|
||||
@app.route('/imgs_list/<blocname>', methods=['GET'], defaults={'page': ''})
|
||||
@app.route('/<page>/imgs_list/<blocname>', methods=['GET'])
|
||||
@login_required
|
||||
def imagesList(page, blocname):
|
||||
user = '%s'% escape(session['username'])
|
||||
page = '%s' % escape(page)
|
||||
blocname = '%s' % escape(blocname)
|
||||
|
||||
db = DataSite(user, USERS_FOLDER)
|
||||
theme = db.datas['config']['theme']
|
||||
bloc = db.datas['blocs'][blocname]
|
||||
form = MyBlocs.makeForm(bloc)
|
||||
myblocs = db.getBlocs(page)['blocs']
|
||||
bloc = myblocs[blocname]
|
||||
|
||||
return render_template(THEMES_FOLDER+theme+'/blocs/edit/images_list.html',page=page,
|
||||
bloc=bloc)
|
||||
|
||||
|
||||
@app.route('/edit/<blocname>', methods=['GET', 'POST'], defaults={'page': ''})
|
||||
@app.route('/<page>/edit/<blocname>', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def editBloc(page, blocname):
|
||||
user = '%s'% escape(session['username'])
|
||||
page = '%s' % escape(page)
|
||||
db = DataSite(user, USERS_FOLDER)
|
||||
theme = db.datas['config']['theme']
|
||||
myblocs = db.getBlocs(page)['blocs']
|
||||
bloc = myblocs[blocname]
|
||||
form = MyBlocs.makeForm(bloc)
|
||||
|
||||
if request.method == 'POST':
|
||||
datas=dict()
|
||||
if form.validate_on_submit():
|
||||
print(form.name.data)
|
||||
db.datas['blocs'][form.name.data]=DataSite.updateBloc(bloc, form)
|
||||
db.saveJson()
|
||||
|
||||
for field, value in request.form.items():
|
||||
print (field)
|
||||
if field != 'csrf_token' and field != 'image':
|
||||
myblocs[blocname][field] = value
|
||||
if 'image' in request.files.keys():
|
||||
file = request.files['image']
|
||||
print ('filename: '+ file.filename)
|
||||
filename = secure_filename(file.filename)
|
||||
bg_custom = 'bg_custom_'+bloc['name']+filename
|
||||
print('bg_custom : '+ bg_custom)
|
||||
file.save(os.path.join(USERS_FOLDER, user, 'public', 'img', bg_custom ))
|
||||
if 'bg_img' in bloc.keys():
|
||||
db.delImg(bloc, bloc['bg_img'])
|
||||
|
||||
|
||||
myblocs[blocname]['bg_img'] = bg_custom
|
||||
|
||||
db.saveBlocs(page, myblocs)
|
||||
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',
|
||||
return render_template(THEMES_FOLDER+theme+'/blocs/_'+bloc['type']+'.html',
|
||||
theme=theme,
|
||||
bloc=db.datas['blocs'][blocname])
|
||||
page=page,
|
||||
bloc=myblocs[blocname])
|
||||
else:
|
||||
return redirect(url_for('edit'))
|
||||
|
||||
|
||||
else:
|
||||
if "hx-request" in request.headers:
|
||||
return render_template(theme+'/blocs/edit/_'+bloc['type']+'.html',
|
||||
return render_template(THEMES_FOLDER+theme+'/blocs/edit/_'+bloc['type']+'.html',
|
||||
theme=theme,
|
||||
bloc=bloc,
|
||||
page=page,
|
||||
form=form)
|
||||
else:
|
||||
return render_template('/edit.html.tpl',
|
||||
config=db.datas['config'],
|
||||
menu=db.datas['menu'],
|
||||
myblocs=db.datas['blocs'],
|
||||
myblocs=myblocs,
|
||||
page=page,
|
||||
theme=theme,
|
||||
blocEdit=bloc['name'],
|
||||
form=form)
|
||||
|
||||
@app.route('/view/<bloc>', methods=['GET'])
|
||||
@app.route('/view/<bloc>', methods=['GET'], defaults={'page': ''})
|
||||
@app.route('/<page>/view/<bloc>', methods=['GET'])
|
||||
@login_required
|
||||
def viewBloc(bloc):
|
||||
def viewBloc(page, bloc):
|
||||
user = '%s'% escape(session['username'])
|
||||
page = '%s' % escape(page)
|
||||
|
||||
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]
|
||||
myblocs = db.getBlocs(page)['blocs']
|
||||
bloc = myblocs[bloc]
|
||||
|
||||
return render_template(theme+'/blocs/_'+bloc['type']+'.html',
|
||||
return render_template(THEMES_FOLDER+theme+'/blocs/_'+bloc['type']+'.html',
|
||||
bloc=bloc)
|
||||
|
||||
@app.route('/addBloc', methods=['POST'])
|
||||
@app.route('/addBloc', methods=['POST'], defaults={'page': ''})
|
||||
@app.route('/<page>/addBloc', methods=['POST'])
|
||||
@login_required
|
||||
def addBloc():
|
||||
def addBloc(page):
|
||||
user = '%s'% escape(session['username'])
|
||||
page = '%s' % escape(page)
|
||||
|
||||
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))
|
||||
datas = dict()
|
||||
myblocs = db.getBlocs(page)['blocs']
|
||||
|
||||
blocName = '%s' % escape(request.form['blocName'])
|
||||
blocType = request.form['blocType']
|
||||
bloc = MyBlocs.new(blocName, blocType, db.datas['config']['theme'])
|
||||
test_name = "^[A-Za-z0-9_-]*$"
|
||||
|
||||
if bloc != None:
|
||||
if bool(re.match(test_name, blocName)) :
|
||||
|
||||
myblocs[blocName] = { 'name': blocName, 'type': blocType}
|
||||
flash (u'Bloc ajouté avec succès', 'succes');
|
||||
else:
|
||||
return make_response(('Invalid bloc Name', 500))
|
||||
|
||||
db.saveBlocs(page, myblocs)
|
||||
|
||||
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'])
|
||||
|
||||
|
||||
@app.route('/addPage', methods=['POST'])
|
||||
@login_required
|
||||
def sortblocs():
|
||||
def addPage():
|
||||
user = '%s'% escape(session['username'])
|
||||
|
||||
db = DataSite(user, USERS_FOLDER)
|
||||
datas = dict()
|
||||
|
||||
pageName = '%s' % escape(request.form['pageName'])
|
||||
pageType = request.form['pageType']
|
||||
test_name = "^[A-Za-z0-9_-]*$"
|
||||
if bool(re.match(test_name, pageName)) :
|
||||
try :
|
||||
page = db.new_page(pageName, pageType)
|
||||
except FileExistsError:
|
||||
return make_response(('Page already exist', 500))
|
||||
else:
|
||||
flash (u'Page créé avec succès', 'success');
|
||||
else:
|
||||
return make_response(('Invalid type ', 500))
|
||||
|
||||
|
||||
mypages = db.getPages()
|
||||
return redirect(url_for('edit', page=pageName))
|
||||
|
||||
@app.route('/rmPage/<pageName>')
|
||||
@login_required
|
||||
def rmPage(pageName):
|
||||
pageName = '%s' % escape(pageName)
|
||||
user = '%s'% escape(session['username'])
|
||||
|
||||
db = DataSite(user, USERS_FOLDER)
|
||||
|
||||
try:
|
||||
db.rm_page(pageName)
|
||||
flash (u'Page supprimé avec succès', 'success');
|
||||
except OSError as e:
|
||||
flash (u"La page n'a pa pu être supprimer", 'error');
|
||||
|
||||
|
||||
return redirect(url_for('edit'))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@app.route('/sortblocs', methods=['POST'], defaults={'page': ''})
|
||||
@app.route('/<page>/sortblocs', methods=['POST'])
|
||||
@login_required
|
||||
def sortblocs(page):
|
||||
user = '%s'% escape(session['username'])
|
||||
page = '%s' % escape(page)
|
||||
|
||||
db = DataSite(user, USERS_FOLDER)
|
||||
config = db.datas['config']
|
||||
menu = db.datas['menu']
|
||||
myblocs = deepcopy(TMP.datas['blocs'])
|
||||
db.datas['blocs']=dict()
|
||||
datas = dict()
|
||||
myblocs = dict()
|
||||
|
||||
myblocs_orig = db.getBlocs(page)['blocs']
|
||||
|
||||
for bloc in request.form:
|
||||
if bloc != 'csrf_token':
|
||||
bloc_name = bloc.replace("bloc-", "", 2)
|
||||
db.datas['blocs'][bloc_name] = myblocs[bloc_name]
|
||||
myblocs[bloc_name] = myblocs_orig[bloc_name]
|
||||
flash (u'Les blocs ont été réagencés', 'succes');
|
||||
db.saveJson()
|
||||
|
||||
db.saveBlocs(page, myblocs)
|
||||
|
||||
return redirect(url_for('edit'))
|
||||
|
||||
@app.route('/editmenu', methods=['POST'])
|
||||
@@ -291,7 +389,59 @@ def editMenu():
|
||||
else:
|
||||
db.datas['menu'][menu] = str(request.form[menu])
|
||||
|
||||
db.saveJson()
|
||||
db.saveMenu(db.datas['menu'])
|
||||
flash (u'Le menu a bien été modifier', 'success');
|
||||
return redirect(url_for('edit'))
|
||||
|
||||
|
||||
@app.route('/public/img/<filename>')
|
||||
@login_required
|
||||
def myimgs(filename):
|
||||
user = '%s' % escape(session['username'])
|
||||
return send_from_directory(
|
||||
os.path.join(USERS_FOLDER, user, 'public', 'img'), filename )
|
||||
|
||||
@app.route('/public/img/thumbnails/<filename>')
|
||||
@login_required
|
||||
def mythumbnails(filename):
|
||||
user = '%s' % escape(session['username'])
|
||||
return send_from_directory(
|
||||
os.path.join(USERS_FOLDER, user, 'public', 'img', 'thumbnails'), filename )
|
||||
|
||||
@app.route('/favicon.ico', methods=['GET'])
|
||||
@app.route('/favicon.ico/', methods=['GET'])
|
||||
def favicon():
|
||||
return make_response(('Ok! ', 200))
|
||||
|
||||
|
||||
|
||||
@app.route('/publish', methods=['GET'])
|
||||
@login_required
|
||||
def publish():
|
||||
user = '%s' % escape(session['username'])
|
||||
db = DataSite(user, USERS_FOLDER)
|
||||
listPages = db.getPages()
|
||||
theme = db.datas['config']['theme']
|
||||
menu = db.datas['menu']
|
||||
|
||||
for page in listPages:
|
||||
myblocs = db.getBlocs(page)['blocs']
|
||||
htmlExport = render_template('/index.html.tpl',
|
||||
config=db.datas['config'],
|
||||
menu=menu,
|
||||
theme=theme,
|
||||
page=page,
|
||||
myblocs=myblocs)
|
||||
db.writeHTML(theme, page, htmlExport)
|
||||
|
||||
# Export index.html landing page
|
||||
myblocs = db.getBlocs('')['blocs']
|
||||
htmlExport = render_template('/index.html.tpl',
|
||||
config=db.datas['config'],
|
||||
menu=menu,
|
||||
theme=theme,
|
||||
page='/',
|
||||
myblocs=myblocs)
|
||||
|
||||
db.writeHTML(theme, 'index', htmlExport)
|
||||
return redirect(url_for('edit'))
|
||||
|
||||
|
||||
@@ -63,6 +63,92 @@ h6 {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.ql-align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ql-align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ql-align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
padding: 60px 80px 40px;
|
||||
position: relative;
|
||||
}
|
||||
blockquote p {
|
||||
font-size: 35px;
|
||||
font-weight: 700px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*blockquote p::before {
|
||||
content: "\f095";
|
||||
font-family: FontAwesome;
|
||||
display: inline-block;
|
||||
padding-right: 6px;
|
||||
vertical-align: middle;
|
||||
font-size: 180px;
|
||||
}*/
|
||||
|
||||
blockquote:before {
|
||||
position: absolute;
|
||||
font-family: 'FontAwesome';
|
||||
top: 0;
|
||||
content:"\f10d";
|
||||
font-size: 200px;
|
||||
color: rgba(0,0,0,0.1);
|
||||
|
||||
}
|
||||
|
||||
blockquote::after {
|
||||
content: "";
|
||||
top: 20px;
|
||||
left: 50%;
|
||||
margin-left: -100px;
|
||||
position: absolute;
|
||||
height: 3px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
blockquote{
|
||||
font-size: 1.4em;
|
||||
width:60%;
|
||||
margin:50px auto;
|
||||
font-style:italic;
|
||||
color: #555555;
|
||||
padding:1.2em 30px 1.2em 75px;
|
||||
border-left:8px solid #f05f40;
|
||||
line-height:1.6;
|
||||
position: relative;
|
||||
background:#EDEDED;
|
||||
}
|
||||
|
||||
blockquote::before{
|
||||
font-family:Arial;
|
||||
content: "\201C";
|
||||
color:#f05f40;
|
||||
font-size:4em;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top:-10px;
|
||||
}
|
||||
|
||||
blockquote::after{
|
||||
content: '';
|
||||
}
|
||||
|
||||
blockquote span{
|
||||
display:block;
|
||||
color:#333333;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
margin-top:1em;
|
||||
}
|
||||
|
||||
section {
|
||||
padding: 8rem 0;
|
||||
z-index: -1;
|
||||
@@ -141,7 +227,7 @@ img::-moz-selection {
|
||||
@media (min-width: 992px) {
|
||||
#mainNav {
|
||||
border-color: transparent;
|
||||
background-color: transparent;
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
}
|
||||
#mainNav .navbar-brand {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
@@ -190,16 +276,27 @@ header.masthead {
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
header.masthead hr {
|
||||
header.article-img {
|
||||
padding-top: 10rem;
|
||||
padding-bottom: calc(10rem - 56px);
|
||||
background-position: center center;
|
||||
-webkit-background-size: cover;
|
||||
-moz-background-size: cover;
|
||||
-o-background-size: cover;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
|
||||
header.article-img header.masthead hr {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
header.masthead h1 {
|
||||
header.article-img header.masthead h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
header.masthead p {
|
||||
header.article-img header.masthead p {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
@@ -210,19 +307,27 @@ header.masthead p {
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
header.article-img {
|
||||
height: 50vh;
|
||||
min-height: 300px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
header.masthead {
|
||||
height: 100vh;
|
||||
min-height: 650px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
header.masthead h1 {
|
||||
|
||||
header.article-img header.masthead h1 {
|
||||
font-size: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
header.masthead h1 {
|
||||
header.article-img header.masthead h1 {
|
||||
font-size: 4rem;
|
||||
}
|
||||
.btn-success {
|
||||
|
||||
@@ -4,3 +4,37 @@
|
||||
border-top-color: currentcolor;
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
.visible {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.msginfo
|
||||
{
|
||||
color: white;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.msginfo .success
|
||||
{
|
||||
background-color: green;
|
||||
|
||||
}
|
||||
|
||||
.msginfo .error{
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.ql-toolbar {
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.ql-editor {
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
|
||||
}
|
||||
|
||||
3
app/static/css/prism.min.css
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/* PrismJS 1.30.0
|
||||
https://prismjs.com/download#themes=prism-okaidia&languages=markup+css+clike+javascript+bash+c+cpp+markdown+markup-templating+nginx+php+python */
|
||||
code[class*=language-],pre[data-language*=language-]{color:#f8f8f2;background:0 0;text-shadow:0 1px rgba(0,0,0,.3);font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}:not(pre)>code[class*=language-],pre[class*=language-]{background:#272822}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#8292a2}.token.punctuation{color:#f8f8f2}.token.namespace{opacity:.7}.token.constant,.token.deleted,.token.property,.token.symbol,.token.tag{color:#f92672}.token.boolean,.token.number{color:#ae81ff}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#a6e22e}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url,.token.variable{color:#f8f8f2}.token.atrule,.token.attr-value,.token.class-name,.token.function{color:#e6db74}.token.keyword{color:#66d9ef}.token.important,.token.regex{color:#fd971f}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}
|
||||
|
Before Width: | Height: | Size: 180 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 23 KiB |
15
app/static/js/prism.js
Normal file
@@ -12,7 +12,7 @@
|
||||
dictDefaultMessage: 'Déposez vos fichiers ici!',
|
||||
paramName: "file",
|
||||
maxFilesize: 1024, // MB
|
||||
url: "/upload-dropzone",
|
||||
url: "{% if page %}/{{ page }}{% endif %}/upload-gallery/{{bloc.name}}",
|
||||
chunking: true,
|
||||
forceChunking: true,
|
||||
chunkSize: 1000000,
|
||||
|
||||
4
app/templates/_print_colors.css
Normal file
@@ -0,0 +1,4 @@
|
||||
{% if bloc.fg_color != bloc.bg_color %}
|
||||
color: {{ bloc.fg_color }}; background-color: {{ bloc.bg_color }};
|
||||
{% endif %}
|
||||
|
||||
@@ -9,28 +9,40 @@
|
||||
<button class="btn btn-outline-success" onclick="printForm()">+</button>
|
||||
|
||||
<div class="formAddBloc" id="addBloc">
|
||||
<form action="/addBloc" method="POST" class="" >
|
||||
<form action="/addBloc" id="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="">
|
||||
<label for="blocName">Nom du bloc (caractères sans accents uniquement) </label>
|
||||
<div class="input-group">
|
||||
<input type="text"
|
||||
name="blocName"
|
||||
class="form-control"
|
||||
id="blocName"
|
||||
placeholder="Bloc1"
|
||||
required>
|
||||
<div class="invalid-feedback">
|
||||
Entrez le nom du bloc sans espaces ni caractères spéciaux
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<label for="link"><b>Type de bloc</b></label>
|
||||
<br/>
|
||||
<select id="blocType" name="blocType" size="8">
|
||||
<option value="presentation">Présentation</option>
|
||||
<select id="blocType" name="blocType" size="8" required>
|
||||
<option value="presentation"> Ecran d'Accueil </option>
|
||||
<option value="presentation"> Image En-tête d'article </option>
|
||||
<option value="text">Texte libre</option>
|
||||
<option value="simple_article">Article Simple</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>
|
||||
onclick="valid_nameBloc()"
|
||||
hx-post="/addBloc"
|
||||
hx-swap="outerHTML"
|
||||
hx-target="#myblocs"> Créer le bloc </button>
|
||||
</form>
|
||||
</div>
|
||||
<hr/>
|
||||
@@ -39,9 +51,20 @@
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
function valid_nameBloc()
|
||||
{
|
||||
var blocName = document.getElementById("blocName");
|
||||
let name_field = blocName.value.trim();
|
||||
let Valid = /^[a-z0-9]+$/i.test(name_field);
|
||||
console.log(Valid);
|
||||
if (!Valid) {
|
||||
document.getElementById("blocName").setAttribute("class", "form-control is-invalid");
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
<form class="sortblocs" action="/sortblocs" method="POST" id="myblocs">
|
||||
<div id="myblocs" class="myblocs">
|
||||
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
{% for item in myblocs.keys() %}
|
||||
|
||||
<div class="bloc" id="bloc-{{ item }}" style="margin-top: 10px;">
|
||||
<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>
|
||||
@@ -29,5 +29,5 @@
|
||||
fallbackOnBody: true,
|
||||
swapThreshold: 0.65,
|
||||
})};
|
||||
|
||||
</script>
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
{% 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 %}
|
||||
@@ -6,14 +6,14 @@
|
||||
type="button"
|
||||
data-toggle="modal"
|
||||
data-target="#addBloc">
|
||||
Agencer es blocs
|
||||
Blocs de cette page
|
||||
</button>
|
||||
|
||||
<button class="btn btn-info nav-brand js-scroll-trigger"
|
||||
type="button"
|
||||
data-toggle="modal"
|
||||
data-target="#mymenu">
|
||||
Editer le menu
|
||||
Mon menu
|
||||
</button>
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
type="button"
|
||||
data-toggle="modal"
|
||||
data-target="#mypages">
|
||||
Gérer mes pages
|
||||
Mes pages
|
||||
</button>
|
||||
|
||||
<button class="btn btn-secondary"
|
||||
@@ -46,39 +46,19 @@
|
||||
<div class="modal-content">
|
||||
<!-- Modal Header -->
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title"> Agencer mes blocs </h4>
|
||||
<h4 class="modal-title"> Mes blocs </h4>
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
</div>
|
||||
<div class="modal-body text-center">
|
||||
{% include 'admin/_bloc-edit.html' %}
|
||||
</div>
|
||||
<div class="modal-footer mx-auto">
|
||||
<a class="btn btn-danger" href="/edit" > Annuler </a>
|
||||
<a class="btn btn-danger" href="/" > Annuler </a>
|
||||
</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">×</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">
|
||||
@@ -91,12 +71,32 @@
|
||||
{% include 'admin/_menu-edit.html' %}
|
||||
</div>
|
||||
<div class="modal-footer mx-auto">
|
||||
<a class="btn btn-danger" href="/edit" > Annuler </a>
|
||||
<a class="btn btn-danger" href="/" > Annuler </a>
|
||||
</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">×</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="/" > Annuler </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="modal" id="parameters">
|
||||
<div class="modal-dialog modal-lg">
|
||||
@@ -134,8 +134,9 @@
|
||||
|
||||
<!-- Modal footer -->
|
||||
<div class="modal-footer mx-auto">
|
||||
<a class="btn btn-danger" href="/edit" > Annuler </a>
|
||||
<a class="btn btn-danger" href="/" > Annuler </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -52,7 +52,6 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="/static/vendors/Sortable/Sortable.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
|
||||
<!--
|
||||
<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>
|
||||
@@ -1,24 +1,47 @@
|
||||
<div id="mypages">
|
||||
<ul style="list-style:none;" id="mypages" class="mypages">
|
||||
<li><a href="/"> <button class="btn"> Page d'accueil </button> </a> </li>
|
||||
|
||||
<!--
|
||||
<form class="sortblocs" action="/createpage" method="POST" id="mypages">
|
||||
<div id="myblocs" class="myblocs">
|
||||
</div>
|
||||
</form>
|
||||
{% for item in pagesList %}
|
||||
|
||||
-->
|
||||
<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>
|
||||
<li style="padding-top: 10px;">
|
||||
<a href="/{{ item }}/">
|
||||
<button class="btn"> {{ item }} </button>
|
||||
</a>
|
||||
<a href="/rmPage/{{ item }}"><button class="btn btn-danger"> X </button></a>
|
||||
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
||||
</ul>
|
||||
|
||||
<div class="formAddPage" id="addPage">
|
||||
<form action="/addPage" id="addPage" method="POST" class="" >
|
||||
<input id="csrf_token" name="csrf_token" type="hidden" value="{{ csrf_token() }}">
|
||||
<h3>Créé un nouveau bloc</H3>
|
||||
<br>
|
||||
<label for="blocName">Nom du bloc (caractères sans accents uniquement) </label>
|
||||
<div class="input-group">
|
||||
<input type="text"
|
||||
name="pageName"
|
||||
class="form-control"
|
||||
id="pageName"
|
||||
placeholder="Ma_Page"
|
||||
required>
|
||||
<div class="invalid-feedback">
|
||||
Entrez le nom de la page sans espaces ni caractères spéciaux
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<label for="link"><b>Type de bloc</b></label>
|
||||
<br/>
|
||||
<select id="pageType" name="pageType" size="8" required>
|
||||
<option value="article_image"> Article avec une image d'en tête </option>
|
||||
<option value="simple_article"> Page blanche Texte libre </option>
|
||||
</select>
|
||||
<br/>
|
||||
<button type="submit" class="btn btn-success"
|
||||
onclick="valid_nameBloc()"> Créer la page </button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
<header class="masthead text-center text-white d-flex" style="background-image: url('/static/img/{{ bloc.bg_img }}');">
|
||||
<div class="container my-auto">
|
||||
<form method='POST' action='/edit/accueil' enctype="multipart/form-data">
|
||||
{{ form.csrf_token }}
|
||||
<div class="row">
|
||||
<div class="col-lg-10 form-group mx-auto">
|
||||
{{ form.titre(value=bloc.title,
|
||||
class="form-control form-control-lg text-center text-uppercase")
|
||||
}}
|
||||
{% for error in form.titre.errors %}
|
||||
<span style="color: red;">{{ error }}</span>
|
||||
{% endfor %}
|
||||
<hr>
|
||||
</div>
|
||||
<div class="col-lg-8 form-group mx-auto">
|
||||
{% set f = form.presentation.process_data(bloc.text) %}
|
||||
{{ form.presentation(
|
||||
class="form-control text-center",
|
||||
rows="7")
|
||||
}}
|
||||
{% for error in form.presentation.errors %}
|
||||
<span style="color: red;">{{ error }}</span>
|
||||
{% endfor %}
|
||||
<br/>
|
||||
<div class="col-lg-4 form-group mx-auto">
|
||||
{{ form.texte_boutton(value=bloc.text_button,
|
||||
class="form-control text-center") }}
|
||||
{% for error in form.texte_boutton.errors %}
|
||||
<span style="color: red;">
|
||||
{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="col-lg-3 form-group mx-auto">
|
||||
{{ form.image(class="form-control" ) }}
|
||||
</div>
|
||||
{{ form.submit() }}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</header>
|
||||
@@ -1,16 +0,0 @@
|
||||
<header class="masthead text-center text-white d-flex" style="background-image: url('/static/img/{{ mesinfos.presentation.bg_img }}');" >
|
||||
<div class="container my-auto">
|
||||
<div class="row">
|
||||
<div class="col-lg-10 mx-auto">
|
||||
<h1 class="text-uppercase">
|
||||
<strong> {{ mesinfos.presentation.title }} </strong>
|
||||
</h1>
|
||||
<hr>
|
||||
</div>
|
||||
<div class="col-lg-8 mx-auto">
|
||||
<p class="text-faded mb-5"> {{ mesinfos.presentation.text }} </p>
|
||||
<a class="btn btn-primary btn-xl js-scroll-trigger" href="#about">{{ mesinfos.presentation.text_button }} </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@@ -1,34 +0,0 @@
|
||||
|
||||
<div class="container-fluid p-0">
|
||||
<form method='POST' action='/edit/images/{{ bloc.name }}/{{ image.file }}' hx-swap="outerHTML" hx-target="#{{ bloc.name }}">
|
||||
{{ 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="#{{ bloc.name }}"> Valider </button>
|
||||
<a class="btn btn-danger mx-auto" href="/edit/images/del/{{ image.nom_fichier }}">Supprimer l'image</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
<section class="bg-primary" id="about">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 mx-auto text-center">
|
||||
<h2 class="section-heading text-white">{{ mesinfos.text.title }}</h2>
|
||||
<hr class="light my-4">
|
||||
<p class="text-faded mb-4"> {{ mesinfos.text.text }} </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -1,20 +0,0 @@
|
||||
<header class="masthead text-center text-white d-flex" style="background-image: url('/static/img/{{ bloc.bg_img }}');" id="{{ bloc.name }}" >
|
||||
<div class="container my-auto">
|
||||
<div class="row">
|
||||
<div class="col-lg-10 mx-auto">
|
||||
<h1 class="text-uppercase">
|
||||
<strong> {{ bloc.title }} </strong>
|
||||
</h1>
|
||||
<hr>
|
||||
</div>
|
||||
<div class="col-lg-8 mx-auto">
|
||||
<p class="text-faded mb-5"> {{ bloc.text }} </p>
|
||||
<a class="btn btn-primary btn-xl js-scroll-trigger" href="#">{{ bloc.text_button }}
|
||||
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
|
||||
<form id="uploader" methods="POST" class="dropzone dz-clickable"></form>
|
||||
|
||||
{% include theme+'/blocs/edit/images_list.html' %}
|
||||
|
||||
{% include '_js_dropzone.html' %}
|
||||
@@ -1,30 +0,0 @@
|
||||
{% extends 'creative/_layout.html' %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
{% include theme+'/_nav.html' %}
|
||||
{% include theme+'/_navtool.html' %}
|
||||
|
||||
|
||||
{% for bloc in myblocs.values() %}
|
||||
|
||||
{% if blocEdit == bloc.name %}
|
||||
{% include theme+'/_'+bloc.type+'-edit.html' %}
|
||||
{% else %}
|
||||
|
||||
{% include theme+'/_'+bloc.type+'.html' %}
|
||||
|
||||
<button class="btn btn-success btn-xl pull-right"
|
||||
style="margin-top:-7rem; margin-right:1rem;"
|
||||
hx-get="/edit/{{ bloc.name }}"
|
||||
hx-target="#{{bloc.name}}"
|
||||
hw-swap="none"
|
||||
> Éditer </button>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,15 +0,0 @@
|
||||
{% extends "creative/layout.html" %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<!-- Navigation -->
|
||||
{% include 'creative/_nav.html' %}
|
||||
|
||||
{% for bloc in myblocs.values() %}
|
||||
|
||||
{% include 'creative/_'+bloc.type+'.html' %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,15 +0,0 @@
|
||||
{% extends "creative/layout.html" %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<!-- Navigation -->
|
||||
{% include 'creative/_nav.html' %}
|
||||
|
||||
{% for bloc in myblocs.values() %}
|
||||
|
||||
{% include 'creative/_'+bloc.type+'.html' %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,19 +0,0 @@
|
||||
{# creative/layout.html #}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
|
||||
<head>
|
||||
<!-- Style CSS -->
|
||||
{% include 'creative/_head.html' %}
|
||||
</head>
|
||||
|
||||
<body id="page-top">
|
||||
{% block body %}
|
||||
|
||||
{% endblock %}
|
||||
</body>
|
||||
|
||||
{% include 'creative/javascript.html' %}
|
||||
|
||||
</html>
|
||||
@@ -1,10 +1,31 @@
|
||||
<div class="text-center mx-auto">
|
||||
<button class="btn btn-success"
|
||||
hx-post='/edit/{{ bloc.name }}'
|
||||
hx-swap="outerHTML"
|
||||
onclick="saveText()"
|
||||
hx-post='{% if page %}/{{ page }}{% endif %}/edit/{{ bloc.name }}'
|
||||
hx-swap="outerHTML swap:100ms"
|
||||
hx-target="#{{ bloc.name }}" > Enregistrer </button>
|
||||
|
||||
|
||||
<button class="btn btn-danger"
|
||||
hx-get="/view/{{ bloc.name }}"
|
||||
onclick="enableModBtn()"
|
||||
hx-get="{% if page %}/{{ page }}{% endif %}/view/{{ bloc.name }}"
|
||||
hx-swap="outerHTML"
|
||||
hx-target="#{{ bloc.name }}" > Annuler </button>
|
||||
</div>
|
||||
<script>
|
||||
function enableModBtn(){
|
||||
document.getElementById("modify-{{ bloc.name }}").disabled = false;
|
||||
}
|
||||
|
||||
function saveText(){
|
||||
|
||||
editor_content = document.getElementById("editor");
|
||||
if (editor_content != null)
|
||||
{
|
||||
document.getElementById("text").innerHTML = quill.getSemanticHTML(0);
|
||||
delete quill;
|
||||
}
|
||||
enableModBtn();
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
4
app/templates/edit-tools/_disable-modify-button.html
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
<script>
|
||||
document.getElementById("modify-{{ bloc.name }}").disabled = true;
|
||||
</script>
|
||||
52
app/templates/edit-tools/_editor-wysiwyg.html
Normal file
@@ -0,0 +1,52 @@
|
||||
|
||||
<div id="editor">
|
||||
{{ bloc.text|safe }}
|
||||
</div>
|
||||
<br/>
|
||||
<textarea style="display :none;" id="text" name="text"> </textarea>
|
||||
|
||||
<!-- Initialize Quill editor -->
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
var toolbarOptions = [
|
||||
['bold', 'italic', 'underline', 'strike'], // toggled buttons
|
||||
['blockquote', 'code-block'],
|
||||
['link', 'image'],
|
||||
|
||||
[{ 'header': 2 }, { 'header': 3 }, { 'header': 4},], // custom button values
|
||||
[{ 'list': 'ordered'}, { 'list': 'bullet' }, { 'list': 'check' }],
|
||||
[{ 'script': 'sub'}, { 'script': 'super' }], // superscript/subscript
|
||||
[{ 'indent': '-1'}, { 'indent': '+1' }], // outdent/indent
|
||||
[{ 'direction': 'rtl' }], // text direction
|
||||
|
||||
[{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown
|
||||
[{ 'header': [ 2, 3, 4, 5, 6, false] }],
|
||||
|
||||
[{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme
|
||||
[{ 'font': [] }],
|
||||
[{ 'align': [] }],
|
||||
|
||||
['clean'] // remove formatting button
|
||||
];
|
||||
var quill = new Quill('#editor', {
|
||||
modules: {
|
||||
syntax: true, // Include syntax module
|
||||
toolbar: toolbarOptions // Include button in toolbar
|
||||
},
|
||||
theme: 'snow'
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.ql-container {
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
.ql-editor {
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
|
||||
<h3> Nom du bloc : {{ bloc.name }} </h3>
|
||||
<div class="row mx-md-5">
|
||||
<div class="col-auto">
|
||||
<label> Nom du bloc </label>
|
||||
{{ form.name(col=4,value=bloc.name,
|
||||
<label> Classes CSS </label>
|
||||
{{ form.property(col=4,value=bloc.property,
|
||||
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") }}
|
||||
class="form-control form-control-color text-center",
|
||||
value=bloc.bg_color) }}
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<label> Couleur du texte</label>
|
||||
{{ form.fg_color(col=4,
|
||||
class="form-control form-control-color text-center") }}
|
||||
class="form-control form-control-color text-center",
|
||||
value=bloc.fg_color) }}
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
@@ -15,4 +15,9 @@
|
||||
.msginfo .error{
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.ql-toolbar {
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
<style>
|
||||
|
||||
.msginfo
|
||||
{
|
||||
color: white;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
.msginfo .success
|
||||
{
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.msginfo .error{
|
||||
background-color: red;
|
||||
}
|
||||
</style>
|
||||
@@ -2,27 +2,38 @@
|
||||
|
||||
{% block css %}
|
||||
{% include 'edit-tools/css/dropzone' %}
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css" rel="stylesheet">
|
||||
<link href="/static/css/edit-toolbar.css" rel="stylesheet">
|
||||
|
||||
<link href="/static/css/prism.min.css" rel="stylesheet">
|
||||
<!-- Include the highlight.js library -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/quill@2.0.3/dist/quill.snow.css" rel="stylesheet" />
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
{% include config.theme+'/_nav.html' %}
|
||||
{% include config.theme+'/_navtool.html' %}
|
||||
{% include 'themes/'+config.theme+'/_nav.html' %}
|
||||
{% include 'admin/_menu-admin.html' %}
|
||||
|
||||
{% macro print_colors() %}
|
||||
{% endmacro %}
|
||||
|
||||
{% for bloc in myblocs.values() %}
|
||||
|
||||
{% if blocEdit == bloc.name %}
|
||||
{% include config.theme+'/blocs/edit/_'+bloc.type+'.html' %}
|
||||
{% else %}
|
||||
{% include config.theme+'/blocs/_'+bloc.type+'.html' %}
|
||||
|
||||
<button class="btn btn-success btn-xl pull-right"
|
||||
style="margin-top:-7rem; margin-right:1rem;"
|
||||
hx-get="/edit/{{ bloc.name }}"
|
||||
hx-target="#{{bloc.name}}"
|
||||
hx-swap="oob"> Modifier </button>
|
||||
{% include 'themes/'+config.theme+'/blocs/edit/_'+bloc.type+'.html' %}
|
||||
|
||||
{% else %}
|
||||
|
||||
{% include 'themes/'+config.theme+'/blocs/_'+bloc.type+'.html' %}
|
||||
|
||||
<button class="btn btn-success btn-xl pull-right"
|
||||
id="modify-{{ bloc.name }}"
|
||||
style="margin-top:-7rem; margin-right:1rem;"
|
||||
hx-get="{% if page %}/{{ page }}{% endif %}/edit/{{ bloc.name }}"
|
||||
hx-target="#{{bloc.name}}"
|
||||
hx-swap="oob"> Modifier </button>
|
||||
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -31,5 +42,13 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<!-- Include the Quill library -->
|
||||
|
||||
<script src="/static/vendors/htmx/htmx.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/languages/cpp.min.js"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/quill@2.0.3/dist/quill.js"></script>
|
||||
|
||||
<script src="/static/js/prism.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<head>
|
||||
<!-- Style CSS -->
|
||||
{% include config.theme+'/_head.html' %}
|
||||
{% include 'themes/'+config.theme+'/_head.html' %}
|
||||
{% block css %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
@@ -11,17 +11,17 @@
|
||||
<body id="page-top">
|
||||
{% block body %}
|
||||
|
||||
{% include config.theme+'/_nav.html' %}
|
||||
{% include 'themes/'+config.theme+'/_nav.html' %}
|
||||
|
||||
{% for bloc in myblocs.values() %}
|
||||
{% include config.theme+'/blocs/_'+bloc.type+'.html' %}
|
||||
{% include 'themes/'+config.theme+'/blocs/_'+bloc.type+'.html' %}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% endblock %}
|
||||
</body>
|
||||
|
||||
{% include config.theme+'/javascript.html' %}
|
||||
{% include 'themes/'+config.theme+'/javascript.html' %}
|
||||
{% block js %}
|
||||
{% endblock js %}
|
||||
</html>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="{{ item }}">
|
||||
{% for subitem in menu[item].keys() %}
|
||||
<a class="dropdown-item" href="{{item[subitem]}}">{{ subitem }}</a>
|
||||
<a class="dropdown-item" href="{{menu[item][subitem]}}">{{ subitem }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</li>
|
||||
@@ -1,11 +1,10 @@
|
||||
<section class="bg-primary" id="{{ bloc.name }}">
|
||||
<section class="bg-primary {{ bloc.property }}" id="about">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 mx-auto text-center">
|
||||
<h2 class="section-heading text-white">{{ bloc.title }}</h2>
|
||||
<hr class="light my-4">
|
||||
<p class="text-faded mb-4"> {{ bloc.text }} </p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,4 +1,4 @@
|
||||
<section id="contact" >
|
||||
<section id="contact" class="{{ bloc.property }}" style="{% include '_print_colors.css' %}">
|
||||
<div class="container" id="{{ bloc.name }}">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 mx-auto text-center">
|
||||
@@ -1,7 +1,7 @@
|
||||
<section class="bg-dark text-white" id="{{ bloc.name }}" hx-swap-oob="true" >
|
||||
<section class="{{ bloc.property }}" style="{% include '_print_colors.css' %}" id="{{ bloc.name }}" >
|
||||
<div class="container text-center">
|
||||
<h2 class="mb-4">{{ bloc.title }}</h2>
|
||||
<p> {{ bloc.text }} </p>
|
||||
{{ bloc.text|safe }}
|
||||
<a class="btn btn-light btn-xl sr-button" href="{{ bloc.link }}">
|
||||
{{ bloc.text_button }}
|
||||
</a>
|
||||
@@ -1,12 +1,14 @@
|
||||
|
||||
<section class="p-0" id="{{ bloc.name }}">
|
||||
<section class="p-0 {{ bloc.property }}" id="{{ bloc.name }}">
|
||||
<div class="container-fluid p-0">
|
||||
<div class="row no-gutters popup-gallery">
|
||||
{% for image in bloc.values() %}
|
||||
{% if image.file %}
|
||||
<div class="col-lg-4 col-sm-6 text-center">
|
||||
<a class="portfolio-box" href="/static/img/portfolio/fullsize/{{ image.file }}" alt="{{ image.description }}">
|
||||
<img class="img-fluid" src="/static/img/portfolio/thumbnails/{{ image.file }}" alt="{{ image.description }}">
|
||||
<a class="portfolio-box" href="/public/img/{{ image.file }}"
|
||||
alt="{{ image.description }}">
|
||||
<img class="img-fluid" src="/public/img/thumbnails/{{ image.file }}"
|
||||
alt="{{ image.description }}">
|
||||
<div class="portfolio-box-caption">
|
||||
<div class="portfolio-box-caption-content">
|
||||
<div class="project-category text-faded">
|
||||
14
app/templates/themes/creative/blocs/_head_image.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<header class="article-img text-center text-white d-flex" style="{% include '_print_colors.css' %} background-image: url('/public/img/{{ bloc.bg_img }}');" id="{{ bloc.name }}" >
|
||||
<div class="container my-auto">
|
||||
<div class="row" style="mix-blend-mode: hard-light;background-color: rgba(0,0,0,0.3);">
|
||||
<div class="col-lg-10 mx-auto">
|
||||
<h1 class="text-uppercase">
|
||||
<strong> {{ bloc.title }} </strong>
|
||||
</h1>
|
||||
<hr>
|
||||
<h3> {{ bloc.subtitle }} </h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
25
app/templates/themes/creative/blocs/_presentation.html
Normal file
@@ -0,0 +1,25 @@
|
||||
<header class="masthead text-center text-white d-flex" style="{% include '_print_colors.css' %} background-image: url('/public/img/{{ bloc.bg_img }}');" id="{{ bloc.name }}" >
|
||||
<div class="container my-auto">
|
||||
<div class="row" style="mix-blend-mode: hard-light;background-color: rgba(0,0,0,0.3);">
|
||||
<div class="col-lg-10 mx-auto">
|
||||
<h1 class="text-uppercase">
|
||||
<strong> {{ bloc.title }} </strong>
|
||||
</h1>
|
||||
<hr>
|
||||
</div>
|
||||
<div class="col-lg-10 mx-auto">
|
||||
<p class="text-faded mb-5"> {{ bloc.text|safe }} </p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="center mx-auto mt-5">
|
||||
<a class="btn btn-primary btn-xl js-scroll-trigger" href="{{ bloc.link }}">
|
||||
{{ bloc.text_button }}
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</header>
|
||||
|
||||
11
app/templates/themes/creative/blocs/_simple_article.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<section class="{{ bloc.property }}" id="{{ bloc.name }}" style="{{print_colors()}}" >
|
||||
<h2 class="section-heading text-center">{{ bloc.title }}</h2>
|
||||
<hr class="my-4">
|
||||
|
||||
<div class="container">
|
||||
<div class="col-lg-8 mx-auto">
|
||||
<p class="mb-4"> {{ bloc.text|safe }} </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
8
app/templates/themes/creative/blocs/_text.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<section class="{{ bloc.property }}" id="{{ bloc.name }}" style="{% include '_print_colors.css' %}">
|
||||
<div class="container">
|
||||
<div class="px-3 mx-auto">
|
||||
{{ bloc.text|safe }}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -50,3 +50,4 @@
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
{% include 'edit-tools/_disable-modify-button.html' %}
|
||||
@@ -7,8 +7,8 @@
|
||||
{{ form.title(value=bloc.title,
|
||||
class="form-control form-control-lg text-center") }}
|
||||
<h3> Description du lien </h3>
|
||||
{{ form.text(value=bloc.text,
|
||||
class="form-control text-center") }}
|
||||
{% include 'edit-tools/_editor-wysiwyg.html' %}
|
||||
|
||||
<h3> Votre lien (https://exemple.com) </h3>
|
||||
{{ form.link(value=bloc.link, class="form-control text-center") }}
|
||||
<br />
|
||||
@@ -23,4 +23,4 @@
|
||||
{% include 'edit-tools/_btn-save-cancel.html' %}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% include 'edit-tools/_disable-modify-button.html' %}
|
||||
12
app/templates/themes/creative/blocs/edit/_gallery.html
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
<form id="uploader" methods="POST" class="dropzone dz-clickable">
|
||||
{{ form.csrf_token }}
|
||||
</form>
|
||||
<div hx-get="{{ url_for('imagesList', page=page, blocname=bloc.name) }}" hx-trigger="load, every 7s">
|
||||
|
||||
</div>
|
||||
|
||||
<div id="editImage">
|
||||
</div>
|
||||
{% include '_js_dropzone.html' %}
|
||||
{% include 'edit-tools/_disable-modify-button.html' %}
|
||||
43
app/templates/themes/creative/blocs/edit/_head_image.html
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
<div class="container my-auto pt-5" style="background-color: rgba(0,0,0,0.3);">
|
||||
<form method='POST' action='/edit/{{ bloc.name }}' enctype="multipart/form-data" hx-swap="outerHTML" hx-target="#{{ bloc.name }}" hx-encoding="multipart/form-data">
|
||||
{{ form.csrf_token }}
|
||||
|
||||
|
||||
<div class="container my-auto">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-lg-10 form-group mx-auto">
|
||||
{% include 'edit-tools/_form-base.html' %}
|
||||
{{ form.title(value=bloc.title,
|
||||
class="form-control form-control-lg text-center text-uppercase")
|
||||
}}
|
||||
{% for error in form.title.errors %}
|
||||
<span style="color: red;">{{ error }}</span>
|
||||
{% endfor %}
|
||||
<hr>
|
||||
</div>
|
||||
<div class="col-lg-10 form-group mx-auto">
|
||||
{{ form.subtitle(value=bloc.subtitle,
|
||||
class="form-control form-control-lg text-center text-uppercase")
|
||||
}}
|
||||
{% for error in form.subtitle.errors %}
|
||||
<span style="color: red;">{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="col-lg-8 form-group mx-auto">
|
||||
{{ form.image(class="form-control" ) }}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
{% include 'edit-tools/_btn-save-cancel.html' %}
|
||||
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
{% include 'edit-tools/_disable-modify-button.html' %}
|
||||
@@ -1,10 +1,10 @@
|
||||
|
||||
<div class="container-fluid p-0">
|
||||
<div class="container-fluid p-0" id="editImageInfo">
|
||||
<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 }}">
|
||||
<img class="img-fluid" src="/public/img/thumbnails/{{ image.file }}" alt="{{ image.description }}">
|
||||
</div>
|
||||
<div class="col-lg-4 mx-auto my-4 text-center">
|
||||
<h3> Titre </h3>
|
||||
@@ -22,10 +22,13 @@
|
||||
{{ 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-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>
|
||||
hx-target="#editImageInfo"
|
||||
hx-swap="delete"> Valider </button>
|
||||
<button class="btn btn-danger mx-auto" hx-get="{{ url_for('delImage', page=page, bloc=bloc.name, image=image.file) }}"
|
||||
hx-swap="delete"
|
||||
hx-target="#editImageInfo"> Supprimer l'image</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="container my-auto">
|
||||
<form method='POST' action='/edit/{{ bloc.name }}' hx-swap="outerHTML" hx-target="#{{ bloc.name }}" enctype="multipart/form-data">
|
||||
<div class="container mt-5 py-5 pb-5" style="width:100%;">
|
||||
<form method='POST' action='/edit/{{ bloc.name }}' enctype="multipart/form-data" hx-swap="outerHTML" hx-target="#{{ bloc.name }}" hx-encoding="multipart/form-data">
|
||||
{{ form.csrf_token }}
|
||||
<div class="row">
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
</div>
|
||||
<div class="col-lg-8 form-group mx-auto">
|
||||
{% set f = form.text.process_data(bloc.text) %}
|
||||
<textarea class="form-control text-center" id="text" name="text"> {{ bloc.text }} </textarea>
|
||||
{% for error in form.text.errors %}
|
||||
{% include 'edit-tools/_editor-wysiwyg.html' %}
|
||||
|
||||
{% for error in form.text.errors %}
|
||||
<span style="color: red;">{{ error }}</span>
|
||||
{% endfor %}
|
||||
<br/>
|
||||
@@ -27,11 +28,11 @@
|
||||
<span style="color: red;">
|
||||
{{ error }}</span>
|
||||
{% endfor %}
|
||||
<h4> cible du bouton </h4>
|
||||
<h4> cible du bouton #bloc ou un lien (https://exemple.com) </h4>
|
||||
{{ form.link(value=bloc.link, class="form-control text-center") }}
|
||||
<br />
|
||||
</div>
|
||||
<div class="col-lg-3 form-group mx-auto">
|
||||
|
||||
<div class="col-lg-8 form-group mx-auto">
|
||||
{{ form.image(class="form-control" ) }}
|
||||
</div>
|
||||
{% include 'edit-tools/_btn-save-cancel.html' %}
|
||||
@@ -39,4 +40,4 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% include 'edit-tools/_disable-modify-button.html' %}
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
<form method='POST' action='/edit/{{ bloc.name }}' >
|
||||
{{ form.csrf_token }}
|
||||
@@ -9,12 +9,12 @@
|
||||
{{ form.title(col=5,value=bloc.title,
|
||||
class="form-control form-control-lg text-center") }}
|
||||
<hr class="light my-4">
|
||||
<textarea class="form-control text-center" id="text" name="text"> {{ bloc.text }} </textarea>
|
||||
<br/>
|
||||
{% include 'edit-tools/_btn-save-cancel.html' %}
|
||||
{% include 'edit-tools/_editor-wysiwyg.html' %}
|
||||
|
||||
{% include 'edit-tools/_btn-save-cancel.html' %}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% include 'edit-tools/_disable-modify-button.html' %}
|
||||
16
app/templates/themes/creative/blocs/edit/_text.html
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
<div class="container">
|
||||
<form method='POST' action='/edit/{{ bloc.name }}' >
|
||||
{{ form.csrf_token }}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-8 mx-auto text-center">
|
||||
{% include 'edit-tools/_form-base.html' %}
|
||||
{% include 'edit-tools/_editor-wysiwyg.html' %}
|
||||
</div>
|
||||
</div>
|
||||
{% include 'edit-tools/_btn-save-cancel.html' %}
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
{% include 'edit-tools/_disable-modify-button.html' %}
|
||||
@@ -1,11 +1,11 @@
|
||||
<section class="p-0">
|
||||
<section class="p-0" id="{{bloc.name}}">
|
||||
<div class="container-fluid p-0" id="editImg">
|
||||
<div class="row no-gutters ">
|
||||
{% for image in bloc.values() %}
|
||||
{% if image.file %}
|
||||
<div class="col-lg-4 col-sm-6 text-center">
|
||||
<a class="portfolio-box">
|
||||
<img class="img-fluid" src="/static/img/portfolio/thumbnails/{{ image.file }}" alt="{{ image.description }}">
|
||||
<img class="img-fluid" src="/public/img/thumbnails/{{ image.file }}" alt="{{ image.description }}">
|
||||
<div class="portfolio-box-caption">
|
||||
<div class="portfolio-box-caption-content">
|
||||
<div class="project-category text-faded">
|
||||
@@ -20,7 +20,7 @@
|
||||
</a>
|
||||
<button type="button" class="btn btn-success m-4"
|
||||
hx-get="/edit/images/{{ bloc.name }}/{{ image.file }}"
|
||||
hx-target="#editImg"
|
||||
hx-target="#editImage"
|
||||
hw-swap="none">
|
||||
<i class="fa fa-pencil-square-o"></i>
|
||||
</button>
|
||||
@@ -1,4 +1,9 @@
|
||||
|
||||
<script>
|
||||
function rm_node(idName){
|
||||
const element = document.getElementById(idName);
|
||||
element.remove();
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Bootstrap core JavaScript -->
|
||||
<script src="/static/vendors/jquery/jquery.min.js"></script>
|
||||
22
app/templates/themes/creative/pages/article_image.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"blocs": {
|
||||
"bloc0": {
|
||||
"type": "head_image",
|
||||
"name": "bloc0",
|
||||
"bg_color": "#000000",
|
||||
"fg_color": "#000000",
|
||||
"title": "PAge avec une image de presentation",
|
||||
"bg_img": "bg_custom_bloc0image_entete_exemple.jpg",
|
||||
"property": "",
|
||||
"subtitle": "Votre sous-titre"
|
||||
},
|
||||
"bloc1": {
|
||||
"name": "bloc1",
|
||||
"type": "text",
|
||||
"text": "<h3>Votre\u00a0texte\u00a0libre\u00a0!\u00a0</h3><p></p><p>Vous\u00a0pouvez\u00a0\u00e9crire\u00a0ce\u00a0que\u00a0vous\u00a0voulez\u00a0ici</p>",
|
||||
"bg_color": "#000000",
|
||||
"fg_color": "#000000",
|
||||
"property": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
20
app/templates/themes/creative/pages/simple_article.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"blocs": {
|
||||
"test_bloc": {
|
||||
"name": "test_bloc",
|
||||
"type": "text",
|
||||
"title": "Salut c'est moi et ... voila quoi !!!!",
|
||||
"text": "<h2 class=\"ql-align-center\">Votre\u00a0titre\u00a0</h2><pre data-language=\"bash\">\n#!/bin/bash\necho \"Un exemple de code\"\n</pre><p></p><h2>Titre\u00a02</h2><h3>Titre\u00a03</h3><h4>Titre\u00a04\u00a0</h4><p></p><p class=\"ql-align-right\"><span style=\"background-color: rgb(255, 153, 0);\">Youpi\u00a0!!!!!!!!!!!!!!!</span></p><p class=\"ql-align-center\"></p><blockquote>Une\u00a0citation</blockquote><p></p><p></p><p>Vous\u00a0pouvez\u00a0aussi\u00a0empiler\u00a0les\u00a0blocs\u00a0de\u00a0texte\u00a0poiur\u00a0les\u00a0mettre\u00a0de\u00a0couleur\u00a0diff\u00e9rentes\u00a0par\u00a0exemple\u00a0</p><p></p><p></p>",
|
||||
"bg_color": "#000000",
|
||||
"fg_color": "#000000",
|
||||
"text_button": null,
|
||||
"link": null,
|
||||
"email": null,
|
||||
"address": null,
|
||||
"phone": null,
|
||||
"postal_code": null,
|
||||
"city": null,
|
||||
"property": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
451
app/templates/themes/creative/static/css/creative.css
Normal file
@@ -0,0 +1,451 @@
|
||||
body,
|
||||
html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Merriweather', 'Helvetica Neue', Arial, sans-serif;
|
||||
}
|
||||
|
||||
hr {
|
||||
max-width: 50px;
|
||||
border-width: 3px;
|
||||
border-color: #F05F40;
|
||||
}
|
||||
|
||||
hr.light {
|
||||
border-color: #fff;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #F05F40;
|
||||
-webkit-transition: all 0.2s;
|
||||
-moz-transition: all 0.2s;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.btn-success{
|
||||
z-index: 999;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.img-fluid {
|
||||
position: relative;
|
||||
z-index:-30;
|
||||
}
|
||||
a:hover {
|
||||
color: #f05f40;
|
||||
}
|
||||
|
||||
.modal-backdrop{
|
||||
z-index:auto
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
|
||||
}
|
||||
|
||||
.bg-primary {
|
||||
background-color: #F05F40 !important;
|
||||
}
|
||||
|
||||
.bg-dark {
|
||||
background-color: #212529 !important;
|
||||
}
|
||||
|
||||
.text-faded {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.ql-align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ql-align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ql-align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
padding: 60px 80px 40px;
|
||||
position: relative;
|
||||
}
|
||||
blockquote p {
|
||||
font-size: 35px;
|
||||
font-weight: 700px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*blockquote p::before {
|
||||
content: "\f095";
|
||||
font-family: FontAwesome;
|
||||
display: inline-block;
|
||||
padding-right: 6px;
|
||||
vertical-align: middle;
|
||||
font-size: 180px;
|
||||
}*/
|
||||
|
||||
blockquote:before {
|
||||
position: absolute;
|
||||
font-family: 'FontAwesome';
|
||||
top: 0;
|
||||
content:"\f10d";
|
||||
font-size: 200px;
|
||||
color: rgba(0,0,0,0.1);
|
||||
|
||||
}
|
||||
|
||||
blockquote::after {
|
||||
content: "";
|
||||
top: 20px;
|
||||
left: 50%;
|
||||
margin-left: -100px;
|
||||
position: absolute;
|
||||
height: 3px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
blockquote{
|
||||
font-size: 1.4em;
|
||||
width:60%;
|
||||
margin:50px auto;
|
||||
font-style:italic;
|
||||
color: #555555;
|
||||
padding:1.2em 30px 1.2em 75px;
|
||||
border-left:8px solid #f05f40;
|
||||
line-height:1.6;
|
||||
position: relative;
|
||||
background:#EDEDED;
|
||||
}
|
||||
|
||||
blockquote::before{
|
||||
font-family:Arial;
|
||||
content: "\201C";
|
||||
color:#f05f40;
|
||||
font-size:4em;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top:-10px;
|
||||
}
|
||||
|
||||
blockquote::after{
|
||||
content: '';
|
||||
}
|
||||
|
||||
blockquote span{
|
||||
display:block;
|
||||
color:#333333;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
margin-top:1em;
|
||||
}
|
||||
|
||||
section {
|
||||
padding: 8rem 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.section-heading {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
::-moz-selection {
|
||||
color: #fff;
|
||||
background: #212529;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
::selection {
|
||||
color: #fff;
|
||||
background: #212529;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
img::selection {
|
||||
color: #fff;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
img::-moz-selection {
|
||||
color: #fff;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#mainNav {
|
||||
border-bottom: 1px solid rgba(33, 37, 41, 0.1);
|
||||
background-color: #fff;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
|
||||
-webkit-transition: all 0.2s;
|
||||
-moz-transition: all 0.2s;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
#mainNav .navbar-brand {
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
color: #F05F40;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
|
||||
}
|
||||
|
||||
#mainNav .navbar-brand:focus, #mainNav .navbar-brand:hover {
|
||||
color: #f05f40;
|
||||
}
|
||||
|
||||
#mainNav .navbar-nav > li.nav-item > a.nav-link,
|
||||
#mainNav .navbar-nav > li.nav-item > a.nav-link:focus {
|
||||
font-size: .9rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
color: #212529;
|
||||
}
|
||||
|
||||
#mainNav .navbar-nav > li.nav-item > a.nav-link:hover,
|
||||
#mainNav .navbar-nav > li.nav-item > a.nav-link:focus:hover {
|
||||
color: #F05F40;
|
||||
}
|
||||
|
||||
#mainNav .navbar-nav > li.nav-item > a.nav-link.active,
|
||||
#mainNav .navbar-nav > li.nav-item > a.nav-link:focus.active {
|
||||
color: #F05F40 !important;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#mainNav .navbar-nav > li.nav-item > a.nav-link.active:hover,
|
||||
#mainNav .navbar-nav > li.nav-item > a.nav-link:focus.active:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
#mainNav {
|
||||
border-color: transparent;
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
}
|
||||
#mainNav .navbar-brand {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
#mainNav .navbar-brand:focus, #mainNav .navbar-brand:hover {
|
||||
color: #fff;
|
||||
}
|
||||
#mainNav .navbar-nav > li.nav-item > a.nav-link {
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
#mainNav .navbar-nav > li.nav-item > a.nav-link,
|
||||
#mainNav .navbar-nav > li.nav-item > a.nav-link:focus {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
#mainNav .navbar-nav > li.nav-item > a.nav-link:hover,
|
||||
#mainNav .navbar-nav > li.nav-item > a.nav-link:focus:hover {
|
||||
color: #fff;
|
||||
}
|
||||
#mainNav.navbar-shrink {
|
||||
border-bottom: 1px solid rgba(33, 37, 41, 0.1);
|
||||
background-color: #fff;
|
||||
}
|
||||
#mainNav.navbar-shrink .navbar-brand {
|
||||
color: #F05F40;
|
||||
}
|
||||
#mainNav.navbar-shrink .navbar-brand:focus, #mainNav.navbar-shrink .navbar-brand:hover {
|
||||
color: #f05f40;
|
||||
}
|
||||
#mainNav.navbar-shrink .navbar-nav > li.nav-item > a.nav-link,
|
||||
#mainNav.navbar-shrink .navbar-nav > li.nav-item > a.nav-link:focus {
|
||||
color: #212529;
|
||||
}
|
||||
#mainNav.navbar-shrink .navbar-nav > li.nav-item > a.nav-link:hover,
|
||||
#mainNav.navbar-shrink .navbar-nav > li.nav-item > a.nav-link:focus:hover {
|
||||
color: #F05F40;
|
||||
}
|
||||
}
|
||||
|
||||
header.masthead {
|
||||
padding-top: 10rem;
|
||||
padding-bottom: calc(10rem - 56px);
|
||||
background-position: center center;
|
||||
-webkit-background-size: cover;
|
||||
-moz-background-size: cover;
|
||||
-o-background-size: cover;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
header.article-img {
|
||||
padding-top: 10rem;
|
||||
padding-bottom: calc(10rem - 56px);
|
||||
background-position: center center;
|
||||
-webkit-background-size: cover;
|
||||
-moz-background-size: cover;
|
||||
-o-background-size: cover;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
|
||||
header.article-img header.masthead hr {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
header.article-img header.masthead h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
header.article-img header.masthead p {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
header.masthead p {
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
header.article-img {
|
||||
height: 50vh;
|
||||
min-height: 300px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
header.masthead {
|
||||
height: 100vh;
|
||||
min-height: 650px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
header.article-img header.masthead h1 {
|
||||
font-size: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
header.article-img header.masthead h1 {
|
||||
font-size: 4rem;
|
||||
}
|
||||
.btn-success {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.service-box {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
|
||||
.portfolio-box {
|
||||
position: relative;
|
||||
display: block;
|
||||
max-width: 650px;
|
||||
margin: 0 auto;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.portfolio-box .portfolio-box-caption {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
opacity: 0;
|
||||
color: #fff;
|
||||
background: rgba(240, 95, 64, 0.9);
|
||||
-webkit-transition: all 0.2s;
|
||||
-moz-transition: all 0.2s;
|
||||
transition: all 0.2s;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 100%;
|
||||
transform: translateY(-50%);
|
||||
text-align: center;
|
||||
z-index:-10;
|
||||
}
|
||||
|
||||
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-category,
|
||||
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-name {
|
||||
padding: 0 15px;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
|
||||
}
|
||||
|
||||
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-category {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-name {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.portfolio-box:hover .portfolio-box-caption {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.portfolio-box:focus {
|
||||
outline: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-category {
|
||||
font-size: 16px;
|
||||
}
|
||||
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-name {
|
||||
font-size: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: #F05F40 !important;
|
||||
}
|
||||
|
||||
.btn {
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
border: none;
|
||||
border-radius: 300px;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.btn-xl {
|
||||
padding: 1rem 2rem;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #F05F40;
|
||||
border-color: #F05F40;
|
||||
}
|
||||
|
||||
.btn-primary:hover, .btn-primary:focus, .btn-primary:active {
|
||||
color: #fff;
|
||||
background-color: #ee4b28 !important;
|
||||
}
|
||||
|
||||
.btn-primary:active, .btn-primary:focus {
|
||||
box-shadow: 0 0 0 0.2rem rgba(240, 95, 64, 0.5) !important;
|
||||
}
|
||||
|
||||
section.bg-dark p {
|
||||
|
||||
padding-bottom: 3rem;
|
||||
|
||||
}
|
||||
|
||||
section.bg-dark {
|
||||
padding-top: 3rem;
|
||||
padding-bottom: 3rem;
|
||||
}
|
||||
73
app/templates/themes/creative/static/css/fontes-creative.css
Normal file
@@ -0,0 +1,73 @@
|
||||
@font-face {
|
||||
font-family: 'Merryweather';
|
||||
src:url("../fontes/Merryweather/Merryweather-Regular.woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Merryweather';
|
||||
src:url("../fontes/Merryweather/Merryweather-Bold.woff");
|
||||
font-weight: bold;
|
||||
font-style: bold;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src:url("../fontes/OpenSans/open-sans-v15-latin-regular.woff2");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src:url("../fontes/OpenSans/open-sans-v15-latin-italic.woff2");
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src:url("../fontes/OpenSans/open-sans-v15-latin-300.woff2");
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src:url("../fontes/OpenSans/open-sans-v15-latin-300italic.woff2");
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src:url("../fontes/OpenSans/open-sans-v15-latin-600.woff2");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src:url("../fontes/OpenSans/open-sans-v15-latin-600italic.woff2");
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src:url("../fontes/OpenSans/open-sans-v15-latin-700.woff2");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src:url("../fontes/OpenSans/open-sans-v15-latin-700italic.woff2");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
31
app/templates/themes/creative/static/css/fontes.css
Normal file
@@ -0,0 +1,31 @@
|
||||
/*Import de fontes trouver sur font2u.com Bon site !!!! */
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lora';
|
||||
src:url("../fonts/Lora-Regular.woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Raleway';
|
||||
src:url("../fonts/Raleway-Regular.woff");
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Raleway';
|
||||
src:url("../fonts/Raleway-Bold.woff");
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family:'Lora-Italic';
|
||||
src:url("../fonts/Lora-Italic.woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family:'Roboto';
|
||||
src:url("../fonts/Roboto-Regular.woff");
|
||||
}
|
||||
|
||||
3
app/templates/themes/creative/static/css/prism.min.css
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/* PrismJS 1.30.0
|
||||
https://prismjs.com/download#themes=prism-okaidia&languages=markup+css+clike+javascript+bash+c+cpp+markdown+markup-templating+nginx+php+python */
|
||||
code[class*=language-],pre[data-language*=language-]{color:#f8f8f2;background:0 0;text-shadow:0 1px rgba(0,0,0,.3);font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}:not(pre)>code[class*=language-],pre[class*=language-]{background:#272822}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#8292a2}.token.punctuation{color:#f8f8f2}.token.namespace{opacity:.7}.token.constant,.token.deleted,.token.property,.token.symbol,.token.tag{color:#f92672}.token.boolean,.token.number{color:#ae81ff}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#a6e22e}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url,.token.variable{color:#f8f8f2}.token.atrule,.token.attr-value,.token.class-name,.token.function{color:#e6db74}.token.keyword{color:#66d9ef}.token.important,.token.regex{color:#fd971f}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}
|
||||
106
app/templates/themes/creative/static/js/creative.js
Normal file
@@ -0,0 +1,106 @@
|
||||
(function($) {
|
||||
"use strict"; // Start of use strict
|
||||
|
||||
// Smooth scrolling using jQuery easing
|
||||
$('a.js-scroll-trigger[href*="#"]:not([href="#"])').click(function() {
|
||||
if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) {
|
||||
var target = $(this.hash);
|
||||
target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
|
||||
if (target.length) {
|
||||
$('html, body').animate({
|
||||
scrollTop: (target.offset().top - 57)
|
||||
}, 1000, "easeInOutExpo");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Closes responsive menu when a scroll trigger link is clicked
|
||||
$('.js-scroll-trigger').click(function() {
|
||||
$('.navbar-collapse').collapse('hide');
|
||||
});
|
||||
|
||||
// Activate scrollspy to add active class to navbar items on scroll
|
||||
$('body').scrollspy({
|
||||
target: '#mainNav',
|
||||
offset: 57
|
||||
});
|
||||
|
||||
// Collapse Navbar
|
||||
var navbarCollapse = function() {
|
||||
if ($("#mainNav").offset().top > 100) {
|
||||
$("#mainNav").addClass("navbar-shrink");
|
||||
} else {
|
||||
$("#mainNav").removeClass("navbar-shrink");
|
||||
}
|
||||
};
|
||||
// Collapse now if page is not at top
|
||||
navbarCollapse();
|
||||
// Collapse the navbar when page is scrolled
|
||||
$(window).scroll(navbarCollapse);
|
||||
|
||||
// Scroll reveal calls
|
||||
window.sr = ScrollReveal();
|
||||
sr.reveal('.sr-icons', {
|
||||
duration: 600,
|
||||
scale: 0.3,
|
||||
distance: '0px'
|
||||
}, 200);
|
||||
sr.reveal('.sr-button', {
|
||||
duration: 1000,
|
||||
delay: 200
|
||||
});
|
||||
sr.reveal('.sr-contact', {
|
||||
duration: 600,
|
||||
scale: 0.3,
|
||||
distance: '0px'
|
||||
}, 300);
|
||||
|
||||
// Magnific popup calls
|
||||
$('.popup-gallery').magnificPopup({
|
||||
delegate: 'a',
|
||||
type: 'image',
|
||||
tLoading: 'Loading image #%curr%...',
|
||||
mainClass: 'mfp-img-mobile',
|
||||
gallery: {
|
||||
enabled: true,
|
||||
navigateByImgClick: true,
|
||||
preload: [0, 1]
|
||||
},
|
||||
image: {
|
||||
tError: '<a href="%url%">The image #%curr%</a> could not be loaded.'
|
||||
}
|
||||
});
|
||||
|
||||
$(".obfuscate").each(function () {
|
||||
|
||||
$(this).html($(this).html()
|
||||
.replace("__chez__", "@").replace(/\.\.\./g, ".")
|
||||
.replace(/Un/g, "1")
|
||||
.replace(/Deux/g, "2")
|
||||
.replace(/Trois/g, "3")
|
||||
.replace(/Quatre/g, "4")
|
||||
.replace(/Cinq/g, "5")
|
||||
.replace(/Six/g, "6")
|
||||
.replace(/Sept/g, "7")
|
||||
.replace(/Huit/g, "8")
|
||||
.replace(/Neuf/g, "9")
|
||||
.replace(/Zero/g, "0"))
|
||||
|
||||
$(this).attr("href", $(this).attr("href")
|
||||
.replace("__chez__", "@").replace(/\.\.\./g, ".")
|
||||
.replace(/Un/g, "1")
|
||||
.replace(/Deux/g, "2")
|
||||
.replace(/Trois/g, "3")
|
||||
.replace(/Quatre/g, "4")
|
||||
.replace(/Cinq/g, "5")
|
||||
.replace(/Six/g, "6")
|
||||
.replace(/Sept/g, "7")
|
||||
.replace(/Huit/g, "8")
|
||||
.replace(/Neuf/g, "9")
|
||||
.replace(/Zero/g, "0"))
|
||||
|
||||
});
|
||||
|
||||
|
||||
})(jQuery); // End of use strict
|
||||
15
app/templates/themes/creative/static/js/prism.js
Normal file
1912
app/templates/themes/creative/static/vendors/bootstrap/css/bootstrap-grid.css
vendored
Normal file
1
app/templates/themes/creative/static/vendors/bootstrap/css/bootstrap-grid.css.map
vendored
Normal file
7
app/templates/themes/creative/static/vendors/bootstrap/css/bootstrap-grid.min.css
vendored
Normal file
1
app/templates/themes/creative/static/vendors/bootstrap/css/bootstrap-grid.min.css.map
vendored
Normal file
331
app/templates/themes/creative/static/vendors/bootstrap/css/bootstrap-reboot.css
vendored
Normal file
@@ -0,0 +1,331 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2018 The Bootstrap Authors
|
||||
* Copyright 2011-2018 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: sans-serif;
|
||||
line-height: 1.15;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-ms-overflow-style: scrollbar;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
@-ms-viewport {
|
||||
width: device-width;
|
||||
}
|
||||
|
||||
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #212529;
|
||||
text-align: left;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
[tabindex="-1"]:focus {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
hr {
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title],
|
||||
abbr[data-original-title] {
|
||||
text-decoration: underline;
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: .5rem;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
-webkit-text-decoration-skip: objects;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #0056b3;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:not([href]):not([tabindex]) {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:not([href]):not([tabindex]):focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
-ms-overflow-style: scrollbar;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img {
|
||||
vertical-align: middle;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
svg {
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.75rem;
|
||||
padding-bottom: 0.75rem;
|
||||
color: #6c757d;
|
||||
text-align: left;
|
||||
caption-side: bottom;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: 1px dotted;
|
||||
outline: 5px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
input {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
button,
|
||||
html [type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
input[type="radio"],
|
||||
input[type="checkbox"] {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
input[type="date"],
|
||||
input[type="time"],
|
||||
input[type="datetime-local"],
|
||||
input[type="month"] {
|
||||
-webkit-appearance: listbox;
|
||||
}
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: .5rem;
|
||||
font-size: 1.5rem;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type="search"] {
|
||||
outline-offset: -2px;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
[type="search"]::-webkit-search-cancel-button,
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
||||
1
app/templates/themes/creative/static/vendors/bootstrap/css/bootstrap-reboot.css.map
vendored
Normal file
8
app/templates/themes/creative/static/vendors/bootstrap/css/bootstrap-reboot.min.css
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2018 The Bootstrap Authors
|
||||
* Copyright 2011-2018 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
|
||||
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
|
||||