├── .github └── workflows │ └── django.yml ├── .gitignore ├── CloudPanel ├── __init__.py ├── asgi.py ├── celery.py ├── settings.py ├── urls.py └── wsgi.py ├── README.md ├── apps ├── azure │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── management │ │ └── commands │ │ │ ├── az_update.py │ │ │ └── init_az_images.py │ ├── models.py │ ├── tasks.py │ ├── urls.py │ └── views.py └── users │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── management │ └── commands │ │ └── init_db.py │ ├── models.py │ ├── urls.py │ └── views.py ├── config └── nginx.conf ├── entrypoint.sh ├── libs ├── azure.py └── utils.py ├── manage.py ├── requirements.txt ├── scripts ├── celery-beat.conf ├── celery-worker.conf └── django.conf └── web ├── favicon.ico ├── index.html └── static ├── admin ├── css │ ├── autocomplete.css │ ├── base.css │ ├── changelists.css │ ├── dashboard.css │ ├── fonts.css │ ├── forms.css │ ├── login.css │ ├── nav_sidebar.css │ ├── responsive.css │ ├── responsive_rtl.css │ ├── rtl.css │ ├── vendor │ │ └── select2 │ │ │ ├── LICENSE-SELECT2.md │ │ │ ├── select2.css │ │ │ └── select2.min.css │ └── widgets.css ├── fonts │ ├── LICENSE.txt │ ├── README.txt │ ├── Roboto-Bold-webfont.woff │ ├── Roboto-Light-webfont.woff │ └── Roboto-Regular-webfont.woff ├── img │ ├── LICENSE │ ├── README.txt │ ├── calendar-icons.svg │ ├── gis │ │ ├── move_vertex_off.svg │ │ └── move_vertex_on.svg │ ├── icon-addlink.svg │ ├── icon-alert.svg │ ├── icon-calendar.svg │ ├── icon-changelink.svg │ ├── icon-clock.svg │ ├── icon-deletelink.svg │ ├── icon-no.svg │ ├── icon-unknown-alt.svg │ ├── icon-unknown.svg │ ├── icon-viewlink.svg │ ├── icon-yes.svg │ ├── inline-delete.svg │ ├── search.svg │ ├── selector-icons.svg │ ├── sorting-icons.svg │ ├── tooltag-add.svg │ └── tooltag-arrowright.svg └── js │ ├── SelectBox.js │ ├── SelectFilter2.js │ ├── actions.js │ ├── admin │ ├── DateTimeShortcuts.js │ └── RelatedObjectLookups.js │ ├── autocomplete.js │ ├── calendar.js │ ├── cancel.js │ ├── change_form.js │ ├── collapse.js │ ├── core.js │ ├── inlines.js │ ├── jquery.init.js │ ├── nav_sidebar.js │ ├── popup_response.js │ ├── prepopulate.js │ ├── prepopulate_init.js │ ├── urlify.js │ └── vendor │ ├── jquery │ ├── LICENSE.txt │ ├── jquery.js │ └── jquery.min.js │ ├── select2 │ ├── LICENSE.md │ ├── i18n │ │ ├── af.js │ │ ├── ar.js │ │ ├── az.js │ │ ├── bg.js │ │ ├── bn.js │ │ ├── bs.js │ │ ├── ca.js │ │ ├── cs.js │ │ ├── da.js │ │ ├── de.js │ │ ├── dsb.js │ │ ├── el.js │ │ ├── en.js │ │ ├── es.js │ │ ├── et.js │ │ ├── eu.js │ │ ├── fa.js │ │ ├── fi.js │ │ ├── fr.js │ │ ├── gl.js │ │ ├── he.js │ │ ├── hi.js │ │ ├── hr.js │ │ ├── hsb.js │ │ ├── hu.js │ │ ├── hy.js │ │ ├── id.js │ │ ├── is.js │ │ ├── it.js │ │ ├── ja.js │ │ ├── ka.js │ │ ├── km.js │ │ ├── ko.js │ │ ├── lt.js │ │ ├── lv.js │ │ ├── mk.js │ │ ├── ms.js │ │ ├── nb.js │ │ ├── ne.js │ │ ├── nl.js │ │ ├── pl.js │ │ ├── ps.js │ │ ├── pt-BR.js │ │ ├── pt.js │ │ ├── ro.js │ │ ├── ru.js │ │ ├── sk.js │ │ ├── sl.js │ │ ├── sq.js │ │ ├── sr-Cyrl.js │ │ ├── sr.js │ │ ├── sv.js │ │ ├── th.js │ │ ├── tk.js │ │ ├── tr.js │ │ ├── uk.js │ │ ├── vi.js │ │ ├── zh-CN.js │ │ └── zh-TW.js │ ├── select2.full.js │ └── select2.full.min.js │ └── xregexp │ ├── LICENSE.txt │ ├── xregexp.js │ └── xregexp.min.js ├── css ├── app.d5578ff9.css ├── chunk-0475a8a9.c54cc8a5.css ├── chunk-1f940af7.6bb20c54.css ├── chunk-50499323.e2ce212c.css ├── chunk-5786617a.310d8994.css ├── chunk-6146664d.d855fcd7.css ├── chunk-714ebfa6.0f43044d.css └── chunk-libs.3dfb7769.css ├── fonts ├── element-icons.535877f5.woff └── element-icons.732389de.ttf ├── img ├── 401.089007e7.gif ├── 404.a57b6f31.png └── 404_cloud.0f4bc32b.png └── js ├── app.9e7b9244.js ├── chunk-0475a8a9.779a60da.js ├── chunk-1f940af7.6ecba6b3.js ├── chunk-2d2105d3.8eb9d2f2.js ├── chunk-2d230fe7.fcb684d8.js ├── chunk-50499323.0282e3c3.js ├── chunk-5786617a.f4a2e354.js ├── chunk-6146664d.515324ec.js ├── chunk-714ebfa6.57d9f2c9.js ├── chunk-elementUI.c3fe5fec.js └── chunk-libs.d7c6d8a3.js /.github/workflows/django.yml: -------------------------------------------------------------------------------- 1 | name: Django CI 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | strategy: 14 | max-parallel: 4 15 | matrix: 16 | python-version: [3.8] 17 | 18 | steps: 19 | - uses: actions/checkout@v3 20 | - name: Set up Python ${{ matrix.python-version }} 21 | uses: actions/setup-python@v3 22 | with: 23 | python-version: ${{ matrix.python-version }} 24 | - name: Install Dependencies 25 | run: | 26 | python -m pip install --upgrade pip 27 | pip install -r requirements.txt 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | db.sqlite3 2 | migrations 3 | celerybeat* 4 | .idea 5 | __pycache__ 6 | tests.py 7 | Dockerfile -------------------------------------------------------------------------------- /CloudPanel/__init__.py: -------------------------------------------------------------------------------- 1 | from .celery import app as celery_app 2 | 3 | __all__ = ('celery_app',) -------------------------------------------------------------------------------- /CloudPanel/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for CloudPanel project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CloudPanel.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /CloudPanel/celery.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import unicode_literals 3 | import os 4 | from celery import Celery 5 | from django.utils import timezone 6 | from kombu import Exchange 7 | from kombu import Queue 8 | import datetime 9 | from celery.schedules import crontab 10 | 11 | # set the default Django settings module for the 'celery' program. 12 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CloudPanel.settings') 13 | os.environ.setdefault('FORKED_BY_MULTIPROCESSING', '1') 14 | app = Celery("app", backend='redis', broker='redis://127.0.0.1:6379/2') 15 | 16 | # app.now=datetime.datetime.utcnow 17 | # print app.now(), 'celery---------------->>>>>>' 18 | 19 | # Using a string here means the worker doesn't have to serialize 20 | # the configuration object to child processes. 21 | # - namespace='CELERY' means all celery-related configuration keys 22 | # should have a `CELERY_` prefix. 23 | # 在django配置文件中进行配置,以大写CELERY开头 24 | app.config_from_object('django.conf:settings', namespace='celery') 25 | # 解决时区问题,定时任务启动就循环输出 26 | app.now = datetime.datetime.now 27 | 28 | # Load task modules from all registered Django app configs. 29 | # celery自动发现所有django-app下面的任务tasks.py 30 | app.autodiscover_tasks() 31 | 32 | # 通过设置x-max-priority参数来配置队列以支持优先级 33 | # app.conf.task_queues = [ 34 | # Queue('tasks', Exchange('tasks'), routing_key='tasks', 35 | # queue_arguments={'x-max-priority': 10}), 36 | # ] 37 | 38 | # 设置所有队列的默认值 39 | app.conf.task_queue_max_priority = 10 40 | CELERYD_MAX_TASKS_PER_CHILD = 5 41 | # 设置了三个Queue绑定到一个direct类型的exchange上,然后consumer监听所有的队列,消息来了后就轮询调用consumer进行处理. 42 | task_exchange = Exchange('tasks', type='direct') 43 | # 异步任务优先级 44 | task_queues = [Queue('hipri', task_exchange, routing_key='hipri'), 45 | Queue('midpri', task_exchange, routing_key='midpri'), 46 | Queue('lopri', task_exchange, routing_key='lopri')] 47 | 48 | 49 | app.conf.beat_schedule = { 50 | # AZURE 每小时 5 分, 自动更新一次订阅 51 | 'updateAzureAccount': { 52 | 'task': 'apps.azure.tasks.beat_update_azure_account', 53 | 'schedule': crontab(minute='05', hour='*'), 54 | 'args': '' 55 | }, 56 | 57 | # AZURE 每 5 分, 自动更新一次异常VM 58 | 'updateAzureVM': { 59 | 'task': 'apps.azure.tasks.beat_update_azure_vm', 60 | 'schedule': crontab(minute='*'), 61 | 'args': '' 62 | }, 63 | } -------------------------------------------------------------------------------- /CloudPanel/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for CloudPanel project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.2.5. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.2/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | import os 15 | 16 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 17 | BASE_DIR = Path(__file__).resolve().parent.parent 18 | 19 | 20 | # Quick-start development settings - unsuitable for production 21 | # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ 22 | 23 | # SECURITY WARNING: keep the secret key used in production secret! 24 | SECRET_KEY = 'django-insecure-s5(icgo^*dlk91xt6_k-y@-)5^9vgjm)jcstt6)^ald^yuwy)w' 25 | 26 | # SECURITY WARNING: don't run with debug turned on in production! 27 | DEBUG = True 28 | 29 | ALLOWED_HOSTS = ['*'] 30 | 31 | 32 | # Application definition 33 | 34 | INSTALLED_APPS = [ 35 | 'django.contrib.admin', 36 | 'django.contrib.auth', 37 | 'django.contrib.contenttypes', 38 | 'django.contrib.sessions', 39 | 'django.contrib.messages', 40 | 'django.contrib.staticfiles', 41 | 'corsheaders', 42 | 'apps.users', 43 | 'apps.azure' 44 | ] 45 | 46 | MIDDLEWARE = [ 47 | 'django.middleware.security.SecurityMiddleware', 48 | 'django.contrib.sessions.middleware.SessionMiddleware', 49 | 'corsheaders.middleware.CorsMiddleware', 50 | 'django.middleware.common.CommonMiddleware', 51 | # 'django.middleware.csrf.CsrfViewMiddleware', 52 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 53 | 'django.contrib.messages.middleware.MessageMiddleware', 54 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 55 | ] 56 | 57 | # 跨域参数 start 58 | CORS_ALLOW_CREDENTIALS = True 59 | CORS_ORIGIN_ALLOW_ALL = True 60 | CORS_ORIGIN_WHITELIST = () 61 | CORS_ALLOW_METHODS = ( 62 | 'DELETE', 63 | 'GET', 64 | 'OPTIONS', 65 | 'PATCH', 66 | 'POST', 67 | 'PUT', 68 | 'VIEW', 69 | ) 70 | 71 | CORS_ALLOW_HEADERS = ( 72 | 'XMLHttpRequest', 73 | 'X_FILENAME', 74 | 'accept-encoding', 75 | 'authorization', 76 | 'content-type', 77 | 'dnt', 78 | 'origin', 79 | 'user-agent', 80 | 'x-token', 81 | 'x-csrftoken', 82 | 'x-requested-with', 83 | 'Pragma', 84 | ) 85 | # 跨域参数 end 86 | 87 | ROOT_URLCONF = 'CloudPanel.urls' 88 | 89 | TEMPLATES = [ 90 | { 91 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 92 | 'DIRS': [BASE_DIR / 'templates'] 93 | , 94 | 'APP_DIRS': True, 95 | 'OPTIONS': { 96 | 'context_processors': [ 97 | 'django.template.context_processors.debug', 98 | 'django.template.context_processors.request', 99 | 'django.contrib.auth.context_processors.auth', 100 | 'django.contrib.messages.context_processors.messages', 101 | ], 102 | }, 103 | }, 104 | ] 105 | 106 | WSGI_APPLICATION = 'CloudPanel.wsgi.application' 107 | 108 | 109 | # Database 110 | # https://docs.djangoproject.com/en/3.2/ref/settings/#databases 111 | 112 | DATABASES = { 113 | 'default': { 114 | 'ENGINE': 'django.db.backends.sqlite3', 115 | 'NAME': BASE_DIR / 'db.sqlite3', 116 | } 117 | } 118 | 119 | CACHES = { 120 | "default": { 121 | "BACKEND": "django_redis.cache.RedisCache", 122 | "LOCATION": "redis://127.0.0.1:6379/1", 123 | "OPTIONS": { 124 | "CLIENT_CLASS": "django_redis.client.DefaultClient", 125 | } 126 | } 127 | } 128 | SESSION_COOKIE_AGE = 60 * 60 * 24 * 2 # 设置session过期时间为 2 天 129 | SESSION_ENGINE = 'django.contrib.sessions.backends.cache' 130 | 131 | # Password validation 132 | # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators 133 | 134 | AUTH_PASSWORD_VALIDATORS = [ 135 | { 136 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 137 | }, 138 | { 139 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 140 | }, 141 | { 142 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 143 | }, 144 | { 145 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 146 | }, 147 | ] 148 | 149 | 150 | # Internationalization 151 | # https://docs.djangoproject.com/en/3.2/topics/i18n/ 152 | 153 | LANGUAGE_CODE = 'zh-Hans' 154 | 155 | TIME_ZONE = 'Asia/Shanghai' 156 | 157 | USE_I18N = True 158 | 159 | USE_L10N = True 160 | 161 | USE_TZ = False 162 | 163 | 164 | # Static files (CSS, JavaScript, Images) 165 | # https://docs.djangoproject.com/en/3.2/howto/static-files/ 166 | 167 | STATIC_URL = '/static/' 168 | STATIC_ROOT = os.path.join(BASE_DIR, 'static') 169 | 170 | # Default primary key field type 171 | # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field 172 | 173 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 174 | 175 | 176 | # CELERY 177 | CELERY_TASK_TRACK_STARTED = True 178 | CELERY_TASK_TIME_LIMIT = 30 * 60 179 | CELERY_TIMEZONE = 'Asia/Shanghai' 180 | -------------------------------------------------------------------------------- /CloudPanel/urls.py: -------------------------------------------------------------------------------- 1 | """CloudPanel URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.2/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | 19 | urlpatterns = [ 20 | path('api/admin/', admin.site.urls), 21 | path('api/passport/', include('apps.users.urls')), 22 | path('api/azure/', include('apps.azure.urls')), 23 | ] 24 | -------------------------------------------------------------------------------- /CloudPanel/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for CloudPanel project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CloudPanel.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cloudpanel -------------------------------------------------------------------------------- /apps/azure/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdntip/cloudpanel/a093fd3d4b3c5ed9fbca72a8ca4080d412691976/apps/azure/__init__.py -------------------------------------------------------------------------------- /apps/azure/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | # Register your models here. 5 | from apps.azure.models import Account, Vm, Images 6 | 7 | @admin.register(Account) 8 | class AccountAdmin(admin.ModelAdmin): 9 | search_fields = ['tenant_id', 'password', 'client_id', 'subscription_id'] 10 | 11 | list_filter = ('status',) 12 | list_display = ('id', 'display_name', 'email', 'status', 'subscription_id', 'note', 'create_time', 'update_time') 13 | 14 | @admin.register(Vm) 15 | class VmAdmin(admin.ModelAdmin): 16 | 17 | search_fields = ('name', 'vm_id', 'ip', 'vm_size', 'image', 'os_disk', ) 18 | list_filter = ('status',) 19 | list_display = ('id', 'name', 'vm_id', 'ip', 'status', 'vm_size', 'image', 'os_disk', 'create_time', 'update_time') 20 | 21 | @admin.register(Images) 22 | class ImagesAdmin(admin.ModelAdmin): 23 | search_fields = ('name', 'value', ) 24 | list_filter = ('status', ) 25 | 26 | list_display = ('id', 'name', 'value', 'status', 'create_time', 'update_time') -------------------------------------------------------------------------------- /apps/azure/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AzureConfig(AppConfig): 5 | name = 'apps.azure' 6 | -------------------------------------------------------------------------------- /apps/azure/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from apps.azure import models 4 | 5 | 6 | class AccountForm(forms.Form): 7 | id = forms.IntegerField(required=False) 8 | email = forms.CharField(max_length=255) 9 | app_id = forms.CharField(max_length=255) 10 | password = forms.CharField(max_length=255) 11 | login_password = forms.CharField(max_length=255, required=False) 12 | tenant_id = forms.CharField(max_length=255) 13 | note = forms.CharField(max_length=255, required=False) 14 | 15 | def clean_id(self): 16 | try: 17 | id = self.cleaned_data.get('id', False) 18 | if not id: return False 19 | nodeInfo = models.Account.objects.filter(id=id).first() 20 | if not nodeInfo: 21 | raise forms.ValidationError(message='账号不存在') 22 | return nodeInfo 23 | except: 24 | return False 25 | 26 | 27 | -------------------------------------------------------------------------------- /apps/azure/management/commands/az_update.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from django.core.management import execute_from_command_line 3 | from django.conf import settings 4 | 5 | from apps.azure.models import Account, Vm 6 | import time 7 | 8 | class Command(BaseCommand): 9 | help = '更新全部azure账号信息' 10 | 11 | def handle(self, *args, **options): 12 | for _account in Account.objects.filter(status__in=['Enabled', 'Warned']): 13 | _account.update_subscriptions() 14 | _account.update_vm_list() 15 | 16 | for _vm in Vm.objects.filter(): 17 | _vm.update_public_ip() 18 | _vm.update_vm_info() -------------------------------------------------------------------------------- /apps/azure/management/commands/init_az_images.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from django.core.management import execute_from_command_line 3 | from django.conf import settings 4 | 5 | from apps.azure.models import Images 6 | 7 | class Command(BaseCommand): 8 | help = '更新全部azure镜像地址' 9 | 10 | def handle(self, *args, **options): 11 | images = { 12 | 'OpenLogic:CentOS:7.5:latest': 'CentOS 7.5', 13 | 'OpenLogic:CentOS:7_9:latest': 'CentOS 7.9', 14 | 'Canonical:UbuntuServer:18.04-LTS:latest': 'Ubuntu 18.04', 15 | 'canonical:0001-com-ubuntu-server-focal:20_04-lts-gen2:latest': 'Ubuntu 20.04', 16 | 'Debian:debian-10:10:latest': 'Debian 10', 17 | 'MicrosoftWindowsServer:WindowsServer:2012-Datacenter-zhcn:latest': 'Windows 2012 DC CN', 18 | 'MicrosoftWindowsServer:WindowsServer:2016-Datacenter-zhcn:latest': 'Windows 2016 DC CN', 19 | 'MicrosoftWindowsServer:WindowsServer:2019-Datacenter-smalldisk:latest': 'Windows 2019 DC', 20 | 'MicrosoftWindowsDesktop:Windows-10:21h1-pro:latest ': 'Windows 10 PRO', 21 | } 22 | for k, v in images.items(): 23 | # print(k, v) 24 | if Images.objects.filter(value=k).first(): continue 25 | 26 | Images.objects.create(name=v, value=k) 27 | continue -------------------------------------------------------------------------------- /apps/azure/tasks.py: -------------------------------------------------------------------------------- 1 | from django.db.models import Q 2 | 3 | from celery import shared_task 4 | 5 | from apps.azure import models 6 | 7 | # 更新账号 8 | @shared_task() 9 | def task_update_az(account_id): 10 | account_info = models.Account.objects.filter(id=account_id).first() 11 | 12 | if not account_info: 13 | return '账号不存在', False 14 | 15 | account_info.update_subscriptions() 16 | account_info.update_vm_list() 17 | 18 | for _vm in models.Vm.objects.filter(account_id=account_info.id): 19 | _vm.update_public_ip() 20 | _vm.update_vm_info() 21 | return '更新完成', True 22 | 23 | # 更新虚拟机 24 | @shared_task() 25 | def update_azure_vm(vm_id): 26 | try: 27 | vm_info = models.Vm.objects.filter(id=vm_id).first() 28 | if not vm_info: 29 | return 'VM 实例不存在', False 30 | vm_info.update_public_ip() 31 | vm_info.update_vm_info() 32 | return '更新完成', True 33 | except: 34 | return '更新失败', False 35 | 36 | # 更新全部账号的订阅 37 | @shared_task() 38 | def beat_update_azure_account(): 39 | account_list = models.Account.objects.filter(status__in=['Enabled', 'Warned']) 40 | print(f'需要更新的账号数量为 {account_list.count()}') 41 | for foo in account_list: 42 | task_update_az.delay(foo.id) 43 | return True 44 | 45 | # 更新全部需要更新的VM 46 | @shared_task() 47 | def beat_update_azure_vm(): 48 | q = Q(ip='') 49 | q.add(~Q(status='running'), Q.OR) 50 | data_list = models.Vm.objects.filter(q) 51 | print(f'需要更新的VM数量为 {data_list.count()}') 52 | for foo in data_list: 53 | update_azure_vm.delay(foo.id) 54 | return True -------------------------------------------------------------------------------- /apps/azure/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from apps.azure import views 3 | from apps.users.views import is_token 4 | 5 | urlpatterns = [ 6 | # aws 账号 7 | path('account', is_token(views.AzureAccountView.as_view()), name="AzureAccountView"), 8 | path('account/delete', is_token(views.AzureAccountDeleteView.as_view()), name="AzureAccountDeleteView"), 9 | path('vm', is_token(views.AzureVmListView.as_view()), name="AzureVmListView"), 10 | path('vm/action', is_token(views.AzureVmActionView.as_view()), name="AzureVmActionView"), 11 | path('vm/create', is_token(views.AzureVmCreateView.as_view()), name="AzureVmCreateView"), 12 | ] 13 | -------------------------------------------------------------------------------- /apps/users/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdntip/cloudpanel/a093fd3d4b3c5ed9fbca72a8ca4080d412691976/apps/users/__init__.py -------------------------------------------------------------------------------- /apps/users/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /apps/users/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class UserConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'apps.users' 7 | -------------------------------------------------------------------------------- /apps/users/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.models import User 3 | 4 | # 登录 5 | class Login(forms.Form): 6 | username = forms.CharField(max_length=32, min_length=3, error_messages={'required': '账号不能为空', 'max_length': '账号最大长度为32位', 'min_length': '账号最小长度为4位'}) 7 | password = forms.CharField(max_length=32, min_length=3, error_messages={'required': '密码不能为空', 'max_length': '密码最大长度为32位', 'min_length': '密码最小长度为4位'}) 8 | code = forms.CharField(required=False, max_length=4, error_messages={'required': '验证码错误', 'max_length': '验证码错误'}) 9 | 10 | # 判断账号是否存在 11 | def clean_username(self): 12 | username = self.cleaned_data.get('username').strip().lower() 13 | user_info = User.objects.filter(username=username).first() 14 | if not user_info: 15 | raise forms.ValidationError(message='该 %s 用户不存在' % username) 16 | self.cleaned_data.update({ 17 | 'user_info': user_info 18 | }) 19 | return username 20 | 21 | # 处理密码 22 | def clean_password(self): 23 | password = self.cleaned_data.get('password').strip() 24 | return password 25 | -------------------------------------------------------------------------------- /apps/users/management/commands/init_db.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from django.core.management import execute_from_command_line 3 | from django.conf import settings 4 | 5 | class Command(BaseCommand): 6 | help = '初始化/更新数据库' 7 | 8 | def handle(self, *args, **options): 9 | args = ['manage.py', 'makemigrations'] 10 | apps = [x.split('.')[-1] for x in settings.INSTALLED_APPS if x.startswith('apps.')] 11 | execute_from_command_line(args + apps) 12 | execute_from_command_line(['manage.py', 'migrate']) 13 | self.stdout.write(self.style.SUCCESS(' 初始化/更新成功')) -------------------------------------------------------------------------------- /apps/users/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /apps/users/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from apps.users import views 3 | 4 | urlpatterns = [ 5 | path('login', views.Login, name="UserLogin"), 6 | path('info', views.Info, name="UserInfo"), 7 | ] 8 | -------------------------------------------------------------------------------- /apps/users/views.py: -------------------------------------------------------------------------------- 1 | from django.http import JsonResponse 2 | from django.core.cache import cache 3 | 4 | from django.contrib.auth.models import User 5 | from django.contrib.auth import authenticate 6 | from apps.users import forms 7 | 8 | # Create your views here. 9 | import time 10 | 11 | from libs.utils import md5 12 | # 判断是否登录 13 | def is_token(func): 14 | def inner(request, *args, **kwargs): 15 | token = request.META.get('HTTP_X_TOKEN', False) 16 | if not token: 17 | return JsonResponse({'code': 50008, 'message': '登录会话失效,请重新的登录'}) 18 | 19 | user = cache.get(token, False) 20 | if not user or not user.is_active or not user.is_superuser: 21 | return JsonResponse({'code': 50008, 'message': '登录会话失效,请重新的登录'}) 22 | request.user = user 23 | return func(request, *args, **kwargs) 24 | return inner 25 | 26 | 27 | # 登录 28 | def Login(request): 29 | if request.method == "POST": 30 | input_data = forms.Login(request.POST) 31 | if input_data.is_valid(): 32 | data = input_data.clean() 33 | user_info = data.get('user_info') 34 | username = data.get('username') 35 | password = data.get('password') 36 | 37 | if not user_info.is_active: 38 | return JsonResponse({'code': 20002, 'message': '该用户禁止登录'}) 39 | 40 | user = authenticate(username=username, password=password) 41 | 42 | if not user: return JsonResponse({'code': 20002, 'message': '登录密码错误'}) 43 | 44 | token = md5("%s%s" %(user.username, time.time())).upper() 45 | cache.set(token, user, 172800) 46 | res_data = {'code': 20000, 'message': '登录成功', 'data': {'token': token}} 47 | return JsonResponse(res_data) 48 | return JsonResponse({'code': 20001, 'message': '登录失败', 'error_data': input_data.errors}) 49 | 50 | # 获取用户信息 51 | @is_token 52 | def Info(request): 53 | userinfo = User.objects.filter(username=request.user.username).first() 54 | if not userinfo: 55 | return JsonResponse({'code': 50008, 'message': '用户信息不存在,请重新登录'}) 56 | data = { 57 | 'avatar': 'https://t1.picb.cc/uploads/2021/10/05/wXMX1y.th.jpg', 58 | 'name': userinfo.username, 59 | 'username': userinfo.username, 60 | 'create_time': userinfo.date_joined.strftime("%Y-%m-%d %H:%M:%S"), 61 | 'roles': ['user'] 62 | } 63 | if userinfo.is_superuser: 64 | # 管理员 65 | data.update({'roles': ['admin'], 'introduction': '.'}) 66 | 67 | return JsonResponse({'code': 20000, 'message': '获取成功', 'data': data}) 68 | 69 | # 退出 70 | def Logout(request): 71 | cache.set(request.token, '', 0) 72 | return JsonResponse({'code': 20000, 'data': 'success'}) -------------------------------------------------------------------------------- /config/nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes auto; 2 | events { 3 | worker_connections 51200; 4 | } 5 | http { 6 | include mime.types; 7 | default_type application/octet-stream; 8 | sendfile on; 9 | keepalive_timeout 65; 10 | server { 11 | listen 80; 12 | server_name localhost; 13 | root /home/python/cloudpanel/web; 14 | index index.html; 15 | location /api { 16 | proxy_set_header Accept-Encoding ''; 17 | proxy_set_header Host $http_host; 18 | proxy_set_header Referer $http_referer; 19 | proxy_set_header X-Real-IP $remote_addr; 20 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 21 | proxy_set_header X-Forwarded-Proto $scheme; 22 | proxy_pass http://127.0.0.1:887; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | /etc/init.d/redis-server start 4 | /etc/init.d/nginx start 5 | /etc/init.d/supervisor start 6 | 7 | tail -F /home/python/cloudpanel/django.log -------------------------------------------------------------------------------- /libs/utils.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # 分页 5 | def Pagination(page, limit, dataLen=999): 6 | if page == 1 or page == 0: 7 | return 0, limit 8 | a = int(limit) * int(page) 9 | if dataLen < int(limit): 10 | return 0, a 11 | return a - int(limit), a 12 | 13 | 14 | def DateTimeToStr(_datetime): 15 | try: 16 | return _datetime.strftime("%Y-%m-%d %H:%M:%S") 17 | except: 18 | return str(_datetime) 19 | 20 | def is_ipv4(ip: str) -> bool: 21 | return True if [1] * 4 == [x.isdigit() and 0 <= int(x) <= 255 for x in ip.split(".")] else False 22 | 23 | 24 | def md5(str): 25 | import hashlib 26 | m2 = hashlib.md5() 27 | m2.update(str.encode("utf-8")) 28 | return m2.hexdigest() 29 | 30 | 31 | def traffic_format(traffic): 32 | if traffic < 1024 * 8: 33 | return str(int(traffic)) + "B" 34 | 35 | if traffic < 1024 * 1024: 36 | return str(round((traffic / 1024.0), 1)) + "KB" 37 | 38 | if traffic < 1024 * 1024 * 1024: 39 | return str(round((traffic / (1024.0 * 1024)), 1)) + "MB" 40 | 41 | if traffic < 1024 * 1024 * 1024 * 1024 * 1024: 42 | return str(round((traffic / (1024.0 * 1024 * 1024 * 1024)), 1)) + "PB" 43 | 44 | return str(round((traffic / 1073741824.0), 1)) + "GB" 45 | 46 | if __name__ == '__main__': 47 | print('Hello CDNTIP') -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CloudPanel.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdntip/cloudpanel/a093fd3d4b3c5ed9fbca72a8ca4080d412691976/requirements.txt -------------------------------------------------------------------------------- /scripts/celery-beat.conf: -------------------------------------------------------------------------------- 1 | [program:celery-beat] 2 | process_name=%(program_name)s_%(process_num)02d 3 | command=celery -A CloudPanel beat -l info 4 | directory=/home/python/cloudpanel/ 5 | autostart=true 6 | autorestart=true 7 | user=root 8 | redirect_stderr=true 9 | stdout_logfile=/home/python/cloudpanel/beat.log -------------------------------------------------------------------------------- /scripts/celery-worker.conf: -------------------------------------------------------------------------------- 1 | [program:celery-worker] 2 | process_name=%(program_name)s_%(process_num)02d 3 | command=celery -A CloudPanel worker -l info 4 | directory=/home/python/cloudpanel/ 5 | autostart=true 6 | autorestart=true 7 | user=root 8 | redirect_stderr=true 9 | stdout_logfile=/home/python/cloudpanel/worker.log -------------------------------------------------------------------------------- /scripts/django.conf: -------------------------------------------------------------------------------- 1 | [program:django] 2 | process_name=%(program_name)s_%(process_num)02d 3 | command=python3 manage.py runserver 0.0.0.0:887 4 | directory=/home/python/cloudpanel/ 5 | autostart=true 6 | autorestart=true 7 | user=root 8 | redirect_stderr=true 9 | stdout_logfile=/home/python/cloudpanel/django.log -------------------------------------------------------------------------------- /web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdntip/cloudpanel/a093fd3d4b3c5ed9fbca72a8ca4080d412691976/web/favicon.ico -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | Cloud Panel - CDNTIP
-------------------------------------------------------------------------------- /web/static/admin/css/changelists.css: -------------------------------------------------------------------------------- 1 | /* CHANGELISTS */ 2 | 3 | #changelist { 4 | display: flex; 5 | align-items: flex-start; 6 | justify-content: space-between; 7 | } 8 | 9 | #changelist .changelist-form-container { 10 | flex: 1 1 auto; 11 | min-width: 0; 12 | } 13 | 14 | #changelist table { 15 | width: 100%; 16 | } 17 | 18 | .change-list .hiddenfields { display:none; } 19 | 20 | .change-list .filtered table { 21 | border-right: none; 22 | } 23 | 24 | .change-list .filtered { 25 | min-height: 400px; 26 | } 27 | 28 | .change-list .filtered .results, .change-list .filtered .paginator, 29 | .filtered #toolbar, .filtered div.xfull { 30 | width: auto; 31 | } 32 | 33 | .change-list .filtered table tbody th { 34 | padding-right: 1em; 35 | } 36 | 37 | #changelist-form .results { 38 | overflow-x: auto; 39 | width: 100%; 40 | } 41 | 42 | #changelist .toplinks { 43 | border-bottom: 1px solid var(--hairline-color); 44 | } 45 | 46 | #changelist .paginator { 47 | color: var(--body-quiet-color); 48 | border-bottom: 1px solid var(--hairline-color); 49 | background: var(--body-bg); 50 | overflow: hidden; 51 | } 52 | 53 | /* CHANGELIST TABLES */ 54 | 55 | #changelist table thead th { 56 | padding: 0; 57 | white-space: nowrap; 58 | vertical-align: middle; 59 | } 60 | 61 | #changelist table thead th.action-checkbox-column { 62 | width: 1.5em; 63 | text-align: center; 64 | } 65 | 66 | #changelist table tbody td.action-checkbox { 67 | text-align: center; 68 | } 69 | 70 | #changelist table tfoot { 71 | color: var(--body-quiet-color); 72 | } 73 | 74 | /* TOOLBAR */ 75 | 76 | #toolbar { 77 | padding: 8px 10px; 78 | margin-bottom: 15px; 79 | border-top: 1px solid var(--hairline-color); 80 | border-bottom: 1px solid var(--hairline-color); 81 | background: var(--darkened-bg); 82 | color: var(--body-quiet-color); 83 | } 84 | 85 | #toolbar form input { 86 | border-radius: 4px; 87 | font-size: 14px; 88 | padding: 5px; 89 | color: var(--body-fg); 90 | } 91 | 92 | #toolbar #searchbar { 93 | height: 19px; 94 | border: 1px solid var(--border-color); 95 | padding: 2px 5px; 96 | margin: 0; 97 | vertical-align: top; 98 | font-size: 13px; 99 | max-width: 100%; 100 | } 101 | 102 | #toolbar #searchbar:focus { 103 | border-color: var(--body-quiet-color); 104 | } 105 | 106 | #toolbar form input[type="submit"] { 107 | border: 1px solid var(--border-color); 108 | font-size: 13px; 109 | padding: 4px 8px; 110 | margin: 0; 111 | vertical-align: middle; 112 | background: var(--body-bg); 113 | box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset; 114 | cursor: pointer; 115 | color: var(--body-fg); 116 | } 117 | 118 | #toolbar form input[type="submit"]:focus, 119 | #toolbar form input[type="submit"]:hover { 120 | border-color: var(--body-quiet-color); 121 | } 122 | 123 | #changelist-search img { 124 | vertical-align: middle; 125 | margin-right: 4px; 126 | } 127 | 128 | /* FILTER COLUMN */ 129 | 130 | #changelist-filter { 131 | flex: 0 0 240px; 132 | order: 1; 133 | background: var(--darkened-bg); 134 | border-left: none; 135 | margin: 0 0 0 30px; 136 | } 137 | 138 | #changelist-filter h2 { 139 | font-size: 14px; 140 | text-transform: uppercase; 141 | letter-spacing: 0.5px; 142 | padding: 5px 15px; 143 | margin-bottom: 12px; 144 | border-bottom: none; 145 | } 146 | 147 | #changelist-filter h3 { 148 | font-weight: 400; 149 | padding: 0 15px; 150 | margin-bottom: 10px; 151 | } 152 | 153 | #changelist-filter ul { 154 | margin: 5px 0; 155 | padding: 0 15px 15px; 156 | border-bottom: 1px solid var(--hairline-color); 157 | } 158 | 159 | #changelist-filter ul:last-child { 160 | border-bottom: none; 161 | } 162 | 163 | #changelist-filter li { 164 | list-style-type: none; 165 | margin-left: 0; 166 | padding-left: 0; 167 | } 168 | 169 | #changelist-filter a { 170 | display: block; 171 | color: var(--body-quiet-color); 172 | text-overflow: ellipsis; 173 | overflow-x: hidden; 174 | } 175 | 176 | #changelist-filter li.selected { 177 | border-left: 5px solid var(--hairline-color); 178 | padding-left: 10px; 179 | margin-left: -15px; 180 | } 181 | 182 | #changelist-filter li.selected a { 183 | color: var(--link-selected-fg); 184 | } 185 | 186 | #changelist-filter a:focus, #changelist-filter a:hover, 187 | #changelist-filter li.selected a:focus, 188 | #changelist-filter li.selected a:hover { 189 | color: var(--link-hover-color); 190 | } 191 | 192 | #changelist-filter #changelist-filter-clear a { 193 | font-size: 13px; 194 | padding-bottom: 10px; 195 | border-bottom: 1px solid var(--hairline-color); 196 | } 197 | 198 | /* DATE DRILLDOWN */ 199 | 200 | .change-list ul.toplinks { 201 | display: block; 202 | float: left; 203 | padding: 0; 204 | margin: 0; 205 | width: 100%; 206 | } 207 | 208 | .change-list ul.toplinks li { 209 | padding: 3px 6px; 210 | font-weight: bold; 211 | list-style-type: none; 212 | display: inline-block; 213 | } 214 | 215 | .change-list ul.toplinks .date-back a { 216 | color: var(--body-quiet-color); 217 | } 218 | 219 | .change-list ul.toplinks .date-back a:focus, 220 | .change-list ul.toplinks .date-back a:hover { 221 | color: var(--link-hover-color); 222 | } 223 | 224 | /* PAGINATOR */ 225 | 226 | .paginator { 227 | font-size: 13px; 228 | padding-top: 10px; 229 | padding-bottom: 10px; 230 | line-height: 22px; 231 | margin: 0; 232 | border-top: 1px solid var(--hairline-color); 233 | width: 100%; 234 | } 235 | 236 | .paginator a:link, .paginator a:visited { 237 | padding: 2px 6px; 238 | background: var(--button-bg); 239 | text-decoration: none; 240 | color: var(--button-fg); 241 | } 242 | 243 | .paginator a.showall { 244 | border: none; 245 | background: none; 246 | color: var(--link-fg); 247 | } 248 | 249 | .paginator a.showall:focus, .paginator a.showall:hover { 250 | background: none; 251 | color: var(--link-hover-color); 252 | } 253 | 254 | .paginator .end { 255 | margin-right: 6px; 256 | } 257 | 258 | .paginator .this-page { 259 | padding: 2px 6px; 260 | font-weight: bold; 261 | font-size: 13px; 262 | vertical-align: top; 263 | } 264 | 265 | .paginator a:focus, .paginator a:hover { 266 | color: white; 267 | background: var(--link-hover-color); 268 | } 269 | 270 | /* ACTIONS */ 271 | 272 | .filtered .actions { 273 | border-right: none; 274 | } 275 | 276 | #changelist table input { 277 | margin: 0; 278 | vertical-align: baseline; 279 | } 280 | 281 | #changelist table tbody tr.selected { 282 | background-color: var(--selected-row); 283 | } 284 | 285 | #changelist .actions { 286 | padding: 10px; 287 | background: var(--body-bg); 288 | border-top: none; 289 | border-bottom: none; 290 | line-height: 24px; 291 | color: var(--body-quiet-color); 292 | width: 100%; 293 | } 294 | 295 | #changelist .actions.selected { /* XXX Probably unused? */ 296 | background: var(--body-bg); 297 | border-top: 1px solid var(--body-bg); 298 | border-bottom: 1px solid #edecd6; 299 | } 300 | 301 | #changelist .actions span.all, 302 | #changelist .actions span.action-counter, 303 | #changelist .actions span.clear, 304 | #changelist .actions span.question { 305 | font-size: 13px; 306 | margin: 0 0.5em; 307 | } 308 | 309 | #changelist .actions:last-child { 310 | border-bottom: none; 311 | } 312 | 313 | #changelist .actions select { 314 | vertical-align: top; 315 | height: 24px; 316 | color: var(--body-fg); 317 | border: 1px solid var(--border-color); 318 | border-radius: 4px; 319 | font-size: 14px; 320 | padding: 0 0 0 4px; 321 | margin: 0; 322 | margin-left: 10px; 323 | } 324 | 325 | #changelist .actions select:focus { 326 | border-color: var(--body-quiet-color); 327 | } 328 | 329 | #changelist .actions label { 330 | display: inline-block; 331 | vertical-align: middle; 332 | font-size: 13px; 333 | } 334 | 335 | #changelist .actions .button { 336 | font-size: 13px; 337 | border: 1px solid var(--border-color); 338 | border-radius: 4px; 339 | background: var(--body-bg); 340 | box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset; 341 | cursor: pointer; 342 | height: 24px; 343 | line-height: 1; 344 | padding: 4px 8px; 345 | margin: 0; 346 | color: var(--body-fg); 347 | } 348 | 349 | #changelist .actions .button:focus, #changelist .actions .button:hover { 350 | border-color: var(--body-quiet-color); 351 | } 352 | -------------------------------------------------------------------------------- /web/static/admin/css/dashboard.css: -------------------------------------------------------------------------------- 1 | /* DASHBOARD */ 2 | 3 | .dashboard .module table th { 4 | width: 100%; 5 | } 6 | 7 | .dashboard .module table td { 8 | white-space: nowrap; 9 | } 10 | 11 | .dashboard .module table td a { 12 | display: block; 13 | padding-right: .6em; 14 | } 15 | 16 | /* RECENT ACTIONS MODULE */ 17 | 18 | .module ul.actionlist { 19 | margin-left: 0; 20 | } 21 | 22 | ul.actionlist li { 23 | list-style-type: none; 24 | overflow: hidden; 25 | text-overflow: ellipsis; 26 | } 27 | -------------------------------------------------------------------------------- /web/static/admin/css/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Roboto'; 3 | src: url('../fonts/Roboto-Bold-webfont.woff'); 4 | font-weight: 700; 5 | font-style: normal; 6 | } 7 | 8 | @font-face { 9 | font-family: 'Roboto'; 10 | src: url('../fonts/Roboto-Regular-webfont.woff'); 11 | font-weight: 400; 12 | font-style: normal; 13 | } 14 | 15 | @font-face { 16 | font-family: 'Roboto'; 17 | src: url('../fonts/Roboto-Light-webfont.woff'); 18 | font-weight: 300; 19 | font-style: normal; 20 | } 21 | -------------------------------------------------------------------------------- /web/static/admin/css/login.css: -------------------------------------------------------------------------------- 1 | /* LOGIN FORM */ 2 | 3 | .login { 4 | background: var(--darkened-bg); 5 | height: auto; 6 | } 7 | 8 | .login #header { 9 | height: auto; 10 | padding: 15px 16px; 11 | justify-content: center; 12 | } 13 | 14 | .login #header h1 { 15 | font-size: 18px; 16 | } 17 | 18 | .login #header h1 a { 19 | color: var(--header-link-color); 20 | } 21 | 22 | .login #content { 23 | padding: 20px 20px 0; 24 | } 25 | 26 | .login #container { 27 | background: var(--body-bg); 28 | border: 1px solid var(--hairline-color); 29 | border-radius: 4px; 30 | overflow: hidden; 31 | width: 28em; 32 | min-width: 300px; 33 | margin: 100px auto; 34 | height: auto; 35 | } 36 | 37 | .login .form-row { 38 | padding: 4px 0; 39 | } 40 | 41 | .login .form-row label { 42 | display: block; 43 | line-height: 2em; 44 | } 45 | 46 | .login .form-row #id_username, .login .form-row #id_password { 47 | padding: 8px; 48 | width: 100%; 49 | box-sizing: border-box; 50 | } 51 | 52 | .login .submit-row { 53 | padding: 1em 0 0 0; 54 | margin: 0; 55 | text-align: center; 56 | } 57 | 58 | .login .password-reset-link { 59 | text-align: center; 60 | } 61 | -------------------------------------------------------------------------------- /web/static/admin/css/nav_sidebar.css: -------------------------------------------------------------------------------- 1 | .sticky { 2 | position: sticky; 3 | top: 0; 4 | max-height: 100vh; 5 | } 6 | 7 | .toggle-nav-sidebar { 8 | z-index: 20; 9 | left: 0; 10 | display: flex; 11 | align-items: center; 12 | justify-content: center; 13 | flex: 0 0 23px; 14 | width: 23px; 15 | border: 0; 16 | border-right: 1px solid var(--hairline-color); 17 | background-color: var(--body-bg); 18 | cursor: pointer; 19 | font-size: 20px; 20 | color: var(--link-fg); 21 | padding: 0; 22 | } 23 | 24 | [dir="rtl"] .toggle-nav-sidebar { 25 | border-left: 1px solid var(--hairline-color); 26 | border-right: 0; 27 | } 28 | 29 | .toggle-nav-sidebar:hover, 30 | .toggle-nav-sidebar:focus { 31 | background-color: var(--darkened-bg); 32 | } 33 | 34 | #nav-sidebar { 35 | z-index: 15; 36 | flex: 0 0 275px; 37 | left: -276px; 38 | margin-left: -276px; 39 | border-top: 1px solid transparent; 40 | border-right: 1px solid var(--hairline-color); 41 | background-color: var(--body-bg); 42 | overflow: auto; 43 | } 44 | 45 | [dir="rtl"] #nav-sidebar { 46 | border-left: 1px solid var(--hairline-color); 47 | border-right: 0; 48 | left: 0; 49 | margin-left: 0; 50 | right: -276px; 51 | margin-right: -276px; 52 | } 53 | 54 | .toggle-nav-sidebar::before { 55 | content: '\00BB'; 56 | } 57 | 58 | .main.shifted .toggle-nav-sidebar::before { 59 | content: '\00AB'; 60 | } 61 | 62 | .main.shifted > #nav-sidebar { 63 | left: 24px; 64 | margin-left: 0; 65 | } 66 | 67 | [dir="rtl"] .main.shifted > #nav-sidebar { 68 | left: 0; 69 | right: 24px; 70 | margin-right: 0; 71 | } 72 | 73 | #nav-sidebar .module th { 74 | width: 100%; 75 | overflow-wrap: anywhere; 76 | } 77 | 78 | #nav-sidebar .module th, 79 | #nav-sidebar .module caption { 80 | padding-left: 16px; 81 | } 82 | 83 | #nav-sidebar .module td { 84 | white-space: nowrap; 85 | } 86 | 87 | [dir="rtl"] #nav-sidebar .module th, 88 | [dir="rtl"] #nav-sidebar .module caption { 89 | padding-left: 8px; 90 | padding-right: 16px; 91 | } 92 | 93 | #nav-sidebar .current-app .section:link, 94 | #nav-sidebar .current-app .section:visited { 95 | color: var(--header-color); 96 | font-weight: bold; 97 | } 98 | 99 | #nav-sidebar .current-model { 100 | background: var(--selected-row); 101 | } 102 | 103 | .main > #nav-sidebar + .content { 104 | max-width: calc(100% - 23px); 105 | } 106 | 107 | .main.shifted > #nav-sidebar + .content { 108 | max-width: calc(100% - 299px); 109 | } 110 | 111 | @media (max-width: 767px) { 112 | #nav-sidebar, #toggle-nav-sidebar { 113 | display: none; 114 | } 115 | 116 | .main > #nav-sidebar + .content, 117 | .main.shifted > #nav-sidebar + .content { 118 | max-width: 100%; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /web/static/admin/css/responsive_rtl.css: -------------------------------------------------------------------------------- 1 | /* TABLETS */ 2 | 3 | @media (max-width: 1024px) { 4 | [dir="rtl"] .colMS { 5 | margin-right: 0; 6 | } 7 | 8 | [dir="rtl"] #user-tools { 9 | text-align: right; 10 | } 11 | 12 | [dir="rtl"] #changelist .actions label { 13 | padding-left: 10px; 14 | padding-right: 0; 15 | } 16 | 17 | [dir="rtl"] #changelist .actions select { 18 | margin-left: 0; 19 | margin-right: 15px; 20 | } 21 | 22 | [dir="rtl"] .change-list .filtered .results, 23 | [dir="rtl"] .change-list .filtered .paginator, 24 | [dir="rtl"] .filtered #toolbar, 25 | [dir="rtl"] .filtered div.xfull, 26 | [dir="rtl"] .filtered .actions, 27 | [dir="rtl"] #changelist-filter { 28 | margin-left: 0; 29 | } 30 | 31 | [dir="rtl"] .inline-group ul.tools a.add, 32 | [dir="rtl"] .inline-group div.add-row a, 33 | [dir="rtl"] .inline-group .tabular tr.add-row td a { 34 | padding: 8px 26px 8px 10px; 35 | background-position: calc(100% - 8px) 9px; 36 | } 37 | 38 | [dir="rtl"] .related-widget-wrapper-link + .selector { 39 | margin-right: 0; 40 | margin-left: 15px; 41 | } 42 | 43 | [dir="rtl"] .selector .selector-filter label { 44 | margin-right: 0; 45 | margin-left: 8px; 46 | } 47 | 48 | [dir="rtl"] .object-tools li { 49 | float: right; 50 | } 51 | 52 | [dir="rtl"] .object-tools li + li { 53 | margin-left: 0; 54 | margin-right: 15px; 55 | } 56 | 57 | [dir="rtl"] .dashboard .module table td a { 58 | padding-left: 0; 59 | padding-right: 16px; 60 | } 61 | } 62 | 63 | /* MOBILE */ 64 | 65 | @media (max-width: 767px) { 66 | [dir="rtl"] .aligned .related-lookup, 67 | [dir="rtl"] .aligned .datetimeshortcuts { 68 | margin-left: 0; 69 | margin-right: 15px; 70 | } 71 | 72 | [dir="rtl"] .aligned ul { 73 | margin-right: 0; 74 | } 75 | 76 | [dir="rtl"] #changelist-filter { 77 | margin-left: 0; 78 | margin-right: 0; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /web/static/admin/css/rtl.css: -------------------------------------------------------------------------------- 1 | /* GLOBAL */ 2 | 3 | th { 4 | text-align: right; 5 | } 6 | 7 | .module h2, .module caption { 8 | text-align: right; 9 | } 10 | 11 | .module ul, .module ol { 12 | margin-left: 0; 13 | margin-right: 1.5em; 14 | } 15 | 16 | .viewlink, .addlink, .changelink { 17 | padding-left: 0; 18 | padding-right: 16px; 19 | background-position: 100% 1px; 20 | } 21 | 22 | .deletelink { 23 | padding-left: 0; 24 | padding-right: 16px; 25 | background-position: 100% 1px; 26 | } 27 | 28 | .object-tools { 29 | float: left; 30 | } 31 | 32 | thead th:first-child, 33 | tfoot td:first-child { 34 | border-left: none; 35 | } 36 | 37 | /* LAYOUT */ 38 | 39 | #user-tools { 40 | right: auto; 41 | left: 0; 42 | text-align: left; 43 | } 44 | 45 | div.breadcrumbs { 46 | text-align: right; 47 | } 48 | 49 | #content-main { 50 | float: right; 51 | } 52 | 53 | #content-related { 54 | float: left; 55 | margin-left: -300px; 56 | margin-right: auto; 57 | } 58 | 59 | .colMS { 60 | margin-left: 300px; 61 | margin-right: 0; 62 | } 63 | 64 | /* SORTABLE TABLES */ 65 | 66 | table thead th.sorted .sortoptions { 67 | float: left; 68 | } 69 | 70 | thead th.sorted .text { 71 | padding-right: 0; 72 | padding-left: 42px; 73 | } 74 | 75 | /* dashboard styles */ 76 | 77 | .dashboard .module table td a { 78 | padding-left: .6em; 79 | padding-right: 16px; 80 | } 81 | 82 | /* changelists styles */ 83 | 84 | .change-list .filtered table { 85 | border-left: none; 86 | border-right: 0px none; 87 | } 88 | 89 | #changelist-filter { 90 | border-left: none; 91 | border-right: none; 92 | margin-left: 0; 93 | margin-right: 30px; 94 | } 95 | 96 | #changelist-filter li.selected { 97 | border-left: none; 98 | padding-left: 10px; 99 | margin-left: 0; 100 | border-right: 5px solid var(--hairline-color); 101 | padding-right: 10px; 102 | margin-right: -15px; 103 | } 104 | 105 | #changelist table tbody td:first-child, #changelist table tbody th:first-child { 106 | border-right: none; 107 | border-left: none; 108 | } 109 | 110 | /* FORMS */ 111 | 112 | .aligned label { 113 | padding: 0 0 3px 1em; 114 | float: right; 115 | } 116 | 117 | .submit-row { 118 | text-align: left 119 | } 120 | 121 | .submit-row p.deletelink-box { 122 | float: right; 123 | } 124 | 125 | .submit-row input.default { 126 | margin-left: 0; 127 | } 128 | 129 | .vDateField, .vTimeField { 130 | margin-left: 2px; 131 | } 132 | 133 | .aligned .form-row input { 134 | margin-left: 5px; 135 | } 136 | 137 | form .aligned p.help, form .aligned div.help { 138 | clear: right; 139 | } 140 | 141 | form .aligned ul { 142 | margin-right: 163px; 143 | margin-left: 0; 144 | } 145 | 146 | form ul.inline li { 147 | float: right; 148 | padding-right: 0; 149 | padding-left: 7px; 150 | } 151 | 152 | input[type=submit].default, .submit-row input.default { 153 | float: left; 154 | } 155 | 156 | fieldset .fieldBox { 157 | float: right; 158 | margin-left: 20px; 159 | margin-right: 0; 160 | } 161 | 162 | .errorlist li { 163 | background-position: 100% 12px; 164 | padding: 0; 165 | } 166 | 167 | .errornote { 168 | background-position: 100% 12px; 169 | padding: 10px 12px; 170 | } 171 | 172 | /* WIDGETS */ 173 | 174 | .calendarnav-previous { 175 | top: 0; 176 | left: auto; 177 | right: 10px; 178 | } 179 | 180 | .calendarnav-next { 181 | top: 0; 182 | right: auto; 183 | left: 10px; 184 | } 185 | 186 | .calendar caption, .calendarbox h2 { 187 | text-align: center; 188 | } 189 | 190 | .selector { 191 | float: right; 192 | } 193 | 194 | .selector .selector-filter { 195 | text-align: right; 196 | } 197 | 198 | .inline-deletelink { 199 | float: left; 200 | } 201 | 202 | form .form-row p.datetime { 203 | overflow: hidden; 204 | } 205 | 206 | .related-widget-wrapper { 207 | float: right; 208 | } 209 | 210 | /* MISC */ 211 | 212 | .inline-related h2, .inline-group h2 { 213 | text-align: right 214 | } 215 | 216 | .inline-related h3 span.delete { 217 | padding-right: 20px; 218 | padding-left: inherit; 219 | left: 10px; 220 | right: inherit; 221 | float:left; 222 | } 223 | 224 | .inline-related h3 span.delete label { 225 | margin-left: inherit; 226 | margin-right: 2px; 227 | } 228 | -------------------------------------------------------------------------------- /web/static/admin/css/vendor/select2/LICENSE-SELECT2.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /web/static/admin/fonts/README.txt: -------------------------------------------------------------------------------- 1 | Roboto webfont source: https://www.google.com/fonts/specimen/Roboto 2 | WOFF files extracted using https://github.com/majodev/google-webfonts-helper 3 | Weights used in this project: Light (300), Regular (400), Bold (700) 4 | -------------------------------------------------------------------------------- /web/static/admin/fonts/Roboto-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdntip/cloudpanel/a093fd3d4b3c5ed9fbca72a8ca4080d412691976/web/static/admin/fonts/Roboto-Bold-webfont.woff -------------------------------------------------------------------------------- /web/static/admin/fonts/Roboto-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdntip/cloudpanel/a093fd3d4b3c5ed9fbca72a8ca4080d412691976/web/static/admin/fonts/Roboto-Light-webfont.woff -------------------------------------------------------------------------------- /web/static/admin/fonts/Roboto-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdntip/cloudpanel/a093fd3d4b3c5ed9fbca72a8ca4080d412691976/web/static/admin/fonts/Roboto-Regular-webfont.woff -------------------------------------------------------------------------------- /web/static/admin/img/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Code Charm Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /web/static/admin/img/README.txt: -------------------------------------------------------------------------------- 1 | All icons are taken from Font Awesome (http://fontawesome.io/) project. 2 | The Font Awesome font is licensed under the SIL OFL 1.1: 3 | - https://scripts.sil.org/OFL 4 | 5 | SVG icons source: https://github.com/encharm/Font-Awesome-SVG-PNG 6 | Font-Awesome-SVG-PNG is licensed under the MIT license (see file license 7 | in current folder). 8 | -------------------------------------------------------------------------------- /web/static/admin/img/calendar-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /web/static/admin/img/gis/move_vertex_off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/static/admin/img/gis/move_vertex_on.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/static/admin/img/icon-addlink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/static/admin/img/icon-alert.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/static/admin/img/icon-calendar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /web/static/admin/img/icon-changelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/static/admin/img/icon-clock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /web/static/admin/img/icon-deletelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/static/admin/img/icon-no.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/static/admin/img/icon-unknown-alt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/static/admin/img/icon-unknown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/static/admin/img/icon-viewlink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/static/admin/img/icon-yes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/static/admin/img/inline-delete.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/static/admin/img/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/static/admin/img/selector-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /web/static/admin/img/sorting-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /web/static/admin/img/tooltag-add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/static/admin/img/tooltag-arrowright.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/static/admin/js/SelectBox.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | { 3 | const SelectBox = { 4 | cache: {}, 5 | init: function(id) { 6 | const box = document.getElementById(id); 7 | SelectBox.cache[id] = []; 8 | const cache = SelectBox.cache[id]; 9 | for (const node of box.options) { 10 | cache.push({value: node.value, text: node.text, displayed: 1}); 11 | } 12 | }, 13 | redisplay: function(id) { 14 | // Repopulate HTML select box from cache 15 | const box = document.getElementById(id); 16 | const scroll_value_from_top = box.scrollTop; 17 | box.innerHTML = ''; 18 | for (const node of SelectBox.cache[id]) { 19 | if (node.displayed) { 20 | const new_option = new Option(node.text, node.value, false, false); 21 | // Shows a tooltip when hovering over the option 22 | new_option.title = node.text; 23 | box.appendChild(new_option); 24 | } 25 | } 26 | box.scrollTop = scroll_value_from_top; 27 | }, 28 | filter: function(id, text) { 29 | // Redisplay the HTML select box, displaying only the choices containing ALL 30 | // the words in text. (It's an AND search.) 31 | const tokens = text.toLowerCase().split(/\s+/); 32 | for (const node of SelectBox.cache[id]) { 33 | node.displayed = 1; 34 | const node_text = node.text.toLowerCase(); 35 | for (const token of tokens) { 36 | if (!node_text.includes(token)) { 37 | node.displayed = 0; 38 | break; // Once the first token isn't found we're done 39 | } 40 | } 41 | } 42 | SelectBox.redisplay(id); 43 | }, 44 | delete_from_cache: function(id, value) { 45 | let delete_index = null; 46 | const cache = SelectBox.cache[id]; 47 | for (const [i, node] of cache.entries()) { 48 | if (node.value === value) { 49 | delete_index = i; 50 | break; 51 | } 52 | } 53 | cache.splice(delete_index, 1); 54 | }, 55 | add_to_cache: function(id, option) { 56 | SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1}); 57 | }, 58 | cache_contains: function(id, value) { 59 | // Check if an item is contained in the cache 60 | for (const node of SelectBox.cache[id]) { 61 | if (node.value === value) { 62 | return true; 63 | } 64 | } 65 | return false; 66 | }, 67 | move: function(from, to) { 68 | const from_box = document.getElementById(from); 69 | for (const option of from_box.options) { 70 | const option_value = option.value; 71 | if (option.selected && SelectBox.cache_contains(from, option_value)) { 72 | SelectBox.add_to_cache(to, {value: option_value, text: option.text, displayed: 1}); 73 | SelectBox.delete_from_cache(from, option_value); 74 | } 75 | } 76 | SelectBox.redisplay(from); 77 | SelectBox.redisplay(to); 78 | }, 79 | move_all: function(from, to) { 80 | const from_box = document.getElementById(from); 81 | for (const option of from_box.options) { 82 | const option_value = option.value; 83 | if (SelectBox.cache_contains(from, option_value)) { 84 | SelectBox.add_to_cache(to, {value: option_value, text: option.text, displayed: 1}); 85 | SelectBox.delete_from_cache(from, option_value); 86 | } 87 | } 88 | SelectBox.redisplay(from); 89 | SelectBox.redisplay(to); 90 | }, 91 | sort: function(id) { 92 | SelectBox.cache[id].sort(function(a, b) { 93 | a = a.text.toLowerCase(); 94 | b = b.text.toLowerCase(); 95 | if (a > b) { 96 | return 1; 97 | } 98 | if (a < b) { 99 | return -1; 100 | } 101 | return 0; 102 | } ); 103 | }, 104 | select_all: function(id) { 105 | const box = document.getElementById(id); 106 | for (const option of box.options) { 107 | option.selected = true; 108 | } 109 | } 110 | }; 111 | window.SelectBox = SelectBox; 112 | } 113 | -------------------------------------------------------------------------------- /web/static/admin/js/actions.js: -------------------------------------------------------------------------------- 1 | /*global gettext, interpolate, ngettext*/ 2 | 'use strict'; 3 | { 4 | function show(selector) { 5 | document.querySelectorAll(selector).forEach(function(el) { 6 | el.classList.remove('hidden'); 7 | }); 8 | } 9 | 10 | function hide(selector) { 11 | document.querySelectorAll(selector).forEach(function(el) { 12 | el.classList.add('hidden'); 13 | }); 14 | } 15 | 16 | function showQuestion(options) { 17 | hide(options.acrossClears); 18 | show(options.acrossQuestions); 19 | hide(options.allContainer); 20 | } 21 | 22 | function showClear(options) { 23 | show(options.acrossClears); 24 | hide(options.acrossQuestions); 25 | document.querySelector(options.actionContainer).classList.remove(options.selectedClass); 26 | show(options.allContainer); 27 | hide(options.counterContainer); 28 | } 29 | 30 | function reset(options) { 31 | hide(options.acrossClears); 32 | hide(options.acrossQuestions); 33 | hide(options.allContainer); 34 | show(options.counterContainer); 35 | } 36 | 37 | function clearAcross(options) { 38 | reset(options); 39 | document.querySelector(options.acrossInput).value = 0; 40 | document.querySelector(options.actionContainer).classList.remove(options.selectedClass); 41 | } 42 | 43 | function checker(actionCheckboxes, options, checked) { 44 | if (checked) { 45 | showQuestion(options); 46 | } else { 47 | reset(options); 48 | } 49 | actionCheckboxes.forEach(function(el) { 50 | el.checked = checked; 51 | el.closest('tr').classList.toggle(options.selectedClass, checked); 52 | }); 53 | } 54 | 55 | function updateCounter(actionCheckboxes, options) { 56 | const sel = Array.from(actionCheckboxes).filter(function(el) { 57 | return el.checked; 58 | }).length; 59 | const counter = document.querySelector(options.counterContainer); 60 | // data-actions-icnt is defined in the generated HTML 61 | // and contains the total amount of objects in the queryset 62 | const actions_icnt = Number(counter.dataset.actionsIcnt); 63 | counter.textContent = interpolate( 64 | ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), { 65 | sel: sel, 66 | cnt: actions_icnt 67 | }, true); 68 | const allToggle = document.getElementById(options.allToggleId); 69 | allToggle.checked = sel === actionCheckboxes.length; 70 | if (allToggle.checked) { 71 | showQuestion(options); 72 | } else { 73 | clearAcross(options); 74 | } 75 | } 76 | 77 | const defaults = { 78 | actionContainer: "div.actions", 79 | counterContainer: "span.action-counter", 80 | allContainer: "div.actions span.all", 81 | acrossInput: "div.actions input.select-across", 82 | acrossQuestions: "div.actions span.question", 83 | acrossClears: "div.actions span.clear", 84 | allToggleId: "action-toggle", 85 | selectedClass: "selected" 86 | }; 87 | 88 | window.Actions = function(actionCheckboxes, options) { 89 | options = Object.assign({}, defaults, options); 90 | let list_editable_changed = false; 91 | let lastChecked = null; 92 | let shiftPressed = false; 93 | 94 | document.addEventListener('keydown', (event) => { 95 | shiftPressed = event.shiftKey; 96 | }); 97 | 98 | document.addEventListener('keyup', (event) => { 99 | shiftPressed = event.shiftKey; 100 | }); 101 | 102 | document.getElementById(options.allToggleId).addEventListener('click', function(event) { 103 | checker(actionCheckboxes, options, this.checked); 104 | updateCounter(actionCheckboxes, options); 105 | }); 106 | 107 | document.querySelectorAll(options.acrossQuestions + " a").forEach(function(el) { 108 | el.addEventListener('click', function(event) { 109 | event.preventDefault(); 110 | const acrossInput = document.querySelector(options.acrossInput); 111 | acrossInput.value = 1; 112 | showClear(options); 113 | }); 114 | }); 115 | 116 | document.querySelectorAll(options.acrossClears + " a").forEach(function(el) { 117 | el.addEventListener('click', function(event) { 118 | event.preventDefault(); 119 | document.getElementById(options.allToggleId).checked = false; 120 | clearAcross(options); 121 | checker(actionCheckboxes, options, false); 122 | updateCounter(actionCheckboxes, options); 123 | }); 124 | }); 125 | 126 | function affectedCheckboxes(target, withModifier) { 127 | const multiSelect = (lastChecked && withModifier && lastChecked !== target); 128 | if (!multiSelect) { 129 | return [target]; 130 | } 131 | const checkboxes = Array.from(actionCheckboxes); 132 | const targetIndex = checkboxes.findIndex(el => el === target); 133 | const lastCheckedIndex = checkboxes.findIndex(el => el === lastChecked); 134 | const startIndex = Math.min(targetIndex, lastCheckedIndex); 135 | const endIndex = Math.max(targetIndex, lastCheckedIndex); 136 | const filtered = checkboxes.filter((el, index) => (startIndex <= index) && (index <= endIndex)); 137 | return filtered; 138 | }; 139 | 140 | Array.from(document.getElementById('result_list').tBodies).forEach(function(el) { 141 | el.addEventListener('change', function(event) { 142 | const target = event.target; 143 | if (target.classList.contains('action-select')) { 144 | const checkboxes = affectedCheckboxes(target, shiftPressed); 145 | checker(checkboxes, options, target.checked); 146 | updateCounter(actionCheckboxes, options); 147 | lastChecked = target; 148 | } else { 149 | list_editable_changed = true; 150 | } 151 | }); 152 | }); 153 | 154 | document.querySelector('#changelist-form button[name=index]').addEventListener('click', function() { 155 | if (list_editable_changed) { 156 | const confirmed = confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.")); 157 | if (!confirmed) { 158 | event.preventDefault(); 159 | } 160 | } 161 | }); 162 | 163 | const el = document.querySelector('#changelist-form input[name=_save]'); 164 | // The button does not exist if no fields are editable. 165 | if (el) { 166 | el.addEventListener('click', function(event) { 167 | if (document.querySelector('[name=action]').value) { 168 | const text = list_editable_changed 169 | ? gettext("You have selected an action, but you haven’t saved your changes to individual fields yet. Please click OK to save. You’ll need to re-run the action.") 170 | : gettext("You have selected an action, and you haven’t made any changes on individual fields. You’re probably looking for the Go button rather than the Save button."); 171 | if (!confirm(text)) { 172 | event.preventDefault(); 173 | } 174 | } 175 | }); 176 | } 177 | }; 178 | 179 | // Call function fn when the DOM is loaded and ready. If it is already 180 | // loaded, call the function now. 181 | // http://youmightnotneedjquery.com/#ready 182 | function ready(fn) { 183 | if (document.readyState !== 'loading') { 184 | fn(); 185 | } else { 186 | document.addEventListener('DOMContentLoaded', fn); 187 | } 188 | } 189 | 190 | ready(function() { 191 | const actionsEls = document.querySelectorAll('tr input.action-select'); 192 | if (actionsEls.length > 0) { 193 | Actions(actionsEls); 194 | } 195 | }); 196 | } 197 | -------------------------------------------------------------------------------- /web/static/admin/js/admin/RelatedObjectLookups.js: -------------------------------------------------------------------------------- 1 | /*global SelectBox, interpolate*/ 2 | // Handles related-objects functionality: lookup link for raw_id_fields 3 | // and Add Another links. 4 | 'use strict'; 5 | { 6 | const $ = django.jQuery; 7 | 8 | function showAdminPopup(triggeringLink, name_regexp, add_popup) { 9 | const name = triggeringLink.id.replace(name_regexp, ''); 10 | const href = new URL(triggeringLink.href); 11 | if (add_popup) { 12 | href.searchParams.set('_popup', 1); 13 | } 14 | const win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); 15 | win.focus(); 16 | return false; 17 | } 18 | 19 | function showRelatedObjectLookupPopup(triggeringLink) { 20 | return showAdminPopup(triggeringLink, /^lookup_/, true); 21 | } 22 | 23 | function dismissRelatedLookupPopup(win, chosenId) { 24 | const name = win.name; 25 | const elem = document.getElementById(name); 26 | if (elem.classList.contains('vManyToManyRawIdAdminField') && elem.value) { 27 | elem.value += ',' + chosenId; 28 | } else { 29 | document.getElementById(name).value = chosenId; 30 | } 31 | win.close(); 32 | } 33 | 34 | function showRelatedObjectPopup(triggeringLink) { 35 | return showAdminPopup(triggeringLink, /^(change|add|delete)_/, false); 36 | } 37 | 38 | function updateRelatedObjectLinks(triggeringLink) { 39 | const $this = $(triggeringLink); 40 | const siblings = $this.nextAll('.view-related, .change-related, .delete-related'); 41 | if (!siblings.length) { 42 | return; 43 | } 44 | const value = $this.val(); 45 | if (value) { 46 | siblings.each(function() { 47 | const elm = $(this); 48 | elm.attr('href', elm.attr('data-href-template').replace('__fk__', value)); 49 | }); 50 | } else { 51 | siblings.removeAttr('href'); 52 | } 53 | } 54 | 55 | function dismissAddRelatedObjectPopup(win, newId, newRepr) { 56 | const name = win.name; 57 | const elem = document.getElementById(name); 58 | if (elem) { 59 | const elemName = elem.nodeName.toUpperCase(); 60 | if (elemName === 'SELECT') { 61 | elem.options[elem.options.length] = new Option(newRepr, newId, true, true); 62 | } else if (elemName === 'INPUT') { 63 | if (elem.classList.contains('vManyToManyRawIdAdminField') && elem.value) { 64 | elem.value += ',' + newId; 65 | } else { 66 | elem.value = newId; 67 | } 68 | } 69 | // Trigger a change event to update related links if required. 70 | $(elem).trigger('change'); 71 | } else { 72 | const toId = name + "_to"; 73 | const o = new Option(newRepr, newId); 74 | SelectBox.add_to_cache(toId, o); 75 | SelectBox.redisplay(toId); 76 | } 77 | win.close(); 78 | } 79 | 80 | function dismissChangeRelatedObjectPopup(win, objId, newRepr, newId) { 81 | const id = win.name.replace(/^edit_/, ''); 82 | const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]); 83 | const selects = $(selectsSelector); 84 | selects.find('option').each(function() { 85 | if (this.value === objId) { 86 | this.textContent = newRepr; 87 | this.value = newId; 88 | } 89 | }); 90 | selects.next().find('.select2-selection__rendered').each(function() { 91 | // The element can have a clear button as a child. 92 | // Use the lastChild to modify only the displayed value. 93 | this.lastChild.textContent = newRepr; 94 | this.title = newRepr; 95 | }); 96 | win.close(); 97 | } 98 | 99 | function dismissDeleteRelatedObjectPopup(win, objId) { 100 | const id = win.name.replace(/^delete_/, ''); 101 | const selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]); 102 | const selects = $(selectsSelector); 103 | selects.find('option').each(function() { 104 | if (this.value === objId) { 105 | $(this).remove(); 106 | } 107 | }).trigger('change'); 108 | win.close(); 109 | } 110 | 111 | window.showRelatedObjectLookupPopup = showRelatedObjectLookupPopup; 112 | window.dismissRelatedLookupPopup = dismissRelatedLookupPopup; 113 | window.showRelatedObjectPopup = showRelatedObjectPopup; 114 | window.updateRelatedObjectLinks = updateRelatedObjectLinks; 115 | window.dismissAddRelatedObjectPopup = dismissAddRelatedObjectPopup; 116 | window.dismissChangeRelatedObjectPopup = dismissChangeRelatedObjectPopup; 117 | window.dismissDeleteRelatedObjectPopup = dismissDeleteRelatedObjectPopup; 118 | 119 | // Kept for backward compatibility 120 | window.showAddAnotherPopup = showRelatedObjectPopup; 121 | window.dismissAddAnotherPopup = dismissAddRelatedObjectPopup; 122 | 123 | $(document).ready(function() { 124 | $("a[data-popup-opener]").on('click', function(event) { 125 | event.preventDefault(); 126 | opener.dismissRelatedLookupPopup(window, $(this).data("popup-opener")); 127 | }); 128 | $('body').on('click', '.related-widget-wrapper-link', function(e) { 129 | e.preventDefault(); 130 | if (this.href) { 131 | const event = $.Event('django:show-related', {href: this.href}); 132 | $(this).trigger(event); 133 | if (!event.isDefaultPrevented()) { 134 | showRelatedObjectPopup(this); 135 | } 136 | } 137 | }); 138 | $('body').on('change', '.related-widget-wrapper select', function(e) { 139 | const event = $.Event('django:update-related'); 140 | $(this).trigger(event); 141 | if (!event.isDefaultPrevented()) { 142 | updateRelatedObjectLinks(this); 143 | } 144 | }); 145 | $('.related-widget-wrapper select').trigger('change'); 146 | $('body').on('click', '.related-lookup', function(e) { 147 | e.preventDefault(); 148 | const event = $.Event('django:lookup-related'); 149 | $(this).trigger(event); 150 | if (!event.isDefaultPrevented()) { 151 | showRelatedObjectLookupPopup(this); 152 | } 153 | }); 154 | }); 155 | } 156 | -------------------------------------------------------------------------------- /web/static/admin/js/autocomplete.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | { 3 | const $ = django.jQuery; 4 | const init = function($element, options) { 5 | const settings = $.extend({ 6 | ajax: { 7 | data: function(params) { 8 | return { 9 | term: params.term, 10 | page: params.page, 11 | app_label: $element.data('app-label'), 12 | model_name: $element.data('model-name'), 13 | field_name: $element.data('field-name') 14 | }; 15 | } 16 | } 17 | }, options); 18 | $element.select2(settings); 19 | }; 20 | 21 | $.fn.djangoAdminSelect2 = function(options) { 22 | const settings = $.extend({}, options); 23 | $.each(this, function(i, element) { 24 | const $element = $(element); 25 | init($element, settings); 26 | }); 27 | return this; 28 | }; 29 | 30 | $(function() { 31 | // Initialize all autocomplete widgets except the one in the template 32 | // form used when a new formset is added. 33 | $('.admin-autocomplete').not('[name*=__prefix__]').djangoAdminSelect2(); 34 | }); 35 | 36 | $(document).on('formset:added', (function() { 37 | return function(event, $newFormset) { 38 | return $newFormset.find('.admin-autocomplete').djangoAdminSelect2(); 39 | }; 40 | })(this)); 41 | } 42 | -------------------------------------------------------------------------------- /web/static/admin/js/calendar.js: -------------------------------------------------------------------------------- 1 | /*global gettext, pgettext, get_format, quickElement, removeChildren*/ 2 | /* 3 | calendar.js - Calendar functions by Adrian Holovaty 4 | depends on core.js for utility functions like removeChildren or quickElement 5 | */ 6 | 'use strict'; 7 | { 8 | // CalendarNamespace -- Provides a collection of HTML calendar-related helper functions 9 | const CalendarNamespace = { 10 | monthsOfYear: [ 11 | gettext('January'), 12 | gettext('February'), 13 | gettext('March'), 14 | gettext('April'), 15 | gettext('May'), 16 | gettext('June'), 17 | gettext('July'), 18 | gettext('August'), 19 | gettext('September'), 20 | gettext('October'), 21 | gettext('November'), 22 | gettext('December') 23 | ], 24 | monthsOfYearAbbrev: [ 25 | pgettext('abbrev. month January', 'Jan'), 26 | pgettext('abbrev. month February', 'Feb'), 27 | pgettext('abbrev. month March', 'Mar'), 28 | pgettext('abbrev. month April', 'Apr'), 29 | pgettext('abbrev. month May', 'May'), 30 | pgettext('abbrev. month June', 'Jun'), 31 | pgettext('abbrev. month July', 'Jul'), 32 | pgettext('abbrev. month August', 'Aug'), 33 | pgettext('abbrev. month September', 'Sep'), 34 | pgettext('abbrev. month October', 'Oct'), 35 | pgettext('abbrev. month November', 'Nov'), 36 | pgettext('abbrev. month December', 'Dec') 37 | ], 38 | daysOfWeek: [ 39 | pgettext('one letter Sunday', 'S'), 40 | pgettext('one letter Monday', 'M'), 41 | pgettext('one letter Tuesday', 'T'), 42 | pgettext('one letter Wednesday', 'W'), 43 | pgettext('one letter Thursday', 'T'), 44 | pgettext('one letter Friday', 'F'), 45 | pgettext('one letter Saturday', 'S') 46 | ], 47 | firstDayOfWeek: parseInt(get_format('FIRST_DAY_OF_WEEK')), 48 | isLeapYear: function(year) { 49 | return (((year % 4) === 0) && ((year % 100) !== 0 ) || ((year % 400) === 0)); 50 | }, 51 | getDaysInMonth: function(month, year) { 52 | let days; 53 | if (month === 1 || month === 3 || month === 5 || month === 7 || month === 8 || month === 10 || month === 12) { 54 | days = 31; 55 | } 56 | else if (month === 4 || month === 6 || month === 9 || month === 11) { 57 | days = 30; 58 | } 59 | else if (month === 2 && CalendarNamespace.isLeapYear(year)) { 60 | days = 29; 61 | } 62 | else { 63 | days = 28; 64 | } 65 | return days; 66 | }, 67 | draw: function(month, year, div_id, callback, selected) { // month = 1-12, year = 1-9999 68 | const today = new Date(); 69 | const todayDay = today.getDate(); 70 | const todayMonth = today.getMonth() + 1; 71 | const todayYear = today.getFullYear(); 72 | let todayClass = ''; 73 | 74 | // Use UTC functions here because the date field does not contain time 75 | // and using the UTC function variants prevent the local time offset 76 | // from altering the date, specifically the day field. For example: 77 | // 78 | // ``` 79 | // var x = new Date('2013-10-02'); 80 | // var day = x.getDate(); 81 | // ``` 82 | // 83 | // The day variable above will be 1 instead of 2 in, say, US Pacific time 84 | // zone. 85 | let isSelectedMonth = false; 86 | if (typeof selected !== 'undefined') { 87 | isSelectedMonth = (selected.getUTCFullYear() === year && (selected.getUTCMonth() + 1) === month); 88 | } 89 | 90 | month = parseInt(month); 91 | year = parseInt(year); 92 | const calDiv = document.getElementById(div_id); 93 | removeChildren(calDiv); 94 | const calTable = document.createElement('table'); 95 | quickElement('caption', calTable, CalendarNamespace.monthsOfYear[month - 1] + ' ' + year); 96 | const tableBody = quickElement('tbody', calTable); 97 | 98 | // Draw days-of-week header 99 | let tableRow = quickElement('tr', tableBody); 100 | for (let i = 0; i < 7; i++) { 101 | quickElement('th', tableRow, CalendarNamespace.daysOfWeek[(i + CalendarNamespace.firstDayOfWeek) % 7]); 102 | } 103 | 104 | const startingPos = new Date(year, month - 1, 1 - CalendarNamespace.firstDayOfWeek).getDay(); 105 | const days = CalendarNamespace.getDaysInMonth(month, year); 106 | 107 | let nonDayCell; 108 | 109 | // Draw blanks before first of month 110 | tableRow = quickElement('tr', tableBody); 111 | for (let i = 0; i < startingPos; i++) { 112 | nonDayCell = quickElement('td', tableRow, ' '); 113 | nonDayCell.className = "nonday"; 114 | } 115 | 116 | function calendarMonth(y, m) { 117 | function onClick(e) { 118 | e.preventDefault(); 119 | callback(y, m, this.textContent); 120 | } 121 | return onClick; 122 | } 123 | 124 | // Draw days of month 125 | let currentDay = 1; 126 | for (let i = startingPos; currentDay <= days; i++) { 127 | if (i % 7 === 0 && currentDay !== 1) { 128 | tableRow = quickElement('tr', tableBody); 129 | } 130 | if ((currentDay === todayDay) && (month === todayMonth) && (year === todayYear)) { 131 | todayClass = 'today'; 132 | } else { 133 | todayClass = ''; 134 | } 135 | 136 | // use UTC function; see above for explanation. 137 | if (isSelectedMonth && currentDay === selected.getUTCDate()) { 138 | if (todayClass !== '') { 139 | todayClass += " "; 140 | } 141 | todayClass += "selected"; 142 | } 143 | 144 | const cell = quickElement('td', tableRow, '', 'class', todayClass); 145 | const link = quickElement('a', cell, currentDay, 'href', '#'); 146 | link.addEventListener('click', calendarMonth(year, month)); 147 | currentDay++; 148 | } 149 | 150 | // Draw blanks after end of month (optional, but makes for valid code) 151 | while (tableRow.childNodes.length < 7) { 152 | nonDayCell = quickElement('td', tableRow, ' '); 153 | nonDayCell.className = "nonday"; 154 | } 155 | 156 | calDiv.appendChild(calTable); 157 | } 158 | }; 159 | 160 | // Calendar -- A calendar instance 161 | function Calendar(div_id, callback, selected) { 162 | // div_id (string) is the ID of the element in which the calendar will 163 | // be displayed 164 | // callback (string) is the name of a JavaScript function that will be 165 | // called with the parameters (year, month, day) when a day in the 166 | // calendar is clicked 167 | this.div_id = div_id; 168 | this.callback = callback; 169 | this.today = new Date(); 170 | this.currentMonth = this.today.getMonth() + 1; 171 | this.currentYear = this.today.getFullYear(); 172 | if (typeof selected !== 'undefined') { 173 | this.selected = selected; 174 | } 175 | } 176 | Calendar.prototype = { 177 | drawCurrent: function() { 178 | CalendarNamespace.draw(this.currentMonth, this.currentYear, this.div_id, this.callback, this.selected); 179 | }, 180 | drawDate: function(month, year, selected) { 181 | this.currentMonth = month; 182 | this.currentYear = year; 183 | 184 | if(selected) { 185 | this.selected = selected; 186 | } 187 | 188 | this.drawCurrent(); 189 | }, 190 | drawPreviousMonth: function() { 191 | if (this.currentMonth === 1) { 192 | this.currentMonth = 12; 193 | this.currentYear--; 194 | } 195 | else { 196 | this.currentMonth--; 197 | } 198 | this.drawCurrent(); 199 | }, 200 | drawNextMonth: function() { 201 | if (this.currentMonth === 12) { 202 | this.currentMonth = 1; 203 | this.currentYear++; 204 | } 205 | else { 206 | this.currentMonth++; 207 | } 208 | this.drawCurrent(); 209 | }, 210 | drawPreviousYear: function() { 211 | this.currentYear--; 212 | this.drawCurrent(); 213 | }, 214 | drawNextYear: function() { 215 | this.currentYear++; 216 | this.drawCurrent(); 217 | } 218 | }; 219 | window.Calendar = Calendar; 220 | window.CalendarNamespace = CalendarNamespace; 221 | } 222 | -------------------------------------------------------------------------------- /web/static/admin/js/cancel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | { 3 | // Call function fn when the DOM is loaded and ready. If it is already 4 | // loaded, call the function now. 5 | // http://youmightnotneedjquery.com/#ready 6 | function ready(fn) { 7 | if (document.readyState !== 'loading') { 8 | fn(); 9 | } else { 10 | document.addEventListener('DOMContentLoaded', fn); 11 | } 12 | } 13 | 14 | ready(function() { 15 | function handleClick(event) { 16 | event.preventDefault(); 17 | const params = new URLSearchParams(window.location.search); 18 | if (params.has('_popup')) { 19 | window.close(); // Close the popup. 20 | } else { 21 | window.history.back(); // Otherwise, go back. 22 | } 23 | } 24 | 25 | document.querySelectorAll('.cancel-link').forEach(function(el) { 26 | el.addEventListener('click', handleClick); 27 | }); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /web/static/admin/js/change_form.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | { 3 | const inputTags = ['BUTTON', 'INPUT', 'SELECT', 'TEXTAREA']; 4 | const modelName = document.getElementById('django-admin-form-add-constants').dataset.modelName; 5 | if (modelName) { 6 | const form = document.getElementById(modelName + '_form'); 7 | for (const element of form.elements) { 8 | // HTMLElement.offsetParent returns null when the element is not 9 | // rendered. 10 | if (inputTags.includes(element.tagName) && !element.disabled && element.offsetParent) { 11 | element.focus(); 12 | break; 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /web/static/admin/js/collapse.js: -------------------------------------------------------------------------------- 1 | /*global gettext*/ 2 | 'use strict'; 3 | { 4 | window.addEventListener('load', function() { 5 | // Add anchor tag for Show/Hide link 6 | const fieldsets = document.querySelectorAll('fieldset.collapse'); 7 | for (const [i, elem] of fieldsets.entries()) { 8 | // Don't hide if fields in this fieldset have errors 9 | if (elem.querySelectorAll('div.errors, ul.errorlist').length === 0) { 10 | elem.classList.add('collapsed'); 11 | const h2 = elem.querySelector('h2'); 12 | const link = document.createElement('a'); 13 | link.id = 'fieldsetcollapser' + i; 14 | link.className = 'collapse-toggle'; 15 | link.href = '#'; 16 | link.textContent = gettext('Show'); 17 | h2.appendChild(document.createTextNode(' (')); 18 | h2.appendChild(link); 19 | h2.appendChild(document.createTextNode(')')); 20 | } 21 | } 22 | // Add toggle to hide/show anchor tag 23 | const toggleFunc = function(ev) { 24 | if (ev.target.matches('.collapse-toggle')) { 25 | ev.preventDefault(); 26 | ev.stopPropagation(); 27 | const fieldset = ev.target.closest('fieldset'); 28 | if (fieldset.classList.contains('collapsed')) { 29 | // Show 30 | ev.target.textContent = gettext('Hide'); 31 | fieldset.classList.remove('collapsed'); 32 | } else { 33 | // Hide 34 | ev.target.textContent = gettext('Show'); 35 | fieldset.classList.add('collapsed'); 36 | } 37 | } 38 | }; 39 | document.querySelectorAll('fieldset.module').forEach(function(el) { 40 | el.addEventListener('click', toggleFunc); 41 | }); 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /web/static/admin/js/core.js: -------------------------------------------------------------------------------- 1 | // Core javascript helper functions 2 | 'use strict'; 3 | 4 | // quickElement(tagType, parentReference [, textInChildNode, attribute, attributeValue ...]); 5 | function quickElement() { 6 | const obj = document.createElement(arguments[0]); 7 | if (arguments[2]) { 8 | const textNode = document.createTextNode(arguments[2]); 9 | obj.appendChild(textNode); 10 | } 11 | const len = arguments.length; 12 | for (let i = 3; i < len; i += 2) { 13 | obj.setAttribute(arguments[i], arguments[i + 1]); 14 | } 15 | arguments[1].appendChild(obj); 16 | return obj; 17 | } 18 | 19 | // "a" is reference to an object 20 | function removeChildren(a) { 21 | while (a.hasChildNodes()) { 22 | a.removeChild(a.lastChild); 23 | } 24 | } 25 | 26 | // ---------------------------------------------------------------------------- 27 | // Find-position functions by PPK 28 | // See https://www.quirksmode.org/js/findpos.html 29 | // ---------------------------------------------------------------------------- 30 | function findPosX(obj) { 31 | let curleft = 0; 32 | if (obj.offsetParent) { 33 | while (obj.offsetParent) { 34 | curleft += obj.offsetLeft - obj.scrollLeft; 35 | obj = obj.offsetParent; 36 | } 37 | } else if (obj.x) { 38 | curleft += obj.x; 39 | } 40 | return curleft; 41 | } 42 | 43 | function findPosY(obj) { 44 | let curtop = 0; 45 | if (obj.offsetParent) { 46 | while (obj.offsetParent) { 47 | curtop += obj.offsetTop - obj.scrollTop; 48 | obj = obj.offsetParent; 49 | } 50 | } else if (obj.y) { 51 | curtop += obj.y; 52 | } 53 | return curtop; 54 | } 55 | 56 | //----------------------------------------------------------------------------- 57 | // Date object extensions 58 | // ---------------------------------------------------------------------------- 59 | { 60 | Date.prototype.getTwelveHours = function() { 61 | return this.getHours() % 12 || 12; 62 | }; 63 | 64 | Date.prototype.getTwoDigitMonth = function() { 65 | return (this.getMonth() < 9) ? '0' + (this.getMonth() + 1) : (this.getMonth() + 1); 66 | }; 67 | 68 | Date.prototype.getTwoDigitDate = function() { 69 | return (this.getDate() < 10) ? '0' + this.getDate() : this.getDate(); 70 | }; 71 | 72 | Date.prototype.getTwoDigitTwelveHour = function() { 73 | return (this.getTwelveHours() < 10) ? '0' + this.getTwelveHours() : this.getTwelveHours(); 74 | }; 75 | 76 | Date.prototype.getTwoDigitHour = function() { 77 | return (this.getHours() < 10) ? '0' + this.getHours() : this.getHours(); 78 | }; 79 | 80 | Date.prototype.getTwoDigitMinute = function() { 81 | return (this.getMinutes() < 10) ? '0' + this.getMinutes() : this.getMinutes(); 82 | }; 83 | 84 | Date.prototype.getTwoDigitSecond = function() { 85 | return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds(); 86 | }; 87 | 88 | Date.prototype.getAbbrevMonthName = function() { 89 | return typeof window.CalendarNamespace === "undefined" 90 | ? this.getTwoDigitMonth() 91 | : window.CalendarNamespace.monthsOfYearAbbrev[this.getMonth()]; 92 | }; 93 | 94 | Date.prototype.getFullMonthName = function() { 95 | return typeof window.CalendarNamespace === "undefined" 96 | ? this.getTwoDigitMonth() 97 | : window.CalendarNamespace.monthsOfYear[this.getMonth()]; 98 | }; 99 | 100 | Date.prototype.strftime = function(format) { 101 | const fields = { 102 | b: this.getAbbrevMonthName(), 103 | B: this.getFullMonthName(), 104 | c: this.toString(), 105 | d: this.getTwoDigitDate(), 106 | H: this.getTwoDigitHour(), 107 | I: this.getTwoDigitTwelveHour(), 108 | m: this.getTwoDigitMonth(), 109 | M: this.getTwoDigitMinute(), 110 | p: (this.getHours() >= 12) ? 'PM' : 'AM', 111 | S: this.getTwoDigitSecond(), 112 | w: '0' + this.getDay(), 113 | x: this.toLocaleDateString(), 114 | X: this.toLocaleTimeString(), 115 | y: ('' + this.getFullYear()).substr(2, 4), 116 | Y: '' + this.getFullYear(), 117 | '%': '%' 118 | }; 119 | let result = '', i = 0; 120 | while (i < format.length) { 121 | if (format.charAt(i) === '%') { 122 | result = result + fields[format.charAt(i + 1)]; 123 | ++i; 124 | } 125 | else { 126 | result = result + format.charAt(i); 127 | } 128 | ++i; 129 | } 130 | return result; 131 | }; 132 | 133 | // ---------------------------------------------------------------------------- 134 | // String object extensions 135 | // ---------------------------------------------------------------------------- 136 | String.prototype.strptime = function(format) { 137 | const split_format = format.split(/[.\-/]/); 138 | const date = this.split(/[.\-/]/); 139 | let i = 0; 140 | let day, month, year; 141 | while (i < split_format.length) { 142 | switch (split_format[i]) { 143 | case "%d": 144 | day = date[i]; 145 | break; 146 | case "%m": 147 | month = date[i] - 1; 148 | break; 149 | case "%Y": 150 | year = date[i]; 151 | break; 152 | case "%y": 153 | // A %y value in the range of [00, 68] is in the current 154 | // century, while [69, 99] is in the previous century, 155 | // according to the Open Group Specification. 156 | if (parseInt(date[i], 10) >= 69) { 157 | year = date[i]; 158 | } else { 159 | year = (new Date(Date.UTC(date[i], 0))).getUTCFullYear() + 100; 160 | } 161 | break; 162 | } 163 | ++i; 164 | } 165 | // Create Date object from UTC since the parsed value is supposed to be 166 | // in UTC, not local time. Also, the calendar uses UTC functions for 167 | // date extraction. 168 | return new Date(Date.UTC(year, month, day)); 169 | }; 170 | } 171 | -------------------------------------------------------------------------------- /web/static/admin/js/jquery.init.js: -------------------------------------------------------------------------------- 1 | /*global jQuery:false*/ 2 | 'use strict'; 3 | /* Puts the included jQuery into our own namespace using noConflict and passing 4 | * it 'true'. This ensures that the included jQuery doesn't pollute the global 5 | * namespace (i.e. this preserves pre-existing values for both window.$ and 6 | * window.jQuery). 7 | */ 8 | window.django = {jQuery: jQuery.noConflict(true)}; 9 | -------------------------------------------------------------------------------- /web/static/admin/js/nav_sidebar.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | { 3 | const toggleNavSidebar = document.getElementById('toggle-nav-sidebar'); 4 | if (toggleNavSidebar !== null) { 5 | const navLinks = document.querySelectorAll('#nav-sidebar a'); 6 | function disableNavLinkTabbing() { 7 | for (const navLink of navLinks) { 8 | navLink.tabIndex = -1; 9 | } 10 | } 11 | function enableNavLinkTabbing() { 12 | for (const navLink of navLinks) { 13 | navLink.tabIndex = 0; 14 | } 15 | } 16 | 17 | const main = document.getElementById('main'); 18 | let navSidebarIsOpen = localStorage.getItem('django.admin.navSidebarIsOpen'); 19 | if (navSidebarIsOpen === null) { 20 | navSidebarIsOpen = 'true'; 21 | } 22 | if (navSidebarIsOpen === 'false') { 23 | disableNavLinkTabbing(); 24 | } 25 | main.classList.toggle('shifted', navSidebarIsOpen === 'true'); 26 | 27 | toggleNavSidebar.addEventListener('click', function() { 28 | if (navSidebarIsOpen === 'true') { 29 | navSidebarIsOpen = 'false'; 30 | disableNavLinkTabbing(); 31 | } else { 32 | navSidebarIsOpen = 'true'; 33 | enableNavLinkTabbing(); 34 | } 35 | localStorage.setItem('django.admin.navSidebarIsOpen', navSidebarIsOpen); 36 | main.classList.toggle('shifted'); 37 | }); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /web/static/admin/js/popup_response.js: -------------------------------------------------------------------------------- 1 | /*global opener */ 2 | 'use strict'; 3 | { 4 | const initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse); 5 | switch(initData.action) { 6 | case 'change': 7 | opener.dismissChangeRelatedObjectPopup(window, initData.value, initData.obj, initData.new_value); 8 | break; 9 | case 'delete': 10 | opener.dismissDeleteRelatedObjectPopup(window, initData.value); 11 | break; 12 | default: 13 | opener.dismissAddRelatedObjectPopup(window, initData.value, initData.obj); 14 | break; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /web/static/admin/js/prepopulate.js: -------------------------------------------------------------------------------- 1 | /*global URLify*/ 2 | 'use strict'; 3 | { 4 | const $ = django.jQuery; 5 | $.fn.prepopulate = function(dependencies, maxLength, allowUnicode) { 6 | /* 7 | Depends on urlify.js 8 | Populates a selected field with the values of the dependent fields, 9 | URLifies and shortens the string. 10 | dependencies - array of dependent fields ids 11 | maxLength - maximum length of the URLify'd string 12 | allowUnicode - Unicode support of the URLify'd string 13 | */ 14 | return this.each(function() { 15 | const prepopulatedField = $(this); 16 | 17 | const populate = function() { 18 | // Bail if the field's value has been changed by the user 19 | if (prepopulatedField.data('_changed')) { 20 | return; 21 | } 22 | 23 | const values = []; 24 | $.each(dependencies, function(i, field) { 25 | field = $(field); 26 | if (field.val().length > 0) { 27 | values.push(field.val()); 28 | } 29 | }); 30 | prepopulatedField.val(URLify(values.join(' '), maxLength, allowUnicode)); 31 | }; 32 | 33 | prepopulatedField.data('_changed', false); 34 | prepopulatedField.on('change', function() { 35 | prepopulatedField.data('_changed', true); 36 | }); 37 | 38 | if (!prepopulatedField.val()) { 39 | $(dependencies.join(',')).on('keyup change focus', populate); 40 | } 41 | }); 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /web/static/admin/js/prepopulate_init.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | { 3 | const $ = django.jQuery; 4 | const fields = $('#django-admin-prepopulated-fields-constants').data('prepopulatedFields'); 5 | $.each(fields, function(index, field) { 6 | $('.empty-form .form-row .field-' + field.name + ', .empty-form.form-row .field-' + field.name).addClass('prepopulated_field'); 7 | $(field.id).data('dependency_list', field.dependency_list).prepopulate( 8 | field.dependency_ids, field.maxLength, field.allowUnicode 9 | ); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /web/static/admin/js/urlify.js: -------------------------------------------------------------------------------- 1 | /*global XRegExp*/ 2 | 'use strict'; 3 | { 4 | const LATIN_MAP = { 5 | 'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', 6 | 'Ç': 'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', 7 | 'Î': 'I', 'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', 8 | 'Õ': 'O', 'Ö': 'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 9 | 'Ü': 'U', 'Ű': 'U', 'Ý': 'Y', 'Þ': 'TH', 'Ÿ': 'Y', 'ß': 'ss', 'à': 'a', 10 | 'á': 'a', 'â': 'a', 'ã': 'a', 'ä': 'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 11 | 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e', 'ì': 'i', 'í': 'i', 'î': 'i', 12 | 'ï': 'i', 'ð': 'd', 'ñ': 'n', 'ò': 'o', 'ó': 'o', 'ô': 'o', 'õ': 'o', 13 | 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u', 14 | 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y' 15 | }; 16 | const LATIN_SYMBOLS_MAP = { 17 | '©': '(c)' 18 | }; 19 | const GREEK_MAP = { 20 | 'α': 'a', 'β': 'b', 'γ': 'g', 'δ': 'd', 'ε': 'e', 'ζ': 'z', 'η': 'h', 21 | 'θ': '8', 'ι': 'i', 'κ': 'k', 'λ': 'l', 'μ': 'm', 'ν': 'n', 'ξ': '3', 22 | 'ο': 'o', 'π': 'p', 'ρ': 'r', 'σ': 's', 'τ': 't', 'υ': 'y', 'φ': 'f', 23 | 'χ': 'x', 'ψ': 'ps', 'ω': 'w', 'ά': 'a', 'έ': 'e', 'ί': 'i', 'ό': 'o', 24 | 'ύ': 'y', 'ή': 'h', 'ώ': 'w', 'ς': 's', 'ϊ': 'i', 'ΰ': 'y', 'ϋ': 'y', 25 | 'ΐ': 'i', 'Α': 'A', 'Β': 'B', 'Γ': 'G', 'Δ': 'D', 'Ε': 'E', 'Ζ': 'Z', 26 | 'Η': 'H', 'Θ': '8', 'Ι': 'I', 'Κ': 'K', 'Λ': 'L', 'Μ': 'M', 'Ν': 'N', 27 | 'Ξ': '3', 'Ο': 'O', 'Π': 'P', 'Ρ': 'R', 'Σ': 'S', 'Τ': 'T', 'Υ': 'Y', 28 | 'Φ': 'F', 'Χ': 'X', 'Ψ': 'PS', 'Ω': 'W', 'Ά': 'A', 'Έ': 'E', 'Ί': 'I', 29 | 'Ό': 'O', 'Ύ': 'Y', 'Ή': 'H', 'Ώ': 'W', 'Ϊ': 'I', 'Ϋ': 'Y' 30 | }; 31 | const TURKISH_MAP = { 32 | 'ş': 's', 'Ş': 'S', 'ı': 'i', 'İ': 'I', 'ç': 'c', 'Ç': 'C', 'ü': 'u', 33 | 'Ü': 'U', 'ö': 'o', 'Ö': 'O', 'ğ': 'g', 'Ğ': 'G' 34 | }; 35 | const ROMANIAN_MAP = { 36 | 'ă': 'a', 'î': 'i', 'ș': 's', 'ț': 't', 'â': 'a', 37 | 'Ă': 'A', 'Î': 'I', 'Ș': 'S', 'Ț': 'T', 'Â': 'A' 38 | }; 39 | const RUSSIAN_MAP = { 40 | 'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo', 41 | 'ж': 'zh', 'з': 'z', 'и': 'i', 'й': 'j', 'к': 'k', 'л': 'l', 'м': 'm', 42 | 'н': 'n', 'о': 'o', 'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u', 43 | 'ф': 'f', 'х': 'h', 'ц': 'c', 'ч': 'ch', 'ш': 'sh', 'щ': 'sh', 'ъ': '', 44 | 'ы': 'y', 'ь': '', 'э': 'e', 'ю': 'yu', 'я': 'ya', 45 | 'А': 'A', 'Б': 'B', 'В': 'V', 'Г': 'G', 'Д': 'D', 'Е': 'E', 'Ё': 'Yo', 46 | 'Ж': 'Zh', 'З': 'Z', 'И': 'I', 'Й': 'J', 'К': 'K', 'Л': 'L', 'М': 'M', 47 | 'Н': 'N', 'О': 'O', 'П': 'P', 'Р': 'R', 'С': 'S', 'Т': 'T', 'У': 'U', 48 | 'Ф': 'F', 'Х': 'H', 'Ц': 'C', 'Ч': 'Ch', 'Ш': 'Sh', 'Щ': 'Sh', 'Ъ': '', 49 | 'Ы': 'Y', 'Ь': '', 'Э': 'E', 'Ю': 'Yu', 'Я': 'Ya' 50 | }; 51 | const UKRAINIAN_MAP = { 52 | 'Є': 'Ye', 'І': 'I', 'Ї': 'Yi', 'Ґ': 'G', 'є': 'ye', 'і': 'i', 53 | 'ї': 'yi', 'ґ': 'g' 54 | }; 55 | const CZECH_MAP = { 56 | 'č': 'c', 'ď': 'd', 'ě': 'e', 'ň': 'n', 'ř': 'r', 'š': 's', 'ť': 't', 57 | 'ů': 'u', 'ž': 'z', 'Č': 'C', 'Ď': 'D', 'Ě': 'E', 'Ň': 'N', 'Ř': 'R', 58 | 'Š': 'S', 'Ť': 'T', 'Ů': 'U', 'Ž': 'Z' 59 | }; 60 | const SLOVAK_MAP = { 61 | 'á': 'a', 'ä': 'a', 'č': 'c', 'ď': 'd', 'é': 'e', 'í': 'i', 'ľ': 'l', 62 | 'ĺ': 'l', 'ň': 'n', 'ó': 'o', 'ô': 'o', 'ŕ': 'r', 'š': 's', 'ť': 't', 63 | 'ú': 'u', 'ý': 'y', 'ž': 'z', 64 | 'Á': 'a', 'Ä': 'A', 'Č': 'C', 'Ď': 'D', 'É': 'E', 'Í': 'I', 'Ľ': 'L', 65 | 'Ĺ': 'L', 'Ň': 'N', 'Ó': 'O', 'Ô': 'O', 'Ŕ': 'R', 'Š': 'S', 'Ť': 'T', 66 | 'Ú': 'U', 'Ý': 'Y', 'Ž': 'Z' 67 | }; 68 | const POLISH_MAP = { 69 | 'ą': 'a', 'ć': 'c', 'ę': 'e', 'ł': 'l', 'ń': 'n', 'ó': 'o', 'ś': 's', 70 | 'ź': 'z', 'ż': 'z', 71 | 'Ą': 'A', 'Ć': 'C', 'Ę': 'E', 'Ł': 'L', 'Ń': 'N', 'Ó': 'O', 'Ś': 'S', 72 | 'Ź': 'Z', 'Ż': 'Z' 73 | }; 74 | const LATVIAN_MAP = { 75 | 'ā': 'a', 'č': 'c', 'ē': 'e', 'ģ': 'g', 'ī': 'i', 'ķ': 'k', 'ļ': 'l', 76 | 'ņ': 'n', 'š': 's', 'ū': 'u', 'ž': 'z', 77 | 'Ā': 'A', 'Č': 'C', 'Ē': 'E', 'Ģ': 'G', 'Ī': 'I', 'Ķ': 'K', 'Ļ': 'L', 78 | 'Ņ': 'N', 'Š': 'S', 'Ū': 'U', 'Ž': 'Z' 79 | }; 80 | const ARABIC_MAP = { 81 | 'أ': 'a', 'ب': 'b', 'ت': 't', 'ث': 'th', 'ج': 'g', 'ح': 'h', 'خ': 'kh', 'د': 'd', 82 | 'ذ': 'th', 'ر': 'r', 'ز': 'z', 'س': 's', 'ش': 'sh', 'ص': 's', 'ض': 'd', 'ط': 't', 83 | 'ظ': 'th', 'ع': 'aa', 'غ': 'gh', 'ف': 'f', 'ق': 'k', 'ك': 'k', 'ل': 'l', 'م': 'm', 84 | 'ن': 'n', 'ه': 'h', 'و': 'o', 'ي': 'y' 85 | }; 86 | const LITHUANIAN_MAP = { 87 | 'ą': 'a', 'č': 'c', 'ę': 'e', 'ė': 'e', 'į': 'i', 'š': 's', 'ų': 'u', 88 | 'ū': 'u', 'ž': 'z', 89 | 'Ą': 'A', 'Č': 'C', 'Ę': 'E', 'Ė': 'E', 'Į': 'I', 'Š': 'S', 'Ų': 'U', 90 | 'Ū': 'U', 'Ž': 'Z' 91 | }; 92 | const SERBIAN_MAP = { 93 | 'ђ': 'dj', 'ј': 'j', 'љ': 'lj', 'њ': 'nj', 'ћ': 'c', 'џ': 'dz', 94 | 'đ': 'dj', 'Ђ': 'Dj', 'Ј': 'j', 'Љ': 'Lj', 'Њ': 'Nj', 'Ћ': 'C', 95 | 'Џ': 'Dz', 'Đ': 'Dj' 96 | }; 97 | const AZERBAIJANI_MAP = { 98 | 'ç': 'c', 'ə': 'e', 'ğ': 'g', 'ı': 'i', 'ö': 'o', 'ş': 's', 'ü': 'u', 99 | 'Ç': 'C', 'Ə': 'E', 'Ğ': 'G', 'İ': 'I', 'Ö': 'O', 'Ş': 'S', 'Ü': 'U' 100 | }; 101 | const GEORGIAN_MAP = { 102 | 'ა': 'a', 'ბ': 'b', 'გ': 'g', 'დ': 'd', 'ე': 'e', 'ვ': 'v', 'ზ': 'z', 103 | 'თ': 't', 'ი': 'i', 'კ': 'k', 'ლ': 'l', 'მ': 'm', 'ნ': 'n', 'ო': 'o', 104 | 'პ': 'p', 'ჟ': 'j', 'რ': 'r', 'ს': 's', 'ტ': 't', 'უ': 'u', 'ფ': 'f', 105 | 'ქ': 'q', 'ღ': 'g', 'ყ': 'y', 'შ': 'sh', 'ჩ': 'ch', 'ც': 'c', 'ძ': 'dz', 106 | 'წ': 'w', 'ჭ': 'ch', 'ხ': 'x', 'ჯ': 'j', 'ჰ': 'h' 107 | }; 108 | 109 | const ALL_DOWNCODE_MAPS = [ 110 | LATIN_MAP, 111 | LATIN_SYMBOLS_MAP, 112 | GREEK_MAP, 113 | TURKISH_MAP, 114 | ROMANIAN_MAP, 115 | RUSSIAN_MAP, 116 | UKRAINIAN_MAP, 117 | CZECH_MAP, 118 | SLOVAK_MAP, 119 | POLISH_MAP, 120 | LATVIAN_MAP, 121 | ARABIC_MAP, 122 | LITHUANIAN_MAP, 123 | SERBIAN_MAP, 124 | AZERBAIJANI_MAP, 125 | GEORGIAN_MAP 126 | ]; 127 | 128 | const Downcoder = { 129 | 'Initialize': function() { 130 | if (Downcoder.map) { // already made 131 | return; 132 | } 133 | Downcoder.map = {}; 134 | for (const lookup of ALL_DOWNCODE_MAPS) { 135 | Object.assign(Downcoder.map, lookup); 136 | } 137 | Downcoder.regex = new RegExp(Object.keys(Downcoder.map).join('|'), 'g'); 138 | } 139 | }; 140 | 141 | function downcode(slug) { 142 | Downcoder.Initialize(); 143 | return slug.replace(Downcoder.regex, function(m) { 144 | return Downcoder.map[m]; 145 | }); 146 | } 147 | 148 | 149 | function URLify(s, num_chars, allowUnicode) { 150 | // changes, e.g., "Petty theft" to "petty-theft" 151 | if (!allowUnicode) { 152 | s = downcode(s); 153 | } 154 | s = s.toLowerCase(); // convert to lowercase 155 | // if downcode doesn't hit, the char will be stripped here 156 | if (allowUnicode) { 157 | // Keep Unicode letters including both lowercase and uppercase 158 | // characters, whitespace, and dash; remove other characters. 159 | s = XRegExp.replace(s, XRegExp('[^-_\\p{L}\\p{N}\\s]', 'g'), ''); 160 | } else { 161 | s = s.replace(/[^-\w\s]/g, ''); // remove unneeded chars 162 | } 163 | s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces 164 | s = s.replace(/[-\s]+/g, '-'); // convert spaces to hyphens 165 | s = s.substring(0, num_chars); // trim to first num_chars chars 166 | s = s.replace(/-+$/g, ''); // trim any trailing hyphens 167 | return s; 168 | } 169 | window.URLify = URLify; 170 | } 171 | -------------------------------------------------------------------------------- /web/static/admin/js/vendor/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright JS Foundation and other contributors, https://js.foundation/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/af.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/af",[],function(){return{errorLoading:function(){return"Die resultate kon nie gelaai word nie."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Verwyders asseblief "+n+" character";return 1!=n&&(r+="s"),r},inputTooShort:function(e){return"Voer asseblief "+(e.minimum-e.input.length)+" of meer karakters"},loadingMore:function(){return"Meer resultate word gelaai…"},maximumSelected:function(e){var n="Kies asseblief net "+e.maximum+" item";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"Geen resultate gevind"},searching:function(){return"Besig…"},removeAllItems:function(){return"Verwyder alle items"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/ar.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ar",[],function(){return{errorLoading:function(){return"لا يمكن تحميل النتائج"},inputTooLong:function(n){return"الرجاء حذف "+(n.input.length-n.maximum)+" عناصر"},inputTooShort:function(n){return"الرجاء إضافة "+(n.minimum-n.input.length)+" عناصر"},loadingMore:function(){return"جاري تحميل نتائج إضافية..."},maximumSelected:function(n){return"تستطيع إختيار "+n.maximum+" بنود فقط"},noResults:function(){return"لم يتم العثور على أي نتائج"},searching:function(){return"جاري البحث…"},removeAllItems:function(){return"قم بإزالة كل العناصر"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/az.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/az",[],function(){return{inputTooLong:function(n){return n.input.length-n.maximum+" simvol silin"},inputTooShort:function(n){return n.minimum-n.input.length+" simvol daxil edin"},loadingMore:function(){return"Daha çox nəticə yüklənir…"},maximumSelected:function(n){return"Sadəcə "+n.maximum+" element seçə bilərsiniz"},noResults:function(){return"Nəticə tapılmadı"},searching:function(){return"Axtarılır…"},removeAllItems:function(){return"Bütün elementləri sil"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/bg.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/bg",[],function(){return{inputTooLong:function(n){var e=n.input.length-n.maximum,u="Моля въведете с "+e+" по-малко символ";return e>1&&(u+="a"),u},inputTooShort:function(n){var e=n.minimum-n.input.length,u="Моля въведете още "+e+" символ";return e>1&&(u+="a"),u},loadingMore:function(){return"Зареждат се още…"},maximumSelected:function(n){var e="Можете да направите до "+n.maximum+" ";return n.maximum>1?e+="избора":e+="избор",e},noResults:function(){return"Няма намерени съвпадения"},searching:function(){return"Търсене…"},removeAllItems:function(){return"Премахнете всички елементи"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/bn.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/bn",[],function(){return{errorLoading:function(){return"ফলাফলগুলি লোড করা যায়নি।"},inputTooLong:function(n){var e=n.input.length-n.maximum,u="অনুগ্রহ করে "+e+" টি অক্ষর মুছে দিন।";return 1!=e&&(u="অনুগ্রহ করে "+e+" টি অক্ষর মুছে দিন।"),u},inputTooShort:function(n){return n.minimum-n.input.length+" টি অক্ষর অথবা অধিক অক্ষর লিখুন।"},loadingMore:function(){return"আরো ফলাফল লোড হচ্ছে ..."},maximumSelected:function(n){var e=n.maximum+" টি আইটেম নির্বাচন করতে পারবেন।";return 1!=n.maximum&&(e=n.maximum+" টি আইটেম নির্বাচন করতে পারবেন।"),e},noResults:function(){return"কোন ফলাফল পাওয়া যায়নি।"},searching:function(){return"অনুসন্ধান করা হচ্ছে ..."}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/bs.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/bs",[],function(){function e(e,n,r,t){return e%10==1&&e%100!=11?n:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?r:t}return{errorLoading:function(){return"Preuzimanje nije uspijelo."},inputTooLong:function(n){var r=n.input.length-n.maximum,t="Obrišite "+r+" simbol";return t+=e(r,"","a","a")},inputTooShort:function(n){var r=n.minimum-n.input.length,t="Ukucajte bar još "+r+" simbol";return t+=e(r,"","a","a")},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(n){var r="Možete izabrati samo "+n.maximum+" stavk";return r+=e(n.maximum,"u","e","i")},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Uklonite sve stavke"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/ca.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/ca",[],function(){return{errorLoading:function(){return"La càrrega ha fallat"},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Si us plau, elimina "+n+" car";return r+=1==n?"àcter":"àcters"},inputTooShort:function(e){var n=e.minimum-e.input.length,r="Si us plau, introdueix "+n+" car";return r+=1==n?"àcter":"àcters"},loadingMore:function(){return"Carregant més resultats…"},maximumSelected:function(e){var n="Només es pot seleccionar "+e.maximum+" element";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No s'han trobat resultats"},searching:function(){return"Cercant…"},removeAllItems:function(){return"Treu tots els elements"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/cs.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/cs",[],function(){function e(e,n){switch(e){case 2:return n?"dva":"dvě";case 3:return"tři";case 4:return"čtyři"}return""}return{errorLoading:function(){return"Výsledky nemohly být načteny."},inputTooLong:function(n){var t=n.input.length-n.maximum;return 1==t?"Prosím, zadejte o jeden znak méně.":t<=4?"Prosím, zadejte o "+e(t,!0)+" znaky méně.":"Prosím, zadejte o "+t+" znaků méně."},inputTooShort:function(n){var t=n.minimum-n.input.length;return 1==t?"Prosím, zadejte ještě jeden znak.":t<=4?"Prosím, zadejte ještě další "+e(t,!0)+" znaky.":"Prosím, zadejte ještě dalších "+t+" znaků."},loadingMore:function(){return"Načítají se další výsledky…"},maximumSelected:function(n){var t=n.maximum;return 1==t?"Můžete zvolit jen jednu položku.":t<=4?"Můžete zvolit maximálně "+e(t,!1)+" položky.":"Můžete zvolit maximálně "+t+" položek."},noResults:function(){return"Nenalezeny žádné položky."},searching:function(){return"Vyhledávání…"},removeAllItems:function(){return"Odstraňte všechny položky"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/da.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/da",[],function(){return{errorLoading:function(){return"Resultaterne kunne ikke indlæses."},inputTooLong:function(e){return"Angiv venligst "+(e.input.length-e.maximum)+" tegn mindre"},inputTooShort:function(e){return"Angiv venligst "+(e.minimum-e.input.length)+" tegn mere"},loadingMore:function(){return"Indlæser flere resultater…"},maximumSelected:function(e){var n="Du kan kun vælge "+e.maximum+" emne";return 1!=e.maximum&&(n+="r"),n},noResults:function(){return"Ingen resultater fundet"},searching:function(){return"Søger…"},removeAllItems:function(){return"Fjern alle elementer"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/de.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/de",[],function(){return{errorLoading:function(){return"Die Ergebnisse konnten nicht geladen werden."},inputTooLong:function(e){return"Bitte "+(e.input.length-e.maximum)+" Zeichen weniger eingeben"},inputTooShort:function(e){return"Bitte "+(e.minimum-e.input.length)+" Zeichen mehr eingeben"},loadingMore:function(){return"Lade mehr Ergebnisse…"},maximumSelected:function(e){var n="Sie können nur "+e.maximum+" Element";return 1!=e.maximum&&(n+="e"),n+=" auswählen"},noResults:function(){return"Keine Übereinstimmungen gefunden"},searching:function(){return"Suche…"},removeAllItems:function(){return"Entferne alle Elemente"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/dsb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/dsb",[],function(){var n=["znamuško","znamušce","znamuška","znamuškow"],e=["zapisk","zapiska","zapiski","zapiskow"],u=function(n,e){return 1===n?e[0]:2===n?e[1]:n>2&&n<=4?e[2]:n>=5?e[3]:void 0};return{errorLoading:function(){return"Wuslědki njejsu se dali zacytaś."},inputTooLong:function(e){var a=e.input.length-e.maximum;return"Pšosym lašuj "+a+" "+u(a,n)},inputTooShort:function(e){var a=e.minimum-e.input.length;return"Pšosym zapódaj nanejmjenjej "+a+" "+u(a,n)},loadingMore:function(){return"Dalšne wuslědki se zacytaju…"},maximumSelected:function(n){return"Móžoš jano "+n.maximum+" "+u(n.maximum,e)+"wubraś."},noResults:function(){return"Žedne wuslědki namakane"},searching:function(){return"Pyta se…"},removeAllItems:function(){return"Remove all items"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/el.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/el",[],function(){return{errorLoading:function(){return"Τα αποτελέσματα δεν μπόρεσαν να φορτώσουν."},inputTooLong:function(n){var e=n.input.length-n.maximum,u="Παρακαλώ διαγράψτε "+e+" χαρακτήρ";return 1==e&&(u+="α"),1!=e&&(u+="ες"),u},inputTooShort:function(n){return"Παρακαλώ συμπληρώστε "+(n.minimum-n.input.length)+" ή περισσότερους χαρακτήρες"},loadingMore:function(){return"Φόρτωση περισσότερων αποτελεσμάτων…"},maximumSelected:function(n){var e="Μπορείτε να επιλέξετε μόνο "+n.maximum+" επιλογ";return 1==n.maximum&&(e+="ή"),1!=n.maximum&&(e+="ές"),e},noResults:function(){return"Δεν βρέθηκαν αποτελέσματα"},searching:function(){return"Αναζήτηση…"},removeAllItems:function(){return"Καταργήστε όλα τα στοιχεία"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/en.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"The results could not be loaded."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Please delete "+n+" character";return 1!=n&&(r+="s"),r},inputTooShort:function(e){return"Please enter "+(e.minimum-e.input.length)+" or more characters"},loadingMore:function(){return"Loading more results…"},maximumSelected:function(e){var n="You can only select "+e.maximum+" item";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No results found"},searching:function(){return"Searching…"},removeAllItems:function(){return"Remove all items"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/es.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/es",[],function(){return{errorLoading:function(){return"No se pudieron cargar los resultados"},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Por favor, elimine "+n+" car";return r+=1==n?"ácter":"acteres"},inputTooShort:function(e){var n=e.minimum-e.input.length,r="Por favor, introduzca "+n+" car";return r+=1==n?"ácter":"acteres"},loadingMore:function(){return"Cargando más resultados…"},maximumSelected:function(e){var n="Sólo puede seleccionar "+e.maximum+" elemento";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No se encontraron resultados"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Eliminar todos los elementos"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/et.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/et",[],function(){return{inputTooLong:function(e){var n=e.input.length-e.maximum,t="Sisesta "+n+" täht";return 1!=n&&(t+="e"),t+=" vähem"},inputTooShort:function(e){var n=e.minimum-e.input.length,t="Sisesta "+n+" täht";return 1!=n&&(t+="e"),t+=" rohkem"},loadingMore:function(){return"Laen tulemusi…"},maximumSelected:function(e){var n="Saad vaid "+e.maximum+" tulemus";return 1==e.maximum?n+="e":n+="t",n+=" valida"},noResults:function(){return"Tulemused puuduvad"},searching:function(){return"Otsin…"},removeAllItems:function(){return"Eemalda kõik esemed"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/eu.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/eu",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Idatzi ";return n+=1==t?"karaktere bat":t+" karaktere",n+=" gutxiago"},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Idatzi ";return n+=1==t?"karaktere bat":t+" karaktere",n+=" gehiago"},loadingMore:function(){return"Emaitza gehiago kargatzen…"},maximumSelected:function(e){return 1===e.maximum?"Elementu bakarra hauta dezakezu":e.maximum+" elementu hauta ditzakezu soilik"},noResults:function(){return"Ez da bat datorrenik aurkitu"},searching:function(){return"Bilatzen…"},removeAllItems:function(){return"Kendu elementu guztiak"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/fa.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/fa",[],function(){return{errorLoading:function(){return"امکان بارگذاری نتایج وجود ندارد."},inputTooLong:function(n){return"لطفاً "+(n.input.length-n.maximum)+" کاراکتر را حذف نمایید"},inputTooShort:function(n){return"لطفاً تعداد "+(n.minimum-n.input.length)+" کاراکتر یا بیشتر وارد نمایید"},loadingMore:function(){return"در حال بارگذاری نتایج بیشتر..."},maximumSelected:function(n){return"شما تنها می‌توانید "+n.maximum+" آیتم را انتخاب نمایید"},noResults:function(){return"هیچ نتیجه‌ای یافت نشد"},searching:function(){return"در حال جستجو..."},removeAllItems:function(){return"همه موارد را حذف کنید"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/fi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/fi",[],function(){return{errorLoading:function(){return"Tuloksia ei saatu ladattua."},inputTooLong:function(n){return"Ole hyvä ja anna "+(n.input.length-n.maximum)+" merkkiä vähemmän"},inputTooShort:function(n){return"Ole hyvä ja anna "+(n.minimum-n.input.length)+" merkkiä lisää"},loadingMore:function(){return"Ladataan lisää tuloksia…"},maximumSelected:function(n){return"Voit valita ainoastaan "+n.maximum+" kpl"},noResults:function(){return"Ei tuloksia"},searching:function(){return"Haetaan…"},removeAllItems:function(){return"Poista kaikki kohteet"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/fr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/fr",[],function(){return{errorLoading:function(){return"Les résultats ne peuvent pas être chargés."},inputTooLong:function(e){var n=e.input.length-e.maximum;return"Supprimez "+n+" caractère"+(n>1?"s":"")},inputTooShort:function(e){var n=e.minimum-e.input.length;return"Saisissez au moins "+n+" caractère"+(n>1?"s":"")},loadingMore:function(){return"Chargement de résultats supplémentaires…"},maximumSelected:function(e){return"Vous pouvez seulement sélectionner "+e.maximum+" élément"+(e.maximum>1?"s":"")},noResults:function(){return"Aucun résultat trouvé"},searching:function(){return"Recherche en cours…"},removeAllItems:function(){return"Supprimer tous les éléments"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/gl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/gl",[],function(){return{errorLoading:function(){return"Non foi posíbel cargar os resultados."},inputTooLong:function(e){var n=e.input.length-e.maximum;return 1===n?"Elimine un carácter":"Elimine "+n+" caracteres"},inputTooShort:function(e){var n=e.minimum-e.input.length;return 1===n?"Engada un carácter":"Engada "+n+" caracteres"},loadingMore:function(){return"Cargando máis resultados…"},maximumSelected:function(e){return 1===e.maximum?"Só pode seleccionar un elemento":"Só pode seleccionar "+e.maximum+" elementos"},noResults:function(){return"Non se atoparon resultados"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Elimina todos os elementos"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/he.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/he",[],function(){return{errorLoading:function(){return"שגיאה בטעינת התוצאות"},inputTooLong:function(n){var e=n.input.length-n.maximum,r="נא למחוק ";return r+=1===e?"תו אחד":e+" תווים"},inputTooShort:function(n){var e=n.minimum-n.input.length,r="נא להכניס ";return r+=1===e?"תו אחד":e+" תווים",r+=" או יותר"},loadingMore:function(){return"טוען תוצאות נוספות…"},maximumSelected:function(n){var e="באפשרותך לבחור עד ";return 1===n.maximum?e+="פריט אחד":e+=n.maximum+" פריטים",e},noResults:function(){return"לא נמצאו תוצאות"},searching:function(){return"מחפש…"},removeAllItems:function(){return"הסר את כל הפריטים"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/hi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hi",[],function(){return{errorLoading:function(){return"परिणामों को लोड नहीं किया जा सका।"},inputTooLong:function(n){var e=n.input.length-n.maximum,r=e+" अक्षर को हटा दें";return e>1&&(r=e+" अक्षरों को हटा दें "),r},inputTooShort:function(n){return"कृपया "+(n.minimum-n.input.length)+" या अधिक अक्षर दर्ज करें"},loadingMore:function(){return"अधिक परिणाम लोड हो रहे है..."},maximumSelected:function(n){return"आप केवल "+n.maximum+" आइटम का चयन कर सकते हैं"},noResults:function(){return"कोई परिणाम नहीं मिला"},searching:function(){return"खोज रहा है..."},removeAllItems:function(){return"सभी वस्तुओं को हटा दें"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/hr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hr",[],function(){function n(n){var e=" "+n+" znak";return n%10<5&&n%10>0&&(n%100<5||n%100>19)?n%10>1&&(e+="a"):e+="ova",e}return{errorLoading:function(){return"Preuzimanje nije uspjelo."},inputTooLong:function(e){return"Unesite "+n(e.input.length-e.maximum)},inputTooShort:function(e){return"Unesite još "+n(e.minimum-e.input.length)},loadingMore:function(){return"Učitavanje rezultata…"},maximumSelected:function(n){return"Maksimalan broj odabranih stavki je "+n.maximum},noResults:function(){return"Nema rezultata"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Ukloni sve stavke"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/hsb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hsb",[],function(){var n=["znamješko","znamješce","znamješka","znamješkow"],e=["zapisk","zapiskaj","zapiski","zapiskow"],u=function(n,e){return 1===n?e[0]:2===n?e[1]:n>2&&n<=4?e[2]:n>=5?e[3]:void 0};return{errorLoading:function(){return"Wuslědki njedachu so začitać."},inputTooLong:function(e){var a=e.input.length-e.maximum;return"Prošu zhašej "+a+" "+u(a,n)},inputTooShort:function(e){var a=e.minimum-e.input.length;return"Prošu zapodaj znajmjeńša "+a+" "+u(a,n)},loadingMore:function(){return"Dalše wuslědki so začitaja…"},maximumSelected:function(n){return"Móžeš jenož "+n.maximum+" "+u(n.maximum,e)+"wubrać"},noResults:function(){return"Žane wuslědki namakane"},searching:function(){return"Pyta so…"},removeAllItems:function(){return"Remove all items"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/hu.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/hu",[],function(){return{errorLoading:function(){return"Az eredmények betöltése nem sikerült."},inputTooLong:function(e){return"Túl hosszú. "+(e.input.length-e.maximum)+" karakterrel több, mint kellene."},inputTooShort:function(e){return"Túl rövid. Még "+(e.minimum-e.input.length)+" karakter hiányzik."},loadingMore:function(){return"Töltés…"},maximumSelected:function(e){return"Csak "+e.maximum+" elemet lehet kiválasztani."},noResults:function(){return"Nincs találat."},searching:function(){return"Keresés…"},removeAllItems:function(){return"Távolítson el minden elemet"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/hy.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hy",[],function(){return{errorLoading:function(){return"Արդյունքները հնարավոր չէ բեռնել։"},inputTooLong:function(n){return"Խնդրում ենք հեռացնել "+(n.input.length-n.maximum)+" նշան"},inputTooShort:function(n){return"Խնդրում ենք մուտքագրել "+(n.minimum-n.input.length)+" կամ ավել նշաններ"},loadingMore:function(){return"Բեռնվում են նոր արդյունքներ․․․"},maximumSelected:function(n){return"Դուք կարող եք ընտրել առավելագույնը "+n.maximum+" կետ"},noResults:function(){return"Արդյունքներ չեն գտնվել"},searching:function(){return"Որոնում․․․"},removeAllItems:function(){return"Հեռացնել բոլոր տարրերը"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/id.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/id",[],function(){return{errorLoading:function(){return"Data tidak boleh diambil."},inputTooLong:function(n){return"Hapuskan "+(n.input.length-n.maximum)+" huruf"},inputTooShort:function(n){return"Masukkan "+(n.minimum-n.input.length)+" huruf lagi"},loadingMore:function(){return"Mengambil data…"},maximumSelected:function(n){return"Anda hanya dapat memilih "+n.maximum+" pilihan"},noResults:function(){return"Tidak ada data yang sesuai"},searching:function(){return"Mencari…"},removeAllItems:function(){return"Hapus semua item"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/is.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/is",[],function(){return{inputTooLong:function(n){var t=n.input.length-n.maximum,e="Vinsamlegast styttið texta um "+t+" staf";return t<=1?e:e+"i"},inputTooShort:function(n){var t=n.minimum-n.input.length,e="Vinsamlegast skrifið "+t+" staf";return t>1&&(e+="i"),e+=" í viðbót"},loadingMore:function(){return"Sæki fleiri niðurstöður…"},maximumSelected:function(n){return"Þú getur aðeins valið "+n.maximum+" atriði"},noResults:function(){return"Ekkert fannst"},searching:function(){return"Leita…"},removeAllItems:function(){return"Fjarlægðu öll atriði"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/it.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/it",[],function(){return{errorLoading:function(){return"I risultati non possono essere caricati."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Per favore cancella "+n+" caratter";return t+=1!==n?"i":"e"},inputTooShort:function(e){return"Per favore inserisci "+(e.minimum-e.input.length)+" o più caratteri"},loadingMore:function(){return"Caricando più risultati…"},maximumSelected:function(e){var n="Puoi selezionare solo "+e.maximum+" element";return 1!==e.maximum?n+="i":n+="o",n},noResults:function(){return"Nessun risultato trovato"},searching:function(){return"Sto cercando…"},removeAllItems:function(){return"Rimuovi tutti gli oggetti"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/ja.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ja",[],function(){return{errorLoading:function(){return"結果が読み込まれませんでした"},inputTooLong:function(n){return n.input.length-n.maximum+" 文字を削除してください"},inputTooShort:function(n){return"少なくとも "+(n.minimum-n.input.length)+" 文字を入力してください"},loadingMore:function(){return"読み込み中…"},maximumSelected:function(n){return n.maximum+" 件しか選択できません"},noResults:function(){return"対象が見つかりません"},searching:function(){return"検索しています…"},removeAllItems:function(){return"すべてのアイテムを削除"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/ka.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ka",[],function(){return{errorLoading:function(){return"მონაცემების ჩატვირთვა შეუძლებელია."},inputTooLong:function(n){return"გთხოვთ აკრიფეთ "+(n.input.length-n.maximum)+" სიმბოლოთი ნაკლები"},inputTooShort:function(n){return"გთხოვთ აკრიფეთ "+(n.minimum-n.input.length)+" სიმბოლო ან მეტი"},loadingMore:function(){return"მონაცემების ჩატვირთვა…"},maximumSelected:function(n){return"თქვენ შეგიძლიათ აირჩიოთ არაუმეტეს "+n.maximum+" ელემენტი"},noResults:function(){return"რეზულტატი არ მოიძებნა"},searching:function(){return"ძიება…"},removeAllItems:function(){return"ამოიღე ყველა ელემენტი"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/km.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/km",[],function(){return{errorLoading:function(){return"មិនអាចទាញយកទិន្នន័យ"},inputTooLong:function(n){return"សូមលុបចេញ "+(n.input.length-n.maximum)+" អក្សរ"},inputTooShort:function(n){return"សូមបញ្ចូល"+(n.minimum-n.input.length)+" អក្សរ រឺ ច្រើនជាងនេះ"},loadingMore:function(){return"កំពុងទាញយកទិន្នន័យបន្ថែម..."},maximumSelected:function(n){return"អ្នកអាចជ្រើសរើសបានតែ "+n.maximum+" ជម្រើសប៉ុណ្ណោះ"},noResults:function(){return"មិនមានលទ្ធផល"},searching:function(){return"កំពុងស្វែងរក..."},removeAllItems:function(){return"លុបធាតុទាំងអស់"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/ko.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ko",[],function(){return{errorLoading:function(){return"결과를 불러올 수 없습니다."},inputTooLong:function(n){return"너무 깁니다. "+(n.input.length-n.maximum)+" 글자 지워주세요."},inputTooShort:function(n){return"너무 짧습니다. "+(n.minimum-n.input.length)+" 글자 더 입력해주세요."},loadingMore:function(){return"불러오는 중…"},maximumSelected:function(n){return"최대 "+n.maximum+"개까지만 선택 가능합니다."},noResults:function(){return"결과가 없습니다."},searching:function(){return"검색 중…"},removeAllItems:function(){return"모든 항목 삭제"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/lt.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/lt",[],function(){function n(n,e,i,t){return n%10==1&&(n%100<11||n%100>19)?e:n%10>=2&&n%10<=9&&(n%100<11||n%100>19)?i:t}return{inputTooLong:function(e){var i=e.input.length-e.maximum,t="Pašalinkite "+i+" simbol";return t+=n(i,"į","ius","ių")},inputTooShort:function(e){var i=e.minimum-e.input.length,t="Įrašykite dar "+i+" simbol";return t+=n(i,"į","ius","ių")},loadingMore:function(){return"Kraunama daugiau rezultatų…"},maximumSelected:function(e){var i="Jūs galite pasirinkti tik "+e.maximum+" element";return i+=n(e.maximum,"ą","us","ų")},noResults:function(){return"Atitikmenų nerasta"},searching:function(){return"Ieškoma…"},removeAllItems:function(){return"Pašalinti visus elementus"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/lv.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/lv",[],function(){function e(e,n,u,i){return 11===e?n:e%10==1?u:i}return{inputTooLong:function(n){var u=n.input.length-n.maximum,i="Lūdzu ievadiet par "+u;return(i+=" simbol"+e(u,"iem","u","iem"))+" mazāk"},inputTooShort:function(n){var u=n.minimum-n.input.length,i="Lūdzu ievadiet vēl "+u;return i+=" simbol"+e(u,"us","u","us")},loadingMore:function(){return"Datu ielāde…"},maximumSelected:function(n){var u="Jūs varat izvēlēties ne vairāk kā "+n.maximum;return u+=" element"+e(n.maximum,"us","u","us")},noResults:function(){return"Sakritību nav"},searching:function(){return"Meklēšana…"},removeAllItems:function(){return"Noņemt visus vienumus"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/mk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/mk",[],function(){return{inputTooLong:function(n){var e=(n.input.length,n.maximum,"Ве молиме внесете "+n.maximum+" помалку карактер");return 1!==n.maximum&&(e+="и"),e},inputTooShort:function(n){var e=(n.minimum,n.input.length,"Ве молиме внесете уште "+n.maximum+" карактер");return 1!==n.maximum&&(e+="и"),e},loadingMore:function(){return"Вчитување резултати…"},maximumSelected:function(n){var e="Можете да изберете само "+n.maximum+" ставк";return 1===n.maximum?e+="а":e+="и",e},noResults:function(){return"Нема пронајдено совпаѓања"},searching:function(){return"Пребарување…"},removeAllItems:function(){return"Отстрани ги сите предмети"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/ms.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ms",[],function(){return{errorLoading:function(){return"Keputusan tidak berjaya dimuatkan."},inputTooLong:function(n){return"Sila hapuskan "+(n.input.length-n.maximum)+" aksara"},inputTooShort:function(n){return"Sila masukkan "+(n.minimum-n.input.length)+" atau lebih aksara"},loadingMore:function(){return"Sedang memuatkan keputusan…"},maximumSelected:function(n){return"Anda hanya boleh memilih "+n.maximum+" pilihan"},noResults:function(){return"Tiada padanan yang ditemui"},searching:function(){return"Mencari…"},removeAllItems:function(){return"Keluarkan semua item"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/nb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/nb",[],function(){return{errorLoading:function(){return"Kunne ikke hente resultater."},inputTooLong:function(e){return"Vennligst fjern "+(e.input.length-e.maximum)+" tegn"},inputTooShort:function(e){return"Vennligst skriv inn "+(e.minimum-e.input.length)+" tegn til"},loadingMore:function(){return"Laster flere resultater…"},maximumSelected:function(e){return"Du kan velge maks "+e.maximum+" elementer"},noResults:function(){return"Ingen treff"},searching:function(){return"Søker…"},removeAllItems:function(){return"Fjern alle elementer"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/ne.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ne",[],function(){return{errorLoading:function(){return"नतिजाहरु देखाउन सकिएन।"},inputTooLong:function(n){var e=n.input.length-n.maximum,u="कृपया "+e+" अक्षर मेटाउनुहोस्।";return 1!=e&&(u+="कृपया "+e+" अक्षरहरु मेटाउनुहोस्।"),u},inputTooShort:function(n){return"कृपया बाँकी रहेका "+(n.minimum-n.input.length)+" वा अरु धेरै अक्षरहरु भर्नुहोस्।"},loadingMore:function(){return"अरु नतिजाहरु भरिँदैछन् …"},maximumSelected:function(n){var e="तँपाई "+n.maximum+" वस्तु मात्र छान्न पाउँनुहुन्छ।";return 1!=n.maximum&&(e="तँपाई "+n.maximum+" वस्तुहरु मात्र छान्न पाउँनुहुन्छ।"),e},noResults:function(){return"कुनै पनि नतिजा भेटिएन।"},searching:function(){return"खोजि हुँदैछ…"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/nl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/nl",[],function(){return{errorLoading:function(){return"De resultaten konden niet worden geladen."},inputTooLong:function(e){return"Gelieve "+(e.input.length-e.maximum)+" karakters te verwijderen"},inputTooShort:function(e){return"Gelieve "+(e.minimum-e.input.length)+" of meer karakters in te voeren"},loadingMore:function(){return"Meer resultaten laden…"},maximumSelected:function(e){var n=1==e.maximum?"kan":"kunnen",r="Er "+n+" maar "+e.maximum+" item";return 1!=e.maximum&&(r+="s"),r+=" worden geselecteerd"},noResults:function(){return"Geen resultaten gevonden…"},searching:function(){return"Zoeken…"},removeAllItems:function(){return"Verwijder alle items"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/pl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/pl",[],function(){var n=["znak","znaki","znaków"],e=["element","elementy","elementów"],r=function(n,e){return 1===n?e[0]:n>1&&n<=4?e[1]:n>=5?e[2]:void 0};return{errorLoading:function(){return"Nie można załadować wyników."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Usuń "+t+" "+r(t,n)},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Podaj przynajmniej "+t+" "+r(t,n)},loadingMore:function(){return"Trwa ładowanie…"},maximumSelected:function(n){return"Możesz zaznaczyć tylko "+n.maximum+" "+r(n.maximum,e)},noResults:function(){return"Brak wyników"},searching:function(){return"Trwa wyszukiwanie…"},removeAllItems:function(){return"Usuń wszystkie przedmioty"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/ps.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ps",[],function(){return{errorLoading:function(){return"پايلي نه سي ترلاسه کېدای"},inputTooLong:function(n){var e=n.input.length-n.maximum,r="د مهربانۍ لمخي "+e+" توری ړنګ کړئ";return 1!=e&&(r=r.replace("توری","توري")),r},inputTooShort:function(n){return"لږ تر لږه "+(n.minimum-n.input.length)+" يا ډېر توري وليکئ"},loadingMore:function(){return"نوري پايلي ترلاسه کيږي..."},maximumSelected:function(n){var e="تاسو يوازي "+n.maximum+" قلم په نښه کولای سی";return 1!=n.maximum&&(e=e.replace("قلم","قلمونه")),e},noResults:function(){return"پايلي و نه موندل سوې"},searching:function(){return"لټول کيږي..."},removeAllItems:function(){return"ټول توکي لرې کړئ"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/pt-BR.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/pt-BR",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Apague "+n+" caracter";return 1!=n&&(r+="es"),r},inputTooShort:function(e){return"Digite "+(e.minimum-e.input.length)+" ou mais caracteres"},loadingMore:function(){return"Carregando mais resultados…"},maximumSelected:function(e){var n="Você só pode selecionar "+e.maximum+" ite";return 1==e.maximum?n+="m":n+="ns",n},noResults:function(){return"Nenhum resultado encontrado"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Remover todos os itens"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/pt.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/pt",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var r=e.input.length-e.maximum,n="Por favor apague "+r+" ";return n+=1!=r?"caracteres":"caractere"},inputTooShort:function(e){return"Introduza "+(e.minimum-e.input.length)+" ou mais caracteres"},loadingMore:function(){return"A carregar mais resultados…"},maximumSelected:function(e){var r="Apenas pode seleccionar "+e.maximum+" ";return r+=1!=e.maximum?"itens":"item"},noResults:function(){return"Sem resultados"},searching:function(){return"A procurar…"},removeAllItems:function(){return"Remover todos os itens"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/ro.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/ro",[],function(){return{errorLoading:function(){return"Rezultatele nu au putut fi incărcate."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vă rugăm să ștergeți"+t+" caracter";return 1!==t&&(n+="e"),n},inputTooShort:function(e){return"Vă rugăm să introduceți "+(e.minimum-e.input.length)+" sau mai multe caractere"},loadingMore:function(){return"Se încarcă mai multe rezultate…"},maximumSelected:function(e){var t="Aveți voie să selectați cel mult "+e.maximum;return t+=" element",1!==e.maximum&&(t+="e"),t},noResults:function(){return"Nu au fost găsite rezultate"},searching:function(){return"Căutare…"},removeAllItems:function(){return"Eliminați toate elementele"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/ru.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ru",[],function(){function n(n,e,r,u){return n%10<5&&n%10>0&&n%100<5||n%100>20?n%10>1?r:e:u}return{errorLoading:function(){return"Невозможно загрузить результаты"},inputTooLong:function(e){var r=e.input.length-e.maximum,u="Пожалуйста, введите на "+r+" символ";return u+=n(r,"","a","ов"),u+=" меньше"},inputTooShort:function(e){var r=e.minimum-e.input.length,u="Пожалуйста, введите ещё хотя бы "+r+" символ";return u+=n(r,"","a","ов")},loadingMore:function(){return"Загрузка данных…"},maximumSelected:function(e){var r="Вы можете выбрать не более "+e.maximum+" элемент";return r+=n(e.maximum,"","a","ов")},noResults:function(){return"Совпадений не найдено"},searching:function(){return"Поиск…"},removeAllItems:function(){return"Удалить все элементы"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/sk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sk",[],function(){var e={2:function(e){return e?"dva":"dve"},3:function(){return"tri"},4:function(){return"štyri"}};return{errorLoading:function(){return"Výsledky sa nepodarilo načítať."},inputTooLong:function(n){var t=n.input.length-n.maximum;return 1==t?"Prosím, zadajte o jeden znak menej":t>=2&&t<=4?"Prosím, zadajte o "+e[t](!0)+" znaky menej":"Prosím, zadajte o "+t+" znakov menej"},inputTooShort:function(n){var t=n.minimum-n.input.length;return 1==t?"Prosím, zadajte ešte jeden znak":t<=4?"Prosím, zadajte ešte ďalšie "+e[t](!0)+" znaky":"Prosím, zadajte ešte ďalších "+t+" znakov"},loadingMore:function(){return"Načítanie ďalších výsledkov…"},maximumSelected:function(n){return 1==n.maximum?"Môžete zvoliť len jednu položku":n.maximum>=2&&n.maximum<=4?"Môžete zvoliť najviac "+e[n.maximum](!1)+" položky":"Môžete zvoliť najviac "+n.maximum+" položiek"},noResults:function(){return"Nenašli sa žiadne položky"},searching:function(){return"Vyhľadávanie…"},removeAllItems:function(){return"Odstráňte všetky položky"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/sl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sl",[],function(){return{errorLoading:function(){return"Zadetkov iskanja ni bilo mogoče naložiti."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Prosim zbrišite "+n+" znak";return 2==n?t+="a":1!=n&&(t+="e"),t},inputTooShort:function(e){var n=e.minimum-e.input.length,t="Prosim vpišite še "+n+" znak";return 2==n?t+="a":1!=n&&(t+="e"),t},loadingMore:function(){return"Nalagam več zadetkov…"},maximumSelected:function(e){var n="Označite lahko največ "+e.maximum+" predmet";return 2==e.maximum?n+="a":1!=e.maximum&&(n+="e"),n},noResults:function(){return"Ni zadetkov."},searching:function(){return"Iščem…"},removeAllItems:function(){return"Odstranite vse elemente"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/sq.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sq",[],function(){return{errorLoading:function(){return"Rezultatet nuk mund të ngarkoheshin."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Të lutem fshi "+n+" karakter";return 1!=n&&(t+="e"),t},inputTooShort:function(e){return"Të lutem shkruaj "+(e.minimum-e.input.length)+" ose më shumë karaktere"},loadingMore:function(){return"Duke ngarkuar më shumë rezultate…"},maximumSelected:function(e){var n="Mund të zgjedhësh vetëm "+e.maximum+" element";return 1!=e.maximum&&(n+="e"),n},noResults:function(){return"Nuk u gjet asnjë rezultat"},searching:function(){return"Duke kërkuar…"},removeAllItems:function(){return"Hiq të gjitha sendet"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/sr-Cyrl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sr-Cyrl",[],function(){function n(n,e,r,u){return n%10==1&&n%100!=11?e:n%10>=2&&n%10<=4&&(n%100<12||n%100>14)?r:u}return{errorLoading:function(){return"Преузимање није успело."},inputTooLong:function(e){var r=e.input.length-e.maximum,u="Обришите "+r+" симбол";return u+=n(r,"","а","а")},inputTooShort:function(e){var r=e.minimum-e.input.length,u="Укуцајте бар још "+r+" симбол";return u+=n(r,"","а","а")},loadingMore:function(){return"Преузимање још резултата…"},maximumSelected:function(e){var r="Можете изабрати само "+e.maximum+" ставк";return r+=n(e.maximum,"у","е","и")},noResults:function(){return"Ништа није пронађено"},searching:function(){return"Претрага…"},removeAllItems:function(){return"Уклоните све ставке"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/sr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sr",[],function(){function n(n,e,r,t){return n%10==1&&n%100!=11?e:n%10>=2&&n%10<=4&&(n%100<12||n%100>14)?r:t}return{errorLoading:function(){return"Preuzimanje nije uspelo."},inputTooLong:function(e){var r=e.input.length-e.maximum,t="Obrišite "+r+" simbol";return t+=n(r,"","a","a")},inputTooShort:function(e){var r=e.minimum-e.input.length,t="Ukucajte bar još "+r+" simbol";return t+=n(r,"","a","a")},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(e){var r="Možete izabrati samo "+e.maximum+" stavk";return r+=n(e.maximum,"u","e","i")},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Уклоните све ставке"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/sv.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sv",[],function(){return{errorLoading:function(){return"Resultat kunde inte laddas."},inputTooLong:function(n){return"Vänligen sudda ut "+(n.input.length-n.maximum)+" tecken"},inputTooShort:function(n){return"Vänligen skriv in "+(n.minimum-n.input.length)+" eller fler tecken"},loadingMore:function(){return"Laddar fler resultat…"},maximumSelected:function(n){return"Du kan max välja "+n.maximum+" element"},noResults:function(){return"Inga träffar"},searching:function(){return"Söker…"},removeAllItems:function(){return"Ta bort alla objekt"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/th.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/th",[],function(){return{errorLoading:function(){return"ไม่สามารถค้นข้อมูลได้"},inputTooLong:function(n){return"โปรดลบออก "+(n.input.length-n.maximum)+" ตัวอักษร"},inputTooShort:function(n){return"โปรดพิมพ์เพิ่มอีก "+(n.minimum-n.input.length)+" ตัวอักษร"},loadingMore:function(){return"กำลังค้นข้อมูลเพิ่ม…"},maximumSelected:function(n){return"คุณสามารถเลือกได้ไม่เกิน "+n.maximum+" รายการ"},noResults:function(){return"ไม่พบข้อมูล"},searching:function(){return"กำลังค้นข้อมูล…"},removeAllItems:function(){return"ลบรายการทั้งหมด"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/tk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/tk",[],function(){return{errorLoading:function(){return"Netije ýüklenmedi."},inputTooLong:function(e){return e.input.length-e.maximum+" harp bozuň."},inputTooShort:function(e){return"Ýene-de iň az "+(e.minimum-e.input.length)+" harp ýazyň."},loadingMore:function(){return"Köpräk netije görkezilýär…"},maximumSelected:function(e){return"Diňe "+e.maximum+" sanysyny saýlaň."},noResults:function(){return"Netije tapylmady."},searching:function(){return"Gözlenýär…"},removeAllItems:function(){return"Remove all items"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/tr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/tr",[],function(){return{errorLoading:function(){return"Sonuç yüklenemedi"},inputTooLong:function(n){return n.input.length-n.maximum+" karakter daha girmelisiniz"},inputTooShort:function(n){return"En az "+(n.minimum-n.input.length)+" karakter daha girmelisiniz"},loadingMore:function(){return"Daha fazla…"},maximumSelected:function(n){return"Sadece "+n.maximum+" seçim yapabilirsiniz"},noResults:function(){return"Sonuç bulunamadı"},searching:function(){return"Aranıyor…"},removeAllItems:function(){return"Tüm öğeleri kaldır"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/uk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/uk",[],function(){function n(n,e,u,r){return n%100>10&&n%100<15?r:n%10==1?e:n%10>1&&n%10<5?u:r}return{errorLoading:function(){return"Неможливо завантажити результати"},inputTooLong:function(e){return"Будь ласка, видаліть "+(e.input.length-e.maximum)+" "+n(e.maximum,"літеру","літери","літер")},inputTooShort:function(n){return"Будь ласка, введіть "+(n.minimum-n.input.length)+" або більше літер"},loadingMore:function(){return"Завантаження інших результатів…"},maximumSelected:function(e){return"Ви можете вибрати лише "+e.maximum+" "+n(e.maximum,"пункт","пункти","пунктів")},noResults:function(){return"Нічого не знайдено"},searching:function(){return"Пошук…"},removeAllItems:function(){return"Видалити всі елементи"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/vi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/vi",[],function(){return{inputTooLong:function(n){return"Vui lòng xóa bớt "+(n.input.length-n.maximum)+" ký tự"},inputTooShort:function(n){return"Vui lòng nhập thêm từ "+(n.minimum-n.input.length)+" ký tự trở lên"},loadingMore:function(){return"Đang lấy thêm kết quả…"},maximumSelected:function(n){return"Chỉ có thể chọn được "+n.maximum+" lựa chọn"},noResults:function(){return"Không tìm thấy kết quả"},searching:function(){return"Đang tìm…"},removeAllItems:function(){return"Xóa tất cả các mục"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/zh-CN.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-CN",[],function(){return{errorLoading:function(){return"无法载入结果。"},inputTooLong:function(n){return"请删除"+(n.input.length-n.maximum)+"个字符"},inputTooShort:function(n){return"请再输入至少"+(n.minimum-n.input.length)+"个字符"},loadingMore:function(){return"载入更多结果…"},maximumSelected:function(n){return"最多只能选择"+n.maximum+"个项目"},noResults:function(){return"未找到结果"},searching:function(){return"搜索中…"},removeAllItems:function(){return"删除所有项目"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/select2/i18n/zh-TW.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-TW",[],function(){return{inputTooLong:function(n){return"請刪掉"+(n.input.length-n.maximum)+"個字元"},inputTooShort:function(n){return"請再輸入"+(n.minimum-n.input.length)+"個字元"},loadingMore:function(){return"載入中…"},maximumSelected:function(n){return"你只能選擇最多"+n.maximum+"項"},noResults:function(){return"沒有找到相符的項目"},searching:function(){return"搜尋中…"},removeAllItems:function(){return"刪除所有項目"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/static/admin/js/vendor/xregexp/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2007-2017 Steven Levithan 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /web/static/css/chunk-0475a8a9.c54cc8a5.css: -------------------------------------------------------------------------------- 1 | .pagination-container[data-v-6a2bc7ec]{background:#fff;padding:32px 16px}.pagination-container.hidden[data-v-6a2bc7ec]{display:none}.detail-base .el-form-item{margin-bottom:2px}.demo-table-expand[data-v-81cf5baa]{font-size:0}.demo-table-expand label[data-v-81cf5baa]{width:120px;color:#99a9bf}.demo-table-expand .el-form-item[data-v-81cf5baa]{margin-right:0;margin-bottom:0;width:50%}.el-dropdown-link[data-v-81cf5baa],.to-console[data-v-81cf5baa]{cursor:pointer;font-size:12px;color:#1890ff;margin-left:10px}.el-icon-arrow-down[data-v-81cf5baa]{font-size:12px} -------------------------------------------------------------------------------- /web/static/css/chunk-1f940af7.6bb20c54.css: -------------------------------------------------------------------------------- 1 | @supports (-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#fff;height:47px;caret-color:#fff}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #283443 inset!important;box-shadow:inset 0 0 0 1000px #283443!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container[data-v-5f1ca375]{min-height:100%;width:100%;background-color:#2d3a4b;overflow:hidden}.login-container .login-form[data-v-5f1ca375]{position:relative;width:520px;max-width:100%;padding:160px 35px 0;margin:0 auto;overflow:hidden}.login-container .tips[data-v-5f1ca375]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips span[data-v-5f1ca375]:first-of-type{margin-right:16px}.login-container .svg-container[data-v-5f1ca375]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title-container[data-v-5f1ca375]{position:relative}.login-container .title-container .title[data-v-5f1ca375]{font-size:26px;color:#eee;margin:0 auto 40px auto;text-align:center;font-weight:700}.login-container .show-pwd[data-v-5f1ca375]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.login-container .thirdparty-button[data-v-5f1ca375]{position:absolute;right:0;bottom:6px}@media only screen and (max-width:470px){.login-container .thirdparty-button[data-v-5f1ca375]{display:none}} -------------------------------------------------------------------------------- /web/static/css/chunk-50499323.e2ce212c.css: -------------------------------------------------------------------------------- 1 | .wscn-http404-container[data-v-26fcd89f]{-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;top:40%;left:50%}.wscn-http404[data-v-26fcd89f]{position:relative;width:1200px;padding:0 50px;overflow:hidden}.wscn-http404 .pic-404[data-v-26fcd89f]{position:relative;float:left;width:600px;overflow:hidden}.wscn-http404 .pic-404__parent[data-v-26fcd89f]{width:100%}.wscn-http404 .pic-404__child[data-v-26fcd89f]{position:absolute}.wscn-http404 .pic-404__child.left[data-v-26fcd89f]{width:80px;top:17px;left:220px;opacity:0;-webkit-animation-name:cloudLeft-data-v-26fcd89f;animation-name:cloudLeft-data-v-26fcd89f;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1s;animation-delay:1s}.wscn-http404 .pic-404__child.mid[data-v-26fcd89f]{width:46px;top:10px;left:420px;opacity:0;-webkit-animation-name:cloudMid-data-v-26fcd89f;animation-name:cloudMid-data-v-26fcd89f;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1.2s;animation-delay:1.2s}.wscn-http404 .pic-404__child.right[data-v-26fcd89f]{width:62px;top:100px;left:500px;opacity:0;-webkit-animation-name:cloudRight-data-v-26fcd89f;animation-name:cloudRight-data-v-26fcd89f;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1s;animation-delay:1s}@-webkit-keyframes cloudLeft-data-v-26fcd89f{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@keyframes cloudLeft-data-v-26fcd89f{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@-webkit-keyframes cloudMid-data-v-26fcd89f{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@keyframes cloudMid-data-v-26fcd89f{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@-webkit-keyframes cloudRight-data-v-26fcd89f{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}@keyframes cloudRight-data-v-26fcd89f{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}.wscn-http404 .bullshit[data-v-26fcd89f]{position:relative;float:left;width:300px;padding:30px 0;overflow:hidden}.wscn-http404 .bullshit__oops[data-v-26fcd89f]{font-size:32px;line-height:40px;color:#1482f0;margin-bottom:20px;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__headline[data-v-26fcd89f],.wscn-http404 .bullshit__oops[data-v-26fcd89f]{font-weight:700;opacity:0;-webkit-animation-name:slideUp-data-v-26fcd89f;animation-name:slideUp-data-v-26fcd89f;-webkit-animation-duration:.5s;animation-duration:.5s}.wscn-http404 .bullshit__headline[data-v-26fcd89f]{font-size:20px;line-height:24px;color:#222;margin-bottom:10px;-webkit-animation-delay:.1s;animation-delay:.1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-26fcd89f]{font-size:13px;line-height:21px;color:grey;margin-bottom:30px;-webkit-animation-delay:.2s;animation-delay:.2s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-26fcd89f],.wscn-http404 .bullshit__return-home[data-v-26fcd89f]{opacity:0;-webkit-animation-name:slideUp-data-v-26fcd89f;animation-name:slideUp-data-v-26fcd89f;-webkit-animation-duration:.5s;animation-duration:.5s}.wscn-http404 .bullshit__return-home[data-v-26fcd89f]{display:block;float:left;width:110px;height:36px;background:#1482f0;border-radius:100px;text-align:center;color:#fff;font-size:14px;line-height:36px;cursor:pointer;-webkit-animation-delay:.3s;animation-delay:.3s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@-webkit-keyframes slideUp-data-v-26fcd89f{0%{-webkit-transform:translateY(60px);transform:translateY(60px);opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}@keyframes slideUp-data-v-26fcd89f{0%{-webkit-transform:translateY(60px);transform:translateY(60px);opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}} -------------------------------------------------------------------------------- /web/static/css/chunk-5786617a.310d8994.css: -------------------------------------------------------------------------------- 1 | .errPage-container[data-v-6fb1594e]{width:800px;max-width:100%;margin:100px auto}.errPage-container .pan-back-btn[data-v-6fb1594e]{background:#008489;color:#fff;border:none!important}.errPage-container .pan-gif[data-v-6fb1594e]{margin:0 auto;display:block}.errPage-container .pan-img[data-v-6fb1594e]{display:block;margin:0 auto;width:100%}.errPage-container .text-jumbo[data-v-6fb1594e]{font-size:60px;font-weight:700;color:#484848}.errPage-container .list-unstyled[data-v-6fb1594e]{font-size:14px}.errPage-container .list-unstyled li[data-v-6fb1594e]{padding-bottom:5px}.errPage-container .list-unstyled a[data-v-6fb1594e]{color:#008489;text-decoration:none}.errPage-container .list-unstyled a[data-v-6fb1594e]:hover{text-decoration:underline} -------------------------------------------------------------------------------- /web/static/css/chunk-6146664d.d855fcd7.css: -------------------------------------------------------------------------------- 1 | @supports (-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#fff;height:47px;caret-color:#fff}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #283443 inset!important;box-shadow:inset 0 0 0 1000px #283443!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container[data-v-21a0965a]{min-height:100%;width:100%;background-color:#2d3a4b;overflow:hidden}.login-container .login-form[data-v-21a0965a]{position:relative;width:520px;max-width:100%;padding:160px 35px 0;margin:0 auto;overflow:hidden}.login-container .tips[data-v-21a0965a]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips span[data-v-21a0965a]:first-of-type{margin-right:16px}.login-container .svg-container[data-v-21a0965a]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title-container[data-v-21a0965a]{position:relative}.login-container .title-container .title[data-v-21a0965a]{font-size:26px;color:#eee;margin:0 auto 40px auto;text-align:center;font-weight:700}.login-container .show-pwd[data-v-21a0965a]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.login-container .thirdparty-button[data-v-21a0965a]{position:absolute;right:0;bottom:6px}@media only screen and (max-width:470px){.login-container .thirdparty-button[data-v-21a0965a]{display:none}} -------------------------------------------------------------------------------- /web/static/css/chunk-714ebfa6.0f43044d.css: -------------------------------------------------------------------------------- 1 | .pagination-container[data-v-6a2bc7ec]{background:#fff;padding:32px 16px}.pagination-container.hidden[data-v-6a2bc7ec]{display:none}.demo-table-expand{font-size:0}.demo-table-expand label{width:120px;color:#99a9bf}.demo-table-expand .el-form-item{margin-right:0;margin-bottom:0;width:50%}.boxtext{margin-left:2px;color:red;cursor:pointer}.el-dropdown-link,.to-console{cursor:pointer;font-size:12px;color:#1890ff;margin-left:10px}.el-icon-arrow-down{font-size:12px} -------------------------------------------------------------------------------- /web/static/css/chunk-libs.3dfb7769.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:inherit;font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}[hidden],template{display:none}#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;-webkit-box-shadow:0 0 10px #29d,0 0 5px #29d;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translateY(-4px);transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;-webkit-box-sizing:border-box;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}} -------------------------------------------------------------------------------- /web/static/fonts/element-icons.535877f5.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdntip/cloudpanel/a093fd3d4b3c5ed9fbca72a8ca4080d412691976/web/static/fonts/element-icons.535877f5.woff -------------------------------------------------------------------------------- /web/static/fonts/element-icons.732389de.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdntip/cloudpanel/a093fd3d4b3c5ed9fbca72a8ca4080d412691976/web/static/fonts/element-icons.732389de.ttf -------------------------------------------------------------------------------- /web/static/img/401.089007e7.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdntip/cloudpanel/a093fd3d4b3c5ed9fbca72a8ca4080d412691976/web/static/img/401.089007e7.gif -------------------------------------------------------------------------------- /web/static/img/404.a57b6f31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdntip/cloudpanel/a093fd3d4b3c5ed9fbca72a8ca4080d412691976/web/static/img/404.a57b6f31.png -------------------------------------------------------------------------------- /web/static/img/404_cloud.0f4bc32b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdntip/cloudpanel/a093fd3d4b3c5ed9fbca72a8ca4080d412691976/web/static/img/404_cloud.0f4bc32b.png -------------------------------------------------------------------------------- /web/static/js/chunk-1f940af7.6ecba6b3.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-1f940af7"],{"324a":function(e,r,o){},"3e05":function(e,r,o){"use strict";var s=o("324a"),t=o.n(s);t.a},9683:function(e,r,o){},afb8:function(e,r,o){"use strict";var s=o("9683"),t=o.n(s);t.a},f667:function(e,r,o){"use strict";o.r(r);var s=function(){var e=this,r=e.$createElement,o=e._self._c||r;return o("div",{staticClass:"login-container"},[o("el-form",{ref:"regForm",staticClass:"login-form",attrs:{model:e.loginForm,rules:e.loginRules,autocomplete:"on","label-position":"left"}},[o("div",{staticClass:"title-container"},[o("h3",{staticClass:"title"},[e._v("注册账号")])]),e._v(" "),o("el-form-item",{attrs:{prop:"username",error:e.errorRegForm.username}},[o("span",{staticClass:"svg-container"},[o("svg-icon",{attrs:{"icon-class":"user"}})],1),e._v(" "),o("el-input",{ref:"username",attrs:{placeholder:"登录账号",name:"username",type:"text",autocomplete:"on"},model:{value:e.loginForm.username,callback:function(r){e.$set(e.loginForm,"username",r)},expression:"loginForm.username"}})],1),e._v(" "),o("el-form-item",{attrs:{prop:"email",error:e.errorRegForm.email}},[o("span",{staticClass:"svg-container"},[o("svg-icon",{attrs:{"icon-class":"email"}})],1),e._v(" "),o("el-input",{ref:"email",attrs:{placeholder:"注册邮箱",name:"email",type:"text",autocomplete:"on"},model:{value:e.loginForm.email,callback:function(r){e.$set(e.loginForm,"email",r)},expression:"loginForm.email"}})],1),e._v(" "),o("el-form-item",{attrs:{prop:"password",error:e.errorRegForm.password}},[o("span",{staticClass:"svg-container"},[o("svg-icon",{attrs:{"icon-class":"password"}})],1),e._v(" "),o("el-input",{key:e.passwordType,ref:"password",attrs:{type:e.passwordType,placeholder:"登录密码"},model:{value:e.loginForm.password,callback:function(r){e.$set(e.loginForm,"password",r)},expression:"loginForm.password"}}),e._v(" "),o("span",{staticClass:"show-pwd",on:{click:e.showPwd}},[o("svg-icon",{attrs:{"icon-class":"password"===e.passwordType?"eye":"eye-open"}})],1)],1),e._v(" "),o("el-form-item",{attrs:{prop:"password2",error:e.errorRegForm.password2}},[o("span",{staticClass:"svg-container"},[o("svg-icon",{attrs:{"icon-class":"password"}})],1),e._v(" "),o("el-input",{key:e.passwordType,ref:"password2",attrs:{type:e.passwordType,placeholder:"确认密码",name:"password2",autocomplete:"on"},on:{blur:function(r){e.capsTooltip=!1}},nativeOn:{keyup:[function(r){return e.checkCapslock(r)},function(r){return!r.type.indexOf("key")&&e._k(r.keyCode,"enter",13,r.key,"Enter")?null:e.onSubmit(r)}]},model:{value:e.loginForm.password2,callback:function(r){e.$set(e.loginForm,"password2",r)},expression:"loginForm.password2"}}),e._v(" "),o("span",{staticClass:"show-pwd",on:{click:e.showPwd}},[o("svg-icon",{attrs:{"icon-class":"password"===e.passwordType?"eye":"eye-open"}})],1)],1),e._v(" "),o("el-button",{staticStyle:{width:"100%","margin-bottom":"30px"},attrs:{loading:e.loading,type:"primary"},nativeOn:{click:function(r){return r.preventDefault(),e.onSubmit(r)}}},[e._v("注册")]),e._v(" "),o("div",{staticStyle:{"font-size":"13px"}},[o("span",{staticStyle:{color:"#ffffff"}},[e._v("已经注册? "),o("router-link",{staticStyle:{color:"#4A9FF9"},attrs:{to:"/login"}},[e._v("返回登录")])],1)])],1)],1)},t=[],a=(o("ac6a"),o("456d"),o("c24f")),n=o("4328"),i=o.n(n),l={name:"Login",data:function(){return{loginForm:{email:"",username:"",password:"",password2:""},loginRules:{username:[{required:!0,message:"登录账号必须填写",trigger:"blur"}],password:[{required:!0,message:"登录密码必须填写",trigger:"blur"}],password2:[{required:!0,message:"确认密码必须填写",trigger:"blur"}],email:[{required:!0,message:"邮件地址必须填写",trigger:"blur"}]},passwordType:"password",capsTooltip:!1,loading:!1,showDialog:!1,redirect:void 0,errorRegForm:{},otherQuery:{}}},watch:{$route:{handler:function(e){var r=e.query;r&&(this.redirect=r.redirect,this.otherQuery=this.getOtherQuery(r))},immediate:!0}},created:function(){},mounted:function(){""===this.loginForm.username?this.$refs.username.focus():""===this.loginForm.password&&this.$refs.password.focus()},destroyed:function(){},methods:{checkCapslock:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=e.shiftKey,o=e.key;o&&1===o.length&&(this.capsTooltip=!!(r&&o>="a"&&o<="z"||!r&&o>="A"&&o<="Z")),"CapsLock"===o&&!0===this.capsTooltip&&(this.capsTooltip=!1)},showPwd:function(){var e=this;"password"===this.passwordType?this.passwordType="":this.passwordType="password",this.$nextTick(function(){e.$refs.password.focus()})},handleLogin:function(){var e=this;this.$refs.loginForm.validate(function(r){if(!r)return console.log("error submit!!"),!1;e.loading=!0,e.$store.dispatch("user/login",e.loginForm).then(function(){e.$router.push({path:e.redirect||"/",query:e.otherQuery}),e.loading=!1}).catch(function(){e.loading=!1})})},onSubmit:function(){var e=this;this.errorRegForm={username:"",email:"",password2:"",password:""},this.$refs.regForm.validate(function(r){Object(a["register"])(i.a.stringify(e.loginForm)).then(function(r){e.$notify({title:r.title,message:r.message,type:"success",duration:2e3}),e.showDialog=!1,e.$router.push("/login")}).catch(function(r){if(e.dialogLoading=!1,r.error_data)for(var o in r.error_data){var s=r.error_data[o][0];e.errorRegForm[o]=s}})})},getOtherQuery:function(e){return Object.keys(e).reduce(function(r,o){return"redirect"!==o&&(r[o]=e[o]),r},{})}}},c=l,p=(o("3e05"),o("afb8"),o("2877")),u=Object(p["a"])(c,s,t,!1,null,"5f1ca375",null);r["default"]=u.exports}}]); -------------------------------------------------------------------------------- /web/static/js/chunk-2d2105d3.8eb9d2f2.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d2105d3"],{b829:function(n,e,o){"use strict";o.r(e);o("386d");var t,c,a={name:"AuthRedirect",created:function(){var n=window.location.search.slice(1);window.localStorage&&(window.localStorage.setItem("x-admin-oauth-code",n),window.close())},render:function(n){return n()}},d=a,i=o("2877"),l=Object(i["a"])(d,t,c,!1,null,null,null);e["default"]=l.exports}}]); -------------------------------------------------------------------------------- /web/static/js/chunk-2d230fe7.fcb684d8.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d230fe7"],{ef3c:function(e,r,n){"use strict";n.r(r);n("a481");var t,u,a={created:function(){var e=this.$route,r=e.params,n=e.query,t=r.path;this.$router.replace({path:"/"+t,query:n})},render:function(e){return e()}},c=a,o=n("2877"),p=Object(o["a"])(c,t,u,!1,null,null,null);r["default"]=p.exports}}]); -------------------------------------------------------------------------------- /web/static/js/chunk-50499323.0282e3c3.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-50499323"],{"1db4":function(t,s,a){"use strict";a.r(s);var e=function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("div",{staticClass:"wscn-http404-container"},[a("div",{staticClass:"wscn-http404"},[t._m(0),t._v(" "),a("div",{staticClass:"bullshit"},[a("div",{staticClass:"bullshit__oops"},[t._v("OOPS!")]),t._v(" "),t._m(1),t._v(" "),a("div",{staticClass:"bullshit__headline"},[t._v(t._s(t.message))]),t._v(" "),a("div",{staticClass:"bullshit__info"},[t._v("Please check that the URL you entered is correct, or click the button below to return to the homepage.")]),t._v(" "),a("a",{staticClass:"bullshit__return-home",attrs:{href:""}},[t._v("Back to home")])])])])},c=[function(){var t=this,s=t.$createElement,e=t._self._c||s;return e("div",{staticClass:"pic-404"},[e("img",{staticClass:"pic-404__parent",attrs:{src:a("a36b"),alt:"404"}}),t._v(" "),e("img",{staticClass:"pic-404__child left",attrs:{src:a("26fc"),alt:"404"}}),t._v(" "),e("img",{staticClass:"pic-404__child mid",attrs:{src:a("26fc"),alt:"404"}}),t._v(" "),e("img",{staticClass:"pic-404__child right",attrs:{src:a("26fc"),alt:"404"}})])},function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("div",{staticClass:"bullshit__info"},[t._v("All rights reserved\n "),a("a",{staticStyle:{color:"#20a0ff"},attrs:{href:"https://wallstreetcn.com",target:"_blank"}},[t._v("wallstreetcn")])])}],i={name:"Page404",computed:{message:function(){return"The webmaster said that you can not enter this page..."}}},l=i,n=(a("35e7"),a("2877")),r=Object(n["a"])(l,e,c,!1,null,"26fcd89f",null);s["default"]=r.exports},"26fc":function(t,s,a){t.exports=a.p+"static/img/404_cloud.0f4bc32b.png"},"35e7":function(t,s,a){"use strict";var e=a("5254"),c=a.n(e);c.a},5254:function(t,s,a){},a36b:function(t,s,a){t.exports=a.p+"static/img/404.a57b6f31.png"}}]); -------------------------------------------------------------------------------- /web/static/js/chunk-5786617a.f4a2e354.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-5786617a"],{"24e2":function(t,a,e){"use strict";e.r(a);var i=function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("div",{staticClass:"errPage-container"},[e("el-button",{staticClass:"pan-back-btn",attrs:{icon:"arrow-left"},on:{click:t.back}},[t._v("\n 返回\n ")]),t._v(" "),e("el-row",[e("el-col",{attrs:{span:12}},[e("h1",{staticClass:"text-jumbo text-ginormous"},[t._v("\n Oops!\n ")]),t._v("\n gif来源"),e("a",{attrs:{href:"https://zh.airbnb.com/",target:"_blank"}},[t._v("airbnb")]),t._v(" 页面\n "),e("h2",[t._v("你没有权限去该页面")]),t._v(" "),e("h6",[t._v("如有不满请联系你领导")]),t._v(" "),e("ul",{staticClass:"list-unstyled"},[e("li",[t._v("或者你可以去:")]),t._v(" "),e("li",{staticClass:"link-type"},[e("router-link",{attrs:{to:"/dashboard"}},[t._v("\n 回首页\n ")])],1),t._v(" "),e("li",{staticClass:"link-type"},[e("a",{attrs:{href:"https://www.taobao.com/"}},[t._v("随便看看")])]),t._v(" "),e("li",[e("a",{attrs:{href:"#"},on:{click:function(a){a.preventDefault(),t.dialogVisible=!0}}},[t._v("点我看图")])])])]),t._v(" "),e("el-col",{attrs:{span:12}},[e("img",{attrs:{src:t.errGif,width:"313",height:"428",alt:"Girl has dropped her ice cream."}})])],1),t._v(" "),e("el-dialog",{attrs:{visible:t.dialogVisible,title:"随便看"},on:{"update:visible":function(a){t.dialogVisible=a}}},[e("img",{staticClass:"pan-img",attrs:{src:t.ewizardClap}})])],1)},s=[],n=e("cc6c"),r=e.n(n),l={name:"Page401",data:function(){return{errGif:r.a+"?"+ +new Date,ewizardClap:"https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646",dialogVisible:!1}},methods:{back:function(){this.$route.query.noGoBack?this.$router.push({path:"/dashboard"}):this.$router.go(-1)}}},c=l,o=(e("4f2e"),e("2877")),u=Object(o["a"])(c,i,s,!1,null,"6fb1594e",null);a["default"]=u.exports},"4f2e":function(t,a,e){"use strict";var i=e("cbee"),s=e.n(i);s.a},cbee:function(t,a,e){},cc6c:function(t,a,e){t.exports=e.p+"static/img/401.089007e7.gif"}}]); -------------------------------------------------------------------------------- /web/static/js/chunk-6146664d.515324ec.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-6146664d"],{"0338":function(e,r,t){"use strict";t.r(r);var o=function(){var e=this,r=e.$createElement,t=e._self._c||r;return t("div",{staticStyle:{height:"100%"}},[t("div",{staticClass:"login-container"},[t("el-form",{ref:"loginForm",staticClass:"login-form",attrs:{model:e.loginForm,rules:e.loginRules,autocomplete:"on","label-position":"left"}},[t("div",{staticClass:"title-container"},[t("h3",{staticClass:"title"},[e._v("登 录")])]),e._v(" "),t("el-form-item",{attrs:{prop:"username",error:e.errorLogForm.username}},[t("span",{staticClass:"svg-container"},[t("svg-icon",{attrs:{"icon-class":"user"}})],1),e._v(" "),t("el-input",{ref:"username",attrs:{placeholder:"登录账号",name:"username",type:"text",tabindex:"1",autocomplete:"on"},model:{value:e.loginForm.username,callback:function(r){e.$set(e.loginForm,"username",r)},expression:"loginForm.username"}})],1),e._v(" "),t("el-tooltip",{attrs:{content:"Caps lock is On",placement:"right",manual:""},model:{value:e.capsTooltip,callback:function(r){e.capsTooltip=r},expression:"capsTooltip"}},[t("el-form-item",{attrs:{prop:"password",error:e.errorLogForm.password}},[t("span",{staticClass:"svg-container"},[t("svg-icon",{attrs:{"icon-class":"password"}})],1),e._v(" "),t("el-input",{key:e.passwordType,ref:"password",attrs:{type:e.passwordType,placeholder:"登录密码",name:"password",tabindex:"2",autocomplete:"on"},on:{blur:function(r){e.capsTooltip=!1}},nativeOn:{keyup:[function(r){return e.checkCapslock(r)},function(r){return!r.type.indexOf("key")&&e._k(r.keyCode,"enter",13,r.key,"Enter")?null:e.handleLogin(r)}]},model:{value:e.loginForm.password,callback:function(r){e.$set(e.loginForm,"password",r)},expression:"loginForm.password"}}),e._v(" "),t("span",{staticClass:"show-pwd",on:{click:e.showPwd}},[t("svg-icon",{attrs:{"icon-class":"password"===e.passwordType?"eye":"eye-open"}})],1)],1)],1),e._v(" "),t("el-button",{staticStyle:{width:"100%","margin-bottom":"10px"},attrs:{loading:e.loading,type:"primary"},nativeOn:{click:function(r){return r.preventDefault(),e.handleLogin(r)}}},[e._v("登 录")]),e._v(" "),t("div",{staticStyle:{"font-size":"13px"}},[t("span",{staticStyle:{color:"#ffffff"}},[e._v("该程序为 CDNTIP 免费提供, 请不要相信任何收费. ")])])],1)],1)])},s=[],a=(t("ac6a"),t("456d"),t("c24f")),n=t("4328"),i=t.n(n),c={name:"Login",data:function(){return{reg_form:{username:"",email:"",password:"",password2:""},errorLogForm:{username:"",password:""},errorRegForm:{username:"",email:"",password2:"",password:""},rules:{username:[{required:!0,message:"登录账号必须填写",trigger:"blur"}],password:[{required:!0,message:"登录密码必须填写",trigger:"blur"}],email:[{required:!0,message:"邮件地址必须填写",trigger:"blur"}],password2:[{required:!0,message:"确认密码必须填写",trigger:"blur"}]},loginForm:{},formInline:{user:"",region:""},loginRules:{username:[{required:!0,trigger:"blur",message:"登录账号必须填写"}],password:[{required:!0,trigger:"blur",message:"登录密码必须填写"}]},passwordType:"password",capsTooltip:!1,loading:!1,showDialog:!1,redirect:void 0,otherQuery:{}}},watch:{$route:{handler:function(e){var r=e.query;r&&(this.redirect=r.redirect,this.otherQuery=this.getOtherQuery(r))},immediate:!0}},created:function(){},mounted:function(){""===this.loginForm.username?this.$refs.username.focus():""===this.loginForm.password&&this.$refs.password.focus()},destroyed:function(){},methods:{checkCapslock:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=e.shiftKey,t=e.key;t&&1===t.length&&(this.capsTooltip=!!(r&&t>="a"&&t<="z"||!r&&t>="A"&&t<="Z")),"CapsLock"===t&&!0===this.capsTooltip&&(this.capsTooltip=!1)},resetPassword:function(){var e=this;this.$prompt("请输入邮箱或者账号","提示",{confirmButtonText:"确定",cancelButtonText:"取消"}).then(function(r){var t=r.value;Object(a["sendResetPassword"])(i.a.stringify({wd:t})).then(function(r){e.$notify({title:r.title,message:r.message,type:"success",duration:2e3})}).catch(function(r){e.$notify({title:r.title,message:r.message,type:"error",duration:2e3})})})},showPwd:function(){var e=this;"password"===this.passwordType?this.passwordType="":this.passwordType="password",this.$nextTick(function(){e.$refs.password.focus()})},handleLogin:function(){var e=this;this.errorLogForm={username:"",password:""},this.$refs.loginForm.validate(function(r){if(!r)return console.log("error submit!!"),!1;e.loading=!0,e.$store.dispatch("user/login",e.loginForm).then(function(){e.$router.push({path:e.redirect||"/",query:e.otherQuery}),e.loading=!1}).catch(function(r){if(e.loading=!1,r.error_data&&r.error_data)for(var t in r.error_data){var o=r.error_data[t][0];e.errorLogForm[t]=o}})})},handleReg:function(){var e=this;this.showDialog=!0,this.$nextTick(function(){e.$refs["regForm"].clearValidate()})},onSubmit:function(){var e=this;this.errorRegForm={username:"",email:"",password2:"",password:""},this.$refs.regForm.validate(function(r){Object(a["register"])(i.a.stringify(e.reg_form)).then(function(r){e.$notify({title:r.title,message:r.message,type:"success",duration:2e3}),e.showDialog=!1}).catch(function(r){if(e.dialogLoading=!1,r.error_data)for(var t in r.error_data){var o=r.error_data[t][0];e.errorRegForm[t]=o}})})},closeModal:function(){this.errorForm={},this.reg_form={}},getOtherQuery:function(e){return Object.keys(e).reduce(function(r,t){return"redirect"!==t&&(r[t]=e[t]),r},{})}}},l=c,u=(t("da58"),t("0541"),t("2877")),d=Object(u["a"])(l,o,s,!1,null,"21a0965a",null);r["default"]=d.exports},"0541":function(e,r,t){"use strict";var o=t("bbca"),s=t.n(o);s.a},"201d":function(e,r,t){},bbca:function(e,r,t){},da58:function(e,r,t){"use strict";var o=t("201d"),s=t.n(o);s.a}}]); --------------------------------------------------------------------------------