diff --git a/.env b/.env index c723847..d1b3b36 100644 --- a/.env +++ b/.env @@ -9,25 +9,27 @@ # Real environment variables win over .env files. # # DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES. -# https://symfony.com/doc/current/configuration/secrets.html # # Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). # https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration ###> symfony/framework-bundle ### APP_ENV=dev -APP_SECRET= +APP_SECRET=e6e287f176fe2c69112fc620e1801bf0 ###< symfony/framework-bundle ### -###> symfony/mailer ### -# MAILER_DSN=smtp://localhost -###< symfony/mailer ### - ###> doctrine/doctrine-bundle ### # Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url # IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml # DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" -# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8&charset=utf8mb4" -# DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=14&charset=utf8" +# DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7" +# DATABASE_URL="postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=13&charset=utf8" ###< doctrine/doctrine-bundle ### + +###> symfony/swiftmailer-bundle ### +# For Gmail as a transport, use: "gmail://username:password@localhost" +# For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode=" +# Delivery is disabled by default via "null://localhost" +MAILER_URL=null://localhost +###< symfony/swiftmailer-bundle ### diff --git a/.env.test b/.env.test index 3261772..9e7162f 100644 --- a/.env.test +++ b/.env.test @@ -4,4 +4,3 @@ APP_SECRET='$ecretf0rt3st' SYMFONY_DEPRECATIONS_HELPER=999999 PANTHER_APP_ENV=panther PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots -DATABASE_URL="sqlite:///%kernel.project_dir%/var/data_tests.db" diff --git a/.gitignore b/.gitignore index 2f54f0e..18ffc85 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ ###< symfony/framework-bundle ### ###> symfony/phpunit-bridge ### +.phpunit .phpunit.result.cache /phpunit.xml ###< symfony/phpunit-bridge ### @@ -23,13 +24,6 @@ npm-debug.log yarn-error.log ###< symfony/webpack-encore-bundle ### -/public/uploads/* +/public/uploads/ !/public/uploads/.gitkeep /public/media/ -/migrations/* -!/migrations/.gitkeep - -###> phpunit/phpunit ### -/phpunit.xml -.phpunit.result.cache -###< phpunit/phpunit ### diff --git a/.php-version b/.php-version deleted file mode 100644 index cc40bca..0000000 --- a/.php-version +++ /dev/null @@ -1 +0,0 @@ -8.0 diff --git a/.woodpecker.yml b/.woodpecker.yml deleted file mode 100644 index 89f9811..0000000 --- a/.woodpecker.yml +++ /dev/null @@ -1,49 +0,0 @@ -matrix: - PHP_VERSION: - - 8.0 - - 8.1 - -services: - db: - image: mariadb:10.3 - environment: - - MARIADB_ROOT_PASSWORD=root - -steps: - db_wait: - image: gitnet.fr/deblan/timeout:latest - commands: - - /bin/timeout -t 30 -v -c 'while true; do nc -z -v db 3306 2>&1 | grep succeeded && exit 0; sleep 0.5; done' - - db_create: - image: mariadb:10.3 - commands: - - mysql -hdb -uroot -proot -e "CREATE DATABASE app" - - config: - image: deblan/php:${PHP_VERSION} - commands: - - echo APP_ENV=prod >> .env.local - - echo APP_SECRET=$(openssl rand -hex 32) >> .env.local - - echo DATABASE_URL=mysql://root:root@db/app >> .env.local - - composer: - image: deblan/php:${PHP_VERSION} - commands: - - apt-get update && apt-get -y install git - - composer install --no-scripts - - db_migrate: - image: deblan/php:${PHP_VERSION} - environment: - - PHP=php - commands: - - ./bin/doctrine-migrate - - node: - image: node:16-slim - commands: - - yarn - - test -d public/js || mkdir public/js - - test -f public/js/fos_js_routes.json || echo "{}" > public/js/fos_js_routes.json - - npm run build diff --git a/CHANGELOG.md b/CHANGELOG.md index 9920ba6..d6db227 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,243 +1,3 @@ ## [Unreleased] -## [v1.26.0] - 2025-03-17 -### Changed -* upgrade murph/murph-core - -## [v1.25.1] - 2024-05-13 -### Fixed -* fix murph-npm version - -## [v1.25.0] - 2024-05-12 -### Changed -* upgrade murph/murph-core - -## [v1.23.0] - 2023-09-28 -### Changed -* upgrade murph/murph-core - -## [v1.22.0] - 2023-09-28 -### Added -* update woodpecker ci base file -### Fixed -* fix #1: add UniqueEntity constraint in the User entity -### Changed -* upgrade murph/murph-core - -## [1.21.0] - 2023-08-11 -### Changed -* upgrade murph/murph-core - -## [1.20.0] - 2023-07-27 -### Fixed -* fix collection widget: allow_add/allow_delete and prototype -### Added -* add user admin controller and simples views in default files -* add chdir in the console entrypoint -### Changed -* upgrade murph/murph-core - -## [1.19.0] - 2023-04-15 -### Changed -* upgrade murph/murph-core - -## [1.18.0] - 2023-01-13 -### Added -* feat(dep): update dependencies -* feat(update): apply new recipe for phpunit -* feat(update): apply recipes:update doctrine/doctrine-bundle -* feat(update): apply recipes:update doctrine/doctrine-migrations-bundle -* feat(update): apply recipes:update liip/imagine-bundle -* feat(update): apply recipes:update stof/doctrine-extensions-bundle -* feat(update): apply recipes:update symfony/apache-pack -* feat(update): apply recipes:update symfony/console -* feat(update): apply recipes:update symfony/debug-bundle -* feat(update): apply recipes:update symfony/flex -* feat(update): apply recipes:update symfony/mailer -* feat(update): apply recipes:update symfony/framework-bundle -* feat(update): apply recipes:update symfony/monolog-bundle -* feat(update): apply recipes:update symfony/routing -* feat(update): apply recipes:update symfony/security-bundle -* feat(update): apply recipes:update symfony/translation -* feat(update): apply recipes:update symfony/twig-bundle -* feat(update): apply recipes:update symfony/validator -* feat(update): apply recipes:update symfony/web-profiler-bundle -* feat(update): apply recipes:update symfony/webpack-encore-bundle -* feat(update): apply recipes:update scheb/2fa-bundle -### Fixed -* fix(config): fix typo in 2fa conf -* fix(config): fix firewall config - - -## [1.17.0] - 2022-11-19 -### Changed -* upgrade murph/murph-core -* replace annotation with attributes -* use encore from node_modules in npm scripts - -## [1.16.0] -### Added -* add a admin dashboard controller -* add meta description in base.html.twig -### Fixed -### Changed -* upgrade murph/murph-core - -## [1.15.0] -### Changed -* upgrade murph/murph-core - -## [1.14.3] -### Added -* add blocks in default template -### Changed -* upgrade murph/murph-core - -## [1.14.2] - -## [1.14.1] -### Fixed -* fix missing envvar in makefile (npm) - -## [1.14.0] -### Changed -* upgrade murph/murph-core - -## [1.13.0] -### Changed -* upgrade murph/murph-core - -## [1.12.0] -### Changed -* upgrade murph/murph-core - -## [1.11.0] -### Changed -* upgrade murph/murph-core -* use murph-npm to install npm requirements - -## [1.10.0] -### Added -* add translated title in dashboard template -### Fixed -* remove useless env var from makefile -### Changed -* upgrade murph/murph-core - -## [1.9.1] - 2022-03-14 -### Added -* add murph version in autoload file -### Changed -* remove AdminController constructor - -## [1.9.0] - 2022-03-13 -### Added -* add murph version in admin ui -### Changed -* the core is now installed with composer - -## [1.8.0] - 2022-03-10 -### Added -* add security roles in app configuration -* add option to restrict node access to specific roles -### Changed -* rename `core/EventSuscriber` with `core/EventSubscriber` - -## [1.7.3] - 2022-03-06 -### Added -* add ability to rename file in the file manager -### Fixed -* fix user factory -* fix user creation from ui - -## [1.7.2] - 2022-03-03 -### Added -* add templates to render sections and items in the admin menu -### Fixed -* fix the analytic table when a path is a long - -## [1.7.1] - 2022-03-01 -### Added -* add translations -### Fixed -* fix missing directories - -## [1.7.0] - 2022-03-01 -### Fixed -* fix the analytic referers table when a referer has a long domain -### Changed -* upgrade dependencies -* move assets to the core directory - -## [1.6.0] - 2022-02-28 -### Added -* add block in field templates to allow override -* merge route params in crud admin redirects -* improve murph:user:create command - -### Fixed -* fix form namespace prefix in the crud controller maker -* fix date field when the value is empty -* fix crud batch column width -* fix sidebar icon width -* fix cache clear task - -### Changed -* remove password generation from the user factory - -## [1.5.0] - 2022-02-25 -### Added -* add desktop views and mobile views - -### Changed -* upgrade dependencies -* replace jaybizzle/crawler-detect with matomo/device-detector - -## [1.4.1] - 2022-02-23 -### Added -* handle app urls in twig routing filters - -### Fixed -* fix views in analytics modal -* replace empty path with "/" in analytics -### Changed -* update default templates - -## [1.4.0] - 2022-02-21 -### Added -* add basic analytics - -## [1.3.0] - 2022-02-19 -### Added -* add support of regexp with substitution in redirect -* url tags can be used as redirect location -* add builders to replace file information tags and url tags - -### Fixed -* fix filemanager sorting -* fix batch action setter - -## [1.2.0] - 2022-02-14 -### Added -* add sort in file manager -* add redirect manager - -### Changed -* replace node-sass with sass - -## [1.1.0] - 2022-02-29 -### Added -* add directory upload in file manager - -### Fixed -* fix admin node routing - -### Changed -* symfony/swiftmailer-bundle is replaced by symfony/mailer - -## [1.0.1] - 2022-02-25 -### Fixed -* fix Makefile environment vars (renaming) -* fix composer minimum stability - -## [1.0.0] - 2022-01-23 +## 1.0.0 diff --git a/Makefile b/Makefile index 4a190b7..393e17c 100644 --- a/Makefile +++ b/Makefile @@ -1,26 +1,30 @@ -COMPOSER_BIN ?= composer -PHP_BIN ?= php8.1 -YARN_BIN ?= yarn -NPM_BIN ?= npm +COMPOSER ?= composer +PHP ?= php8.1 +SSH ?= ssh +WEBPACK ?= webpack +YARN ?= yarn -all: build +all: dep asset clean + +.ONESHELL: +dep: + $(COMPOSER) update --ignore-platform-reqs + $(COMPOSER) install --ignore-platform-reqs + $(YARN) asset-watch: - $(YARN_BIN) - $(NPM_BIN) run watch + $(WEBPACK) -w asset: js-routing - $(YARN_BIN) - $(NPM_BIN) run build + $(YARN) + $(WEBPACK) -js-routing: doctrine-migration - $(PHP_BIN) bin/console fos:js-routing:dump --format=json --target=public/js/fos_js_routes.json +js-routing: + $(PHP) bin/console fos:js-routing:dump --format=json --target=public/js/fos_js_routes.json clean: rm -fr var/cache/dev/* rm -fr var/cache/prod/* doctrine-migration: - PHP=$(PHP_BIN) ./bin/doctrine-migrate - -build: clean js-routing asset + PHP=$(PHP) ./bin/doctrine-migrate diff --git a/README.md b/README.md index 928d935..c8e100d 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,8 @@ -# Murph +# MURPH -Murph is an **open-source CMF** built on top of Symfony that helps you to **build your own CMS with several domains and languages**. It comes with: +Muprh is an open-source CMF built on top of Symfony that helps you to build your own CMS with several domains and languages. It comes with a fully implemented and customizable tree manager, a CRUD generator, a 2FA authentication, settings and tasks managers. -* A fully implemented and customizable **tree manager** ๐ŸŒณ -* A **CRUD generator** โœ๏ธ -* A global **settings manager** and a navigation settings manager โš™๏ธ -* A **tasks manager** ๐Ÿงน -* A basic **web analytics** ๐Ÿ“Š -* **2FA authentication** ๐Ÿ”’ +Symfony developers will love build on Murph ๐Ÿ’ช +End users will be fond of the interface and the powerful tools ๐Ÿ’œ -**Symfony developers will love build on Murph ๐Ÿงช** - -**End users will be fond of the interface and the powerful tools ๐Ÿ’œ** - -๐Ÿ“— [Read the documentation](https://doc.murph-project.org/) +## [Read the documentation](https://doc.murph-project.org/) diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 1b21cbc..0000000 --- a/SECURITY.md +++ /dev/null @@ -1,12 +0,0 @@ -# Security Policy - -## Supported Versions - -| Version | Supported | -| ---------- | --------- | -| >= 2.0 | :x: | -| >= 1.0 | :white_check_mark: | - -## Reporting a Vulnerability - -If you discover a security vulnerability within Murph, send an email to security [at] murph-project.org. diff --git a/UPGRADE.md b/UPGRADE.md deleted file mode 100644 index 2195d97..0000000 --- a/UPGRADE.md +++ /dev/null @@ -1,115 +0,0 @@ -## General process - -Upgrade dependencies: - -* `composer update` -* `yarn upgrade` - -Build: - -* `make build` - -## [Unreleased] - -## Upgrade to v1.17.0 - -Replace all annotations with PHP8 attributes and change the doctrine configuration: - -``` -# config/packages/doctrine.yaml -doctrine: - ... - orm: - ... - mappings: - App\Core\Entity: - type: attribute - ... - App\Entity: - type: attribute - ... -``` - -## Upgrade to v1.15.0 - -``` -cd public/vendor -ln -rs ../../node_modules/grapesjs-plugin-export . -ln -rs ../../node_modules/grapesjs-parser-postcss . -``` - -## Upgrade to v1.10.0 -### Commands - -``` -make doctrine-migration -``` - - -## Upgrade to v1.9.0 - -This version uses the package `murph/murph-core`. - - -## Upgrade to v1.8.0 -### Commands - -``` -make doctrine-migration -``` - -### Files - -Event subscribers in `src/EventSubscriber` must update namespaces. - -## Upgrade to v1.7.0 -### Commands - -``` -yarn add sortablejs@^1.14.0 - -``` - -### Files - -* `assets/css/_admin_extend.scss` is removed -* `assets/css/_admin_vars.scss` is removed -* `assets/css/_admin_vars.scss` is changed -* `assets/js/admin` is removed -* `assets/js/admin.js` is changed - - -## Upgrade to v1.5.0 -### Commands - -``` -composer remove jaybizzle/crawler-detect -composer require matomo/device-detector -make doctrine-migration -``` - -## Upgrade to v1.4.0 -### Commands - -``` -yarn remove node-sass -yarn add sass --dev --save -yarn add chart.js --save -composer require jaybizzle/crawler-detect -make doctrine-migration -make asset -``` - -### Configuration - -``` -// config/services.yaml -services: - App\Core\EventListener\RedirectListener: - tags: - - { name: kernel.event_listener, event: kernel.exception } - - App\Core\EventListener\AnalyticListener: - tags: - - { name: kernel.event_listener, event: kernel.request } -``` diff --git a/assets/css/_admin_extend.scss b/assets/css/_admin_extend.scss new file mode 100644 index 0000000..88f6b3d --- /dev/null +++ b/assets/css/_admin_extend.scss @@ -0,0 +1,5 @@ +$theme-colors: ( + "primary": #1ab5dc, + "primary-light": lighten(#3183aa, 40%), + "dark-blue": #1e2430, +) !default; diff --git a/migrations/.gitkeep b/assets/css/_admin_vars.scss similarity index 100% rename from migrations/.gitkeep rename to assets/css/_admin_vars.scss diff --git a/assets/css/admin.scss b/assets/css/admin.scss index 790ff01..668eeef 100644 --- a/assets/css/admin.scss +++ b/assets/css/admin.scss @@ -1,6 +1,523 @@ -/* Custom variables */ +@import "./_admin_vars.scss"; -@import "../../vendor/murph/murph-core/src/core/Resources/assets/css/admin.scss"; +$theme-colors: ( + "primary": #1ab5dc, + "primary-light": lighten(#3183aa, 40%), + "dark-blue": #1e2430, +) !default; -/* Custom CSS */ +$grid-gutter-width: 0px !default; +$pagination-color: #343a40 !default; +$pagination-bg: #ffffff !default; +$pagination-active-color: #ffffff !default; +$pagination-active-bg: #343a40 !default; +@import "~choices.js/src/styles/choices.scss"; +@import "~bootstrap/scss/bootstrap.scss"; +@import "~@fortawesome/fontawesome-free/css/all.css"; +@import "~flag-icon-css/sass/flag-icon.scss"; + +@for $i from 1 through 100 { + .miw-#{$i*5} { + min-width: $i * 5px; + } +} + +.flag-icon-en { + background-image: url(~flag-icon-css/flags/4x3/gb.svg); +} + +body { + overflow-x: hidden; +} + +#logo { + width: 30px; +} + +.choices__list--dropdown { + display: none; +} + +.choices__list--dropdown.is-active { + display: block; +} + +.dropdown-toggle-hide-after { + &::after { + display: none; + } +} + +.login { + &-container { + margin-top: 5%; + margin-bottom: 5%; + } + + &-form { + padding: 5%; + } + + &-image { + width: 100%; + max-width: 80%; + } +} + +.sidebar { + position: fixed; + top: 0; + bottom: 0; + left: 0; + z-index: 100; + padding: 71px 0 0; + box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1); +} + +.sidebar-sticky { + position: relative; + top: 0; + height: calc(100vh - 71px); + padding-top: .5rem; + overflow-x: hidden; + overflow-y: hidden; + + &:hover { + overflow-y: auto; + } +} + +@supports ((position: -webkit-sticky) or (position: sticky)) { + .sidebar-sticky { + position: -webkit-sticky; + position: sticky; + } +} + +.actions-container { + padding-right: 25px; +} + +.table .thead-light { + a, th { + color: map-get($theme-colors, 'dark-blue'); + } +} + +tr.table-primary-light { + background-color: #ecf5fa; +} + +.td-nowrap { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.table tr { + td { + transition: border 500ms ease-out; + border-bottom: 1px solid #dee2e6; + } + + &:hover { + td { + border-bottom: 1px solid #a8aaac; + } + } +} + +.bg-dark-blue { + background: map-get($theme-colors, 'dark-blue'); + color: #fff; + + .nav-item-label { + color: #fff; + } +} + +.nav-pills { + .nav-item { + margin-right: 3px; + } + + .nav-link:not(.active) { + color: #333; + background: #eee; + } +} + + +.sidebar { + width: 260px; + display: inline-block; + + .nav-link { + font-weight: 500; + color: #333; + border-left: 4px solid map-get($theme-colors, 'dark-blue'); + padding-top: 14px; + padding-bottom: 14px; + + .fa { + font-size: 1.2rem; + margin-right: 5px; + min-width: 30px; + color: #fff; + } + + &.active { + font-weight: bold; + border-left: 4px solid map-get($theme-colors, 'primary'); + background: map-get($theme-colors, 'dark-blue'); + } + } + + &-heading { + font-size: .75rem; + text-transform: uppercase; + display: flex; + } +} + +*[data-selectable-selector] { + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; +} + +*[data-selectable-selector] { + &:hover { + cursor: pointer; + } +} + +*[data-sortable-item] { + &:hover { + cursor: pointer; + } + + &.sortable-chosen { + background: map-get($theme-colors, 'primary-light'); + } +} + +.footer { + position: absolute; + bottom: 0; + left: 0; + width: 100%; + z-index: 1000; + height: 35px; + background: #f8f9fa; +} + +.body { + padding-top: 60px; + width: calc(100% - 260px); + margin-left: 260px; + display: inline-block; + + .nav { + padding-left: 10px; + } +} + +@media screen and (max-width: 770px) { + .body { + margin-left: 50px; + width: calc(100vw - 50px); + } + + .sidebar { + width: 50px; + max-width: 100% !important; + + .sidebar-sticky { + width: 50px; + max-width: 100% !important; + } + + .nav { + padding-left: 0; + } + + .nav-link { + padding-left: 10px; + } + + .nav-item-label { + display: none; + } + + .sidebar-heading { + display: none; + } + } +} + +th { + &.sorted { + &::before { + content: '\f0dc'; + font-family: 'FontAwesome'; + color: #aaa; + margin-right: 3px; + } + } +} + +.table-responsive { + max-width: 100%; + overflow-y: hidden; +} + +.toast-container { + display: flex; + position: relative; + z-index: 4000; + + .toast-wrapper { + position: fixed; + top: 20px; + right: 20px; + z-index: 1060; + width: 300px; + } +} + +.bg-tiles { + background-color: #c1c1c1; + background-image: linear-gradient(45deg, #646464 25%, transparent 25%, transparent 75%, #646464 75%), linear-gradient(45deg, #646464 25%, transparent 25%, transparent 75%, #646464 75%); + background-size: 20px 20px; + background-position: 0 0, 10px 10px; +} + +.tab-form { + padding: 15px; +} + +.icon-margin { + margin-right: 4px; +} + +.file-icon { + font-size: 2em; +} + +.d-ib { + display: inline-block; +} + +.list-checkbox { + vertical-align: middle; + margin-right: 10px; + margin-top: -2px; +} + +.password-strenth { + padding: 0 0 5px 0; + margin-top: -4px; + + .col-sm { + height: 8px; + border: 2px solid #fff; + } + + &-info { + font-size: 13px; + height: 22px; + } +} + +.notification-bell:not([disabled]) { + [data-counter]:after { + display: block; + color: #fff; + background: red; + width: 9px; + height: 9px; + position: absolute; + content: ' '; + top: 4px; + right: 10px; + border-radius: 4px; + } +} + +.form-error-icon { + margin-right: 4px; +} + +.custom-file-label::after { + content: "Parcourir"; +} + +#lease_template_html { + height: calc(100vh - 270px); +} + +.panel { + &-toggler { + &:hover { + cursor: pointer; + } + } + + &-content { + display: block; + + &:not(.active) { + display: none; + } + } +} + +*[data-collection-delete-container] { + cursor: pointer; +} + +*[data-collection-add] { + cursor: pointer; +} + +.login-image { + width: 50%; +} + +.tree { + position: relative; + background: white; + color: #212529; + + span { + font-style: italic; + letter-spacing: .4px; + color: #a8a8a8; + } + + .fa-folder-open, .fa-folder { + color: #007bff; + } + + .fa-html5 { + color: #f21f10; + } + + ul { + padding-left: 5px; + list-style: none; + margin: 0; + padding-bottom: 0; + + li { + position: relative; + padding-top: 5px; + padding-bottom: 5px; + padding-left: 15px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + + &:before { + position: absolute; + top: 15px; + left: 0; + width: 10px; + height: 1px; + margin: auto; + content: ''; + background-color: #666; + } + + &:after { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 1px; + height: 100%; + content: ''; + background-color: #666; + } + + &:last-child:after { + height: 15px; + } + } + + a { + cursor: pointer; + + &:hover { + text-decoration: none; + } + } + } +} + +fieldset.form-group { + margin-bottom: 0; +} + +.crud-header { + &-title { + font-size: 2em; + } + + &-actions { + text-align: right; + margin-bottom: 10px; + } + + @media screen and (min-width: 770px) { + &-title { + float: left; + font-size: 2em; + } + + &-actions { + float: right; + } + + } + + &::after { + display: block; + content: ""; + clear: both; + } +} + +th.crud-batch-column { + width: 20px !important; + max-width: 20px; +} + +form { + .loader { + display: none; + } + + &.is-loading .loader { + display: inline-block; + } +} + +.modal { + z-index: 3000; +} + +.modal-dialog-large { + max-width: 80%; +} + +.output { + &-console { + background: #073642; + line-height: normal; + } +} + +@import "./_admin_extend.scss"; diff --git a/assets/css/app.scss b/assets/css/app.scss deleted file mode 100644 index 08c1c99..0000000 --- a/assets/css/app.scss +++ /dev/null @@ -1,2 +0,0 @@ -/* CSS of you app */ - diff --git a/assets/images/blank.png b/assets/images/blank.png new file mode 100644 index 0000000..5e21c8a Binary files /dev/null and b/assets/images/blank.png differ diff --git a/assets/images/logo.png b/assets/images/logo.png new file mode 100644 index 0000000..53eae46 Binary files /dev/null and b/assets/images/logo.png differ diff --git a/assets/images/no-image.png b/assets/images/no-image.png new file mode 100644 index 0000000..7957221 Binary files /dev/null and b/assets/images/no-image.png differ diff --git a/assets/js/admin.js b/assets/js/admin.js index e32d857..0a1192e 100644 --- a/assets/js/admin.js +++ b/assets/js/admin.js @@ -1 +1 @@ -import '../../vendor/murph/murph-core/src/core/Resources/assets/js/admin.js' +import './admin/admin.js' diff --git a/assets/js/admin/admin.js b/assets/js/admin/admin.js new file mode 100644 index 0000000..0bf8794 --- /dev/null +++ b/assets/js/admin/admin.js @@ -0,0 +1,25 @@ +import '../../css/admin.scss' + +require('../../../node_modules/bootstrap/dist/js/bootstrap.min.js') +require('./modules/table-fixed.js')() +require('./modules/form-confirm.js')() +require('./modules/form-file.js')() +require('./modules/form-error.js')() +require('./modules/form-ajax.js')() +require('./modules/dbclick.js')() +require('./modules/toast.js')() +require('./modules/modal.js')() +require('./modules/push-state.js')() +require('./modules/password.js')() +require('./modules/tooltip.js')() +require('./modules/editor.js')() +require('./modules/panel.js')() +require('./modules/choices.js')() +require('./modules/checkbox-checker.js')() +require('./modules/rest-choices.js')() +require('./modules/form-collection.js')() +require('./modules/datepicker.js')() +require('./modules/sortable.js')() +require('./modules/batch.js')() +require('./modules/file-manager.js')() +require('./modules/file-picker.js')() diff --git a/assets/js/admin/components/file-manager/FileIcon.vue b/assets/js/admin/components/file-manager/FileIcon.vue new file mode 100644 index 0000000..7769928 --- /dev/null +++ b/assets/js/admin/components/file-manager/FileIcon.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/assets/js/admin/components/file-manager/FileManager.vue b/assets/js/admin/components/file-manager/FileManager.vue new file mode 100644 index 0000000..eab7f4a --- /dev/null +++ b/assets/js/admin/components/file-manager/FileManager.vue @@ -0,0 +1,30 @@ + + + + + diff --git a/assets/js/admin/components/file-manager/Files.vue b/assets/js/admin/components/file-manager/Files.vue new file mode 100644 index 0000000..edc575e --- /dev/null +++ b/assets/js/admin/components/file-manager/Files.vue @@ -0,0 +1,344 @@ + + + + + diff --git a/assets/js/admin/modules/batch.js b/assets/js/admin/modules/batch.js new file mode 100644 index 0000000..2d5c1f2 --- /dev/null +++ b/assets/js/admin/modules/batch.js @@ -0,0 +1,23 @@ +const $ = require('jquery') + +module.exports = () => { + $('th.crud-batch-column input').change((e) => { + $('td.crud-batch-column input').prop('checked', $(e.target).is(':checked')) + }) + + const form = $('#form-batch') + + form.submit((e) => { + e.preventDefault() + + const route = form.attr('action') + const datas = form.serialize() + + form.addClass('is-loading') + + $.post(route, datas) + .always(() => { + document.location.reload() + }) + }) +} diff --git a/assets/js/admin/modules/checkbox-checker.js b/assets/js/admin/modules/checkbox-checker.js new file mode 100644 index 0000000..c6804a5 --- /dev/null +++ b/assets/js/admin/modules/checkbox-checker.js @@ -0,0 +1,31 @@ +const $ = require('jquery') + +module.exports = function () { + $('*[data-checkbox-ckecker]').click(function () { + const wrapperName = $(this).attr('data-checkbox-ckecker') + + if (!wrapperName) { + return + } + + const checkboxes = $('*[data-checkbox-wrapper="' + wrapperName + '"] *[data-checkbox] input[type="checkbox"]') + + $(checkboxes).each(function (i, v) { + $(v).prop('checked', true) + }) + }) + + $('*[data-checkbox-unckecker]').click(function () { + const wrapperName = $(this).attr('data-checkbox-unckecker') + + if (!wrapperName) { + return + } + + const checkboxes = $('*[data-checkbox-wrapper="' + wrapperName + '"] *[data-checkbox] input[type="checkbox"]') + + $(checkboxes).each(function (i, v) { + $(v).prop('checked', false) + }) + }) +} diff --git a/assets/js/admin/modules/choices.js b/assets/js/admin/modules/choices.js new file mode 100644 index 0000000..d2da709 --- /dev/null +++ b/assets/js/admin/modules/choices.js @@ -0,0 +1,8 @@ +const Choices = require('choices.js') +const $ = require('jquery') + +module.exports = function () { + $('*[data-jschoice]').each(function (key, item) { + return new Choices(item) + }) +} diff --git a/assets/js/admin/modules/datepicker.js b/assets/js/admin/modules/datepicker.js new file mode 100644 index 0000000..673ae32 --- /dev/null +++ b/assets/js/admin/modules/datepicker.js @@ -0,0 +1,30 @@ +const Datepicker = require('vanillajs-datepicker') + +const isDateSupported = () => { + const input = document.createElement('input') + const value = 'a' + + input.setAttribute('type', 'date') + input.setAttribute('value', value) + + return input.value !== value +} + +const createDatePicker = (input) => { + return new Datepicker.Datepicker(input, { + format: 'yyyy-mm-dd' + }) +} + +module.exports = () => { + if (isDateSupported()) { + return + } + + const inputs = document.querySelectorAll('input[type="date"]') + const size = inputs.length + + for (let i = 0, c = size; i < c; i++) { + createDatePicker(inputs[i]) + } +} diff --git a/assets/js/admin/modules/dbclick.js b/assets/js/admin/modules/dbclick.js new file mode 100644 index 0000000..57713cf --- /dev/null +++ b/assets/js/admin/modules/dbclick.js @@ -0,0 +1,7 @@ +const $ = require('jquery') + +module.exports = function () { + $('*[data-dblclick]').dblclick(function (e) { + document.location.href = $(this).attr('data-dblclick') + }) +} diff --git a/assets/js/admin/modules/document-selector.js b/assets/js/admin/modules/document-selector.js new file mode 100644 index 0000000..604f77f --- /dev/null +++ b/assets/js/admin/modules/document-selector.js @@ -0,0 +1,42 @@ +const $ = require('jquery') + +const DocumentSelector = () => { + const forms = $('.document-selector-form') + + const handler = function () { + forms.each((fi, f) => { + const form = $(f) + const ids = form.find('.document-selector-ids') + const btn = form.find('.document-selector-button') + + ids.html('') + let hasSelection = false + + $('*[data-documents] *[data-selectable-row] input[data-selectable-checkbox]').each((i, c) => { + const checkbox = $(c) + + if (checkbox.is(':checked')) { + ids.append(checkbox[0].outerHTML) + hasSelection = true + } + }) + + if (hasSelection && btn.length) { + btn.removeAttr('disabled') + ids.find('input').prop('checked', true) + } else { + btn.attr('disabled', 'disabled') + } + }) + } + + $('*[data-documents] *[data-selectable-row]').click(function () { + window.setTimeout(handler, 100) + }) + + $('*[data-documents] *[data-selectable-row]').on('clicked', function () { + window.setTimeout(handler, 100) + }) +} + +module.exports = DocumentSelector diff --git a/assets/js/admin/modules/editor.js b/assets/js/admin/modules/editor.js new file mode 100644 index 0000000..7bfba77 --- /dev/null +++ b/assets/js/admin/modules/editor.js @@ -0,0 +1,626 @@ +const $ = require('jquery') +const Vue = require('vue').default +const FileManager = require('../components/file-manager/FileManager').default + +const createModal = function () { + let container = $('#fm-modal') + const body = $('body') + + if (!container.length) { + container = $('