feat: VivesPOS landing on Winter CMS 1.2 — theme + plugin + Dockerfile
Some checks are pending
Module sub-split / Sub-split (push) Waiting to run
- Base: wintercms/winter branch 1.2 (full framework) - Theme vivespos: Canvas 7 + Bootstrap 5 CDN, custom CSS - Layout: deferred GTM/GA4 tracking, JSON-LD SoftwareApplication - Partials: hero (offline-first), features, modes (offline/nube toggle), screenshots, pricing (3 planes), comparison, FAQ, CTA - Plugin VivesPOS.Site with ContactForm - Dockerfile: PHP 8.2 Apache, port 80, healthcheck - Added winter/wn-pages, blog, sitemap, seo plugins - Active theme set to vivespos
11
.devcontainer/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Listen for Xdebug",
|
||||
"type": "php",
|
||||
"request": "launch",
|
||||
"port": 9003
|
||||
},
|
||||
]
|
||||
}
|
||||
72
.devcontainer/README.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Welcome to the Winter development environment
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/wintercms/winter/raw/develop/.github/assets/Github%20Banner.png?raw=true" alt="Winter CMS Logo" width="100%" style="max-width: 600px" />
|
||||
</p>
|
||||
|
||||
This development environment container sets up a fully-functional installation of Winter CMS, built on [FrankenPHP](https://frankenphp.dev/) with PHP 8.4. It makes it simple to start working with Winter CMS in VSCode, PHPStorm and online code-editing suites such as GitHub Codespaces.
|
||||
|
||||
This image is based on the official [Winter CMS Docker image](https://github.com/wintercms/docker) and inherits all its features. For detailed configuration options, see the [Docker image README](https://github.com/wintercms/docker/blob/main/README.md).
|
||||
|
||||
If you opted to use the `bootstrap-winter` feature, which is enabled by default, Winter CMS will be automatically configured and an administrator account will be generated with the credentials **admin / admin** for you to quickly sign in. It is recommended once you have done so that you change this password immediately.
|
||||
|
||||
The following plugins and themes will be installed automatically with this feature:
|
||||
|
||||
- Workshop theme (https://github.com/wintercms/wn-workshop-theme)
|
||||
- Pages plugin (https://github.com/wintercms/wn-pages-plugin)
|
||||
- Blog plugin (https://github.com/wintercms/wn-blog-plugin)
|
||||
- Test plugin (https://github.com/wintercms/wn-test-plugin)
|
||||
|
||||
## Using this environment
|
||||
|
||||
When this environment is built, FrankenPHP is automatically started, with the root folder of the Winter project being used. A preview of the website will be opened immediately - if you do not see this, you can open the **Ports** tab in VSCode to view the URL generated for viewing the project.
|
||||
|
||||
XDebug is enabled by default, and allows you to quickly use step debugging. It will be available in the **Debug** tab of VSCode or similar screen in other IDEs.
|
||||
|
||||
By default, when using the `bootstrap-winter` feature, changes to certain folders and locations will be ignored by Git to keep the change list clean. This includes the `plugins` and `themes` folders, the `config/app.php` file and the `composer.json` file in the root folder. If you wish to use this environment for your own projects, it is recommended that you do not use this feature. Please see the **Using in your own projects** section below for using this environment outside of Winter development.
|
||||
|
||||
## Environment platform
|
||||
|
||||
The following software is installed in this environment.
|
||||
|
||||
- FrankenPHP (Caddy)
|
||||
- PHP 8.4 with the following extensions:
|
||||
- `intl`
|
||||
- `gd`
|
||||
- `xdebug`
|
||||
- Composer
|
||||
- NodeJS 24 (including `npm`)
|
||||
- Git
|
||||
|
||||
## Using in your own projects
|
||||
|
||||
You may use this development environment for your own projects, making it a great starting point to hit the ground running with Winter. It is recommended that you *disable* the `bootstrap-winter` feature when using this environment for your own projects.
|
||||
|
||||
You may disable this feature by modifying the `.devcontainer/devcontainer.json` file before running the container and commenting out the feature:
|
||||
|
||||
```json5
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/common-utils:2": {},
|
||||
"ghcr.io/devcontainers/features/github-cli:1": {},
|
||||
// Comment the following feature if you wish to bootstrap and configure Winter manually (ie. you wish to use this for your own project)
|
||||
"./local-features/bootstrap-winter": "latest"
|
||||
},
|
||||
```
|
||||
|
||||
If this feature is disabled, you must bootstrap your project manually. This includes:
|
||||
|
||||
- Downloading the Composer dependencies.
|
||||
- Generating the configuration for the project, either as an `.env` file or in the `config` folder.
|
||||
- Finally, Running the database migrations.
|
||||
|
||||
You may view the `.devcontainer/local-features/bootstrap-winter/bootstrap.sh` file to see how we bootstrap Winter, and run these commands manually. You will only need to do this once per project container.
|
||||
|
||||
If you wish to mount your own volumes, use your own databases or any other complex usages, please review the [Winter Docker image documentation](https://github.com/wintercms/docker/blob/main/README.md#persisting-data) or the [FrankenPHP environment variables](https://frankenphp.dev/docs/config/#environment-variables) for configuration options.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Preview website missing styles / assets on Codespaces
|
||||
|
||||
By default, ports that are forwarded in Codespaces are private by default. While we have tried to fix this automatically in the Winter bootstrap process by making the port public through the GitHub CLI, it unfortunately is not consistently applied.
|
||||
|
||||
If you find that your preview website is missing assets or styling, open the **Ports** tab by opening the Action Palette in Codespaces (`F1`) and using the **View: Toggle Ports** action. Right click on the **Preview Winter installation** port, right click on it and choose **Port Visiblity -> Public**. This should resolve the issue.
|
||||
60
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,60 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||
// README at: https://github.com/devcontainers/templates/tree/main/src/debian
|
||||
{
|
||||
"name": "Winter on PHP 8.4",
|
||||
"image": "ghcr.io/wintercms/winter:latest",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/common-utils:2": {
|
||||
"installZsh": true,
|
||||
"configureZshAsDefaultShell": true,
|
||||
"username": "winter",
|
||||
"upgradePackages": false
|
||||
},
|
||||
"ghcr.io/devcontainers/features/github-cli:1": {},
|
||||
// Comment the following feature if you wish to bootstrap and configure Winter manually (ie. you wish to use this for your own project)
|
||||
"./local-features/bootstrap-winter": "latest"
|
||||
},
|
||||
"workspaceMount": "source=${localWorkspaceFolder},target=/winter,type=bind",
|
||||
"workspaceFolder": "/winter",
|
||||
"containerEnv": {
|
||||
"APP_DEBUG": "true",
|
||||
"XDEBUG_MODE": "debug",
|
||||
"ROUTES_CACHE": "false",
|
||||
"ASSET_CACHE": "false",
|
||||
"DB_CONNECTION": "sqlite",
|
||||
"DB_DATABASE": "${containerWorkspaceFolder}/storage/database.sqlite"
|
||||
},
|
||||
"forwardPorts": [8000],
|
||||
"portsAttributes": {
|
||||
"8000": {
|
||||
"label": "Preview Winter installation",
|
||||
"onAutoForward": "openPreview"
|
||||
},
|
||||
"9003": {
|
||||
"label": "Xdebug",
|
||||
"onAutoForward": "notify"
|
||||
}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"settings": {
|
||||
"php.validate.executablePath": "/usr/local/bin/php",
|
||||
"phpcs.executablePath": "${containerWorkspaceFolder}/vendor/bin/phpcs"
|
||||
},
|
||||
"extensions": [
|
||||
"xdebug.php-debug",
|
||||
"bmewburn.vscode-intelephense-client",
|
||||
"shevaua.phpcs",
|
||||
"swordev.phpstan",
|
||||
"wintercms.winter-cms"
|
||||
]
|
||||
},
|
||||
"codespaces": {
|
||||
"openFiles": [
|
||||
".devcontainer/README.md"
|
||||
]
|
||||
}
|
||||
},
|
||||
"postAttachCommand": "nohup ${containerWorkspaceFolder}/.devcontainer/run-frankenphp.sh > /dev/null 2>&1",
|
||||
"remoteUser": "winter"
|
||||
}
|
||||
51
.devcontainer/local-features/bootstrap-winter/bootstrap.sh
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ ! -d "${PWD}/vendor" ] && [ ! -f "${PWD}/composer.lock" ]; then
|
||||
echo "### Updating Composer dependencies"
|
||||
php ${PWD}/.devcontainer/local-features/bootstrap-winter/update-composer.php
|
||||
composer update --no-interaction --no-scripts --no-audit
|
||||
fi
|
||||
|
||||
if [ ! -f "${PWD}/.env" ]; then
|
||||
echo "### Generating .env file"
|
||||
php artisan winter:env -q
|
||||
php artisan key:generate -q
|
||||
fi
|
||||
|
||||
if [ "${DB_CONNECTION}" = "sqlite" ] && [ "${DB_DATABASE}" = "${PWD}/storage/database.sqlite" ] && [ ! -f "${PWD}/storage/database.sqlite" ]; then
|
||||
SETUP_ADMIN=true
|
||||
echo "### Creating SQLite database"
|
||||
touch storage/database.sqlite
|
||||
fi
|
||||
|
||||
echo "### Run migrations"
|
||||
php artisan migrate
|
||||
|
||||
echo "### Set theme"
|
||||
php artisan theme:use workshop
|
||||
|
||||
if [ "${SETUP_ADMIN}" = true ]; then
|
||||
echo "### Setup admin"
|
||||
php artisan winter:passwd admin admin
|
||||
fi
|
||||
|
||||
echo "### Ignoring files in Git"
|
||||
echo "plugins/*" >> "${PWD}/.git/info/exclude"
|
||||
echo "themes/*" >> "${PWD}/.git/info/exclude"
|
||||
echo "composer.json" >> "${PWD}/.git/info/exclude"
|
||||
git update-index --assume-unchanged composer.json
|
||||
git restore config
|
||||
|
||||
cp ${PWD}/.devcontainer/.vscode/launch.json ${PWD}/.vscode/launch.json
|
||||
|
||||
echo "### Mirror site to public directory"
|
||||
php artisan winter:mirror public
|
||||
|
||||
if [ "${CODESPACES}" = "true" ]; then
|
||||
echo "### Configure for Codespaces"
|
||||
php ${PWD}/.devcontainer/local-features/bootstrap-winter/codespaces.php
|
||||
git update-index --assume-unchanged config/app.php
|
||||
gh codespace ports visibility 8000:public -c $CODESPACE_NAME
|
||||
fi
|
||||
25
.devcontainer/local-features/bootstrap-winter/codespaces.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
$root = dirname(__DIR__, 3);
|
||||
|
||||
require_once $root . '/vendor/autoload.php';
|
||||
|
||||
use Winter\LaravelConfigWriter\ArrayFile;
|
||||
use Winter\LaravelConfigWriter\EnvFile;
|
||||
|
||||
$config = ArrayFile::open($root . '/config/app.php');
|
||||
|
||||
$config->set('trustedHosts', [
|
||||
'localhost',
|
||||
'^(.+\.)?app.github.dev',
|
||||
]);
|
||||
$config->set('trustedProxies', '*');
|
||||
|
||||
$config->write();
|
||||
|
||||
$env = EnvFile::open($root . '/.env');
|
||||
|
||||
$env->set('APP_URL', 'https://' . $_ENV['CODESPACE_NAME'] . '.app.github.dev');
|
||||
$env->set('LINK_POLICY', 'force');
|
||||
|
||||
$env->write();
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"id": "bootstrap-winter",
|
||||
"name": "Bootstrap Winter",
|
||||
"description": "Bootstrap and configure Winter CMS automatically for development on Winter itself",
|
||||
"postCreateCommand": "sh ./.devcontainer/local-features/bootstrap-winter/bootstrap.sh"
|
||||
}
|
||||
8
.devcontainer/local-features/bootstrap-winter/install.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
# Install Xdebug extension
|
||||
install-php-extensions xdebug
|
||||
|
||||
echo "Done"
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
$composerPath = dirname(__DIR__, 3) . '/composer.json';
|
||||
$composer = json_decode(file_get_contents($composerPath), true);
|
||||
|
||||
$packages = [
|
||||
'winter/wn-test-plugin' => 'dev-main',
|
||||
'winter/wn-blog-plugin' => 'dev-main',
|
||||
'winter/wn-blog-plugin' => 'dev-main',
|
||||
'winter/wn-workshop-theme' => 'dev-main',
|
||||
];
|
||||
|
||||
// Install Winter packages
|
||||
foreach ($packages as $package => $version) {
|
||||
if (!in_array($package, array_keys($composer['require']))) {
|
||||
$composer['require'][$package] = $version;
|
||||
}
|
||||
}
|
||||
|
||||
// Change Merge plugin config
|
||||
$composer['extra']['merge-plugin']['include'] = [
|
||||
'plugins/*/*/composer.json',
|
||||
];
|
||||
|
||||
file_put_contents(
|
||||
$composerPath,
|
||||
json_encode($composer, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
|
||||
);
|
||||
26
.devcontainer/run-frankenphp.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
USER_ID=$(id -u)
|
||||
GROUP_ID=$(id -g)
|
||||
|
||||
# Ensure the Caddy config and data directories are owned by the current user
|
||||
sudo chown -R $USER_ID:$GROUP_ID /config/caddy
|
||||
sudo chown -R $USER_ID:$GROUP_ID /data
|
||||
sudo touch /var/log/frankenphp.log
|
||||
sudo chown $USER_ID:$GROUP_ID /var/log/frankenphp.log
|
||||
|
||||
# If debugging is enabled, disable Opcache so changes are reflected immediately
|
||||
if [ "${APP_DEBUG}" = "true" ] || [ "${APP_DEBUG}" = "1" ]; then
|
||||
sudo sed -i 's/opcache.enable = On/opcache.enable = Off/' /usr/local/etc/php/conf.d/winter.ini
|
||||
fi
|
||||
|
||||
# Run server in background
|
||||
if [ "${CODESPACES}" = "true" ]; then
|
||||
# Ensure environment variables are set correctly for Codespaces
|
||||
SERVER_NAME="http://:8000" APP_URL="https://${CODESPACE_NAME}-8000.app.github.dev" /usr/local/bin/frankenphp run -c /etc/frankenphp/Caddyfile -a caddyfile > /var/log/frankenphp.log 2>&1 &
|
||||
else
|
||||
/usr/local/bin/frankenphp run -c /etc/frankenphp/Caddyfile -a caddyfile > /var/log/frankenphp.log 2>&1 &
|
||||
fi
|
||||
|
||||
15
.editorconfig
Normal file
@@ -0,0 +1,15 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[**/.github/workflows/**.{yml,yaml}]
|
||||
indent_size = 2
|
||||
13
.env.example
Normal file
@@ -0,0 +1,13 @@
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_KEY=
|
||||
APP_URL=http://localhost
|
||||
|
||||
DB_CONNECTION=sqlite
|
||||
DB_DATABASE=storage/database.sqlite
|
||||
|
||||
CACHE_STORE=file
|
||||
SESSION_DRIVER=file
|
||||
QUEUE_CONNECTION=sync
|
||||
|
||||
MAIL_MAILER=log
|
||||
10
.gitattributes
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
* text=auto
|
||||
|
||||
*.md diff=markdown
|
||||
*.php diff=php
|
||||
|
||||
/.devcontainer export-ignore
|
||||
/.github export-ignore
|
||||
.gitattributes export-ignore
|
||||
CHANGELOG.md export-ignore
|
||||
/package.json export-ignore
|
||||
78
.github/ISSUE_TEMPLATE/1_BUG_REPORT.yaml
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
name: Bug Report
|
||||
description: Report a general Winter CMS or Storm library issue. See our policy below if reporting a security issue.
|
||||
labels: ["Status: Review Needed", "Type: Unconfirmed Bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for your interest in improving Winter CMS! To avoid duplicate issues please ensure that no previous issues already cover the problem you wish to report before you submit your report. Otherwise, feel free to fill out the form below to submit an issue.
|
||||
|
||||
**Please do not use this form to report a security issue. For security issues, review our [Security Policy](https://github.com/wintercms/winter/security/policy).**
|
||||
- type: dropdown
|
||||
id: build
|
||||
attributes:
|
||||
label: Winter CMS Build
|
||||
description: Please select the Winter CMS build that you encountered your issue with. You can find the version in the **Updates & Plugins** section of the Settings page of the Backend, or by running the `php artisan winter:version` command.
|
||||
options:
|
||||
- dev-develop
|
||||
- 1.2
|
||||
- 1.1
|
||||
- 1.0 (please try updating first)
|
||||
- Other (please specify below)
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: php_version
|
||||
attributes:
|
||||
label: PHP Version
|
||||
description: Please provide us the branch of PHP version. For example, for PHP version 7.4.9, select `7.4`, or for PHP version 8.0.1, select `8.0`.
|
||||
options:
|
||||
- 8.4
|
||||
- 8.3
|
||||
- 8.2
|
||||
- 8.1
|
||||
- 8.0
|
||||
- 7.4
|
||||
- 7.3
|
||||
- 7.2
|
||||
- Other (please specify below)
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: database
|
||||
attributes:
|
||||
label: Database engine
|
||||
description: Please provide us with the database server type you are running.
|
||||
options:
|
||||
- MySQL/MariaDB
|
||||
- PostgreSQL
|
||||
- SQLite
|
||||
- SQL Server
|
||||
- No database
|
||||
- Other (please specify below)
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: plugins
|
||||
attributes:
|
||||
label: Plugins installed
|
||||
description: If any plugins are installed, please list them here in the format `Author.PluginName, Author2.PluginName, etc`.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Issue description
|
||||
description: Please describe the issue in as much detail as possible. Include screenshots of error messages or copy and paste any logs that result from the issue occurring.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: replication
|
||||
attributes:
|
||||
label: Steps to replicate
|
||||
description: Please list the steps that you took in order for the issue to occur.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: workaround
|
||||
attributes:
|
||||
label: Workaround
|
||||
description: If you have a workaround, please detail it here, for the benefit of other users who encounter the issue.
|
||||
32
.github/ISSUE_TEMPLATE/2_PRE_PR.yaml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Pre-Pull Request Discussion
|
||||
description: If you intend to submit a PR and wish to discuss it first, start here.
|
||||
labels: ["Status: Review Needed", "Type: Conceptual Enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for your interest in submitting a pull request to Winter CMS. We always value contributions from our community. If you wish to start a discussion on the pull request before submission, such as discussing implementation details, please use this form.
|
||||
- type: dropdown
|
||||
id: subsystem
|
||||
attributes:
|
||||
label: Package targeted
|
||||
description: Please select which portion of Winter CMS your PR is targeting.
|
||||
options:
|
||||
- Winter CMS
|
||||
- Storm Library
|
||||
- Both
|
||||
- Other (please specify below)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: Please describe what your PR is intending to do.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: compatibility
|
||||
attributes:
|
||||
label: Will this change be backwards-compatible?
|
||||
description: Please describe if this intended change may break backwards compatibility or not. If it does, state the rationale in which you believe this to be an acceptable break in backwards compatibility.
|
||||
14
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: General Winter CMS Support
|
||||
url: https://wintercms.com/support
|
||||
about: If you need help with Winter CMS, please review our support options.
|
||||
- name: Discord
|
||||
url: https://discord.gg/D5MFSPH6Ux
|
||||
about: Join us on Discord for general discussions and one-on-one help.
|
||||
- name: Feature Requests
|
||||
url: https://github.com/wintercms/winter/discussions
|
||||
about: Please post an Idea thread to the Discussions section for feature requests.
|
||||
- name: Documentation Issue
|
||||
url: https://github.com/wintercms/docs
|
||||
about: For documentation issues, please submit an issue or PR to the Docs repository.
|
||||
BIN
.github/assets/Github Banner.png
vendored
Normal file
|
After Width: | Height: | Size: 500 KiB |
BIN
.github/assets/sponsor-route4me.png
vendored
Normal file
|
After Width: | Height: | Size: 13 KiB |
68
.github/workflows/code-quality.yaml
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
name: Code Quality
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- 1.0
|
||||
- 1.1
|
||||
- 1.2
|
||||
- develop
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
codeQuality:
|
||||
runs-on: ubuntu-latest
|
||||
name: PHP
|
||||
steps:
|
||||
- name: Checkout changes
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install PHP and PHP Code Sniffer
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 8.2
|
||||
extensions: curl, fileinfo, gd, mbstring, openssl, pdo, pdo_sqlite, sqlite3, xml, zip
|
||||
tools: phpcs
|
||||
|
||||
- name: Run code quality checks (on push)
|
||||
if: github.event_name == 'push'
|
||||
run: ./.github/workflows/utilities/phpcs-push ${{ github.sha }}
|
||||
|
||||
- name: Run code quality checks (on pull request)
|
||||
if: github.event_name == 'pull_request'
|
||||
run: ./.github/workflows/utilities/phpcs-pr ${{ github.base_ref }}
|
||||
codeQualityJS:
|
||||
runs-on: ubuntu-latest
|
||||
name: JavaScript
|
||||
steps:
|
||||
- name: Checkout changes
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12
|
||||
|
||||
- name: Install Node dependencies for System Module
|
||||
working-directory: ./modules/system
|
||||
run: npm install
|
||||
|
||||
- name: Run code quality checks on System Module
|
||||
working-directory: ./modules/system
|
||||
run: npx eslint .
|
||||
|
||||
- name: Install Node dependencies for Backend Module
|
||||
working-directory: ./modules/backend
|
||||
run: npm install
|
||||
|
||||
- name: Run code quality checks on Backend Module
|
||||
working-directory: ./modules/backend
|
||||
run: npx eslint .
|
||||
128
.github/workflows/docker.yml
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
name: Docker
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v[0-9]+.[0-9]+.[0-9]+"
|
||||
|
||||
concurrency:
|
||||
group: docker-${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
updateDockerImage:
|
||||
name: Update Docker image
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
version: ${{ github.ref_name }}
|
||||
steps:
|
||||
- name: Checkout changes
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: wintercms/docker
|
||||
ref: main
|
||||
token: ${{ secrets.WINTER_BOT_TOKEN }}
|
||||
|
||||
- name: Determine latest FrankenPHP, PHP and Node versions
|
||||
id: versions
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Stay within the major versions currently used by the Dockerfile
|
||||
frankenphpMajor=$(sed -n 's/^ARG FRANKENPHP_VERSION="\([0-9]*\)\..*"$/\1/p' Dockerfile)
|
||||
phpMajor=$(sed -n 's/^ARG PHP_VERSION="\([0-9]*\)\..*"$/\1/p' Dockerfile)
|
||||
nodeMajor=$(sed -n 's/^ARG NODE_VERSION="v\([0-9]*\)\..*"$/\1/p' Dockerfile)
|
||||
|
||||
# The base image is a combined FrankenPHP + PHP tag, so both versions must be resolved
|
||||
# together - the latest of each individually may not exist as a published image. Walk
|
||||
# back through the FrankenPHP releases until one with a Trixie image is found.
|
||||
frankenphp=""
|
||||
php=""
|
||||
|
||||
for candidate in $(gh api "repos/php/frankenphp/releases?per_page=100" \
|
||||
--jq '.[] | select(.draft == false and .prerelease == false) | .tag_name' \
|
||||
| sed -n "s/^v\($frankenphpMajor\.[0-9]\+\.[0-9]\+\)$/\1/p"); do
|
||||
php=$(curl -fsSL "https://hub.docker.com/v2/repositories/dunglas/frankenphp/tags?page_size=100&name=$candidate-php$phpMajor" \
|
||||
| jq -r '.results[].name' \
|
||||
| sed -n "s/^$candidate-php\($phpMajor\.[0-9]\+\.[0-9]\+\)-trixie$/\1/p" \
|
||||
| sort -V \
|
||||
| tail -n 1)
|
||||
|
||||
if [ -n "$php" ]; then
|
||||
frankenphp="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "$frankenphp" ] || [ -z "$php" ]; then
|
||||
echo "Unable to resolve a FrankenPHP $frankenphpMajor.x image for PHP $phpMajor.x" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
node=$(curl -fsSL "https://nodejs.org/dist/index.json" \
|
||||
| jq -r --arg major "v$nodeMajor." 'map(select(.version | startswith($major))) | .[0].version // ""')
|
||||
|
||||
if [ -z "$node" ]; then
|
||||
echo "Unable to resolve a Node $nodeMajor.x release" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "frankenphp=$frankenphp" >> "$GITHUB_OUTPUT"
|
||||
echo "php=$php" >> "$GITHUB_OUTPUT"
|
||||
echo "node=$node" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Update versions
|
||||
env:
|
||||
frankenphp: ${{ steps.versions.outputs.frankenphp }}
|
||||
php: ${{ steps.versions.outputs.php }}
|
||||
node: ${{ steps.versions.outputs.node }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
currentFrankenphp=$(sed -n 's/^ARG FRANKENPHP_VERSION="\(.*\)"$/\1/p' Dockerfile)
|
||||
currentPhp=$(sed -n 's/^ARG PHP_VERSION="\(.*\)"$/\1/p' Dockerfile)
|
||||
currentNode=$(sed -n 's/^ARG NODE_VERSION="\(.*\)"$/\1/p' Dockerfile)
|
||||
|
||||
sed -i -E "s/^ARG WINTER_VERSION=\".*\"$/ARG WINTER_VERSION=\"$version\"/" Dockerfile
|
||||
sed -i -E "s/^ARG FRANKENPHP_VERSION=\".*\"$/ARG FRANKENPHP_VERSION=\"$frankenphp\"/" Dockerfile
|
||||
sed -i -E "s/^ARG PHP_VERSION=\".*\"$/ARG PHP_VERSION=\"$php\"/" Dockerfile
|
||||
sed -i -E "s/^ARG NODE_VERSION=\".*\"$/ARG NODE_VERSION=\"$node\"/" Dockerfile
|
||||
|
||||
grep -q "^ARG WINTER_VERSION=\"$version\"$" Dockerfile
|
||||
grep -q "^ARG FRANKENPHP_VERSION=\"$frankenphp\"$" Dockerfile
|
||||
grep -q "^ARG PHP_VERSION=\"$php\"$" Dockerfile
|
||||
grep -q "^ARG NODE_VERSION=\"$node\"$" Dockerfile
|
||||
|
||||
# Written outside the checkout so that it is not picked up by the commit
|
||||
notes="$RUNNER_TEMP/release-notes.md"
|
||||
echo "- Updated Winter to version $version" > "$notes"
|
||||
|
||||
if [ "$currentFrankenphp" != "$frankenphp" ]; then
|
||||
echo "- Updated FrankenPHP to version $frankenphp" >> "$notes"
|
||||
fi
|
||||
if [ "$currentPhp" != "$php" ]; then
|
||||
echo "- Updated PHP to version $php" >> "$notes"
|
||||
fi
|
||||
if [ "$currentNode" != "$node" ]; then
|
||||
echo "- Updated Node to version $node" >> "$notes"
|
||||
fi
|
||||
|
||||
- name: Commit changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: Update to Winter ${{ env.version }}
|
||||
file_pattern: Dockerfile
|
||||
commit_user_name: Winter Bot
|
||||
commit_user_email: 80384029+WinterCMSBot@users.noreply.github.com
|
||||
|
||||
- name: Publish release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.WINTER_BOT_TOKEN }}
|
||||
run: |
|
||||
gh release create "$version" \
|
||||
--repo wintercms/docker \
|
||||
--target main \
|
||||
--title "$version" \
|
||||
--notes-file "$RUNNER_TEMP/release-notes.md"
|
||||
69
.github/workflows/manifest.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
name: Manifest
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: manifest-${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
updateManifest:
|
||||
name: Update manifest
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
phpVersion: "8.4"
|
||||
extensions: curl, fileinfo, gd, mbstring, openssl, pdo, pdo_sqlite, sqlite3, xml, zip
|
||||
key: winter-cms-cache-develop
|
||||
steps:
|
||||
- name: Checkout changes
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ env.phpVersion }}
|
||||
extensions: ${{ env.extensions }}
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-interaction --no-progress --no-scripts
|
||||
|
||||
- name: Download manifest
|
||||
run: wget -O builds.json https://github.com/wintercms/meta/raw/master/manifest/builds.json
|
||||
|
||||
- name: Run manifest
|
||||
run: php artisan winter:manifest builds.json
|
||||
|
||||
- name: Create artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: winter-manifest
|
||||
path: builds.json
|
||||
|
||||
commitManifest:
|
||||
name: Commit manifest
|
||||
runs-on: ubuntu-latest
|
||||
needs: updateManifest
|
||||
steps:
|
||||
- name: Checkout changes
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: wintercms/meta
|
||||
ref: master
|
||||
token: ${{ secrets.WINTER_BOT_TOKEN }}
|
||||
|
||||
- name: Download artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: winter-manifest
|
||||
path: manifest
|
||||
|
||||
- name: Commit changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: Update manifest
|
||||
commit_user_name: Winter Bot
|
||||
commit_user_email: 80384029+WinterCMSBot@users.noreply.github.com
|
||||
32
.github/workflows/subsplit.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Module sub-split
|
||||
|
||||
on:
|
||||
push:
|
||||
# Branches only. Tag pushes are handled by the `create` event below; without
|
||||
# this filter they would also fire here and pass the tag name to `split -b`,
|
||||
# which then fails looking for a branch that doesn't exist.
|
||||
branches:
|
||||
- "**"
|
||||
create:
|
||||
delete:
|
||||
|
||||
jobs:
|
||||
split:
|
||||
name: Sub-split
|
||||
runs-on: ubuntu-latest
|
||||
container: wintercms/cli:0.3.4
|
||||
env:
|
||||
WINTER_CLI_GITHUB_TOKEN: ${{ secrets.WINTER_SPLIT_TOKEN }}
|
||||
steps:
|
||||
- name: Create tag
|
||||
if: github.event_name == 'create' && github.ref_type == 'tag'
|
||||
run: winter split -a "${{ github.ref_name }}"
|
||||
- name: Delete branch
|
||||
if: github.event_name == 'delete' && github.ref_type == 'branch'
|
||||
run: winter split --remove-branch="${{ github.event.ref }}"
|
||||
- name: Delete tag
|
||||
if: github.event_name == 'delete' && github.ref_type == 'tag'
|
||||
run: winter split --remove-tag="${{ github.event.ref }}"
|
||||
- name: Push
|
||||
if: github.event_name == 'push'
|
||||
run: winter split -b "${{ github.ref_name }}"
|
||||
175
.github/workflows/tests.yml
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '1.2'
|
||||
- develop
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
frontendTests:
|
||||
strategy:
|
||||
max-parallel: 2
|
||||
matrix:
|
||||
operatingSystem: [ubuntu-latest, windows-latest]
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.operatingSystem }}
|
||||
name: ${{ matrix.operatingSystem }} / JavaScript
|
||||
env:
|
||||
nodeVersion: 16
|
||||
phpVersion: '8.2'
|
||||
extensions: curl, fileinfo, gd, mbstring, openssl, pdo, pdo_sqlite, sqlite3, xml, zip
|
||||
key: winter-cms-cache-develop
|
||||
steps:
|
||||
- name: Checkout changes
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup extension cache
|
||||
id: extcache
|
||||
uses: shivammathur/cache-extensions@v1
|
||||
with:
|
||||
php-version: ${{ env.phpVersion }}
|
||||
extensions: ${{ env.extensions }}
|
||||
key: ${{ env.key }}
|
||||
|
||||
- name: Cache extensions
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.extcache.outputs.dir }}
|
||||
key: ${{ steps.extcache.outputs.key }}
|
||||
restore-keys: ${{ steps.extcache.outputs.key }}
|
||||
|
||||
- name: Install PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ env.phpVersion }}
|
||||
extensions: ${{ env.extensions }}
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ env.nodeVersion }}
|
||||
|
||||
- name: Switch library dependency (develop)
|
||||
if: github.ref == 'refs/heads/develop' || github.base_ref == 'develop'
|
||||
run: php ./.github/workflows/utilities/library-switcher "dev-develop as 1.2"
|
||||
|
||||
- name: Switch library dependency (1.2)
|
||||
if: github.head_ref == '1.2' || github.ref == 'refs/heads/1.2' || github.base_ref == '1.2'
|
||||
run: php ./.github/workflows/utilities/library-switcher "1.2.x-dev as 1.2"
|
||||
|
||||
- name: Setup dependency cache
|
||||
id: composercache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.composercache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
|
||||
restore-keys: ${{ runner.os }}-composer-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-interaction --no-progress --no-scripts
|
||||
|
||||
- name: Reset modules
|
||||
run: |
|
||||
git reset --hard
|
||||
git clean -fd
|
||||
|
||||
- name: Run post-update Composer scripts
|
||||
run: php artisan package:discover
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
php artisan mix:install
|
||||
php artisan mix:run module-system test
|
||||
|
||||
phpUnitTests:
|
||||
strategy:
|
||||
max-parallel: 8
|
||||
matrix:
|
||||
operatingSystem: [ubuntu-latest, windows-latest]
|
||||
phpVersion: ['8.1', '8.2', '8.3', '8.4', '8.5']
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.operatingSystem }}
|
||||
name: ${{ matrix.operatingSystem }} / PHP ${{ matrix.phpVersion }}
|
||||
env:
|
||||
extensions: curl, fileinfo, gd, mbstring, openssl, pdo, pdo_sqlite, sqlite3, xml, zip
|
||||
key: winter-cms-cache-develop
|
||||
steps:
|
||||
- name: Checkout changes
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup extension cache
|
||||
id: extcache
|
||||
uses: shivammathur/cache-extensions@v1
|
||||
with:
|
||||
php-version: ${{ matrix.phpVersion }}
|
||||
extensions: ${{ env.extensions }}
|
||||
key: ${{ env.key }}
|
||||
|
||||
- name: Cache extensions
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.extcache.outputs.dir }}
|
||||
key: ${{ steps.extcache.outputs.key }}
|
||||
restore-keys: ${{ steps.extcache.outputs.key }}
|
||||
|
||||
- name: Install PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.phpVersion }}
|
||||
extensions: ${{ env.extensions }}
|
||||
|
||||
- name: Switch library dependency (develop)
|
||||
if: github.ref == 'refs/heads/develop' || github.base_ref == 'develop'
|
||||
run: php ./.github/workflows/utilities/library-switcher "dev-develop as 1.2"
|
||||
|
||||
- name: Switch library dependency (1.0)
|
||||
if: github.head_ref == '1.0' || github.ref == 'refs/heads/1.0' || github.base_ref == '1.0'
|
||||
run: php ./.github/workflows/utilities/library-switcher "1.0.x-dev as 1.0"
|
||||
|
||||
- name: Switch library dependency (1.1)
|
||||
if: github.head_ref == '1.1' || github.ref == 'refs/heads/1.1' || github.base_ref == '1.1'
|
||||
run: php ./.github/workflows/utilities/library-switcher "1.1.x-dev as 1.1"
|
||||
|
||||
- name: Switch library dependency (1.2)
|
||||
if: github.head_ref == '1.2' || github.ref == 'refs/heads/1.2' || github.base_ref == '1.2'
|
||||
run: php ./.github/workflows/utilities/library-switcher "1.2.x-dev as 1.2"
|
||||
|
||||
- name: Setup dependency cache
|
||||
id: composercache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.composercache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
|
||||
restore-keys: ${{ runner.os }}-composer-
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install --no-interaction --no-progress --no-scripts
|
||||
|
||||
- name: Reset modules
|
||||
run: |
|
||||
git reset --hard
|
||||
git clean -fd
|
||||
|
||||
- name: Run post-update Composer scripts
|
||||
run: php artisan package:discover
|
||||
|
||||
- name: Setup problem matchers for PHPUnit
|
||||
if: matrix.phpVersion == '8.1'
|
||||
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
|
||||
|
||||
- name: Run Linting and Tests
|
||||
run: |
|
||||
composer lint
|
||||
php artisan winter:test -m system -m backend -m cms
|
||||
18
.github/workflows/utilities/library-switcher
vendored
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* Storm library switch for CI
|
||||
*
|
||||
* Switches the version of the Storm library being required through Composer. The only argument is the branch or tag
|
||||
* to switch to.
|
||||
*/
|
||||
if (empty($argv[1])) {
|
||||
echo 'You must provide a version to switch the library dependency to.';
|
||||
echo "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$composer = json_decode(file_get_contents(getcwd() . '/composer.json'), true);
|
||||
$composer['require']['winter/storm'] = $argv[1];
|
||||
|
||||
file_put_contents(getcwd() . '/composer.json', json_encode($composer, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
87
.github/workflows/utilities/phpcs-pr
vendored
Executable file
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* Run PHPCS tests against a PR.
|
||||
*
|
||||
* The only argument is for the PR's base branch, which is then compared to the HEAD of the PR to retrieve the list
|
||||
* of changed files. The PHPCS tests are only run against these changed files, to speed up the tests.
|
||||
*/
|
||||
if (empty($argv[1])) {
|
||||
fwrite(STDERR, 'You must provide a base branch to check this PR against.');
|
||||
fwrite(STDERR, "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Get a changelist of files from Git for this PR.
|
||||
$fileList = shell_exec('git diff --name-only --diff-filter=ACMR origin/' . $argv[1] . ' HEAD');
|
||||
$files = array_filter(explode("\n", $fileList));
|
||||
|
||||
foreach ($files as &$file) {
|
||||
if (strpos($file, ' ') !== false) {
|
||||
$file = str_replace(' ', '\\ ', $file);
|
||||
}
|
||||
}
|
||||
|
||||
// no changes found in diff, early exit
|
||||
if (!count($files)) {
|
||||
fwrite(STDOUT, "\e[0;32mFound no changed files.\e[0m");
|
||||
fwrite(STDOUT, "\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Run all changed files through the PHPCS code sniffer and generate a CSV report
|
||||
$csv = shell_exec('phpcs --colors -nq --report="csv" --extensions="php" ' . implode(' ', $files));
|
||||
$lines = array_map(function ($row) {
|
||||
return array_map(function ($column) {
|
||||
return trim($column, '"');
|
||||
}, explode(',', $row));
|
||||
}, array_filter(explode("\n", $csv)));
|
||||
|
||||
// Remove header row
|
||||
array_shift($lines);
|
||||
|
||||
if (!count($lines)) {
|
||||
fwrite(STDOUT, "\e[0;32mFound no issues with code quality.\e[0m");
|
||||
fwrite(STDOUT, "\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Group errors by file
|
||||
$files = [];
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$filename = str_replace(dirname(dirname(dirname(__DIR__))), '', $line[0]);
|
||||
|
||||
if (empty($files[$filename])) {
|
||||
$files[$filename] = [];
|
||||
}
|
||||
|
||||
$files[$filename][] = [
|
||||
'warning' => (($line[3] ?? 'err') === 'warning'),
|
||||
'message' => $line[4] ?? 'unknown',
|
||||
'line' => $line[1] ?? '0',
|
||||
];
|
||||
}
|
||||
|
||||
// Render report
|
||||
fwrite(STDERR, "\e[0;31mFound "
|
||||
. ((count($lines) === 1)
|
||||
? '1 issue'
|
||||
: count($lines) . ' issues')
|
||||
. " with code quality.\e[0m");
|
||||
fwrite(STDERR, "\n");
|
||||
|
||||
foreach ($files as $file => $errors) {
|
||||
fwrite(STDERR, "\n");
|
||||
fwrite(STDERR, "\e[1;37m" . str_replace('"', '', $file) . "\e[0m");
|
||||
fwrite(STDERR, "\n\n");
|
||||
|
||||
foreach ($errors as $error) {
|
||||
fwrite(STDERR, "\e[2m" . str_pad(' L' . $error['line'], 7) . " | \e[0m");
|
||||
fwrite(STDERR, $error['warning'] ? "\e[1;33mWARN:\e[0m " : "\e[0;31mERR:\e[0m ");
|
||||
fwrite(STDERR, $error['message']);
|
||||
fwrite(STDERR, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
exit(1);
|
||||
87
.github/workflows/utilities/phpcs-push
vendored
Executable file
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* Run PHPCS tests against a push.
|
||||
*
|
||||
* The only argument is for the commit, which a list of changed files is retrieved from. The PHPCS tests are only run
|
||||
* against these changed files, to speed up the tests.
|
||||
*/
|
||||
if (empty($argv[1])) {
|
||||
fwrite(STDERR, 'You must provide a commit SHA to check.');
|
||||
fwrite(STDERR, "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Get a changelist of files from Git for this push.
|
||||
$fileList = shell_exec('git show --name-only --pretty="" --diff-filter=ACMR ' . $argv[1]);
|
||||
$files = array_filter(explode("\n", $fileList));
|
||||
|
||||
foreach ($files as &$file) {
|
||||
if (strpos($file, ' ') !== false) {
|
||||
$file = str_replace(' ', '\\ ', $file);
|
||||
}
|
||||
}
|
||||
|
||||
// no changes found in diff, early exit
|
||||
if (!count($files)) {
|
||||
fwrite(STDOUT, "\e[0;32mFound no changed files.\e[0m");
|
||||
fwrite(STDOUT, "\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Run all changed files through the PHPCS code sniffer and generate a CSV report
|
||||
$csv = shell_exec('phpcs --colors -nq --report="csv" --extensions="php" ' . implode(' ', $files));
|
||||
$lines = array_map(function ($row) {
|
||||
return array_map(function ($column) {
|
||||
return trim($column, '"');
|
||||
}, explode(',', $row));
|
||||
}, array_filter(explode("\n", $csv)));
|
||||
|
||||
// Remove header row
|
||||
array_shift($lines);
|
||||
|
||||
if (!count($lines)) {
|
||||
fwrite(STDOUT, "\e[0;32mFound no issues with code quality.\e[0m");
|
||||
fwrite(STDOUT, "\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Group errors by file
|
||||
$files = [];
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$filename = str_replace(dirname(dirname(dirname(__DIR__))), '', $line[0]);
|
||||
|
||||
if (empty($files[$filename])) {
|
||||
$files[$filename] = [];
|
||||
}
|
||||
|
||||
$files[$filename][] = [
|
||||
'warning' => (($line[3] ?? 'err') === 'warning'),
|
||||
'message' => $line[4] ?? 'unknown',
|
||||
'line' => $line[1] ?? '0',
|
||||
];
|
||||
}
|
||||
|
||||
// Render report
|
||||
fwrite(STDERR, "\e[0;31mFound "
|
||||
. ((count($lines) === 1)
|
||||
? '1 issue'
|
||||
: count($lines) . ' issues')
|
||||
. " with code quality.\e[0m");
|
||||
fwrite(STDERR, "\n");
|
||||
|
||||
foreach ($files as $file => $errors) {
|
||||
fwrite(STDERR, "\n");
|
||||
fwrite(STDERR, "\e[1;37m" . str_replace('"', '', $file) . "\e[0m");
|
||||
fwrite(STDERR, "\n\n");
|
||||
|
||||
foreach ($errors as $error) {
|
||||
fwrite(STDERR, "\e[2m" . str_pad(' L' . $error['line'], 7) . " | \e[0m");
|
||||
fwrite(STDERR, $error['warning'] ? "\e[1;33mWARN:\e[0m " : "\e[0;31mERR:\e[0m ");
|
||||
fwrite(STDERR, $error['message']);
|
||||
fwrite(STDERR, "\n");
|
||||
}
|
||||
}
|
||||
exit(1);
|
||||
|
||||
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/storage/
|
||||
/vendor/
|
||||
/node_modules/
|
||||
.env
|
||||
composer.lock
|
||||
*.sqlite
|
||||
*.sqlite-journal
|
||||
60
.htaccess
Normal file
@@ -0,0 +1,60 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
|
||||
<IfModule mod_negotiation.c>
|
||||
Options -MultiViews
|
||||
</IfModule>
|
||||
|
||||
RewriteEngine On
|
||||
|
||||
##
|
||||
## You may need to uncomment the following line for some hosting environments,
|
||||
## if you have installed to a subdirectory, enter the name here also.
|
||||
##
|
||||
# RewriteBase /
|
||||
|
||||
##
|
||||
## Uncomment following lines to force HTTPS.
|
||||
##
|
||||
# RewriteCond %{HTTPS} off
|
||||
# RewriteRule (.*) https://%{SERVER_NAME}/$1 [L,R=301]
|
||||
|
||||
##
|
||||
## Paths explicitly blocked from being handled by the server
|
||||
##
|
||||
RewriteRule ^bootstrap/.* index.php [L,NC]
|
||||
RewriteRule ^config/.* index.php [L,NC]
|
||||
RewriteRule ^vendor/.* index.php [L,NC]
|
||||
RewriteRule ^storage/cms/.* index.php [L,NC]
|
||||
RewriteRule ^storage/logs/.* index.php [L,NC]
|
||||
RewriteRule ^storage/framework/.* index.php [L,NC]
|
||||
RewriteRule ^storage/temp/protected/.* index.php [L,NC]
|
||||
RewriteRule ^storage/app/uploads/protected/.* index.php [L,NC]
|
||||
|
||||
##
|
||||
## Paths explicitly handled by the server
|
||||
##
|
||||
RewriteCond %{REQUEST_FILENAME} -f
|
||||
RewriteCond %{REQUEST_FILENAME} !/.well-known/*
|
||||
RewriteCond %{REQUEST_FILENAME} !/storage/app/uploads/public/.*
|
||||
RewriteCond %{REQUEST_FILENAME} !/storage/app/media/.*
|
||||
RewriteCond %{REQUEST_FILENAME} !/storage/app/resized/.*
|
||||
RewriteCond %{REQUEST_FILENAME} !/storage/temp/public/.*
|
||||
RewriteCond %{REQUEST_FILENAME} !/themes/.*/(assets|resources)/.*
|
||||
RewriteCond %{REQUEST_FILENAME} !/plugins/.*/(assets|resources)/.*
|
||||
RewriteCond %{REQUEST_FILENAME} !/modules/.*/(assets|resources)/.*
|
||||
RewriteRule !^index.php index.php [L,NC]
|
||||
|
||||
##
|
||||
## Block all PHP files, except index
|
||||
##
|
||||
RewriteCond %{REQUEST_FILENAME} -f
|
||||
RewriteCond %{REQUEST_FILENAME} \.php$
|
||||
RewriteRule !^index.php index.php [L,NC]
|
||||
|
||||
##
|
||||
## Standard routes
|
||||
##
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [L]
|
||||
|
||||
</IfModule>
|
||||
5
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"wintercms.winter-cms"
|
||||
]
|
||||
}
|
||||
41
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"**/modules/*/behaviors/*/partials/*.htm": "php",
|
||||
"**/modules/*/blocks/*.block": "wintercms-block",
|
||||
"**/modules/*/controllers/*/*.htm": "php",
|
||||
"**/modules/*/formwidgets/*/partials/*.htm": "php",
|
||||
"**/modules/*/layouts/*.htm": "php",
|
||||
"**/modules/*/models/*/*.htm": "php",
|
||||
"**/modules/*/partials/*.htm": "php",
|
||||
"**/modules/*/reportwidgets/*/partials/*.htm": "php",
|
||||
"**/modules/*/views/mail/*.htm": "wintercms",
|
||||
"**/modules/*/widgets/*/partials/*.htm": "php",
|
||||
|
||||
"**/plugins/*/*/behaviors/*/partials/*.htm": "php",
|
||||
"**/plugins/*/*/blocks/*.block": "wintercms-block",
|
||||
"**/plugins/*/*/components/**/*.htm": "wintercms-twig",
|
||||
"**/plugins/*/*/controllers/*/*.htm": "php",
|
||||
"**/plugins/*/*/formwidgets/*/partials/*.htm": "php",
|
||||
"**/plugins/*/*/layouts/*.htm": "php",
|
||||
"**/plugins/*/*/models/*/*.htm": "php",
|
||||
"**/plugins/*/*/partials/*.htm": "php",
|
||||
"**/plugins/*/*/reportwidgets/*/partials/*.htm": "php",
|
||||
"**/plugins/*/*/views/mail/*.htm": "wintercms",
|
||||
"**/plugins/*/*/widgets/*/partials/*.htm": "php",
|
||||
|
||||
"**/themes/*/blocks/**/*.block": "wintercms-block",
|
||||
"**/themes/*/content/**/*.htm": "wintercms",
|
||||
"**/themes/*/layouts/*.htm": "wintercms",
|
||||
"**/themes/*/pages/**/*.htm": "wintercms",
|
||||
"**/themes/*/partials/**/*.htm": "wintercms"
|
||||
},
|
||||
"emmet.includeLanguages": {
|
||||
"wintercms": "html",
|
||||
"wintercms-twig": "html",
|
||||
"wintercms-block": "html"
|
||||
},
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"vue"
|
||||
]
|
||||
}
|
||||
95
AGENTS.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Agent guide — Winter CMS core
|
||||
|
||||
Winter core sits on top of [Winter Storm](https://github.com/wintercms/storm) (installed at `vendor/winter/storm/`), which sits on top of Laravel, which sits on top of Symfony components. The helper you want almost certainly already exists at one of those layers. **Search Storm → Laravel → Symfony before writing any "small utility"**, often with safer edge-case handling than a fresh implementation would have.
|
||||
|
||||
## Where to look (in this order)
|
||||
|
||||
1. **Storm itself** — each `vendor/winter/storm/src/<Module>/README.md` catalogues that module's public API:
|
||||
- `Filesystem/` — `PathResolver` (`resolve`, `within`, `join`, `standardize`), `Filesystem` (extends Illuminate's; adds `isAbsolutePath`, `symbolizePath`, `existsInsensitive`, `chmodRecursive`)
|
||||
- `Support/` — strings, arrays, class loading
|
||||
- `Network/`, `Html/`, `Parse/`, `Database/`, `Halcyon/`, `Auth/`, etc.
|
||||
- Path helpers (always loaded): `themes_path()`, `plugins_path()`, `media_path()`, `uploads_path()`, `temp_path()` — use these instead of `base_path('themes')` etc.
|
||||
|
||||
2. **Laravel (Illuminate)** — everything Laravel ships is available:
|
||||
- `Illuminate\Support\Str` — `Str::startsWith/endsWith/contains/before/after/between/slug/camel/snake/kebab/studly/random/uuid/limit/mask/finish/start/of/headline/title`. Use instead of regex one-liners.
|
||||
- `Illuminate\Support\Arr` — `Arr::get/set/has/forget/only/except/dot/undot/flatten/pluck/wrap/first/last/where`. Use instead of nested foreach.
|
||||
- `Illuminate\Support\Collection` (via `collect()`) — chainable map/filter/reduce.
|
||||
- `Illuminate\Filesystem\Filesystem` — `deleteDirectory()`, `cleanDirectory()`, `copyDirectory()`, `moveDirectory()`, `allFiles()`, `glob()`, `isDirectory()`, `prepend()`, `append()`, `replace()`, `hash()`.
|
||||
- Global helpers: `data_get/set/fill`, `value`, `tap`, `optional`, `transform`, `head`, `last`, `class_basename`, `now`, `today`, `e`, `__`/`trans`, `cache`, `config`, `env`, `app`, `resolve`, `route`, `url`, `report`, `rescue`, `retry`, `throw_if`/`unless`, `abort`/`abort_if`/`unless`.
|
||||
- Facades: `Cache`, `Config`, `DB`, `Event`, `File`, `Hash`, `Http`, `Lang`, `Log`, `Mail`, `Queue`, `Redis`, `Route`, `Schema`, `Session`, `Storage`, `URL`, `Validator`, `View`.
|
||||
|
||||
3. **Symfony components** at `vendor/symfony/`: `console`, `css-selector`, `error-handler`, `event-dispatcher`, `finder`, `http-foundation`, `http-kernel`, `mailer`, `mime`, `process`, `routing`, `string`, `translation`, `uid`, `var-dumper`, `yaml`. Most commonly reached for:
|
||||
- `Symfony\Component\Finder\Finder` — `Finder::create()->files()->name('*.less')->in($dir)` replaces RecursiveIteratorIterator chains.
|
||||
- `Symfony\Component\Filesystem\Filesystem` — `dumpFile()` (atomic write), `mirror()`, `mkdir()` (idempotent), `remove()`, `symlink()`.
|
||||
- `Symfony\Component\Process\Process` — safe external command execution instead of `exec()`/`shell_exec()`.
|
||||
- `Symfony\Component\Yaml\Yaml` — strict YAML.
|
||||
- `Symfony\Component\String\` — Unicode-aware strings.
|
||||
- `Symfony\Component\Uid\Uuid`/`Ulid` — UUID/ULID generation.
|
||||
|
||||
`grep -rl 'function <thing>' vendor/winter/storm/src/ vendor/laravel/framework/src/ vendor/symfony/` is a 10-second check.
|
||||
|
||||
## Concrete substitutions worth memorising
|
||||
|
||||
Paths and filesystem:
|
||||
|
||||
| If you reach for… | Use this instead |
|
||||
|---|---|
|
||||
| `realpath()` + null-check + slash-trim | `\Winter\Storm\Filesystem\PathResolver::resolve()` |
|
||||
| `str_starts_with($path, $root)` to gate file access | `PathResolver::within($path, $root)` — separator-boundary safe |
|
||||
| Manual `base_path('themes')` / `base_path('plugins')` | `themes_path()` / `plugins_path()` (Storm's autoloaded helpers) |
|
||||
| Recursive `rmrf` in tests | `\File::deleteDirectory($path)` (Laravel facade) |
|
||||
| Detect absolute path | `(new \Winter\Storm\Filesystem\Filesystem())->isAbsolutePath($path)` |
|
||||
| Custom path-symbol resolution (`~/...`) | `(new \Winter\Storm\Filesystem\Filesystem())->symbolizePath($path)` |
|
||||
| `str_replace('\\', '/', $path)` (cross-platform comparison) | `(new \Winter\Storm\Filesystem\Filesystem())->normalizePath($path)` |
|
||||
| `str_replace('/', DIRECTORY_SEPARATOR, $path)` (handing to OS API) | `\Winter\Storm\Filesystem\PathResolver::standardize($path)` |
|
||||
| Atomic file write (avoid partial-write races) | `(new \Symfony\Component\Filesystem\Filesystem())->dumpFile($path, $contents)` |
|
||||
| Find files matching a pattern | `\Symfony\Component\Finder\Finder::create()->files()->name('*.ext')->in($dir)` |
|
||||
|
||||
Strings and arrays:
|
||||
|
||||
| If you reach for… | Use this instead |
|
||||
|---|---|
|
||||
| `preg_match('/^prefix/', $s)` | `Str::startsWith($s, 'prefix')` (accepts array of prefixes) |
|
||||
| Manual `strpos !== false` | `Str::contains($s, $needle)` |
|
||||
| `strtolower`-then-replace slug generation | `Str::slug($s)` |
|
||||
| Random hex/string for tmp paths, tokens | `Str::random()` / `Str::uuid()` |
|
||||
| Deep array key access with null safety | `data_get($array, 'a.b.c', $default)` |
|
||||
| Pulling subset of array keys | `Arr::only($array, [...])` / `Arr::except($array, [...])` |
|
||||
| Chained map / filter / reduce on array | `collect($array)->filter(...)->map(...)->values()->all()` |
|
||||
|
||||
Other:
|
||||
|
||||
| If you reach for… | Use this instead |
|
||||
|---|---|
|
||||
| `exec()` / `shell_exec()` / backticks | `(new \Symfony\Component\Process\Process([$cmd, ...$args]))->mustRun()` |
|
||||
| Manual YAML parsing | `\Symfony\Component\Yaml\Yaml::parse()` |
|
||||
| JSON parsing without strict error handling | `json_decode($s, true, 512, JSON_THROW_ON_ERROR)` |
|
||||
| UUID generation by `random_bytes` + hex shuffle | `Str::uuid()` or `\Symfony\Component\Uid\Uuid::v7()` |
|
||||
| HTTP request to external service | Laravel's `\Http::get(...)` facade |
|
||||
|
||||
## Layering boundaries
|
||||
|
||||
Storm depends on Laravel + Symfony pieces. It must **not** depend on Winter modules. Conversely, Winter core modules are free to use Storm. So:
|
||||
|
||||
- CMS / theme / plugin / system concerns live in `modules/` (backend, cms, system).
|
||||
- Generic filesystem, path, parser, network primitives live in `vendor/winter/storm/`.
|
||||
- When a Storm class needs a *policy* that's CMS-specific (e.g. "which directories count as theme asset roots"), expose a public setter on the Storm class and have the module-level caller supply the policy. Don't reach into module-level constants from Storm.
|
||||
|
||||
## Autoloading & file placement
|
||||
|
||||
Modules and plugins are autoloaded by `Winter\Storm\Support\ClassLoader` (see `ClassLoader::load()`), **not** plain PSR-4. Its convention: the namespace's **directory segments are lower-cased** to form the path, while the class file keeps its proper PascalCase name. So `System\Twig\SecurityPolicy\SafeCollection` resolves to `modules/system/twig/securitypolicy/SafeCollection.php` — note the lowercase `securitypolicy/` directory.
|
||||
|
||||
- **New sub-namespace directories must be lowercase on disk**, even though the namespace segment stays PascalCase: `System\Twig\Node` → `modules/system/twig/node/`, not `Node/`. The file name keeps its PascalCase and must match the class name exactly.
|
||||
- This only bites on case-sensitive filesystems: a capitalized directory works on macOS/Windows (case-insensitive) and passes local tests, then fails Linux CI with `Class "…" not found`. **If Windows CI is green but every Ubuntu job fails to find a class, suspect a directory-case mismatch.**
|
||||
|
||||
## Tests
|
||||
|
||||
- Backend/CMS/system tests usually extend `System\Tests\Bootstrap\PluginTestCase` (boots Laravel, plugins, auth) or `System\Tests\Bootstrap\TestCase` (boots the framework but not plugins).
|
||||
- Fixtures that flow through `Assetic\Asset\FileAsset` (e.g. `CombineAssets::combineToFile()`) must live under `base_path()`. `sys_get_temp_dir()` will fail with "source is not in the root directory". Use `base_path('storage/framework/cache/<unique>')` for temp dirs and clean up with `\File::deleteDirectory()` in `tearDown()`.
|
||||
- A failing test that doesn't reproduce on a fresh clone is almost always a stale local `vendor/`. Run `composer update` in Storm (`~/Repositories/WinterCMS/Core/storm` or wherever you check it out) before claiming "environment issue".
|
||||
|
||||
## Working across Winter core + Storm
|
||||
|
||||
When a change touches both, work in the actual local checkouts (e.g. `~/Repositories/WinterCMS/Core/storm` and `~/Repositories/WinterCMS/Core/winter`) on parallel branches, and symlink `vendor/winter/storm` to the local Storm checkout so changes are visible in the live install. Avoid `/tmp` worktrees — the user can't test what they can't see.
|
||||
|
||||
Open both PRs concurrently; the maintainer handles merge order and Storm release tagging. The Winter core PR's `composer.json` constraint bump waits for the Storm tag.
|
||||
1
CHANGELOG.md
Normal file
@@ -0,0 +1 @@
|
||||
View the changelog on the [meta repository](https://github.com/wintercms/meta/tree/master/release-notes)
|
||||
45
Dockerfile
Normal file
@@ -0,0 +1,45 @@
|
||||
FROM php:8.2-apache-bookworm
|
||||
|
||||
LABEL coolify.managed=true
|
||||
LABEL maintainer="VivesPOS"
|
||||
|
||||
ENV APACHE_DOCUMENT_ROOT=/var/www/html
|
||||
ENV COMPOSER_ALLOW_SUPERUSER=1
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libpng-dev libjpeg-dev libfreetype6-dev libzip-dev libsqlite3-dev \
|
||||
unzip git curl && \
|
||||
docker-php-ext-configure gd --with-freetype --with-jpeg && \
|
||||
docker-php-ext-install gd zip pdo_sqlite pdo_mysql mbstring exif opcache && \
|
||||
a2enmod rewrite headers expires && \
|
||||
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' \
|
||||
/etc/apache2/sites-available/*.conf && \
|
||||
sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' \
|
||||
/etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf && \
|
||||
printf '<Directory ${APACHE_DOCUMENT_ROOT}>\n AllowOverride All\n Require all granted\n</Directory>\n' \
|
||||
> /etc/apache2/conf-available/vivespos.conf && \
|
||||
a2enconf vivespos
|
||||
|
||||
WORKDIR /var/www/html
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN composer install --no-dev --optimize-autoloader --no-interaction || true
|
||||
|
||||
RUN php artisan winter:version 2>/dev/null || true
|
||||
|
||||
RUN php artisan key:generate --force 2>/dev/null || true
|
||||
|
||||
RUN chown -R www-data:www-data /var/www/html && \
|
||||
chmod -R 755 /var/www/html && \
|
||||
chmod -R 777 storage bootstrap/cache themes plugins
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
|
||||
CMD curl -f http://localhost:80/ || exit 1
|
||||
|
||||
CMD ["apache2-foreground"]
|
||||
22
LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2013-2021.03.01 October CMS
|
||||
Copyright (c) 2021 Winter CMS
|
||||
|
||||
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.
|
||||
115
README.md
Normal file
@@ -0,0 +1,115 @@
|
||||
<p align="center">
|
||||
<img src="https://github.com/wintercms/winter/raw/develop/.github/assets/Github%20Banner.png?raw=true" alt="Winter CMS Logo" width="100%" />
|
||||
</p>
|
||||
|
||||
[Winter](https://wintercms.com) is a free, open-source content management system based on the [Laravel](https://laravel.com) PHP framework. Developers and agencies all around the world rely upon Winter for its quick prototyping and development, safe and secure codebase and dedication to simplicity.
|
||||
|
||||
No matter how large or small your project is, Winter provides a rich development environment, regardless of your level of experience.
|
||||
|
||||
[](https://github.com/wintercms/winter/releases)
|
||||
[](https://github.com/wintercms/winter/actions)
|
||||
[](https://packagist.org/packages/wintercms/winter)
|
||||
[](https://discord.gg/D5MFSPH6Ux)
|
||||
|
||||
## Installing Winter
|
||||
|
||||
Winter can be installed in several ways for both new users and experienced developers - see our [Installation page](https://wintercms.com/install) for more information.
|
||||
|
||||
### Quick start with Composer
|
||||
|
||||
For advanced users, run the following command in your terminal to install Winter via Composer:
|
||||
|
||||
```shell
|
||||
composer create-project wintercms/winter example.com "dev-develop"
|
||||
```
|
||||
|
||||
Run the following command with the folder created by the previous command to generate an environment file which will contain your configuration settings:
|
||||
|
||||
```shell
|
||||
php artisan winter:env
|
||||
```
|
||||
|
||||
After configuring your installation, you can run the following command to run the database migrations and automatically create an administrator account with the username `admin`. The password of this account will be automatically generated and displayed in your terminal.
|
||||
|
||||
```shell
|
||||
php artisan winter:up
|
||||
```
|
||||
|
||||
## Learning Winter
|
||||
|
||||
The best place to learn Winter is by [reading the documentation](https://wintercms.com/docs) or [following some tutorials](https://wintercms.com/blog/category/tutorials). You can also join the maintenance team and our active community on [Discord](https://discord.gg/D5MFSPH6Ux) who are always willing to help out with questions.
|
||||
|
||||
## Development team
|
||||
|
||||
Winter was forked from October CMS in March 2021 due to a difference in open source management philosophies between the core maintainer team and the two founders of October.
|
||||
|
||||
The development of Winter is lead by [Luke Towers](https://luketowers.ca/), along with many wonderful people that dedicate their time to help support and grow the community. The [Frostbyte Foundation](mailto:hello@frostbytefoundation.org) provides an organisational backing for the project and the continued development of Winter, its plugins and themes and its ecosystem.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/luketowers"><img src="https://avatars.githubusercontent.com/u/7253840?v=3" width="100px;" alt="Luke Towers"/><br /><sub><b>Luke Towers</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/bennothommo"><img src="https://avatars.githubusercontent.com/u/15900351?v=3" width="100px;" alt="Ben Thomson"/><br /><sub><b>Ben Thomson</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/mjauvin"><img src="https://avatars.githubusercontent.com/u/2013630?v=3" width="100px;" alt="Marc Jauvin"/><br /><sub><b>Marc Jauvin</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/jaxwilko"><img src="https://avatars.githubusercontent.com/u/31214002?v=4" width="100px;" alt="Jack Wilkinson"/><br /><sub><b>Jack Wilkinson</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/damsfx"><img src="https://cdn.wintercms.com/media/coins/headshots/19.jpg" width="100px;" alt="Damien Mathieu"/><br /><sub><b>Damien Mathieu</b></sub></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Foundation library
|
||||
|
||||
Winter is built on top of the wildly-popular [Laravel](https://laravel.com) framework for PHP, with the in-house [Storm](https://github.com/wintercms/storm) library as a buffer between the Laravel framework and the Winter project, to minimize breaking changes and improve stability.
|
||||
|
||||
## Getting in touch
|
||||
|
||||
You can get in touch with the maintainer team using the following mediums:
|
||||
|
||||
* [Follow us on Twitter](https://twitter.com/usewintercms) for announcements and updates.
|
||||
* [Join us on Discord](https://discord.gg/D5MFSPH6Ux) to chat with us.
|
||||
|
||||
## Contributing
|
||||
|
||||
Before contributing issues or pull requests, be sure to review the [Contributing Guidelines](https://github.com/wintercms/.github/blob/master/CONTRIBUTING.md) first.
|
||||
|
||||
### Coding standards
|
||||
|
||||
Please follow the following guides and code standards:
|
||||
|
||||
* [PSR 4 Coding Standards](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md)
|
||||
* [PSR 2 Coding Style Guide](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
|
||||
* [PSR 1 Coding Standards](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md)
|
||||
|
||||
### Code of conduct
|
||||
|
||||
In order to ensure that the Winter community is welcoming to all, please review and abide by the [Code of Conduct](https://github.com/wintercms/.github/blob/master/CODE_OF_CONDUCT.md).
|
||||
|
||||
## Sponsors
|
||||
|
||||
Winter CMS development is financially supported by the generosity of the following sponsors. If you would like to have your name, company and link added to this list and support open-source development, feel free to make a donation to our [Open Collective](https://opencollective.com/wintercms).
|
||||
|
||||
### Organizations
|
||||
|
||||
<a href="https://laravel.com/?ref=wintercms" target="_blank">
|
||||
<img src="https://raw.githubusercontent.com/laravel/art/refs/heads/master/logo-type/5%20svg/3%20RGB/1%20Full%20Color/laravel-logotype-rgb-red.svg" alt="Laravel logo" width="300">
|
||||
</a>
|
||||
|
||||
Laravel provides [Laravel Vapor](https://vapor.laravel.com/?ref=wintercms) to the Winter CMS project which is used to power the serverless PHP hosting used for our [main website and documentation](https://wintercms.com/).
|
||||
|
||||
<a href="https://froala.com/wysiwyg-editor/" target="_blank">
|
||||
<img src="https://froala.com/wp-content/uploads/2019/10/froala.svg" alt="Froala logo" width="300">
|
||||
</a>
|
||||
|
||||
Froala provides a perpetual, Enterprise license to Winter CMS which allows us and our users to use the Froala WYSIWYG Editor in Winter CMS powered projects.
|
||||
|
||||
### Individuals
|
||||
|
||||
Big thanks to our sponsors on OpenCollective:
|
||||
|
||||
- Orville
|
||||
|
||||
## License
|
||||
|
||||
The Winter platform is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
|
||||
|
||||
## Security vulnerabilities
|
||||
|
||||
Please review [our security policy](https://github.com/wintercms/winter/security/policy) on how to report security vulnerabilities.
|
||||
51
artisan
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register The Auto Loader
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Composer provides a convenient, automatically generated class loader
|
||||
| for our application. We just need to utilize it! We'll require it
|
||||
| into the script here so that we do not have to worry about the
|
||||
| loading of any of our classes manually. It's great to relax.
|
||||
|
|
||||
*/
|
||||
|
||||
require __DIR__.'/bootstrap/autoload.php';
|
||||
|
||||
$app = require_once __DIR__.'/bootstrap/app.php';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Run The Artisan Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When we run the console application, the current CLI command will be
|
||||
| executed in this console and the response sent back to a terminal
|
||||
| or another output device for the developers. Here goes nothing!
|
||||
|
|
||||
*/
|
||||
|
||||
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
||||
|
||||
$status = $kernel->handle(
|
||||
$input = new Symfony\Component\Console\Input\ArgvInput,
|
||||
new Symfony\Component\Console\Output\ConsoleOutput
|
||||
);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Shutdown The Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Once Artisan has finished running, we will fire off the shutdown events
|
||||
| so that any final work may be done by the application before we shut
|
||||
| down the process. This is the last thing to happen to the request.
|
||||
|
|
||||
*/
|
||||
|
||||
$kernel->terminate($input, $status);
|
||||
|
||||
exit($status);
|
||||
55
bootstrap/app.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Create The Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The first thing we will do is create a new Laravel application instance
|
||||
| which serves as the "glue" for all the components of Laravel, and is
|
||||
| the IoC container for the system binding all of the various parts.
|
||||
|
|
||||
*/
|
||||
|
||||
$app = new Winter\Storm\Foundation\Application(
|
||||
realpath(__DIR__.'/../')
|
||||
);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bind Important Interfaces
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Next, we need to bind some important interfaces into the container so
|
||||
| we will be able to resolve them when needed. The kernels serve the
|
||||
| incoming requests to this application from both the web and CLI.
|
||||
|
|
||||
*/
|
||||
|
||||
$app->singleton(
|
||||
Illuminate\Contracts\Http\Kernel::class,
|
||||
Winter\Storm\Foundation\Http\Kernel::class
|
||||
);
|
||||
|
||||
$app->singleton(
|
||||
Illuminate\Contracts\Console\Kernel::class,
|
||||
Winter\Storm\Foundation\Console\Kernel::class
|
||||
);
|
||||
|
||||
$app->singleton(
|
||||
Illuminate\Contracts\Debug\ExceptionHandler::class,
|
||||
Winter\Storm\Foundation\Exception\Handler::class
|
||||
);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Return The Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This script returns the application instance. The instance is given to
|
||||
| the calling script so we can separate the building of the instances
|
||||
| from the actual running of the application and sending responses.
|
||||
|
|
||||
*/
|
||||
|
||||
return $app;
|
||||
38
bootstrap/autoload.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
define('LARAVEL_START', microtime(true));
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register Core Helpers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| We cannot rely on Composer's load order when calculating the weight of
|
||||
| each package. This line ensures that the core global helpers are
|
||||
| always given priority one status.
|
||||
|
|
||||
*/
|
||||
|
||||
$helperPath = __DIR__.'/../vendor/winter/storm/src/Support/helpers.php';
|
||||
|
||||
if (!file_exists($helperPath)) {
|
||||
header('HTTP/1.0 500 Internal Server Error');
|
||||
echo 'Missing vendor files, try running "composer install" or use the Wizard installer.'.PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require $helperPath;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register The Composer Auto Loader
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Composer provides a convenient, automatically generated class loader
|
||||
| for our application. We just need to utilize it! We'll require it
|
||||
| into the script here so that we do not have to worry about the
|
||||
| loading of any our classes "manually". Feels great to relax.
|
||||
|
|
||||
*/
|
||||
|
||||
require __DIR__.'/../vendor/autoload.php';
|
||||
2
bootstrap/cache/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
92
composer.json
Normal file
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"name": "wintercms/winter",
|
||||
"description": "Free, open-source, self-hosted CMS platform based on the Laravel PHP Framework. Originally known as October CMS.",
|
||||
"homepage": "https://wintercms.com",
|
||||
"type": "project",
|
||||
"keywords": ["winter", "cms", "wintercms", "laravel", "cmf"],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alexey Bobkov",
|
||||
"email": "aleksey.bobkov@gmail.com",
|
||||
"role": "Original Author"
|
||||
},
|
||||
{
|
||||
"name": "Samuel Georges",
|
||||
"email": "daftspunky@gmail.com",
|
||||
"role": "Original Author"
|
||||
},
|
||||
{
|
||||
"name": "Luke Towers",
|
||||
"email": "wintercms@luketowers.ca",
|
||||
"role": "Lead Maintainer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/wintercms/winter/issues",
|
||||
"docs": "https://wintercms.com/docs/",
|
||||
"discord": "https://discord.gg/D5MFSPH6Ux",
|
||||
"source": "https://github.com/wintercms/winter"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"winter/storm": "~1.2.0",
|
||||
"winter/wn-system-module": "~1.2.0",
|
||||
"winter/wn-backend-module": "~1.2.0",
|
||||
"winter/wn-cms-module": "~1.2.0",
|
||||
"laravel/framework": "^9.1",
|
||||
"wikimedia/composer-merge-plugin": "~2.1.0",
|
||||
"winter/wn-pages-plugin": "~1.2.0",
|
||||
"winter/wn-blog-plugin": "~1.2.0",
|
||||
"winter/wn-sitemap-plugin": "~1.2.0",
|
||||
"winter/wn-seo-plugin": "~1.2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.5.8",
|
||||
"mockery/mockery": "^1.4.4",
|
||||
"fakerphp/faker": "^1.9.2",
|
||||
"squizlabs/php_codesniffer": "^3.2",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.0",
|
||||
"dms/phpunit-arraysubset-asserts": "^0.1.0|^0.2.1"
|
||||
},
|
||||
"scripts": {
|
||||
"post-create-project-cmd": [
|
||||
"@php artisan winter:install",
|
||||
"@php artisan winter:env",
|
||||
"@php artisan winter:mirror public --relative"
|
||||
],
|
||||
"post-update-cmd": [
|
||||
"@php artisan winter:version",
|
||||
"@php artisan package:discover"
|
||||
],
|
||||
"test": [
|
||||
"phpunit --stop-on-failure"
|
||||
],
|
||||
"lint": [
|
||||
"parallel-lint --exclude vendor --exclude storage --exclude modules/system/tests/fixtures/plugins/testvendor/goto/Plugin.php ."
|
||||
],
|
||||
"sniff": [
|
||||
"phpcs --colors -nq --report=\"full\" --extensions=\"php\""
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"extra": {
|
||||
"merge-plugin": {
|
||||
"include": [
|
||||
"plugins/myauthor/*/composer.json",
|
||||
"plugins/vivespos/*/composer.json"
|
||||
],
|
||||
"recurse": true,
|
||||
"replace": false,
|
||||
"merge-replace": false,
|
||||
"merge-dev": false
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"composer/installers": true,
|
||||
"wikimedia/composer-merge-plugin": true
|
||||
}
|
||||
}
|
||||
}
|
||||
322
config/app.php
Normal file
@@ -0,0 +1,322 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Debug Mode
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When your application is in debug mode, detailed error messages with
|
||||
| stack traces will be shown on every error that occurs within your
|
||||
| application. If disabled, a simple generic error page is shown.
|
||||
|
|
||||
| You can create a CMS page with route "/error" to set the contents
|
||||
| of this page. Otherwise a default error page is shown.
|
||||
|
|
||||
| IMPORTANT: Always have debug mode set to false in production environments
|
||||
| as it can reveal sensitive information about your application and
|
||||
| infrastructure to untrusted users through more detailed errors.
|
||||
|
|
||||
*/
|
||||
|
||||
'debug' => env('APP_DEBUG', true),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value is the name of your application. This value is used when the
|
||||
| framework needs to place the application's name in a notification or
|
||||
| any other location as required by the application or its packages.
|
||||
|
|
||||
*/
|
||||
|
||||
'name' => env('APP_NAME', 'Winter CMS'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application URL
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This URL is used by the console to properly generate URLs when using
|
||||
| the Artisan command line tool. You should set this to the root of
|
||||
| your application so that it is used when running Artisan tasks.
|
||||
|
|
||||
*/
|
||||
|
||||
'url' => env('APP_URL', 'http://localhost'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Asset URL
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This URL is used to properly generate URLs for assets, including
|
||||
| URLs generated by the `| theme` & `| asset` filters in Twig, or the
|
||||
| `Url::asset()` & `asset()` helpers. If set to null, the URL used will
|
||||
| be the current hostname or `app.url` config.
|
||||
|
|
||||
| 'asset_url' => 'https://cdn.example.com/',
|
||||
|
|
||||
*/
|
||||
|
||||
'asset_url' => env('ASSET_URL', null),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Temporary Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is used to set the application's temporary path. Normally this value
|
||||
| is set automatically by the application, however on some systems you
|
||||
| may need to change it (Laravel Vapor / read-only systems: /tmp).
|
||||
|
|
||||
*/
|
||||
|
||||
'tempPath' => env('APP_TEMP_PATH', null),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Trusted hosts
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You may specify valid hosts for your application as an array or boolean
|
||||
| below. This helps prevent host header poisoning attacks.
|
||||
|
|
||||
| Possible values:
|
||||
| - `true`: Trust the host specified in app.url, as well as the "www"
|
||||
| subdomain, if applicable.
|
||||
| - `false`: Disable the trusted hosts feature.
|
||||
| - array: Defines the domains to be trusted hosts. Each item should be
|
||||
| a string defining a domain, IP address, or a regex pattern.
|
||||
|
|
||||
| Example of array values:
|
||||
|
|
||||
| 'trustedHosts' => [
|
||||
| 'example.com', // Matches just example.com
|
||||
| 'www.example.com', // Matches just www.example.com
|
||||
| '^(.+\.)?example\.com$', // Matches example.com and all subdomains
|
||||
| 'https://example.com', // Matches just example.com
|
||||
| ],
|
||||
|
|
||||
| NOTE: Even when set to `false`, this functionality is explicitly enabled
|
||||
| on the Backend password reset flow for security reasons.
|
||||
*/
|
||||
|
||||
'trustedHosts' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Trusted proxies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You may specify valid proxies for your application, in order for URLs
|
||||
| and requests to be presented as the proxy address should you request
|
||||
| a URL through the proxy.
|
||||
|
|
||||
| Possible values:
|
||||
| - `null` or `false`: Do not trust any proxies
|
||||
| - `'*'`: Trust all proxies
|
||||
| - string: A single or comma-separated list of proxies to trust
|
||||
| - array: An array of proxies to trust
|
||||
|
|
||||
| Examples:
|
||||
| - To trust any proxy (i.e. a single proxy with an unknown IP address):
|
||||
|
|
||||
| 'trustedProxies' => '*',
|
||||
|
|
||||
| - To trust all proxies (i.e. AWS ELB behind CloudFront):
|
||||
|
|
||||
| 'trustedProxies' => '**',
|
||||
|
|
||||
| - To trust two IP addresses as proxies
|
||||
|
|
||||
| 'trustedProxies' => '192.168.1.1, 192.168.1.2',
|
||||
| 'trustedProxies' => ['192.168.1.1', '192.168.1.2'],
|
||||
*/
|
||||
|
||||
'trustedProxies' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Trusted proxy headers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| In addition to the above, you can also determine which headers to trust
|
||||
| from your proxy when rewriting the request. This is an integer map value
|
||||
| so you may specify more than one value.
|
||||
|
|
||||
| Possible values:
|
||||
| - 'HEADER_X_FORWARDED_ALL' - trust all forwarded headers
|
||||
| - Illuminate\Http\Request::HEADER_X_FORWARDED_FOR - trust only the proxy IP
|
||||
| - Illuminate\Http\Request::HEADER_X_FORWARDED_HOST - trust only the proxy hostname
|
||||
| - Illuminate\Http\Request::HEADER_X_FORWARDED_PORT - trust only the proxy port
|
||||
| - Illuminate\Http\Request::HEADER_X_FORWARDED_PROTO - trust only the proxy protocol
|
||||
| - Illuminate\Http\Request::HEADER_X_FORWARDED_PREFIX - trust only the proxy prefix
|
||||
| - Illuminate\Http\Request::HEADER_X_FORWARDED_AWS_ELB - trust Amazon Elastic Load Balancing headers
|
||||
| - Illuminate\Http\Request::HEADER_X_FORWARDED_TRAEFIK - trust Traefik reverse proxy headers
|
||||
|
|
||||
| Examples:
|
||||
| - To trust only the hostname, use the following:
|
||||
|
|
||||
| 'trustedProxyHeaders' => Illuminate\Http\Request::HEADER_X_FORWARDED_HOST
|
||||
|
|
||||
| - For trusting all except the protocol, you can use the following:
|
||||
|
|
||||
| 'trustedProxyHeaders' => Illuminate\Http\Request::HEADER_X_FORWARDED_FOR
|
||||
| | Illuminate\Http\Request::HEADER_X_FORWARDED_HOST
|
||||
| | Illuminate\Http\Request::HEADER_X_FORWARDED_PORT
|
||||
|
|
||||
| - Amazon ELB users should always use the "HEADER_X_FORWARDED_AWS_ELB" option.
|
||||
*/
|
||||
|
||||
'trustedProxyHeaders' => 'HEADER_X_FORWARDED_ALL',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Timezone
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default timezone for your application, which
|
||||
| will be used by the PHP date and date-time functions. We have gone
|
||||
| ahead and set this to a sensible default for you out of the box.
|
||||
|
|
||||
|
|
||||
| -------- STOP! --------
|
||||
| Before you change this value, consider carefully if that is actually
|
||||
| what you want to do. It is HIGHLY recommended that this is always set
|
||||
| to UTC (as your server & DB timezone should be as well) and instead you
|
||||
| use cms.backendTimezone to set the default timezone used in the backend
|
||||
| to display dates & times.
|
||||
|
|
||||
*/
|
||||
|
||||
'timezone' => 'UTC',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Scheduler Timezone
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This property specifies the default timezone for your application's
|
||||
| scheduled tasks. You can set it independently of the application's
|
||||
| default timezone to ensure that schedules run at the desired local time.
|
||||
|
|
||||
*/
|
||||
|
||||
'schedule_timezone' => 'UTC',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Locale Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The application locale determines the default locale that will be used
|
||||
| by the translation service provider. You are free to set this value
|
||||
| to any of the locales which will be supported by the application.
|
||||
|
|
||||
| WARNING: Avoid setting this to a locale that is not supported by the
|
||||
| backend yet, as this can cause issues in the backend.
|
||||
|
|
||||
| Currently supported backend locales are listed in
|
||||
| Backend\Models\Preference->getLocaleOptions()
|
||||
|
|
||||
*/
|
||||
|
||||
'locale' => 'en',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Fallback Locale
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The fallback locale determines the locale to use when the current one
|
||||
| is not available. You may change the value to correspond to any of
|
||||
| the language folders that are provided through your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'fallback_locale' => 'en',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Faker Locale
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This locale will be used by the Faker PHP library when generating fake
|
||||
| data for your database seeds. For example, this will be used to get
|
||||
| localized telephone numbers, street address information and more.
|
||||
|
|
||||
*/
|
||||
|
||||
'faker_locale' => 'en_US',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Encryption Key
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This key is used by the Illuminate encrypter service and should be set
|
||||
| to a random, 32 character string, otherwise these encrypted strings
|
||||
| will not be safe. Please do this before deploying an application!
|
||||
|
|
||||
*/
|
||||
|
||||
'key' => env('APP_KEY'),
|
||||
'cipher' => 'AES-256-CBC',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Autoloaded Service Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The service providers listed here will be automatically loaded on the
|
||||
| request to your application. Feel free to add your own services to
|
||||
| this array to grant expanded functionality to your applications.
|
||||
|
|
||||
*/
|
||||
|
||||
'providers' => array_merge(include(base_path('modules/system/providers.php')), [
|
||||
|
||||
// 'Illuminate\Html\HtmlServiceProvider', // Example
|
||||
|
||||
System\ServiceProvider::class,
|
||||
]),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Load automatically discovered packages
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By default, Winter CMS disables the loading of discovered packages
|
||||
| through Laravel's package discovery service, in order to allow packages
|
||||
| used by plugins to be disabled if the plugin itself is disabled.
|
||||
|
|
||||
| Set this to `true` to enable automatic loading of these packages. This
|
||||
| will result in packages being loaded, even if the plugin using them is
|
||||
| disabled. This is NOT RECOMMENDED.
|
||||
|
|
||||
| Please note that packages defined in `app.providers` will still be loaded
|
||||
| even if discovery is disabled.
|
||||
|
|
||||
*/
|
||||
|
||||
'loadDiscoveredPackages' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Class Aliases
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This array of class aliases will be registered when this application
|
||||
| is started. However, feel free to register as many as you wish as
|
||||
| the aliases are "lazy" loaded so they don't hinder performance.
|
||||
|
|
||||
*/
|
||||
|
||||
'aliases' => array_merge(include(base_path('modules/system/aliases.php')), [
|
||||
// 'Str' => 'Illuminate\Support\Str', // Example
|
||||
]),
|
||||
];
|
||||
41
config/auth.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'throttle' => [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Enable throttling of Backend authentication attempts
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If set to true, users will be given a limited number of attempts to sign
|
||||
| in to the Backend before being blocked for a specified number of minutes.
|
||||
|
|
||||
*/
|
||||
|
||||
'enabled' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Failed Authentication Attempt Limit
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Number of failed attempts allowed while trying to authenticate a user.
|
||||
|
|
||||
*/
|
||||
|
||||
'attemptLimit' => 5,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Suspension Time
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The number of minutes to suspend further attempts on authentication once
|
||||
| the attempt limit is reached.
|
||||
|
|
||||
*/
|
||||
|
||||
'suspensionTime' => 15,
|
||||
],
|
||||
];
|
||||
60
config/broadcasting.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Broadcaster
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default broadcaster that will be used by the
|
||||
| framework when an event needs to be broadcast. You may set this to
|
||||
| any of the connections defined in the "connections" array below.
|
||||
|
|
||||
| Supported: "pusher", "ably", "redis", "log", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('BROADCAST_DRIVER', 'null'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Broadcast Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define all of the broadcast connections that will be used
|
||||
| to broadcast events to other systems or over websockets. Samples of
|
||||
| each available type of connection are provided inside this array.
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
'pusher' => [
|
||||
'app_id' => env('PUSHER_APP_ID'),
|
||||
'client_options' => [
|
||||
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
|
||||
],
|
||||
'driver' => 'pusher',
|
||||
'key' => env('PUSHER_APP_KEY'),
|
||||
'options' => [
|
||||
'cluster' => env('PUSHER_APP_CLUSTER'),
|
||||
'useTLS' => true,
|
||||
],
|
||||
'secret' => env('PUSHER_APP_SECRET'),
|
||||
],
|
||||
'ably' => [
|
||||
'driver' => 'ably',
|
||||
'key' => env('ABLY_KEY'),
|
||||
],
|
||||
'redis' => [
|
||||
'connection' => 'default',
|
||||
'driver' => 'redis',
|
||||
],
|
||||
'log' => [
|
||||
'driver' => 'log',
|
||||
],
|
||||
'null' => [
|
||||
'driver' => 'null',
|
||||
],
|
||||
],
|
||||
];
|
||||
139
config/cache.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cache Store
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default cache connection that gets used while
|
||||
| using this caching library. This connection is used when another is
|
||||
| not explicitly specified when executing a given caching function.
|
||||
|
|
||||
| WARNING! Do not use anything that is used for other information in your
|
||||
| application. Example: If you are using redis for managing queues and / or
|
||||
| sessions, you should NOT be using the EXACT SAME redis connection for the
|
||||
| Cache store, as calling Cache::flush() will flush the entire redis store.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('CACHE_DRIVER', 'file'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Stores
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define all of the cache "stores" for your application as
|
||||
| well as their drivers. You may even define multiple stores for the
|
||||
| same cache driver to group types of items stored in your caches.
|
||||
|
|
||||
| Supported drivers: "apc", "array", "database", "file",
|
||||
| "memcached", "redis", "dynamodb", "octane", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'stores' => [
|
||||
'apc' => [
|
||||
'driver' => 'apc',
|
||||
],
|
||||
'array' => [
|
||||
'driver' => 'array',
|
||||
'serialize' => false,
|
||||
],
|
||||
'database' => [
|
||||
'connection' => null,
|
||||
'driver' => 'database',
|
||||
'lock_connection' => null,
|
||||
'table' => 'cache',
|
||||
],
|
||||
'file' => [
|
||||
'driver' => 'file',
|
||||
'path' => storage_path('framework/cache'),
|
||||
],
|
||||
'memcached' => [
|
||||
'driver' => 'memcached',
|
||||
'options' => [
|
||||
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
|
||||
],
|
||||
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
|
||||
'sasl' => [
|
||||
env('MEMCACHED_USERNAME'),
|
||||
env('MEMCACHED_PASSWORD'),
|
||||
],
|
||||
'servers' => [
|
||||
[
|
||||
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
|
||||
'port' => env('MEMCACHED_PORT', 11211),
|
||||
'weight' => 100,
|
||||
],
|
||||
],
|
||||
],
|
||||
'redis' => [
|
||||
'connection' => 'cache',
|
||||
'driver' => 'redis',
|
||||
'lock_connection' => 'default',
|
||||
],
|
||||
'dynamodb' => [
|
||||
'driver' => 'dynamodb',
|
||||
'endpoint' => env('DYNAMODB_ENDPOINT'),
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
|
||||
],
|
||||
'octane' => [
|
||||
'driver' => 'octane',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Key Prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When utilizing a RAM based store such as APC or Memcached, there might
|
||||
| be other applications utilizing the same cache. So, we'll specify a
|
||||
| value to get prefixed to all our keys so we can avoid collisions.
|
||||
|
|
||||
*/
|
||||
|
||||
'prefix' => env('CACHE_PREFIX', str_slug(env('APP_NAME', 'winter'), '_') . '_cache'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Key for the CMS' PHP code parser cache
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the cache key used by the CMS when storing generated
|
||||
| PHP from the theme PHP sections. Recommended to change this when multiple
|
||||
| servers running Winter CMS are connected to the same cache server to
|
||||
| prevent conflicts.
|
||||
|
|
||||
*/
|
||||
|
||||
'codeParserDataCacheKey' => 'cms-php-file-data',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Disable Request Cache
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The request cache stores cache retrievals from the cache store
|
||||
| in memory to speed up consecutive retrievals within the same request.
|
||||
|
|
||||
| true - always disable this in-memory request cache
|
||||
|
|
||||
| false - always enable; be aware that long-running console commands
|
||||
| (including queue workers) may retain cache entries in memory that
|
||||
| have been changed in other processes or would have otherwise
|
||||
| expired, causing issues with the `queue:restart` command, for
|
||||
| example
|
||||
|
|
||||
| null - enable for HTTP requests, disable when running in CLI
|
||||
|
|
||||
*/
|
||||
|
||||
'disableRequestCache' => null,
|
||||
];
|
||||
476
config/cms.php
Normal file
@@ -0,0 +1,476 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Specifies the default CMS theme.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This parameter value can be overridden by the CMS back-end settings.
|
||||
|
|
||||
*/
|
||||
|
||||
'activeTheme' => 'vivespos',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bleeding edge updates
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you are developing with Winter, it is important to have the latest
|
||||
| code base. Set this value to 'true' to tell the platform to download
|
||||
| and use the development copies of core files and plugins.
|
||||
|
|
||||
*/
|
||||
|
||||
'edgeUpdates' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Back-end URI prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specifies the URL name used for accessing back-end pages.
|
||||
| For example: backend -> http://localhost/backend
|
||||
|
|
||||
*/
|
||||
|
||||
'backendUri' => 'backend',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Back-end force HTTPS security
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Use this setting to force a secure protocol when accessing any back-end
|
||||
| pages, including the authentication pages. This is usually handled by
|
||||
| web server config, but can be handled by the app for added security.
|
||||
|
|
||||
*/
|
||||
|
||||
'backendForceSecure' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Back-end login remember
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define live duration of backend sessions:
|
||||
|
|
||||
| true - session never expire (cookie expiration in 5 years)
|
||||
|
|
||||
| false - session have a limited time (see session.lifetime)
|
||||
|
|
||||
| null - The form login display a checkbox that allow user to choose
|
||||
| wanted behavior
|
||||
|
|
||||
*/
|
||||
|
||||
'backendForceRemember' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Back-end timezone
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This acts as the default setting for a back-end user's timezone. This can
|
||||
| be changed by the user at any time using the backend preferences. All
|
||||
| dates displayed in the back-end will be converted to this timezone.
|
||||
|
|
||||
*/
|
||||
|
||||
'backendTimezone' => 'UTC',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Back-end Skin
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specifies the back-end skin to use.
|
||||
|
|
||||
*/
|
||||
|
||||
'backendSkin' => \Backend\Skins\Standard::class,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Automatically run migrations on login
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If value is true, UpdateManager will be run on logging in to the backend.
|
||||
| It's recommended to set this value to 'null' in production enviroments
|
||||
| because it clears the cache every time a user logs in to the backend.
|
||||
| If set to null, this setting is enabled when debug mode (app.debug) is enabled
|
||||
| and disabled when debug mode is disabled.
|
||||
|
|
||||
*/
|
||||
|
||||
'runMigrationsOnLogin' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Determines which modules to load
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specify which modules should be registered when using the application.
|
||||
|
|
||||
*/
|
||||
|
||||
'loadModules' => [
|
||||
'System',
|
||||
'Backend',
|
||||
'Cms',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Prevents application updates
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If using composer or git to download updates to the core files, set this
|
||||
| value to 'true' to prevent the update gateway from trying to download
|
||||
| these files again as part of the application update process. Plugins
|
||||
| and themes will still be downloaded.
|
||||
|
|
||||
*/
|
||||
|
||||
'disableCoreUpdates' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Specific plugins to disable
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specify plugin codes which will always be disabled in the application.
|
||||
|
|
||||
*/
|
||||
|
||||
'disablePlugins' => [],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Determines if the routing caching is enabled.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If the caching is enabled, the page URL map is saved in the cache. If a page
|
||||
| URL was changed on the disk, the old URL value could be still saved in the cache.
|
||||
| To update the cache the back-end Clear Cache feature should be used. It is recommended
|
||||
| to disable the caching during the development, and enable it in the production mode.
|
||||
|
|
||||
*/
|
||||
|
||||
'enableRoutesCache' => env('ROUTES_CACHE', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Time to live for the URL map.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The URL map used in the CMS page routing process. By default
|
||||
| the map is updated every time when a page is saved in the back-end or when the
|
||||
| interval, in minutes, specified with the urlMapCacheTTL parameter expires.
|
||||
|
|
||||
*/
|
||||
|
||||
'urlCacheTtl' => 10,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Time to live for parsed CMS objects.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specifies the number of minutes the CMS object cache lives. After the interval
|
||||
| is expired item are re-cached. Note that items are re-cached automatically when
|
||||
| the corresponding template file is modified.
|
||||
|
|
||||
*/
|
||||
|
||||
'parsedPageCacheTTL' => 10,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Determines if the asset caching is enabled.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If the caching is enabled, combined assets are cached. If a asset file
|
||||
| is changed on the disk, the old file contents could be still saved in the cache.
|
||||
| To update the cache the back-end Clear Cache feature should be used. It is recommended
|
||||
| to disable the caching during the development, and enable it in the production mode.
|
||||
|
|
||||
*/
|
||||
|
||||
'enableAssetCache' => env('ASSET_CACHE', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Determines if the asset minification is enabled.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If the minification is enabled, combined assets are compressed (minified).
|
||||
| It is recommended to disable the minification during development, and
|
||||
| enable it in production mode. If set to null, assets are minified
|
||||
| when debug mode (app.debug) is disabled.
|
||||
|
|
||||
*/
|
||||
|
||||
'enableAssetMinify' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Check import timestamps when combining assets
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If deep hashing is enabled, the combiner cache will be reset when a change
|
||||
| is detected on imported files, in addition to those referenced directly.
|
||||
| This will cause slower page performance. If set to null, deep hashing
|
||||
| is used when debug mode (app.debug) is enabled.
|
||||
|
|
||||
*/
|
||||
|
||||
'enableAssetDeepHashing' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Database-driven Themes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Stores theme templates in the database instead of the filesystem.
|
||||
|
|
||||
| false - All theme templates are sourced from the filesystem.
|
||||
|
|
||||
| true - Source theme templates from the database with fallback to the filesytem.
|
||||
|
|
||||
| null - Setting equal to the inverse of app.debug: debug enabled, this disabled.
|
||||
|
|
||||
| The database layer stores all modified CMS files in the database. Files that are
|
||||
| not modified continue to be loaded from the filesystem. The `theme:sync $themeDir`
|
||||
| console command is available to populate the database from the filesystem with
|
||||
| the `--toFile` flag to sync in the other direction (database to filesystem) and
|
||||
| the `--paths="/path/to/file.md,/path/to/file2.md" flag to sync only specific files.
|
||||
|
|
||||
| Files modified in the database are cached to indicate that they should be loaded
|
||||
| from the database.
|
||||
|
|
||||
*/
|
||||
|
||||
'databaseTemplates' => env('DATABASE_TEMPLATES', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Public plugins path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specifies the public plugins path relative to the application base URL,
|
||||
| or you can specify a full URL path.
|
||||
|
|
||||
*/
|
||||
|
||||
'pluginsPath' => '/plugins',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Public themes path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specifies the public themes path relative to the application base URL,
|
||||
| or you can specify a full URL path.
|
||||
|
|
||||
*/
|
||||
|
||||
'themesPath' => '/themes',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Resource storage
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specifies the configuration for resource storage, such as media and
|
||||
| upload files. These resources are used:
|
||||
|
|
||||
| media - generated by the media manager.
|
||||
| uploads - generated by attachment model relationships.
|
||||
| resized - generated by System\Classes\ImageResizer or the resize() Twig filter
|
||||
|
|
||||
| For each resource you can specify:
|
||||
|
|
||||
| disk - filesystem disk, as specified in filesystems.php config.
|
||||
| folder - a folder prefix for storing all generated files inside.
|
||||
| path - the public path relative to the application base URL,
|
||||
| or you can specify a full URL path.
|
||||
|
|
||||
| Optionally, you can specify how long temporary URLs to protected files
|
||||
| in cloud storage (ex. AWS, RackSpace) are valid for by setting
|
||||
| temporaryUrlTTL to a value in seconds to define a validity period. This
|
||||
| is only used for the 'uploads' config when using a supported cloud disk
|
||||
|
|
||||
| NOTE: If you have installed Winter in a subfolder, are using local
|
||||
| storage and are not using a linkPolicy of 'force' you should include
|
||||
| the path to the subfolder in the `path` option for these storage
|
||||
| configurations.
|
||||
|
|
||||
| Example: Winter is installed under https://localhost/projects/winter.
|
||||
| You should then specify `/projects/winter/storage/app/uploads` as the
|
||||
| path for the uploads disk and `/projects/winter/storage/app/media` as
|
||||
| the path for the media disk.
|
||||
*/
|
||||
|
||||
'storage' => [
|
||||
'uploads' => [
|
||||
'disk' => 'local',
|
||||
'folder' => 'uploads',
|
||||
'path' => '/storage/app/uploads',
|
||||
'temporaryUrlTTL' => 3600,
|
||||
],
|
||||
'media' => [
|
||||
'disk' => 'local',
|
||||
'folder' => 'media',
|
||||
'path' => '/storage/app/media',
|
||||
],
|
||||
'resized' => [
|
||||
'disk' => 'local',
|
||||
'folder' => 'resized',
|
||||
'path' => '/storage/app/resized',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Convert Line Endings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Determines if Winter should convert line endings from the windows style
|
||||
| \r\n to the unix style \n.
|
||||
|
|
||||
*/
|
||||
|
||||
'convertLineEndings' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Linking policy
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Controls how URL links are generated throughout the application.
|
||||
|
|
||||
| detect - detect hostname and use the current schema
|
||||
| secure - detect hostname and force HTTPS schema
|
||||
| insecure - detect hostname and force HTTP schema
|
||||
| force - force hostname and schema using app.url config value
|
||||
|
|
||||
| NOTE: force will ensure that the app.url value is used as the host for
|
||||
| urls generated through the URL helpers which might have unintended
|
||||
| consequences for projects that support multiple hostnames.
|
||||
|
|
||||
*/
|
||||
|
||||
'linkPolicy' => env('LINK_POLICY', 'detect'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default permission mask
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specifies a default file and folder permission for newly created objects.
|
||||
|
|
||||
*/
|
||||
|
||||
'defaultMask' => [
|
||||
'file' => null,
|
||||
'folder' => null,
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Safe mode
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If safe mode is enabled, the PHP code section is disabled in the CMS
|
||||
| for security reasons. If set to null, safe mode is enabled when
|
||||
| debug mode (app.debug) is disabled.
|
||||
|
|
||||
*/
|
||||
|
||||
'enableSafeMode' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cross Site Request Forgery (CSRF) Protection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If the CSRF protection is enabled, all "postback" & AJAX requests are
|
||||
| checked for a valid security token.
|
||||
|
|
||||
*/
|
||||
|
||||
'enableCsrfProtection' => env('ENABLE_CSRF', true),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Force bytecode invalidation
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using OPcache with opcache.validate_timestamps set to 0 or APC
|
||||
| with apc.stat set to 0 and Twig cache enabled, clearing the template
|
||||
| cache won't update the cache, set to true to get around this.
|
||||
|
|
||||
*/
|
||||
|
||||
'forceBytecodeInvalidation' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Twig Strict Variables
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If strict_variables is disabled, Twig will silently ignore invalid
|
||||
| variables (variables and or attributes/methods that do not exist) and
|
||||
| replace them with a null value. When enabled, Twig throws an exception
|
||||
| instead. If set to null, it is enabled when debug mode (app.debug) is
|
||||
| enabled.
|
||||
|
|
||||
*/
|
||||
|
||||
'enableTwigStrictVariables' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Base Directory Restriction
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Restricts loading backend template and config files to within the base
|
||||
| directory of the application.
|
||||
|
|
||||
| WARNING: This should always be enabled for security reasons. However, in
|
||||
| some cases you may need to disable this; for instance when developing
|
||||
| plugins that are stored elsewhere in the filesystem for organizational
|
||||
| reasons and then symlinked into the application plugins/ directory.
|
||||
|
|
||||
| NEVER have this disabled in production.
|
||||
|
|
||||
*/
|
||||
|
||||
'restrictBaseDir' => env('RESTRICT_BASE_DIR', true),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Backend Service Worker
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Allow plugins to run Service Workers in the backend.
|
||||
|
|
||||
| WARNING: This should always be disabled for security reasons as Service
|
||||
| Workers can be hijacked and used to run XSS into the backend. Turning
|
||||
| this feature on can create a conflict if you have a frontend Service
|
||||
| Worker running. The 'scope' needs to be correctly set and not have a
|
||||
| duplicate subfolder structure on the frontend, otherwise it will run
|
||||
| on both the frontend and backend of your website.
|
||||
|
|
||||
| true - allow service workers to run in the backend
|
||||
|
|
||||
| false - disallow service workers to run in the backend
|
||||
|
|
||||
*/
|
||||
|
||||
'enableBackendServiceWorkers' => false,
|
||||
];
|
||||
20
config/cookie.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cookies that should not be encrypted
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Winter CMS encrypts/decrypts cookies by default. You can specify cookies
|
||||
| that should not be encrypted or decrypted here. This is useful, for
|
||||
| example, when you want to pass data from frontend to server side backend
|
||||
| via cookies, and vice versa.
|
||||
|
|
||||
*/
|
||||
|
||||
'unencryptedCookies' => [
|
||||
// 'my_cookie',
|
||||
],
|
||||
];
|
||||
34
config/cors.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cross-Origin Resource Sharing (CORS) Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure your settings for cross-origin resource sharing
|
||||
| or "CORS". This determines what cross-origin operations may execute
|
||||
| in web browsers. You are free to adjust these settings as needed.
|
||||
|
|
||||
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
||||
|
|
||||
*/
|
||||
|
||||
'paths' => [],
|
||||
|
||||
'allowed_methods' => ['*'],
|
||||
|
||||
'allowed_origins' => ['*'],
|
||||
|
||||
'allowed_origins_patterns' => [],
|
||||
|
||||
'allowed_headers' => ['*'],
|
||||
|
||||
'exposed_headers' => [],
|
||||
|
||||
'max_age' => 0,
|
||||
|
||||
'supports_credentials' => false,
|
||||
|
||||
];
|
||||
133
config/database.php
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Database Connection Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which of the database connections below you wish
|
||||
| to use as your default connection for all database work. Of course
|
||||
| you may use many connections at once using the Database library.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('DB_CONNECTION', 'mysql'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Database Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here are each of the database connections setup for your application.
|
||||
| Of course, examples of configuring each database platform that is
|
||||
| supported by Winter CMS is shown below to make development simple.
|
||||
|
|
||||
| All database work in Winter CMS is done through the PHP PDO facilities
|
||||
| so make sure you have the driver for your particular database of
|
||||
| choice installed on your machine before you begin development.
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
'sqlite' => [
|
||||
'database' => env('DB_DATABASE', storage_path('database.sqlite')),
|
||||
'driver' => 'sqlite',
|
||||
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
||||
'prefix' => '',
|
||||
'url' => env('DATABASE_URL'),
|
||||
],
|
||||
'mysql' => [
|
||||
'charset' => 'utf8mb4',
|
||||
'collation' => 'utf8mb4_unicode_ci',
|
||||
'database' => env('DB_DATABASE', 'winter'),
|
||||
'driver' => 'mysql',
|
||||
'engine' => 'InnoDB',
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
||||
]) : [],
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'port' => env('DB_PORT', '3306'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'strict' => true,
|
||||
'unix_socket' => env('DB_SOCKET', ''),
|
||||
'url' => env('DATABASE_URL'),
|
||||
'username' => env('DB_USERNAME', 'winter'),
|
||||
],
|
||||
'pgsql' => [
|
||||
'charset' => 'utf8',
|
||||
'database' => env('DB_DATABASE', 'winter'),
|
||||
'driver' => 'pgsql',
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'port' => env('DB_PORT', '5432'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'search_path' => 'public',
|
||||
'sslmode' => 'prefer',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'username' => env('DB_USERNAME', 'winter'),
|
||||
],
|
||||
'sqlsrv' => [
|
||||
'charset' => 'utf8',
|
||||
'database' => env('DB_DATABASE', 'winter'),
|
||||
'driver' => 'sqlsrv',
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'port' => env('DB_PORT', '1433'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'url' => env('DATABASE_URL'),
|
||||
'username' => env('DB_USERNAME', 'winter'),
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Migration Repository Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This table keeps track of all the migrations that have already run for
|
||||
| your application. Using this information, we can determine which of
|
||||
| the migrations on disk haven't actually been run in the database.
|
||||
|
|
||||
*/
|
||||
|
||||
'migrations' => 'migrations',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Redis Databases
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Redis is an open source, fast, and advanced key-value store that also
|
||||
| provides a richer body of commands than a typical key-value system
|
||||
| such as APC or Memcached. Winter makes it easy to dig right in.
|
||||
|
|
||||
*/
|
||||
|
||||
'redis' => [
|
||||
'client' => env('REDIS_CLIENT', 'phpredis'),
|
||||
'options' => [
|
||||
'cluster' => env('REDIS_CLUSTER', 'redis'),
|
||||
'prefix' => env('REDIS_PREFIX', str_slug(env('APP_NAME', 'winter'), '_') . '_database_'),
|
||||
],
|
||||
'default' => [
|
||||
'database' => env('REDIS_DB', '0'),
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'password' => env('REDIS_PASSWORD'),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'url' => env('REDIS_URL'),
|
||||
],
|
||||
'cache' => [
|
||||
'database' => env('REDIS_CACHE_DB', '1'),
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'password' => env('REDIS_PASSWORD'),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'url' => env('REDIS_URL'),
|
||||
],
|
||||
],
|
||||
];
|
||||
2
config/dev/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
58
config/develop.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Decompile backend assets
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Enabling this will load all individual backend asset files, instead of
|
||||
| loading the compiled asset files generated by `winter:util compile
|
||||
| assets`. This is useful only for development purposes, and should not be
|
||||
| enabled in production. Please note that enabling this will make the
|
||||
| Backend load a LOT of individual asset files.
|
||||
|
|
||||
| true - allow decompiled backend assets
|
||||
|
|
||||
| false - use compiled backend assets (default)
|
||||
|
|
||||
*/
|
||||
|
||||
'decompileBackendAssets' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Allow deep-level symlinks
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Winter CMS, by default, will allow symlinks within the first level of
|
||||
| subdirectories. When this feature is enabled, the system will allow
|
||||
| symlinks to be used at any directory level. This can be useful for
|
||||
| symlinking individual plugins or themes.
|
||||
|
|
||||
| Please note that this has a negative effect on performance. This feature
|
||||
| abides by "cms.restrictBaseDir" - if enabled, symlinks cannot point to
|
||||
| resources outside of the root folder.
|
||||
|
|
||||
| true - allow symlinks at any level
|
||||
|
|
||||
| false - only allow symlinks at the first level of subdirectories (default)
|
||||
|
|
||||
*/
|
||||
|
||||
'allowDeepSymlinks' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Enable Snowboard debugging
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By default, Snowboard debugging and client-side logging is disabled.
|
||||
|
|
||||
| If you wish to enable Snowboard debugging, set this value to `true`.
|
||||
|
|
||||
*/
|
||||
|
||||
'debugSnowboard' => env('DEBUG_SNOWBOARD', false),
|
||||
];
|
||||
32
config/environment.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Application Environment
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value determines the "environment" your application is currently
|
||||
| running in. This may determine how you prefer to configure various
|
||||
| services your application utilizes. Set this in your ".env" file.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => 'development',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Environment Multitenancy
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You may specify a different environment according to the hostname that
|
||||
| is provided with the HTTP request. This is useful if you want to use
|
||||
| different configuration, such as database and theme, per hostname.
|
||||
|
|
||||
*/
|
||||
|
||||
'hosts' => [
|
||||
'localhost' => 'dev',
|
||||
],
|
||||
];
|
||||
53
config/filesystems.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default filesystem disk that should be used
|
||||
| by the framework. The "local" disk, as well as a variety of cloud
|
||||
| based disks are available to your application. Just store away!
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('FILESYSTEM_DISK', 'local'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Filesystem Disks
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure as many filesystem "disks" as you wish, and you
|
||||
| may even configure multiple disks of the same driver. Defaults have
|
||||
| been setup for each driver as an example of the required options.
|
||||
|
|
||||
| Supported Drivers: "local", "ftp", "sftp", "s3"
|
||||
|
|
||||
| NOTE: s3's stream_uploads option requires the Winter.DriverAWS plugin
|
||||
| to be installed and enabled.
|
||||
|
|
||||
*/
|
||||
|
||||
'disks' => [
|
||||
'local' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app'),
|
||||
'url' => '/storage/app',
|
||||
'visibility' => 'public',
|
||||
],
|
||||
's3' => [
|
||||
'bucket' => env('AWS_BUCKET'),
|
||||
'driver' => 's3',
|
||||
'endpoint' => env('AWS_ENDPOINT'),
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'region' => env('AWS_DEFAULT_REGION'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'stream_uploads' => env('AWS_S3_STREAM_UPLOADS', false),
|
||||
'url' => env('AWS_URL'),
|
||||
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
|
||||
],
|
||||
],
|
||||
];
|
||||
51
config/hashing.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Hash Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default hash driver that will be used to hash
|
||||
| passwords for your application. By default, the bcrypt algorithm is
|
||||
| used; however, you remain free to modify this option if you wish.
|
||||
|
|
||||
| Supported: "bcrypt", "argon", "argon2id"
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => 'bcrypt',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bcrypt Options
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the configuration options that should be used when
|
||||
| passwords are hashed using the Bcrypt algorithm. This will allow you
|
||||
| to control the amount of time it takes to hash the given password.
|
||||
|
|
||||
*/
|
||||
|
||||
'bcrypt' => [
|
||||
'rounds' => env('BCRYPT_ROUNDS', 10),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Argon Options
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the configuration options that should be used when
|
||||
| passwords are hashed using the Argon algorithm. These will allow you
|
||||
| to control the amount of time it takes to hash the given password.
|
||||
|
|
||||
*/
|
||||
|
||||
'argon' => [
|
||||
'memory' => 65536,
|
||||
'threads' => 1,
|
||||
'time' => 4,
|
||||
],
|
||||
];
|
||||
107
config/logging.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Log Channel
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option defines the default log channel that gets used when writing
|
||||
| messages to the logs. The name specified in this option should match
|
||||
| one of the channels defined in the "channels" configuration array.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('LOG_CHANNEL', 'stack'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Deprecations Log Channel
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the log channel that should be used to log warnings
|
||||
| regarding deprecated PHP and library features. This allows you to get
|
||||
| your application ready for upcoming major versions of dependencies.
|
||||
|
|
||||
*/
|
||||
|
||||
'deprecations' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Log Channels
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the log channels for your application. Out of
|
||||
| the box, Winter uses the Monolog PHP logging library. This gives
|
||||
| you a variety of powerful log handlers / formatters to utilize.
|
||||
|
|
||||
| Available Drivers: "single", "daily", "slack", "syslog",
|
||||
| "errorlog", "monolog",
|
||||
| "custom", "stack"
|
||||
|
|
||||
*/
|
||||
|
||||
'channels' => [
|
||||
'stack' => [
|
||||
'channels' => [
|
||||
'single',
|
||||
],
|
||||
'driver' => 'stack',
|
||||
'ignore_exceptions' => false,
|
||||
],
|
||||
'single' => [
|
||||
'driver' => 'single',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'path' => storage_path('logs/system.log'),
|
||||
],
|
||||
'daily' => [
|
||||
'days' => 14,
|
||||
'driver' => 'daily',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'path' => storage_path('logs/system.log'),
|
||||
],
|
||||
'slack' => [
|
||||
'driver' => 'slack',
|
||||
'emoji' => ':boom:',
|
||||
'level' => env('LOG_LEVEL', 'critical'),
|
||||
'url' => env('LOG_SLACK_WEBHOOK_URL'),
|
||||
'username' => 'Winter Log',
|
||||
],
|
||||
'papertrail' => [
|
||||
'driver' => 'monolog',
|
||||
'handler' => env('LOG_PAPERTRAIL_HANDLER', \Monolog\Handler\SyslogUdpHandler::class),
|
||||
'handler_with' => [
|
||||
'connectionString' => 'tls://' . env('PAPERTRAIL_URL') . ':' . env('PAPERTRAIL_PORT'),
|
||||
'host' => env('PAPERTRAIL_URL'),
|
||||
'port' => env('PAPERTRAIL_PORT'),
|
||||
],
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
],
|
||||
'stderr' => [
|
||||
'driver' => 'monolog',
|
||||
'formatter' => env('LOG_STDERR_FORMATTER'),
|
||||
'handler' => \Monolog\Handler\StreamHandler::class,
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'with' => [
|
||||
'stream' => 'php://stderr',
|
||||
],
|
||||
],
|
||||
'syslog' => [
|
||||
'driver' => 'syslog',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
],
|
||||
'errorlog' => [
|
||||
'driver' => 'errorlog',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
],
|
||||
'null' => [
|
||||
'driver' => 'monolog',
|
||||
'handler' => \Monolog\Handler\NullHandler::class,
|
||||
],
|
||||
'emergency' => [
|
||||
'path' => storage_path('logs/system.log'),
|
||||
],
|
||||
],
|
||||
];
|
||||
92
config/mail.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Mailer
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default mailer that is used to send any email
|
||||
| messages sent by your application. Alternative mailers may be setup
|
||||
| and used as needed; however, this mailer will be used by default.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('MAIL_MAILER', 'smtp'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Mailer Configurations
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure all of the mailers used by your application plus
|
||||
| their respective settings. Several examples have been configured for
|
||||
| you and you are free to add your own as your application requires.
|
||||
|
|
||||
| Winter supports a variety of mail "transport" drivers to be used while
|
||||
| sending an e-mail. You will specify which one you are using for your
|
||||
| mailers below. You are free to add additional mailers as required.
|
||||
|
|
||||
| Supported: "smtp", "sendmail", "mailgun", "ses",
|
||||
| "postmark", "log", "array", "failover"
|
||||
|
|
||||
*/
|
||||
|
||||
'mailers' => [
|
||||
'smtp' => [
|
||||
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
|
||||
'password' => env('MAIL_PASSWORD'),
|
||||
'port' => env('MAIL_PORT', 587),
|
||||
'timeout' => null,
|
||||
'transport' => 'smtp',
|
||||
'username' => env('MAIL_USERNAME'),
|
||||
],
|
||||
'ses' => [
|
||||
'transport' => 'ses',
|
||||
],
|
||||
'mailgun' => [
|
||||
'transport' => 'mailgun',
|
||||
],
|
||||
'postmark' => [
|
||||
'transport' => 'postmark',
|
||||
],
|
||||
'mail' => [
|
||||
'transport' => 'mail',
|
||||
],
|
||||
'sendmail' => [
|
||||
'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -t -i'),
|
||||
'transport' => 'sendmail',
|
||||
],
|
||||
'log' => [
|
||||
'channel' => env('MAIL_LOG_CHANNEL'),
|
||||
'transport' => 'log',
|
||||
],
|
||||
'array' => [
|
||||
'transport' => 'array',
|
||||
],
|
||||
'failover' => [
|
||||
'mailers' => [
|
||||
'smtp',
|
||||
'log',
|
||||
],
|
||||
'transport' => 'failover',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Global "From" Address
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You may wish for all e-mails sent by your application to be sent from
|
||||
| the same address. Here, you may specify a name and address that is
|
||||
| used globally for all e-mails that are sent by your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'from' => [
|
||||
'address' => env('MAIL_FROM_ADDRESS', 'noreply@example.com'),
|
||||
'name' => env('MAIL_FROM_NAME', env('APP_NAME', 'Winter CMS')),
|
||||
],
|
||||
];
|
||||
102
config/queue.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Queue Connection Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Winter's queue API supports an assortment of back-ends via a single
|
||||
| API, giving you convenient access to each back-end using the same
|
||||
| syntax for every one. Here you may define a default connection.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('QUEUE_CONNECTION', 'sync'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Queue Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the connection information for each server that
|
||||
| is used by your application. A default configuration has been added
|
||||
| for each back-end shipped with Winter. You are free to add more.
|
||||
|
|
||||
| Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
'sync' => [
|
||||
'driver' => 'sync',
|
||||
],
|
||||
'database' => [
|
||||
'after_commit' => false,
|
||||
'driver' => 'database',
|
||||
'queue' => 'default',
|
||||
'retry_after' => 90,
|
||||
'table' => 'jobs',
|
||||
],
|
||||
'beanstalkd' => [
|
||||
'after_commit' => false,
|
||||
'block_for' => 0,
|
||||
'driver' => 'beanstalkd',
|
||||
'host' => 'localhost',
|
||||
'queue' => 'default',
|
||||
'retry_after' => 90,
|
||||
],
|
||||
'sqs' => [
|
||||
'after_commit' => false,
|
||||
'driver' => 'sqs',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
|
||||
'queue' => env('SQS_QUEUE', 'default'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'suffix' => env('SQS_SUFFIX'),
|
||||
],
|
||||
'redis' => [
|
||||
'after_commit' => false,
|
||||
'block_for' => null,
|
||||
'connection' => 'default',
|
||||
'driver' => 'redis',
|
||||
'queue' => env('REDIS_QUEUE', 'default'),
|
||||
'retry_after' => 90,
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Job Batching
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following options configure the database and table that store job
|
||||
| batching information. These options can be updated to any database
|
||||
| connection and table which has been defined by your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'batching' => [
|
||||
'database' => env('DB_CONNECTION', 'mysql'),
|
||||
'table' => 'job_batches',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Failed Queue Jobs
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These options configure the behavior of failed queue job logging so you
|
||||
| can control which database and table are used to store the jobs that
|
||||
| have failed. You may change them to any database / table you wish.
|
||||
|
|
||||
*/
|
||||
|
||||
'failed' => [
|
||||
'database' => env('DB_CONNECTION', 'mysql'),
|
||||
'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),
|
||||
'table' => 'failed_jobs',
|
||||
],
|
||||
];
|
||||
30
config/services.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Third Party Services
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This file is for storing the credentials for third party services such
|
||||
| as Mailgun, Postmark, AWS and more. This file provides the de facto
|
||||
| location for this type of information, allowing packages to have
|
||||
| a conventional file to locate the various service credentials.
|
||||
|
|
||||
*/
|
||||
|
||||
'mailgun' => [
|
||||
'domain' => env('MAILGUN_DOMAIN'),
|
||||
'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
|
||||
'secret' => env('MAILGUN_SECRET'),
|
||||
],
|
||||
'postmark' => [
|
||||
'token' => env('POSTMARK_TOKEN'),
|
||||
],
|
||||
'ses' => [
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
],
|
||||
];
|
||||
216
config/session.php
Normal file
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Session Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default session "driver" that will be used on
|
||||
| requests. By default, we will use the lightweight native driver but
|
||||
| you may specify any of the other wonderful drivers provided here.
|
||||
|
|
||||
| Supported: "file", "cookie", "database", "apc",
|
||||
| "memcached", "redis", "dynamodb", "array"
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => env('SESSION_DRIVER', 'file'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Lifetime
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the number of minutes that you wish the session
|
||||
| to be allowed to remain idle before it expires. If you want them
|
||||
| to immediately expire on the browser closing, set that option.
|
||||
|
|
||||
*/
|
||||
|
||||
'lifetime' => env('SESSION_LIFETIME', 120),
|
||||
'expire_on_close' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Encryption
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option allows you to easily specify that all of your session data
|
||||
| should be encrypted before it is stored. All encryption will be run
|
||||
| automatically by Laravel and you can use the Session like normal.
|
||||
|
|
||||
*/
|
||||
|
||||
'encrypt' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session File Location
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the native session driver, we need a location where session
|
||||
| files may be stored. A default has been set for you but a different
|
||||
| location may be specified. This is only needed for file sessions.
|
||||
|
|
||||
*/
|
||||
|
||||
'files' => storage_path('framework/sessions'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Connection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" or "redis" session drivers, you may specify a
|
||||
| connection that should be used to manage these sessions. This should
|
||||
| correspond to a connection in your database configuration options.
|
||||
|
|
||||
*/
|
||||
|
||||
'connection' => env('SESSION_CONNECTION'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" session driver, you may specify the table we
|
||||
| should use to manage the sessions. Of course, a sensible default is
|
||||
| provided for you; however, you are free to change this as needed.
|
||||
|
|
||||
*/
|
||||
|
||||
'table' => 'sessions',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cache Store
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| While using one of the framework's cache driven session backends you may
|
||||
| list a cache store that should be used for these sessions. This value
|
||||
| must match with one of the application's configured cache "stores".
|
||||
|
|
||||
| Affects: "apc", "dynamodb", "memcached", "redis"
|
||||
|
|
||||
*/
|
||||
|
||||
'store' => env('SESSION_STORE'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Sweeping Lottery
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Some session drivers must manually sweep their storage location to get
|
||||
| rid of old sessions from storage. Here are the chances that it will
|
||||
| happen on a given request. By default, the odds are 2 out of 100.
|
||||
|
|
||||
*/
|
||||
|
||||
'lottery' => [
|
||||
2,
|
||||
100,
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may change the name of the cookie used to identify a session
|
||||
| instance by ID. The name specified here will get used every time a
|
||||
| new session cookie is created by the framework for every driver.
|
||||
|
|
||||
*/
|
||||
|
||||
'cookie' => env('SESSION_COOKIE', str_slug(env('APP_NAME', 'winter'), '_') . '_session'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The session cookie path determines the path for which the cookie will
|
||||
| be regarded as available. Typically, this will be the root path of
|
||||
| your application but you are free to change this when necessary.
|
||||
|
|
||||
*/
|
||||
|
||||
'path' => '/',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Domain
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may change the domain of the cookie used to identify a session
|
||||
| in your application. This will determine which domains the cookie is
|
||||
| available to in your application. A sensible default has been set.
|
||||
|
|
||||
*/
|
||||
|
||||
'domain' => env('SESSION_DOMAIN'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTP Access Only
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Setting this value to true will prevent JavaScript from accessing the
|
||||
| value of the cookie and the cookie will only be accessible through
|
||||
| the HTTP protocol. You are free to modify this option if needed.
|
||||
|
|
||||
*/
|
||||
|
||||
'http_only' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTPS Only Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By setting this option to true, session cookies will only be sent back
|
||||
| to the server if the browser has a HTTPS connection. This will keep
|
||||
| the cookie from being sent to you when it can't be done securely.
|
||||
|
|
||||
*/
|
||||
|
||||
'secure' => env('SESSION_SECURE_COOKIE', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Same-Site Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option determines how your cookies behave when cross-site requests
|
||||
| take place, and can be used to mitigate CSRF attacks. By default, we
|
||||
| will set this value to "lax" since this is a secure default value.
|
||||
|
|
||||
| Cookies that match the domain of the current site, i.e. what's displayed
|
||||
| in the browser's address bar, are referred to as first-party cookies.
|
||||
| Similarly, cookies from domains other than the current site are referred
|
||||
| to as third-party cookies.
|
||||
|
|
||||
| Cookies without a SameSite attribute will be treated as `SameSite=lax`,
|
||||
| meaning the default behaviour will be to restrict cookies to first party
|
||||
| contexts only.
|
||||
|
|
||||
| Cookies for cross-site usage must specify `same_site` as 'None' and `secure`
|
||||
| as `true` to work correctly.
|
||||
|
|
||||
| lax - Cookies are allowed to be sent with top-level navigations and will
|
||||
| be sent along with GET request initiated by third party website.
|
||||
| This is the default value in modern browsers.
|
||||
|
|
||||
| strict - Cookies will only be sent in a first-party context and not be
|
||||
| sent along with requests initiated by third party websites.
|
||||
|
|
||||
| Supported: "lax", "strict", "none", null
|
||||
|
|
||||
*/
|
||||
|
||||
'same_site' => 'lax',
|
||||
];
|
||||
182
config/testing/cms.php
Normal file
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Specifies the default CMS theme
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This parameter value can be overridden by the CMS back-end settings.
|
||||
|
|
||||
*/
|
||||
|
||||
'activeTheme' => 'test',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Time to live for parsed CMS objects.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specifies the number of minutes the CMS object cache lives. After the interval
|
||||
| is expired item are re-cached. Note that items are re-cached automatically when
|
||||
| the corresponding template file is modified.
|
||||
|
|
||||
*/
|
||||
|
||||
'parsedPageCacheTTL' => 1440,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Determines if the routing caching is enabled.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If the caching is enabled, the page URL map is saved in the cache. If a page
|
||||
| URL was changed on the disk, the old URL value could be still saved in the cache.
|
||||
| To update the cache the back-end Clear Cache feature should be used. It is recommended
|
||||
| to disable the caching during the development, and enable it in the production mode.
|
||||
|
|
||||
*/
|
||||
|
||||
'enableRoutesCache' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Time to live for the URL map.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The URL map used in the CMS page routing process. By default
|
||||
| the map is updated every time when a page is saved in the back-end or when the
|
||||
| interval, in minutes, specified with the urlMapCacheTTL parameter expires.
|
||||
|
|
||||
*/
|
||||
|
||||
'urlCacheTtl' => 1,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Determines if the asset caching is enabled.
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If the caching is enabled, combined assets are cached. If a asset file
|
||||
| is changed on the disk, the old file contents could be still saved in the cache.
|
||||
| To update the cache the back-end Clear Cache feature should be used. It is recommended
|
||||
| to disable the caching during the development, and enable it in the production mode.
|
||||
|
|
||||
*/
|
||||
|
||||
'enableAssetCache' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Disables Twig caching for unit tests
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'twigNoCache' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Convert Line Endings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Determines if Winter should convert line endings from the windows style
|
||||
| \r\n to the unix style \n.
|
||||
|
|
||||
*/
|
||||
|
||||
'convertLineEndings' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Local plugins path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specifies the absolute local plugins path.
|
||||
|
|
||||
*/
|
||||
|
||||
'pluginsPathLocal' => base_path('modules/system/tests/fixtures/plugins'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Local themes path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specifies the absolute local themes path.
|
||||
|
|
||||
*/
|
||||
|
||||
'themesPathLocal' => base_path('modules/cms/tests/fixtures/themes'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Resource storage
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specifies the configuration for resource storage, such as media and
|
||||
| upload files. These resources are used:
|
||||
|
|
||||
| media - generated by the media manager.
|
||||
| uploads - generated by attachment model relationships.
|
||||
| resized - generated by System\Classes\ImageResizer or the resize() Twig filter
|
||||
|
|
||||
| For each resource you can specify:
|
||||
|
|
||||
| disk - filesystem disk, as specified in filesystems.php config.
|
||||
| folder - a folder prefix for storing all generated files inside.
|
||||
| path - the public path relative to the application base URL,
|
||||
| or you can specify a full URL path.
|
||||
|
|
||||
| Optionally, you can specify how long temporary URLs to protected files
|
||||
| in cloud storage (ex. AWS, RackSpace) are valid for by setting
|
||||
| temporaryUrlTTL to a value in seconds to define a validity period. This
|
||||
| is only used for the 'uploads' config when using a supported cloud disk
|
||||
|
|
||||
| NOTE: If you have installed Winter in a subfolder, are using local
|
||||
| storage and are not using a linkPolicy of 'force' you should include
|
||||
| the path to the subfolder in the `path` option for these storage
|
||||
| configurations.
|
||||
|
|
||||
| Example: Winter is installed under https://localhost/projects/winter.
|
||||
| You should then specify `/projects/winter/storage/app/uploads` as the
|
||||
| path for the uploads disk and `/projects/winter/storage/app/media` as
|
||||
| the path for the media disk.
|
||||
*/
|
||||
|
||||
'storage' => [
|
||||
|
||||
'uploads' => [
|
||||
'disk' => 'local',
|
||||
'folder' => 'uploads',
|
||||
'path' => '/storage/tests/app/uploads',
|
||||
'temporaryUrlTTL' => 3600,
|
||||
],
|
||||
|
||||
'media' => [
|
||||
'disk' => 'local',
|
||||
'folder' => 'media',
|
||||
'path' => '/storage/tests/app/media',
|
||||
],
|
||||
|
||||
'resized' => [
|
||||
'disk' => 'local',
|
||||
'folder' => 'resized',
|
||||
'path' => '/storage/tests/app/resized',
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cross Site Request Forgery (CSRF) Protection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If the CSRF protection is enabled, all "postback" requests are checked
|
||||
| for a valid security token.
|
||||
|
|
||||
*/
|
||||
|
||||
'enableCsrfProtection' => false,
|
||||
|
||||
];
|
||||
64
config/testing/filesystems.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default filesystem disk that should be used
|
||||
| by the framework. The "local" disk, as well as a variety of cloud
|
||||
| based disks are available to your application. Just store away!
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => 'local',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cloud Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Many applications store files both locally and in the cloud. For this
|
||||
| reason, you may specify a default "cloud" driver here. This driver
|
||||
| will be bound as the Cloud disk implementation in the container.
|
||||
|
|
||||
*/
|
||||
|
||||
'cloud' => 's3',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Filesystem Disks
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure as many filesystem "disks" as you wish, and you
|
||||
| may even configure multiple disks of the same driver. Defaults have
|
||||
| been setup for each driver as an example of the required options.
|
||||
|
|
||||
| Supported Drivers: "local", "ftp", "sftp", "s3"
|
||||
|
|
||||
*/
|
||||
|
||||
'disks' => [
|
||||
|
||||
'local' => [
|
||||
'driver' => 'local',
|
||||
'root' => base_path('storage/tests/app'),
|
||||
'url' => '/storage/tests/app',
|
||||
],
|
||||
|
||||
's3' => [
|
||||
'driver' => 's3',
|
||||
'key' => '',
|
||||
'secret' => '',
|
||||
'region' => '',
|
||||
'bucket' => '',
|
||||
// 'url' => env('AWS_URL'),
|
||||
// 'endpoint' => env('AWS_ENDPOINT'),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
34
config/view.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| View Storage Paths
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Most templating systems load templates from disk. Here you may specify
|
||||
| an array of paths that should be checked for your views. Of course
|
||||
| the usual Laravel view path has already been registered for you.
|
||||
|
|
||||
*/
|
||||
|
||||
'paths' => [
|
||||
// Default Laravel Blade template location
|
||||
// @see https://github.com/octobercms/october/issues/3473 & https://github.com/octobercms/october/issues/3459
|
||||
// realpath(base_path('resources/views'))
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Compiled View Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option determines where all the compiled Blade templates will be
|
||||
| stored for your application. Typically, this is within the storage
|
||||
| directory. However, as usual, you are free to change this value.
|
||||
|
|
||||
*/
|
||||
|
||||
'compiled' => env('VIEW_COMPILED_PATH', realpath(storage_path('framework/views'))),
|
||||
];
|
||||
48
index.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* Winter CMS - The PHP platform that gets back to basics.
|
||||
*
|
||||
* @package Winter
|
||||
* @author Alexey Bobkov, Samuel Georges
|
||||
*/
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register composer
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Composer provides a generated class loader for the application.
|
||||
|
|
||||
*/
|
||||
|
||||
require __DIR__.'/bootstrap/autoload.php';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Load framework
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This bootstraps the framework and loads up this application.
|
||||
|
|
||||
*/
|
||||
|
||||
$app = require_once __DIR__.'/bootstrap/app.php';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Process request
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Execute the request and send the response back to the client.
|
||||
|
|
||||
*/
|
||||
|
||||
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
|
||||
|
||||
$response = $kernel->handle(
|
||||
$request = Illuminate\Http\Request::capture()
|
||||
);
|
||||
|
||||
$response->send();
|
||||
|
||||
$kernel->terminate($request, $response);
|
||||
17
modules/backend/.eslintignore
Normal file
@@ -0,0 +1,17 @@
|
||||
# Ignore build files
|
||||
**/node_modules/**
|
||||
build/*.js
|
||||
**/build/*.js
|
||||
**/mix.webpack.js
|
||||
|
||||
# Ignore all JS except for Mix-based assets
|
||||
assets/js
|
||||
assets/vendor
|
||||
behaviors/**/*.js
|
||||
controllers/**/*.js
|
||||
formwidgets/**/*.js
|
||||
reportwidgets/**/*.js
|
||||
widgets/**/*.js
|
||||
|
||||
# Ignore test fixtures
|
||||
tests
|
||||
45
modules/backend/.eslintrc.json
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"env": {
|
||||
"es6": true,
|
||||
"browser": true
|
||||
},
|
||||
"globals": {
|
||||
"Snowboard": "writable"
|
||||
},
|
||||
"extends": [
|
||||
"airbnb-base",
|
||||
"plugin:vue/vue3-recommended"
|
||||
],
|
||||
"ignorePatterns": [
|
||||
"assets/js",
|
||||
"assets/vendor",
|
||||
"behaviors/**/*.js",
|
||||
"controllers/**/*.js",
|
||||
"formwidgets/**/*.js",
|
||||
"reportwidgets/**/*.js",
|
||||
"widgets/**/*.js"
|
||||
],
|
||||
"rules": {
|
||||
"class-methods-use-this": ["off"],
|
||||
"indent": ["error", 4, {
|
||||
"SwitchCase": 1
|
||||
}],
|
||||
"max-len": ["off"],
|
||||
"new-cap": ["error", { "properties": false }],
|
||||
"no-alert": ["off"],
|
||||
"no-param-reassign": ["error", {
|
||||
"props": false
|
||||
}],
|
||||
"vue/html-indent": ["error", 4],
|
||||
"vue/html-self-closing": ["error", {
|
||||
"html": {
|
||||
"void": "never",
|
||||
"normal": "any",
|
||||
"component": "always"
|
||||
},
|
||||
"svg": "always",
|
||||
"math": "always"
|
||||
}],
|
||||
"vue/multi-word-component-names": ["off"]
|
||||
}
|
||||
}
|
||||
6
modules/backend/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# Backend module ignores
|
||||
|
||||
# Ignore Mix files
|
||||
node_modules
|
||||
package-lock.json
|
||||
mix.webpack.js
|
||||
22
modules/backend/LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2013-2021.03.01 October CMS
|
||||
Copyright (c) 2021 Winter CMS
|
||||
|
||||
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.
|
||||
5
modules/backend/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Winter CMS - Backend Module
|
||||
|
||||
This repository is a read-only sub-split of the Winter CMS `Backend` module for use in Composer. Please note that we do not accept any pull requests to this repository.
|
||||
|
||||
If you wish to make changes to this module, please submit them to the [main repository](https://github.com/wintercms/winter).
|
||||
338
modules/backend/ServiceProvider.php
Normal file
@@ -0,0 +1,338 @@
|
||||
<?php
|
||||
|
||||
namespace Backend;
|
||||
|
||||
use Backend\Classes\WidgetManager;
|
||||
use Backend\Facades\Backend;
|
||||
use Backend\Facades\BackendAuth;
|
||||
use Backend\Facades\BackendMenu;
|
||||
use Backend\Models\AccessLog;
|
||||
use Backend\Models\UserRole;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use System\Classes\Asset\PackageManager;
|
||||
use System\Classes\CombineAssets;
|
||||
use System\Classes\MailManager;
|
||||
use System\Classes\SettingsManager;
|
||||
use System\Classes\UpdateManager;
|
||||
use Winter\Storm\Support\Facades\Config;
|
||||
use Winter\Storm\Support\Facades\Flash;
|
||||
use Winter\Storm\Support\ModuleServiceProvider;
|
||||
|
||||
class ServiceProvider extends ModuleServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
parent::register();
|
||||
|
||||
$this->registerConsole();
|
||||
$this->registerMailer();
|
||||
$this->registerBackendPermissions();
|
||||
$this->registerBackendUserEvents();
|
||||
|
||||
/*
|
||||
* Backend specific
|
||||
*/
|
||||
if ($this->app->runningInBackend()) {
|
||||
$this->registerBackendNavigation();
|
||||
$this->registerBackendReportWidgets();
|
||||
$this->registerBackendWidgets();
|
||||
$this->registerBackendSettings();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap the module events.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->registerAssetBundles();
|
||||
parent::boot('backend');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register console commands
|
||||
*/
|
||||
protected function registerConsole()
|
||||
{
|
||||
$this->registerConsoleCommand('create.controller', \Backend\Console\CreateController::class);
|
||||
$this->registerConsoleCommand('create.formwidget', \Backend\Console\CreateFormWidget::class);
|
||||
$this->registerConsoleCommand('create.reportwidget', \Backend\Console\CreateReportWidget::class);
|
||||
$this->registerConsoleCommand('user.create', \Backend\Console\UserCreate::class);
|
||||
$this->registerConsoleCommand('winter.passwd', \Backend\Console\WinterPasswd::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register mail templates
|
||||
*/
|
||||
protected function registerMailer()
|
||||
{
|
||||
MailManager::instance()->registerCallback(function ($manager) {
|
||||
$manager->registerMailTemplates([
|
||||
'backend::mail.invite',
|
||||
'backend::mail.restore',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register asset bundles
|
||||
*/
|
||||
protected function registerAssetBundles()
|
||||
{
|
||||
CombineAssets::registerCallback(function ($combiner) {
|
||||
$combiner->registerBundle('~/modules/backend/assets/less/winter.less');
|
||||
$combiner->registerBundle('~/modules/backend/assets/js/winter.js');
|
||||
$combiner->registerBundle('~/modules/backend/widgets/table/assets/js/build.js');
|
||||
$combiner->registerBundle('~/modules/backend/assets/vendor/ace-codeeditor/build.js');
|
||||
$combiner->registerBundle('~/modules/backend/widgets/mediamanager/assets/js/mediamanager-browser.js');
|
||||
$combiner->registerBundle('~/modules/backend/widgets/mediamanager/assets/less/mediamanager.less');
|
||||
$combiner->registerBundle('~/modules/backend/widgets/reportcontainer/assets/less/reportcontainer.less');
|
||||
$combiner->registerBundle('~/modules/backend/widgets/table/assets/less/table.less');
|
||||
$combiner->registerBundle('~/modules/backend/formwidgets/repeater/assets/less/repeater.less');
|
||||
$combiner->registerBundle('~/modules/backend/formwidgets/fieldset/assets/less/fieldset.less');
|
||||
$combiner->registerBundle('~/modules/backend/formwidgets/fileupload/assets/less/fileupload.less');
|
||||
$combiner->registerBundle('~/modules/backend/formwidgets/nestedform/assets/less/nestedform.less');
|
||||
$combiner->registerBundle('~/modules/backend/formwidgets/richeditor/assets/js/build-plugins.js');
|
||||
$combiner->registerBundle('~/modules/backend/formwidgets/permissioneditor/assets/less/permissioneditor.less');
|
||||
$combiner->registerBundle('~/modules/backend/formwidgets/markdowneditor/assets/less/markdowneditor.less');
|
||||
|
||||
/*
|
||||
* Rich Editor is protected by DRM
|
||||
*/
|
||||
if (file_exists(base_path('modules/backend/formwidgets/richeditor/assets/vendor/froala_drm'))) {
|
||||
$combiner->registerBundle('~/modules/backend/formwidgets/richeditor/assets/less/richeditor.less');
|
||||
$combiner->registerBundle('~/modules/backend/formwidgets/richeditor/assets/js/build.js');
|
||||
}
|
||||
});
|
||||
|
||||
PackageManager::registerCallback(function ($mix) {
|
||||
$mix->registerPackage('module-backend.formwidgets.codeeditor', '~/modules/backend/formwidgets/codeeditor/assets/winter.mix.js');
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Register navigation
|
||||
*/
|
||||
protected function registerBackendNavigation()
|
||||
{
|
||||
BackendMenu::registerCallback(function ($manager) {
|
||||
$manager->registerMenuItems('Winter.Backend', [
|
||||
'dashboard' => [
|
||||
'label' => 'backend::lang.dashboard.menu_label',
|
||||
'icon' => 'icon-dashboard',
|
||||
'iconSvg' => 'modules/backend/assets/images/dashboard-icon.svg',
|
||||
'url' => Backend::url('backend'),
|
||||
'permissions' => ['backend.access_dashboard'],
|
||||
'order' => 10
|
||||
],
|
||||
'media' => [
|
||||
'label' => 'backend::lang.media.menu_label',
|
||||
'icon' => 'icon-folder',
|
||||
'iconSvg' => 'modules/backend/assets/images/media-icon.svg',
|
||||
'url' => Backend::url('backend/media'),
|
||||
'permissions' => ['media.*'],
|
||||
'order' => 200
|
||||
]
|
||||
]);
|
||||
$manager->registerOwnerAlias('Winter.Backend', 'October.Backend');
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Register report widgets
|
||||
*/
|
||||
protected function registerBackendReportWidgets()
|
||||
{
|
||||
WidgetManager::instance()->registerReportWidgets(function ($manager) {
|
||||
$manager->registerReportWidget(\Backend\ReportWidgets\Welcome::class, [
|
||||
'label' => 'backend::lang.dashboard.welcome.widget_title_default',
|
||||
'context' => 'dashboard'
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Register permissions
|
||||
*/
|
||||
protected function registerBackendPermissions()
|
||||
{
|
||||
BackendAuth::registerCallback(function ($manager) {
|
||||
$manager->registerPermissions('Winter.Backend', [
|
||||
'backend.access_dashboard' => [
|
||||
'label' => 'system::lang.permissions.view_the_dashboard',
|
||||
'tab' => 'system::lang.permissions.name',
|
||||
'roles' => [UserRole::CODE_DEVELOPER, UserRole::CODE_PUBLISHER],
|
||||
],
|
||||
'backend.manage_default_dashboard' => [
|
||||
'label' => 'system::lang.permissions.manage_default_dashboard',
|
||||
'tab' => 'system::lang.permissions.name',
|
||||
'comment' => 'system::lang.permissions.manage_default_dashboard_comment',
|
||||
'roles' => [UserRole::CODE_DEVELOPER],
|
||||
],
|
||||
'backend.manage_users' => [
|
||||
'label' => 'system::lang.permissions.manage_other_administrators',
|
||||
'tab' => 'system::lang.permissions.name',
|
||||
'comment' => 'system::lang.permissions.manage_other_administrators_comment',
|
||||
'roles' => [UserRole::CODE_DEVELOPER],
|
||||
],
|
||||
'backend.impersonate_users' => [
|
||||
'label' => 'system::lang.permissions.impersonate_users',
|
||||
'tab' => 'system::lang.permissions.name',
|
||||
'comment' => 'system::lang.permissions.impersonate_users_comment',
|
||||
'roles' => [UserRole::CODE_DEVELOPER],
|
||||
],
|
||||
'backend.manage_preferences' => [
|
||||
'label' => 'system::lang.permissions.manage_preferences',
|
||||
'tab' => 'system::lang.permissions.name',
|
||||
'roles' => [UserRole::CODE_DEVELOPER, UserRole::CODE_PUBLISHER],
|
||||
],
|
||||
'backend.manage_editor' => [
|
||||
'label' => 'system::lang.permissions.manage_editor',
|
||||
'tab' => 'system::lang.permissions.name',
|
||||
'comment' => 'system::lang.permissions.manage_editor_comment',
|
||||
'roles' => [UserRole::CODE_DEVELOPER],
|
||||
],
|
||||
'backend.manage_own_editor' => [
|
||||
'label' => 'system::lang.permissions.manage_own_editor',
|
||||
'tab' => 'system::lang.permissions.name',
|
||||
'roles' => [UserRole::CODE_DEVELOPER, UserRole::CODE_PUBLISHER],
|
||||
],
|
||||
'backend.manage_branding' => [
|
||||
'label' => 'system::lang.permissions.manage_branding',
|
||||
'tab' => 'system::lang.permissions.name',
|
||||
'comment' => 'system::lang.permissions.manage_branding_comment',
|
||||
'roles' => [UserRole::CODE_DEVELOPER],
|
||||
],
|
||||
'media.manage_media' => [
|
||||
'label' => 'backend::lang.permissions.manage_media',
|
||||
'tab' => 'system::lang.permissions.name',
|
||||
'roles' => [UserRole::CODE_DEVELOPER, UserRole::CODE_PUBLISHER],
|
||||
],
|
||||
'backend.allow_unsafe_markdown' => [
|
||||
'label' => 'backend::lang.permissions.allow_unsafe_markdown',
|
||||
'tab' => 'system::lang.permissions.name',
|
||||
'comment' => 'backend::lang.permissions.allow_unsafe_markdown_comment',
|
||||
'roles' => [UserRole::CODE_DEVELOPER],
|
||||
],
|
||||
]);
|
||||
$manager->registerPermissionOwnerAlias('Winter.Backend', 'October.Backend');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the backend user events
|
||||
*/
|
||||
protected function registerBackendUserEvents()
|
||||
{
|
||||
Event::listen('backend.user.login', function (\Backend\Models\User $user) {
|
||||
// @TODO: Deprecate this, and only run migrations when it makes sense
|
||||
$runMigrationsOnLogin = (bool) Config::get('cms.runMigrationsOnLogin', Config::get('app.debug', false));
|
||||
if ($runMigrationsOnLogin) {
|
||||
try {
|
||||
// Load version updates
|
||||
UpdateManager::instance()->update();
|
||||
} catch (Exception $e) {
|
||||
Flash::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Log the sign in event
|
||||
AccessLog::add($user);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Register widgets
|
||||
*/
|
||||
protected function registerBackendWidgets()
|
||||
{
|
||||
WidgetManager::instance()->registerFormWidgets(function ($manager) {
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\CodeEditor::class, 'codeeditor');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\ColorPicker::class, 'colorpicker');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\DataTable::class, 'datatable');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\DatePicker::class, 'datepicker');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\FieldSet::class, 'fieldset');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\FileUpload::class, 'fileupload');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\IconPicker::class, 'iconpicker');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\MarkdownEditor::class, 'markdown');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\MediaFinder::class, 'mediafinder');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\NestedForm::class, 'nestedform');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\RecordFinder::class, 'recordfinder');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\Relation::class, 'relation');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\RelationManager::class, 'relationmanager');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\Repeater::class, 'repeater');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\RichEditor::class, 'richeditor');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\Sensitive::class, 'sensitive');
|
||||
$manager->registerFormWidget(\Backend\FormWidgets\TagList::class, 'taglist');
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Register settings
|
||||
*/
|
||||
protected function registerBackendSettings()
|
||||
{
|
||||
SettingsManager::instance()->registerCallback(function ($manager) {
|
||||
$manager->registerSettingItems('Winter.Backend', [
|
||||
'branding' => [
|
||||
'label' => 'backend::lang.branding.menu_label',
|
||||
'description' => 'backend::lang.branding.menu_description',
|
||||
'category' => SettingsManager::CATEGORY_SYSTEM,
|
||||
'icon' => 'icon-paint-brush',
|
||||
'class' => 'Backend\Models\BrandSetting',
|
||||
'permissions' => ['backend.manage_branding'],
|
||||
'order' => 500,
|
||||
'keywords' => 'brand style'
|
||||
],
|
||||
'editor' => [
|
||||
'label' => 'backend::lang.editor.menu_label',
|
||||
'description' => 'backend::lang.editor.menu_description',
|
||||
'category' => SettingsManager::CATEGORY_SYSTEM,
|
||||
'icon' => 'icon-code',
|
||||
'class' => 'Backend\Models\EditorSetting',
|
||||
'permissions' => ['backend.manage_editor'],
|
||||
'order' => 500,
|
||||
'keywords' => 'html code class style'
|
||||
],
|
||||
'myaccount' => [
|
||||
'label' => 'backend::lang.myaccount.menu_label',
|
||||
'description' => 'backend::lang.myaccount.menu_description',
|
||||
'category' => SettingsManager::CATEGORY_MYSETTINGS,
|
||||
'icon' => 'icon-user',
|
||||
'url' => Backend::url('backend/myaccount'),
|
||||
'order' => 500,
|
||||
'context' => 'mysettings',
|
||||
'keywords' => 'backend::lang.myaccount.menu_keywords'
|
||||
],
|
||||
'preferences' => [
|
||||
'label' => 'backend::lang.backend_preferences.menu_label',
|
||||
'description' => 'backend::lang.backend_preferences.menu_description',
|
||||
'category' => SettingsManager::CATEGORY_MYSETTINGS,
|
||||
'icon' => 'icon-laptop',
|
||||
'url' => Backend::url('backend/preferences'),
|
||||
'permissions' => ['backend.manage_preferences'],
|
||||
'order' => 510,
|
||||
'context' => 'mysettings'
|
||||
],
|
||||
'access_logs' => [
|
||||
'label' => 'backend::lang.access_log.menu_label',
|
||||
'description' => 'backend::lang.access_log.menu_description',
|
||||
'category' => SettingsManager::CATEGORY_LOGS,
|
||||
'icon' => 'icon-lock',
|
||||
'url' => Backend::url('backend/accesslogs'),
|
||||
'permissions' => ['system.access_logs'],
|
||||
'order' => 920
|
||||
]
|
||||
]);
|
||||
$manager->registerOwnerAlias('Winter.Backend', 'October.Backend');
|
||||
});
|
||||
}
|
||||
}
|
||||
1
modules/backend/assets/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!vendor
|
||||
12
modules/backend/assets/css/dashboard/dashboard.css
Normal file
@@ -0,0 +1,12 @@
|
||||
.dashboard-container > .report-container.loading {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.dashboard-container > .report-container.loading .loading-indicator-container {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
1118
modules/backend/assets/css/winter.css
Normal file
17
modules/backend/assets/images/dashboard-icon.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<!-- Generator: Sketch 3.4.4 (17249) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>dashboard-icon</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<g id="speed" sketch:type="MSLayerGroup">
|
||||
<path fill="#88C9E7" d="M20 3.542C9.14 3.542.336 12.347.336 23.207c0 4.713 1.66 9.032 4.424 12.42l1.552-3.105H33.69l1.55 3.104c2.763-3.387 4.425-7.706 4.425-12.42 0-10.86-8.806-19.664-19.665-19.664z"/>
|
||||
<path fill="#ECEFF1" d="M36.56 23.206c0-9.145-7.415-16.56-16.56-16.56-9.144 0-16.56 7.415-16.56 16.56 0 3.454 1.062 6.66 2.872 9.314L4.76 35.625h30.48l-1.55-3.104c1.807-2.654 2.87-5.86 2.87-9.314z"/>
|
||||
<path fill="#081821" d="M3.473 22.17c-.02.345-.032.687-.032 1.036 0 .35.012.69.033 1.035h4.16c-.028-.34-.053-.686-.053-1.034 0-.35.024-.694.052-1.036h-4.16zm6.402 8.192c-.407-.557-.768-1.145-1.08-1.766l-3.55 2.157c.325.614.67 1.2 1.067 1.767l3.563-2.158zm2.823-17.187c.557-.405 1.146-.765 1.77-1.075l-2.114-3.585c-.615.322-1.226.69-1.792 1.083l2.136 3.577zM8.75 17.97c.293-.63.63-1.233 1.02-1.8l-3.567-2.125c-.378.576-.77 1.247-1.075 1.87L8.75 17.97zm12.286-7.13V6.68c-.346-.023-.687-.033-1.036-.033s-.69-.022-1.035 0v4.193c.343-.03.687-.054 1.035-.054s.692.025 1.036.053zm9.074 19.626l3.6 2.055c.378-.574.76-1.215 1.064-1.836l-3.646-2.018c-.293.628-.63 1.232-1.018 1.8zm6.417-6.226c.02-.344.032-.686.032-1.034 0-.35-.012-.69-.033-1.036h-4.16c.027.342.052.687.052 1.036 0 .35-.025.693-.053 1.035h4.16zm-7.41-14.858c-.573-.38-1.205-.74-1.827-1.047l-2.055 3.622c.63.293 1.235.63 1.802 1.02l2.08-3.595z"/>
|
||||
<path fill="#90A4AE" d="M15.86 28.38h8.28v2.07h-8.28v-2.07z"/>
|
||||
<path fill="none" stroke="#E01346" stroke-miterlimit="10" d="M20 23.206l12.42-7.245"/>
|
||||
<path fill="#E01346" d="M19.883 20.002c1.683 0 3.047 1.365 3.047 3.045 0 1.685-1.363 3.048-3.047 3.048-1.682 0-3.045-1.363-3.045-3.048 0-1.68 1.363-3.045 3.045-3.045z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
BIN
modules/backend/assets/images/favicon.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
1
modules/backend/assets/images/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 1988 2212" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-miterlimit:10;"><g id="Snowflake"><g><path d="M993.872,1105.52l-0,833.334" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/><path d="M807.62,1476.42l186.252,-186.252l186.252,186.252" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;stroke-linecap:square;"/><path d="M752.928,1781.55l240.944,-240.944l240.944,240.944" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/></g><g><path d="M993.872,1105.52l-721.688,416.667" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/><path d="M579.534,1129.67l254.425,68.173l-68.173,254.425" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;stroke-linecap:square;"/><path d="M287.943,1234.87l329.135,88.191l-88.191,329.135" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/></g><g><path d="M993.872,1105.52l-721.688,-416.666" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/><path d="M765.786,758.767l68.173,254.425l-254.425,68.173" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;stroke-linecap:square;"/><path d="M528.887,558.841l88.191,329.135l-329.135,88.191" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/></g><g><path d="M993.872,1105.52l-0,-833.333" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/><path d="M1180.12,734.614l-186.252,186.252l-186.252,-186.252" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;stroke-linecap:square;"/><path d="M1234.82,429.49l-240.944,240.944l-240.944,-240.944" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/></g><g><path d="M993.872,1105.52l721.688,-416.666" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/><path d="M1408.21,1081.37l-254.425,-68.173l68.173,-254.425" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;stroke-linecap:square;"/><path d="M1699.8,976.167l-329.135,-88.191l88.191,-329.135" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/></g><g><path d="M993.872,1105.52l721.688,416.667" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/><path d="M1221.96,1452.27l-68.173,-254.425l254.425,-68.173" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;stroke-linecap:square;"/><path d="M1458.86,1652.19l-88.191,-329.135l329.135,-88.191" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
22
modules/backend/assets/images/media-icon.svg
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="42px" height="42px" viewBox="0 0 42 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<!-- Generator: Sketch 3.4.4 (17249) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>media-icon</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<g id="slr_back_side" sketch:type="MSLayerGroup" transform="translate(0.000000, 2.000000)">
|
||||
<path d="M37.8,4.22222222 L29.82,4.22222222 L27.72,1.05555556 C27.3,0.422222222 26.67,0.105555556 25.935,0.105555556 L15.855,0.105555556 C15.12,0.105555556 14.49,0.422222222 14.07,1.05555556 L11.97,4.22222222 L4.2,4.22222222 C1.89,4.22222222 0,6.12222222 0,8.44444444 L0,33.7777778 C0,36.1 1.89,38 4.2,38 L37.8,38 C40.11,38 42,36.1 42,33.7777778 L42,8.44444444 C42,6.12222222 40.11,4.22222222 37.8,4.22222222 L37.8,4.22222222 Z" id="Shape" fill="#B281C5" sketch:type="MSShapeGroup"></path>
|
||||
<path d="M7.35,10.5555556 L28.35,10.5555556 C28.98,10.5555556 29.4,10.9777778 29.4,11.6111111 L29.4,28.5 C29.4,29.1333333 28.98,29.5555556 28.35,29.5555556 L7.35,29.5555556 C6.72,29.5555556 6.3,29.1333333 6.3,28.5 L6.3,11.6111111 C6.3,10.9777778 6.72,10.5555556 7.35,10.5555556 L7.35,10.5555556 Z" id="Shape" fill="#2DA7C7" sketch:type="MSShapeGroup"></path>
|
||||
<path d="M15.645,16.8888889 L8.4,27.4444444 L22.89,27.4444444 L15.645,16.8888889 Z" id="Shape" fill="#227F96" sketch:type="MSShapeGroup"></path>
|
||||
<ellipse id="Oval" fill="#F8E095" sketch:type="MSShapeGroup" cx="24.15" cy="15.8333333" rx="2.1" ry="2.11111111"></ellipse>
|
||||
<path d="M22.26,21.1111111 L17.22,27.4444444 L27.3,27.4444444 L22.26,21.1111111 Z" id="Shape" fill="#88c9e7" sketch:type="MSShapeGroup"></path>
|
||||
<g id="Group" transform="translate(31.500000, 2.111111)" fill="#7B4E8E" sketch:type="MSShapeGroup">
|
||||
<path d="M0,2.11111111 L6.3,2.11111111 L6.3,1.26666667 C6.3,0.527777778 5.775,0 5.04,0 L1.26,0 C0.525,0 0,0.527777778 0,1.26666667 L0,2.11111111 L0,2.11111111 Z" id="Shape"></path>
|
||||
<ellipse id="Oval" cx="4.2" cy="10.5555556" rx="2.1" ry="2.11111111"></ellipse>
|
||||
<ellipse id="Oval" cx="4.2" cy="16.8888889" rx="2.1" ry="2.11111111"></ellipse>
|
||||
<ellipse id="Oval" cx="4.2" cy="23.2222222" rx="2.1" ry="2.11111111"></ellipse>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
|
||||
]>
|
||||
<svg version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
|
||||
x="0px" y="0px" width="77px" height="25px" viewBox="0 -0.167 77 25" enable-background="new 0 -0.167 77 25"
|
||||
xml:space="preserve">
|
||||
<defs>
|
||||
</defs>
|
||||
<path fill="#FFFFFF" d="M60,25h15c-5.037,0-5-25-15-25V25z"/>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M15,25H0C5.037,25,5,0,15,0V25z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 704 B |
16
modules/backend/assets/images/tab-shape.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
|
||||
]>
|
||||
<svg version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
|
||||
x="0px" y="0px" width="100px" height="110px" viewBox="0 0 100 110" enable-background="new 0 0 100 110" xml:space="preserve">
|
||||
<defs>
|
||||
</defs>
|
||||
<path d="M0,30C5,30,10,0,20,0c5,0,60,0,65,0c10,0,10,30,15,30"/>
|
||||
<path fill="#2DA7C7" d="M0,70c5,0,10-30,20-30c0,10,0,15,0,15v15"/>
|
||||
<path fill="#2DA7C7" d="M100,70c-5,0-10-30-20-30c0,10,0,15,0,15v15"/>
|
||||
<path fill="#227F96" d="M0,110c5,0,10-30,20-30c0,10,0,15,0,15v15"/>
|
||||
<path fill="#227F96" d="M100,110c-5,0-10-30-20-30c0,10,0,15,0,15v15"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 909 B |
BIN
modules/backend/assets/images/treeview-icons.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
modules/backend/assets/images/treeview-submenu-tabs.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
46
modules/backend/assets/images/winter-logo-white.svg
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 2159 531" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-miterlimit:10;">
|
||||
<g transform="matrix(1,0,0,1,-203.164,-34.6758)">
|
||||
<g id="Snowflake" transform="matrix(1,0,0,1,1723.13,0)">
|
||||
<g>
|
||||
<path d="M400,300L400,500" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;"/>
|
||||
<path d="M355.3,389.017L400,344.316L444.7,389.017" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;stroke-linecap:square;"/>
|
||||
<path d="M342.174,462.247L400,404.42L457.826,462.247" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M400,300L226.795,400" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;"/>
|
||||
<path d="M300.559,305.797L361.621,322.158L345.259,383.22" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;stroke-linecap:square;"/>
|
||||
<path d="M230.577,331.044L309.57,352.21L288.404,431.202" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M400,300L226.795,200" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;"/>
|
||||
<path d="M345.259,216.78L361.621,277.842L300.559,294.203" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;stroke-linecap:square;"/>
|
||||
<path d="M288.404,168.798L309.57,247.79L230.577,268.956" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M400,300L400,100" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;"/>
|
||||
<path d="M444.7,210.983L400,255.684L355.3,210.983" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;stroke-linecap:square;"/>
|
||||
<path d="M457.826,137.753L400,195.58L342.174,137.753" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M400,300L573.205,200" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;"/>
|
||||
<path d="M499.441,294.203L438.379,277.842L454.741,216.78" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;stroke-linecap:square;"/>
|
||||
<path d="M569.423,268.956L490.43,247.79L511.596,168.798" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M400,300L573.205,400" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;"/>
|
||||
<path d="M454.741,383.22L438.379,322.158L499.441,305.797" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;stroke-linecap:square;"/>
|
||||
<path d="M511.596,431.202L490.43,352.21L569.423,331.044" style="fill:none;fill-rule:nonzero;stroke:rgb(45,167,199);stroke-width:13px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(4.85947,0,0,4.85947,-731.059,-919.349)">
|
||||
<path d="M217.275,286.281L210.955,286.281L192.351,215.563L197.717,215.563L214.055,278.172L231.228,215.563L238.502,215.563L255.794,278.172L272.132,215.563L277.499,215.563L258.895,286.281L252.574,286.281L234.925,222.361L217.275,286.281Z" style="fill:white;fill-rule:nonzero;stroke:white;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:2;"/>
|
||||
<rect x="286.681" y="215.563" width="4.77" height="70.718" style="fill:white;fill-rule:nonzero;stroke:white;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:2;"/>
|
||||
<path d="M311.486,286.281L306.716,286.281L306.716,215.563L313.275,215.563L355.968,280.438L355.968,215.563L360.738,215.563L360.738,286.281L354.179,286.281L311.486,222.361L311.486,286.281Z" style="fill:white;fill-rule:nonzero;stroke:white;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:2;"/>
|
||||
<path d="M397.827,286.281L393.056,286.281L393.056,220.214L368.848,220.214L368.848,215.563L422.274,215.563L422.274,220.214L397.827,220.214L397.827,286.281Z" style="fill:white;fill-rule:nonzero;stroke:white;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:2;"/>
|
||||
<path d="M476.535,286.281L430.383,286.281L430.383,215.563L476.535,215.563L476.535,220.214L435.153,220.214L435.153,247.404L472.957,247.404L472.957,251.817L435.153,251.817L435.153,281.75L476.535,281.75L476.535,286.281Z" style="fill:white;fill-rule:nonzero;stroke:white;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:2;"/>
|
||||
<path d="M490.249,286.281L485.479,286.281L485.479,215.563L519.228,215.563C524.078,215.563 528.212,217.392 531.63,221.049C535.049,224.627 536.758,228.999 536.758,234.167C536.758,238.699 535.725,242.634 533.658,245.973C531.511,249.312 528.848,251.26 525.668,251.817C528.609,252.612 530.994,255.116 532.823,259.33C534.651,263.543 535.566,268.632 535.566,274.594C535.566,277.933 535.645,280.438 535.804,282.107C535.963,284.095 536.281,285.486 536.758,286.281L531.988,286.281C531.193,285.327 530.676,283.578 530.438,281.034L530.08,270.897C530.08,266.127 528.927,262.033 526.622,258.614C524.396,255.275 521.653,253.606 518.393,253.606L490.249,253.606L490.249,286.281ZM490.249,249.193L518.393,249.193C522.13,249.193 525.35,247.762 528.053,244.9C530.676,242.117 531.988,238.699 531.988,234.644C531.988,230.669 530.676,227.25 528.053,224.388C525.35,221.606 522.13,220.214 518.393,220.214L490.249,220.214L490.249,249.193Z" style="fill:white;fill-rule:nonzero;stroke:white;stroke-width:0.21px;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:2;"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.1 KiB |
1
modules/backend/assets/images/winter-logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 8992 2212" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-miterlimit:10;"><g id="Snowflake"><g><path d="M7997.78,1105.52l0,833.334" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/><path d="M7811.52,1476.42l186.252,-186.252l186.252,186.252" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;stroke-linecap:square;"/><path d="M7756.83,1781.55l240.943,-240.944l240.944,240.944" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/></g><g><path d="M7997.78,1105.52l-721.688,416.667" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/><path d="M7583.44,1129.67l254.425,68.173l-68.173,254.425" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;stroke-linecap:square;"/><path d="M7291.85,1234.87l329.135,88.191l-88.192,329.135" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/></g><g><path d="M7997.78,1105.52l-721.688,-416.666" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/><path d="M7769.69,758.767l68.173,254.425l-254.425,68.173" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;stroke-linecap:square;"/><path d="M7532.79,558.841l88.192,329.135l-329.135,88.191" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/></g><g><path d="M7997.78,1105.52l0,-833.333" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/><path d="M8184.03,734.614l-186.252,186.252l-186.252,-186.252" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;stroke-linecap:square;"/><path d="M8238.72,429.49l-240.944,240.944l-240.943,-240.944" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/></g><g><path d="M7997.78,1105.52l721.688,-416.666" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/><path d="M8412.11,1081.37l-254.425,-68.173l68.173,-254.425" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;stroke-linecap:square;"/><path d="M8703.7,976.167l-329.135,-88.191l88.191,-329.135" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/></g><g><path d="M7997.78,1105.52l721.688,416.667" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/><path d="M8225.86,1452.27l-68.173,-254.425l254.425,-68.173" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;stroke-linecap:square;"/><path d="M8462.76,1652.19l-88.191,-329.135l329.135,-88.191" style="fill:none;fill-rule:nonzero;stroke:#2da7c7;stroke-width:54.17px;"/></g></g><path d="M504.66,1821.46l-127.976,0l-376.684,-1431.88l108.659,-0l330.806,1267.69l347.709,-1267.69l147.293,-0l350.123,1267.69l330.806,-1267.69l108.659,-0l-376.684,1431.88l-127.976,0l-357.367,-1294.25l-357.368,1294.25Z" style="fill:#103141;fill-rule:nonzero;"/><rect x="1909.98" y="389.576" width="96.586" height="1431.88" style="fill:#103141;fill-rule:nonzero;"/><path d="M2412.23,1821.46l-96.586,0l-0,-1431.88l132.805,-0l864.443,1313.57l-0,-1313.57l96.585,-0l0,1431.88l-132.805,0l-864.442,-1294.25l-0,1294.25Z" style="fill:#103141;fill-rule:nonzero;"/><path d="M4160.43,1821.46l-96.585,0l-0,-1337.71l-490.173,-0l0,-94.171l1081.76,-0l0,94.171l-495.002,-0l0,1337.71Z" style="fill:#103141;fill-rule:nonzero;"/><path d="M5754.1,1821.46l-934.467,0l0,-1431.88l934.467,-0l0,94.171l-837.881,-0l-0,550.538l765.442,0l-0,89.342l-765.442,0l-0,606.076l837.881,-0l0,91.756Z" style="fill:#103141;fill-rule:nonzero;"/><path d="M6031.78,1821.46l-96.586,0l0,-1431.88l683.344,-0c98.196,-0 181.904,37.024 251.123,111.073c69.22,72.44 103.83,160.977 103.83,265.611c-0,91.757 -20.927,171.44 -62.781,239.05c-43.463,67.61 -97.39,107.049 -161.781,118.317c59.561,16.098 107.854,66.805 144.879,152.123c37.024,85.317 55.537,188.342 55.537,309.074c-0,67.61 1.609,118.318 4.829,152.123c3.219,40.244 9.658,68.415 19.317,84.512l-96.586,0c-16.097,-19.317 -26.561,-54.732 -31.39,-106.244l-7.244,-205.245c-0,-96.586 -23.342,-179.488 -70.025,-248.708c-45.073,-67.61 -100.61,-101.415 -166.61,-101.415l-569.856,-0l0,661.612Zm0,-750.954l569.856,0c75.659,0 140.854,-28.976 195.586,-86.927c53.122,-56.342 79.683,-125.561 79.683,-207.659c0,-80.488 -26.561,-149.708 -79.683,-207.66c-54.732,-56.341 -119.927,-84.512 -195.586,-84.512l-569.856,-0l0,586.758Z" style="fill:#103141;fill-rule:nonzero;"/></svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
BIN
modules/backend/assets/images/wordmark.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
5
modules/backend/assets/js/auth/auth.js
Normal file
@@ -0,0 +1,5 @@
|
||||
$(document).ready(function(){
|
||||
$(document.body).removeClass('preload')
|
||||
|
||||
$('form input[type=text], form input[type=password]').first().focus()
|
||||
})
|
||||
102
modules/backend/assets/js/backend.js
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Winter General Utilities
|
||||
*/
|
||||
|
||||
/*
|
||||
* Path helpers
|
||||
*/
|
||||
|
||||
if ($.wn === undefined)
|
||||
$.wn = {}
|
||||
if ($.oc === undefined)
|
||||
$.oc = $.wn
|
||||
|
||||
$.wn.backendUrl = function(url) {
|
||||
var backendBasePath = $('meta[name="backend-base-path"]').attr('content')
|
||||
|
||||
if (!backendBasePath)
|
||||
return url
|
||||
|
||||
if (url.substr(0, 1) == '/')
|
||||
url = url.substr(1)
|
||||
|
||||
return backendBasePath + '/' + url
|
||||
}
|
||||
|
||||
/*
|
||||
* String escape
|
||||
*/
|
||||
if ($.wn === undefined)
|
||||
$.wn = {}
|
||||
if ($.oc === undefined)
|
||||
$.oc = $.wn
|
||||
|
||||
$.wn.escapeHtmlString = function(string) {
|
||||
var htmlEscapes = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
'/': '/'
|
||||
},
|
||||
htmlEscaper = /[&<>"'\/]/g
|
||||
|
||||
return ('' + string).replace(htmlEscaper, function(match) {
|
||||
return htmlEscapes[match];
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* Inverse Click Event (not used)
|
||||
*
|
||||
* Calls the handler function if the user has clicked outside the object
|
||||
* and not on any of the elements in the exception list.
|
||||
*/
|
||||
/*
|
||||
$.fn.extend({
|
||||
clickOutside: function(handler, exceptions) {
|
||||
var $this = this;
|
||||
|
||||
$('body').on('click', function(event) {
|
||||
if (exceptions && $.inArray(event.target, exceptions) > -1) {
|
||||
return;
|
||||
} else if ($.contains($this[0], event.target)) {
|
||||
return;
|
||||
} else {
|
||||
handler(event, $this);
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
})
|
||||
*/
|
||||
|
||||
/*
|
||||
* Browser Fixes
|
||||
* - If another fix using JS is necessary, move this logic to backend.fixes.js
|
||||
*/
|
||||
|
||||
/*
|
||||
* Internet Explorer v11
|
||||
* - IE11 will not honor height 100% when overflow is used on the Y axis.
|
||||
*/
|
||||
if (!!window.MSInputMethodContext && !!document.documentMode) {
|
||||
$(window).on('resize', function() {
|
||||
fixMediaManager()
|
||||
fixSidebar()
|
||||
})
|
||||
|
||||
function fixMediaManager() {
|
||||
var $el = $('div[data-control="media-manager"] .control-scrollpad')
|
||||
$el.height($el.parent().height())
|
||||
}
|
||||
|
||||
function fixSidebar() {
|
||||
$('#layout-sidenav').height(Math.max(
|
||||
$('#layout-body').innerHeight(),
|
||||
$(window).height() - $('#layout-mainmenu').height()
|
||||
))
|
||||
}
|
||||
}
|
||||
1
modules/backend/assets/js/preferences/preferences.js
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";(self.webpackChunk_wintercms_wn_backend_module=self.webpackChunk_wintercms_wn_backend_module||[]).push([[429],{449:function(e,t,i){var n=i(171);(e=>{class t extends e.Singleton{construct(){this.widget=null}listens(){return{"backend.widget.initialized":"onWidgetInitialized"}}onWidgetInitialized(e,t){e===document.getElementById("CodeEditor-formEditorPreview-_editor_preview")&&(this.widget=t,this.enablePreferences())}enablePreferences(){(0,n.M)("change");Object.entries({show_gutter:"showGutter",highlight_active_line:"highlightActiveLine",use_hard_tabs:"!useSoftTabs",display_indent_guides:"displayIndentGuides",show_invisibles:"showInvisibles",show_print_margin:"showPrintMargin",show_minimap:"showMinimap",enable_folding:"codeFolding",bracket_colors:"bracketColors",show_colors:"showColors"}).forEach(([e,t])=>{this.element(e).addEventListener("change",e=>{this.widget.setConfig(t.replace(/^!/,""),/^!/.test(t)?!e.target.checked:e.target.checked)})}),this.element("theme").addEventListener("$change",e=>{this.widget.loadTheme(e.target.value)}),this.element("font_size").addEventListener("$change",e=>{this.widget.setConfig("fontSize",e.target.value)}),this.element("tab_size").addEventListener("$change",e=>{this.widget.setConfig("tabSize",e.target.value)}),this.element("word_wrap").addEventListener("$change",e=>{const{value:t}=e.target;switch(t){case"off":this.widget.setConfig("wordWrap",!1);break;case"fluid":this.widget.setConfig("wordWrap","fluid");break;default:this.widget.setConfig("wordWrap",parseInt(t,10))}}),document.querySelectorAll("[data-switch-lang]").forEach(e=>{e.addEventListener("click",t=>{t.preventDefault();const i=e.dataset.switchLang,n=document.querySelector(`[data-lang-snippet="${i}"]`);n&&(this.widget.setValue(n.textContent.trim()),this.widget.setLanguage(i))})}),this.widget.events.once("create",()=>{const e=new MouseEvent("click");document.querySelector('[data-switch-lang="css"]').dispatchEvent(e)})}element(e){return document.getElementById(`Form-field-Preference-editor_${e}`)}}e.addPlugin("backend.preferences",t)})(window.Snowboard)}},function(e){e.O(0,[810],function(){return t=449,e(e.s=t);var t});e.O()}]);
|
||||
5
modules/backend/assets/js/vendor/jquery-and-migrate.min.js
vendored
Normal file
2
modules/backend/assets/js/vendor/jquery-migrate.min.js
vendored
Normal file
447
modules/backend/assets/js/vendor/jquery.autoellipsis.js
vendored
Normal file
@@ -0,0 +1,447 @@
|
||||
/*!
|
||||
|
||||
Copyright (c) 2011 Peter van der Spek
|
||||
|
||||
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($) {
|
||||
|
||||
/**
|
||||
* Hash containing mapping of selectors to settings hashes for target selectors that should be live updated.
|
||||
*
|
||||
* @type {Object.<string, Object>}
|
||||
* @private
|
||||
*/
|
||||
var liveUpdatingTargetSelectors = {};
|
||||
|
||||
/**
|
||||
* Interval ID for live updater. Contains interval ID when the live updater interval is active, or is undefined
|
||||
* otherwise.
|
||||
*
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
var liveUpdaterIntervalId;
|
||||
|
||||
/**
|
||||
* Boolean indicating whether the live updater is running.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
var liveUpdaterRunning = false;
|
||||
|
||||
/**
|
||||
* Set of default settings.
|
||||
*
|
||||
* @type {Object.<string, string>}
|
||||
* @private
|
||||
*/
|
||||
var defaultSettings = {
|
||||
ellipsis: '...',
|
||||
setTitle: 'never',
|
||||
live: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform ellipsis on selected elements.
|
||||
*
|
||||
* @param {string} selector the inner selector of elements that ellipsis may work on. Inner elements not referred to by this
|
||||
* selector are left untouched.
|
||||
* @param {Object.<string, string>=} options optional options to override default settings.
|
||||
* @return {jQuery} the current jQuery object for chaining purposes.
|
||||
* @this {jQuery} the current jQuery object.
|
||||
*/
|
||||
$.fn.ellipsis = function(selector, options) {
|
||||
var subjectElements, settings;
|
||||
|
||||
subjectElements = $(this);
|
||||
|
||||
// Check for options argument only.
|
||||
if (typeof selector !== 'string') {
|
||||
options = selector;
|
||||
selector = undefined;
|
||||
}
|
||||
|
||||
// Create the settings from the given options and the default settings.
|
||||
settings = $.extend({}, defaultSettings, options);
|
||||
|
||||
// If selector is not set, work on immediate children (default behaviour).
|
||||
settings.selector = selector;
|
||||
|
||||
// Do ellipsis on each subject element.
|
||||
subjectElements.each(function() {
|
||||
var elem = $(this);
|
||||
|
||||
// Do ellipsis on subject element.
|
||||
ellipsisOnElement(elem, settings);
|
||||
});
|
||||
|
||||
// If live option is enabled, add subject elements to live updater. Otherwise remove from live updater.
|
||||
if (settings.live) {
|
||||
addToLiveUpdater(subjectElements.selector, settings);
|
||||
|
||||
} else {
|
||||
removeFromLiveUpdater(subjectElements.selector);
|
||||
}
|
||||
|
||||
// Return jQuery object for chaining.
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Perform ellipsis on the given container.
|
||||
*
|
||||
* @param {jQuery} containerElement jQuery object containing one DOM element to perform ellipsis on.
|
||||
* @param {Object.<string, string>} settings the settings for this ellipsis operation.
|
||||
* @private
|
||||
*/
|
||||
function ellipsisOnElement(containerElement, settings) {
|
||||
var containerData = containerElement.data('jqae');
|
||||
if (!containerData) containerData = {};
|
||||
|
||||
// Check if wrapper div was already created and bound to the container element.
|
||||
var wrapperElement = containerData.wrapperElement;
|
||||
|
||||
// If not, create wrapper element.
|
||||
if (!wrapperElement) {
|
||||
wrapperElement = containerElement.wrapInner('<div/>').find('>div');
|
||||
|
||||
// Wrapper div should not add extra size.
|
||||
wrapperElement.css({
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
border: 0
|
||||
});
|
||||
}
|
||||
|
||||
// Check if the original wrapper element content was already bound to the wrapper element.
|
||||
var wrapperElementData = wrapperElement.data('jqae');
|
||||
if (!wrapperElementData) wrapperElementData = {};
|
||||
|
||||
var wrapperOriginalContent = wrapperElementData.originalContent;
|
||||
|
||||
// If so, clone the original content, re-bind the original wrapper content to the clone, and replace the
|
||||
// wrapper with the clone.
|
||||
if (wrapperOriginalContent) {
|
||||
wrapperElement = wrapperElementData.originalContent.clone(true)
|
||||
.data('jqae', {originalContent: wrapperOriginalContent}).replaceAll(wrapperElement);
|
||||
|
||||
} else {
|
||||
// Otherwise, clone the current wrapper element and bind it as original content to the wrapper element.
|
||||
|
||||
wrapperElement.data('jqae', {originalContent: wrapperElement.clone(true)});
|
||||
}
|
||||
|
||||
// Bind the wrapper element and current container width and height to the container element. Current container
|
||||
// width and height are stored to detect changes to the container size.
|
||||
containerElement.data('jqae', {
|
||||
wrapperElement: wrapperElement,
|
||||
containerWidth: containerElement.width(),
|
||||
containerHeight: containerElement.height()
|
||||
});
|
||||
|
||||
// Calculate with current container element height.
|
||||
var containerElementHeight = containerElement.height();
|
||||
|
||||
// Calculate wrapper offset.
|
||||
var wrapperOffset = (parseInt(containerElement.css('padding-top'), 10) || 0) + (parseInt(containerElement.css('border-top-width'), 10) || 0) - (wrapperElement.offset().top - containerElement.offset().top);
|
||||
|
||||
// Normally the ellipsis characters are applied to the last non-empty text-node in the selected element. If the
|
||||
// selected element becomes empty during ellipsis iteration, the ellipsis characters cannot be applied to that
|
||||
// selected element, and must be deferred to the previous selected element. This parameter keeps track of that.
|
||||
var deferAppendEllipsis = false;
|
||||
|
||||
// Loop through all selected elements in reverse order.
|
||||
var selectedElements = wrapperElement;
|
||||
if (settings.selector) selectedElements = $(wrapperElement.find(settings.selector).get().reverse());
|
||||
|
||||
selectedElements.each(function() {
|
||||
var selectedElement = $(this),
|
||||
originalText = selectedElement.text(),
|
||||
ellipsisApplied = false;
|
||||
|
||||
// Check if we can safely remove the selected element. This saves a lot of unnecessary iterations.
|
||||
if (wrapperElement.innerHeight() - selectedElement.innerHeight() > containerElementHeight + wrapperOffset) {
|
||||
selectedElement.remove();
|
||||
|
||||
} else {
|
||||
// Reverse recursively remove empty elements, until the element that contains a non-empty text-node.
|
||||
removeLastEmptyElements(selectedElement);
|
||||
|
||||
// If the selected element has not become empty, start ellipsis iterations on the selected element.
|
||||
if (selectedElement.contents().length) {
|
||||
|
||||
// If a deffered ellipsis is still pending, apply it now to the last text-node.
|
||||
if (deferAppendEllipsis) {
|
||||
getLastTextNode(selectedElement).get(0).nodeValue += settings.ellipsis;
|
||||
deferAppendEllipsis = false;
|
||||
}
|
||||
|
||||
// Iterate until wrapper element height is less than or equal to the original container element
|
||||
// height plus possible wrapperOffset.
|
||||
while (wrapperElement.innerHeight() > containerElementHeight + wrapperOffset) {
|
||||
// Apply ellipsis on last text node, by removing one word.
|
||||
ellipsisApplied = ellipsisOnLastTextNode(selectedElement);
|
||||
|
||||
// If ellipsis was succesfully applied, remove any remaining empty last elements and append the
|
||||
// ellipsis characters.
|
||||
if (ellipsisApplied) {
|
||||
removeLastEmptyElements(selectedElement);
|
||||
|
||||
// If the selected element is not empty, append the ellipsis characters.
|
||||
if (selectedElement.contents().length) {
|
||||
getLastTextNode(selectedElement).get(0).nodeValue += settings.ellipsis;
|
||||
|
||||
} else {
|
||||
// If the selected element has become empty, defer the appending of the ellipsis characters
|
||||
// to the previous selected element.
|
||||
deferAppendEllipsis = true;
|
||||
selectedElement.remove();
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
// If ellipsis could not be applied, defer the appending of the ellipsis characters to the
|
||||
// previous selected element.
|
||||
deferAppendEllipsis = true;
|
||||
selectedElement.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the "setTitle" property is set to "onEllipsis" and the ellipsis has been applied, or if the
|
||||
// property is set to "always", the add the "title" attribute with the original text. Else remove the
|
||||
// "title" attribute. When the "setTitle" property is set to "never" we do not touch the "title"
|
||||
// attribute.
|
||||
if (((settings.setTitle == 'onEllipsis') && ellipsisApplied) || (settings.setTitle == 'always')) {
|
||||
selectedElement.attr('title', originalText);
|
||||
|
||||
} else if (settings.setTitle != 'never') {
|
||||
selectedElement.removeAttr('title');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs ellipsis on the last text node of the given element. Ellipsis is done by removing a full word.
|
||||
*
|
||||
* @param {jQuery} element jQuery object containing a single DOM element.
|
||||
* @return {boolean} true when ellipsis has been done, false otherwise.
|
||||
* @private
|
||||
*/
|
||||
function ellipsisOnLastTextNode(element) {
|
||||
var lastTextNode = getLastTextNode(element);
|
||||
|
||||
// If the last text node is found, do ellipsis on that node.
|
||||
if (lastTextNode.length) {
|
||||
var text = lastTextNode.get(0).nodeValue;
|
||||
|
||||
// Find last space character, and remove text from there. If no space is found the full remaining text is
|
||||
// removed.
|
||||
var pos = text.lastIndexOf(' ');
|
||||
if (pos > -1) {
|
||||
text = $.trim(text.substring(0, pos));
|
||||
lastTextNode.get(0).nodeValue = text;
|
||||
|
||||
} else {
|
||||
lastTextNode.get(0).nodeValue = '';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last text node of the given element.
|
||||
*
|
||||
* @param {jQuery} element jQuery object containing a single element.
|
||||
* @return {jQuery} jQuery object containing a single text node.
|
||||
* @private
|
||||
*/
|
||||
function getLastTextNode(element) {
|
||||
if (element.contents().length) {
|
||||
|
||||
// Get last child node.
|
||||
var contents = element.contents();
|
||||
var lastNode = contents.eq(contents.length - 1);
|
||||
|
||||
// If last node is a text node, return it.
|
||||
if (lastNode.filter(textNodeFilter).length) {
|
||||
return lastNode;
|
||||
|
||||
} else {
|
||||
// Else it is an element node, and we recurse into it.
|
||||
|
||||
return getLastTextNode(lastNode);
|
||||
}
|
||||
|
||||
} else {
|
||||
// If there is no last child node, we append an empty text node and return that. Normally this should not
|
||||
// happen, as we test for emptiness before calling getLastTextNode.
|
||||
|
||||
element.append('');
|
||||
var contents = element.contents();
|
||||
return contents.eq(contents.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove last empty elements. This is done recursively until the last element contains a non-empty text node.
|
||||
*
|
||||
* @param {jQuery} element jQuery object containing a single element.
|
||||
* @return {boolean} true when elements have been removed, false otherwise.
|
||||
* @private
|
||||
*/
|
||||
function removeLastEmptyElements(element) {
|
||||
if (element.contents().length) {
|
||||
|
||||
// Get last child node.
|
||||
var contents = element.contents();
|
||||
var lastNode = contents.eq(contents.length - 1);
|
||||
|
||||
// If last child node is a text node, check for emptiness.
|
||||
if (lastNode.filter(textNodeFilter).length) {
|
||||
var text = lastNode.get(0).nodeValue;
|
||||
text = $.trim(text);
|
||||
|
||||
if (text == '') {
|
||||
// If empty, remove the text node.
|
||||
lastNode.remove();
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
// If the last child node is an element node, remove the last empty child nodes on that node.
|
||||
while (removeLastEmptyElements(lastNode)) {
|
||||
}
|
||||
|
||||
// If the last child node contains no more child nodes, remove the last child node.
|
||||
if (lastNode.contents().length) {
|
||||
return false;
|
||||
|
||||
} else {
|
||||
lastNode.remove();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter for testing on text nodes.
|
||||
*
|
||||
* @return {boolean} true when this node is a text node, false otherwise.
|
||||
* @this {Node}
|
||||
* @private
|
||||
*/
|
||||
function textNodeFilter() {
|
||||
return this.nodeType === 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add target selector to hash of target selectors. If this is the first target selector added, start the live
|
||||
* updater.
|
||||
*
|
||||
* @param {string} targetSelector the target selector to run the live updater for.
|
||||
* @param {Object.<string, string>} settings the settings to apply on this target selector.
|
||||
* @private
|
||||
*/
|
||||
function addToLiveUpdater(targetSelector, settings) {
|
||||
// Store target selector with its settings.
|
||||
liveUpdatingTargetSelectors[targetSelector] = settings;
|
||||
|
||||
// If the live updater has not yet been started, start it now.
|
||||
if (!liveUpdaterIntervalId) {
|
||||
liveUpdaterIntervalId = window.setInterval(function() {
|
||||
doLiveUpdater();
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the target selector from the hash of target selectors. It this is the last remaining target selector
|
||||
* being removed, stop the live updater.
|
||||
*
|
||||
* @param {string} targetSelector the target selector to stop running the live updater for.
|
||||
* @private
|
||||
*/
|
||||
function removeFromLiveUpdater(targetSelector) {
|
||||
// If the hash contains the target selector, remove it.
|
||||
if (liveUpdatingTargetSelectors[targetSelector]) {
|
||||
delete liveUpdatingTargetSelectors[targetSelector];
|
||||
|
||||
// If no more target selectors are in the hash, stop the live updater.
|
||||
if (!liveUpdatingTargetSelectors.length) {
|
||||
if (liveUpdaterIntervalId) {
|
||||
window.clearInterval(liveUpdaterIntervalId);
|
||||
liveUpdaterIntervalId = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Run the live updater. The live updater is periodically run to check if its monitored target selectors require
|
||||
* re-applying of the ellipsis.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function doLiveUpdater() {
|
||||
// If the live updater is already running, skip this time. We only want one instance running at a time.
|
||||
if (!liveUpdaterRunning) {
|
||||
liveUpdaterRunning = true;
|
||||
|
||||
// Loop through target selectors.
|
||||
for (var targetSelector in liveUpdatingTargetSelectors) {
|
||||
$(targetSelector).each(function() {
|
||||
var containerElement, containerData;
|
||||
|
||||
containerElement = $(this);
|
||||
containerData = containerElement.data('jqae');
|
||||
|
||||
// If container element dimensions have changed, or the container element is new, run ellipsis on
|
||||
// that container element.
|
||||
if ((containerData.containerWidth != containerElement.width()) ||
|
||||
(containerData.containerHeight != containerElement.height())) {
|
||||
ellipsisOnElement(containerElement, liveUpdatingTargetSelectors[targetSelector]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
liveUpdaterRunning = false;
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
117
modules/backend/assets/js/vendor/jquery.cookie.js
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
/*!
|
||||
* jQuery Cookie Plugin v1.4.1
|
||||
* https://github.com/carhartl/jquery-cookie
|
||||
*
|
||||
* Copyright 2006, 2014 Klaus Hartl
|
||||
* Released under the MIT license
|
||||
*/
|
||||
(function (factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD
|
||||
define(['jquery'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// CommonJS
|
||||
factory(require('jquery'));
|
||||
} else {
|
||||
// Browser globals
|
||||
factory(jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
|
||||
var pluses = /\+/g;
|
||||
|
||||
function encode(s) {
|
||||
return config.raw ? s : encodeURIComponent(s);
|
||||
}
|
||||
|
||||
function decode(s) {
|
||||
return config.raw ? s : decodeURIComponent(s);
|
||||
}
|
||||
|
||||
function stringifyCookieValue(value) {
|
||||
return encode(config.json ? JSON.stringify(value) : String(value));
|
||||
}
|
||||
|
||||
function parseCookieValue(s) {
|
||||
if (s.indexOf('"') === 0) {
|
||||
// This is a quoted cookie as according to RFC2068, unescape...
|
||||
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
|
||||
}
|
||||
|
||||
try {
|
||||
// Replace server-side written pluses with spaces.
|
||||
// If we can't decode the cookie, ignore it, it's unusable.
|
||||
// If we can't parse the cookie, ignore it, it's unusable.
|
||||
s = decodeURIComponent(s.replace(pluses, ' '));
|
||||
return config.json ? JSON.parse(s) : s;
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
function read(s, converter) {
|
||||
var value = config.raw ? s : parseCookieValue(s);
|
||||
return $.isFunction(converter) ? converter(value) : value;
|
||||
}
|
||||
|
||||
var config = $.cookie = function (key, value, options) {
|
||||
|
||||
// Write
|
||||
|
||||
if (arguments.length > 1 && !$.isFunction(value)) {
|
||||
options = $.extend({}, config.defaults, options);
|
||||
|
||||
if (typeof options.expires === 'number') {
|
||||
var days = options.expires, t = options.expires = new Date();
|
||||
t.setTime(+t + days * 864e+5);
|
||||
}
|
||||
|
||||
return (document.cookie = [
|
||||
encode(key), '=', stringifyCookieValue(value),
|
||||
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
|
||||
options.path ? '; path=' + options.path : '',
|
||||
options.domain ? '; domain=' + options.domain : '',
|
||||
options.secure ? '; secure' : ''
|
||||
].join(''));
|
||||
}
|
||||
|
||||
// Read
|
||||
|
||||
var result = key ? undefined : {};
|
||||
|
||||
// To prevent the for loop in the first place assign an empty array
|
||||
// in case there are no cookies at all. Also prevents odd result when
|
||||
// calling $.cookie().
|
||||
var cookies = document.cookie ? document.cookie.split('; ') : [];
|
||||
|
||||
for (var i = 0, l = cookies.length; i < l; i++) {
|
||||
var parts = cookies[i].split('=');
|
||||
var name = decode(parts.shift());
|
||||
var cookie = parts.join('=');
|
||||
|
||||
if (key && key === name) {
|
||||
// If second argument (value) is a function it's a converter...
|
||||
result = read(cookie, value);
|
||||
break;
|
||||
}
|
||||
|
||||
// Prevent storing a cookie that we couldn't decode.
|
||||
if (!key && (cookie = read(cookie)) !== undefined) {
|
||||
result[name] = cookie;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
config.defaults = {};
|
||||
|
||||
$.removeCookie = function (key, options) {
|
||||
if ($.cookie(key) === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Must not alter options, thus extending a fresh object...
|
||||
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
|
||||
return !$.cookie(key);
|
||||
};
|
||||
|
||||
}));
|
||||
2
modules/backend/assets/js/vendor/jquery.min.js
vendored
Normal file
82
modules/backend/assets/js/vendor/jquery.touchwipe.js
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* jQuery Plugin to obtain touch gestures from iPhone, iPod Touch and iPad, should also work with Android mobile phones (not tested yet!)
|
||||
* Common usage: wipe images (left and right to show the previous or next image)
|
||||
*
|
||||
* @author Andreas Waltl, netCU Internetagentur (http://www.netcu.de)
|
||||
* @version 1.1.1 (9th December 2010) - fix bug (older IE's had problems)
|
||||
* @version 1.1 (1st September 2010) - support wipe up and wipe down
|
||||
* @version 1.0 (15th July 2010)
|
||||
*/
|
||||
(function($) {
|
||||
$.fn.touchwipe = function(settings) {
|
||||
var config = {
|
||||
min_move_x: 20,
|
||||
min_move_y: 20,
|
||||
wipeLeft: function() { },
|
||||
wipeRight: function() { },
|
||||
wipeUp: function() { },
|
||||
wipeDown: function() { },
|
||||
preventDefaultEvents: true
|
||||
};
|
||||
|
||||
if (settings) $.extend(config, settings);
|
||||
|
||||
this.each(function() {
|
||||
var startX;
|
||||
var startY;
|
||||
var isMoving = false;
|
||||
|
||||
function cancelTouch() {
|
||||
this.removeEventListener('touchmove', onTouchMove);
|
||||
startX = null;
|
||||
isMoving = false;
|
||||
}
|
||||
|
||||
function onTouchMove(e) {
|
||||
if(config.preventDefaultEvents) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if(isMoving) {
|
||||
var x = e.touches[0].pageX;
|
||||
var y = e.touches[0].pageY;
|
||||
var dx = startX - x;
|
||||
var dy = startY - y;
|
||||
if(Math.abs(dx) >= config.min_move_x) {
|
||||
cancelTouch();
|
||||
if(dx > 0) {
|
||||
config.wipeLeft();
|
||||
}
|
||||
else {
|
||||
config.wipeRight();
|
||||
}
|
||||
}
|
||||
else if(Math.abs(dy) >= config.min_move_y) {
|
||||
cancelTouch();
|
||||
if(dy > 0) {
|
||||
config.wipeDown();
|
||||
}
|
||||
else {
|
||||
config.wipeUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onTouchStart(e)
|
||||
{
|
||||
if (e.touches.length == 1) {
|
||||
startX = e.touches[0].pageX;
|
||||
startY = e.touches[0].pageY;
|
||||
isMoving = true;
|
||||
this.addEventListener('touchmove', onTouchMove, false);
|
||||
}
|
||||
}
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
this.addEventListener('touchstart', onTouchStart, false);
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
63
modules/backend/assets/js/vendor/jquery.waterfall.js
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
(function($) {
|
||||
/**
|
||||
* Runs functions given in arguments in series, each functions passing their results to the next one.
|
||||
* Return jQuery Deferred object.
|
||||
*
|
||||
* @example
|
||||
* $.waterfall(
|
||||
* function() { return $.ajax({url : first_url}) },
|
||||
* function() { return $.ajax({url : second_url}) },
|
||||
* function() { return $.ajax({url : another_url}) }
|
||||
*).fail(function() {
|
||||
* console.log(arguments)
|
||||
*).done(function() {
|
||||
* console.log(arguments)
|
||||
*})
|
||||
*
|
||||
* @example2
|
||||
* event_chain = [];
|
||||
* event_chain.push(function() { var deferred = $.Deferred(); deferred.resolve(); return deferred; });
|
||||
* $.waterfall.apply(this, event_chain).fail(function(){}).done(function(){});
|
||||
*
|
||||
* @author Dmitry (dio) Levashov, dio@std42.ru
|
||||
* @return jQuery.Deferred
|
||||
*/
|
||||
$.waterfall = function() {
|
||||
var steps = [],
|
||||
dfrd = $.Deferred(),
|
||||
pointer = 0;
|
||||
|
||||
$.each(arguments, function(i, a) {
|
||||
steps.push(function() {
|
||||
var args = [].slice.apply(arguments), d;
|
||||
|
||||
if (typeof(a) == 'function') {
|
||||
if (!((d = a.apply(null, args)) && d.promise)) {
|
||||
d = $.Deferred()[d === false ? 'reject' : 'resolve'](d);
|
||||
}
|
||||
} else if (a && a.promise) {
|
||||
d = a;
|
||||
} else {
|
||||
d = $.Deferred()[a === false ? 'reject' : 'resolve'](a);
|
||||
}
|
||||
|
||||
d.fail(function() {
|
||||
dfrd.reject.apply(dfrd, [].slice.apply(arguments));
|
||||
})
|
||||
.done(function(data) {
|
||||
pointer++;
|
||||
args.push(data);
|
||||
|
||||
pointer == steps.length
|
||||
? dfrd.resolve.apply(dfrd, args)
|
||||
: steps[pointer].apply(null, args);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
steps.length ? steps[0]() : dfrd.resolve();
|
||||
|
||||
return dfrd;
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
762
modules/backend/assets/js/winter-min.js
vendored
Normal file
@@ -0,0 +1,762 @@
|
||||
(function($){$.fn.touchwipe=function(settings){var config={min_move_x:20,min_move_y:20,wipeLeft:function(){},wipeRight:function(){},wipeUp:function(){},wipeDown:function(){},preventDefaultEvents:true};if(settings)$.extend(config,settings);this.each(function(){var startX;var startY;var isMoving=false;function cancelTouch(){this.removeEventListener('touchmove',onTouchMove);startX=null;isMoving=false;}function onTouchMove(e){if(config.preventDefaultEvents){e.preventDefault();}if(isMoving){var x=e.touches[0].pageX;var y=e.touches[0].pageY;var dx=startX-x;var dy=startY-y;if(Math.abs(dx)>=config.min_move_x){cancelTouch();if(dx>0){config.wipeLeft();}else{config.wipeRight();}}else if(Math.abs(dy)>=config.min_move_y){cancelTouch();if(dy>0){config.wipeDown();}else{config.wipeUp();}}}}function onTouchStart(e){if(e.touches.length==1){startX=e.touches[0].pageX;startY=e.touches[0].pageY;isMoving=true;this.addEventListener('touchmove',onTouchMove,false);}}if('ontouchstart'in document.documentElement){
|
||||
this.addEventListener('touchstart',onTouchStart,false);}});return this;};})(jQuery);(function($){var liveUpdatingTargetSelectors={};var liveUpdaterIntervalId;var liveUpdaterRunning=false;var defaultSettings={ellipsis:'...',setTitle:'never',live:false};$.fn.ellipsis=function(selector,options){var subjectElements,settings;subjectElements=$(this);if(typeof selector!=='string'){options=selector;selector=undefined;}settings=$.extend({},defaultSettings,options);settings.selector=selector;subjectElements.each(function(){var elem=$(this);ellipsisOnElement(elem,settings);});if(settings.live){addToLiveUpdater(subjectElements.selector,settings);}else{removeFromLiveUpdater(subjectElements.selector);}return this;};function ellipsisOnElement(containerElement,settings){var containerData=containerElement.data('jqae');if(!containerData)containerData={};var wrapperElement=containerData.wrapperElement;if(!wrapperElement){wrapperElement=containerElement.wrapInner('<div/>').find('>div');wrapperElement.css({
|
||||
margin:0,padding:0,border:0});}var wrapperElementData=wrapperElement.data('jqae');if(!wrapperElementData)wrapperElementData={};var wrapperOriginalContent=wrapperElementData.originalContent;if(wrapperOriginalContent){wrapperElement=wrapperElementData.originalContent.clone(true).data('jqae',{originalContent:wrapperOriginalContent}).replaceAll(wrapperElement);}else{wrapperElement.data('jqae',{originalContent:wrapperElement.clone(true)});}containerElement.data('jqae',{wrapperElement:wrapperElement,containerWidth:containerElement.width(),containerHeight:containerElement.height()});var containerElementHeight=containerElement.height();var wrapperOffset=(parseInt(containerElement.css('padding-top'),10)||0)+(parseInt(containerElement.css('border-top-width'),10)||0)-(wrapperElement.offset().top-containerElement.offset().top);var deferAppendEllipsis=false;var selectedElements=wrapperElement;if(settings.selector)selectedElements=$(wrapperElement.find(settings.selector).get().reverse());
|
||||
selectedElements.each(function(){var selectedElement=$(this),originalText=selectedElement.text(),ellipsisApplied=false;if(wrapperElement.innerHeight()-selectedElement.innerHeight()>containerElementHeight+wrapperOffset){selectedElement.remove();}else{removeLastEmptyElements(selectedElement);if(selectedElement.contents().length){if(deferAppendEllipsis){getLastTextNode(selectedElement).get(0).nodeValue+=settings.ellipsis;deferAppendEllipsis=false;}while(wrapperElement.innerHeight()>containerElementHeight+wrapperOffset){ellipsisApplied=ellipsisOnLastTextNode(selectedElement);if(ellipsisApplied){removeLastEmptyElements(selectedElement);if(selectedElement.contents().length){getLastTextNode(selectedElement).get(0).nodeValue+=settings.ellipsis;}else{deferAppendEllipsis=true;selectedElement.remove();break;}}else{deferAppendEllipsis=true;selectedElement.remove();break;}}if(((settings.setTitle=='onEllipsis')&&ellipsisApplied)||(settings.setTitle=='always')){selectedElement.attr('title',originalText);
|
||||
}else if(settings.setTitle!='never'){selectedElement.removeAttr('title');}}}});}function ellipsisOnLastTextNode(element){var lastTextNode=getLastTextNode(element);if(lastTextNode.length){var text=lastTextNode.get(0).nodeValue;var pos=text.lastIndexOf(' ');if(pos>-1){text=$.trim(text.substring(0,pos));lastTextNode.get(0).nodeValue=text;}else{lastTextNode.get(0).nodeValue='';}return true;}return false;}function getLastTextNode(element){if(element.contents().length){var contents=element.contents();var lastNode=contents.eq(contents.length-1);if(lastNode.filter(textNodeFilter).length){return lastNode;}else{return getLastTextNode(lastNode);}}else{element.append('');var contents=element.contents();return contents.eq(contents.length-1);}}function removeLastEmptyElements(element){if(element.contents().length){var contents=element.contents();var lastNode=contents.eq(contents.length-1);if(lastNode.filter(textNodeFilter).length){var text=lastNode.get(0).nodeValue;text=$.trim(text);if(text==''){
|
||||
lastNode.remove();return true;}else{return false;}}else{while(removeLastEmptyElements(lastNode)){}if(lastNode.contents().length){return false;}else{lastNode.remove();return true;}}}return false;}function textNodeFilter(){return this.nodeType===3;}function addToLiveUpdater(targetSelector,settings){liveUpdatingTargetSelectors[targetSelector]=settings;if(!liveUpdaterIntervalId){liveUpdaterIntervalId=window.setInterval(function(){doLiveUpdater();},200);}}function removeFromLiveUpdater(targetSelector){if(liveUpdatingTargetSelectors[targetSelector]){delete liveUpdatingTargetSelectors[targetSelector];if(!liveUpdatingTargetSelectors.length){if(liveUpdaterIntervalId){window.clearInterval(liveUpdaterIntervalId);liveUpdaterIntervalId=undefined;}}}};function doLiveUpdater(){if(!liveUpdaterRunning){liveUpdaterRunning=true;for(var targetSelector in liveUpdatingTargetSelectors){$(targetSelector).each(function(){var containerElement,containerData;containerElement=$(this);containerData=containerElement.data('jqae');
|
||||
if((containerData.containerWidth!=containerElement.width())||(containerData.containerHeight!=containerElement.height())){ellipsisOnElement(containerElement,liveUpdatingTargetSelectors[targetSelector]);}});}liveUpdaterRunning=false;}};})(jQuery);(function($){$.waterfall=function(){var steps=[],dfrd=$.Deferred(),pointer=0;$.each(arguments,function(i,a){steps.push(function(){var args=[].slice.apply(arguments),d;if(typeof(a)=='function'){if(!((d=a.apply(null,args))&&d.promise)){d=$.Deferred()[d===false?'reject':'resolve'](d);}}else if(a&&a.promise){d=a;}else{d=$.Deferred()[a===false?'reject':'resolve'](a);}d.fail(function(){dfrd.reject.apply(dfrd,[].slice.apply(arguments));}).done(function(data){pointer++;args.push(data);pointer==steps.length?dfrd.resolve.apply(dfrd,args):steps[pointer].apply(null,args);});});});steps.length?steps[0]():dfrd.resolve();return dfrd;}})(jQuery);(function(factory){if(typeof define==='function'&&define.amd){define(['jquery'],factory);}else if(typeof exports==='object'){
|
||||
factory(require('jquery'));}else{factory(jQuery);}}(function($){var pluses=/\+/g;function encode(s){return config.raw?s:encodeURIComponent(s);}function decode(s){return config.raw?s:decodeURIComponent(s);}function stringifyCookieValue(value){return encode(config.json?JSON.stringify(value):String(value));}function parseCookieValue(s){if(s.indexOf('"')===0){s=s.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,'\\');}try{s=decodeURIComponent(s.replace(pluses,' '));return config.json?JSON.parse(s):s;}catch(e){}}function read(s,converter){var value=config.raw?s:parseCookieValue(s);return $.isFunction(converter)?converter(value):value;}var config=$.cookie=function(key,value,options){if(arguments.length>1&&!$.isFunction(value)){options=$.extend({},config.defaults,options);if(typeof options.expires==='number'){var days=options.expires,t=options.expires=new Date();t.setTime(+t+days*864e+5);}return(document.cookie=[encode(key),'=',stringifyCookieValue(value),options.expires?'; expires='+options.expires.toUTCString():'',
|
||||
options.path?'; path='+options.path:'',options.domain?'; domain='+options.domain:'',options.secure?'; secure':''].join(''));}var result=key?undefined:{};var cookies=document.cookie?document.cookie.split('; '):[];for(var i=0,l=cookies.length;i<l;i++){var parts=cookies[i].split('=');var name=decode(parts.shift());var cookie=parts.join('=');if(key&&key===name){result=read(cookie,value);break;}if(!key&&(cookie=read(cookie))!==undefined){result[name]=cookie;}}return result;};config.defaults={};$.removeCookie=function(key,options){if($.cookie(key)===undefined){return false;}$.cookie(key,'',$.extend({},options,{expires:-1}));return!$.cookie(key);};}));"use strict";var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};}();
|
||||
function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call&&(typeof call==="object"||typeof call==="function")?call:self;}function _inherits(subClass,superClass){if(typeof superClass!=="function"&&superClass!==null){throw new TypeError("Super expression must either be null or a function, not "+typeof superClass);}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass;}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}var Emitter=function(){function Emitter(){_classCallCheck(this,Emitter);}_createClass(Emitter,[{key:"on",value:function on(event,fn){this._callbacks=this._callbacks||{};if(!this._callbacks[event]){
|
||||
this._callbacks[event]=[];}this._callbacks[event].push(fn);return this;}},{key:"emit",value:function emit(event){this._callbacks=this._callbacks||{};var callbacks=this._callbacks[event];if(callbacks){for(var _len=arguments.length,args=Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}for(var _iterator=callbacks,_isArray=true,_i=0,_iterator=_isArray?_iterator:_iterator[Symbol.iterator]();;){var _ref;if(_isArray){if(_i>=_iterator.length)break;_ref=_iterator[_i++];}else{_i=_iterator.next();if(_i.done)break;_ref=_i.value;}var callback=_ref;callback.apply(this,args);}}return this;}},{key:"off",value:function off(event,fn){if(!this._callbacks||arguments.length===0){this._callbacks={};return this;}var callbacks=this._callbacks[event];if(!callbacks){return this;}if(arguments.length===1){delete this._callbacks[event];return this;}for(var i=0;i<callbacks.length;i++){var callback=callbacks[i];if(callback===fn){callbacks.splice(i,1);break;}}return this;}}]);return Emitter;
|
||||
}();var Dropzone=function(_Emitter){_inherits(Dropzone,_Emitter);_createClass(Dropzone,null,[{key:"initClass",value:function initClass(){this.prototype.Emitter=Emitter;this.prototype.events=["drop","dragstart","dragend","dragenter","dragover","dragleave","addedfile","addedfiles","removedfile","thumbnail","error","errormultiple","processing","processingmultiple","uploadprogress","totaluploadprogress","sending","sendingmultiple","success","successmultiple","canceled","canceledmultiple","complete","completemultiple","reset","maxfilesexceeded","maxfilesreached","queuecomplete"];this.prototype.defaultOptions={url:null,method:"post",withCredentials:false,timeout:30000,parallelUploads:2,uploadMultiple:false,chunking:false,forceChunking:false,chunkSize:2000000,parallelChunkUploads:false,retryChunks:false,retryChunksLimit:3,maxFilesize:256,paramName:"file",createImageThumbnails:true,maxThumbnailFilesize:10,thumbnailWidth:120,thumbnailHeight:120,thumbnailMethod:'crop',resizeWidth:null,
|
||||
resizeHeight:null,resizeMimeType:null,resizeQuality:0.8,resizeMethod:'contain',filesizeBase:1000,maxFiles:null,headers:null,clickable:true,ignoreHiddenFiles:true,acceptedFiles:null,acceptedMimeTypes:null,autoProcessQueue:true,autoQueue:true,addRemoveLinks:false,previewsContainer:null,hiddenInputContainer:"body",capture:null,renameFilename:null,renameFile:null,forceFallback:false,dictDefaultMessage:"Drop files here to upload",dictFallbackMessage:"Your browser does not support drag'n'drop file uploads.",dictFallbackText:"Please use the fallback form below to upload your files like in the olden days.",dictFileTooBig:"File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",dictInvalidFileType:"You can't upload files of this type.",dictResponseError:"Server responded with {{statusCode}} code.",dictCancelUpload:"Cancel upload",dictUploadCanceled:"Upload canceled.",dictCancelUploadConfirmation:"Are you sure you want to cancel this upload?",dictRemoveFile:"Remove file",
|
||||
dictRemoveFileConfirmation:null,dictMaxFilesExceeded:"You can not upload any more files.",dictFileSizeUnits:{tb:"TB",gb:"GB",mb:"MB",kb:"KB",b:"b"},init:function init(){},params:function params(files,xhr,chunk){if(chunk){return{dzuuid:chunk.file.upload.uuid,dzchunkindex:chunk.index,dztotalfilesize:chunk.file.size,dzchunksize:this.options.chunkSize,dztotalchunkcount:chunk.file.upload.totalChunkCount,dzchunkbyteoffset:chunk.index*this.options.chunkSize};}},accept:function accept(file,done){return done();},chunksUploaded:function chunksUploaded(file,done){done();},fallback:function fallback(){var messageElement=void 0;this.element.className=this.element.className+" dz-browser-not-supported";for(var _iterator2=this.element.getElementsByTagName("div"),_isArray2=true,_i2=0,_iterator2=_isArray2?_iterator2:_iterator2[Symbol.iterator]();;){var _ref2;if(_isArray2){if(_i2>=_iterator2.length)break;_ref2=_iterator2[_i2++];}else{_i2=_iterator2.next();if(_i2.done)break;_ref2=_i2.value;}var child=_ref2;
|
||||
if(/(^| )dz-message($| )/.test(child.className)){messageElement=child;child.className="dz-message";break;}}if(!messageElement){messageElement=Dropzone.createElement("<div class=\"dz-message\"><span></span></div>");this.element.appendChild(messageElement);}var span=messageElement.getElementsByTagName("span")[0];if(span){if(span.textContent!=null){span.textContent=this.options.dictFallbackMessage;}else if(span.innerText!=null){span.innerText=this.options.dictFallbackMessage;}}return this.element.appendChild(this.getFallbackForm());},resize:function resize(file,width,height,resizeMethod){var info={srcX:0,srcY:0,srcWidth:file.width,srcHeight:file.height};var srcRatio=file.width/file.height;if(width==null&&height==null){width=info.srcWidth;height=info.srcHeight;}else if(width==null){width=height*srcRatio;}else if(height==null){height=width/srcRatio;}width=Math.min(width,info.srcWidth);height=Math.min(height,info.srcHeight);var trgRatio=width/height;if(info.srcWidth>width||info.srcHeight>height){
|
||||
if(resizeMethod==='crop'){if(srcRatio>trgRatio){info.srcHeight=file.height;info.srcWidth=info.srcHeight*trgRatio;}else{info.srcWidth=file.width;info.srcHeight=info.srcWidth/trgRatio;}}else if(resizeMethod==='contain'){if(srcRatio>trgRatio){height=width/srcRatio;}else{width=height*srcRatio;}}else{throw new Error("Unknown resizeMethod '"+resizeMethod+"'");}}info.srcX=(file.width-info.srcWidth)/2;info.srcY=(file.height-info.srcHeight)/2;info.trgWidth=width;info.trgHeight=height;return info;},transformFile:function transformFile(file,done){if((this.options.resizeWidth||this.options.resizeHeight)&&file.type.match(/image.*/)){return this.resizeImage(file,this.options.resizeWidth,this.options.resizeHeight,this.options.resizeMethod,done);}else{return done(file);}},previewTemplate:"<div class=\"dz-preview dz-file-preview\">\n <div class=\"dz-image\"><img data-dz-thumbnail /></div>\n <div class=\"dz-details\">\n <div class=\"dz-size\"><span data-dz-size></span></div>\n <div class=\"dz-filename\"><span data-dz-name></span></div>\n </div>\n <div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress></span></div>\n <div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n <div class=\"dz-success-mark\">\n <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n <title>Check</title>\n <defs></defs>\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n <path d=\"M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" stroke-opacity=\"0.198794158\" stroke=\"#747474\" fill-opacity=\"0.816519475\" fill=\"#FFFFFF\" sketch:type=\"MSShapeGroup\"></path>\n </g>\n </svg>\n </div>\n <div class=\"dz-error-mark\">\n <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n <title>Error</title>\n <defs></defs>\n <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n <g id=\"Check-+-Oval-2\" sketch:type=\"MSLayerGroup\" stroke=\"#747474\" stroke-opacity=\"0.198794158\" fill=\"#FFFFFF\" fill-opacity=\"0.816519475\">\n <path d=\"M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" sketch:type=\"MSShapeGroup\"></path>\n </g>\n </g>\n </svg>\n </div>\n</div>",
|
||||
drop:function drop(e){return this.element.classList.remove("dz-drag-hover");},dragstart:function dragstart(e){},dragend:function dragend(e){return this.element.classList.remove("dz-drag-hover");},dragenter:function dragenter(e){return this.element.classList.add("dz-drag-hover");},dragover:function dragover(e){return this.element.classList.add("dz-drag-hover");},dragleave:function dragleave(e){return this.element.classList.remove("dz-drag-hover");},paste:function paste(e){},reset:function reset(){return this.element.classList.remove("dz-started");},addedfile:function addedfile(file){var _this2=this;if(this.element===this.previewsContainer){this.element.classList.add("dz-started");}if(this.previewsContainer){file.previewElement=Dropzone.createElement(this.options.previewTemplate.trim());file.previewTemplate=file.previewElement;this.previewsContainer.appendChild(file.previewElement);for(var _iterator3=file.previewElement.querySelectorAll("[data-dz-name]"),_isArray3=true,_i3=0,_iterator3=_isArray3?_iterator3:_iterator3[Symbol.iterator]();;){
|
||||
var _ref3;if(_isArray3){if(_i3>=_iterator3.length)break;_ref3=_iterator3[_i3++];}else{_i3=_iterator3.next();if(_i3.done)break;_ref3=_i3.value;}var node=_ref3;node.textContent=file.name;}for(var _iterator4=file.previewElement.querySelectorAll("[data-dz-size]"),_isArray4=true,_i4=0,_iterator4=_isArray4?_iterator4:_iterator4[Symbol.iterator]();;){if(_isArray4){if(_i4>=_iterator4.length)break;node=_iterator4[_i4++];}else{_i4=_iterator4.next();if(_i4.done)break;node=_i4.value;}node.innerHTML=this.filesize(file.size);}if(this.options.addRemoveLinks){file._removeLink=Dropzone.createElement("<a class=\"dz-remove\" href=\"javascript:undefined;\" data-dz-remove>"+this.options.dictRemoveFile+"</a>");file.previewElement.appendChild(file._removeLink);}var removeFileEvent=function removeFileEvent(e){e.preventDefault();e.stopPropagation();if(file.status===Dropzone.UPLOADING){return Dropzone.confirm(_this2.options.dictCancelUploadConfirmation,function(){return _this2.removeFile(file);});}else{if(_this2.options.dictRemoveFileConfirmation){
|
||||
return Dropzone.confirm(_this2.options.dictRemoveFileConfirmation,function(){return _this2.removeFile(file);});}else{return _this2.removeFile(file);}}};for(var _iterator5=file.previewElement.querySelectorAll("[data-dz-remove]"),_isArray5=true,_i5=0,_iterator5=_isArray5?_iterator5:_iterator5[Symbol.iterator]();;){var _ref4;if(_isArray5){if(_i5>=_iterator5.length)break;_ref4=_iterator5[_i5++];}else{_i5=_iterator5.next();if(_i5.done)break;_ref4=_i5.value;}var removeLink=_ref4;removeLink.addEventListener("click",removeFileEvent);}}},removedfile:function removedfile(file){if(file.previewElement!=null&&file.previewElement.parentNode!=null){file.previewElement.parentNode.removeChild(file.previewElement);}return this._updateMaxFilesReachedClass();},thumbnail:function thumbnail(file,dataUrl){if(file.previewElement){file.previewElement.classList.remove("dz-file-preview");for(var _iterator6=file.previewElement.querySelectorAll("[data-dz-thumbnail]"),_isArray6=true,_i6=0,_iterator6=_isArray6?_iterator6:_iterator6[Symbol.iterator]();;){
|
||||
var _ref5;if(_isArray6){if(_i6>=_iterator6.length)break;_ref5=_iterator6[_i6++];}else{_i6=_iterator6.next();if(_i6.done)break;_ref5=_i6.value;}var thumbnailElement=_ref5;thumbnailElement.alt=file.name;thumbnailElement.src=dataUrl;}return setTimeout(function(){return file.previewElement.classList.add("dz-image-preview");},1);}},error:function error(file,message){if(file.previewElement){file.previewElement.classList.add("dz-error");if(typeof message!=="String"&&message.error){message=message.error;}for(var _iterator7=file.previewElement.querySelectorAll("[data-dz-errormessage]"),_isArray7=true,_i7=0,_iterator7=_isArray7?_iterator7:_iterator7[Symbol.iterator]();;){var _ref6;if(_isArray7){if(_i7>=_iterator7.length)break;_ref6=_iterator7[_i7++];}else{_i7=_iterator7.next();if(_i7.done)break;_ref6=_i7.value;}var node=_ref6;node.textContent=message;}}},errormultiple:function errormultiple(){},processing:function processing(file){if(file.previewElement){file.previewElement.classList.add("dz-processing");
|
||||
if(file._removeLink){return file._removeLink.innerHTML=this.options.dictCancelUpload;}}},processingmultiple:function processingmultiple(){},uploadprogress:function uploadprogress(file,progress,bytesSent){if(file.previewElement){for(var _iterator8=file.previewElement.querySelectorAll("[data-dz-uploadprogress]"),_isArray8=true,_i8=0,_iterator8=_isArray8?_iterator8:_iterator8[Symbol.iterator]();;){var _ref7;if(_isArray8){if(_i8>=_iterator8.length)break;_ref7=_iterator8[_i8++];}else{_i8=_iterator8.next();if(_i8.done)break;_ref7=_i8.value;}var node=_ref7;node.nodeName==='PROGRESS'?node.value=progress:node.style.width=progress+"%";}}},totaluploadprogress:function totaluploadprogress(){},sending:function sending(){},sendingmultiple:function sendingmultiple(){},success:function success(file){if(file.previewElement){return file.previewElement.classList.add("dz-success");}},successmultiple:function successmultiple(){},canceled:function canceled(file){return this.emit("error",file,this.options.dictUploadCanceled);
|
||||
},canceledmultiple:function canceledmultiple(){},complete:function complete(file){if(file._removeLink){file._removeLink.innerHTML=this.options.dictRemoveFile;}if(file.previewElement){return file.previewElement.classList.add("dz-complete");}},completemultiple:function completemultiple(){},maxfilesexceeded:function maxfilesexceeded(){},maxfilesreached:function maxfilesreached(){},queuecomplete:function queuecomplete(){},addedfiles:function addedfiles(){}};this.prototype._thumbnailQueue=[];this.prototype._processingThumbnail=false;}},{key:"extend",value:function extend(target){for(var _len2=arguments.length,objects=Array(_len2>1?_len2-1:0),_key2=1;_key2<_len2;_key2++){objects[_key2-1]=arguments[_key2];}for(var _iterator9=objects,_isArray9=true,_i9=0,_iterator9=_isArray9?_iterator9:_iterator9[Symbol.iterator]();;){var _ref8;if(_isArray9){if(_i9>=_iterator9.length)break;_ref8=_iterator9[_i9++];}else{_i9=_iterator9.next();if(_i9.done)break;_ref8=_i9.value;}var object=_ref8;for(var key in object){
|
||||
var val=object[key];target[key]=val;}}return target;}}]);function Dropzone(el,options){_classCallCheck(this,Dropzone);var _this=_possibleConstructorReturn(this,(Dropzone.__proto__||Object.getPrototypeOf(Dropzone)).call(this));var fallback=void 0,left=void 0;_this.element=el;_this.version=Dropzone.version;_this.defaultOptions.previewTemplate=_this.defaultOptions.previewTemplate.replace(/\n*/g,"");_this.clickableElements=[];_this.listeners=[];_this.files=[];if(typeof _this.element==="string"){_this.element=document.querySelector(_this.element);}if(!_this.element||_this.element.nodeType==null){throw new Error("Invalid dropzone element.");}if(_this.element.dropzone){throw new Error("Dropzone already attached.");}Dropzone.instances.push(_this);_this.element.dropzone=_this;var elementOptions=(left=Dropzone.optionsForElement(_this.element))!=null?left:{};_this.options=Dropzone.extend({},_this.defaultOptions,elementOptions,options!=null?options:{});if(_this.options.forceFallback||!Dropzone.isBrowserSupported()){
|
||||
var _ret;return _ret=_this.options.fallback.call(_this),_possibleConstructorReturn(_this,_ret);}if(_this.options.url==null){_this.options.url=_this.element.getAttribute("action");}if(!_this.options.url){throw new Error("No URL provided.");}if(_this.options.acceptedFiles&&_this.options.acceptedMimeTypes){throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");}if(_this.options.uploadMultiple&&_this.options.chunking){throw new Error('You cannot set both: uploadMultiple and chunking.');}if(_this.options.acceptedMimeTypes){_this.options.acceptedFiles=_this.options.acceptedMimeTypes;delete _this.options.acceptedMimeTypes;}if(_this.options.renameFilename!=null){_this.options.renameFile=function(file){return _this.options.renameFilename.call(_this,file.name,file);};}_this.options.method=_this.options.method.toUpperCase();if((fallback=_this.getExistingFallback())&&fallback.parentNode){fallback.parentNode.removeChild(fallback);}if(_this.options.previewsContainer!==false){
|
||||
if(_this.options.previewsContainer){_this.previewsContainer=Dropzone.getElement(_this.options.previewsContainer,"previewsContainer");}else{_this.previewsContainer=_this.element;}}if(_this.options.clickable){if(_this.options.clickable===true){_this.clickableElements=[_this.element];}else{_this.clickableElements=Dropzone.getElements(_this.options.clickable,"clickable");}}_this.init();return _this;}_createClass(Dropzone,[{key:"getAcceptedFiles",value:function getAcceptedFiles(){return this.files.filter(function(file){return file.accepted;}).map(function(file){return file;});}},{key:"getRejectedFiles",value:function getRejectedFiles(){return this.files.filter(function(file){return!file.accepted;}).map(function(file){return file;});}},{key:"getFilesWithStatus",value:function getFilesWithStatus(status){return this.files.filter(function(file){return file.status===status;}).map(function(file){return file;});}},{key:"getQueuedFiles",value:function getQueuedFiles(){return this.getFilesWithStatus(Dropzone.QUEUED);
|
||||
}},{key:"getUploadingFiles",value:function getUploadingFiles(){return this.getFilesWithStatus(Dropzone.UPLOADING);}},{key:"getAddedFiles",value:function getAddedFiles(){return this.getFilesWithStatus(Dropzone.ADDED);}},{key:"getActiveFiles",value:function getActiveFiles(){return this.files.filter(function(file){return file.status===Dropzone.UPLOADING||file.status===Dropzone.QUEUED;}).map(function(file){return file;});}},{key:"init",value:function init(){var _this3=this;if(this.element.tagName==="form"){this.element.setAttribute("enctype","multipart/form-data");}if(this.element.classList.contains("dropzone")&&!this.element.querySelector(".dz-message")){this.element.appendChild(Dropzone.createElement("<div class=\"dz-default dz-message\"><span>"+this.options.dictDefaultMessage+"</span></div>"));}if(this.clickableElements.length){var setupHiddenFileInput=function setupHiddenFileInput(){if(_this3.hiddenFileInput){_this3.hiddenFileInput.parentNode.removeChild(_this3.hiddenFileInput);}_this3.hiddenFileInput=document.createElement("input");
|
||||
_this3.hiddenFileInput.setAttribute("type","file");if(_this3.options.maxFiles===null||_this3.options.maxFiles>1){_this3.hiddenFileInput.setAttribute("multiple","multiple");}_this3.hiddenFileInput.className="dz-hidden-input";if(_this3.options.acceptedFiles!==null){_this3.hiddenFileInput.setAttribute("accept",_this3.options.acceptedFiles);}if(_this3.options.capture!==null){_this3.hiddenFileInput.setAttribute("capture",_this3.options.capture);}_this3.hiddenFileInput.style.visibility="hidden";_this3.hiddenFileInput.style.position="absolute";_this3.hiddenFileInput.style.top="0";_this3.hiddenFileInput.style.left="0";_this3.hiddenFileInput.style.height="0";_this3.hiddenFileInput.style.width="0";Dropzone.getElement(_this3.options.hiddenInputContainer,'hiddenInputContainer').appendChild(_this3.hiddenFileInput);return _this3.hiddenFileInput.addEventListener("change",function(){var files=_this3.hiddenFileInput.files;if(files.length){for(var _iterator10=files,_isArray10=true,_i10=0,_iterator10=_isArray10?_iterator10:_iterator10[Symbol.iterator]();;){
|
||||
var _ref9;if(_isArray10){if(_i10>=_iterator10.length)break;_ref9=_iterator10[_i10++];}else{_i10=_iterator10.next();if(_i10.done)break;_ref9=_i10.value;}var file=_ref9;_this3.addFile(file);}}_this3.emit("addedfiles",files);return setupHiddenFileInput();});};setupHiddenFileInput();}this.URL=window.URL!==null?window.URL:window.webkitURL;for(var _iterator11=this.events,_isArray11=true,_i11=0,_iterator11=_isArray11?_iterator11:_iterator11[Symbol.iterator]();;){var _ref10;if(_isArray11){if(_i11>=_iterator11.length)break;_ref10=_iterator11[_i11++];}else{_i11=_iterator11.next();if(_i11.done)break;_ref10=_i11.value;}var eventName=_ref10;this.on(eventName,this.options[eventName]);}this.on("uploadprogress",function(){return _this3.updateTotalUploadProgress();});this.on("removedfile",function(){return _this3.updateTotalUploadProgress();});this.on("canceled",function(file){return _this3.emit("complete",file);});this.on("complete",function(file){if(_this3.getAddedFiles().length===0&&_this3.getUploadingFiles().length===0&&_this3.getQueuedFiles().length===0){
|
||||
return setTimeout(function(){return _this3.emit("queuecomplete");},0);}});var noPropagation=function noPropagation(e){e.stopPropagation();if(e.preventDefault){return e.preventDefault();}else{return e.returnValue=false;}};this.listeners=[{element:this.element,events:{"dragstart":function dragstart(e){return _this3.emit("dragstart",e);},"dragenter":function dragenter(e){noPropagation(e);return _this3.emit("dragenter",e);},"dragover":function dragover(e){var efct=void 0;try{efct=e.dataTransfer.effectAllowed;}catch(error){}e.dataTransfer.dropEffect='move'===efct||'linkMove'===efct?'move':'copy';noPropagation(e);return _this3.emit("dragover",e);},"dragleave":function dragleave(e){return _this3.emit("dragleave",e);},"drop":function drop(e){noPropagation(e);return _this3.drop(e);},"dragend":function dragend(e){return _this3.emit("dragend",e);}}}];this.clickableElements.forEach(function(clickableElement){return _this3.listeners.push({element:clickableElement,events:{"click":function click(evt){
|
||||
if(clickableElement!==_this3.element||evt.target===_this3.element||Dropzone.elementInside(evt.target,_this3.element.querySelector(".dz-message"))){_this3.hiddenFileInput.click();}return true;}}});});this.enable();return this.options.init.call(this);}},{key:"destroy",value:function destroy(){this.disable();this.removeAllFiles(true);if(this.hiddenFileInput!=null?this.hiddenFileInput.parentNode:undefined){this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);this.hiddenFileInput=null;}delete this.element.dropzone;return Dropzone.instances.splice(Dropzone.instances.indexOf(this),1);}},{key:"updateTotalUploadProgress",value:function updateTotalUploadProgress(){var totalUploadProgress=void 0;var totalBytesSent=0;var totalBytes=0;var activeFiles=this.getActiveFiles();if(activeFiles.length){for(var _iterator12=this.getActiveFiles(),_isArray12=true,_i12=0,_iterator12=_isArray12?_iterator12:_iterator12[Symbol.iterator]();;){var _ref11;if(_isArray12){if(_i12>=_iterator12.length)break;
|
||||
_ref11=_iterator12[_i12++];}else{_i12=_iterator12.next();if(_i12.done)break;_ref11=_i12.value;}var file=_ref11;totalBytesSent+=file.upload.bytesSent;totalBytes+=file.upload.total;}totalUploadProgress=100*totalBytesSent/totalBytes;}else{totalUploadProgress=100;}return this.emit("totaluploadprogress",totalUploadProgress,totalBytes,totalBytesSent);}},{key:"_getParamName",value:function _getParamName(n){if(typeof this.options.paramName==="function"){return this.options.paramName(n);}else{return""+this.options.paramName+(this.options.uploadMultiple?"["+n+"]":"");}}},{key:"_renameFile",value:function _renameFile(file){if(typeof this.options.renameFile!=="function"){return file.name;}return this.options.renameFile(file);}},{key:"getFallbackForm",value:function getFallbackForm(){var existingFallback=void 0,form=void 0;if(existingFallback=this.getExistingFallback()){return existingFallback;}var fieldsString="<div class=\"dz-fallback\">";if(this.options.dictFallbackText){fieldsString+="<p>"+this.options.dictFallbackText+"</p>";
|
||||
}fieldsString+="<input type=\"file\" name=\""+this._getParamName(0)+"\" "+(this.options.uploadMultiple?'multiple="multiple"':undefined)+" /><input type=\"submit\" value=\"Upload!\"></div>";var fields=Dropzone.createElement(fieldsString);if(this.element.tagName!=="FORM"){form=Dropzone.createElement("<form action=\""+this.options.url+"\" enctype=\"multipart/form-data\" method=\""+this.options.method+"\"></form>");form.appendChild(fields);}else{this.element.setAttribute("enctype","multipart/form-data");this.element.setAttribute("method",this.options.method);}return form!=null?form:fields;}},{key:"getExistingFallback",value:function getExistingFallback(){var getFallback=function getFallback(elements){for(var _iterator13=elements,_isArray13=true,_i13=0,_iterator13=_isArray13?_iterator13:_iterator13[Symbol.iterator]();;){var _ref12;if(_isArray13){if(_i13>=_iterator13.length)break;_ref12=_iterator13[_i13++];}else{_i13=_iterator13.next();if(_i13.done)break;_ref12=_i13.value;}var el=_ref12;if(/(^| )fallback($| )/.test(el.className)){
|
||||
return el;}}};var _arr=["div","form"];for(var _i14=0;_i14<_arr.length;_i14++){var tagName=_arr[_i14];var fallback;if(fallback=getFallback(this.element.getElementsByTagName(tagName))){return fallback;}}}},{key:"setupEventListeners",value:function setupEventListeners(){return this.listeners.map(function(elementListeners){return function(){var result=[];for(var event in elementListeners.events){var listener=elementListeners.events[event];result.push(elementListeners.element.addEventListener(event,listener,false));}return result;}();});}},{key:"removeEventListeners",value:function removeEventListeners(){return this.listeners.map(function(elementListeners){return function(){var result=[];for(var event in elementListeners.events){var listener=elementListeners.events[event];result.push(elementListeners.element.removeEventListener(event,listener,false));}return result;}();});}},{key:"disable",value:function disable(){var _this4=this;this.clickableElements.forEach(function(element){return element.classList.remove("dz-clickable");
|
||||
});this.removeEventListeners();this.disabled=true;return this.files.map(function(file){return _this4.cancelUpload(file);});}},{key:"enable",value:function enable(){delete this.disabled;this.clickableElements.forEach(function(element){return element.classList.add("dz-clickable");});return this.setupEventListeners();}},{key:"filesize",value:function filesize(size){var selectedSize=0;var selectedUnit="b";if(size>0){var units=['tb','gb','mb','kb','b'];for(var i=0;i<units.length;i++){var unit=units[i];var cutoff=Math.pow(this.options.filesizeBase,4-i)/10;if(size>=cutoff){selectedSize=size/Math.pow(this.options.filesizeBase,4-i);selectedUnit=unit;break;}}selectedSize=Math.round(10*selectedSize)/10;}return"<strong>"+selectedSize+"</strong> "+this.options.dictFileSizeUnits[selectedUnit];}},{key:"_updateMaxFilesReachedClass",value:function _updateMaxFilesReachedClass(){if(this.options.maxFiles!=null&&this.getAcceptedFiles().length>=this.options.maxFiles){if(this.getAcceptedFiles().length===this.options.maxFiles){
|
||||
this.emit('maxfilesreached',this.files);}return this.element.classList.add("dz-max-files-reached");}else{return this.element.classList.remove("dz-max-files-reached");}}},{key:"drop",value:function drop(e){if(!e.dataTransfer){return;}this.emit("drop",e);var files=[];for(var i=0;i<e.dataTransfer.files.length;i++){files[i]=e.dataTransfer.files[i];}this.emit("addedfiles",files);if(files.length){var items=e.dataTransfer.items;if(items&&items.length&&items[0].webkitGetAsEntry!=null){this._addFilesFromItems(items);}else{this.handleFiles(files);}}}},{key:"paste",value:function paste(e){if(__guard__(e!=null?e.clipboardData:undefined,function(x){return x.items;})==null){return;}this.emit("paste",e);var items=e.clipboardData.items;if(items.length){return this._addFilesFromItems(items);}}},{key:"handleFiles",value:function handleFiles(files){for(var _iterator14=files,_isArray14=true,_i15=0,_iterator14=_isArray14?_iterator14:_iterator14[Symbol.iterator]();;){var _ref13;if(_isArray14){if(_i15>=_iterator14.length)break;
|
||||
_ref13=_iterator14[_i15++];}else{_i15=_iterator14.next();if(_i15.done)break;_ref13=_i15.value;}var file=_ref13;this.addFile(file);}}},{key:"_addFilesFromItems",value:function _addFilesFromItems(items){var _this5=this;return function(){var result=[];for(var _iterator15=items,_isArray15=true,_i16=0,_iterator15=_isArray15?_iterator15:_iterator15[Symbol.iterator]();;){var _ref14;if(_isArray15){if(_i16>=_iterator15.length)break;_ref14=_iterator15[_i16++];}else{_i16=_iterator15.next();if(_i16.done)break;_ref14=_i16.value;}var item=_ref14;var entry;if(item.webkitGetAsEntry!=null&&(entry=item.webkitGetAsEntry())){if(entry.isFile){result.push(_this5.addFile(item.getAsFile()));}else if(entry.isDirectory){result.push(_this5._addFilesFromDirectory(entry,entry.name));}else{result.push(undefined);}}else if(item.getAsFile!=null){if(item.kind==null||item.kind==="file"){result.push(_this5.addFile(item.getAsFile()));}else{result.push(undefined);}}else{result.push(undefined);}}return result;}();}},{key:"_addFilesFromDirectory",
|
||||
value:function _addFilesFromDirectory(directory,path){var _this6=this;var dirReader=directory.createReader();var errorHandler=function errorHandler(error){return __guardMethod__(console,'log',function(o){return o.log(error);});};var readEntries=function readEntries(){return dirReader.readEntries(function(entries){if(entries.length>0){for(var _iterator16=entries,_isArray16=true,_i17=0,_iterator16=_isArray16?_iterator16:_iterator16[Symbol.iterator]();;){var _ref15;if(_isArray16){if(_i17>=_iterator16.length)break;_ref15=_iterator16[_i17++];}else{_i17=_iterator16.next();if(_i17.done)break;_ref15=_i17.value;}var entry=_ref15;if(entry.isFile){entry.file(function(file){if(_this6.options.ignoreHiddenFiles&&file.name.substring(0,1)==='.'){return;}file.fullPath=path+"/"+file.name;return _this6.addFile(file);});}else if(entry.isDirectory){_this6._addFilesFromDirectory(entry,path+"/"+entry.name);}}readEntries();}return null;},errorHandler);};return readEntries();}},{key:"accept",value:function accept(file,done){
|
||||
if(this.options.maxFilesize&&file.size>this.options.maxFilesize*1024*1024){return done(this.options.dictFileTooBig.replace("{{filesize}}",Math.round(file.size/1024/10.24)/100).replace("{{maxFilesize}}",this.options.maxFilesize));}else if(!Dropzone.isValidFile(file,this.options.acceptedFiles)){return done(this.options.dictInvalidFileType);}else if(this.options.maxFiles!=null&&this.getAcceptedFiles().length>=this.options.maxFiles){done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}",this.options.maxFiles));return this.emit("maxfilesexceeded",file);}else{return this.options.accept.call(this,file,done);}}},{key:"addFile",value:function addFile(file){var _this7=this;file.upload={uuid:Dropzone.uuidv4(),progress:0,total:file.size,bytesSent:0,filename:this._renameFile(file),chunked:this.options.chunking&&(this.options.forceChunking||file.size>this.options.chunkSize),totalChunkCount:Math.ceil(file.size/this.options.chunkSize)};this.files.push(file);file.status=Dropzone.ADDED;this.emit("addedfile",file);
|
||||
this._enqueueThumbnail(file);return this.accept(file,function(error){if(error){file.accepted=false;_this7._errorProcessing([file],error);}else{file.accepted=true;if(_this7.options.autoQueue){_this7.enqueueFile(file);}}return _this7._updateMaxFilesReachedClass();});}},{key:"enqueueFiles",value:function enqueueFiles(files){for(var _iterator17=files,_isArray17=true,_i18=0,_iterator17=_isArray17?_iterator17:_iterator17[Symbol.iterator]();;){var _ref16;if(_isArray17){if(_i18>=_iterator17.length)break;_ref16=_iterator17[_i18++];}else{_i18=_iterator17.next();if(_i18.done)break;_ref16=_i18.value;}var file=_ref16;this.enqueueFile(file);}return null;}},{key:"enqueueFile",value:function enqueueFile(file){var _this8=this;if(file.status===Dropzone.ADDED&&file.accepted===true){file.status=Dropzone.QUEUED;if(this.options.autoProcessQueue){return setTimeout(function(){return _this8.processQueue();},0);}}else{throw new Error("This file can't be queued because it has already been processed or was rejected.");
|
||||
}}},{key:"_enqueueThumbnail",value:function _enqueueThumbnail(file){var _this9=this;if(this.options.createImageThumbnails&&file.type.match(/image.*/)&&file.size<=this.options.maxThumbnailFilesize*1024*1024){this._thumbnailQueue.push(file);return setTimeout(function(){return _this9._processThumbnailQueue();},0);}}},{key:"_processThumbnailQueue",value:function _processThumbnailQueue(){var _this10=this;if(this._processingThumbnail||this._thumbnailQueue.length===0){return;}this._processingThumbnail=true;var file=this._thumbnailQueue.shift();return this.createThumbnail(file,this.options.thumbnailWidth,this.options.thumbnailHeight,this.options.thumbnailMethod,true,function(dataUrl){_this10.emit("thumbnail",file,dataUrl);_this10._processingThumbnail=false;return _this10._processThumbnailQueue();});}},{key:"removeFile",value:function removeFile(file){if(file.status===Dropzone.UPLOADING){this.cancelUpload(file);}this.files=without(this.files,file);this.emit("removedfile",file);if(this.files.length===0){
|
||||
return this.emit("reset");}}},{key:"removeAllFiles",value:function removeAllFiles(cancelIfNecessary){if(cancelIfNecessary==null){cancelIfNecessary=false;}for(var _iterator18=this.files.slice(),_isArray18=true,_i19=0,_iterator18=_isArray18?_iterator18:_iterator18[Symbol.iterator]();;){var _ref17;if(_isArray18){if(_i19>=_iterator18.length)break;_ref17=_iterator18[_i19++];}else{_i19=_iterator18.next();if(_i19.done)break;_ref17=_i19.value;}var file=_ref17;if(file.status!==Dropzone.UPLOADING||cancelIfNecessary){this.removeFile(file);}}return null;}},{key:"resizeImage",value:function resizeImage(file,width,height,resizeMethod,callback){var _this11=this;return this.createThumbnail(file,width,height,resizeMethod,true,function(dataUrl,canvas){if(canvas==null){return callback(file);}else{var resizeMimeType=_this11.options.resizeMimeType;if(resizeMimeType==null){resizeMimeType=file.type;}var resizedDataURL=canvas.toDataURL(resizeMimeType,_this11.options.resizeQuality);if(resizeMimeType==='image/jpeg'||resizeMimeType==='image/jpg'){
|
||||
resizedDataURL=ExifRestore.restore(file.dataURL,resizedDataURL);}return callback(Dropzone.dataURItoBlob(resizedDataURL));}});}},{key:"createThumbnail",value:function createThumbnail(file,width,height,resizeMethod,fixOrientation,callback){var _this12=this;var fileReader=new FileReader();fileReader.onload=function(){file.dataURL=fileReader.result;if(file.type==="image/svg+xml"){if(callback!=null){callback(fileReader.result);}return;}return _this12.createThumbnailFromUrl(file,width,height,resizeMethod,fixOrientation,callback);};return fileReader.readAsDataURL(file);}},{key:"createThumbnailFromUrl",value:function createThumbnailFromUrl(file,width,height,resizeMethod,fixOrientation,callback,crossOrigin){var _this13=this;var img=document.createElement("img");if(crossOrigin){img.crossOrigin=crossOrigin;}img.onload=function(){var loadExif=function loadExif(callback){return callback(1);};if(typeof EXIF!=='undefined'&&EXIF!==null&&fixOrientation){loadExif=function loadExif(callback){return EXIF.getData(img,function(){
|
||||
return callback(EXIF.getTag(this,'Orientation'));});};}return loadExif(function(orientation){file.width=img.width;file.height=img.height;var resizeInfo=_this13.options.resize.call(_this13,file,width,height,resizeMethod);var canvas=document.createElement("canvas");var ctx=canvas.getContext("2d");canvas.width=resizeInfo.trgWidth;canvas.height=resizeInfo.trgHeight;if(orientation>4){canvas.width=resizeInfo.trgHeight;canvas.height=resizeInfo.trgWidth;}switch(orientation){case 2:ctx.translate(canvas.width,0);ctx.scale(-1,1);break;case 3:ctx.translate(canvas.width,canvas.height);ctx.rotate(Math.PI);break;case 4:ctx.translate(0,canvas.height);ctx.scale(1,-1);break;case 5:ctx.rotate(0.5*Math.PI);ctx.scale(1,-1);break;case 6:ctx.rotate(0.5*Math.PI);ctx.translate(0,-canvas.width);break;case 7:ctx.rotate(0.5*Math.PI);ctx.translate(canvas.height,-canvas.width);ctx.scale(-1,1);break;case 8:ctx.rotate(-0.5*Math.PI);ctx.translate(-canvas.height,0);break;}drawImageIOSFix(ctx,img,resizeInfo.srcX!=null?resizeInfo.srcX:0,resizeInfo.srcY!=null?resizeInfo.srcY:0,resizeInfo.srcWidth,resizeInfo.srcHeight,resizeInfo.trgX!=null?resizeInfo.trgX:0,resizeInfo.trgY!=null?resizeInfo.trgY:0,resizeInfo.trgWidth,resizeInfo.trgHeight);
|
||||
var thumbnail=canvas.toDataURL("image/png");if(callback!=null){return callback(thumbnail,canvas);}});};if(callback!=null){img.onerror=callback;}return img.src=file.dataURL;}},{key:"processQueue",value:function processQueue(){var parallelUploads=this.options.parallelUploads;var processingLength=this.getUploadingFiles().length;var i=processingLength;if(processingLength>=parallelUploads){return;}var queuedFiles=this.getQueuedFiles();if(!(queuedFiles.length>0)){return;}if(this.options.uploadMultiple){return this.processFiles(queuedFiles.slice(0,parallelUploads-processingLength));}else{while(i<parallelUploads){if(!queuedFiles.length){return;}this.processFile(queuedFiles.shift());i++;}}}},{key:"processFile",value:function processFile(file){return this.processFiles([file]);}},{key:"processFiles",value:function processFiles(files){for(var _iterator19=files,_isArray19=true,_i20=0,_iterator19=_isArray19?_iterator19:_iterator19[Symbol.iterator]();;){var _ref18;if(_isArray19){if(_i20>=_iterator19.length)break;
|
||||
_ref18=_iterator19[_i20++];}else{_i20=_iterator19.next();if(_i20.done)break;_ref18=_i20.value;}var file=_ref18;file.processing=true;file.status=Dropzone.UPLOADING;this.emit("processing",file);}if(this.options.uploadMultiple){this.emit("processingmultiple",files);}return this.uploadFiles(files);}},{key:"_getFilesWithXhr",value:function _getFilesWithXhr(xhr){var files=void 0;return files=this.files.filter(function(file){return file.xhr===xhr;}).map(function(file){return file;});}},{key:"cancelUpload",value:function cancelUpload(file){if(file.status===Dropzone.UPLOADING){var groupedFiles=this._getFilesWithXhr(file.xhr);for(var _iterator20=groupedFiles,_isArray20=true,_i21=0,_iterator20=_isArray20?_iterator20:_iterator20[Symbol.iterator]();;){var _ref19;if(_isArray20){if(_i21>=_iterator20.length)break;_ref19=_iterator20[_i21++];}else{_i21=_iterator20.next();if(_i21.done)break;_ref19=_i21.value;}var groupedFile=_ref19;groupedFile.status=Dropzone.CANCELED;}if(typeof file.xhr!=='undefined'){
|
||||
file.xhr.abort();}for(var _iterator21=groupedFiles,_isArray21=true,_i22=0,_iterator21=_isArray21?_iterator21:_iterator21[Symbol.iterator]();;){var _ref20;if(_isArray21){if(_i22>=_iterator21.length)break;_ref20=_iterator21[_i22++];}else{_i22=_iterator21.next();if(_i22.done)break;_ref20=_i22.value;}var _groupedFile=_ref20;this.emit("canceled",_groupedFile);}if(this.options.uploadMultiple){this.emit("canceledmultiple",groupedFiles);}}else if(file.status===Dropzone.ADDED||file.status===Dropzone.QUEUED){file.status=Dropzone.CANCELED;this.emit("canceled",file);if(this.options.uploadMultiple){this.emit("canceledmultiple",[file]);}}if(this.options.autoProcessQueue){return this.processQueue();}}},{key:"resolveOption",value:function resolveOption(option){if(typeof option==='function'){for(var _len3=arguments.length,args=Array(_len3>1?_len3-1:0),_key3=1;_key3<_len3;_key3++){args[_key3-1]=arguments[_key3];}return option.apply(this,args);}return option;}},{key:"uploadFile",value:function uploadFile(file){
|
||||
return this.uploadFiles([file]);}},{key:"uploadFiles",value:function uploadFiles(files){var _this14=this;this._transformFiles(files,function(transformedFiles){if(files[0].upload.chunked){var file=files[0];var transformedFile=transformedFiles[0];var startedChunkCount=0;file.upload.chunks=[];var handleNextChunk=function handleNextChunk(){var chunkIndex=0;while(file.upload.chunks[chunkIndex]!==undefined){chunkIndex++;}if(chunkIndex>=file.upload.totalChunkCount)return;startedChunkCount++;var start=chunkIndex*_this14.options.chunkSize;var end=Math.min(start+_this14.options.chunkSize,file.size);var dataBlock={name:_this14._getParamName(0),data:transformedFile.webkitSlice?transformedFile.webkitSlice(start,end):transformedFile.slice(start,end),filename:file.upload.filename,chunkIndex:chunkIndex};file.upload.chunks[chunkIndex]={file:file,index:chunkIndex,dataBlock:dataBlock,status:Dropzone.UPLOADING,progress:0,retries:0};_this14._uploadData(files,[dataBlock]);};file.upload.finishedChunkUpload=function(chunk){
|
||||
var allFinished=true;chunk.status=Dropzone.SUCCESS;chunk.dataBlock=null;chunk.xhr=null;for(var i=0;i<file.upload.totalChunkCount;i++){if(file.upload.chunks[i]===undefined){return handleNextChunk();}if(file.upload.chunks[i].status!==Dropzone.SUCCESS){allFinished=false;}}if(allFinished){_this14.options.chunksUploaded(file,function(){_this14._finished(files,'',null);});}};if(_this14.options.parallelChunkUploads){for(var i=0;i<file.upload.totalChunkCount;i++){handleNextChunk();}}else{handleNextChunk();}}else{var dataBlocks=[];for(var _i23=0;_i23<files.length;_i23++){dataBlocks[_i23]={name:_this14._getParamName(_i23),data:transformedFiles[_i23],filename:files[_i23].upload.filename};}_this14._uploadData(files,dataBlocks);}});}},{key:"_getChunk",value:function _getChunk(file,xhr){for(var i=0;i<file.upload.totalChunkCount;i++){if(file.upload.chunks[i]!==undefined&&file.upload.chunks[i].xhr===xhr){return file.upload.chunks[i];}}}},{key:"_uploadData",value:function _uploadData(files,dataBlocks){
|
||||
var _this15=this;var xhr=new XMLHttpRequest();for(var _iterator22=files,_isArray22=true,_i24=0,_iterator22=_isArray22?_iterator22:_iterator22[Symbol.iterator]();;){var _ref21;if(_isArray22){if(_i24>=_iterator22.length)break;_ref21=_iterator22[_i24++];}else{_i24=_iterator22.next();if(_i24.done)break;_ref21=_i24.value;}var file=_ref21;file.xhr=xhr;}if(files[0].upload.chunked){files[0].upload.chunks[dataBlocks[0].chunkIndex].xhr=xhr;}var method=this.resolveOption(this.options.method,files);var url=this.resolveOption(this.options.url,files);xhr.open(method,url,true);xhr.timeout=this.resolveOption(this.options.timeout,files);xhr.withCredentials=!!this.options.withCredentials;xhr.onload=function(e){_this15._finishedUploading(files,xhr,e);};xhr.onerror=function(){_this15._handleUploadError(files,xhr);};var progressObj=xhr.upload!=null?xhr.upload:xhr;progressObj.onprogress=function(e){return _this15._updateFilesUploadProgress(files,xhr,e);};var headers={"Accept":"application/json",
|
||||
"Cache-Control":"no-cache","X-Requested-With":"XMLHttpRequest"};if(this.options.headers){Dropzone.extend(headers,this.options.headers);}for(var headerName in headers){var headerValue=headers[headerName];if(headerValue){xhr.setRequestHeader(headerName,headerValue);}}var formData=new FormData();if(this.options.params){var additionalParams=this.options.params;if(typeof additionalParams==='function'){additionalParams=additionalParams.call(this,files,xhr,files[0].upload.chunked?this._getChunk(files[0],xhr):null);}for(var key in additionalParams){var value=additionalParams[key];formData.append(key,value);}}for(var _iterator23=files,_isArray23=true,_i25=0,_iterator23=_isArray23?_iterator23:_iterator23[Symbol.iterator]();;){var _ref22;if(_isArray23){if(_i25>=_iterator23.length)break;_ref22=_iterator23[_i25++];}else{_i25=_iterator23.next();if(_i25.done)break;_ref22=_i25.value;}var _file=_ref22;this.emit("sending",_file,xhr,formData);}if(this.options.uploadMultiple){this.emit("sendingmultiple",files,xhr,formData);
|
||||
}this._addFormElementData(formData);for(var i=0;i<dataBlocks.length;i++){var dataBlock=dataBlocks[i];formData.append(dataBlock.name,dataBlock.data,dataBlock.filename);}this.submitRequest(xhr,formData,files);}},{key:"_transformFiles",value:function _transformFiles(files,done){var _this16=this;var transformedFiles=[];var doneCounter=0;var _loop=function _loop(i){_this16.options.transformFile.call(_this16,files[i],function(transformedFile){transformedFiles[i]=transformedFile;if(++doneCounter===files.length){done(transformedFiles);}});};for(var i=0;i<files.length;i++){_loop(i);}}},{key:"_addFormElementData",value:function _addFormElementData(formData){if(this.element.tagName==="FORM"){for(var _iterator24=this.element.querySelectorAll("input, textarea, select, button"),_isArray24=true,_i26=0,_iterator24=_isArray24?_iterator24:_iterator24[Symbol.iterator]();;){var _ref23;if(_isArray24){if(_i26>=_iterator24.length)break;_ref23=_iterator24[_i26++];}else{_i26=_iterator24.next();if(_i26.done)break;
|
||||
_ref23=_i26.value;}var input=_ref23;var inputName=input.getAttribute("name");var inputType=input.getAttribute("type");if(inputType)inputType=inputType.toLowerCase();if(typeof inputName==='undefined'||inputName===null)continue;if(input.tagName==="SELECT"&&input.hasAttribute("multiple")){for(var _iterator25=input.options,_isArray25=true,_i27=0,_iterator25=_isArray25?_iterator25:_iterator25[Symbol.iterator]();;){var _ref24;if(_isArray25){if(_i27>=_iterator25.length)break;_ref24=_iterator25[_i27++];}else{_i27=_iterator25.next();if(_i27.done)break;_ref24=_i27.value;}var option=_ref24;if(option.selected){formData.append(inputName,option.value);}}}else if(!inputType||inputType!=="checkbox"&&inputType!=="radio"||input.checked){formData.append(inputName,input.value);}}}}},{key:"_updateFilesUploadProgress",value:function _updateFilesUploadProgress(files,xhr,e){var progress=void 0;if(typeof e!=='undefined'){progress=100*e.loaded/e.total;if(files[0].upload.chunked){var file=files[0];var chunk=this._getChunk(file,xhr);
|
||||
chunk.progress=progress;chunk.total=e.total;chunk.bytesSent=e.loaded;var fileProgress=0,fileTotal=void 0,fileBytesSent=void 0;file.upload.progress=0;file.upload.total=0;file.upload.bytesSent=0;for(var i=0;i<file.upload.totalChunkCount;i++){if(file.upload.chunks[i]!==undefined&&file.upload.chunks[i].progress!==undefined){file.upload.progress+=file.upload.chunks[i].progress;file.upload.total+=file.upload.chunks[i].total;file.upload.bytesSent+=file.upload.chunks[i].bytesSent;}}file.upload.progress=file.upload.progress/file.upload.totalChunkCount;}else{for(var _iterator26=files,_isArray26=true,_i28=0,_iterator26=_isArray26?_iterator26:_iterator26[Symbol.iterator]();;){var _ref25;if(_isArray26){if(_i28>=_iterator26.length)break;_ref25=_iterator26[_i28++];}else{_i28=_iterator26.next();if(_i28.done)break;_ref25=_i28.value;}var _file2=_ref25;_file2.upload.progress=progress;_file2.upload.total=e.total;_file2.upload.bytesSent=e.loaded;}}for(var _iterator27=files,_isArray27=true,_i29=0,_iterator27=_isArray27?_iterator27:_iterator27[Symbol.iterator]();;){
|
||||
var _ref26;if(_isArray27){if(_i29>=_iterator27.length)break;_ref26=_iterator27[_i29++];}else{_i29=_iterator27.next();if(_i29.done)break;_ref26=_i29.value;}var _file3=_ref26;this.emit("uploadprogress",_file3,_file3.upload.progress,_file3.upload.bytesSent);}}else{var allFilesFinished=true;progress=100;for(var _iterator28=files,_isArray28=true,_i30=0,_iterator28=_isArray28?_iterator28:_iterator28[Symbol.iterator]();;){var _ref27;if(_isArray28){if(_i30>=_iterator28.length)break;_ref27=_iterator28[_i30++];}else{_i30=_iterator28.next();if(_i30.done)break;_ref27=_i30.value;}var _file4=_ref27;if(_file4.upload.progress!==100||_file4.upload.bytesSent!==_file4.upload.total){allFilesFinished=false;}_file4.upload.progress=progress;_file4.upload.bytesSent=_file4.upload.total;}if(allFilesFinished){return;}for(var _iterator29=files,_isArray29=true,_i31=0,_iterator29=_isArray29?_iterator29:_iterator29[Symbol.iterator]();;){var _ref28;if(_isArray29){if(_i31>=_iterator29.length)break;_ref28=_iterator29[_i31++];
|
||||
}else{_i31=_iterator29.next();if(_i31.done)break;_ref28=_i31.value;}var _file5=_ref28;this.emit("uploadprogress",_file5,progress,_file5.upload.bytesSent);}}}},{key:"_finishedUploading",value:function _finishedUploading(files,xhr,e){var response=void 0;if(files[0].status===Dropzone.CANCELED){return;}if(xhr.readyState!==4){return;}if(xhr.responseType!=='arraybuffer'&&xhr.responseType!=='blob'){response=xhr.responseText;if(xhr.getResponseHeader("content-type")&&~xhr.getResponseHeader("content-type").indexOf("application/json")){try{response=JSON.parse(response);}catch(error){e=error;response="Invalid JSON response from server.";}}}this._updateFilesUploadProgress(files);if(!(200<=xhr.status&&xhr.status<300)){this._handleUploadError(files,xhr,response);}else{if(files[0].upload.chunked){files[0].upload.finishedChunkUpload(this._getChunk(files[0],xhr));}else{this._finished(files,response,e);}}}},{key:"_handleUploadError",value:function _handleUploadError(files,xhr,response){if(files[0].status===Dropzone.CANCELED){
|
||||
return;}if(files[0].upload.chunked&&this.options.retryChunks){var chunk=this._getChunk(files[0],xhr);if(chunk.retries++<this.options.retryChunksLimit){this._uploadData(files,[chunk.dataBlock]);return;}else{console.warn('Retried this chunk too often. Giving up.');}}for(var _iterator30=files,_isArray30=true,_i32=0,_iterator30=_isArray30?_iterator30:_iterator30[Symbol.iterator]();;){var _ref29;if(_isArray30){if(_i32>=_iterator30.length)break;_ref29=_iterator30[_i32++];}else{_i32=_iterator30.next();if(_i32.done)break;_ref29=_i32.value;}var file=_ref29;this._errorProcessing(files,response||this.options.dictResponseError.replace("{{statusCode}}",xhr.status),xhr);}}},{key:"submitRequest",value:function submitRequest(xhr,formData,files){xhr.send(formData);}},{key:"_finished",value:function _finished(files,responseText,e){for(var _iterator31=files,_isArray31=true,_i33=0,_iterator31=_isArray31?_iterator31:_iterator31[Symbol.iterator]();;){var _ref30;if(_isArray31){if(_i33>=_iterator31.length)break;
|
||||
_ref30=_iterator31[_i33++];}else{_i33=_iterator31.next();if(_i33.done)break;_ref30=_i33.value;}var file=_ref30;file.status=Dropzone.SUCCESS;this.emit("success",file,responseText,e);this.emit("complete",file);}if(this.options.uploadMultiple){this.emit("successmultiple",files,responseText,e);this.emit("completemultiple",files);}if(this.options.autoProcessQueue){return this.processQueue();}}},{key:"_errorProcessing",value:function _errorProcessing(files,message,xhr){for(var _iterator32=files,_isArray32=true,_i34=0,_iterator32=_isArray32?_iterator32:_iterator32[Symbol.iterator]();;){var _ref31;if(_isArray32){if(_i34>=_iterator32.length)break;_ref31=_iterator32[_i34++];}else{_i34=_iterator32.next();if(_i34.done)break;_ref31=_i34.value;}var file=_ref31;file.status=Dropzone.ERROR;this.emit("error",file,message,xhr);this.emit("complete",file);}if(this.options.uploadMultiple){this.emit("errormultiple",files,message,xhr);this.emit("completemultiple",files);}if(this.options.autoProcessQueue){
|
||||
return this.processQueue();}}}],[{key:"uuidv4",value:function uuidv4(){return'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(c){var r=Math.random()*16|0,v=c==='x'?r:r&0x3|0x8;return v.toString(16);});}}]);return Dropzone;}(Emitter);Dropzone.initClass();Dropzone.version="5.5.1";Dropzone.options={};Dropzone.optionsForElement=function(element){if(element.getAttribute("id")){return Dropzone.options[camelize(element.getAttribute("id"))];}else{return undefined;}};Dropzone.instances=[];Dropzone.forElement=function(element){if(typeof element==="string"){element=document.querySelector(element);}if((element!=null?element.dropzone:undefined)==null){throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.");}return element.dropzone;};Dropzone.autoDiscover=true;Dropzone.discover=function(){var dropzones=void 0;if(document.querySelectorAll){
|
||||
dropzones=document.querySelectorAll(".dropzone");}else{dropzones=[];var checkElements=function checkElements(elements){return function(){var result=[];for(var _iterator33=elements,_isArray33=true,_i35=0,_iterator33=_isArray33?_iterator33:_iterator33[Symbol.iterator]();;){var _ref32;if(_isArray33){if(_i35>=_iterator33.length)break;_ref32=_iterator33[_i35++];}else{_i35=_iterator33.next();if(_i35.done)break;_ref32=_i35.value;}var el=_ref32;if(/(^| )dropzone($| )/.test(el.className)){result.push(dropzones.push(el));}else{result.push(undefined);}}return result;}();};checkElements(document.getElementsByTagName("div"));checkElements(document.getElementsByTagName("form"));}return function(){var result=[];for(var _iterator34=dropzones,_isArray34=true,_i36=0,_iterator34=_isArray34?_iterator34:_iterator34[Symbol.iterator]();;){var _ref33;if(_isArray34){if(_i36>=_iterator34.length)break;_ref33=_iterator34[_i36++];}else{_i36=_iterator34.next();if(_i36.done)break;_ref33=_i36.value;}var dropzone=_ref33;
|
||||
if(Dropzone.optionsForElement(dropzone)!==false){result.push(new Dropzone(dropzone));}else{result.push(undefined);}}return result;}();};Dropzone.blacklistedBrowsers=[/opera.*(Macintosh|Windows Phone).*version\/12/i];Dropzone.isBrowserSupported=function(){var capableBrowser=true;if(window.File&&window.FileReader&&window.FileList&&window.Blob&&window.FormData&&document.querySelector){if(!("classList"in document.createElement("a"))){capableBrowser=false;}else{for(var _iterator35=Dropzone.blacklistedBrowsers,_isArray35=true,_i37=0,_iterator35=_isArray35?_iterator35:_iterator35[Symbol.iterator]();;){var _ref34;if(_isArray35){if(_i37>=_iterator35.length)break;_ref34=_iterator35[_i37++];}else{_i37=_iterator35.next();if(_i37.done)break;_ref34=_i37.value;}var regex=_ref34;if(regex.test(navigator.userAgent)){capableBrowser=false;continue;}}}}else{capableBrowser=false;}return capableBrowser;};Dropzone.dataURItoBlob=function(dataURI){var byteString=atob(dataURI.split(',')[1]);var mimeString=dataURI.split(',')[0].split(':')[1].split(';')[0];
|
||||
var ab=new ArrayBuffer(byteString.length);var ia=new Uint8Array(ab);for(var i=0,end=byteString.length,asc=0<=end;asc?i<=end:i>=end;asc?i++:i--){ia[i]=byteString.charCodeAt(i);}return new Blob([ab],{type:mimeString});};var without=function without(list,rejectedItem){return list.filter(function(item){return item!==rejectedItem;}).map(function(item){return item;});};var camelize=function camelize(str){return str.replace(/[\-_](\w)/g,function(match){return match.charAt(1).toUpperCase();});};Dropzone.createElement=function(string){var div=document.createElement("div");div.innerHTML=string;return div.childNodes[0];};Dropzone.elementInside=function(element,container){if(element===container){return true;}while(element=element.parentNode){if(element===container){return true;}}return false;};Dropzone.getElement=function(el,name){var element=void 0;if(typeof el==="string"){element=document.querySelector(el);}else if(el.nodeType!=null){element=el;}if(element==null){throw new Error("Invalid `"+name+"` option provided. Please provide a CSS selector or a plain HTML element.");
|
||||
}return element;};Dropzone.getElements=function(els,name){var el=void 0,elements=void 0;if(els instanceof Array){elements=[];try{for(var _iterator36=els,_isArray36=true,_i38=0,_iterator36=_isArray36?_iterator36:_iterator36[Symbol.iterator]();;){if(_isArray36){if(_i38>=_iterator36.length)break;el=_iterator36[_i38++];}else{_i38=_iterator36.next();if(_i38.done)break;el=_i38.value;}elements.push(this.getElement(el,name));}}catch(e){elements=null;}}else if(typeof els==="string"){elements=[];for(var _iterator37=document.querySelectorAll(els),_isArray37=true,_i39=0,_iterator37=_isArray37?_iterator37:_iterator37[Symbol.iterator]();;){if(_isArray37){if(_i39>=_iterator37.length)break;el=_iterator37[_i39++];}else{_i39=_iterator37.next();if(_i39.done)break;el=_i39.value;}elements.push(el);}}else if(els.nodeType!=null){elements=[els];}if(elements==null||!elements.length){throw new Error("Invalid `"+name+"` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");}
|
||||
return elements;};Dropzone.confirm=function(question,accepted,rejected){if(window.confirm(question)){return accepted();}else if(rejected!=null){return rejected();}};Dropzone.isValidFile=function(file,acceptedFiles){if(!acceptedFiles){return true;}acceptedFiles=acceptedFiles.split(",");var mimeType=file.type;var baseMimeType=mimeType.replace(/\/.*$/,"");for(var _iterator38=acceptedFiles,_isArray38=true,_i40=0,_iterator38=_isArray38?_iterator38:_iterator38[Symbol.iterator]();;){var _ref35;if(_isArray38){if(_i40>=_iterator38.length)break;_ref35=_iterator38[_i40++];}else{_i40=_iterator38.next();if(_i40.done)break;_ref35=_i40.value;}var validType=_ref35;validType=validType.trim();if(validType.charAt(0)==="."){if(file.name.toLowerCase().indexOf(validType.toLowerCase(),file.name.length-validType.length)!==-1){return true;}}else if(/\/\*$/.test(validType)){if(baseMimeType===validType.replace(/\/.*$/,"")){return true;}}else{if(mimeType===validType){return true;}}}return false;};if(typeof jQuery!=='undefined'&&jQuery!==null){
|
||||
jQuery.fn.dropzone=function(options){return this.each(function(){return new Dropzone(this,options);});};}if(typeof module!=='undefined'&&module!==null){module.exports=Dropzone;}else{window.Dropzone=Dropzone;}Dropzone.ADDED="added";Dropzone.QUEUED="queued";Dropzone.ACCEPTED=Dropzone.QUEUED;Dropzone.UPLOADING="uploading";Dropzone.PROCESSING=Dropzone.UPLOADING;Dropzone.CANCELED="canceled";Dropzone.ERROR="error";Dropzone.SUCCESS="success";var detectVerticalSquash=function detectVerticalSquash(img){var iw=img.naturalWidth;var ih=img.naturalHeight;var canvas=document.createElement("canvas");canvas.width=1;canvas.height=ih;var ctx=canvas.getContext("2d");ctx.drawImage(img,0,0);var _ctx$getImageData=ctx.getImageData(1,0,1,ih),data=_ctx$getImageData.data;var sy=0;var ey=ih;var py=ih;while(py>sy){var alpha=data[(py-1)*4+3];if(alpha===0){ey=py;}else{sy=py;}py=ey+sy>>1;}var ratio=py/ih;if(ratio===0){return 1;}else{return ratio;}};var drawImageIOSFix=function drawImageIOSFix(ctx,img,sx,sy,sw,sh,dx,dy,dw,dh){
|
||||
var vertSquashRatio=detectVerticalSquash(img);return ctx.drawImage(img,sx,sy,sw,sh,dx,dy,dw,dh/vertSquashRatio);};var ExifRestore=function(){function ExifRestore(){_classCallCheck(this,ExifRestore);}_createClass(ExifRestore,null,[{key:"initClass",value:function initClass(){this.KEY_STR='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';}},{key:"encode64",value:function encode64(input){var output='';var chr1=undefined;var chr2=undefined;var chr3='';var enc1=undefined;var enc2=undefined;var enc3=undefined;var enc4='';var i=0;while(true){chr1=input[i++];chr2=input[i++];chr3=input[i++];enc1=chr1>>2;enc2=(chr1&3)<<4|chr2>>4;enc3=(chr2&15)<<2|chr3>>6;enc4=chr3&63;if(isNaN(chr2)){enc3=enc4=64;}else if(isNaN(chr3)){enc4=64;}output=output+this.KEY_STR.charAt(enc1)+this.KEY_STR.charAt(enc2)+this.KEY_STR.charAt(enc3)+this.KEY_STR.charAt(enc4);chr1=chr2=chr3='';enc1=enc2=enc3=enc4='';if(!(i<input.length)){break;}}return output;}},{key:"restore",value:function restore(origFileBase64,resizedFileBase64){
|
||||
if(!origFileBase64.match('data:image/jpeg;base64,')){return resizedFileBase64;}var rawImage=this.decode64(origFileBase64.replace('data:image/jpeg;base64,',''));var segments=this.slice2Segments(rawImage);var image=this.exifManipulation(resizedFileBase64,segments);return"data:image/jpeg;base64,"+this.encode64(image);}},{key:"exifManipulation",value:function exifManipulation(resizedFileBase64,segments){var exifArray=this.getExifArray(segments);var newImageArray=this.insertExif(resizedFileBase64,exifArray);var aBuffer=new Uint8Array(newImageArray);return aBuffer;}},{key:"getExifArray",value:function getExifArray(segments){var seg=undefined;var x=0;while(x<segments.length){seg=segments[x];if(seg[0]===255&seg[1]===225){return seg;}x++;}return[];}},{key:"insertExif",value:function insertExif(resizedFileBase64,exifArray){var imageData=resizedFileBase64.replace('data:image/jpeg;base64,','');var buf=this.decode64(imageData);var separatePoint=buf.indexOf(255,3);var mae=buf.slice(0,separatePoint);
|
||||
var ato=buf.slice(separatePoint);var array=mae;array=array.concat(exifArray);array=array.concat(ato);return array;}},{key:"slice2Segments",value:function slice2Segments(rawImageArray){var head=0;var segments=[];while(true){var length;if(rawImageArray[head]===255&rawImageArray[head+1]===218){break;}if(rawImageArray[head]===255&rawImageArray[head+1]===216){head+=2;}else{length=rawImageArray[head+2]*256+rawImageArray[head+3];var endPoint=head+length+2;var seg=rawImageArray.slice(head,endPoint);segments.push(seg);head=endPoint;}if(head>rawImageArray.length){break;}}return segments;}},{key:"decode64",value:function decode64(input){var output='';var chr1=undefined;var chr2=undefined;var chr3='';var enc1=undefined;var enc2=undefined;var enc3=undefined;var enc4='';var i=0;var buf=[];var base64test=/[^A-Za-z0-9\+\/\=]/g;if(base64test.exec(input)){console.warn('There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, \'+\', \'/\',and \'=\'\nExpect errors in decoding.');
|
||||
}input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(true){enc1=this.KEY_STR.indexOf(input.charAt(i++));enc2=this.KEY_STR.indexOf(input.charAt(i++));enc3=this.KEY_STR.indexOf(input.charAt(i++));enc4=this.KEY_STR.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;buf.push(chr1);if(enc3!==64){buf.push(chr2);}if(enc4!==64){buf.push(chr3);}chr1=chr2=chr3='';enc1=enc2=enc3=enc4='';if(!(i<input.length)){break;}}return buf;}}]);return ExifRestore;}();ExifRestore.initClass();var contentLoaded=function contentLoaded(win,fn){var done=false;var top=true;var doc=win.document;var root=doc.documentElement;var add=doc.addEventListener?"addEventListener":"attachEvent";var rem=doc.addEventListener?"removeEventListener":"detachEvent";var pre=doc.addEventListener?"":"on";var init=function init(e){if(e.type==="readystatechange"&&doc.readyState!=="complete"){return;}(e.type==="load"?win:doc)[rem](pre+e.type,init,false);if(!done&&(done=true)){return fn.call(win,e.type||e);
|
||||
}};var poll=function poll(){try{root.doScroll("left");}catch(e){setTimeout(poll,50);return;}return init("poll");};if(doc.readyState!=="complete"){if(doc.createEventObject&&root.doScroll){try{top=!win.frameElement;}catch(error){}if(top){poll();}}doc[add](pre+"DOMContentLoaded",init,false);doc[add](pre+"readystatechange",init,false);return win[add](pre+"load",init,false);}};Dropzone._autoDiscoverFunction=function(){if(Dropzone.autoDiscover){return Dropzone.discover();}};contentLoaded(window,Dropzone._autoDiscoverFunction);function __guard__(value,transform){return typeof value!=='undefined'&&value!==null?transform(value):undefined;}function __guardMethod__(obj,methodName,transform){if(typeof obj!=='undefined'&&obj!==null&&typeof obj[methodName]==='function'){return transform(obj,methodName);}else{return undefined;}}(function(window,document){var modalClass='.sweet-alert',overlayClass='.sweet-overlay',alertTypes=['error','warning','info','success'],defaultParams={title:'',text:'',type:null,
|
||||
allowOutsideClick:false,showCancelButton:false,showConfirmButton:true,closeOnConfirm:true,closeOnCancel:true,confirmButtonText:'OK',confirmButtonClass:'btn-primary',cancelButtonText:'Cancel',cancelButtonClass:'btn-default',containerClass:'',titleClass:'',textClass:'',imageUrl:null,imageSize:null,timer:null};var getModal=function(){return document.querySelector(modalClass);},getOverlay=function(){return document.querySelector(overlayClass);},hasClass=function(elem,className){return new RegExp(' '+className+' ').test(' '+elem.className+' ');},addClass=function(elem,className){if(className&&!hasClass(elem,className)){elem.className+=' '+className;}},removeClass=function(elem,className){var newClass=' '+elem.className.replace(/[\t\r\n]/g,' ')+' ';if(hasClass(elem,className)){while(newClass.indexOf(' '+className+' ')>=0){newClass=newClass.replace(' '+className+' ',' ');}elem.className=newClass.replace(/^\s+|\s+$/g,'');}},escapeHtml=function(str){var div=document.createElement('div');div.appendChild(document.createTextNode(str));
|
||||
return div.innerHTML;},_show=function(elem){elem.style.opacity='';elem.style.display='block';},show=function(elems){if(elems&&!elems.length){return _show(elems);}for(var i=0;i<elems.length;++i){_show(elems[i]);}},_hide=function(elem){elem.style.opacity='';elem.style.display='none';},hide=function(elems){if(elems&&!elems.length){return _hide(elems);}for(var i=0;i<elems.length;++i){_hide(elems[i]);}},isDescendant=function(parent,child){var node=child.parentNode;while(node!==null){if(node===parent){return true;}node=node.parentNode;}return false;},getTopMargin=function(elem){elem.style.left='-9999px';elem.style.display='block';var height=elem.clientHeight;var padding=parseInt(getComputedStyle(elem).getPropertyValue('padding'),10);elem.style.left='';elem.style.display='none';return('-'+parseInt(height/2+padding)+'px');},fadeIn=function(elem,interval){if(+elem.style.opacity<1){interval=interval||16;elem.style.opacity=0;elem.style.display='block';var last=+new Date();var tick=function(){elem.style.opacity=+elem.style.opacity+(new Date()-last)/100;
|
||||
last=+new Date();if(+elem.style.opacity<1){setTimeout(tick,interval);}};tick();}},fadeOut=function(elem,interval){interval=interval||16;elem.style.opacity=1;var last=+new Date();var tick=function(){elem.style.opacity=+elem.style.opacity-(new Date()-last)/100;last=+new Date();if(+elem.style.opacity>0){setTimeout(tick,interval);}else{elem.style.display='none';}};tick();},fireClick=function(node){if(MouseEvent){var mevt=new MouseEvent('click',{view:window,bubbles:false,cancelable:true});node.dispatchEvent(mevt);}else if(document.createEvent){var evt=document.createEvent('MouseEvents');evt.initEvent('click',false,false);node.dispatchEvent(evt);}else if(document.createEventObject){node.fireEvent('onclick');}else if(typeof node.onclick==='function'){node.onclick();}},stopEventPropagation=function(e){if(typeof e.stopPropagation==='function'){e.stopPropagation();e.preventDefault();}else if(window.event&&window.event.hasOwnProperty('cancelBubble')){window.event.cancelBubble=true;}};var previousActiveElement,
|
||||
previousDocumentClick,previousWindowKeyDown,lastFocusedButton;window.sweetAlertInitialize=function(){var sweetHTML='<div class="sweet-overlay"></div><div class="sweet-alert"><div class="icon error"><span class="x-mark"><span class="line left"></span><span class="line right"></span></span></div><div class="icon warning"> <span class="body"></span> <span class="dot"></span> </div> <div class="icon info"></div> <div class="icon success"> <span class="line tip"></span> <span class="line long"></span> <div class="placeholder"></div> <div class="fix"></div> </div> <div class="icon custom"></div> <h2>Title</h2><p class="lead text-muted">Text</p><p><button class="cancel btn" tabIndex="2">Cancel</button> <button class="confirm btn" tabIndex="1">OK</button></p></div>',sweetWrap=document.createElement('div');sweetWrap.innerHTML=sweetHTML;document.body.appendChild(sweetWrap);}
|
||||
window.sweetAlert=window.swal=function(){if(arguments[0]===undefined){window.console.error('sweetAlert expects at least 1 attribute!');return false;}var params=extend({},defaultParams);switch(typeof arguments[0]){case'string':params.title=arguments[0];params.text=arguments[1]||'';params.type=arguments[2]||'';break;case'object':if(arguments[0].title===undefined){window.console.error('Missing "title" argument!');return false;}params.title=arguments[0].title;params.text=arguments[0].text||defaultParams.text;params.type=arguments[0].type||defaultParams.type;params.allowOutsideClick=arguments[0].allowOutsideClick||defaultParams.allowOutsideClick;params.showCancelButton=arguments[0].showCancelButton!==undefined?arguments[0].showCancelButton:defaultParams.showCancelButton;params.showConfirmButton=arguments[0].showConfirmButton!==undefined?arguments[0].showConfirmButton:defaultParams.showConfirmButton;params.closeOnConfirm=arguments[0].closeOnConfirm!==undefined?arguments[0].closeOnConfirm:defaultParams.closeOnConfirm;
|
||||
params.closeOnCancel=arguments[0].closeOnCancel!==undefined?arguments[0].closeOnCancel:defaultParams.closeOnCancel;params.timer=arguments[0].timer||defaultParams.timer;params.confirmButtonText=(defaultParams.showCancelButton)?'Confirm':defaultParams.confirmButtonText;params.confirmButtonText=arguments[0].confirmButtonText||defaultParams.confirmButtonText;params.confirmButtonClass=arguments[0].confirmButtonClass||(arguments[0].type?'btn-'+arguments[0].type:null)||defaultParams.confirmButtonClass;params.cancelButtonText=arguments[0].cancelButtonText||defaultParams.cancelButtonText;params.cancelButtonClass=arguments[0].cancelButtonClass||defaultParams.cancelButtonClass;params.containerClass=arguments[0].containerClass||defaultParams.containerClass;params.titleClass=arguments[0].titleClass||defaultParams.titleClass;params.textClass=arguments[0].textClass||defaultParams.textClass;params.imageUrl=arguments[0].imageUrl||defaultParams.imageUrl;params.imageSize=arguments[0].imageSize||defaultParams.imageSize;
|
||||
params.doneFunction=arguments[1]||null;break;default:window.console.error('Unexpected type of argument! Expected "string" or "object", got '+typeof arguments[0]);return false;}setParameters(params);fixVerticalPosition();openModal();var modal=getModal();var onButtonEvent=function(e){var target=e.target||e.srcElement,targetedConfirm=(target.className.indexOf('confirm')>-1),modalIsVisible=hasClass(modal,'visible'),doneFunctionExists=(params.doneFunction&&modal.getAttribute('data-has-done-function')==='true');switch(e.type){case("click"):if(targetedConfirm&&doneFunctionExists&&modalIsVisible){params.doneFunction(true);if(params.closeOnConfirm){closeModal();}}else if(doneFunctionExists&&modalIsVisible){var functionAsStr=String(params.doneFunction).replace(/\s/g,'');var functionHandlesCancel=functionAsStr.substring(0,9)==="function("&&functionAsStr.substring(9,10)!==")";if(functionHandlesCancel){params.doneFunction(false);}if(params.closeOnCancel){closeModal();}}else{closeModal();}break;}};
|
||||
var $buttons=modal.querySelectorAll('button');for(var i=0;i<$buttons.length;i++){$buttons[i].onclick=onButtonEvent;}previousDocumentClick=document.onclick;document.onclick=function(e){var target=e.target||e.srcElement;var clickedOnModal=(modal===target),clickedOnModalChild=isDescendant(modal,e.target),modalIsVisible=hasClass(modal,'visible'),outsideClickIsAllowed=modal.getAttribute('data-allow-ouside-click')==='true';if(!clickedOnModal&&!clickedOnModalChild&&modalIsVisible&&outsideClickIsAllowed){closeModal();}};var $okButton=modal.querySelector('button.confirm'),$cancelButton=modal.querySelector('button.cancel'),$modalButtons=modal.querySelectorAll('button:not([type=hidden])');function handleKeyDown(e){var keyCode=e.keyCode||e.which;if([9,13,32,27].indexOf(keyCode)===-1){return;}var $targetElement=e.target||e.srcElement;var btnIndex=-1;for(var i=0;i<$modalButtons.length;i++){if($targetElement===$modalButtons[i]){btnIndex=i;break;}}if(keyCode===9){if(btnIndex===-1){$targetElement=$okButton;
|
||||
}else{if(btnIndex===$modalButtons.length-1){$targetElement=$modalButtons[0];}else{$targetElement=$modalButtons[btnIndex+1];}}stopEventPropagation(e);$targetElement.focus();}else{if(keyCode===13||keyCode===32){if(btnIndex===-1){$targetElement=$okButton;}else{$targetElement=undefined;}}else if(keyCode===27&&!($cancelButton.hidden||$cancelButton.style.display==='none')){$targetElement=$cancelButton;}else{$targetElement=undefined;}if($targetElement!==undefined){fireClick($targetElement,e);}}}previousWindowKeyDown=window.onkeydown;window.onkeydown=handleKeyDown;function handleOnBlur(e){var $targetElement=e.target||e.srcElement,$focusElement=e.relatedTarget,modalIsVisible=hasClass(modal,'visible'),bootstrapModalIsVisible=document.querySelector('.control-popup.modal')||false;if(bootstrapModalIsVisible){return;}if(modalIsVisible){var btnIndex=-1;if($focusElement!==null){for(var i=0;i<$modalButtons.length;i++){if($focusElement===$modalButtons[i]){btnIndex=i;break;}}if(btnIndex===-1){
|
||||
$targetElement.focus();}}else{lastFocusedButton=$targetElement;}}}$okButton.onblur=handleOnBlur;$cancelButton.onblur=handleOnBlur;window.onfocus=function(){window.setTimeout(function(){if(lastFocusedButton!==undefined){lastFocusedButton.focus();lastFocusedButton=undefined;}},0);};};window.swal.setDefaults=function(userParams){if(!userParams){throw new Error('userParams is required');}if(typeof userParams!=='object'){throw new Error('userParams has to be a object');}extend(defaultParams,userParams);};window.swal.close=function(){closeModal();}
|
||||
function setParameters(params){var modal=getModal();var $title=modal.querySelector('h2'),$text=modal.querySelector('p'),$cancelBtn=modal.querySelector('button.cancel'),$confirmBtn=modal.querySelector('button.confirm');$title.innerHTML=escapeHtml(params.title).split("\n").join("<br>");$text.innerHTML=escapeHtml(params.text||'').split("\n").join("<br>");if(params.text){show($text);}hide(modal.querySelectorAll('.icon'));if(params.type){var validType=false;for(var i=0;i<alertTypes.length;i++){if(params.type===alertTypes[i]){validType=true;break;}}if(!validType){window.console.error('Unknown alert type: '+params.type);return false;}var $icon=modal.querySelector('.icon.'+params.type);show($icon);switch(params.type){case"success":addClass($icon,'animate');addClass($icon.querySelector('.tip'),'animateSuccessTip');addClass($icon.querySelector('.long'),'animateSuccessLong');break;case"error":addClass($icon,'animateErrorIcon');addClass($icon.querySelector('.x-mark'),'animateXMark');break;case"warning":
|
||||
addClass($icon,'pulseWarning');addClass($icon.querySelector('.body'),'pulseWarningIns');addClass($icon.querySelector('.dot'),'pulseWarningIns');break;}}if(params.imageUrl){var $customIcon=modal.querySelector('.icon.custom');$customIcon.style.backgroundImage='url('+params.imageUrl+')';show($customIcon);var _imgWidth=80,_imgHeight=80;if(params.imageSize){var imgWidth=params.imageSize.split('x')[0];var imgHeight=params.imageSize.split('x')[1];if(!imgWidth||!imgHeight){window.console.error("Parameter imageSize expects value with format WIDTHxHEIGHT, got "+params.imageSize);}else{_imgWidth=imgWidth;_imgHeight=imgHeight;$customIcon.css({'width':imgWidth+'px','height':imgHeight+'px'});}}$customIcon.setAttribute('style',$customIcon.getAttribute('style')+'width:'+_imgWidth+'px; height:'+_imgHeight+'px');}modal.setAttribute('data-has-cancel-button',params.showCancelButton);if(params.showCancelButton){$cancelBtn.style.display='inline-block';}else{hide($cancelBtn);}modal.setAttribute('data-has-confirm-button',params.showConfirmButton);
|
||||
if(params.showConfirmButton){$confirmBtn.style.display='inline-block';}else{hide($confirmBtn);}if(params.cancelButtonText){$cancelBtn.innerHTML=escapeHtml(params.cancelButtonText);}if(params.confirmButtonText){$confirmBtn.innerHTML=escapeHtml(params.confirmButtonText);}$confirmBtn.className='confirm btn'
|
||||
addClass(modal,params.containerClass);addClass($confirmBtn,params.confirmButtonClass);addClass($cancelBtn,params.cancelButtonClass);addClass($title,params.titleClass);addClass($text,params.textClass);modal.setAttribute('data-allow-ouside-click',params.allowOutsideClick);var hasDoneFunction=(params.doneFunction)?true:false;modal.setAttribute('data-has-done-function',hasDoneFunction);modal.setAttribute('data-timer',params.timer);}function colorLuminance(hex,lum){hex=String(hex).replace(/[^0-9a-f]/gi,'');if(hex.length<6){hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];}lum=lum||0;var rgb="#",c,i;for(i=0;i<3;i++){c=parseInt(hex.substr(i*2,2),16);c=Math.round(Math.min(Math.max(0,c+(c*lum)),255)).toString(16);rgb+=("00"+c).substr(c.length);}return rgb;}function extend(a,b){for(var key in b){if(b.hasOwnProperty(key)){a[key]=b[key];}}return a;}function hexToRgb(hex){var result=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);return result?parseInt(result[1],16)+', '+parseInt(result[2],16)+', '+parseInt(result[3],16):null;
|
||||
}function setFocusStyle($button,bgColor){var rgbColor=hexToRgb(bgColor);$button.style.boxShadow='0 0 2px rgba('+rgbColor+', 0.8), inset 0 0 0 1px rgba(0, 0, 0, 0.05)';}function openModal(){var modal=getModal();fadeIn(getOverlay(),10);show(modal);addClass(modal,'showSweetAlert');removeClass(modal,'hideSweetAlert');previousActiveElement=document.activeElement;var $okButton=modal.querySelector('button.confirm');$okButton.focus();setTimeout(function(){addClass(modal,'visible');},500);var timer=modal.getAttribute('data-timer');if(timer!=="null"&&timer!==""){setTimeout(function(){closeModal();},timer);}}function closeModal(){var modal=getModal();fadeOut(getOverlay(),5);fadeOut(modal,5);removeClass(modal,'showSweetAlert');addClass(modal,'hideSweetAlert');removeClass(modal,'visible');var $successIcon=modal.querySelector('.icon.success');removeClass($successIcon,'animate');removeClass($successIcon.querySelector('.tip'),'animateSuccessTip');removeClass($successIcon.querySelector('.long'),'animateSuccessLong');
|
||||
var $errorIcon=modal.querySelector('.icon.error');removeClass($errorIcon,'animateErrorIcon');removeClass($errorIcon.querySelector('.x-mark'),'animateXMark');var $warningIcon=modal.querySelector('.icon.warning');removeClass($warningIcon,'pulseWarning');removeClass($warningIcon.querySelector('.body'),'pulseWarningIns');removeClass($warningIcon.querySelector('.dot'),'pulseWarningIns');window.onkeydown=previousWindowKeyDown;document.onclick=previousDocumentClick;if(previousActiveElement){previousActiveElement.focus();}lastFocusedButton=undefined;}function fixVerticalPosition(){var modal=getModal();modal.style.marginTop=getTopMargin(getModal());}(function(){if(document.readyState==="complete"||document.readyState==="interactive"&&document.body){sweetAlertInitialize();}else{if(document.addEventListener){document.addEventListener('DOMContentLoaded',function handler(){document.removeEventListener('DOMContentLoaded',handler,false);sweetAlertInitialize();},false);}else if(document.attachEvent){
|
||||
document.attachEvent('onreadystatechange',function handler(){if(document.readyState==='complete'){document.detachEvent('onreadystatechange',handler);sweetAlertInitialize();}});}}})();})(window,document);(function($){$.Jcrop=function(obj,opt){var options=$.extend({},$.Jcrop.defaults),docOffset,_ua=navigator.userAgent.toLowerCase(),is_msie=/msie/.test(_ua),ie6mode=/msie [1-6]\./.test(_ua);function px(n){return Math.round(n)+'px';}function cssClass(cl){return options.baseClass+'-'+cl;}function supportsColorFade(){return $.fx.step.hasOwnProperty('backgroundColor');}function getPos(obj){var pos=$(obj).offset();return[pos.left,pos.top];}function mouseAbs(e){return[(e.pageX-docOffset[0]),(e.pageY-docOffset[1])];}function setOptions(opt){if(typeof(opt)!=='object')opt={};options=$.extend(options,opt);$.each(['onChange','onSelect','onRelease','onDblClick'],function(i,e){if(typeof(options[e])!=='function')options[e]=function(){};});}function startDragMode(mode,pos,touch){docOffset=getPos($img);
|
||||
Tracker.setCursor(mode==='move'?mode:mode+'-resize');if(mode==='move'){return Tracker.activateHandlers(createMover(pos),doneSelect,touch);}var fc=Coords.getFixed();var opp=oppLockCorner(mode);var opc=Coords.getCorner(oppLockCorner(opp));Coords.setPressed(Coords.getCorner(opp));Coords.setCurrent(opc);Tracker.activateHandlers(dragmodeHandler(mode,fc),doneSelect,touch);}function dragmodeHandler(mode,f){return function(pos){if(!options.aspectRatio){switch(mode){case'e':pos[1]=f.y2;break;case'w':pos[1]=f.y2;break;case'n':pos[0]=f.x2;break;case's':pos[0]=f.x2;break;}}else{switch(mode){case'e':pos[1]=f.y+1;break;case'w':pos[1]=f.y+1;break;case'n':pos[0]=f.x+1;break;case's':pos[0]=f.x+1;break;}}Coords.setCurrent(pos);Selection.update();};}function createMover(pos){var lloc=pos;KeyManager.watchKeys();return function(pos){Coords.moveOffset([pos[0]-lloc[0],pos[1]-lloc[1]]);lloc=pos;Selection.update();};}function oppLockCorner(ord){switch(ord){case'n':return'sw';case's':return'nw';case'e':return'nw';
|
||||
case'w':return'ne';case'ne':return'sw';case'nw':return'se';case'se':return'nw';case'sw':return'ne';}}function createDragger(ord){return function(e){if(options.disabled){return false;}if((ord==='move')&&!options.allowMove){return false;}docOffset=getPos($img);btndown=true;startDragMode(ord,mouseAbs(e));e.stopPropagation();e.preventDefault();return false;};}function presize($obj,w,h){var nw=$obj.width(),nh=$obj.height();if((nw>w)&&w>0){nw=w;nh=(w/$obj.width())*$obj.height();}if((nh>h)&&h>0){nh=h;nw=(h/$obj.height())*$obj.width();}xscale=$obj.width()/nw;yscale=$obj.height()/nh;$obj.width(nw).height(nh);}function unscale(c){return{x:c.x*xscale,y:c.y*yscale,x2:c.x2*xscale,y2:c.y2*yscale,w:c.w*xscale,h:c.h*yscale};}function doneSelect(pos){var c=Coords.getFixed();if((c.w>options.minSelect[0])&&(c.h>options.minSelect[1])){Selection.enableHandles();Selection.done();}else{Selection.release();}Tracker.setCursor(options.allowSelect?'crosshair':'default');}function newSelection(e){if(options.disabled){
|
||||
return false;}if(!options.allowSelect){return false;}btndown=true;docOffset=getPos($img);Selection.disableHandles();Tracker.setCursor('crosshair');var pos=mouseAbs(e);Coords.setPressed(pos);Selection.update();Tracker.activateHandlers(selectDrag,doneSelect,e.type.substring(0,5)==='touch');KeyManager.watchKeys();e.stopPropagation();e.preventDefault();return false;}function selectDrag(pos){Coords.setCurrent(pos);Selection.update();}function newTracker(){var trk=$('<div></div>').addClass(cssClass('tracker'));if(is_msie){trk.css({opacity:0,backgroundColor:'white'});}return trk;}if(typeof(obj)!=='object'){obj=$(obj)[0];}if(typeof(opt)!=='object'){opt={};}setOptions(opt);var img_css={border:'none',visibility:'visible',margin:0,padding:0,position:'absolute',top:0,left:0};var $origimg=$(obj),img_mode=true;if(obj.tagName=='IMG'){if($origimg[0].width!=0&&$origimg[0].height!=0){$origimg.width($origimg[0].width);$origimg.height($origimg[0].height);}else{var tempImage=new Image();tempImage.src=$origimg[0].src;
|
||||
$origimg.width(tempImage.width);$origimg.height(tempImage.height);}var $img=$origimg.clone().removeAttr('id').css(img_css).show();$img.width($origimg.width());$img.height($origimg.height());$origimg.after($img).hide();}else{$img=$origimg.css(img_css).show();img_mode=false;if(options.shade===null){options.shade=true;}}presize($img,options.boxWidth,options.boxHeight);var boundx=$img.width(),boundy=$img.height(),$div=$('<div />').width(boundx).height(boundy).addClass(cssClass('holder')).css({position:'relative',backgroundColor:options.bgColor}).insertAfter($origimg).append($img);if(options.addClass){$div.addClass(options.addClass);}var $img2=$('<div />'),$img_holder=$('<div />').width('100%').height('100%').css({zIndex:310,position:'absolute',overflow:'hidden'}),$hdl_holder=$('<div />').width('100%').height('100%').css('zIndex',320),$sel=$('<div />').css({position:'absolute',zIndex:600}).dblclick(function(){var c=Coords.getFixed();options.onDblClick.call(api,c);}).insertBefore($img).append($img_holder,$hdl_holder);
|
||||
if(img_mode){$img2=$('<img />').attr('src',$img.attr('src')).css(img_css).width(boundx).height(boundy),$img_holder.append($img2);}if(ie6mode){$sel.css({overflowY:'hidden'});}var bound=options.boundary;var $trk=newTracker().width(boundx+(bound*2)).height(boundy+(bound*2)).css({position:'absolute',top:px(-bound),left:px(-bound),zIndex:290}).mousedown(newSelection);var bgcolor=options.bgColor,bgopacity=options.bgOpacity,xlimit,ylimit,xmin,ymin,xscale,yscale,enabled=true,btndown,animating,shift_down;docOffset=getPos($img);var Touch=(function(){function hasTouchSupport(){var support={},events=['touchstart','touchmove','touchend'],el=document.createElement('div'),i;try{for(i=0;i<events.length;i++){var eventName=events[i];eventName='on'+eventName;var isSupported=(eventName in el);if(!isSupported){el.setAttribute(eventName,'return;');isSupported=typeof el[eventName]=='function';}support[events[i]]=isSupported;}return support.touchstart&&support.touchend&&support.touchmove;}catch(err){return false;
|
||||
}}function detectSupport(){if((options.touchSupport===true)||(options.touchSupport===false))return options.touchSupport;else return hasTouchSupport();}return{createDragger:function(ord){return function(e){if(options.disabled){return false;}if((ord==='move')&&!options.allowMove){return false;}docOffset=getPos($img);btndown=true;startDragMode(ord,mouseAbs(Touch.cfilter(e)),true);e.stopPropagation();e.preventDefault();return false;};},newSelection:function(e){return newSelection(Touch.cfilter(e));},cfilter:function(e){e.pageX=e.originalEvent.changedTouches[0].pageX;e.pageY=e.originalEvent.changedTouches[0].pageY;return e;},fixTouchSupport:function(e){if($(e.currentTarget).hasClass('jcrop-tracker'))e.stopPropagation();},isSupported:hasTouchSupport,support:detectSupport()};}());var Coords=(function(){var x1=0,y1=0,x2=0,y2=0,ox,oy;function setPressed(pos){pos=rebound(pos);x2=x1=pos[0];y2=y1=pos[1];}function setCurrent(pos){pos=rebound(pos);ox=pos[0]-x2;oy=pos[1]-y2;x2=pos[0];y2=pos[1];}
|
||||
function getOffset(){return[ox,oy];}function moveOffset(offset){var ox=offset[0],oy=offset[1];if(0>x1+ox){ox-=ox+x1;}if(0>y1+oy){oy-=oy+y1;}if(boundy<y2+oy){oy+=boundy-(y2+oy);}if(boundx<x2+ox){ox+=boundx-(x2+ox);}x1+=ox;x2+=ox;y1+=oy;y2+=oy;}function getCorner(ord){var c=getFixed();switch(ord){case'ne':return[c.x2,c.y];case'nw':return[c.x,c.y];case'se':return[c.x2,c.y2];case'sw':return[c.x,c.y2];}}function getFixed(){if(!options.aspectRatio){return getRect();}var aspect=options.aspectRatio,min_x=options.minSize[0]/xscale,max_x=options.maxSize[0]/xscale,max_y=options.maxSize[1]/yscale,rw=x2-x1,rh=y2-y1,rwa=Math.abs(rw),rha=Math.abs(rh),real_ratio=rwa/rha,xx,yy,w,h;if(max_x===0){max_x=boundx*10;}if(max_y===0){max_y=boundy*10;}if(real_ratio<aspect){yy=y2;w=rha*aspect;xx=rw<0?x1-w:w+x1;if(xx<0){xx=0;h=Math.abs((xx-x1)/aspect);yy=rh<0?y1-h:h+y1;}else if(xx>boundx){xx=boundx;h=Math.abs((xx-x1)/aspect);yy=rh<0?y1-h:h+y1;}}else{xx=x2;h=rwa/aspect;yy=rh<0?y1-h:y1+h;if(yy<0){yy=0;w=Math.abs((yy-y1)*aspect);
|
||||
xx=rw<0?x1-w:w+x1;}else if(yy>boundy){yy=boundy;w=Math.abs(yy-y1)*aspect;xx=rw<0?x1-w:w+x1;}}if(xx>x1){if(xx-x1<min_x){xx=x1+min_x;}else if(xx-x1>max_x){xx=x1+max_x;}if(yy>y1){yy=y1+(xx-x1)/aspect;}else{yy=y1-(xx-x1)/aspect;}}else if(xx<x1){if(x1-xx<min_x){xx=x1-min_x;}else if(x1-xx>max_x){xx=x1-max_x;}if(yy>y1){yy=y1+(x1-xx)/aspect;}else{yy=y1-(x1-xx)/aspect;}}if(xx<0){x1-=xx;xx=0;}else if(xx>boundx){x1-=xx-boundx;xx=boundx;}if(yy<0){y1-=yy;yy=0;}else if(yy>boundy){y1-=yy-boundy;yy=boundy;}return makeObj(flipCoords(x1,y1,xx,yy));}function rebound(p){if(p[0]<0)p[0]=0;if(p[1]<0)p[1]=0;if(p[0]>boundx)p[0]=boundx;if(p[1]>boundy)p[1]=boundy;return[Math.round(p[0]),Math.round(p[1])];}function flipCoords(x1,y1,x2,y2){var xa=x1,xb=x2,ya=y1,yb=y2;if(x2<x1){xa=x2;xb=x1;}if(y2<y1){ya=y2;yb=y1;}return[xa,ya,xb,yb];}function getRect(){var xsize=x2-x1,ysize=y2-y1,delta;if(xlimit&&(Math.abs(xsize)>xlimit)){x2=(xsize>0)?(x1+xlimit):(x1-xlimit);}if(ylimit&&(Math.abs(ysize)>ylimit)){y2=(ysize>0)?(y1+ylimit):(y1-ylimit);
|
||||
}if(ymin/yscale&&(Math.abs(ysize)<ymin/yscale)){y2=(ysize>0)?(y1+ymin/yscale):(y1-ymin/yscale);}if(xmin/xscale&&(Math.abs(xsize)<xmin/xscale)){x2=(xsize>0)?(x1+xmin/xscale):(x1-xmin/xscale);}if(x1<0){x2-=x1;x1-=x1;}if(y1<0){y2-=y1;y1-=y1;}if(x2<0){x1-=x2;x2-=x2;}if(y2<0){y1-=y2;y2-=y2;}if(x2>boundx){delta=x2-boundx;x1-=delta;x2-=delta;}if(y2>boundy){delta=y2-boundy;y1-=delta;y2-=delta;}if(x1>boundx){delta=x1-boundy;y2-=delta;y1-=delta;}if(y1>boundy){delta=y1-boundy;y2-=delta;y1-=delta;}return makeObj(flipCoords(x1,y1,x2,y2));}function makeObj(a){return{x:a[0],y:a[1],x2:a[2],y2:a[3],w:a[2]-a[0],h:a[3]-a[1]};}return{flipCoords:flipCoords,setPressed:setPressed,setCurrent:setCurrent,getOffset:getOffset,moveOffset:moveOffset,getCorner:getCorner,getFixed:getFixed};}());var Shade=(function(){var enabled=false,holder=$('<div />').css({position:'absolute',zIndex:240,opacity:0}),shades={top:createShade(),left:createShade().height(boundy),right:createShade().height(boundy),bottom:createShade()};
|
||||
function resizeShades(w,h){shades.left.css({height:px(h)});shades.right.css({height:px(h)});}function updateAuto(){return updateShade(Coords.getFixed());}function updateShade(c){shades.top.css({left:px(c.x),width:px(c.w),height:px(c.y)});shades.bottom.css({top:px(c.y2),left:px(c.x),width:px(c.w),height:px(boundy-c.y2)});shades.right.css({left:px(c.x2),width:px(boundx-c.x2)});shades.left.css({width:px(c.x)});}function createShade(){return $('<div />').css({position:'absolute',backgroundColor:options.shadeColor||options.bgColor}).appendTo(holder);}function enableShade(){if(!enabled){enabled=true;holder.insertBefore($img);updateAuto();Selection.setBgOpacity(1,0,1);$img2.hide();setBgColor(options.shadeColor||options.bgColor,1);if(Selection.isAwake()){setOpacity(options.bgOpacity,1);}else setOpacity(1,1);}}function setBgColor(color,now){colorChangeMacro(getShades(),color,now);}function disableShade(){if(enabled){holder.remove();$img2.show();enabled=false;if(Selection.isAwake()){Selection.setBgOpacity(options.bgOpacity,1,1);
|
||||
}else{Selection.setBgOpacity(1,1,1);Selection.disableHandles();}colorChangeMacro($div,0,1);}}function setOpacity(opacity,now){if(enabled){if(options.bgFade&&!now){holder.animate({opacity:1-opacity},{queue:false,duration:options.fadeTime});}else holder.css({opacity:1-opacity});}}function refreshAll(){options.shade?enableShade():disableShade();if(Selection.isAwake())setOpacity(options.bgOpacity);}function getShades(){return holder.children();}return{update:updateAuto,updateRaw:updateShade,getShades:getShades,setBgColor:setBgColor,enable:enableShade,disable:disableShade,resize:resizeShades,refresh:refreshAll,opacity:setOpacity};}());var Selection=(function(){var awake,hdep=370,borders={},handle={},dragbar={},seehandles=false;function insertBorder(type){var jq=$('<div />').css({position:'absolute',opacity:options.borderOpacity}).addClass(cssClass(type));$img_holder.append(jq);return jq;}function dragDiv(ord,zi){var jq=$('<div />').mousedown(createDragger(ord)).css({cursor:ord+'-resize',
|
||||
position:'absolute',zIndex:zi}).addClass('ord-'+ord);if(Touch.support){jq.bind('touchstart.jcrop',Touch.createDragger(ord));}$hdl_holder.append(jq);return jq;}function insertHandle(ord){var hs=options.handleSize,div=dragDiv(ord,hdep++).css({opacity:options.handleOpacity}).addClass(cssClass('handle'));if(hs){div.width(hs).height(hs);}return div;}function insertDragbar(ord){return dragDiv(ord,hdep++).addClass('jcrop-dragbar');}function createDragbars(li){var i;for(i=0;i<li.length;i++){dragbar[li[i]]=insertDragbar(li[i]);}}function createBorders(li){var cl,i;for(i=0;i<li.length;i++){switch(li[i]){case'n':cl='hline';break;case's':cl='hline bottom';break;case'e':cl='vline right';break;case'w':cl='vline';break;}borders[li[i]]=insertBorder(cl);}}function createHandles(li){var i;for(i=0;i<li.length;i++){handle[li[i]]=insertHandle(li[i]);}}function moveto(x,y){if(!options.shade){$img2.css({top:px(-y),left:px(-x)});}$sel.css({top:px(y),left:px(x)});}function resize(w,h){$sel.width(Math.round(w)).height(Math.round(h));
|
||||
}function refresh(){var c=Coords.getFixed();Coords.setPressed([c.x,c.y]);Coords.setCurrent([c.x2,c.y2]);updateVisible();}function updateVisible(select){if(awake){return update(select);}}function update(select){var c=Coords.getFixed();resize(c.w,c.h);moveto(c.x,c.y);if(options.shade)Shade.updateRaw(c);awake||show();if(select){options.onSelect.call(api,unscale(c));}else{options.onChange.call(api,unscale(c));}}function setBgOpacity(opacity,force,now){if(!awake&&!force)return;if(options.bgFade&&!now){$img.animate({opacity:opacity},{queue:false,duration:options.fadeTime});}else{$img.css('opacity',opacity);}}function show(){$sel.show();if(options.shade)Shade.opacity(bgopacity);else setBgOpacity(bgopacity,true);awake=true;}function release(){disableHandles();$sel.hide();if(options.shade)Shade.opacity(1);else setBgOpacity(1);awake=false;options.onRelease.call(api);}function showHandles(){if(seehandles){$hdl_holder.show();}}function enableHandles(){seehandles=true;if(options.allowResize){
|
||||
$hdl_holder.show();return true;}}function disableHandles(){seehandles=false;$hdl_holder.hide();}function animMode(v){if(v){animating=true;disableHandles();}else{animating=false;enableHandles();}}function done(){animMode(false);refresh();}if(options.dragEdges&&$.isArray(options.createDragbars))createDragbars(options.createDragbars);if($.isArray(options.createHandles))createHandles(options.createHandles);if(options.drawBorders&&$.isArray(options.createBorders))createBorders(options.createBorders);$(document).bind('touchstart.jcrop-ios',Touch.fixTouchSupport);var $track=newTracker().mousedown(createDragger('move')).css({cursor:'move',position:'absolute',zIndex:360});if(Touch.support){$track.bind('touchstart.jcrop',Touch.createDragger('move'));}$img_holder.append($track);disableHandles();return{updateVisible:updateVisible,update:update,release:release,refresh:refresh,isAwake:function(){return awake;},setCursor:function(cursor){$track.css('cursor',cursor);},enableHandles:enableHandles,
|
||||
enableOnly:function(){seehandles=true;},showHandles:showHandles,disableHandles:disableHandles,animMode:animMode,setBgOpacity:setBgOpacity,done:done};}());var Tracker=(function(){var onMove=function(){},onDone=function(){},trackDoc=options.trackDocument;function toFront(touch){$trk.css({zIndex:450});if(touch)$(document).bind('touchmove.jcrop',trackTouchMove).bind('touchend.jcrop',trackTouchEnd);else if(trackDoc)$(document).bind('mousemove.jcrop',trackMove).bind('mouseup.jcrop',trackUp);}function toBack(){$trk.css({zIndex:290});$(document).unbind('.jcrop');}function trackMove(e){onMove(mouseAbs(e));return false;}function trackUp(e){e.preventDefault();e.stopPropagation();if(btndown){btndown=false;onDone(mouseAbs(e));if(Selection.isAwake()){options.onSelect.call(api,unscale(Coords.getFixed()));}toBack();onMove=function(){};onDone=function(){};}return false;}function activateHandlers(move,done,touch){btndown=true;onMove=move;onDone=done;toFront(touch);return false;}function trackTouchMove(e)
|
||||
{onMove(mouseAbs(Touch.cfilter(e)));return false;}function trackTouchEnd(e){return trackUp(Touch.cfilter(e));}function setCursor(t){$trk.css('cursor',t);}if(!trackDoc){$trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp);}$img.before($trk);return{activateHandlers:activateHandlers,setCursor:setCursor};}());var KeyManager=(function(){var $keymgr=$('<input type="radio" />').css({position:'fixed',left:'-120px',width:'12px'}).addClass('jcrop-keymgr'),$keywrap=$('<div />').css({position:'absolute',overflow:'hidden'}).append($keymgr);function watchKeys(){if(options.keySupport){$keymgr.show();$keymgr.focus();}}function onBlur(e){$keymgr.hide();}function doNudge(e,x,y){if(options.allowMove){Coords.moveOffset([x,y]);Selection.updateVisible(true);}e.preventDefault();e.stopPropagation();}function parseKey(e){if(e.ctrlKey||e.metaKey){return true;}shift_down=e.shiftKey?true:false;var nudge=shift_down?10:1;switch(e.keyCode){case 37:doNudge(e,-nudge,0);break;case 39:doNudge(e,nudge,0);break;
|
||||
case 38:doNudge(e,0,-nudge);break;case 40:doNudge(e,0,nudge);break;case 27:if(options.allowSelect)Selection.release();break;case 9:return true;}return false;}if(options.keySupport){$keymgr.keydown(parseKey).blur(onBlur);if(ie6mode||!options.fixedSupport){$keymgr.css({position:'absolute',left:'-20px'});$keywrap.append($keymgr).insertBefore($img);}else{$keymgr.insertBefore($img);}}return{watchKeys:watchKeys};}());function setClass(cname){$div.removeClass().addClass(cssClass('holder')).addClass(cname);}function animateTo(a,callback){var x1=a[0]/xscale,y1=a[1]/yscale,x2=a[2]/xscale,y2=a[3]/yscale;if(animating){return;}var animto=Coords.flipCoords(x1,y1,x2,y2),c=Coords.getFixed(),initcr=[c.x,c.y,c.x2,c.y2],animat=initcr,interv=options.animationDelay,ix1=animto[0]-initcr[0],iy1=animto[1]-initcr[1],ix2=animto[2]-initcr[2],iy2=animto[3]-initcr[3],pcent=0,velocity=options.swingSpeed;x1=animat[0];y1=animat[1];x2=animat[2];y2=animat[3];Selection.animMode(true);var anim_timer;function queueAnimator(){
|
||||
window.setTimeout(animator,interv);}var animator=(function(){return function(){pcent+=(100-pcent)/velocity;animat[0]=Math.round(x1+((pcent/100)*ix1));animat[1]=Math.round(y1+((pcent/100)*iy1));animat[2]=Math.round(x2+((pcent/100)*ix2));animat[3]=Math.round(y2+((pcent/100)*iy2));if(pcent>=99.8){pcent=100;}if(pcent<100){setSelectRaw(animat);queueAnimator();}else{Selection.done();Selection.animMode(false);if(typeof(callback)==='function'){callback.call(api);}}};}());queueAnimator();}function setSelect(rect){setSelectRaw([rect[0]/xscale,rect[1]/yscale,rect[2]/xscale,rect[3]/yscale]);options.onSelect.call(api,unscale(Coords.getFixed()));Selection.enableHandles();}function setSelectRaw(l){Coords.setPressed([l[0],l[1]]);Coords.setCurrent([l[2],l[3]]);Selection.update();}function tellSelect(){return unscale(Coords.getFixed());}function tellScaled(){return Coords.getFixed();}function setOptionsNew(opt){setOptions(opt);interfaceUpdate();}function disableCrop(){options.disabled=true;Selection.disableHandles();
|
||||
Selection.setCursor('default');Tracker.setCursor('default');}function enableCrop(){options.disabled=false;interfaceUpdate();}function cancelCrop(){Selection.done();Tracker.activateHandlers(null,null);}function destroy(){$(document).unbind('touchstart.jcrop-ios',Touch.fixTouchSupport);$div.remove();$origimg.show();$origimg.css('visibility','visible');$(obj).removeData('Jcrop');}function setImage(src,callback){Selection.release();disableCrop();var img=new Image();img.onload=function(){var iw=img.width;var ih=img.height;var bw=options.boxWidth;var bh=options.boxHeight;$img.width(iw).height(ih);$img.attr('src',src);$img2.attr('src',src);presize($img,bw,bh);boundx=$img.width();boundy=$img.height();$img2.width(boundx).height(boundy);$trk.width(boundx+(bound*2)).height(boundy+(bound*2));$div.width(boundx).height(boundy);Shade.resize(boundx,boundy);enableCrop();if(typeof(callback)==='function'){callback.call(api);}};img.src=src;}function colorChangeMacro($obj,color,now){var mycolor=color||options.bgColor;
|
||||
if(options.bgFade&&supportsColorFade()&&options.fadeTime&&!now){$obj.animate({backgroundColor:mycolor},{queue:false,duration:options.fadeTime});}else{$obj.css('backgroundColor',mycolor);}}function interfaceUpdate(alt){if(options.allowResize){if(alt){Selection.enableOnly();}else{Selection.enableHandles();}}else{Selection.disableHandles();}Tracker.setCursor(options.allowSelect?'crosshair':'default');Selection.setCursor(options.allowMove?'move':'default');if(options.hasOwnProperty('trueSize')){xscale=options.trueSize[0]/boundx;yscale=options.trueSize[1]/boundy;}if(options.hasOwnProperty('setSelect')){setSelect(options.setSelect);Selection.done();delete(options.setSelect);}Shade.refresh();if(options.bgColor!=bgcolor){colorChangeMacro(options.shade?Shade.getShades():$div,options.shade?(options.shadeColor||options.bgColor):options.bgColor);bgcolor=options.bgColor;}if(bgopacity!=options.bgOpacity){bgopacity=options.bgOpacity;if(options.shade)Shade.refresh();else Selection.setBgOpacity(bgopacity);
|
||||
}xlimit=options.maxSize[0]||0;ylimit=options.maxSize[1]||0;xmin=options.minSize[0]||0;ymin=options.minSize[1]||0;if(options.hasOwnProperty('outerImage')){$img.attr('src',options.outerImage);delete(options.outerImage);}Selection.refresh();}if(Touch.support)$trk.bind('touchstart.jcrop',Touch.newSelection);$hdl_holder.hide();interfaceUpdate(true);var api={setImage:setImage,animateTo:animateTo,setSelect:setSelect,setOptions:setOptionsNew,tellSelect:tellSelect,tellScaled:tellScaled,setClass:setClass,disable:disableCrop,enable:enableCrop,cancel:cancelCrop,release:Selection.release,destroy:destroy,focus:KeyManager.watchKeys,getBounds:function(){return[boundx*xscale,boundy*yscale];},getWidgetSize:function(){return[boundx,boundy];},getScaleFactor:function(){return[xscale,yscale];},getOptions:function(){return options;},ui:{holder:$div,selection:$sel}};if(is_msie)$div.bind('selectstart',function(){return false;});$origimg.data('Jcrop',api);return api;};$.fn.Jcrop=function(options,callback){var api;
|
||||
this.each(function(){if($(this).data('Jcrop')){if(options==='api')return $(this).data('Jcrop');else $(this).data('Jcrop').setOptions(options);}else{if(this.tagName=='IMG')$.Jcrop.Loader(this,function(){$(this).css({display:'block',visibility:'hidden'});api=$.Jcrop(this,options);if($.isFunction(callback))callback.call(api);});else{$(this).css({display:'block',visibility:'hidden'});api=$.Jcrop(this,options);if($.isFunction(callback))callback.call(api);}}});return this;};$.Jcrop.Loader=function(imgobj,success,error){var $img=$(imgobj),img=$img[0];function completeCheck(){if(img.complete){$img.unbind('.jcloader');if($.isFunction(success))success.call(img);}else window.setTimeout(completeCheck,50);}$img.bind('load.jcloader',completeCheck).bind('error.jcloader',function(e){$img.unbind('.jcloader');if($.isFunction(error))error.call(img);});if(img.complete&&$.isFunction(success)){$img.unbind('.jcloader');success.call(img);}};$.Jcrop.defaults={allowSelect:true,allowMove:true,allowResize:true,
|
||||
trackDocument:true,baseClass:'jcrop',addClass:null,bgColor:'black',bgOpacity:0.6,bgFade:false,borderOpacity:0.4,handleOpacity:0.5,handleSize:null,aspectRatio:0,keySupport:true,createHandles:['n','s','e','w','nw','ne','se','sw'],createDragbars:['n','s','e','w'],createBorders:['n','s','e','w'],drawBorders:true,dragEdges:true,fixedSupport:true,touchSupport:null,shade:null,boxWidth:0,boxHeight:0,boundary:2,fadeTime:400,animationDelay:20,swingSpeed:3,minSelect:[0,0],maxSize:[0,0],minSize:[0,0],onChange:function(){},onSelect:function(){},onDblClick:function(){},onRelease:function(){}};}(jQuery));!function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;(function(){function S(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:"0"<=a&&a<="7"?parseInt(e.substring(1),8):a==="u"||a==="x"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return e==="\\"||e==="-"||e==="]"||e==="^"?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),e=[],a=
|
||||
b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,f=b.length;a<f;++a){var h=b[a];if(/\\[bdsw]/i.test(h))c.push(h);else{var h=d(h),l;a+2<f&&"-"===b[a+1]?(l=d(b[a+2]),a+=2):l=h;e.push([h,l]);l<65||h>122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;a<e.length;++a)h=e[a],h[0]<=f[1]+1?f[1]=Math.max(f[1],h[1]):b.push(f=h);for(a=0;a<b.length;++a)h=b[a],c.push(g(h[0])),h[1]>h[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(g(h[1])));c.push("]");return c.join("")}function s(e){for(var a=e.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],f=0,h=0;f<c;++f){var l=a[f];l==="("?++h:"\\"===l.charAt(0)&&(l=+l.substring(1))&&(l<=h?d[l]=-1:a[f]=g(l))}for(f=1;f<d.length;++f)-1===d[f]&&(d[f]=++x);for(h=f=0;f<c;++f)l=a[f],l==="("?(++h,d[h]||(a[f]="(?:")):"\\"===l.charAt(0)&&(l=+l.substring(1))&&l<=h&&
|
||||
(a[f]="\\"+d[l]);for(f=0;f<c;++f)"^"===a[f]&&"^"!==a[f+1]&&(a[f]="");if(e.ignoreCase&&m)for(f=0;f<c;++f)l=a[f],e=l.charAt(0),l.length>=2&&e==="["?a[f]=b(l):e!=="\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k<c;++k){var i=a[k];if(i.ignoreCase)j=!0;else if(/[a-z]/i.test(i.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){m=!0;j=!1;break}}for(var r={b:8,t:9,n:10,v:11,f:12,r:13},n=[],k=0,c=a.length;k<c;++k){i=a[k];if(i.global||i.multiline)throw Error(""+i);n.push("(?:"+s(i)+")")}return RegExp(n.join("|"),j?"gi":"g")}function T(a,d){function g(a){var c=a.nodeType;if(c==1){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)g(c);c=a.nodeName.toLowerCase();if("br"===c||"li"===c)s[j]="\n",m[j<<1]=x++,m[j++<<1|1]=a}}else if(c==3||c==4)c=a.nodeValue,c.length&&(c=d?c.replace(/\r\n?/g,"\n"):c.replace(/[\t\n\r ]+/g," "),s[j]=c,m[j<<1]=x,x+=c.length,m[j++<<1|1]=
|
||||
a)}var b=/(?:^|\s)nocode(?:\s|$)/,s=[],x=0,m=[],j=0;g(a);return{a:s.join("").replace(/\n$/,""),d:m}}function H(a,d,g,b){d&&(a={a:d,e:a},g(a),b.push.apply(b,a.g))}function U(a){for(var d=void 0,g=a.firstChild;g;g=g.nextSibling)var b=g.nodeType,d=b===1?d?a:g:b===3?V.test(g.nodeValue)?a:d:d;return d===a?void 0:d}function C(a,d){function g(a){for(var j=a.e,k=[j,"pln"],c=0,i=a.a.match(s)||[],r={},n=0,e=i.length;n<e;++n){var z=i[n],w=r[z],t=void 0,f;if(typeof w==="string")f=!1;else{var h=b[z.charAt(0)];if(h)t=z.match(h[1]),w=h[0];else{for(f=0;f<x;++f)if(h=d[f],t=z.match(h[1])){w=h[0];break}t||(w="pln")}if((f=w.length>=5&&"lang-"===w.substring(0,5))&&!(t&&typeof t[1]==="string"))f=!1,w="src";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c<i;++c){var r=
|
||||
g[c],n=r[3];if(n)for(var e=n.length;--e>=0;)b[n.charAt(e)]=r;r=r[1];n=""+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\S\s]/);s=S(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&g.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),g.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,q])):d.push(["com",
|
||||
/^#[^\n\r]*/,q,"#"]));a.cStyleComments&&(g.push(["com",/^\/\/[^\n\r]*/,q]),g.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?"":"\n\r")?".":"[\\S\\s]";g.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+s+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,
|
||||
q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d=c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i<c.length;++i)b(c[i]);d===(d|0)&&c[0].setAttribute("value",d);var r=j.createElement("ol");
|
||||
r.className="linenums";for(var d=Math.max(0,d-1|0)||0,i=0,n=c.length;i<n;++i)k=c[i],k.className="L"+(i+d)%10,k.firstChild||k.appendChild(j.createTextNode("\u00a0")),r.appendChild(k);a.appendChild(r)}function p(a,d){for(var g=d.length;--g>=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*</.test(d)?"default-markup":"default-code";return F[a]}function K(a){var d=a.h;try{var g=T(a.c,a.i),b=g.a;a.a=b;a.d=g.d;a.e=0;I(d,b)(a);var s=/\bMSIE\s(\d+)/.exec(navigator.userAgent),s=s&&+s[1]<=8,d=/\n/g,x=a.a,m=x.length,g=0,j=a.d,k=j.length,b=0,c=a.g,i=c.length,r=0;c[i]=m;var n,e;for(e=n=0;e<i;)c[e]!==c[e+2]?(c[n++]=c[e++],c[n++]=c[e++]):e+=2;i=n;for(e=n=0;e<i;){for(var p=c[e],w=c[e+1],t=e+2;t+2<=i&&c[t+1]===w;)t+=2;c[n++]=p;c[n++]=w;e=t}c.length=n;var f=a.c,h;if(f)h=f.style.display,f.style.display="none";try{for(;b<k;){var l=j[b+2]||m,B=c[r+2]||m,t=Math.min(l,B),A=j[b+1],G;if(A.nodeType!==1&&(G=x.substring(g,
|
||||
t))){s&&(G=G.replace(d,"\r"));A.nodeValue=G;var L=A.ownerDocument,o=L.createElement("span");o.className=c[r+1];var v=A.parentNode;v.replaceChild(o,A);o.appendChild(A);g<l&&(j[b+1]=A=L.createTextNode(x.substring(t,l)),v.insertBefore(A,o.nextSibling))}g=t;g>=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],
|
||||
O=[N,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],E=[E,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],P=[y,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],Q=[y,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],W=[y,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],y=[y,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],R=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,
|
||||
V=/\S/,X=v({keywords:[M,O,E,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",P,Q,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,["default-code"]);p(C([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);p(C([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],
|
||||
["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);p(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);p(v({keywords:M,hashComments:!0,cStyleComments:!0,types:R}),["c","cc","cpp","cxx","cyc","m"]);p(v({keywords:"null,true,false"}),["json"]);p(v({keywords:O,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:R}),["cs"]);p(v({keywords:N,cStyleComments:!0}),["java"]);p(v({keywords:y,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(v({keywords:P,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(v({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);p(v({keywords:Q,
|
||||
hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(v({keywords:E,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(v({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(v({keywords:W,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]);p(C([],[["str",/^[\S\s]+/]]),["regex"]);var Y=D.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:v,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:D.prettyPrintOne=function(a,d,g){var b=document.createElement("div");b.innerHTML="<pre>"+a+"</pre>";b=b.firstChild;g&&J(b,g,!0);K({h:d,j:g,c:b,i:1});
|
||||
return b.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function g(){for(var b=D.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;i<p.length&&c.now()<b;i++){for(var d=p[i],j=h,k=d;k=k.previousSibling;){var m=k.nodeType,o=(m===7||m===8)&&k.nodeValue;if(o?!/^\??prettify\b/.test(o):m!==3||/\S/.test(k.nodeValue))break;if(o){j={};o.replace(/\b(\w+)=([\w%+\-.:]+)/g,function(a,b,c){j[b]=c});break}}k=d.className;if((j!==h||e.test(k))&&!v.test(k)){m=!1;for(o=d.parentNode;o;o=o.parentNode)if(f.test(o.tagName)&&o.className&&e.test(o.className)){m=!0;break}if(!m){d.className+=" prettyprinted";m=j.lang;if(!m){var m=k.match(n),y;if(!m&&(y=U(d))&&t.test(y.tagName))m=y.className.match(n);m&&(m=m[1])}if(w.test(d.tagName))o=1;else var o=d.currentStyle,u=s.defaultView,o=(o=o?o.whiteSpace:u&&u.getComputedStyle?u.getComputedStyle(d,q).getPropertyValue("white-space"):0)&&"pre"===o.substring(0,3);u=j.linenums;if(!(u=u==="true"||+u))u=(u=k.match(/\blinenums\b(?::(\d+))?/))?u[1]&&u[1].length?+u[1]:!0:!1;u&&J(d,u,o);r=
|
||||
{h:m,c:d,j:u,i:o};K(r)}}}i<p.length?setTimeout(g,250):"function"===typeof a&&a()}for(var b=d||document.body,s=b.ownerDocument||document,b=[b.getElementsByTagName("pre"),b.getElementsByTagName("code"),b.getElementsByTagName("xmp")],p=[],m=0;m<b.length;++m)for(var j=0,k=b[m].length;j<k;++j)p.push(b[m][j]);var b=q,c=Date;c.now||(c={now:function(){return+new Date}});var i=0,r,n=/\blang(?:uage)?-([\w.]+)(?!\S)/,e=/\bprettyprint\b/,v=/\bprettyprinted\b/,w=/pre|xmp/i,t=/^code$/i,f=/^(?:pre|code|xmp)$/i,h={};g()}};typeof define==="function"&&define.amd&&define("google-code-prettify",[],function(){return Y})})();}()+function($){"use strict";if($.wn.mediaManager===undefined)$.wn.mediaManager={}
|
||||
var Base=$.wn.foundation.base,BaseProto=Base.prototype
|
||||
var MediaManagerPopup=function(options){this.$popupRootElement=null
|
||||
this.options=$.extend({},MediaManagerPopup.DEFAULTS,options)
|
||||
Base.call(this)
|
||||
this.init()
|
||||
this.show()}
|
||||
MediaManagerPopup.prototype=Object.create(BaseProto)
|
||||
MediaManagerPopup.prototype.constructor=MediaManagerPopup
|
||||
MediaManagerPopup.prototype.dispose=function(){this.unregisterHandlers()
|
||||
this.$popupRootElement.remove()
|
||||
this.$popupRootElement=null
|
||||
this.$popupElement=null
|
||||
BaseProto.dispose.call(this)}
|
||||
MediaManagerPopup.prototype.init=function(){if(this.options.alias===undefined)throw new Error('Media Manager popup option "alias" is not set.')
|
||||
this.$popupRootElement=$('<div/>')
|
||||
this.registerHandlers()}
|
||||
MediaManagerPopup.prototype.registerHandlers=function(){this.$popupRootElement.one('hide.oc.popup',this.proxy(this.onPopupHidden))
|
||||
this.$popupRootElement.one('shown.oc.popup',this.proxy(this.onPopupShown))}
|
||||
MediaManagerPopup.prototype.unregisterHandlers=function(){this.$popupElement.off('popupcommand',this.proxy(this.onPopupCommand))
|
||||
this.$popupRootElement.off('popupcommand',this.proxy(this.onPopupCommand))}
|
||||
MediaManagerPopup.prototype.show=function(){var data={bottomToolbar:this.options.bottomToolbar?1:0,cropAndInsertButton:this.options.cropAndInsertButton?1:0,mode:this.options.mode||'all',}
|
||||
this.$popupRootElement.popup({extraData:data,size:'adaptive',adaptiveHeight:true,handler:this.options.alias+'::onLoadPopup'})}
|
||||
MediaManagerPopup.prototype.hide=function(){if(this.$popupElement)this.$popupElement.trigger('close.oc.popup')}
|
||||
MediaManagerPopup.prototype.getMediaManagerElement=function(){return this.$popupElement.find('[data-control="media-manager"]')}
|
||||
MediaManagerPopup.prototype.insertMedia=function(){var items=this.getMediaManagerElement().mediaManager('getSelectedItems')
|
||||
if(this.options.onInsert!==undefined)this.options.onInsert.call(this,items)}
|
||||
MediaManagerPopup.prototype.insertCroppedImage=function(imageItem){if(this.options.onInsert!==undefined)this.options.onInsert.call(this,[imageItem])}
|
||||
MediaManagerPopup.prototype.onPopupHidden=function(event,element,popup){var mediaManager=this.getMediaManagerElement()
|
||||
mediaManager.mediaManager('dispose')
|
||||
mediaManager.remove()
|
||||
$(document).trigger('mousedown')
|
||||
this.dispose()
|
||||
if(this.options.onClose!==undefined)this.options.onClose.call(this)}
|
||||
MediaManagerPopup.prototype.onPopupShown=function(event,element,popup){this.$popupElement=popup
|
||||
this.$popupElement.on('popupcommand',this.proxy(this.onPopupCommand))
|
||||
this.getMediaManagerElement().mediaManager('selectFirstItem')}
|
||||
MediaManagerPopup.prototype.onPopupCommand=function(ev,command,param){switch(command){case'insert':this.insertMedia()
|
||||
break;case'insert-cropped':this.insertCroppedImage(param)
|
||||
break;}return false}
|
||||
MediaManagerPopup.DEFAULTS={alias:undefined,bottomToolbar:true,cropAndInsertButton:false,onInsert:undefined,onClose:undefined}
|
||||
$.wn.mediaManager.popup=MediaManagerPopup}(window.jQuery);if($.wn===undefined)$.wn={}
|
||||
if($.oc===undefined)$.oc=$.wn
|
||||
if($.wn.langMessages===undefined)$.wn.langMessages={}
|
||||
$.wn.lang=(function(lang,messages){lang.load=function(locale){if(messages[locale]===undefined){messages[locale]={}}lang.loadedMessages=messages[locale]}
|
||||
lang.get=function(name,defaultValue){if(!name)return
|
||||
var result=lang.loadedMessages
|
||||
if(!defaultValue)defaultValue=name
|
||||
$.each(name.split('.'),function(index,value){if(result[value]===undefined){result=defaultValue
|
||||
return false}result=result[value]})
|
||||
return result}
|
||||
if(lang.locale===undefined){lang.locale=$('html').attr('lang')||'en'}if(lang.loadedMessages===undefined){lang.load(lang.locale)}return lang})($.wn.lang||{},$.wn.langMessages);(function($){if($.wn===undefined)$.wn={}
|
||||
if($.oc===undefined)$.oc=$.wn
|
||||
$.wn.alert=function alert(message){swal({title:message,confirmButtonClass:'btn-primary'})}
|
||||
$.wn.confirm=function confirm(message,callback){swal({title:message,showCancelButton:true,confirmButtonClass:'btn-primary'},callback)}})(jQuery);$(window).on('ajaxErrorMessage',function(event,message){if(!message)return
|
||||
$.wn.alert(message)
|
||||
event.preventDefault()})
|
||||
$(window).on('ajaxConfirmMessage',function(event,message){if(!message)return
|
||||
$.wn.confirm(message,function(isConfirm){isConfirm?event.promise.resolve():event.promise.reject()})
|
||||
event.preventDefault()
|
||||
return true})
|
||||
$(document).ready(function(){if(!window.swal)return
|
||||
var swal=window.swal
|
||||
window.sweetAlert=window.swal=function(message,callback){if(typeof message==='object'){message.confirmButtonText=message.confirmButtonText||$.wn.lang.get('alert.confirm_button_text')
|
||||
message.cancelButtonText=message.cancelButtonText||$.wn.lang.get('alert.cancel_button_text')}else{message={title:message,confirmButtonText:$.wn.lang.get('alert.confirm_button_text'),cancelButtonText:$.wn.lang.get('alert.cancel_button_text')}}swal(message,callback)}})+function($){"use strict";var Base=$.wn.foundation.base,BaseProto=Base.prototype
|
||||
var Scrollpad=function(element,options){this.$el=$(element)
|
||||
this.scrollbarElement=null
|
||||
this.dragHandleElement=null
|
||||
this.scrollContentElement=null
|
||||
this.contentElement=null
|
||||
this.options=options
|
||||
this.scrollbarSize=null
|
||||
this.updateScrollbarTimer=null
|
||||
this.dragOffset=null
|
||||
Base.call(this)
|
||||
this.init()
|
||||
$.wn.foundation.controlUtils.markDisposable(element)}
|
||||
Scrollpad.prototype=Object.create(BaseProto)
|
||||
Scrollpad.prototype.constructor=Scrollpad
|
||||
Scrollpad.prototype.dispose=function(){this.unregisterHandlers()
|
||||
this.$el.get(0).removeChild(this.scrollbarElement)
|
||||
this.$el.removeData('oc.scrollpad')
|
||||
this.$el=null
|
||||
this.scrollbarElement=null
|
||||
this.dragHandleElement=null
|
||||
this.scrollContentElement=null
|
||||
this.contentElement=null
|
||||
BaseProto.dispose.call(this)}
|
||||
Scrollpad.prototype.scrollToStart=function(){var scrollAttr=this.options.direction=='vertical'?'scrollTop':'scrollLeft'
|
||||
this.scrollContentElement[scrollAttr]=0}
|
||||
Scrollpad.prototype.update=function(){this.updateScrollbarSize()}
|
||||
Scrollpad.prototype.init=function(){this.build()
|
||||
this.setScrollContentSize()
|
||||
this.registerHandlers()}
|
||||
Scrollpad.prototype.build=function(){var el=this.$el.get(0)
|
||||
this.scrollContentElement=el.children[0]
|
||||
this.contentElement=this.scrollContentElement.children[0]
|
||||
this.$el.prepend('<div class="scrollpad-scrollbar"><div class="drag-handle"></div></div>')
|
||||
this.scrollbarElement=el.querySelector('.scrollpad-scrollbar')
|
||||
this.dragHandleElement=el.querySelector('.scrollpad-scrollbar > .drag-handle')}
|
||||
Scrollpad.prototype.registerHandlers=function(){this.$el.on('mouseenter',this.proxy(this.onMouseEnter))
|
||||
this.$el.on('mouseleave',this.proxy(this.onMouseLeave))
|
||||
this.$el.one('dispose-control',this.proxy(this.dispose))
|
||||
this.scrollContentElement.addEventListener('scroll',this.proxy(this.onScroll))
|
||||
this.dragHandleElement.addEventListener('mousedown',this.proxy(this.onStartDrag))}
|
||||
Scrollpad.prototype.unregisterHandlers=function(){this.$el.off('mouseenter',this.proxy(this.onMouseEnter))
|
||||
this.$el.off('mouseleave',this.proxy(this.onMouseLeave))
|
||||
this.$el.off('dispose-control',this.proxy(this.dispose))
|
||||
this.scrollContentElement.removeEventListener('scroll',this.proxy(this.onScroll))
|
||||
this.dragHandleElement.removeEventListener('mousedown',this.proxy(this.onStartDrag))
|
||||
document.removeEventListener('mousemove',this.proxy(this.onMouseMove))
|
||||
document.removeEventListener('mouseup',this.proxy(this.onEndDrag))}
|
||||
Scrollpad.prototype.setScrollContentSize=function(){var scrollbarSize=this.getScrollbarSize()
|
||||
if(this.options.direction=='vertical')this.scrollContentElement.setAttribute('style','margin-right: -'+scrollbarSize+'px')
|
||||
else this.scrollContentElement.setAttribute('style','margin-bottom: -'+scrollbarSize+'px')}
|
||||
Scrollpad.prototype.getScrollbarSize=function(){if(this.scrollbarSize!==null)return this.scrollbarSize
|
||||
var testerElement=document.createElement('div')
|
||||
testerElement.setAttribute('class','scrollpad-scrollbar-size-tester')
|
||||
testerElement.appendChild(document.createElement('div'))
|
||||
document.body.appendChild(testerElement)
|
||||
var width=testerElement.offsetWidth,innerWidth=testerElement.querySelector('div').offsetWidth
|
||||
document.body.removeChild(testerElement)
|
||||
if(width===innerWidth&&navigator.userAgent.toLowerCase().indexOf('firefox')>-1)return this.scrollbarSize=17
|
||||
return this.scrollbarSize=width-innerWidth}
|
||||
Scrollpad.prototype.updateScrollbarSize=function(){this.scrollbarElement.removeAttribute('data-hidden')
|
||||
var contentSize=this.options.direction=='vertical'?this.contentElement.scrollHeight:this.contentElement.scrollWidth,scrollOffset=this.options.direction=='vertical'?this.scrollContentElement.scrollTop:this.scrollContentElement.scrollLeft,scrollbarSize=this.options.direction=='vertical'?this.scrollbarElement.offsetHeight:this.scrollbarElement.offsetWidth,scrollbarRatio=scrollbarSize/contentSize,handleOffset=Math.round(scrollbarRatio*scrollOffset)+2,handleSize=Math.floor(scrollbarRatio*(scrollbarSize-2))-2;if(scrollbarSize<contentSize){if(this.options.direction=='vertical')this.dragHandleElement.setAttribute('style','top: '+handleOffset+'px; height: '+handleSize+'px')
|
||||
else this.dragHandleElement.setAttribute('style','left: '+handleOffset+'px; width: '+handleSize+'px')
|
||||
this.scrollbarElement.removeAttribute('data-hidden')}else this.scrollbarElement.setAttribute('data-hidden',true)}
|
||||
Scrollpad.prototype.displayScrollbar=function(){this.clearUpdateScrollbarTimer()
|
||||
this.updateScrollbarSize()
|
||||
this.scrollbarElement.setAttribute('data-visible','true')}
|
||||
Scrollpad.prototype.hideScrollbar=function(){this.scrollbarElement.removeAttribute('data-visible')}
|
||||
Scrollpad.prototype.clearUpdateScrollbarTimer=function(){if(this.updateScrollbarTimer===null)return
|
||||
clearTimeout(this.updateScrollbarTimer)
|
||||
this.updateScrollbarTimer=null}
|
||||
Scrollpad.prototype.onMouseEnter=function(){this.displayScrollbar()}
|
||||
Scrollpad.prototype.onMouseLeave=function(){this.hideScrollbar()}
|
||||
Scrollpad.prototype.onScroll=function(){if(this.updateScrollbarTimer!==null)return
|
||||
this.updateScrollbarTimer=setTimeout(this.proxy(this.displayScrollbar),10)}
|
||||
Scrollpad.prototype.onStartDrag=function(ev){$.wn.foundation.event.stop(ev)
|
||||
var pageCoords=$.wn.foundation.event.pageCoordinates(ev),eventOffset=this.options.direction=='vertical'?pageCoords.y:pageCoords.x,handleCoords=$.wn.foundation.element.absolutePosition(this.dragHandleElement),handleOffset=this.options.direction=='vertical'?handleCoords.top:handleCoords.left
|
||||
this.dragOffset=eventOffset-handleOffset
|
||||
document.addEventListener('mousemove',this.proxy(this.onMouseMove))
|
||||
document.addEventListener('mouseup',this.proxy(this.onEndDrag))}
|
||||
Scrollpad.prototype.onMouseMove=function(ev){$.wn.foundation.event.stop(ev)
|
||||
var eventCoordsAttr=this.options.direction=='vertical'?'y':'x',elementCoordsAttr=this.options.direction=='vertical'?'top':'left',offsetAttr=this.options.direction=='vertical'?'offsetHeight':'offsetWidth',scrollAttr=this.options.direction=='vertical'?'scrollTop':'scrollLeft'
|
||||
var eventOffset=$.wn.foundation.event.pageCoordinates(ev)[eventCoordsAttr],scrollbarOffset=$.wn.foundation.element.absolutePosition(this.scrollbarElement)[elementCoordsAttr],dragPos=eventOffset-scrollbarOffset-this.dragOffset,scrollbarSize=this.scrollbarElement[offsetAttr],contentSize=this.contentElement[offsetAttr],dragPerc=dragPos/scrollbarSize
|
||||
if(dragPerc>1)dragPerc=1
|
||||
var scrollPos=dragPerc*contentSize;this.scrollContentElement[scrollAttr]=scrollPos}
|
||||
Scrollpad.prototype.onEndDrag=function(ev){document.removeEventListener('mousemove',this.proxy(this.onMouseMove))
|
||||
document.removeEventListener('mouseup',this.proxy(this.onEndDrag))}
|
||||
Scrollpad.DEFAULTS={direction:'vertical'}
|
||||
var old=$.fn.scrollpad
|
||||
$.fn.scrollpad=function(option){var args=Array.prototype.slice.call(arguments,1),result=undefined
|
||||
this.each(function(){var $this=$(this)
|
||||
var data=$this.data('oc.scrollpad')
|
||||
var options=$.extend({},Scrollpad.DEFAULTS,$this.data(),typeof option=='object'&&option)
|
||||
if(!data)$this.data('oc.scrollpad',(data=new Scrollpad(this,options)))
|
||||
if(typeof option=='string')result=data[option].apply(data,args)
|
||||
if(typeof result!='undefined')return false})
|
||||
return result?result:this}
|
||||
$.fn.scrollpad.Constructor=Scrollpad
|
||||
$.fn.scrollpad.noConflict=function(){$.fn.scrollpad=old
|
||||
return this}
|
||||
$(document).on('render',function(){$('div[data-control=scrollpad]').scrollpad()})}(window.jQuery);+function($){"use strict";var VerticalMenu=function(element,toggle,options){this.$el=$(element)
|
||||
this.body=$('body')
|
||||
this.toggle=$(toggle)
|
||||
this.options=options||{}
|
||||
this.options=$.extend({},VerticalMenu.DEFAULTS,this.options)
|
||||
this.wrapper=$(this.options.contentWrapper)
|
||||
this.breakpoint=options.breakpoint
|
||||
this.menuPanel=$('<div></div>').appendTo('body').addClass(this.options.collapsedMenuClass).css('width',0)
|
||||
this.menuContainer=$('<div></div>').appendTo(this.menuPanel).css('display','none')
|
||||
this.menuElement=this.$el.clone().appendTo(this.menuContainer).css('width','auto')
|
||||
var self=this
|
||||
this.toggle.click(function(){if(!self.body.hasClass(self.options.bodyMenuOpenClass)){var wrapperWidth=self.wrapper.outerWidth()
|
||||
self.menuElement.dragScroll('goToStart')
|
||||
self.wrapper.css({'position':'absolute','min-width':self.wrapper.width(),'height':'100%'})
|
||||
self.body.addClass(self.options.bodyMenuOpenClass)
|
||||
self.menuContainer.css('display','block')
|
||||
self.wrapper.animate({'left':self.options.menuWidth},{duration:200,queue:false})
|
||||
self.menuPanel.animate({'width':self.options.menuWidth},{duration:200,queue:false,complete:function(){self.menuElement.css('width',self.options.menuWidth)}})}else{closeMenu()}return false})
|
||||
this.wrapper.click(function(){if(self.body.hasClass(self.options.bodyMenuOpenClass)){closeMenu()
|
||||
return false}})
|
||||
$(window).resize(function(){if(self.body.hasClass(self.options.bodyMenuOpenClass)){if($(window).width()>self.breakpoint){hideMenu()}}})
|
||||
this.menuElement.dragScroll({vertical:true,useNative:true,start:function(){self.menuElement.addClass('drag')},stop:function(){self.menuElement.removeClass('drag')},scrollClassContainer:self.menuPanel,scrollMarkerContainer:self.menuContainer})
|
||||
this.menuElement.on('click',function(){if(self.menuElement.hasClass('drag'))return false})
|
||||
function hideMenu(){self.body.removeClass(self.options.bodyMenuOpenClass)
|
||||
self.wrapper.css({'position':'static','min-width':0,'right':0,'height':'100%'})
|
||||
self.menuPanel.css('width',0)
|
||||
self.menuElement.css('width','auto')
|
||||
self.menuContainer.css('display','none')}function closeMenu(){self.wrapper.animate({'left':0},{duration:200,queue:false})
|
||||
self.menuPanel.animate({'width':0},{duration:200,queue:false,complete:hideMenu})
|
||||
self.menuElement.animate({'width':0},{duration:200,queue:false})}}
|
||||
VerticalMenu.DEFAULTS={menuWidth:230,breakpoint:769,bodyMenuOpenClass:'mainmenu-open',collapsedMenuClass:'mainmenu-collapsed',contentWrapper:'#layout-canvas'}
|
||||
var old=$.fn.verticalMenu
|
||||
$.fn.verticalMenu=function(toggleSelector,option){return this.each(function(){var $this=$(this)
|
||||
var data=$this.data('oc.verticalMenu')
|
||||
var options=typeof option=='object'&&option
|
||||
if(!data)$this.data('oc.verticalMenu',(data=new VerticalMenu(this,toggleSelector,options)))
|
||||
if(typeof option=='string')data[option].call($this)})}
|
||||
$.fn.verticalMenu.Constructor=VerticalMenu
|
||||
$.fn.verticalMenu.noConflict=function(){$.fn.verticalMenu=old
|
||||
return this}}(window.jQuery);(function($){$(document).ready(function(){$('nav.navbar').each(function(){var navbar=$(this),nav=$('ul.nav',navbar),collapseMode=navbar.hasClass('navbar-mode-collapse'),isMobile=$('html').hasClass('mobile')
|
||||
nav.verticalMenu($('a.menu-toggle',navbar),{breakpoint:collapseMode?Infinity:769})
|
||||
$('li.with-tooltip:not(.active) > a',navbar).tooltip({container:'body',placement:'bottom',template:'<div class="tooltip mainmenu-tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'}).on('show.bs.tooltip',function(e){if(isMobile)e.preventDefault()})
|
||||
var dragScroll=$('[data-control=toolbar]',navbar).data('oc.dragScroll')
|
||||
if(dragScroll){dragScroll.goToElement($('ul.nav > li.active',navbar),undefined,{'duration':0})}})})})(jQuery);+function($){"use strict";if($.wn===undefined)$.wn={}
|
||||
if($.oc===undefined)$.oc=$.wn
|
||||
var SideNav=function(element,options){this.options=options
|
||||
this.$el=$(element)
|
||||
this.$list=$('ul',this.$el)
|
||||
this.$items=$('li',this.$list)
|
||||
this.init();}
|
||||
SideNav.DEFAULTS={activeClass:'active'}
|
||||
SideNav.prototype.init=function(){var self=this
|
||||
this.$list.dragScroll({vertical:true,useNative:true,start:function(){self.$list.addClass('drag')},stop:function(){self.$list.removeClass('drag')},scrollClassContainer:self.$el,scrollMarkerContainer:self.$el})
|
||||
this.$list.on('click',function(){if(self.$list.hasClass('drag')){return false}})}
|
||||
SideNav.prototype.unsetActiveItem=function(itemId){this.$items.removeClass(this.options.activeClass)}
|
||||
SideNav.prototype.setActiveItem=function(itemId){if(!itemId){return}this.$items.removeClass(this.options.activeClass).filter('[data-menu-item='+itemId+']').addClass(this.options.activeClass)}
|
||||
SideNav.prototype.setCounter=function(itemId,value){var $counter=$('span.counter[data-menu-id="'+itemId+'"]',this.$el)
|
||||
$counter.removeClass('empty')
|
||||
$counter.toggleClass('empty',value==0)
|
||||
$counter.text(value)
|
||||
return this}
|
||||
SideNav.prototype.increaseCounter=function(itemId,value){var $counter=$('span.counter[data-menu-id="'+itemId+'"]',this.$el)
|
||||
var originalValue=parseInt($counter.text())
|
||||
if(isNaN(originalValue))originalValue=0
|
||||
var newValue=value+originalValue
|
||||
$counter.toggleClass('empty',newValue==0)
|
||||
$counter.text(newValue)
|
||||
return this}
|
||||
SideNav.prototype.dropCounter=function(itemId){this.setCounter(itemId,0)
|
||||
return this}
|
||||
var old=$.fn.sideNav
|
||||
$.fn.sideNav=function(option){var args=Array.prototype.slice.call(arguments,1),result
|
||||
this.each(function(){var $this=$(this)
|
||||
var data=$this.data('oc.sideNav')
|
||||
var options=$.extend({},SideNav.DEFAULTS,$this.data(),typeof option=='object'&&option)
|
||||
if(!data)$this.data('oc.sideNav',(data=new SideNav(this,options)))
|
||||
if(typeof option=='string')result=data[option].apply(data,args)
|
||||
if(typeof result!='undefined')return false
|
||||
if($.wn.sideNav===undefined)$.wn.sideNav=data})
|
||||
return result?result:this}
|
||||
$.fn.sideNav.Constructor=SideNav
|
||||
$.fn.sideNav.noConflict=function(){$.fn.sideNav=old
|
||||
return this}
|
||||
$(document).ready(function(){$('[data-control="sidenav"]').sideNav()})}(window.jQuery);+function($){"use strict";var Base=$.wn.foundation.base,BaseProto=Base.prototype
|
||||
var Scrollbar=function(element,options){var $el=this.$el=$(element),el=$el.get(0),self=this,options=this.options=options||{},sizeName=this.sizeName=options.vertical?'height':'width',isNative=$('html').hasClass('mobile'),isTouch=this.isTouch=Modernizr.touchevents,isScrollable=this.isScrollable=false,isLocked=this.isLocked=false,eventElementName=options.vertical?'pageY':'pageX',dragStart=0,startOffset=0;$.wn.foundation.controlUtils.markDisposable(element)
|
||||
Base.call(this)
|
||||
this.$el.one('dispose-control',this.proxy(this.dispose))
|
||||
if(isNative){return}this.$scrollbar=$('<div />').addClass('scrollbar-scrollbar')
|
||||
this.$track=$('<div />').addClass('scrollbar-track').appendTo(this.$scrollbar)
|
||||
this.$thumb=$('<div />').addClass('scrollbar-thumb').appendTo(this.$track)
|
||||
$el.addClass('drag-scrollbar').addClass(options.vertical?'vertical':'horizontal').prepend(this.$scrollbar)
|
||||
if(isTouch){this.$el.on('touchstart',function(event){var touchEvent=event.originalEvent;if(touchEvent.touches.length==1){startDrag(touchEvent.touches[0])
|
||||
event.stopPropagation()}})}else{this.$thumb.on('mousedown',function(event){startDrag(event)})
|
||||
this.$track.on('mouseup',function(event){moveDrag(event)})}$el.mousewheel(function(event){var offset=self.options.vertical?((event.deltaFactor*event.deltaY)*-1):(event.deltaFactor*event.deltaX)
|
||||
return!scrollWheel(offset*self.options.scrollSpeed)})
|
||||
$el.on('oc.scrollbar.gotoStart',function(event){self.options.vertical?$el.scrollTop(0):$el.scrollLeft(0)
|
||||
self.update()
|
||||
event.stopPropagation()})
|
||||
$(window).on('resize',$.proxy(this.update,this))
|
||||
$(window).on('oc.updateUi',$.proxy(this.update,this))
|
||||
function startDrag(event){$('body').addClass('drag-noselect')
|
||||
$el.trigger('oc.scrollStart')
|
||||
dragStart=event[eventElementName]
|
||||
startOffset=self.options.vertical?$el.scrollTop():$el.scrollLeft()
|
||||
if(isTouch){$(window).on('touchmove.scrollbar',function(event){var touchEvent=event.originalEvent
|
||||
if(moveDrag(touchEvent.touches[0]))event.preventDefault();});$el.on('touchend.scrollbar',stopDrag)}else{$(window).on('mousemove.scrollbar',function(event){moveDrag(event)
|
||||
return false})
|
||||
$(window).on('mouseup.scrollbar',function(){stopDrag()
|
||||
return false})}}function moveDrag(event){self.isLocked=true;var offset,dragTo=event[eventElementName]
|
||||
if(self.isTouch){offset=dragStart-dragTo}else{var ratio=self.getCanvasSize()/self.getViewportSize()
|
||||
offset=(dragTo-dragStart)*ratio}self.options.vertical?$el.scrollTop(startOffset+offset):$el.scrollLeft(startOffset+offset)
|
||||
self.setThumbPosition()
|
||||
return self.options.vertical?el.scrollTop!=startOffset:el.scrollLeft!=startOffset}function stopDrag(){$('body').removeClass('drag-noselect')
|
||||
$el.trigger('oc.scrollEnd')
|
||||
$(window).off('.scrollbar')}var isWebkit=$(document.documentElement).hasClass('webkit')
|
||||
function scrollWheel(offset){startOffset=self.options.vertical?el.scrollTop:el.scrollLeft
|
||||
$el.trigger('oc.scrollStart')
|
||||
self.options.vertical?$el.scrollTop(startOffset+offset):$el.scrollLeft(startOffset+offset)
|
||||
var scrolled=self.options.vertical?el.scrollTop!=startOffset:el.scrollLeft!=startOffset
|
||||
self.setThumbPosition()
|
||||
if(!isWebkit){if(self.endScrollTimeout!==undefined){clearTimeout(self.endScrollTimeout)
|
||||
self.endScrollTimeout=undefined}self.endScrollTimeout=setTimeout(function(){$el.trigger('oc.scrollEnd')
|
||||
self.endScrollTimeout=undefined},50)}else{$el.trigger('oc.scrollEnd')}return scrolled}setTimeout(function(){self.update()},1);}
|
||||
Scrollbar.prototype=Object.create(BaseProto)
|
||||
Scrollbar.prototype.constructor=Scrollbar
|
||||
Scrollbar.prototype.dispose=function(){this.unregisterHandlers()
|
||||
BaseProto.dispose.call(this)}
|
||||
Scrollbar.prototype.unregisterHandlers=function(){}
|
||||
Scrollbar.DEFAULTS={vertical:true,scrollSpeed:2,animation:true,start:function(){},drag:function(){},stop:function(){}}
|
||||
Scrollbar.prototype.update=function(){if(!this.$scrollbar)return
|
||||
this.$scrollbar.hide()
|
||||
this.setThumbSize()
|
||||
this.setThumbPosition()
|
||||
this.$scrollbar.show()}
|
||||
Scrollbar.prototype.setThumbSize=function(){var properties=this.calculateProperties()
|
||||
this.isScrollable=!(properties.thumbSizeRatio>=1);this.$scrollbar.toggleClass('disabled',!this.isScrollable)
|
||||
if(this.options.vertical){this.$track.height(properties.canvasSize)
|
||||
this.$thumb.height(properties.thumbSize)}else{this.$track.width(properties.canvasSize)
|
||||
this.$thumb.width(properties.thumbSize)}}
|
||||
Scrollbar.prototype.setThumbPosition=function(){var properties=this.calculateProperties()
|
||||
if(this.options.vertical)this.$thumb.css({top:properties.thumbPosition})
|
||||
else this.$thumb.css({left:properties.thumbPosition})}
|
||||
Scrollbar.prototype.calculateProperties=function(){var $el=this.$el,properties={};properties.viewportSize=this.getViewportSize()
|
||||
properties.canvasSize=this.getCanvasSize()
|
||||
properties.scrollAmount=(this.options.vertical)?$el.scrollTop():$el.scrollLeft()
|
||||
properties.thumbSizeRatio=properties.viewportSize/properties.canvasSize
|
||||
properties.thumbSize=properties.viewportSize*properties.thumbSizeRatio
|
||||
properties.thumbPositionRatio=properties.scrollAmount/(properties.canvasSize-properties.viewportSize)
|
||||
properties.thumbPosition=((properties.viewportSize-properties.thumbSize)*properties.thumbPositionRatio)+properties.scrollAmount
|
||||
if(isNaN(properties.thumbPosition))properties.thumbPosition=0
|
||||
return properties;}
|
||||
Scrollbar.prototype.getViewportSize=function(){return(this.options.vertical)?this.$el.height():this.$el.width();}
|
||||
Scrollbar.prototype.getCanvasSize=function(){return(this.options.vertical)?this.$el.get(0).scrollHeight:this.$el.get(0).scrollWidth;}
|
||||
Scrollbar.prototype.gotoElement=function(element,callback){var $el=$(element)
|
||||
if(!$el.length)return;var self=this,offset=0,animated=false,params={duration:300,queue:false,complete:function(){if(callback!==undefined)callback()}}
|
||||
if(!this.options.vertical){offset=$el.get(0).offsetLeft-this.$el.scrollLeft()
|
||||
if(offset<0){this.$el.animate({'scrollLeft':$el.get(0).offsetLeft},params)
|
||||
animated=true}else{offset=$el.get(0).offsetLeft+$el.outerWidth()-(this.$el.scrollLeft()+this.$el.outerWidth())
|
||||
if(offset>0){this.$el.animate({'scrollLeft':$el.get(0).offsetLeft+$el.outerWidth()-this.$el.outerWidth()},params)
|
||||
animated=true}}}else{offset=$el.get(0).offsetTop-this.$el.scrollTop()
|
||||
if(this.options.animation){if(offset<0){this.$el.animate({'scrollTop':$el.get(0).offsetTop},params)
|
||||
animated=true}else{offset=$el.get(0).offsetTop-(this.$el.scrollTop()+this.$el.outerHeight())
|
||||
if(offset>0){this.$el.animate({'scrollTop':$el.get(0).offsetTop+$el.outerHeight()-this.$el.outerHeight()},params)
|
||||
animated=true}}}else{if(offset<0){this.$el.scrollTop($el.get(0).offsetTop)}else{offset=$el.get(0).offsetTop-(this.$el.scrollTop()+this.$el.outerHeight())
|
||||
if(offset>0)this.$el.scrollTop($el.get(0).offsetTop+$el.outerHeight()-this.$el.outerHeight())}}}if(!animated&&callback!==undefined)callback()
|
||||
return this}
|
||||
Scrollbar.prototype.dispose=function(){this.$el=null
|
||||
this.$scrollbar=null
|
||||
this.$track=null
|
||||
this.$thumb=null}
|
||||
var old=$.fn.scrollbar
|
||||
$.fn.scrollbar=function(option){return this.each(function(){var $this=$(this)
|
||||
var data=$this.data('oc.scrollbar')
|
||||
var options=$.extend({},Scrollbar.DEFAULTS,$this.data(),typeof option=='object'&&option)
|
||||
if(!data)$this.data('oc.scrollbar',(data=new Scrollbar(this,options)))
|
||||
if(typeof option=='string')data[option].call($this)})}
|
||||
$.fn.scrollbar.Constructor=Scrollbar
|
||||
$.fn.scrollbar.noConflict=function(){$.fn.scrollbar=old
|
||||
return this}
|
||||
$(document).render(function(){$('[data-control=scrollbar]').scrollbar()})}(window.jQuery);+function($){"use strict";var FileList=function(element,options){this.options=options
|
||||
this.$el=$(element)
|
||||
this.init();}
|
||||
FileList.DEFAULTS={ignoreItemClick:false}
|
||||
FileList.prototype.init=function(){var self=this
|
||||
this.$el.on('click','li.group > h4 > a, li.group > div.group',function(){self.toggleGroup($(this).closest('li'))
|
||||
return false;});if(!this.options.ignoreItemClick){this.$el.on('click','li.item > a',function(event){var e=$.Event('open.oc.list',{relatedTarget:$(this).parent().get(0),clickEvent:event})
|
||||
self.$el.trigger(e,this)
|
||||
return false})}this.$el.on('ajaxUpdate',$.proxy(this.update,this))}
|
||||
FileList.prototype.toggleGroup=function(group){var $group=$(group);$group.attr('data-status')=='expanded'?this.collapseGroup($group):this.expandGroup($group)}
|
||||
FileList.prototype.collapseGroup=function(group){var $list=$('> ul, > div.subitems',group),self=this;$list.css('overflow','hidden')
|
||||
$list.animate({'height':0},{duration:100,queue:false,complete:function(){$list.css({'overflow':'visible','display':'none'})
|
||||
$(group).attr('data-status','collapsed')
|
||||
$(window).trigger('resize')}})
|
||||
this.sendGroupStatusRequest(group,0);}
|
||||
FileList.prototype.expandGroup=function(group){var $list=$('> ul, > div.subitems',group),self=this;$list.css({'overflow':'hidden','display':'block','height':0})
|
||||
$list.animate({'height':$list[0].scrollHeight},{duration:100,queue:false,complete:function(){$list.css({'overflow':'visible','height':'auto'})
|
||||
$(group).attr('data-status','expanded')
|
||||
$(window).trigger('resize')}})
|
||||
this.sendGroupStatusRequest(group,1);}
|
||||
FileList.prototype.sendGroupStatusRequest=function(group,status){if(this.options.groupStatusHandler!==undefined){var groupId=$(group).data('group-id')
|
||||
if(groupId===undefined)groupId=$('> h4 a',group).text();$(group).request(this.options.groupStatusHandler,{data:{group:groupId,status:status}})}}
|
||||
FileList.prototype.markActive=function(dataId){$('li.item',this.$el).removeClass('active')
|
||||
if(dataId)$('li.item[data-id="'+dataId+'"]',this.$el).addClass('active')
|
||||
this.dataId=dataId}
|
||||
FileList.prototype.update=function(){if(this.dataId!==undefined)this.markActive(this.dataId)}
|
||||
var old=$.fn.fileList
|
||||
$.fn.fileList=function(option){var args=arguments;return this.each(function(){var $this=$(this)
|
||||
var data=$this.data('oc.fileList')
|
||||
var options=$.extend({},FileList.DEFAULTS,$this.data(),typeof option=='object'&&option)
|
||||
if(!data)$this.data('oc.fileList',(data=new FileList(this,options)))
|
||||
if(typeof option=='string'){var methodArgs=[];for(var i=1;i<args.length;i++)methodArgs.push(args[i])
|
||||
data[option].apply(data,methodArgs)}})}
|
||||
$.fn.fileList.Constructor=FileList
|
||||
$.fn.fileList.noConflict=function(){$.fn.fileList=old
|
||||
return this}
|
||||
$(document).ready(function(){$('[data-control=filelist]').fileList()})}(window.jQuery);(function($){var WinterLayout=function(){this.$accountMenuOverlay=null}
|
||||
WinterLayout.prototype.setPageTitle=function(title){var $title=$('title')
|
||||
if(this.pageTitleTemplate===undefined)this.pageTitleTemplate=$title.data('titleTemplate')
|
||||
$title.text(this.pageTitleTemplate.replace('%s',title))}
|
||||
WinterLayout.prototype.updateLayout=function(title){var $children,$el,fixedWidth,margin
|
||||
$('[data-calculate-width]').each(function(){$children=$(this).children()
|
||||
if($children.length>0){fixedWidth=0
|
||||
$children.each(function(){$el=$(this)
|
||||
margin=$el.data('oc.layoutMargin')
|
||||
if(margin===undefined){margin=parseInt($el.css('marginRight'))+parseInt($el.css('marginLeft'))
|
||||
$el.data('oc.layoutMargin',margin)}fixedWidth+=$el.get(0).offsetWidth+margin})
|
||||
$(this).width(fixedWidth)
|
||||
$(this).trigger('oc.widthFixed')}})}
|
||||
WinterLayout.prototype.toggleAccountMenu=function(el){var self=this,$el=$(el),$parent=$(el).parent(),$menu=$el.next()
|
||||
$el.tooltip('hide')
|
||||
if($menu.hasClass('active')){self.$accountMenuOverlay.remove()
|
||||
$parent.removeClass('highlight')
|
||||
$menu.removeClass('active')}else{self.$accountMenuOverlay=$('<div />').addClass('popover-overlay')
|
||||
$(document.body).append(self.$accountMenuOverlay)
|
||||
$parent.addClass('highlight')
|
||||
$menu.addClass('active')
|
||||
self.$accountMenuOverlay.one('click',function(){self.$accountMenuOverlay.remove()
|
||||
$menu.removeClass('active')
|
||||
$parent.removeClass('highlight')})}}
|
||||
if($.wn===undefined)$.wn={}
|
||||
if($.oc===undefined)$.oc=$.wn
|
||||
$.wn.layout=new WinterLayout()
|
||||
$(document).ready(function(){$.wn.layout.updateLayout()
|
||||
window.setTimeout($.wn.layout.updateLayout,100)})
|
||||
$(window).on('resize',function(){$.wn.layout.updateLayout()})
|
||||
$(window).on('oc.updateUi',function(){$.wn.layout.updateLayout()})})(jQuery);+function($){"use strict";var SidePanelTab=function(element,options){this.options=options
|
||||
this.$el=$(element)
|
||||
this.init()}
|
||||
SidePanelTab.prototype.init=function(){var self=this
|
||||
this.tabOpenDelay=200
|
||||
this.tabOpenTimeout=undefined
|
||||
this.panelOpenTimeout=undefined
|
||||
this.$sideNav=$('#layout-sidenav')
|
||||
this.$sideNavItems=$('ul li',this.$sideNav)
|
||||
this.$sidePanelItems=$('[data-content-id]',this.$el)
|
||||
this.sideNavWidth=this.$sideNavItems.outerWidth()
|
||||
this.mainNavHeight=$('#layout-mainmenu').outerHeight()
|
||||
this.panelVisible=false
|
||||
this.visibleItemId=false
|
||||
this.$fixButton=$('<a href="#" class="fix-button"><i class="icon-thumb-tack"></i></a>')
|
||||
this.$fixButton.click(function(){self.fixPanel()
|
||||
return false})
|
||||
$('.fix-button-container',this.$el).append(this.$fixButton)
|
||||
this.$sideNavItems.click(function(){if($(this).data('no-side-panel')){return}if(Modernizr.touchevents&&$(window).width()<self.options.breakpoint){if($(this).data('menu-item')==self.visibleItemId&&self.panelVisible){self.hideSidePanel()
|
||||
return}else{self.displaySidePanel()}}self.displayTab(this)
|
||||
return false})
|
||||
if(!Modernizr.touchevents){self.$sideNav.mouseleave(function(){clearTimeout(self.panelOpenTimeout)})
|
||||
self.$el.mouseleave(function(){self.hideSidePanel()})
|
||||
self.$sideNavItems.mouseenter(function(){if($(window).width()<self.options.breakpoint||!self.panelFixed()){if($(this).data('no-side-panel')){self.hideSidePanel()
|
||||
return}var _this=this
|
||||
self.tabOpenTimeout=setTimeout(function(){self.displaySidePanel()
|
||||
self.displayTab(_this)},self.tabOpenDelay)}})
|
||||
self.$sideNavItems.mouseleave(function(){clearTimeout(self.tabOpenTimeout)})
|
||||
$(window).resize(function(){self.updatePanelPosition()
|
||||
self.updateActiveTab()})}else{$('#layout-body').click(function(){if(self.panelVisible){self.hideSidePanel()
|
||||
return false}})
|
||||
self.$el.on('close.oc.sidePanel',function(){self.hideSidePanel()})}this.updateActiveTab()}
|
||||
SidePanelTab.prototype.displayTab=function(menuItem){var menuItemId=$(menuItem).data('menu-item')
|
||||
this.visibleItemId=menuItemId
|
||||
if($.wn.sideNav!==undefined){$.wn.sideNav.setActiveItem(menuItemId)}this.$sidePanelItems.each(function(){var $el=$(this)
|
||||
$el.toggleClass('hide',$el.data('content-id')!=menuItemId)})
|
||||
$(window).trigger('resize')}
|
||||
SidePanelTab.prototype.displaySidePanel=function(){$(document.body).addClass('display-side-panel')
|
||||
this.$el.appendTo('#layout-canvas')
|
||||
this.panelVisible=true
|
||||
this.$el.css({left:this.sideNavWidth,top:this.mainNavHeight})
|
||||
this.updatePanelPosition()
|
||||
$(window).trigger('resize')}
|
||||
SidePanelTab.prototype.hideSidePanel=function(){$(document.body).removeClass('display-side-panel')
|
||||
if(this.$el.next('#layout-body').length==0){$('#layout-body').before(this.$el)}this.panelVisible=false
|
||||
this.updateActiveTab()}
|
||||
SidePanelTab.prototype.updatePanelPosition=function(){if(!this.panelFixed()||Modernizr.touchevents){this.$el.height($(document).height()-this.mainNavHeight)}else{this.$el.css('height','')}if(this.panelVisible&&$(window).width()>this.options.breakpoint&&this.panelFixed()){this.hideSidePanel()}}
|
||||
SidePanelTab.prototype.updateActiveTab=function(){if($.wn.sideNav===undefined){return}if(!this.panelVisible&&($(window).width()<this.options.breakpoint||!this.panelFixed())){$.wn.sideNav.unsetActiveItem()}else{$.wn.sideNav.setActiveItem(this.visibleItemId)}}
|
||||
SidePanelTab.prototype.panelFixed=function(){return!($(window).width()<this.options.breakpoint)&&!$(document.body).hasClass('side-panel-not-fixed')}
|
||||
SidePanelTab.prototype.fixPanel=function(){$(document.body).toggleClass('side-panel-not-fixed')
|
||||
var self=this
|
||||
window.setTimeout(function(){var fixed=self.panelFixed()
|
||||
if(fixed){self.updateActiveTab()
|
||||
$(document.body).addClass('side-panel-fix-shadow')}else{$(document.body).removeClass('side-panel-fix-shadow')
|
||||
self.hideSidePanel()}if(typeof(localStorage)!=='undefined')localStorage.ocSidePanelFixed=fixed?1:0},0)}
|
||||
SidePanelTab.DEFAULTS={breakpoint:769}
|
||||
var old=$.fn.sidePanelTab
|
||||
$.fn.sidePanelTab=function(option){return this.each(function(){var $this=$(this)
|
||||
var data=$this.data('oc.sidePanelTab')
|
||||
var options=$.extend({},SidePanelTab.DEFAULTS,$this.data(),typeof option=='object'&&option)
|
||||
if(!data)$this.data('oc.sidePanelTab',(data=new SidePanelTab(this,options)))
|
||||
if(typeof option=='string')data[option].call(data)})}
|
||||
$.fn.sidePanelTab.Constructor=SidePanelTab
|
||||
$.fn.sidePanelTab.noConflict=function(){$.fn.sidePanelTab=old
|
||||
return this}
|
||||
$(document).ready(function(){$('[data-control=layout-sidepanel]').sidePanelTab()})
|
||||
$(document).ready(function(){if(Modernizr.touchevents||(typeof(localStorage)!=='undefined')){if(localStorage.ocSidePanelFixed==0){$(document.body).addClass('side-panel-not-fixed')
|
||||
$(window).trigger('resize')}else if(localStorage.ocSidePanelFixed==1){$(document.body).removeClass('side-panel-not-fixed')
|
||||
$(window).trigger('resize')}}})}(window.jQuery);+function($){"use strict";var SimpleList=function(element,options){var $el=this.$el=$(element)
|
||||
this.options=options||{}
|
||||
if($el.hasClass('is-sortable')){var sortableOptions={distance:10}
|
||||
if(this.options.sortableHandle)sortableOptions[handle]=this.options.sortableHandle
|
||||
$el.find('> ul, > ol').sortable(sortableOptions)}if($el.hasClass('is-scrollable')){$el.wrapInner($('<div />').addClass('control-scrollbar'))
|
||||
var $scrollbar=$el.find('>.control-scrollbar:first')
|
||||
$scrollbar.scrollbar()}}
|
||||
SimpleList.DEFAULTS={sortableHandle:null}
|
||||
var old=$.fn.simplelist
|
||||
$.fn.simplelist=function(option){return this.each(function(){var $this=$(this)
|
||||
var data=$this.data('oc.simplelist')
|
||||
var options=$.extend({},SimpleList.DEFAULTS,$this.data(),typeof option=='object'&&option)
|
||||
if(!data)$this.data('oc.simplelist',(data=new SimpleList(this,options)))})}
|
||||
$.fn.simplelist.Constructor=SimpleList
|
||||
$.fn.simplelist.noConflict=function(){$.fn.simplelist=old
|
||||
return this}
|
||||
$(document).render(function(){$('[data-control="simplelist"]').simplelist()})}(window.jQuery);+function($){"use strict";var Base=$.wn.foundation.base,BaseProto=Base.prototype
|
||||
var TreeListWidget=function(element,options){this.$el=$(element)
|
||||
this.options=options||{};Base.call(this)
|
||||
$.wn.foundation.controlUtils.markDisposable(element)
|
||||
this.init()}
|
||||
TreeListWidget.prototype=Object.create(BaseProto)
|
||||
TreeListWidget.prototype.constructor=TreeListWidget
|
||||
TreeListWidget.prototype.init=function(){var sortableOptions={handle:this.options.handle,nested:this.options.nested,onDrop:this.proxy(this.onDrop),afterMove:this.proxy(this.onAfterMove)}
|
||||
this.$el.find('> ol').sortable($.extend(sortableOptions,this.options))
|
||||
if(!this.options.nested)this.$el.find('> ol ol').sortable($.extend(sortableOptions,this.options))
|
||||
this.$el.one('dispose-control',this.proxy(this.dispose))}
|
||||
TreeListWidget.prototype.dispose=function(){this.unbind()
|
||||
BaseProto.dispose.call(this)}
|
||||
TreeListWidget.prototype.unbind=function(){this.$el.off('dispose-control',this.proxy(this.dispose))
|
||||
this.$el.find('> ol').sortable('destroy')
|
||||
if(!this.options.nested){this.$el.find('> ol ol').sortable('destroy')}this.$el.removeData('oc.treelist')
|
||||
this.$el=null
|
||||
this.options=null}
|
||||
TreeListWidget.DEFAULTS={handle:null,nested:true}
|
||||
TreeListWidget.prototype.onDrop=function($item,container,_super){if(!this.$el){return}this.$el.trigger('move.oc.treelist',{item:$item,container:container})
|
||||
_super($item,container)}
|
||||
TreeListWidget.prototype.onAfterMove=function($placeholder,container,$closestEl){if(!this.$el){return}this.$el.trigger('aftermove.oc.treelist',{placeholder:$placeholder,container:container,closestEl:$closestEl})}
|
||||
var old=$.fn.treeListWidget
|
||||
$.fn.treeListWidget=function(option){var args=arguments,result
|
||||
this.each(function(){var $this=$(this)
|
||||
var data=$this.data('oc.treelist')
|
||||
var options=$.extend({},TreeListWidget.DEFAULTS,$this.data(),typeof option=='object'&&option)
|
||||
if(!data)$this.data('oc.treelist',(data=new TreeListWidget(this,options)))
|
||||
if(typeof option=='string')result=data[option].call(data)
|
||||
if(typeof result!='undefined')return false})
|
||||
return result?result:this}
|
||||
$.fn.treeListWidget.Constructor=TreeListWidget
|
||||
$.fn.treeListWidget.noConflict=function(){$.fn.treeListWidget=old
|
||||
return this}
|
||||
$(document).render(function(){$('[data-control="treelist"]').treeListWidget();})}(window.jQuery);+function($){"use strict";var SidenavTree=function(element,options){this.options=options
|
||||
this.$el=$(element)
|
||||
this.init()}
|
||||
SidenavTree.DEFAULTS={treeName:'sidenav_tree'}
|
||||
SidenavTree.prototype.init=function(){var self=this
|
||||
$(document.body).addClass('has-sidenav-tree')
|
||||
this.statusCookieName=this.options.treeName+'groupStatus'
|
||||
this.searchCookieName=this.options.treeName+'search'
|
||||
this.$searchInput=$(this.options.searchInput)
|
||||
this.$el.on('click','li > div.group',function(){self.toggleGroup($(this).closest('li'))
|
||||
return false})
|
||||
this.$searchInput.on('input',function(){self.handleSearchChange()})
|
||||
var searchTerm=$.cookie(this.searchCookieName)
|
||||
if(searchTerm!==undefined&&searchTerm.length>0){this.$searchInput.val(searchTerm)
|
||||
this.applySearch()}var scrollbar=$('[data-control=scrollbar]',this.$el).data('oc.scrollbar'),active=$('li.active',this.$el)
|
||||
if(active.length>0){scrollbar.gotoElement(active)}}
|
||||
SidenavTree.prototype.toggleGroup=function(group){var $group=$(group),status=$group.attr('data-status')
|
||||
status===undefined||status=='expanded'?this.collapseGroup($group):this.expandGroup($group)}
|
||||
SidenavTree.prototype.collapseGroup=function(group){var $list=$('> ul',group),self=this
|
||||
$list.css('overflow','hidden')
|
||||
$list.animate({'height':0},{duration:100,queue:false,complete:function(){$list.css({'overflow':'visible','display':'none'})
|
||||
$(group).attr('data-status','collapsed')
|
||||
$(window).trigger('oc.updateUi')
|
||||
self.saveGroupStatus($(group).data('group-code'),true)}})}
|
||||
SidenavTree.prototype.expandGroup=function(group,duration){var $list=$('> ul',group),self=this
|
||||
duration=duration===undefined?100:duration
|
||||
$list.css({'overflow':'hidden','height':0})
|
||||
$list.animate({'height':$list[0].scrollHeight},{duration:duration,queue:false,complete:function(){$list.css({'overflow':'visible','height':'auto','display':''})
|
||||
$(group).attr('data-status','expanded')
|
||||
$(window).trigger('oc.updateUi')
|
||||
self.saveGroupStatus($(group).data('group-code'),false)}})}
|
||||
SidenavTree.prototype.saveGroupStatus=function(groupCode,collapsed){var collapsedGroups=$.cookie(this.statusCookieName),updatedGroups=[]
|
||||
if(collapsedGroups===undefined){collapsedGroups=''}collapsedGroups=collapsedGroups.split('|')
|
||||
$.each(collapsedGroups,function(){if(groupCode!=this)updatedGroups.push(this)})
|
||||
if(collapsed){updatedGroups.push(groupCode)}$.cookie(this.statusCookieName,updatedGroups.join('|'),{expires:30,path:'/'})}
|
||||
SidenavTree.prototype.handleSearchChange=function(){var lastValue=this.$searchInput.data('oc.lastvalue');if(lastValue!==undefined&&lastValue==this.$searchInput.val()){return}this.$searchInput.data('oc.lastvalue',this.$searchInput.val())
|
||||
if(this.dataTrackInputTimer!==undefined){window.clearTimeout(this.dataTrackInputTimer)}var self=this
|
||||
this.dataTrackInputTimer=window.setTimeout(function(){self.applySearch()},300);$.cookie(this.searchCookieName,$.trim(this.$searchInput.val()),{expires:30,path:'/'})}
|
||||
SidenavTree.prototype.applySearch=function(){var query=$.trim(this.$searchInput.val()),words=query.toLowerCase().split(' '),visibleGroups=[],visibleItems=[],self=this
|
||||
if(query.length==0){$('li',this.$el).removeClass('hidden')
|
||||
return}$('ul.top-level > li',this.$el).each(function(){var $li=$(this)
|
||||
if(self.textContainsWords($('div.group h3',$li).text(),words)){visibleGroups.push($li.get(0))
|
||||
$('ul li',$li).each(function(){visibleItems.push(this)})}else{$('ul li',$li).each(function(){if(self.textContainsWords($(this).text(),words)||self.textContainsWords($(this).data('keywords'),words)){visibleGroups.push($li.get(0))
|
||||
visibleItems.push(this)}})}})
|
||||
$('ul.top-level > li',this.$el).each(function(){var $li=$(this),groupIsVisible=$.inArray(this,visibleGroups)!==-1
|
||||
$li.toggleClass('hidden',!groupIsVisible)
|
||||
if(groupIsVisible)self.expandGroup($li,0)
|
||||
$('ul li',$li).each(function(){var $itemLi=$(this)
|
||||
$itemLi.toggleClass('hidden',$.inArray(this,visibleItems)==-1)})})
|
||||
return false}
|
||||
SidenavTree.prototype.textContainsWords=function(text,words){text=text.toLowerCase()
|
||||
for(var i=0;i<words.length;i++){if(text.indexOf(words[i])===-1)return false}return true}
|
||||
var old=$.fn.sidenavTree
|
||||
$.fn.sidenavTree=function(option){var args=arguments;return this.each(function(){var $this=$(this)
|
||||
var data=$this.data('oc.sidenavTree')
|
||||
var options=$.extend({},SidenavTree.DEFAULTS,$this.data(),typeof option=='object'&&option)
|
||||
if(!data)$this.data('oc.sidenavTree',(data=new SidenavTree(this,options)))
|
||||
if(typeof option=='string'){var methodArgs=[];for(var i=1;i<args.length;i++)methodArgs.push(args[i])
|
||||
data[option].apply(data,methodArgs)}})}
|
||||
$.fn.sidenavTree.Constructor=SidenavTree
|
||||
$.fn.sidenavTree.noConflict=function(){$.fn.sidenavTree=old
|
||||
return this}
|
||||
$(document).ready(function(){$('[data-control=sidenav-tree]').sidenavTree()})}(window.jQuery);+function($){"use strict";var Base=$.wn.foundation.base,BaseProto=Base.prototype
|
||||
var DateTimeConverter=function(element,options){this.$el=$(element)
|
||||
this.options=options||{}
|
||||
$.wn.foundation.controlUtils.markDisposable(element)
|
||||
Base.call(this)
|
||||
this.init()}
|
||||
DateTimeConverter.prototype=Object.create(BaseProto)
|
||||
DateTimeConverter.prototype.constructor=DateTimeConverter
|
||||
DateTimeConverter.prototype.init=function(){this.initDefaults()
|
||||
this.$el.text(this.getDateTimeValue())
|
||||
this.$el.one('dispose-control',this.proxy(this.dispose))}
|
||||
DateTimeConverter.prototype.initDefaults=function(){if(!this.options.timezone){this.options.timezone=$('meta[name="backend-timezone"]').attr('content')}if(!this.options.locale){this.options.locale=$('meta[name="backend-locale"]').attr('content')}if(!this.options.format){this.options.format='llll'}if(this.options.formatAlias){this.options.format=this.getFormatFromAlias(this.options.formatAlias)}this.appTimezone=$('meta[name="app-timezone"]').attr('content')
|
||||
if(!this.appTimezone){this.appTimezone='UTC'}}
|
||||
DateTimeConverter.prototype.getDateTimeValue=function(){this.datetime=this.$el.attr('datetime')
|
||||
if(this.$el.get(0).hasAttribute('data-ignore-timezone')){this.appTimezone='UTC'
|
||||
this.options.timezone='UTC'}var momentObj=moment.tz(this.datetime,this.appTimezone),result
|
||||
if(this.options.locale){momentObj=momentObj.locale(this.options.locale)}if(this.options.timezone){momentObj=momentObj.tz(this.options.timezone)}if(this.options.timeSince){result=momentObj.fromNow()}else if(this.options.timeTense){result=momentObj.calendar()}else{result=momentObj.format(this.options.format)}return result}
|
||||
DateTimeConverter.prototype.getFormatFromAlias=function(alias){var map={time:'LT',timeLong:'LTS',date:'L',dateMin:'l',dateLong:'LL',dateLongMin:'ll',dateTime:'LLL',dateTimeMin:'lll',dateTimeLong:'LLLL',dateTimeLongMin:'llll'}
|
||||
return map[alias]?map[alias]:'llll'}
|
||||
DateTimeConverter.prototype.dispose=function(){this.$el.off('dispose-control',this.proxy(this.dispose))
|
||||
this.$el.removeData('oc.dateTimeConverter')
|
||||
this.$el=null
|
||||
this.options=null
|
||||
BaseProto.dispose.call(this)}
|
||||
DateTimeConverter.DEFAULTS={format:null,formatAlias:null,timezone:null,locale:null,timeTense:false,timeSince:false}
|
||||
var old=$.fn.dateTimeConverter
|
||||
$.fn.dateTimeConverter=function(option){var args=Array.prototype.slice.call(arguments,1),items,result
|
||||
items=this.each(function(){var $this=$(this)
|
||||
var data=$this.data('oc.dateTimeConverter')
|
||||
var options=$.extend({},DateTimeConverter.DEFAULTS,$this.data(),typeof option=='object'&&option)
|
||||
if(!data)$this.data('oc.dateTimeConverter',(data=new DateTimeConverter(this,options)))
|
||||
if(typeof option=='string')result=data[option].apply(data,args)
|
||||
if(typeof result!='undefined')return false})
|
||||
return result?result:items}
|
||||
$.fn.dateTimeConverter.Constructor=DateTimeConverter
|
||||
$.fn.dateTimeConverter.noConflict=function(){$.fn.dateTimeConverter=old
|
||||
return this}
|
||||
$(document).render(function(){$('time[data-datetime-control]').dateTimeConverter()})}(window.jQuery);if($.wn===undefined)$.wn={}
|
||||
if($.oc===undefined)$.oc=$.wn
|
||||
$.wn.backendUrl=function(url){var backendBasePath=$('meta[name="backend-base-path"]').attr('content')
|
||||
if(!backendBasePath)return url
|
||||
if(url.substr(0,1)=='/')url=url.substr(1)
|
||||
return backendBasePath+'/'+url}
|
||||
if($.wn===undefined)$.wn={}
|
||||
if($.oc===undefined)$.oc=$.wn
|
||||
$.wn.escapeHtmlString=function(string){var htmlEscapes={'&':'&','<':'<','>':'>','"':'"',"'":''','/':'/'},htmlEscaper=/[&<>"'\/]/g
|
||||
return(''+string).replace(htmlEscaper,function(match){return htmlEscapes[match];})}
|
||||
if(!!window.MSInputMethodContext&&!!document.documentMode){$(window).on('resize',function(){fixMediaManager()
|
||||
fixSidebar()})
|
||||
function fixMediaManager(){var $el=$('div[data-control="media-manager"] .control-scrollpad')
|
||||
$el.height($el.parent().height())}function fixSidebar(){$('#layout-sidenav').height(Math.max($('#layout-body').innerHeight(),$(window).height()-$('#layout-mainmenu').height()))}}
|
||||
92
modules/backend/assets/js/winter.alert.js
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Alerts
|
||||
*
|
||||
* Displays alert and confirmation dialogs
|
||||
*
|
||||
* JavaScript API:
|
||||
* $.wn.alert()
|
||||
* $.wn.confirm()
|
||||
*
|
||||
* Dependences:
|
||||
* - Sweet Alert
|
||||
* - Translations (winter.lang.js)
|
||||
*/
|
||||
(function($){
|
||||
|
||||
if ($.wn === undefined)
|
||||
$.wn = {}
|
||||
if ($.oc === undefined)
|
||||
$.oc = $.wn
|
||||
|
||||
$.wn.alert = function alert(message) {
|
||||
swal({
|
||||
title: message,
|
||||
confirmButtonClass: 'btn-primary'
|
||||
})
|
||||
}
|
||||
|
||||
$.wn.confirm = function confirm(message, callback) {
|
||||
|
||||
swal({
|
||||
title: message,
|
||||
showCancelButton: true,
|
||||
confirmButtonClass: 'btn-primary'
|
||||
}, callback)
|
||||
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
|
||||
/*
|
||||
* Implement alerts with AJAX framework
|
||||
*/
|
||||
|
||||
$(window).on('ajaxErrorMessage', function(event, message){
|
||||
if (!message) return
|
||||
|
||||
$.wn.alert(message)
|
||||
|
||||
// Prevent the default alert() message
|
||||
event.preventDefault()
|
||||
})
|
||||
|
||||
$(window).on('ajaxConfirmMessage', function(event, message){
|
||||
if (!message) return
|
||||
|
||||
$.wn.confirm(message, function(isConfirm){
|
||||
isConfirm
|
||||
? event.promise.resolve()
|
||||
: event.promise.reject()
|
||||
})
|
||||
|
||||
// Prevent the default confirm() message
|
||||
event.preventDefault()
|
||||
return true
|
||||
})
|
||||
|
||||
/*
|
||||
* Override "Sweet Alert" functions to translate default buttons
|
||||
*/
|
||||
|
||||
$(document).ready(function(){
|
||||
if (!window.swal) return
|
||||
|
||||
var swal = window.swal
|
||||
|
||||
window.sweetAlert = window.swal = function(message, callback) {
|
||||
if (typeof message === 'object') {
|
||||
// Do not override if texts are provided
|
||||
message.confirmButtonText = message.confirmButtonText || $.wn.lang.get('alert.confirm_button_text')
|
||||
message.cancelButtonText = message.cancelButtonText || $.wn.lang.get('alert.cancel_button_text')
|
||||
}
|
||||
else {
|
||||
message = {
|
||||
title: message,
|
||||
confirmButtonText: $.wn.lang.get('alert.confirm_button_text'),
|
||||
cancelButtonText: $.wn.lang.get('alert.cancel_button_text')
|
||||
}
|
||||
}
|
||||
|
||||
swal(message, callback)
|
||||
}
|
||||
})
|
||||
175
modules/backend/assets/js/winter.datetime.js
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Date time converter.
|
||||
* See moment.js for format options.
|
||||
* http://momentjs.com/docs/#/displaying/format/
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* <time
|
||||
* data-datetime-control
|
||||
* datetime="2014-11-19 01:21:57"
|
||||
* data-format="dddd Do [o]f MMMM YYYY hh:mm:ss A"
|
||||
* data-timezone="Australia/Sydney"
|
||||
* data-locale="en-au">This text will be replaced</time>
|
||||
*
|
||||
* Alias options:
|
||||
*
|
||||
* time -> 6:28 AM
|
||||
* timeLong -> 6:28:01 AM
|
||||
* date -> 04/23/2016
|
||||
* dateMin -> 4/23/2016
|
||||
* dateLong -> April 23, 2016
|
||||
* dateLongMin -> Apr 23, 2016
|
||||
* dateTime -> April 23, 2016 6:28 AM
|
||||
* dateTimeMin -> Apr 23, 2016 6:28 AM
|
||||
* dateTimeLong -> Saturday, April 23, 2016 6:28 AM
|
||||
* dateTimeLongMin -> Sat, Apr 23, 2016 6:29 AM
|
||||
*
|
||||
*/
|
||||
+function ($) { "use strict";
|
||||
var Base = $.wn.foundation.base,
|
||||
BaseProto = Base.prototype
|
||||
|
||||
var DateTimeConverter = function (element, options) {
|
||||
this.$el = $(element)
|
||||
this.options = options || {}
|
||||
|
||||
$.wn.foundation.controlUtils.markDisposable(element)
|
||||
Base.call(this)
|
||||
this.init()
|
||||
}
|
||||
|
||||
DateTimeConverter.prototype = Object.create(BaseProto)
|
||||
DateTimeConverter.prototype.constructor = DateTimeConverter
|
||||
|
||||
DateTimeConverter.prototype.init = function() {
|
||||
this.initDefaults()
|
||||
|
||||
this.$el.text(this.getDateTimeValue())
|
||||
|
||||
this.$el.one('dispose-control', this.proxy(this.dispose))
|
||||
}
|
||||
|
||||
DateTimeConverter.prototype.initDefaults = function() {
|
||||
if (!this.options.timezone) {
|
||||
this.options.timezone = $('meta[name="backend-timezone"]').attr('content')
|
||||
}
|
||||
|
||||
if (!this.options.locale) {
|
||||
this.options.locale = $('meta[name="backend-locale"]').attr('content')
|
||||
}
|
||||
|
||||
if (!this.options.format) {
|
||||
this.options.format = 'llll'
|
||||
}
|
||||
|
||||
if (this.options.formatAlias) {
|
||||
this.options.format = this.getFormatFromAlias(this.options.formatAlias)
|
||||
}
|
||||
|
||||
this.appTimezone = $('meta[name="app-timezone"]').attr('content')
|
||||
if (!this.appTimezone) {
|
||||
this.appTimezone = 'UTC'
|
||||
}
|
||||
}
|
||||
|
||||
DateTimeConverter.prototype.getDateTimeValue = function() {
|
||||
this.datetime = this.$el.attr('datetime')
|
||||
|
||||
if (this.$el.get(0).hasAttribute('data-ignore-timezone')) {
|
||||
this.appTimezone = 'UTC'
|
||||
this.options.timezone = 'UTC'
|
||||
}
|
||||
|
||||
var momentObj = moment.tz(this.datetime, this.appTimezone),
|
||||
result
|
||||
|
||||
if (this.options.locale) {
|
||||
momentObj = momentObj.locale(this.options.locale)
|
||||
}
|
||||
|
||||
if (this.options.timezone) {
|
||||
momentObj = momentObj.tz(this.options.timezone)
|
||||
}
|
||||
|
||||
if (this.options.timeSince) {
|
||||
result = momentObj.fromNow()
|
||||
}
|
||||
else if (this.options.timeTense) {
|
||||
result = momentObj.calendar()
|
||||
}
|
||||
else {
|
||||
result = momentObj.format(this.options.format)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
DateTimeConverter.prototype.getFormatFromAlias = function(alias) {
|
||||
var map = {
|
||||
time: 'LT',
|
||||
timeLong: 'LTS',
|
||||
date: 'L',
|
||||
dateMin: 'l',
|
||||
dateLong: 'LL',
|
||||
dateLongMin: 'll',
|
||||
dateTime: 'LLL',
|
||||
dateTimeMin: 'lll',
|
||||
dateTimeLong: 'LLLL',
|
||||
dateTimeLongMin: 'llll'
|
||||
}
|
||||
|
||||
return map[alias] ? map[alias] : 'llll'
|
||||
}
|
||||
|
||||
DateTimeConverter.prototype.dispose = function() {
|
||||
this.$el.off('dispose-control', this.proxy(this.dispose))
|
||||
this.$el.removeData('oc.dateTimeConverter')
|
||||
|
||||
this.$el = null
|
||||
this.options = null
|
||||
|
||||
BaseProto.dispose.call(this)
|
||||
}
|
||||
|
||||
DateTimeConverter.DEFAULTS = {
|
||||
format: null,
|
||||
formatAlias: null,
|
||||
timezone: null,
|
||||
locale: null,
|
||||
timeTense: false,
|
||||
timeSince: false
|
||||
}
|
||||
|
||||
// PLUGIN DEFINITION
|
||||
// ============================
|
||||
|
||||
var old = $.fn.dateTimeConverter
|
||||
|
||||
$.fn.dateTimeConverter = function (option) {
|
||||
var args = Array.prototype.slice.call(arguments, 1), items, result
|
||||
|
||||
items = this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('oc.dateTimeConverter')
|
||||
var options = $.extend({}, DateTimeConverter.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
||||
if (!data) $this.data('oc.dateTimeConverter', (data = new DateTimeConverter(this, options)))
|
||||
if (typeof option == 'string') result = data[option].apply(data, args)
|
||||
if (typeof result != 'undefined') return false
|
||||
})
|
||||
|
||||
return result ? result : items
|
||||
}
|
||||
|
||||
$.fn.dateTimeConverter.Constructor = DateTimeConverter
|
||||
|
||||
$.fn.dateTimeConverter.noConflict = function () {
|
||||
$.fn.dateTimeConverter = old
|
||||
return this
|
||||
}
|
||||
|
||||
$(document).render(function (){
|
||||
$('time[data-datetime-control]').dateTimeConverter()
|
||||
})
|
||||
|
||||
}(window.jQuery);
|
||||
169
modules/backend/assets/js/winter.filelist.js
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* File List
|
||||
*
|
||||
* Creates a tree list of clickable folders and files.
|
||||
*
|
||||
* Data attributes:
|
||||
* - data-control="filelist" - enables the file list plugin
|
||||
* - data-group-status-handler - AJAX handler to execute when a group is collapsed or expanded by a user
|
||||
*
|
||||
* JavaScript API:
|
||||
* $('#list').fileList()
|
||||
*
|
||||
* Events
|
||||
* - open.oc.list - this event is triggered on the list element when an item is clicked.
|
||||
*
|
||||
* Dependences:
|
||||
* - Null
|
||||
*/
|
||||
|
||||
+function ($) { "use strict";
|
||||
|
||||
// FILELIST CLASS DEFINITION
|
||||
// ============================
|
||||
|
||||
var FileList = function(element, options) {
|
||||
this.options = options
|
||||
this.$el = $(element)
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
FileList.DEFAULTS = {
|
||||
ignoreItemClick: false
|
||||
}
|
||||
|
||||
FileList.prototype.init = function (){
|
||||
var self = this
|
||||
|
||||
this.$el.on('click', 'li.group > h4 > a, li.group > div.group', function() {
|
||||
self.toggleGroup($(this).closest('li'))
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!this.options.ignoreItemClick) {
|
||||
this.$el.on('click', 'li.item > a', function(event) {
|
||||
var e = $.Event('open.oc.list', {relatedTarget: $(this).parent().get(0), clickEvent: event})
|
||||
self.$el.trigger(e, this)
|
||||
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
this.$el.on('ajaxUpdate', $.proxy(this.update, this))
|
||||
}
|
||||
|
||||
FileList.prototype.toggleGroup = function(group) {
|
||||
var $group = $(group);
|
||||
|
||||
$group.attr('data-status') == 'expanded' ?
|
||||
this.collapseGroup($group) :
|
||||
this.expandGroup($group)
|
||||
}
|
||||
|
||||
FileList.prototype.collapseGroup = function(group) {
|
||||
var
|
||||
$list = $('> ul, > div.subitems', group),
|
||||
self = this;
|
||||
|
||||
$list.css('overflow', 'hidden')
|
||||
$list.animate({'height': 0}, { duration: 100, queue: false, complete: function() {
|
||||
$list.css({
|
||||
'overflow': 'visible',
|
||||
'display': 'none'
|
||||
})
|
||||
$(group).attr('data-status', 'collapsed')
|
||||
$(window).trigger('resize')
|
||||
} })
|
||||
|
||||
this.sendGroupStatusRequest(group, 0);
|
||||
}
|
||||
|
||||
FileList.prototype.expandGroup = function(group) {
|
||||
var
|
||||
$list = $('> ul, > div.subitems', group),
|
||||
self = this;
|
||||
|
||||
$list.css({
|
||||
'overflow': 'hidden',
|
||||
'display': 'block',
|
||||
'height': 0
|
||||
})
|
||||
$list.animate({'height': $list[0].scrollHeight}, { duration: 100, queue: false, complete: function() {
|
||||
$list.css({
|
||||
'overflow': 'visible',
|
||||
'height': 'auto'
|
||||
})
|
||||
$(group).attr('data-status', 'expanded')
|
||||
$(window).trigger('resize')
|
||||
} })
|
||||
|
||||
this.sendGroupStatusRequest(group, 1);
|
||||
}
|
||||
|
||||
FileList.prototype.sendGroupStatusRequest = function(group, status) {
|
||||
if (this.options.groupStatusHandler !== undefined) {
|
||||
var groupId = $(group).data('group-id')
|
||||
if (groupId === undefined)
|
||||
groupId = $('> h4 a', group).text();
|
||||
|
||||
$(group).request(this.options.groupStatusHandler, {data: {group: groupId, status: status}})
|
||||
}
|
||||
}
|
||||
|
||||
FileList.prototype.markActive = function(dataId) {
|
||||
$('li.item', this.$el).removeClass('active')
|
||||
if (dataId)
|
||||
$('li.item[data-id="'+dataId+'"]', this.$el).addClass('active')
|
||||
|
||||
this.dataId = dataId
|
||||
}
|
||||
|
||||
FileList.prototype.update = function() {
|
||||
if (this.dataId !== undefined)
|
||||
this.markActive(this.dataId)
|
||||
}
|
||||
|
||||
// FILELIST PLUGIN DEFINITION
|
||||
// ============================
|
||||
|
||||
var old = $.fn.fileList
|
||||
|
||||
$.fn.fileList = function (option) {
|
||||
var args = arguments;
|
||||
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('oc.fileList')
|
||||
var options = $.extend({}, FileList.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
||||
|
||||
if (!data) $this.data('oc.fileList', (data = new FileList(this, options)))
|
||||
if (typeof option == 'string') {
|
||||
var methodArgs = [];
|
||||
for (var i=1; i<args.length; i++)
|
||||
methodArgs.push(args[i])
|
||||
|
||||
data[option].apply(data, methodArgs)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.fileList.Constructor = FileList
|
||||
|
||||
// FILELIST NO CONFLICT
|
||||
// =================
|
||||
|
||||
$.fn.fileList.noConflict = function () {
|
||||
$.fn.fileList = old
|
||||
return this
|
||||
}
|
||||
|
||||
// FILELIST DATA-API
|
||||
// ===============
|
||||
|
||||
$(document).ready(function () {
|
||||
$('[data-control=filelist]').fileList()
|
||||
})
|
||||
|
||||
}(window.jQuery);
|
||||
224
modules/backend/assets/js/winter.flyout.js
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Flyout plugin.
|
||||
*/
|
||||
+function ($) { "use strict";
|
||||
|
||||
var Base = $.wn.foundation.base,
|
||||
BaseProto = Base.prototype
|
||||
|
||||
// SCROLLPAD CLASS DEFINITION
|
||||
// ============================
|
||||
|
||||
var Flyout = function(element, options) {
|
||||
this.$el = $(element)
|
||||
this.$overlay = null
|
||||
this.options = options
|
||||
|
||||
Base.call(this)
|
||||
|
||||
this.init()
|
||||
}
|
||||
|
||||
Flyout.prototype = Object.create(BaseProto)
|
||||
Flyout.prototype.constructor = Flyout
|
||||
|
||||
Flyout.prototype.dispose = function() {
|
||||
this.removeOverlay()
|
||||
this.$el.removeData('oc.flyout')
|
||||
this.$el = null
|
||||
|
||||
if (this.options.flyoutToggle) {
|
||||
this.removeToggle()
|
||||
}
|
||||
|
||||
BaseProto.dispose.call(this)
|
||||
}
|
||||
|
||||
Flyout.prototype.show = function() {
|
||||
var $cells = this.$el.find('> .layout-cell'),
|
||||
$flyout = this.$el.find('> .flyout')
|
||||
|
||||
$('[data-control=layout-sidepanel]').sidePanelTab('hideSidePanel')
|
||||
|
||||
this.removeOverlay()
|
||||
|
||||
for (var i = 0; i < $cells.length; i++) {
|
||||
var $cell = $($cells[i]),
|
||||
width = $cell.width()
|
||||
|
||||
$cell.css('width', width)
|
||||
}
|
||||
|
||||
this.createOverlay()
|
||||
|
||||
window.setTimeout(this.proxy(this.setBodyClass), 1)
|
||||
$flyout.css('width', this.options.flyoutWidth)
|
||||
|
||||
this.hideToggle()
|
||||
}
|
||||
|
||||
Flyout.prototype.hide = function() {
|
||||
var $cells = this.$el.find('> .layout-cell'),
|
||||
$flyout = this.$el.find('> .flyout')
|
||||
|
||||
for (var i = 0; i < $cells.length; i++) {
|
||||
var $cell = $($cells[i])
|
||||
|
||||
$cell.css('width', '')
|
||||
}
|
||||
|
||||
$flyout.css('width', 0)
|
||||
|
||||
window.setTimeout(this.proxy(this.removeBodyClass), 1)
|
||||
window.setTimeout(this.proxy(this.removeOverlayAndShowToggle), 300)
|
||||
}
|
||||
|
||||
// FLYOUT INTERNAL METHODS
|
||||
// ============================
|
||||
|
||||
Flyout.prototype.init = function() {
|
||||
this.build()
|
||||
}
|
||||
|
||||
Flyout.prototype.build = function() {
|
||||
if (this.options.flyoutToggle) {
|
||||
this.buildToggle()
|
||||
}
|
||||
}
|
||||
|
||||
Flyout.prototype.buildToggle = function() {
|
||||
var $toggleContainer = $(this.options.flyoutToggle),
|
||||
$toggle = $('<div class="flyout-toggle"><i class="icon-chevron-right"></i></div>')
|
||||
|
||||
$toggle.on('click', this.proxy(this.show))
|
||||
$toggleContainer.append($toggle)
|
||||
}
|
||||
|
||||
Flyout.prototype.removeToggle = function() {
|
||||
var $toggle = this.getToggle()
|
||||
|
||||
$toggle.off('click', this.proxy(this.show))
|
||||
$toggle.remove()
|
||||
}
|
||||
|
||||
Flyout.prototype.hideToggle = function() {
|
||||
if (!this.options.flyoutToggle) {
|
||||
return
|
||||
}
|
||||
|
||||
this.getToggle().hide()
|
||||
}
|
||||
|
||||
Flyout.prototype.showToggle = function() {
|
||||
if (!this.options.flyoutToggle) {
|
||||
return
|
||||
}
|
||||
|
||||
this.getToggle().show()
|
||||
}
|
||||
|
||||
Flyout.prototype.getToggle = function() {
|
||||
var $toggleContainer = $(this.options.flyoutToggle)
|
||||
|
||||
return $toggleContainer.find('.flyout-toggle')
|
||||
}
|
||||
|
||||
Flyout.prototype.setBodyClass = function() {
|
||||
$(document.body).addClass('flyout-visible')
|
||||
}
|
||||
|
||||
Flyout.prototype.removeBodyClass = function() {
|
||||
$(document.body).removeClass('flyout-visible')
|
||||
}
|
||||
|
||||
Flyout.prototype.createOverlay = function() {
|
||||
this.$overlay = $('<div class="flyout-overlay"/>')
|
||||
|
||||
var position = this.$el.offset()
|
||||
|
||||
this.$overlay.css({
|
||||
top: position.top,
|
||||
left: this.options.flyoutWidth
|
||||
})
|
||||
|
||||
this.$overlay.on('click', this.proxy(this.onOverlayClick))
|
||||
$(document.body).on('keydown', this.proxy(this.onDocumentKeydown))
|
||||
|
||||
$(document.body).append(this.$overlay)
|
||||
}
|
||||
|
||||
Flyout.prototype.removeOverlay = function() {
|
||||
if (!this.$overlay) {
|
||||
return
|
||||
}
|
||||
|
||||
this.$overlay.off('click', this.proxy(this.onOverlayClick))
|
||||
$(document.body).off('keydown', this.proxy(this.onDocumentKeydown))
|
||||
|
||||
this.$overlay.remove()
|
||||
this.$overlay = null
|
||||
}
|
||||
|
||||
Flyout.prototype.removeOverlayAndShowToggle = function() {
|
||||
this.removeOverlay()
|
||||
this.showToggle()
|
||||
}
|
||||
|
||||
// EVENT HANDLERS
|
||||
// ============================
|
||||
|
||||
Flyout.prototype.onOverlayClick = function() {
|
||||
this.hide()
|
||||
}
|
||||
|
||||
Flyout.prototype.onDocumentKeydown = function(ev) {
|
||||
if (ev.key === 'Escape') {
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
// FLYOUT PLUGIN DEFINITION
|
||||
// ============================
|
||||
|
||||
Flyout.DEFAULTS = {
|
||||
flyoutWidth: 400,
|
||||
flyoutToggle: null
|
||||
}
|
||||
|
||||
var old = $.fn.flyout
|
||||
|
||||
$.fn.flyout = function (option) {
|
||||
var args = Array.prototype.slice.call(arguments, 1),
|
||||
result = undefined
|
||||
|
||||
this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('oc.flyout')
|
||||
var options = $.extend({}, Flyout.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
||||
if (!data) $this.data('oc.flyout', (data = new Flyout(this, options)))
|
||||
if (typeof option == 'string') result = data[option].apply(data, args)
|
||||
if (typeof result != 'undefined') return false
|
||||
})
|
||||
|
||||
return result ? result : this
|
||||
}
|
||||
|
||||
$.fn.flyout.Constructor = Flyout
|
||||
|
||||
// FLYOUT NO CONFLICT
|
||||
// =================
|
||||
|
||||
$.fn.flyout.noConflict = function () {
|
||||
$.fn.flyout = old
|
||||
return this
|
||||
}
|
||||
|
||||
// FLYOUT DATA-API
|
||||
// ===============
|
||||
|
||||
// Currently flyouts don't use the document render event
|
||||
// and can't be created dynamically (performance considerations).
|
||||
$(document).ready(function(){
|
||||
$('div[data-control=flyout]').flyout()
|
||||
})
|
||||
}(window.jQuery);
|
||||
35
modules/backend/assets/js/winter.js
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This is a bundle file, you can compile this by running
|
||||
*
|
||||
* php artisan winter:util compile assets
|
||||
*
|
||||
* @see winter-min.js
|
||||
*
|
||||
|
||||
=require vendor/jquery.touchwipe.js
|
||||
=require vendor/jquery.autoellipsis.js
|
||||
=require vendor/jquery.waterfall.js
|
||||
=require vendor/jquery.cookie.js
|
||||
=require ../vendor/dropzone/dropzone.js
|
||||
=require ../vendor/sweet-alert/sweet-alert.js
|
||||
=require ../vendor/jcrop/js/jquery.Jcrop.js
|
||||
=require ../../../system/assets/vendor/prettify/prettify.js
|
||||
=require ../../widgets/mediamanager/assets/js/mediamanager-global.js
|
||||
|
||||
=require winter.lang.js
|
||||
=require winter.alert.js
|
||||
=require winter.scrollpad.js
|
||||
=require winter.verticalmenu.js
|
||||
=require winter.navbar.js
|
||||
=require winter.sidenav.js
|
||||
=require winter.scrollbar.js
|
||||
=require winter.filelist.js
|
||||
=require winter.layout.js
|
||||
=require winter.sidepaneltab.js
|
||||
=require winter.simplelist.js
|
||||
=require winter.treelist.js
|
||||
=require winter.sidenav-tree.js
|
||||
=require winter.datetime.js
|
||||
|
||||
=require backend.js
|
||||
*/
|
||||
52
modules/backend/assets/js/winter.lang.js
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Client side translations
|
||||
*/
|
||||
|
||||
if ($.wn === undefined)
|
||||
$.wn = {}
|
||||
if ($.oc === undefined)
|
||||
$.oc = $.wn
|
||||
|
||||
if ($.wn.langMessages === undefined)
|
||||
$.wn.langMessages = {}
|
||||
|
||||
$.wn.lang = (function(lang, messages) {
|
||||
|
||||
lang.load = function(locale) {
|
||||
if (messages[locale] === undefined) {
|
||||
messages[locale] = {}
|
||||
}
|
||||
|
||||
lang.loadedMessages = messages[locale]
|
||||
}
|
||||
|
||||
lang.get = function(name, defaultValue) {
|
||||
if (!name) return
|
||||
|
||||
var result = lang.loadedMessages
|
||||
|
||||
if (!defaultValue) defaultValue = name
|
||||
|
||||
$.each(name.split('.'), function(index, value) {
|
||||
if (result[value] === undefined) {
|
||||
result = defaultValue
|
||||
return false
|
||||
}
|
||||
|
||||
result = result[value]
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
if (lang.locale === undefined) {
|
||||
lang.locale = $('html').attr('lang') || 'en'
|
||||
}
|
||||
|
||||
if (lang.loadedMessages === undefined) {
|
||||
lang.load(lang.locale)
|
||||
}
|
||||
|
||||
return lang
|
||||
|
||||
})($.wn.lang || {}, $.wn.langMessages);
|
||||
86
modules/backend/assets/js/winter.layout.js
Normal file
@@ -0,0 +1,86 @@
|
||||
(function($){
|
||||
var WinterLayout = function() {
|
||||
this.$accountMenuOverlay = null
|
||||
}
|
||||
|
||||
WinterLayout.prototype.setPageTitle = function(title) {
|
||||
var $title = $('title')
|
||||
|
||||
if (this.pageTitleTemplate === undefined)
|
||||
this.pageTitleTemplate = $title.data('titleTemplate')
|
||||
|
||||
$title.text(this.pageTitleTemplate.replace('%s', title))
|
||||
}
|
||||
|
||||
WinterLayout.prototype.updateLayout = function(title) {
|
||||
var $children, $el, fixedWidth, margin
|
||||
|
||||
$('[data-calculate-width]').each(function(){
|
||||
$children = $(this).children()
|
||||
|
||||
if ($children.length > 0) {
|
||||
fixedWidth = 0
|
||||
|
||||
$children.each(function() {
|
||||
$el = $(this)
|
||||
margin = $el.data('oc.layoutMargin')
|
||||
|
||||
if (margin === undefined) {
|
||||
margin = parseInt($el.css('marginRight')) + parseInt($el.css('marginLeft'))
|
||||
$el.data('oc.layoutMargin', margin)
|
||||
}
|
||||
fixedWidth += $el.get(0).offsetWidth + margin
|
||||
})
|
||||
|
||||
$(this).width(fixedWidth)
|
||||
$(this).trigger('oc.widthFixed')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
WinterLayout.prototype.toggleAccountMenu = function(el) {
|
||||
var self = this,
|
||||
$el = $(el),
|
||||
$parent = $(el).parent(),
|
||||
$menu = $el.next()
|
||||
|
||||
$el.tooltip('hide')
|
||||
|
||||
if ($menu.hasClass('active')) {
|
||||
self.$accountMenuOverlay.remove()
|
||||
$parent.removeClass('highlight')
|
||||
$menu.removeClass('active')
|
||||
}
|
||||
else {
|
||||
self.$accountMenuOverlay = $('<div />').addClass('popover-overlay')
|
||||
$(document.body).append(self.$accountMenuOverlay)
|
||||
$parent.addClass('highlight')
|
||||
$menu.addClass('active')
|
||||
|
||||
self.$accountMenuOverlay.one('click', function(){
|
||||
self.$accountMenuOverlay.remove()
|
||||
$menu.removeClass('active')
|
||||
$parent.removeClass('highlight')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if ($.wn === undefined)
|
||||
$.wn = {}
|
||||
if ($.oc === undefined)
|
||||
$.oc = $.wn
|
||||
|
||||
$.wn.layout = new WinterLayout()
|
||||
|
||||
$(document).ready(function(){
|
||||
$.wn.layout.updateLayout()
|
||||
|
||||
window.setTimeout($.wn.layout.updateLayout, 100)
|
||||
})
|
||||
$(window).on('resize', function() {
|
||||
$.wn.layout.updateLayout()
|
||||
})
|
||||
$(window).on('oc.updateUi', function() {
|
||||
$.wn.layout.updateLayout()
|
||||
})
|
||||
})(jQuery);
|
||||
41
modules/backend/assets/js/winter.navbar.js
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Top navigation bar. Features of the bar:
|
||||
* - Hide content if the display width is less than 768px. In this case the menu icon is displayed.
|
||||
* When the icon is clicked, the menu content is displayed on the left side of the page.
|
||||
* - If the content doesn't fit the navbar, it can be dragged left and right.
|
||||
*
|
||||
* Dependences:
|
||||
* - DragScroll (winter.dragscroll.js)
|
||||
* - VerticalMenu (winter.verticalmenu.js)
|
||||
*/
|
||||
|
||||
(function($){
|
||||
$(document).ready(function(){
|
||||
$('nav.navbar').each(function(){
|
||||
var
|
||||
navbar = $(this),
|
||||
nav = $('ul.nav', navbar),
|
||||
collapseMode = navbar.hasClass('navbar-mode-collapse'),
|
||||
isMobile = $('html').hasClass('mobile')
|
||||
|
||||
nav.verticalMenu($('a.menu-toggle', navbar), {
|
||||
breakpoint: collapseMode ? Infinity : 769
|
||||
})
|
||||
|
||||
$('li.with-tooltip:not(.active) > a', navbar).tooltip({
|
||||
container: 'body',
|
||||
placement: 'bottom',
|
||||
template: '<div class="tooltip mainmenu-tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
|
||||
})
|
||||
.on('show.bs.tooltip', function (e) {
|
||||
if (isMobile) e.preventDefault()
|
||||
})
|
||||
|
||||
// Scroll to the currently active nav item.
|
||||
var dragScroll = $('[data-control=toolbar]', navbar).data('oc.dragScroll')
|
||||
if (dragScroll) {
|
||||
dragScroll.goToElement($('ul.nav > li.active', navbar), undefined, {'duration': 0})
|
||||
}
|
||||
})
|
||||
})
|
||||
})(jQuery);
|
||||