Compare commits

..

24 Commits

Author SHA1 Message Date
m038 9f798daaa3 Add remote-deploy target: pull user repo and install plugins 2026-06-13 21:11:00 +02:00
m038 c7877f3ce0 Pin Grav version, install plugins as part of remote-install 2026-06-13 21:08:50 +02:00
m038 bc3df5c24b Split SERVER into REMOTE_USER/HOST/HOME, rename USER_REPO to REPO 2026-06-13 21:06:48 +02:00
m038 596b94519f Remove chown from install script 2026-06-13 21:05:08 +02:00
m038 766b7edcdd Derive WEBROOT_USER from WEBROOT, remove from env 2026-06-13 21:03:43 +02:00
m038 ef8c0e1a32 Add WEBROOT_USER for chown, pass to remote-install 2026-06-13 21:02:33 +02:00
m038 2b9a926338 Pass Gitea credentials to remote-install, clean up after clone 2026-06-13 20:53:58 +02:00
m038 643b1ccc61 Fix env var forwarding in remote-install, add remote-clean target 2026-06-13 20:51:53 +02:00
m038 a815593f52 Rename server-* targets to remote-*, update README 2026-06-13 20:30:12 +02:00
m038 8154628101 Rename deploy/pull-content to content-push/content-pull 2026-06-13 20:29:28 +02:00
m038 59f8795670 Update README to reflect VPS and git subtree deployment 2026-06-13 19:21:22 +02:00
m038 5bbaa8bb8b Add server make targets, install script, and .env setup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 19:18:22 +02:00
m038 e0444fa40c Add deploy and pull-content Makefile targets for user repo
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 18:52:39 +02:00
m038 103e344408 Rename image fields and implement werk-in-detail gallery
- Rename image_main/image_secondary/image_logo/image_portrait to
  portret/extra_1/logo/extra_2 in pages, blueprints, and templates
- Add extra_2 image slot to home and CV (hidden on mobile)
- Wire werk-in-detail to real child pages instead of picsum placeholders
- Remove glightbox CDN dependency from werk-in-detail
- Add album blueprint, template, and grote-objecten album page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 18:49:29 +02:00
m038 589b70aae9 Apply UI/UX improvements and fix broken Bootstrap JS
- Add CSS custom properties for brand colors
- Remove global font-weight: bold from body
- Increase content panel opacity from 0.6 to 0.88
- Add dynamic lang attribute, favicon, and Open Graph meta tags
- Move scripts to <head> with defer (required due to automagic-images plugin)
- Disable automagic-images plugin (PHPHtmlParser strips all <script src> tags
  during HTML re-serialization, breaking Bootstrap JS and all dropdowns)
- Add loading="lazy" to below-fold images across templates

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 02:15:40 +02:00
m038 87b0893ebd Add README with development setup and deployment workflow
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 00:59:41 +02:00
m038 741f7fe57b Move plugins to manifest, pin Docker version, add Makefile
- Add plugins.txt listing all plugins for reproducible installs
- Add Makefile with setup/start/stop/install-plugins targets
- Remove user/plugins/ from git tracking
- Pin Docker image to 1.7.49.5-ls244

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 00:55:59 +02:00
m038 1a1fbec6ed Update system config, theme blueprint and langswitcher config
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 00:47:58 +02:00
m038 9cf5b4eece Make logo editable on home and CV pages, add all media to page folders
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 00:45:37 +02:00
m038 09208c5a87 Make CV page portrait image editable via admin
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 00:43:55 +02:00
m038 a7a4db6505 Translate home page blueprint labels to Dutch
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 00:35:03 +02:00
m038 9c708a620e Switch home page image fields to pagemediaselect for easier reuse
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 00:34:31 +02:00
m038 1a4f6a5b69 Add English translations for all pages, rename Dutch pages to .nl.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 00:30:12 +02:00
m038 cf487eeed1 Add portrait images to home page media and set as defaults
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 00:26:58 +02:00
2787 changed files with 420 additions and 472493 deletions
+9
View File
@@ -0,0 +1,9 @@
REMOTE_USER=root
REMOTE_HOST=example.com
REMOTE_HOME=/home/example.com
REPO=https://gitea.example.com/user/natascha-rieter.nl-user.git
GRAV_VERSION=1.7.49.5
GITEA_HOST=gitea.example.com
GITEA_USER=natascha-deploy
GITEA_TOKEN=your-token-here
+4
View File
@@ -1,7 +1,11 @@
# Environment
.env
# Grav CMS
user/accounts/
user/data/
user/cache/
user/plugins/
# Claude
.claude/
+40
View File
@@ -0,0 +1,40 @@
-include .env
export
SSH := $(REMOTE_USER)@$(REMOTE_HOST)
WEBROOT := $(REMOTE_HOME)/public_html
# Local dev
start:
docker compose up -d
stop:
docker compose down
setup: start install-plugins
install-plugins:
docker exec natascha_grav php /app/www/public/bin/gpm install $(shell cat plugins.txt | tr '\n' ' ') -y
# Content (user repo)
content-push:
git subtree push --prefix=user user-deploy main
content-pull:
git subtree pull --prefix=user user-deploy main --squash
# Remote
remote-install:
ssh $(SSH) "WEBROOT=$(WEBROOT) REPO=$(REPO) GRAV_VERSION=$(GRAV_VERSION) PLUGINS='$(shell cat plugins.txt | tr '\n' ' ')' GITEA_HOST=$(GITEA_HOST) GITEA_USER=$(GITEA_USER) GITEA_TOKEN=$(GITEA_TOKEN) bash -s" < scripts/server-install.sh
remote-deploy:
ssh $(SSH) "cd $(WEBROOT)/user && git pull && cd $(WEBROOT) && php bin/gpm install $(shell cat plugins.txt | tr '\n' ' ') -y"
remote-install-plugins:
ssh $(SSH) "cd $(WEBROOT) && php bin/gpm install $(shell cat plugins.txt | tr '\n' ' ') -y"
remote-upgrade-grav:
ssh $(SSH) "cd $(WEBROOT) && php bin/grav upgrade"
remote-clean:
ssh $(SSH) "cd $(WEBROOT) && php bin/grav clearcache"
+94
View File
@@ -0,0 +1,94 @@
# natascha-rieter.nl — Grav CMS
## Local development
Requires Docker. To set up from scratch:
```
make setup
```
This starts the container and installs all plugins listed in `plugins.txt` via GPM.
Other commands:
```
make start # start the container
make stop # stop the container
make install-plugins # (re)install plugins from plugins.txt
```
Site runs at http://localhost:8080.
## Repository structure
This project uses two git repositories:
| Repo | Contents | Purpose |
|------|----------|---------|
| `natascha-rieter-nl` (this repo) | Docker setup, Makefile, scripts | Local dev and server management |
| `natascha-rieter.nl-user` | Contents of `user/` | Deployed to production, synced with Git Sync |
The `user/` folder in this repo is linked to the user repo via git subtree.
### What goes where
| Path | Description | In git |
|------|-------------|--------|
| `user/config/` | Site and plugin configuration | user repo |
| `user/pages/` | Page content | user repo |
| `user/themes/natascha/` | Custom theme | user repo |
| `user/plugins/` | Plugins (see plugins.txt) | no |
| `user/accounts/` | Admin credentials | no |
| `user/data/` | Runtime data | no |
| `user/cache/` | Generated cache | no |
## Deployment
Production runs on a VPS with Apache. The user repo is cloned into the Grav `user/` folder on the server and kept in sync via the Git Sync plugin.
### Remote config
Copy `.env.example` to `.env` and fill in your values (gitignored):
```
SERVER=user@example.com
WEBROOT=/path/to/public_html
USER_REPO=ssh://git@gitea.example.com/user/repo.git
```
### First-time install
```
make remote-install
```
This SSHes into the server and runs `scripts/server-install.sh`, which installs Grav and clones the user repo.
### Deploying content changes
```
make content-push # push local user/ changes to the user repo on Gitea
make content-pull # pull editor's content changes back locally
```
After `make content-push`, trigger a deploy on the server:
```
make remote-deploy # pull latest user repo changes and install plugins on server
```
### Remote maintenance
```
make remote-install-plugins # install/update plugins from plugins.txt on server
make remote-upgrade-grav # upgrade Grav core on server
make remote-clean # clear Grav cache on server
```
## Plugins
Plugins are not committed to git. The full list is in `plugins.txt`.
- Locally: `make install-plugins`
- Remotely: `make remote-install-plugins`
+1 -1
View File
@@ -1,6 +1,6 @@
services:
grav:
image: lscr.io/linuxserver/grav:latest
image: lscr.io/linuxserver/grav:1.7.49.5-ls244
container_name: natascha_grav
environment:
- PUID=1000
+15
View File
@@ -0,0 +1,15 @@
admin
email
error
flex-objects
form
login
problems
sitemap
social-meta-tags
draft-preview
langswitcher
automagic-images
admin-media-move
admin-media-replace
admin-media-actions
+33
View File
@@ -0,0 +1,33 @@
#!/bin/bash
set -e
: "${WEBROOT:?WEBROOT is not set}"
: "${REPO:?REPO is not set}"
: "${GRAV_VERSION:?GRAV_VERSION is not set}"
: "${PLUGINS:?PLUGINS is not set}"
: "${GITEA_HOST:?GITEA_HOST is not set}"
: "${GITEA_USER:?GITEA_USER is not set}"
: "${GITEA_TOKEN:?GITEA_TOKEN is not set}"
echo "==> Downloading Grav $GRAV_VERSION"
cd "$WEBROOT"
wget -q "https://getgrav.org/download/core/grav-admin/$GRAV_VERSION" -O grav-admin.zip
unzip -q grav-admin.zip
mv grav-admin/* grav-admin/.htaccess .
rm -rf grav-admin grav-admin.zip
echo "==> Cloning user repo"
printf 'machine %s\nlogin %s\npassword %s\n' "$GITEA_HOST" "$GITEA_USER" "$GITEA_TOKEN" > ~/.netrc
chmod 600 ~/.netrc
rm -rf user
git clone "$REPO" user
rm ~/.netrc
echo "==> Installing plugins"
php bin/gpm install $PLUGINS -y
echo "==> Setting permissions"
find "$WEBROOT" -type f -exec chmod 664 {} \;
find "$WEBROOT" -type d -exec chmod 775 {} \;
echo "==> Done. Visit your domain to complete setup."
@@ -0,0 +1 @@
enabled: false
@@ -2,4 +2,4 @@ enabled: true
built_in_css: true
translated_urls: true
untranslated_pages_behavior: none
language_display: long
language_display: short
+1 -1
View File
@@ -168,7 +168,7 @@ debugger:
shutdown:
close_connection: true
images:
adapter: gd
adapter: imagick
default_image_quality: 85
cache_all: false
cache_perms: '0755'
+15
View File
@@ -0,0 +1,15 @@
---
title: 'Natascha Rieter'
menu: Home
published: true
sitemap:
lastmod: '19-04-2026 00:00'
portret: portret-2.jpg
extra_1: portret-1.jpg
logo: logo-blauw.png
extra_2: ''
---
I create small sculptures, reliefs, clay paintings, modelled figures and wheel-thrown work. My work is emotional and poetic with a monumental character. The outdoor objects are frost-resistant. In my clay paintings I combine ceramic and painting techniques. Working with clay is for me the same as writing a poem. In recent years I have been almost exclusively occupied with monumental commissions. I work on commission and give courses and workshops.
Side activities: Ceramics teacher, Kumulus in Maastricht; gallery owner of ceramic gallery "Groot Welsden"; owner of B&B de Kunstkamer.
@@ -4,6 +4,10 @@ menu: Home
published: true
sitemap:
lastmod: '18-04-2026 21:48'
portret: portret-2.jpg
extra_1: portret-1.jpg
logo: logo-blauw.png
extra_2: ''
---
Ik maak kleinplastieken, reliëfs, kleischilderijen, geboetseerde beelden en draaiwerk. Mijn werk is emotioneel en poëtisch met een monumentaal karakter. De objecten voor buiten zijn winterhard. In mijn kleischilderijen worden de keramische- en schilderstechniek met elkaar gecombineerd. Het werken met klei is voor mij het zelfde als het schrijven van een gedicht. De laatste jaren ben ik bijna uitsluitend met monumentale opdrachten bezig geweest. Ik werk in opdracht en geef cursussen en workshops.
Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

+18
View File
@@ -0,0 +1,18 @@
---
title: Natascha Rieter Curriculum Vitae
menu: CV
portret: portret-1.jpg
extra_1: ''
logo: logo-blauw.png
extra_2: ''
---
Natascha Rieter, born in Roermond (1948), has lived since 1988 in Margraten, in the hamlet of Groot Welsden, where she and her husband Siegfried Gorinskat (also a ceramist, who passed away in 2006) established their studios in a typical half-timbered farmhouse. Both artists enjoy great renown in the art world for their ceramic works. In 1989 they opened Ceramic Gallery "Groot Welsden" — with great success. Natascha Rieter is an emotional and poetic artist for whom ceramics is the mirror of the soul.
Natascha studied monumental design, majoring in painting, at the City Academy in Maastricht (19671971). After her studies she worked for two years in a ceramic studio in Switzerland (19711972). From 1972 to 1975 she studied ceramics at the Ceramic Hochschule in Höhr-Grenzhausen, Germany. She then moved to Nijswiller (South Limburg), where she established herself as a ceramist (19761988). She has exhibited in many galleries in the Netherlands, Germany, Belgium, France and Japan. The themes in her work are nature and humanity: LIFE. She translates her feelings into ceramics — "Working with clay is for me the same as writing a poem."
Natascha Rieter makes functional ceramics, reliefs, small sculptures, modelled figures and clay paintings. She uses stoneware clay from Germany and porcelain from France. In her clay paintings she combines ceramics with painting techniques on wooden panels.
In recent years Natascha has been almost exclusively occupied with monumental commissions in applied art — wall reliefs in building lobbies, monumental sculpture groups, and private and corporate commissions.
Side activities: Ceramics teacher at Kumulus, Centre for the Arts, Maastricht since 1977. Gallery owner of Ceramic Gallery "Groot Welsden" since 1989.
@@ -1,6 +1,10 @@
---
title: Natascha Rieter Curriculum Vitae
menu: CV
portret: portret-1.jpg
extra_1: ''
logo: logo-blauw.png
extra_2: ''
---
Natascha Rieter, geboren te Roermond (1948), woont sinds 1988 te Margraten, in het gehucht Groot Welsden, waar zij met haar man Siegfried Gorinskat (ook keramist) (2006 gestorven) in een typische vakwerkboerderij hun ateliers hebben gevestigd. Beide kunstenaars genieten vanwege hun keramische werken grote bekendheid in de kunstwereld. In 1989 openden zij Keramiek Galerie "Groot Welsden" en niet zonder succes. Natascha Rieter is een emotioneel en poëtisch kunstenaar voor wie keramiek de spiegel van de ziel is.
Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

+6
View File
@@ -0,0 +1,6 @@
---
title: Gallery
menu: Gallery
---
A selection of ceramic works by Natascha Rieter — from small sculptures to monumental commissions. Click an image for an enlarged view.
Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

@@ -0,0 +1,7 @@
---
title: 'Large objects'
sitemap:
lastmod: '13-06-2026 13:29'
---
A series of larges objects made in the last years
@@ -0,0 +1,8 @@
---
title: 'Grote objecten'
sitemap:
lastmod: '13-06-2026 13:29'
media_order: '10298359_1112080642156692_2004541195504715933_o_1112080642156692.jpg,1936306_1105443762820380_8216889586053322199_n_1105443762820380.jpg,10683502_1112079375490152_4488529684021326036_o_1112079375490152.jpg,11053920_1112081192156637_6689568670232240087_o_1112081192156637.jpg,12029743_1107926249238798_5277465818662466467_o_1107926249238798.jpg,12418905_1112080445490045_6622839067204183466_o_1112080445490045.jpg,12418905_1112080975489992_3344234153253759058_o_1112080975489992.jpg,12418926_1112081552156601_1127226366914273536_o_1112081552156601.jpg,12493616_1112080162156740_7951360208797715360_o_1112080162156740.jpg,12495917_1112079482156808_5584179686913736172_o_1112079482156808.jpg,12496352_1112081338823289_3609436053778783843_o_1112081338823289.jpg,12593704_1112080822156674_1315022773915505238_o_1112080822156674.jpg'
---
Een serie van grote objecte gemaakt in de afgelopen jaren
@@ -0,0 +1,4 @@
---
title: Work in detail
menu: Work in detail
---
+15
View File
@@ -0,0 +1,15 @@
---
title: Contact & Address
menu: Contact
---
**Opening hours**
Every Friday and Saturday
The first Sunday of the month
From 11:00 to 17:00
Also by appointment
Sint Agnesplein 4
NL-6241 CA Bunde
[+31 (0)43 458 27 51](tel:+31434582751)
[info@natascha-rieter.nl](mailto:info@natascha-rieter.nl)
@@ -1,32 +0,0 @@
# v1.0.4
## 2/15/2018
1. [](#new)
* Update styles for Grav Admin v1.7.
# v1.0.3
## 2/15/2018
1. [](#new)
* Add column margin to media actions.
* Add border-radius to media actions.
# v1.0.2
## 2/14/2018
1. [](#new)
* Update bugs URL.
* Update addAction signature
# v1.0.1
## 2/7/2018
1. [](#new)
* Show alert dialog for sample actions.
* Update sample action log message.
# v1.0.0
## 1/24/2018
1. [](#Initial)
*
-21
View File
@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2018 TwelveTone LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -1,34 +0,0 @@
# Admin Media Actions Plugin
The **Admin Media Actions** Plugin is for [Grav CMS](http://github.com/getgrav/grav). A plugin which adds an API for adding actions items to media items in the media bin.
## Installation
Installing the Admin Media Actions plugin can be done in one of two ways. The GPM (Grav Package Manager) installation method enables you to quickly and easily install the plugin with a simple terminal command, while the manual method enables you to do so via a zip file.
### GPM Installation (Preferred)
The simplest way to install this plugin is via the [Grav Package Manager (GPM)](http://learn.getgrav.org/advanced/grav-gpm) through your system's terminal (also called the command line). From the root of your Grav install type:
bin/gpm install admin-media-actions
This will install the Admin Media Actions plugin into your `/user/plugins` directory within Grav. Its files can be found under `/your/site/grav/user/plugins/admin-media-actions`.
### Manual Installation
To install this plugin, just download the zip version of this repository and unzip it under `/your/site/grav/user/plugins`. Then, rename the folder to `admin-media-actions`. You can find these files on [GitHub](https://github.com) or via [GetGrav.org](http://getgrav.org/downloads/plugins#extras).
You should now have all the plugin files under
/your/site/grav/user/plugins/admin-media-actions
> NOTE: This plugin is a modular component for Grav which requires [Grav](http://github.com/getgrav/grav) and the [Admin](https://github.com/getgrav/grav-plugin-admin) plugin to operate.
## Usage
See online [documentation](https://www.twelvetone.tv/docs/developer-tools/grav-plugins/grav-admin-media-actions-plugin)
## Credits
A big thanks to David Szabo and his development on the grav-plugin-admin-addon-media-rename for some clever approaches
on tapping into the Grav architecture.
@@ -1,227 +0,0 @@
<?php
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 TwelveTone LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Grav\Plugin;
use Grav\Common\Plugin;
/**
* Class AdminMediaActionsPlugin
* @package Grav\Plugin
*/
class AdminMediaActionsPlugin extends Plugin
{
const ROUTE = '/admin-media-actions';
public static function getSubscribedEvents()
{
return [
'onPluginsInitialized' => ['onPluginsInitialized', 0]
];
}
public function getPath()
{
return '/' . trim($this->grav['admin']->base, '/') . '/' . trim(self::ROUTE, '/');
}
public function buildBaseUrl()
{
$ret = rtrim($this->grav['uri']->rootUrl(false), '/') . '/' . trim($this->getPath(), '/');
return $ret;
}
public function onPluginsInitialized()
{
if (!$this->isAdmin() || !$this->grav['user']->authenticated) {
return;
}
// Register the media actions service
$this->grav['media-actions'] = function ($c) {
return new MediaActionsController();
};
// Ignore requests to the plugin URL
if ($this->grav['uri']->path() == $this->getPath()) {
return;
}
if ($this->config->get('plugins.admin-media-actions.show_samples')) {
// Sample Actions
$this->grav['media-actions']->addAction("SampleAction1", "Sample Action 1", "play-circle", function ($page, $mediaName, $payload) {
return [
"path" => $page->path(),
"route" => $page->route(),
"mediaName" => $mediaName,
];
});
$this->grav['media-actions']->addAction("SampleAction2", "Sample Action 2", "play-circle", function ($page, $mediaName, $payload) {
return [
"path" => $page->path(),
"route" => $page->route(),
"mediaName" => $mediaName,
];
});
$this->grav['media-actions']->addAction("SampleAction3", "Sample Action 3", "play-circle", function ($page, $mediaName, $payload) {
return [
"path" => $page->path(),
"route" => $page->route(),
"mediaName" => $mediaName,
];
});
$this->grav['media-actions']->addAction("SampleForm", "Sample Form", "list", function ($page, $mediaName, $payload) {
return "ok";
});
}
$this->enable([
'onAdminTwigTemplatePaths' => ['onAdminTwigTemplatePaths', 0],
'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0],
'onPagesInitialized' => ['onTwigExtensions', 0],
'onAdminTaskExecute' => ['onAdminTaskExecute', 0],
]);
}
public function onAdminTaskExecute($e)
{
$method = $e['method'];
switch ($method) {
case "taskMedia-action":
$page = $this->grav['admin']->page(false);
//$route = $page->route();
$actionId = $_POST['action_id'];
$media_name = $_POST['media_name'];
$payload = json_decode($_POST['payload'], true);
$handler = $this->grav['media-actions']->getHandlerForAction($actionId);
if ($handler) {
$json = $handler($page, $media_name, $payload);
die("{\"result\":" . json_encode($json) . "}");
} else {
die("{\"result\":{\"error\":true}}");
}
break;
default:
return false;
}
}
public function onAdminTwigTemplatePaths()
{
// $event['paths'] = __DIR__ . '/themes/grav/templates';
}
public function onTwigTemplatePaths()
{
$this->grav['twig']->twig_paths[] = __DIR__ . '/templates';
}
public function onTwigExtensions()
{
$page = $this->grav['admin']->page(true);
if (!$page) {
return;
}
if ($this->config->get('plugins.admin-media-actions.show_samples')) {
$this->grav['assets']->addJs('plugin://admin-media-actions/assets/samples/sample_actions.js', -1000, false);
$this->grav['assets']->addJs('plugin://admin-media-actions/assets/samples/sample_form_action.js', -1000, false);
}
$oCopy = [];
foreach ($this->grav['media-actions']->actions as $action) {
$oCopy[] = [
'actionId' => $action['actionId'],
'icon' => $action['icon'],
'caption' => $action['caption'],
];
}
$this->grav['assets']->addInlineJs('const MEDIA_ACTIONS = ' . json_encode($oCopy) . ';', -1000, false);
$taskUrl = $this->buildBaseUrl() . $page->route() . '/task:media-action';
$this->grav['assets']->addInlineJs('const MEDIA_ACTION_TASK_URL = ' . json_encode($taskUrl) . ';', -1000, false);
$this->grav['assets']->addJs('plugin://admin-media-actions/assets/admin-media-actions.js', -1000, false);
$this->grav['assets']->addCss('plugin://admin-media-actions/assets/admin-media-actions.css', -1000, false);
}
public function outputError($msg)
{
header('HTTP/1.1 400 Bad Request');
die(json_encode(['error' => ['msg' => $msg]]));
}
}
class MediaActionsController
{
public $actions = [];
/**
* @param $actionId A unique id for the action. Must be a valid Javascript function name.
* This can also be an array containing keys of the same parameter names.
*
* @param $caption The caption for the action. Used for the tooltip.
* @param $icon The font-awesome icon name. The 'fa-' prefix is optional.
* @param $handler A handler for the action. (page, mediaName, payload) => object.
*/
function addAction($actionId, $caption = null, $icon = null, $handler = null)
{
if (is_array($actionId)) {
if (isset($actionId['caption'])) {
$caption = $actionId['caption'];
}
if (isset($actionId['icon'])) {
$icon = $actionId['icon'];
}
if (isset($actionId['handler'])) {
$handler = $actionId['handler'];
}
// do this last...
$actionId = $actionId['actionId'];
}
$this->actions[$actionId] = [
'handler' => $handler,
'caption' => $caption,
'icon' => $icon,
'actionId' => $actionId,
];
}
function getHandlerForAction($actionId)
{
if (isset($this->actions[$actionId])) {
return $this->actions[$actionId]['handler'];
} else {
return null;
}
}
}
@@ -1,26 +0,0 @@
#
# The MIT License (MIT)
#
# Copyright (c) 2018 TwelveTone LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
enabled: true
show_samples: false
@@ -1,62 +0,0 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2018 TwelveTone LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
span[data-dz-name] {
cursor: text;
}
.dz-rename:hover:after {
color: #0082ba;
}
/*.dropzone .dz-preview:hover .dz-rename {*/
/*display: block;*/
/*}*/
.dropzone .dz-preview:hover .dz-media-action {
display: flex;
}
.dz-media-action {
display: none;
position: absolute;
width: 25px;
height: 25px;
cursor: pointer;
background: #e1e1e1;
justify-content: center;
align-items: center;
border-radius: 2px;
}
body.ga-theme-17x .dz-media-action {
background: #f2f2f2;
}
.dz-media-action i {
color: #737c81;
}
.dz-media-action i:hover {
color: #0082ba;
}
@@ -1,119 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 TwelveTone LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// MEDIA_ACTIONS must be set
// MEDIA_ACTION_TASK_URL must be set
function _onMediaAction(actionId, mediaName, dz) {
let fn = "onMediaAction_" + actionId;
if (typeof window[fn] === 'function') {
window[fn].apply(null, [actionId, mediaName, dz]);
} else {
submitMediaAction(actionId, mediaName, "");
}
}
function submitMediaAction(actionId, mediaName, payload = "", callback = null, modal = null) {
if (modal) {
$('.loading', modal).removeClass('hidden');
$('.button', modal).addClass('hidden');
}
var data = new FormData();
data.append('admin-nonce', GravAdmin.config.admin_nonce);
data.append("action_id", actionId);
data.append("media_name", mediaName);
data.append("payload", JSON.stringify(payload));
fetch(MEDIA_ACTION_TASK_URL, {method: 'POST', body: data, credentials: 'same-origin'})
.then(res => res.json())
.then(result => {
if (modal) {
if (!result.error) {
modal.close();
}
}
if (callback) {
callback(result);
}
});
}
// Check for new media every 1000 ms and add actions
setInterval(function () {
const size = 25; // The action icon size
const maxRows = 5;
const colMargin = 2;
$('.dz-preview').each(function (i, dz) {
if (!dz._actions) {
dz._actions = true;
let actionsIndex = 3; //TODO hardcoded to standard action count
//let top = 72; //TODO get max top of children (they are not in order)
//let top = actionsCount * size - size; // the standard icons ar off by 1 pixel!?
const that = this;
MEDIA_ACTIONS.forEach(function (item) {
actionsIndex++;
let faIcon = item.icon;
if (!faIcon) {
faIcon = "fa-play-circle";
}
if (!faIcon.startsWith('fa-')) {
faIcon = 'fa-' + faIcon;
}
const ele = document.createElement('a');
ele.className = 'dz-media-action';
ele.style.top = (Math.floor(actionsIndex % maxRows) * size - (Math.floor(actionsIndex % maxRows)) - 1) + 'px';
let right;
const col = Math.floor(actionsIndex / maxRows);
if (col === 0) {
right = -size;
} else {
right = -((1 + Math.floor((actionsIndex) / maxRows)) * size) - (col * colMargin);
}
ele.style.right = right + 'px';
ele.href = 'javascript:undefined;';
ele.title = item.caption;
ele.innerText = "";//item.caption;
const nameEle = $(dz).find('[data-dz-name]');
ele._file_name = nameEle.text();
ele._dz_preview = dz;
$(that).append(ele);
const i = document.createElement("i");
ele.appendChild(i);
i.className = 'fa fa-fw ' + faIcon;
ele.addEventListener('click', () => _onMediaAction(item.actionId, nameEle.text(), dz));
//Invisible div to maintain hover when the mouseover is on the column margin
const ele2 = document.createElement('div');
ele2.className = 'dz-media-action';
ele2.style.background = 'transparent';
ele2.style.right = (right + colMargin) + "px";
ele2.style.top = ele.style.top;
$(ele2).insertBefore(ele);
});
dz.style.marginRight = 15 + Math.floor(actionsIndex / maxRows) * (size + colMargin) + "px";
}
});
}, 1000);
@@ -1,47 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 TwelveTone LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
function onMediaAction_SampleAction1(actionId, mediaName, mediaElement) {
console.log(`Media action ${actionId} was selected.`);
alert(`Media action ${actionId} was selected.`);
submitMediaAction(actionId, mediaName, `${actionId} was selected`, function (result) {
console.log(result);
});
}
function onMediaAction_SampleAction2(actionId, mediaName, mediaElement) {
console.log(`Media action ${actionId} was selected.`);
alert(`Media action ${actionId} was selected.`);
submitMediaAction(actionId, mediaName, `${actionId} was selected`, function (result) {
console.log(result);
});
}
function onMediaAction_SampleAction3(actionId, mediaName, mediaElement) {
console.log(`Media action ${actionId} was selected.`);
alert(`Media action ${actionId} was selected.`);
submitMediaAction(actionId, mediaName, `${actionId} was selected`, function (result) {
console.log(result);
});
}
@@ -1,29 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 TwelveTone LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// Sample Form Action
function onMediaAction_SampleForm(actionId, mediaName, mediaElement) {
alert("This is a sample form.");
submitMediaAction(actionId, mediaName, '{"key1":"value1", "key2":"value2"}');
}
@@ -1,66 +0,0 @@
#
# The MIT License (MIT)
#
# Copyright (c) 2018 TwelveTone LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
name: Admin Media Actions
version: 1.0.4
description: A plugin that extends Grav with an API for adding actions to media items in the page media bin. This plugin is required by other plugins that add media actions.
icon: plug
author:
name: TwelveTone LLC
email: info@twelvetone.tv
homepage: https://www.twelvetone.tv/docs/developer-tools/grav-plugins/grav-admin-media-actions-plugin
keywords: grav, plugin, admin, media, action
bugs: https://github.com/Flamenco/grav-admin-media-actions/issues
docs: https://www.twelvetone.tv/docs/developer-tools/grav-plugins/grav-admin-media-actions-plugin
license: MIT
dependencies:
- { name: grav, version: '>=1.0.0' }
- { name: admin, version: '>=1.0.0' }
form:
validation: strict
fields:
enabled:
type: toggle
label: Plugin status
highlight: 1
default: 0
options:
1: Enabled
0: Disabled
validate:
type: bool
show_samples:
type: toggle
label: Show sample actions
description: For testing purposes, several actions will be added to each media item.
highlight: 0
default: 0
options:
1: Enabled
0: Disabled
validate:
type: bool
@@ -1,17 +0,0 @@
plugins {
id("com.github.hierynomus.license").version("0.14.0")
}
apply plugin:'java'
sourceSets {
grav {
resources {
srcDirs += "."
include "**/*.yaml"
include "**/*.php"
include "**/*.css"
include "**/*.js"
include "**/*.twig"
}
}
}
@@ -1,29 +0,0 @@
<!--A generic form dialog that contains a loading indicator, submit button, and message -->
<div class="remodal" data-remodal-id="modal-admin-media-actions" data-remodal-options="hashTracking: false">
<form method="post" onsubmit='return false;'>
{% for field in fields %}
{% if field.type %}
{% set value = data.value(field.name) %}
<div class="block block-{{field.type}}">
{% include ["forms/fields/#{field.type}/#{field.type}.html.twig", 'forms/fields/text/text.html.twig'] %}
</div>
{% endif %}
{% endfor %}
<div class="block page-media-info hidden">
<div class="form-field grid">{{ "Page Info" }}</div>
</div>
<div class="block non-page-media-info hidden">
<div class="form-field grid">{{ "Non-Page Info" }}</div>
</div>
<div class="button-bar">
<div class="loading">
{{ "Moving" }}... <i class="fa fa-spinner fa-spin"></i>
</div>
<button class="button primary" style="visibility: hidden">{{ "PLUGIN_ADMIN.CONTINUE"|tu }}</button>
</div>
</form>
</div>
@@ -1,30 +0,0 @@
# v1.0.4
## 12/11/2018
1. [](#bugfix)
* Update addInlineJs load order
# v1.0.3
## 2/24/2018
1. [](#new)
* Check that dependencies are enabled before loading
# v1.0.2
## 2/24/2018
1. [](#new)
* Check for dependencies before loading
# v1.0.1
## 2/14/2018
1. [](#new)
* Update bugs URL
* Update addAction signature
# v1.0.0
## 1/24/2018
1. [](#initial)
*
-21
View File
@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2018 TwelveTone LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-27
View File
@@ -1,27 +0,0 @@
# Admin Media Move Plugin
The **Admin Media Move** Plugin is for [Grav CMS](http://github.com/getgrav/grav). A plugin which adds the option to move media files in the page bin to another page.
## Installation
Installing the Admin Media Move plugin can be done in one of two ways. The GPM (Grav Package Manager) installation method enables you to quickly and easily install the plugin with a simple terminal command, while the manual method enables you to do so via a zip file.
### GPM Installation (Preferred)
The simplest way to install this plugin is via the [Grav Package Manager (GPM)](http://learn.getgrav.org/advanced/grav-gpm) through your system's terminal (also called the command line). From the root of your Grav install type:
bin/gpm install admin-media-move
This will install the Admin Media Move plugin into your `/user/plugins` directory within Grav. Its files can be found under `/your/site/grav/user/plugins/admin-media-move`.
### Manual Installation
To install this plugin, just download the zip version of this repository and unzip it under `/your/site/grav/user/plugins`. Then, rename the folder to `admin-media-move`. You can find these files on [GitHub](https://github.com) or via [GetGrav.org](http://getgrav.org/downloads/plugins#extras).
You should now have all the plugin files under
/your/site/grav/user/plugins/admin-media-move
> NOTE: This plugin is a modular component for Grav which requires [Grav](http://github.com/getgrav/grav) and the [Admin](https://github.com/getgrav/grav-plugin-admin) plugin to operate.
## Usage
@@ -1,234 +0,0 @@
<?php
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 TwelveTone LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Grav\Plugin;
use Grav\Common\Grav;
use Grav\Common\Plugin;
/**
* Class AdminMediaMovePlugin
* @package Grav\Plugin
*/
class AdminMediaMovePlugin extends Plugin
{
const ROUTE = '/admin-media-move';
public static function getSubscribedEvents()
{
return [
'onPluginsInitialized' => ['onPluginsInitialized', 0]
];
}
public function getPath()
{
return '/' . trim($this->grav['admin']->base, '/') . '/' . trim(self::ROUTE, '/');
}
public function buildBaseUrl()
{
$ret = rtrim($this->grav['uri']->rootUrl(false), '/') . '/' . trim($this->getPath(), '/');
return $ret;
}
public function onPluginsInitialized()
{
if (!$this->isAdmin() || !$this->grav['user']->authenticated) {
return;
}
if ($this->grav['uri']->path() == $this->getPath()) {
return;
}
if (!self::_checkDependencies($this)) {
return;
}
$this->enable([
'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0],
'onPagesInitialized' => ['onTwigExtensions', 0],
]);
$this->grav['media-actions']->addAction([
'actionId' => "MediaMove",
'caption' => "Move",
'icon' => "arrows",
'handler' => function ($page, $mediaName, $payload) {
$destination_route = $payload['destination_route'];
if (!$destination_route || !$page || !$mediaName || !$payload) {
$this->outputError("Invalid input");
}
$basePath = $page->path() . DS;
$filePath = $basePath . $mediaName;
if (!file_exists($filePath)) {
$this->outputError("Media file not found");
}
// Locate the target page
$targetPage = $this->grav['pages']->find($destination_route);
if (!$targetPage) {
$this->outputError("Page for route $destination_route not found");
}
$path = $targetPage->path();
try {
rename($filePath, "$path/$mediaName");
$this->grav['log']->info("Moved media file '$mediaName' to '$path'");
} catch (\Exception $e) {
$this->outputError("Could not move file: " . $e);
}
$ret = [
"error" => false
];
// Redirects will not work for fetch, so send destination url in result
if (get($payload, "go", false)) {
// Get the admin edit-page url
//$url = $this->grav['twig']->twig->getExtension('Grav\Plugin\Admin\AdminTwigExtension')->getPageUrl($this, $targetPage);
$url = $this->grav['uri']->rootUrl(false) . "/admin/pages" . $targetPage->route();
$ret["destination_url"] = $url;
}
//header('HTTP/1.1 200 OK');
return $ret;
}
]);
}
public function onTwigTemplatePaths()
{
$this->grav['twig']->twig_paths[] = __DIR__ . '/templates';
}
public function onTwigExtensions()
{
$page = $this->grav['admin']->page(true);
if (!$page) {
return;
}
$modal_move = $this->grav['twig']->twig()->render('move-modal.twig.html', $this->config->get('plugins.admin-media-move.modal_move'));
$jsConfig_move = [
'MODAL' => $modal_move
];
$this->grav['assets']->addInlineJs('var ADMIN_ADDON_MEDIA_MOVE = ' . json_encode($jsConfig_move) . ';', -1000);
$this->grav['assets']->addJs('plugin://admin-media-move/assets/media_move_action.js', -1000, false);
}
public function outputError($msg)
{
header('HTTP/1.1 400 Bad Request');
die(json_encode(['error' => ['msg' => $msg]]));
}
/**
* Checks plugin dependencies. Call this after all plugins have been loaded and are enabled.
*
* @param $plugin
* @param $issues array Receives issues as strings. If null, grav['messages'] is used.
* @return bool true if dependencies are met.
*/
public static function _checkDependencies($plugin, &$issues = null)
{
$grav = Grav::instance();
$errors = 0;
$messages = $grav['messages'];
$plugins = $grav['plugins'];
$deps = $plugin->getBlueprint()->dependencies;
if ($deps) {
foreach ($deps as $dep) {
$name = $dep['name'];
if ($name === 'grav') {
//TODO check grav version
continue;
}
$version = $dep['version'];
if (!preg_match("#^([<>=]+)?(.*)#", $version, $m)) {
continue;
}
$compare = $m[1];
$version = $m[2];
if (!$compare) {
$compare = '=';
}
$found = $plugins->get($name);
if (!$found) {
$msg = "Missing Dependency: '$name'";
if (is_array($issues)) {
$issues[] = $msg;
} else {
$messages->add($msg, 'error');
}
$errors++;
continue;
}
if (!$grav['config']->get("plugins.$name.enabled")) {
//BUG admin should always be enabled if installed
if ($name !== 'admin') {
$msg = "Dependency Not Enabled: '$name'";
if (is_array($issues)) {
$issues[] = $msg;
} else {
$messages->add($msg, 'error');
}
$errors++;
continue;
}
}
$realVersion = $found->blueprints()->version;
if (!version_compare($realVersion, $version, $compare)) {
$msg = "Missing Dependency: '$name' $version";
if (is_array($issues)) {
$issues[] = $msg;
} else {
$messages->add($msg, 'error');
}
$errors++;
continue;
}
}
}
if ($errors > 0) {
$msg = "Plugin '$plugin->name' was not loaded due to dependency issues";
if (is_array($issues)) {
$issues[] = $msg;
} else {
$messages->add($msg, 'error');
}
}
return $errors === 0;
}
}
@@ -1,44 +0,0 @@
#
# The MIT License (MIT)
#
# Copyright (c) 2018 TwelveTone LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
enabled: true
modal_move:
fields:
- type: section
title: "Move Media"
- type: text
label: Filename
name: file_name
readonly: true
- type: pages
label: Destination Page
name: destination_page
- type: text
label: Destination Route
name: destination_route
autofocus: on
@@ -1,70 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 TwelveTone LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// This must be in a function call for remodal to register it
$(function () {
$('body').append(ADMIN_ADDON_MEDIA_MOVE.MODAL);
});
function onMediaAction_MediaMove(actionId, mediaName, mediaElement) {
var modal = $.remodal.lookup[$('[data-remodal-id=modal-admin-media-move]').data('remodal')];
modal.open();
var $modal = modal.$modal;
// Populate fields
$('[name=file_name]', $modal).val(mediaName);
$('[name=destination_route]', $modal).val("");
$('[name=destination_page]', $modal).val("");
// Reset loading state
$('.loading', $modal).addClass('hidden');
$('.button', $modal).removeClass('hidden').css('visibility', 'visible');
$(document).off('click', '[data-remodal-id=modal-admin-media-move] .button');
$(document).on('click', '[data-remodal-id=modal-admin-media-move] .button', function (e) {
var destination_route = $('[name=destination_route]').val();
if (!destination_route) {
destination_route = $('[name=destination_page]').val();
}
if (destination_route) {
const payload = {
destination_route
};
if (e.target.name === 'move_and_go') {
payload.go = true;
}
const callback = function (result) {
if (result.error) {
alert(result.error.msg);
} else {
$(mediaElement).remove();
if (payload.go) {
window.location = result.result.destination_url;
}
}
};
submitMediaAction(actionId, mediaName, payload, callback, modal);
}
});
}
@@ -1,55 +0,0 @@
#
# The MIT License (MIT)
#
# Copyright (c) 2018 TwelveTone LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
name: Admin Media Move
version: 1.0.4
description: Moves media from one page to another.
icon: plug
author:
name: TwelveTone LLC
email: info@twelvetone.tv
homepage: https://www.twelvetone.tv/docs/developer-tools/grav-plugins/grav-admin-media-move-plugin
keywords: grav, plugin, admin, media
bugs: https://github.com/Flamenco/grav-admin-media-move
docs: https://www.twelvetone.tv/docs/developer-tools/grav-plugins/grav-admin-media-move-plugin
license: MIT
dependencies:
- { name: grav, version: '>=1.0.0' }
- { name: admin, version: '>=1.0.0' }
- { name: admin-media-actions, version: '>=1.0.0' }
form:
validation: strict
fields:
enabled:
type: toggle
label: Plugin status
highlight: 1
default: 0
options:
1: Enabled
0: Disabled
validate:
type: bool
@@ -1,17 +0,0 @@
plugins {
id("com.github.hierynomus.license").version("0.14.0")
}
apply plugin:'java'
sourceSets {
grav {
resources {
srcDirs += "."
include "**/*.yaml"
include "**/*.php"
include "**/*.css"
include "**/*.js"
include "**/*.twig"
}
}
}
@@ -1,23 +0,0 @@
<div class="remodal" data-remodal-id="modal-admin-media-move" data-remodal-options="hashTracking: false">
<form method="post" onsubmit='return false;'>
{% for field in fields %}
{% if field.type %}
{% set value = data.value(field.name) %}
<div class="block block-{{field.type}}">
{% include ["forms/fields/#{field.type}/#{field.type}.html.twig", 'forms/fields/text/text.html.twig'] %}
</div>
{% endif %}
{% endfor %}
<div class="form-field grid">Select a destination page or enter the destination page route.</div>
<div class="button-bar">
<div class="loading">
{{ "Moving" }}... <i class="fa fa-spinner fa-spin"></i>
</div>
<button class="button primary" style="visibility: hidden" name="move">{{ "Move" }}</button>
<button class="button" style="visibility: hidden" name="move_and_go">{{ "Move And Go" }}</button>
</div>
</form>
</div>
@@ -1,32 +0,0 @@
# v1.0.4
## 12/11/2018
1. [](#feature)
* Update documentation
# v1.0.3
## 2/24/2018
1. [](#new)
* Check that dependencies are enabled before loading
# v1.0.2
## 2/24/2018
1. [](#new)
* Check for dependencies before loading
# v1.0.1
## 1/25/2018
1. [](#new)
* Add dialog
* Add quicksend option
* Enforce extension, image, and file-rename options
* Refactor project layout
# v1.0.0
## 1/24/2018
1. [](#initial)
*
-21
View File
@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2018 TwelveTone LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -1,29 +0,0 @@
# Admin Media Replace Plugin
The **Admin Media Replace** Plugin is for [Grav CMS](http://github.com/getgrav/grav). A plugin which adds the option to replace media.
## Installation
Installing the Admin Media Replace plugin can be done in one of two ways. The GPM (Grav Package Manager) installation method enables you to quickly and easily install the plugin with a simple terminal command, while the manual method enables you to do so via a zip file.
### GPM Installation (Preferred)
The simplest way to install this plugin is via the [Grav Package Manager (GPM)](http://learn.getgrav.org/advanced/grav-gpm) through your system's terminal (also called the command line). From the root of your Grav install type:
bin/gpm install admin-media-replace
This will install the Admin Media Replace plugin into your `/user/plugins` directory within Grav. Its files can be found under `/your/site/grav/user/plugins/admin-media-replace`.
### Manual Installation
To install this plugin, just download the zip version of this repository and unzip it under `/your/site/grav/user/plugins`. Then, rename the folder to `admin-media-replace`. You can find these files on [GitHub](https://github.com) or via [GetGrav.org](http://getgrav.org/downloads/plugins#extras).
You should now have all the plugin files under
/your/site/grav/user/plugins/admin-media-replace
> NOTE: This plugin is a modular component for Grav which requires [Grav](http://github.com/getgrav/grav) and the [Admin](https://github.com/getgrav/grav-plugin-admin) plugin to operate.
## Usage
See [Official Documentation](https://www.twelvetone.tv/docs/developer-tools/grav-plugins/admin-media-replace-plugin)
@@ -1,297 +0,0 @@
<?php
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 TwelveTone LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Grav\Plugin;
use Grav\Common\Grav;
use Grav\Common\Page\Media;
use Grav\Common\Plugin;
use Grav\Common\Utils;
include_once 'classes/DialogUtil.php';
function array_get($arr, $key, $default = null)
{
if (!isset($arr[$key])) {
if ($default === null) {
throw new \Exception("A key is missing: " . $key);
} else {
return $default;
}
}
return $arr[$key];
}
/**
* Class AdminMediaReplacePlugin
* @package Grav\Plugin
*/
class AdminMediaReplacePlugin extends Plugin
{
const ROUTE = '/admin-media-replace';
public static function getSubscribedEvents()
{
return [
'onPluginsInitialized' => ['onPluginsInitialized', 0]
];
}
public function onPluginsInitialized()
{
if (!$this->isAdmin() || !$this->grav['user']->authenticated) {
return;
}
if (!self::_checkDependencies($this)) {
return;
}
$this->enable([
'onAdminTwigTemplatePaths' => ['onAdminTwigTemplatePaths', 0],
'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0],
'onTwigInitialized' => ['onTwigInitialized', 0],
'onTwigExtensions' => ['onTwigExtensions', -1],
'onPageNotFound' => ['onPageNotFound', 1],
]);
$this->grav['media-actions']->addAction([
'actionId' => "MediaReplace",
'caption' => "Replace",
'icon' => "exchange",
'handler' => function ($page, $mediaName, $payload) {
$ret = [
"error" => false
];
return $ret;
}
]);
}
public function onPageNotFound($e)
{
if (!$this->isAdmin()) {
return;
}
$route = $this->grav['admin']->location . "/" . $this->grav['admin']->route;
switch ($route) {
case "admin-media-replace/replace":
try {
$filename = array_get($_POST, "media-new-filename");
$route = array_get($_POST, "media-route");
$media = array_get($_POST, "media-filename");
$media_rename = array_get($_POST, "media-rename", "1") === "1";
$require_image = array_get($_POST, "media-require-image", "1") === "1";
$match_extension = array_get($_POST, "media-match-extension", "1") === "1";
$page = $this->grav['pages']->find($route);
if (!$page) {
throw new \Exception("Page not found.");
}
$mediaPath = $page->path() . "/" . $media;
if (!is_file($mediaPath)) {
throw new \Exception("Media not found.");
}
$tmp_name = $_FILES['mediaupload']['tmp_name'];
if ($match_extension) {
if (basename($filename) !== basename($media)) {
throw new \Exception("Media extensions do not match.");
}
}
if ($require_image) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['mediaupload']['tmp_name']);
finfo_close($finfo);
if (!Utils::startsWith($mime, "image/")) {
throw new \Exception("Media must be an image.");
}
}
if ($media_rename) {
// overwrite current file
$finalName = basename($mediaPath);
} else {
// delete current file
unlink($page->path() . '/' . $media);
$finalName = basename($filename);
}
move_uploaded_file($tmp_name, $page->path() . '/' . $finalName);
//$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
// basename() may prevent filesystem traversal attacks;
// further validation/sanitation of the filename may be appropriate
//$name = basename($_FILES["pictures"]["name"][$key]);
$media1 = new Media($page->path());
$medium = $media1[basename($finalName)];
$url = $medium->display($medium->get('extension') === 'svg' ? 'source' : 'thumbnail')->cropZoom(400, 300)->url();
$ret = ["thumbnail" => $url];
$ret['newName'] = $finalName;
// if (!$media_rename) {
// $ret['toast'] = "Refresh the page to update the new page media name.";
// }
die(json_encode($ret));
// Get original name
//$source = $medium->higherQualityAlternative()->get('filename');
//$media_list[$name] = ['url' => $medium->display($medium->get('extension') === 'svg' ? 'source' : 'thumbnail')->cropZoom(400, 300)->url(), 'size' => $medium->get('size'), 'metadata' => $metadata, 'original' => $source->get('filename')];
} catch
(\Exception $exception) {
// die(print_r($_SERVER));
die(json_encode(["error" => $exception->getMessage()]));
}
break;
}
}
public
function onTwigTemplatePaths()
{
$this->grav['twig']->twig_paths[] = __DIR__ . '/templates';
}
public
function onTwigInitialized()
{
$this->grav['assets']->addJs('plugin://admin-media-replace/assets/dialog_util.js', -1000, false);
$this->grav['assets']->addJs('plugin://admin-media-replace/assets/media_replace_action.js', -1000, false);
if ($this->config->get("plugins.admin-media-replace.quicksend", false)) {
$this->grav['assets']->addInlineJs("const _media_replace_isQuicksend = true;");
}
}
public
function onTwigExtensions()
{
if (!$this->isAdmin()) {
return;
}
addModalForm("MediaReplace", "generic-modal.twig.html");
}
public
function onAdminTwigTemplatePaths($event)
{
$event['paths'] = array_merge($event['paths'], [__DIR__ . '/templates']);
return $event;
}
public
function outputError($msg)
{
header('HTTP/1.1 400 Bad Request');
die(json_encode(['error' => ['msg' => $msg]]));
}
/**
* Checks plugin dependencies. Call this after all plugins have been loaded and are enabled.
*
* @param $plugin
* @param $issues array Receives issues as strings. If null, grav['messages'] is used.
* @return bool true if dependencies are met.
*/
public static function _checkDependencies($plugin, &$issues = null)
{
$grav = Grav::instance();
$errors = 0;
$messages = $grav['messages'];
$plugins = $grav['plugins'];
$deps = $plugin->getBlueprint()->dependencies;
if ($deps) {
foreach ($deps as $dep) {
$name = $dep['name'];
if ($name === 'grav') {
//TODO check grav version
continue;
}
$version = $dep['version'];
if (!preg_match("#^([<>=]+)?(.*)#", $version, $m)) {
continue;
}
$compare = $m[1];
$version = $m[2];
if (!$compare) {
$compare = '=';
}
$found = $plugins->get($name);
if (!$found) {
$msg = "Missing Dependency: '$name'";
if (is_array($issues)) {
$issues[] = $msg;
} else {
$messages->add($msg, 'error');
}
$errors++;
continue;
}
if (!$grav['config']->get("plugins.$name.enabled")) {
//BUG admin should always be enabled if installed
if ($name !== 'admin') {
$msg = "Dependency Not Enabled: '$name'";
if (is_array($issues)) {
$issues[] = $msg;
} else {
$messages->add($msg, 'error');
}
$errors++;
continue;
}
}
$realVersion = $found->blueprints()->version;
if (!version_compare($realVersion, $version, $compare)) {
$msg = "Missing Dependency: '$name' $version";
if (is_array($issues)) {
$issues[] = $msg;
} else {
$messages->add($msg, 'error');
}
$errors++;
continue;
}
}
}
if ($errors > 0) {
$msg = "Plugin '$plugin->name' was not loaded due to dependency issues";
if (is_array($issues)) {
$issues[] = $msg;
} else {
$messages->add($msg, 'error');
}
}
return $errors === 0;
}
}
@@ -1,26 +0,0 @@
#
# The MIT License (MIT)
#
# Copyright (c) 2018 TwelveTone LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
enabled: true
quicksend: false
@@ -1,55 +0,0 @@
/**
* A re-modal wrapper to simplify usage.
*/
function openModalDialog(remodalId) {
const dlgElement = $(`[data-remodal-id=${remodalId}]`);
const modal = $.remodal.lookup[dlgElement.data('remodal')];
modal.open();
$(dlgElement).find('input[temporary=true]').remove();
return {
show: function () {
modal.open();
},
close: function () {
modal.close();
},
/**
* Replaces a message listener
* @param selector
* @param message
* @param callback
*/
on: function (selector, message, callback) {
const found = dlgElement.find(selector);
found.off(message);
found.on(message, callback);
},
/**
*
* @param selector {string}
* @returns {element} The HTML element
*/
get: function (selector) {
const found = dlgElement.find(selector);
return found[0];
},
/**
*
* @param selector {string}
* @returns {jquery element}
*/
jget: function (selector) {
const found = dlgElement.find(selector);
return found;
},
setHiddenField: function (name, value, temporary = true) {
const form = $(dlgElement).find('form');
form.append(`<input type='hidden' temporary='${temporary}' name='${name}' value='${value}' />`);
}
}
// For getting/setting values
// var $modal = modal.$modal;
}
@@ -1,157 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 TwelveTone LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
//TODO refactor AJAX code
function onMediaAction_MediaReplace(actionId, mediaName, mediaElement) {
if (window._media_replace_isQuicksend) {
doQuicksend(actionId, mediaName, mediaElement);
return;
}
const form = openModalDialog('MediaReplace');
form.on('.button[name=cancel]', 'click', () => {
form.close();
});
form.on('.button[name=continue]', 'click', () => {
form.close();
const input = form.get('input[type=file]');
if (input.files.length === 0) {
return;
}
let file = input.files[0];
let data = new FormData();
data.append('mediaupload', file, file.name);
let xhr = new XMLHttpRequest();
xhr.open("POST", GravAdmin.config.base_url_relative + '/admin-media-replace/replace', true);
// xhr.setRequestHeader("X_FILENAME", file.name);
// Grav is stripping out X_ from $_SERVER
xhr.setRequestHeader("X-MEDIA-NEW-FILENAME", file.name);
xhr.setRequestHeader("X-MEDIA-ROUTE", '/' + GravAdmin.config.route);
xhr.setRequestHeader("X-MEDIA-FILENAME", mediaName);
data.append("media-new-filename", file.name);
data.append("media-route", '/' + GravAdmin.config.route);
data.append("media-filename", mediaName);
data.append("media-rename", form.jget('input[name=rename_file]:checked').val());
data.append("media-match-extension", form.jget('input[name=match_extension]:checked').val());
data.append("media-require-image", form.jget('input[name=require_image]:checked').val());
xhr.onload = function () {
//get response and show the uploading status
if (xhr.status === 200) {
let response = JSON.parse(xhr.responseText);
if (response.error) {
alert(response.error);
}
else if (response.thumbnail) {
let img = mediaElement.querySelector('img');
if (!img) {
return;
}
img.src = response.thumbnail + "?refresh=" + new Date().getTime();
if (response.toast) {
Grav.default.Utils.toastr.info(response.toast);
}
if (response.newName) {
const nameEle = $(mediaElement).find('[data-dz-name]');
nameEle.text(response.newName);
}
} else {
location.reload();
}
}
};
xhr.send(data);
});
}
function doQuicksend(actionId, mediaName, mediaElement) {
let form = document.querySelector('form[id="replace-media"]');
if (!form) {
form = $("<form id='replace-media' action='MediaReplace' method='post'>" +
"<input type='file' style='visibility: hidden; position: absolute; top: 0px; left: 0px; height: 0px; width: 0px;'></input>" +
"</form>")[0];
document.body.appendChild(form);
let input = form.querySelector('input[type=file]');
input.addEventListener('change', function () {
if (input.files.length !== 1) {
return;
}
let file = input.files[0];
let data = new FormData();
data.append('mediaupload', file, file.name);
let xhr = new XMLHttpRequest();
xhr.open("POST", GravAdmin.config.base_url_relative + '/admin-media-replace/replace', true);
// xhr.setRequestHeader("X_FILENAME", file.name);
// Grav is stripping out X_ from $_SERVER
xhr.setRequestHeader("X-MEDIA-NEW-FILENAME", file.name);
xhr.setRequestHeader("X-MEDIA-ROUTE", '/' + GravAdmin.config.route);
xhr.setRequestHeader("X-MEDIA-FILENAME", mediaName);
data.append("media-new-filename", file.name);
data.append("media-route", '/' + GravAdmin.config.route);
data.append("media-filename", mediaName);
data.append("media-rename", "1");
data.append("media-match-extension", "1");
data.append("media-require-image", "1");
xhr.onload = function () {
//get response and show the uploading status
if (xhr.status === 200) {
let response = JSON.parse(xhr.responseText);
if (response.error) {
alert(response.error);
}
else if (response.thumbnail) {
let img = mediaElement.querySelector('img');
if (!img) {
return;
}
img.src = response.thumbnail + "?refresh=" + new Date().getTime();
} else {
location.reload();
}
}
};
xhr.send(data);
});
}
let input = form.querySelector('input[type=file]');
input.click();
}
@@ -1,67 +0,0 @@
#
# The MIT License (MIT)
#
# Copyright (c) 2018 TwelveTone LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
name: Admin Media Replace
version: 1.0.4
description: Replaces media in the page media bin.
icon: plug
author:
name: TwelveTone LLC
email: info@twelvetone.tv
homepage: https://www.twelvetone.tv/docs/developer-tools/grav-plugins/grav-admin-media-replace-plugin
keywords: grav, plugin, admin, media
bugs: https://www.twelvetone.tv/docs/developer-tools/grav-plugins/grav-admin-media-replace-plugin
docs: https://www.twelvetone.tv/docs/developer-tools/grav-plugins/grav-admin-media-replace-plugin
license: MIT
dependencies:
- { name: grav, version: '>=1.0.0' }
- { name: admin, version: '>=1.0.0' }
- { name: admin-media-actions, version: '>=1.0.2' }
form:
validation: strict
fields:
enabled:
type: toggle
label: Plugin status
highlight: 1
default: 0
options:
1: Enabled
0: Disabled
validate:
type: bool
quicksend:
type: toggle
label: Quick send
description: Bypasses the upload dialog.
highlight: 1
default: 1
options:
1: Enabled
0: Disabled
validate:
type: bool
@@ -1,51 +0,0 @@
form:
fields:
foobar:
type: section
title: Replace Media
rename_file:
type: toggle
label: Rename file
description: Renames the uploaded file to the target file name. This includes the basename and extension.
highlight: 1
default: 1
options:
1: Yes
0: No
validate:
type: bool
require_image:
type: toggle
label: Require image
description: Require upload to be an image MIME type.
highlight: 0
default: 0
options:
1: Yes
0: No
validate:
type: bool
match_extension:
type: toggle
label: Match Extension
description: Require new file extension to match current file extension.
highlight: 0
default: 0
options:
1: Yes
0: No
validate:
type: bool
file:
type: singlefile
label: File
description: You can also drop a file on the <em>choose file button</em>.
spacer:
type: spacer
text: To bypass this dialog and simply <em>pick and send</em> the file using default values, go to the plugin settings and enable <em>quicksend</em>.
@@ -1,17 +0,0 @@
plugins {
id("com.github.hierynomus.license").version("0.14.0")
}
apply plugin:'java'
sourceSets {
grav {
resources {
srcDirs += "."
include "**/*.yaml"
include "**/*.php"
include "**/*.css"
include "**/*.js"
include "**/*.twig"
}
}
}
@@ -1,29 +0,0 @@
<?php
// Do not call until Grav 'twig' is initialized and the base twig extensions are loaded.
function addModalForm($jsid, $twigName)
{
//TODO parametize
$bpNewPage = new \Grav\Common\Data\Blueprint("media-replace.yaml");
$bpNewPage->setContext(__DIR__ . "/../blueprints");
$bpNewPage = $bpNewPage->load()->init();
$params = [];
$params["remodalId"] = $jsid;
$params["fields"] = $bpNewPage->toArray()['form']['fields'];
$grav = \Grav\Common\Grav::instance();
$rendered = $grav['twig']->twig()->render($twigName, $params);
$arr = [
'MODAL' => $rendered
];
$grav['assets']->addInlineJs("var $jsid = " . json_encode($arr) . ';', -1000, false);
$modalReg = "
$(function () {
$('body').append($jsid.MODAL);
});";
$grav['assets']->addInlineJs($modalReg, -999, false);
}
@@ -1,9 +0,0 @@
{% extends "forms/field.html.twig" %}
{% block label %}
{{ label ?: "File" }}
{% endblock %}
{% block input %}
<input name="{{ name }}" type="file" style="width: 100%"/>
{% endblock %}
@@ -1,22 +0,0 @@
<div class="remodal" data-remodal-id="{{remodalId}}" data-remodal-options="hashTracking: false">
<form method="post" onsubmit='return false;'>
{% for name, field in fields %}
{% if field.type %}
{% set value = data.value(name) %}
<div class="block block-{{field.type}}">
{% include ["forms/fields/#{field.type}/#{field.type}.html.twig", 'forms/fields/text/text.html.twig'] %}
</div>
{% endif %}
{% endfor %}
<div class="form-field grid">{{message}}</div>
<div class="button-bar">
<!--<div class="loading">-->
<!--{{ "Moving" }}... <i class="fa fa-spinner fa-spin"></i>-->
<!--</div>-->
<button class="button" style="visibility: visible" name="cancel">{{ "Cancel" }}</button>
<button class="button primary" style="visibility: visible" name="continue">{{ "Continue" }}</button>
</div>
</form>
</div>
-8
View File
@@ -1,8 +0,0 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: grav
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
custom: # Replace with a single custom sponsorship URL
-6
View File
@@ -1,6 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
File diff suppressed because it is too large Load Diff
-1
View File
@@ -1 +0,0 @@
Please read the <a href="https://github.com/getgrav/grav/blob/develop/CONTRIBUTING.md" target="_blank">Contributing Guidelines of the Grav Project</a>
-21
View File
@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2017 Grav
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-152
View File
@@ -1,152 +0,0 @@
# Grav Standard Administration Panel Plugin
This **admin plugin** for [Grav](https://github.com/getgrav/grav) is an HTML user interface that provides a convenient way to configure Grav and easily create and modify pages. This will remain a totally optional plugin, and is not in any way required or needed to use Grav effectively. In fact, the admin provides an intentionally limited view to ensure it remains easy to use and not overwhelming. I'm sure power users will still prefer to work with the configuration files directly.
![](assets/admin-dashboard.png)
# Features
* User login with automatic password encryption
* Forgot password functionality
* Logged-in-user management
* One click Grav core updates
* Dashboard with maintenance status, site activity and latest page updates
* Notifications system for latest news, blogs, and announcements
* Ajax-powered backup capability
* Ajax-powered clear-cache capability
* System configuration management
* Site configuration management
* Normal and Expert modes which allow editing via forms or YAML
* Page listing with filtering and search
* Page creation, editing, moving, copying, and deleting
* Powerful syntax highlighting code editor with instant Grav-powered preview
* Editor features, hot keys, toolbar, and distraction-free fullscreen mode
* Drag-n-drop upload of page media files including drag-n-drop placement in the editor
* One click theme and plugin updates
* Plugin manager that allows listing and configuration of installed plugins
* Theme manager that allows listing and configuration of installed themes
* GPM-powered installation of new plugins and themes
# Support
#### Support
We have tested internally, but we hope to use this public beta phase to identify, isolate, and fix issues related to the plugin to ensure it is as solid and reliable as possible.
For **live chatting**, please use the dedicated [Discord Chat Room](https://getgrav.org/discord) for discussions directly related to Grav.
For **bugs, features, improvements**, please ensure you [create issues in the admin plugin GitHub repository](https://github.com/getgrav/grav-plugin-admin).
# Installation
First ensure you are running the latest **Grav 1.6.7 or later**. This is required for the admin plugin to run properly (`-f` forces a refresh of the GPM index).
```
$ bin/gpm selfupgrade -f
```
The admin plugin actually requires the help of 3 other plugins, so to get the admin plugin to work you first need to install **admin**, **login**, **forms**, and **email** plugins. These are available via GPM, and because the plugin has dependencies you just need to proceed and install the admin plugin, and agree when prompted to install the others:
```
$ bin/gpm install admin
```
### Manual Installation
Manual installation is not the recommended method of installation, however, it is still possible to install the admin plugin manually. Basically, you need to download each of the following plugins individually:
* [admin](https://github.com/getgrav/grav-plugin-admin/archive/develop.zip)
* [login](https://github.com/getgrav/grav-plugin-login/archive/develop.zip)
* [form](https://github.com/getgrav/grav-plugin-form/archive/develop.zip)
* [email](https://github.com/getgrav/grav-plugin-email/archive/develop.zip)
Extract each archive file into your `user/plugins` folder, then ensure the folders are renamed to just `admin/`, `login/`, `form/`, and `email/`. Then proceed with the **Usage instructions below**.
# Usage
### Create User with CLI
After this you need to create a user account with admin privileges:
```
$ bin/plugin login new-user
```
### Create User Manually
Alternatively, you can create a user account manually, in a file called `user/accounts/admin.yaml`. This **filename** is actually the **username** that you will use to login. The contents will contain the other information for the user.
```
password: 'password'
email: 'youremail@mail.com'
fullname: 'Johnny Appleseed'
title: 'Site Administrator'
access:
admin:
login: true
super: true
```
Of course you should edit your `email`, `password`, `fullname`, and `title` to suit your needs.
> You can use any password when you manually put it in this `.yaml` file. However, when you change your password in the admin, it must contain at least one number and one uppercase and lowercase letter, and at least 8 or more characters.
# Accessing the Admin
By default, you can access the admin by pointing your browser to `http://yoursite.com/admin`. You can simply log in with the `username` and `password` set in the YAML file you configured earlier.
> After logging in, your **plaintext password** will be removed and replaced by an **encrypted** one.
# Standard Free & Paid Pro Versions
If you have been following the [blog](https://getgrav.org/blog), [Twitter](https://twitter.com/getgrav), [Discord chat](https://getgrav.org/discord), etc., you probably already know now that our intention is to provide two versions of this plugin.
The **standard free version**, is very powerful, and has more functionality than most commercial flat-file CMS systems.
We also intend to release in the near future a more feature-rich **pro version** that will include enhanced functionality, as well as some additional nice-to-have capabilities. This pro version will be a **paid** plugin the price of which is not yet 100% finalized.
# Admin Events
## General events
- onAdminRegisterPermissions - (admin)
- onAdminThemeInitialized
- onAdminPage - (page)
- onAdminMenu
- onAdminTwigTemplatePaths - (paths)
## Page specific events
- onAdminDashboard
- onAdminTools - (tools)
- onAdminLogFiles - (logs)
- onAdminGenerateReports - (reports)
## Tasks
- onAdminControllerInit - (controller)
- onAdminTaskExecute - (controller, method)
## Editing
- onAdminData
- onAdminSave - (object)
- onAdminAfterSave - (object)
## Pages
- onAdminPageTypes - (types)
- onAdminModularPageTypes
- onAdminSave - (page)
- onAdminAfterSaveAs - (path)
- onAdminAfterSave - (page)
- onAdminAfterDelete - (page)
- onAdminAfterAddMedia - (page)
- onAdminAfterDelMedia - (page)
- onAdminCreatePageFrontmatter - (header, data)
# Running Tests
First install the dev dependencies by running `composer update` from the Grav root.
Then `composer test` will run the Unit Tests, which should be always executed successfully on any site.
-6
View File
@@ -1,6 +0,0 @@
# Upgrading to Admin 1.10
Twig:
* **Admin link**: When linking to another admin page, use `{{ admin_route('/config/site') }}` instead of any other method, such as `{{ base_url_relative }}/config/site` (fixes multi-language issues)
File diff suppressed because it is too large Load Diff
-84
View File
@@ -1,84 +0,0 @@
enabled: true
route: '/admin'
cache_enabled: true
theme: grav
logo_text: ''
body_classes: ''
content_padding: true
twofa_enabled: true
sidebar:
activate: tab
hover_delay: 100
size: auto
dashboard:
days_of_stats: 7
widgets_display:
dashboard-maintenance: true
dashboard-statistics: true
dashboard-notifications: true
dashboard-feed: true
dashboard-pages: true
pages:
show_parents: both
show_modular: true
session:
timeout: 1800
edit_mode: normal
frontend_preview_target: inline
show_github_msg: true
admin_icons: line-awesome
enable_auto_updates_check: false
notifications:
feed: true
dashboard: true
plugins: true
themes: true
popularity:
enabled: true
ignore: ['/test*','/modular']
history:
daily: 30
monthly: 12
visitors: 20
whitelabel:
quicktray_recompile: false
codemirror_theme: paper
codemirror_fontsize: md
codemirror_md_font: sans
logo_custom:
logo_login:
color_scheme:
accents:
primary-accent: button
secondary-accent: notice
tertiary-accent: critical
colors:
logo-bg: '#323640'
logo-link: '#FFFFFF'
nav-bg: '#3D424E'
nav-text: '#B7B9BD'
nav-link: '#ffffff'
nav-selected-bg: '#323640'
nav-selected-link: '#ffffff'
nav-hover-bg: '#434753'
nav-hover-link: '#ffffff'
toolbar-bg: '#ffffff'
toolbar-text: '#3D424E'
page-bg: '#F6F6F6'
page-text: '#6f7b8a'
page-link: '#0090D9'
content-bg: '#ffffff'
content-text: '#6f7b8a'
content-link: '#0090D9'
content-link2: '#da4b46'
content-header: '#414147'
content-tabs-bg: '#e6e6e6'
content-tabs-text: '#808080'
button-bg: '#0090D9'
button-text: '#ffffff'
notice-bg: '#06A599'
notice-text: '#ffffff'
update-bg: '#77559D'
update-text: '#ffffff'
critical-bg: '#F45857'
critical-text: '#ffffff'
Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 KiB

-781
View File
@@ -1,781 +0,0 @@
name: Admin Panel
slug: admin
type: plugin
version: 1.10.49.4
description: Adds an advanced administration panel to manage your site
icon: empire
author:
name: Team Grav
email: devs@getgrav.org
url: https://getgrav.org
homepage: https://github.com/getgrav/grav-plugin-admin
keywords: admin, plugin, manager, panel
bugs: https://github.com/getgrav/grav-plugin-admin/issues
docs: https://github.com/getgrav/grav-plugin-admin/blob/develop/README.md
license: MIT
dependencies:
- { name: grav, version: '>=1.7.49' }
- { name: form, version: '>=6.0.1' }
- { name: login, version: '>=3.7.8' }
- { name: email, version: '>=3.1.6' }
- { name: flex-objects, version: '>=1.2.0' }
form:
validation: loose
fields:
admin_tabs:
type: tabs
fields:
config_tab:
type: tab
title: PLUGIN_ADMIN.CONFIGURATION
fields:
Basics:
type: section
title: PLUGIN_ADMIN.BASICS
underline: false
enabled:
type: hidden
label: PLUGIN_ADMIN.PLUGIN_STATUS
highlight: 1
default: 0
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
cache_enabled:
type: toggle
label: PLUGIN_ADMIN.ADMIN_CACHING
help: PLUGIN_ADMIN.ADMIN_CACHING_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
twofa_enabled:
type: toggle
label: PLUGIN_LOGIN.2FA_TITLE
help: PLUGIN_LOGIN.2FA_ENABLED_HELP
default: 1
highlight: 1
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
route:
type: text
label: PLUGIN_ADMIN.ADMIN_PATH
size: medium
placeholder: ADMIN_PATH_PLACEHOLDER
help: ADMIN_PATH_HELP
logo_text:
type: text
label: PLUGIN_ADMIN.LOGO_TEXT
size: medium
placeholder: "Grav"
help: PLUGIN_ADMIN.LOGO_TEXT_HELP
content_padding:
type: toggle
label: PLUGIN_ADMIN.CONTENT_PADDING
help: PLUGIN_ADMIN.CONTENT_PADDING_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
body_classes:
type: text
label: PLUGIN_ADMIN.BODY_CLASSES
size: medium
help: PLUGIN_ADMIN.BODY_CLASSES_HELP
sidebar.activate:
type: select
label: PLUGIN_ADMIN.SIDEBAR_ACTIVATION
help: PLUGIN_ADMIN.SIDEBAR_ACTIVATION_HELP
size: small
default: tab
options:
tab: PLUGIN_ADMIN.SIDEBAR_ACTIVATION_TAB
hover: PLUGIN_ADMIN.SIDEBAR_ACTIVATION_HOVER
sidebar.hover_delay:
type: text
size: x-small
append: PLUGIN_ADMIN.SIDEBAR_HOVER_DELAY_APPEND
label: PLUGIN_ADMIN.SIDEBAR_HOVER_DELAY
default: 500
validate:
type: number
min: 1
sidebar.size:
type: select
label: PLUGIN_ADMIN.SIDEBAR_SIZE
help: PLUGIN_ADMIN.SIDEBAR_SIZE_HELP
size: medium
default: auto
options:
auto: PLUGIN_ADMIN.SIDEBAR_SIZE_AUTO
small: PLUGIN_ADMIN.SIDEBAR_SIZE_SMALL
theme:
type: hidden
label: PLUGIN_ADMIN.THEME
default: grav
edit_mode:
type: select
label: PLUGIN_ADMIN.EDIT_MODE
size: small
default: normal
options:
normal: PLUGIN_ADMIN.NORMAL
expert: PLUGIN_ADMIN.EXPERT
help: PLUGIN_ADMIN.EDIT_MODE_HELP
frontend_preview_target:
type: select
label: PLUGIN_ADMIN.FRONTEND_PREVIEW_TARGET
size: medium
default: inline
options:
inline: PLUGIN_ADMIN.FRONTEND_PREVIEW_TARGET_INLINE
_blank: PLUGIN_ADMIN.FRONTEND_PREVIEW_TARGET_NEW
_self: PLUGIN_ADMIN.FRONTEND_PREVIEW_TARGET_CURRENT
pages.show_parents:
type: select
size: medium
label: PLUGIN_ADMIN.PARENT_DROPDOWN
highlight: 1
options:
both: PLUGIN_ADMIN.PARENT_DROPDOWN_BOTH
folder: PLUGIN_ADMIN.PARENT_DROPDOWN_FOLDER
fullpath: PLUGIN_ADMIN.PARENT_DROPDOWN_FULLPATH
pages.parents_levels:
type: text
label: PLUGIN_ADMIN.PARENTS_LEVELS
size: small
help: PLUGIN_ADMIN.PARENTS_LEVELS_HELP
pages.show_modular:
type: toggle
label: PLUGIN_ADMIN.MODULAR_PARENTS
highlight: 1
default: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
help: PLUGIN_ADMIN.MODULAR_PARENTS_HELP
show_beta_msg:
type: hidden
show_github_msg:
type: toggle
label: PLUGIN_ADMIN.SHOW_GITHUB_LINK
highlight: 1
default: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
help: PLUGIN_ADMIN.SHOW_GITHUB_LINK_HELP
enable_auto_updates_check:
type: toggle
label: PLUGIN_ADMIN.AUTO_UPDATES
highlight: 1
default: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
help: PLUGIN_ADMIN.AUTO_UPDATES_HELP
session.timeout:
type: text
size: small
label: PLUGIN_ADMIN.TIMEOUT
append: GRAV.NICETIME.SECOND_PLURAL
help: PLUGIN_ADMIN.TIMEOUT_HELP
validate:
type: number
min: 1
hide_page_types:
type: select
size: large
label: PLUGIN_ADMIN.HIDE_PAGE_TYPES
classes: fancy
multiple: true
array: true
selectize:
create: true
data-options@: ['\Grav\Plugin\AdminPlugin::pagesTypes', true]
hide_modular_page_types:
type: select
size: large
label: PLUGIN_ADMIN.HIDE_MODULAR_PAGE_TYPES
classes: fancy
multiple: true
array: true
selectize:
create: true
data-options@: ['\Grav\Plugin\AdminPlugin::pagesModularTypes', true]
Dashboard:
type: section
title: PLUGIN_ADMIN.DASHBOARD
underline: true
widgets_display:
type: widgets
label: PLUGIN_ADMIN.WIDGETS_DISPLAY
validate:
type: array
Notifications:
type: section
title: PLUGIN_ADMIN.NOTIFICATIONS
underline: true
notifications.feed:
type: toggle
label: PLUGIN_ADMIN.FEED_NOTIFICATIONS
highlight: 1
default: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
help: PLUGIN_ADMIN.FEED_NOTIFICATIONS_HELP
notifications.dashboard:
type: toggle
label: PLUGIN_ADMIN.DASHBOARD_NOTIFICATIONS
highlight: 1
default: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
help: PLUGIN_ADMIN.DASHBOARD_NOTIFICATIONS_HELP
notifications.plugins:
type: toggle
label: PLUGIN_ADMIN.PLUGINS_NOTIFICATIONS
highlight: 1
default: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
help: PLUGIN_ADMIN.PLUGINS_NOTIFICATIONS_HELP
notifications.themes:
type: toggle
label: PLUGIN_ADMIN.THEMES_NOTIFICATIONS
highlight: 1
default: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
help: PLUGIN_ADMIN.THEMES_NOTIFICATIONS_HELP
customization_tab:
type: tab
title: PLUGIN_ADMIN.CUSTOMIZATION
fields:
whitelabel.logos:
type: section
underline: true
title: PLUGIN_ADMIN.LOGOS
whitelabel.logo_login:
type: file
label: PLUGIN_ADMIN.LOGIN_SCREEN_CUSTOM_LOGO_LABEL
destination: 'user://assets'
accept:
- image/*
whitelabel.logo_custom:
type: file
label: PLUGIN_ADMIN.TOP_LEFT_CUSTOM_LOGO_LABEL
destination: 'user://assets'
accept:
- image/*
codemirror_section:
type: section
underline: true
title: PLUGIN_ADMIN.CODEMIRROR
whitelabel.codemirror_theme:
type: select
label: PLUGIN_ADMIN.CODEMIRROR_THEME
default: paper
markdown: true
data-options@: '\Grav\Plugin\AdminPlugin::themeOptions'
description: PLUGIN_ADMIN.CODEMIRROR_THEME_DESC
whitelabel.codemirror_fontsize:
type: select
label: PLUGIN_ADMIN.CODEMIRROR_FONTSIZE
default: md
options:
sm: PLUGIN_ADMIN.CODEMIRROR_FONTSIZE_SM
md: PLUGIN_ADMIN.CODEMIRROR_FONTSIZE_MD
lg: PLUGIN_ADMIN.CODEMIRROR_FONTSIZE_LG
whitelabel.codemirror_md_font:
type: select
label: PLUGIN_ADMIN.CODEMIRROR_MD_FONT
default: sans
options:
sans: PLUGIN_ADMIN.CODEMIRROR_MD_FONT_SANS
mono: PLUGIN_ADMIN.CODEMIRROR_MD_FONT_MONO
customization_section:
type: section
underline: true
title: PLUGIN_ADMIN.CUSTOMIZATION
whitelabel.quicktray_recompile:
type: toggle
label: PLUGIN_ADMIN.QUICKTRAY_RECOMPILE
help: PLUGIN_ADMIN.QUICKTRAY_RECOMPILE_HELP
highlight: 0
default: 0
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
whitelabel.color_scheme.name:
type: text
label: PLUGIN_ADMIN.COLOR_SCHEME_NAME
help: PLUGIN_ADMIN.COLOR_SCHEME_NAME_HELP
placeholder: PLUGIN_ADMIN.COLOR_SCHEME_NAME_PLACEHOLDER
themes-preview:
type: themepreview
ignore: true;
label: PLUGIN_ADMIN.PRESETS
style: vertical
colorschemes:
type: colorscheme
label: PLUGIN_ADMIN.COLOR_SCHEME_LABEL
style: vertical
help: PLUGIN_ADMIN.COLOR_SCHEME_HELP
fields:
whitelabel.color_scheme.colors.logo-bg:
type: colorscheme.color
default: '#1e333e'
help: PLUGIN_ADMIN.LOGO_BG_HELP
whitelabel.color_scheme.colors.logo-link:
type: colorscheme.color
default: '#ffffff'
help: PLUGIN_ADMIN.LOGO_LINK_HELP
whitelabel.color_scheme.colors.nav-bg:
type: colorscheme.color
default: '#253a47'
help: PLUGIN_ADMIN.NAV_BG_HELP
whitelabel.color_scheme.colors.nav-text:
type: colorscheme.color
default: '#afc7d5'
help: PLUGIN_ADMIN.NAV_TEXT_HELP
whitelabel.color_scheme.colors.nav-link:
type: colorscheme.color
default: '#d1dee7'
help: PLUGIN_ADMIN.NAV_LINK_HELP
whitelabel.color_scheme.colors.nav-selected-bg:
type: colorscheme.color
default: '#2d4d5b'
help: PLUGIN_ADMIN.NAV_SELECTED_BG_HELP
whitelabel.color_scheme.colors.nav-selected-link:
type: colorscheme.color
default: '#ffffff'
help: PLUGIN_ADMIN.NAV_SELECTED_LINK_HELP
whitelabel.color_scheme.colors.nav-hover-bg:
type: colorscheme.color
default: '#1e333e'
help: PLUGIN_ADMIN.NAV_HOVER_BG_HELP
whitelabel.color_scheme.colors.nav-hover-link:
type: colorscheme.color
default: '#ffffff'
help: PLUGIN_ADMIN.NAV_HOVER_LINK_HELP
whitelabel.color_scheme.colors.toolbar-bg:
type: colorscheme.color
default: '#349886'
help: PLUGIN_ADMIN.TOOLBAR_BG_HELP
whitelabel.color_scheme.colors.toolbar-text:
type: colorscheme.color
default: '#ffffff'
help: PLUGIN_ADMIN.TOOLBAR_TEXT_HELP
whitelabel.color_scheme.colors.page-bg:
type: colorscheme.color
default: '#314d5b'
help: PLUGIN_ADMIN.PAGE_BG_HELP
whitelabel.color_scheme.colors.page-text:
type: colorscheme.color
default: '#81a5b5'
help: PLUGIN_ADMIN.PAGE_TEXT_HELP
whitelabel.color_scheme.colors.page-link:
type: colorscheme.color
default: '#aad9ed'
help: PLUGIN_ADMIN.PAGE_LINK_HELP
whitelabel.color_scheme.colors.content-bg:
type: colorscheme.color
default: '#eeeeee'
help: PLUGIN_ADMIN.CONTENT_BG_HELP
whitelabel.color_scheme.colors.content-text:
type: colorscheme.color
default: '#737c81'
help: PLUGIN_ADMIN.CONTENT_TEXT_HELP
whitelabel.color_scheme.colors.content-link:
type: colorscheme.color
default: '#0082ba'
help: PLUGIN_ADMIN.CONTENT_LINK_HELP
whitelabel.color_scheme.colors.content-link2:
type: colorscheme.color
default: '#da4b46'
help: PLUGIN_ADMIN.CONTENT_LINK2_HELP
whitelabel.color_scheme.colors.content-header:
type: colorscheme.color
default: '#314d5b'
help: PLUGIN_ADMIN.CONTENT_HEADER_HELP
whitelabel.color_scheme.colors.content-tabs-bg:
type: colorscheme.color
default: '#223a47'
help: PLUGIN_ADMIN.CONTENT_TABS_BG_HELP
whitelabel.color_scheme.colors.content-tabs-text:
type: colorscheme.color
default: '#d1dee7'
help: PLUGIN_ADMIN.CONTENT_TABS_TEXT_HELP
whitelabel.color_scheme.colors.content-highlight:
type: colorscheme.color
default: '#ffffd7'
help: PLUGIN_ADMIN.CONTENT_HIGHLIGHT_HELP
whitelabel.color_scheme.colors.button-bg:
type: colorscheme.color
default: '#41bea8'
help: PLUGIN_ADMIN.BUTTON_BG_HELP
whitelabel.color_scheme.colors.button-text:
type: colorscheme.color
default: '#ffffff'
help: PLUGIN_ADMIN.BUTTON_TEXT_HELP
whitelabel.color_scheme.colors.notice-bg:
type: colorscheme.color
default: '#00a6cf'
help: PLUGIN_ADMIN.NOTICE_BG_HELP
whitelabel.color_scheme.colors.notice-text:
type: colorscheme.color
default: '#ffffff'
help: PLUGIN_ADMIN.NOTICE_TEXT_HELP
whitelabel.color_scheme.colors.update-bg:
type: colorscheme.color
default: '#8f5aad'
help: PLUGIN_ADMIN.UPDATES_BG_HELP
whitelabel.color_scheme.colors.update-text:
type: colorscheme.color
default: '#ffffff'
help: PLUGIN_ADMIN.UPDATES_TEXT_HELP
whitelabel.color_scheme.colors.critical-bg:
type: colorscheme.color
default: '#da4b46'
help: PLUGIN_ADMIN.CRITICAL_BG_HELP
whitelabel.color_scheme.colors.critical-text:
type: colorscheme.color
default: '#ffffff'
help: PLUGIN_ADMIN.CRITICAL_TEXT_HELP
whitelabel.color_scheme.accents.primary-accent:
type: select
size: medium
classes: fancy
label: PLUGIN_ADMIN.PRIMARY_ACCENT_LABEL
help: PLUGIN_ADMIN.PRIMARY_ACCENT_HELP
options:
button: PLUGIN_ADMIN.BUTTON_COLORS
content: PLUGIN_ADMIN.CONTENT_COLORS
tabs: PLUGIN_ADMIN.TABS_COLORS
critical: PLUGIN_ADMIN.CRITICAL_COLORS
logo: PLUGIN_ADMIN.LOGO_COLORS
nav: PLUGIN_ADMIN.NAV_COLORS
notice: PLUGIN_ADMIN.NOTICE_COLORS
page: PLUGIN_ADMIN.PAGE_COLORS
toolbar: PLUGIN_ADMIN.TOOLBAR_COLORS
update: PLUGIN_ADMIN.UPDATE_COLORS
whitelabel.color_scheme.accents.secondary-accent:
type: select
size: medium
classes: fancy
label: PLUGIN_ADMIN.SECONDARY_ACCENT_LABEL
help: PLUGIN_ADMIN.SECONDARY_ACCENT_HELP
options:
button: PLUGIN_ADMIN.BUTTON_COLORS
content: PLUGIN_ADMIN.CONTENT_COLORS
tabs: PLUGIN_ADMIN.TABS_COLORS
critical: PLUGIN_ADMIN.CRITICAL_COLORS
logo: PLUGIN_ADMIN.LOGO_COLORS
nav: PLUGIN_ADMIN.NAV_COLORS
notice: PLUGIN_ADMIN.NOTICE_COLORS
page: PLUGIN_ADMIN.PAGE_COLORS
toolbar: PLUGIN_ADMIN.TOOLBAR_COLORS
update: PLUGIN_ADMIN.UPDATE_COLORS
whitelabel.color_scheme.accents.tertiary-accent:
type: select
size: medium
classes: fancy
label: PLUGIN_ADMIN.TERTIARY_ACCENT_LABEL
help: PLUGIN_ADMIN.TERTIARY_ACCENT_HELP
options:
button: PLUGIN_ADMIN.BUTTON_COLORS
content: PLUGIN_ADMIN.CONTENT_COLORS
tabs: PLUGIN_ADMIN.TABS_COLORS
critical: PLUGIN_ADMIN.CRITICAL_COLORS
logo: PLUGIN_ADMIN.LOGO_COLORS
nav: PLUGIN_ADMIN.NAV_COLORS
notice: PLUGIN_ADMIN.NOTICE_COLORS
page: PLUGIN_ADMIN.PAGE_COLORS
toolbar: PLUGIN_ADMIN.TOOLBAR_COLORS
update: PLUGIN_ADMIN.UPDATE_COLORS
whitelabel.custom_footer:
type: textarea
rows: 2
label: PLUGIN_ADMIN.CUSTOM_FOOTER
help: PLUGIN_ADMIN.CUSTOM_FOOTER_HELP
placeholder: PLUGIN_ADMIN.CUSTOM_FOOTER_PLACEHOLDER
whitelabel.custom_css:
label: PLUGIN_ADMIN.CUSTOM_CSS_LABEL
placeholder: PLUGIN_ADMIN.CUSTOM_CSS_PLACEHOLDER
help: PLUGIN_ADMIN.CUSTOM_CSS_HELP
type: editor
codemirror:
mode: 'css'
indentUnit: 2
autofocus: true
indentWithTabs: true
lineNumbers: true
styleActiveLine: true
whitelabel.custom_presets:
label: PLUGIN_ADMIN.CUSTOM_PRESETS
help: PLUGIN_ADMIN.CUSTOM_PRESETS_HELP
placeholder: PLUGIN_ADMIN.CUSTOM_PRESETS_PLACEHOLDER
type: editor
codemirror:
mode: 'yaml'
indentUnit: 2
autofocus: true
indentWithTabs: false
lineNumbers: true
styleActiveLine: true
gutters: ['CodeMirror-lint-markers']
lint: true
extras_tab:
type: tab
title: PLUGIN_ADMIN.EXTRAS
fields:
Popularity:
type: section
title: PLUGIN_ADMIN.POPULARITY
underline: true
popularity.enabled:
type: toggle
label: PLUGIN_ADMIN.VISITOR_TRACKING
highlight: 1
default: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
help: PLUGIN_ADMIN.VISITOR_TRACKING_HELP
dashboard.days_of_stats:
type: text
label: PLUGIN_ADMIN.DAYS_OF_STATS
append: days
size: x-small
default: 7
help: PLUGIN_ADMIN.DAYS_OF_STATS_HELP
validate:
type: int
popularity.ignore:
type: array
label: PLUGIN_ADMIN.IGNORE_URLS
size: large
help: PLUGIN_ADMIN.IGNORE_URLS_HELP
default: ['/test*','/modular']
value_only: true
placeholder_value: /ignore-this-route
popularity.history.daily:
type: hidden
label: PLUGIN_ADMIN.DAILY_HISTORY
default: 30
popularity.history.monthly:
type: hidden
label: PLUGIN_ADMIN.MONTHLY_HISTORY
default: 12
popularity.history.visitors:
type: hidden
label: PLUGIN_ADMIN.VISITORS_HISTORY
default: 20
MediaResize:
type: section
title: PLUGIN_ADMIN.MEDIA_RESIZE
underline: true
MediaResizeNote:
type: spacer
text: PLUGIN_ADMIN.PAGEMEDIA_RESIZER
markdown: true
pagemedia.resize_width:
type: number
size: x-small
append: PLUGIN_ADMIN.PIXELS
label: PLUGIN_ADMIN.RESIZE_WIDTH
default: 0
validate:
type: number
help: PLUGIN_ADMIN.RESIZE_WIDTH_HELP
pagemedia.resize_height:
type: number
size: x-small
append: PLUGIN_ADMIN.PIXELS
label: PLUGIN_ADMIN.RESIZE_HEIGHT
default: 0
validate:
type: number
help: PLUGIN_ADMIN.RESIZE_HEIGHT_HELP
pagemedia.res_min_width:
type: number
size: x-small
append: PLUGIN_ADMIN.PIXELS
label: PLUGIN_ADMIN.RES_MIN_WIDTH
default: 0
validate:
type: number
help: PLUGIN_ADMIN.RES_MIN_WIDTH_HELP
pagemedia.res_min_height:
type: number
size: x-small
append: PLUGIN_ADMIN.PIXELS
label: PLUGIN_ADMIN.RES_MIN_HEIGHT
default: 0
validate:
type: number
help: PLUGIN_ADMIN.RES_MIN_HEIGHT_HELP
pagemedia.res_max_width:
type: number
size: x-small
append: PLUGIN_ADMIN.PIXELS
label: PLUGIN_ADMIN.RES_MAX_WIDTH
default: 0
validate:
type: number
help: PLUGIN_ADMIN.RES_MAX_WIDTH_HELP
pagemedia.res_max_height:
type: number
size: x-small
append: PLUGIN_ADMIN.PIXELS
label: PLUGIN_ADMIN.RES_MAX_HEIGHT
default: 0
validate:
type: number
help: PLUGIN_ADMIN.RES_MAX_HEIGHT_HELP
pagemedia.resize_quality:
type: number
size: x-small
append: 0...1
label: PLUGIN_ADMIN.RESIZE_QUALITY
default: 0.8
validate:
type: number
step: 0.01
help: PLUGIN_ADMIN.RESIZE_QUALITY_HELP
@@ -1,43 +0,0 @@
rules:
slug:
pattern: '[a-zA-Zа-яA-Я0-9_\-]+'
min: 1
max: 200
form:
validation: loose
fields:
section:
type: section
title: PLUGIN_ADMIN.COPY_PAGE
title:
type: text
label: PLUGIN_ADMIN.PAGE_TITLE
help: PLUGIN_ADMIN.PAGE_TITLE_HELP
validate:
required: true
folder:
type: text
label: PLUGIN_ADMIN.FOLDER_NAME
help: PLUGIN_ADMIN.FOLDER_NAME_HELP
validate:
rule: slug
required: true
header.published:
id: move-header-published
type: toggle
label: PLUGIN_ADMIN.PUBLISHED
help: PLUGIN_ADMIN.PUBLISHED_HELP
highlight: ''
default: ''
size: medium
options:
'': PLUGIN_ADMIN.AUTO
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
@@ -1,52 +0,0 @@
rules:
slug:
pattern: '[a-zA-Zа-яA-Я0-9_\-]+'
min: 1
max: 200
form:
validation: loose
fields:
section:
type: section
title: PLUGIN_ADMIN.ADD_MODULE_CONTENT
title:
type: text
label: PLUGIN_ADMIN.PAGE_TITLE
validate:
required: true
folder:
type: text
label: PLUGIN_ADMIN.FOLDER_NAME
validate:
rule: slug
required: true
route:
type: parents
label: PLUGIN_ADMIN.PAGE
classes: fancy
validate:
required: true
name:
type: select
classes: fancy
label: PLUGIN_ADMIN.MODULE_TEMPLATE
help: PLUGIN_ADMIN.PAGE_FILE_HELP
default: default
data-options@: '\Grav\Plugin\AdminPlugin::pagesModularTypes'
validate:
required: true
modular:
type: hidden
default: 1
validate:
type: bool
blueprint:
type: blueprint
@@ -1,104 +0,0 @@
rules:
slug:
pattern: '[a-zA-Zа-яA-Я0-9_\-]+'
min: 1
max: 200
form:
validation: loose
fields:
tabs:
type: tabs
active: 1
fields:
content:
type: tab
title: PLUGIN_ADMIN.CONTENT
fields:
xss_check:
type: xss
frontmatter:
classes: frontmatter
type: editor
label: PLUGIN_ADMIN.FRONTMATTER
autofocus: true
codemirror:
mode: 'yaml'
indentUnit: 4
autofocus: true
indentWithTabs: false
lineNumbers: true
styleActiveLine: true
gutters: ['CodeMirror-lint-markers']
lint: true
content:
type: markdown
header.media_order:
type: pagemedia
label: PLUGIN_ADMIN.PAGE_MEDIA
options:
type: tab
title: PLUGIN_ADMIN.OPTIONS
fields:
columns:
type: columns
fields:
column1:
type: column
fields:
ordering:
type: toggle
label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX
help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
folder:
type: text
label: PLUGIN_ADMIN.FILENAME
validate:
rule: slug
required: true
route:
type: parents
label: PLUGIN_ADMIN.PARENT
classes: fancy
validate:
required: true
name:
type: select
classes: fancy
label: PLUGIN_ADMIN.MODULE_TEMPLATE
default: default
data-options@: '\Grav\Plugin\AdminPlugin::pagesModularTypes'
validate:
required: true
column2:
type: column
fields:
order:
type: order
label: PLUGIN_ADMIN.ORDERING
blueprint:
type: blueprint
@@ -1,5 +0,0 @@
form:
validation: loose
fields:
route:
type: hidden
@@ -1,62 +0,0 @@
rules:
slug:
pattern: '[a-zA-Zа-яA-Я0-9_\-]+'
min: 1
max: 200
form:
validation: loose
fields:
section:
type: section
title: PLUGIN_ADMIN.ADD_PAGE
title:
type: text
label: PLUGIN_ADMIN.PAGE_TITLE
help: PLUGIN_ADMIN.PAGE_TITLE_HELP
validate:
required: true
folder:
type: text
label: PLUGIN_ADMIN.FOLDER_NAME
help: PLUGIN_ADMIN.FOLDER_NAME_HELP
validate:
rule: slug
required: true
route:
type: parents
label: PLUGIN_ADMIN.PARENT_PAGE
classes: fancy
validate:
required: true
name:
type: select
classes: fancy
label: PLUGIN_ADMIN.PAGE_FILE
help: PLUGIN_ADMIN.PAGE_FILE_HELP
data-options@: '\Grav\Plugin\AdminPlugin::pagesTypes'
data-default@: '\Grav\Plugin\Admin\Admin::getLastPageName'
validate:
required: true
visible:
type: toggle
label: PLUGIN_ADMIN.VISIBLE
help: PLUGIN_ADMIN.VISIBLE_HELP
highlight: ''
default: ''
options:
'': PLUGIN_ADMIN.AUTO
1: PLUGIN_ADMIN.YES
0: PLUGIN_ADMIN.NO
validate:
type: bool
required: true
blueprint:
type: blueprint
@@ -1,31 +0,0 @@
rules:
slug:
pattern: '[a-zA-Zа-яA-Я0-9_\-]+'
min: 1
max: 200
form:
validation: loose
fields:
section:
type: section
title: PLUGIN_ADMIN.ADD_FOLDER
folder:
type: text
label: PLUGIN_ADMIN.FOLDER_NAME
help: PLUGIN_ADMIN.FOLDER_NAME_HELP
validate:
rule: slug
required: true
route:
type: parents
label: PLUGIN_ADMIN.PARENT_PAGE
classes: fancy
validate:
required: true
blueprint:
type: blueprint
@@ -1,104 +0,0 @@
rules:
slug:
pattern: '[a-zA-Zа-яA-Я0-9_\-]+'
min: 1
max: 200
form:
validation: loose
fields:
tabs:
type: tabs
active: 1
fields:
content:
type: tab
title: PLUGIN_ADMIN.CONTENT
fields:
xss_check:
type: xss
frontmatter:
classes: frontmatter
type: editor
label: PLUGIN_ADMIN.FRONTMATTER
autofocus: true
codemirror:
mode: 'yaml'
indentUnit: 4
autofocus: true
indentWithTabs: false
lineNumbers: true
styleActiveLine: true
gutters: ['CodeMirror-lint-markers']
lint: true
content:
type: codemirror
header.media_order:
type: pagemedia
label: PLUGIN_ADMIN.PAGE_MEDIA
options:
type: tab
title: PLUGIN_ADMIN.OPTIONS
fields:
columns:
type: columns
fields:
column1:
type: column
fields:
ordering:
type: toggle
label: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX
help: PLUGIN_ADMIN.FOLDER_NUMERIC_PREFIX_HELP
highlight: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
folder:
type: text
label: PLUGIN_ADMIN.FOLDER_NAME
help: PLUGIN_ADMIN.FOLDER_NAME_HELP
validate:
rule: slug
required: true
route:
type: parents
label: PLUGIN_ADMIN.PARENT
classes: fancy
name:
type: select
classes: fancy
label: PLUGIN_ADMIN.DISPLAY_TEMPLATE
help: PLUGIN_ADMIN.DISPLAY_TEMPLATE_HELP
default: default
data-options@: '\Grav\Plugin\AdminPlugin::pagesTypes'
validate:
required: true
column2:
type: column
fields:
order:
type: order
label: PLUGIN_ADMIN.ORDERING
blueprint:
type: blueprint
@@ -1,34 +0,0 @@
rules:
slug:
pattern: '[a-zA-Zа-яA-Я0-9_\-]+'
min: 1
max: 200
form:
validation: loose
fields:
tabs:
type: tabs
active: 1
fields:
content:
type: tab
title: PLUGIN_ADMIN.CONTENT
fields:
frontmatter:
classes: frontmatter
type: editor
label: PLUGIN_ADMIN.FRONTMATTER
autofocus: true
codemirror:
mode: 'yaml'
indentUnit: 4
autofocus: true
indentWithTabs: false
lineNumbers: true
styleActiveLine: true
gutters: ['CodeMirror-lint-markers']
lint: true
@@ -1,36 +0,0 @@
title: PLUGIN_ADMIN.MEDIA
form:
validation: loose
fields:
'types':
name: medias
type: list
label: PLUGIN_ADMIN.MEDIA_TYPES
style: vertical
key: extension
controls: both
collapsed: true
fields:
.extension:
type: key
label: PLUGIN_ADMIN.FILE_EXTENSION
.type:
type: text
label: PLUGIN_ADMIN.TYPE
.thumb:
type: text
label: PLUGIN_ADMIN.THUMB
.mime:
type: text
label: PLUGIN_ADMIN.MIME_TYPE
validate:
type: lower
.image:
type: textarea
yaml: true
label: PLUGIN_ADMIN.IMAGE_OPTIONS
validate:
type: yaml
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,182 +0,0 @@
<?php
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2024 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Plugin\Admin;
use ArrayAccess;
use Exception;
use Grav\Common\Data\Blueprint;
use Grav\Common\Data\Data;
use Grav\Framework\Form\Interfaces\FormFlashInterface;
use Grav\Framework\Form\Interfaces\FormInterface;
use Grav\Framework\Form\Traits\FormTrait;
use InvalidArgumentException;
use JsonSerializable;
/**
* Class AdminForm
* @package Grav\Plugin\Admin
*/
class AdminForm implements FormInterface, JsonSerializable
{
use FormTrait;
/** @var string */
protected $nonce_name;
/** @var string */
protected $nonce_action;
/** @var callable */
protected $submitMethod;
/**
* AdminForm constructor.
*
* @param string $name
* @param array $options
*/
public function __construct(string $name, array $options)
{
$this->name = $name;
$this->nonce_name = $options['nonce_name'] ?? 'admin-nonce';
$this->nonce_action = $options['nonce_action'] ?? 'admin-form';
$this->setId($options['id'] ?? $this->getName());
$this->setUniqueId($options['unique_id'] ?? $this->getName());
$this->setBlueprint($options['blueprint']);
$this->setSubmitMethod($options['submit_method'] ?? null);
$this->setFlashLookupFolder('tmp://admin/forms/[SESSIONID]');
if (!empty($options['reset'])) {
$this->getFlash()->delete();
}
$this->initialize();
}
/**
* @return $this
*/
public function initialize(): AdminForm
{
$this->messages = [];
$this->submitted = false;
$this->unsetFlash();
/** @var FormFlashInterface $flash */
$flash = $this->getFlash();
if ($flash->exists()) {
$data = $flash->getData();
if (null !== $data) {
$data = new Data($data, $this->getBlueprint());
$data->setKeepEmptyValues(true);
$data->setMissingValuesAsNull(true);
}
$this->data = $data;
$this->files = $flash->getFilesByFields(false);
} else {
$this->data = new Data([], $this->getBlueprint());
$this->files = [];
}
return $this;
}
/**
* @return string
*/
public function getNonceName(): string
{
return $this->nonce_name;
}
/**
* @return string
*/
public function getNonceAction(): string
{
return $this->nonce_action;
}
/**
* @return string
*/
public function getScope(): string
{
return 'data.';
}
/**
* @param Blueprint $blueprint
*/
public function setBlueprint(Blueprint $blueprint): void
{
if (null === $blueprint) {
throw new InvalidArgumentException('Blueprint is required');
}
$this->blueprint = $blueprint;
}
/**
* @param string $field
* @param mixed $value
*/
public function setData(string $field, $value): void
{
$this->getData()->set($field, $value);
}
/**
* @return Blueprint
*/
public function getBlueprint(): Blueprint
{
return $this->blueprint;
}
/**
* @param callable|null $submitMethod
*/
public function setSubmitMethod(?callable $submitMethod): void
{
if (null === $submitMethod) {
throw new InvalidArgumentException('Submit method is required');
}
$this->submitMethod = $submitMethod;
}
/**
* @param array $data
* @param array $files
* @return void
* @throws Exception
*/
protected function doSubmit(array $data, array $files): void
{
$method = $this->submitMethod;
$method($data, $files);
$this->reset();
}
/**
* Filter validated data.
*
* @param ArrayAccess|Data|null $data
* @return void
*/
protected function filterData($data = null): void
{
if ($data instanceof Data) {
$data->filter(true, true);
}
}
}

Some files were not shown because too many files have changed in this diff Show More