├── .editorconfig ├── .env.example ├── .gitattributes ├── .gitignore ├── Makefile ├── README.md ├── _ide_helper.php ├── _ide_helper_models.php ├── app ├── Http │ ├── Controllers │ │ ├── CategoryController.php │ │ ├── CompanyController.php │ │ ├── Controller.php │ │ └── LayoutController.php │ └── Requests │ │ ├── Auth │ │ └── LoginRequest.php │ │ ├── CompanyRequest.php │ │ └── ProfileUpdateRequest.php ├── Models │ ├── Category.php │ ├── Company.php │ └── User.php ├── MoonShine │ ├── Pages │ │ └── Dashboard.php │ └── Resources │ │ ├── CompanyResource.php │ │ └── InactiveCompanyResource.php ├── Providers │ ├── AppServiceProvider.php │ └── MoonShineServiceProvider.php └── View │ └── Components │ ├── AppLayout.php │ └── GuestLayout.php ├── artisan ├── bootstrap ├── app.php ├── cache │ └── .gitignore └── providers.php ├── composer.json ├── composer.lock ├── config ├── app.php ├── auth.php ├── cache.php ├── database.php ├── filesystems.php ├── logging.php ├── mail.php ├── moonshine.php ├── queue.php ├── services.php └── session.php ├── database ├── .gitignore ├── factories │ └── UserFactory.php ├── migrations │ ├── 0001_01_01_000000_create_users_table.php │ ├── 0001_01_01_000001_create_cache_table.php │ ├── 0001_01_01_000002_create_jobs_table.php │ ├── 2024_10_29_112923_create_companies_table.php │ ├── 2024_11_04_113429_create_categories_table.php │ └── 2024_11_26_062942_add_status_to_companies_table.php └── seeders │ ├── CategorySeeder.php │ └── DatabaseSeeder.php ├── docker-compose.yml ├── docker ├── config │ ├── phpstan.neon.dist │ └── pint.json └── development │ ├── nginx │ └── conf.d │ │ └── phpwork.conf │ └── php │ ├── Dockerfile │ ├── php.ini │ └── xdebug.ini ├── identifier.sqlite ├── lang └── vendor │ └── moonshine │ ├── en │ ├── auth.php │ ├── pagination.php │ ├── ui.php │ └── validation.php │ └── ru │ ├── auth.php │ ├── pagination.php │ ├── ui.php │ └── validation.php ├── package-lock.json ├── package.json ├── phpstan-local.neon.dist ├── phpunit.xml ├── phpwork ├── postcss.config.js ├── public ├── .htaccess ├── assets │ └── img │ │ ├── as.png │ │ ├── b.png │ │ ├── c.jpg │ │ └── hh.svg ├── favicon.ico ├── index.php ├── robots.txt └── vendor │ └── moonshine │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── assets │ ├── app.js │ ├── main.css │ └── minimalistic.css │ ├── avatar.jpg │ ├── browserconfig.xml │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── fonts │ ├── Gilroy-Black.woff2 │ ├── Gilroy-Bold.woff2 │ ├── Gilroy-Medium.woff2 │ ├── Gilroy-Regular.woff2 │ └── Gilroy-SemiBold.woff2 │ ├── libs │ ├── apexcharts │ │ ├── apexcharts-config.js │ │ └── apexcharts.min.js │ ├── easymde │ │ ├── easymde.min.css │ │ ├── easymde.min.js │ │ ├── purify.min.js │ │ └── purify.min.js.map │ └── tinymce │ │ ├── icons │ │ └── default │ │ │ └── icons.min.js │ │ ├── langs │ │ ├── README.md │ │ ├── ru.js │ │ └── uk.js │ │ ├── license.txt │ │ ├── models │ │ └── dom │ │ │ └── model.min.js │ │ ├── plugins │ │ ├── accordion │ │ │ └── plugin.min.js │ │ ├── advlist │ │ │ └── plugin.min.js │ │ ├── anchor │ │ │ └── plugin.min.js │ │ ├── autolink │ │ │ └── plugin.min.js │ │ ├── autoresize │ │ │ └── plugin.min.js │ │ ├── autosave │ │ │ └── plugin.min.js │ │ ├── charmap │ │ │ └── plugin.min.js │ │ ├── code │ │ │ └── plugin.min.js │ │ ├── codesample │ │ │ └── plugin.min.js │ │ ├── directionality │ │ │ └── plugin.min.js │ │ ├── emoticons │ │ │ ├── js │ │ │ │ ├── emojiimages.js │ │ │ │ ├── emojiimages.min.js │ │ │ │ ├── emojis.js │ │ │ │ └── emojis.min.js │ │ │ └── plugin.min.js │ │ ├── fullscreen │ │ │ └── plugin.min.js │ │ ├── help │ │ │ ├── js │ │ │ │ └── i18n │ │ │ │ │ └── keynav │ │ │ │ │ ├── ar.js │ │ │ │ │ ├── bg_BG.js │ │ │ │ │ ├── ca.js │ │ │ │ │ ├── cs.js │ │ │ │ │ ├── da.js │ │ │ │ │ ├── de.js │ │ │ │ │ ├── el.js │ │ │ │ │ ├── en.js │ │ │ │ │ ├── es.js │ │ │ │ │ ├── eu.js │ │ │ │ │ ├── fa.js │ │ │ │ │ ├── fi.js │ │ │ │ │ ├── fr_FR.js │ │ │ │ │ ├── he_IL.js │ │ │ │ │ ├── hi.js │ │ │ │ │ ├── hr.js │ │ │ │ │ ├── hu_HU.js │ │ │ │ │ ├── id.js │ │ │ │ │ ├── it.js │ │ │ │ │ ├── ja.js │ │ │ │ │ ├── kk.js │ │ │ │ │ ├── ko_KR.js │ │ │ │ │ ├── ms.js │ │ │ │ │ ├── nb_NO.js │ │ │ │ │ ├── nl.js │ │ │ │ │ ├── pl.js │ │ │ │ │ ├── pt_BR.js │ │ │ │ │ ├── pt_PT.js │ │ │ │ │ ├── ro.js │ │ │ │ │ ├── ru.js │ │ │ │ │ ├── sk.js │ │ │ │ │ ├── sl_SI.js │ │ │ │ │ ├── sv_SE.js │ │ │ │ │ ├── th_TH.js │ │ │ │ │ ├── tr.js │ │ │ │ │ ├── uk.js │ │ │ │ │ ├── vi.js │ │ │ │ │ ├── zh_CN.js │ │ │ │ │ └── zh_TW.js │ │ │ └── plugin.min.js │ │ ├── image │ │ │ └── plugin.min.js │ │ ├── importcss │ │ │ └── plugin.min.js │ │ ├── insertdatetime │ │ │ └── plugin.min.js │ │ ├── link │ │ │ └── plugin.min.js │ │ ├── lists │ │ │ └── plugin.min.js │ │ ├── media │ │ │ └── plugin.min.js │ │ ├── nonbreaking │ │ │ └── plugin.min.js │ │ ├── pagebreak │ │ │ └── plugin.min.js │ │ ├── preview │ │ │ └── plugin.min.js │ │ ├── quickbars │ │ │ └── plugin.min.js │ │ ├── save │ │ │ └── plugin.min.js │ │ ├── searchreplace │ │ │ └── plugin.min.js │ │ ├── table │ │ │ └── plugin.min.js │ │ ├── template │ │ │ └── plugin.min.js │ │ ├── visualblocks │ │ │ └── plugin.min.js │ │ ├── visualchars │ │ │ └── plugin.min.js │ │ └── wordcount │ │ │ └── plugin.min.js │ │ ├── skins │ │ ├── content │ │ │ ├── dark │ │ │ │ ├── content.js │ │ │ │ └── content.min.css │ │ │ ├── default │ │ │ │ ├── content.js │ │ │ │ └── content.min.css │ │ │ ├── document │ │ │ │ ├── content.js │ │ │ │ └── content.min.css │ │ │ ├── tinymce-5-dark │ │ │ │ ├── content.js │ │ │ │ └── content.min.css │ │ │ ├── tinymce-5 │ │ │ │ ├── content.js │ │ │ │ └── content.min.css │ │ │ └── writer │ │ │ │ ├── content.js │ │ │ │ └── content.min.css │ │ └── ui │ │ │ ├── oxide-dark │ │ │ ├── content.inline.js │ │ │ ├── content.inline.min.css │ │ │ ├── content.js │ │ │ ├── content.min.css │ │ │ ├── skin.js │ │ │ ├── skin.min.css │ │ │ ├── skin.shadowdom.js │ │ │ └── skin.shadowdom.min.css │ │ │ ├── oxide │ │ │ ├── content.inline.js │ │ │ ├── content.inline.min.css │ │ │ ├── content.js │ │ │ ├── content.min.css │ │ │ ├── skin.js │ │ │ ├── skin.min.css │ │ │ ├── skin.shadowdom.js │ │ │ └── skin.shadowdom.min.css │ │ │ ├── tinymce-5-dark │ │ │ ├── content.inline.js │ │ │ ├── content.inline.min.css │ │ │ ├── content.js │ │ │ ├── content.min.css │ │ │ ├── skin.js │ │ │ ├── skin.min.css │ │ │ ├── skin.shadowdom.js │ │ │ └── skin.shadowdom.min.css │ │ │ └── tinymce-5 │ │ │ ├── content.inline.js │ │ │ ├── content.inline.min.css │ │ │ ├── content.js │ │ │ ├── content.min.css │ │ │ ├── skin.js │ │ │ ├── skin.min.css │ │ │ ├── skin.shadowdom.js │ │ │ └── skin.shadowdom.min.css │ │ ├── themes │ │ └── silver │ │ │ └── theme.min.js │ │ ├── tinymce.d.ts │ │ └── tinymce.min.js │ ├── logo-small.svg │ ├── logo.svg │ ├── manifest.json │ ├── mstile-150x150.png │ ├── robots.txt │ ├── safari-pinned-tab.svg │ └── site.webmanifest ├── resources ├── css │ └── app.css ├── js │ ├── app.js │ └── bootstrap.js └── views │ └── welcome.blade.php ├── routes └── web.php ├── storage ├── app │ ├── .gitignore │ ├── private │ │ └── .gitignore │ └── public │ │ └── .gitignore ├── framework │ ├── .gitignore │ ├── cache │ │ ├── .gitignore │ │ └── data │ │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ ├── testing │ │ └── .gitignore │ └── views │ │ └── .gitignore └── logs │ └── .gitignore ├── tailwind.config.js ├── tests ├── Feature │ ├── Auth │ │ ├── AuthenticationTest.php │ │ ├── EmailVerificationTest.php │ │ ├── PasswordConfirmationTest.php │ │ ├── PasswordResetTest.php │ │ ├── PasswordUpdateTest.php │ │ └── RegistrationTest.php │ ├── ExampleTest.php │ └── ProfileTest.php ├── TestCase.php └── Unit │ └── ExampleTest.php └── vite.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | 17 | [docker-compose.yml] 18 | indent_size = 4 19 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_ENV=local 3 | APP_KEY= 4 | APP_DEBUG=true 5 | APP_TIMEZONE=UTC 6 | APP_URL=http://localhost 7 | 8 | APP_LOCALE=en 9 | APP_FALLBACK_LOCALE=en 10 | APP_FAKER_LOCALE=en_US 11 | 12 | APP_MAINTENANCE_DRIVER=file 13 | # APP_MAINTENANCE_STORE=database 14 | 15 | PHP_CLI_SERVER_WORKERS=4 16 | 17 | BCRYPT_ROUNDS=12 18 | 19 | LOG_CHANNEL=stack 20 | LOG_STACK=single 21 | LOG_DEPRECATIONS_CHANNEL=null 22 | LOG_LEVEL=debug 23 | 24 | DB_CONNECTION=sqlite 25 | # DB_HOST=127.0.0.1 26 | # DB_PORT=3306 27 | # DB_DATABASE=laravel 28 | # DB_USERNAME=root 29 | # DB_PASSWORD= 30 | 31 | SESSION_DRIVER=database 32 | SESSION_LIFETIME=120 33 | SESSION_ENCRYPT=false 34 | SESSION_PATH=/ 35 | SESSION_DOMAIN=null 36 | 37 | BROADCAST_CONNECTION=log 38 | FILESYSTEM_DISK=local 39 | QUEUE_CONNECTION=database 40 | 41 | CACHE_STORE=database 42 | CACHE_PREFIX= 43 | 44 | MEMCACHED_HOST=127.0.0.1 45 | 46 | REDIS_CLIENT=phpredis 47 | REDIS_HOST=127.0.0.1 48 | REDIS_PASSWORD=null 49 | REDIS_PORT=6379 50 | 51 | MAIL_MAILER=log 52 | MAIL_HOST=127.0.0.1 53 | MAIL_PORT=2525 54 | MAIL_USERNAME=null 55 | MAIL_PASSWORD=null 56 | MAIL_ENCRYPTION=null 57 | MAIL_FROM_ADDRESS="hello@example.com" 58 | MAIL_FROM_NAME="${APP_NAME}" 59 | 60 | AWS_ACCESS_KEY_ID= 61 | AWS_SECRET_ACCESS_KEY= 62 | AWS_DEFAULT_REGION=us-east-1 63 | AWS_BUCKET= 64 | AWS_USE_PATH_STYLE_ENDPOINT=false 65 | 66 | VITE_APP_NAME="${APP_NAME}" 67 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | *.blade.php diff=html 4 | *.css diff=css 5 | *.html diff=html 6 | *.md diff=markdown 7 | *.php diff=php 8 | 9 | /.github export-ignore 10 | CHANGELOG.md export-ignore 11 | .styleci.yml export-ignore 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.phpunit.cache 2 | /node_modules 3 | /public/build 4 | /public/hot 5 | /public/storage 6 | /storage/*.key 7 | /storage/pail 8 | /vendor 9 | .env 10 | .env.backup 11 | .env.production 12 | .phpactor.json 13 | .phpunit.result.cache 14 | Homestead.json 15 | Homestead.yaml 16 | auth.json 17 | npm-debug.log 18 | yarn-error.log 19 | /.fleet 20 | /.idea 21 | /.vscode 22 | /.zed 23 | /database/database.sqlite 24 | /mariadb 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | -include .env.docker 2 | 3 | init: build \ 4 | up \ 5 | project-composer-install \ 6 | project-migrate 7 | 8 | docker-compose: 9 | docker-compose --project-name phpwork ${COMMAND} 10 | up: 11 | make docker-compose COMMAND="up -d" 12 | down: 13 | make docker-compose COMMAND="down --remove-orphans" 14 | docker-restart: 15 | make docker-compose COMMAND="down --remove-orphans" 16 | make docker-compose COMMAND="up -d" 17 | docker-pull: 18 | make docker-compose COMMAND="pull" 19 | build: 20 | make docker-compose COMMAND="build --pull" 21 | docker-exec: 22 | make docker-compose COMMAND="exec -it app ${COMMAND}" 23 | 24 | project-composer: 25 | make docker-exec COMMAND="composer ${name}" 26 | project-composer-install: 27 | make docker-exec COMMAND="composer install" 28 | project-composer-update: 29 | make docker-exec COMMAND="composer update" 30 | 31 | project-migrate: 32 | make docker-exec COMMAND="php artisan migrate" 33 | project-key-generate: 34 | make docker-exec COMMAND="php artisan key:generate" 35 | laravel: 36 | make docker-exec COMMAND="php -d memory_limit=-1 artisan ${name}" 37 | 38 | project-cs-check: 39 | make docker-exec COMMAND="./vendor/bin/php-cs-fixer fix -vvv --dry-run --show-progress=dots --config=./docker/config/.php-cs-fixer.php --allow-risky=yes" 40 | project-cs-fix: 41 | make docker-exec COMMAND="./vendor/bin/pint --config=./docker/config/pint.json" 42 | project-analyze: 43 | make docker-exec COMMAND="./vendor/bin/phpstan analyse --memory-limit=2G --configuration='docker/config/phpstan.neon.dist'" 44 | project-test: 45 | make docker-exec COMMAND="./vendor/bin/phpunit" 46 | 47 | check: project-analyze \ 48 | project-cs-check 49 | 50 | fix: project-cs-fix \ 51 | project-analyze 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # phpwork.uz 2 | 3 | **phpwork.uz** — PHP dasturlash tili bo'yicha ish o'rinlarini topish uchun platforma. Bu saytda PHP dasturchilari uchun turli vakansiyalar, ish joylari va freelans imkoniyatlari mavjud. Biz PHP bo'yicha tajribali va yangi boshlovchi dasturchilarni ishga joylashtirishga yordam beramiz. 4 | 5 | <<<<<<< HEAD 6 | ## Loyihaning maqsadi 7 | 8 | phpwork.uz — PHP dasturlash tili bo'yicha ish o'rinlarini topishga yordam beruvchi onlayn platformadir. Sayt foydalanuvchilari PHP dasturchilari uchun vakansiyalarni qidirish va ariza berish imkoniyatiga ega. Loyihaning maqsadi PHP dasturchilarini ish bilan ta'minlash va ish beruvchilarni malakali mutaxassislar bilan bog'lashdir. 9 | 10 | ## Xususiyatlar 11 | 12 | - **Vakansiyalar ro'yxati**: PHP dasturlash tili bo'yicha mavjud ish o'rinlari va freelancerlik imkoniyatlari. 13 | - **Qidiruv tizimi**: PHP vakansiyalarini sanoat, joylashuv va boshqa mezonlarga qarab izlash. 14 | - **Foydalanuvchi ro'yxatdan o'tishi**: Ish izlovchilar va ish beruvchilar uchun ro'yxatdan o'tish imkoniyati. 15 | - **Ariza yuborish**: PHP vakansiyalariga onlayn ariza yuborish. 16 | - **Profil yaratish**: Foydalanuvchilar uchun shaxsiy profil yaratish va ish izlovchilariga o'z malakalarini ko'rsatish imkoniyati. 17 | 18 | ## O'rnatish 19 | 20 | Ushbu loyiha GitHub'da open source sifatida mavjud va siz o'z kompyuteringizda ishlatishingiz yoki o'zgartirishingiz mumkin. 21 | 22 | 23 | ### O'rnatish qadamlar 24 | 25 | 1. **Loyihani klonlash**: 26 | GitHub reposini klonlash uchun quyidagi buyruqni bajarishingiz mumkin: 27 | 28 | ```bash 29 | git clone https://github.com/SukhrobNuraliev/phpwork.git 30 | ======= 31 | ## Loyiha haqida 32 | 33 | Bu loyiha orqali siz PHP ishlatadigan kompaniyalarni bir joyda topishingiz mumkin. Ularning: 34 | Saytlari 🌐 35 | Ish imkoniyatlari (hh.uz havolasi) 💼 36 | LinkedIn profillari va boshqa ma’lumotlari 🛠️ 37 | 👉 Nega bu loyiha ochiq manbali? 38 | Men vaqt yetishmasligi tufayli loyihani yakunlay olmayapman, shuning uchun uni ochiq manbali qilib, barchani hamkorlikka taklif qilmoqchiman. Bu loyiha birgalikda rivojlanadi va yanada kuchli bo‘ladi! 💪 39 | 40 | - GitHub: https://github.com/SukhrobNuraliev/ph... 41 | - Trello: https://trello.com/b/uGROFkgt/php-work 42 | - Website: https://phpwork.uz/ (https://phpwork.sukhrob.uz/) 43 | - Telegram Guruh: https://t.me/phpwork_uz_collab 44 | - Google Sheet: https://docs.google.com/spreadsheets/... 45 | 46 | 47 | ## Loyihani o'rnatish 48 | 49 | ### Docker orqali ishlash 50 | 51 | Bu uchun sizda docker va docker-compose o'rnatilgan bo'lishi lozim, va Docker desctop container lar bilan ishlash uchun 52 | 53 | - git clone git@github.com:SukhrobNuraliev/phpwork.git 54 | - cd phpwork 55 | - make init 56 | - cp .env.example .env 57 | - make project-key-generate 58 | - cp database/test-database.sqlite database.sqlite 59 | - make project-migrate 60 | 61 | phpstan va Laravel pint ni zapusk qilish uchun 62 | 63 | - make fix 64 | 65 | 66 | ### Local development 67 | 68 | - git clone git@github.com:SukhrobNuraliev/phpwork.git 69 | - cd phpwork 70 | - composer install 71 | - cp .env.example .env 72 | - php artisan key:generate 73 | - cp database/test-database.sqlite database.sqlite 74 | - php artisan migrate 75 | 76 | phpstan va Laravel pint ni zapusk qilish uchun 77 | - composer cs-fix 78 | - composer larastan 79 | >>>>>>> a97f15daf293c6625bc409749cf784fa9404cddb 80 | -------------------------------------------------------------------------------- /app/Http/Controllers/CategoryController.php: -------------------------------------------------------------------------------- 1 | 26 | */ 27 | public function rules(): array 28 | { 29 | return [ 30 | 'email' => ['required', 'string', 'email'], 31 | 'password' => ['required', 'string'], 32 | ]; 33 | } 34 | 35 | /** 36 | * Attempt to authenticate the request's credentials. 37 | * 38 | * @throws ValidationException 39 | */ 40 | public function authenticate(): void 41 | { 42 | $this->ensureIsNotRateLimited(); 43 | 44 | if (!Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) { 45 | RateLimiter::hit($this->throttleKey()); 46 | 47 | throw ValidationException::withMessages([ 48 | 'email' => trans('auth.failed'), 49 | ]); 50 | } 51 | 52 | RateLimiter::clear($this->throttleKey()); 53 | } 54 | 55 | /** 56 | * Ensure the login request is not rate limited. 57 | * 58 | * @throws ValidationException 59 | */ 60 | public function ensureIsNotRateLimited(): void 61 | { 62 | if (!RateLimiter::tooManyAttempts($this->throttleKey(), 5)) { 63 | return; 64 | } 65 | 66 | event(new Lockout($this)); 67 | 68 | $seconds = RateLimiter::availableIn($this->throttleKey()); 69 | 70 | throw ValidationException::withMessages([ 71 | 'email' => trans('auth.throttle', [ 72 | 'seconds' => $seconds, 73 | 'minutes' => ceil($seconds / 60), 74 | ]), 75 | ]); 76 | } 77 | 78 | /** 79 | * Get the rate limiting throttle key for the request. 80 | */ 81 | public function throttleKey(): string 82 | { 83 | return Str::transliterate(Str::lower($this->string('email')) . '|' . $this->ip()); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/Http/Requests/CompanyRequest.php: -------------------------------------------------------------------------------- 1 | 'required|string|max:255', 18 | 'logo' => 'nullable|file|mimes:jpg,png,jpeg|max:2048', 19 | 'category_id' => 'required|exists:categories,id', 20 | 'website_url' => 'nullable|url', 21 | 'hh_url' => 'nullable|url', 22 | 'linkedin_url' => 'nullable|url', 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Requests/ProfileUpdateRequest.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | public function rules(): array 17 | { 18 | return [ 19 | 'name' => ['required', 'string', 'max:255'], 20 | 'email' => [ 21 | 'required', 22 | 'string', 23 | 'lowercase', 24 | 'email', 25 | 'max:255', 26 | Rule::unique(User::class)->ignore($this->user()->id), 27 | ], 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Models/Category.php: -------------------------------------------------------------------------------- 1 | 'array', 15 | ]; 16 | 17 | public function companies(): HasMany 18 | { 19 | return $this->hasMany(Company::class); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Models/Company.php: -------------------------------------------------------------------------------- 1 | belongsTo(Category::class); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Models/User.php: -------------------------------------------------------------------------------- 1 | */ 14 | use HasFactory, Notifiable; 15 | 16 | protected $fillable = [ 17 | 'name', 18 | 'email', 19 | 'password', 20 | ]; 21 | 22 | protected $hidden = [ 23 | 'password', 24 | 'remember_token', 25 | ]; 26 | 27 | /** 28 | * Get the attributes that should be cast. 29 | * 30 | * @return array 31 | */ 32 | protected function casts(): array 33 | { 34 | return [ 35 | 'email_verified_at' => 'datetime', 36 | 'password' => 'hashed', 37 | ]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/MoonShine/Pages/Dashboard.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | public function breadcrumbs(): array 16 | { 17 | return [ 18 | '#' => $this->title(), 19 | ]; 20 | } 21 | 22 | public function title(): string 23 | { 24 | return $this->title ?: 'Dashboard'; 25 | } 26 | 27 | /** 28 | * @return list 29 | */ 30 | public function components(): array 31 | { 32 | return []; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/MoonShine/Resources/CompanyResource.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | class CompanyResource extends ModelResource 21 | { 22 | protected string $model = Company::class; 23 | protected string $title = 'Companies'; 24 | 25 | /** 26 | * @return list 27 | */ 28 | public function fields(): array 29 | { 30 | $locale = App::currentLocale(); 31 | 32 | return [ 33 | Text::make('Name', 'name') 34 | ->required(), 35 | 36 | Image::make('Logo', 'logo') 37 | ->required(), 38 | 39 | Select::make('category_id') 40 | ->options(Category::query() 41 | ->select(["translates->{$locale} as name", 'id']) 42 | ->pluck('name', 'id')->toArray()), 43 | Url::make('Website URL', 'website_url') 44 | ->nullable(), 45 | 46 | Url::make('HH URL', 'hh_url') 47 | ->nullable(), 48 | 49 | Url::make('LinkedIn URL', 'linkedin_url') 50 | ->nullable(), 51 | 52 | Select::make('Status', 'status') 53 | ->options([ 54 | 'active' => 'Active', 55 | 'inactive' => 'Inactive', 56 | ]), 57 | ]; 58 | } 59 | 60 | public function query(): \Illuminate\Contracts\Database\Eloquent\Builder 61 | { 62 | return parent::query() 63 | ->where('status', 'active'); 64 | } 65 | 66 | /** 67 | * @return array 68 | * 69 | * @see https://laravel.com/docs/validation#available-validation-rules 70 | */ 71 | public function rules(Model $item): array 72 | { 73 | return []; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/MoonShine/Resources/InactiveCompanyResource.php: -------------------------------------------------------------------------------- 1 | 21 | */ 22 | class InactiveCompanyResource extends ModelResource 23 | { 24 | protected string $model = Company::class; 25 | 26 | protected string $title = 'Inactive Companies'; 27 | 28 | /** 29 | * @return list 30 | */ 31 | public function fields(): array 32 | { 33 | $locale = App::currentLocale(); 34 | 35 | return [ 36 | Text::make('Name', 'name') 37 | ->required(), 38 | 39 | Image::make('Logo', 'logo')->readonly(), 40 | 41 | Select::make('category_id') 42 | ->options(Category::query() 43 | ->select(["translates->{$locale} as name", 'id']) 44 | ->pluck('name', 'id')->toArray()), 45 | Url::make('Website URL', 'website_url') 46 | ->nullable(), 47 | 48 | Url::make('HH URL', 'hh_url') 49 | ->nullable(), 50 | 51 | Url::make('LinkedIn URL', 'linkedin_url') 52 | ->nullable(), 53 | 54 | Select::make('Status', 'status') 55 | ->options([ 56 | 'active' => 'Active', 57 | 'inactive' => 'Inactive', 58 | ]), 59 | ]; 60 | } 61 | 62 | /** 63 | * Override the query method to filter by inactive status. 64 | */ 65 | public function query(): \Illuminate\Contracts\Database\Eloquent\Builder 66 | { 67 | return parent::query() 68 | ->where('status', 'inactive'); 69 | } 70 | 71 | /** 72 | * Disable the creation of new records. 73 | */ 74 | public function canCreate(): bool 75 | { 76 | return false; // Disable the create option 77 | } 78 | 79 | /** 80 | * Disable the ability to add new records. 81 | */ 82 | public function canStore(): bool 83 | { 84 | return false; // Disable storing new records 85 | } 86 | 87 | /** 88 | * @param Company $item 89 | * @return array 90 | * 91 | * @see https://laravel.com/docs/validation#available-validation-rules 92 | */ 93 | public function rules(Model $item): array 94 | { 95 | return []; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | 21 | */ 22 | protected function resources(): array 23 | { 24 | return [ 25 | new CompanyResource, 26 | new InactiveCompanyResource, 27 | ]; 28 | } 29 | 30 | /** 31 | * @return list 32 | */ 33 | protected function pages(): array 34 | { 35 | return [ 36 | 37 | ]; 38 | } 39 | 40 | protected function menu(): array 41 | { 42 | return [ 43 | MenuGroup::make(static fn () => __('moonshine::ui.resource.system'), [ 44 | MenuItem::make( 45 | static fn () => __('moonshine::ui.resource.admins_title'), 46 | new MoonShineUserResource 47 | ), 48 | MenuItem::make( 49 | static fn () => __('moonshine::ui.resource.role_title'), 50 | new MoonShineUserRoleResource 51 | ), 52 | ]), 53 | 54 | MenuItem::make( 55 | static fn () => __('Companies'), 56 | new CompanyResource 57 | )->icon('heroicons.academic-cap'), 58 | 59 | MenuItem::make( 60 | static fn () => __('Inactive Company'), 61 | new InactiveCompanyResource 62 | )->icon('heroicons.check-circle'), 63 | ]; 64 | } 65 | 66 | protected function theme(): array 67 | { 68 | return []; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/View/Components/AppLayout.php: -------------------------------------------------------------------------------- 1 | handleCommand(new ArgvInput); 14 | 15 | exit($status); 16 | -------------------------------------------------------------------------------- /bootstrap/app.php: -------------------------------------------------------------------------------- 1 | withRouting( 9 | web: __DIR__ . '/../routes/web.php', 10 | health: '/up', 11 | ) 12 | ->withMiddleware(function (Middleware $middleware) { 13 | // 14 | }) 15 | ->withExceptions(function (Exceptions $exceptions) { 16 | // 17 | })->create(); 18 | -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /bootstrap/providers.php: -------------------------------------------------------------------------------- 1 | env('CACHE_STORE', 'database'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Cache Stores 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the cache "stores" for your application as 26 | | well as their drivers. You may even define multiple stores for the 27 | | same cache driver to group types of items stored in your caches. 28 | | 29 | | Supported drivers: "array", "database", "file", "memcached", 30 | | "redis", "dynamodb", "octane", "null" 31 | | 32 | */ 33 | 34 | 'stores' => [ 35 | 36 | 'array' => [ 37 | 'driver' => 'array', 38 | 'serialize' => false, 39 | ], 40 | 41 | 'database' => [ 42 | 'driver' => 'database', 43 | 'connection' => env('DB_CACHE_CONNECTION'), 44 | 'table' => env('DB_CACHE_TABLE', 'cache'), 45 | 'lock_connection' => env('DB_CACHE_LOCK_CONNECTION'), 46 | 'lock_table' => env('DB_CACHE_LOCK_TABLE'), 47 | ], 48 | 49 | 'file' => [ 50 | 'driver' => 'file', 51 | 'path' => storage_path('framework/cache/data'), 52 | 'lock_path' => storage_path('framework/cache/data'), 53 | ], 54 | 55 | 'memcached' => [ 56 | 'driver' => 'memcached', 57 | 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 58 | 'sasl' => [ 59 | env('MEMCACHED_USERNAME'), 60 | env('MEMCACHED_PASSWORD'), 61 | ], 62 | 'options' => [ 63 | // Memcached::OPT_CONNECT_TIMEOUT => 2000, 64 | ], 65 | 'servers' => [ 66 | [ 67 | 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 68 | 'port' => env('MEMCACHED_PORT', 11211), 69 | 'weight' => 100, 70 | ], 71 | ], 72 | ], 73 | 74 | 'redis' => [ 75 | 'driver' => 'redis', 76 | 'connection' => env('REDIS_CACHE_CONNECTION', 'cache'), 77 | 'lock_connection' => env('REDIS_CACHE_LOCK_CONNECTION', 'default'), 78 | ], 79 | 80 | 'dynamodb' => [ 81 | 'driver' => 'dynamodb', 82 | 'key' => env('AWS_ACCESS_KEY_ID'), 83 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 84 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 85 | 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), 86 | 'endpoint' => env('DYNAMODB_ENDPOINT'), 87 | ], 88 | 89 | 'octane' => [ 90 | 'driver' => 'octane', 91 | ], 92 | 93 | ], 94 | 95 | /* 96 | |-------------------------------------------------------------------------- 97 | | Cache Key Prefix 98 | |-------------------------------------------------------------------------- 99 | | 100 | | When utilizing the APC, database, memcached, Redis, and DynamoDB cache 101 | | stores, there might be other applications using the same cache. For 102 | | that reason, you may prefix every cache key to avoid collisions. 103 | | 104 | */ 105 | 106 | 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_cache_'), 107 | 108 | ]; 109 | -------------------------------------------------------------------------------- /config/filesystems.php: -------------------------------------------------------------------------------- 1 | env('FILESYSTEM_DISK', 'local'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Filesystem Disks 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Below you may configure as many filesystem disks as necessary, and you 24 | | may even configure multiple disks for the same driver. Examples for 25 | | most supported storage drivers are configured here for reference. 26 | | 27 | | Supported drivers: "local", "ftp", "sftp", "s3" 28 | | 29 | */ 30 | 31 | 'disks' => [ 32 | 33 | 'local' => [ 34 | 'driver' => 'local', 35 | 'root' => storage_path('app/private'), 36 | 'serve' => true, 37 | 'throw' => false, 38 | ], 39 | 40 | 'public' => [ 41 | 'driver' => 'local', 42 | 'root' => storage_path('app/public'), 43 | 'url' => env('APP_URL') . '/storage', 44 | 'visibility' => 'public', 45 | 'throw' => false, 46 | ], 47 | 48 | 's3' => [ 49 | 'driver' => 's3', 50 | 'key' => env('AWS_ACCESS_KEY_ID'), 51 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 52 | 'region' => env('AWS_DEFAULT_REGION'), 53 | 'bucket' => env('AWS_BUCKET'), 54 | 'url' => env('AWS_URL'), 55 | 'endpoint' => env('AWS_ENDPOINT'), 56 | 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), 57 | 'throw' => false, 58 | ], 59 | 60 | ], 61 | 62 | /* 63 | |-------------------------------------------------------------------------- 64 | | Symbolic Links 65 | |-------------------------------------------------------------------------- 66 | | 67 | | Here you may configure the symbolic links that will be created when the 68 | | `storage:link` Artisan command is executed. The array keys should be 69 | | the locations of the links and the values should be their targets. 70 | | 71 | */ 72 | 73 | 'links' => [ 74 | public_path('storage') => storage_path('app/public'), 75 | ], 76 | 77 | ]; 78 | -------------------------------------------------------------------------------- /config/mail.php: -------------------------------------------------------------------------------- 1 | env('MAIL_MAILER', 'log'), 18 | 19 | /* 20 | |-------------------------------------------------------------------------- 21 | | Mailer Configurations 22 | |-------------------------------------------------------------------------- 23 | | 24 | | Here you may configure all of the mailers used by your application plus 25 | | their respective settings. Several examples have been configured for 26 | | you and you are free to add your own as your application requires. 27 | | 28 | | Laravel supports a variety of mail "transport" drivers that can be used 29 | | when delivering an email. You may specify which one you're using for 30 | | your mailers below. You may also add additional mailers if needed. 31 | | 32 | | Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2", 33 | | "postmark", "resend", "log", "array", 34 | | "failover", "roundrobin" 35 | | 36 | */ 37 | 38 | 'mailers' => [ 39 | 40 | 'smtp' => [ 41 | 'transport' => 'smtp', 42 | 'url' => env('MAIL_URL'), 43 | 'host' => env('MAIL_HOST', '127.0.0.1'), 44 | 'port' => env('MAIL_PORT', 2525), 45 | 'encryption' => env('MAIL_ENCRYPTION', 'tls'), 46 | 'username' => env('MAIL_USERNAME'), 47 | 'password' => env('MAIL_PASSWORD'), 48 | 'timeout' => null, 49 | 'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url(env('APP_URL', 'http://localhost'), PHP_URL_HOST)), 50 | ], 51 | 52 | 'ses' => [ 53 | 'transport' => 'ses', 54 | ], 55 | 56 | 'postmark' => [ 57 | 'transport' => 'postmark', 58 | // 'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'), 59 | // 'client' => [ 60 | // 'timeout' => 5, 61 | // ], 62 | ], 63 | 64 | 'resend' => [ 65 | 'transport' => 'resend', 66 | ], 67 | 68 | 'sendmail' => [ 69 | 'transport' => 'sendmail', 70 | 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'), 71 | ], 72 | 73 | 'log' => [ 74 | 'transport' => 'log', 75 | 'channel' => env('MAIL_LOG_CHANNEL'), 76 | ], 77 | 78 | 'array' => [ 79 | 'transport' => 'array', 80 | ], 81 | 82 | 'failover' => [ 83 | 'transport' => 'failover', 84 | 'mailers' => [ 85 | 'smtp', 86 | 'log', 87 | ], 88 | ], 89 | 90 | 'roundrobin' => [ 91 | 'transport' => 'roundrobin', 92 | 'mailers' => [ 93 | 'ses', 94 | 'postmark', 95 | ], 96 | ], 97 | 98 | ], 99 | 100 | /* 101 | |-------------------------------------------------------------------------- 102 | | Global "From" Address 103 | |-------------------------------------------------------------------------- 104 | | 105 | | You may wish for all emails sent by your application to be sent from 106 | | the same address. Here you may specify a name and address that is 107 | | used globally for all emails that are sent by your application. 108 | | 109 | */ 110 | 111 | 'from' => [ 112 | 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), 113 | 'name' => env('MAIL_FROM_NAME', 'Example'), 114 | ], 115 | 116 | ]; 117 | -------------------------------------------------------------------------------- /config/moonshine.php: -------------------------------------------------------------------------------- 1 | 'app/MoonShine', 13 | 'namespace' => 'App\MoonShine', 14 | 15 | 'title' => env('MOONSHINE_TITLE', 'MoonShine'), 16 | 'logo' => env('MOONSHINE_LOGO'), 17 | 'logo_small' => env('MOONSHINE_LOGO_SMALL'), 18 | 19 | 'route' => [ 20 | 'domain' => env('MOONSHINE_URL', ''), 21 | 'prefix' => env('MOONSHINE_ROUTE_PREFIX', 'admin'), 22 | 'single_page_prefix' => 'page', 23 | 'index' => 'moonshine.index', 24 | 'middlewares' => [ 25 | SecurityHeadersMiddleware::class, 26 | ], 27 | 'notFoundHandler' => MoonShineNotFoundException::class, 28 | ], 29 | 30 | 'use_migrations' => true, 31 | 'use_notifications' => true, 32 | 'use_theme_switcher' => true, 33 | 34 | 'layout' => MoonShineLayout::class, 35 | 36 | 'disk' => 'public', 37 | 38 | 'disk_options' => [], 39 | 40 | 'cache' => 'file', 41 | 42 | 'assets' => [ 43 | 'js' => [ 44 | 'script_attributes' => [ 45 | 'defer', 46 | ], 47 | ], 48 | 'css' => [ 49 | 'link_attributes' => [ 50 | 'rel' => 'stylesheet', 51 | ], 52 | ], 53 | ], 54 | 55 | 'forms' => [ 56 | 'login' => LoginForm::class, 57 | ], 58 | 59 | 'pages' => [ 60 | 'dashboard' => App\MoonShine\Pages\Dashboard::class, 61 | 'profile' => ProfilePage::class, 62 | ], 63 | 64 | 'model_resources' => [ 65 | 'default_with_import' => true, 66 | 'default_with_export' => true, 67 | ], 68 | 69 | 'auth' => [ 70 | 'enable' => true, 71 | 'middleware' => Authenticate::class, 72 | 'fields' => [ 73 | 'username' => 'email', 74 | 'password' => 'password', 75 | 'name' => 'name', 76 | 'avatar' => 'avatar', 77 | ], 78 | 'guard' => 'moonshine', 79 | 'guards' => [ 80 | 'moonshine' => [ 81 | 'driver' => 'session', 82 | 'provider' => 'moonshine', 83 | ], 84 | ], 85 | 'providers' => [ 86 | 'moonshine' => [ 87 | 'driver' => 'eloquent', 88 | 'model' => MoonshineUser::class, 89 | ], 90 | ], 91 | 'pipelines' => [], 92 | ], 93 | 'locales' => [ 94 | 'en', 95 | 'ru', 96 | ], 97 | 98 | 'global_search' => [ 99 | // User::class 100 | ], 101 | 102 | 'tinymce' => [ 103 | 'file_manager' => false, // or 'laravel-filemanager' prefix for lfm 104 | 'token' => env('MOONSHINE_TINYMCE_TOKEN', ''), 105 | 'version' => env('MOONSHINE_TINYMCE_VERSION', '6'), 106 | ], 107 | 108 | 'socialite' => [ 109 | // 'driver' => 'path_to_image_for_button' 110 | ], 111 | ]; 112 | -------------------------------------------------------------------------------- /config/queue.php: -------------------------------------------------------------------------------- 1 | env('QUEUE_CONNECTION', 'database'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Queue Connections 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure the connection options for every queue backend 24 | | used by your application. An example configuration is provided for 25 | | each backend supported by Laravel. You're also free to add more. 26 | | 27 | | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'sync' => [ 34 | 'driver' => 'sync', 35 | ], 36 | 37 | 'database' => [ 38 | 'driver' => 'database', 39 | 'connection' => env('DB_QUEUE_CONNECTION'), 40 | 'table' => env('DB_QUEUE_TABLE', 'jobs'), 41 | 'queue' => env('DB_QUEUE', 'default'), 42 | 'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90), 43 | 'after_commit' => false, 44 | ], 45 | 46 | 'beanstalkd' => [ 47 | 'driver' => 'beanstalkd', 48 | 'host' => env('BEANSTALKD_QUEUE_HOST', 'localhost'), 49 | 'queue' => env('BEANSTALKD_QUEUE', 'default'), 50 | 'retry_after' => (int) env('BEANSTALKD_QUEUE_RETRY_AFTER', 90), 51 | 'block_for' => 0, 52 | 'after_commit' => false, 53 | ], 54 | 55 | 'sqs' => [ 56 | 'driver' => 'sqs', 57 | 'key' => env('AWS_ACCESS_KEY_ID'), 58 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 59 | 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), 60 | 'queue' => env('SQS_QUEUE', 'default'), 61 | 'suffix' => env('SQS_SUFFIX'), 62 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 63 | 'after_commit' => false, 64 | ], 65 | 66 | 'redis' => [ 67 | 'driver' => 'redis', 68 | 'connection' => env('REDIS_QUEUE_CONNECTION', 'default'), 69 | 'queue' => env('REDIS_QUEUE', 'default'), 70 | 'retry_after' => (int) env('REDIS_QUEUE_RETRY_AFTER', 90), 71 | 'block_for' => null, 72 | 'after_commit' => false, 73 | ], 74 | 75 | ], 76 | 77 | /* 78 | |-------------------------------------------------------------------------- 79 | | Job Batching 80 | |-------------------------------------------------------------------------- 81 | | 82 | | The following options configure the database and table that store job 83 | | batching information. These options can be updated to any database 84 | | connection and table which has been defined by your application. 85 | | 86 | */ 87 | 88 | 'batching' => [ 89 | 'database' => env('DB_CONNECTION', 'sqlite'), 90 | 'table' => 'job_batches', 91 | ], 92 | 93 | /* 94 | |-------------------------------------------------------------------------- 95 | | Failed Queue Jobs 96 | |-------------------------------------------------------------------------- 97 | | 98 | | These options configure the behavior of failed queue job logging so you 99 | | can control how and where failed jobs are stored. Laravel ships with 100 | | support for storing failed jobs in a simple file or in a database. 101 | | 102 | | Supported drivers: "database-uuids", "dynamodb", "file", "null" 103 | | 104 | */ 105 | 106 | 'failed' => [ 107 | 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'), 108 | 'database' => env('DB_CONNECTION', 'sqlite'), 109 | 'table' => 'failed_jobs', 110 | ], 111 | 112 | ]; 113 | -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'token' => env('POSTMARK_TOKEN'), 19 | ], 20 | 21 | 'ses' => [ 22 | 'key' => env('AWS_ACCESS_KEY_ID'), 23 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 24 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 25 | ], 26 | 27 | 'resend' => [ 28 | 'key' => env('RESEND_KEY'), 29 | ], 30 | 31 | 'slack' => [ 32 | 'notifications' => [ 33 | 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'), 34 | 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'), 35 | ], 36 | ], 37 | 38 | ]; 39 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite* 2 | -------------------------------------------------------------------------------- /database/factories/UserFactory.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class UserFactory extends Factory 13 | { 14 | /** 15 | * The current password being used by the factory. 16 | */ 17 | protected static ?string $password; 18 | 19 | /** 20 | * Define the model's default state. 21 | * 22 | * @return array 23 | */ 24 | public function definition(): array 25 | { 26 | return [ 27 | 'name' => fake()->name(), 28 | 'email' => fake()->unique()->safeEmail(), 29 | 'email_verified_at' => now(), 30 | 'password' => static::$password ??= Hash::make('password'), 31 | 'remember_token' => Str::random(10), 32 | ]; 33 | } 34 | 35 | /** 36 | * Indicate that the model's email address should be unverified. 37 | */ 38 | public function unverified(): static 39 | { 40 | return $this->state(fn (array $attributes) => [ 41 | 'email_verified_at' => null, 42 | ]); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /database/migrations/0001_01_01_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('name'); 17 | $table->string('email')->unique(); 18 | $table->timestamp('email_verified_at')->nullable(); 19 | $table->string('password'); 20 | $table->rememberToken(); 21 | $table->timestamps(); 22 | }); 23 | 24 | Schema::create('password_reset_tokens', function (Blueprint $table) { 25 | $table->string('email')->primary(); 26 | $table->string('token'); 27 | $table->timestamp('created_at')->nullable(); 28 | }); 29 | 30 | Schema::create('sessions', function (Blueprint $table) { 31 | $table->string('id')->primary(); 32 | $table->foreignId('user_id')->nullable()->index(); 33 | $table->string('ip_address', 45)->nullable(); 34 | $table->text('user_agent')->nullable(); 35 | $table->longText('payload'); 36 | $table->integer('last_activity')->index(); 37 | }); 38 | } 39 | 40 | /** 41 | * Reverse the migrations. 42 | */ 43 | public function down(): void 44 | { 45 | Schema::dropIfExists('users'); 46 | Schema::dropIfExists('password_reset_tokens'); 47 | Schema::dropIfExists('sessions'); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /database/migrations/0001_01_01_000001_create_cache_table.php: -------------------------------------------------------------------------------- 1 | string('key')->primary(); 16 | $table->mediumText('value'); 17 | $table->integer('expiration'); 18 | }); 19 | 20 | Schema::create('cache_locks', function (Blueprint $table) { 21 | $table->string('key')->primary(); 22 | $table->string('owner'); 23 | $table->integer('expiration'); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | */ 30 | public function down(): void 31 | { 32 | Schema::dropIfExists('cache'); 33 | Schema::dropIfExists('cache_locks'); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /database/migrations/0001_01_01_000002_create_jobs_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('queue')->index(); 17 | $table->longText('payload'); 18 | $table->unsignedTinyInteger('attempts'); 19 | $table->unsignedInteger('reserved_at')->nullable(); 20 | $table->unsignedInteger('available_at'); 21 | $table->unsignedInteger('created_at'); 22 | }); 23 | 24 | Schema::create('job_batches', function (Blueprint $table) { 25 | $table->string('id')->primary(); 26 | $table->string('name'); 27 | $table->integer('total_jobs'); 28 | $table->integer('pending_jobs'); 29 | $table->integer('failed_jobs'); 30 | $table->longText('failed_job_ids'); 31 | $table->mediumText('options')->nullable(); 32 | $table->integer('cancelled_at')->nullable(); 33 | $table->integer('created_at'); 34 | $table->integer('finished_at')->nullable(); 35 | }); 36 | 37 | Schema::create('failed_jobs', function (Blueprint $table) { 38 | $table->id(); 39 | $table->string('uuid')->unique(); 40 | $table->text('connection'); 41 | $table->text('queue'); 42 | $table->longText('payload'); 43 | $table->longText('exception'); 44 | $table->timestamp('failed_at')->useCurrent(); 45 | }); 46 | } 47 | 48 | /** 49 | * Reverse the migrations. 50 | */ 51 | public function down(): void 52 | { 53 | Schema::dropIfExists('jobs'); 54 | Schema::dropIfExists('job_batches'); 55 | Schema::dropIfExists('failed_jobs'); 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /database/migrations/2024_10_29_112923_create_companies_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('name'); 17 | $table->text('logo'); 18 | $table->foreignId('category_id'); 19 | $table->string('website_url')->nullable(); 20 | $table->string('hh_url')->nullable(); 21 | $table->string('linkedin_url')->nullable(); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | */ 29 | public function down(): void 30 | { 31 | Schema::dropIfExists('companies'); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /database/migrations/2024_11_04_113429_create_categories_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('type'); 17 | $table->json('translates')->nullable(); 18 | $table->timestamps(); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | */ 25 | public function down() 26 | { 27 | Schema::dropIfExists('categories'); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /database/migrations/2024_11_26_062942_add_status_to_companies_table.php: -------------------------------------------------------------------------------- 1 | enum('status', ['active', 'inactive'])->default('inactive'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('companies', function (Blueprint $table) { 25 | $table->dropColumn('status'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/seeders/CategorySeeder.php: -------------------------------------------------------------------------------- 1 | [ 17 | 'uz' => 'Veb-studiya va agentliklar', 18 | 'ru' => 'Веб-студии и агентства', 19 | ], 20 | 'e_commerce' => [ 21 | 'uz' => 'E-commerce kompaniyalar', 22 | 'ru' => 'E-commerce компании', 23 | ], 24 | 'it_outsourcing' => [ 25 | 'uz' => 'IT autsorsing kompaniyalari', 26 | 'ru' => 'IT аутсорсинговые компании', 27 | ], 28 | 'startups' => [ 29 | 'uz' => 'Startaplar', 30 | 'ru' => 'Стартапы', 31 | ], 32 | 'media_portals' => [ 33 | 'uz' => 'Yangiliklar va media portallar', 34 | 'ru' => 'Новостные и медийные порталы', 35 | ], 36 | 'social_networks' => [ 37 | 'uz' => 'Ijtimoiy tarmoqlar va platformalar', 38 | 'ru' => 'Социальные сети и платформы', 39 | ], 40 | 'corporate_sites' => [ 41 | 'uz' => 'Korporativ saytlar', 42 | 'ru' => 'Корпоративные сайты', 43 | ], 44 | 'educational_platforms' => [ 45 | 'uz' => 'Ta\'lim platformalari', 46 | 'ru' => 'Образовательные платформы', 47 | ], 48 | 'bank' => [ 49 | 'uz' => 'Bank', 50 | 'ru' => 'Банк', 51 | ], 52 | 'fin_tex' => [ 53 | 'uz' => 'Fin Tex', 54 | 'ru' => 'Фин Тех', 55 | ], 56 | ]; 57 | $insertCompanies = []; 58 | foreach ($companies as $type => $translate) { 59 | $category = new Category; 60 | $category->type = $type; 61 | $category->translates = json_encode($translate); 62 | $category->getQualifiedCreatedAtColumn(); 63 | $category->getQualifiedUpdatedAtColumn(); 64 | $insertCompanies[] = $category->toArray(); 65 | } 66 | Category::query()->insert($insertCompanies); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /database/seeders/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | create([ 17 | 'name' => 'Test User', 18 | 'email' => 'test@example.com', 19 | ]); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | app: 3 | build: 4 | args: 5 | user: sammy 6 | uid: 1000 7 | context: ./ 8 | dockerfile: ./docker/development/php/Dockerfile 9 | image: phpwork_app 10 | container_name: phpwork_core_app 11 | restart: unless-stopped 12 | working_dir: /var/www/ 13 | volumes: 14 | - ./:/var/www 15 | networks: 16 | - phpwork_core 17 | 18 | mariadb: 19 | image: mariadb:10.6.5 20 | container_name: mariadb-phpwork-backend 21 | ports: 22 | - "3306:3306" 23 | environment: 24 | MYSQL_ROOT_PASSWORD: 123 25 | volumes: 26 | - ./mariadb:/var/lib/mysql 27 | networks: 28 | - phpwork_core 29 | 30 | nginx: 31 | image: nginx:alpine 32 | container_name: phpwork_nginx 33 | restart: unless-stopped 34 | ports: 35 | - 9080:80 36 | volumes: 37 | - ./:/var/www 38 | - ./docker/development/nginx/conf.d:/etc/nginx/conf.d/ 39 | networks: 40 | - phpwork_core 41 | 42 | redis: 43 | image: redis:latest 44 | container_name: phpwork_redis 45 | command: redis-server 46 | volumes: 47 | - ./docker/my-redis:/var/lib/redis 48 | ports: 49 | - 6379:6379 50 | networks: 51 | - phpwork_core 52 | 53 | networks: 54 | phpwork_core: 55 | driver: bridge 56 | -------------------------------------------------------------------------------- /docker/config/phpstan.neon.dist: -------------------------------------------------------------------------------- 1 | includes: 2 | - /var/www/vendor/larastan/larastan/extension.neon 3 | - /var/www/vendor/nesbot/carbon/extension.neon 4 | 5 | parameters: 6 | 7 | paths: 8 | - /var/www/app 9 | 10 | # Level 10 is the highest level 11 | level: 5 12 | 13 | # ignoreErrors: 14 | # - '#PHPDoc tag @var#' 15 | # 16 | # excludePaths: 17 | # - ./*/*/FileToBeExcluded.php 18 | -------------------------------------------------------------------------------- /docker/config/pint.json: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "laravel", 3 | "rules": { 4 | "@PSR12:risky": true, 5 | "ordered_imports": { 6 | "sort_algorithm": "length", 7 | "imports_order": [ 8 | "const", 9 | "function", 10 | "class" 11 | ] 12 | }, 13 | "declare_strict_types": false, 14 | "no_unused_imports": true, 15 | "whitespace_after_comma_in_array": true, 16 | "cast_spaces": true, 17 | "include": true, 18 | "single_quote": false, 19 | "space_after_semicolon": true, 20 | "standardize_not_equals": true, 21 | "trailing_comma_in_multiline": true, 22 | "trim_array_spaces": true, 23 | "unary_operator_spaces": true, 24 | "psr_autoloading": true, 25 | "array_syntax": { 26 | "syntax": "short" 27 | }, 28 | "concat_space": { 29 | "spacing": "one" 30 | }, 31 | "native_function_casing": true, 32 | "no_spaces_around_offset": true, 33 | "single_line_comment_style": { 34 | "comment_types": [ 35 | "hash" 36 | ] 37 | }, 38 | "self_accessor": true, 39 | "magic_method_casing": true, 40 | "magic_constant_casing": true, 41 | "no_singleline_whitespace_before_semicolons": true, 42 | "no_useless_return": true, 43 | "no_whitespace_before_comma_in_array": true, 44 | "normalize_index_brace": true, 45 | "not_operator_with_successor_space": false, 46 | "object_operator_without_whitespace": true, 47 | "no_short_bool_cast": true, 48 | "no_empty_statement": true, 49 | "no_leading_namespace_whitespace": true, 50 | "binary_operator_spaces": { 51 | "default": "single_space", 52 | "operators": { 53 | "=>": null 54 | } 55 | }, 56 | "blank_line_before_statement": { 57 | "statements": [ 58 | "return" 59 | ] 60 | }, 61 | "no_unneeded_control_parentheses": true, 62 | "class_attributes_separation": { 63 | "elements": { 64 | "method": "one" 65 | } 66 | }, 67 | "fully_qualified_strict_types": true, 68 | "function_typehint_space": true, 69 | "increment_style": { 70 | "style": "post" 71 | }, 72 | "linebreak_after_opening_tag": true, 73 | "no_extra_blank_lines": { 74 | "tokens": [ 75 | "extra", 76 | "throw", 77 | "use" 78 | ] 79 | }, 80 | "no_multiline_whitespace_around_double_arrow": true, 81 | "multiline_whitespace_before_semicolons": { 82 | "strategy": "no_multi_line" 83 | }, 84 | "no_blank_lines_after_phpdoc": true, 85 | "no_empty_phpdoc": true, 86 | "phpdoc_indent": true, 87 | "general_phpdoc_tag_rename": true, 88 | "phpdoc_inline_tag_normalizer": true, 89 | "phpdoc_tag_type": true, 90 | "phpdoc_no_access": true, 91 | "phpdoc_no_package": true, 92 | "phpdoc_no_useless_inheritdoc": true, 93 | "phpdoc_scalar": true, 94 | "phpdoc_single_line_var_spacing": true, 95 | "phpdoc_summary": true, 96 | "phpdoc_trim": true, 97 | "phpdoc_types": true, 98 | "phpdoc_var_without_name": true 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /docker/development/nginx/conf.d/phpwork.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name phpwork.uz; 4 | root /var/www/public; 5 | index index.php; 6 | location ~ \.php$ { 7 | try_files $uri =404; 8 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 9 | fastcgi_pass phpwork_core_app:9000; 10 | fastcgi_index index.php; 11 | include fastcgi_params; 12 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 13 | fastcgi_param PATH_INFO $fastcgi_path_info; 14 | } 15 | location / { 16 | try_files $uri $uri/ /index.php?$query_string; 17 | gzip_static on; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docker/development/php/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the official PHP 8.1 FPM image as the base image 2 | FROM php:8.2-fpm 3 | 4 | # Arguments defined in docker-compose.yml 5 | ARG user 6 | ARG uid 7 | 8 | 9 | # Install required dependencies 10 | RUN apt-get update && apt-get install -y \ 11 | libpq-dev \ 12 | libsqlite3-dev \ 13 | libzip-dev \ 14 | libxslt-dev \ 15 | libxml2-dev \ 16 | libicu-dev \ 17 | libpng-dev \ 18 | libjpeg62-turbo-dev \ 19 | libfreetype6-dev \ 20 | && docker-php-ext-install zip \ 21 | && docker-php-ext-install xsl \ 22 | && docker-php-ext-install intl \ 23 | && docker-php-ext-install pcntl \ 24 | && docker-php-ext-configure gd \ 25 | --with-freetype \ 26 | --with-jpeg \ 27 | && docker-php-ext-install gd \ 28 | && docker-php-ext-install pdo_sqlite 29 | 30 | 31 | # Install Node.js (v18.x as an example) and npm 32 | RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \ 33 | apt-get install -y nodejs 34 | 35 | # Set the working directory 36 | WORKDIR /var/www/ 37 | 38 | # Copy your application files into the container 39 | COPY . /var/www/ 40 | 41 | # Expose port if necessary (PHP FPM listens on port 9000 by default) 42 | # EXPOSE 9000 43 | # Get latest Composer 44 | COPY --from=composer:latest /usr/bin/composer /usr/bin/composer 45 | 46 | # Create system user to run Composer and Artisan Commands 47 | RUN useradd -G www-data,root -u $uid -d /home/$user $user 48 | RUN mkdir -p /home/$user/.composer && \ 49 | chown -R $user:$user /home/$user 50 | 51 | # Set working directory 52 | WORKDIR /var/www 53 | 54 | USER $user 55 | 56 | 57 | ## Start PHP FPM 58 | #CMD ["php-fpm"] 59 | -------------------------------------------------------------------------------- /docker/development/php/php.ini: -------------------------------------------------------------------------------- 1 | [PHP] 2 | 3 | file_uploads = On 4 | memory_limit = 64M 5 | upload_max_filesize = 64M 6 | post_max_size = 64M 7 | max_execution_time = 600 8 | -------------------------------------------------------------------------------- /docker/development/php/xdebug.ini: -------------------------------------------------------------------------------- 1 | ;zend_extension = xdebug 2 | 3 | [xdebug] 4 | # coverage,profile,trace,gcstats,trace,profile 5 | xdebug.mode = develop,debug 6 | xdebug.trace_format = 3 7 | xdebug.client_host = host.docker.internal 8 | xdebug.client_port = 9008 9 | xdebug.start_with_request = yes 10 | xdebug.output_dir = /app/storage/xdebug 11 | xdebug.trace_output_name = trace.%c 12 | xdebug.profiler_output_name = cachegrind.out.%p 13 | ;xdebug.collect_return = 1 14 | ;xdebug.collect_assignments = 1 15 | xdebug.log_level = 0 16 | xdebug.idekey = PHPSTORM 17 | -------------------------------------------------------------------------------- /identifier.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/identifier.sqlite -------------------------------------------------------------------------------- /lang/vendor/moonshine/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'password' => 'The provided password is incorrect.', 18 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 19 | 20 | 'socialite' => [ 21 | 'link_exists' => 'Account already exists', 22 | 'link_success' => 'Account linked', 23 | ] 24 | ]; 25 | -------------------------------------------------------------------------------- /lang/vendor/moonshine/en/pagination.php: -------------------------------------------------------------------------------- 1 | 'Showing', 17 | 'of' => 'of', 18 | 'to' => 'to', 19 | 'results' => 'results', 20 | 'previous' => '« Previous', 21 | 'next' => 'Next »', 22 | 23 | ]; 24 | -------------------------------------------------------------------------------- /lang/vendor/moonshine/en/ui.php: -------------------------------------------------------------------------------- 1 | 'Profile', 5 | 'dashboard' => 'Dashboard', 6 | 'add' => 'Add', 7 | 'create' => 'Create', 8 | 'edit' => 'Edit', 9 | 'show' => 'Show', 10 | 'save' => 'Save', 11 | 'saved' => 'Saved', 12 | 'saved_error' => 'Error', 13 | 'filters' => 'Filters', 14 | 'search' => 'Search', 15 | 'reset' => 'Reset', 16 | 'total' => 'Total', 17 | 'deleted' => 'Deleted', 18 | 'delete' => 'Delete', 19 | 'deleting' => 'Deleting', 20 | 'download' => 'Download', 21 | 'export' => 'Export', 22 | 'import' => 'Import', 23 | 'cancel' => 'Cancel', 24 | 'confirm' => 'Confirm', 25 | 'close' => 'Close', 26 | 'confirm_message' => 'Are you sure?', 27 | 'back' => 'Back', 28 | 'more' => 'More', 29 | 'all_sections' => 'All sections', 30 | 'file' => 'File', 31 | 'loading' => 'Loading ...', 32 | 'notfound' => 'Records not found', 33 | 'collapse_menu' => 'Collapse menu', 34 | '404' => 'Houston we have a problem page not found', 35 | 'copied' => 'Copied!', 36 | 'notifications' => [ 37 | 'title' => 'Notifications', 38 | 'mark_as_read_all' => 'Mark all as read', 39 | 'mark_as_read' => 'Mark as read', 40 | ], 41 | 'login' => [ 42 | 'title' => 'Welcome to :moonshine_title!', 43 | 'description' => 'Please sign-in to your account', 44 | 'authorization' => 'Authorization', 45 | 'remember_me' => 'Remember me', 46 | 'login' => 'Log in', 47 | 'logout' => 'Log out', 48 | 'username' => 'Username', 49 | 'email' => 'E-mail', 50 | 'password' => 'Password', 51 | 'or_socials' => 'or', 52 | ], 53 | 'resource' => [ 54 | 'system' => 'System', 55 | 'role' => 'Roles', 56 | 'name' => 'Name', 57 | 'email' => 'E-mail', 58 | 'password' => 'Password', 59 | 'repeat_password' => 'Repeat password', 60 | 'avatar' => 'Avatar', 61 | 'created_at' => 'Created At', 62 | 'admins_title' => 'Admins', 63 | 'role_title' => 'Roles', 64 | 'role_name' => 'Title', 65 | 66 | 'main_information' => 'Main information', 67 | 'change_password' => 'Change password', 68 | 69 | 'link_socialite' => 'Link account', 70 | 'linked_socialite' => 'Account linked', 71 | 72 | 'queued' => 'Queued', 73 | 74 | 'export' => [ 75 | 'exported' => 'File exported', 76 | 'confirm_content' => 'Confirm data export', 77 | ], 78 | 79 | 'import' => [ 80 | 'imported' => 'Imported', 81 | 'file_required' => 'File is required', 82 | 'extension_not_supported' => 'File extension not supported' 83 | ] 84 | ], 85 | 'choices' => [ 86 | 'no_results' => 'No results found', 87 | 'no_choices' => 'No choices to choose from', 88 | 'item_select' => 'Press to select', 89 | 'unique_item' => 'Only unique values can be added', 90 | 'custom_add_item' => 'Only values matching specific conditions can be added', 91 | 'add_item' => 'Press Enter to add ":value"', 92 | 'max_item' => 'Only :count values can be added', 93 | 'remove_item' => 'Remove item', 94 | ] 95 | ]; 96 | -------------------------------------------------------------------------------- /lang/vendor/moonshine/ru/auth.php: -------------------------------------------------------------------------------- 1 | 'Неверное имя пользователя или пароль.', 16 | 'password' => 'Неверный пароль.', 17 | 'throttle' => 'Слишком много попыток входа. Пожалуйста, попробуйте еще раз через :seconds секунд(ы).', 18 | 19 | 'socialite' => [ 20 | 'link_exists' => 'Аккаунт уже привязан', 21 | 'link_success' => 'Аккаунт привязан', 22 | ] 23 | ]; 24 | -------------------------------------------------------------------------------- /lang/vendor/moonshine/ru/pagination.php: -------------------------------------------------------------------------------- 1 | 'Показано от', 16 | 'of' => 'из', 17 | 'to' => 'до', 18 | 'results' => '', 19 | 'previous' => '« Назад', 20 | 'next' => 'Вперёд »', 21 | ]; 22 | -------------------------------------------------------------------------------- /lang/vendor/moonshine/ru/ui.php: -------------------------------------------------------------------------------- 1 | 'Профиль', 5 | 'dashboard' => 'Панель', 6 | 'add' => 'Добавить', 7 | 'create' => 'Создать', 8 | 'edit' => 'Редактировать', 9 | 'show' => 'Просмотр', 10 | 'save' => 'Сохранить', 11 | 'saved' => 'Сохранено', 12 | 'saved_error' => 'Произошла ошибка', 13 | 'filters' => 'Фильтры', 14 | 'search' => 'Поиск', 15 | 'reset' => 'Сбросить', 16 | 'total' => 'Всего', 17 | 'deleted' => 'Удалено', 18 | 'delete' => 'Удалить', 19 | 'deleting' => 'Удаление', 20 | 'download' => 'Скачать', 21 | 'export' => 'Экспорт', 22 | 'import' => 'Импорт', 23 | 'cancel' => 'Отмена', 24 | 'confirm' => 'Подтвердить', 25 | 'close' => 'Закрыть', 26 | 'confirm_message' => 'Вы уверены, что хотите удалить запись?', 27 | 'back' => 'Вернуться назад', 28 | 'more' => 'Перейти', 29 | 'all_sections' => 'Все разделы', 30 | 'file' => 'Файл', 31 | 'loading' => 'Загрузка ...', 32 | 'notfound' => 'Пока записей нет', 33 | 'collapse_menu' => 'Свернуть меню', 34 | '404' => 'Хьюстон! У нас проблема - страница не найдена', 35 | 'copied' => 'Скопировано!', 36 | 'notifications' => [ 37 | 'title' => 'Уведомления', 38 | 'mark_as_read_all' => 'Все прочитано', 39 | 'mark_as_read' => 'Прочитано', 40 | ], 41 | 'login' => [ 42 | 'title' => 'Добро пожаловать в :moonshine_title!', 43 | 'description' => 'Пожалуйста, войдите в свою учетную запись', 44 | 'authorization' => 'Авторизация', 45 | 'remember_me' => 'Запомнить', 46 | 'login' => 'Войти', 47 | 'logout' => 'Выйти', 48 | 'username' => 'Логин', 49 | 'email' => 'E-mail', 50 | 'password' => 'Пароль', 51 | 'or_socials' => 'или', 52 | ], 53 | 'resource' => [ 54 | 'system' => 'Система', 55 | 'role' => 'Роли', 56 | 'name' => 'Имя', 57 | 'email' => 'E-mail', 58 | 'password' => 'Пароль', 59 | 'repeat_password' => 'Повторите пароль', 60 | 'avatar' => 'Аватар', 61 | 'created_at' => 'Дата создания', 62 | 'admins_title' => 'Администраторы', 63 | 'role_title' => 'Роли', 64 | 'role_name' => 'Название', 65 | 66 | 'main_information' => 'Основная информация', 67 | 'change_password' => 'Изменить пароль', 68 | 69 | 'link_socialite' => 'Привязать аккаунты', 70 | 'linked_socialite' => 'Привязанные аккаунты', 71 | 72 | 'queued' => 'Поставлен в очередь', 73 | 74 | 'export' => [ 75 | 'exported' => 'Экспортирован', 76 | 'confirm_content' => 'Подтвердите экспорт данных', 77 | ], 78 | 79 | 'import' => [ 80 | 'imported' => 'Импортирован', 81 | 'file_required' => 'Файл обязателен', 82 | 'extension_not_supported' => 'Расширение файла не поддерживается' 83 | ] 84 | ], 85 | 'choices' => [ 86 | 'no_results' => 'Ничего не найдено', 87 | 'no_choices' => 'Нет вариантов для выбора', 88 | 'item_select' => 'Нажмите для выбора', 89 | 'unique_item' => 'Можно добавлять только уникальные значения', 90 | 'custom_add_item' => 'Можно добавлять только значения, соответствующие определённым условиям', 91 | 'add_item' => 'Нажмите Enter для добавления «:value»', 92 | 'max_item' => 'Максимальное количество элементов: :count', 93 | 'remove_item' => 'Удалить элемент', 94 | ] 95 | ]; 96 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "type": "module", 4 | "scripts": { 5 | "build": "vite build", 6 | "dev": "vite" 7 | }, 8 | "devDependencies": { 9 | "@tailwindcss/forms": "^0.5.2", 10 | "alpinejs": "^3.4.2", 11 | "autoprefixer": "^10.4.2", 12 | "axios": "^1.7.4", 13 | "concurrently": "^9.0.1", 14 | "flowbite": "^2.5.2", 15 | "laravel-vite-plugin": "^1.0", 16 | "postcss": "^8.4.31", 17 | "tailwindcss": "^3.1.0", 18 | "vite": "^5.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /phpstan-local.neon.dist: -------------------------------------------------------------------------------- 1 | includes: 2 | - vendor/larastan/larastan/extension.neon 3 | - vendor/nesbot/carbon/extension.neon 4 | 5 | parameters: 6 | 7 | paths: 8 | - app 9 | 10 | # Level 10 is the highest level 11 | level: 5 12 | 13 | # ignoreErrors: 14 | # - '#PHPDoc tag @var#' 15 | # 16 | # excludePaths: 17 | # - ./*/*/FileToBeExcluded.php 18 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | tests/Unit 10 | 11 | 12 | tests/Feature 13 | 14 | 15 | 16 | 17 | app 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /phpwork: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/phpwork -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /public/assets/img/as.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/assets/img/as.png -------------------------------------------------------------------------------- /public/assets/img/b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/assets/img/b.png -------------------------------------------------------------------------------- /public/assets/img/c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/assets/img/c.jpg -------------------------------------------------------------------------------- /public/assets/img/hh.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/favicon.ico -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | handleRequest(Request::capture()); 18 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /public/vendor/moonshine/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/vendor/moonshine/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/vendor/moonshine/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/vendor/moonshine/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/vendor/moonshine/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/vendor/moonshine/apple-touch-icon.png -------------------------------------------------------------------------------- /public/vendor/moonshine/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/vendor/moonshine/avatar.jpg -------------------------------------------------------------------------------- /public/vendor/moonshine/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #7843E9 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/vendor/moonshine/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/vendor/moonshine/favicon-16x16.png -------------------------------------------------------------------------------- /public/vendor/moonshine/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/vendor/moonshine/favicon-32x32.png -------------------------------------------------------------------------------- /public/vendor/moonshine/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/vendor/moonshine/favicon.ico -------------------------------------------------------------------------------- /public/vendor/moonshine/fonts/Gilroy-Black.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/vendor/moonshine/fonts/Gilroy-Black.woff2 -------------------------------------------------------------------------------- /public/vendor/moonshine/fonts/Gilroy-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/vendor/moonshine/fonts/Gilroy-Bold.woff2 -------------------------------------------------------------------------------- /public/vendor/moonshine/fonts/Gilroy-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/vendor/moonshine/fonts/Gilroy-Medium.woff2 -------------------------------------------------------------------------------- /public/vendor/moonshine/fonts/Gilroy-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/vendor/moonshine/fonts/Gilroy-Regular.woff2 -------------------------------------------------------------------------------- /public/vendor/moonshine/fonts/Gilroy-SemiBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sukhrobnurali/phpwork/14cb54c02e9c6710459b0e49a23ed439e5b04e21/public/vendor/moonshine/fonts/Gilroy-SemiBold.woff2 -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/apexcharts/apexcharts-config.js: -------------------------------------------------------------------------------- 1 | /* Global ApexChart settings */ 2 | window.Apex = { 3 | chart: { 4 | background: 'transparent', 5 | toolbar: { 6 | show: false, 7 | }, 8 | zoom: { 9 | enabled: false, 10 | }, 11 | }, 12 | dataLabels: { 13 | enabled: false, 14 | }, 15 | grid: { 16 | strokeDashArray: 2, 17 | }, 18 | legend: { 19 | position: 'bottom', 20 | offsetY: 10, 21 | itemMargin: { 22 | horizontal: 6, 23 | vertical: 6, 24 | }, 25 | }, 26 | stroke: { 27 | width: 3, 28 | curve: 'smooth', 29 | }, 30 | xaxis: { 31 | tooltip: { 32 | enabled: false, 33 | }, 34 | axisBorder: { 35 | show: false, 36 | }, 37 | axisTicks: { 38 | show: false, 39 | }, 40 | }, 41 | } 42 | -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/langs/README.md: -------------------------------------------------------------------------------- 1 | This is where language files should be placed. 2 | 3 | Please DO NOT translate these directly, use this service instead: https://crowdin.com/project/tinymce 4 | -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Ephox Corporation DBA Tiny Technologies, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/advlist/plugin.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TinyMCE version 6.8.3 (2024-02-08) 3 | */ 4 | !function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=(t,e,s)=>{const r="UL"===e?"InsertUnorderedList":"InsertOrderedList";t.execCommand(r,!1,!1===s?null:{"list-style-type":s})},s=t=>e=>e.options.get(t),r=s("advlist_number_styles"),n=s("advlist_bullet_styles"),i=t=>null==t,l=t=>!i(t);var o=tinymce.util.Tools.resolve("tinymce.util.Tools");class a{constructor(t,e){this.tag=t,this.value=e}static some(t){return new a(!0,t)}static none(){return a.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?a.some(t(this.value)):a.none()}bind(t){return this.tag?t(this.value):a.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:a.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return l(t)?a.some(t):a.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);const u=t=>e=>l(e)&&t.test(e.nodeName),d=u(/^(OL|UL|DL)$/),g=u(/^(TH|TD)$/),c=t=>i(t)||"default"===t?"":t,h=(t,e)=>s=>((t,e)=>{const s=t.selection.getNode();return e({parents:t.dom.getParents(s),element:s}),t.on("NodeChange",e),()=>t.off("NodeChange",e)})(t,(r=>((t,r)=>{const n=t.selection.getStart(!0);s.setActive(((t,e,s)=>((t,e,s)=>{for(let e=0,n=t.length;ee.nodeName===s&&((t,e)=>t.dom.isChildOf(e,t.getBody()))(t,e))))(t,r,e)),s.setEnabled(!((t,e)=>{const s=t.dom.getParent(e,"ol,ul,dl");return((t,e)=>null!==e&&!t.dom.isEditable(e))(t,s)&&t.selection.isEditable()})(t,n)&&t.selection.isEditable())})(t,r.parents))),m=(t,s,r,n,i,l)=>{l.length>1?((t,s,r,n,i,l)=>{t.ui.registry.addSplitButton(s,{tooltip:r,icon:"OL"===i?"ordered-list":"unordered-list",presets:"listpreview",columns:3,fetch:t=>{t(o.map(l,(t=>{const e="OL"===i?"num":"bull",s="disc"===t||"decimal"===t?"default":t,r=c(t),n=(t=>t.replace(/\-/g," ").replace(/\b\w/g,(t=>t.toUpperCase())))(t);return{type:"choiceitem",value:r,icon:"list-"+e+"-"+s,text:n}})))},onAction:()=>t.execCommand(n),onItemAction:(s,r)=>{e(t,i,r)},select:e=>{const s=(t=>{const e=t.dom.getParent(t.selection.getNode(),"ol,ul"),s=t.dom.getStyle(e,"listStyleType");return a.from(s)})(t);return s.map((t=>e===t)).getOr(!1)},onSetup:h(t,i)})})(t,s,r,n,i,l):((t,s,r,n,i,l)=>{t.ui.registry.addToggleButton(s,{active:!1,tooltip:r,icon:"OL"===i?"ordered-list":"unordered-list",onSetup:h(t,i),onAction:()=>t.queryCommandState(n)||""===l?t.execCommand(n):e(t,i,l)})})(t,s,r,n,i,c(l[0]))};t.add("advlist",(t=>{t.hasPlugin("lists")?((t=>{const e=t.options.register;e("advlist_number_styles",{processor:"string[]",default:"default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman".split(",")}),e("advlist_bullet_styles",{processor:"string[]",default:"default,circle,square".split(",")})})(t),(t=>{m(t,"numlist","Numbered list","InsertOrderedList","OL",r(t)),m(t,"bullist","Bullet list","InsertUnorderedList","UL",n(t))})(t),(t=>{t.addCommand("ApplyUnorderedListStyle",((s,r)=>{e(t,"UL",r["list-style-type"])})),t.addCommand("ApplyOrderedListStyle",((s,r)=>{e(t,"OL",r["list-style-type"])}))})(t)):console.error("Please use the Lists plugin together with the Advanced List plugin.")}))}(); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/anchor/plugin.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TinyMCE version 6.8.3 (2024-02-08) 3 | */ 4 | !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),o=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=("allow_html_in_named_anchor",e=>e.options.get("allow_html_in_named_anchor"));const a="a:not([href])",r=e=>!e,i=e=>e.getAttribute("id")||e.getAttribute("name")||"",l=e=>(e=>"a"===e.nodeName.toLowerCase())(e)&&!e.getAttribute("href")&&""!==i(e),s=e=>e.dom.getParent(e.selection.getStart(),a),d=(e,a)=>{const r=s(e);r?((e,t,o)=>{o.removeAttribute("name"),o.id=t,e.addVisual(),e.undoManager.add()})(e,a,r):((e,a)=>{e.undoManager.transact((()=>{n(e)||e.selection.collapse(!0),e.selection.isCollapsed()?e.insertContent(e.dom.createHTML("a",{id:a})):((e=>{const n=e.dom;t(n).walk(e.selection.getRng(),(e=>{o.each(e,(e=>{var t;l(t=e)&&!t.firstChild&&n.remove(e,!1)}))}))})(e),e.formatter.remove("namedAnchor",void 0,void 0,!0),e.formatter.apply("namedAnchor",{value:a}),e.addVisual())}))})(e,a),e.focus()},c=e=>(e=>r(e.attr("href"))&&!r(e.attr("id")||e.attr("name")))(e)&&!e.firstChild,m=e=>t=>{for(let o=0;ot=>{const o=()=>{t.setEnabled(e.selection.isEditable())};return e.on("NodeChange",o),o(),()=>{e.off("NodeChange",o)}};e.add("anchor",(e=>{(e=>{(0,e.options.register)("allow_html_in_named_anchor",{processor:"boolean",default:!1})})(e),(e=>{e.on("PreInit",(()=>{e.parser.addNodeFilter("a",m("false")),e.serializer.addNodeFilter("a",m(null))}))})(e),(e=>{e.addCommand("mceAnchor",(()=>{(e=>{const t=(e=>{const t=s(e);return t?i(t):""})(e);e.windowManager.open({title:"Anchor",size:"normal",body:{type:"panel",items:[{name:"id",type:"input",label:"ID",placeholder:"example"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{id:t},onSubmit:t=>{((e,t)=>/^[A-Za-z][A-Za-z0-9\-:._]*$/.test(t)?(d(e,t),!0):(e.windowManager.alert("ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores."),!1))(e,t.getData().id)&&t.close()}})})(e)}))})(e),(e=>{const t=()=>e.execCommand("mceAnchor");e.ui.registry.addToggleButton("anchor",{icon:"bookmark",tooltip:"Anchor",onAction:t,onSetup:t=>{const o=e.selection.selectorChangedWithUnbind("a:not([href])",t.setActive).unbind,n=u(e)(t);return()=>{o(),n()}}}),e.ui.registry.addMenuItem("anchor",{icon:"bookmark",text:"Anchor...",onAction:t,onSetup:u(e)})})(e),e.on("PreInit",(()=>{(e=>{e.formatter.register("namedAnchor",{inline:"a",selector:a,remove:"all",split:!0,deep:!0,attributes:{id:"%value"},onmatch:(e,t,o)=>l(e)})})(e)}))}))}(); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/autolink/plugin.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TinyMCE version 6.8.3 (2024-02-08) 3 | */ 4 | !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>t.options.get(e),n=t("autolink_pattern"),o=t("link_default_target"),r=t("link_default_protocol"),a=t("allow_unsafe_link_target"),s=("string",e=>"string"===(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=o=e,(r=String).prototype.isPrototypeOf(n)||(null===(a=o.constructor)||void 0===a?void 0:a.name)===r.name)?"string":t;var n,o,r,a})(e));const l=(void 0,e=>undefined===e);const i=e=>!(e=>null==e)(e),c=Object.hasOwnProperty,d=e=>"\ufeff"===e;var u=tinymce.util.Tools.resolve("tinymce.dom.TextSeeker");const f=e=>/^[(\[{ \u00a0]$/.test(e),g=(e,t,n)=>{for(let o=t-1;o>=0;o--){const t=e.charAt(o);if(!d(t)&&n(t))return o}return-1},m=(e,t)=>{var o;const a=e.schema.getVoidElements(),s=n(e),{dom:i,selection:d}=e;if(null!==i.getParent(d.getNode(),"a[href]"))return null;const m=d.getRng(),k=u(i,(e=>{return i.isBlock(e)||(t=a,n=e.nodeName.toLowerCase(),c.call(t,n))||"false"===i.getContentEditable(e);var t,n})),{container:p,offset:y}=((e,t)=>{let n=e,o=t;for(;1===n.nodeType&&n.childNodes[o];)n=n.childNodes[o],o=3===n.nodeType?n.data.length:n.childNodes.length;return{container:n,offset:o}})(m.endContainer,m.endOffset),w=null!==(o=i.getParent(p,i.isBlock))&&void 0!==o?o:i.getRoot(),h=k.backwards(p,y+t,((e,t)=>{const n=e.data,o=g(n,t,(r=f,e=>!r(e)));var r,a;return-1===o||(a=n[o],/[?!,.;:]/.test(a))?o:o+1}),w);if(!h)return null;let v=h.container;const _=k.backwards(h.container,h.offset,((e,t)=>{v=e;const n=g(e.data,t,f);return-1===n?n:n+1}),w),A=i.createRng();_?A.setStart(_.container,_.offset):A.setStart(v,0),A.setEnd(h.container,h.offset);const C=A.toString().replace(/\uFEFF/g,"").match(s);if(C){let t=C[0];return $="www.",(b=t).length>=4&&b.substr(0,4)===$?t=r(e)+"://"+t:((e,t,n=0,o)=>{const r=e.indexOf(t,n);return-1!==r&&(!!l(o)||r+t.length<=o)})(t,"@")&&!(e=>/^([A-Za-z][A-Za-z\d.+-]*:\/\/)|mailto:/.test(e))(t)&&(t="mailto:"+t),{rng:A,url:t}}var b,$;return null},k=(e,t)=>{const{dom:n,selection:r}=e,{rng:l,url:i}=t,c=r.getBookmark();r.setRng(l);const d="createlink",u={command:d,ui:!1,value:i};if(!e.dispatch("BeforeExecCommand",u).isDefaultPrevented()){e.getDoc().execCommand(d,!1,i),e.dispatch("ExecCommand",u);const t=o(e);if(s(t)){const o=r.getNode();n.setAttrib(o,"target",t),"_blank"!==t||a(e)||n.setAttrib(o,"rel","noopener")}}r.moveToBookmark(c),e.nodeChanged()},p=e=>{const t=m(e,-1);i(t)&&k(e,t)},y=p;e.add("autolink",(e=>{(e=>{const t=e.options.register;t("autolink_pattern",{processor:"regexp",default:new RegExp("^"+/(?:[A-Za-z][A-Za-z\d.+-]{0,14}:\/\/(?:[-.~*+=!&;:'%@?^${}(),\w]+@)?|www\.|[-;:&=+$,.\w]+@)[A-Za-z\d-]+(?:\.[A-Za-z\d-]+)*(?::\d+)?(?:\/(?:[-.~*+=!;:'%@$(),\/\w]*[-~*+=%@$()\/\w])?)?(?:\?(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?(?:#(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?/g.source+"$","i")}),t("link_default_target",{processor:"string"}),t("link_default_protocol",{processor:"string",default:"https"})})(e),(e=>{e.on("keydown",(t=>{13!==t.keyCode||t.isDefaultPrevented()||(e=>{const t=m(e,0);i(t)&&k(e,t)})(e)})),e.on("keyup",(t=>{32===t.keyCode?p(e):(48===t.keyCode&&t.shiftKey||221===t.keyCode)&&y(e)}))})(e)}))}(); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/autoresize/plugin.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TinyMCE version 6.8.3 (2024-02-08) 3 | */ 4 | !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.Env");const o=e=>t=>t.options.get(e),s=o("min_height"),i=o("max_height"),n=o("autoresize_overflow_padding"),r=o("autoresize_bottom_margin"),l=(e,t)=>{const o=e.getBody();o&&(o.style.overflowY=t?"":"hidden",t||(o.scrollTop=0))},g=(e,t,o,s)=>{var i;const n=parseInt(null!==(i=e.getStyle(t,o,s))&&void 0!==i?i:"",10);return isNaN(n)?0:n},a=(e,o,r,c)=>{var d;const f=e.dom,u=e.getDoc();if(!u)return;if((e=>e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen())(e))return void l(e,!0);const m=u.documentElement,h=c?c():n(e),p=null!==(d=s(e))&&void 0!==d?d:e.getElement().offsetHeight;let y=p;const S=g(f,m,"margin-top",!0),v=g(f,m,"margin-bottom",!0);let C=m.offsetHeight+S+v+h;C<0&&(C=0);const b=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight;C+b>p&&(y=C+b);const w=i(e);if(w&&y>w?(y=w,l(e,!0)):l(e,!1),y!==o.get()){const s=y-o.get();if(f.setStyle(e.getContainer(),"height",y+"px"),o.set(y),(e=>{e.dispatch("ResizeEditor")})(e),t.browser.isSafari()&&(t.os.isMacOS()||t.os.isiOS())){const t=e.getWin();t.scrollTo(t.pageXOffset,t.pageYOffset)}e.hasFocus()&&(e=>{if("setcontent"===(null==e?void 0:e.type.toLowerCase())){const t=e;return!0===t.selection||!0===t.paste}return!1})(r)&&e.selection.scrollIntoView(),(t.browser.isSafari()||t.browser.isChromium())&&s<0&&a(e,o,r,c)}};e.add("autoresize",(e=>{if((e=>{const t=e.options.register;t("autoresize_overflow_padding",{processor:"number",default:1}),t("autoresize_bottom_margin",{processor:"number",default:50})})(e),e.options.isSet("resize")||e.options.set("resize",!1),!e.inline){const o=(e=>{let t=0;return{get:()=>t,set:e=>{t=e}}})();((e,t)=>{e.addCommand("mceAutoResize",(()=>{a(e,t)}))})(e,o),((e,o)=>{let s,i,l=()=>r(e);e.on("init",(i=>{s=0;const r=n(e),g=e.dom;g.setStyles(e.getDoc().documentElement,{height:"auto"}),t.browser.isEdge()||t.browser.isIE()?g.setStyles(e.getBody(),{paddingLeft:r,paddingRight:r,"min-height":0}):g.setStyles(e.getBody(),{paddingLeft:r,paddingRight:r}),a(e,o,i,l),s+=1})),e.on("NodeChange SetContent keyup FullscreenStateChanged ResizeContent",(t=>{if(1===s)i=e.getContainer().offsetHeight,a(e,o,t,l),s+=1;else if(2===s){const t=i0):l,s+=1}else a(e,o,t,l)}))})(e,o)}}))}(); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/autosave/plugin.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TinyMCE version 6.8.3 (2024-02-08) 3 | */ 4 | !function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=("string",t=>"string"===(t=>{const e=typeof t;return null===t?"null":"object"===e&&Array.isArray(t)?"array":"object"===e&&(r=o=t,(a=String).prototype.isPrototypeOf(r)||(null===(s=o.constructor)||void 0===s?void 0:s.name)===a.name)?"string":e;var r,o,a,s})(t));const r=(void 0,t=>undefined===t);var o=tinymce.util.Tools.resolve("tinymce.util.Delay"),a=tinymce.util.Tools.resolve("tinymce.util.LocalStorage"),s=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=t=>{const e=/^(\d+)([ms]?)$/.exec(t);return(e&&e[2]?{s:1e3,m:6e4}[e[2]]:1)*parseInt(t,10)},i=t=>e=>e.options.get(t),u=i("autosave_ask_before_unload"),l=i("autosave_restore_when_empty"),c=i("autosave_interval"),d=i("autosave_retention"),m=t=>{const e=document.location;return t.options.get("autosave_prefix").replace(/{path}/g,e.pathname).replace(/{query}/g,e.search).replace(/{hash}/g,e.hash).replace(/{id}/g,t.id)},v=(t,e)=>{if(r(e))return t.dom.isEmpty(t.getBody());{const r=s.trim(e);if(""===r)return!0;{const e=(new DOMParser).parseFromString(r,"text/html");return t.dom.isEmpty(e)}}},f=t=>{var e;const r=parseInt(null!==(e=a.getItem(m(t)+"time"))&&void 0!==e?e:"0",10)||0;return!((new Date).getTime()-r>d(t)&&(p(t,!1),1))},p=(t,e)=>{const r=m(t);a.removeItem(r+"draft"),a.removeItem(r+"time"),!1!==e&&(t=>{t.dispatch("RemoveDraft")})(t)},g=t=>{const e=m(t);!v(t)&&t.isDirty()&&(a.setItem(e+"draft",t.getContent({format:"raw",no_events:!0})),a.setItem(e+"time",(new Date).getTime().toString()),(t=>{t.dispatch("StoreDraft")})(t))},y=t=>{var e;const r=m(t);f(t)&&(t.setContent(null!==(e=a.getItem(r+"draft"))&&void 0!==e?e:"",{format:"raw"}),(t=>{t.dispatch("RestoreDraft")})(t))};var D=tinymce.util.Tools.resolve("tinymce.EditorManager");const h=t=>e=>{e.setEnabled(f(t));const r=()=>e.setEnabled(f(t));return t.on("StoreDraft RestoreDraft RemoveDraft",r),()=>t.off("StoreDraft RestoreDraft RemoveDraft",r)};t.add("autosave",(t=>((t=>{const r=t.options.register,o=t=>{const r=e(t);return r?{value:n(t),valid:r}:{valid:!1,message:"Must be a string."}};r("autosave_ask_before_unload",{processor:"boolean",default:!0}),r("autosave_prefix",{processor:"string",default:"tinymce-autosave-{path}{query}{hash}-{id}-"}),r("autosave_restore_when_empty",{processor:"boolean",default:!1}),r("autosave_interval",{processor:o,default:"30s"}),r("autosave_retention",{processor:o,default:"20m"})})(t),(t=>{t.editorManager.on("BeforeUnload",(t=>{let e;s.each(D.get(),(t=>{t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&u(t)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))})),e&&(t.preventDefault(),t.returnValue=e)}))})(t),(t=>{(t=>{const e=c(t);o.setEditorInterval(t,(()=>{g(t)}),e)})(t);const e=()=>{(t=>{t.undoManager.transact((()=>{y(t),p(t)})),t.focus()})(t)};t.ui.registry.addButton("restoredraft",{tooltip:"Restore last draft",icon:"restore-draft",onAction:e,onSetup:h(t)}),t.ui.registry.addMenuItem("restoredraft",{text:"Restore last draft",icon:"restore-draft",onAction:e,onSetup:h(t)})})(t),t.on("init",(()=>{l(t)&&t.dom.isEmpty(t.getBody())&&y(t)})),(t=>({hasDraft:()=>f(t),storeDraft:()=>g(t),restoreDraft:()=>y(t),removeDraft:e=>p(t,e),isEmpty:e=>v(t,e)}))(t))))}(); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/code/plugin.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TinyMCE version 6.8.3 (2024-02-08) 3 | */ 4 | !function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("code",(e=>((e=>{e.addCommand("mceCodeEditor",(()=>{(e=>{const o=(e=>e.getContent({source_view:!0}))(e);e.windowManager.open({title:"Source Code",size:"large",body:{type:"panel",items:[{type:"textarea",name:"code"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{code:o},onSubmit:o=>{((e,o)=>{e.focus(),e.undoManager.transact((()=>{e.setContent(o)})),e.selection.setCursorLocation(),e.nodeChanged()})(e,o.getData().code),o.close()}})})(e)}))})(e),(e=>{const o=()=>e.execCommand("mceCodeEditor");e.ui.registry.addButton("code",{icon:"sourcecode",tooltip:"Source code",onAction:o}),e.ui.registry.addMenuItem("code",{icon:"sourcecode",text:"Source code",onAction:o})})(e),{})))}(); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/directionality/plugin.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TinyMCE version 6.8.3 (2024-02-08) 3 | */ 4 | !function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=t=>e=>typeof e===t,o=t=>"string"===(t=>{const e=typeof t;return null===t?"null":"object"===e&&Array.isArray(t)?"array":"object"===e&&(o=r=t,(n=String).prototype.isPrototypeOf(o)||(null===(i=r.constructor)||void 0===i?void 0:i.name)===n.name)?"string":e;var o,r,n,i})(t),r=e("boolean"),n=t=>!(t=>null==t)(t),i=e("function"),s=e("number"),l=(!1,()=>false);class a{constructor(t,e){this.tag=t,this.value=e}static some(t){return new a(!0,t)}static none(){return a.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?a.some(t(this.value)):a.none()}bind(t){return this.tag?t(this.value):a.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:a.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return n(t)?a.some(t):a.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);const u=(t,e)=>{for(let o=0,r=t.length;o{if(null==t)throw new Error("Node cannot be null or undefined");return{dom:t}},d=c,h=(t,e)=>{const o=t.dom;if(1!==o.nodeType)return!1;{const t=o;if(void 0!==t.matches)return t.matches(e);if(void 0!==t.msMatchesSelector)return t.msMatchesSelector(e);if(void 0!==t.webkitMatchesSelector)return t.webkitMatchesSelector(e);if(void 0!==t.mozMatchesSelector)return t.mozMatchesSelector(e);throw new Error("Browser lacks native selectors")}};"undefined"!=typeof window?window:Function("return this;")();const m=t=>e=>(t=>t.dom.nodeType)(e)===t,g=m(1),f=m(3),v=m(9),y=m(11),p=(t,e)=>{t.dom.removeAttribute(e)},w=i(Element.prototype.attachShadow)&&i(Node.prototype.getRootNode)?t=>d(t.dom.getRootNode()):t=>v(t)?t:d(t.dom.ownerDocument),b=t=>d(t.dom.host),N=t=>{const e=f(t)?t.dom.parentNode:t.dom;if(null==e||null===e.ownerDocument)return!1;const o=e.ownerDocument;return(t=>{const e=w(t);return y(o=e)&&n(o.dom.host)?a.some(e):a.none();var o})(d(e)).fold((()=>o.body.contains(e)),(r=N,i=b,t=>r(i(t))));var r,i},S=t=>"rtl"===((t,e)=>{const o=t.dom,r=window.getComputedStyle(o).getPropertyValue(e);return""!==r||N(t)?r:((t,e)=>(t=>void 0!==t.style&&i(t.style.getPropertyValue))(t)?t.style.getPropertyValue(e):"")(o,e)})(t,"direction")?"rtl":"ltr",A=(t,e)=>((t,o)=>((t,e)=>{const o=[];for(let r=0,n=t.length;r{const o=t.length,r=new Array(o);for(let n=0;nh(t,e))))(t),E=("li",t=>g(t)&&"li"===t.dom.nodeName.toLowerCase());const T=(t,e,n)=>{u(e,(e=>{const c=d(e),m=E(c),f=((t,e)=>{return(e?(o=t,r="ol,ul",((t,e,o)=>{let n=t.dom;const s=i(o)?o:l;for(;n.parentNode;){n=n.parentNode;const t=d(n);if(h(t,r))return a.some(t);if(s(t))break}return a.none()})(o,0,n)):a.some(t)).getOr(t);var o,r,n})(c,m);var v;(v=f,(t=>a.from(t.dom.parentNode).map(d))(v).filter(g)).each((e=>{if(t.setStyle(f.dom,"direction",null),S(e)===n?p(f,"dir"):((t,e,n)=>{((t,e,n)=>{if(!(o(n)||r(n)||s(n)))throw console.error("Invalid call to Attribute.set. Key ",e,":: Value ",n,":: Element ",t),new Error("Attribute value was not simple");t.setAttribute(e,n+"")})(t.dom,e,n)})(f,"dir",n),S(f)!==n&&t.setStyle(f.dom,"direction",n),m){const e=A(f,"li[dir],li[style]");u(e,(e=>{p(e,"dir"),t.setStyle(e.dom,"direction",null)}))}}))}))},C=(t,e)=>{t.selection.isEditable()&&(T(t.dom,t.selection.getSelectedBlocks(),e),t.nodeChanged())},D=(t,e)=>o=>{const r=r=>{const n=d(r.element);o.setActive(S(n)===e),o.setEnabled(t.selection.isEditable())};return t.on("NodeChange",r),o.setEnabled(t.selection.isEditable()),()=>t.off("NodeChange",r)};t.add("directionality",(t=>{(t=>{t.addCommand("mceDirectionLTR",(()=>{C(t,"ltr")})),t.addCommand("mceDirectionRTL",(()=>{C(t,"rtl")}))})(t),(t=>{t.ui.registry.addToggleButton("ltr",{tooltip:"Left to right",icon:"ltr",onAction:()=>t.execCommand("mceDirectionLTR"),onSetup:D(t,"ltr")}),t.ui.registry.addToggleButton("rtl",{tooltip:"Right to left",icon:"rtl",onAction:()=>t.execCommand("mceDirectionRTL"),onSetup:D(t,"rtl")})})(t)}))}(); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/help/js/i18n/keynav/en.js: -------------------------------------------------------------------------------- 1 | tinymce.Resource.add('tinymce.html-i18n.help-keynav.en', 2 | '

Begin keyboard navigation

\n' + 3 | '\n' + 4 | '
\n' + 5 | '
Focus the Menu bar
\n' + 6 | '
Windows or Linux: Alt+F9
\n' + 7 | '
macOS: ⌥F9
\n' + 8 | '
Focus the Toolbar
\n' + 9 | '
Windows or Linux: Alt+F10
\n' + 10 | '
macOS: ⌥F10
\n' + 11 | '
Focus the footer
\n' + 12 | '
Windows or Linux: Alt+F11
\n' + 13 | '
macOS: ⌥F11
\n' + 14 | '
Focus a contextual toolbar
\n' + 15 | '
Windows, Linux or macOS: Ctrl+F9\n' + 16 | '
\n' + 17 | '\n' + 18 | '

Navigation will start at the first UI item, which will be highlighted, or underlined in the case of the first item in\n' + 19 | ' the Footer element path.

\n' + 20 | '\n' + 21 | '

Navigate between UI sections

\n' + 22 | '\n' + 23 | '

To move from one UI section to the next, press Tab.

\n' + 24 | '\n' + 25 | '

To move from one UI section to the previous, press Shift+Tab.

\n' + 26 | '\n' + 27 | '

The Tab order of these UI sections is:

\n' + 28 | '\n' + 29 | '
    \n' + 30 | '
  1. Menu bar
  2. \n' + 31 | '
  3. Each toolbar group
  4. \n' + 32 | '
  5. Sidebar
  6. \n' + 33 | '
  7. Element path in the footer
  8. \n' + 34 | '
  9. Word count toggle button in the footer
  10. \n' + 35 | '
  11. Branding link in the footer
  12. \n' + 36 | '
  13. Editor resize handle in the footer
  14. \n' + 37 | '
\n' + 38 | '\n' + 39 | '

If a UI section is not present, it is skipped.

\n' + 40 | '\n' + 41 | '

If the footer has keyboard navigation focus, and there is no visible sidebar, pressing Shift+Tab\n' + 42 | ' moves focus to the first toolbar group, not the last.

\n' + 43 | '\n' + 44 | '

Navigate within UI sections

\n' + 45 | '\n' + 46 | '

To move from one UI element to the next, press the appropriate Arrow key.

\n' + 47 | '\n' + 48 | '

The Left and Right arrow keys

\n' + 49 | '\n' + 50 | '
    \n' + 51 | '
  • move between menus in the menu bar.
  • \n' + 52 | '
  • open a sub-menu in a menu.
  • \n' + 53 | '
  • move between buttons in a toolbar group.
  • \n' + 54 | '
  • move between items in the footer’s element path.
  • \n' + 55 | '
\n' + 56 | '\n' + 57 | '

The Down and Up arrow keys

\n' + 58 | '\n' + 59 | '
    \n' + 60 | '
  • move between menu items in a menu.
  • \n' + 61 | '
  • move between items in a toolbar pop-up menu.
  • \n' + 62 | '
\n' + 63 | '\n' + 64 | '

Arrow keys cycle within the focused UI section.

\n' + 65 | '\n' + 66 | '

To close an open menu, an open sub-menu, or an open pop-up menu, press the Esc key.

\n' + 67 | '\n' + 68 | '

If the current focus is at the ‘top’ of a particular UI section, pressing the Esc key also exits\n' + 69 | ' keyboard navigation entirely.

\n' + 70 | '\n' + 71 | '

Execute a menu item or toolbar button

\n' + 72 | '\n' + 73 | '

When the desired menu item or toolbar button is highlighted, press Return, Enter,\n' + 74 | ' or the Space bar to execute the item.

\n' + 75 | '\n' + 76 | '

Navigate non-tabbed dialogs

\n' + 77 | '\n' + 78 | '

In non-tabbed dialogs, the first interactive component takes focus when the dialog opens.

\n' + 79 | '\n' + 80 | '

Navigate between interactive dialog components by pressing Tab or Shift+Tab.

\n' + 81 | '\n' + 82 | '

Navigate tabbed dialogs

\n' + 83 | '\n' + 84 | '

In tabbed dialogs, the first button in the tab menu takes focus when the dialog opens.

\n' + 85 | '\n' + 86 | '

Navigate between interactive components of this dialog tab by pressing Tab or\n' + 87 | ' Shift+Tab.

\n' + 88 | '\n' + 89 | '

Switch to another dialog tab by giving the tab menu focus and then pressing the appropriate Arrow\n' + 90 | ' key to cycle through the available tabs.

\n'); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/help/js/i18n/keynav/fa.js: -------------------------------------------------------------------------------- 1 | tinymce.Resource.add('tinymce.html-i18n.help-keynav.fa', 2 | '

شروع پیمایش صفحه‌کلید

\n' + 3 | '\n' + 4 | '
\n' + 5 | '
تمرکز بر نوار منو
\n' + 6 | '
Windows یا Linux:‎‏: Alt+F9
\n' + 7 | '
‎‏macOS: ⌥F9‎‏
\n' + 8 | '
تمرکز بر نوار ابزار
\n' + 9 | '
Windows یا Linux‎‏: Alt+F10
\n' + 10 | '
‎‏macOS: ⌥F10‎‏
\n' + 11 | '
تمرکز بر پانویس
\n' + 12 | '
Windows یا Linux‎‏: Alt+F11
\n' + 13 | '
‎‏macOS: ⌥F11‎‏
\n' + 14 | '
تمرکز بر نوار ابزار بافتاری
\n' + 15 | '
Windows ،Linux یا macOS:‏ Ctrl+F9\n' + 16 | '
\n' + 17 | '\n' + 18 | '

پیمایش در اولین مورد رابط کاربری شروع می‌شود و درخصوص اولین مورد در\n' + 19 | ' مسیر عنصر پانویس، برجسته یا زیرخط‌دار می‌شود.

\n' + 20 | '\n' + 21 | '

پیمایش بین بخش‌های رابط کاربری

\n' + 22 | '\n' + 23 | '

برای جابجایی از یک بخش رابط کاربری به بخش بعدی، Tab را فشار دهید.

\n' + 24 | '\n' + 25 | '

برای جابجایی از یک بخش رابط کاربری به بخش قبلی، Shift+Tab را فشار دهید.

\n' + 26 | '\n' + 27 | '

ترتیب Tab این بخش‌های رابط کاربری عبارتند از:

\n' + 28 | '\n' + 29 | '
    \n' + 30 | '
  1. نوار منو
  2. \n' + 31 | '
  3. هر گروه نوار ابزار
  4. \n' + 32 | '
  5. نوار کناری
  6. \n' + 33 | '
  7. مسیر عنصر در پانویس
  8. \n' + 34 | '
  9. دکمه تغییر وضعیت تعداد کلمات در پانویس
  10. \n' + 35 | '
  11. پیوند نمانام‌سازی در پانویس
  12. \n' + 36 | '
  13. دسته تغییر اندازه ویرایشگر در پانویس
  14. \n' + 37 | '
\n' + 38 | '\n' + 39 | '

اگر بخشی از رابط کاربری موجود نباشد، رد می‌شود.

\n' + 40 | '\n' + 41 | '

اگر پانویس دارای تمرکز بر پیمایش صفحه‌کلید باشد،‌ و نوار کناری قابل‌مشاهده وجود ندارد، فشردن Shift+Tab\n' + 42 | ' تمرکز را به گروه نوار ابزار اول می‌برد، نه آخر.

\n' + 43 | '\n' + 44 | '

پیمایش در بخش‌های رابط کاربری

\n' + 45 | '\n' + 46 | '

برای جابجایی از یک عنصر رابط کاربری به بعدی، کلید جهت‌نمای مناسب را فشار دهید.

\n' + 47 | '\n' + 48 | '

کلیدهای جهت‌نمای چپ و راست

\n' + 49 | '\n' + 50 | '
    \n' + 51 | '
  • جابجایی بین منوها در نوار منو.
  • \n' + 52 | '
  • باز کردن منوی فرعی در یک منو.
  • \n' + 53 | '
  • جابجایی بین دکمه‌ها در یک گروه نوار ابزار.
  • \n' + 54 | '
  • جابجایی بین موارد در مسیر عنصر پانویس.
  • \n' + 55 | '
\n' + 56 | '\n' + 57 | '

کلیدهای جهت‌نمای پایین و بالا

\n' + 58 | '\n' + 59 | '
    \n' + 60 | '
  • جابجایی بین موارد منو در یک منو.
  • \n' + 61 | '
  • جابجایی بین موارد در یک منوی بازشوی نوار ابزار.
  • \n' + 62 | '
\n' + 63 | '\n' + 64 | '

کلیدهایجهت‌نما در بخش رابط کاربری متمرکز می‌چرخند.

\n' + 65 | '\n' + 66 | '

برای بستن یک منوی باز، یک منوی فرعی باز، یا یک منوی بازشوی باز، کلید Esc را فشار دهید.

\n' + 67 | '\n' + 68 | '

اگر تمرکز فعلی در «بالای» یک بخش رابط کاربری خاص است، فشردن کلید Esc نیز موجب\n' + 69 | ' خروج کامل از پیمایش صفحه‌کلید می‌شود.

\n' + 70 | '\n' + 71 | '

اجرای یک مورد منو یا دکمه نوار ابزار

\n' + 72 | '\n' + 73 | '

وقتی مورد منو یا دکمه نوار ابزار مورد نظر هایلایت شد، دکمه بازگشت، Enter،\n' + 74 | ' یا نوار Space را فشار دهید تا مورد را اجرا کنید.

\n' + 75 | '\n' + 76 | '

پیمایش در کادرهای گفتگوی بدون زبانه

\n' + 77 | '\n' + 78 | '

در کادرهای گفتگوی بدون زبانه، وقتی کادر گفتگو باز می‌شود، اولین جزء تعاملی متمرکز می‌شود.

\n' + 79 | '\n' + 80 | '

با فشردن Tab یا Shift+Tab، بین اجزای کادر گفتگوی تعاملی پیمایش کنید.

\n' + 81 | '\n' + 82 | '

پیمایش کادرهای گفتگوی زبانه‌دار

\n' + 83 | '\n' + 84 | '

در کادرهای گفتگوی زبانه‌دار، وقتی کادر گفتگو باز می‌شود، اولین دکمه در منوی زبانه متمرکز می‌شود.

\n' + 85 | '\n' + 86 | '

با فشردن Tab یا\n' + 87 | ' Shift+Tab، بین اجزای تعاملی این زبانه کادر گفتگو پیمایش کنید.

\n' + 88 | '\n' + 89 | '

با دادن تمرکز به منوی زبانه و سپس فشار دادن کلید جهت‌نمای\n' + 90 | ' مناسب برای چرخش میان زبانه‌های موجود، به زبانه کادر گفتگوی دیگری بروید.

\n'); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/help/js/i18n/keynav/he_IL.js: -------------------------------------------------------------------------------- 1 | tinymce.Resource.add('tinymce.html-i18n.help-keynav.he_IL', 2 | '

התחל ניווט במקלדת

\n' + 3 | '\n' + 4 | '
\n' + 5 | '
התמקד בשורת התפריטים
\n' + 6 | '
Windows או Linux:‏ Alt+F9
\n' + 7 | '
macOS: ⌥F9
\n' + 8 | '
העבר מיקוד לסרגל הכלים
\n' + 9 | '
Windows או Linux:‏ Alt+F10
\n' + 10 | '
macOS: ⌥F10
\n' + 11 | '
העבר מיקוד לכותרת התחתונה
\n' + 12 | '
Windows או Linux:‏ Alt+F11
\n' + 13 | '
macOS: ⌥F11
\n' + 14 | '
העבר מיקוד לסרגל כלים הקשרי
\n' + 15 | '
Windows‏, Linux או macOS:‏ Ctrl+F9\n' + 16 | '
\n' + 17 | '\n' + 18 | '

הניווט יתחיל ברכיב הראשון במשך, שיודגש או שיהיה מתחתיו קו תחתון במקרה של הפריט הראשון\n' + 19 | ' הנתיב של רכיב הכותרת התחתונה.

\n' + 20 | '\n' + 21 | '

עבור בין מקטעים במסך

\n' + 22 | '\n' + 23 | '

כדי לעבור בין המקטעים במסך, הקש Tab.

\n' + 24 | '\n' + 25 | '

כדי לעבור למקטע הקודם במסך, הקש Shift+Tab.

\n' + 26 | '\n' + 27 | '

הסדר מבחינת מקש Tab של הרכיבים במסך:

\n' + 28 | '\n' + 29 | '
    \n' + 30 | '
  1. שורת התפריטים
  2. \n' + 31 | '
  3. כל קבוצה בסרגל הכלים
  4. \n' + 32 | '
  5. הסרגל הצידי
  6. \n' + 33 | '
  7. נתיב של רכיב בכותרת התחתונה
  8. \n' + 34 | '
  9. לחצן לספירת מילים בכותרת התחתונה
  10. \n' + 35 | '
  11. קישור של המותג בכותרת התחתונה
  12. \n' + 36 | '
  13. ידית לשינוי גודל עבור העורך בכותרת התחתונה
  14. \n' + 37 | '
\n' + 38 | '\n' + 39 | '

אם רכיב כלשהו במסך לא מופיע, המערכת תדלג עליו.

\n' + 40 | '\n' + 41 | '

אם בכותרת התחתונה יש מיקוד של ניווט במקלדת, ולא מופיע סרגל בצד, יש להקיש Shift+Tab\n' + 42 | ' מעביר את המיקוד לקבוצה הראשונה בסרגל הכלים, לא האחרונה.

\n' + 43 | '\n' + 44 | '

עבור בתוך מקטעים במסך

\n' + 45 | '\n' + 46 | '

כדי לעבור מרכיב אחד לרכיב אחר במסך, הקש על מקש החץ המתאים.

\n' + 47 | '\n' + 48 | '

מקשי החיצים שמאלה וימינה

\n' + 49 | '\n' + 50 | '
    \n' + 51 | '
  • עבור בין תפריטים בשורת התפריטים.
  • \n' + 52 | '
  • פתח תפריט משני בתפריט.
  • \n' + 53 | '
  • עבור בין לחצנים בקבוצה בסרגל הכלים.
  • \n' + 54 | '
  • עבור בין פריטים ברכיב בכותרת התחתונה.
  • \n' + 55 | '
\n' + 56 | '\n' + 57 | '

מקשי החיצים למטה ולמעלה

\n' + 58 | '\n' + 59 | '
    \n' + 60 | '
  • עבור בין פריטים בתפריט.
  • \n' + 61 | '
  • עבור בין פריטים בחלון הקובץ של סרגל הכלים.
  • \n' + 62 | '
\n' + 63 | '\n' + 64 | '

מקשי החצים משתנים בתוך המקטע במסך שעליו נמצא המיקוד.

\n' + 65 | '\n' + 66 | '

כדי לסגור תפריט פתוח, תפריט משני פתוח או חלון קופץ, הקש על Esc.

\n' + 67 | '\n' + 68 | "

אם המיקוד הוא על החלק 'העליון' של מקטע מסוים במסך, הקשה על Esc מביאה גם ליציאה\n" + 69 | ' מהניווט במקלדת לחלוטין.

\n' + 70 | '\n' + 71 | '

הפעל פריט בתפריט או לחצן בסרגל הכלים

\n' + 72 | '\n' + 73 | '

כאשר הפריט הרצוי בתפריט או הלחצן בסרגל הכלים מודגשים, הקש על Return, Enter,\n' + 74 | ' או על מקש הרווח כדי להפעיל את הפריט.

\n' + 75 | '\n' + 76 | '

ניווט בחלונות דו-שיח בלי כרטיסיות

\n' + 77 | '\n' + 78 | '

בחלונות דו-שיח בלי כרטיסיות, הרכיב האינטראקטיבי הראשון מקבל את המיקוד כאשר החלון נפתח.

\n' + 79 | '\n' + 80 | '

עבור בין רכיבים אינטראקטיביים בחלון על ידי הקשה על Tab או Shift+Tab.

\n' + 81 | '\n' + 82 | '

ניווט בחלונות דו-שיח עם כרטיסיות

\n' + 83 | '\n' + 84 | '

בחלונות דו-שיח עם כרטיסיות, הלחצן הראשון בתפריט מקבל את המיקוד כאשר החלון נפתח.

\n' + 85 | '\n' + 86 | '

עבור בין רכיבים אינטראקטיביים בחלון על ידי הקשה על Tab או\n' + 87 | ' Shift+Tab.

\n' + 88 | '\n' + 89 | '

עבור לכרטיסיה אחרת בחלון על ידי העברת המיקוד לתפריט הכרטיסיות והקשה על החץהמתאים\n' + 90 | ' כדי לעבור בין הכרטיסיות הזמינות.

\n'); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/help/js/i18n/keynav/hi.js: -------------------------------------------------------------------------------- 1 | tinymce.Resource.add('tinymce.html-i18n.help-keynav.hi', 2 | '

कीबोर्ड नेविगेशन शुरू करें

\n' + 3 | '\n' + 4 | '
\n' + 5 | '
मेन्यू बार पर फ़ोकस करें
\n' + 6 | '
Windows या Linux: Alt+F9
\n' + 7 | '
macOS: ⌥F9
\n' + 8 | '
टूलबार पर फ़ोकस करें
\n' + 9 | '
Windows या Linux: Alt+F10
\n' + 10 | '
macOS: ⌥F10
\n' + 11 | '
फ़ुटर पर फ़ोकस करें
\n' + 12 | '
Windows या Linux: Alt+F11
\n' + 13 | '
macOS: ⌥F11
\n' + 14 | '
प्रासंगिक टूलबार पर फ़ोकस करें
\n' + 15 | '
Windows, Linux या macOS: Ctrl+F9\n' + 16 | '
\n' + 17 | '\n' + 18 | '

नेविगेशन पहले UI आइटम पर शुरू होगा, जिसे हाइलाइट किया जाएगा या पहले आइटम के मामले में फ़ुटर तत्व पथ में\n' + 19 | ' रेखांकित किया जाएगा।

\n' + 20 | '\n' + 21 | '

UI सेक्शन के बीच नेविगेट करें

\n' + 22 | '\n' + 23 | '

एक UI सेक्शन से दूसरे सेक्शन में जाने के लिए, Tab दबाएं।

\n' + 24 | '\n' + 25 | '

एक UI सेक्शन से पिछले सेक्शन में जाने के लिए, Shift+Tab दबाएं।

\n' + 26 | '\n' + 27 | '

इन UI सेक्शन का Tab क्रम नीचे दिया गया है:

\n' + 28 | '\n' + 29 | '
    \n' + 30 | '
  1. मेन्यू बार
  2. \n' + 31 | '
  3. प्रत्येक टूलबार समूह
  4. \n' + 32 | '
  5. साइडबार
  6. \n' + 33 | '
  7. फ़ुटर में तत्व पथ
  8. \n' + 34 | '
  9. फ़ुटर में शब्द गणना टॉगल बटन
  10. \n' + 35 | '
  11. फ़ुटर में ब्रांडिंग लिंक
  12. \n' + 36 | '
  13. फ़ुटर में संपादक का आकार बदलने का हैंडल
  14. \n' + 37 | '
\n' + 38 | '\n' + 39 | '

अगर कोई UI सेक्शन मौजूद नहीं है, तो उसे छोड़ दिया जाता है।

\n' + 40 | '\n' + 41 | '

अगर फ़ुटर में कीबोर्ड नेविगेशन फ़ोकस है, और कोई दिखा देने वाला साइडबार नहीं है, तो Shift+Tab दबाने से\n' + 42 | ' फ़ोकस पहले टूलबार समूह पर चला जाता है, पिछले पर नहीं।

\n' + 43 | '\n' + 44 | '

UI सेक्शन के भीतर नेविगेट करें

\n' + 45 | '\n' + 46 | '

एक UI तत्व से दूसरे में जाने के लिए उपयुक्त ऐरो कुंजी दबाएं।

\n' + 47 | '\n' + 48 | '

बाएं और दाएं ऐरो कुंजियां

\n' + 49 | '\n' + 50 | '
    \n' + 51 | '
  • मेन्यू बार में मेन्यू के बीच ले जाती हैं।
  • \n' + 52 | '
  • मेन्यू में एक सब-मेन्यू खोलें।
  • \n' + 53 | '
  • टूलबार समूह में बटनों के बीच ले जाएं।
  • \n' + 54 | '
  • फ़ुटर के तत्व पथ में आइटम के बीच ले जाएं।
  • \n' + 55 | '
\n' + 56 | '\n' + 57 | '

नीचे और ऊपर ऐरो कुंजियां

\n' + 58 | '\n' + 59 | '
    \n' + 60 | '
  • मेन्यू में मेन्यू आइटम के बीच ले जाती हैं।
  • \n' + 61 | '
  • टूलबार पॉप-अप मेन्यू में आइटम के बीच ले जाएं।
  • \n' + 62 | '
\n' + 63 | '\n' + 64 | '

फ़ोकस वाले UI सेक्शन के भीतर ऐरो कुंजियां चलाती रहती हैं।

\n' + 65 | '\n' + 66 | '

कोई खुला मेन्यू, कोई खुला सब-मेन्यू या कोई खुला पॉप-अप मेन्यू बंद करने के लिए Esc कुंजी दबाएं।

\n' + 67 | '\n' + 68 | "

अगर मौजूदा फ़ोकस किसी विशेष UI सेक्शन के 'शीर्ष' पर है, तो Esc कुंजी दबाने से भी\n" + 69 | ' कीबोर्ड नेविगेशन पूरी तरह से बाहर हो जाता है।

\n' + 70 | '\n' + 71 | '

मेन्यू आइटम या टूलबार बटन निष्पादित करें

\n' + 72 | '\n' + 73 | '

जब वांछित मेन्यू आइटम या टूलबार बटन हाइलाइट किया जाता है, तो आइटम को निष्पादित करने के लिए Return, Enter,\n' + 74 | ' या Space bar दबाएं।

\n' + 75 | '\n' + 76 | '

गैर-टैब वाले डायलॉग पर नेविगेट करें

\n' + 77 | '\n' + 78 | '

गैर-टैब वाले डायलॉग में, डायलॉग खुलने पर पहला इंटरैक्टिव घटक फ़ोकस लेता है।

\n' + 79 | '\n' + 80 | '

Tab or Shift+Tab दबाकर इंटरैक्टिव डायलॉग घटकों के बीच नेविगेट करें।

\n' + 81 | '\n' + 82 | '

टैब किए गए डायलॉग पर नेविगेट करें

\n' + 83 | '\n' + 84 | '

टैब किए गए डायलॉग में, डायलॉग खुलने पर टैब मेन्यू में पहला बटन फ़ोकस लेता है।

\n' + 85 | '\n' + 86 | '

इस डायलॉग टैब के इंटरैक्टिव घटकों के बीच नेविगेट करने के लिए Tab या\n' + 87 | ' Shift+Tab दबाएं।

\n' + 88 | '\n' + 89 | '

टैब मेन्यू को फ़ोकस देकर और फिर उपलब्ध टैब में के बीच जाने के लिए उपयुक्त ऐरो\n' + 90 | ' कुंजी दबाकर दूसरे डायलॉग टैब पर स्विच करें।

\n'); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/help/js/i18n/keynav/ja.js: -------------------------------------------------------------------------------- 1 | tinymce.Resource.add('tinymce.html-i18n.help-keynav.ja', 2 | '

キーボード ナビゲーションの開始

\n' + 3 | '\n' + 4 | '
\n' + 5 | '
メニュー バーをフォーカス
\n' + 6 | '
Windows または Linux: Alt+F9
\n' + 7 | '
macOS: ⌥F9
\n' + 8 | '
ツール バーをフォーカス
\n' + 9 | '
Windows または Linux: Alt+F10
\n' + 10 | '
macOS: ⌥F10
\n' + 11 | '
フッターをフォーカス
\n' + 12 | '
Windows または Linux: Alt+F11
\n' + 13 | '
macOS: ⌥F11
\n' + 14 | '
コンテキスト ツール バーをフォーカス
\n' + 15 | '
Windows、Linux または macOS: Ctrl+F9\n' + 16 | '
\n' + 17 | '\n' + 18 | '

ナビゲーションは最初の UI 項目から開始され、強調表示されるか、フッターの要素パスにある最初の項目の場合は\n' + 19 | ' 下線が引かれます。

\n' + 20 | '\n' + 21 | '

UI セクション間の移動

\n' + 22 | '\n' + 23 | '

次の UI セクションに移動するには、Tab を押します。

\n' + 24 | '\n' + 25 | '

前の UI セクションに移動するには、Shift+Tab を押します。

\n' + 26 | '\n' + 27 | '

これらの UI セクションの Tab の順序:

\n' + 28 | '\n' + 29 | '
    \n' + 30 | '
  1. メニュー バー
  2. \n' + 31 | '
  3. 各ツール バー グループ
  4. \n' + 32 | '
  5. サイド バー
  6. \n' + 33 | '
  7. フッターの要素パス
  8. \n' + 34 | '
  9. フッターの単語数切り替えボタン
  10. \n' + 35 | '
  11. フッターのブランド リンク
  12. \n' + 36 | '
  13. フッターのエディター サイズ変更ハンドル
  14. \n' + 37 | '
\n' + 38 | '\n' + 39 | '

UI セクションが存在しない場合は、スキップされます。

\n' + 40 | '\n' + 41 | '

フッターにキーボード ナビゲーション フォーカスがあり、表示可能なサイド バーがない場合、Shift+Tab を押すと、\n' + 42 | ' フォーカスが最後ではなく最初のツール バー グループに移動します。

\n' + 43 | '\n' + 44 | '

UI セクション内の移動

\n' + 45 | '\n' + 46 | '

次の UI 要素に移動するには、適切な矢印キーを押します。

\n' + 47 | '\n' + 48 | '

左矢印右矢印のキー

\n' + 49 | '\n' + 50 | '
    \n' + 51 | '
  • メニュー バーのメニュー間で移動します。
  • \n' + 52 | '
  • メニュー内のサブメニューを開きます。
  • \n' + 53 | '
  • ツール バー グループのボタン間で移動します。
  • \n' + 54 | '
  • フッターの要素パスの項目間で移動します。
  • \n' + 55 | '
\n' + 56 | '\n' + 57 | '

下矢印上矢印のキー

\n' + 58 | '\n' + 59 | '
    \n' + 60 | '
  • メニュー内のメニュー項目間で移動します。
  • \n' + 61 | '
  • ツール バー ポップアップ メニュー内のメニュー項目間で移動します。
  • \n' + 62 | '
\n' + 63 | '\n' + 64 | '

矢印キーで、フォーカスされた UI セクション内で循環します。

\n' + 65 | '\n' + 66 | '

開いたメニュー、開いたサブメニュー、開いたポップアップ メニューを閉じるには、Esc キーを押します。

\n' + 67 | '\n' + 68 | '

現在のフォーカスが特定の UI セクションの「一番上」にある場合、Esc キーを押すと\n' + 69 | ' キーボード ナビゲーションも完全に閉じられます。

\n' + 70 | '\n' + 71 | '

メニュー項目またはツール バー ボタンの実行

\n' + 72 | '\n' + 73 | '

目的のメニュー項目やツール バー ボタンが強調表示されている場合、リターンEnter、\n' + 74 | ' またはスペース キーを押して項目を実行します。

\n' + 75 | '\n' + 76 | '

タブのないダイアログの移動

\n' + 77 | '\n' + 78 | '

タブのないダイアログでは、ダイアログが開くと最初の対話型コンポーネントがフォーカスされます。

\n' + 79 | '\n' + 80 | '

Tab または Shift+Tab を押して、対話型ダイアログ コンポーネント間で移動します。

\n' + 81 | '\n' + 82 | '

タブ付きダイアログの移動

\n' + 83 | '\n' + 84 | '

タブ付きダイアログでは、ダイアログが開くとタブ メニューの最初のボタンがフォーカスされます。

\n' + 85 | '\n' + 86 | '

Tab または\n' + 87 | ' Shift+Tab を押して、このダイアログ タブの対話型コンポーネント間で移動します。

\n' + 88 | '\n' + 89 | '

タブ メニューをフォーカスしてから適切な矢印キーを押して表示可能なタブを循環して、\n' + 90 | ' 別のダイアログに切り替えます。

\n'); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/help/js/i18n/keynav/ko_KR.js: -------------------------------------------------------------------------------- 1 | tinymce.Resource.add('tinymce.html-i18n.help-keynav.ko_KR', 2 | '

키보드 탐색 시작

\n' + 3 | '\n' + 4 | '
\n' + 5 | '
메뉴 모음 포커스 표시
\n' + 6 | '
Windows 또는 Linux: Alt+F9
\n' + 7 | '
macOS: ⌥F9
\n' + 8 | '
도구 모음 포커스 표시
\n' + 9 | '
Windows 또는 Linux: Alt+F10
\n' + 10 | '
macOS: ⌥F10
\n' + 11 | '
푸터 포커스 표시
\n' + 12 | '
Windows 또는 Linux: Alt+F11
\n' + 13 | '
macOS: ⌥F11
\n' + 14 | '
컨텍스트 도구 모음에 포커스 표시
\n' + 15 | '
Windows, Linux 또는 macOS: Ctrl+F9\n' + 16 | '
\n' + 17 | '\n' + 18 | '

첫 번째 UI 항목에서 탐색이 시작되며, 이때 첫 번째 항목이 강조 표시되거나 푸터 요소 경로에 있는\n' + 19 | ' 경우 밑줄 표시됩니다.

\n' + 20 | '\n' + 21 | '

UI 섹션 간 탐색

\n' + 22 | '\n' + 23 | '

한 UI 섹션에서 다음 UI 섹션으로 이동하려면 Tab(탭)을 누릅니다.

\n' + 24 | '\n' + 25 | '

한 UI 섹션에서 이전 UI 섹션으로 돌아가려면 Shift+Tab(시프트+탭)을 누릅니다.

\n' + 26 | '\n' + 27 | '

이 UI 섹션의 Tab(탭) 순서는 다음과 같습니다.

\n' + 28 | '\n' + 29 | '
    \n' + 30 | '
  1. 메뉴 바
  2. \n' + 31 | '
  3. 각 도구 모음 그룹
  4. \n' + 32 | '
  5. 사이드바
  6. \n' + 33 | '
  7. 푸터의 요소 경로
  8. \n' + 34 | '
  9. 푸터의 단어 수 토글 버튼
  10. \n' + 35 | '
  11. 푸터의 브랜딩 링크
  12. \n' + 36 | '
  13. 푸터의 에디터 크기 변경 핸들
  14. \n' + 37 | '
\n' + 38 | '\n' + 39 | '

UI 섹션이 없는 경우 건너뛰기합니다.

\n' + 40 | '\n' + 41 | '

푸터에 키보드 탐색 포커스가 있고 사이드바는 보이지 않는 경우 Shift+Tab(시프트+탭)을 누르면\n' + 42 | ' 포커스 표시가 마지막이 아닌 첫 번째 도구 모음 그룹으로 이동합니다.

\n' + 43 | '\n' + 44 | '

UI 섹션 내 탐색

\n' + 45 | '\n' + 46 | '

한 UI 요소에서 다음 UI 요소로 이동하려면 적절한 화살표 키를 누릅니다.

\n' + 47 | '\n' + 48 | '

왼쪽오른쪽 화살표 키의 용도:

\n' + 49 | '\n' + 50 | '
    \n' + 51 | '
  • 메뉴 모음에서 메뉴 항목 사이를 이동합니다.
  • \n' + 52 | '
  • 메뉴에서 하위 메뉴를 엽니다.
  • \n' + 53 | '
  • 도구 모음 그룹에서 버튼 사이를 이동합니다.
  • \n' + 54 | '
  • 푸터의 요소 경로에서 항목 간에 이동합니다.
  • \n' + 55 | '
\n' + 56 | '\n' + 57 | '

아래 화살표 키의 용도:

\n' + 58 | '\n' + 59 | '
    \n' + 60 | '
  • 메뉴에서 메뉴 항목 사이를 이동합니다.
  • \n' + 61 | '
  • 도구 모음 팝업 메뉴에서 메뉴 항목 사이를 이동합니다.
  • \n' + 62 | '
\n' + 63 | '\n' + 64 | '

화살표 키는 포커스 표시 UI 섹션 내에서 순환됩니다.

\n' + 65 | '\n' + 66 | '

열려 있는 메뉴, 열려 있는 하위 메뉴 또는 열려 있는 팝업 메뉴를 닫으려면 Esc 키를 누릅니다.

\n' + 67 | '\n' + 68 | "

현재 포커스 표시가 특정 UI 섹션 '상단'에 있는 경우 이때도 Esc 키를 누르면\n" + 69 | ' 키보드 탐색이 완전히 종료됩니다.

\n' + 70 | '\n' + 71 | '

메뉴 항목 또는 도구 모음 버튼 실행

\n' + 72 | '\n' + 73 | '

원하는 메뉴 항목 또는 도구 모음 버튼이 강조 표시되어 있을 때 Return(리턴), Enter(엔터),\n' + 74 | ' 또는 Space bar(스페이스바)를 눌러 해당 항목을 실행합니다.

\n' + 75 | '\n' + 76 | '

탭이 없는 대화 탐색

\n' + 77 | '\n' + 78 | '

탭이 없는 대화의 경우, 첫 번째 대화형 요소가 포커스 표시된 상태로 대화가 열립니다.

\n' + 79 | '\n' + 80 | '

대화형 요소들 사이를 이동할 때는 Tab(탭) 또는 Shift+Tab(시프트+탭)을 누릅니다.

\n' + 81 | '\n' + 82 | '

탭이 있는 대화 탐색

\n' + 83 | '\n' + 84 | '

탭이 있는 대화의 경우, 탭 메뉴에서 첫 번째 버튼이 포커스 표시된 상태로 대화가 열립니다.

\n' + 85 | '\n' + 86 | '

이 대화 탭의 대화형 요소들 사이를 이동할 때는 Tab(탭) 또는\n' + 87 | ' Shift+Tab(시프트+탭)을 누릅니다.

\n' + 88 | '\n' + 89 | '

다른 대화 탭으로 이동하려면 탭 메뉴를 포커스 표시한 다음 적절한 화살표\n' + 90 | ' 키를 눌러 사용 가능한 탭들을 지나 원하는 탭으로 이동합니다.

\n'); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/help/js/i18n/keynav/ms.js: -------------------------------------------------------------------------------- 1 | tinymce.Resource.add('tinymce.html-i18n.help-keynav.ms', 2 | '

Mulakan navigasi papan kekunci

\n' + 3 | '\n' + 4 | '
\n' + 5 | '
Fokus bar Menu
\n' + 6 | '
Windows atau Linux: Alt+F9
\n' + 7 | '
macOS: ⌥F9
\n' + 8 | '
Fokus Bar Alat
\n' + 9 | '
Windows atau Linux: Alt+F10
\n' + 10 | '
macOS: ⌥F10
\n' + 11 | '
Fokus pengaki
\n' + 12 | '
Windows atau Linux: Alt+F11
\n' + 13 | '
macOS: ⌥F11
\n' + 14 | '
Fokus bar alat kontekstual
\n' + 15 | '
Windows, Linux atau macOS: Ctrl+F9\n' + 16 | '
\n' + 17 | '\n' + 18 | '

Navigasi akan bermula pada item UI pertama, yang akan diserlahkan atau digaris bawah dalam saiz item pertama dalam\n' + 19 | ' laluan elemen Pengaki.

\n' + 20 | '\n' + 21 | '

Navigasi antara bahagian UI

\n' + 22 | '\n' + 23 | '

Untuk bergerak dari satu bahagian UI ke yang seterusnya, tekan Tab.

\n' + 24 | '\n' + 25 | '

Untuk bergerak dari satu bahagian UI ke yang sebelumnya, tekan Shift+Tab.

\n' + 26 | '\n' + 27 | '

Tertib Tab bahagian UI ini ialah:

\n' + 28 | '\n' + 29 | '
    \n' + 30 | '
  1. Bar menu
  2. \n' + 31 | '
  3. Setiap kumpulan bar alat
  4. \n' + 32 | '
  5. Bar sisi
  6. \n' + 33 | '
  7. Laluan elemen dalam pengaki
  8. \n' + 34 | '
  9. Butang togol kiraan perkataan dalam pengaki
  10. \n' + 35 | '
  11. Pautan penjenamaan dalam pengaki
  12. \n' + 36 | '
  13. Pemegang saiz semula editor dalam pengaki
  14. \n' + 37 | '
\n' + 38 | '\n' + 39 | '

Jika bahagian UI tidak wujud, ia dilangkau.

\n' + 40 | '\n' + 41 | '

Jika pengaki mempunyai fokus navigasi papan kekunci dan tiada bar sisi kelihatan, menekan Shift+Tab\n' + 42 | ' akan mengalihkan fokus ke kumpulan bar alat pertama, bukannya yang terakhir.

\n' + 43 | '\n' + 44 | '

Navigasi dalam bahagian UI

\n' + 45 | '\n' + 46 | '

Untuk bergerak dari satu elemen UI ke yang seterusnya, tekan kekunci Anak Panah yang bersesuaian.

\n' + 47 | '\n' + 48 | '

Kekunci anak panah Kiri dan Kanan

\n' + 49 | '\n' + 50 | '
    \n' + 51 | '
  • bergerak antara menu dalam bar menu.
  • \n' + 52 | '
  • membukan submenu dalam menu.
  • \n' + 53 | '
  • bergerak antara butang dalam kumpulan bar alat.
  • \n' + 54 | '
  • Laluan elemen dalam pengaki.
  • \n' + 55 | '
\n' + 56 | '\n' + 57 | '

Kekunci anak panah Bawah dan Atas

\n' + 58 | '\n' + 59 | '
    \n' + 60 | '
  • bergerak antara item menu dalam menu.
  • \n' + 61 | '
  • bergerak antara item dalam menu timbul bar alat.
  • \n' + 62 | '
\n' + 63 | '\n' + 64 | '

Kekunci Anak Panah berkitar dalam bahagian UI difokuskan.

\n' + 65 | '\n' + 66 | '

Untuk menutup menu buka, submenu terbuka atau menu timbul terbuka, tekan kekunci Esc.

\n' + 67 | '\n' + 68 | "

Jika fokus semasa berada di bahagian 'atas' bahagian UI tertentu, menekan kekunci Esc juga akan keluar daripada\n" + 69 | ' navigasi papan kekunci sepenuhnya.

\n' + 70 | '\n' + 71 | '

Laksanakan item menu atau butang bar alat

\n' + 72 | '\n' + 73 | '

Apabila item menu atau butang bar alat yang diinginkan diserlahkan, tekan Return, Enter,\n' + 74 | ' atau bar Space untuk melaksanakan item.

\n' + 75 | '\n' + 76 | '

Navigasi ke dialog tidak bertab

\n' + 77 | '\n' + 78 | '

Dalam dialog tidak bertab, komponen interaksi pertama difokuskan apabila dialog dibuka.

\n' + 79 | '\n' + 80 | '

Navigasi antara komponen dialog interaktif dengan menekan Tab atau Shift+Tab.

\n' + 81 | '\n' + 82 | '

Navigasi ke dialog bertab

\n' + 83 | '\n' + 84 | '

Dalam dialog bertab, butang pertama dalam menu tab difokuskan apabila dialog dibuka.

\n' + 85 | '\n' + 86 | '

Navigasi antara komponen interaktif tab dialog ini dengan menekan Tab atau\n' + 87 | ' Shift+Tab.

\n' + 88 | '\n' + 89 | '

Tukar kepada tab dialog lain dengan memfokuskan menu tab, kemudian menekan kekunci Anak Panah yang bersesuaian\n' + 90 | ' untuk berkitar menerusi tab yang tersedia.

\n'); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/help/js/i18n/keynav/sv_SE.js: -------------------------------------------------------------------------------- 1 | tinymce.Resource.add('tinymce.html-i18n.help-keynav.sv_SE', 2 | '

Påbörja tangentbordsnavigering

\n' + 3 | '\n' + 4 | '
\n' + 5 | '
Fokusera på menyraden
\n' + 6 | '
Windows eller Linux: Alt+F9
\n' + 7 | '
macOS: ⌥F9
\n' + 8 | '
Fokusera på verktygsraden
\n' + 9 | '
Windows eller Linux: Alt+F10
\n' + 10 | '
macOS: ⌥F10
\n' + 11 | '
Fokusera på verktygsraden
\n' + 12 | '
Windows eller Linux: Alt+F11
\n' + 13 | '
macOS: ⌥F11
\n' + 14 | '
Fokusera på en snabbverktygsrad
\n' + 15 | '
Windows, Linux eller macOS: Ctrl+F9\n' + 16 | '
\n' + 17 | '\n' + 18 | '

Navigeringen börjar vid det första gränssnittsobjektet, vilket är markerat eller understruket om det gäller det första objektet i\n' + 19 | ' sidfotens elementsökväg.

\n' + 20 | '\n' + 21 | '

Navigera mellan UI-avsnitt

\n' + 22 | '\n' + 23 | '

Flytta från ett UI-avsnitt till nästa genom att trycka på Tabb.

\n' + 24 | '\n' + 25 | '

Flytta från ett UI-avsnitt till det föregående genom att trycka på Skift+Tabb.

\n' + 26 | '\n' + 27 | '

Tabb-ordningen för dessa UI-avsnitt är:

\n' + 28 | '\n' + 29 | '
    \n' + 30 | '
  1. Menyrad
  2. \n' + 31 | '
  3. Varje verktygsradsgrupp
  4. \n' + 32 | '
  5. Sidoruta
  6. \n' + 33 | '
  7. Elementsökväg i sidfoten
  8. \n' + 34 | '
  9. Växlingsknapp för ordantal i sidfoten
  10. \n' + 35 | '
  11. Varumärkeslänk i sidfoten
  12. \n' + 36 | '
  13. Storlekshandtag för redigeraren i sidfoten
  14. \n' + 37 | '
\n' + 38 | '\n' + 39 | '

Om ett UI-avsnitt inte finns hoppas det över.

\n' + 40 | '\n' + 41 | '

Om sidfoten har fokus på tangentbordsnavigering, och det inte finns någon synlig sidoruta, flyttas fokus till den första verktygsradsgruppen\n' + 42 | ' när du trycker på Skift+Tabb, inte till den sista.

\n' + 43 | '\n' + 44 | '

Navigera i UI-avsnitt

\n' + 45 | '\n' + 46 | '

Flytta från ett UI-element till nästa genom att trycka på motsvarande piltangent.

\n' + 47 | '\n' + 48 | '

Vänsterpil och högerpil

\n' + 49 | '\n' + 50 | '
    \n' + 51 | '
  • flytta mellan menyer på menyraden.
  • \n' + 52 | '
  • öppna en undermeny på en meny.
  • \n' + 53 | '
  • flytta mellan knappar i en verktygsradgrupp.
  • \n' + 54 | '
  • flytta mellan objekt i sidfotens elementsökväg.
  • \n' + 55 | '
\n' + 56 | '\n' + 57 | '

Nedpil och uppil

\n' + 58 | '\n' + 59 | '
    \n' + 60 | '
  • flytta mellan menyalternativ på en meny.
  • \n' + 61 | '
  • flytta mellan alternativ på en popup-meny på verktygsraden.
  • \n' + 62 | '
\n' + 63 | '\n' + 64 | '

Piltangenterna cirkulerar inom det fokuserade UI-avsnittet.

\n' + 65 | '\n' + 66 | '

Tryck på Esc-tangenten om du vill stänga en öppen meny, undermeny eller popup-meny.

\n' + 67 | '\n' + 68 | '

Om det aktuella fokuset är högst upp i ett UI-avsnitt avlutas även tangentbordsnavigeringen helt när\n' + 69 | ' du trycker på Esc-tangenten.

\n' + 70 | '\n' + 71 | '

Köra ett menyalternativ eller en verktygfältsknapp

\n' + 72 | '\n' + 73 | '

När menyalternativet eller verktygsradsknappen är markerad trycker du på Retur, Enter\n' + 74 | ' eller blanksteg för att köra alternativet.

\n' + 75 | '\n' + 76 | '

Navigera i dialogrutor utan flikar

\n' + 77 | '\n' + 78 | '

I dialogrutor utan flikar är den första interaktiva komponenten i fokus när dialogrutan öppnas.

\n' + 79 | '\n' + 80 | '

Navigera mellan interaktiva dialogkomponenter genom att trycka på Tabb eller Skift+Tabb.

\n' + 81 | '\n' + 82 | '

Navigera i dialogrutor med flikar

\n' + 83 | '\n' + 84 | '

I dialogrutor utan flikar är den första knappen på flikmenyn i fokus när dialogrutan öppnas.

\n' + 85 | '\n' + 86 | '

Navigera mellan interaktiva komponenter på dialogrutefliken genom att trycka på Tabb eller\n' + 87 | ' Skift+Tabb.

\n' + 88 | '\n' + 89 | '

Växla till en annan dialogruta genom att fokusera på flikmenyn och sedan trycka på motsvarande piltangent\n' + 90 | ' för att cirkulera mellan de tillgängliga flikarna.

\n'); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/help/js/i18n/keynav/th_TH.js: -------------------------------------------------------------------------------- 1 | tinymce.Resource.add('tinymce.html-i18n.help-keynav.th_TH', 2 | '

เริ่มต้นการนำทางด้วยแป้นพิมพ์

\n' + 3 | '\n' + 4 | '
\n' + 5 | '
โฟกัสที่แถบเมนู
\n' + 6 | '
Windows หรือ Linux: Alt+F9
\n' + 7 | '
macOS: ⌥F9
\n' + 8 | '
โฟกัสที่แถบเครื่องมือ
\n' + 9 | '
Windows หรือ Linux: Alt+F10
\n' + 10 | '
macOS: ⌥F10
\n' + 11 | '
โฟกัสที่ส่วนท้าย
\n' + 12 | '
Windows หรือ Linux: Alt+F11
\n' + 13 | '
macOS: ⌥F11
\n' + 14 | '
โฟกัสที่แถบเครื่องมือตามบริบท
\n' + 15 | '
Windows, Linux หรือ macOS: Ctrl+F9\n' + 16 | '
\n' + 17 | '\n' + 18 | '

การนำทางจะเริ่มที่รายการ UI แรก ซึ่งจะมีการไฮไลต์หรือขีดเส้นใต้ไว้ในกรณีที่รายการแรกอยู่ใน\n' + 19 | ' พาธองค์ประกอบส่วนท้าย

\n' + 20 | '\n' + 21 | '

การนำทางระหว่างส่วนต่างๆ ของ UI

\n' + 22 | '\n' + 23 | '

ในการย้ายจากส่วน UI หนึ่งไปยังส่วนถัดไป ให้กด Tab

\n' + 24 | '\n' + 25 | '

ในการย้ายจากส่วน UI หนึ่งไปยังส่วนก่อนหน้า ให้กด Shift+Tab

\n' + 26 | '\n' + 27 | '

ลำดับแท็บของส่วนต่างๆ ของ UI คือ:

\n' + 28 | '\n' + 29 | '
    \n' + 30 | '
  1. แถบเมนู
  2. \n' + 31 | '
  3. แต่ละกลุ่มแถบเครื่องมือ
  4. \n' + 32 | '
  5. แถบข้าง
  6. \n' + 33 | '
  7. พาธองค์ประกอบในส่วนท้าย
  8. \n' + 34 | '
  9. ปุ่มสลับเปิด/ปิดจำนวนคำในส่วนท้าย
  10. \n' + 35 | '
  11. ลิงก์ชื่อแบรนด์ในส่วนท้าย
  12. \n' + 36 | '
  13. จุดจับปรับขนาดของตัวแก้ไขในส่วนท้าย
  14. \n' + 37 | '
\n' + 38 | '\n' + 39 | '

หากส่วน UI ไม่ปรากฏ แสดงว่าถูกข้ามไป

\n' + 40 | '\n' + 41 | '

หากส่วนท้ายมีการโฟกัสการนำทางแป้นพิมพ์และไม่มีแถบข้างปรากฏ การกด Shift+Tab\n' + 42 | ' จะย้ายการโฟกัสไปที่กลุ่มแถบเครื่องมือแรก ไม่ใช่สุดท้าย

\n' + 43 | '\n' + 44 | '

การนำทางภายในส่วนต่างๆ ของ UI

\n' + 45 | '\n' + 46 | '

ในการย้ายจากองค์ประกอบ UI หนึ่งไปยังองค์ประกอบส่วนถัดไป ให้กดปุ่มลูกศรที่เหมาะสม

\n' + 47 | '\n' + 48 | '

ปุ่มลูกศรซ้ายและขวา

\n' + 49 | '\n' + 50 | '
    \n' + 51 | '
  • ย้ายไปมาระหว่างเมนูต่างๆ ในแถบเมนู
  • \n' + 52 | '
  • เปิดเมนูย่อยในเมนู
  • \n' + 53 | '
  • ย้ายไปมาระหว่างปุ่มต่างๆ ในกลุ่มแถบเครื่องมือ
  • \n' + 54 | '
  • ย้ายไปมาระหว่างรายการต่างๆ ในพาธองค์ประกอบของส่วนท้าย
  • \n' + 55 | '
\n' + 56 | '\n' + 57 | '

ปุ่มลูกศรลงและขึ้น

\n' + 58 | '\n' + 59 | '
    \n' + 60 | '
  • ย้ายไปมาระหว่างรายการเมนูต่างๆ ในเมนู
  • \n' + 61 | '
  • ย้ายไปมาระหว่างรายการต่างๆ ในเมนูป๊อบอัพแถบเครื่องมือ
  • \n' + 62 | '
\n' + 63 | '\n' + 64 | '

ปุ่มลูกศรจะเลื่อนไปมาภายในส่วน UI ที่โฟกัส

\n' + 65 | '\n' + 66 | '

ในการปิดเมนูที่เปิดอยู่ เมนูย่อยที่เปิดอยู่ หรือเมนูป๊อบอัพที่เปิดอยู่ ให้กดปุ่ม Esc

\n' + 67 | '\n' + 68 | '

หากโฟกัสปัจจุบันอยู่ที่ ‘ด้านบนสุด’ ของส่วน UI เฉพาะ การกดปุ่ม Esc จะทำให้ออกจาก\n' + 69 | ' การนำทางด้วยแป้นพิมพ์ทั้งหมดเช่นกัน

\n' + 70 | '\n' + 71 | '

การดำเนินการรายการเมนูหรือปุ่มในแถบเครื่องมือ

\n' + 72 | '\n' + 73 | '

เมื่อไฮไลต์รายการเมนูหรือปุ่มในแถบเครื่องมือที่ต้องการ ให้กด Return, Enter\n' + 74 | ' หรือ Space bar เพื่อดำเนินการรายการดังกล่าว

\n' + 75 | '\n' + 76 | '

การนำทางสำหรับกล่องโต้ตอบที่ไม่อยู่ในแท็บ

\n' + 77 | '\n' + 78 | '

ในกล่องโต้ตอบที่ไม่อยู่ในแท็บ จะโฟกัสที่ส่วนประกอบเชิงโต้ตอบแรกเมื่อกล่องโต้ตอบเปิด

\n' + 79 | '\n' + 80 | '

นำทางระหว่างส่วนประกอบเชิงโต้ตอบต่างๆ ของกล่องโต้ตอบ โดยการกด Tab หรือ Shift+Tab

\n' + 81 | '\n' + 82 | '

การนำทางสำหรับกล่องโต้ตอบที่อยู่ในแท็บ

\n' + 83 | '\n' + 84 | '

ในกล่องโต้ตอบที่อยู่ในแท็บ จะโฟกัสที่ปุ่มแรกในเมนูแท็บเมื่อกล่องโต้ตอบเปิด

\n' + 85 | '\n' + 86 | '

นำทางระหว่างส่วนประกอบเชิงโต้ตอบต่างๆ ของแท็บกล่องโต้ตอบนี้โดยการกด Tab หรือ\n' + 87 | ' Shift+Tab

\n' + 88 | '\n' + 89 | '

สลับไปยังแท็บกล่องโต้ตอบอื่นโดยการเลือกโฟกัสที่เมนูแท็บ แล้วกดปุ่มลูกศรที่เหมาะสม\n' + 90 | ' เพื่อเลือกแท็บที่ใช้ได้

\n'); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/help/js/i18n/keynav/zh_CN.js: -------------------------------------------------------------------------------- 1 | tinymce.Resource.add('tinymce.html-i18n.help-keynav.zh_CN', 2 | '

开始键盘导航

\n' + 3 | '\n' + 4 | '
\n' + 5 | '
聚焦于菜单栏
\n' + 6 | '
Windows 或 Linux:Alt+F9
\n' + 7 | '
macOS:⌥F9
\n' + 8 | '
聚焦于工具栏
\n' + 9 | '
Windows 或 Linux:Alt+F10
\n' + 10 | '
macOS:⌥F10
\n' + 11 | '
聚焦于页脚
\n' + 12 | '
Windows 或 Linux:Alt+F11
\n' + 13 | '
macOS:⌥F11
\n' + 14 | '
聚焦于上下文工具栏
\n' + 15 | '
Windows、Linux 或 macOS:Ctrl+F9\n' + 16 | '
\n' + 17 | '\n' + 18 | '

导航将在第一个 UI 项上开始,其中突出显示该项,或者对于页脚元素路径中的第一项,将为其添加下划线。

\n' + 19 | '\n' + 20 | '

在 UI 部分之间导航

\n' + 21 | '\n' + 22 | '

要从一个 UI 部分移至下一个,请按 Tab

\n' + 23 | '\n' + 24 | '

要从一个 UI 部分移至上一个,请按 Shift+Tab

\n' + 25 | '\n' + 26 | '

这些 UI 部分的 Tab 顺序为:

\n' + 27 | '\n' + 28 | '
    \n' + 29 | '
  1. 菜单栏
  2. \n' + 30 | '
  3. 每个工具栏组
  4. \n' + 31 | '
  5. 边栏
  6. \n' + 32 | '
  7. 页脚中的元素路径
  8. \n' + 33 | '
  9. 页脚中的字数切换按钮
  10. \n' + 34 | '
  11. 页脚中的品牌链接
  12. \n' + 35 | '
  13. 页脚中的编辑器调整大小图柄
  14. \n' + 36 | '
\n' + 37 | '\n' + 38 | '

如果不存在某个 UI 部分,则跳过它。

\n' + 39 | '\n' + 40 | '

如果键盘导航焦点在页脚,并且没有可见的边栏,则按 Shift+Tab 将焦点移至第一个工具栏组而非最后一个。

\n' + 41 | '\n' + 42 | '

在 UI 部分内导航

\n' + 43 | '\n' + 44 | '

要从一个 UI 元素移至下一个,请按相应的箭头键。

\n' + 45 | '\n' + 46 | '

箭头键

\n' + 47 | '\n' + 48 | '
    \n' + 49 | '
  • 在菜单栏中的菜单之间移动。
  • \n' + 50 | '
  • 打开菜单中的子菜单。
  • \n' + 51 | '
  • 在工具栏组中的按钮之间移动。
  • \n' + 52 | '
  • 在页脚的元素路径中的各项之间移动。
  • \n' + 53 | '
\n' + 54 | '\n' + 55 | '

箭头键

\n' + 56 | '\n' + 57 | '
    \n' + 58 | '
  • 在菜单中的菜单项之间移动。
  • \n' + 59 | '
  • 在工具栏弹出菜单中的各项之间移动。
  • \n' + 60 | '
\n' + 61 | '\n' + 62 | '

箭头键在具有焦点的 UI 部分内循环。

\n' + 63 | '\n' + 64 | '

要关闭打开的菜单、打开的子菜单或打开的弹出菜单,请按 Esc 键。

\n' + 65 | '\n' + 66 | '

如果当前的焦点在特定 UI 部分的“顶部”,则按 Esc 键还将完全退出键盘导航。

\n' + 67 | '\n' + 68 | '

执行菜单项或工具栏按钮

\n' + 69 | '\n' + 70 | '

当突出显示所需的菜单项或工具栏按钮时,按 ReturnEnter空格以执行该项。

\n' + 71 | '\n' + 72 | '

在非标签页式对话框中导航

\n' + 73 | '\n' + 74 | '

在非标签页式对话框中,当对话框打开时,第一个交互组件获得焦点。

\n' + 75 | '\n' + 76 | '

通过按 TabShift+Tab,在交互对话框组件之间导航。

\n' + 77 | '\n' + 78 | '

在标签页式对话框中导航

\n' + 79 | '\n' + 80 | '

在标签页式对话框中,当对话框打开时,标签页菜单中的第一个按钮获得焦点。

\n' + 81 | '\n' + 82 | '

通过按 TabShift+Tab,在此对话框的交互组件之间导航。

\n' + 83 | '\n' + 84 | '

通过将焦点移至另一对话框标签页的菜单,然后按相应的箭头键以在可用的标签页间循环,从而切换到该对话框标签页。

\n'); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/help/js/i18n/keynav/zh_TW.js: -------------------------------------------------------------------------------- 1 | tinymce.Resource.add('tinymce.html-i18n.help-keynav.zh_TW', 2 | '

開始鍵盤瀏覽

\n' + 3 | '\n' + 4 | '
\n' + 5 | '
跳至功能表列
\n' + 6 | '
Windows 或 Linux:Alt+F9
\n' + 7 | '
macOS:⌥F9
\n' + 8 | '
跳至工具列
\n' + 9 | '
Windows 或 Linux:Alt+F10
\n' + 10 | '
macOS:⌥F10
\n' + 11 | '
跳至頁尾
\n' + 12 | '
Windows 或 Linux:Alt+F11
\n' + 13 | '
macOS:⌥F11
\n' + 14 | '
跳至關聯式工具列
\n' + 15 | '
Windows、Linux 或 macOS:Ctrl+F9\n' + 16 | '
\n' + 17 | '\n' + 18 | '

瀏覽會從第一個 UI 項目開始,該項目會反白顯示,但如果是「頁尾」元素路徑的第一項,\n' + 19 | ' 則加底線。

\n' + 20 | '\n' + 21 | '

在 UI 區段之間瀏覽

\n' + 22 | '\n' + 23 | '

從 UI 區段移至下一個,請按 Tab

\n' + 24 | '\n' + 25 | '

從 UI 區段移回上一個,請按 Shift+Tab

\n' + 26 | '\n' + 27 | '

這些 UI 區段的 Tab 順序如下:

\n' + 28 | '\n' + 29 | '
    \n' + 30 | '
  1. 功能表列
  2. \n' + 31 | '
  3. 各個工具列群組
  4. \n' + 32 | '
  5. 側邊欄
  6. \n' + 33 | '
  7. 頁尾中的元素路徑
  8. \n' + 34 | '
  9. 頁尾中字數切換按鈕
  10. \n' + 35 | '
  11. 頁尾中的品牌連結
  12. \n' + 36 | '
  13. 頁尾中編輯器調整大小控點
  14. \n' + 37 | '
\n' + 38 | '\n' + 39 | '

如果 UI 區段未顯示,表示已略過該區段。

\n' + 40 | '\n' + 41 | '

如果鍵盤瀏覽跳至頁尾,但沒有顯示側邊欄,則按下 Shift+Tab\n' + 42 | ' 會跳至第一個工具列群組,而不是最後一個。

\n' + 43 | '\n' + 44 | '

在 UI 區段之內瀏覽

\n' + 45 | '\n' + 46 | '

在兩個 UI 元素之間移動,請按適當的方向鍵。

\n' + 47 | '\n' + 48 | '

向左向右方向鍵

\n' + 49 | '\n' + 50 | '
    \n' + 51 | '
  • 在功能表列中的功能表之間移動。
  • \n' + 52 | '
  • 開啟功能表中的子功能表。
  • \n' + 53 | '
  • 在工具列群組中的按鈕之間移動。
  • \n' + 54 | '
  • 在頁尾的元素路徑中項目之間移動。
  • \n' + 55 | '
\n' + 56 | '\n' + 57 | '

向下向上方向鍵

\n' + 58 | '\n' + 59 | '
    \n' + 60 | '
  • 在功能表中的功能表項目之間移動。
  • \n' + 61 | '
  • 在工具列快顯功能表中的項目之間移動。
  • \n' + 62 | '
\n' + 63 | '\n' + 64 | '

方向鍵會在所跳至 UI 區段之內循環。

\n' + 65 | '\n' + 66 | '

若要關閉已開啟的功能表、已開啟的子功能表,或已開啟的快顯功能表,請按 Esc 鍵。

\n' + 67 | '\n' + 68 | '

如果目前已跳至特定 UI 區段的「頂端」,則按 Esc 鍵也會結束\n' + 69 | ' 整個鍵盤瀏覽。

\n' + 70 | '\n' + 71 | '

執行功能表列項目或工具列按鈕

\n' + 72 | '\n' + 73 | '

當想要的功能表項目或工具列按鈕已反白顯示時,按 ReturnEnter、\n' + 74 | ' 或空白鍵即可執行該項目。

\n' + 75 | '\n' + 76 | '

瀏覽非索引標籤式對話方塊

\n' + 77 | '\n' + 78 | '

在非索引標籤式對話方塊中,開啟對話方塊時會跳至第一個互動元件。

\n' + 79 | '\n' + 80 | '

TabShift+Tab 即可在互動式對話方塊元件之間瀏覽。

\n' + 81 | '\n' + 82 | '

瀏覽索引標籤式對話方塊

\n' + 83 | '\n' + 84 | '

在索引標籤式對話方塊中,開啟對話方塊時會跳至索引標籤式功能表中的第一個按鈕。

\n' + 85 | '\n' + 86 | '

若要在此對話方塊的互動式元件之間瀏覽,請按 Tab 或\n' + 87 | ' Shift+Tab

\n' + 88 | '\n' + 89 | '

先跳至索引標籤式功能表,然後按適當的方向鍵,即可切換至另一個對話方塊索引標籤,\n' + 90 | ' 以循環瀏覽可用的索引標籤。

\n'); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/importcss/plugin.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TinyMCE version 6.8.3 (2024-02-08) 3 | */ 4 | !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(s=r=e,(o=String).prototype.isPrototypeOf(s)||(null===(n=r.constructor)||void 0===n?void 0:n.name)===o.name)?"string":t;var s,r,o,n})(t)===e,s=t("string"),r=t("object"),o=t("array"),n=("function",e=>"function"==typeof e);var c=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),i=tinymce.util.Tools.resolve("tinymce.EditorManager"),l=tinymce.util.Tools.resolve("tinymce.Env"),a=tinymce.util.Tools.resolve("tinymce.util.Tools");const p=e=>t=>t.options.get(e),u=p("importcss_merge_classes"),m=p("importcss_exclusive"),f=p("importcss_selector_converter"),y=p("importcss_selector_filter"),d=p("importcss_groups"),h=p("importcss_append"),_=p("importcss_file_filter"),g=p("skin"),v=p("skin_url"),b=Array.prototype.push,x=/^\.(?:ephox|tiny-pageembed|mce)(?:[.-]+\w+)+$/,T=e=>s(e)?t=>-1!==t.indexOf(e):e instanceof RegExp?t=>e.test(t):e,S=(e,t)=>{let s={};const r=/^(?:([a-z0-9\-_]+))?(\.[a-z0-9_\-\.]+)$/i.exec(t);if(!r)return;const o=r[1],n=r[2].substr(1).split(".").join(" "),c=a.makeMap("a,img");return r[1]?(s={title:t},e.schema.getTextBlockElements()[o]?s.block=o:e.schema.getBlockElements()[o]||c[o.toLowerCase()]?s.selector=o:s.inline=o):r[2]&&(s={inline:"span",title:t.substr(1),classes:n}),u(e)?s.classes=n:s.attributes={class:n},s},k=(e,t)=>null===t||m(e),w=e=>{e.on("init",(()=>{const t=(()=>{const e=[],t=[],s={};return{addItemToGroup:(e,r)=>{s[e]?s[e].push(r):(t.push(e),s[e]=[r])},addItem:t=>{e.push(t)},toFormats:()=>{return(r=t,n=e=>{const t=s[e];return 0===t.length?[]:[{title:e,items:t}]},(e=>{const t=[];for(let s=0,r=e.length;s{const s=e.length,r=new Array(s);for(let o=0;oa.map(e,(e=>a.extend({},e,{original:e,selectors:{},filter:T(e.filter)}))))(d(e)),u=(t,s)=>{if(((e,t,s,r)=>!(k(e,s)?t in r:t in s.selectors))(e,t,s,r)){((e,t,s,r)=>{k(e,s)?r[t]=!0:s.selectors[t]=!0})(e,t,s,r);const o=((e,t,s,r)=>{let o;const n=f(e);return o=r&&r.selector_converter?r.selector_converter:n||(()=>S(e,s)),o.call(t,s,r)})(e,e.plugins.importcss,t,s);if(o){const t=o.name||c.DOM.uniqueId();return e.formatter.register(t,o),{title:o.title,format:t}}}return null};a.each(((e,t,r)=>{const o=[],n={},c=(t,n)=>{let p,u=t.href;if(u=(e=>{const t=l.cacheSuffix;return s(e)&&(e=e.replace("?"+t,"").replace("&"+t,"")),e})(u),u&&(!r||r(u,n))&&!((e,t)=>{const s=g(e);if(s){const r=v(e),o=r?e.documentBaseURI.toAbsolute(r):i.baseURL+"/skins/ui/"+s,n=i.baseURL+"/skins/content/";return t===o+"/content"+(e.inline?".inline":"")+".min.css"||-1!==t.indexOf(n)}return!1})(e,u)){a.each(t.imports,(e=>{c(e,!0)}));try{p=t.cssRules||t.rules}catch(e){}a.each(p,(e=>{e.styleSheet&&e.styleSheet?c(e.styleSheet,!0):e.selectorText&&a.each(e.selectorText.split(","),(e=>{o.push(a.trim(e))}))}))}};a.each(e.contentCSS,(e=>{n[e]=!0})),r||(r=(e,t)=>t||n[e]);try{a.each(t.styleSheets,(e=>{c(e)}))}catch(e){}return o})(e,e.getDoc(),T(_(e))),(e=>{if(!x.test(e)&&(!n||n(e))){const s=((e,t)=>a.grep(e,(e=>!e.filter||e.filter(t))))(p,e);if(s.length>0)a.each(s,(s=>{const r=u(e,s);r&&t.addItemToGroup(s.title,r)}));else{const s=u(e,null);s&&t.addItem(s)}}}));const m=t.toFormats();e.dispatch("addStyleModifications",{items:m,replace:!h(e)})}))};e.add("importcss",(e=>((e=>{const t=e.options.register,o=e=>s(e)||n(e)||r(e);t("importcss_merge_classes",{processor:"boolean",default:!0}),t("importcss_exclusive",{processor:"boolean",default:!0}),t("importcss_selector_converter",{processor:"function"}),t("importcss_selector_filter",{processor:o}),t("importcss_file_filter",{processor:o}),t("importcss_groups",{processor:"object[]"}),t("importcss_append",{processor:"boolean",default:!1})})(e),w(e),(e=>({convertSelectorToFormat:t=>S(e,t)}))(e))))}(); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/insertdatetime/plugin.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TinyMCE version 6.8.3 (2024-02-08) 3 | */ 4 | !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>t.options.get(e),a=t("insertdatetime_dateformat"),n=t("insertdatetime_timeformat"),r=t("insertdatetime_formats"),s=t("insertdatetime_element"),i="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),o="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),l="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),m="January February March April May June July August September October November December".split(" "),c=(e,t)=>{if((e=""+e).length(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=t.replace("%D","%m/%d/%Y")).replace("%r","%I:%M:%S %p")).replace("%Y",""+a.getFullYear())).replace("%y",""+a.getYear())).replace("%m",c(a.getMonth()+1,2))).replace("%d",c(a.getDate(),2))).replace("%H",""+c(a.getHours(),2))).replace("%M",""+c(a.getMinutes(),2))).replace("%S",""+c(a.getSeconds(),2))).replace("%I",""+((a.getHours()+11)%12+1))).replace("%p",a.getHours()<12?"AM":"PM")).replace("%B",""+e.translate(m[a.getMonth()]))).replace("%b",""+e.translate(l[a.getMonth()]))).replace("%A",""+e.translate(o[a.getDay()]))).replace("%a",""+e.translate(i[a.getDay()]))).replace("%%","%"),u=(e,t)=>{if(s(e)){const a=d(e,t);let n;n=/%[HMSIp]/.test(t)?d(e,"%Y-%m-%dT%H:%M"):d(e,"%Y-%m-%d");const r=e.dom.getParent(e.selection.getStart(),"time");r?((e,t,a,n)=>{const r=e.dom.create("time",{datetime:a},n);e.dom.replace(r,t),e.selection.select(r,!0),e.selection.collapse(!1)})(e,r,n,a):e.insertContent('")}else e.insertContent(d(e,t))};var p=tinymce.util.Tools.resolve("tinymce.util.Tools");const g=e=>t=>{const a=()=>{t.setEnabled(e.selection.isEditable())};return e.on("NodeChange",a),a(),()=>{e.off("NodeChange",a)}};e.add("insertdatetime",(e=>{(e=>{const t=e.options.register;t("insertdatetime_dateformat",{processor:"string",default:e.translate("%Y-%m-%d")}),t("insertdatetime_timeformat",{processor:"string",default:e.translate("%H:%M:%S")}),t("insertdatetime_formats",{processor:"string[]",default:["%H:%M:%S","%Y-%m-%d","%I:%M:%S %p","%D"]}),t("insertdatetime_element",{processor:"boolean",default:!1})})(e),(e=>{e.addCommand("mceInsertDate",((t,n)=>{u(e,null!=n?n:a(e))})),e.addCommand("mceInsertTime",((t,a)=>{u(e,null!=a?a:n(e))}))})(e),(e=>{const t=r(e),a=(e=>{let t=e;return{get:()=>t,set:e=>{t=e}}})((e=>{const t=r(e);return t.length>0?t[0]:n(e)})(e)),s=t=>e.execCommand("mceInsertDate",!1,t);e.ui.registry.addSplitButton("insertdatetime",{icon:"insert-time",tooltip:"Insert date/time",select:e=>e===a.get(),fetch:a=>{a(p.map(t,(t=>({type:"choiceitem",text:d(e,t),value:t}))))},onAction:e=>{s(a.get())},onItemAction:(e,t)=>{a.set(t),s(t)},onSetup:g(e)});const i=e=>()=>{a.set(e),s(e)};e.ui.registry.addNestedMenuItem("insertdatetime",{icon:"insert-time",text:"Date/time",getSubmenuItems:()=>p.map(t,(t=>({type:"menuitem",text:d(e,t),onAction:i(t)}))),onSetup:g(e)})})(e)}))}(); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/nonbreaking/plugin.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TinyMCE version 6.8.3 (2024-02-08) 3 | */ 4 | !function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=n=>e=>typeof e===n,o=e("boolean"),a=e("number"),t=n=>e=>e.options.get(n),i=t("nonbreaking_force_tab"),s=t("nonbreaking_wrap"),r=(n,e)=>{let o="";for(let a=0;a{const o=s(n)||n.plugins.visualchars?`${r(" ",e)}`:r(" ",e);n.undoManager.transact((()=>n.insertContent(o)))};var l=tinymce.util.Tools.resolve("tinymce.util.VK");const u=n=>e=>{const o=()=>{e.setEnabled(n.selection.isEditable())};return n.on("NodeChange",o),o(),()=>{n.off("NodeChange",o)}};n.add("nonbreaking",(n=>{(n=>{const e=n.options.register;e("nonbreaking_force_tab",{processor:n=>o(n)?{value:n?3:0,valid:!0}:a(n)?{value:n,valid:!0}:{valid:!1,message:"Must be a boolean or number."},default:!1}),e("nonbreaking_wrap",{processor:"boolean",default:!0})})(n),(n=>{n.addCommand("mceNonBreaking",(()=>{c(n,1)}))})(n),(n=>{const e=()=>n.execCommand("mceNonBreaking");n.ui.registry.addButton("nonbreaking",{icon:"non-breaking",tooltip:"Nonbreaking space",onAction:e,onSetup:u(n)}),n.ui.registry.addMenuItem("nonbreaking",{icon:"non-breaking",text:"Nonbreaking space",onAction:e,onSetup:u(n)})})(n),(n=>{const e=i(n);e>0&&n.on("keydown",(o=>{if(o.keyCode===l.TAB&&!o.isDefaultPrevented()){if(o.shiftKey)return;o.preventDefault(),o.stopImmediatePropagation(),c(n,e)}}))})(n)}))}(); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/pagebreak/plugin.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TinyMCE version 6.8.3 (2024-02-08) 3 | */ 4 | !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=tinymce.util.Tools.resolve("tinymce.Env");const t=e=>a=>a.options.get(e),n=t("pagebreak_separator"),o=t("pagebreak_split_block"),r="mce-pagebreak",s=e=>{const t=``;return e?`

${t}

`:t},c=e=>a=>{const t=()=>{a.setEnabled(e.selection.isEditable())};return e.on("NodeChange",t),t(),()=>{e.off("NodeChange",t)}};e.add("pagebreak",(e=>{(e=>{const a=e.options.register;a("pagebreak_separator",{processor:"string",default:"\x3c!-- pagebreak --\x3e"}),a("pagebreak_split_block",{processor:"boolean",default:!1})})(e),(e=>{e.addCommand("mcePageBreak",(()=>{e.insertContent(s(o(e)))}))})(e),(e=>{const a=()=>e.execCommand("mcePageBreak");e.ui.registry.addButton("pagebreak",{icon:"page-break",tooltip:"Page break",onAction:a,onSetup:c(e)}),e.ui.registry.addMenuItem("pagebreak",{text:"Page break",icon:"page-break",onAction:a,onSetup:c(e)})})(e),(e=>{const a=n(e),t=()=>o(e),c=new RegExp(a.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,(e=>"\\"+e)),"gi");e.on("BeforeSetContent",(e=>{e.content=e.content.replace(c,s(t()))})),e.on("PreInit",(()=>{e.serializer.addNodeFilter("img",(n=>{let o,s,c=n.length;for(;c--;)if(o=n[c],s=o.attr("class"),s&&-1!==s.indexOf(r)){const n=o.parent;if(n&&e.schema.getBlockElements()[n.name]&&t()){n.type=3,n.value=a,n.raw=!0,o.remove();continue}o.type=3,o.value=a,o.raw=!0}}))}))})(e),(e=>{e.on("ResolveName",(a=>{"IMG"===a.target.nodeName&&e.dom.hasClass(a.target,r)&&(a.name="pagebreak")}))})(e)}))}(); -------------------------------------------------------------------------------- /public/vendor/moonshine/libs/tinymce/plugins/preview/plugin.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TinyMCE version 6.8.3 (2024-02-08) 3 | */ 4 | !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.Env"),o=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=e=>t=>t.options.get(e),i=n("content_style"),s=n("content_css_cors"),c=n("body_class"),r=n("body_id");e.add("preview",(e=>{(e=>{e.addCommand("mcePreview",(()=>{(e=>{const n=(e=>{var n;let l="";const a=e.dom.encode,d=null!==(n=i(e))&&void 0!==n?n:"";l+='';const m=s(e)?' crossorigin="anonymous"':"";o.each(e.contentCSS,(t=>{l+='"})),d&&(l+='");const y=r(e),u=c(e),v='