(Grav GitSync) Automatic Commit from dan

This commit is contained in:
dan 2023-01-07 00:06:20 +01:00 committed by GitSync
parent 097ec8a938
commit 22c9b32b38
49 changed files with 832 additions and 77 deletions

View File

@ -0,0 +1,444 @@
---
title: 'Your own open source finance tool - Firefly III'
author: Dan
published: true
date: '06-01-2023 23:04'
taxonomy:
category:
- news
tag:
- tutorials
- firefly3
- opensource
- finance
aura:
author: dan
---
# Your own open source finance tool - Firefly III
New year - new opportunities!
Maybe firefly can help you to reach your goal(s) faster with an easier overview of your finances and your bad and good habits.
It's open source as usual and covers the privacy part as well.
You shouldn't use a [cloud](../media/there_is_no_cloud.jpg) at all if it's not your own, and especially when it comes to your finances. So it has privacy in mind as well.... a quote from the developer:
> It is completely self-hosted and isolated, and will never contact external servers until you explicitly tell it to.
There are many others, but this one is a simple system for all your financial management. Gnucash, for example, is another very helpful tool for your accounting - business and personal. But having everything together, private (your bank account, your partner's bank account, savings accounts, credit, visa debit,...), company 1, company 2.... So you have the ultimate overview of all your finances in just one software.
> - You can create and edit transactions, accounts, and give them budgets, categories and tags.
> - You can automate part of this with recurring transactions and auto-budgets.
> - You can keep track of liabilities.
> - You can import data into Firefly III from almost any bank.
# Features
Just check the link https://docs.firefly-iii.org/firefly-iii/about-firefly-iii/introduction/?mtm_campaign=docu-internal&mtm_kwd=introduction. It is not necessary to list them here as well. But one thing is good to mention:
> Supports any currency you want, including crypto currencies such as ₿itcoin and Ξthereum
So if you're a crypto guy and/or have money in other countries, that's possible too.
# Installation
We will use a quick and dirty [Docker installation](https://docs.firefly-iii.org/firefly-iii/installation/docker/) here. Just to show what Firefly III can do. Check the other options if you prefer another way and please take responsibility for your own security.
We've also an installation process on Arch in [our wiki](https://wiki.techsaviours.org/en/extras/firefly3), if you prefer not to use docker.
## Docker & docker compose
```
pacman -Sy docker docker-compose --noconfirm
systemctl enable --now docker.service
```
## docker-compose.yml
```
mkdir /opt/firefly3
cd /opt/firefly3
wget https://raw.githubusercontent.com/firefly-iii/docker/main/docker-compose.yml
```
> **NOTE**:
> Change `docker-compose.yml` to your needs - `ports`, `password`
## .env
```
wget https://raw.githubusercontent.com/firefly-iii/firefly-iii/main/.env.example -O .env
```
Change at least:
```
TRUSTED_PROXIES=**
APP_URL=http://SERVER_IP:PORT
```
### Example docker-compose file
```
version: '3.3'
services:
app:
image: fireflyiii/core:latest
restart: always
volumes:
- firefly_iii_upload:/var/www/html/storage/upload
env_file: .env
ports:
- 80:8080
depends_on:
- db
db:
image: mariadb
hostname: fireflyiiidb
restart: always
environment:
- MYSQL_RANDOM_ROOT_PASSWORD=yes
- MYSQL_USER=firefly
- MYSQL_PASSWORD=secret_firefly_password
- MYSQL_DATABASE=firefly
volumes:
- firefly_iii_db:/var/lib/mysql
volumes:
firefly_iii_upload:
firefly_iii_db:
```
## Download & start
```
docker compose up -d
```
# Firefly III
Go to `http://SERVER_IP:PORT`.
> **HINT**:
> `Unable to connect`, just wait a bit longer.
https://firefly-iii.org
https://docs.firefly-iii.org/
## Register a new account
Straight forward...
![Registration.png](d7abb9575c78ee282f42cde304965184.png)
## Getting started
![Getting_started.png](767c0c2d5cc0bf0ee003e9b475979bed.png)
1. First of all, read the page ;)
2. Start with your private bank (Bankname - Your name)
- If you are just by your own, you can use just the bankname. If you add your partners bank and ggf company etc. its easier to have a proper overview with your name behind as well. Especially, if it's the same bank. You can change it later as well of course.
3. `Submit` when you're ready and read the intro.
## Navigation
![Navigation.png](3c416b33c37e1c1e5f7a16e232d3ffd5.png)
### Dashboard
![Dashboard.png](0a8d160ff60ee0b10ff46c13f6356fe7.png)
### Budgets
![Budget.png](f6e4db7283f5ed5fc148ff2aedf80afa.png)
Probably one of the most use budget is for *Groceries*. Give yourself a limit for your weekly/monthly groceries budget.
![Budget - auto-budget.png](d2588f30e8522a5fb76e4ed05641896b.png)
The common question will be here which one do you want to choose in `Auto-budget`.
1. `Set a fixed amount every period`
It's actually straight forward. Every week you'll get the same amount. "Starting new" every week.
2. `Add an amount every period`
This gives you the opportunity to buy more the next week if you saved the week before. The unspent money from last week is simply added to the next week's limit. It can show how much money you can increase (save). At the same time, you will probably end up spending more money than the set amount. It depends a bit on what your personal discipline is. Are you more of a person like:
- Wow! I saved so much money last week, let's see how much money I can save this week. LET IT GROW!
- Wow! I saved so much money last week! This week I'm going to go crazy and spend it all!
Using fixed amounts is probably the best way to save money if that is your goal.
https://docs.firefly-iii.org/firefly-iii/concepts/budgets/
### Bills
![bills](../media/bills.png)
Just add here all fixed costs like mortgage, rent, .....
The *minimum and maximum* amount depends on what you need it for. For example, power varies between this and that. If your rent is always the same, just add the same amount for both.
It is important that you specify the correct date for the next invoice. If you pay rent fortnightly, you must *Skip* 1 week.
> If you enter a number in the "skip" field, the bill will be automatically skipped every X times; a bill that arrives every 3 months can be entered by filling in "2".
Also add a *Group* which will give you a [better overview](link here) later. The rest is basically self explained.
> *NOTE:*
> Don't be surprised if you are redirected to *Automation* - *Rules*. Go to [Automation - Rules](#rules) (here in the tutorial) if you want to continue with your setup. I will continue with the structure of the navigation/Firefly3.
https://docs.firefly-iii.org/firefly-iii/advanced-concepts/bills/
### Piggy banks
![piggy_bank](../media/piggy_bank.png)
Actually, everything is pretty much self explained, the only "problem" you will come across is how you are going to achieve your goal. If you have a big goal, you may need to add two or even four bank accounts to one goal ("Group"). Having multiple accounts in a "Group" can be a little confusing because you don't know which bank account is which when you "Name" it as your actual goal. I like to use the name of my bank account when I need to add multiple accounts to a "Group". Take a look at the image below.
![piggy_bank2](../media/piggy_bank2-1.png)
So there are 35 euros left (under "Account status") in my main account that I would like to add to the roof repair, but is it the main account?
https://docs.firefly-iii.org/firefly-iii/advanced-concepts/piggies/
### Transactions
This does not need to be explained. You will find all your transactions there (expenses, revenue/income, transfers).
### Automation
#### Rules
Now it gets a bit more complicated because there are many things happening at once here. We will more or less only cover the basics here.
![creating_a_rule](../media/creating_a_rule.png)
You can create a `Rule group `directly under `Rules`. You can open it in another tab to create it. A rule group could be your main accounts (`Personal`, `Company1`, `Company2`).
The `Description contains` option in `Trigger` is one of the most important options here. Download a `csv` file from your bank and check the names of your transactions. We will import the `csv` file later using Firefly's data importer. The rest in `Trigger` is pretty much self explained. There are also a lot of other things that might suit you better.
The part `Action` contains more important things, which also has to be created before like `Rule group`, but you have to start somewhere and I will just continue.
The `Set category to..` function gives you a good overview of all your categories in your bank account during the specified period. And here you need to think about how you want it.
A good example of this is `Insurances`. Are you satisfied with a category with only insurances or do you want to see all your insurances in the chart? Then you need to add a category for each insurance.
Another example would be suppliers, a category for all suppliers or do you want to know which suppliers get the most money from you?
`Add tag` feature can be very helpful if you set a category as a supplier, but want to see how much you paid for a particular supplier. Or if you have all insurances in each category separately. And a tag that covers all `Insurances`.
Can be seen as a subcategory without the benefit of a chart in your bank account.
`Set destination account to..` ...
Depends on how many `Expense accounts` you want to add, e.g. `Personal`, `Company1`, `Company2`, ...
I suggest to keep it simple. If you set up many expense accounts, you will lose track. The same goes for too many categories and too many tags. Let's say you have 4 personal accounts: 2 for you (main account and savings account) and the same for your partner. All transactions on all your personal accounts are actually just a `Personal` expense.
As I mentioned earlier, the main reason for creating rules is to automatically assign the transaction to the correct bank account, category and tags when importing the csv file. Otherwise, you will lose track very quickly if you add everything manually and you get confused with the tags because you simply forget what the tag name was, likewise, with too many categories. These steps are really important. Think carefully about how you want your structure to look. Otherwise, you won't use it for long because it will cost you too much time and it won't be fun.
Check also [categories](https://docs.firefly-iii.org/firefly-iii/concepts/categories/) and [tags](https://docs.firefly-iii.org/firefly-iii/concepts/tags/).
#### Recurring transactions
I personally don't use this because I prefer to import all my transactions. And I'm not a fan of automating payments. The same goes for setting them up in your real bank account. These payments are too quickly forgotten.
https://docs.firefly-iii.org/firefly-iii/advanced-concepts/recurring/
### Accounts
#### Asset accounts
You should have also at least 3 accounts:
1. BankName - YourName
2. BankName - YourName savings account
3. Cash wallet
Here you can change and add more accounts.
![asset_accounts](../media/asset_accounts.png)
https://docs.firefly-iii.org/firefly-iii/concepts/accounts/#default-asset-accounts
#### Expense accounts
![expenses](../media/expenses.png)
I prefer to keep it simple here. I work more with categories and tags. It is up to you if you want to add all expenses already here or under categories. For example, I only use private and have "grocery shops" as a category and if I want to know how much I spend on a particular store, I have the shop name as a tag. But you can also do it like this:
![expenses2](../media/expenses2.png)
Maybe you need a "Expense" already as "Grocery shops" and the specific store as a category and different tags for everything you bought in that store. This way you could track how much milk you bought last year.
https://docs.firefly-iii.org/firefly-iii/concepts/accounts/#expense-accounts
#### Revenue accounts
![revenue](../media/revenue.png)
Actually similar like expenses. You can also use private or if you get a refund from an online store.
#### Liabilities
![liabilities](../media/liabilities.png)
Another good feature if you have given someone money or if you have loans, debts or mortgages to pay. Here you have the possibility to manage them as well.
https://docs.firefly-iii.org/firefly-iii/concepts/accounts/#liabilities
### Classification (Categories, Tags & Groups)
As already explained more under [Rules](#Rules), I won't go into more detail here.
https://docs.firefly-iii.org/firefly-iii/concepts/categories/
https://docs.firefly-iii.org/firefly-iii/concepts/tags/
https://docs.firefly-iii.org/firefly-iii/concepts/groups/
### Reports
![reports](../media/reports.png)
An overview of what your accounts have done. You can select all accounts or only specific accounts. The same goes for categories and tags.
You can see some charts and other information about your accounts.
https://docs.firefly-iii.org/firefly-iii/advanced-concepts/reports/
### Export data
![export_data](../media/export_data.png)
I have never used it. So no comment here. Just look at the link below.
https://docs.firefly-iii.org/firefly-iii/exporting-data/
### Options
Nothing to mention here, really. I will just leave some screenshots below.
#### Profile
![profile](../media/profile.png)
#### Preferences
![preferences](../media/preferences.png)
![preferences2](../media/preferences2.png)
![preferences3](../media/preferences3.png)
#### Currencies
![currencies](../media/currencies.png)
#### Administration
![administration](../media/administration.png)
![administration2](../media/administration2.png)
![administration3](../media/administration3.png)
![administration4](../media/administration4.png)
![administration5](../media/administration5.png)
# Data importer
An easy way to import all your transactions via csv files.
https://docs.firefly-iii.org/data-importer/
## docker-compose.yml
Add the following to the [docker-compose.yml](#example-docker-compose-file) file:
```
fidi:
image: fireflyiii/data-importer:latest
restart: always
env_file: .fidi.env
ports:
- 8081:8080
depends_on:
- app
```
Just before:
```
volumes :
firefly_iii_upload:
firefly_iii_db:
```
## Create access token
Go to your http://SERVER_IP:PORT(firefly3)/profile and create a new access token and name it `Importer` or whatever suits you.
![token](../media/token.png)
## .fidi.env
```
wget https://raw.githubusercontent.com/firefly-iii/data-importer/main/.env.example -O .fidi.env
```
The link to the Firefly main page will be important. So whatever you set in [.env](#.env) (`APP_URL=`) must also be set here:
```
FIREFLY_III_URL=http://app:8080
VANITY_URL=http://SERVER_IP:PORT(firefly3)
FIREFLY_III_ACCESS_TOKEN=YourTOKEN
TRUSTED_PROXIES=**
APP_URL=http://SERVER_IP:PORT(data-importer)
```
## Download & start
```
docker compose up -d
```
Go to http://SERVER_IP:PORT(data-importer).
![data_importer](../media/data_importer.png)
## Import file
Go to your bank and export your transactions to a csv file.
![data_importer2](../media/data_importer2.png)
You can create a configuration file later so that you do not have to keep changing the following information.
![data_importer3](../media/data_importer3.png)
I mainly use the default settings. Only "Import tag" and "Date format" are different. But the settings really depend on how your bank exports your transactions. You have to test that a bit yourself. Every bank is different so it makes no sense to put here a reasonable config for all. See the link https://docs.firefly-iii.org/data-importer/usage/configure/#file-options for that while you're setting it up for yourself.
After the import you will see all transactions under the selected bank account - http://SERVER_IP:PORT(firefly3). Start creating your [rules](#rules) if you think they will appear frequently.
# That's it!
I hope it helps you a little to save/earn more money this year while prices are blowing up.
And if you like it, leave the developer your personal transaction in his instance as well - https://www.patreon.com/jc5 and/or https://github.com/sponsors/JC5.
Have a good year
Dan

View File

@ -1,3 +1,10 @@
# v1.10.38
## 01/02/2023
1. [](#new)
* Update copyright dates
* Keep version number in sync with Grav version
# v1.10.37.1
## 10/08/2022

View File

@ -1,7 +1,7 @@
name: Admin Panel
slug: admin
type: plugin
version: 1.10.37.1
version: 1.10.38
description: Adds an advanced administration panel to manage your site
icon: empire
author:

View File

@ -1,5 +1,12 @@
<?php
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Plugin\Admin;
use DateTime;

View File

@ -1,5 +1,12 @@
<?php
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Plugin\Admin;
use Grav\Common\Cache;

View File

@ -1,5 +1,12 @@
<?php
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Plugin\Admin;
use Grav\Common\Backup\Backups;

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -1,5 +1,12 @@
<?php
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
declare(strict_types=1);
namespace Grav\Plugin\Admin;

View File

@ -1,5 +1,12 @@
<?php
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
declare(strict_types=1);
namespace Grav\Plugin\Admin\Controllers;

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -1,5 +1,12 @@
<?php
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Plugin\Admin;
use Grav\Common\Cache;

View File

@ -1,5 +1,12 @@
<?php
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Plugin\Admin;
use Grav\Common\Config\Config;

View File

@ -1,5 +1,12 @@
<?php
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Plugin\Admin;
use Grav\Common\Grav;

View File

@ -3,7 +3,7 @@
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

View File

@ -1,4 +1,12 @@
<?php
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Plugin\Admin;
use ScssPhp\ScssPhp\Compiler;

View File

@ -1,5 +1,12 @@
<?php
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Plugin\Admin;
class ScssList

View File

@ -1,5 +1,12 @@
<?php
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Plugin\Admin;
/**

View File

@ -1,5 +1,12 @@
<?php
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Plugin\Admin\Twig;
use Grav\Common\Data\Data;

View File

@ -1,5 +1,12 @@
<?php
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Plugin\Admin;
use Grav\Common\Grav;

View File

@ -1,6 +1,13 @@
<?php
namespace Grav\Plugin\Admin;
/**
* @package Grav\Plugin\Admin
*
* @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
use Grav\Common\Filesystem\Folder;
use Grav\Common\Grav;
use Grav\Framework\File\File;

View File

@ -1,3 +1,18 @@
# v1.3.3
## 01/04/2023
1. [](#improved)
* Save `post-save` action to session
* Set default `post-save` action to `edit` for create and edit
# v1.3.2
## 12/02/2022
1. [](#improved)
* Various translation enhancements
1. [](#bugfix)
* Fixed frontend editing objects with urlencoded ids
# v1.3.1
## 09/08/2022

View File

@ -54,7 +54,7 @@
{# FIXME: Search fields should be passed and individually customizable, right now defaulting to all fields selected #}
{% set searchFields = searchFields|merge([key|replace({'.': '_'})]) %}
{% endfor %}
{% set tableFields = tableFields|merge([{ name: '_actions_', title: 'Actions', titleClass: 'right' }]) %}
{% set tableFields = tableFields|merge([{ name: '_actions_', title: "PLUGIN_FLEX_OBJECTS.ACTION.ACTIONS"|tu, titleClass: 'right' }]) %}
{% set list = table.jsonSerialize %}

View File

@ -3,7 +3,7 @@
{% set originalValue = value %}
{% set value = (value is null ? field.default : value) %}
{% set isNew = key ? false : true %}
{% set savedOption = grav.session.post_entries_save|default('create-new') %}
{% set savedOption = grav.session.post_entries_save|default('edit') %}
{% if isNew %}
{% set options = {'create-new':'PLUGIN_FLEX_OBJECTS.ACTION.CREATE_NEW', 'edit':'PLUGIN_FLEX_OBJECTS.ACTION.EDIT_ITEM', 'list':'PLUGIN_FLEX_OBJECTS.ACTION.LIST_ITEMS'} %}
@ -12,7 +12,6 @@
{% endif %}
{% block input %}
{% set savedOption = not isNew and savedOption == 'create-new' ? 'edit' : savedOption %}
{% for key, text in options %}
{% set id = field.id|default(field.name) ~ '-' ~ key %}

View File

@ -1,7 +1,7 @@
name: Flex Objects
slug: flex-objects
type: plugin
version: 1.3.1
version: 1.3.3
description: Flex Objects plugin allows you to manage Flex Objects in Grav Admin.
icon: list-alt
author:

View File

@ -907,6 +907,7 @@ class AdminController
// Set route to point to the current page.
if (!$this->redirect) {
$postAction = $request->getParsedBody()['_post_entries_save'] ?? 'edit';
$this->grav['session']->post_entries_save = $postAction;
if ($postAction === 'create-new') {
// Create another.
$route = $this->referrerRoute->withGravParam('action', null)->withGravParam('', 'add');

View File

@ -261,7 +261,7 @@ class FlexObjectsPlugin extends Plugin
if (!isset($form['flex']['key']) && $edit === true) {
/** @var Route $route */
$route = $this->grav['route'];
$id = $route->getGravParam('id');
$id = rawurldecode($route->getGravParam('id'));
if (null !== $id) {
$form['flex']['key'] = $id;
$event['form'] = $form;

View File

@ -13,6 +13,7 @@ PLUGIN_FLEX_OBJECTS:
DIRECTORIES: "Verzeichnisse"
CSV: "CSV"
PARENTS: "Eltern"
NEW: "Neu"
CONTROLLER:
TASK_DELETE_SUCCESS: 'Eintrag erfolgreich gelöscht'
@ -35,6 +36,7 @@ PLUGIN_FLEX_OBJECTS:
ADVANCED_OPTIONS: "Erweiterte Optionen"
APPLY_FILTERS: "Filter anwenden"
RESET_FILTERS: "Filter zurücksetzen"
ACTIONS: "Aktionen"
FILTER:
PAGE_ATTRIBUTES: "Seitenattribute"

View File

@ -30,13 +30,13 @@ PLUGIN_FLEX_OBJECTS:
CREATE_NEW: Create New Item
EDIT_ITEM: Edit Item
LIST_ITEMS: "List Items"
LIST_ITEM: List Items
DELETE_N: "Delete" # In some languages 'delete OBJECT' may need a special declination
REALLY_DELETE: "Are you sure you want to permanently delete the %s?"
SEARCH_PLACEHOLDER: "Search…"
ADVANCED_OPTIONS: "Advanced Options"
APPLY_FILTERS: "Apply Filters"
RESET_FILTERS: "Reset to Defaults"
ACTIONS: "Actions"
FILTER:
PAGE_ATTRIBUTES: "Page Attributes"

View File

@ -30,13 +30,13 @@ PLUGIN_FLEX_OBJECTS:
CREATE_NEW: "Crear nuevo ítem"
EDIT_ITEM: "Editar ítem"
LIST_ITEMS: "Listar ítems"
LIST_ITEM: "Listar ítem"
DELETE_N: "Eliminar"
REALLY_DELETE: "¿Realmente quieres eliminar %s permanentemente?"
SEARCH_PLACEHOLDER: "Buscar…"
ADVANCED_OPTIONS: "Opciones avazadas"
APPLY_FILTERS: "Aplicar filtros"
RESET_FILTERS: "Restablecer filtros"
ACTIONS: "Acciones"
FILTER:
PAGE_ATTRIBUTES: "Atributos de página"

View File

@ -30,13 +30,13 @@ PLUGIN_FLEX_OBJECTS:
CREATE_NEW: 新しいデータを作成
EDIT_ITEM: "データの編集"
LIST_ITEMS: "データの一覧表示"
LIST_ITEM: データの一覧
DELETE_N: "削除" # In some languages 'delete OBJECT' may need a special declination
REALLY_DELETE: "%s を削除します。復元はできませんがよろしいですか?"
SEARCH_PLACEHOLDER: "検索…"
ADVANCED_OPTIONS: "詳細設定"
APPLY_FILTERS: "フィルターを適用"
RESET_FILTERS: "標準にリセットする"
ACTIONS: "アクション"
FILTER:
PAGE_ATTRIBUTES: "ページ属性"

View File

@ -0,0 +1,71 @@
PLUGIN_FLEX_OBJECTS:
PLUGIN_NAME: "Flex Objects"
PLUGIN_DESCRIPTION: "De Flex Objects plugin maakt het mogelijk om flexibele objecten te maken en te beheren."
TITLE: Flex Objects
TYPES_TITLE: Mappen
AFTER_SAVE: Na opslaan…
LIST_INFO: '{from} tot {to} van {total} items weergegeven'
EMPTY_RESULT: Deze zoekopdracht geeft geen resultaat
USE_BUILT_IN_CSS: "Gebruik ingebouwde CSS"
EXTRA_ADMIN_TWIG_PATH: "Extra Admin Twig pad"
DIRECTORIES: "Mappen"
CSV: "CSV"
PARENTS: "Ouders"
CONTROLLER:
TASK_DELETE_SUCCESS: 'Item succesvol verwijderd'
TASK_DELETE_FAILURE: 'Item verwijderen mislukt: %s'
TASK_NEW_FOLDER_SUCCESS: 'Map succesvol aangemaakt'
TASK_COPY_SUCCESS: 'Kopie succesvol aangemaakt'
TASK_COPY_FAILURE: 'Kopie aanmaken mislukt: %s'
TASK_SAVE_SUCCESS: 'Item succesvol opgeslagen'
TASK_SAVE_FAILURE: 'Item opslaan mislukt: %s'
TASK_CONFIGURE_SUCCESS: 'Configuratie succesvol opgeslagen'
TASK_CONFIGURE_FAILURE: 'Configuratie opslaan mislukt: %s'
ACTION:
CREATE_NEW: Nieuw item aanmaken
EDIT_ITEM: Item bewerken
LIST_ITEMS: Items weergeven
DELETE_N: "Verwijderen"
REALLY_DELETE: "Weet je zeker dat je %s permanent wilt verwijderen?"
SEARCH_PLACEHOLDER: "Zoeken…"
ADVANCED_OPTIONS: "Geavanceerde opties"
APPLY_FILTERS: "Filters toepassen"
RESET_FILTERS: "Filters resetten"
FILTER:
PAGE_ATTRIBUTES: "Pagina attributen"
PAGE_TYPES: "Pagina types"
MODULAR_TYPES: "Modulaire types"
LANGUAGE:
USING_DEFAULT: "<b>Standaard</b> taalbestand in gebruik."
UNUSED_DEFAULT: "Ongebruikt <b>standaard</b> taalbestand aanwezig."
USING_OVERRIDE: "<b>%s</b> taalbestand in gebruik."
NOT_TRANSLATED_YET: "Deze pagina is nog niet vertaald naar <i class=\"fa fa-flag-o\"></i> <b>%s</b>!"
NO_FALLBACK_FOUND: "Geen fallback taalbestand gevonden."
FALLING_BACK: "Terugvallen op <b>%s</b> taalbestand."
STATE:
LOADING: "Laden…"
CREATED_SUCCESSFULLY: "Succesvol aangemaakt"
UPDATED_SUCCESSFULLY: "Succesvol bijgewerkt"
DELETED_SUCCESSFULLY: "Succesvol verwijderd"
EDITING_DRAFT: "Je bewerkt een concept."
NOT_CREATED_YET: "Deze pagina bestaat niet, totdat je hem opslaat."
ERROR:
BAD_DIRECTORY: "Niet bestaande map"
PAGE_NOT_FOUND: "Pagina niet gevonden"
PAGE_NOT_EXIST: "Oeps! Deze pagina bestaat niet."
PAGE_FORBIDDEN: "Oeps! Je hebt geen toegang tot deze pagina."
LAYOUT_NOT_FOUND: "Object layout '%s' niet gevonden."
BLUEPRINT_NO_LIST: "De blueprint van <i>%s</i> bevat geen velddata of lijst pagina overschrijving."
BLUEPRINT_NO_LIST_ADVISE: "Voeg een <i>list</i> sectie toe aan de blueprint of overschrijf de <i>list</i> pagina in de configuratie."
BLUEPRINT_NO_LIST_TEMPLATE: "Maak een template bestand voor dit type aan in <b>flex-objects/types/%s/list.html.twig</b>"
LIST_EMPTY: "Er zijn geen items gevonden."
LIST_EMPTY_ADD: "Er zijn geen items op dit moment. Klik op de knop <a href=\"%s\">Toevoegen</a> om een nieuw item aan te maken."
NO_FLEX_DIRECTORIES: "Geen Flex Object mappen gedefinieerd."

View File

@ -1,3 +1,9 @@
# v7.1.1
## 11/29/2022
1. [](#bugfix)
* Fix missing blueprint entries for Turnstile configuration [#583](https://github.com/getgrav/grav-plugin-form/issues/583)
# v7.1.0
## 11/16/2022

View File

@ -1,7 +1,7 @@
name: Form
slug: form
type: plugin
version: 7.1.0
version: 7.1.1
description: Enables forms handling and processing
icon: check-square
author:
@ -197,6 +197,29 @@ form:
help: PLUGIN_FORM.RECAPTCHA_SECRET_KEY_HELP
default: ''
turnstile_captcha:
type: section
title: PLUGIN_FORM.TURNSTILE_CAPTCHA
fields:
turnstile.theme:
type: select
label: PLUGIN_FORM.RECAPTCHA_THEME
default: light
options:
light: PLUGIN_FORM.RECAPTCHA_THEME_LIGHT
dark: PLUGIN_FORM.RECAPTCHA_THEME_DARK
turnstile.site_key:
type: text
label: PLUGIN_FORM.RECAPTCHA_SITE_KEY
help: PLUGIN_FORM.RECAPTCHA_SITE_KEY_HELP
default: ''
turnstile.secret_key:
type: text
label: PLUGIN_FORM.RECAPTCHA_SECRET_KEY
help: PLUGIN_FORM.RECAPTCHA_SECRET_KEY_HELP
default: ''
basic_captcha:
type: section
title: PLUGIN_FORM.BASIC_CAPTCHA

View File

@ -19,7 +19,6 @@ recaptcha:
site_key:
secret_key:
turnstile:
widget: managed # options: [managed | non-interactive | invisible]
theme: light # options: [light | dark]
site_key:
secret_key:

View File

@ -87,6 +87,7 @@ en:
BASIC_CAPTCHA_MATH_MIN: "Minimum number"
BASIC_CAPTCHA_MATH_MAX: "Maximum number"
BASIC_CAPTCHA_MATH_OPERATORS: "Mathematical operators (randomized)"
TURNSTILE_CAPTCHA: "Cloudflare Turnstile Captcha"
eu:
PLUGIN_FORM:

View File

@ -1,3 +1,9 @@
# v3.1.0
## 12/12/2022
1. [](#new)
* Using blocks in `partials/langswitcher.html.twig` to make it easier to extend without having to copy the logic
# v3.0.2
## 10/05/2022

View File

@ -1,5 +1,5 @@
name: LangSwitcher
version: 3.0.2
version: 3.1.0
description: LangSwitcher is a [Grav](https://github.com/getgrav/grav) plugin that provides native language text links to switch between [multiple languages](http://learn.getgrav.org/content/multi-language) in Grav **v0.9.30** or greater.
icon: globe
author:

View File

@ -0,0 +1,29 @@
{{ block('language_block_start') }}
{% set display_format = display_format ?? config.get('plugins.langswitcher.language_display', 'long') %}
{% for language in langswitcher.languages %}
{% set active_class = '' %}
{% set show_language = true %}
{% if language == langswitcher.current %}
{% set active_class = 'active' %}
{% endif %}
{% if langswitcher.translated_routes[language] %}
{% set lang_url = langswitcher.translated_routes[language] ~ page.urlExtension %}
{% else %}
{% set base_lang_url = base_url_simple ~ grav.language.getLanguageURLPrefix(language) %}
{% set lang_url = base_lang_url ~ langswitcher.page_route ~ page.urlExtension %}
{% endif %}
{% set untranslated_pages_behavior = grav.config.plugins.langswitcher.untranslated_pages_behavior %}
{% if untranslated_pages_behavior != 'none' %}
{% set translated_page = langswitcher.translated_pages[language] %}
{% if (not translated_page) or (not translated_page.published) %}
{% if untranslated_pages_behavior == 'redirect' %}
{% set lang_url = url('/') %}
{% elseif untranslated_pages_behavior == 'hide' %}
{% set show_language = false %}
{% endif %}
{% endif %}
{% endif %}
{{ block('language_item') }}
{% endfor %}
{{ block('language_block_end') }}

View File

@ -1,33 +1,15 @@
{% extends 'partials/langswitcher-logic.html.twig' %}
{% block language_block_start %}
<ul class="langswitcher">
{% set display_format = display_format ?? config.get('plugins.langswitcher.language_display', 'long') %}
{% endblock %}
{% for language in langswitcher.languages %}
{% set active_class = '' %}
{% set show_language = true %}
{% if language == langswitcher.current %}
{% set active_class = 'active' %}
{% endif %}
{% if langswitcher.translated_routes[language] %}
{% set lang_url = langswitcher.translated_routes[language] ~ page.urlExtension %}
{% else %}
{% set base_lang_url = base_url_simple ~ grav.language.getLanguageURLPrefix(language) %}
{% set lang_url = base_lang_url ~ langswitcher.page_route ~ page.urlExtension %}
{% endif %}
{% set untranslated_pages_behavior = grav.config.plugins.langswitcher.untranslated_pages_behavior %}
{% if untranslated_pages_behavior != 'none' %}
{% set translated_page = langswitcher.translated_pages[language] %}
{% if (not translated_page) or (not translated_page.published) %}
{% if untranslated_pages_behavior == 'redirect' %}
{% set lang_url = url('/') %}
{% elseif untranslated_pages_behavior == 'hide' %}
{% set show_language = false %}
{% endif %}
{% endif %}
{% endif %}
{% if show_language %}
<li><a href="{{ lang_url ~ uri.params ~ (uri.query|length > 1 ? '?' ~ uri.query) }}" class="external {{ active_class }}">{% include 'partials/langswitcher-' ~ display_format ~ '.html.twig' %}</a></li>
{% endif %}
{% endfor %}
{% block language_block_end %}
</ul>
{% endblock %}
{% block language_item %}
{% if show_language %}
<li><a href="{{ lang_url ~ uri.params ~ (uri.query|length > 1 ? '?' ~ uri.query) }}" class="external {{ active_class }}">{% include 'partials/langswitcher-' ~ display_format ~ '.html.twig' %}</a></li>
{% endif %}
{% endblock %}

View File

@ -1,3 +1,10 @@
# v3.7.2
## 01/02/2023
1. [](#new)
* Added new `onBeforeSessionStart()` event to store redirect + messages when session is regenerated during login
* Requires Grav `1.7.38` for new event availability
# v3.7.1
## 06/14/2022

View File

@ -1,7 +1,7 @@
name: Login
slug: login
type: plugin
version: 3.7.1
version: 3.7.2
testing: false
description: Enables user authentication and login screen.
icon: sign-in
@ -15,7 +15,7 @@ bugs: https://github.com/getgrav/grav-plugin-login/issues
license: MIT
dependencies:
- { name: grav, version: '>=1.7.32' }
- { name: grav, version: '>=1.7.38' }
- { name: form, version: '>=6.0.0' }
- { name: email, version: '>=3.1.6' }

View File

@ -23,6 +23,7 @@ use Grav\Common\User\Interfaces\UserCollectionInterface;
use Grav\Common\User\Interfaces\UserInterface;
use Grav\Common\Utils;
use Grav\Common\Uri;
use Grav\Events\BeforeSessionStartEvent;
use Grav\Events\PluginsLoadedEvent;
use Grav\Events\SessionStartEvent;
use Grav\Framework\Flex\Interfaces\FlexCollectionInterface;
@ -62,6 +63,9 @@ class LoginPlugin extends Plugin
/** @var Invitation|null */
protected $invitation;
protected $temp_redirect;
protected $temp_messages;
/**
* @return array
*/
@ -70,6 +74,7 @@ class LoginPlugin extends Plugin
return [
PluginsLoadedEvent::class => [['onPluginsLoaded', 10]],
SessionStartEvent::class => ['onSessionStart', 0],
BeforeSessionStartEvent::class => ['onBeforeSessionStart', 0],
PageAuthorizeEvent::class => ['onPageAuthorizeEvent', -10000],
'onPluginsInitialized' => [['initializeSession', 10000], ['initializeLogin', 1000]],
'onTask.login.login' => ['loginController', 0],
@ -124,6 +129,18 @@ class LoginPlugin extends Plugin
};
}
/**
* @param BeforeSessionStartEvent $event
* @return void
*/
public function onBeforeSessionStart(BeforeSessionStartEvent $event): void
{
$session = $event->session;
$this->temp_redirect = $session->redirect_after_login ?? null;
$this->temp_messages = $session->messages;
}
/**
* @param SessionStartEvent $event
* @return void
@ -132,6 +149,15 @@ class LoginPlugin extends Plugin
{
$session = $event->session;
if (isset($this->temp_redirect)) {
$session->redirect_after_login = $this->temp_redirect;
unset($this->temp_redirect);
}
if (isset($this->temp_messages)) {
$session->messages = $this->temp_messages;
unset($this->temp_messages);
}
$user = $session->user ?? null;
if ($user && $user->exists() && ($this->config()['session_user_sync'] ?? false)) {
// User is stored into the filesystem.

View File

@ -1,3 +1,9 @@
# v1.2.4
## 12/06/2022
1. [](#bugfix)
* Fix broken "page in collection" test that was causing plugin not to function
# v1.2.3
## 01/22/2021

View File

@ -45,6 +45,9 @@ score_threshold: 20 # minimum score needed to show up in the list
filter: # filter a configurable collection of pages to compare
items:
@page: /blog # supports @self, @page, and @taxonomy collections
excluded_types: # exclude certain type of content if the header contains the type of one in the list
- quote
- video
order:
by: date # order type by default
dir: desc # order direction

View File

@ -1,7 +1,7 @@
name: Related Pages
slug: relatedpages
type: plugin
version: 1.2.3
version: 1.2.4
description: "A highly sophisticated and configurable plugin that calculates related pages in relation to the current page."
icon: newspaper-o
author:
@ -61,7 +61,14 @@ form:
type: multilevel
label: PLUGIN_REL_PAGES.ITEMS
value_only: true
validate:
validate:
type: array
filter.excluded_types:
type: array
label: PLUGIN_REL_PAGES.EXCLUDED_TYPES
value_only: true
validate:
type: array
filter.order.by:

View File

@ -28,7 +28,8 @@ en:
ADVANCED: Advanced
TAXONOMY_SCORE_SCALE: Taxonomy-taxonomy score scale
CONTENT_SCORE_SCALE: Taxonomy-content score scale
EXCLUDED_TYPES: Page types to exclude from results
de:
PLUGIN_REL_PAGES:
PLUGIN_STATUS: Plugin-Status
@ -60,7 +61,8 @@ de:
ADVANCED: Erweitert
TAXONOMY_SCORE_SCALE: Taxonomie-Taxonomie Bewertungsskala
CONTENT_SCORE_SCALE: Taxonomie-Inhalt Bewertungsskala
EXCLUDED_TYPES: Seitentypen, die von den Ergebnissen ausgeschlossen werden sollen
fr:
PLUGIN_REL_PAGES:
BASICS: Réglages de base
@ -91,7 +93,8 @@ fr:
ADVANCED: Avancés
TAXONOMY_SCORE_SCALE: Taxonomie-niveau de score de taxonomie
CONTENT_SCORE_SCALE: Taxonomie-niveau de score de contenu
EXCLUDED_TYPES: Types de pages à exclure des résultats
nl:
PLUGIN_REL_PAGES:
BASICS: Basisinstellingen
@ -122,6 +125,7 @@ nl:
ADVANCED: Geavanceerd
TAXONOMY_SCORE_SCALE: Taxonomie-taxonomie score schaal
CONTENT_SCORE_SCALE: Taxonomie-inhoud score schaal
EXCLUDED_TYPES: Paginatypen die moeten worden uitgesloten van resultaten
ro:
PLUGIN_REL_PAGES:
@ -133,26 +137,27 @@ ro:
SHOW_SCORE: Arată scorul
SHOW_SCORE_HELP: Comutați pentru afișarea scorurilor
ITEMS: Articole
ITEMS_HELP: Acceptă colecții bazate pe `@self`, `@page` și `@taxonomy`
ITEMS_HELP: Acceptă colecții bazate pe `@self`, `@page` și `@taxonomy`
PAGE_IN_FILTER: Filtru 'in' pagină
PAGE_IN_FILTER_HELP: Activează dacă pagina curentă trebuie să fie în colecția filtrată
EXPLICIT_PROCESS: Procesează anumite pagini specifice
EXPLICIT_PROCESS_HELP: Activează pentru procesarea anumitor pagini specifice
EXPLICIT_SCORE: Scorul paginilor specifice
EXPLICIT_SCORE: Scorul paginilor specifice
EXPLICIT_SCORE_HELP: Un scor între (0 - 100) pentru a da unor pagini specifice greutate
TAXONOMY_MATCH: Potrivire după Taxonomie
TAXONOMY_MATCH: Potrivire după Taxonomie
TAXONOMY: Taxonomie
TAXONOMY_HELP: Ce fel de taxonomie să fie folosită la potrivirea paginilor
TAXONOMY_HELP: Ce fel de taxonomie să fie folosită la potrivirea paginilor
TAXONOMY_TAXONOMY_PROCESS: Taxonomie-taxonomie
TAXONOMY_TAXONOMY_PROCESS_HELP: Activeazā potrivirea între taxonomii
TAXONOMY_CONTENT_PROCESS: Taxonomie-conținut
TAXONOMY_CONTENT_PROCESS_HELP: Activează potrivirea după taxonomie - conținut
CONTENT_MATCH: Potrivirea după conținut
TAXONOMY_CONTENT_PROCESS_HELP: Activează potrivirea după taxonomie - conținut
CONTENT_MATCH: Potrivirea după conținut
CONTENT_PROCESS: Conținut-conținut
CONTENT_PROCESS_HELP: "Activează pentru potrivire după conținut (Notă: dezactivați dacă aveți conținut mult)"
ADVANCED: Avansat
TAXONOMY_SCORE_SCALE: Scorul scalei Taxonomie-taxonomie
CONTENT_SCORE_SCALE: Scorul scalei Taxonomie-conținut
EXCLUDED_TYPES: tipuri de pagini de exclus din rezultate
es:
PLUGIN_REL_PAGES:
@ -184,4 +189,4 @@ es:
ADVANCED: Avanzado
TAXONOMY_SCORE_SCALE: Escala de puntuación Taxonomía-taxonomía
CONTENT_SCORE_SCALE: Escala de puntuación Taxonomía-contenido
EXCLUDED_TYPES: tipos de página para excluir de los resultados

View File

@ -1,12 +1,13 @@
<?php
namespace Grav\Plugin;
use Grav\Common\Cache;
use Grav\Common\Config\Config;
use Grav\Common\Debugger;
use Grav\Common\Page\Interfaces\PageInterface;
use \Grav\Common\Plugin;
use \Grav\Common\Cache;
use \Grav\Common\Debugger;
use \Grav\Common\Config\Config;
use \Grav\Common\Page\Pages;
use Grav\Common\Page\Pages;
use Grav\Common\Plugin;
class RelatedPagesPlugin extends Plugin
{
@ -73,7 +74,7 @@ class RelatedPagesPlugin extends Plugin
'onTwigSiteVariables' => ['onTwigSiteVariables', 0]
]);
$cache_id = md5('relatedpages'.$page->path().$cache->getKey());
$cache_id = md5('relatedpages' . $page->path() . $cache->getKey());
$this->related_pages = $cache->fetch($cache_id);
if ($this->related_pages === false) {
@ -81,8 +82,21 @@ class RelatedPagesPlugin extends Plugin
// get all the pages
$collection = $page->collection($config['filter']);
//If the header of a page has a type and it is included in the excluded types remove it from the collection
foreach ($collection as $pageKey) {
$header = $pageKey->header();
if (
property_exists($header, 'type') &&
array_key_exists('filter', $config) &&
array_key_exists('excluded_types', $config['filter']) &&
in_array($header->type, $config['filter']['excluded_types'])
) {
$collection->remove($pageKey);
}
}
// perform check if page must be in filter values
if ($config['page_in_filter'] && !\in_array($page, iterator_to_array($collection), true)) {
if ($config['page_in_filter'] && !array_key_exists($page->path(), $collection->toArray())) {
return;
}
@ -129,11 +143,11 @@ class RelatedPagesPlugin extends Plugin
// Check for multiple taxonomies.
$taxonomy_list = $config['taxonomy_match']['taxonomy'];
// Support the single value by converting it to array.
if (!\is_array ($taxonomy_list)) {
if (!\is_array($taxonomy_list)) {
$taxonomy_list = array($taxonomy_list);
}
$score_scale = $config['taxonomy_match']['taxonomy_taxonomy']['score_scale'];
$score = 0;
$has_matches = false;
foreach ($taxonomy_list as $taxonomy) {
@ -151,13 +165,13 @@ class RelatedPagesPlugin extends Plugin
} else {
$score += max(array_keys($score_scale));
}
$has_matches = true;
}
}
}
}
if ($has_matches) {
$taxonomy_taxonomy_matches[$item->path()] = $score;
}
@ -169,7 +183,7 @@ class RelatedPagesPlugin extends Plugin
// Check for multiple taxonomies.
$taxonomy_list = $config['taxonomy_match']['taxonomy'];
// Support the single value by converting it to array.
if (!is_array ($taxonomy_list)) {
if (!is_array($taxonomy_list)) {
$taxonomy_list = array($taxonomy_list);
}
$score_scale = $config['taxonomy_match']['taxonomy_content']['score_scale'];
@ -179,7 +193,7 @@ class RelatedPagesPlugin extends Plugin
foreach ($taxonomy_list as $taxonomy) {
if (isset($page_taxonomies[$taxonomy])) {
$page_taxonomy = $page_taxonomies[$taxonomy];
$count = $this->substringCountArray($item->title().' '.$item->rawMarkdown(), $page_taxonomy);
$count = $this->substringCountArray($item->title() . ' ' . $item->rawMarkdown(), $page_taxonomy);
if ($count > 0) {
if (array_key_exists($count, $score_scale)) {
@ -187,12 +201,12 @@ class RelatedPagesPlugin extends Plugin
} else {
$score += max(array_keys($score_scale));
}
$has_matches = true;
}
}
}
if ($has_matches) {
$taxonomy_content_matches[$item->path()] = $score;
}
@ -243,7 +257,7 @@ class RelatedPagesPlugin extends Plugin
protected function mergeRelatedPages(array $pages)
{
foreach ((array) $pages as $path => $score) {
foreach ((array)$pages as $path => $score) {
$page_exists = array_key_exists($path, $this->related_pages);
if ($score > $this->config['score_threshold'] &&
(!$page_exists || ($page_exists && $score > $this->related_pages[$path]))) {

View File

@ -4,7 +4,10 @@ show_score: true # toggle to determine if scores should be displa
score_threshold: 20 # minimum score needed to show up in the list
filter: # filter a configurable collection of pages to compare
items:
'@page': /blog # supports @self, @page, and @taxonomy collections
'@page': /blog # supports @self, @page, and @taxonomy collections
excluded_types: # exclude certain type of content if the header contains the type of one in the list
- quote
- video
order:
by: date # order type by default
dir: desc # order direction