Initial commit
This commit is contained in:
commit
65e0da7e11
1397 changed files with 596542 additions and 0 deletions
|
|
@ -0,0 +1,12 @@
|
|||
.modules-layout__preview {
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.modules-layout__preview:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.modules-layout__preview--bottom {
|
||||
border-bottom: none;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
3
site/OFF_plugins/sortable/fields/modules/controller.php
Normal file
3
site/OFF_plugins/sortable/fields/modules/controller.php
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
|
||||
class ModulesFieldController extends LukasKleinschmidt\Sortable\Controllers\Field {}
|
||||
31
site/OFF_plugins/sortable/fields/modules/modules.php
Normal file
31
site/OFF_plugins/sortable/fields/modules/modules.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
class ModulesField extends SortableField {
|
||||
|
||||
public $add = true;
|
||||
public $copy = true;
|
||||
public $paste = true;
|
||||
public $layout = 'module';
|
||||
public $variant = 'modules';
|
||||
public $actions = array(
|
||||
'edit',
|
||||
'duplicate',
|
||||
'delete',
|
||||
'toggle',
|
||||
);
|
||||
|
||||
static public $assets = array(
|
||||
'css' => array(
|
||||
'modules.css',
|
||||
),
|
||||
);
|
||||
|
||||
public function parent() {
|
||||
return Kirby\Modules\Settings::parentUid();
|
||||
}
|
||||
|
||||
public function prefix() {
|
||||
return Kirby\Modules\Settings::templatePrefix();
|
||||
}
|
||||
|
||||
}
|
||||
164
site/OFF_plugins/sortable/fields/modules/readme.md
Normal file
164
site/OFF_plugins/sortable/fields/modules/readme.md
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
# Kirby Modules Field
|
||||
|
||||
This field extends the `sortable` field and adds some presets and features to help you manage your modules.
|
||||
To use this field you have to install the [modules-plugin](https://github.com/getkirby-plugins/modules-plugin).
|
||||
|
||||
### Some of the features
|
||||
- Preset `parent` and `prefix` to match those set by the modules-plugin
|
||||
- Adds a [preview](#preview) if provided
|
||||
|
||||

|
||||
|
||||
## Blueprint
|
||||
|
||||
After installing the plugin, you can use the new field type `modules`.
|
||||
This blueprint shows all available options and their defaults.
|
||||
|
||||
```yml
|
||||
fields:
|
||||
title:
|
||||
label: Title
|
||||
type: text
|
||||
|
||||
modules:
|
||||
label: Modules
|
||||
type: modules
|
||||
|
||||
add: true
|
||||
copy: true
|
||||
paste: true
|
||||
limit: false
|
||||
variant: modules
|
||||
|
||||
actions:
|
||||
- edit
|
||||
- duplicate
|
||||
- delete
|
||||
- toggle
|
||||
|
||||
options:
|
||||
preview: true
|
||||
limit: false
|
||||
edit: true
|
||||
duplicate: true
|
||||
delete: true
|
||||
toggle: true
|
||||
...
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
The following examples show and explain some of the possible settings.
|
||||
|
||||
### Preview
|
||||
|
||||
A preview is a normal PHP file with the HTML and PHP code that defines your preview. The preview has access to the following variables:
|
||||
|
||||
- `$page` is the page on which the module appears
|
||||
- `$module` is the module subpage, which you can use to access the fields from your module blueprint as well as module files
|
||||
- `$moduleName` is the name of the module such as text or gallery
|
||||
|
||||
The preview file must be in the same folder as the module itself.
|
||||
The module directory looks something like this:
|
||||
|
||||
```
|
||||
site/modules/
|
||||
gallery/
|
||||
gallery.html.php
|
||||
gallery.yml
|
||||
|
||||
# The preview file
|
||||
gallery.preview.php
|
||||
...
|
||||
```
|
||||
|
||||
### Preview options
|
||||
|
||||
Previews are enabled by default. Set `preview` to `false` to disable the preview.
|
||||
It is also possible to change the position in the module.
|
||||
|
||||
```yml
|
||||
options:
|
||||
# Render the preview at the bottom
|
||||
preview: bottom
|
||||
|
||||
# Or at the top
|
||||
preview: top
|
||||
preview: true
|
||||
```
|
||||
|
||||
|
||||
### Limit the number of visible modules
|
||||
|
||||
```yml
|
||||
modules_field:
|
||||
label: Modules
|
||||
type: modules
|
||||
|
||||
# Allow 3 visible modules overall
|
||||
limit: 3
|
||||
|
||||
# Template specific option
|
||||
options:
|
||||
module.gallery:
|
||||
# Allow only 1 visible gallery module
|
||||
limit: 1
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Is it a module or a section?
|
||||
|
||||
Change the naming.
|
||||
|
||||
```yml
|
||||
# Modules is fine
|
||||
variant: modules
|
||||
|
||||
# Nah sections it is
|
||||
variant: sections
|
||||
```
|
||||
|
||||
### Changing actions
|
||||
|
||||
To change the actions or remove an action completely from the modules, you must specify the `actions` array in the blueprint.
|
||||
|
||||
```yml
|
||||
# Default
|
||||
actions:
|
||||
- edit
|
||||
- duplicate
|
||||
- delete
|
||||
- toggle
|
||||
```
|
||||
|
||||

|
||||
|
||||
```yml
|
||||
actions:
|
||||
- edit
|
||||
- toggle
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Disabling an action
|
||||
|
||||
```yml
|
||||
options:
|
||||
edit: false
|
||||
duplicate: false
|
||||
delete: true
|
||||
toggle: true
|
||||
|
||||
# Template specific options
|
||||
module.gallery:
|
||||
edit: true
|
||||
duplicate: true
|
||||
```
|
||||
|
||||

|
||||
|
||||
## Requirements
|
||||
|
||||
- [Kirby Modules Plugin](https://github.com/getkirby-plugins/modules-plugin) 1.3+
|
||||
32
site/OFF_plugins/sortable/fields/modules/template.php
Normal file
32
site/OFF_plugins/sortable/fields/modules/template.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<label class="label">
|
||||
<?= $field->label(); ?>
|
||||
<?= $field->counter(); ?>
|
||||
<?php if($field->add()) echo $field->action('add'); ?>
|
||||
</label>
|
||||
|
||||
<?php if($field->entries()->count()): ?>
|
||||
<?= $field->layouts(); ?>
|
||||
<?php else: ?>
|
||||
<div class="sortable__empty">
|
||||
<?php
|
||||
echo $field->l('field.sortable.empty');
|
||||
if($field->add()) {
|
||||
echo $field->action('add', ['label' => $field->l('field.sortable.add.first'), 'icon' => '', 'class' => '']);
|
||||
if($field->paste()) {
|
||||
echo $field->l('field.sortable.or');
|
||||
echo $field->action('paste', ['label' => $field->l('field.sortable.paste.first'), 'icon' => '', 'class' => '']);
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="sortable__navigation">
|
||||
<?php
|
||||
if($field->copy()) echo $field->action('copy');
|
||||
if($field->add()) {
|
||||
if($field->paste()) echo $field->action('paste');
|
||||
echo $field->action('add');
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
44
site/OFF_plugins/sortable/fields/options/options.php
Normal file
44
site/OFF_plugins/sortable/fields/options/options.php
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
class OptionsField extends CheckboxesField {
|
||||
|
||||
public function input() {
|
||||
|
||||
$value = func_get_arg(0);
|
||||
$data = func_get_arg(1);
|
||||
|
||||
$input = parent::input($value);
|
||||
|
||||
if(!$this->error) {
|
||||
$input->attr('checked', v::accepted($this->value()) || v::accepted($data->checked()));
|
||||
}
|
||||
|
||||
if($data->readonly()) {
|
||||
$input->attr('disabled', true);
|
||||
$input->attr('readonly', true);
|
||||
$input->addClass('input-is-readonly');
|
||||
}
|
||||
|
||||
return $input;
|
||||
|
||||
}
|
||||
|
||||
public function item($value, $data) {
|
||||
|
||||
$data = new Obj($data);
|
||||
$input = $this->input($value, $data);
|
||||
|
||||
$label = new Brick('label', '<span>' . $this->i18n($data->label()) . '</span>');
|
||||
$label->addClass('input input-with-checkbox');
|
||||
$label->attr('data-focus', 'true');
|
||||
$label->prepend($input);
|
||||
|
||||
if($data->readonly()) {
|
||||
$label->addClass('input-is-readonly');
|
||||
}
|
||||
|
||||
return $label;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
39
site/OFF_plugins/sortable/fields/redirect/readme.md
Normal file
39
site/OFF_plugins/sortable/fields/redirect/readme.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# Kirby Redirect Field
|
||||
|
||||
This field redirects a user to the parent of the currently visited panel page.
|
||||
Useful for pages that act like a container.
|
||||
|
||||
## Blueprint
|
||||
```yml
|
||||
fields:
|
||||
title:
|
||||
label: Title
|
||||
type: text
|
||||
|
||||
redirect:
|
||||
label: Redirect
|
||||
type: redirect
|
||||
...
|
||||
```
|
||||
|
||||
## Redirect to a specific page
|
||||
|
||||
Redirect to `panel/projects/project-a/edit`.
|
||||
When the page is not found you will get redirected to the dashboard.
|
||||
|
||||
```yml
|
||||
redirect:
|
||||
label: Redirect
|
||||
type: redirect
|
||||
|
||||
redirect: projects/project-a
|
||||
```
|
||||
|
||||
## Hide pages
|
||||
There are several ways to hide pages in the panel. The easyiest way would be to set `hide: true` in the pages [blueprint](https://getkirby.com/docs/panel/blueprints/page-settings#hide-page). This would hide a page in the sidebar. To get rid of the breadcrumb link you can put something like this to your [custom panel css](https://getkirby.com/docs/developer-guide/panel/css).
|
||||
|
||||
```css
|
||||
.breadcrumb-link[title="your-page-title"] {
|
||||
display: none;
|
||||
}
|
||||
```
|
||||
25
site/OFF_plugins/sortable/fields/redirect/redirect.php
Normal file
25
site/OFF_plugins/sortable/fields/redirect/redirect.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
class RedirectField extends BaseField {
|
||||
|
||||
public $redirect;
|
||||
|
||||
public function template() {
|
||||
|
||||
$redirect = $this->redirect();
|
||||
|
||||
if(is_null($redirect)) {
|
||||
return go(purl($this->page()->parent(), 'edit'));
|
||||
}
|
||||
|
||||
$page = panel()->page($redirect);
|
||||
|
||||
if(is_null($page)) {
|
||||
return go(purl());
|
||||
}
|
||||
|
||||
return go(purl($page));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
/* TEMP: until https://github.com/getkirby/panel/pull/986 is resolved */
|
||||
.form-blueprint-home > fieldset {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@-moz-document url-prefix() {
|
||||
.form-blueprint-home > fieldset {
|
||||
display: table-cell;
|
||||
}
|
||||
}
|
||||
|
||||
.sortable__counter {
|
||||
padding-left: 0.25em;
|
||||
font-size: 0.8em;
|
||||
font-weight: 400;
|
||||
color: #bbb;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.sortable__empty {
|
||||
background: #ddd;
|
||||
padding: 1.5em;
|
||||
}
|
||||
|
||||
.sortable__empty a {
|
||||
border-bottom: 2px solid #bbb;
|
||||
margin: 0 0.25em;
|
||||
}
|
||||
|
||||
.sortable__empty a:hover {
|
||||
border-color: #000;
|
||||
}
|
||||
|
||||
.sortable__empty a:first-child {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
.sortable__navigation {
|
||||
padding-top: 0.5em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sortable__action {
|
||||
color: #777;
|
||||
font-weight: 400;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.sortable__action .icon,
|
||||
.sortable__action:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.sortable__action--add {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.sortable__action:nth-child(n+2) {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.sortable__action.is-disabled {
|
||||
pointer-events: none;
|
||||
color: #c9c9c9;
|
||||
}
|
||||
|
||||
.sortable__layout {
|
||||
margin-bottom: 0.25em;
|
||||
}
|
||||
|
||||
.sortable-layout a,
|
||||
.sortable-layout button,
|
||||
.sortable__action.is-disabled .icon {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.sortable-layout {
|
||||
background: #fff;
|
||||
border: 2px solid #ddd;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sortable-layout .icon {
|
||||
vertical-align: -5%;
|
||||
}
|
||||
|
||||
.sortable-layout .icon:not(.icon-left) {
|
||||
width: 1.28571em;
|
||||
}
|
||||
|
||||
.sortable-layout__icon {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.sortable-layout__counter {
|
||||
padding-left: 0.25em;
|
||||
font-size: 0.8em;
|
||||
color: #bbb;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.sortable-layout [data-handle] {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.sortable-layout__navigation {
|
||||
min-height: 44px;
|
||||
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-flex-flow: row nowrap;
|
||||
-ms-flex-flow: row nowrap;
|
||||
flex-flow: row nowrap;
|
||||
}
|
||||
|
||||
.sortable-layout__icon,
|
||||
.sortable-layout__action,
|
||||
.sortable-layout__title {
|
||||
padding: 0.6em;
|
||||
white-space: nowrap;
|
||||
line-height: 1.5em;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.sortable-layout__title {
|
||||
-webkit-flex: 1 0 0%;
|
||||
-ms-flex: 1 0 0%;
|
||||
flex: 1 0 0%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding-left: 0.35em;
|
||||
}
|
||||
|
||||
.sortable-layout[data-visible=false] .sortable-layout__icon,
|
||||
.sortable-layout[data-visible=false] .sortable-layout__title {
|
||||
color: #c9c9c9;
|
||||
}
|
||||
|
||||
.sortable-layout__action {
|
||||
-webkit-flex: 0 0 auto;
|
||||
-ms-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
border: none;
|
||||
//border-left: 1px solid #efefef;
|
||||
background: 0 0;
|
||||
cursor: pointer;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.sortable-layout__action.is-disabled {
|
||||
pointer-events: none;
|
||||
color: #c9c9c9;
|
||||
}
|
||||
|
||||
.sortable-placeholder {
|
||||
width: 25%;
|
||||
height: 25%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.sortable__grid {
|
||||
width: 33%; display: inline-block; vertical-align: middle;
|
||||
}
|
||||
|
||||
.sortable__grid .sortable-layout__icon {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sortable__action--copy, .sortable__action--paste {
|
||||
display: none;
|
||||
}
|
||||
207
site/OFF_plugins/sortable/fields/sortable/assets/js/sortable.js
Normal file
207
site/OFF_plugins/sortable/fields/sortable/assets/js/sortable.js
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
(function($) {
|
||||
|
||||
var Sort = function(element) {
|
||||
var self = this;
|
||||
|
||||
this.element = $(element);
|
||||
this.container = $('.sortable__container', element);
|
||||
this.api = this.element.data('api');
|
||||
|
||||
this.container._sortable({
|
||||
handle: '[data-handle]',
|
||||
placeholder: "sortable-placeholder",
|
||||
start: function(event, ui) {
|
||||
self.container._sortable('refreshPositions');
|
||||
self.blur();
|
||||
},
|
||||
update: function(event, ui) {
|
||||
var to = self.container.children().index(ui.item) + 1;
|
||||
var uid = ui.item.data('uid');
|
||||
var action = [self.api, uid, to, 'sort'].join('/');
|
||||
|
||||
// disable sorting because a reload is expected
|
||||
self.disable();
|
||||
|
||||
$.post(action, self.reload.bind(self));
|
||||
}
|
||||
});
|
||||
|
||||
this.element.on('click', '[data-action]', function(event) {
|
||||
var element = $(this);
|
||||
var action = element.data('action') || element.attr('href');
|
||||
|
||||
$.post(action, self.reload.bind(self));
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// setup extended field script
|
||||
var key = this.element.data('field-extended');
|
||||
if(key != 'sortable' && this.element[key]) this.element[key]();
|
||||
};
|
||||
|
||||
Sort.prototype.blur = function() {
|
||||
$('.form input:focus, .form select:focus, .form textarea:focus').blur();
|
||||
app.content.focus.forget();
|
||||
}
|
||||
|
||||
Sort.prototype.disable = function() {
|
||||
this.container._sortable('disable');
|
||||
}
|
||||
|
||||
Sort.prototype.reload = function() {
|
||||
this.disable();
|
||||
app.content.reload();
|
||||
}
|
||||
|
||||
|
||||
// Fixing scrollbar jumping issue
|
||||
// http://stackoverflow.com/questions/1735372/jquery-sortable-list-scroll-bar-jumps-up-when-sorting
|
||||
if (typeof($.ui._sortable) === 'undefined') {
|
||||
$.widget('ui._sortable', $.ui.sortable, {
|
||||
_mouseStart: function(event, overrideHandle, noActivation) {
|
||||
var i, body,
|
||||
o = this.options;
|
||||
|
||||
this.currentContainer = this;
|
||||
|
||||
//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
|
||||
this.refreshPositions();
|
||||
|
||||
//Create and append the visible helper
|
||||
this.helper = this._createHelper(event);
|
||||
|
||||
//Cache the helper size
|
||||
this._cacheHelperProportions();
|
||||
|
||||
/*
|
||||
* - Position generation -
|
||||
* This block generates everything position related - it's the core of draggables.
|
||||
*/
|
||||
|
||||
//Cache the margins of the original element
|
||||
this._cacheMargins();
|
||||
|
||||
//Get the next scrolling parent
|
||||
this.scrollParent = this.helper.scrollParent();
|
||||
|
||||
//The element's absolute position on the page minus margins
|
||||
this.offset = this.currentItem.offset();
|
||||
this.offset = {
|
||||
top: this.offset.top - this.margins.top,
|
||||
left: this.offset.left - this.margins.left
|
||||
};
|
||||
|
||||
$.extend(this.offset, {
|
||||
click: { //Where the click happened, relative to the element
|
||||
left: event.pageX - this.offset.left,
|
||||
top: event.pageY - this.offset.top
|
||||
},
|
||||
parent: this._getParentOffset(),
|
||||
relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
|
||||
});
|
||||
|
||||
//Create the placeholder
|
||||
this._createPlaceholder();
|
||||
|
||||
// Only after we got the offset, we can change the helper's position to absolute
|
||||
this.helper.css("position", "absolute");
|
||||
this.cssPosition = this.helper.css("position");
|
||||
|
||||
//Generate the original position
|
||||
this.originalPosition = this._generatePosition(event);
|
||||
this.originalPageX = event.pageX;
|
||||
this.originalPageY = event.pageY;
|
||||
|
||||
//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
|
||||
(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
|
||||
|
||||
//Cache the former DOM position
|
||||
this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
|
||||
|
||||
//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
|
||||
if(this.helper[0] !== this.currentItem[0]) {
|
||||
this.currentItem.hide();
|
||||
}
|
||||
|
||||
//Set a containment if given in the options
|
||||
if(o.containment) {
|
||||
this._setContainment();
|
||||
}
|
||||
|
||||
if( o.cursor && o.cursor !== "auto" ) { // cursor option
|
||||
body = this.document.find( "body" );
|
||||
|
||||
// support: IE
|
||||
this.storedCursor = body.css( "cursor" );
|
||||
body.css( "cursor", o.cursor );
|
||||
|
||||
this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
|
||||
}
|
||||
|
||||
if(o.opacity) { // opacity option
|
||||
if (this.helper.css("opacity")) {
|
||||
this._storedOpacity = this.helper.css("opacity");
|
||||
}
|
||||
this.helper.css("opacity", o.opacity);
|
||||
}
|
||||
|
||||
if(o.zIndex) { // zIndex option
|
||||
if (this.helper.css("zIndex")) {
|
||||
this._storedZIndex = this.helper.css("zIndex");
|
||||
}
|
||||
this.helper.css("zIndex", o.zIndex);
|
||||
}
|
||||
|
||||
//Prepare scrolling
|
||||
if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
|
||||
this.overflowOffset = this.scrollParent.offset();
|
||||
}
|
||||
|
||||
//Call callbacks
|
||||
this._trigger("start", event, this._uiHash());
|
||||
|
||||
//Recache the helper size
|
||||
if(!this._preserveHelperProportions) {
|
||||
this._cacheHelperProportions();
|
||||
}
|
||||
|
||||
|
||||
//Post "activate" events to possible containers
|
||||
if( !noActivation ) {
|
||||
for ( i = this.containers.length - 1; i >= 0; i-- ) {
|
||||
this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
|
||||
}
|
||||
}
|
||||
|
||||
//Prepare possible droppables
|
||||
if($.ui.ddmanager) {
|
||||
$.ui.ddmanager.current = this;
|
||||
}
|
||||
|
||||
if ($.ui.ddmanager && !o.dropBehaviour) {
|
||||
$.ui.ddmanager.prepareOffsets(this, event);
|
||||
}
|
||||
|
||||
this.dragging = true;
|
||||
|
||||
this.helper.addClass("ui-sortable-helper");
|
||||
this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$.fn.sort = function() {
|
||||
return this.each(function() {
|
||||
if ($(this).data('sort')) {
|
||||
return $(this);
|
||||
} else {
|
||||
var sort = new Sort(this);
|
||||
$(this).data('sort', sort);
|
||||
return $(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
3
site/OFF_plugins/sortable/fields/sortable/controller.php
Normal file
3
site/OFF_plugins/sortable/fields/sortable/controller.php
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
|
||||
class SortableFieldController extends LukasKleinschmidt\Sortable\Controllers\Field {}
|
||||
315
site/OFF_plugins/sortable/fields/sortable/sortable.php
Normal file
315
site/OFF_plugins/sortable/fields/sortable/sortable.php
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
<?php
|
||||
|
||||
use LukasKleinschmidt\Sortable;
|
||||
|
||||
// Load all registerd classes
|
||||
sortable()->load();
|
||||
|
||||
class SortableField extends InputField {
|
||||
|
||||
public $limit = false;
|
||||
public $parent = null;
|
||||
public $prefix = null;
|
||||
public $layout = 'base';
|
||||
public $variant = null;
|
||||
public $options = array();
|
||||
|
||||
// Caches
|
||||
protected $entries;
|
||||
protected $defaults;
|
||||
protected $origin;
|
||||
|
||||
static public $assets = array(
|
||||
'js' => array(
|
||||
'sortable.js',
|
||||
),
|
||||
'css' => array(
|
||||
'sortable.css',
|
||||
),
|
||||
);
|
||||
|
||||
public function routes() {
|
||||
return array(
|
||||
array(
|
||||
'pattern' => 'action/(:any)/(:all?)',
|
||||
'method' => 'POST|GET',
|
||||
'action' => 'forAction',
|
||||
'filter' => 'auth',
|
||||
),
|
||||
array(
|
||||
'pattern' => '(:all)/(:all)/sort',
|
||||
'method' => 'POST|GET',
|
||||
'action' => 'sort',
|
||||
'filter' => 'auth',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function parent() {
|
||||
return $this->i18n($this->parent);
|
||||
}
|
||||
|
||||
public function action($type, $data = array()) {
|
||||
|
||||
$data = a::update($data, array(
|
||||
'field' => $this,
|
||||
'parent' => $this->origin(),
|
||||
));
|
||||
|
||||
return sortable::action($type, $data);
|
||||
|
||||
}
|
||||
|
||||
public function layout($type, $data = array()) {
|
||||
|
||||
$data = a::update($data, array(
|
||||
'field' => $this,
|
||||
'parent' => $this->origin(),
|
||||
));
|
||||
|
||||
return sortable::layout($type, $data);
|
||||
|
||||
}
|
||||
|
||||
public function layouts() {
|
||||
|
||||
$layouts = new Brick('div');
|
||||
$layouts->addClass('sortable__container');
|
||||
|
||||
$numVisible = 0;
|
||||
$num = 0;
|
||||
|
||||
foreach($this->entries() as $page) {
|
||||
|
||||
if($page->isVisible()) $numVisible++;
|
||||
$num++;
|
||||
|
||||
$data = a::update($this->options($page)->toArray(), array(
|
||||
'numVisible' => $numVisible,
|
||||
'page' => $page,
|
||||
'num' => $num,
|
||||
));
|
||||
|
||||
$layout = $this->layout($this->layout, $data);
|
||||
$layouts->append($layout);
|
||||
|
||||
}
|
||||
|
||||
return $layouts;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get translation
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $variant
|
||||
* @return string
|
||||
*/
|
||||
public function l($key, $variant = null) {
|
||||
|
||||
if(is_null($variant)) {
|
||||
$variant = $this->variant();
|
||||
}
|
||||
|
||||
return sortable()->translation($key, $variant);
|
||||
|
||||
}
|
||||
|
||||
public function input() {
|
||||
|
||||
$value = func_get_arg(0);
|
||||
$input = parent::input();
|
||||
$input->attr(array(
|
||||
'id' => $value,
|
||||
'name' => $this->name() . '[]',
|
||||
'type' => 'hidden',
|
||||
'value' => $value,
|
||||
'required' => false,
|
||||
'autocomplete' => false,
|
||||
));
|
||||
|
||||
return $input;
|
||||
|
||||
}
|
||||
|
||||
public function defaults() {
|
||||
|
||||
// Return from cache if possible
|
||||
if(!is_null($this->defaults)) {
|
||||
return $this->defaults;
|
||||
}
|
||||
|
||||
if(!$this->options) {
|
||||
return $this->defaults = array();
|
||||
}
|
||||
|
||||
// Available templates
|
||||
$templates = $this->origin()->blueprint()->pages()->template()->pluck('name');
|
||||
|
||||
// Remove template specific options from the defaults
|
||||
$defaults = array();
|
||||
|
||||
foreach($this->options as $key => $value) {
|
||||
if(in_array($key, $templates)) continue;
|
||||
$defaults[$key] = $value;
|
||||
}
|
||||
|
||||
return $this->defaults = $defaults;
|
||||
|
||||
}
|
||||
|
||||
public function options($template) {
|
||||
|
||||
if(is_a($template, 'Page')) {
|
||||
$template = $template->intendedTemplate();
|
||||
}
|
||||
|
||||
// Get entry specific options
|
||||
$options = a::get($this->options, $template, array());
|
||||
|
||||
return new Obj(a::update($this->defaults(), $options));
|
||||
|
||||
}
|
||||
|
||||
public function content() {
|
||||
|
||||
$template = $this->root() . DS . 'template.php';
|
||||
|
||||
if(!is_file($template)) {
|
||||
$template = __DIR__ . DS . 'template.php';
|
||||
}
|
||||
|
||||
$content = new Brick('div');
|
||||
|
||||
// Sort namespace is used because otherwise there
|
||||
// would be a collision with the jquery sortable plugin
|
||||
$content->attr('data-field', 'sort');
|
||||
$content->attr('data-field-extended', $this->type());
|
||||
$content->attr('data-api', $this->url());
|
||||
$content->addClass('sortable');
|
||||
$content->append(tpl::load($template, array('field' => $this)));
|
||||
|
||||
return $content;
|
||||
|
||||
}
|
||||
|
||||
public function origin() {
|
||||
|
||||
// Return from cache if possible
|
||||
if($this->origin) {
|
||||
return $this->origin;
|
||||
}
|
||||
|
||||
$origin = $this->page();
|
||||
|
||||
if($this->parent()) {
|
||||
$origin = $origin->find($this->parent());
|
||||
}
|
||||
|
||||
if(!is_a($origin, 'Page')) {
|
||||
throw new Exception('The parent page could not be found');
|
||||
}
|
||||
|
||||
return $this->origin = $origin;
|
||||
|
||||
}
|
||||
|
||||
public function entries() {
|
||||
|
||||
// Return from cache if possible
|
||||
if(!is_null($this->entries)) {
|
||||
return $this->entries;
|
||||
}
|
||||
|
||||
$entries = $this->origin()->children();
|
||||
|
||||
// Filter the entries
|
||||
if($entries->count() && $this->prefix()) {
|
||||
$entries = $entries->filter(function($page) {
|
||||
return str::startsWith($page->intendedTemplate(), $this->prefix());
|
||||
});
|
||||
}
|
||||
|
||||
// Sort entries
|
||||
if($entries->count() && $this->value()) {
|
||||
$i = 0;
|
||||
|
||||
$order = a::merge(array_flip($this->value()), array_flip($entries->pluck('uid')));
|
||||
$order = array_map(function($value) use(&$i) {
|
||||
return $i++;
|
||||
}, $order);
|
||||
|
||||
$entries = $entries->find(array_flip($order));
|
||||
}
|
||||
|
||||
// Always return a collection
|
||||
if(is_a($entries, 'Page')) {
|
||||
$page = $entries;
|
||||
$entries = new Children($this->origin());
|
||||
|
||||
$entries->data[$page->id()] = $page;
|
||||
}
|
||||
|
||||
return $this->entries = $entries;
|
||||
|
||||
}
|
||||
|
||||
public function counter() {
|
||||
|
||||
if($this->limit()) {
|
||||
|
||||
$counter = new Brick('span');
|
||||
$counter->addClass('sortable__counter');
|
||||
$counter->append('( ' . $this->entries()->published()->count() . ' / ' . $this->limit() . ' )');
|
||||
|
||||
return $counter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function label() {
|
||||
return $this->i18n($this->label);
|
||||
}
|
||||
|
||||
public function validate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function value() {
|
||||
|
||||
$value = parent::value();
|
||||
if(is_array($value)) {
|
||||
return $value;
|
||||
} else {
|
||||
return str::split($value, ',');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function result() {
|
||||
|
||||
$result = parent::result();
|
||||
return is_array($result) ? implode(', ', $result) : '';
|
||||
|
||||
}
|
||||
|
||||
public function url($action = null) {
|
||||
|
||||
$url = purl($this->model(), 'field/' . $this->name() . '/' . $this->type());
|
||||
|
||||
if(is_null($action)) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
return $url . '/action/' . $action;
|
||||
|
||||
}
|
||||
|
||||
public function template() {
|
||||
return $this->element()
|
||||
->append($this->content())
|
||||
->append($this->help());
|
||||
}
|
||||
|
||||
}
|
||||
22
site/OFF_plugins/sortable/fields/sortable/template.php
Normal file
22
site/OFF_plugins/sortable/fields/sortable/template.php
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<label class="label">
|
||||
<?= $field->label(); ?>
|
||||
<?= $field->counter(); ?>
|
||||
<!-- <?= $field->action('add'); ?> -->
|
||||
</label>
|
||||
|
||||
<?php if($field->entries()->count()): ?>
|
||||
<?= $field->layouts(); ?>
|
||||
<?php else: ?>
|
||||
<!-- <div class="sortable__empty">
|
||||
<?= $field->l('field.sortable.empty'); ?>
|
||||
<?= $field->action('add', ['label' => $field->l('field.sortable.add.first'), 'icon' => '', 'class' => '']); ?>
|
||||
<?= $field->l('field.sortable.or'); ?>
|
||||
<?= $field->action('paste', ['label' => $field->l('field.sortable.paste.first'), 'icon' => '', 'class' => '']); ?>
|
||||
</div> -->
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- <div class="sortable__navigation">
|
||||
<?= $field->action('copy'); ?>
|
||||
<?= $field->action('paste'); ?>
|
||||
<?= $field->action('add'); ?>
|
||||
</div> -->
|
||||
7
site/OFF_plugins/sortable/package.json
Normal file
7
site/OFF_plugins/sortable/package.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"name": "sortable",
|
||||
"version": "2.3.2",
|
||||
"description": "Kirby Sortable",
|
||||
"license": "MIT",
|
||||
"type": "kirby-plugin"
|
||||
}
|
||||
241
site/OFF_plugins/sortable/readme.md
Normal file
241
site/OFF_plugins/sortable/readme.md
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
# Kirby Sortable
|
||||
A toolkit for managing subpages in the content area.
|
||||
|
||||

|
||||
|
||||
|
||||
## Table of contents
|
||||
1. [Features](#1-features)
|
||||
3. [Installation](#2-installation)
|
||||
4. [Blueprint](#3-blueprint)
|
||||
5. [Customize](#4-customize)
|
||||
6. [Donate](#5-donate)
|
||||
|
||||
|
||||
## 1 Features
|
||||
This project started as a simple field and has grown into a reliable and extendable plugin.
|
||||
It includes the [`sortable`](#sortable), [`modules`](#modules), [`redirect`](#redirect) and [`options`](#options) field.
|
||||
In addition to the four fields the plugin has its own [registry](#registry).
|
||||
|
||||
### Fields
|
||||
#### `sortable`
|
||||
The core field. It is the base for the `modules` field.
|
||||
Change appereance in the [blueprint](#3-blueprint) or [build your own field](#4-customize) based on this one.
|
||||
|
||||
#### `modules`
|
||||
The `modules` field is an extended `sortable` field. Bundled with the [modules-plugin](https://github.com/getkirby-plugins/modules-plugin) it is a very powerful tool. You can find further informations [here](fields/modules).
|
||||
To disable the field add `c::get('sortable.field.modules', false);` to your `config.php`.
|
||||
|
||||
#### `redirect`
|
||||
Redirect a user to the parent of the currently visited panel page. Useful for pages that act as a container. You can find further informations [here](fields/redirect).
|
||||
To disable the field add `c::get('sortable.field.redirect', false);` to your `config.php`.
|
||||
|
||||
#### `options`
|
||||
This field is used internally by the `sortable` field for the copy and paste functionality.
|
||||
|
||||
### Registry
|
||||
With the registry you are able to customize the visual appearance and modify or add custom functionality.
|
||||
The registry makes it possible to register [layouts](#layout-1), [actions](#action), [variants](#variant-1) and [translations](#translation). Learn more about how to register components in the [customize](#4-customize) section.
|
||||
|
||||
|
||||
## 2 Installation
|
||||
There are several ways to install the plugin.
|
||||
Please make sure you meet the minimum requirements.
|
||||
|
||||
### Requirements
|
||||
- PHP 5.4+
|
||||
- [Kirby](https://getkirby.com/) 2.3+
|
||||
- [Kirby Modules Plugin](https://github.com/getkirby-plugins/modules-plugin) 1.3+
|
||||
when you want to use the `modules` field
|
||||
|
||||
### Git
|
||||
To clone or add the plugin as a submodule you need to cd to the root directory of your Kirby installation and run one of the corresponding command:
|
||||
`$ git clone https://github.com/lukaskleinschmidt/kirby-sortable.git site/plugins/sortable`
|
||||
`$ git submodule add https://github.com/lukaskleinschmidt/kirby-sortable.git site/plugins/sortable`
|
||||
|
||||
### Kirby CLI
|
||||
If you're using the Kirby CLI, you need to cd to the root directory of your Kirby installation and run the following command: `kirby plugin:install lukaskleinschmidt/kirby-sortable`
|
||||
|
||||
### Download
|
||||
You can download the latest version of the plugin [here](https://github.com/lukaskleinschmidt/kirby-sortable/releases/latest).
|
||||
To install the plugin, please put it in the `site/plugins` directory.
|
||||
The plugin folder must be named `sortable`.
|
||||
|
||||
```
|
||||
site/plugins/
|
||||
sortable/
|
||||
sortable.php
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
## 3 Blueprint
|
||||
After installing the plugin you can use the new field types.
|
||||
This blueprint shows all available options of the `sortable` field.
|
||||
|
||||
```yml
|
||||
fields:
|
||||
title:
|
||||
label: Title
|
||||
type: text
|
||||
|
||||
sortable:
|
||||
label: Sortable
|
||||
type: sortable
|
||||
|
||||
layout: base
|
||||
variant: null
|
||||
|
||||
limit: false
|
||||
|
||||
parent: null
|
||||
prefix: null
|
||||
|
||||
options:
|
||||
limit: false
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
#### `layout`
|
||||
Load a registerd layout. The layout defines how a entry is rendered. Learn how to [register your own layout](#layout-1).
|
||||
|
||||
#### `variant`
|
||||
Load a registerd variant. A variant is used to change the naming of the field from page to modules for example. Learn how to [register your own variant](#variant-1).
|
||||
|
||||
#### `limit`
|
||||
Limit he number of visible pages. Example blueprint from the `modules` field.
|
||||
```yml
|
||||
fields:
|
||||
modules:
|
||||
label: Modules
|
||||
type: modules
|
||||
|
||||
# Allow 5 visible modules overall
|
||||
limit: 5
|
||||
|
||||
# Template specific option
|
||||
options:
|
||||
|
||||
# Allow only 3 modules per template (applies to all templates)
|
||||
limit: 3
|
||||
module.gallery:
|
||||
|
||||
# Allow only 1 visible gallery module (overwrites the current limit of 3)
|
||||
limit: 1
|
||||
```
|
||||
|
||||
#### `parent`
|
||||
Uid to use when looking for the container page. If left empty the field will look for subpages in the current page.
|
||||
```yml
|
||||
# home.yml
|
||||
|
||||
fields:
|
||||
events:
|
||||
label: Events
|
||||
type: sortable
|
||||
|
||||
parent: events
|
||||
```
|
||||
```
|
||||
site/content/
|
||||
home/
|
||||
home.txt
|
||||
events/
|
||||
event-1/
|
||||
event.txt
|
||||
event-2/
|
||||
event.txt
|
||||
...
|
||||
```
|
||||
|
||||
#### `prefix`
|
||||
Template prefix to filter available subpages.
|
||||
```yml
|
||||
# home.yml
|
||||
|
||||
fields:
|
||||
events:
|
||||
label: Events
|
||||
type: sortable
|
||||
|
||||
prefix: event.
|
||||
```
|
||||
```
|
||||
site/content/
|
||||
home/
|
||||
home.txt
|
||||
event-1/
|
||||
event.default.txt
|
||||
event-2/
|
||||
event.default.txt
|
||||
subpage/
|
||||
default.txt
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
## 4 Customize
|
||||
With the registry you are able to customize the visual appearance and modify or add functionality.
|
||||
The registry makes it possible to register layouts, actions, variants and translations.
|
||||
|
||||
```php
|
||||
// site/plugins/sortable-variants/sortable-variants.php
|
||||
|
||||
// Make sure that the sortable plugin is loaded
|
||||
$kirby->plugin('sortable');
|
||||
|
||||
if(!function_exists('sortable')) return;
|
||||
|
||||
$kirby->set('field', 'variants', __DIR__ . DS . 'field');
|
||||
|
||||
$sortable = sortable();
|
||||
$sortable->set('layout', 'variant', __DIR__ . DS . 'layout');
|
||||
$sortable->set('variant', 'variants', __DIR__ . DS . 'variant');
|
||||
$sortable->set('action', '_add', __DIR__ . DS . 'actions' . DS . '_add');
|
||||
$sortable->set('action', '_paste', __DIR__ . DS . 'actions' . DS . '_paste');
|
||||
$sortable->set('action', '_duplicate', __DIR__ . DS . 'actions' . DS . '_duplicate');
|
||||
```
|
||||
|
||||
A plugin can take care of registering all kinds of extensions, which will then be available in the `sortable` field or any field based on that.
|
||||
|
||||
### List of registry extensions
|
||||
These are all possible registry extensions you can register this way:
|
||||
|
||||
#### layout
|
||||
```php
|
||||
// The layout directory must exist and it must have a PHP file with the same name in it
|
||||
sortable()->set('layout', 'mylayout', __DIR__ . DS . 'mylayout');
|
||||
```
|
||||
Have a look at the [base layout](sortable/layouts/base) or the [module layout](sortable/layouts/module).
|
||||
|
||||
#### action
|
||||
```php
|
||||
// The action directory must exist and it must have a PHP file with the same name in it
|
||||
sortable()->set('action', 'myaction', __DIR__ . DS . 'myaction');
|
||||
```
|
||||
Have a look at the [actions](sortable/actions).
|
||||
|
||||
#### variant
|
||||
```php
|
||||
// The variant directory must exist and can have multiple tranlation files
|
||||
sortable()->set('variant', 'myvariant', __DIR__ . DS . 'myvariant');
|
||||
```
|
||||
Have a look at the [modules variant](sortable/variants/modules) or the [sections variant](sortable/variants/sections).
|
||||
|
||||
#### translation
|
||||
```php
|
||||
// The translation file must exist at the given location
|
||||
sortable()->set('translation', 'en', __DIR__ . DS . 'en.php');
|
||||
sortable()->set('translation', 'sv_SE', __DIR__ . DS . 'sv_SE.php');
|
||||
```
|
||||
Have a look at the [translations](sortable/translations).
|
||||
|
||||
### Examples
|
||||
- [kirby-sortable-variants](https://github.com/lukaskleinschmidt/kirby-sortable-variants)
|
||||
- [kirby-sortable-events](https://github.com/lukaskleinschmidt/kirby-sortable-events)
|
||||
|
||||
|
||||
## 5 Donate
|
||||
|
||||
If you enjoy this plugin and want to support me you can [buy me a beer](https://www.paypal.me/lukaskleinschmidt/5eur) :)
|
||||
19
site/OFF_plugins/sortable/sortable.php
Normal file
19
site/OFF_plugins/sortable/sortable.php
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
if(!function_exists('panel')) return;
|
||||
|
||||
// load the sortable bootstrapper
|
||||
require(__DIR__ . DS . 'sortable' . DS . 'bootstrap.php');
|
||||
|
||||
sortable()->register();
|
||||
|
||||
$kirby->set('field', 'sortable', __DIR__ . DS . 'fields' . DS . 'sortable');
|
||||
$kirby->set('field', 'options' , __DIR__ . DS . 'fields' . DS . 'options');
|
||||
|
||||
if(c::get('sortable.field.redirect', true)) {
|
||||
$kirby->set('field', 'redirect', __DIR__ . DS . 'fields' . DS . 'redirect');
|
||||
}
|
||||
|
||||
if(c::get('sortable.field.modules', true)) {
|
||||
$kirby->set('field', 'modules', __DIR__ . DS . 'fields' . DS . 'modules');
|
||||
}
|
||||
33
site/OFF_plugins/sortable/sortable/actions/add/add.php
Normal file
33
site/OFF_plugins/sortable/sortable/actions/add/add.php
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
class AddAction extends BaseAction {
|
||||
|
||||
public $icon = 'plus-circle';
|
||||
public $class = 'sortable__action sortable__action--add';
|
||||
public $label = 'field.sortable.add';
|
||||
|
||||
public function routes() {
|
||||
return array(
|
||||
array(
|
||||
'pattern' => '/',
|
||||
'method' => 'POST|GET',
|
||||
'action' => 'add',
|
||||
'filter' => 'auth',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function content() {
|
||||
|
||||
$content = parent::content();
|
||||
$content->data('modal', true);
|
||||
|
||||
return $content;
|
||||
|
||||
}
|
||||
|
||||
public function disabled() {
|
||||
return $this->disabled || $this->parent()->ui()->create() === false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
class AddActionController extends LukasKleinschmidt\Sortable\Controllers\Action {
|
||||
|
||||
/**
|
||||
* Add a entry
|
||||
*/
|
||||
public function add() {
|
||||
|
||||
$self = $this;
|
||||
$parent = $this->field()->origin();
|
||||
|
||||
if($parent->ui()->create() === false) {
|
||||
throw new Kirby\Panel\Exceptions\PermissionsException();
|
||||
}
|
||||
|
||||
$form = $this->form('add', array($parent, $this->model(), $this->field()), function($form) use($parent, $self) {
|
||||
|
||||
try {
|
||||
|
||||
$form->validate();
|
||||
|
||||
if(!$form->isValid()) {
|
||||
throw new Exception($self->field()->l('field.sortable.add.error.template'));
|
||||
}
|
||||
|
||||
$data = $form->serialize();
|
||||
$template = $data['template'];
|
||||
|
||||
$page = $parent->children()->create($self->uid($template), $template, array(
|
||||
'title' => i18n($parent->blueprint()->pages()->template()->findBy('name', $template)->title())
|
||||
));
|
||||
|
||||
$self->update($self->field()->entries()->pluck('uid'));
|
||||
$self->notify(':)');
|
||||
$self->redirect($self->model());
|
||||
// $this->redirect($page, 'edit');
|
||||
|
||||
} catch(Exception $e) {
|
||||
$form->alert($e->getMessage());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return $this->modal('add', compact('form'));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
28
site/OFF_plugins/sortable/sortable/actions/add/forms/add.php
Normal file
28
site/OFF_plugins/sortable/sortable/actions/add/forms/add.php
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
return function($page, $model, $field) {
|
||||
|
||||
$options = [];
|
||||
|
||||
foreach($page->blueprint()->pages()->template() as $template) {
|
||||
$options[$template->name()] = $template->title();
|
||||
}
|
||||
|
||||
$form = new Kirby\Panel\Form(array(
|
||||
'template' => array(
|
||||
'label' => $field->l('field.sortable.add.template.label'),
|
||||
'type' => 'select',
|
||||
'options' => $options,
|
||||
'default' => key($options),
|
||||
'required' => true,
|
||||
'readonly' => count($options) == 1 ? true : false,
|
||||
'icon' => count($options) == 1 ? $page->blueprint()->pages()->template()->first()->icon() : 'chevron-down',
|
||||
)
|
||||
));
|
||||
|
||||
$form->cancel($model);
|
||||
$form->buttons->submit->val($field->l('field.sortable.add'));
|
||||
|
||||
return $form;
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<div class="modal-content modal-content-small">
|
||||
<?php echo $form ?>
|
||||
</div>
|
||||
92
site/OFF_plugins/sortable/sortable/actions/base/base.php
Normal file
92
site/OFF_plugins/sortable/sortable/actions/base/base.php
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
class BaseAction {
|
||||
|
||||
public $type = null;
|
||||
public $icon = null;
|
||||
public $label = null;
|
||||
public $title = null;
|
||||
public $class = 'sortable-layout__action';
|
||||
public $disabled = false;
|
||||
|
||||
public function root() {
|
||||
$obj = new ReflectionClass($this);
|
||||
return dirname($obj->getFileName());
|
||||
}
|
||||
|
||||
public function __construct($type) {
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function __call($method, $arguments) {
|
||||
return isset($this->$method) ? $this->$method : null;
|
||||
}
|
||||
|
||||
public function type() {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function url() {
|
||||
return $this->field()->url($this->type);
|
||||
}
|
||||
|
||||
public function i18n($value) {
|
||||
|
||||
if(is_array($value)) {
|
||||
return i18n($value);
|
||||
}
|
||||
|
||||
return $this->field()->l($value);
|
||||
|
||||
}
|
||||
|
||||
public function l($key, $variant = null) {
|
||||
return $this->field()->l($key, $variant);
|
||||
}
|
||||
|
||||
public function icon($position = null) {
|
||||
if(!$this->icon) return null;
|
||||
return icon($this->icon, $position);
|
||||
}
|
||||
|
||||
public function label() {
|
||||
if(!$this->label) return null;
|
||||
return $this->i18n($this->label);
|
||||
}
|
||||
|
||||
public function title() {
|
||||
if(!$this->title) return null;
|
||||
return $this->i18n($this->title);
|
||||
}
|
||||
|
||||
public function content() {
|
||||
|
||||
$a = new Brick('a');
|
||||
|
||||
$a->addClass($this->class());
|
||||
$a->attr('title', $this->title());
|
||||
$a->attr('href', $this->url());
|
||||
|
||||
if($this->disabled()) {
|
||||
$a->addClass('is-disabled');
|
||||
}
|
||||
|
||||
if($label = $this->label()) {
|
||||
$a->append($this->icon('left') . $label);
|
||||
} else {
|
||||
$a->append($this->icon());
|
||||
}
|
||||
|
||||
return $a;
|
||||
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
try {
|
||||
return (string)$this->content();
|
||||
} catch(Exception $e) {
|
||||
return (string)$e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
class CopyActionController extends LukasKleinschmidt\Sortable\Controllers\Action {
|
||||
|
||||
/**
|
||||
* Save to clipboard
|
||||
*/
|
||||
public function save() {
|
||||
|
||||
$self = $this;
|
||||
$page = $this->field()->origin();
|
||||
$entries = $this->field()->entries();
|
||||
|
||||
$form = $this->form('copy', array($page, $entries, $this->model(), $this->field()), function($form) use($page, $self) {
|
||||
|
||||
try {
|
||||
|
||||
$form->validate();
|
||||
|
||||
if(!$form->isValid()) {
|
||||
throw new Exception($self->field()->l('field.sortable.copy.error.uri'));
|
||||
}
|
||||
|
||||
$data = $form->serialize();
|
||||
|
||||
site()->user()->update(array(
|
||||
'clipboard' => str::split($data['uri']),
|
||||
));
|
||||
|
||||
$self->notify(':)');
|
||||
$self->redirect($this->model());
|
||||
|
||||
} catch(Exception $e) {
|
||||
$form->alert($e->getMessage());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return $this->modal('copy', compact('form'));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
29
site/OFF_plugins/sortable/sortable/actions/copy/copy.php
Normal file
29
site/OFF_plugins/sortable/sortable/actions/copy/copy.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
class CopyAction extends BaseAction {
|
||||
|
||||
public $icon = 'copy';
|
||||
public $class = 'sortable__action sortable__action--copy';
|
||||
public $label = 'field.sortable.copy';
|
||||
|
||||
public function routes() {
|
||||
return array(
|
||||
array(
|
||||
'pattern' => '/',
|
||||
'method' => 'POST|GET',
|
||||
'action' => 'save',
|
||||
'filter' => 'auth',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function content() {
|
||||
|
||||
$content = parent::content();
|
||||
$content->data('modal', true);
|
||||
|
||||
return $content;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
return function($page, $entries, $model, $field) {
|
||||
|
||||
if($entries->count()) {
|
||||
|
||||
$options = [];
|
||||
|
||||
foreach($entries as $entry) {
|
||||
$options[$entry->uri()] = array(
|
||||
'label' => $entry->title(),
|
||||
'checked' => true,
|
||||
'readonly' => false,
|
||||
);
|
||||
}
|
||||
|
||||
$form = new Kirby\Panel\Form(array(
|
||||
'uri' => array(
|
||||
'label' => $field->l('field.sortable.copy.uri.label'),
|
||||
'type' => 'options',
|
||||
'columns' => 1,
|
||||
'required' => true,
|
||||
'options' => $options,
|
||||
)
|
||||
));
|
||||
|
||||
} else {
|
||||
|
||||
$form = new Kirby\Panel\Form(array(
|
||||
'info' => array(
|
||||
'label' => $field->l('field.sortable.copy.info.label'),
|
||||
'type' => 'info',
|
||||
'text' => $field->l('field.sortable.copy.info.text')
|
||||
)
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
$form->cancel($model);
|
||||
$form->buttons->submit->val($field->l('field.sortable.copy'));
|
||||
|
||||
if(!$entries->count()) {
|
||||
$form->buttons->submit = $form->buttons->cancel;
|
||||
$form->style('centered');
|
||||
}
|
||||
|
||||
return $form;
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<div class="modal-content modal-content-small">
|
||||
<?php echo $form; ?>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
class DeleteActionController extends LukasKleinschmidt\Sortable\Controllers\Action {
|
||||
|
||||
/**
|
||||
* Delete a entry
|
||||
*
|
||||
* @param string $uid
|
||||
*/
|
||||
public function delete($uid) {
|
||||
|
||||
$self = $this;
|
||||
$page = $this->field()->entries()->find($uid);
|
||||
|
||||
if($page->ui()->delete() === false) {
|
||||
throw new Kirby\Panel\Exceptions\PermissionsException();
|
||||
}
|
||||
|
||||
$form = $this->form('delete', array($page, $this->model(), $this->field()), function($form) use($page, $self) {
|
||||
|
||||
try {
|
||||
|
||||
$page->delete();
|
||||
$self->update($self->field()->entries()->not($page)->pluck('uid'));
|
||||
$self->notify(':)');
|
||||
$self->redirect($self->model());
|
||||
|
||||
} catch(Exception $e) {
|
||||
$form->alert($e->getMessage());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return $this->modal('delete', compact('form'));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
34
site/OFF_plugins/sortable/sortable/actions/delete/delete.php
Normal file
34
site/OFF_plugins/sortable/sortable/actions/delete/delete.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
class DeleteAction extends BaseAction {
|
||||
|
||||
public $icon = 'trash-o';
|
||||
public $title = 'field.sortable.delete';
|
||||
|
||||
public function routes() {
|
||||
return array(
|
||||
array(
|
||||
'pattern' => '(:any)',
|
||||
'method' => 'POST|GET',
|
||||
'action' => 'delete',
|
||||
'filter' => 'auth',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function content() {
|
||||
|
||||
$content = parent::content();
|
||||
$content->attr('href', $this->url() . '/' . $this->page()->uid());
|
||||
$content->data('modal', true);
|
||||
|
||||
return $content;
|
||||
|
||||
}
|
||||
|
||||
public function disabled() {
|
||||
$page = $this->page();
|
||||
return $this->disabled || $page->blueprint()->options()->delete() === false || $page->ui()->delete() === false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
return function($page, $model, $field) {
|
||||
|
||||
$form = new Kirby\Panel\Form(array(
|
||||
'page' => array(
|
||||
'label' => $field->l('field.sortable.delete.page.label'),
|
||||
'type' => 'text',
|
||||
'readonly' => true,
|
||||
'default' => $page->title(),
|
||||
'help' => $page->id(),
|
||||
)
|
||||
));
|
||||
|
||||
$form->cancel($model);
|
||||
$form->style('delete');
|
||||
|
||||
return $form;
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<div class="modal-content">
|
||||
<?php echo $form ?>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
class DuplicateActionController extends LukasKleinschmidt\Sortable\Controllers\Action {
|
||||
|
||||
/**
|
||||
* Duplicate a entry
|
||||
*
|
||||
* @param string $uid
|
||||
* @param int $to
|
||||
*/
|
||||
public function duplicate($uid, $to) {
|
||||
|
||||
$entries = $this->field()->entries();
|
||||
$parent = $this->field()->origin();
|
||||
$page = $entries->find($uid);
|
||||
|
||||
if($parent->ui()->create() === false) {
|
||||
throw new Kirby\Panel\Exceptions\PermissionsException();
|
||||
}
|
||||
|
||||
$page = $this->copy($page, $parent);
|
||||
|
||||
$entries->add($page->uid());
|
||||
$this->sort($page->uid(), $to);
|
||||
$this->notify(':)');
|
||||
$this->redirect($this->model());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
class DuplicateAction extends BaseAction {
|
||||
|
||||
public $icon = 'clone';
|
||||
public $title = 'field.sortable.duplicate';
|
||||
|
||||
public function routes() {
|
||||
return array(
|
||||
array(
|
||||
'pattern' => '(:any)/(:any)',
|
||||
'method' => 'POST|GET',
|
||||
'action' => 'duplicate',
|
||||
'filter' => 'auth',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function content() {
|
||||
|
||||
$content = parent::content();
|
||||
$content->attr('href', $this->url() . '/' . $this->page()->uid() . '/' . ($this->layout()->num() + 1));
|
||||
$content->data('action', true);
|
||||
|
||||
return $content;
|
||||
|
||||
}
|
||||
|
||||
public function disabled() {
|
||||
return $this->disabled || $this->field()->origin()->ui()->create() === false;
|
||||
}
|
||||
|
||||
}
|
||||
21
site/OFF_plugins/sortable/sortable/actions/edit/edit.php
Normal file
21
site/OFF_plugins/sortable/sortable/actions/edit/edit.php
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
class EditAction extends BaseAction {
|
||||
|
||||
public $icon = 'pencil';
|
||||
public $title = 'field.sortable.edit';
|
||||
|
||||
public function content() {
|
||||
|
||||
$content = parent::content();
|
||||
$content->attr('href', $this->page()->url('edit'));
|
||||
|
||||
return $content;
|
||||
|
||||
}
|
||||
|
||||
public function disabled() {
|
||||
return $this->disabled || $this->page()->ui()->read() === false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
class PasteActionController extends LukasKleinschmidt\Sortable\Controllers\Action {
|
||||
|
||||
/**
|
||||
* Add from clipboard
|
||||
*/
|
||||
public function paste() {
|
||||
|
||||
$self = $this;
|
||||
$parent = $this->field()->origin();
|
||||
$entries = site()->user()->clipboard();
|
||||
|
||||
if(empty($entries)) {
|
||||
$entries = array();
|
||||
}
|
||||
|
||||
$entries = pages($entries);
|
||||
|
||||
if($parent->ui()->create() === false) {
|
||||
throw new Kirby\Panel\Exceptions\PermissionsException();
|
||||
}
|
||||
|
||||
$form = $this->form('paste', array($parent, $entries, $this->model(), $this->field()), function($form) use($parent, $self) {
|
||||
|
||||
try {
|
||||
|
||||
$form->validate();
|
||||
|
||||
if(!$form->isValid()) {
|
||||
throw new Exception($self->field()->l('field.sortable.paste.error.uri'));
|
||||
}
|
||||
|
||||
$data = $form->serialize();
|
||||
|
||||
$templates = $parent->blueprint()->pages()->template()->pluck('name');
|
||||
$entries = $self->field()->entries();
|
||||
$to = $entries->count();
|
||||
|
||||
foreach(pages(str::split($data['uri'], ',')) as $page) {
|
||||
|
||||
if(!in_array($page->intendedTemplate(), $templates)) continue;
|
||||
|
||||
// Reset previously triggered hooks
|
||||
kirby()::$triggered = array();
|
||||
|
||||
$page = $self->copy($page, $parent);
|
||||
|
||||
$entries->add($page->uid());
|
||||
$self->sort($page->uid(), ++$to);
|
||||
|
||||
}
|
||||
|
||||
$self->notify(':)');
|
||||
$self->redirect($self->model());
|
||||
|
||||
} catch(Exception $e) {
|
||||
$form->alert($e->getMessage());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return $this->modal('paste', compact('form'));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
return function($page, $entries, $model, $field) {
|
||||
|
||||
if($entries->count()) {
|
||||
|
||||
$templates = $page->blueprint()->pages()->template();
|
||||
$options = [];
|
||||
$help = false;
|
||||
|
||||
foreach($entries as $entry) {
|
||||
$template = $entry->intendedTemplate();
|
||||
$value = $entry->uri();
|
||||
|
||||
$options[$value] = array(
|
||||
// 'label' => icon($templates->findBy('name', $template)->icon(), 'left') . ' ' . $entry->title(),
|
||||
'label' => $entry->title(),
|
||||
'checked' => true,
|
||||
'readonly' => false,
|
||||
);
|
||||
|
||||
if(v::notIn($template, $templates->pluck('name'))) {
|
||||
$options[$value]['checked'] = false;
|
||||
$options[$value]['readonly'] = true;
|
||||
|
||||
$help = true;
|
||||
}
|
||||
}
|
||||
|
||||
$form = new Kirby\Panel\Form(array(
|
||||
'uri' => array(
|
||||
'label' => $field->l('field.sortable.paste.uri.label'),
|
||||
'type' => 'options',
|
||||
'columns' => 1,
|
||||
'required' => true,
|
||||
'options' => $options,
|
||||
'help' => $help ? $field->l('field.sortable.paste.uri.help') : '',
|
||||
)
|
||||
));
|
||||
|
||||
} else {
|
||||
|
||||
$form = new Kirby\Panel\Form(array(
|
||||
'info' => array(
|
||||
'label' => $field->l('field.sortable.paste.info.label'),
|
||||
'type' => 'info',
|
||||
'text' => $field->l('field.sortable.paste.info.text')
|
||||
)
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
$form->cancel($model);
|
||||
$form->buttons->submit->val($field->l('field.sortable.paste'));
|
||||
|
||||
if(!$entries->count()) {
|
||||
$form->buttons->submit = $form->buttons->cancel;
|
||||
$form->style('centered');
|
||||
}
|
||||
|
||||
return $form;
|
||||
|
||||
};
|
||||
33
site/OFF_plugins/sortable/sortable/actions/paste/paste.php
Normal file
33
site/OFF_plugins/sortable/sortable/actions/paste/paste.php
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
class PasteAction extends BaseAction {
|
||||
|
||||
public $icon = 'paste';
|
||||
public $class = 'sortable__action sortable__action--paste';
|
||||
public $label = 'field.sortable.paste';
|
||||
|
||||
public function routes() {
|
||||
return array(
|
||||
array(
|
||||
'pattern' => '/',
|
||||
'method' => 'POST|GET',
|
||||
'action' => 'paste',
|
||||
'filter' => 'auth',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function content() {
|
||||
|
||||
$content = parent::content();
|
||||
$content->data('modal', true);
|
||||
|
||||
return $content;
|
||||
|
||||
}
|
||||
|
||||
public function disabled() {
|
||||
return $this->disabled || $this->parent()->ui()->create() === false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
<div class="modal-content modal-content-small">
|
||||
<?php echo $form; ?>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
use Kirby\Panel\Exceptions\PermissionsException;
|
||||
|
||||
class ToggleActionController extends LukasKleinschmidt\Sortable\Controllers\Action {
|
||||
|
||||
/**
|
||||
* Show page
|
||||
*
|
||||
* @param string $uid
|
||||
* @param int $to
|
||||
*/
|
||||
public function show($uid, $to) {
|
||||
|
||||
$entries = $this->field()->entries();
|
||||
$page = $entries->find($uid);
|
||||
|
||||
if($page->ui()->visibility() === false) {
|
||||
throw new PermissionsException();
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// Check template specific limit
|
||||
$count = $entries->filterBy('template', $page->intendedTemplate())->published()->count();
|
||||
$limit = $this->field()->options($page)->limit();
|
||||
|
||||
if($limit && $count >= $limit) {
|
||||
throw new Exception($this->field()->l('field.sortable.limit.template'));
|
||||
}
|
||||
|
||||
// Check limit
|
||||
$count = $entries->published()->count();
|
||||
$limit = $this->field()->limit();
|
||||
|
||||
if($limit && $count >= $limit) {
|
||||
throw new Exception($this->field()->l('field.sortable.limit'));
|
||||
}
|
||||
|
||||
$page->sort($to);
|
||||
$this->notify(':)');
|
||||
|
||||
} catch(Exception $e) {
|
||||
$this->alert($e->getMessage());
|
||||
}
|
||||
|
||||
$this->redirect($this->model());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide page
|
||||
*
|
||||
* @param string $uid
|
||||
*/
|
||||
public function hide($uid) {
|
||||
|
||||
$page = $this->field()->entries()->find($uid);
|
||||
|
||||
if($page->ui()->visibility() === false) {
|
||||
throw new PermissionsException();
|
||||
}
|
||||
|
||||
try {
|
||||
$page->hide();
|
||||
$this->notify(':)');
|
||||
} catch(Exception $e) {
|
||||
$this->alert($e->getMessage());
|
||||
}
|
||||
|
||||
$this->redirect($this->model());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
66
site/OFF_plugins/sortable/sortable/actions/toggle/toggle.php
Normal file
66
site/OFF_plugins/sortable/sortable/actions/toggle/toggle.php
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
class ToggleAction extends BaseAction {
|
||||
|
||||
public $status;
|
||||
public $icon = array(
|
||||
'hide' => 'toggle-on',
|
||||
'show' => 'toggle-off',
|
||||
);
|
||||
public $title = array(
|
||||
'hide' => 'field.sortable.hide',
|
||||
'show' => 'field.sortable.show',
|
||||
);
|
||||
|
||||
public function routes() {
|
||||
return array(
|
||||
array(
|
||||
'pattern' => 'show/(:any)/(:any)',
|
||||
'method' => 'POST|GET',
|
||||
'action' => 'show',
|
||||
'filter' => 'auth',
|
||||
),
|
||||
array(
|
||||
'pattern' => 'hide/(:any)',
|
||||
'method' => 'POST|GET',
|
||||
'action' => 'hide',
|
||||
'filter' => 'auth',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function status() {
|
||||
if($this->status) return $this->status;
|
||||
return $this->status = $this->page()->isVisible() ? 'hide' : 'show';
|
||||
}
|
||||
|
||||
public function title() {
|
||||
$title = a::get($this->title, $this->status());
|
||||
return $this->i18n($title);
|
||||
}
|
||||
|
||||
public function icon($position = null) {
|
||||
if(empty($this->icon)) return null;
|
||||
$icon = a::get($this->icon, $this->status());
|
||||
return icon($icon, $position);
|
||||
}
|
||||
|
||||
public function content() {
|
||||
|
||||
$content = parent::content();
|
||||
$content->data('action', true);
|
||||
$content->attr('href', $this->url() . '/' . $this->status() . '/' . $this->page()->uid());
|
||||
|
||||
if($this->status() == 'show') {
|
||||
$content->attr('href', $content->attr('href') . '/' . ($this->layout()->numVisible() + 1));
|
||||
}
|
||||
|
||||
return $content;
|
||||
|
||||
}
|
||||
|
||||
public function disabled() {
|
||||
return $this->disabled || $this->page()->ui()->visibility() === false;
|
||||
}
|
||||
|
||||
}
|
||||
24
site/OFF_plugins/sortable/sortable/bootstrap.php
Normal file
24
site/OFF_plugins/sortable/sortable/bootstrap.php
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
load([
|
||||
|
||||
// main class
|
||||
'lukaskleinschmidt\\sortable\\sortable' => 'sortable.php',
|
||||
|
||||
// global stuff
|
||||
'lukaskleinschmidt\\sortable\\registry' => 'sortable' . DS . 'registry.php',
|
||||
'lukaskleinschmidt\\sortable\\roots' => 'sortable' . DS . 'roots.php',
|
||||
|
||||
// controllers
|
||||
'lukaskleinschmidt\\sortable\\controllers\\field' => 'sortable' . DS . 'controllers' . DS . 'field.php',
|
||||
'lukaskleinschmidt\\sortable\\controllers\\action' => 'sortable' . DS . 'controllers' . DS . 'action.php',
|
||||
|
||||
], __DIR__ . DS . 'src' );
|
||||
|
||||
class_alias('LukasKleinschmidt\\Sortable\\Sortable', 'LukasKleinschmidt\\Sortable');
|
||||
|
||||
// TEMP: Added for convenience because those two classes and namespaces were used in v2.3.1 and below
|
||||
class_alias('LukasKleinschmidt\\Sortable\\Controllers\\Field', 'Kirby\\Sortable\\Controllers\\Field');
|
||||
class_alias('LukasKleinschmidt\\Sortable\\Controllers\\Action', 'Kirby\\Sortable\\Controllers\\Action');
|
||||
|
||||
include(__DIR__ . DS . 'helpers.php');
|
||||
5
site/OFF_plugins/sortable/sortable/helpers.php
Normal file
5
site/OFF_plugins/sortable/sortable/helpers.php
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
function sortable() {
|
||||
return LukasKleinschmidt\Sortable::instance();
|
||||
}
|
||||
113
site/OFF_plugins/sortable/sortable/layouts/base/base.php
Normal file
113
site/OFF_plugins/sortable/sortable/layouts/base/base.php
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
class BaseLayout {
|
||||
|
||||
public $type;
|
||||
|
||||
public function root() {
|
||||
$obj = new ReflectionClass($this);
|
||||
return dirname($obj->getFileName());
|
||||
}
|
||||
|
||||
public function __construct($type) {
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function __call($method, $arguments) {
|
||||
return isset($this->$method) ? $this->$method : null;
|
||||
}
|
||||
|
||||
public function type() {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function input() {
|
||||
return $this->field()->input($this->page()->uid());
|
||||
}
|
||||
|
||||
public function counter() {
|
||||
|
||||
$page = $this->page();
|
||||
|
||||
if(!$page->isVisible() || !$this->limit()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$entries = $this->field()->entries()->filterBy('template', $page->intendedTemplate());
|
||||
$index = $entries->published()->indexOf($page) + 1;
|
||||
$limit = $this->limit();
|
||||
|
||||
$counter = new Brick('span');
|
||||
$counter->addClass('sortable-layout__counter');
|
||||
$counter->html('( ' . $index . ' / ' . $limit . ' )');
|
||||
|
||||
return $counter;
|
||||
|
||||
}
|
||||
|
||||
public function l($key, $variant = null) {
|
||||
return $this->field()->l($key, $variant);
|
||||
}
|
||||
|
||||
public function icon($position = '') {
|
||||
return $this->page()->icon($position);
|
||||
}
|
||||
|
||||
public function featured($position = '') {
|
||||
return $this->page()->featured();
|
||||
}
|
||||
|
||||
public function blueprint() {
|
||||
return $this->page()->blueprint();
|
||||
}
|
||||
|
||||
public function title() {
|
||||
return $this->page()->title();
|
||||
}
|
||||
|
||||
public function action($type, $data = array()) {
|
||||
|
||||
$data = a::update($data, array(
|
||||
'layout' => $this,
|
||||
'page' => $this->page(),
|
||||
));
|
||||
|
||||
return $this->field()->action($type, $data);
|
||||
|
||||
}
|
||||
|
||||
public function content() {
|
||||
|
||||
$template = $this->root() . DS . 'template.php';
|
||||
|
||||
if(!is_file($template)) {
|
||||
$template = __DIR__ . DS . 'template.php';
|
||||
}
|
||||
|
||||
return tpl::load($template, ['layout' => $this], true);
|
||||
|
||||
}
|
||||
|
||||
public function template() {
|
||||
|
||||
$template = new Brick('div');
|
||||
$template->addClass('sortable__layout');
|
||||
$template->addClass('sortable__grid');
|
||||
$template->attr('data-uid', $this->page()->uid());
|
||||
$template->attr('data-visible', $this->page()->isVisible() ? 'true' : 'false');
|
||||
$template->append($this->content());
|
||||
$template->append($this->input());
|
||||
|
||||
return $template;
|
||||
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
try {
|
||||
return (string)$this->template();
|
||||
} catch(Exception $e) {
|
||||
return (string)$e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
17
site/OFF_plugins/sortable/sortable/layouts/base/template.php
Normal file
17
site/OFF_plugins/sortable/sortable/layouts/base/template.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<div class="sortable-layout">
|
||||
<nav class="sortable-layout__navigation" >
|
||||
<div class="sortable-layout__icon" title="<?= l('pages.show.template') . ': ' . i18n($layout->blueprint()->title()); ?>" data-handle>
|
||||
<?php if($layout->featured()->isNotEmpty()): ?>
|
||||
<img src="<?= $layout->featured()->toFile()->thumb(array('width'=>400))->url(); ?>" alt="" width="100%">
|
||||
<?php endif ?>
|
||||
<div class="sortable-layout__title" title="<?= $layout->title(); ?>" data-handle>
|
||||
<?= $layout->title(); ?>
|
||||
<?= $layout->counter(); ?>
|
||||
</div>
|
||||
<?= $layout->action('edit'); ?>
|
||||
<?= $layout->action('toggle'); ?>
|
||||
</div>
|
||||
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
49
site/OFF_plugins/sortable/sortable/layouts/module/module.php
Normal file
49
site/OFF_plugins/sortable/sortable/layouts/module/module.php
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
class ModuleLayout extends BaseLayout {
|
||||
|
||||
public $edit = true;
|
||||
public $limit = false;
|
||||
public $toggle = true;
|
||||
public $delete = true;
|
||||
public $preview = true;
|
||||
public $duplicate = true;
|
||||
|
||||
public function preview() {
|
||||
|
||||
$page = $this->page();
|
||||
|
||||
if(!$preview = $this->preview) {
|
||||
return;
|
||||
}
|
||||
|
||||
$entry = Kirby\Modules\Modules::instance()->get($page);
|
||||
$template = $entry->path() . DS . $entry->name() . '.preview.php';
|
||||
|
||||
if(!is_file($template)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$position = $preview === true ? 'top' : $preview;
|
||||
|
||||
$preview = new Brick('div');
|
||||
$preview->addClass('modules-layout__preview modules-layout__preview--' . $position);
|
||||
$preview->data('module', $entry->name());
|
||||
$preview->data('handle', true);
|
||||
$preview->html(tpl::load($template, array('page' => $this->origin(), 'module' => $page, 'moduleName' => $entry->name())));
|
||||
|
||||
return $preview;
|
||||
|
||||
}
|
||||
|
||||
public function action($type, $data = array()) {
|
||||
|
||||
$data = a::update($data, array(
|
||||
'disabled' => $this->$type() === false
|
||||
));
|
||||
|
||||
return parent::action($type, $data);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<div class="sortable-layout">
|
||||
<?php if($layout->preview === true || $layout->preview === 'top') echo $layout->preview(); ?>
|
||||
<nav class="sortable-layout__navigation">
|
||||
<div class="sortable-layout__icon" title="<?= l('pages.show.template') . ': ' . i18n($layout->blueprint()->title()); ?>" data-handle>
|
||||
<?= $layout->icon(); ?>
|
||||
</div>
|
||||
<div class="sortable-layout__title" title="<?= $layout->title(); ?>" data-handle>
|
||||
<?= $layout->title(); ?>
|
||||
<?= $layout->counter(); ?>
|
||||
</div>
|
||||
<?php foreach($layout->field()->actions() as $action): ?>
|
||||
<?= $layout->action($action); ?>
|
||||
<?php endforeach; ?>
|
||||
</nav>
|
||||
<?php if($layout->preview === 'bottom') echo $layout->preview(); ?>
|
||||
</div>
|
||||
154
site/OFF_plugins/sortable/sortable/src/sortable.php
Normal file
154
site/OFF_plugins/sortable/sortable/src/sortable.php
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
<?php
|
||||
|
||||
namespace LukasKleinschmidt\Sortable;
|
||||
|
||||
use A;
|
||||
use F;
|
||||
use L;
|
||||
use Dir;
|
||||
use Str;
|
||||
use Data;
|
||||
use Exception;
|
||||
|
||||
class Sortable {
|
||||
|
||||
static public $instance;
|
||||
|
||||
public $kirby;
|
||||
public $roots;
|
||||
public $registry;
|
||||
public $variants;
|
||||
|
||||
public function __construct() {
|
||||
|
||||
$this->kirby = kirby();
|
||||
|
||||
$this->roots = new Roots(dirname(__DIR__));
|
||||
$this->registry = new Registry($this->kirby());
|
||||
|
||||
}
|
||||
|
||||
public static function instance() {
|
||||
if(!is_null(static::$instance)) return static::$instance;
|
||||
return static::$instance = new static();
|
||||
}
|
||||
|
||||
public static function layout($type, $data = array()) {
|
||||
|
||||
$class = $type . 'layout';
|
||||
|
||||
if(!class_exists($class)) {
|
||||
throw new Exception('The ' . $type . ' layout is missing.');
|
||||
}
|
||||
|
||||
$layout = new $class($type);
|
||||
|
||||
foreach($data as $key => $val) {
|
||||
if(!is_string($key) || str::length($key) === 0) continue;
|
||||
$layout->{$key} = $val;
|
||||
}
|
||||
|
||||
return $layout;
|
||||
|
||||
}
|
||||
|
||||
public static function action($type, $data = array()) {
|
||||
|
||||
$class = $type . 'action';
|
||||
|
||||
if(!class_exists($class)) {
|
||||
throw new Exception('The ' . $type . ' action is missing.');
|
||||
}
|
||||
|
||||
$action = new $class($type);
|
||||
|
||||
foreach($data as $key => $val) {
|
||||
if(!is_string($key) || str::length($key) === 0) continue;
|
||||
$action->{$key} = $val;
|
||||
}
|
||||
|
||||
return $action;
|
||||
|
||||
}
|
||||
|
||||
public function translation($key, $variant = null) {
|
||||
|
||||
// IDEA: outsource into own class
|
||||
// $variants = $this->variants();
|
||||
// return $variants->get($key, $variant, l::get($key));
|
||||
|
||||
if(!is_null($variant) && $variant = a::get($this->variants, $variant)) {
|
||||
return a::get($variant, $key, l::get($key, $key));
|
||||
}
|
||||
|
||||
return l::get($key, $key);
|
||||
|
||||
}
|
||||
|
||||
public function register() {
|
||||
|
||||
foreach(dir::read($this->roots()->translations()) as $name) {
|
||||
$this->set('translation', f::name($name), $this->roots()->translations() . DS . $name);
|
||||
}
|
||||
|
||||
foreach(dir::read($this->roots()->variants()) as $name) {
|
||||
$this->set('variant', $name, $this->roots()->variants() . DS . $name);
|
||||
}
|
||||
|
||||
foreach(dir::read($this->roots()->layouts()) as $name) {
|
||||
$this->set('layout', $name, $this->roots()->layouts() . DS . $name);
|
||||
}
|
||||
|
||||
foreach(dir::read($this->roots()->actions()) as $name) {
|
||||
$this->set('action', $name, $this->roots()->actions() . DS . $name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function load() {
|
||||
|
||||
$code = panel()->translation()->code();
|
||||
|
||||
if(!$path = $this->get('translation', $code)) {
|
||||
$path = $this->get('translation', 'en');
|
||||
}
|
||||
|
||||
l::set(data::read($path));
|
||||
|
||||
if($variants = $this->get('variant', $code)) {
|
||||
foreach($variants as $name => $path) {
|
||||
$this->variants[$name] = data::read($path);
|
||||
}
|
||||
}
|
||||
|
||||
$classes = [];
|
||||
|
||||
foreach($this->get('layout') as $name => $layout) {
|
||||
$classes[$layout->class()] = $layout->file();
|
||||
}
|
||||
|
||||
foreach($this->get('action') as $name => $action) {
|
||||
$classes[$action->class()] = $action->file();
|
||||
}
|
||||
|
||||
load($classes);
|
||||
|
||||
}
|
||||
|
||||
public function kirby() {
|
||||
return $this->kirby;
|
||||
}
|
||||
|
||||
public function roots() {
|
||||
return $this->roots;
|
||||
}
|
||||
|
||||
public function set() {
|
||||
return call_user_func_array([$this->registry, 'set'], func_get_args());
|
||||
}
|
||||
|
||||
public function get() {
|
||||
return call_user_func_array([$this->registry, 'get'], func_get_args());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace LukasKleinschmidt\Sortable\Controllers;
|
||||
|
||||
use Kirby\Panel\View;
|
||||
use Kirby\Panel\Snippet;
|
||||
|
||||
class Action extends Field {
|
||||
|
||||
public function __construct($model, $field, $action) {
|
||||
|
||||
$this->model = $model;
|
||||
$this->field = $field;
|
||||
$this->action = $action;
|
||||
|
||||
}
|
||||
|
||||
public function form($id, $data = array(), $submit = null) {
|
||||
$file = $this->action->root() . DS . 'forms' . DS . $id . '.php';
|
||||
return panel()->form($file, $data, $submit);
|
||||
}
|
||||
|
||||
public function view($file, $data = array()) {
|
||||
|
||||
$view = new View($file, $data);
|
||||
$root = $this->action->root() . DS . 'views';
|
||||
|
||||
if(file_exists($root . DS . $file . '.php')) {
|
||||
$view->_root = $root;
|
||||
}
|
||||
|
||||
return $view;
|
||||
|
||||
}
|
||||
|
||||
public function snippet($file, $data = array()) {
|
||||
|
||||
$snippet = new Snippet($file, $data);
|
||||
$root = $this->action->root() . DS . 'snippets';
|
||||
|
||||
if(file_exists($root . DS . $file . '.php')) {
|
||||
$snippet->_root = $root;
|
||||
}
|
||||
|
||||
return $snippet;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
<?php
|
||||
|
||||
namespace LukasKleinschmidt\Sortable\Controllers;
|
||||
|
||||
use Str;
|
||||
use Dir;
|
||||
use Router;
|
||||
use Children;
|
||||
use Kirby\Panel\Event;
|
||||
use Kirby\Panel\Models\Page\Blueprint;
|
||||
use Kirby\Panel\Exceptions\PermissionsException;
|
||||
use LukasKleinschmidt\Sortable;
|
||||
|
||||
class Field extends \Kirby\Panel\Controllers\Field {
|
||||
|
||||
/**
|
||||
* Initiates a action controller
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $path
|
||||
* @return mixed
|
||||
*/
|
||||
public function forAction($type, $path = '') {
|
||||
|
||||
$model = $this->model();
|
||||
$field = $this->field();
|
||||
|
||||
$action = sortable::action($type);
|
||||
$routes = $action->routes();
|
||||
$router = new Router($routes);
|
||||
|
||||
if($route = $router->run($path)) {
|
||||
if(is_callable($route->action()) && is_a($route->action(), 'Closure')) {
|
||||
return call($route->action(), $route->arguments());
|
||||
} else {
|
||||
|
||||
$controllerFile = $action->root() . DS . 'controller.php';
|
||||
$controllerName = $type . 'ActionController';
|
||||
|
||||
if(!file_exists($controllerFile)) {
|
||||
throw new Exception('The action controller file is missing');
|
||||
}
|
||||
|
||||
require_once($controllerFile);
|
||||
|
||||
if(!class_exists($controllerName)) {
|
||||
throw new Exception('The action controller class is missing');
|
||||
}
|
||||
|
||||
$controller = new $controllerName($model, $field, $action);
|
||||
|
||||
return call(array($controller, $route->action()), $route->arguments());
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new Exception('Invalid action route');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update field value and sort number
|
||||
*
|
||||
* @param string $uid
|
||||
* @param int $to
|
||||
*/
|
||||
public function sort($uid, $to) {
|
||||
|
||||
try {
|
||||
$entries = $this->field()->entries();
|
||||
$value = $entries->not($uid)->pluck('uid');
|
||||
|
||||
// Order entries value
|
||||
array_splice($value, $to - 1, 0, $uid);
|
||||
|
||||
if($entries->find($uid)->ui()->visibility() === false) {
|
||||
throw new PermissionsException();
|
||||
}
|
||||
|
||||
// Update field value
|
||||
$this->update($value);
|
||||
} catch(Exception $e) {
|
||||
$this->alert($e->getMessage());
|
||||
}
|
||||
|
||||
// Get current page
|
||||
$page = $entries->find($uid);
|
||||
|
||||
// Figure out the correct sort num
|
||||
if($page && $page->isVisible()) {
|
||||
$collection = new Children($page->parent());
|
||||
|
||||
foreach(array_slice($value, 0, $to - 1) as $id) {
|
||||
if($entry = $entries->find($id)) {
|
||||
$collection->data[$entry->id()] = $entry;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Sort the page
|
||||
$page->sort($collection->published()->count() + 1);
|
||||
} catch(Exception $e) {
|
||||
$this->alert($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a page to a new location
|
||||
*
|
||||
* @param object $page
|
||||
* @param object $to
|
||||
* @return object
|
||||
*/
|
||||
public function copy($page, $to) {
|
||||
|
||||
$template = $page->intendedTempalte();
|
||||
$blueprint = new Blueprint($template);
|
||||
$parent = $to;
|
||||
$data = array();
|
||||
$uid = $this->uid($page);
|
||||
|
||||
foreach($blueprint->fields(null) as $key => $field) {
|
||||
$data[$key] = $field->default();
|
||||
}
|
||||
|
||||
$data = array_merge($data, $page->content()->toArray());
|
||||
$event = $parent->event('create:action', [
|
||||
'parent' => $parent,
|
||||
'template' => $template,
|
||||
'blueprint' => $blueprint,
|
||||
'uid' => $uid,
|
||||
'data' => $data
|
||||
]);
|
||||
|
||||
$event->check();
|
||||
|
||||
// Actually copy the page
|
||||
dir::copy($page->root(), $parent->root() . DS . $uid);
|
||||
|
||||
$page = $parent->children()->find($uid);
|
||||
|
||||
if(!$page) {
|
||||
throw new Exception(l('pages.add.error.create'));
|
||||
}
|
||||
|
||||
kirby()->trigger($event, $page);
|
||||
|
||||
return $page;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the field value
|
||||
*
|
||||
* @param array $value
|
||||
*/
|
||||
public function update($value) {
|
||||
|
||||
try {
|
||||
$this->model()->update(array(
|
||||
$this->field()->name() => implode(', ', $value)
|
||||
));
|
||||
} catch(Exception $e) {
|
||||
$this->alert($e->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create unique uid
|
||||
*
|
||||
* @param string $template
|
||||
* @return string
|
||||
*/
|
||||
public function uid($template) {
|
||||
|
||||
if(is_a($template, 'Page')) {
|
||||
$template = $template->intendedTemplate();
|
||||
}
|
||||
|
||||
$prefix = $this->field()->prefix();
|
||||
|
||||
if(strpos($template, $prefix) !== false) {
|
||||
$length = str::length($prefix);
|
||||
$template = str::substr($template, $length);
|
||||
}
|
||||
|
||||
// add a unique hash
|
||||
$checksum = sprintf('%u', crc32($template . microtime()));
|
||||
return $template . '-' . base_convert($checksum, 10, 36);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
48
site/OFF_plugins/sortable/sortable/src/sortable/registry.php
Normal file
48
site/OFF_plugins/sortable/sortable/src/sortable/registry.php
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace LukasKleinschmidt\Sortable;
|
||||
|
||||
// Kirby dependencies
|
||||
use Exception;
|
||||
use Kirby;
|
||||
|
||||
class Registry extends Kirby\Registry {
|
||||
|
||||
/**
|
||||
* @param Kirby $kirby
|
||||
*/
|
||||
public function __construct(Kirby $kirby) {
|
||||
|
||||
$this->kirby = $kirby;
|
||||
|
||||
// start the registry entry autoloader
|
||||
load([
|
||||
'lukaskleinschmidt\\sortable\\registry\\translation' => __DIR__ . DS . 'registry' . DS . 'translation.php',
|
||||
'lukaskleinschmidt\\sortable\\registry\\variant' => __DIR__ . DS . 'registry' . DS . 'variant.php',
|
||||
'lukaskleinschmidt\\sortable\\registry\\layout' => __DIR__ . DS . 'registry' . DS . 'layout.php',
|
||||
'lukaskleinschmidt\\sortable\\registry\\action' => __DIR__ . DS . 'registry' . DS . 'action.php',
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a registry entry object by type
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $subtype
|
||||
* @return Kirby\Registry\Entry
|
||||
*/
|
||||
public function entry($type, $subtype = null) {
|
||||
|
||||
$class = 'lukaskleinschmidt\\sortable\\registry\\' . $type;
|
||||
|
||||
if(!class_exists('lukaskleinschmidt\\sortable\\registry\\' . $type)) {
|
||||
throw new Exception('Unsupported registry entry type: ' . $type);
|
||||
}
|
||||
|
||||
return new $class($this);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace LukasKleinschmidt\Sortable\Registry;
|
||||
|
||||
use Exception;
|
||||
use Kirby;
|
||||
use Obj;
|
||||
use A;
|
||||
|
||||
class Action extends Kirby\Registry\Entry {
|
||||
|
||||
// Store of registered actions
|
||||
protected static $actions = [];
|
||||
|
||||
/**
|
||||
* Adds a new action to the registry
|
||||
*
|
||||
* @param mixed $name
|
||||
* @param string $root
|
||||
*/
|
||||
public function set($name, $root = null) {
|
||||
|
||||
$name = strtolower($name);
|
||||
$file = $root . DS . $name . '.php';
|
||||
|
||||
if(!$this->kirby->option('debug') || (is_dir($root) && is_file($file))) {
|
||||
return static::$actions[$name] = new Obj([
|
||||
'root' => $root,
|
||||
'file' => $file,
|
||||
'name' => $name,
|
||||
'class' => $name . 'action',
|
||||
]);
|
||||
}
|
||||
|
||||
throw new Exception('The action does not exist at the specified path: ' . $root);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retreives a registered action file
|
||||
* If called without params, retrieves all registered actions
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name = null) {
|
||||
|
||||
if(is_null($name)) {
|
||||
return static::$actions;
|
||||
}
|
||||
|
||||
return a::get(static::$actions, $name);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace LukasKleinschmidt\Sortable\Registry;
|
||||
|
||||
use Exception;
|
||||
use Kirby;
|
||||
use Obj;
|
||||
use A;
|
||||
|
||||
class Layout extends Kirby\Registry\Entry {
|
||||
|
||||
// Store of registered layouts
|
||||
protected static $layouts = [];
|
||||
|
||||
/**
|
||||
* Adds a new layout to the registry
|
||||
*
|
||||
* @param mixed $name
|
||||
* @param string $root
|
||||
*/
|
||||
public function set($name, $root = null) {
|
||||
|
||||
$name = strtolower($name);
|
||||
$file = $root . DS . $name . '.php';
|
||||
|
||||
if(!$this->kirby->option('debug') || (is_dir($root) && is_file($file))) {
|
||||
return static::$layouts[$name] = new Obj([
|
||||
'root' => $root,
|
||||
'file' => $file,
|
||||
'name' => $name,
|
||||
'class' => $name . 'layout',
|
||||
]);
|
||||
}
|
||||
|
||||
throw new Exception('The layout does not exist at the specified path: ' . $root);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retreives a registered layout file
|
||||
* If called without params, retrieves all registered layouts
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name = null) {
|
||||
|
||||
if(is_null($name)) {
|
||||
return static::$layouts;
|
||||
}
|
||||
|
||||
return a::get(static::$layouts, $name);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace LukasKleinschmidt\Sortable\Registry;
|
||||
|
||||
use Exception;
|
||||
use Kirby;
|
||||
use Obj;
|
||||
use A;
|
||||
|
||||
class Translation extends Kirby\Registry\Entry {
|
||||
|
||||
// Store of registered translations
|
||||
protected static $translations = [];
|
||||
|
||||
/**
|
||||
* Adds a new translation to the registry
|
||||
*
|
||||
* @param mixed $name
|
||||
* @param string $path
|
||||
*/
|
||||
public function set($name, $path = null) {
|
||||
|
||||
if(!$this->kirby->option('debug') || is_file($path)) {
|
||||
return static::$translations[$name] = $path;
|
||||
}
|
||||
|
||||
throw new Exception('The translation does not exist at the specified path: ' . $root);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retreives a registered translation file
|
||||
* If called without params, retrieves all registered translations
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name = null) {
|
||||
|
||||
if(is_null($name)) {
|
||||
return static::$translations;
|
||||
}
|
||||
|
||||
return a::get(static::$translations, $name);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace LukasKleinschmidt\Sortable\Registry;
|
||||
|
||||
use Exception;
|
||||
use Kirby;
|
||||
use Dir;
|
||||
use Obj;
|
||||
use A;
|
||||
use F;
|
||||
|
||||
class Variant extends Kirby\Registry\Entry {
|
||||
|
||||
// Store of registered variants
|
||||
protected static $variants = [];
|
||||
|
||||
/**
|
||||
* Adds a new variant to the registry
|
||||
*
|
||||
* @param mixed $name
|
||||
* @param string $root
|
||||
*/
|
||||
public function set($name, $root = null) {
|
||||
//
|
||||
// $name = strtolower($name);
|
||||
// $files = array();
|
||||
|
||||
if(!$this->kirby->option('debug') || is_dir($root)) {
|
||||
foreach(dir::read($root) as $file) {
|
||||
static::$variants[f::name($file)][$name] = $root . DS . $file;
|
||||
}
|
||||
|
||||
return static::$variants;
|
||||
// return static::$variants[$name] = new Obj([
|
||||
// 'root' => $root,
|
||||
// 'name' => $name,
|
||||
// 'files' => $files,
|
||||
// ]);
|
||||
}
|
||||
|
||||
throw new Exception('The variant does not exist at the specified path: ' . $root);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retreives a registered variant file
|
||||
* If called without params, retrieves all registered variants
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name = null) {
|
||||
|
||||
if(is_null($name)) {
|
||||
return static::$variants;
|
||||
}
|
||||
|
||||
return a::get(static::$variants, $name);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
26
site/OFF_plugins/sortable/sortable/src/sortable/roots.php
Normal file
26
site/OFF_plugins/sortable/sortable/src/sortable/roots.php
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace LukasKleinschmidt\Sortable;
|
||||
|
||||
use Obj;
|
||||
|
||||
class Roots extends Obj {
|
||||
|
||||
public $index;
|
||||
|
||||
public function __construct($root) {
|
||||
|
||||
$this->index = $root;
|
||||
|
||||
$this->translations = $this->index . DS . 'translations';
|
||||
$this->variants = $this->index . DS . 'variants';
|
||||
$this->layouts = $this->index . DS . 'layouts';
|
||||
$this->actions = $this->index . DS . 'actions';
|
||||
|
||||
}
|
||||
|
||||
public function __debuginfo() {
|
||||
return parent::__debuginfo();
|
||||
}
|
||||
|
||||
}
|
||||
37
site/OFF_plugins/sortable/sortable/translations/de.php
Normal file
37
site/OFF_plugins/sortable/sortable/translations/de.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'Keine Seiten vorhanden.',
|
||||
'field.sortable.or' => 'oder',
|
||||
'field.sortable.add.first' => 'Füge die erste Seite hinzu',
|
||||
'field.sortable.paste.first' => 'aus der Zwischenablage hinzufügen',
|
||||
|
||||
'field.sortable.limit' => 'Limit erreicht',
|
||||
'field.sortable.limit.template' => 'Limit für diese Vorlage erreicht',
|
||||
|
||||
'field.sortable.add' => 'Hinzufügen',
|
||||
'field.sortable.add.template.label' => 'Eine neue Seite hinzufügen',
|
||||
'field.sortable.add.error.template' => 'Die Vorlage fehlt',
|
||||
|
||||
'field.sortable.copy' => 'Kopieren',
|
||||
'field.sortable.copy.uri.label' => 'In die Zwischenablage kopieren',
|
||||
'field.sortable.copy.info.label' => 'Keine Seiten vorhanden',
|
||||
'field.sortable.copy.info.text' => 'Es gibt noch keine Seiten die du in der Zwischenablage speichern kannst.',
|
||||
'field.sortable.copy.error.uri' => 'Wähle mindestens eine Seite aus',
|
||||
|
||||
'field.sortable.delete' => 'Löschen',
|
||||
'field.sortable.delete.page.label' => 'Willst du diese Seite wirklich löschen?',
|
||||
|
||||
'field.sortable.duplicate' => 'Duplizieren',
|
||||
'field.sortable.edit' => 'Bearbeiten',
|
||||
|
||||
'field.sortable.paste' => 'Einfügen',
|
||||
'field.sortable.paste.uri.label' => 'Aus Zwischenablage einfügen',
|
||||
'field.sortable.paste.uri.help' => 'Eine oder mehrere Vorlagen sind nicht verfügbar',
|
||||
'field.sortable.paste.info.label' => 'Die Zwischenablage ist leer',
|
||||
'field.sortable.paste.info.text' => 'In der Zwischenablage befinden sich derzeit keine Seiten.',
|
||||
'field.sortable.paste.error.uri' => 'Wähle mindestens eine Seite aus',
|
||||
|
||||
'field.sortable.hide' => 'Verstecken',
|
||||
'field.sortable.show' => 'Anzeigen',
|
||||
);
|
||||
37
site/OFF_plugins/sortable/sortable/translations/en.php
Normal file
37
site/OFF_plugins/sortable/sortable/translations/en.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'No pages yet.',
|
||||
'field.sortable.or' => 'or',
|
||||
'field.sortable.add.first' => 'Add the first page',
|
||||
'field.sortable.paste.first' => 'add from clipboard',
|
||||
|
||||
'field.sortable.limit' => 'Limit reached',
|
||||
'field.sortable.limit.template' => 'Limit reached for this template',
|
||||
|
||||
'field.sortable.add' => 'Add',
|
||||
'field.sortable.add.template.label' => 'Add a new page',
|
||||
'field.sortable.add.error.template' => 'The template is missing',
|
||||
|
||||
'field.sortable.copy' => 'Copy',
|
||||
'field.sortable.copy.uri.label' => 'Copy to clipboard',
|
||||
'field.sortable.copy.info.label' => 'No pages yet',
|
||||
'field.sortable.copy.info.text' => 'There are no pages you can store in the clipboard yet.',
|
||||
'field.sortable.copy.error.uri' => 'Select at least one page',
|
||||
|
||||
'field.sortable.delete' => 'Delete',
|
||||
'field.sortable.delete.page.label' => 'Do you really want to delete this page?',
|
||||
|
||||
'field.sortable.duplicate' => 'Duplicate',
|
||||
'field.sortable.edit' => 'Edit',
|
||||
|
||||
'field.sortable.paste' => 'Paste',
|
||||
'field.sortable.paste.uri.label' => 'Paste from clipboard',
|
||||
'field.sortable.paste.uri.help' => 'One or more templates are not available',
|
||||
'field.sortable.paste.info.label' => 'Clipboard is empty',
|
||||
'field.sortable.paste.info.text' => 'There are no pages stored in the clipboard at the moment.',
|
||||
'field.sortable.paste.error.uri' => 'Select at least one page',
|
||||
|
||||
'field.sortable.hide' => 'Hide',
|
||||
'field.sortable.show' => 'Show',
|
||||
);
|
||||
37
site/OFF_plugins/sortable/sortable/translations/fr.php
Normal file
37
site/OFF_plugins/sortable/sortable/translations/fr.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'Aucune page pour le moment.',
|
||||
'field.sortable.or' => 'ou',
|
||||
'field.sortable.add.first' => 'Ajouter la première page',
|
||||
'field.sortable.paste.first' => 'ajouter du presse-papiers',
|
||||
|
||||
'field.sortable.limit' => 'Limite atteinte',
|
||||
'field.sortable.limit.template' => 'Limite atteinte pour ce modèle',
|
||||
|
||||
'field.sortable.add' => 'Ajouter',
|
||||
'field.sortable.add.template.label' => 'Ajouter une nouvelle page',
|
||||
'field.sortable.add.error.template' => 'Le modèle est manquant',
|
||||
|
||||
'field.sortable.copy' => 'Copier',
|
||||
'field.sortable.copy.uri.label' => 'Copier dans le presse-papiers',
|
||||
'field.sortable.copy.info.label' => 'Aucune page pour le moment',
|
||||
'field.sortable.copy.info.text' => 'Il n\'y a aucune page que vous pouvez stocker dans le presse-papiers pour le moment.',
|
||||
'field.sortable.copy.error.uri' => 'Selectionner au moins une page',
|
||||
|
||||
'field.sortable.delete' => 'Effacer',
|
||||
'field.sortable.delete.page.label' => 'Voulez-vous vraiment effacer cette page ?',
|
||||
|
||||
'field.sortable.duplicate' => 'Dupliquer',
|
||||
'field.sortable.edit' => 'Editer',
|
||||
|
||||
'field.sortable.paste' => 'Coller',
|
||||
'field.sortable.paste.uri.label' => 'Coller du presse-papiers',
|
||||
'field.sortable.paste.uri.help' => 'Un ou plusieurs modèle ne sont pas disponibles',
|
||||
'field.sortable.paste.info.label' => 'Le presse-papiers et vide',
|
||||
'field.sortable.paste.info.text' => 'Il n\y a aucune page stockée dans le presse-papiers pour le moment.',
|
||||
'field.sortable.paste.error.uri' => 'Selectionner au moins une page',
|
||||
|
||||
'field.sortable.hide' => 'Cacher',
|
||||
'field.sortable.show' => 'Montrer',
|
||||
);
|
||||
37
site/OFF_plugins/sortable/sortable/translations/pt_BR.php
Normal file
37
site/OFF_plugins/sortable/sortable/translations/pt_BR.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'Nenhuma página até o momento.',
|
||||
'field.sortable.or' => 'ou',
|
||||
'field.sortable.add.first' => 'Adicione a primeira página',
|
||||
'field.sortable.paste.first' => 'adicionar a partir da área de transferência',
|
||||
|
||||
'field.sortable.limit' => 'Limite alcançado',
|
||||
'field.sortable.limit.template' => 'Limite alcançado para este template',
|
||||
|
||||
'field.sortable.add' => 'Adicionar',
|
||||
'field.sortable.add.template.label' => 'Adicionar uma nova página',
|
||||
'field.sortable.add.error.template' => 'Template não encontrado',
|
||||
|
||||
'field.sortable.copy' => 'Copiar',
|
||||
'field.sortable.copy.uri.label' => 'Copiar para a área de transferência',
|
||||
'field.sortable.copy.info.label' => 'Nenhuma página até o momento',
|
||||
'field.sortable.copy.info.text' => 'Ainda não há nenhuma página para você copiar.',
|
||||
'field.sortable.copy.error.uri' => 'Selecione pelo menos uma página',
|
||||
|
||||
'field.sortable.delete' => 'Excluir',
|
||||
'field.sortable.delete.page.label' => 'Você realmente deseja excluir esta página?',
|
||||
|
||||
'field.sortable.duplicate' => 'Duplicar',
|
||||
'field.sortable.edit' => 'Editar',
|
||||
|
||||
'field.sortable.paste' => 'Colar',
|
||||
'field.sortable.paste.uri.label' => 'Colar da área de transferência',
|
||||
'field.sortable.paste.uri.help' => 'Um ou mais templates não estão disponíveis',
|
||||
'field.sortable.paste.info.label' => 'Área de transferência vazia',
|
||||
'field.sortable.paste.info.text' => 'Ainda não há nenhuma página para você colar.',
|
||||
'field.sortable.paste.error.uri' => 'Selecione pelo menos uma página',
|
||||
|
||||
'field.sortable.hide' => 'Esconder',
|
||||
'field.sortable.show' => 'Mostrar',
|
||||
);
|
||||
37
site/OFF_plugins/sortable/sortable/translations/sv_SE.php
Normal file
37
site/OFF_plugins/sortable/sortable/translations/sv_SE.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'Inga inlägg är skapade ännu.',
|
||||
'field.sortable.or' => 'eller',
|
||||
'field.sortable.add.first' => 'Lägg till första inlägget',
|
||||
'field.sortable.paste.first' => 'lägg till från urklipp',
|
||||
|
||||
'field.sortable.limit' => 'Gräns nådd',
|
||||
'field.sortable.limit.template' => 'Gräns nådd för den här mallen',
|
||||
|
||||
'field.sortable.add' => 'Lägg till',
|
||||
'field.sortable.add.template.label' => 'Lägg till nytt inlägg',
|
||||
'field.sortable.add.error.template' => 'Mallen saknas',
|
||||
|
||||
'field.sortable.copy' => 'Kopiera',
|
||||
'field.sortable.copy.uri.label' => 'Kopiera till urklipp',
|
||||
'field.sortable.copy.info.label' => 'Inga inlägg ännu',
|
||||
'field.sortable.copy.info.text' => 'Det finns inga inlägg som du kan spara i urklipp ännu.',
|
||||
'field.sortable.copy.error.uri' => 'Välj minst ett inlägg',
|
||||
|
||||
'field.sortable.delete' => 'Ta bort',
|
||||
'field.sortable.delete.page.label' => 'Är du säker på att du vill ta bort det här inlägget?',
|
||||
|
||||
'field.sortable.duplicate' => 'Duplicera',
|
||||
'field.sortable.edit' => 'Ändra',
|
||||
|
||||
'field.sortable.paste' => 'Klistra in',
|
||||
'field.sortable.paste.uri.label' => 'Klistra in från urklipp',
|
||||
'field.sortable.paste.uri.help' => 'En eller fler mallar är inte tillgängliga',
|
||||
'field.sortable.paste.info.label' => 'Urklipp är tomt',
|
||||
'field.sortable.paste.info.text' => 'Det finns inga inlägg sparade i urklipp.',
|
||||
'field.sortable.paste.error.uri' => 'Välj minst ett inlägg',
|
||||
|
||||
'field.sortable.hide' => 'Göm',
|
||||
'field.sortable.show' => 'Visa',
|
||||
);
|
||||
17
site/OFF_plugins/sortable/sortable/variants/modules/de.php
Normal file
17
site/OFF_plugins/sortable/sortable/variants/modules/de.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'Keine Module vorhanden.',
|
||||
'field.sortable.add.first' => 'Füge das erste Modul hinzu',
|
||||
|
||||
'field.sortable.add.template.label' => 'Ein neues Module hinzufügen',
|
||||
|
||||
'field.sortable.copy.info.label' => 'Keine Module vorhanden',
|
||||
'field.sortable.copy.info.text' => 'Es gibt noch keine Module die du in der Zwischenablage speichern kannst.',
|
||||
'field.sortable.copy.error.uri' => 'Wähle mindestens ein Modul aus',
|
||||
|
||||
'field.sortable.delete.page.label' => 'Willst du dieses Modul wirklich löschen?',
|
||||
|
||||
'field.sortable.paste.info.text' => 'In der Zwischenablage befinden sich derzeit keine Module.',
|
||||
'field.sortable.paste.error.uri' => 'Wähle mindestens ein Modul aus',
|
||||
);
|
||||
17
site/OFF_plugins/sortable/sortable/variants/modules/en.php
Normal file
17
site/OFF_plugins/sortable/sortable/variants/modules/en.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'No modules yet.',
|
||||
'field.sortable.add.first' => 'Add the first module',
|
||||
|
||||
'field.sortable.add.template.label' => 'Add a new module',
|
||||
|
||||
'field.sortable.copy.info.label' => 'No modules yet',
|
||||
'field.sortable.copy.info.text' => 'There are no modules you can store in the clipboard yet.',
|
||||
'field.sortable.copy.error.uri' => 'Select at least one module',
|
||||
|
||||
'field.sortable.delete.page.label' => 'Do you really want to delete this module?',
|
||||
|
||||
'field.sortable.paste.info.text' => 'There are no modules stored in the clipboard at the moment.',
|
||||
'field.sortable.paste.error.uri' => 'Select at least one module',
|
||||
);
|
||||
17
site/OFF_plugins/sortable/sortable/variants/modules/fr.php
Normal file
17
site/OFF_plugins/sortable/sortable/variants/modules/fr.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'Aucun module pour le moment.',
|
||||
'field.sortable.add.first' => 'Ajouter le premier module',
|
||||
|
||||
'field.sortable.add.template.label' => 'Ajouter un nouveau module',
|
||||
|
||||
'field.sortable.copy.info.label' => 'Aucun module pour le moment',
|
||||
'field.sortable.copy.info.text' => 'Il n\'y a pas encore de modules que vous puissiez stocker dans le presse-papiers.',
|
||||
'field.sortable.copy.error.uri' => 'Selectionner au moins un module',
|
||||
|
||||
'field.sortable.delete.page.label' => 'Voulez-vous vraiment effacer ce module ?',
|
||||
|
||||
'field.sortable.paste.info.text' => 'Il n\'y a pas de modules stockés dans le presse-papiers pour le moment.',
|
||||
'field.sortable.paste.error.uri' => 'Selectionner au moins un module',
|
||||
);
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'Nenhum módulo até o momento.',
|
||||
'field.sortable.add.first' => 'Adicione o primeiro módulo',
|
||||
|
||||
'field.sortable.add.template.label' => 'Adicionar um novo módulo',
|
||||
|
||||
'field.sortable.copy.info.label' => 'Nenhum módulo até o momento',
|
||||
'field.sortable.copy.info.text' => 'Ainda não há nenhum módulo para você copiar.',
|
||||
'field.sortable.copy.error.uri' => 'Selecione pelo menos um módulo',
|
||||
|
||||
'field.sortable.delete.page.label' => 'Você realmente deseja excluir este módulo?',
|
||||
|
||||
'field.sortable.paste.info.text' => 'Ainda não há nenhum módulo para você colar.',
|
||||
'field.sortable.paste.error.uri' => 'Selecione pelo menos um módulo',
|
||||
);
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'Inga moduler är skapade ännu.',
|
||||
'field.sortable.add.first' => 'Lägg till första modulen',
|
||||
|
||||
'field.sortable.add.template.label' => 'Lägg till en ny modul',
|
||||
|
||||
'field.sortable.copy.info.label' => 'Inga moduler ännu',
|
||||
'field.sortable.copy.info.text' => 'Det finns inga moduler som du kan spara i urklipp ännu.',
|
||||
'field.sortable.copy.error.uri' => 'Välj minst en modul',
|
||||
|
||||
'field.sortable.delete.page.label' => 'Är du säker på att du vill ta bort den här modulen?',
|
||||
|
||||
'field.sortable.paste.info.text' => 'Det finns inga moduler sparade i urklipp.',
|
||||
'field.sortable.paste.error.uri' => 'Välj minst en modul',
|
||||
);
|
||||
17
site/OFF_plugins/sortable/sortable/variants/sections/de.php
Normal file
17
site/OFF_plugins/sortable/sortable/variants/sections/de.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'Keine Sektionen vorhanden.',
|
||||
'field.sortable.add.first' => 'Füge die erste Sektion hinzu',
|
||||
|
||||
'field.sortable.add.template.label' => 'Eine neue Sektion hinzufügen',
|
||||
|
||||
'field.sortable.copy.info.label' => 'Keine Sektionen vorhanden',
|
||||
'field.sortable.copy.info.text' => 'Es gibt noch keine Sektionen die du in der Zwischenablage speichern kannst.',
|
||||
'field.sortable.copy.error.uri' => 'Wähle mindestens eine Sektion aus',
|
||||
|
||||
'field.sortable.delete.page.label' => 'Willst du diese Sektion wirklich löschen?',
|
||||
|
||||
'field.sortable.paste.info.text' => 'In der Zwischenablage befinden sich derzeit keine Seiten.',
|
||||
'field.sortable.paste.error.uri' => 'Wähle mindestens eine Seite aus',
|
||||
);
|
||||
17
site/OFF_plugins/sortable/sortable/variants/sections/en.php
Normal file
17
site/OFF_plugins/sortable/sortable/variants/sections/en.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'No sections yet.',
|
||||
'field.sortable.add.first' => 'Add the first section',
|
||||
|
||||
'field.sortable.add.template.label' => 'Add a new section',
|
||||
|
||||
'field.sortable.copy.info.label' => 'No sections yet',
|
||||
'field.sortable.copy.info.text' => 'There are no sections you can store in the clipboard yet.',
|
||||
'field.sortable.copy.error.uri' => 'Select at least one section',
|
||||
|
||||
'field.sortable.delete.page.label' => 'Do you really want to delete this section?',
|
||||
|
||||
'field.sortable.paste.info.text' => 'There are no sections stored in the clipboard at the moment.',
|
||||
'field.sortable.paste.error.uri' => 'Select at least one section',
|
||||
);
|
||||
17
site/OFF_plugins/sortable/sortable/variants/sections/fr.php
Normal file
17
site/OFF_plugins/sortable/sortable/variants/sections/fr.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'Aucune section pour le moment.',
|
||||
'field.sortable.add.first' => 'Ajouter la première section',
|
||||
|
||||
'field.sortable.add.template.label' => 'Ajouter une nouvelle section',
|
||||
|
||||
'field.sortable.copy.info.label' => 'Aucune section pour le moment',
|
||||
'field.sortable.copy.info.text' => 'Il n\'y a pas encore de sections que vous puissiez stocker dans le presse-papiers.',
|
||||
'field.sortable.copy.error.uri' => 'Selectionner au moins une section',
|
||||
|
||||
'field.sortable.delete.page.label' => 'Voulez-vous vraiment effacer cette section ?',
|
||||
|
||||
'field.sortable.paste.info.text' => 'Il n\'y a pas de sections stockées dans le presse-papiers pour le moment.',
|
||||
'field.sortable.paste.error.uri' => 'Selectionner au moins une section',
|
||||
);
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'Nenhuma seção até o momento.',
|
||||
'field.sortable.add.first' => 'Adicione a primeira seção',
|
||||
|
||||
'field.sortable.add.template.label' => 'Adicionar uma nova seção',
|
||||
|
||||
'field.sortable.copy.info.label' => 'Nenhuma seção até o momento',
|
||||
'field.sortable.copy.info.text' => 'Ainda não há nenhuma seção para você copiar.',
|
||||
'field.sortable.copy.error.uri' => 'Selecione pelo menos uma seção',
|
||||
|
||||
'field.sortable.delete.page.label' => 'Você realmente deseja excluir esta seção?',
|
||||
|
||||
'field.sortable.paste.info.text' => 'Ainda não há nenhuma seção para você colar.',
|
||||
'field.sortable.paste.error.uri' => 'Selecione pelo menos uma seção',
|
||||
);
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'field.sortable.empty' => 'Inga sektioner är skapade ännu.',
|
||||
'field.sortable.add.first' => 'Lägg till första sektionen',
|
||||
|
||||
'field.sortable.add.template.label' => 'Lägg till en ny sektion',
|
||||
|
||||
'field.sortable.copy.info.label' => 'Inga sektioner ännu',
|
||||
'field.sortable.copy.info.text' => 'Det finns inga sektioner som du kan spara i urklipp ännu.',
|
||||
'field.sortable.copy.error.uri' => 'Välj minst en sektion',
|
||||
|
||||
'field.sortable.delete.page.label' => 'Är du säker på att du vill ta bort den här sektionen?',
|
||||
|
||||
'field.sortable.paste.info.text' => 'Det finns inga sektioner sparade i urklipp.',
|
||||
'field.sortable.paste.error.uri' => 'Välj minst en sektion',
|
||||
);
|
||||
Loading…
Add table
Add a link
Reference in a new issue