mirror of
https://github.com/Floriansylvain/RenewCMS.git
synced 2026-08-19 19:53:21 +02:00
First EditorJS implementation
This commit is contained in:
@@ -34,18 +34,39 @@ h1 {
|
||||
font-family: 'Frank Ruhl Libre', serif;
|
||||
font-size: 40px;
|
||||
}
|
||||
h2 { font-size: 32px; }
|
||||
h3 { font-size: 24px; }
|
||||
h4 { font-size: 18px; }
|
||||
h2, h3, h4, h5, h6 {
|
||||
|
||||
h2 {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: 'Nunito', sans-serif;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
p,
|
||||
a,
|
||||
input,
|
||||
label,
|
||||
button,
|
||||
span {
|
||||
font-family: 'Hind', sans-serif;
|
||||
color: var(--neutral-dark);
|
||||
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.label-input,
|
||||
@@ -89,13 +110,13 @@ h2, h3, h4, h5, h6 {
|
||||
.button-disabled {
|
||||
border-radius: var(--radius);
|
||||
border: none;
|
||||
|
||||
|
||||
padding: 3px 16px;
|
||||
font-size: var(--font-body);
|
||||
font-weight: var(--medium-weight);
|
||||
|
||||
|
||||
background-color: var(--primary);
|
||||
|
||||
|
||||
transition: background-color 150ms;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"time": 1672423262433,
|
||||
"blocks": [
|
||||
{
|
||||
"id": "SsMzvSlYdr",
|
||||
"type": "Header",
|
||||
"data": {
|
||||
"text": "Bienvenue sur l'éditeur d'article !",
|
||||
"level": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "SCdiyR3ZLh",
|
||||
"type": "paragraph",
|
||||
"data": {
|
||||
"text": "<b>Ici</b>, vous pouvez <u class=\"cdx-underline\">créer</u> votre <i>article</i>."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PYzhBNCoxo",
|
||||
"type": "paragraph",
|
||||
"data": {
|
||||
"text": "Supprimez ces blocks pour commencer.<br>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"version": "2.26.4"
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"messages": {
|
||||
"ui": {
|
||||
"blockTunes": {
|
||||
"toggler": {
|
||||
"Click to tune": "Cliquez pour régler",
|
||||
"or drag to move": "ou glissez pour déplacer"
|
||||
}
|
||||
},
|
||||
"inlineToolbar": {
|
||||
"converter": {
|
||||
"Convert to": "Convertir en"
|
||||
}
|
||||
},
|
||||
"toolbar": {
|
||||
"toolbox": {
|
||||
"Add": "Ajouter"
|
||||
}
|
||||
}
|
||||
},
|
||||
"toolNames": {
|
||||
"Text": "Paragraphe",
|
||||
"Heading": "Titre",
|
||||
"List": "Liste",
|
||||
"Warning": "Avertissement",
|
||||
"Checklist": "Checklist",
|
||||
"Quote": "Citation",
|
||||
"Code": "Code",
|
||||
"Delimiter": "Délimiteur",
|
||||
"Table": "Tableau",
|
||||
"Link": "Lien",
|
||||
"Marker": "Surligner",
|
||||
"Bold": "Gras",
|
||||
"Italic": "Italique",
|
||||
"Underline": "Sousligner"
|
||||
},
|
||||
"tools": {
|
||||
"Header": {
|
||||
"Heading 1": "Titre 1",
|
||||
"Heading 2": "Titre 2",
|
||||
"Heading 3": "Titre 3",
|
||||
"Heading 4": "Titre 4",
|
||||
"Heading 5": "Titre 5",
|
||||
"Heading 6": "Titre 6"
|
||||
},
|
||||
"Warning": {
|
||||
"Title": "Titre",
|
||||
"Message": "Message"
|
||||
},
|
||||
"stub": {
|
||||
"The block can not be displayed correctly.": "Le block ne peut pas être affiché correctement :(."
|
||||
},
|
||||
"Code": {
|
||||
"Enter a code": "Entrez votre code"
|
||||
}
|
||||
},
|
||||
"blockTunes": {
|
||||
"delete": {
|
||||
"Delete": "Supprimer"
|
||||
},
|
||||
"moveUp": {
|
||||
"Move up": "Vers le haut"
|
||||
},
|
||||
"moveDown": {
|
||||
"Move down": "Vers le bas"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<script setup lang="ts">
|
||||
import i18n from "@/assets/editor_translation.json";
|
||||
import defaultData from '@/assets/editor_default_content.json'
|
||||
|
||||
import EditorJS, { type EditorConfig, type OutputData } from "@editorjs/editorjs";
|
||||
import Header from "@editorjs/header";
|
||||
import List from "@editorjs/list";
|
||||
import NestedList from "@editorjs/nested-list";
|
||||
import CheckList from "@editorjs/checklist";
|
||||
import Quote from "@editorjs/quote";
|
||||
import Warning from "@editorjs/warning";
|
||||
import Marker from "@editorjs/marker";
|
||||
import Code from "@editorjs/code";
|
||||
import Table from "@editorjs/table";
|
||||
import Underline from "@editorjs/underline";
|
||||
import Delimiter from "@editorjs/delimiter";
|
||||
|
||||
|
||||
const props = defineProps<{
|
||||
showDefaultData: boolean
|
||||
}>()
|
||||
|
||||
function getEditorConfig(): EditorConfig {
|
||||
let editorConfig: EditorConfig = {
|
||||
tools: {
|
||||
Header,
|
||||
Quote,
|
||||
NestedList,
|
||||
Code,
|
||||
Table,
|
||||
Warning,
|
||||
Delimiter,
|
||||
Marker,
|
||||
Underline
|
||||
},
|
||||
i18n
|
||||
}
|
||||
if (!props.showDefaultData) return editorConfig
|
||||
editorConfig = {
|
||||
...editorConfig,
|
||||
data: defaultData
|
||||
}
|
||||
return editorConfig
|
||||
}
|
||||
|
||||
const editor = new EditorJS(getEditorConfig())
|
||||
|
||||
async function getEditorData(): Promise<OutputData | undefined> {
|
||||
let data = undefined
|
||||
await editor.save()
|
||||
.then(outputData => {
|
||||
data = outputData
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error)
|
||||
})
|
||||
return data
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container">
|
||||
<div id="editorjs"></div>
|
||||
<button @click="getEditorData()" class="button-primary">Enregistrer</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#editorjs {
|
||||
font-family: 'Hind', sans-serif;
|
||||
}
|
||||
|
||||
button {
|
||||
margin: auto;
|
||||
}
|
||||
</style>
|
||||
@@ -1,71 +1,62 @@
|
||||
<script setup lang="ts">
|
||||
// import EditorJS from '@editorjs/editorjs';
|
||||
import { useAuthStore, type jwtFormat } from '@/stores/AuthStore';
|
||||
import Editor from '@/components/Editor.vue';
|
||||
import { useAuthStore } from '@/stores/AuthStore';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const email = ref('')
|
||||
const password = ref('')
|
||||
|
||||
const baseURL = `http://${__APP_ENV__.APP_HOST_ADDRESS}:${__APP_ENV__.APP_API_PORT}`
|
||||
const articleID = ref('')
|
||||
|
||||
function getArticles() {
|
||||
fetch(`${baseURL}/articles/`, {
|
||||
function getArticles(id?: string) {
|
||||
fetch(`${baseURL}/articles/${id ?? ''}`, {
|
||||
headers: { "Authorization": `Bearer ${useAuthStore().token}` }
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => console.log(result))
|
||||
.then(response => response.json())
|
||||
.then(result => console.log(result))
|
||||
}
|
||||
|
||||
function ping() {
|
||||
fetch(`${baseURL}/ping/`, {
|
||||
headers: { "Authorization": `Bearer ${useAuthStore().token}` }
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => console.log(result))
|
||||
}
|
||||
|
||||
function jwtHandler(apiResponse: jwtFormat): void {
|
||||
if (apiResponse.code !== 200) {
|
||||
console.log(apiResponse)
|
||||
return
|
||||
}
|
||||
useAuthStore().token = apiResponse.token
|
||||
useAuthStore().expire = apiResponse.expire
|
||||
console.log('success! logged in.')
|
||||
}
|
||||
|
||||
function login(email: string, password: string): void {
|
||||
fetch(`${baseURL}/login/`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
email: email,
|
||||
password: password
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(result => jwtHandler(result))
|
||||
.then(response => response.json())
|
||||
.then(result => console.log(result))
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h2>Connexion</h2>
|
||||
|
||||
<form @submit.prevent="login(email, password)">
|
||||
<div class="inputs-group">
|
||||
<div>
|
||||
<label for="email">Email address</label>
|
||||
<input id="email" name="email" placeholder="email" type="text" v-model="email">
|
||||
</div>
|
||||
<div>
|
||||
<label for="password">Password</label>
|
||||
<input id="password" name="password" placeholder="password" type="password" v-model="password">
|
||||
</div>
|
||||
<button type="submit">Se connecter</button>
|
||||
</form>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<button class="button-primary" @click="getArticles()">get all articles</button>
|
||||
<button class="button-primary" @click="ping()">ping</button>
|
||||
<input type="text" placeholder="article ID" v-model="articleID">
|
||||
<button class="button-primary" @click="getArticles(articleID)">get article</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons-group">
|
||||
<button class="button-primary" @click="ping()">ping</button>
|
||||
</div>
|
||||
<div class="editor">
|
||||
<Editor :show-default-data="true"></Editor>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.buttons-group,
|
||||
.inputs-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin: 32px;
|
||||
}
|
||||
|
||||
.inputs-group {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.inputs-group div {
|
||||
flex-direction: row;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.editor {
|
||||
border: solid black 2px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user