Merge branch 'master' of github.com:bolt/core

This commit is contained in:
Bob den Otter
2020-09-11 06:36:36 +02:00
22 changed files with 398 additions and 186 deletions
+155 -48
View File
@@ -1,33 +1,75 @@
<template>
<div ref="collectionContainer" class="collection-container">
<div v-for="element in elements" :key="element.id" class="collection-item">
<div :is="element"></div>
<div class="expand-buttons">
<label>{{ labels.field_label }}:</label>
<div class="btn-group" role="group">
<button class="btn btn-secondary btn-sm collection-expand-all">
<i class="fas fa-fw fa-expand-alt"></i>
{{ labels.expand_all }}
</button>
<button class="btn btn-secondary btn-sm collection-collapse-all">
<i class="fas fa-fw fa-compress-alt"></i>
{{ labels.collapse_all }}
</button>
</div>
</div>
<div class="d-flex">
<editor-select
ref="templateSelect"
class="flex-grow-1 mr-2"
:value="initialSelectValue"
:name="templateSelectName"
:options="templateSelectOptions"
:allowempty="false"
></editor-select>
<div
v-for="element in existingFields"
:key="element.hash"
class="collection-item"
>
<details :open="state === 'expanded'">
<summary>
<!-- Initial title. This is replaced by dynamic title in JS below. -->
<div class="collection-item-title" :data-label="element.label">
<i :class="[element.icon, 'fas fa-fw']" />
{{ element.label }}
</div>
<!-- Navigation buttons -->
<div :is="compile(element.buttons)"></div>
</summary>
<!-- The actual field -->
<div :is="compile(element.content)"></div>
</details>
</div>
<small>{{ labels.select_tooltip }}</small>
<div class="dropdown">
<button
class="btn btn-secondary"
type="button"
id="dropdownMenuButton"
:disabled="!allowMore"
@click="addCollectionItem"
class="btn btn-secondary dropdown-toggle"
type="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
<i class="fas fa-fw fa-plus"></i>
{{ labels.add_collection_item }}
<i class="fas fa-fw fa-plus"></i> {{ labels.add_collection_item }}
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<a
v-for="template in templates"
:key="template.label"
class="dropdown-item"
:data-template="template.label"
@click="addCollectionItem($event)"
>
<i :class="[template.icon, 'fas fa-fw']" />
{{ template.label }}
</a>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue';
import $ from 'jquery';
var uniqid = require('locutus/php/misc/uniqid');
export default {
@@ -48,25 +90,17 @@ export default {
type: Number,
required: true,
},
state: {
type: String,
required: true,
},
},
data() {
let elements = [];
this.existingFields.forEach(function(field) {
elements.push(Vue.compile(field.html));
});
let templateSelectOptions = [];
this.templates.forEach(function(template) {
templateSelectOptions.push({
key: template.label,
value: template.label,
});
});
return {
elements: elements,
counter: elements.length,
elements: this.existingFields,
counter: this.existingFields.length,
templateSelectName: 'templateSelect' + this.id,
templateSelectOptions: templateSelectOptions,
selector: {
@@ -75,6 +109,9 @@ export default {
remove: '.action-remove-collection-item',
moveUp: '.action-move-up-collection-item',
moveDown: '.action-move-down-collection-item',
expandAll: '.collection-expand-all',
collapseAll: '.collection-collapse-all',
editor: '#editor',
},
};
},
@@ -87,11 +124,13 @@ export default {
},
},
mounted() {
this.setAllButtonsStates(window.$(this.$refs.collectionContainer));
let vueThis = this;
/*
** Event listeners on collection items buttons
** This is a jQuery event listener, because Vue cannot handle an event emitted by a non-vue element.
** The collection items are not Vue elements in order to initialise them correctly within their twig template.
/**
* Event listeners on collection items buttons
* This is a jQuery event listener, because Vue cannot handle an event emitted by a non-vue element.
* The collection items are not Vue elements in order to initialise them correctly within their twig template.
*/
window.$(document).on('click', vueThis.selector.remove, function(e) {
e.preventDefault();
@@ -126,11 +165,76 @@ export default {
vueThis.setButtonsState(thisCollectionItem);
vueThis.setButtonsState(nextCollectionItem);
});
window.$(document).on('click', vueThis.selector.expandAll, function(e) {
e.preventDefault();
const collection = $(e.target).closest(
vueThis.selector.collectionContainer,
);
collection.find('details').attr('open', '');
});
window.$(document).on('click', vueThis.selector.collapseAll, function(e) {
e.preventDefault();
const collection = $(e.target).closest(
vueThis.selector.collectionContainer,
);
collection.find('details').removeAttr('open');
});
/**
* Update the title dynamically.
*/
$(document).ready(function() {
$.each(window.$(vueThis.selector.item), function() {
updateTitle(this);
});
window
.$(vueThis.selector.editor)
.on('keyup change', vueThis.selector.item, function() {
updateTitle(this);
});
});
/**
* Pass a .collection-item element to update the title
* with the value of the first text-based field.
*/
function updateTitle(item) {
const label = $(item)
.find('.collection-item-title')
.first();
const icon = label
.find('i')
.first()
.get(0).outerHTML;
const input = $(item)
.find('textarea,input[type="text"]')
.first();
const title = $(input).val() ? $(input).val() : label.attr('data-label');
label.html(icon + title);
}
/**
* Open newly inserted collection items.
*/
$(document).on('DOMNodeInserted', function(e) {
if ($(e.target).hasClass('collection-item')) {
$(e.target)
.find('details')
.first()
.attr('open', '');
}
});
},
updated() {
this.setAllButtonsStates(window.$(this.$refs.collectionContainer));
},
methods: {
compile(element) {
return Vue.compile(element);
},
setAllButtonsStates(collectionContainer) {
let vueThis = this;
collectionContainer.children(vueThis.selector.item).each(function() {
@@ -180,26 +284,29 @@ export default {
.closest('.collection-item')
.last();
},
addCollectionItem() {
let template = this.getSelectedTemplate();
addCollectionItem(event) {
// duplicate template without reference
let template = $.extend(true, {}, this.getSelectedTemplate(event));
let html = template.html.replace(
const realhash = uniqid();
template.content = template.content.replace(
new RegExp(template.hash, 'g'),
uniqid(),
realhash,
);
let res = Vue.compile(html);
this.elements.push(res);
template.hash = realhash;
this.elements.push(template);
this.counter++;
},
getSelectedTemplate() {
let selectValue = this.$refs.templateSelect.selected;
if (Array.isArray(selectValue)) {
selectValue = selectValue[0];
}
getSelectedTemplate(event) {
const target = $(event.target).attr('data-template')
? $(event.target)
: $(event.target).closest('[data-template]');
let selectValue = target.attr('data-template');
return this.templates.find(
template => template.label === selectValue.key,
);
return this.templates.find(template => template.label === selectValue);
},
},
};
+13 -32
View File
@@ -8,10 +8,16 @@
<img
src="/assets/images/bolt_logo_dashboard.svg"
alt="⚙️ Bolt"
height="28"
height="26"
/>
</div>
<div class="toolbar-item toolbar-item__site">
<a href="/" target="_blank">
<i class="fas fa-sign-out-alt"></i>{{ labels['action.view_site'] }}
</a>
</div>
<form
:action="backendPrefix"
class="toolbar-item toolbar-item__filter input-group"
@@ -25,41 +31,16 @@
:value="filterValue"
/>
<div class="input-group-append">
<button class="btn btn-tertiary" type="submit">
<i class="fas fa-search"></i>{{ labels['listing.button_search'] }}
<button
class="btn btn-tertiary"
type="submit"
:title="labels['listing.button_search']"
>
<i class="fas fa-search" style="margin: 0;"></i>
</button>
</div>
</form>
<div class="toolbar-item toolbar-item__site">
<a href="/" target="_blank">
<i class="fas fa-sign-out-alt"></i>{{ labels['action.view_site'] }}
</a>
</div>
<div class="toolbar-item btn-group toolbar-item__new">
<button
class="btn new-item__dropdown-toggler dropdown-toggle"
type="button"
data-toggle="dropdown"
data-display="static"
aria-haspopup="true"
aria-expanded="false"
>
<i class="fas fa-magic"></i>{{ labels['action.create_new'] }}
</button>
<div class="new-item__dropdown dropdown-menu">
<ul>
<li v-for="(item, index) in createMenu" :key="index">
<a :href="item.link_new"
><i :class="`fa fa-fw ${item.icon}`"></i>
{{ item.singular_name }}</a
>
</li>
</ul>
</div>
</div>
<div class="toolbar-item btn-group toolbar-item__profile">
<button
class="btn user profile__dropdown-toggler dropdown-toggle"
+3 -11
View File
@@ -41,7 +41,6 @@
align-items: center;
justify-content: center;
font-size: 0.875rem;
padding: 0;
a {
font-size: 0.9375rem;
@@ -119,15 +118,7 @@
&__brand {
justify-content: left;
padding-left: 2rem;
@include media-breakpoint-up(lg) {
flex: 0 1 $admin-sidebar-width;
}
@include media-breakpoint-up(wd) {
flex: 0 1 $admin-sidebar-width-wide;
}
padding: 0 2rem;
svg,
img {
@@ -152,7 +143,7 @@
&__filter {
margin-left: auto;
max-width: 400px;
max-width: 200px;
margin-right: 1rem;
}
@@ -161,6 +152,7 @@
@include media-breakpoint-up(sm) {
display: block;
padding-top: 0.1rem;
}
a {
@@ -0,0 +1,47 @@
//** Fields | Collection
.collection-container {
.expand-buttons {
display: flex;
justify-content: space-between;
margin-bottom: 0.5rem;
.btn-group {
height: min-content;
}
}
.collection-item {
summary {
margin-bottom: 1rem;
&::-webkit-details-marker {
display: none;
}
&:focus {
outline: none;
}
&::before {
content: "";
vertical-align: 25%; // middle of line
margin-right: 0.5rem;
width: 15px;
display: inline-block;
}
}
details[open] summary::before {
content: "";
}
.collection-item-title {
display: inline-block;
max-width: 40%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
}
}
@@ -8,3 +8,4 @@
@import '_file';
@import '_pre_postfix';
@import '_multiselect';
@import '_collection';
+1 -1
View File
@@ -93,7 +93,7 @@
}
}
&.showTimeInput.hasTime {
&.hasTime {
.flatpickr-time {
height: $timeHeight;
border-top: 1px solid $calendarBorderColor;
+23 -23
View File
@@ -38,32 +38,32 @@
"sensiolabs/security-checker": "^6.0",
"siriusphp/upload": "^3.0.1",
"squirrelphp/twig-php-syntax": "^1.5",
"symfony/asset": "^4.4 | ^5.1",
"symfony/console": "^4.4 | ^5.1",
"symfony/debug-bundle": "^4.4 | ^5.1",
"symfony/dependency-injection": "^4.4 | ^5.1",
"symfony/dotenv": "^4.4 | ^5.1",
"symfony/expression-language": "^4.4 | ^5.1",
"symfony/asset": "^5.1",
"symfony/console": "^5.1",
"symfony/debug-bundle": "^5.1",
"symfony/dependency-injection": "^5.1",
"symfony/dotenv": "^5.1",
"symfony/expression-language": "^5.1",
"symfony/flex": "^1.9",
"symfony/form": "^4.4 | ^5.1",
"symfony/framework-bundle": "^4.4 | ^5.1",
"symfony/http-client": "^4.4 | ^5.1",
"symfony/mailer": "^4.4 | ^5.1",
"symfony/form": "^5.1",
"symfony/framework-bundle": "^5.1",
"symfony/http-client": "^5.1",
"symfony/mailer": "^5.1",
"symfony/maker-bundle": "^1.14",
"symfony/monolog-bridge": "^4.4 | ^5.1",
"symfony/monolog-bridge": "^5.1",
"symfony/monolog-bundle": "^3.5",
"symfony/polyfill-php72": "^1.13",
"symfony/security-bundle": "^4.4 | ^5.1",
"symfony/serializer": "^4.4 | ^5.1",
"symfony/stopwatch": "^4.4 | ^5.1",
"symfony/translation": "^4.4 | ^5.1",
"symfony/twig-bundle": "^4.4 | ^5.1",
"symfony/validator": "^4.4 | ^5.1",
"symfony/var-dumper": "^4.4 | ^5.1",
"symfony/web-profiler-bundle": "^4.4 | ^5.1",
"symfony/security-bundle": "^5.1",
"symfony/serializer": "^5.1",
"symfony/stopwatch": "^5.1",
"symfony/translation": "^5.1",
"symfony/twig-bundle": "^5.1",
"symfony/validator": "^5.1",
"symfony/var-dumper": "^5.1",
"symfony/web-profiler-bundle": "^5.1",
"symfony/web-server-bundle": "^4.4",
"symfony/webpack-encore-bundle": "^1.7",
"symfony/yaml": "^4.4 | ^5.1",
"symfony/yaml": "^5.1",
"tightenco/collect": "^7.25",
"twig/twig": "^3.0",
"ua-parser/uap-php": "^3.9",
@@ -102,8 +102,8 @@
"phpunit/phpunit": "^7.5",
"roave/security-advisories": "dev-master@dev",
"se/selenium-server-standalone": "^3.141",
"symfony/browser-kit": "^4.4 | ^5.1",
"symfony/css-selector": "^4.4 | ^5.1",
"symfony/browser-kit": "^5.1",
"symfony/css-selector": "^5.1",
"symplify/easy-coding-standard": "^8.2.3",
"vaimo/binary-chromedriver": "^5.0"
},
@@ -116,7 +116,7 @@
"extra": {
"symfony": {
"allow-contrib": true,
"require": "^4.4 | ^5.1"
"require": "^5.1"
},
"public-dir": "public"
},
+3
View File
@@ -174,6 +174,7 @@ showcases:
error: "The Title field is required, and must contain at least 2 characters"
placeholder: "Placeholder for the title"
group: Text
fixture_format: '{name}'
postfix: |
This is an example of a longer "postfix". Simple text is capped at a reasonable width
to enhance legibility. Necessitatibus dolor corrupti assumenda placeat quia occati
@@ -262,6 +263,7 @@ showcases:
collection:
type: collection
group: Collections
default_state: expanded
fields:
set:
type: set
@@ -270,6 +272,7 @@ showcases:
type: text
textarea:
type: textarea
icon: fa-anchor
relations:
entries:
multiple: false
+45 -33
View File
@@ -32,13 +32,13 @@
}
},
"@babel/core": {
"version": "7.11.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.5.tgz",
"integrity": "sha512-fsEANVOcZHzrsV6dMVWqpSeXClq3lNbYrfFGme6DE25FQWe7pyeYpXyx9guqUnpy466JLzZ8z4uwSr2iv60V5Q==",
"version": "7.11.6",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz",
"integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.10.4",
"@babel/generator": "^7.11.5",
"@babel/generator": "^7.11.6",
"@babel/helper-module-transforms": "^7.11.0",
"@babel/helpers": "^7.10.4",
"@babel/parser": "^7.11.5",
@@ -52,7 +52,7 @@
"lodash": "^4.17.19",
"resolve": "^1.3.2",
"semver": "^5.4.1",
"source-map": "^0.6.1"
"source-map": "^0.5.0"
},
"dependencies": {
"@babel/code-frame": {
@@ -65,14 +65,14 @@
}
},
"@babel/generator": {
"version": "7.11.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.5.tgz",
"integrity": "sha512-9UqHWJ4IwRTy4l0o8gq2ef8ws8UPzvtMkVKjTLAiRmza9p9V6Z+OfuNd9fB1j5Q67F+dVJtPC2sZXI8NM9br4g==",
"version": "7.11.6",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz",
"integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==",
"dev": true,
"requires": {
"@babel/types": "^7.11.5",
"jsesc": "^2.5.1",
"source-map": "^0.6.1"
"source-map": "^0.5.0"
}
},
"@babel/helper-function-name": {
@@ -174,6 +174,12 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
}
}
},
@@ -1097,14 +1103,14 @@
}
},
"@babel/generator": {
"version": "7.11.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.5.tgz",
"integrity": "sha512-9UqHWJ4IwRTy4l0o8gq2ef8ws8UPzvtMkVKjTLAiRmza9p9V6Z+OfuNd9fB1j5Q67F+dVJtPC2sZXI8NM9br4g==",
"version": "7.11.6",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz",
"integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==",
"dev": true,
"requires": {
"@babel/types": "^7.11.5",
"jsesc": "^2.5.1",
"source-map": "^0.6.1"
"source-map": "^0.5.0"
}
},
"@babel/helper-function-name": {
@@ -1191,6 +1197,12 @@
"lodash": "^4.17.19",
"to-fast-properties": "^2.0.0"
}
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
}
}
},
@@ -6257,12 +6269,12 @@
}
},
"browserslist": {
"version": "4.14.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.0.tgz",
"integrity": "sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==",
"version": "4.14.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.1.tgz",
"integrity": "sha512-zyBTIHydW37pnb63c7fHFXUG6EcqWOqoMdDx6cdyaDFriZ20EoVxcE95S54N+heRqY8m8IUgB5zYta/gCwSaaA==",
"requires": {
"caniuse-lite": "^1.0.30001111",
"electron-to-chromium": "^1.3.523",
"caniuse-lite": "^1.0.30001124",
"electron-to-chromium": "^1.3.562",
"escalade": "^3.0.2",
"node-releases": "^1.1.60"
}
@@ -6470,9 +6482,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30001122",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001122.tgz",
"integrity": "sha512-pxjw28CThdrqfz06nJkpAc5SXM404TXB/h5f4UJX+rrXJKE/1bu/KAILc2AY+O6cQIFtRjV9qOR2vaEp9LDGUA=="
"version": "1.0.30001124",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001124.tgz",
"integrity": "sha512-zQW8V3CdND7GHRH6rxm6s59Ww4g/qGWTheoboW9nfeMg7sUoopIfKCcNZUjwYRCOrvereh3kwDpZj4VLQ7zGtA=="
},
"capture-exit": {
"version": "2.0.0",
@@ -8249,9 +8261,9 @@
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA=="
},
"electron-to-chromium": {
"version": "1.3.533",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.533.tgz",
"integrity": "sha512-YqAL+NXOzjBnpY+dcOKDlZybJDCOzgsq4koW3fvyty/ldTmsb4QazZpOWmVvZ2m0t5jbBf7L0lIGU3BUipwG+A=="
"version": "1.3.564",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.564.tgz",
"integrity": "sha512-fNaYN3EtKQWLQsrKXui8mzcryJXuA0LbCLoizeX6oayG2emBaS5MauKjCPAvc29NEY4FpLHIUWiP+Y0Bfrs5dg=="
},
"elliptic": {
"version": "6.5.3",
@@ -11219,7 +11231,7 @@
},
"is-obj": {
"version": "1.0.1",
"resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
},
"is-path-cwd": {
@@ -13371,9 +13383,9 @@
}
},
"locutus": {
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/locutus/-/locutus-2.0.11.tgz",
"integrity": "sha512-C0q1L38lK5q1t+wE0KY21/9szrBHxye6o2z5EJzU+5B79tubNOC+nLAEzTTn1vPUGoUuehKh8kYKqiVUTWRyaQ==",
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/locutus/-/locutus-2.0.12.tgz",
"integrity": "sha512-wnzhY9xOdDb2djr17kQhTh9oZgEfp78zI27KRRiiV1GnPXWA2xfVODbpH3QgpIuUMLupM02+6X/rJXvktTpnoA==",
"requires": {
"es6-promise": "^4.2.5"
}
@@ -13662,7 +13674,7 @@
},
"load-json-file": {
"version": "1.1.0",
"resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
"dev": true,
"requires": {
@@ -14158,7 +14170,7 @@
},
"semver": {
"version": "5.3.0",
"resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
"dev": true
}
@@ -16956,7 +16968,7 @@
},
"safe-regex": {
"version": "1.1.0",
"resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
"requires": {
"ret": "~0.1.10"
@@ -18034,7 +18046,7 @@
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"requires": {
"ansi-regex": "^2.0.0"
@@ -18058,7 +18070,7 @@
},
"strip-eof": {
"version": "1.0.0",
"resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
},
"strip-final-newline": {
+4 -4
View File
@@ -32,14 +32,14 @@
"baguettebox.js": "^1.11.1",
"bootbox": "^5.4.0",
"bootstrap": "^4.5.2",
"browserslist": "^4.14.0",
"caniuse-lite": "^1.0.30001122",
"browserslist": "^4.14.1",
"caniuse-lite": "^1.0.30001124",
"codemirror": "^5.57.0",
"dropzone": "^5.7.2",
"flagpack": "^1.0.5",
"hotkeys-js": "^3.8.1",
"jquery": "^3.5.1",
"locutus": "^2.0.11",
"locutus": "^2.0.12",
"luxon": "^1.25.0",
"no-scroll": "^2.1.1",
"node-vibrant": "^3.1.5",
@@ -61,7 +61,7 @@
"zxcvbn": "^4.4.2"
},
"devDependencies": {
"@babel/core": "^7.11.5",
"@babel/core": "^7.11.6",
"@babel/plugin-transform-regenerator": "^7.10.4",
"@babel/plugin-transform-runtime": "^7.11.5",
"@babel/polyfill": "^7.11.5",
+1
View File
@@ -51,6 +51,7 @@ class FieldType extends Collection
'default_locale' => 'en',
// 10 rows by default
'height' => '10',
'icon' => '',
]);
}
+29 -4
View File
@@ -213,6 +213,35 @@ class ContentFixtures extends BaseFixture implements DependentFixtureInterface,
}
private function getValuesforFieldType(string $name, DeepCollection $field, bool $singleton): array
{
$data = isset($field['fixture_format']) ? $this->getFixtureFormatValues($field['fixture_format']) : $this->getFieldTypeValue($field, $singleton);
if ($name === 'title' || $name === 'heading') {
$this->lastTitle = $data;
}
return $data;
}
private function getFixtureFormatValues(string $format): array
{
return [preg_replace_callback(
'/{([\w]+)}/i',
function ($match) {
$match = $match[1];
try {
return $this->faker->{$match};
} catch (\Throwable $e) {
}
return '(unknown)';
},
$format
)];
}
private function getFieldTypeValue(DeepCollection $field, bool $singleton)
{
$nb = $singleton ? 8 : 4;
@@ -317,10 +346,6 @@ class ContentFixtures extends BaseFixture implements DependentFixtureInterface,
$data = [$this->faker->sentence(6, true)];
}
if ($name === 'title' || $name === 'heading') {
$this->lastTitle = $data;
}
return $data;
}
+2 -2
View File
@@ -103,7 +103,7 @@ class HtmlExtension extends AbstractExtension
return Html::makeAbsoluteLink($link);
}
public function placeholders(string $string, array $replacements = []): string
public function placeholders(?string $string = null, array $replacements = []): string
{
$baseReplacements = [
'year' => date('Y'),
@@ -115,6 +115,6 @@ class HtmlExtension extends AbstractExtension
$replacements = array_merge($baseReplacements, $replacements);
return Str::placeholders($string, $replacements, true);
return Str::placeholders((string) $string, $replacements, true);
}
}
+9
View File
@@ -175,6 +175,15 @@ class ContentHelper
return $field;
}
if ($record->hasTaxonomyDefined($match[1])) {
$result = [];
foreach ($record->getTaxonomies($match[1]) as $item) {
$result[] = $item->getName();
}
return implode(', ', $result);
}
// We must ensure this method is not called recursively. For example
// `title_format: {title}` would otherwise result in an endless loop
// @see https://github.com/bolt/core/issues/1825
+1 -2
View File
@@ -28,8 +28,7 @@
{# Setting the labels and their localisations that are used in the sidebar-menu. #}
{% set labels = {
'about.bolt_documentation': 'about.bolt_documentation'|trans,
'action.view_site': 'action.view_site'|trans,
'action.create_new': 'action.create_new'|trans,
'action.view_site': config.get('general/sitename'),
'general.greeting': 'general.greeting'|trans({'%name%': user_display_name}),
'action.logout': 'action.logout'|trans,
'action.edit_profile': 'action.edit_profile'|trans,
+15 -3
View File
@@ -39,7 +39,7 @@
{% endapply %}{% endmacro %}
{% macro generate_collection_fields(collectionField, fields, compileTemplates) %}{% apply spaceless %}
{% macro generate_collection_fields(collectionField, fields, record, compileTemplates) %}{% apply spaceless %}
{% set fieldsHtml = [] %}
{% for item_field in fields %}
{% set collectionItemName = 'collections[' ~ collectionField.name ~ '][' ~ item_field.definition.name ~ ']' %}
@@ -60,6 +60,7 @@
'collection_name': collectionField.name,
'collection_label': collectionField.definition.label,
'hash': hash,
'record': record
} %}
{% if item_field.type != 'set' %}
@@ -72,11 +73,22 @@
'@bolt/_partials/fields/generic.html.twig'
] %}
{% include includeLookup with context only %}
<div>
{% include includeLookup with context only %}
<input type="hidden" name="collections[{{ collectionField.name }}][order][]" value="{{ hash }}" />
</div>
{% endset %}
{# Set the buttons #}
{% set buttons %}{% include '@bolt/_partials/fields/_collection_buttons.html.twig' with { in_collection: true, 'hash': hash } %}{% endset %}
{# Set the icon #}
{% set icon = item_field.definition.icon %}
{% if icon is empty%}{% set icon = 'fa-plus' %}{% endif %}
{# set the label manually as set in _base.html.twig, to pass to Collection.vue for templates #}
{% set label = item_field.definition.label|default(item_field.name|default('unnamed')|ucwords) %}
{% set fieldsHtml = fieldsHtml|merge([{'html': new_field, 'hash': hash, 'label': label}]) %}
{% set fieldsHtml = fieldsHtml|merge([{'content': new_field, 'hash': hash, 'label': label, 'buttons': buttons, 'icon': icon}]) %}
{% endfor %}
{{ fieldsHtml|json_encode }}
{% endapply %}{% endmacro %}
@@ -128,7 +128,6 @@
{% block label %}
{% include '@bolt/_partials/fields/_label.html.twig' %}
{% include '@bolt/_partials/fields/_collection_buttons.html.twig' %}
{% endblock %}
{% if variant == 'inline' %}</div><div class="col-9">{% endif %}
@@ -1,7 +1,5 @@
{% if in_collection is defined %}
<div class="float-right" role="group" aria-label="Collection buttons" style="margin-top: -0.25rem">
<input type="hidden" name="collections[{{ collection_name }}][order][]" value="{{ hash }}" />
<div class="float-right btn-group" role="group" aria-label="Collection buttons">
<button class='action-move-up-collection-item btn btn-secondary btn-sm' {% if is_first is defined and is_first %} disabled {% endif %}>
<i class="fas fa-fw fa-chevron-up"></i>
{{ 'collection.move_item_up'|trans }}
@@ -4,16 +4,20 @@
{% block field %}
{% set labels = {
'add_collection_item': 'collection.add_item'|trans({'%name%': field.definition.label}),
'expand_all': 'collection.expand_all'|trans,
'collapse_all': 'collection.collapse_all'|trans,
'select_tooltip': 'collection.select_tooltip'|trans,
'field_label': label,
} %}
{% set limit = field.definition.get('limit')|default(200) %}
{# get the html for all collection field already in the database #}
{% set existing_fields %}{{ macro.generate_collection_fields(field, field.value, false) }}{% endset %}
{% set existing_fields %}{{ macro.generate_collection_fields(field, field.value, record, false) }}{% endset %}
{# get the html template for the collection fields defined in the field definition #}
{% set templated_fields = "" %}
{% if field.templates is defined %}
{% set templated_fields %}{{ macro.generate_collection_fields(field, field.templates, true) }}{% endset %}
{% set templated_fields %}{{ macro.generate_collection_fields(field, field.templates, record, true) }}{% endset %}
{% endif %}
<editor-collection
@@ -21,6 +25,7 @@
:templates='{{ templated_fields }}'
:labels='{{ labels | json_encode }}'
:limit='{{ limit | json_encode }}'
:state="{{ field.definition.get('default_state')|default('collapsed')|json_encode }}"
></editor-collection>
{% endblock %}
+19 -16
View File
@@ -217,28 +217,22 @@ Feature: Edit record
And I should see "Collection:" in the "label[for='field-collection']" element
#templates dropdown
When I scroll "#multiselect-undefined > div > div.multiselect__select" into view
And I click "#multiselect-undefined > div > div.multiselect__select"
Then I should see "Set" in the "#multiselect-undefined li:nth-child(1) > span" element
And the "#multiselect-undefined li:nth-child(2) > span" element should contain "Textarea"
When I click "#multiselect-undefined > div > div.multiselect__select"
And I click "#multiselect-undefined > div > div.multiselect__content-wrapper > ul > li:nth-child(2) > span"
And I press "Add item"
When I scroll "Add item to Collection" into view
And I click "Add item to Collection"
# Click add set
And I click "#field-collection-collection > div > div.dropdown.show > div > a:nth-child(2)"
Then I should see an ".collection-item" element
And I should see an ".trumbowyg-editor" element
And I should see "Textarea:" in the "#collections label[for='field-collection-textarea-2']" element
# And I should see "Textarea" in the "#collections label[for='field-collection-textarea-2']" element
And the 1st ".action-move-up-collection-item" button should be disabled
And the 3rd ".action-move-down-collection-item" button should be disabled
When I scroll "Add item to Collection" into view
And I click "#multiselect-undefined > div > div.multiselect__select"
And I scroll "#multiselect-undefined > div > div.multiselect__content-wrapper > ul > li:nth-child(1)" into view
And I click "#multiselect-undefined > div > div.multiselect__content-wrapper > ul > li:nth-child(1)"
And I press "Add item"
And I click "Add item to Collection"
# Click add textarea
And I click "#field-collection-collection > div > div.dropdown.show > div > a:nth-child(1)"
Then I should see 4 ".collection-item" elements
@@ -255,8 +249,17 @@ Feature: Edit record
And I press "Save changes"
Then I should be on "/bolt/edit/43#collections"
And the field ".collection-item:nth-child(3) input[type='text']" should contain "Hey, Bolt"
And the field ".collection-item:nth-child(4) textarea" should contain "Bye, Bolt"
And the field ".collection-item:nth-child(4) input[type='text']" should contain "Hey, Bolt"
And the field ".collection-item:nth-child(5) textarea" should contain "Bye, Bolt"
And I should see "Hey, Bolt" in the ".collection-item:nth-child(4) .collection-item-title" element
And I should see "Bye, Bolt" in the ".collection-item:nth-child(5) .collection-item-title" element
When I fill the 2nd "#collections textarea" element with ""
And I fill the 2nd ".collection-item input[type='text']" element with ""
And I should see "Set" in the ".collection-item:nth-child(4) .collection-item-title" element
And I should see "Textarea" in the ".collection-item:nth-child(5) .collection-item-title" element
When I scroll the 3rd "Remove item" into view
And I press the 3rd "Remove item" button
@@ -17,7 +17,7 @@ class ContentTypesParserTest extends ParserTestBase
public const AMOUNT_OF_ATTRIBUTES_IN_CONTENT_TYPE = 25;
public const AMOUNT_OF_ATTRIBUTES_IN_FIELD = 25;
public const AMOUNT_OF_ATTRIBUTES_IN_FIELD = 26;
public const ALLOWED_LOCALES = 'en|nl|es|fr|de|pl|it|hu|pt_BR|ja|nb|nn|nl_NL|nl_BE';
+18
View File
@@ -2349,5 +2349,23 @@
<target>Dependencies</target>
</segment>
</unit>
<unit id="H9knE.O" name="collection.expand_all">
<segment>
<source>collection.expand_all</source>
<target>Expand all</target>
</segment>
</unit>
<unit id="JjvI6hp" name="collection.collapse_all">
<segment>
<source>collection.collapse_all</source>
<target>Collapse all</target>
</segment>
</unit>
<unit id="wAltpsD" name="collection.select_tooltip">
<segment>
<source>collection.select_tooltip</source>
<target>Select type of field to add</target>
</segment>
</unit>
</file>
</xliff>