Ajout déplacement blocs
This commit is contained in:
parent
9277154e0c
commit
8d07c38d32
|
|
@ -197,7 +197,8 @@ public class Bloc extends ParamBD {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void supprimerBloc(int idBloc, int idU) {
|
public static boolean supprimerBloc(int idBloc, int idU) {
|
||||||
|
boolean reponse = false;
|
||||||
try {
|
try {
|
||||||
Connection connexion = DriverManager.getConnection(bdURL, bdLogin, bdPassword);
|
Connection connexion = DriverManager.getConnection(bdURL, bdLogin, bdPassword);
|
||||||
String sql = " DELETE FROM bloc"
|
String sql = " DELETE FROM bloc"
|
||||||
|
|
@ -209,8 +210,32 @@ public class Bloc extends ParamBD {
|
||||||
pst.setInt(2, idU);
|
pst.setInt(2, idU);
|
||||||
pst.executeUpdate();
|
pst.executeUpdate();
|
||||||
|
|
||||||
|
pst.close();
|
||||||
|
connexion.close();
|
||||||
|
reponse = true;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return reponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void miseAJourOrdreBloc(int idBloc, int ordre) {
|
||||||
|
try {
|
||||||
|
Connection connexion = DriverManager.getConnection(bdURL, bdLogin, bdPassword);
|
||||||
|
String sql = " UPDATE bloc"
|
||||||
|
+ " SET ordre = ?"
|
||||||
|
+ " WHERE id = ?"
|
||||||
|
+ ";";
|
||||||
|
PreparedStatement pst = connexion.prepareStatement(sql);
|
||||||
|
pst.setInt(1, ordre);
|
||||||
|
pst.setInt(2, idBloc);
|
||||||
|
pst.executeUpdate();
|
||||||
|
|
||||||
|
pst.close();
|
||||||
|
connexion.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
package projet;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.annotation.WebServlet;
|
||||||
|
import jakarta.servlet.http.HttpServlet;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
import javax.json.Json;
|
||||||
|
import javax.json.JsonArray;
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
import javax.json.JsonReader;
|
||||||
|
|
||||||
|
|
||||||
|
@WebServlet("/SauvegarderOrdre")
|
||||||
|
public class SauvegarderOrdre extends HttpServlet {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|
||||||
|
public SauvegarderOrdre() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
HttpSession session = request.getSession();
|
||||||
|
Utilisateur u = (Utilisateur) session.getAttribute("utilisateur");
|
||||||
|
|
||||||
|
if(u != null) {
|
||||||
|
response.sendRedirect("AfficherPage");
|
||||||
|
}else {
|
||||||
|
response.sendRedirect("/Projet/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
response.setContentType("application/json");
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
|
||||||
|
HttpSession session = request.getSession();
|
||||||
|
Utilisateur u = (Utilisateur) session.getAttribute("utilisateur");
|
||||||
|
|
||||||
|
if (u == null) {
|
||||||
|
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
response.getWriter().write("{\"error\": \"Utilisateur non connecté\"}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try (BufferedReader reader = request.getReader()) {
|
||||||
|
StringBuilder json = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
json.append(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonReader jsonReader = Json.createReader(new StringReader(json.toString()));
|
||||||
|
JsonArray jsonArray = jsonReader.readArray();
|
||||||
|
|
||||||
|
for (int i = 0; i < jsonArray.size(); i++) {
|
||||||
|
JsonObject jsonObject = jsonArray.getJsonObject(i);
|
||||||
|
|
||||||
|
if (!jsonObject.containsKey("id") || !jsonObject.containsKey("ordre")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = Integer.parseInt(jsonObject.getString("id"));
|
||||||
|
int ordre = jsonObject.getInt("ordre");
|
||||||
|
|
||||||
|
Bloc.miseAJourOrdreBloc(id, ordre);
|
||||||
|
}
|
||||||
|
|
||||||
|
response.setStatus(HttpServletResponse.SC_OK);
|
||||||
|
response.getWriter().write("{\"success\": true}");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||||
|
response.getWriter().write("{\"error\": \"Données invalides ou erreur serveur\"}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -29,22 +29,35 @@ public class SupprimerBloc extends HttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
response.setContentType("application/json");
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
|
||||||
HttpSession session = request.getSession();
|
HttpSession session = request.getSession();
|
||||||
Utilisateur u = (Utilisateur) session.getAttribute("utilisateur");
|
Utilisateur u = (Utilisateur) session.getAttribute("utilisateur");
|
||||||
|
|
||||||
if(u != null) {
|
if (u == null) {
|
||||||
String idBlocStr = request.getParameter("blocId");
|
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
response.getWriter().write("{\"error\": \"Non autorisé\"}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(idBlocStr == null || idBlocStr.isEmpty()) {
|
String idBlocStr = request.getParameter("blocId");
|
||||||
response.sendRedirect("AfficherPage");
|
|
||||||
} else {
|
|
||||||
int idBloc = Integer.parseInt(idBlocStr);
|
|
||||||
Bloc.supprimerBloc(idBloc, u.getId());
|
|
||||||
response.sendRedirect("AfficherPage");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (idBlocStr == null || idBlocStr.isEmpty()) {
|
||||||
|
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||||
|
response.getWriter().write("{\"error\": \"ID manquant\"}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idBloc = Integer.parseInt(idBlocStr);
|
||||||
|
boolean success = Bloc.supprimerBloc(idBloc, u.getId());
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
response.setStatus(HttpServletResponse.SC_OK);
|
||||||
|
response.getWriter().write("{\"success\": true}");
|
||||||
} else {
|
} else {
|
||||||
response.sendRedirect("/Projet/");
|
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||||
|
response.getWriter().write("{\"error\": \"Suppression interdite\"}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,37 @@
|
||||||
<jsp:param name="titre" value="Accueil" />
|
<jsp:param name="titre" value="Accueil" />
|
||||||
</jsp:include>
|
</jsp:include>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<div class="container">
|
||||||
|
<div class="columns is-centered">
|
||||||
|
<div class="column is-two-thirds">
|
||||||
|
<div class="box has-background-light">
|
||||||
|
<h1 class="title is-3 icon-text">
|
||||||
|
<span class="icon has-text-info"><i class="fas fa-pencil-alt"></i></span>
|
||||||
|
<span>Bienvenue sur notre plateforme de prise de notes collaborative</span>
|
||||||
|
</h1>
|
||||||
|
<p class="content">
|
||||||
|
Ce site vous permet de créer facilement des pages de contenu interactives en utilisant du <strong>Markdown</strong>, d’organiser vos idées en blocs, et de collaborer en temps réel avec d’autres utilisateurs.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Éditeur intelligent :</strong> avec support des titres, listes, citations, et mise en forme automatique.</li>
|
||||||
|
<li><strong>Partage de pages :</strong> invitez vos collaborateurs avec un accès en lecture ou en édition.</li>
|
||||||
|
<li><strong>Sauvegarde en temps réel :</strong> vos modifications sont automatiquement enregistrées et partagées.</li>
|
||||||
|
</ul>
|
||||||
|
<p class="content mt-5">
|
||||||
|
Une fois votre travail terminé, vous pouvez <strong>exporter vos pages</strong> dans plusieurs formats :
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>HTML — pour une intégration facile sur le web</li>
|
||||||
|
<li>LaTeX — idéal pour des documents scientifiques ou académiques</li>
|
||||||
|
<li>Markdown — pour garder un format brut et portable</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<c:set var="erreur" value="${erreur}" />
|
<c:set var="erreur" value="${erreur}" />
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
<c:when test="${not empty page.titre}">
|
<c:when test="${not empty page.titre}">
|
||||||
<div class="is-flex is-justify-content-space-between is-align-items mb-4">
|
<div class="is-flex is-justify-content-space-between is-align-items mb-4">
|
||||||
<h2 class="block">
|
<h2 class="block">
|
||||||
|
<a href = "AfficherPage"><i class="fa-solid fa-house-chimney"></i></a> >
|
||||||
<c:forEach var="entry" items="${hierarchie}">
|
<c:forEach var="entry" items="${hierarchie}">
|
||||||
<a href="AfficherPage?id=${entry.key}">${entry.value}</a> >
|
<a href="AfficherPage?id=${entry.key}">${entry.value}</a> >
|
||||||
</c:forEach>
|
</c:forEach>
|
||||||
|
|
@ -87,7 +88,87 @@
|
||||||
</div>
|
</div>
|
||||||
</c:when>
|
</c:when>
|
||||||
<c:otherwise>
|
<c:otherwise>
|
||||||
<p>Pas encore de page choisie.</p>
|
<a href = "AfficherPage"><i class="fa-solid fa-house-chimney"></i></a>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="title is-3 icon-text">
|
||||||
|
<span>Rappel des Instructions</span>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<h2 class="title is-4 icon-text">
|
||||||
|
<span class="icon has-text-info"><i class="fas fa-terminal"></i></span>
|
||||||
|
<span>Commandes Slash</span>
|
||||||
|
</h2>
|
||||||
|
<p>Dans un bloc, tapez une commande commençant par <code>/</code> :</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>/h1</code>, <code>/h2</code>, <code>/h3</code> → transforme le bloc en titre de niveau 1, 2 ou 3</li>
|
||||||
|
<li><code>/ul</code> → transforme en liste à puces</li>
|
||||||
|
<li><code>/ol</code> → transforme en liste numérotée</li>
|
||||||
|
<li><code>/code</code> → transforme en bloc de code (optionnel : nom du langage)</li>
|
||||||
|
<li><code>/hr</code> → insère une ligne de séparation</li>
|
||||||
|
<li><code>/page [titre]</code> → crée une nouvelle page liée avec le titre donné</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<h2 class="title is-4 icon-text">
|
||||||
|
<span class="icon has-text-link"><i class="fas fa-heading"></i></span>
|
||||||
|
<span>Markdown <em>en début de bloc</em> (type de contenu)</span>
|
||||||
|
</h2>
|
||||||
|
<p>Si le bloc commence par un de ces symboles :</p>
|
||||||
|
<ul>
|
||||||
|
<li><code># Titre</code> → Titre de niveau 1</li>
|
||||||
|
<li><code>## Sous-titre</code> → Titre de niveau 2</li>
|
||||||
|
<li><code>### Titre 3</code> → Titre de niveau 3</li>
|
||||||
|
<li><code>``` code </code> → Bloc de code avec mise en forme monospaced</li>
|
||||||
|
<li><code>+ Élément</code> → Liste à puces</li>
|
||||||
|
<li><code>1. Élément</code> → Liste numérotée</li>
|
||||||
|
<li><code>> Citation</code> → Citation classique</li>
|
||||||
|
<li><code>>! Attention</code> → Bloc d'alerte/info</li>
|
||||||
|
<li><code>>i Note</code> → Bloc d'information</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<h2 class="title is-4 icon-text">
|
||||||
|
<span class="icon has-text-warning"><i class="fas fa-pen-fancy"></i></span>
|
||||||
|
<span>Markdown <em>dans un bloc</em> (mise en forme)</span>
|
||||||
|
</h2>
|
||||||
|
<ul>
|
||||||
|
<li><code>`texte`</code> → <code><code></code> : monospaced/code</li>
|
||||||
|
<li><code>**gras**</code> → <strong>gras</strong></li>
|
||||||
|
<li><code>*italique*</code> → <em>italique</em></li>
|
||||||
|
<li><code>$$math$$ </code> → active le rendu mathématique (MathJax)</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<h2 class="title is-4 icon-text">
|
||||||
|
<span class="icon has-text-success"><i class="fas fa-keyboard"></i></span>
|
||||||
|
<span>Raccourcis Clavier</span>
|
||||||
|
</h2>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Entrée</strong> : crée un nouveau bloc (hors liste)</li>
|
||||||
|
<li><strong>Maj + Entrée</strong> : nouvelle ligne dans une liste</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<h2 class="title is-4 icon-text">
|
||||||
|
<span class="icon has-text-danger"><i class="fas fa-tools"></i></span>
|
||||||
|
<span>Fonctionnalités supplémentaires</span>
|
||||||
|
</h2>
|
||||||
|
<ul>
|
||||||
|
<li>Redimensionnement automatique des blocs</li>
|
||||||
|
<li>Rendu MathJax pour les formules</li>
|
||||||
|
<li>Collage propre (suppression du style)</li>
|
||||||
|
<li>Sauvegarde en temps réel via WebSocket</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</c:otherwise>
|
</c:otherwise>
|
||||||
</c:choose>
|
</c:choose>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -187,8 +187,13 @@ export function addDeleteBloc(button) {
|
||||||
body: params
|
body: params
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
blocContainer.remove(); // Supprime visuellement le bloc
|
blocContainer.remove();
|
||||||
ajouterBlocVideSiBesoin();
|
ajouterBlocVideSiBesoin();
|
||||||
|
|
||||||
|
window.socketBloc.send(JSON.stringify({
|
||||||
|
action: "deleteBloc",
|
||||||
|
blocId,
|
||||||
|
}));
|
||||||
} else {
|
} else {
|
||||||
console.error("Erreur lors de la suppression du bloc.");
|
console.error("Erreur lors de la suppression du bloc.");
|
||||||
}
|
}
|
||||||
|
|
@ -204,7 +209,7 @@ export function ajouterBlocVideSiBesoin() {
|
||||||
|
|
||||||
const message = document.querySelector('.column.is-half p');
|
const message = document.querySelector('.column.is-half p');
|
||||||
if (message && message.textContent.trim() === "Pas encore de page choisie.") {
|
if (message && message.textContent.trim() === "Pas encore de page choisie.") {
|
||||||
return; // Arrête la fonction ici (se passe après avoir supprimé une page)
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allBlocs.length === 0 || allBlocs[allBlocs.length - 1].innerText.trim() !== "") {
|
if (allBlocs.length === 0 || allBlocs[allBlocs.length - 1].innerText.trim() !== "") {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
export function initDragAndDrop(containerSelector, itemSelector = '[draggable]') {
|
||||||
|
const container = document.querySelector(containerSelector);
|
||||||
|
let draggedElement = null;
|
||||||
|
|
||||||
|
if (!container) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
container.addEventListener('dragstart', e => {
|
||||||
|
if (e.target.matches(itemSelector)) {
|
||||||
|
draggedElement = e.target;
|
||||||
|
e.dataTransfer.effectAllowed = 'move';
|
||||||
|
e.target.classList.add('dragging');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
container.addEventListener('dragover', e => {
|
||||||
|
e.preventDefault();
|
||||||
|
const target = e.target.closest(itemSelector);
|
||||||
|
if (target && draggedElement && target !== draggedElement) {
|
||||||
|
container.insertBefore(draggedElement, target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
container.addEventListener('drop', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
container.addEventListener('dragend', () => {
|
||||||
|
if (draggedElement) {
|
||||||
|
draggedElement.classList.remove('dragging');
|
||||||
|
draggedElement = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const blocs = Array.from(container.querySelectorAll(itemSelector));
|
||||||
|
const ordre = blocs.map((bloc, index) => {
|
||||||
|
const editor = bloc.querySelector('.editor');
|
||||||
|
return {
|
||||||
|
id: editor.dataset.id,
|
||||||
|
ordre: index + 1
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch('SauvegarderOrdre', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(ordre)
|
||||||
|
}).then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
const modifOrdre = {
|
||||||
|
action: "modifierOrdreBloc",
|
||||||
|
order: ordre.map(b => b.id)
|
||||||
|
};
|
||||||
|
window.socketBloc.send(JSON.stringify(modifOrdre));
|
||||||
|
} else {
|
||||||
|
console.error("Erreur lors de la modification de l'ordre des blocs.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -71,6 +71,7 @@ export function renderBlocStyle(bloc) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'PAGE':
|
case 'PAGE':
|
||||||
|
renderPage(bloc);
|
||||||
bloc.classList.add('is-page-link');
|
bloc.classList.add('is-page-link');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -112,6 +113,18 @@ export function renderListe(bloc) {
|
||||||
bloc.innerHTML = `<${tag}>${items}</${tag}>`;
|
bloc.innerHTML = `<${tag}>${items}</${tag}>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function renderPage(bloc){
|
||||||
|
const metadata = getBlocDataMetadata(bloc);
|
||||||
|
const pageId = metadata.pageId;
|
||||||
|
|
||||||
|
if (!pageId) return;
|
||||||
|
|
||||||
|
const lien = `AfficherPage?id=${pageId}`;
|
||||||
|
const titre = metadata.title;
|
||||||
|
|
||||||
|
bloc.innerHTML = `<a href="${lien}">${titre}</a>`;
|
||||||
|
}
|
||||||
|
|
||||||
export function handleSlashCommand(bloc, texte) {
|
export function handleSlashCommand(bloc, texte) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const parts = texte.trim().substring(1).split(" ");
|
const parts = texte.trim().substring(1).split(" ");
|
||||||
|
|
@ -172,7 +185,7 @@ export function handleSlashCommand(bloc, texte) {
|
||||||
applyBlocType(bloc, "SEPARATEUR", {}); // ou un type adapté selon ta logique
|
applyBlocType(bloc, "SEPARATEUR", {}); // ou un type adapté selon ta logique
|
||||||
bloc.innerText = ' ';
|
bloc.innerText = ' ';
|
||||||
autoResize(bloc);
|
autoResize(bloc);
|
||||||
resolve(true);
|
resolve();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -189,7 +202,7 @@ export function handleSlashCommand(bloc, texte) {
|
||||||
export async function handleMarkdownSyntax(bloc, texte) {
|
export async function handleMarkdownSyntax(bloc, texte) {
|
||||||
// Vérifier si c'est un titre
|
// Vérifier si c'est un titre
|
||||||
if (texte.startsWith('#')) {
|
if (texte.startsWith('#')) {
|
||||||
const level = texte.split(' ')[0].length; // Compter le nombre de # pour le niveau du titre
|
const level = texte.split(' ')[0].length;
|
||||||
if (level >= 1 && level <= 6) {
|
if (level >= 1 && level <= 6) {
|
||||||
applyBlocType(bloc, "TITRE", { level: level });
|
applyBlocType(bloc, "TITRE", { level: level });
|
||||||
bloc.textContent = texte.replace(/^#+\s*/, '');
|
bloc.textContent = texte.replace(/^#+\s*/, '');
|
||||||
|
|
@ -253,9 +266,7 @@ export function setBlocMetadata(bloc, metadata) {
|
||||||
const citationTypes = {
|
const citationTypes = {
|
||||||
'>!': 'danger',
|
'>!': 'danger',
|
||||||
'>i': 'info',
|
'>i': 'info',
|
||||||
/* '>w': 'warning',
|
'>': 'normal'
|
||||||
'>s': 'success',*/
|
|
||||||
'>': 'normal' // doit rester en dernier
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function detectCitation(texte) {
|
function detectCitation(texte) {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { initBlocs, ajouterBlocVideSiBesoin, focusDernierBloc } from './bloc.js'
|
||||||
import { initTchat } from './tchat.js';
|
import { initTchat } from './tchat.js';
|
||||||
import { initPages } from './page.js';
|
import { initPages } from './page.js';
|
||||||
import { initSocketBloc } from './socket-bloc.js';
|
import { initSocketBloc } from './socket-bloc.js';
|
||||||
|
import { initDragAndDrop } from './drag-and-drop.js';
|
||||||
|
|
||||||
window.addEventListener('DOMContentLoaded', () => {
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
initTchat();
|
initTchat();
|
||||||
|
|
@ -10,6 +11,7 @@ window.addEventListener('DOMContentLoaded', () => {
|
||||||
initBlocs();
|
initBlocs();
|
||||||
ajouterBlocVideSiBesoin();
|
ajouterBlocVideSiBesoin();
|
||||||
focusDernierBloc();
|
focusDernierBloc();
|
||||||
|
initDragAndDrop('#md', '.bloc-container');
|
||||||
|
|
||||||
document.body.addEventListener('click', function(event) {
|
document.body.addEventListener('click', function(event) {
|
||||||
// Vérifie si l'élément cliqué est un lien dans un .editor
|
// Vérifie si l'élément cliqué est un lien dans un .editor
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { autoResize, creerBlocDOM } from './utils.js'
|
import { autoResize, creerBlocDOM } from './utils.js'
|
||||||
import { renderBlocStyle, renderListe } from './functionsBloc.js'
|
|
||||||
|
|
||||||
export function initSocketBloc() {
|
export function initSocketBloc() {
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
|
@ -21,7 +20,7 @@ export function initSocketBloc() {
|
||||||
const data = JSON.parse(event.data);
|
const data = JSON.parse(event.data);
|
||||||
|
|
||||||
if (data.action === "update") {
|
if (data.action === "update") {
|
||||||
const blocElement = document.querySelector(`.editor[data-id='${data.blocId}']`);
|
const blocElement = document.querySelector(`[data-id="${data.blocId}"`);
|
||||||
if (blocElement) {
|
if (blocElement) {
|
||||||
blocElement.innerHTML = data.content;
|
blocElement.innerHTML = data.content;
|
||||||
blocElement.setAttribute('data-metadata', data.metadata);
|
blocElement.setAttribute('data-metadata', data.metadata);
|
||||||
|
|
@ -46,7 +45,7 @@ export function initSocketBloc() {
|
||||||
ordre: data.ordre
|
ordre: data.ordre
|
||||||
});
|
});
|
||||||
} else if (data.action === "actualiserMiseEnPageBloc") {
|
} else if (data.action === "actualiserMiseEnPageBloc") {
|
||||||
const blocElement = document.querySelector(`.editor[data-id='${data.blocId}']`);
|
const blocElement = document.querySelector(`[data-id="${data.blocId}"`);
|
||||||
if (blocElement) {
|
if (blocElement) {
|
||||||
blocElement.dataset.type = data.type;
|
blocElement.dataset.type = data.type;
|
||||||
blocElement.innerHTML = data.content;
|
blocElement.innerHTML = data.content;
|
||||||
|
|
@ -54,6 +53,28 @@ export function initSocketBloc() {
|
||||||
blocElement.className = data.classBloc;
|
blocElement.className = data.classBloc;
|
||||||
renderBloc(blocElement, blocElement.dataset.metadata);
|
renderBloc(blocElement, blocElement.dataset.metadata);
|
||||||
}
|
}
|
||||||
|
} else if (data.action === "modifierOrdreBloc") {
|
||||||
|
const container = document.getElementById("md");
|
||||||
|
const order = data.order;
|
||||||
|
order.forEach(blocId => {
|
||||||
|
|
||||||
|
const blocElement = document.querySelector(`[data-id="${blocId}"]`);
|
||||||
|
if (blocElement) {
|
||||||
|
const blocContainer = blocElement.closest('.bloc-container');
|
||||||
|
if (blocContainer) {
|
||||||
|
container.appendChild(blocContainer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (data.action === "deleteBloc") {
|
||||||
|
const blocId = data.blocId;
|
||||||
|
const blocElement = document.querySelector(`[data-id="${blocId}"]`);
|
||||||
|
if (blocElement) {
|
||||||
|
const blocContainer = blocElement.closest('.bloc-container');
|
||||||
|
if (blocContainer) {
|
||||||
|
blocContainer.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ export function placeCursorAtEnd(element) {
|
||||||
export function creerBlocDOM({ blocId, content = "", type = "TEXTE", metadata = "{}", ordre = null }) {
|
export function creerBlocDOM({ blocId, content = "", type = "TEXTE", metadata = "{}", ordre = null }) {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.classList.add('field', 'is-grouped', 'is-align-items-flex-start', 'bloc-container');
|
container.classList.add('field', 'is-grouped', 'is-align-items-flex-start', 'bloc-container');
|
||||||
|
container.setAttribute('draggable', 'true');
|
||||||
|
|
||||||
const control = document.createElement('div');
|
const control = document.createElement('div');
|
||||||
control.classList.add('control', 'is-expanded');
|
control.classList.add('control', 'is-expanded');
|
||||||
|
|
|
||||||
|
|
@ -89,3 +89,7 @@
|
||||||
background-color: #eaf6fb;
|
background-color: #eaf6fb;
|
||||||
color: #2980b9;
|
color: #2980b9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dragging {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue