70 Commits
vue2 ... master

Author SHA1 Message Date
2d0d56a452 bump version to 0.0.33 and add aosDelay input for animation delay in AosSelect component 2025-11-28 13:30:31 +01:00
eeb3c92778 bump version to 0.0.32 and update margin classes in PagebuilderSection 2025-11-28 10:01:49 +01:00
da0a1b006d Merge remote-tracking branch 'refs/remotes/origin/master' 2025-11-28 09:55:19 +01:00
c2c67c15a7 bump version to 0.0.31 and add AosSelect component for animation selection in Pagebuilder 2025-11-28 09:55:12 +01:00
0386355405 Dodanie do menu wstaw twarda spacja 2025-11-27 09:22:42 +01:00
b54a2c41ce bump version to 0.0.30 and update dropdown checkbox styling in PagebuilderSection 2025-11-17 10:04:15 +01:00
60add34529 refactor: update section title and add dropdown options in PagebuilderSection 2025-11-17 09:32:40 +01:00
96becf4747 bump version to 0.0.28 and enhance TinyMCE configuration with additional menu options 2025-11-13 10:56:03 +01:00
d0d74e8e99 ai plugin modal 2025-07-02 14:20:50 +02:00
12914907bd core_section_video 2025-01-14 13:02:31 +01:00
74b50624fc new v 2025-01-14 09:50:14 +01:00
43927991b6 pagebuilder section video 2025-01-14 09:48:07 +01:00
3fe033c073 simple langs for pagebuilder 2025-01-14 08:56:47 +01:00
a1615ed2cc updat epackege json 2024-11-15 08:13:54 +01:00
f73e173294 fix modal open 2024-11-15 07:57:51 +01:00
09beabe34f fix vif modal 2024-10-03 11:17:16 +02:00
9c52316499 new version 2024-10-03 10:44:47 +02:00
5ed33697ee git fix modal 2024-10-03 10:43:31 +02:00
32e098322c fix pagebuilder 2024-10-02 14:07:16 +02:00
a75ac0921d fix 2024-07-22 14:50:25 +02:00
08d26e5621 udpate packahe.json 2024-07-22 14:43:51 +02:00
45628eb596 tinymce more items 2024-07-22 14:43:37 +02:00
d55fc67fb5 copy option 2024-07-02 10:18:27 +02:00
e19e5cdfa1 fix model value udpate 2024-07-02 09:00:16 +02:00
24eae8c4fe fix 2024-07-02 08:56:47 +02:00
0951c2a4ea fix 2024-07-02 08:53:18 +02:00
883dd6da91 watch for external udpate 2024-07-02 08:46:52 +02:00
4008ebbbcc modal 2024-07-02 07:55:02 +02:00
2ffa793e84 fix modal 2024-07-02 07:53:42 +02:00
c1c6f46255 fix warnigns 2024-07-01 13:35:38 +02:00
dbb2f02049 fix 2024-07-01 13:17:14 +02:00
e80f2b3def f fix 2024-07-01 12:44:42 +02:00
8d2d0c6d77 fix 2024-07-01 12:41:01 +02:00
c5fb9f5080 fix name 2024-07-01 12:40:16 +02:00
e750930057 fix fix 2024-07-01 12:38:36 +02:00
de80d14c64 update model value 2024-07-01 12:36:49 +02:00
6d9857ab59 fix 2024-07-01 12:33:24 +02:00
c7d4125d2c co alelgro "type":"container" 2024-07-01 12:31:22 +02:00
63fa2b9134 new ver 2024-07-01 12:24:04 +02:00
9fe3b379a8 allegro copy descritpion 2024-07-01 12:23:03 +02:00
6f9e2f0eac new verions 2024-06-17 09:06:58 +02:00
ab402a32f1 section image lightbox 2024-06-17 09:03:08 +02:00
008b54431d fix boostarp version 2024-01-19 10:30:20 +01:00
e81fd95970 template dropdown 2024-01-19 09:23:27 +01:00
ab4fdbad85 fix ids 2024-01-11 13:31:10 +01:00
7d7df8ff99 add seciotn wybor 2024-01-11 12:35:13 +01:00
d1d1eaa55d fix modal in textarea 2024-01-11 08:56:26 +01:00
cf875dc704 fix ids 2024-01-11 07:55:56 +01:00
5ba7df5b62 add index to cgroup 2024-01-11 07:53:04 +01:00
c5b4c18d2f id for sections 2024-01-11 07:45:44 +01:00
8785aae615 id for section 2024-01-11 07:26:33 +01:00
f309bc3863 Merge remote-tracking branch 'refs/remotes/origin/master' 2024-01-11 07:25:49 +01:00
7e31c9d34e add unique keys for content 2024-01-11 07:25:04 +01:00
Szymon Haczyk
92ce5c02c2 v-if loadmodal 2023-10-16 11:26:46 +02:00
Szymon Haczyk
ff9b0f4357 fix template load 2023-10-16 11:24:24 +02:00
Szymon Haczyk
baf9dfb0b2 fix btn 2023-10-13 09:06:16 +02:00
Szymon Haczyk
54719ea98c section type choose 2023-10-13 08:10:00 +02:00
a0d55eb5a1 another another Xd 2023-09-26 09:09:05 +02:00
656808255a another section_Id fix 2023-09-26 09:08:47 +02:00
eb9b2c06a6 regsite section fix to site_section_id 2023-09-26 08:39:04 +02:00
cd3a57c12f name for seciton and col 2023-08-30 12:14:48 +02:00
0148c0f3a0 use sections plugin 2023-08-16 13:49:35 +02:00
Szymon Haczyk
8af2815bb6 MAKE IT WORK! 2023-08-11 18:54:43 +02:00
Szymon Haczyk
a7f04d90c4 Merge remote-tracking branch 'origin/vite' 2023-08-11 18:49:35 +02:00
Szymon Haczyk
5554c4a9fd clear master 2023-08-11 18:49:18 +02:00
Szymon Haczyk
ea3498b2d7 init 2023-08-11 18:44:56 +02:00
2801ee9691 play with this sphathegi code 2023-08-11 14:57:48 +02:00
ae877784ee fix v-models 2023-08-02 13:36:01 +02:00
5277849312 fix model value 2023-08-02 12:14:29 +02:00
7d4cc6ee70 vue2 to vue3 migration 2023-08-02 12:03:37 +02:00
40 changed files with 3723 additions and 29266 deletions

14
.eslintrc.cjs Normal file
View File

@@ -0,0 +1,14 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-prettier/skip-formatting'
],
parserOptions: {
ecmaVersion: 'latest'
}
}

8
.prettierrc.json Normal file
View File

@@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"tabWidth": 2,
"singleQuote": true,
"printWidth": 100,
"trailingComma": "none"
}

3
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
}

View File

@@ -1,30 +1,35 @@
# magicopagebuilder # magico-pagebuilder
## Project setup This template should help get you started developing with Vue 3 in Vite.
```
## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
## Customize configuration
See [Vite Configuration Reference](https://vitejs.dev/config/).
## Project Setup
```sh
npm install npm install
``` ```
### Compiles and hot-reloads for development ### Compile and Hot-Reload for Development
```
npm run serve ```sh
npm run dev
``` ```
### Compiles and minifies for production ### Compile and Minify for Production
```
```sh
npm run build npm run build
``` ```
### Lints and fixes files ### Lint with [ESLint](https://eslint.org/)
```
```sh
npm run lint npm run lint
``` ```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
IMPORT TINYMCE FROM CDN
<script src="https://cdn.magico.pl/tinymce/tinymce.min.js"></script>

View File

@@ -1,5 +0,0 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

19
index.html Normal file
View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Magico Pagebuilder</title>
<link rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500|Material+Icons|Material+Icons+Outlined|Material+Icons+Two+Tone|Material+Icons+Round|Material+Icons+Sharp">
<script src="https://cdn.magico.pl/tinymce/tinymce.min.js"></script>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

28168
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,48 +1,33 @@
{ {
"name": "magicopagebuilder", "name": "magico-pagebuilder",
"version": "0.1.0", "version": "0.0.33",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "dev": "vite",
"build": "vue-cli-service build", "build": "vite build",
"lint": "vue-cli-service lint" "preview": "vite preview",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore",
"format": "prettier --write src/"
}, },
"dependencies": { "dependencies": {
"@popperjs/core": "^2.11.7", "@popperjs/core": "^2.11.7",
"@tinymce/tinymce-vue": "^3.2.8", "@tinymce/tinymce-vue": "^4",
"boostrap": "^2.0.0", "bootstrap": "5.2",
"bootstrap": "^5.1.3", "bootstrap-icons": "^1.10.5",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"magico-section": "https://serwer.magico.pl/gitrepos/public/magico-section.git",
"tinymce": "^6.0.3", "tinymce": "^6.0.3",
"vue": "^2.6.11", "vue": "^3.3.4",
"vuedraggable": "^2.24.3" "vue-i18n": "9",
"vuedraggable": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "~4.5.11", "@rushstack/eslint-patch": "^1.3.2",
"@vue/cli-plugin-eslint": "~4.5.11", "@vitejs/plugin-vue": "^4.2.3",
"@vue/cli-service": "~4.5.11", "@vue/eslint-config-prettier": "^8.0.0",
"babel-eslint": "^10.1.0", "eslint": "^8.45.0",
"eslint": "^6.7.2", "eslint-plugin-vue": "^9.15.1",
"eslint-plugin-vue": "^6.2.2", "prettier": "^3.0.0",
"vue-template-compiler": "^2.6.11" "vite": "^4.4.6"
}, }
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
">0.2%",
"not dead",
"not op_mini all"
]
} }

View File

@@ -1,26 +0,0 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500|Material+Icons|Material+Icons+Outlined|Material+Icons+Two+Tone|Material+Icons+Round|Material+Icons+Sharp">
<script src="https://cdn.magico.pl/tinymce/tinymce.min.js"></script>
<title>
<%= htmlWebpackPlugin.options.title %>
</title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@@ -1,24 +1,34 @@
<template> <template>
<div id="app" class="container"> <div id="app" class="container">
<img alt="Vue logo" style="width:100px" src="./assets/logo.png"> <img alt="Vue logo" style="width: 100px" src="./assets/logo.png" />
<h2>Pagebuilder Magico</h2> <h2>Pagebuilder Magico</h2>
<MagicoPagebuilder v-model="data" /> <MagicoPagebuilder v-model="data" />
<div class="bg-dark text-light mt-4 p-2">{{data}}</div> <div class="bg-dark text-light mt-4 p-2">{{ data }}</div>
</div> </div>
</template> </template>
<script> <script>
import { useSections } from './components/registerSections'
import axios from 'axios'
export default { export default {
name: 'App', name: 'App',
components: { components: {},
data: function () {
},
data: function(){
return { return {
data:'[{"label":"1 kolumna ","name":"col_1","columns":[{"name":"col-md-12","items":[{"name":"core_section_textarea","text":""},{"name":"core_section_text","text":""}]}]}]' data: '[{"label":"1 kolumna ","name":"col_1","columns":[{"name":"col-md-12","items":[{"name":"core_section_textarea","text":""},{"name":"core_section_text","text":""}]}]}]'
} }
},
mounted() {
const { register: sectionRegister } = useSections()
let vm = this
this.$pagebuilder.axios = axios.create({
headers: { Authorization: 'Bearer 40660b963460d453d903be5d5091e0c94a3254ce' }
})
this.$pagebuilder.axios.get('https://cms.magico.pro/api/v1/section').then((response) => {
sectionRegister(vm.$pagebuilder, response.data.data)
})
} }
} }
</script> </script>

73
src/assets/base.css Normal file
View File

@@ -0,0 +1,73 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-indigo: #2c3e50;
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}
/* semantic color variables for this project */
:root {
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
--section-gap: 160px;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
font-weight: normal;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition: color 0.5s, background-color 0.5s;
line-height: 1.6;
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

1
src/assets/logo.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

After

Width:  |  Height:  |  Size: 276 B

33
src/assets/main.css Normal file
View File

@@ -0,0 +1,33 @@
@import './base.css';
@import 'bootstrap-icons/font/bootstrap-icons.css';
#app {
min-width: 1980px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
}
a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
}
@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
}
@media (min-width: 1024px) {
body {
display: flex;
}
#app {
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
}

111
src/components/AIModal.vue Normal file
View File

@@ -0,0 +1,111 @@
<template>
<MagicoModal v-model="modal" title="Generuj AI">
<div class="p-1">
<h5>O czym chcesz napisać?</h5>
<textarea
class="form-control mb-3"
rows="5"
v-model="text"
placeholder="Napisz krótki opis, aby AI mogło wygenerować treść."
></textarea>
<div class="form-group">
<label>Ilość znaków</label>
<select v-model="count" class="form-select">
<option value="500">500</option>
<option value="1000">1000</option>
<option value="2000">2000</option>
</select>
</div>
<div class="text-center mt-3">
<button :disabled="loader" @click="generate" class="btn btn-primary">
<span class="spinner-border spinner-border-sm me-2" v-if="loader"></span>
Generuj
</button>
</div>
</div>
</MagicoModal>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue'
const modal = ref(true)
import axios from 'axios';
import MagicoModal from './MagicoModal.vue'
// import axios from '@/api/sync-axios'
const props = defineProps({
product: {
type: Object,
required: true
},
modelValue: {
type: Object,
default: true
},
lang: {
type: String
},
callback: {
type: Function,
default: () => {}
}
})
const text = ref('')
const offer = ref({})
const loader = ref(false)
onMounted(() => {
offer.value = props.modelValue
})
watch(
() => props.modelValue,
(newValue) => {
offer.value = newValue
},
{ immediate: true }
)
const count = ref(500)
const emit = defineEmits(['offerGenerated', 'update:modelValue'])
function generate() {
const prompt = `Twoim zadaniem jest stworzenie opisu.
Do "content" wstaw tekst w formacie HTML, jako akapity dla edytora WYSIWYG na podstawie dostarczonej treści na maksymalnie ${count.value} znaków.
Odpowiedź wygeneruj w języku określanym przez kod kraju: pl.
Wynik zwróć jako czysty JSON bez dodatkowego formatowania, bez używania \`\`\`json i \`\`\`, bez używania \`\`\`html i \`\`\`:
{
"content": ""
}`
const query = `${text.value}`
loader.value = true
axios
.post(
'https://ai.magico.pro/api/v1/message',
{ prompt, query },
{
headers: {
Authorization: 'Bearer ' + localStorage.getItem('access_token')
}
}
)
.then((response) => {
loader.value = false
modal.value = false // Close the modal after generation
// Handle the response, e.g., display the generated content
const jsonText = response.data.data.choices[0].message.content
const jsonData = JSON.parse(jsonText)
console.log('Generated Offer Data:', jsonData)
emit('update:modelValue', offer.value)
props.callback(jsonData)
// Assuming you want to do something with the generated data
// modal.value = false; // Close the modal after generation
})
.catch((error) => {
console.error('Błąd podczas generowania oferty:', error)
alert('Wystąpił błąd podczas generowania oferty.')
})
}
function setFeatureValue(featureName, value) {
const feature = offer.value.features.find((f) => f.feature_name === featureName)
if (feature) {
feature.feature_value = value
}
}
</script>

View File

@@ -0,0 +1,108 @@
<template>
<div class="form form-group mb-3">
<label class="form-label">Wybierz animację</label>
<select v-model="selectedAnimation" @change="changeSelect" class="form-select">
<option value="">Brak animacji</option>
<option v-for="item in animations" :key="item.value" :value="item.value">
{{ item.name }}
</option>
</select>
<div class="mt-2">
<label class="form-label">Opóźnienie animacji (ms)</label>
<input type="number" v-model="aosDelay" @input="changeSelect" class="form-control" min="0" step="50" placeholder="np. 200" />
</div>
<!-- <small class="form-text text-muted" v-if="selectedAnimation">
Wybrana animacja: {{ getCompiledAttribute() }}
</small> -->
</div>
</template>
<script setup>
import { ref, watch, onMounted } from 'vue';
const props = defineProps({
modelValue: {
type: String,
default: ''
}
});
const emit = defineEmits(['update:value', 'aos-changed']);
const selectedAnimation = ref('');
const aosDelay = ref('');
const animations = [
{ value: 'fade', name: 'Zanikanie' },
{ value: 'fade-up', name: 'Zanikanie w górę' },
{ value: 'fade-down', name: 'Zanikanie w dół' },
{ value: 'fade-left', name: 'Zanikanie w lewo' },
{ value: 'fade-right', name: 'Zanikanie w prawo' },
{ value: 'fade-up-right', name: 'Zanikanie w górę i prawo' },
{ value: 'fade-up-left', name: 'Zanikanie w górę i lewo' },
{ value: 'fade-down-right', name: 'Zanikanie w dół i prawo' },
{ value: 'fade-down-left', name: 'Zanikanie w dół i lewo' },
{ value: 'flip-up', name: 'Obrót w górę' },
{ value: 'flip-down', name: 'Obrót w dół' },
{ value: 'flip-left', name: 'Obrót w lewo' },
{ value: 'flip-right', name: 'Obrót w prawo' },
{ value: 'slide-up', name: 'Przesunięcie w górę' },
{ value: 'slide-down', name: 'Przesunięcie w dół' },
{ value: 'slide-left', name: 'Przesunięcie w lewo' },
{ value: 'slide-right', name: 'Przesunięcie w prawo' },
{ value: 'zoom-in', name: 'Powiększenie' },
{ value: 'zoom-in-up', name: 'Powiększenie w górę' },
{ value: 'zoom-in-down', name: 'Powiększenie w dół' },
{ value: 'zoom-in-left', name: 'Powiększenie w lewo' },
{ value: 'zoom-in-right', name: 'Powiększenie w prawo' },
{ value: 'zoom-out', name: 'Pomniejszenie' },
{ value: 'zoom-out-up', name: 'Pomniejszenie w górę' },
{ value: 'zoom-out-down', name: 'Pomniejszenie w dół' },
{ value: 'zoom-out-left', name: 'Pomniejszenie w lewo' },
{ value: 'zoom-out-right', name: 'Pomniejszenie w prawo' }
];
function decompileAosAttribute(val) {
if (val) {
const aosMatch = val.match(/data-aos="([^"]+)"/);
const delayMatch = val.match(/data-aos-delay="(\d+)"/);
if (aosMatch) {
selectedAnimation.value = aosMatch[1];
} else {
selectedAnimation.value = val;
}
if (delayMatch) {
aosDelay.value = delayMatch[1];
} else {
aosDelay.value = '';
}
} else {
selectedAnimation.value = '';
aosDelay.value = '';
}
}
function getCompiledAttribute() {
let attr = '';
if (selectedAnimation.value) {
attr += `data-aos="${selectedAnimation.value}"`;
if (aosDelay.value) {
attr += ` data-aos-delay="${aosDelay.value}"`;
}
}
return attr;
}
function changeSelect() {
const compiledAttribute = getCompiledAttribute();
emit('update:modelValue', compiledAttribute);
emit('aos-changed', compiledAttribute);
}
onMounted(() => {
decompileAosAttribute(props.modelValue);
});
watch(() => props.modelValue, (newVal) => {
decompileAosAttribute(newVal);
});
</script>

View File

@@ -1,44 +1,48 @@
<template> <template>
<div class="row p-2"> <div class="row p-2">
<div v-for="(item, index) in items" :key="index" class="col-md-3"> <div
v-for="(item, index) in items"
<div class="my-check v2"> :key="index"
class="col-md-3"
<input class="form-control" :id="item.name" @input="event => { $emit('input', event.target.value) }" >
type="radio" v-model="value" :value="item.name"> <div class="my-check v2">
<label
<label :for="item.name"><img style="width:100%" @click="emitEvent(item)"
:src="'https://cdn.magico.pl/pagebuilder/images/' + item.name + '.jpg'" :for="item.name"
:alt="item.label" /></label> ><img
</div> style="width: 100%"
:src="'https://cdn.magico.pl/pagebuilder/images/' + item.name + '.jpg'"
</div> :alt="item.label"
/></label>
</div>
</div> </div>
</div>
</template> </template>
<script> <script>
import grid from './grid.js' import { ref } from "vue";
import grid from "./grid.js";
export default { export default {
emits: ["choose"],
setup(props, { emit }) {
const items = ref(grid);
methods: {}, function emitEvent(item) {
data: function () { emit("choose", item);
return { }
items: grid, return { items, emitEvent };
value: '', },
} };
},
}
</script> </script>
<style> <style>
.my-check input { .my-check input {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
opacity: 0; opacity: 0;
} }
.my-check label { .my-check label {
cursor: pointer; cursor: pointer;
} }
</style> </style>

View File

@@ -1,28 +1,51 @@
<template> <template>
<div> <div>
<div class="row col-md-12 pagebuilder_section"> <div class="row col-md-12 pagebuilder_section">
<div v-for="(item, index) in $pagebuilder.items" :key="index" class="col-md-2"> <div
<template v-if="!item.type || item.type != 'custom'"> v-for="(item, index) in $pagebuilder.items"
<div class="my-check v2"> :key="index"
<label @click="$emit('input', index)" :for="'pos_' + index"> class="col-md-2"
<div style="width:100%" v-if="item.svg" v-html="item.svg"></div> >
<img v-else style="width:100%" <template v-if="!item.type || item.type != 'custom'">
:src="'https://cdn.magico.pl/pagebuilder/images/' + index + '.jpg'" alt="1 kolumna"> <div class="my-check v2">
<span style="cursor: pointer" class="d-inline-block w-100 text-center mt-1 mb-1">{{ <label
item.label @click="$emit('choose', index)"
}}</span> :for="'pos_' + index"
</label> >
</div> <div
</template> style="width: 100%"
</div> v-if="item.svg"
</div> v-html="item.svg"
<!-- <div class="col-md-12 text-center"> ></div>
<img
style="width: 100%"
v-else-if="item.image"
:src="item.image"
>
<img
v-else
style="width: 100%"
:src="'https://cdn.magico.pl/pagebuilder/images/' + index + '.jpg'"
alt="1 kolumna"
/>
<span
style="cursor: pointer"
class="d-inline-block w-100 text-center mt-1 mb-1"
>{{ item.label }}</span
>
</label>
</div>
</template>
</div>
</div>
<!-- <div class="col-md-12 text-center">
<h3>DESIGN SYSTEM</h3> <h3>DESIGN SYSTEM</h3>
<div> <div>
<div class="row col-md-12 pagebuilder_section"> <div class="row col-md-12 pagebuilder_section">
<div v-for="(item, index) in items" class="col-md-2" v-if="item.type && item.type == 'custom'"> <div v-for="(item, index) in items" class="col-md-2" v-if="item.type && item.type == 'custom'">
<div class="form-check v2"> <div class="form-check v2">
<input @input="event => { $emit('input', index) }" type="radio" :id="'pos_' + index" <input @input="event => { $emit('update:modelValue', index) }" type="radio" :id="'pos_' + index"
name="pos"> name="pos">
<label :for="'pos_' + index"> <label :for="'pos_' + index">
<div style="width:100%" v-if="item.svg" v-html="item.svg"></div> <div style="width:100%" v-if="item.svg" v-html="item.svg"></div>
@@ -38,32 +61,32 @@
</div> </div>
</div> </div>
</div> --> </div> -->
</div> </div>
</template> </template>
<script> <script>
export default { export default {
methods: {}, methods: {},
props:['value'],
emits:['choose'],
data: function () { data: function () {
return { return {
items: {}, //{'core_pagebuilder_section_naglowek':'core_pagebuilder_section_naglowek', 'core_pagebuilder_section_tresc':'core_pagebuilder_section_tresc', 'core_pagebuilder_section_widget_jakis':'core_pagebuilder_section_widget_jakis'}, items: {}, //{'core_pagebuilder_section_naglowek':'core_pagebuilder_section_naglowek', 'core_pagebuilder_section_tresc':'core_pagebuilder_section_tresc', 'core_pagebuilder_section_widget_jakis':'core_pagebuilder_section_widget_jakis'},
} }
}, },
mounted() { mounted() {
} }
} }
</script> </script>
<style> <style>
.my-check input { .my-check input {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
opacity: 0; opacity: 0;
} }
.my-check label { .my-check label {
cursor: pointer; cursor: pointer;
} }
</style> </style>

View File

@@ -1,69 +1,74 @@
<template> <template>
<div class="modal" :id="id"> <div :id="id" class="modal" data-bs-focus="false" tabindex="-1">
<div class="modal-dialog " :class="class_other"> <div class="modal-dialog" :class="class_other" >
<div v-if="modal" class="modal-content"> <div class="modal-content" v-if="modelValue">
<div v-if="title" class="modal-header"> <div v-if="title" class="modal-header">
<h4 class="modal-title" v-html="title"></h4> <h4 class="modal-title" v-html="title" />
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" />
</div>
<div class="p-3">
<slot></slot>
</div>
</div>
</div> </div>
<div class="p-3">
<slot />
</div>
</div>
</div> </div>
</div>
</template> </template>
<script> <script>
import { Modal } from 'bootstrap'; import { Modal } from 'bootstrap'
import { onMounted, onBeforeUnmount, ref, watch } from 'vue'
export default { export default {
props: ['value', 'title', 'class_other'], props: ['modelValue', 'title', 'class_other'],
data: function () { emits: ['change', 'update:modelValue', 'hide'],
return { setup(props, { emit }) {
id: 'modal' + Math.round(Math.random() * 100000), const id = 'modalpgb' + Math.round(Math.random() * 100000)
modal: null, const modal = ref(null)
const triggerModal = (value, emitEvent = true) => {
if (value == true) {
modal.value.show()
} else {
modal.value.hide()
if (emitEvent) {
emit('hide')
} }
}, }
mounted() { emit('update:modelValue', value)
document.body.append(document.getElementById(this.id));
this.modal = new Modal(document.getElementById(this.id))
let vm = this;
document.getElementById(this.id).addEventListener('hidden.bs.modal', function () {
vm.triggerModal(false);
})
this.triggerModal(this.value, false);
},
methods: {
triggerModal: function (value, emit = true) {
if (value == true) {
this.modal.show();
} else {
this.modal.hide()
if (emit) {
this.$emit('hide');
}
}
this.$emit('input', value);
}
},
watch: {
value: function () {
this.triggerModal(this.value);
}
},
onDestroy: function () {
document.getElementById(this.id).remove();
} }
onMounted(() => {
document.body.append(document.getElementById(id))
modal.value = new Modal(document.getElementById(id))
document.getElementById(id).addEventListener('hidden.bs.modal', function () {
triggerModal(false)
})
triggerModal(props.modelValue, false)
})
onBeforeUnmount(() => {
modal.value.hide()
setTimeout(function () {
document.getElementById(id).remove()
}, 500)
})
watch(
() => props.modelValue,
() => {
triggerModal(props.modelValue)
}
)
return { id, modal }
}
} }
</script> </script>
<style> <style>
.modal-xxl { .modal-xxl {
width: 100% !important; width: 100% !important;
max-width: 100% !important; max-width: 100% !important;
padding: 0 10px !important; padding: 0 10px !important;
} }
.modal-xlg { </style>
width: 75% !important;
max-width: 75% !important;
padding: 0 10px !important;
}
</style>

View File

@@ -1,73 +1,161 @@
<template> <template>
<section :class="{ 'pagebuilder-fullscreen': fullscreen }" class="content card-body " id="pagebuilder"> <section
:class="{ 'pagebuilder-fullscreen': fullscreen }"
class="content card-body p-3"
id="pagebuilder"
>
<div class="pagebuilder-body"> <div class="pagebuilder-body">
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<button @click.prevent="fullscreen = !fullscreen" title="Tryb pełnoekranowy" <button
class="btn btn-outline-primary btn-icon-sm"><span class="material-icons-outlined">fullscreen</span></button> @click.prevent="fullscreen = !fullscreen"
title="Tryb pełnoekranowy"
class="btn btn-outline-primary btn-icon-sm"
>
<span class="material-icons-outlined">fullscreen</span>
</button>
<div> <div>
<div class="dropdown">
<button @click.prevent="modalLoad = !modalLoad; pageType = { name: null }" title="Wczytaj szablon do schowka" <button
class="btn btn-outline-primary btn-icon-sm"><span class="material-icons-outlined">find_replace</span></button> class="btn btn-outline-secondary dropdown-toggle"
<button @click.prevent="modalSave = !modalSave; pageType = { name: null }" title="Zapisz szablon do schowka" type="button"
class="btn btn-outline-success btn-icon-sm"><span class="material-icons-outlined">save</span></button> data-bs-toggle="dropdown"
aria-expanded="false"
>
{{ t('pagebuilder.template') }}
</button>
<ul class="dropdown-menu">
<li>
<a
@click.prevent="
modalLoad = !modalLoad;
pageType = { name: null }
"
class="dropdown-item"
href="#"
>{{ t('pagebuilder.import_template') }}</a
>
</li>
<li>
<a
@click.prevent="
modalSave = !modalSave;
pageType = { name: null }
"
class="dropdown-item"
href="#"
>{{ t('pagebuilder.save_template') }}</a
>
</li>
<li v-if="descriptionAllegro">
<a @click.prevent="pasteAllegro" class="dropdown-item" href="#"
>Wklej opis <i>Allegro</i></a
>
</li>
<li>
<a @click.prevent="copyClipboard" class="dropdown-item" href="#">{{
t('pagebuilder.copy_template')
}}</a>
</li>
<li v-if="pasteAvailable">
<a @click.prevent="pasteClipboard" class="dropdown-item" href="#">{{
t('pagebuilder.paste_template')
}}</a>
</li>
</ul>
</div>
</div> </div>
<!-- <button v-if="showcopy" class="btn btn-outline-secondary mr-1" @click.prevent="modalCopy = !modalCopy;">Kopiuj <!-- <button v-if="showcopy" class="btn btn-outline-secondary mr-1" @click.prevent="modalCopy = !modalCopy;">Kopiuj
układ z innej strony</button> --> układ z innej strony</button> -->
</div> </div>
<draggable :options="{ handle: '.box-move' }" v-model="comps" @start="drag = true" @end="drag = false; onChange()"> <draggable
<div v-for="(item, index) in comps" :key="index"> :options="{ handle: '.box-move' }"
<PagebuilderSection :value="item" v-on:deleteSection="deleteSection" v-on:copy="copySection" @change="onChange"> v-model.value="comps"
@start="drag = true"
item-key="d"
@end="
drag = false;
onChange()
"
>
<template #item="{ element, index }">
<PagebuilderSection
:value="element"
:key="'g' + index"
:id="'g' + index"
:keyIndex="'g' + index"
v-on:deleteSection="deleteSection"
v-on:copy="copySection"
@change="onChange"
>
</PagebuilderSection> </PagebuilderSection>
</div> </template>
</draggable> </draggable>
<b-modal class_other="modal-xl" v-model="modalSave" title="Zapisz szablon do schowka" <b-modal
v-on:onClose="modalSave = false"> v-model="modalSave"
<div slot="modal-title"><span></span></div> title="Zapisz szablon do schowka"
v-on:onClose="modalSave = false"
>
<PagebuilderTemplateSave v-model.value="pageType" :szablon="modelValue">
</PagebuilderTemplateSave>
<div> <div>
<PagebuilderTemplateSave v-model="pageType" :szablon="value"> <button
</PagebuilderTemplateSave> @click.prevent="modalSaveSave"
title="Zapisz do schowka"
class="btn btn-success mr-1"
:disabled="!pageType.name"
>
{{ t('pagebuilder.copy_template') }}
</button>
</div> </div>
<div><button @click.prevent="modalSaveSave" title="Zapisz do schowka" class="btn btn-success mr-1"
:disabled="!pageType.name">Zapisz do schowka </button></div>
</b-modal> </b-modal>
<b-modal class_other="modal-xl" v-model="modalLoad" title="Wczytaj szablon ze schowka" <b-modal
v-on:onClose="modalLoad = false"> v-model="modalLoad"
title="Wczytaj szablon ze schowka"
v-on:onClose="modalLoad = false"
>
<div> <div>
<PagebuilderTemplateLoad v-model="pageType" @input="modalLoadClick"></PagebuilderTemplateLoad> <PagebuilderTemplateLoad
v-model="pageType"
v-if="modalLoad"
@update:modelValue="modalLoadClick"
></PagebuilderTemplateLoad>
</div> </div>
</b-modal> </b-modal>
<b-modal class_other="modal-xl" v-model="modalCopy" v-on:onClose="modalCopy = false"> <b-modal v-model="modalCopy" v-on:onClose="modalCopy = false">
<div slot="modal-title"><span>Zapisz lub Kopiuj układ w schowku</span></div> <PagebuilderTemplateLoad v-model="pageType"></PagebuilderTemplateLoad>
<div> <div>
<PagebuilderTemplateLoad v-model="pageType"></PagebuilderTemplateLoad> <button class="btn btn-primary mr-1" :disabled="!pageType.id" @click.prevent="changeBody">
Skopiuj układ i treść
</button>
</div> </div>
<div slot="modal-footer"><button class="btn btn-primary mr-1" :disabled="!pageType.id"
@click.prevent="changeBody">Skopiuj układ i treść </button></div>
</b-modal> </b-modal>
<b-modal class_other="modal-xl" v-model="modalAddSection" title=" Dodaj sekcję" <b-modal
v-on:onClose="modalAddSection = false" hide-footer> class_other="modal-xl"
<div slot="modal-title"><span> v-model="modalAddSection"
:title="t('pagebuilder.add_section')"
</span></div> v-on:onClose="modalAddSection = false"
hide-footer
>
<div> <div>
<DropdownSectionGrid v-on:input="addSection" v-model="optionx"> <DropdownSectionGrid @choose="addSection"> </DropdownSectionGrid>
</DropdownSectionGrid>
</div> </div>
<div slot="modal-footer"></div> <div></div>
</b-modal> </b-modal>
<div class="text-center"> <div class="text-center">
<!-- <textarea style="display:none" :name="namex">{{ comps }}</textarea> --><button <!-- <textarea style="display:none" :name="namex">{{ comps }}</textarea> --><button
class="btn btn-block btn-primary mt-4" @click.prevent="modalAddSection = !modalAddSection; optionx = false"> class="btn btn-block btn-primary mt-4"
Dodaj sekcję @click.prevent="
modalAddSection = !modalAddSection;
optionx = false
"
>
{{ t('pagebuilder.add_section') }}
</button> </button>
</div> </div>
</div> </div>
@@ -82,9 +170,11 @@ import PagebuilderSection from './PagebuilderSection.vue'
import DropdownSectionGrid from './DropdownSectionGrid.vue' import DropdownSectionGrid from './DropdownSectionGrid.vue'
import PagebuilderTemplateSave from './PagebuilderTemplateSave.vue' import PagebuilderTemplateSave from './PagebuilderTemplateSave.vue'
import PagebuilderTemplateLoad from './PagebuilderTemplateLoad.vue' import PagebuilderTemplateLoad from './PagebuilderTemplateLoad.vue'
import { useI18n } from 'vue-i18n'
export default { export default {
name: 'HelloWorld', name: 'MagicoPagebuilder',
emits: ['update:modelValue', 'change'],
components: { components: {
'b-modal': MagicoModal, 'b-modal': MagicoModal,
PagebuilderSection, PagebuilderSection,
@@ -101,79 +191,165 @@ export default {
drag: false, drag: false,
optionx: '', optionx: '',
comps: [], comps: [],
pasteAvailable: false,
modalAddSection: false, modalAddSection: false,
modalCopy: false, modalCopy: false,
pageType: { id: false }, pageType: { id: false },
modalSave: false, modalSave: false,
modalLoad: false, modalLoad: false,
descriptionAllegro: false,
ownUpdate: false
} }
}, },
props: ['name', 'value', 'showcopy', 'lang'], props: ['name', 'modelValue', 'showcopy', 'lang'],
setup() {
const { t } = useI18n()
return { t }
},
mounted: function () { mounted: function () {
//var trimmed = $("#body_pagebuilder").val().replace((/ |\r\n|\n|\r/gm),""); if (localStorage.getItem('description_clipboard')) {
var trimmed = this.value//.replace((/{2} |\r\n|\n|\r/gm), ""); this.descriptionAllegro = true
try { }
this.comps = JSON.parse(trimmed); if (localStorage.getItem('pagebuilder_clipboard')) {
} catch (e) { this.pasteAvailable = true
console.warn(e); }
this.comps = [{ "label": "1 kolumna ", "name": "col_1", "columns": [{ "name": "col-md-12", "items": [{ "name": "core_section_textarea" }] }] }] //var trimmed = $("#body_pagebuilder").val().replace((/ |\r\n|\n|\r/gm),"");
var trimmed = this.modelValue //.replace((/{2} |\r\n|\n|\r/gm), "");
try {
this.comps = JSON.parse(trimmed)
} catch (e) {
console.warn(e)
this.comps = [
{
label: '1 kolumna ',
name: 'col_1',
columns: [{ name: 'col-md-12', items: [{ name: 'core_section_textarea' }] }]
}
]
} }
}, },
computed: {},
created: function () { created: function () {
if (this.name) this.namex = this.name; else this.namxe = "body"; if (this.name) this.namex = this.name
else this.namxe = 'body'
}, },
watch: { watch: {
// whenever question changes, this function will run // whenever question changes, this function will run
comps: function (newQuestion) { comps: function (newQuestion) {
console.log('nq', newQuestion) console.log('nq', newQuestion)
},
modelValue: function () {
if (this.ownUpdate) {
this.ownUpdate = false
return
}
try {
this.comps = JSON.parse(this.modelValue)
} catch (e) {
console.warn(e)
this.comps = [
{
label: '1 kolumna ',
name: 'col_1',
columns: [{ name: 'col-md-12', items: [{ name: 'core_section_textarea' }] }]
}
]
}
} }
}, },
methods: { methods: {
onChange: function () { onChange: function () {
this.$emit('input', JSON.stringify(this.comps)); this.ownUpdate = true
this.$emit('change'); this.$emit('update:modelValue', JSON.stringify(this.comps))
this.$emit('change')
}, },
copySection: function (item) { copySection: function (item) {
this.comps.push(JSON.parse(JSON.stringify(item))); this.comps.push(JSON.parse(JSON.stringify(item)))
this.onChange(); this.onChange()
}, },
deleteSection: function (item) { deleteSection: function (item) {
this.comps.splice(this.comps.indexOf(item), 1); this.comps.splice(this.comps.indexOf(item), 1)
this.onChange(); this.onChange()
}, },
addSection: function () { pasteClipboard: function () {
this.modalAddSection = false; const item = localStorage.getItem('pagebuilder_clipboard')
var columna = grid; if (!item) return
this.comps.push(JSON.parse(JSON.stringify(columna[this.optionx]))); try {
this.onChange(); this.comps = JSON.parse(item)
} catch (e) {
alert('Bład wklejenia')
}
},
copyClipboard: function () {
localStorage.setItem('pagebuilder_clipboard', JSON.stringify(this.comps))
},
addSection: function (it) {
this.modalAddSection = false
this.comps.push(JSON.parse(JSON.stringify(it)))
this.onChange()
}, },
modalSaveSave: function () { modalSaveSave: function () {
console.log(this.pageType); console.log(this.pageType)
var data = { var data = {
id: this.pageType.id, id: this.pageType.id,
name: this.pageType.name, name: this.pageType.name,
source: this.value, source: this.modelValue,
description: this.pageType.description, description: this.pageType.description
} }
if (this.$pagebuilder.axios) { if (this.$pagebuilder.axios) {
this.$pagebuilder.axios.post('api/v1/pagebuilder/template', data).then(() => { this.$pagebuilder.axios.post('api/v1/pagebuilder/template', data).then(() => {
this.pageType = {}; this.pageType = {}
this.modalSave = false; this.modalSave = false
}); })
} else { } else {
console.error('NO AXIOS INSTACE PROVIDED TO PAGEBUILDER'); console.error('NO AXIOS INSTACE PROVIDED TO PAGEBUILDER')
} }
}, },
modalLoadClick: function () { modalLoadClick: function () {
this.pageType.body = this.pageType.source; this.pageType.body = this.pageType.source
this.changeBody(); this.changeBody()
},
pasteAllegro: function () {
let sections = localStorage.getItem('description_clipboard')
try {
sections = JSON.parse(sections)
} catch (e) {
if (e instanceof SyntaxError) {
sections = [{ name: 'Tekst', cols: [{ type: 'text', value: sections, size: 12 }] }]
}
}
const pagebuilder = sections.map((item) => {
const columns = []
if (item.cols && Array.isArray(item.cols)) {
item.cols.forEach((col) => {
const column = {
type: 'container',
name: 'col-md-' + col.size,
items: [
{
name: col.type === 'img' ? 'core_section_image' : 'core_section_textarea',
text: col.value
}
]
}
if (col.type === 'img' && col.figcaption) {
column.items[0]['figcaption'] = col.figcaption
}
columns.push(column)
})
}
return { columns, label: '', name: '', type: 'container' }
})
this.comps = pagebuilder
this.onChange()
}, },
changeBody() { changeBody() {
var t = this; var t = this
var value = this.pageType.body; var value = this.pageType.body
var trimmed = value var trimmed = value
try { try {
//this.comps.forEach((item)=>{ //this.comps.forEach((item)=>{
@@ -181,20 +357,25 @@ export default {
//}) //})
this.comps = [] this.comps = []
setTimeout(function () { setTimeout(function () {
t.comps = JSON.parse(trimmed); t.comps = JSON.parse(trimmed)
t.onChange(); t.onChange()
}, 300)
}, 300);
//this.comps =JSON.parse(trimmed); //this.comps =JSON.parse(trimmed);
} catch (e) { } catch (e) {
this.comps = [{ "label": "1 kolumna ", "name": "col_1", "columns": [{ "name": "col-md-12", "items": [{ "name": "core_section_textarea" }] }] }] this.comps = [
{
label: '1 kolumna ',
name: 'col_1',
columns: [{ name: 'col-md-12', items: [{ name: 'core_section_textarea' }] }]
}
]
} }
this.modalCopy = false; this.modalCopy = false
this.modalSave = false; this.modalSave = false
this.modalLoad = false; this.modalLoad = false
} }
}, }
} }
</script> </script>

View File

@@ -1,34 +1,40 @@
import MagicoPagebuilder from './MagicoPagebuilder.vue' import MagicoPagebuilder from './MagicoPagebuilder.vue'
export default { export default {
install: (app) => { install: (app) => {
app.component('MagicoPagebuilder', MagicoPagebuilder); app.component('MagicoPagebuilder', MagicoPagebuilder)
console.log(app); console.log(app)
app.prototype.$pagebuilder = { app.config.globalProperties.$pagebuilder = {
items: { items: {
'core_section_text': { core_section_text: {
label: 'Pole nagłowek', label: 'Pole nagłowek',
svg_off: '<svg version="1.1" height="128" width="128" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="31.29px" height="31.29px" viewBox="0 0 31.29 31.29" style="enable-background:new 0 0 31.29 31.29;" xml:space="preserve"><g><g><path d="M18.585,31.226v-1.833h0.577c0.497,0,0.961-0.036,1.395-0.105c0.436-0.072,0.812-0.219,1.131-0.438s0.576-0.537,0.769-0.948c0.192-0.412,0.287-0.959,0.287-1.643V16.03H8.547v10.229c0,0.683,0.095,1.229,0.287,1.644c0.192,0.41,0.448,0.729,0.768,0.947c0.32,0.221,0.699,0.365,1.14,0.438c0.442,0.07,0.902,0.106,1.386,0.106h0.577v1.833H0v-1.833h0.555c0.497,0,0.961-0.036,1.396-0.106c0.434-0.071,0.813-0.217,1.141-0.438c0.326-0.221,0.582-0.537,0.769-0.947c0.184-0.412,0.275-0.961,0.275-1.644v-21.4c0-0.639-0.096-1.153-0.287-1.545c-0.194-0.392-0.454-0.693-0.78-0.906C2.742,2.195,2.363,2.056,1.927,1.992c-0.431-0.065-0.89-0.096-1.373-0.096H0V0.063h12.705v1.833h-0.577c-0.483,0-0.943,0.035-1.386,0.107c-0.44,0.07-0.819,0.217-1.14,0.437C9.283,2.66,9.027,2.976,8.834,3.389C8.642,3.8,8.547,4.348,8.547,5.03v8.823h14.195V5.03c0-0.683-0.096-1.23-0.287-1.642s-0.448-0.729-0.768-0.948c-0.32-0.22-0.696-0.366-1.131-0.437c-0.435-0.072-0.897-0.107-1.396-0.107h-0.577V0.063h12.705v1.833h-0.553c-0.498,0-0.961,0.035-1.396,0.107c-0.434,0.07-0.812,0.217-1.141,0.437c-0.326,0.22-0.582,0.536-0.768,0.948c-0.186,0.411-0.277,0.959-0.277,1.642v21.442c0,0.64,0.097,1.155,0.287,1.545c0.192,0.392,0.453,0.687,0.779,0.884c0.326,0.2,0.705,0.331,1.141,0.396c0.434,0.064,0.892,0.096,1.373,0.096h0.556v1.833H18.585z"/></g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g></svg>' svg_off: ''
}, },
'core_section_textarea': { core_section_textarea: {
label: 'Pole tekstowe', label: 'Pole tekstowe',
svg_off: '<svg id="Capa_1" enable-background="new 0 0 512 512" height="128" viewBox="0 0 512 512" width="128" xmlns="http://www.w3.org/2000/svg"><g><path d="m15 114.235c8.284 0 15-6.716 15-15v-69.235h69.235c8.284 0 15-6.716 15-15s-6.716-15-15-15h-84.235c-8.284 0-15 6.716-15 15v84.235c0 8.285 6.716 15 15 15z"/><path d="m497 0h-84.235c-8.284 0-15 6.716-15 15s6.716 15 15 15h69.235v69.235c0 8.284 6.716 15 15 15s15-6.716 15-15v-84.235c0-8.284-6.716-15-15-15z"/><path d="m497 397.765c-8.284 0-15 6.716-15 15v69.235h-69.235c-8.284 0-15 6.716-15 15s6.716 15 15 15h84.235c8.284 0 15-6.716 15-15v-84.235c0-8.285-6.716-15-15-15z"/><path d="m99.235 482h-69.235v-69.235c0-8.284-6.716-15-15-15s-15 6.716-15 15v84.235c0 8.284 6.716 15 15 15h84.235c8.284 0 15-6.716 15-15s-6.715-15-15-15z"/><path d="m419.66 191.38v-94.73c0-4.7-3.81-8.51-8.52-8.51h-155.14-155.14c-4.71 0-8.52 3.81-8.52 8.51v94.73c0 4.71 3.81 8.52 8.52 8.52h45.24c4.7 0 8.51-3.81 8.51-8.52v-32.45c0-4.71 3.82-8.52 8.52-8.52h53.21c4.71 0 8.52 3.81 8.52 8.52v234.14c0 4.71-3.81 8.52-8.52 8.52h-23.27c-4.71 0-8.52 3.81-8.52 8.52v45.24c0 4.7 3.81 8.51 8.52 8.51h62.93 62.93c4.71 0 8.52-3.81 8.52-8.51v-45.24c0-4.71-3.81-8.52-8.52-8.52h-23.27c-4.71 0-8.52-3.81-8.52-8.52v-234.14c0-4.71 3.81-8.52 8.52-8.52h53.21c4.7 0 8.52 3.81 8.52 8.52v32.45c0 4.71 3.81 8.52 8.51 8.52h45.24c4.71 0 8.52-3.81 8.52-8.52z"/></g></svg>' svg_off: ''
}, },
'core_section_html': { core_section_html: {
label: 'Pole HTML', label: 'Pole HTML',
svg_off: '<svg version="1.1" height="128" width="128" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"><g><g><path d="M467,0H45C20.187,0,0,20.187,0,45v422c0,24.813,20.187,45,45,45h422c24.813,0,45-20.187,45-45V45C512,20.187,491.813,0,467,0z M482,467c0,8.271-6.729,15-15,15H45c-8.271,0-15-6.729-15-15V150h452V467z M482,120H30V45c0-8.271,6.729-15,15-15h422c8.271,0,15,6.729,15,15V120z"/></g></g><g><g><path d="M127.213,316l49.393-49.393c5.858-5.858,5.858-15.356,0-21.214c-5.857-5.858-15.355-5.858-21.213,0l-60,60c-5.858,5.858-5.858,15.355,0,21.213l60,60c5.857,5.857,15.355,5.858,21.213,0c5.858-5.858,5.858-15.355,0-21.213L127.213,316z"/></g></g><g><g><path d="M416.607,305.393l-60.001-60c-5.857-5.858-15.355-5.858-21.213,0c-5.858,5.858-5.858,15.355,0,21.213L384.787,316l-49.393,49.393c-5.858,5.858-5.858,15.355,0,21.213c5.857,5.857,15.355,5.858,21.213,0l60-60C422.465,320.748,422.465,311.251,416.607,305.393z"/></g></g><g><g><path d="M290.744,211.77c-7.862-2.621-16.354,1.628-18.974,9.487l-60,180c-2.62,7.859,1.628,16.354,9.487,18.974c7.861,2.62,16.355-1.629,18.974-9.487l60-180C302.85,222.884,298.603,214.389,290.744,211.77z"/></g></g><g><g><path d="M106,60H76c-8.284,0-15,6.716-15,15s6.716,15,15,15h30c8.284,0,15-6.716,15-15S114.284,60,106,60z"/></g></g><g><g><path d="M196,60h-30c-8.284,0-15,6.716-15,15s6.716,15,15,15h30c8.284,0,15-6.716,15-15S204.284,60,196,60z"/></g></g><g><g><path d="M286,60h-30c-8.284,0-15,6.716-15,15s6.716,15,15,15h30c8.284,0,15-6.716,15-15S294.284,60,286,60z"/></g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g></svg>' svg_off: ''
}, },
'core_section_image': { core_section_image: {
label: 'Obrazek', label: 'Obrazek',
svg_off: '<svg version="1.1" id="Capa_1" height="128" width="128" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"><g><g><path d="M446.575,0H65.425C29.349,0,0,29.35,0,65.426v381.149C0,482.65,29.349,512,65.425,512h381.15C482.651,512,512,482.65,512,446.574V65.426C512,29.35,482.651,0,446.575,0z M481.842,446.575c0,19.447-15.821,35.267-35.267,35.267H65.425c-19.447,0-35.268-15.821-35.268-35.267v-55.007l99.255-84.451c3.622-3.082,8.906-3.111,12.562-0.075l62.174,51.628c5.995,4.977,14.795,4.569,20.304-0.946L372.181,209.77c2.67-2.675,5.783-2.935,7.408-2.852c1.62,0.083,4.695,0.661,7.078,3.596l95.176,117.19V446.575z M481.842,279.865l-71.766-88.366c-7.117-8.764-17.666-14.122-28.942-14.701c-11.268-0.57-22.317,3.672-30.294,11.662L212.832,326.681l-51.59-42.839c-14.959-12.422-36.563-12.293-51.373,0.308l-79.712,67.822V65.426c0-19.447,15.821-35.268,35.268-35.268h381.15c19.447,0,35.267,15.821,35.267,35.268V279.865z"/></g></g><g><g><path d="M161.174,62.995c-40.095,0-72.713,32.62-72.713,72.713c0,40.094,32.619,72.713,72.713,72.713s72.713-32.619,72.713-72.713S201.269,62.995,161.174,62.995z M161.174,178.264c-23.466,0-42.556-19.091-42.556-42.556c0-23.466,19.09-42.556,42.556-42.556c23.466,0,42.556,19.091,42.556,42.556S184.64,178.264,161.174,178.264z"/></g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g></svg>' svg_off: ''
} },
}, core_section_video: {
axios: null, label: 'Wideo',
registerPlugin(name, item, component) { svg_off: ''
this.items[name] = item;
app.component(name, component);
}
} }
},
axios: null,
registerPlugin(name, item, component) {
this.items[name] = item
if (component) {
app.component(name, component)
}
}
} }
}
} }

View File

@@ -1,113 +1,175 @@
<template> <template>
<div style="min-height: 100px;" class="pagebuilder-column" :class="value.name"> <div style="min-height: 100px" class="pagebuilder-column" :class="value.name">
<h6 v-if="value.user_label">{{ value.user_label }}</h6>
<b-modal
v-model="modalAddBox"
class_other="modal-xl"
v-on:onClose="modalAddBox = false"
title="Dodaj widżet"
>
<div>
<DropdownSectionSection v-if="modalAddBox" @choose="clickAdd"> </DropdownSectionSection>
</div>
</b-modal>
<b-modal v-model="modalAddBox" class_other="modal-xl" v-on:onClose="modalAddBox = false" title="Dodaj widżet"> <b-modal
v-model="modalColumnsSettings"
<div> title="Ustawienia kolumny"
<DropdownSectionSection v-on:input="clickAdd" v-model="opcja"> size="sm"
</DropdownSectionSection> v-on:onClose="modalColumnsSettings = false"
</div> >
<div slot="modal-footer"></div> <div>
</b-modal> <div class="from-group mb-3">
<label class="form-label">Nazwa kolumny</label>
<input @input="onChange" v-model="value.user_label" type="text" class="form-control" />
<b-modal v-model="modalColumnsSettings" title="Ustawienia kolumny" size="sm"
v-on:onClose="modalColumnsSettings = false">
<div>
<div class="from-group">
<label>Klasa kolumny</label>
<input @input="onChange" v-model="value.class" type="text" class="form-control">
</div>
</div>
<div slot="modal-footer"><button @click="modalColumnsSettings = false" class="btn btn-outline-secondary">Zapisz
i zamknij</button></div>
</b-modal>
<draggable :options="{ handle: '.box-move' }" v-model="value.items" @start="drag = true"
@end="drag = false; onChange()" group="people">
<div v-for="(item, index) in value.items" :key="index"
class="pb_section table-bordered p-2 pl-3 pr-3 mb-3 rounded">
<component @itemRemoved="removeItem" :key="index" v-bind:is="item.name" v-bind:value="item"
v-model="value.items[index]" @input="onChange" @change="onChange"></component>
</div>
</draggable>
<div :class="value.items.length > 0 ? 'pagebuilder-column-hover-padding' : ''"></div>
<div class="posistion-relative " :class="value.items.length > 0 ? 'pagebuilder-column-hover' : 'd-flex'">
<div class="flex-fill mr-0 pr-0 ">
<button class=" w-100 btn btn-icon-sm btn-outline-primary off_tooltip_off"
@click.prevent="modalAddBox = !modalAddBox" title="Dodaj widget"> <i
class="material-icons-outlined">add_circle_outline</i></button>
</div>
<div class="ml-0 pl-0">
<a title="Ustawienia kolumny" class="btn-icon-sm"
@click.prevent="modalColumnsSettings = !modalColumnsSettings"><i
style=" cursor:pointer; position: relative; top:5px; margin-left: 5px;"
class="material-icons-outlined">create</i></a>
</div>
</div> </div>
<div class="from-group mb-3">
<label class="form-label">Klasa kolumny</label>
<input @input="onChange" v-model="value.class" type="text" class="form-control" />
</div>
<AosSelect v-model="value.attribute" @aos-changed="onChange" />
</div>
<div class="mt-4">
<button @click="modalColumnsSettings = false" class="btn btn-outline-secondary">
Zapisz i zamknij
</button>
</div>
</b-modal>
<draggable
:options="{ handle: '.box-move' }"
v-model="value.items"
itemKey="name"
@start="drag = true"
@end="
drag = false;
onChange()
"
group="people"
>
<template #item="{ element, index }">
<div class="pb_section table-bordered p-2 pl-3 pr-3 mb-3 rounded">
<component
@itemRemoved="removeItem"
:key="keyIndex+contentId + element.name+index"
:id="keyIndex+contentId + element.name+index"
v-bind:is="element.name"
v-bind:value="element"
v-model="value.items[index]"
@update:model-value="onChange"
@change="onChange"
></component>
</div>
</template>
</draggable>
<div :class="value.items.length > 0 ? 'pagebuilder-column-hover-padding' : ''"></div>
<div
class="posistion-relative"
:class="value.items.length > 0 ? 'pagebuilder-column-hover' : 'd-flex'"
>
<div class="flex-fill mr-0 pr-0">
<button
class="w-100 btn btn-icon-sm btn-outline-primary off_tooltip_off"
@click.prevent="modalAddBox = !modalAddBox"
title="Dodaj widget"
>
<i class="material-icons-outlined">add_circle_outline</i>
</button>
</div>
<div class="ml-0 pl-0">
<a
title="Ustawienia kolumny"
class="btn-icon-sm"
@click.prevent="modalColumnsSettings = !modalColumnsSettings"
><i
style="cursor: pointer; position: relative; top: 5px; margin-left: 5px"
class="material-icons-outlined"
>create</i
></a
>
</div>
</div> </div>
</div>
</template> </template>
<script> <script>
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import MagicoModal from './MagicoModal.vue' import MagicoModal from './MagicoModal.vue'
import SectionText from './plugin/SectionText.vue' import SectionText from './plugin/SectionText.vue'
import SectionTextarea from './plugin/SectionTextarea.vue' import SectionTextarea from './plugin/SectionTextarea.vue'
import SectionVideo from './plugin/SectionVideo.vue'
import SectionHtml from './plugin/SectionHtml.vue' import SectionHtml from './plugin/SectionHtml.vue'
import SectionImage from './plugin/SectionImage.vue' import SectionImage from './plugin/SectionImage.vue'
import DropdownSectionSection from './DropdownSectionSection.vue' import DropdownSectionSection from './DropdownSectionSection.vue'
import AosSelect from './AosSelect.vue'
export default { export default {
data: function () { return { opcja: '', modalAddBox: false, drag: false, modalColumnsSettings: false } }, data: function () {
props: { value: Object },
components: { return {
draggable, opcja: '',
'b-modal': MagicoModal, modalAddBox: false,
'core_section_textarea': SectionTextarea, drag: false,
'core_section_text': SectionText,
'core_section_html': SectionHtml,
'core_section_image': SectionImage,
DropdownSectionSection modalColumnsSettings: false,
contentId: 'cnt' + Math.round(Math.random() * 1000)
},
methods: {
onChange: function () {
this.$emit('change');
},
rand: function () { return 'component' + Math.random() * 100 },
removeItem(item) {
this.value.items.indexOf(item);
this.value.items.splice(this.value.items.indexOf(item), 1);
this.onChange();
},
clickAdd: function (item) {
console.log(item);
this.modalAddBox = false;
var a = { name: item, open: true }
this.value.items.push(a);
this.onChange();
this.opcja = '';
}
} }
},
props: { value: Object, keyIndex: String },
emits: ['update:modelValue','change'],
components: {
draggable,
'b-modal': MagicoModal,
core_section_textarea: SectionTextarea,
core_section_text: SectionText,
core_section_html: SectionHtml,
core_section_image: SectionImage,
core_section_video: SectionVideo,
DropdownSectionSection,
AosSelect
},
methods: {
onChange: function () {
this.$emit('change')
},
rand: function () {
return 'c' + Math.round(Math.random() * 1000)
},
removeItem(item) {
this.value.items.indexOf(item)
this.value.items.splice(this.value.items.indexOf(item), 1)
this.onChange()
},
clickAdd: function (item) {
console.log(item)
const sectionobj = this.$pagebuilder.items[item]
console.log('addedd', sectionobj)
this.modalAddBox = false
var a = { name: item, open: true }
if (sectionobj.section_id) {
a.section_id = sectionobj.section_id
}
this.value.items.push(a)
this.onChange()
}
}
} }
</script> </script>
<style> <style>
.pagebuilder-column-hover { .pagebuilder-column-hover {
display: none; display: none;
} }
.pagebuilder-column-hover-padding { .pagebuilder-column-hover-padding {
padding: 17px; padding: 17px;
} }
.pagebuilder-column:hover .pagebuilder-column-hover { .pagebuilder-column:hover .pagebuilder-column-hover {
display: flex; display: flex;
} }
.pagebuilder-column:hover .pagebuilder-column-hover-padding { .pagebuilder-column:hover .pagebuilder-column-hover-padding {
padding: 0px; padding: 0px;
} }
</style> </style>

View File

@@ -1,121 +1,171 @@
<template> <template>
<div class="row pb-3 mb-3 position-relative border-bottom pb_outer_section pr-5"> <div class="row pb-3 mb-3 position-relative border-bottom pb_outer_section pr-5">
<div class="col-sm-12">
<div class="col-sm-12"> <h5 class="mt-4" v-if="value.title">{{ value.title }}</h5>
<div class="row p-0 mt-3 me-2"> <div class="row p-0 mt-3 me-2">
<PagebuilderContent class="col-sm-12" v-for="(column, index) in value.columns" :value="column" <PagebuilderContent class="col-sm-12" v-for="(column, index) in value.columns" :value="column"
:key="index" @change="onChange"></PagebuilderContent> :key="keyIndex + 's' + index" :id="keyIndex + 's' + index" :keyIndex="keyIndex + 's' + index"
</div> @change="onChange"></PagebuilderContent>
</div> </div>
<div class="pb_section_options position-absolute" style="top: 12px; right: 14px; width: 20px;">
<a href="#" title="Przenieś sekcje" class="box-settings-icon box-move"><i
class="material-icons-outlined">sort</i></a>
<a href="#" title="Duplikuj sekcje" @click.prevent="copySection"
class="box-settings-icon box-copy text-warning"><i class="material-icons-outlined">file_copy</i></a>
<a href="#" title="Ustawienia sekcji" @click.prevent="toggleSettings"
class="box-settings-icon box-settings text-secondary"><i
class="material-icons-outlined">settings</i></a>
<a href="#" title="Usuń sekcje" @click.prevent="deleteSection"
class="box-settings-icon box-delete text-danger"><i class="material-icons-outlined">delete</i></a>
<b-modal v-model="show_settings" title="Ustawienia sekcji"
@onClose="ustawieniaSave()">
<div>
<div>
<div class="form-group mb-2">
<label class="w-100 col-form-label">
Klasa sekcji
</label>
<input type="text" class="form-control" v-model="value.class">
</div>
<div class="form-group mb-2">
<label>Margines górny</label>
<div class="input-group mb-3">
<input type="number" class="form-control" v-model="value.margin_top">
<div class="input-group-append">
<span class="input-group-text" id="basic-addon1">px</span>
</div>
</div>
</div>
</div>
<div class="form-group mb-2">
<label>Margines dolny</label>
<div class="input-group mb-3">
<input type="number" class="form-control" v-model="value.margin_bottom">
<div class="input-group-append">
<span class="input-group-text" id="basic-addon1">px</span>
</div>
</div>
</div>
</div>
<div><button class="btn btn-outline-secondary" @click.prevent="ustawieniaSave">
Zapisz
</button></div>
</b-modal>
</div>
</div> </div>
<div class="pb_section_options position-absolute" style="top: 12px; right: 14px; width: 20px">
<a href="#" title="Przenieś sekcje" class="box-settings-icon box-move"><i
class="material-icons-outlined">sort</i></a>
<a href="#" title="Duplikuj sekcje" @click.prevent="copySection"
class="box-settings-icon box-copy text-warning"><i class="material-icons-outlined">file_copy</i></a>
<a href="#" title="Ustawienia sekcji" @click.prevent="toggleSettings"
class="box-settings-icon box-settings text-secondary"><i class="material-icons-outlined">settings</i></a>
<a href="#" title="Usuń sekcje" @click.prevent="deleteSection" class="box-settings-icon box-delete text-danger"><i
class="material-icons-outlined">delete</i></a>
<b-modal v-model="show_settings" :title="t('pagebuilder.section_settings')" @onClose="ustawieniaSave()">
<div>
<div class="form-group mb-3">
<label class="w-100 col-form-label"> {{ t('pagebuilder.section_type') }} </label>
<div class="row">
<div class="col-6">
<button class="btn w-100" @click="setType('container')"
:class="type == 'container' ? 'btn-primary' : 'btn-outline-primary'">
{{ t('pagebuilder.container') }}
</button>
</div>
<div class="col-6">
<button class="btn w-100" @click="setType('full')"
:class="type == 'full' ? 'btn-primary' : 'btn-outline-primary'">
{{ t('pagebuilder.full_width') }}
</button>
</div>
</div>
</div>
<div>
<div class="form-group mb-3">
<label class="w-100 col-form-label">Tytuł sekcji</label>
<input type="text" class="form-control" v-model="value.title">
</div>
<div class="form-group mb-3 ml-4">
<input type="checkbox" id="dropdown" class="form-check-input me-1" v-model="value.dropdown">
<label for="dropdown" class="form-check-label">Sekcja rozwijana</label>
</div>
<div v-if="value.dropdown" class="form-group mb-3 ml-4">
<input type="checkbox" id="dropdown_default_open" class="form-check-input me-1"
v-model="value.dropdown_default_open">
<label for="dropdown_default_open" class="form-check-label">Domyślnie rozwinięta</label>
</div>
<div class="form-group mb-3">
<label class="w-100 col-form-label"> Klasa sekcji </label>
<input type="text" class="form-control" v-model="value.class" />
</div>
<AosSelect v-model="value.attribute" />
<div class="form-group mb-3">
<label class="form-label">Margines górny</label>
<div class="input-group">
<input type="number" class="form-control" v-model="value.margin_top" />
<div class="input-group-append">
<span class="input-group-text" id="basic-addon1">px</span>
</div>
</div>
</div>
</div>
<div class="form-group mb-3">
<label class="form-label">Margines dolny</label>
<div class="input-group">
<input type="number" class="form-control" v-model="value.margin_bottom" />
<div class="input-group-append">
<span class="input-group-text" id="basic-addon1">px</span>
</div>
</div>
</div>
</div>
<div>
<button class="btn btn-outline-secondary" @click.prevent="ustawieniaSave">
{{ t('pagebuilder.save') }}
</button>
</div>
</b-modal>
</div>
</div>
</template> </template>
<script> <script>
import { useI18n } from 'vue-i18n'
import grid from './grid.js' import grid from './grid.js'
import MagicoModal from './MagicoModal.vue' import MagicoModal from './MagicoModal.vue'
import PagebuilderContent from './PagebuilderContent.vue' import PagebuilderContent from './PagebuilderContent.vue'
import AosSelect from './AosSelect.vue'
export default { export default {
props: { value: Object }, props: { value: Object, keyIndex: String },
components: { emits: ['update:modelValue', 'copy', 'deleteSection', 'change'],
'b-modal': MagicoModal, components: {
PagebuilderContent 'b-modal': MagicoModal,
PagebuilderContent,
AosSelect
},
data: function () {
return { items: grid, value2: '', show_settings: false, type: '' }
},
setup() {
const { t } = useI18n()
return { t }
},
methods: {
changeSelect: function () {
this.onChange()
}, },
data: function () { return { items: grid, value2: '', show_settings: false } }, onChange: function () {
methods: { this.$emit('change')
changeSelect: function () {
this.onChange();
},
onChange: function () {
this.$emit('change');
},
deleteSection: function () { this.$emit('deleteSection', this.value) },
copySection: function () { this.$emit('copy', this.value); },
toggleSettings: function () { this.show_settings = !this.show_settings; },
ustawieniaSave: function () { this.show_settings = false; this.onChange(); },
rand: function (index) { return 'column' + index + Math.random() * 100 },
}, },
mounted: function () { deleteSection: function () {
this.$emit('deleteSection', this.value)
}, },
copySection: function () {
this.$emit('copy', this.value)
},
toggleSettings: function () {
this.show_settings = !this.show_settings
},
ustawieniaSave: function () {
this.show_settings = false
this.onChange()
},
rand: function (index) {
return 'column' + index + Math.random() * 100
},
setType: function (type) {
this.type = type
this.value.type = type
this.onChange()
}
},
mounted: function () {
this.type = this.value.type
}
} }
</script> </script>
<style> <style>
#pagebuilder { #pagebuilder {
background-color: #f5f5f5; background-color: #f5f5f5;
} }
.pb_section { .pb_section {
background-color: #fff; background-color: #fff;
>div { >div {
overflow: hidden; overflow: hidden;
} }
} }
.btn.btn-icon-sm, .btn.drp-icon-sm { .btn.btn-icon-sm,
width: 34px; .btn.drp-icon-sm {
height: 34px; width: 34px;
padding: 6px 6px; height: 34px;
margin-bottom: 0px; padding: 6px 6px;
margin-right: 4px; margin-bottom: 0px;
} margin-right: 4px;
.material-icons-outlined{
font-size: 20px;
} }
</style> .material-icons-outlined {
font-size: 20px;
}
</style>

View File

@@ -1,19 +1,20 @@
<template> <template>
<div class="form form-group"> <div class="form form-group">
<div class="ms-3"> <div class="ms-3">
<div class="mb-3" v-for="item, ii in items" :key="ii" :value="item">{{ item.name }} <button <div class="mb-3 w-100" v-for="item, ii in items" :key="ii" :value="item"> <button
class="btn btn-outline-primary" @click="itemselected = item; changeSelect()">Wczytaj</button> class="btn btn-outline-secondary w-100" @click="itemselected = item; changeSelect()">Wczytaj {{ item.name }}</button>
</div> </div>
</div> </div>
<div v-show="items.length == 0"><i>Brak zapisanych szablonów</i></div> <div v-show="items.length == 0"><i>Brak zapisanych szablonów</i></div>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
created() { mounted() {
this.getPost(); this.getPost();
}, },
emits: ['update:modelValue','change'],
data: function () { data: function () {
return { return {
items: [], items: [],
@@ -22,7 +23,7 @@ export default {
}, },
methods: { methods: {
changeSelect() { changeSelect() {
this.$emit('input', this.itemselected); this.$emit('update:modelValue', this.itemselected);
}, },
getPost() { getPost() {
if (this.$pagebuilder.axios) { if (this.$pagebuilder.axios) {

View File

@@ -1,66 +1,102 @@
<template> <template>
<div> <div>
<div class="form-group mb-3 "> <div class="form-group mb-3">
<label v-if="id < 1" class="col-4">Tworzysz nowy szablon</label> <label
<label v-if="id > 0" class="col-4">Nadpiszesz istniejacy szablon</label> v-if="id < 1"
<div class="col-8"><b v-if="id > 0" class="">{{ name2 }}</b></div> class="col-4"
</div> >Tworzysz nowy szablon</label
<div class="form form-group mb-3"> >
<label class="w-100">Wyszukaj istniejący lub zapisz jako nowy</label> <label
<select v-model="itemselected" @change="changeSelect" class="form-control"> v-if="id > 0"
<option :value="{ 'new': 1 }">Stwórz nowy szablon</option> class="col-4"
<option :key="ii" v-for="item, ii in items" :value="item">Nadpisz: {{ item.name }}</option> >Nadpiszesz istniejacy szablon</label
</select> >
</div> <div class="col-8">
<div v-show="itemselected.new == 1"> <b
<div class="form form-group mb-3"><label class="w-100">Nazwa szablonu</label><input @change="change" v-if="id > 0"
class="form-control" type="text" v-model="name"></div> class=""
<div class="form form-group mb-3"><label class="w-100">Opis</label><input @change="change" >{{ name2 }}</b
class="form-control" type="text" v-model="description"></div> >
</div> </div>
</div> </div>
<div class="form form-group mb-3">
<label class="w-100">Wyszukaj istniejący lub zapisz jako nowy</label>
<select
v-model="itemselected"
@change="changeSelect"
class="form-control"
>
<option :value="{ new: 1 }">Stwórz nowy szablon</option>
<option
:key="ii"
v-for="(item, ii) in items"
:value="item"
>
Nadpisz: {{ item.name }}
</option>
</select>
</div>
<div v-show="itemselected.new == 1">
<div class="form form-group mb-3">
<label class="w-100">Nazwa szablonu</label
><input
@change="change"
class="form-control"
type="text"
v-model="name"
/>
</div>
<div class="form form-group mb-3">
<label class="w-100">Opis</label
><input
@change="change"
class="form-control"
type="text"
v-model="description"
/>
</div>
</div>
</div>
</template> </template>
<script> <script>
export default { export default {
created() { created() {
this.getPost(); this.getPost();
},
data: function () {
return {
items: [],
itemselected: { new: 1 },
name: "",
description: "",
id: 0,
};
},
emits: ['update:modelValue','change'],
methods: {
change() {
this.$emit("update:modelValue", {
id: this.id,
name: this.name,
description: this.description,
});
}, },
data: function () { changeSelect() {
return { this.id = this.itemselected.id;
items: [], this.name = this.itemselected.name;
itemselected: {new:1}, this.name2 = this.itemselected.naem;
name: '', this.description = this.itemselected.description;
description: '', this.change();
id: 0,
}
}, },
methods: { getPost() {
change() { if (this.$pagebuilder.axios) {
this.$emit('input', { this.$pagebuilder.axios.get("api/v1/pagebuilder/template").then((response) => {
id: this.id, this.items = response.data.data;
name: this.name, });
description: this.description, } else {
}); console.error("NO AXIOS INSTACE PROVIDED TO PAGEBUILDER");
}, }
changeSelect() { },
this.id = this.itemselected.id; },
this.name = this.itemselected.name; };
this.name2 = this.itemselected.naem; </script>
this.description = this.itemselected.description;
this.change();
},
getPost() {
if (this.$pagebuilder.axios) {
this.$pagebuilder.axios.get('api/v1/pagebuilder/template').then(response => {
this.items = response.data.data;
});
} else {
console.error('NO AXIOS INSTACE PROVIDED TO PAGEBUILDER');
}
}
}
}
</script>

View File

@@ -1,14 +1,129 @@
export default { export default {
'col_1': { label: '1 kolumna ', name: 'col_1', class: '', columns: [{ name: 'col-md-12', items: [] }] }, col_1: {
'col_2': { label: '2 kolumny po 6 ', name: 'col_2', class: '', columns: [{ name: 'col-md-6', items: [] }, { name: 'col-md-6', items: [] }] }, label: '1 kolumna ',
'col_4_8': { label: '2 kolumny 2 i 8 ', name: 'col_4_8', class: '', columns: [{ name: 'col-md-4', items: [] }, { name: 'col-md-8', items: [] }] }, name: 'col_1',
'col_8_4': { label: '2 kolkumny 8 i 2 ', name: 'col_8_4', class: '', columns: [{ name: 'col-md-8', items: [] }, { name: 'col-md-4', items: [] }] }, type: 'container',
'col_2_10': { label: '2 kolumny 2 i 10 ', name: 'col_2_10', class: '', columns: [{ name: 'col-md-2', items: [] }, { name: 'col-md-10', items: [] }] }, class: '',
'col_10_2': { label: '2 kolkumny 10 i 2 ', name: 'col_10_2', class: '', columns: [{ name: 'col-md-10', items: [] }, { name: 'col-md-2', items: [] }] }, columns: [{ name: 'col-md-12', items: [], class: '', attribute: '' }]
'col_3': { label: '3 kolumny po 4 ', name: 'col_3', class: '', columns: [{ name: 'col-md-4', items: [] }, { name: 'col-md-4', items: [] }, { name: 'col-md-4', items: [] }] }, },
'col_3_6_3': { label: '3 kolumny: 3 ,6, 3 ', name: 'col_3_6_3', class: '', columns: [{ name: 'col-md-3', items: [] }, { name: 'col-md-6', items: [] }, { name: 'col-md-3', items: [] }] }, col_2: {
'col_6_3_3': { label: '3 kolumny: 6,3,3 ', name: 'col_6_3_3', class: '', columns: [{ name: 'col-md-6', items: [] }, { name: 'col-md-3', items: [] }, { name: 'col-md-3', items: [] }] }, label: '2 kolumny po 6 ',
'col_3_3_6': { label: '3 kolumny: 3,3,6 ', name: 'col_3_3_6', class: '', columns: [{ name: 'col-md-3', items: [] }, { name: 'col-md-3', items: [] }, { name: 'col-md-6', items: [] }] }, name: 'col_2',
'col_4': { label: '4 kolumny po 3 ', name: 'col_4', class: '', columns: [{ name: 'col-md-3', items: [] }, { name: 'col-md-3', items: [] }, { name: 'col-md-3', items: [] }, { name: 'col-md-3', items: [] }] }, type: 'container',
'col_6': { label: '6 kolumn po 2 ', name: 'col_6', class: '', columns: [{ name: 'col-md-2', items: [] }, { name: 'col-md-2', items: [] }, { name: 'col-md-2', items: [] }, { name: 'col-md-2', items: [] }, { name: 'col-md-2', items: [] }, { name: 'col-md-2', items: [] }] }, class: '',
} columns: [
{ name: 'col-md-6', items: [], class: '', attribute: '' },
{ name: 'col-md-6', items: [], class: '', attribute: '' }
]
},
col_4_8: {
label: '2 kolumny 2 i 8 ',
name: 'col_4_8',
type: 'container',
class: '',
columns: [
{ name: 'col-md-4', items: [], class: '', attribute: '' },
{ name: 'col-md-8', items: [], class: '', attribute: '' }
]
},
col_8_4: {
label: '2 kolkumny 8 i 2 ',
name: 'col_8_4',
type: 'container',
class: '',
columns: [
{ name: 'col-md-8', items: [], class: '', attribute: '' },
{ name: 'col-md-4', items: [], class: '', attribute: '' }
]
},
col_2_10: {
label: '2 kolumny 2 i 10 ',
name: 'col_2_10',
type: 'container',
class: '',
columns: [
{ name: 'col-md-2', items: [], class: '', attribute: '' },
{ name: 'col-md-10', items: [], class: '', attribute: '' }
]
},
col_10_2: {
label: '2 kolkumny 10 i 2 ',
name: 'col_10_2',
type: 'container',
class: '',
columns: [
{ name: 'col-md-10', items: [], class: '', attribute: '' },
{ name: 'col-md-2', items: [], class: '', attribute: '' }
]
},
col_3: {
label: '3 kolumny po 4 ',
name: 'col_3',
type: 'container',
class: '',
columns: [
{ name: 'col-md-4', items: [], class: '', attribute: '' },
{ name: 'col-md-4', items: [], class: '', attribute: '' },
{ name: 'col-md-4', items: [], class: '', attribute: '' }
]
},
col_3_6_3: {
label: '3 kolumny: 3 ,6, 3 ',
name: 'col_3_6_3',
type: 'container',
class: '',
columns: [
{ name: 'col-md-3', items: [], class: '', attribute: '' },
{ name: 'col-md-6', items: [], class: '', attribute: '' },
{ name: 'col-md-3', items: [], class: '', attribute: '' }
]
},
col_6_3_3: {
label: '3 kolumny: 6,3,3 ',
name: 'col_6_3_3',
type: 'container',
class: '',
columns: [
{ name: 'col-md-6', items: [], class: '', attribute: '' },
{ name: 'col-md-3', items: [], class: '', attribute: '' },
{ name: 'col-md-3', items: [], class: '', attribute: '' }
]
},
col_3_3_6: {
label: '3 kolumny: 3,3,6 ',
name: 'col_3_3_6',
type: 'container',
class: '',
columns: [
{ name: 'col-md-3', items: [], class: '', attribute: '' },
{ name: 'col-md-3', items: [], class: '', attribute: '' },
{ name: 'col-md-6', items: [], class: '', attribute: '' }
]
},
col_4: {
label: '4 kolumny po 3 ',
name: 'col_4',
type: 'container',
class: '',
columns: [
{ name: 'col-md-3', items: [], class: '', attribute: '' },
{ name: 'col-md-3', items: [], class: '', attribute: '' },
{ name: 'col-md-3', items: [], class: '', attribute: '' },
{ name: 'col-md-3', items: [], class: '', attribute: '' }
]
},
col_6: {
label: '6 kolumn po 2 ',
name: 'col_6',
type: 'container',
class: '',
columns: [
{ name: 'col-md-2', items: [], class: '', attribute: '' },
{ name: 'col-md-2', items: [], class: '', attribute: '' },
{ name: 'col-md-2', items: [], class: '', attribute: '' },
{ name: 'col-md-2', items: [], class: '', attribute: '' },
{ name: 'col-md-2', items: [], class: '', attribute: '' },
{ name: 'col-md-2', items: [], class: '', attribute: '' }
]
}
}

View File

@@ -31,17 +31,16 @@ import MagicoModal from './../MagicoModal.vue'
export default { export default {
components: { components: {
'b-modal': MagicoModal, 'b-modal': MagicoModal,
}, },
props: { props: {
value: Object modelValue: Object
}, },
mounted: function () { mounted: function () {
this.name = (this.value && this.value.name) ? this.value.name : this.name; this.name = (this.modelValue && this.modelValue.name) ? this.modelValue.name : this.name;
this.text = (this.value && this.value.text) ? this.value.text : this.text; this.text = (this.modelValue && this.modelValue.text) ? this.modelValue.text : this.text;
if (this.value.open) this.modalBox = true; if (this.modelValue.open) this.modalBox = true;
console.log('mounted html'); console.log('mounted html');
this.$emit('input',this.value); this.$emit('update:modelValue',this.modelValue);
}, },
data: function () { data: function () {
return { return {
@@ -58,21 +57,20 @@ export default {
}, },
computed: { computed: {
ctext: function () { ctext: function () {
return this.value.text?this.value.text.replace(/<(?:.|\n)*?>/gm, ''):''; return this.modelValue.text?this.modelValue.text.replace(/<(?:.|\n)*?>/gm, ''):'';
} }
}, },
methods: { methods: {
removeItem: function () { removeItem: function () {
this.$emit('itemRemoved', this.value); this.$emit('itemRemoved', this.modelValue);
}, },
onCloseModal: function () { onCloseModal: function () {
this.modalBox = false; this.modalBox = false;
this.$emit('input', { this.$emit('update:modelValue', {
name: this.name, name: this.name,
text: this.text, text: this.text,
}) })
} }
}, },
} }
</script> </script>

View File

@@ -1,200 +1,228 @@
<template> <template>
<div class="row m-0 p-0 align-items-center"> <div class="row m-0 p-0 align-items-center">
<div class="col-sm-12 col-md-6 p-0">
<div class="col-sm-12 col-md-6 p-0"> <span class="material-icons-outlined box-move me-2" style="cursor: move">open_with</span
<span class="material-icons-outlined box-move me-2" style="cursor:move;">open_with</span><span ><span class="font-weight-bold text-primary">{{ langs.label }}</span>
class="font-weight-bold text-primary">{{ langs.label }}</span>
</div>
<div class="col-sm-12 col-md-6 p-0 text-end">
<a href="#" @click.prevent="modalOpen" title="Edytuj" class="text-primary me-2"><i
class="material-icons-outlined">create</i></a>
<a href="#" title="Usuń" @click.prevent="removeItem()" class="text-danger"><i
class="material-icons-outlined">delete</i></a>
</div>
<b-modal v-model="modalBox" v-on:close="onCloseModal" :title="langs.label">
<div>
<div class="p-0 m-0">
<div class="form-group ">
<label class="w-100 col-form-label">{{ langs.label }}</label>
<div class="input-group mb-3">
<input class="form-control" type="text" v-model="text" />
<button @click="chooseImage" class="btn btn-outline-secondary" type="button" id="button-addon2">Wybierz</button>
</div>
</div>
<div class="form-group ">
<label class="w-100 col-form-label">{{ langs.title }}</label>
<input class="form-control" type="text" v-model="title" />
</div>
<div class="form-group ">
<label class="w-100 col-form-label">{{ langs.alt }}</label>
<input class="form-control" type="text" v-model="alt" />
</div>
<div class="form-group ">
<label class="w-100 col-form-label">Legenda obrazka</label>
<input class="form-control" type="text" v-model="figcaption" />
</div>
<div class="form-group ">
<label class="w-100 col-form-label">{{ langs.scaling }}</label>
<select v-model="scale" class="form-select">
<option v-for="item, ii in scales" :key="ii" :value="item.key">{{ item.value }}
</option>
</select>
</div>
<div class="form-group">
<label class="w-100 col-form-label">{{ langs.href }}</label>
<input class="form-control" type="text" v-model="href" />
</div>
<fieldset class="mt-3" v-show="scale == 'tak'">
<legend>{{ langs.proportions }}</legend>
Brak możliwości skalowania obrazków z zewnętrznego serwera.
<div class="form-group"><label class="w-100 col-form-label">{{ langs.width
}}</label><input class="form-control" v-model="width"></div>
<div class="form-group"><label class="w-100 col-form-label">{{ langs.height
}}</label><input class="form-control" v-model="height"></div>
<div class="form-group"><label class="w-100 col-form-label">{{ langs.ratio
}}</label><select class="form-select" v-model="ratio">
<option v-for="item, ri in ratios" :key="ri">{{ item }}</option>
</select></div>
</fieldset>
<img v-if="text" :src="text" style="max-width: 100%;" class="my-2">
</div>
</div>
<div class="text-center mt-4"><button class="btn btn-outline-secondary mr-1"
@click.prevent="onCloseModal">{{
langs.saveclose
}}</button></div>
</b-modal>
<div v-if="text">
<img :src="text" style="width:100px;" />
</div>
</div> </div>
<div class="col-sm-12 col-md-6 p-0 text-end">
<a href="#" @click.prevent="modalOpen" title="Edytuj" class="text-primary me-2"
><i class="material-icons-outlined">create</i></a
>
<a href="#" title="Usuń" @click.prevent="removeItem()" class="text-danger"
><i class="material-icons-outlined">delete</i></a
>
</div>
<b-modal v-model="modalBox" v-on:close="onCloseModal" :title="langs.label">
<div>
<div class="p-0 m-0">
<div class="form-group">
<label class="w-100 col-form-label">{{ langs.label }}</label>
<div class="input-group mb-3">
<input class="form-control" type="text" v-model="text" />
<button
@click="chooseImage"
class="btn btn-outline-secondary"
type="button"
id="button-addon2"
>
Wybierz
</button>
</div>
</div>
<div class="form-group">
<label class="w-100 col-form-label">{{ langs.title }}</label>
<input class="form-control" type="text" v-model="title" />
</div>
<div class="form-group">
<label class="w-100 col-form-label">{{ langs.alt }}</label>
<input class="form-control" type="text" v-model="alt" />
</div>
<div class="form-group">
<label class="w-100 col-form-label">Legenda obrazka</label>
<input class="form-control" type="text" v-model="figcaption" />
</div>
<div class="form-group">
<label class="w-100 col-form-label">{{ langs.scaling }}</label>
<select v-model="scale" class="form-select">
<option v-for="(item, ii) in scales" :key="ii" :value="item.key">
{{ item.modelValue }}
</option>
</select>
</div>
<div class="form-group">
<label class="w-100 col-form-label">{{ langs.href }}</label>
<input class="form-control" type="text" v-model="href" />
</div>
<fieldset class="mt-3" v-show="scale == 'tak'">
<legend>{{ langs.proportions }}</legend>
Brak możliwości skalowania obrazków z zewnętrznego serwera.
<div class="form-group">
<label class="w-100 col-form-label">{{ langs.width }}</label
><input class="form-control" v-model="width" />
</div>
<div class="form-group">
<label class="w-100 col-form-label">{{ langs.height }}</label
><input class="form-control" v-model="height" />
</div>
<div class="form-group">
<label class="w-100 col-form-label">{{ langs.ratio }}</label
><select class="form-select" v-model="ratio">
<option v-for="(item, ri) in ratios" :key="ri">{{ item }}</option>
</select>
</div>
</fieldset>
<div class="form-group">
<label class="w-100 col-form-label">Używaj lightbox</label>
<select v-model="img_lightbox" class="form-select">
<option :value="false">NIE</option>
<option :value="true">TAK</option>
</select>
</div>
<img v-if="text" :src="text" style="max-width: 100%; max-height: 30vh; width: 100%;object-fit:contain;" class="my-2" />
</div>
</div>
<div class="text-center mt-4">
<button class="btn btn-outline-secondary mr-1" @click.prevent="onCloseModal">
{{ langs.saveclose }}
</button>
</div>
</b-modal>
<div v-if="text">
<img :src="text" style="width: 100px" />
</div>
</div>
</template> </template>
<script> <script>
import MagicoModal from './../MagicoModal.vue' import MagicoModal from './../MagicoModal.vue'
export default { export default {
props: { props: {
value: Object, modelValue: Object
}, },
data: function () { data: function () {
return { return {
langs: { langs: {
saveclose: "Zapisz", saveclose: 'Zapisz',
label: "Obrazek", label: 'Obrazek',
close: "Zamknij", close: 'Zamknij',
removefile: "<?=lang('pagebuilder_core_section_image_removefile')?>", removefile: "<?=lang('pagebuilder_core_section_image_removefile')?>",
fileupload: "<?=lang('pagebuilder_core_section_image_fileupload')?>", fileupload: "<?=lang('pagebuilder_core_section_image_fileupload')?>",
scaling: "Skalowanie", scaling: 'Skalowanie',
scalingyes: "Tak", scalingyes: 'Tak',
scalingno: "Nie", scalingno: 'Nie',
proportions: "Proporcje", proportions: 'Proporcje',
height: "Wysokość", height: 'Wysokość',
width: "Szerokość", width: 'Szerokość',
ratio: "Radio", ratio: 'Radio',
href: "Adres URL", href: 'Adres URL',
alt: "Tekst alternatywny", alt: 'Tekst alternatywny',
title: "Tytuł", title: 'Tytuł'
}, },
modalBox: false, modalBox: false,
items: [], items: [],
text: '', text: '',
name: '', name: '',
alt: '', alt: '',
href: '', href: '',
title: '', title: '',
width: 1800, width: 1800,
height: 600, height: 600,
ratio: 'crop', ratio: 'crop',
figcaption: '', figcaption: '',
ratios: ['crop', 'auto', 'width', 'height'], img_lightbox: true,
scales: [{ ratios: ['crop', 'auto', 'width', 'height'],
"key": "nie", scales: [
"value": "Nie" {
}, { key: 'nie',
"key": "tak", value: 'Nie'
"value": "Tak" },
}], {
scale: "Nie" key: 'tak',
value: 'Tak'
} }
],
scale: 'Nie'
}
},
mounted: function () {
console.log('mount image', this.modelValue)
this.alt = this.modelValue && this.modelValue.alt ? this.modelValue.alt : this.alt
this.title = this.modelValue && this.modelValue.title ? this.modelValue.title : this.title
this.name = this.modelValue && this.modelValue.name ? this.modelValue.name : this.name
this.text = this.modelValue && this.modelValue.text ? this.modelValue.text : this.text
this.width = this.modelValue && this.modelValue.width ? this.modelValue.width : this.width
this.height = this.modelValue && this.modelValue.height ? this.modelValue.height : this.height
this.ratio = this.modelValue && this.modelValue.ratio ? this.modelValue.ratio : this.ratio
this.scale = this.modelValue && this.modelValue.scale ? this.modelValue.scale : this.scale
this.href = this.modelValue && this.modelValue.href ? this.modelValue.href : this.href
this.figcaption =
this.modelValue && this.modelValue.figcaption ? this.modelValue.figcaption : this.figcaption
this.img_lightbox =
this.modelValue && this.modelValue.img_lightbox
? this.modelValue.img_lightbox
: this.img_lightbox
if (this.modelValue.open) this.modalBox = true
},
components: {
'b-modal': MagicoModal
},
methods: {
removeItem: function () {
this.$emit('itemRemoved', this.modelValue)
}, },
mounted: function () { chooseImage: function () {
console.log('mount image', this.value); if (this.$filechooser) {
this.alt = (this.value && this.value.alt) ? this.value.alt : this.alt; let vm = this
this.title = (this.value && this.value.title) ? this.value.title : this.title; this.$filechooser.open({
this.name = (this.value && this.value.name) ? this.value.name : this.name; chooseCallback: function (ev) {
this.text = (this.value && this.value.text) ? this.value.text : this.text; vm.text = ev.publicUrl
this.width = (this.value && this.value.width) ? this.value.width : this.width; }
this.height = (this.value && this.value.height) ? this.value.height : this.height; })
this.ratio = (this.value && this.value.ratio) ? this.value.ratio : this.ratio; } else {
this.scale = (this.value && this.value.scale) ? this.value.scale : this.scale; alert('No FileChooser implemented')
this.href = (this.value && this.value.href) ? this.value.href : this.href; }
this.figcaption = (this.value && this.value.figcaption) ? this.value.figcaption : this.figcaption;
if (this.value.open) this.modalBox = true;
}, },
components: { onCloseModal: function () {
'b-modal': MagicoModal, this.modalBox = false
this.$emit('update:modelValue', {
name: this.name,
text: this.text,
height: this.height,
width: this.width,
ratio: this.ratio,
scale: this.scale,
alt: this.alt,
href: this.href,
title: this.title,
figcaption: this.figcaption,
img_lightbox: this.img_lightbox
})
}, },
methods: { setText: function (item) {
removeItem: function () { this.text = 'files/images/' + item
this.$emit('itemRemoved', this.value); this.$emit('update:modelValue', {
}, name: this.name,
chooseImage: function () { text: this.text,
if (this.$filechooser) { height: this.height,
let vm = this; width: this.width,
this.$filechooser.open({ ratio: this.ratio,
chooseCallback: function (ev) { scale: this.scale,
vm.text = ev.publicUrl alt: this.alt,
} href: this.href,
}) title: this.title,
}else{ figcaption: this.figcaption,
alert('No FileChooser implemented') img_lightbox: this.img_lightbox
} })
},
onCloseModal: function () {
this.modalBox = false;
this.$emit('input', {
name: this.name,
text: this.text,
height: this.height,
width: this.width,
ratio: this.ratio,
scale: this.scale,
alt: this.alt,
href: this.href,
title: this.title,
figcaption: this.figcaption,
})
},
setText: function (item) {
this.text = 'files/images/' + item;
this.$emit('input', {
name: this.name,
text: this.text,
height: this.height,
width: this.width,
ratio: this.ratio,
scale: this.scale,
alt: this.alt,
href: this.href,
title: this.title,
figcaption: this.figcaption,
})
},
modalOpen: function () {
this.modalBox = !this.modalBox;
//this.getItems();
},
}, },
modalOpen: function () {
}; this.modalBox = !this.modalBox
</script> //this.getItems();
}
}
}
</script>

View File

@@ -1,123 +1,149 @@
<template> <template>
<div class="row m-0 p-0 align-items-center"> <div class="row m-0 p-0 align-items-center">
<div class="col-sm-12 col-md-6 p-0 mb-0"> <div class="col-sm-12 col-md-6 p-0 mb-0">
<span class="material-icons-outlined me-1 box-move" style="cursor:move;">open_with</span><span <span class="material-icons-outlined me-1 box-move" style="cursor: move">open_with</span
class="font-weight-bold text-primary">{{ langs.label }}</span> ><span class="font-weight-bold text-primary">{{ t('pagebuilder.widget_text') }}</span>
</div>
<div class="col-sm-12 col-md-6 p-0 text-end">
<a href="#" @click.prevent="modalBox = !modalBox" title="Edytuj" class="text-primary me-2"><i
class="material-icons-outlined">create</i></a>
<a href="#" title="Usuń" @click.prevent="removeItem()" class="text-danger"><i
class="material-icons-outlined">delete</i></a>
</div>
<div class="ms-2">
<strong class="font-weight-bold">{{ langs.type }}:</strong> {{ h_type }},
<strong class="font-weight-bold">{{ langs.content }}:</strong> {{ (text) ? text : ' ' }}
</div>
<b-modal v-model="modalBox" :title="langs.label" @close="onCloseModal">
<div class="form-group">
<label class="w-100 col-form-label">{{ langs.content }}</label>
<input class="form-control" type="text" v-model="text" />
</div>
<div class="form-grou mb-2">
<label class="w-100 col-form-label">{{ langs.type }}</label>
<select class="form-select" v-model="h_type">
<option value="">{{ langs.typeplaintext }}</option>
<option value="h1">{{ langs.typeheader }} 1</option>
<option value="h2">{{ langs.typeheader }} 2</option>
<option value="h3">{{ langs.typeheader }} 3</option>
<option value="h4">{{ langs.typeheader }} 4</option>
<option value="h5">{{ langs.typeheader }} 5</option>
<option value="h6">{{ langs.typeheader }} 6</option>
</select>
</div>
<div class="form-group">
<label class="w-100 col-form-label">Wyrównanie</label>
<div class="">
<button v-tooltip title="Wyrównanie do lewej" @click="align = 'left'" class="btn btn-icon-sm "
:class="align == 'left' ? 'btn-primary' : 'btn-outline-primary'">
<span class="material-icons-outlined">format_align_left</span>
</button>
<button v-tooltip title="Wyrównanie do środka" @click="align = 'center'" class="btn btn-icon-sm "
:class="align == 'center' ? 'btn-primary' : 'btn-outline-primary'">
<span class="material-icons-outlined">format_align_center</span>
</button>
<button v-tooltip title="Wyrównanie do prawej" @click="align = 'right'" class="btn btn-icon-sm "
:class="align == 'right' ? 'btn-primary' : 'btn-outline-primary'">
<span class="material-icons-outlined">format_align_right</span>
</button>
<button v-tooltip title="Justowanie" @click="align = 'justify'" class="btn btn-icon-sm "
:class="align == 'justify' ? 'btn-primary' : 'btn-outline-primary'">
<span class="material-icons-outlined">format_align_justify</span>
</button>
</div>
</div>
<div class="text-center"><button class="btn btn-outline-secondary me-1" @click.prevent="onCloseModal">{{
langs.saveclose
}}</button></div>
</b-modal>
</div> </div>
<div class="col-sm-12 col-md-6 p-0 text-end">
<a href="#" @click.prevent="modalBox = !modalBox" title="Edytuj" class="text-primary me-2"
><i class="material-icons-outlined">create</i></a
>
<a href="#" title="Usuń" @click.prevent="removeItem()" class="text-danger"
><i class="material-icons-outlined">delete</i></a
>
</div>
<div class="ms-2">
<strong class="font-weight-bold">{{ t('pagebuilder.type') }}:</strong> {{ h_type }},
<strong class="font-weight-bold">{{ t('pagebuilder.content') }}:</strong> {{ text ? text : ' ' }}
</div>
<b-modal v-model="modalBox" :title="t('pagebuilder.widget_text')" @close="onCloseModal">
<div class="form-group">
<label class="w-100 col-form-label">{{ t('pagebuilder.content') }}</label>
<input class="form-control" type="text" v-model="text" />
</div>
<div class="form-grou mb-2">
<label class="w-100 col-form-label">{{ t('pagebuilder.type') }}</label>
<select class="form-select" v-model="h_type">
<option value="">{{ langs.typeplaintext }}</option>
<option value="h1">{{ langs.typeheader }} 1</option>
<option value="h2">{{ langs.typeheader }} 2</option>
<option value="h3">{{ langs.typeheader }} 3</option>
<option value="h4">{{ langs.typeheader }} 4</option>
<option value="h5">{{ langs.typeheader }} 5</option>
<option value="h6">{{ langs.typeheader }} 6</option>
</select>
</div>
<div class="form-group">
<label class="w-100 col-form-label">{{ t('pagebuilder.align') }}</label>
<div class="">
<button
vx-tooltip
title="Wyrównanie do lewej"
@click="align = 'left'"
class="btn btn-icon-sm"
:class="align == 'left' ? 'btn-primary' : 'btn-outline-primary'"
>
<span class="material-icons-outlined">format_align_left</span>
</button>
<button
vx-tooltip
title="Wyrównanie do środka"
@click="align = 'center'"
class="btn btn-icon-sm"
:class="align == 'center' ? 'btn-primary' : 'btn-outline-primary'"
>
<span class="material-icons-outlined">format_align_center</span>
</button>
<button
vx-tooltip
title="Wyrównanie do prawej"
@click="align = 'right'"
class="btn btn-icon-sm"
:class="align == 'right' ? 'btn-primary' : 'btn-outline-primary'"
>
<span class="material-icons-outlined">format_align_right</span>
</button>
<button
vx-tooltip
title="Justowanie"
@click="align = 'justify'"
class="btn btn-icon-sm"
:class="align == 'justify' ? 'btn-primary' : 'btn-outline-primary'"
>
<span class="material-icons-outlined">format_align_justify</span>
</button>
</div>
</div>
<div class="text-center">
<button class="btn btn-outline-secondary me-1" @click.prevent="onCloseModal">
{{ langs.saveclose }}
</button>
</div>
</b-modal>
</div>
</template> </template>
<script> <script>
import { useI18n } from 'vue-i18n'
import MagicoModal from './../MagicoModal.vue' import MagicoModal from './../MagicoModal.vue'
export default { export default {
components: { components: {
'b-modal': MagicoModal, 'b-modal': MagicoModal
}, },
props: { props: {
value: Object modelValue: Object
}, },
data: function () { setup() {
return { const { t } = useI18n()
langs: { return { t }
label: "Tekst", },
close: "Zaknij", emits: ['update:modelValue'],
content: "Treść", data: function () {
type: "Typ", return {
typeplaintext: "Tekst", langs: {
typeheader: "Nagłowek", label: 'Tekst',
saveclose: "Zapisz" close: 'Zaknij',
}, content: 'Treść',
modalBox: false, type: 'Typ',
text: '', typeplaintext: 'Tekst',
name: '', typeheader: 'Nagłowek',
h_type: '', saveclose: 'Zapisz'
align: 'left', },
} modalBox: false,
}, text: '',
mounted: function () { name: '',
this.name = (this.value && this.value.name) ? this.value.name : this.name; h_type: '',
this.text = (this.value && this.value.text) ? this.value.text : this.text; align: 'left'
this.h_type = (this.value && this.value.h_type) ? this.value.h_type : this.h_type;
this.align = (this.value && this.value.align) ? this.value.align : this.align;
if (this.value.open) this.modalBox = true;
console.log('mounted text');
this.$emit('input', this.value);
},
methods: {
removeItem: function () {
this.$emit('itemRemoved', this.value);
},
onCloseModal: function () {
this.modalBox = false;
this.$emit('input', {
name: this.name,
text: this.text,
h_type: this.h_type,
align: this.align,
})
}
},
destroy() {
this.modalBox = false;
} }
},
mounted: function () {
this.name = this.modelValue && this.modelValue.name ? this.modelValue.name : this.name
this.text = this.modelValue && this.modelValue.text ? this.modelValue.text : this.text
this.h_type = this.modelValue && this.modelValue.h_type ? this.modelValue.h_type : this.h_type
this.align = this.modelValue && this.modelValue.align ? this.modelValue.align : this.align
if (this.modelValue.open) this.modalBox = true
console.log('mounted text')
this.$emit('update:modelValue', this.modelValue)
},
methods: {
removeItem: function () {
this.$emit('itemRemoved', this.modelValue)
},
onCloseModal: function () {
this.modalBox = false
this.$emit('update:modelValue', {
name: this.name,
text: this.text,
h_type: this.h_type,
align: this.align
})
}
},
destroy() {
this.modalBox = false
}
} }
</script> </script>

View File

@@ -1,106 +1,155 @@
<template> <template>
<div class="row m-0 p-0 align-items-center"> <div class="row m-0 p-0 align-items-center">
<div class="col-sm-12 col-md-6 p-0"> <div class="col-sm-12 col-md-6 p-0">
<span class="material-icons-outlined box-move me-2" style="cursor:move;">open_with</span><span <span class="material-icons-outlined box-move me-2" style="cursor: move">open_with</span
class="font-weight-bold text-primary">{{ langs.label }}</span> ><span class="font-weight-bold text-primary">{{ t('pagebuilder.widget_textarea') }}</span>
</div>
<div class="col-sm-12 col-md-6 p-0 text-end">
<a href="#" @click.prevent="modalBox = !modalBox" title="Edytuj" class="text-primary me-2"><i
class="material-icons-outlined">create</i></a>
<b-modal no-enforce-focus class_other="modal-xl" v-model="modalBox" :title="langs.label"
v-on:hide="onCloseModal">
<div class="mb-4">
<div class="form-group">
<editor api-key="no-api-key" rows="12" class="form-control" v-model="text" :init="vtinymce" />
</div>
</div>
<div class="d-flex"><button class="btn btn-outline-secondary m-auto" @click.prevent="onCloseModal">{{
langs.saveclose
}}</button></div>
</b-modal>
<a href="#" title="Usuń" @click.prevent="removeItem()" class="text-danger"><i
class="material-icons-outlined">delete</i></a>
</div>
<div class="ms-4" style="color: #a9a9a9" v-html="ctext"></div>
</div> </div>
<div class="col-sm-12 col-md-6 p-0 text-end">
<a href="#" @click.prevent="openModal" title="Edytuj" class="text-primary me-2"
><i class="material-icons-outlined">create</i></a
>
<b-modal
no-enforce-focus
class_other="modal-xl"
v-model="modalBox"
:title="t('pagebuilder.widget_textarea')"
v-on:hide="onCloseModal"
>
<div style="min-height: 400px">
<div class="mb-4" v-if="delayModal">
<div class="form-group">
<editor
api-key="no-api-key"
rows="12"
class="form-control"
v-model="text"
:init="{ ...vtinymce, language: locale }"
/>
</div>
</div>
</div>
<div class="d-flex">
<button class="btn btn-outline-secondary m-auto" @click.prevent="onCloseModal">
{{ t('pagebuilder.save') }}
</button>
</div>
</b-modal>
<a href="#" title="Usuń" @click.prevent="removeItem()" class="text-danger"
><i class="material-icons-outlined">delete</i></a
>
</div>
<div class="ms-4" style="color: #a9a9a9" v-html="ctext"></div>
</div>
</template> </template>
<script> <script>
import MagicoModal from './../MagicoModal.vue' import MagicoModal from './../MagicoModal.vue'
import tinymceConfig from '../tinymce/config.js' import tinymceConfig from '../tinymce/config.js'
import Editor from '@tinymce/tinymce-vue' import Editor from '@tinymce/tinymce-vue'
import { nextTick } from 'vue'
import { useI18n } from 'vue-i18n'
export default { export default {
components: { emits: ['update:modelValue'],
'b-modal': MagicoModal, components: {
'b-modal': MagicoModal,
'editor': Editor // <- To jest TINYMCE editor: Editor // <- To jest TINYMCE
}, },
props: { props: {
value: Object modelValue: Object
}, },
mounted: function () { setup() {
this.name = (this.value && this.value.name) ? this.value.name : this.name; const { t, locale } = useI18n()
this.text = (this.value && this.value.text) ? this.value.text : this.text; return { t, locale }
if (this.value.open) this.modalBox = true; },
console.log('mounted textarea'); mounted: function () {
this.$emit('input', this.value); let vm = this
this.name = this.modelValue && this.modelValue.name ? this.modelValue.name : this.name
}, this.text = this.modelValue && this.modelValue.text ? this.modelValue.text : this.text
data: function () { if (this.modelValue.open) {
return { this.modalBox = true
langs: { setTimeout(function () {
saveclose: "Zapisz", vm.delayModal = true
label: "Pole tekstowe", }, 200)
close: "Zamknij" }
}, console.log('mounted textarea')
height: window.innerHeight - window.innerHeight / 4, this.$emit('update:modelValue', this.modelValue)
modalBox: false, },
text: '', data: function () {
name: 'core_section_textarea', return {
vtinymce: Object.assign(tinymceConfig, { langs: {
file_picker_callback: (callback) => { saveclose: 'Zapisz',
if (this.$filechooser) { label: 'Pole tekstowe',
this.$filechooser.open({ close: 'Zamknij'
chooseCallback: function (ev) { },
console.log('filePathChosed', ev) height: window.innerHeight - window.innerHeight / 4,
callback(ev.publicUrl); modalBox: false,
} delayModal: false,
}) editor: null,
} text: '',
} name: 'core_section_textarea',
}), vtinymce: Object.assign(tinymceConfig, {
}
}, file_picker_callback: (callback) => {
watch: { if (this.$filechooser) {
modalBox: function () { this.$filechooser.open({
if (this.modalBox) { chooseCallback: function (ev) {
document.addEventListener('focusin', (e) => { console.log('filePathChosed', ev)
if (e.target.closest(".tox-tinymce-aux, .moxman-window, .tam-assetmanager-root") !== null) { callback(ev.publicUrl)
e.stopImmediatePropagation(); }
}
});
}
console.log('focus');
},
},
computed: {
ctext: function () {
return this.value.text ? this.value.text.replace(/<(?:.|\n)*?>/gm, '') : '';
}
},
methods: {
removeItem: function () {
this.$emit('itemRemoved', this.value);
},
onCloseModal: function () {
this.modalBox = false;
this.$emit('input', {
name: this.name,
text: this.text,
}) })
}
} }
})
}
},
watch: {
modalBox: function () {
if (this.modalBox) {
document.addEventListener('focusin', (e) => {
if (
e.target.closest('.tox-tinymce-aux, .moxman-window, .tam-assetmanager-root') !== null
) {
e.stopImmediatePropagation()
}
})
}
console.log('focus')
}
},
computed: {
ctext: function () {
return this.modelValue.text ? this.modelValue.text.replace(/<(?:.|\n)*?>/gm, '') : ''
}
},
methods: {
openModal: function () {
let vm = this
this.modalBox = true
setTimeout(function () {
vm.delayModal = true
}, 200)
// nextTick(() => {
// vm.delayModal = true
// })
}, },
removeItem: function () {
this.$emit('itemRemoved', this.modelValue)
},
onCloseModal: function () {
setTimeout(
function () {
this.modalBox = false
this.delayModal = false
this.$emit('update:modelValue', {
name: this.name,
text: this.text
})
}.bind(this),
200
)
}
}
} }
</script> </script>

View File

@@ -0,0 +1,211 @@
<template>
<div class="row m-0 p-0 align-items-center">
<div class="col-sm-12 col-md-6 p-0">
<span class="material-icons-outlined box-move me-2 my-1" style="cursor: move">open_with</span>
<span class="font-weight-bold text-primary">{{
t('pagebuilder.core_section_video')
}}</span>
</div>
<div class="col-sm-12 col-md-6 p-0 text-end">
<a href="#" @click.prevent="toggleModal" title="Edytuj" class="text-primary me-2 my-1">
<i class="material-icons-outlined">create</i>
</a>
<MagicoModal
v-model="modalBox"
v-on:close="onCloseModal"
size="xl"
:title="t('pagebuilder.core_section_video')"
>
<div>
<button
@click.prevent="changeView('youtube')"
:class="type == 'youtube' ? 'btn-secondary' : 'btn-outline-secondary'"
class="btn me-1 my-1"
>
Youtube
</button>
<button
@click.prevent="changeView('vimeo')"
:class="type == 'vimeo' ? 'btn-secondary' : 'btn-outline-secondary'"
class="btn me-1 my-1"
>
Vimeo
</button>
<button
@click.prevent="changeView('file')"
:class="type == 'file' ? 'btn-secondary' : 'btn-outline-secondary'"
class="btn me-1 my-1"
>
{{ t('pagebuilder.core_section_video_file') }}
</button>
<div v-if="type === 'youtube'">
<div class="form-group">
<label class="w-100 col-form-label">{{
t('pagebuilder.core_section_video_ytlink')
}}</label>
<input
@change="generateYouTubeEmbedCode"
type="text"
class="form-control"
v-model="link"
/>
</div>
<div class="form-group">
<label class="w-100 col-form-label">{{
t('pagebuilder.core_section_video_ytcode')
}}</label>
<textarea class="form-control" v-model="text"></textarea>
</div>
</div>
<div v-if="type === 'vimeo'">
<div class="form-group">
<label class="w-100 col-form-label">{{
t('pagebuilder.core_section_video_vimeocode')
}}</label>
<textarea class="form-control" v-model="text"></textarea>
</div>
</div>
<div v-if="type === 'file'">
<!-- <div>
<button
class="btn btn-outline-secondary me-1 my-1"
v-for="item in items"
:key="item"
@click.prevent="setText(item)"
@dblclick="deleteItem(item)"
>
{{ item }}
</button>
</div> -->
<div>
<div class="form-group">
<label class="w-100 col-form-label">{{
t('pagebuilder.core_section_video_title')
}}</label>
<input class="form-control" type="text" v-model="text" />
</div>
</div>
</div>
</div>
<div class="text-end mt-4">
<button class="btn btn-outline-secondary me-1 my-1" @click.prevent="onCloseModal">
{{ t('pagebuilder.save') }}
</button>
</div>
</MagicoModal>
<a href="#" title="Usuń" @click.prevent="removeItem" class="text-danger">
<i class="material-icons-outlined">delete</i>
</a>
</div>
<div>
<strong class="font-weight-bold">{{ t('pagebuilder.core_section_video_title') }}:</strong>
{{ text || ' ' }}<br />
<strong class="font-weight-bold">{{ t('pagebuilder.core_section_video_type') }}:</strong>
{{ type }}
</div>
</div>
</template>
<script>
import { ref, watch } from 'vue'
import axios from 'axios'
import MagicoModal from '../MagicoModal.vue'
import { useI18n } from 'vue-i18n'
export default {
name: 'CoreSectionVideo',
components: {
MagicoModal
},
props: {
modelValue: {
type: Object,
default: () => ({})
}
},
setup(props, { emit }) {
const { t } = useI18n()
const modalBox = ref(false)
const items = ref([])
const type = ref('file')
const text = ref('')
const link = ref('')
const name = ref('')
watch(
() => props.modelValue,
(newValue) => {
name.value = newValue?.name || ''
text.value = newValue?.text || ''
type.value = newValue?.type || 'file'
if (newValue?.open) modalBox.value = true
},
{ immediate: true }
)
const toggleModal = () => {
modalBox.value = !modalBox.value
getItems()
}
const onCloseModal = () => {
modalBox.value = false
emit('update:modelValue', { name: name.value, text: text.value, type: type.value })
}
const changeView = (viewType) => {
type.value = viewType
}
const setText = (item) => {
type.value = 'file'
}
const deleteItem = (item) => {
}
const generateYouTubeEmbedCode = () => {
const urlParams = new URLSearchParams(new URL(link.value).search)
const videoId = urlParams.get('v')
text.value = videoId
? `<iframe width="560" height="315" src="https://www.youtube.com/embed/${videoId}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`
: t('Nieprawidłowy link do YouTube.')
}
const getItems = () => {
}
const finishUpload = (e) => {
}
const removeItem = () => {
emit('itemRemoved', props.value)
}
return {
t,
modalBox,
items,
type,
text,
link,
name,
toggleModal,
onCloseModal,
changeView,
setText,
deleteItem,
generateYouTubeEmbedCode,
getItems,
finishUpload,
removeItem
}
}
}
</script>

View File

@@ -0,0 +1,20 @@
import PagebuilderSectionPlugin from 'magico-section/src/components/PagebuilderSectionPlugin.vue'
export function useSections() {
function register(vm, sections) {
console.log('sections', sections, vm)
sections.forEach((item) => {
vm.registerPlugin(
'Sections' + item.site_section_id,
{
label: item.title,
svg_off: ``,
section_id: item.section_id,
image: item.image
},
PagebuilderSectionPlugin
)
})
}
return { register }
}

View File

@@ -0,0 +1,54 @@
export function addAI(editor) {
editor.ui.registry.addButton('ai_button', {
text: 'Wygeneruj treść AI',
onAction: async function () {
open({
callback: (data) => {
editor.setContent(data.content || '<p>Brak treści</p>')
}
})
// const count = 1000
// const lang = 'pl'
// const prompt = `Twoim zadaniem jest stworzenie nowego wpisu na stronę www na podstawie dostarczonej treści strony.
// Do "content" wstaw tekst w formacie HTML, jako akapity dla edytora WYSIWYG na podstawie dostarczonej treści na maksymalnie ${count} znaków.
// Metatagi wygeneruj na podstawie wygenerowanej przez ciebie treści.
// Odpowiedź wygeneruj w języku określanym przez kod kraju: "${lang}".
// Wynik zwróć jako czysty JSON bez dodatkowego formatowania, bez używania \`\`\`json i \`\`\`, bez używania \`\`\`html i \`\`\`:
// {
// "title": "",
// "page_title": "",
// "meta_description": "",
// "meta_keywords": "",
// "og_title": "",
// "og_description": "",
// "content": ""
// }`
// // Tu możesz wysłać zapytanie do swojego endpointa lub OpenAI
// const response = await fetch('/api/generate', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify({ prompt })
// })
// const data = await response.json()
// editor.setContent(data.content || '<p>Brak treści</p>')
}
})
}
import { createApp, h } from 'vue'
import AIModal from '../AIModal.vue'
export function open(props = {}) {
const app = createApp({
render: () => h(AIModal, props)
})
const mountNode = document.createElement('div')
document.body.appendChild(mountNode)
app.mount(mountNode)
return app
}

View File

@@ -1,118 +1,168 @@
import { addAI } from './ai'
export default { export default {
autoresize_max_height: window.innerHeight - window.innerHeight / 4, autoresize_max_height: window.innerHeight - window.innerHeight / 4,
width: '100%', width: '100%',
selector: "textarea.wysiwyg", selector: 'textarea.wysiwyg',
language: "pl", language: 'pl',
language_url: 'https://cdn.magico.pl/tinymce/langs/pl.js', language_url: 'https://cdn.magico.pl/tinymce/langs/pl.js',
forced_root_block: "p", forced_root_block: 'p',
entity_encoding: 'named', entity_encoding: 'named',
entities: '160,nbsp,38,amp,60,lt,62,gt', entities: '160,nbsp,38,amp,60,lt,62,gt',
valid_elements: '*[*]', valid_elements: '*[*]',
document_base_url: window.location, document_base_url: window.location,
relative_urls: false, relative_urls: false,
browser_spellcheck: true, browser_spellcheck: true,
autoresize_bottom_margin: 10, autoresize_bottom_margin: 10,
autoresize_min_height: 90, autoresize_min_height: 90,
image_caption: true, image_caption: true,
image_description: true, image_description: true,
image_title: true, image_title: true,
promotion: false, promotion: false,
visualblocks_default_state: true, visualblocks_default_state: true,
visualchars_default_state: false, visualchars_default_state: false,
formats: { setup(editor) {
mainparagraph: { addAI(editor)
inline: 'span', },
styles: { formats: {
fontSize: '18px' mainparagraph: {
}, inline: 'span',
classes: 'main_paragraph' styles: {
}, fontSize: '18px'
firstlink: { },
inline: 'span', classes: 'main_paragraph'
styles: {
fontSize: '16px'
},
classes: 'default_button_span black'
},
secondlink: {
inline: 'span',
styles: {
fontSize: '16px'
},
classes: 'default_button_span'
}
}, },
style_formats: [{ firstlink: {
title: 'Headers', inline: 'span',
items: [{ styles: {
title: 'h1', fontSize: '16px'
block: 'h1' },
}, { classes: 'default_button_span black'
title: 'h2', },
block: 'h2' secondlink: {
}, { inline: 'span',
title: 'h3', styles: {
block: 'h3' fontSize: '16px'
}, { },
title: 'h4', classes: 'default_button_span'
block: 'h4' }
}, { },
title: 'h5', style_formats: [
block: 'h5' {
}, { title: 'Headers',
title: 'h6', items: [
block: 'h6' {
}] title: 'h1',
}, { block: 'h1'
title: 'Blocks', },
items: [{ {
title: 'Główny akapit', title: 'h2',
format: 'mainparagraph' block: 'h2'
}, { },
title: 'LinkURL - 1', {
format: 'firstlink' title: 'h3',
}, { block: 'h3'
title: 'LinkURL - 2', },
format: 'secondlink' {
}, { title: 'h4',
title: 'p', block: 'h4'
block: 'p' },
}, { {
title: 'div', title: 'h5',
block: 'div' block: 'h5'
}, { },
title: 'pre', {
block: 'pre' title: 'h6',
}] block: 'h6'
}, { }
title: 'Containers', ]
items: [{ },
title: 'section', {
block: 'section', title: 'Blocks',
wrapper: true, items: [
merge_siblings: false {
title: 'Główny akapit',
format: 'mainparagraph'
},
{
title: 'LinkURL - 1',
format: 'firstlink'
},
{
title: 'LinkURL - 2',
format: 'secondlink'
},
{
title: 'p',
block: 'p'
},
{
title: 'div',
block: 'div'
},
{
title: 'pre',
block: 'pre'
}
]
},
{
title: 'Containers',
items: [
{
title: 'section',
block: 'section',
wrapper: true,
merge_siblings: false
}, },
//{ title: 'article', block: 'article', wrapper: true, merge_siblings: false }, //{ title: 'article', block: 'article', wrapper: true, merge_siblings: false },
{ {
title: 'blockquote', title: 'blockquote',
block: 'blockquote', block: 'blockquote',
wrapper: true wrapper: true
}, }
//{ title: 'hgroup', block: 'hgroup', wrapper: true }, //{ title: 'hgroup', block: 'hgroup', wrapper: true },
//{ title: 'aside', block: 'aside', wrapper: true }, //{ title: 'aside', block: 'aside', wrapper: true },
//{ title: 'figure', block: 'figure', wrapper: true } //{ title: 'figure', block: 'figure', wrapper: true }
] ]
}], }
paste_word_valid_elements: "table,tr,td,th,b,strong,i,em,h1,h2, strong", ],
valid_styles: { paste_word_valid_elements: 'table,tr,td,th,b,link,strong,i,em,h1,h2, strong',
'*': 'display, margin, float, margin-left, margin-right, margin-top, margin-bottom, padding-left, padding-right, padding-top, padding-bottom, text-decoration, border,font-size,color,background,background-color,line-height,text-align,list-style-type, border-radius', valid_styles: {
'*': 'display, margin, float, margin-left, margin-right, margin-top, margin-bottom, padding-left, padding-right, padding-top, padding-bottom, text-decoration, border,font-size,color,background,background-color,line-height,text-align,list-style-type, border-radius'
},
plugins: ['autoresize', 'link', 'image', 'media', 'lists', 'nonbreaking'],
removed_menuitems: 'newdocument',
toolbarxx:
'undo redo | bold italic | bullist numlist outdent indent | alignleft aligncenter alignright alignjustify | link image forecolor backcolor | ai_button',
toolbar1:
'undo redo | styles | bold italic | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | link image | media | forecolor backcolor ai_button',
toolbar2: '',
menubar: true,
menu: {
edit: {
title: 'Edit',
items: 'undo redo | cut copy paste pastetext | selectall | searchreplace'
}, },
plugins: ['autoresize'], view: {
removed_menuitems: 'newdocument', title: 'View',
toolbarxx: "undo redo | bold italic | bullist numlist outdent indent | alignleft aligncenter alignright alignjustify | link image forecolor backcolor", items:
toolbar1: 'undo redo | styles | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | media | forecolor backcolor', ' visualaid visualchars visualblocks'
toolbar2: '', },
menubar: true, insert: {
title: 'Insert',
items:
} 'image link media | hr nonbreaking'
},
format: {
title: 'Format',
items:
'bold italic underline strikethrough superscript subscript codeformat | forecolor backcolor | language | removeformat'
},
table: {
title: 'Table',
items: 'inserttable | cell row column | advtablesort | tableprops deletetable'
},
help: { title: 'Help', items: 'help' }
}
}

26
src/locale/en.js Normal file
View File

@@ -0,0 +1,26 @@
export default {
widget_textarea: 'Text area',
close: 'Close',
save: 'Save',
align: 'Alignment',
type: 'Type',
content: 'Content',
widget_text: 'Content',
add_section: 'Add section',
template: 'Templates',
import_template: 'Load template',
save_template: 'Save template',
copy_template: 'Save to clipboard',
paste_template: 'Paste from clipboard',
section_type: 'Section type',
container: 'Container',
full_width: '100% width',
section_settings: 'Section settings',
core_section_video: 'Video',
core_section_video_title: 'Video URL',
core_section_video_file: 'File',
core_section_video_ytlink: 'Youtube address of the video',
core_section_video_ytcode: 'Youtube IFRAME Code',
core_section_video_vimeocode: 'Vimeo IFRAME code',
core_section_video_type: 'Video type'
}

16
src/locale/i18n.js Normal file
View File

@@ -0,0 +1,16 @@
import { createI18n } from 'vue-i18n'
import pl from './pl'
import en from './en'
const messages = {
pl: { pagebuilder: pl },
en: { pagebuilder: en }
}
const i18n = createI18n({
locale: 'en', // Domyślny język
fallbackLocale: 'pl', // Język używany, gdy brakuje tłumaczenia w wybranym języku
messages,
legacy: false
})
export default i18n

26
src/locale/pl.js Normal file
View File

@@ -0,0 +1,26 @@
export default {
widget_textarea: 'Pole tekstowe',
close: 'Zamknij',
save: 'Zapisz',
align: 'Wyrównanie',
type: 'Typ',
content: 'Treść',
widget_text: 'Treść',
add_section: 'Dodaj sekcję',
template: 'Szablony',
import_template: 'Wczytaj szablon',
save_template: 'Zapisz szablon',
copy_template: 'Zapisz do schowka',
paste_template: 'Wklej ze schowka',
section_type: 'Typ sekcji',
container: 'Kontener',
full_width: '100% szerokości',
section_settings: 'Ustawienia sekcji',
core_section_video: 'Wideo',
core_section_video_title: 'Adres URL filmu',
core_section_video_file: 'Plik',
core_section_video_ytlink: 'Adres Youtube filmu',
core_section_video_ytcode: 'Kod IFRAME Youtube',
core_section_video_vimeocode: 'Kod IFRAME Vimeo',
core_section_video_type: 'Typ filmu'
}

View File

@@ -1,9 +1,10 @@
import Vue from 'vue' import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import 'bootstrap/dist/css/bootstrap.min.css'; import axios from 'axios'
import 'bootstrap/dist/css/bootstrap.min.css'
import MagicoPagebuilder from './components/MagicoPagebuilderPlugin.js' import MagicoPagebuilder from './components/MagicoPagebuilderPlugin.js'
Vue.config.productionTip = false import i18n from './locale/i18n'
Vue.use(MagicoPagebuilder);
new Vue({ const app = createApp(App).use(i18n).use(MagicoPagebuilder).mount('#app')
render: h => h(App),
}).$mount('#app')

16
vite.config.js Normal file
View File

@@ -0,0 +1,16 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})

1282
yarn.lock Normal file

File diff suppressed because it is too large Load Diff