diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2323257745..d154f5017d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.6, 3.7] + python-version: [3.6, 3.7, 3.8] services: redis: image: redis diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 85bb561dde..c86f810f30 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,8 +15,6 @@ categories for discussions: * **Ideas** - Ideas for new functionality that isn't yet ready for a formal feature request * **Q&A** - Request help with installing or using NetBox -* **Show and tell** - Share a plugin, script, or something else you've made - using NetBox ### Mailing List diff --git a/docs/additional-features/custom-fields.md b/docs/additional-features/custom-fields.md index 01414062cd..91bf033799 100644 --- a/docs/additional-features/custom-fields.md +++ b/docs/additional-features/custom-fields.md @@ -1,26 +1,69 @@ # Custom Fields -Each object in NetBox is represented in the database as a discrete table, and each attribute of an object exists as a column within its table. For example, sites are stored in the `dcim_site` table, which has columns named `name`, `facility`, `physical_address`, and so on. As new attributes are added to objects throughout the development of NetBox, tables are expanded to include new rows. +Each model in NetBox is represented in the database as a discrete table, and each attribute of a model exists as a column within its table. For example, sites are stored in the `dcim_site` table, which has columns named `name`, `facility`, `physical_address`, and so on. As new attributes are added to objects throughout the development of NetBox, tables are expanded to include new rows. -However, some users might want to associate with objects attributes that are somewhat esoteric in nature, and that would not make sense to include in the core NetBox database schema. For instance, suppose your organization needs to associate each device with a ticket number pointing to the support ticket that was opened to have it installed. This is certainly a legitimate use for NetBox, but it's perhaps not a common enough need to warrant expanding the internal data schema. Instead, you can create a custom field to hold this data. +However, some users might want to store additional object attributes that are somewhat esoteric in nature, and that would not make sense to include in the core NetBox database schema. For instance, suppose your organization needs to associate each device with a ticket number correlating it with an internal support system record. This is certainly a legitimate use for NetBox, but it's not a common enough need to warrant including a field for _every_ NetBox installation. Instead, you can create a custom field to hold this data. -Custom fields must be created through the admin UI under Extras > Custom Fields. To create a new custom field, select the object(s) to which you want it to apply, and the type of field it will be. NetBox supports six field types: +Within the database, custom fields are stored as JSON data directly alongside each object. This alleviates the need for complex queries when retrieving objects. -* Free-form text (up to 255 characters) -* Integer -* Boolean (true/false) -* Date -* URL -* Selection +## Creating Custom Fields -Assign the field a name. This should be a simple database-friendly string, e.g. `tps_report`. You may optionally assign the field a human-friendly label (e.g. "TPS report") as well; the label will be displayed on forms. If a description is provided, it will appear beneath the field in a form. +Custom fields must be created through the admin UI under Extras > Custom Fields. NetBox supports six types of custom field: -Marking the field as required will require the user to provide a value for the field when creating a new object or when saving an existing object. A default value for the field may also be provided. Use "true" or "false" for boolean fields. (The default value has no effect for selection fields.) +* Text: Free-form text (up to 255 characters) +* Integer: A whole number (positive or negative) +* Boolean: True or false +* Date: A date in ISO 8601 format (YYYY-MM-DD) +* URL: This will be presented as a link in the web UI +* Selection: A selection of one of several pre-defined custom choices -When creating a selection field, you should create at least two choices. These choices will be arranged first by weight, with lower weights appearing higher in the list, and then alphabetically. +Each custom field must have a name; this should be a simple database-friendly string, e.g. `tps_report`. You may also assign a corresponding human-friendly label (e.g. "TPS report"); the label will be displayed on web forms. A weight is also required: Higher-weight fields will be ordered lower within a form. (The default weight is 100.) If a description is provided, it will appear beneath the field in a form. -## Using Custom Fields +Marking a field as required will force the user to provide a value for the field when creating a new object or when saving an existing object. A default value for the field may also be provided. Use "true" or "false" for boolean fields, or the exact value of a choice for selection fields. -When a single object is edited, the form will include any custom fields which have been defined for the object type. These fields are included in the "Custom Fields" panel. On the backend, each custom field value is saved separately from the core object as an independent database call, so it's best to avoid adding too many custom fields per object. +The filter logic controls how values are matched when filtering objects by the custom field. Loose filtering (the default) matches on a partial value, whereas exact matching requires a complete match of the given string to a field's value. For example, exact filtering with the string "red" will only match the exact value "red", whereas loose filtering will match on the values "red", "red-orange", or "bored". Setting the filter logic to "disabled" disables filtering by the field entirely. -When editing multiple objects, custom field values are saved in bulk. There is no significant difference in overhead when saving a custom field value for 100 objects versus one object. However, the bulk operation must be performed separately for each custom field. +A custom field must be assigned to one or object types, or models, in NetBox. Once created, custom fields will automatically appear as part of these models in the web UI and REST API. Note that not all models support custom fields. + +### Custom Field Validation + +NetBox supports limited custom validation for custom field values. Following are the types of validation enforced for each field type: + +* Text: Regular expression (optional) +* Integer: Minimum and/or maximum value (optional) +* Selection: Must exactly match one of the prescribed choices + +### Custom Selection Fields + +Each custom selection field must have at least two choices. These are specified as a comma-separated list. Choices appear in forms in the order they are listed. Note that choice values are saved exactly as they appear, so it's best to avoid superfluous punctuation or symbols where possible. + +If a default value is specified for a selection field, it must exactly match one of the provided choices. + +## Custom Fields and the REST API + +When retrieving an object via the REST API, all of its custom data will be included within the `custom_fields` attribute. For example, below is the partial output of a site with two custom fields defined: + +```json +{ + "id": 123, + "url": "http://localhost:8000/api/dcim/sites/123/", + "name": "Raleigh 42", + ... + "custom_fields": { + "deployed": "2018-06-19", + "site_code": "US-NC-RAL42" + }, + ... +``` + +To set or change these values, simply include nested JSON data. For example: + +```json +{ + "name": "New Site", + "slug": "new-site", + "custom_fields": { + "deployed": "2019-03-24" + } +} +``` diff --git a/docs/additional-features/graphs.md b/docs/additional-features/graphs.md deleted file mode 100644 index e3551b91ff..0000000000 --- a/docs/additional-features/graphs.md +++ /dev/null @@ -1,30 +0,0 @@ -# Graphs - -!!! warning - Native support for embedded graphs is due to be removed in NetBox v2.10. It will likely be superseded by a plugin providing similar functionality. - -NetBox does not have the ability to generate graphs natively, but this feature allows you to embed contextual graphs from an external resources (such as a monitoring system) inside the site, provider, and interface views. Each embedded graph must be defined with the following parameters: - -* **Type:** Site, device, provider, or interface. This determines in which view the graph will be displayed. -* **Weight:** Determines the order in which graphs are displayed (lower weights are displayed first). Graphs with equal weights will be ordered alphabetically by name. -* **Name:** The title to display above the graph. -* **Source URL:** The source of the image to be embedded. The associated object will be available as a template variable named `obj`. -* **Link URL (optional):** A URL to which the graph will be linked. The associated object will be available as a template variable named `obj`. - -Graph names and links can be rendered using Jinja2 or [Django's template language](https://docs.djangoproject.com/en/stable/ref/templates/language/). - -## Examples - -You only need to define one graph object for each graph you want to include when viewing an object. For example, if you want to include a graph of traffic through an interface over the past five minutes, your graph source might looks like this: - -``` -https://my.nms.local/graphs/?node={{ obj.device.name }}&interface={{ obj.name }}&duration=5m -``` - -You can define several graphs to provide multiple contexts when viewing an object. For example: - -``` -https://my.nms.local/graphs/?type=throughput&node={{ obj.device.name }}&interface={{ obj.name }}&duration=60m -https://my.nms.local/graphs/?type=throughput&node={{ obj.device.name }}&interface={{ obj.name }}&duration=24h -https://my.nms.local/graphs/?type=errors&node={{ obj.device.name }}&interface={{ obj.name }}&duration=60m -``` diff --git a/docs/administration/netbox-shell.md b/docs/administration/netbox-shell.md index 51a06156a6..2a8d31494c 100644 --- a/docs/administration/netbox-shell.md +++ b/docs/administration/netbox-shell.md @@ -185,7 +185,7 @@ To delete an object, simply call `delete()` on its instance. This will return a >>> vlan >>> vlan.delete() -(1, {'extras.CustomFieldValue': 0, 'ipam.VLAN': 1}) +(1, {'ipam.VLAN': 1}) ``` To delete multiple objects at once, call `delete()` on a filtered queryset. It's a good idea to always sanity-check the count of selected objects _before_ deleting them. @@ -194,9 +194,9 @@ To delete multiple objects at once, call `delete()` on a filtered queryset. It's >>> Device.objects.filter(name__icontains='test').count() 27 >>> Device.objects.filter(name__icontains='test').delete() -(35, {'extras.CustomFieldValue': 0, 'dcim.DeviceBay': 0, 'secrets.Secret': 0, -'dcim.InterfaceConnection': 4, 'extras.ImageAttachment': 0, 'dcim.Device': 27, -'dcim.Interface': 4, 'dcim.ConsolePort': 0, 'dcim.PowerPort': 0}) +(35, {'dcim.DeviceBay': 0, 'secrets.Secret': 0, 'dcim.InterfaceConnection': 4, +'extras.ImageAttachment': 0, 'dcim.Device': 27, 'dcim.Interface': 4, +'dcim.ConsolePort': 0, 'dcim.PowerPort': 0}) ``` !!! warning diff --git a/docs/configuration/optional-settings.md b/docs/configuration/optional-settings.md index eb60222269..fe43f0483b 100644 --- a/docs/configuration/optional-settings.md +++ b/docs/configuration/optional-settings.md @@ -460,7 +460,7 @@ NetBox can be configured to support remote user authentication by inferring user Default: `'HTTP_REMOTE_USER'` -When remote user authentication is in use, this is the name of the HTTP header which informs NetBox of the currently authenticated user. (Requires `REMOTE_AUTH_ENABLED`.) +When remote user authentication is in use, this is the name of the HTTP header which informs NetBox of the currently authenticated user. For example, to use the request header `X-Remote-User` it needs to be set to `HTTP_X_REMOTE_USER`. (Requires `REMOTE_AUTH_ENABLED`.) --- diff --git a/docs/core-functionality/ipam.md b/docs/core-functionality/ipam.md index e5ab22f19e..dd6eee77b0 100644 --- a/docs/core-functionality/ipam.md +++ b/docs/core-functionality/ipam.md @@ -15,3 +15,4 @@ --- {!docs/models/ipam/vrf.md!} +{!docs/models/ipam/routetarget.md!} diff --git a/docs/index.md b/docs/index.md index ee7f77f69d..9dedfedfff 100644 --- a/docs/index.md +++ b/docs/index.md @@ -55,7 +55,7 @@ NetBox is built on the [Django](https://djangoproject.com/) Python framework and ## Supported Python Versions -NetBox supports Python 3.6 and 3.7 environments currently. (Support for Python 3.5 was removed in NetBox v2.8.) +NetBox supports Python 3.6, 3.7, and 3.8 environments currently. (Support for Python 3.5 was removed in NetBox v2.8.) ## Getting Started diff --git a/docs/installation/1-postgresql.md b/docs/installation/1-postgresql.md index 20ddaa07f0..bcc670e2b2 100644 --- a/docs/installation/1-postgresql.md +++ b/docs/installation/1-postgresql.md @@ -5,30 +5,27 @@ This section entails the installation and configuration of a local PostgreSQL da !!! warning NetBox requires PostgreSQL 9.6 or higher. Please note that MySQL and other relational databases are **not** currently supported. -The installation instructions provided here have been tested to work on Ubuntu 18.04 and CentOS 7.5. The particular commands needed to install dependencies on other distributions may vary significantly. Unfortunately, this is outside the control of the NetBox maintainers. Please consult your distribution's documentation for assistance with any errors. - ## Installation #### Ubuntu -If a recent enough version of PostgreSQL is not available through your distribution's package manager, you'll need to install it from an official [PostgreSQL repository](https://wiki.postgresql.org/wiki/Apt). +Install the PostgreSQL server and client development libraries using `apt`. ```no-highlight -# apt-get update -# apt-get install -y postgresql libpq-dev +sudo apt update +sudo apt install -y postgresql libpq-dev ``` #### CentOS -CentOS 7 does not ship with a recent enough version of PostgreSQL, so it will need to be installed from an external repository. The instructions below show the installation of PostgreSQL 9.6, however you may opt to install a more recent version. +PostgreSQL 9.6 and later are available natively on CentOS 8.2. If using an earlier CentOS release, you may need to [install it from an RPM](https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/). ```no-highlight -# yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm -# yum install -y postgresql96 postgresql96-server postgresql96-devel -# /usr/pgsql-9.6/bin/postgresql96-setup initdb +sudo yum install -y postgresql-server libpq-devel +sudo postgresql-setup --initdb ``` -CentOS users should modify the PostgreSQL configuration to accept password-based authentication by replacing `ident` with `md5` for all host entries within `/var/lib/pgsql/9.6/data/pg_hba.conf`. For example: +CentOS configures ident host-based authentication for PostgreSQL by default. Because NetBox will need to authenticate using a username and password, modify `/var/lib/pgsql/data/pg_hba.conf` to support MD5 authentication by changing `ident` to `md5` for the lines below: ```no-highlight host all all 127.0.0.1/32 md5 @@ -38,8 +35,8 @@ host all all ::1/128 md5 Then, start the service and enable it to run at boot: ```no-highlight -# systemctl start postgresql-9.6 -# systemctl enable postgresql-9.6 +sudo systemctl start postgresql +sudo systemctl enable postgresql ``` ## Database Creation @@ -50,8 +47,8 @@ At a minimum, we need to create a database for NetBox and assign it a username a **Do not use the password from the example.** Choose a strong, random password to ensure secure database authentication for your NetBox installation. ```no-highlight -# sudo -u postgres psql -psql (10.12 (Ubuntu 10.12-0ubuntu0.18.04.1)) +$ sudo -u postgres psql +psql (12.5 (Ubuntu 12.5-0ubuntu0.20.04.1)) Type "help" for help. postgres=# CREATE DATABASE netbox; @@ -68,13 +65,16 @@ postgres=# \q You can verify that authentication works issuing the following command and providing the configured password. (Replace `localhost` with your database server if using a remote database.) ```no-highlight -# psql --username netbox --password --host localhost netbox +$ psql --username netbox --password --host localhost netbox Password for user netbox: -psql (10.12 (Ubuntu 10.12-0ubuntu0.18.04.1)) +psql (12.5 (Ubuntu 12.5-0ubuntu0.20.04.1)) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) Type "help" for help. +netbox=> \conninfo +You are connected to database "netbox" as user "netbox" on host "localhost" (address "127.0.0.1") at port "5432". +SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) netbox=> \q ``` -If successful, you will enter a `netbox` prompt. Type `\q` to exit. +If successful, you will enter a `netbox` prompt. Type `\conninfo` to confirm your connection, or type `\q` to exit. diff --git a/docs/installation/2-redis.md b/docs/installation/2-redis.md index 20f0095d06..19ec9073e8 100644 --- a/docs/installation/2-redis.md +++ b/docs/installation/2-redis.md @@ -10,16 +10,15 @@ ### Ubuntu ```no-highlight -# apt-get install -y redis-server +sudo apt install -y redis-server ``` ### CentOS ```no-highlight -# yum install -y epel-release -# yum install -y redis -# systemctl start redis -# systemctl enable redis +sudo yum install -y redis +sudo systemctl start redis +sudo systemctl enable redis ``` You may wish to modify the Redis configuration at `/etc/redis.conf` or `/etc/redis/redis.conf`, however in most cases the default configuration is sufficient. diff --git a/docs/installation/3-netbox.md b/docs/installation/3-netbox.md index 54ecd284a7..39189bbd1c 100644 --- a/docs/installation/3-netbox.md +++ b/docs/installation/3-netbox.md @@ -7,40 +7,39 @@ This section of the documentation discusses installing and configuring the NetBo Begin by installing all system packages required by NetBox and its dependencies. !!! note - NetBox v2.8.0 and later require Python 3.6 or 3.7. This documentation assumes Python 3.6. + NetBox v2.8.0 and later require Python 3.6, 3.7, or 3.8. This documentation assumes Python 3.6. ### Ubuntu ```no-highlight -# apt-get install -y python3.6 python3-pip python3-venv python3-dev build-essential libxml2-dev libxslt1-dev libffi-dev libpq-dev libssl-dev zlib1g-dev +sudo apt install -y python3.6 python3-pip python3-venv python3-dev build-essential libxml2-dev libxslt1-dev libffi-dev libpq-dev libssl-dev zlib1g-dev ``` ### CentOS ```no-highlight -# yum install -y gcc python36 python36-devel python36-setuptools libxml2-devel libxslt-devel libffi-devel openssl-devel redhat-rpm-config -# easy_install-3.6 pip +sudo yum install -y gcc python36 python36-devel python3-pip libxml2-devel libxslt-devel libffi-devel openssl-devel redhat-rpm-config ``` Before continuing with either platform, update pip (Python's package management tool) to its latest release: ```no-highlight -# pip3 install --upgrade pip +sudo pip3 install --upgrade pip ``` ## Download NetBox -This documentation provides two options for installing NetBox: from a downloadable archive, or from the git repository. Installing from a package (option A below) requires manually fetching and decompressing the archive for every future update, whereas installation via git (option B) allows for seamless upgrades by re-pulling the `master` branch. +This documentation provides two options for installing NetBox: from a downloadable archive, or from the git repository. Installing from a package (option A below) requires manually fetching and extracting the archive for every future update, whereas installation via git (option B) allows for seamless upgrades by re-pulling the `master` branch. ### Option A: Download a Release Archive Download the [latest stable release](https://github.com/netbox-community/netbox/releases) from GitHub as a tarball or ZIP archive and extract it to your desired path. In this example, we'll use `/opt/netbox` as the NetBox root. ```no-highlight -# wget https://github.com/netbox-community/netbox/archive/vX.Y.Z.tar.gz -# tar -xzf vX.Y.Z.tar.gz -C /opt -# ln -s /opt/netbox-X.Y.Z/ /opt/netbox -# ls -l /opt | grep netbox +$ sudo wget https://github.com/netbox-community/netbox/archive/vX.Y.Z.tar.gz +$ sudo tar -xzf vX.Y.Z.tar.gz -C /opt +$ sudo ln -s /opt/netbox-X.Y.Z/ /opt/netbox +$ ls -l /opt | grep netbox lrwxrwxrwx 1 root root 13 Jul 20 13:44 netbox -> netbox-2.9.0/ drwxr-xr-x 2 root root 4096 Jul 20 13:44 netbox-2.9.0 ``` @@ -53,7 +52,7 @@ drwxr-xr-x 2 root root 4096 Jul 20 13:44 netbox-2.9.0 Create the base directory for the NetBox installation. For this guide, we'll use `/opt/netbox`. ```no-highlight -# mkdir -p /opt/netbox/ && cd /opt/netbox/ +sudo mkdir -p /opt/netbox/ && cd /opt/netbox/ ``` If `git` is not already installed, install it: @@ -61,19 +60,19 @@ If `git` is not already installed, install it: #### Ubuntu ```no-highlight -# apt-get install -y git +sudo apt install -y git ``` #### CentOS ```no-highlight -# yum install -y git +sudo yum install -y git ``` Next, clone the **master** branch of the NetBox GitHub repository into the current directory. (This branch always holds the current stable release.) ```no-highlight -# git clone -b master https://github.com/netbox-community/netbox.git . +$ sudo git clone -b master https://github.com/netbox-community/netbox.git . Cloning into '.'... remote: Counting objects: 1994, done. remote: Compressing objects: 100% (150/150), done. @@ -93,16 +92,16 @@ Create a system user account named `netbox`. We'll configure the WSGI and HTTP s #### Ubuntu ``` -# adduser --system --group netbox -# chown --recursive netbox /opt/netbox/netbox/media/ +sudo adduser --system --group netbox +sudo chown --recursive netbox /opt/netbox/netbox/media/ ``` #### CentOS ``` -# groupadd --system netbox -# adduser --system -g netbox netbox -# chown --recursive netbox /opt/netbox/netbox/media/ +sudo groupadd --system netbox +sudo adduser --system -g netbox netbox +sudo chown --recursive netbox /opt/netbox/netbox/media/ ``` ## Configuration @@ -110,8 +109,8 @@ Create a system user account named `netbox`. We'll configure the WSGI and HTTP s Move into the NetBox configuration directory and make a copy of `configuration.example.py` named `configuration.py`. This file will hold all of your local configuration parameters. ```no-highlight -# cd /opt/netbox/netbox/netbox/ -# cp configuration.example.py configuration.py +cd /opt/netbox/netbox/netbox/ +sudo cp configuration.example.py configuration.py ``` Open `configuration.py` with your preferred editor to begin configuring NetBox. NetBox offers [many configuration parameters](/configuration/), but only the following four are required for new installations: @@ -154,7 +153,7 @@ DATABASE = { Redis is a in-memory key-value store used by NetBox for caching and background task queuing. Redis typically requires minimal configuration; the values below should suffice for most installations. See the [configuration documentation](/configuration/required-settings/#redis) for more detail on individual parameters. -Note that NetBox requires the specification of two separate Redis databases: `tasks` and `caching`. These may both be provided by the same Redis service, however each should have a unique database ID. +Note that NetBox requires the specification of two separate Redis databases: `tasks` and `caching`. These may both be provided by the same Redis service, however each should have a unique numeric database ID. ```python REDIS = { @@ -182,7 +181,7 @@ This parameter must be assigned a randomly-generated key employed as a salt for A simple Python script named `generate_secret_key.py` is provided in the parent directory to assist in generating a suitable key: ```no-highlight -# python3 ../generate_secret_key.py +python3 ../generate_secret_key.py ``` !!! warning @@ -199,7 +198,7 @@ All Python packages required by NetBox are listed in `requirements.txt` and will The [NAPALM automation](https://napalm-automation.net/) library allows NetBox to fetch live data from devices and return it to a requester via its REST API. The `NAPALM_USERNAME` and `NAPALM_PASSWORD` configuration parameters define the credentials to be used when connecting to a device. ```no-highlight -# echo napalm >> /opt/netbox/local_requirements.txt +sudo echo napalm >> /opt/netbox/local_requirements.txt ``` ### Remote File Storage @@ -207,7 +206,7 @@ The [NAPALM automation](https://napalm-automation.net/) library allows NetBox to By default, NetBox will use the local filesystem to store uploaded files. To use a remote filesystem, install the [`django-storages`](https://django-storages.readthedocs.io/en/stable/) library and configure your [desired storage backend](/configuration/optional-settings/#storage_backend) in `configuration.py`. ```no-highlight -# echo django-storages >> /opt/netbox/local_requirements.txt +sudo echo django-storages >> /opt/netbox/local_requirements.txt ``` ## Run the Upgrade Script @@ -220,7 +219,7 @@ Once NetBox has been configured, we're ready to proceed with the actual installa * Aggregate static resource files on disk ```no-highlight -# /opt/netbox/upgrade.sh +sudo /opt/netbox/upgrade.sh ``` !!! note @@ -231,7 +230,7 @@ Once NetBox has been configured, we're ready to proceed with the actual installa NetBox does not come with any predefined user accounts. You'll need to create a super user (administrative account) to be able to log into NetBox. First, enter the Python virtual environment created by the upgrade script: ```no-highlight -# source /opt/netbox/venv/bin/activate +source /opt/netbox/venv/bin/activate ``` Once the virtual environment has been activated, you should notice the string `(venv)` prepended to your console prompt. @@ -239,8 +238,8 @@ Once the virtual environment has been activated, you should notice the string `( Next, we'll create a superuser account using the `createsuperuser` Django management command (via `manage.py`). Specifying an email address for the user is not required, but be sure to use a very strong password. ```no-highlight -(venv) # cd /opt/netbox/netbox -(venv) # python3 manage.py createsuperuser +(venv) $ cd /opt/netbox/netbox +(venv) $ python3 manage.py createsuperuser Username: admin Email address: admin@example.com Password: @@ -250,28 +249,33 @@ Superuser created successfully. ## Test the Application -At this point, we should be able to run NetBox. We can check by starting a development instance: +At this point, we should be able to run NetBox's development server for testing. We can check by starting a development instance: ```no-highlight -(venv) # python3 manage.py runserver 0.0.0.0:8000 --insecure +(venv) $ python3 manage.py runserver 0.0.0.0:8000 --insecure Performing system checks... System check identified no issues (0 silenced). -November 28, 2018 - 09:33:45 -Django version 2.0.9, using settings 'netbox.settings' +November 17, 2020 - 16:08:13 +Django version 3.1.3, using settings 'netbox.settings' Starting development server at http://0.0.0.0:8000/ Quit the server with CONTROL-C. ``` -Next, connect to the name or IP of the server (as defined in `ALLOWED_HOSTS`) on port 8000; for example, . You should be greeted with the NetBox home page. Note that this built-in web service is for development and testing purposes only. **It is not suited for production use.** +Next, connect to the name or IP of the server (as defined in `ALLOWED_HOSTS`) on port 8000; for example, . You should be greeted with the NetBox home page. + +!!! warning + The development server is for development and testing purposes only. It is neither performant nor secure enough for production use. **Do not use it in production.** !!! warning If the test service does not run, or you cannot reach the NetBox home page, something has gone wrong. Do not proceed with the rest of this guide until the installation has been corrected. -Note that the initial UI will be locked down for non-authenticated users. +Note that the initial user interface will be locked down for non-authenticated users. ![NetBox UI as seen by a non-authenticated user](../media/installation/netbox_ui_guest.png) -Try logging in as the super user we just created. Once authenticated, you'll be able to access all areas of the UI: +Try logging in using the superuser account we just created. Once authenticated, you'll be able to access all areas of the UI: ![NetBox UI as seen by an administrator](../media/installation/netbox_ui_admin.png) + +Type `Ctrl+c` to stop the development server. diff --git a/docs/installation/4-gunicorn.md b/docs/installation/4-gunicorn.md index 48cab756ab..8168ce98bf 100644 --- a/docs/installation/4-gunicorn.md +++ b/docs/installation/4-gunicorn.md @@ -1,32 +1,31 @@ # Gunicorn -Like most Django applications, NetBox runs as a [WSGI application](https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface) behind an HTTP server. This documentation shows how to install and configure [gunicorn](http://gunicorn.org/) for this role, however other WSGIs are available and should work similarly well. +Like most Django applications, NetBox runs as a [WSGI application](https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface) behind an HTTP server. This documentation shows how to install and configure [gunicorn](http://gunicorn.org/) (which is automatically installed with NetBox) for this role, however other WSGI servers are available and should work similarly well. [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/) is a popular alternative. ## Configuration -NetBox ships with a default configuration file for gunicorn. To use it, copy `/opt/netbox/contrib/gunicorn.py` to `/opt/netbox/gunicorn.py`. (We make a copy of this file rather than pointing to it directly to ensure that any changes to it do not get overwritten by a future upgrade.) +NetBox ships with a default configuration file for gunicorn. To use it, copy `/opt/netbox/contrib/gunicorn.py` to `/opt/netbox/gunicorn.py`. (We make a copy of this file rather than pointing to it directly to ensure that any local changes to it do not get overwritten by a future upgrade.) ```no-highlight -# cd /opt/netbox -# cp contrib/gunicorn.py /opt/netbox/gunicorn.py +sudo cp /opt/netbox/contrib/gunicorn.py /opt/netbox/gunicorn.py ``` -While this default configuration should suffice for most initial installations, you may wish to edit this file to change the bound IP address and/or port number, or to make performance-related adjustments. See [the Gunicorn documentation](https://docs.gunicorn.org/en/stable/configure.html) for the available configuration parameters. +While the provided configuration should suffice for most initial installations, you may wish to edit this file to change the bound IP address and/or port number, or to make performance-related adjustments. See [the Gunicorn documentation](https://docs.gunicorn.org/en/stable/configure.html) for the available configuration parameters. ## systemd Setup We'll use systemd to control both gunicorn and NetBox's background worker process. First, copy `contrib/netbox.service` and `contrib/netbox-rq.service` to the `/etc/systemd/system/` directory and reload the systemd dameon: ```no-highlight -# cp contrib/*.service /etc/systemd/system/ -# systemctl daemon-reload +sudo cp -v /opt/netbox/contrib/*.service /etc/systemd/system/ +sudo systemctl daemon-reload ``` Then, start the `netbox` and `netbox-rq` services and enable them to initiate at boot time: ```no-highlight -# systemctl start netbox netbox-rq -# systemctl enable netbox netbox-rq +sudo systemctl start netbox netbox-rq +sudo systemctl enable netbox netbox-rq ``` You can use the command `systemctl status netbox` to verify that the WSGI service is running: @@ -34,16 +33,20 @@ You can use the command `systemctl status netbox` to verify that the WSGI servic ```no-highlight # systemctl status netbox.service ● netbox.service - NetBox WSGI Service - Loaded: loaded (/etc/systemd/system/netbox.service; enabled; vendor preset: enabled) - Active: active (running) since Thu 2019-12-12 19:23:40 UTC; 25s ago - Docs: https://netbox.readthedocs.io/en/stable/ - Main PID: 11993 (gunicorn) - Tasks: 6 (limit: 2362) - CGroup: /system.slice/netbox.service - ├─11993 /usr/bin/python3 /usr/local/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/... - ├─12015 /usr/bin/python3 /usr/local/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/... - ├─12016 /usr/bin/python3 /usr/local/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/... + Loaded: loaded (/etc/systemd/system/netbox.service; enabled; vendor preset: enabled) + Active: active (running) since Tue 2020-11-17 16:18:23 UTC; 3min 35s ago + Docs: https://netbox.readthedocs.io/en/stable/ + Main PID: 22836 (gunicorn) + Tasks: 6 (limit: 2345) + Memory: 339.3M + CGroup: /system.slice/netbox.service + ├─22836 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid> + ├─22854 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid> + ├─22855 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid> ... ``` +!!! note + If the NetBox service fails to start, issue the command `journalctl -eu netbox` to check for log messages that may indicate the problem. + Once you've verified that the WSGI workers are up and running, move on to HTTP server setup. diff --git a/docs/installation/5-http-server.md b/docs/installation/5-http-server.md index 5bd04253a2..eba0db21bb 100644 --- a/docs/installation/5-http-server.md +++ b/docs/installation/5-http-server.md @@ -1,9 +1,9 @@ # HTTP Server Setup -This documentation provides example configurations for both [nginx](https://www.nginx.com/resources/wiki/) and [Apache](http://httpd.apache.org/docs/2.4), though any HTTP server which supports WSGI should be compatible. +This documentation provides example configurations for both [nginx](https://www.nginx.com/resources/wiki/) and [Apache](http://httpd.apache.org/docs/current/), though any HTTP server which supports WSGI should be compatible. !!! info - For the sake of brevity, only Ubuntu 18.04 instructions are provided here, these tasks are not unique to NetBox and should carry over to other distributions with minimal changes. Please consult your distribution's documentation for assistance if needed. + For the sake of brevity, only Ubuntu 20.04 instructions are provided here. These tasks are not unique to NetBox and should carry over to other distributions with minimal changes. Please consult your distribution's documentation for assistance if needed. ## Obtain an SSL Certificate @@ -12,7 +12,7 @@ To enable HTTPS access to NetBox, you'll need a valid SSL certificate. You can p The command below can be used to generate a self-signed certificate for testing purposes, however it is strongly recommended to use a certificate from a trusted authority in production. Two files will be created: the public certificate (`netbox.crt`) and the private key (`netbox.key`). The certificate is published to the world, whereas the private key must be kept secret at all times. ```no-highlight -# openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ +sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout /etc/ssl/private/netbox.key \ -out /etc/ssl/certs/netbox.crt ``` @@ -26,27 +26,26 @@ The above command will prompt you for additional details of the certificate; all Begin by installing nginx: ```no-highlight -# apt-get install -y nginx +sudo apt install -y nginx ``` Once nginx is installed, copy the nginx configuration file provided by NetBox to `/etc/nginx/sites-available/netbox`. Be sure to replace `netbox.example.com` with the domain name or IP address of your installation. (This should match the value configured for `ALLOWED_HOSTS` in `configuration.py`.) ```no-highlight -# cp /opt/netbox/contrib/nginx.conf /etc/nginx/sites-available/netbox +sudo cp /opt/netbox/contrib/nginx.conf /etc/nginx/sites-available/netbox ``` Then, delete `/etc/nginx/sites-enabled/default` and create a symlink in the `sites-enabled` directory to the configuration file you just created. ```no-highlight -# cd /etc/nginx/sites-enabled/ -# rm default -# ln -s /etc/nginx/sites-available/netbox +sudo rm /etc/nginx/sites-enabled/default +sudo ln -s /etc/nginx/sites-available/netbox /etc/nginx/sites-enabled/netbox ``` Finally, restart the `nginx` service to use the new configuration. ```no-highlight -# service nginx restart +sudo systemctl restart nginx ``` ### Option B: Apache @@ -54,26 +53,26 @@ Finally, restart the `nginx` service to use the new configuration. Begin by installing Apache: ```no-highlight -# apt-get install -y apache2 +sudo apt install -y apache2 ``` Next, copy the default configuration file to `/etc/apache2/sites-available/`. Be sure to modify the `ServerName` parameter appropriately. ```no-highlight -# cp /opt/netbox/contrib/apache.conf /etc/apache2/sites-available/netbox.conf +sudo cp /opt/netbox/contrib/apache.conf /etc/apache2/sites-available/netbox.conf ``` Finally, ensure that the required Apache modules are enabled, enable the `netbox` site, and reload Apache: ```no-highlight -# a2enmod ssl proxy proxy_http headers -# a2ensite netbox -# service apache2 restart +sudo a2enmod ssl proxy proxy_http headers +sudo a2ensite netbox +sudo systemctl restart apache2 ``` ## Confirm Connectivity -At this point, you should be able to connect to the HTTP service at the server name or IP address you provided. +At this point, you should be able to connect to the HTTPS service at the server name or IP address you provided. !!! info Please keep in mind that the configurations provided here are bare minimums required to get NetBox up and running. You may want to make adjustments to better suit your production environment. @@ -91,5 +90,5 @@ If you are unable to connect to the HTTP server, check that: If you are able to connect but receive a 502 (bad gateway) error, check the following: * The WSGI worker processes (gunicorn) are running (`systemctl status netbox` should show a status of "active (running)") -* nginx/Apache is configured to connect to the port on which gunicorn is listening (default is 8001). +* Nginx/Apache is configured to connect to the port on which gunicorn is listening (default is 8001). * SELinux is not preventing the reverse proxy connection. You may need to allow HTTP network connections with the command `setsebool -P httpd_can_network_connect 1` diff --git a/docs/installation/6-ldap.md b/docs/installation/6-ldap.md index b7d5254138..ce62625318 100644 --- a/docs/installation/6-ldap.md +++ b/docs/installation/6-ldap.md @@ -9,13 +9,13 @@ This guide explains how to implement LDAP authentication using an external serve On Ubuntu: ```no-highlight -# apt-get install -y libldap2-dev libsasl2-dev libssl-dev +sudo apt install -y libldap2-dev libsasl2-dev libssl-dev ``` On CentOS: ```no-highlight -# yum install -y openldap-devel +sudo yum install -y openldap-devel ``` ### Install django-auth-ldap @@ -23,15 +23,14 @@ On CentOS: Activate the Python virtual environment and install the `django-auth-ldap` package using pip: ```no-highlight -# cd /opt/netbox/ -# source venv/bin/activate -(venv) # pip3 install django-auth-ldap +source /opt/netbox/venv/bin/activate +pip3 install django-auth-ldap ``` Once installed, add the package to `local_requirements.txt` to ensure it is re-installed during future rebuilds of the virtual environment: ```no-highlight -(venv) # echo django-auth-ldap >> local_requirements.txt +sudo echo django-auth-ldap >> /opt/netbox/local_requirements.txt ``` ## Configuration @@ -42,7 +41,7 @@ First, enable the LDAP authentication backend in `configuration.py`. (Be sure to REMOTE_AUTH_BACKEND = 'netbox.authentication.LDAPBackend' ``` -Next, create a file in the same directory as `configuration.py` (typically `netbox/netbox/`) named `ldap_config.py`. Define all of the parameters required below in `ldap_config.py`. Complete documentation of all `django-auth-ldap` configuration options is included in the project's [official documentation](http://django-auth-ldap.readthedocs.io/). +Next, create a file in the same directory as `configuration.py` (typically `/opt/netbox/netbox/netbox/`) named `ldap_config.py`. Define all of the parameters required below in `ldap_config.py`. Complete documentation of all `django-auth-ldap` configuration options is included in the project's [official documentation](http://django-auth-ldap.readthedocs.io/). ### General Server Configuration diff --git a/docs/installation/index.md b/docs/installation/index.md index b520f29178..730176e0ca 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -1,5 +1,7 @@ # Installation +The installation instructions provided here have been tested to work on Ubuntu 20.04 and CentOS 8.2. The particular commands needed to install dependencies on other distributions may vary significantly. Unfortunately, this is outside the control of the NetBox maintainers. Please consult your distribution's documentation for assistance with any errors. + The following sections detail how to set up a new instance of NetBox: 1. [PostgreSQL database](1-postgresql.md) @@ -9,6 +11,14 @@ The following sections detail how to set up a new instance of NetBox: 5. [HTTP server](5-http-server.md) 6. [LDAP authentication](6-ldap.md) (optional) +## Requirements + +| Dependency | Minimum Version | +|------------|-----------------| +| Python | 3.6 | +| PostgreSQL | 9.6 | +| Redis | 4.0 | + Below is a simplified overview of the NetBox application stack for reference: ![NetBox UI as seen by a non-authenticated user](../media/installation/netbox_application_stack.png) diff --git a/docs/installation/upgrading.md b/docs/installation/upgrading.md index 028fcb2a45..cdd20f01b4 100644 --- a/docs/installation/upgrading.md +++ b/docs/installation/upgrading.md @@ -2,7 +2,7 @@ ## Review the Release Notes -Prior to upgrading your NetBox instance, be sure to carefully review all [release notes](../../release-notes/) that have been published since your current version was released. Although the upgrade process typically does not involve additional work, certain releases may introduce breaking or backward-incompatible changes. These are called out in the release notes under the version in which the change went into effect. +Prior to upgrading your NetBox instance, be sure to carefully review all [release notes](../../release-notes/) that have been published since your current version was released. Although the upgrade process typically does not involve additional work, certain releases may introduce breaking or backward-incompatible changes. These are called out in the release notes under the release in which the change went into effect. ## Update Dependencies to Required Versions @@ -14,7 +14,7 @@ NetBox v2.9.0 and later requires the following: | PostgreSQL | 9.6 | | Redis | 4.0 | -## Install the Latest Code +## Install the Latest Release As with the initial installation, you can upgrade NetBox by either downloading the latest release package or by cloning the `master` branch of the git repository. @@ -25,47 +25,36 @@ Download the [latest stable release](https://github.com/netbox-community/netbox/ Download and extract the latest version: ```no-highlight -# wget https://github.com/netbox-community/netbox/archive/vX.Y.Z.tar.gz -# tar -xzf vX.Y.Z.tar.gz -C /opt -# cd /opt/ -# ln -sfn /opt/netbox-X.Y.Z/ /opt/netbox +wget https://github.com/netbox-community/netbox/archive/vX.Y.Z.tar.gz +sudo tar -xzf vX.Y.Z.tar.gz -C /opt +sudo ln -sfn /opt/netbox-X.Y.Z/ /opt/netbox ``` -Copy the 'configuration.py' you created when first installing to the new version: +Copy `local_requirements.txt`, `configuration.py`, and `ldap_config.py` (if present) from the current installation to the new version: ```no-highlight -# cp /opt/netbox-X.Y.Z/netbox/netbox/configuration.py /opt/netbox/netbox/netbox/configuration.py -``` - -Copy your local requirements file if used: - -```no-highlight -# cp /opt/netbox-X.Y.Z/local_requirements.txt /opt/netbox/local_requirements.txt -``` - -Also copy the LDAP configuration if using LDAP: - -```no-highlight -# cp /opt/netbox-X.Y.Z/netbox/netbox/ldap_config.py /opt/netbox/netbox/netbox/ldap_config.py +sudo cp /opt/netbox-X.Y.Z/local_requirements.txt /opt/netbox/ +sudo cp /opt/netbox-X.Y.Z/netbox/netbox/configuration.py /opt/netbox/netbox/netbox/ +sudo cp /opt/netbox-X.Y.Z/netbox/netbox/ldap_config.py /opt/netbox/netbox/netbox/ ``` Be sure to replicate your uploaded media as well. (The exact action necessary will depend on where you choose to store your media, but in general moving or copying the media directory will suffice.) ```no-highlight -# cp -pr /opt/netbox-X.Y.Z/netbox/media/ /opt/netbox/netbox/ +sudo cp -pr /opt/netbox-X.Y.Z/netbox/media/ /opt/netbox/netbox/ ``` -Also make sure to copy over any custom scripts and reports that you've made. Note that if these are stored outside the project root, you will not need to copy them. (Check the `SCRIPTS_ROOT` and `REPORTS_ROOT` parameters in the configuration file above if you're unsure.) +Also make sure to copy or link any custom scripts and reports that you've made. Note that if these are stored outside the project root, you will not need to copy them. (Check the `SCRIPTS_ROOT` and `REPORTS_ROOT` parameters in the configuration file above if you're unsure.) ```no-highlight -# cp -r /opt/netbox-X.Y.Z/netbox/scripts /opt/netbox/netbox/ -# cp -r /opt/netbox-X.Y.Z/netbox/reports /opt/netbox/netbox/ +sudo cp -r /opt/netbox-X.Y.Z/netbox/scripts /opt/netbox/netbox/ +sudo cp -r /opt/netbox-X.Y.Z/netbox/reports /opt/netbox/netbox/ ``` If you followed the original installation guide to set up gunicorn, be sure to copy its configuration as well: ```no-highlight -# cp /opt/netbox-X.Y.Z/gunicorn.py /opt/netbox/gunicorn.py +sudo cp /opt/netbox-X.Y.Z/gunicorn.py /opt/netbox/ ``` ### Option B: Clone the Git Repository @@ -73,10 +62,9 @@ If you followed the original installation guide to set up gunicorn, be sure to c This guide assumes that NetBox is installed at `/opt/netbox`. Pull down the most recent iteration of the master branch: ```no-highlight -# cd /opt/netbox -# git checkout master -# git pull origin master -# git status +cd /opt/netbox +sudo git checkout master +sudo git pull origin master ``` ## Run the Upgrade Script @@ -84,10 +72,10 @@ This guide assumes that NetBox is installed at `/opt/netbox`. Pull down the most Once the new code is in place, verify that any optional Python packages required by your deployment (e.g. `napalm` or `django-auth-ldap`) are listed in `local_requirements.txt`. Then, run the upgrade script: ```no-highlight -# ./upgrade.sh +sudo ./upgrade.sh ``` -This script: +This script performs the following actions: * Destroys and rebuilds the Python virtual environment * Installs all required Python packages (listed in `requirements.txt`) @@ -99,23 +87,20 @@ This script: * Clears all cached data to prevent conflicts with the new release !!! note - It's possible that the upgrade script will display a notice warning of unreflected database migrations: - - Your models have changes that are not yet reflected in a migration, and so won't be applied. - Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them. - - This may occur due to semantic differences in environment, and can be safely ignored. Never attempt to create new migrations unless you are intentionally modifying the database schema. + If the upgrade script prompts a warning about unreflected database migrations, this indicates that some change has + been made to your local codebase and should be investigated. Never attempt to create new migrations unless you are + intentionally modifying the database schema. ## Restart the NetBox Services !!! warning - If you are upgrading from an installation that does not use a Python virtual environment, you'll need to update the systemd service files to reference the new Python and gunicorn executables before restarting the services. These are located in `/opt/netbox/venv/bin/`. See the example service files in `/opt/netbox/contrib/` for reference. + If you are upgrading from an installation that does not use a Python virtual environment (any release prior to v2.7.9), you'll need to update the systemd service files to reference the new Python and gunicorn executables before restarting the services. These are located in `/opt/netbox/venv/bin/`. See the example service files in `/opt/netbox/contrib/` for reference. Finally, restart the gunicorn and RQ services: ```no-highlight -# sudo systemctl restart netbox netbox-rq +sudo systemctl restart netbox netbox-rq ``` !!! note - It's possible you are still using supervisord instead of systemd. If so, please see the instructions for [migrating to systemd](migrating-to-systemd.md). + If upgrading from an installation that uses supervisord, please see the instructions for [migrating to systemd](migrating-to-systemd.md). The use of supervisord is no longer supported. diff --git a/docs/models/ipam/routetarget.md b/docs/models/ipam/routetarget.md new file mode 100644 index 0000000000..b71e969046 --- /dev/null +++ b/docs/models/ipam/routetarget.md @@ -0,0 +1,5 @@ +# Route Targets + +A route target is a particular type of [extended BGP community](https://tools.ietf.org/html/rfc4360#section-4) used to control the redistribution of routes among VRF tables in a network. Route targets can be assigned to individual VRFs in NetBox as import or export targets (or both) to model this exchange in an L3VPN. Each route target must be given a unique name, which should be in a format prescribed by [RFC 4364](https://tools.ietf.org/html/rfc4364#section-4.2), similar to a VR route distinguisher. + +Each route target can optionally be assigned to a tenant, and may have tags assigned to it. diff --git a/docs/models/ipam/vrf.md b/docs/models/ipam/vrf.md index 599d05c828..392141fdde 100644 --- a/docs/models/ipam/vrf.md +++ b/docs/models/ipam/vrf.md @@ -10,3 +10,5 @@ By default, NetBox will allow duplicate prefixes to be assigned to a VRF. This b !!! note Enforcement of unique IP space can be toggled for global table (non-VRF prefixes) using the `ENFORCE_GLOBAL_UNIQUE` configuration setting. + +Each VRF may have one or more import and/or export route targets applied to it. Route targets are used to control the exchange of routes (prefixes) among VRFs in L3VPNs. diff --git a/docs/release-notes/index.md b/docs/release-notes/index.md index f314c53717..8990f83e04 120000 --- a/docs/release-notes/index.md +++ b/docs/release-notes/index.md @@ -1 +1 @@ -version-2.9.md \ No newline at end of file +version-2.10.md \ No newline at end of file diff --git a/docs/release-notes/version-2.10.md b/docs/release-notes/version-2.10.md new file mode 100644 index 0000000000..15ac1fc043 --- /dev/null +++ b/docs/release-notes/version-2.10.md @@ -0,0 +1,147 @@ +# NetBox v2.10 + +## v2.10.0 (2020-12-14) + +**NOTE:** This release completely removes support for embedded graphs. + +**NOTE:** The Django templating language (DTL) is no longer supported for export templates. Ensure that all export templates use Jinja2 before upgrading. + +### New Features + +#### Route Targets ([#259](https://github.com/netbox-community/netbox/issues/259)) + +This release introduces support for modeling L3VPN route targets, which can be used to control the redistribution of advertised prefixes among VRFs. Each VRF may be assigned one or more route targets in the import and/or export direction. Like VRFs, route targets may be assigned to tenants and support tag assignment. + +#### REST API Bulk Deletion ([#3436](https://github.com/netbox-community/netbox/issues/3436)) + +The REST API now supports the bulk deletion of objects of the same type in a single request. Send a `DELETE` HTTP request to the list to the model's list endpoint (e.g. `/api/dcim/sites/`) with a list of JSON objects specifying the numeric ID of each object to be deleted. For example, to delete sites with IDs 10, 11, and 12, issue the following request: + +```no-highlight +curl -s -X DELETE \ +-H "Authorization: Token $TOKEN" \ +-H "Content-Type: application/json" \ +http://netbox/api/dcim/sites/ \ +--data '[{"id": 10}, {"id": 11}, {"id": 12}]' +``` + +#### REST API Bulk Update ([#4882](https://github.com/netbox-community/netbox/issues/4882)) + +Similar to bulk deletion, the REST API also now supports bulk updates. Send a `PUT` or `PATCH` HTTP request to the list to the model's list endpoint (e.g. `/api/dcim/sites/`) with a list of JSON objects specifying the numeric ID of each object and the attribute(s) to be updated. For example, to set a description for sites with IDs 10 and 11, issue the following request: + +```no-highlight +curl -s -X PATCH \ +-H "Authorization: Token $TOKEN" \ +-H "Content-Type: application/json" \ +http://netbox/api/dcim/sites/ \ +--data '[{"id": 10, "description": "Foo"}, {"id": 11, "description": "Bar"}]' +``` + +#### Reimplementation of Custom Fields ([#4878](https://github.com/netbox-community/netbox/issues/4878)) + +NetBox v2.10 introduces a completely overhauled approach to custom fields. Whereas previous versions used CustomFieldValue instances to store values, custom field data is now stored directly on each model instance as JSON data and may be accessed using the `cf` property: + +```python +>>> site = Site.objects.first() +>>> site.cf +{'site_code': 'US-RAL01'} +>>> site.cf['foo'] = 'ABC' +>>> site.full_clean() +>>> site.save() +>>> site = Site.objects.first() +>>> site.cf +{'foo': 'ABC', 'site_code': 'US-RAL01'} +``` + +Additionally, custom selection field choices are now defined on the CustomField model within the admin UI, which greatly simplifies working with choice values. + +#### Improved Cable Trace Performance ([#4900](https://github.com/netbox-community/netbox/issues/4900)) + +All end-to-end cable paths are now cached using the new CablePath backend model. This allows NetBox to now immediately return the complete path originating from any endpoint directly from the database, rather than having to trace each cable recursively. It also resolves some systemic validation issues present in the original implementation. + +**Note:** As part of this change, cable traces will no longer traverse circuits: A circuit termination will be considered the origin or destination of an end-to-end path. + +### Enhancements + +* [#609](https://github.com/netbox-community/netbox/issues/609) - Add min/max value and regex validation for custom fields +* [#1503](https://github.com/netbox-community/netbox/issues/1503) - Allow assigment of secrets to virtual machines +* [#1692](https://github.com/netbox-community/netbox/issues/1692) - Allow assigment of inventory items to parent items in web UI +* [#2179](https://github.com/netbox-community/netbox/issues/2179) - Support the use of multiple port numbers when defining a service +* [#4897](https://github.com/netbox-community/netbox/issues/4897) - Allow filtering by content type identified as `.` string +* [#4918](https://github.com/netbox-community/netbox/issues/4918) - Add a REST API endpoint (`/api/status/`) which returns NetBox's current operational status +* [#4956](https://github.com/netbox-community/netbox/issues/4956) - Include inventory items on primary device view +* [#4967](https://github.com/netbox-community/netbox/issues/4967) - Support tenant assignment for aggregates +* [#5003](https://github.com/netbox-community/netbox/issues/5003) - CSV import now accepts slug values for choice fields +* [#5146](https://github.com/netbox-community/netbox/issues/5146) - Add custom field support for cables, power panels, rack reservations, and virtual chassis +* [#5154](https://github.com/netbox-community/netbox/issues/5154) - The web interface now consumes the entire browser window +* [#5190](https://github.com/netbox-community/netbox/issues/5190) - Add a REST API endpoint for retrieving content types (`/api/extras/content-types/`) +* [#5274](https://github.com/netbox-community/netbox/issues/5274) - Add REST API support for custom fields +* [#5399](https://github.com/netbox-community/netbox/issues/5399) - Show options for cable endpoint types during bulk import +* [#5411](https://github.com/netbox-community/netbox/issues/5411) - Include cable tags in trace view + +### Other Changes + +* [#1846](https://github.com/netbox-community/netbox/issues/1846) - Enable MPTT for InventoryItem hierarchy +* [#2755](https://github.com/netbox-community/netbox/issues/2755) - Switched from Font Awesome/Glyphicons to Material Design icons +* [#4349](https://github.com/netbox-community/netbox/issues/4349) - Dropped support for embedded graphs +* [#4360](https://github.com/netbox-community/netbox/issues/4360) - Dropped support for the Django template language from export templates +* [#4711](https://github.com/netbox-community/netbox/issues/4711) - Renamed Webhook `obj_type` to `content_types` +* [#4941](https://github.com/netbox-community/netbox/issues/4941) - `commit` argument is now required argument in a custom script's `run()` method +* [#5011](https://github.com/netbox-community/netbox/issues/5011) - Standardized name field lengths across all models +* [#5139](https://github.com/netbox-community/netbox/issues/5139) - Omit utilization statistics from RIR list +* [#5225](https://github.com/netbox-community/netbox/issues/5225) - Circuit termination port speed is now an optional field + +### REST API Changes + +* Added support for `PUT`, `PATCH`, and `DELETE` operations on list endpoints (bulk update and delete) +* Added the `/extras/content-types/` endpoint for Django ContentTypes +* Added the `/extras/custom-fields/` endpoint for custom fields +* Removed the `/extras/_custom_field_choices/` endpoint (replaced by new custom fields endpoint) +* Added the `/status/` endpoint to convey NetBox's current status +* circuits.CircuitTermination: + * Added the `/trace/` endpoint + * Replaced `connection_status` with `connected_endpoint_reachable` (boolean) + * Added `cable_peer` and `cable_peer_type` + * `port_speed` may now be null +* dcim.Cable: Added `custom_fields` +* dcim.ConsolePort: + * Replaced `connection_status` with `connected_endpoint_reachable` (boolean) + * Added `cable_peer` and `cable_peer_type` + * Removed `connection_status` from nested serializer +* dcim.ConsoleServerPort: + * Replaced `connection_status` with `connected_endpoint_reachable` (boolean) + * Added `cable_peer` and `cable_peer_type` + * Removed `connection_status` from nested serializer +* dcim.FrontPort: + * Replaced the `/trace/` endpoint with `/paths/`, which returns a list of cable paths + * Added `cable_peer` and `cable_peer_type` +* dcim.Interface: + * Replaced `connection_status` with `connected_endpoint_reachable` (boolean) + * Added `cable_peer` and `cable_peer_type` + * Removed `connection_status` from nested serializer +* dcim.InventoryItem: The `_depth` field has been added to reflect MPTT positioning +* dcim.PowerFeed: + * Added the `/trace/` endpoint + * Added fields `connected_endpoint`, `connected_endpoint_type`, `connected_endpoint_reachable`, `cable_peer`, and `cable_peer_type` +* dcim.PowerOutlet: + * Replaced `connection_status` with `connected_endpoint_reachable` (boolean) + * Added `cable_peer` and `cable_peer_type` + * Removed `connection_status` from nested serializer +* dcim.PowerPanel: Added `custom_fields` +* dcim.PowerPort + * Replaced `connection_status` with `connected_endpoint_reachable` (boolean) + * Added `cable_peer` and `cable_peer_type` + * Removed `connection_status` from nested serializer +* dcim.RackReservation: Added `custom_fields` +* dcim.RearPort: + * Replaced the `/trace/` endpoint with `/paths/`, which returns a list of cable paths + * Added `cable_peer` and `cable_peer_type` +* dcim.VirtualChassis: Added `custom_fields` +* extras.ExportTemplate: The `template_language` field has been removed +* extras.Graph: This API endpoint has been removed (see #4349) +* extras.ImageAttachment: Filtering by `content_type` now takes a string in the form `.` +* extras.ObjectChange: Filtering by `changed_object_type` now takes a string in the form `.` +* ipam.Aggregate: Added `tenant` field +* ipam.RouteTarget: New endpoint +* ipam.Service: Renamed `port` to `ports`; now holds a list of one or more port numbers +* ipam.VRF: Added `import_targets` and `export_targets` fields +* secrets.Secret: Removed `device` field; replaced with `assigned_object` generic foreign key. This may represent either a device or a virtual machine. Assign an object by setting `assigned_object_type` and `assigned_object_id`. diff --git a/docs/rest-api/overview.md b/docs/rest-api/overview.md index d16cd059d1..a3c8143ebe 100644 --- a/docs/rest-api/overview.md +++ b/docs/rest-api/overview.md @@ -468,16 +468,16 @@ http://netbox/api/dcim/sites/ \ ] ``` -### Modifying an Object +### Updating an Object To modify an object which has already been created, make a `PATCH` request to the model's _detail_ endpoint specifying its unique numeric ID. Include any data which you wish to update on the object. As with object creation, the `Authorization` and `Content-Type` headers must also be specified. ```no-highlight curl -s -X PATCH \ -> -H "Authorization: Token $TOKEN" \ -> -H "Content-Type: application/json" \ -> http://netbox/api/ipam/prefixes/18691/ \ -> --data '{"status": "reserved"}' | jq '.' +-H "Authorization: Token $TOKEN" \ +-H "Content-Type: application/json" \ +http://netbox/api/ipam/prefixes/18691/ \ +--data '{"status": "reserved"}' | jq '.' ``` ```json @@ -515,6 +515,23 @@ curl -s -X PATCH \ !!! note "PUT versus PATCH" The NetBox REST API support the use of either `PUT` or `PATCH` to modify an existing object. The difference is that a `PUT` request requires the user to specify a _complete_ representation of the object being modified, whereas a `PATCH` request need include only the attributes that are being updated. For most purposes, using `PATCH` is recommended. +### Updating Multiple Objects + +Multiple objects can be updated simultaneously by issuing a `PUT` or `PATCH` request to a model's list endpoint with a list of dictionaries specifying the numeric ID of each object to be deleted and the attributes to be updated. For example, to update sites with IDs 10 and 11 to a status of "active", issue the following request: + +```no-highlight +curl -s -X PATCH \ +-H "Authorization: Token $TOKEN" \ +-H "Content-Type: application/json" \ +http://netbox/api/dcim/sites/ \ +--data '[{"id": 10, "status": "active"}, {"id": 11, "status": "active"}]' +``` + +Note that there is no requirement for the attributes to be identical among objects. For instance, it's possible to update the status of one site along with the name of another in the same request. + +!!! note + The bulk update of objects is an all-or-none operation, meaning that if NetBox fails to successfully update any of the specified objects (e.g. due a validation error), the entire operation will be aborted and none of the objects will be updated. + ### Deleting an Object To delete an object from NetBox, make a `DELETE` request to the model's _detail_ endpoint specifying its unique numeric ID. The `Authorization` header must be included to specify an authorization token, however this type of request does not support passing any data in the body. @@ -529,3 +546,18 @@ Note that `DELETE` requests do not return any data: If successful, the API will !!! note You can run `curl` with the verbose (`-v`) flag to inspect the HTTP response codes. + +### Deleting Multiple Objects + +NetBox supports the simultaneous deletion of multiple objects of the same type by issuing a `DELETE` request to the model's list endpoint with a list of dictionaries specifying the numeric ID of each object to be deleted. For example, to delete sites with IDs 10, 11, and 12, issue the following request: + +```no-highlight +curl -s -X DELETE \ +-H "Authorization: Token $TOKEN" \ +-H "Content-Type: application/json" \ +http://netbox/api/dcim/sites/ \ +--data '[{"id": 10}, {"id": 11}, {"id": 12}]' +``` + +!!! note + The bulk deletion of objects is an all-or-none operation, meaning that if NetBox fails to delete any of the specified objects (e.g. due a dependency by a related object), the entire operation will be aborted and none of the objects will be deleted. diff --git a/mkdocs.yml b/mkdocs.yml index 9ebf008976..092cb559aa 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -49,7 +49,6 @@ nav: - Custom Links: 'additional-features/custom-links.md' - Custom Scripts: 'additional-features/custom-scripts.md' - Export Templates: 'additional-features/export-templates.md' - - Graphs: 'additional-features/graphs.md' - NAPALM: 'additional-features/napalm.md' - Prometheus Metrics: 'additional-features/prometheus-metrics.md' - Reports: 'additional-features/reports.md' @@ -76,6 +75,7 @@ nav: - User Preferences: 'development/user-preferences.md' - Release Checklist: 'development/release-checklist.md' - Release Notes: + - Version 2.10: 'release-notes/version-2.10.md' - Version 2.9: 'release-notes/version-2.9.md' - Version 2.8: 'release-notes/version-2.8.md' - Version 2.7: 'release-notes/version-2.7.md' diff --git a/netbox/circuits/api/nested_serializers.py b/netbox/circuits/api/nested_serializers.py index 0768832821..2d3457d2c7 100644 --- a/netbox/circuits/api/nested_serializers.py +++ b/netbox/circuits/api/nested_serializers.py @@ -1,7 +1,7 @@ from rest_framework import serializers from circuits.models import Circuit, CircuitTermination, CircuitType, Provider -from utilities.api import WritableNestedSerializer +from netbox.api import WritableNestedSerializer __all__ = [ 'NestedCircuitSerializer', diff --git a/netbox/circuits/api/serializers.py b/netbox/circuits/api/serializers.py index 10ae5e5ee6..88890bf952 100644 --- a/netbox/circuits/api/serializers.py +++ b/netbox/circuits/api/serializers.py @@ -3,11 +3,11 @@ from circuits.choices import CircuitStatusChoices from circuits.models import Provider, Circuit, CircuitTermination, CircuitType from dcim.api.nested_serializers import NestedCableSerializer, NestedInterfaceSerializer, NestedSiteSerializer -from dcim.api.serializers import ConnectedEndpointSerializer +from dcim.api.serializers import CableTerminationSerializer, ConnectedEndpointSerializer from extras.api.customfields import CustomFieldModelSerializer from extras.api.serializers import TaggedObjectSerializer +from netbox.api import ChoiceField, ValidatedModelSerializer, WritableNestedSerializer from tenancy.api.nested_serializers import NestedTenantSerializer -from utilities.api import ChoiceField, ValidatedModelSerializer, WritableNestedSerializer from .nested_serializers import * @@ -67,7 +67,7 @@ class Meta: ] -class CircuitTerminationSerializer(ConnectedEndpointSerializer): +class CircuitTerminationSerializer(CableTerminationSerializer, ConnectedEndpointSerializer): url = serializers.HyperlinkedIdentityField(view_name='circuits-api:circuittermination-detail') circuit = NestedCircuitSerializer() site = NestedSiteSerializer() @@ -77,5 +77,6 @@ class Meta: model = CircuitTermination fields = [ 'id', 'url', 'circuit', 'term_side', 'site', 'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', - 'description', 'connected_endpoint_type', 'connected_endpoint', 'connection_status', 'cable', + 'description', 'cable', 'cable_peer', 'cable_peer_type', 'connected_endpoint', 'connected_endpoint_type', + 'connected_endpoint_reachable' ] diff --git a/netbox/circuits/api/urls.py b/netbox/circuits/api/urls.py index 0bcb2d280b..b496796fe3 100644 --- a/netbox/circuits/api/urls.py +++ b/netbox/circuits/api/urls.py @@ -1,4 +1,4 @@ -from utilities.api import OrderedDefaultRouter +from netbox.api import OrderedDefaultRouter from . import views diff --git a/netbox/circuits/api/views.py b/netbox/circuits/api/views.py index 32adc66ae3..ad497ee5fb 100644 --- a/netbox/circuits/api/views.py +++ b/netbox/circuits/api/views.py @@ -1,15 +1,11 @@ from django.db.models import Prefetch -from django.shortcuts import get_object_or_404 -from rest_framework.decorators import action -from rest_framework.response import Response from rest_framework.routers import APIRootView from circuits import filters from circuits.models import Provider, CircuitTermination, CircuitType, Circuit -from extras.api.serializers import RenderedGraphSerializer +from dcim.api.views import PathEndpointMixin from extras.api.views import CustomFieldModelViewSet -from extras.models import Graph -from utilities.api import ModelViewSet +from netbox.api.views import ModelViewSet from utilities.utils import get_subquery from . import serializers @@ -33,16 +29,6 @@ class ProviderViewSet(CustomFieldModelViewSet): serializer_class = serializers.ProviderSerializer filterset_class = filters.ProviderFilterSet - @action(detail=True) - def graphs(self, request, pk): - """ - A convenience method for rendering graphs for a particular provider. - """ - provider = get_object_or_404(self.queryset, pk=pk) - queryset = Graph.objects.restrict(request.user).filter(type__model='provider') - serializer = RenderedGraphSerializer(queryset, many=True, context={'graphed_object': provider}) - return Response(serializer.data) - # # Circuit Types @@ -62,9 +48,7 @@ class CircuitTypeViewSet(ModelViewSet): class CircuitViewSet(CustomFieldModelViewSet): queryset = Circuit.objects.prefetch_related( - Prefetch('terminations', queryset=CircuitTermination.objects.prefetch_related( - 'site', 'connected_endpoint__device' - )), + Prefetch('terminations', queryset=CircuitTermination.objects.prefetch_related('site')), 'type', 'tenant', 'provider', ).prefetch_related('tags') serializer_class = serializers.CircuitSerializer @@ -75,9 +59,9 @@ class CircuitViewSet(CustomFieldModelViewSet): # Circuit Terminations # -class CircuitTerminationViewSet(ModelViewSet): +class CircuitTerminationViewSet(PathEndpointMixin, ModelViewSet): queryset = CircuitTermination.objects.prefetch_related( - 'circuit', 'site', 'connected_endpoint__device', 'cable' + 'circuit', 'site', '_path__destination', 'cable' ) serializer_class = serializers.CircuitTerminationSerializer filterset_class = filters.CircuitTerminationFilterSet diff --git a/netbox/circuits/choices.py b/netbox/circuits/choices.py index 1b5e69cb59..bbf536800e 100644 --- a/netbox/circuits/choices.py +++ b/netbox/circuits/choices.py @@ -23,6 +23,15 @@ class CircuitStatusChoices(ChoiceSet): (STATUS_DECOMMISSIONED, 'Decommissioned'), ) + CSS_CLASSES = { + STATUS_DEPROVISIONING: 'warning', + STATUS_ACTIVE: 'success', + STATUS_PLANNED: 'info', + STATUS_PROVISIONING: 'primary', + STATUS_OFFLINE: 'danger', + STATUS_DECOMMISSIONED: 'default', + } + # # CircuitTerminations diff --git a/netbox/circuits/filters.py b/netbox/circuits/filters.py index 206dcc3058..fa563881c7 100644 --- a/netbox/circuits/filters.py +++ b/netbox/circuits/filters.py @@ -1,8 +1,9 @@ import django_filters from django.db.models import Q +from dcim.filters import CableTerminationFilterSet, PathEndpointFilterSet from dcim.models import Region, Site -from extras.filters import CustomFieldFilterSet, CreatedUpdatedFilterSet +from extras.filters import CustomFieldModelFilterSet, CreatedUpdatedFilterSet from tenancy.filters import TenancyFilterSet from utilities.filters import ( BaseFilterSet, NameSlugSearchFilterSet, TagFilter, TreeNodeMultipleChoiceFilter @@ -18,7 +19,7 @@ ) -class ProviderFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet): +class ProviderFilterSet(BaseFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): q = django_filters.CharFilter( method='search', label='Search', @@ -72,7 +73,7 @@ class Meta: fields = ['id', 'name', 'slug'] -class CircuitFilterSet(BaseFilterSet, CustomFieldFilterSet, TenancyFilterSet, CreatedUpdatedFilterSet): +class CircuitFilterSet(BaseFilterSet, CustomFieldModelFilterSet, TenancyFilterSet, CreatedUpdatedFilterSet): q = django_filters.CharFilter( method='search', label='Search', @@ -144,7 +145,7 @@ def search(self, queryset, name, value): ).distinct() -class CircuitTerminationFilterSet(BaseFilterSet): +class CircuitTerminationFilterSet(BaseFilterSet, CableTerminationFilterSet, PathEndpointFilterSet): q = django_filters.CharFilter( method='search', label='Search', diff --git a/netbox/circuits/migrations/0020_custom_field_data.py b/netbox/circuits/migrations/0020_custom_field_data.py new file mode 100644 index 0000000000..97da9962cc --- /dev/null +++ b/netbox/circuits/migrations/0020_custom_field_data.py @@ -0,0 +1,22 @@ +import django.core.serializers.json +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('circuits', '0019_nullbooleanfield_to_booleanfield'), + ] + + operations = [ + migrations.AddField( + model_name='circuit', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AddField( + model_name='provider', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + ] diff --git a/netbox/circuits/migrations/0021_cache_cable_peer.py b/netbox/circuits/migrations/0021_cache_cable_peer.py new file mode 100644 index 0000000000..630c3b4ece --- /dev/null +++ b/netbox/circuits/migrations/0021_cache_cable_peer.py @@ -0,0 +1,49 @@ +import sys + +from django.db import migrations, models +import django.db.models.deletion + + +def cache_cable_peers(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + Cable = apps.get_model('dcim', 'Cable') + CircuitTermination = apps.get_model('circuits', 'CircuitTermination') + + if 'test' not in sys.argv: + print(f"\n Updating circuit termination cable peers...", flush=True) + ct = ContentType.objects.get_for_model(CircuitTermination) + for cable in Cable.objects.filter(termination_a_type=ct): + CircuitTermination.objects.filter(pk=cable.termination_a_id).update( + _cable_peer_type_id=cable.termination_b_type_id, + _cable_peer_id=cable.termination_b_id + ) + for cable in Cable.objects.filter(termination_b_type=ct): + CircuitTermination.objects.filter(pk=cable.termination_b_id).update( + _cable_peer_type_id=cable.termination_a_type_id, + _cable_peer_id=cable.termination_a_id + ) + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('circuits', '0020_custom_field_data'), + ] + + operations = [ + migrations.AddField( + model_name='circuittermination', + name='_cable_peer_id', + field=models.PositiveIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='circuittermination', + name='_cable_peer_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + ), + migrations.RunPython( + code=cache_cable_peers, + reverse_code=migrations.RunPython.noop + ), + ] diff --git a/netbox/circuits/migrations/0022_cablepath.py b/netbox/circuits/migrations/0022_cablepath.py new file mode 100644 index 0000000000..4a5b26efa6 --- /dev/null +++ b/netbox/circuits/migrations/0022_cablepath.py @@ -0,0 +1,26 @@ +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0121_cablepath'), + ('circuits', '0021_cache_cable_peer'), + ] + + operations = [ + migrations.AddField( + model_name='circuittermination', + name='_path', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'), + ), + migrations.RemoveField( + model_name='circuittermination', + name='connected_endpoint', + ), + migrations.RemoveField( + model_name='circuittermination', + name='connection_status', + ), + ] diff --git a/netbox/circuits/migrations/0023_circuittermination_port_speed_optional.py b/netbox/circuits/migrations/0023_circuittermination_port_speed_optional.py new file mode 100644 index 0000000000..ea91906235 --- /dev/null +++ b/netbox/circuits/migrations/0023_circuittermination_port_speed_optional.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1 on 2020-10-09 17:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('circuits', '0022_cablepath'), + ] + + operations = [ + migrations.AlterField( + model_name='circuittermination', + name='port_speed', + field=models.PositiveIntegerField(blank=True, null=True), + ), + ] diff --git a/netbox/circuits/migrations/0024_standardize_name_length.py b/netbox/circuits/migrations/0024_standardize_name_length.py new file mode 100644 index 0000000000..8d0ae48e30 --- /dev/null +++ b/netbox/circuits/migrations/0024_standardize_name_length.py @@ -0,0 +1,38 @@ +# Generated by Django 3.1 on 2020-10-15 19:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('circuits', '0023_circuittermination_port_speed_optional'), + ] + + operations = [ + migrations.AlterField( + model_name='circuit', + name='cid', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='circuittype', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='circuittype', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='provider', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='provider', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + ] diff --git a/netbox/circuits/models.py b/netbox/circuits/models.py index cdec41d1fd..3d6d5d2328 100644 --- a/netbox/circuits/models.py +++ b/netbox/circuits/models.py @@ -1,11 +1,9 @@ -from django.contrib.contenttypes.fields import GenericRelation from django.db import models from django.urls import reverse from taggit.managers import TaggableManager -from dcim.constants import CONNECTION_STATUS_CHOICES from dcim.fields import ASNField -from dcim.models import CableTermination +from dcim.models import CableTermination, PathEndpoint from extras.models import ChangeLoggedModel, CustomFieldModel, ObjectChange, TaggedItem from extras.utils import extras_features from utilities.querysets import RestrictedQuerySet @@ -22,17 +20,18 @@ ) -@extras_features('custom_fields', 'custom_links', 'graphs', 'export_templates', 'webhooks') +@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') class Provider(ChangeLoggedModel, CustomFieldModel): """ Each Circuit belongs to a Provider. This is usually a telecommunications company or similar organization. This model stores information pertinent to the user's relationship with the Provider. """ name = models.CharField( - max_length=50, + max_length=100, unique=True ) slug = models.SlugField( + max_length=100, unique=True ) asn = ASNField( @@ -61,11 +60,6 @@ class Provider(ChangeLoggedModel, CustomFieldModel): comments = models.TextField( blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) tags = TaggableManager(through=TaggedItem) objects = RestrictedQuerySet.as_manager() @@ -105,10 +99,11 @@ class CircuitType(ChangeLoggedModel): "Long Haul," "Metro," or "Out-of-Band". """ name = models.CharField( - max_length=50, + max_length=100, unique=True ) slug = models.SlugField( + max_length=100, unique=True ) description = models.CharField( @@ -145,7 +140,7 @@ class Circuit(ChangeLoggedModel, CustomFieldModel): in Kbps. """ cid = models.CharField( - max_length=50, + max_length=100, verbose_name='Circuit ID' ) provider = models.ForeignKey( @@ -186,11 +181,6 @@ class Circuit(ChangeLoggedModel, CustomFieldModel): comments = models.TextField( blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) objects = CircuitQuerySet.as_manager() tags = TaggableManager(through=TaggedItem) @@ -202,15 +192,6 @@ class Circuit(ChangeLoggedModel, CustomFieldModel): 'provider', 'type', 'status', 'tenant', 'install_date', 'commit_rate', 'description', ] - STATUS_CLASS_MAP = { - CircuitStatusChoices.STATUS_DEPROVISIONING: 'warning', - CircuitStatusChoices.STATUS_ACTIVE: 'success', - CircuitStatusChoices.STATUS_PLANNED: 'info', - CircuitStatusChoices.STATUS_PROVISIONING: 'primary', - CircuitStatusChoices.STATUS_OFFLINE: 'danger', - CircuitStatusChoices.STATUS_DECOMMISSIONED: 'default', - } - class Meta: ordering = ['provider', 'cid'] unique_together = ['provider', 'cid'] @@ -235,7 +216,7 @@ def to_csv(self): ) def get_status_class(self): - return self.STATUS_CLASS_MAP.get(self.status) + return CircuitStatusChoices.CSS_CLASSES.get(self.status) def _get_termination(self, side): for ct in self.terminations.all(): @@ -252,7 +233,7 @@ def termination_z(self): return self._get_termination('Z') -class CircuitTermination(CableTermination): +class CircuitTermination(PathEndpoint, CableTermination): circuit = models.ForeignKey( to='circuits.Circuit', on_delete=models.CASCADE, @@ -268,21 +249,11 @@ class CircuitTermination(CableTermination): on_delete=models.PROTECT, related_name='circuit_terminations' ) - connected_endpoint = models.OneToOneField( - to='dcim.Interface', - on_delete=models.SET_NULL, - related_name='+', - blank=True, - null=True - ) - connection_status = models.BooleanField( - choices=CONNECTION_STATUS_CHOICES, + port_speed = models.PositiveIntegerField( + verbose_name='Port speed (Kbps)', blank=True, null=True ) - port_speed = models.PositiveIntegerField( - verbose_name='Port speed (Kbps)' - ) upstream_speed = models.PositiveIntegerField( blank=True, null=True, diff --git a/netbox/circuits/tables.py b/netbox/circuits/tables.py index 4aca8688f9..782b02394e 100644 --- a/netbox/circuits/tables.py +++ b/netbox/circuits/tables.py @@ -2,13 +2,9 @@ from django_tables2.utils import Accessor from tenancy.tables import COL_TENANT -from utilities.tables import BaseTable, ButtonsColumn, TagColumn, ToggleColumn +from utilities.tables import BaseTable, ButtonsColumn, ChoiceFieldColumn, TagColumn, ToggleColumn from .models import Circuit, CircuitType, Provider -STATUS_LABEL = """ -{{ record.get_status_display }} -""" - # # Providers @@ -64,9 +60,7 @@ class CircuitTable(BaseTable): viewname='circuits:provider', args=[Accessor('provider__slug')] ) - status = tables.TemplateColumn( - template_code=STATUS_LABEL - ) + status = ChoiceFieldColumn() tenant = tables.TemplateColumn( template_code=COL_TENANT ) diff --git a/netbox/circuits/tests/test_api.py b/netbox/circuits/tests/test_api.py index fa264aaa2e..6df9315530 100644 --- a/netbox/circuits/tests/test_api.py +++ b/netbox/circuits/tests/test_api.py @@ -1,11 +1,8 @@ -from django.contrib.contenttypes.models import ContentType -from django.test import override_settings from django.urls import reverse from circuits.choices import * from circuits.models import Circuit, CircuitTermination, CircuitType, Provider from dcim.models import Site -from extras.models import Graph from utilities.testing import APITestCase, APIViewTestCases @@ -35,6 +32,9 @@ class ProviderTest(APIViewTestCases.APIViewTestCase): 'slug': 'provider-6', }, ] + bulk_update_data = { + 'asn': 1234, + } @classmethod def setUpTestData(cls): @@ -46,27 +46,6 @@ def setUpTestData(cls): ) Provider.objects.bulk_create(providers) - @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) - def test_get_provider_graphs(self): - """ - Test retrieval of Graphs assigned to Providers. - """ - provider = self.model.objects.first() - ct = ContentType.objects.get(app_label='circuits', model='provider') - graphs = ( - Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=1'), - Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=2'), - Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?provider={{ obj.slug }}&foo=3'), - ) - Graph.objects.bulk_create(graphs) - - self.add_permissions('circuits.view_provider') - url = reverse('circuits-api:provider-graphs', kwargs={'pk': provider.pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(len(response.data), 3) - self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?provider=provider-1&foo=1') - class CircuitTypeTest(APIViewTestCases.APIViewTestCase): model = CircuitType @@ -85,6 +64,9 @@ class CircuitTypeTest(APIViewTestCases.APIViewTestCase): 'slug': 'circuit-type-6', }, ) + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -100,6 +82,9 @@ def setUpTestData(cls): class CircuitTest(APIViewTestCases.APIViewTestCase): model = Circuit brief_fields = ['cid', 'id', 'url'] + bulk_update_data = { + 'status': 'planned', + } @classmethod def setUpTestData(cls): @@ -168,10 +153,10 @@ def setUpTestData(cls): Circuit.objects.bulk_create(circuits) circuit_terminations = ( - CircuitTermination(circuit=circuits[0], site=sites[0], port_speed=100000, term_side=SIDE_A), - CircuitTermination(circuit=circuits[0], site=sites[1], port_speed=100000, term_side=SIDE_Z), - CircuitTermination(circuit=circuits[1], site=sites[0], port_speed=100000, term_side=SIDE_A), - CircuitTermination(circuit=circuits[1], site=sites[1], port_speed=100000, term_side=SIDE_Z), + CircuitTermination(circuit=circuits[0], site=sites[0], term_side=SIDE_A), + CircuitTermination(circuit=circuits[0], site=sites[1], term_side=SIDE_Z), + CircuitTermination(circuit=circuits[1], site=sites[0], term_side=SIDE_A), + CircuitTermination(circuit=circuits[1], site=sites[1], term_side=SIDE_Z), ) CircuitTermination.objects.bulk_create(circuit_terminations) @@ -189,3 +174,7 @@ def setUpTestData(cls): 'port_speed': 200000, }, ] + + cls.bulk_update_data = { + 'port_speed': 123456 + } diff --git a/netbox/circuits/tests/test_filters.py b/netbox/circuits/tests/test_filters.py index 9756c320b0..9477bfbac0 100644 --- a/netbox/circuits/tests/test_filters.py +++ b/netbox/circuits/tests/test_filters.py @@ -3,7 +3,7 @@ from circuits.choices import * from circuits.filters import * from circuits.models import Circuit, CircuitTermination, CircuitType, Provider -from dcim.models import Region, Site +from dcim.models import Cable, Region, Site from tenancy.models import Tenant, TenantGroup @@ -50,8 +50,8 @@ def setUpTestData(cls): Circuit.objects.bulk_create(circuits) CircuitTermination.objects.bulk_create(( - CircuitTermination(circuit=circuits[0], site=sites[0], term_side='A', port_speed=1000), - CircuitTermination(circuit=circuits[1], site=sites[0], term_side='A', port_speed=1000), + CircuitTermination(circuit=circuits[0], site=sites[0], term_side='A'), + CircuitTermination(circuit=circuits[1], site=sites[0], term_side='A'), )) def test_id(self): @@ -176,9 +176,9 @@ def setUpTestData(cls): Circuit.objects.bulk_create(circuits) circuit_terminations = (( - CircuitTermination(circuit=circuits[0], site=sites[0], term_side='A', port_speed=1000), - CircuitTermination(circuit=circuits[1], site=sites[1], term_side='A', port_speed=1000), - CircuitTermination(circuit=circuits[2], site=sites[2], term_side='A', port_speed=1000), + CircuitTermination(circuit=circuits[0], site=sites[0], term_side='A'), + CircuitTermination(circuit=circuits[1], site=sites[1], term_side='A'), + CircuitTermination(circuit=circuits[2], site=sites[2], term_side='A'), )) CircuitTermination.objects.bulk_create(circuit_terminations) @@ -286,6 +286,8 @@ def setUpTestData(cls): )) CircuitTermination.objects.bulk_create(circuit_terminations) + Cable(termination_a=circuit_terminations[0], termination_b=circuit_terminations[1]).save() + def test_term_side(self): params = {'term_side': 'A'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) @@ -313,3 +315,13 @@ def test_site(self): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) params = {'site': [sites[0].slug, sites[1].slug]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_cabled(self): + params = {'cabled': True} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_connected(self): + params = {'connected': True} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'connected': False} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) diff --git a/netbox/circuits/urls.py b/netbox/circuits/urls.py index 86ea55fa86..d757fd90df 100644 --- a/netbox/circuits/urls.py +++ b/netbox/circuits/urls.py @@ -1,6 +1,6 @@ from django.urls import path -from dcim.views import CableCreateView, CableTraceView +from dcim.views import CableCreateView, PathTraceView from extras.views import ObjectChangeLogView from . import views from .models import Circuit, CircuitTermination, CircuitType, Provider @@ -45,6 +45,6 @@ path('circuit-terminations//edit/', views.CircuitTerminationEditView.as_view(), name='circuittermination_edit'), path('circuit-terminations//delete/', views.CircuitTerminationDeleteView.as_view(), name='circuittermination_delete'), path('circuit-terminations//connect//', CableCreateView.as_view(), name='circuittermination_connect', kwargs={'termination_a_type': CircuitTermination}), - path('circuit-terminations//trace/', CableTraceView.as_view(), name='circuittermination_trace', kwargs={'model': CircuitTermination}), + path('circuit-terminations//trace/', PathTraceView.as_view(), name='circuittermination_trace', kwargs={'model': CircuitTermination}), ] diff --git a/netbox/circuits/views.py b/netbox/circuits/views.py index 2722bda67f..653c881a91 100644 --- a/netbox/circuits/views.py +++ b/netbox/circuits/views.py @@ -3,13 +3,10 @@ from django.shortcuts import get_object_or_404, redirect, render from django_tables2 import RequestConfig -from extras.models import Graph +from netbox.views import generic from utilities.forms import ConfirmationForm from utilities.paginator import EnhancedPaginator, get_paginate_count from utilities.utils import get_subquery -from utilities.views import ( - BulkDeleteView, BulkEditView, BulkImportView, ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView, -) from . import filters, forms, tables from .choices import CircuitTerminationSideChoices from .models import Circuit, CircuitTermination, CircuitType, Provider @@ -19,7 +16,7 @@ # Providers # -class ProviderListView(ObjectListView): +class ProviderListView(generic.ObjectListView): queryset = Provider.objects.annotate( count_circuits=get_subquery(Circuit, 'provider') ) @@ -28,18 +25,15 @@ class ProviderListView(ObjectListView): table = tables.ProviderTable -class ProviderView(ObjectView): +class ProviderView(generic.ObjectView): queryset = Provider.objects.all() - def get(self, request, slug): - - provider = get_object_or_404(self.queryset, slug=slug) + def get_extra_context(self, request, instance): circuits = Circuit.objects.restrict(request.user, 'view').filter( - provider=provider + provider=instance ).prefetch_related( 'type', 'tenant', 'terminations__site' ).annotate_sites() - show_graphs = Graph.objects.filter(type__model='provider').exists() circuits_table = tables.CircuitTable(circuits) circuits_table.columns.hide('provider') @@ -50,30 +44,28 @@ def get(self, request, slug): } RequestConfig(request, paginate).configure(circuits_table) - return render(request, 'circuits/provider.html', { - 'provider': provider, + return { 'circuits_table': circuits_table, - 'show_graphs': show_graphs, - }) + } -class ProviderEditView(ObjectEditView): +class ProviderEditView(generic.ObjectEditView): queryset = Provider.objects.all() model_form = forms.ProviderForm template_name = 'circuits/provider_edit.html' -class ProviderDeleteView(ObjectDeleteView): +class ProviderDeleteView(generic.ObjectDeleteView): queryset = Provider.objects.all() -class ProviderBulkImportView(BulkImportView): +class ProviderBulkImportView(generic.BulkImportView): queryset = Provider.objects.all() model_form = forms.ProviderCSVForm table = tables.ProviderTable -class ProviderBulkEditView(BulkEditView): +class ProviderBulkEditView(generic.BulkEditView): queryset = Provider.objects.annotate( count_circuits=get_subquery(Circuit, 'provider') ) @@ -82,7 +74,7 @@ class ProviderBulkEditView(BulkEditView): form = forms.ProviderBulkEditForm -class ProviderBulkDeleteView(BulkDeleteView): +class ProviderBulkDeleteView(generic.BulkDeleteView): queryset = Provider.objects.annotate( count_circuits=get_subquery(Circuit, 'provider') ) @@ -94,29 +86,29 @@ class ProviderBulkDeleteView(BulkDeleteView): # Circuit Types # -class CircuitTypeListView(ObjectListView): +class CircuitTypeListView(generic.ObjectListView): queryset = CircuitType.objects.annotate( circuit_count=get_subquery(Circuit, 'type') ) table = tables.CircuitTypeTable -class CircuitTypeEditView(ObjectEditView): +class CircuitTypeEditView(generic.ObjectEditView): queryset = CircuitType.objects.all() model_form = forms.CircuitTypeForm -class CircuitTypeDeleteView(ObjectDeleteView): +class CircuitTypeDeleteView(generic.ObjectDeleteView): queryset = CircuitType.objects.all() -class CircuitTypeBulkImportView(BulkImportView): +class CircuitTypeBulkImportView(generic.BulkImportView): queryset = CircuitType.objects.all() model_form = forms.CircuitTypeCSVForm table = tables.CircuitTypeTable -class CircuitTypeBulkDeleteView(BulkDeleteView): +class CircuitTypeBulkDeleteView(generic.BulkDeleteView): queryset = CircuitType.objects.annotate( circuit_count=get_subquery(Circuit, 'type') ) @@ -127,7 +119,7 @@ class CircuitTypeBulkDeleteView(BulkDeleteView): # Circuits # -class CircuitListView(ObjectListView): +class CircuitListView(generic.ObjectListView): queryset = Circuit.objects.prefetch_related( 'provider', 'type', 'tenant', 'terminations' ).annotate_sites() @@ -136,52 +128,52 @@ class CircuitListView(ObjectListView): table = tables.CircuitTable -class CircuitView(ObjectView): - queryset = Circuit.objects.prefetch_related('provider', 'type', 'tenant__group') +class CircuitView(generic.ObjectView): + queryset = Circuit.objects.all() - def get(self, request, pk): - circuit = get_object_or_404(self.queryset, pk=pk) + def get_extra_context(self, request, instance): + # A-side termination termination_a = CircuitTermination.objects.restrict(request.user, 'view').prefetch_related( - 'site__region', 'connected_endpoint__device' + 'site__region' ).filter( - circuit=circuit, term_side=CircuitTerminationSideChoices.SIDE_A + circuit=instance, term_side=CircuitTerminationSideChoices.SIDE_A ).first() if termination_a and termination_a.connected_endpoint: termination_a.ip_addresses = termination_a.connected_endpoint.ip_addresses.restrict(request.user, 'view') + # Z-side termination termination_z = CircuitTermination.objects.restrict(request.user, 'view').prefetch_related( - 'site__region', 'connected_endpoint__device' + 'site__region' ).filter( - circuit=circuit, term_side=CircuitTerminationSideChoices.SIDE_Z + circuit=instance, term_side=CircuitTerminationSideChoices.SIDE_Z ).first() if termination_z and termination_z.connected_endpoint: termination_z.ip_addresses = termination_z.connected_endpoint.ip_addresses.restrict(request.user, 'view') - return render(request, 'circuits/circuit.html', { - 'circuit': circuit, + return { 'termination_a': termination_a, 'termination_z': termination_z, - }) + } -class CircuitEditView(ObjectEditView): +class CircuitEditView(generic.ObjectEditView): queryset = Circuit.objects.all() model_form = forms.CircuitForm template_name = 'circuits/circuit_edit.html' -class CircuitDeleteView(ObjectDeleteView): +class CircuitDeleteView(generic.ObjectDeleteView): queryset = Circuit.objects.all() -class CircuitBulkImportView(BulkImportView): +class CircuitBulkImportView(generic.BulkImportView): queryset = Circuit.objects.all() model_form = forms.CircuitCSVForm table = tables.CircuitTable -class CircuitBulkEditView(BulkEditView): +class CircuitBulkEditView(generic.BulkEditView): queryset = Circuit.objects.prefetch_related( 'provider', 'type', 'tenant', 'terminations' ) @@ -190,7 +182,7 @@ class CircuitBulkEditView(BulkEditView): form = forms.CircuitBulkEditForm -class CircuitBulkDeleteView(BulkDeleteView): +class CircuitBulkDeleteView(generic.BulkDeleteView): queryset = Circuit.objects.prefetch_related( 'provider', 'type', 'tenant', 'terminations' ) @@ -198,7 +190,7 @@ class CircuitBulkDeleteView(BulkDeleteView): table = tables.CircuitTable -class CircuitSwapTerminations(ObjectEditView): +class CircuitSwapTerminations(generic.ObjectEditView): """ Swap the A and Z terminations of a circuit. """ @@ -271,7 +263,7 @@ def post(self, request, pk): # Circuit terminations # -class CircuitTerminationEditView(ObjectEditView): +class CircuitTerminationEditView(generic.ObjectEditView): queryset = CircuitTermination.objects.all() model_form = forms.CircuitTerminationForm template_name = 'circuits/circuittermination_edit.html' @@ -285,5 +277,5 @@ def get_return_url(self, request, obj): return obj.circuit.get_absolute_url() -class CircuitTerminationDeleteView(ObjectDeleteView): +class CircuitTerminationDeleteView(generic.ObjectDeleteView): queryset = CircuitTermination.objects.all() diff --git a/netbox/dcim/api/nested_serializers.py b/netbox/dcim/api/nested_serializers.py index 3bc9539918..d63d32d68a 100644 --- a/netbox/dcim/api/nested_serializers.py +++ b/netbox/dcim/api/nested_serializers.py @@ -1,8 +1,7 @@ from rest_framework import serializers -from dcim.constants import CONNECTION_STATUS_CHOICES from dcim import models -from utilities.api import ChoiceField, WritableNestedSerializer +from netbox.api import WritableNestedSerializer __all__ = [ 'NestedCableSerializer', @@ -228,51 +227,46 @@ class Meta: class NestedConsoleServerPortSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleserverport-detail') device = NestedDeviceSerializer(read_only=True) - connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True) class Meta: model = models.ConsoleServerPort - fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status'] + fields = ['id', 'url', 'device', 'name', 'cable'] class NestedConsolePortSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleport-detail') device = NestedDeviceSerializer(read_only=True) - connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True) class Meta: model = models.ConsolePort - fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status'] + fields = ['id', 'url', 'device', 'name', 'cable'] class NestedPowerOutletSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:poweroutlet-detail') device = NestedDeviceSerializer(read_only=True) - connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True) class Meta: model = models.PowerOutlet - fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status'] + fields = ['id', 'url', 'device', 'name', 'cable'] class NestedPowerPortSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerport-detail') device = NestedDeviceSerializer(read_only=True) - connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True) class Meta: model = models.PowerPort - fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status'] + fields = ['id', 'url', 'device', 'name', 'cable'] class NestedInterfaceSerializer(WritableNestedSerializer): device = NestedDeviceSerializer(read_only=True) url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interface-detail') - connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True) class Meta: model = models.Interface - fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status'] + fields = ['id', 'url', 'device', 'name', 'cable'] class NestedRearPortSerializer(WritableNestedSerializer): @@ -305,10 +299,11 @@ class Meta: class NestedInventoryItemSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:inventoryitem-detail') device = NestedDeviceSerializer(read_only=True) + _depth = serializers.IntegerField(source='level', read_only=True) class Meta: model = models.InventoryItem - fields = ['id', 'url', 'device', 'name'] + fields = ['id', 'url', 'device', 'name', '_depth'] # diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index 50c1f99ff3..6f497bfa6d 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -7,37 +7,57 @@ from dcim.choices import * from dcim.constants import * from dcim.models import ( - Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay, + Cable, CablePath, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay, DeviceBayTemplate, DeviceType, DeviceRole, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate, Manufacturer, InventoryItem, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, PowerPort, PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site, VirtualChassis, ) +from dcim.utils import decompile_path_node from extras.api.customfields import CustomFieldModelSerializer from extras.api.serializers import TaggedObjectSerializer from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedVLANSerializer from ipam.models import VLAN -from tenancy.api.nested_serializers import NestedTenantSerializer -from users.api.nested_serializers import NestedUserSerializer -from utilities.api import ( +from netbox.api import ( ChoiceField, ContentTypeField, SerializedPKRelatedField, TimeZoneField, ValidatedModelSerializer, - WritableNestedSerializer, get_serializer_for_model, + WritableNestedSerializer, ) +from tenancy.api.nested_serializers import NestedTenantSerializer +from users.api.nested_serializers import NestedUserSerializer +from utilities.api import get_serializer_for_model from virtualization.api.nested_serializers import NestedClusterSerializer from .nested_serializers import * +class CableTerminationSerializer(serializers.ModelSerializer): + cable_peer_type = serializers.SerializerMethodField(read_only=True) + cable_peer = serializers.SerializerMethodField(read_only=True) + + def get_cable_peer_type(self, obj): + if obj._cable_peer is not None: + return f'{obj._cable_peer._meta.app_label}.{obj._cable_peer._meta.model_name}' + return None + + @swagger_serializer_method(serializer_or_field=serializers.DictField) + def get_cable_peer(self, obj): + """ + Return the appropriate serializer for the cable termination model. + """ + if obj._cable_peer is not None: + serializer = get_serializer_for_model(obj._cable_peer, prefix='Nested') + context = {'request': self.context['request']} + return serializer(obj._cable_peer, context=context).data + return None + + class ConnectedEndpointSerializer(ValidatedModelSerializer): connected_endpoint_type = serializers.SerializerMethodField(read_only=True) connected_endpoint = serializers.SerializerMethodField(read_only=True) - connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True) + connected_endpoint_reachable = serializers.SerializerMethodField(read_only=True) def get_connected_endpoint_type(self, obj): - if hasattr(obj, 'connected_endpoint') and obj.connected_endpoint is not None: - return '{}.{}'.format( - obj.connected_endpoint._meta.app_label, - obj.connected_endpoint._meta.model_name - ) + if obj._path is not None and obj._path.destination is not None: + return f'{obj._path.destination._meta.app_label}.{obj._path.destination._meta.model_name}' return None @swagger_serializer_method(serializer_or_field=serializers.DictField) @@ -45,14 +65,17 @@ def get_connected_endpoint(self, obj): """ Return the appropriate serializer for the type of connected object. """ - if getattr(obj, 'connected_endpoint', None) is None: - return None - - serializer = get_serializer_for_model(obj.connected_endpoint, prefix='Nested') - context = {'request': self.context['request']} - data = serializer(obj.connected_endpoint, context=context).data + if obj._path is not None and obj._path.destination is not None: + serializer = get_serializer_for_model(obj._path.destination, prefix='Nested') + context = {'request': self.context['request']} + return serializer(obj._path.destination, context=context).data + return None - return data + @swagger_serializer_method(serializer_or_field=serializers.BooleanField) + def get_connected_endpoint_reachable(self, obj): + if obj._path is not None: + return obj._path.is_active + return None # @@ -168,7 +191,7 @@ class RackUnitSerializer(serializers.Serializer): occupied = serializers.BooleanField(read_only=True) -class RackReservationSerializer(TaggedObjectSerializer, ValidatedModelSerializer): +class RackReservationSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rackreservation-detail') rack = NestedRackSerializer() user = NestedUserSerializer() @@ -176,7 +199,7 @@ class RackReservationSerializer(TaggedObjectSerializer, ValidatedModelSerializer class Meta: model = RackReservation - fields = ['id', 'url', 'rack', 'units', 'created', 'user', 'tenant', 'description', 'tags'] + fields = ['id', 'url', 'rack', 'units', 'created', 'user', 'tenant', 'description', 'tags', 'custom_fields'] class RackElevationDetailFilterSerializer(serializers.Serializer): @@ -452,7 +475,7 @@ class DeviceNAPALMSerializer(serializers.Serializer): method = serializers.DictField() -class ConsoleServerPortSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer): +class ConsoleServerPortSerializer(TaggedObjectSerializer, CableTerminationSerializer, ConnectedEndpointSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleserverport-detail') device = NestedDeviceSerializer() type = ChoiceField( @@ -465,12 +488,12 @@ class ConsoleServerPortSerializer(TaggedObjectSerializer, ConnectedEndpointSeria class Meta: model = ConsoleServerPort fields = [ - 'id', 'url', 'device', 'name', 'label', 'type', 'description', 'connected_endpoint_type', - 'connected_endpoint', 'connection_status', 'cable', 'tags', + 'id', 'url', 'device', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'cable_peer_type', + 'connected_endpoint', 'connected_endpoint_type', 'connected_endpoint_reachable', 'tags', ] -class ConsolePortSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer): +class ConsolePortSerializer(TaggedObjectSerializer, CableTerminationSerializer, ConnectedEndpointSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleport-detail') device = NestedDeviceSerializer() type = ChoiceField( @@ -483,12 +506,12 @@ class ConsolePortSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer) class Meta: model = ConsolePort fields = [ - 'id', 'url', 'device', 'name', 'label', 'type', 'description', 'connected_endpoint_type', - 'connected_endpoint', 'connection_status', 'cable', 'tags', + 'id', 'url', 'device', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'cable_peer_type', + 'connected_endpoint', 'connected_endpoint_type', 'connected_endpoint_reachable', 'tags', ] -class PowerOutletSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer): +class PowerOutletSerializer(TaggedObjectSerializer, CableTerminationSerializer, ConnectedEndpointSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:poweroutlet-detail') device = NestedDeviceSerializer() type = ChoiceField( @@ -511,12 +534,13 @@ class PowerOutletSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer) class Meta: model = PowerOutlet fields = [ - 'id', 'url', 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', - 'connected_endpoint_type', 'connected_endpoint', 'connection_status', 'cable', 'tags', + 'id', 'url', 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'cable', + 'cable_peer', 'cable_peer_type', 'connected_endpoint', 'connected_endpoint_type', + 'connected_endpoint_reachable', 'tags', ] -class PowerPortSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer): +class PowerPortSerializer(TaggedObjectSerializer, CableTerminationSerializer, ConnectedEndpointSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerport-detail') device = NestedDeviceSerializer() type = ChoiceField( @@ -529,12 +553,13 @@ class PowerPortSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer): class Meta: model = PowerPort fields = [ - 'id', 'url', 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', - 'connected_endpoint_type', 'connected_endpoint', 'connection_status', 'cable', 'tags', + 'id', 'url', 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'cable', + 'cable_peer', 'cable_peer_type', 'connected_endpoint', 'connected_endpoint_type', + 'connected_endpoint_reachable', 'tags', ] -class InterfaceSerializer(TaggedObjectSerializer, ConnectedEndpointSerializer): +class InterfaceSerializer(TaggedObjectSerializer, CableTerminationSerializer, ConnectedEndpointSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interface-detail') device = NestedDeviceSerializer() type = ChoiceField(choices=InterfaceTypeChoices) @@ -554,32 +579,26 @@ class Meta: model = Interface fields = [ 'id', 'url', 'device', 'name', 'label', 'type', 'enabled', 'lag', 'mtu', 'mac_address', 'mgmt_only', - 'description', 'connected_endpoint_type', 'connected_endpoint', 'connection_status', 'cable', 'mode', - 'untagged_vlan', 'tagged_vlans', 'tags', 'count_ipaddresses', + 'description', 'mode', 'untagged_vlan', 'tagged_vlans', 'cable', 'cable_peer', 'cable_peer_type', + 'connected_endpoint', 'connected_endpoint_type', 'connected_endpoint_reachable', 'tags', + 'count_ipaddresses', ] - # TODO: This validation should be handled by Interface.clean() def validate(self, data): - # All associated VLANs be global or assigned to the parent device's site. + # Validate many-to-many VLAN assignments device = self.instance.device if self.instance else data.get('device') - untagged_vlan = data.get('untagged_vlan') - if untagged_vlan and untagged_vlan.site not in [device.site, None]: - raise serializers.ValidationError({ - 'untagged_vlan': "VLAN {} must belong to the same site as the interface's parent device, or it must be " - "global.".format(untagged_vlan) - }) for vlan in data.get('tagged_vlans', []): if vlan.site not in [device.site, None]: raise serializers.ValidationError({ - 'tagged_vlans': "VLAN {} must belong to the same site as the interface's parent device, or it must " - "be global.".format(vlan) + 'tagged_vlans': f"VLAN {vlan} must belong to the same site as the interface's parent device, or " + f"it must be global." }) return super().validate(data) -class RearPortSerializer(TaggedObjectSerializer, ValidatedModelSerializer): +class RearPortSerializer(TaggedObjectSerializer, CableTerminationSerializer, ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rearport-detail') device = NestedDeviceSerializer() type = ChoiceField(choices=PortTypeChoices) @@ -587,7 +606,10 @@ class RearPortSerializer(TaggedObjectSerializer, ValidatedModelSerializer): class Meta: model = RearPort - fields = ['id', 'url', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable', 'tags'] + fields = [ + 'id', 'url', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', + 'cable_peer_type', 'tags', + ] class FrontPortRearPortSerializer(WritableNestedSerializer): @@ -601,7 +623,7 @@ class Meta: fields = ['id', 'url', 'name', 'label'] -class FrontPortSerializer(TaggedObjectSerializer, ValidatedModelSerializer): +class FrontPortSerializer(TaggedObjectSerializer, CableTerminationSerializer, ValidatedModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:frontport-detail') device = NestedDeviceSerializer() type = ChoiceField(choices=PortTypeChoices) @@ -612,7 +634,7 @@ class Meta: model = FrontPort fields = [ 'id', 'url', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', - 'tags', + 'cable_peer', 'cable_peer_type', 'tags', ] @@ -636,12 +658,13 @@ class InventoryItemSerializer(TaggedObjectSerializer, ValidatedModelSerializer): # Provide a default value to satisfy UniqueTogetherValidator parent = serializers.PrimaryKeyRelatedField(queryset=InventoryItem.objects.all(), allow_null=True, default=None) manufacturer = NestedManufacturerSerializer(required=False, allow_null=True, default=None) + _depth = serializers.IntegerField(source='level', read_only=True) class Meta: model = InventoryItem fields = [ 'id', 'url', 'device', 'parent', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', - 'discovered', 'description', 'tags', + 'discovered', 'description', 'tags', '_depth', ] @@ -649,7 +672,7 @@ class Meta: # Cables # -class CableSerializer(TaggedObjectSerializer, ValidatedModelSerializer): +class CableSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:cable-detail') termination_a_type = ContentTypeField( queryset=ContentType.objects.filter(CABLE_TERMINATION_MODELS) @@ -667,6 +690,7 @@ class Meta: fields = [ 'id', 'url', 'termination_a_type', 'termination_a_id', 'termination_a', 'termination_b_type', 'termination_b_id', 'termination_b', 'type', 'status', 'label', 'color', 'length', 'length_unit', 'tags', + 'custom_fields', ] def _get_termination(self, obj, side): @@ -706,6 +730,49 @@ class Meta: ] +class CablePathSerializer(serializers.ModelSerializer): + origin_type = ContentTypeField(read_only=True) + origin = serializers.SerializerMethodField(read_only=True) + destination_type = ContentTypeField(read_only=True) + destination = serializers.SerializerMethodField(read_only=True) + path = serializers.SerializerMethodField(read_only=True) + + class Meta: + model = CablePath + fields = [ + 'id', 'origin_type', 'origin', 'destination_type', 'destination', 'path', 'is_active', 'is_split', + ] + + @swagger_serializer_method(serializer_or_field=serializers.DictField) + def get_origin(self, obj): + """ + Return the appropriate serializer for the origin. + """ + serializer = get_serializer_for_model(obj.origin, prefix='Nested') + context = {'request': self.context['request']} + return serializer(obj.origin, context=context).data + + @swagger_serializer_method(serializer_or_field=serializers.DictField) + def get_destination(self, obj): + """ + Return the appropriate serializer for the destination, if any. + """ + if obj.destination_id is not None: + serializer = get_serializer_for_model(obj.destination, prefix='Nested') + context = {'request': self.context['request']} + return serializer(obj.destination, context=context).data + return None + + @swagger_serializer_method(serializer_or_field=serializers.ListField) + def get_path(self, obj): + ret = [] + for node in obj.get_path(): + serializer = get_serializer_for_model(node, prefix='Nested') + context = {'request': self.context['request']} + ret.append(serializer(node, context=context).data) + return ret + + # # Interface connections # @@ -713,37 +780,43 @@ class Meta: class InterfaceConnectionSerializer(ValidatedModelSerializer): interface_a = serializers.SerializerMethodField() interface_b = NestedInterfaceSerializer(source='connected_endpoint') - connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, required=False) + connected_endpoint_reachable = serializers.SerializerMethodField(read_only=True) class Meta: model = Interface - fields = ['interface_a', 'interface_b', 'connection_status'] + fields = ['interface_a', 'interface_b', 'connected_endpoint_reachable'] @swagger_serializer_method(serializer_or_field=NestedInterfaceSerializer) def get_interface_a(self, obj): context = {'request': self.context['request']} return NestedInterfaceSerializer(instance=obj, context=context).data + @swagger_serializer_method(serializer_or_field=serializers.BooleanField) + def get_connected_endpoint_reachable(self, obj): + if obj._path is not None: + return obj._path.is_active + return None + # # Virtual chassis # -class VirtualChassisSerializer(TaggedObjectSerializer, ValidatedModelSerializer): +class VirtualChassisSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:virtualchassis-detail') master = NestedDeviceSerializer(required=False) member_count = serializers.IntegerField(read_only=True) class Meta: model = VirtualChassis - fields = ['id', 'url', 'name', 'domain', 'master', 'tags', 'member_count'] + fields = ['id', 'url', 'name', 'domain', 'master', 'tags', 'custom_fields', 'member_count'] # # Power panels # -class PowerPanelSerializer(TaggedObjectSerializer, ValidatedModelSerializer): +class PowerPanelSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerpanel-detail') site = NestedSiteSerializer() rack_group = NestedRackGroupSerializer( @@ -755,10 +828,15 @@ class PowerPanelSerializer(TaggedObjectSerializer, ValidatedModelSerializer): class Meta: model = PowerPanel - fields = ['id', 'url', 'site', 'rack_group', 'name', 'tags', 'powerfeed_count'] + fields = ['id', 'url', 'site', 'rack_group', 'name', 'tags', 'custom_fields', 'powerfeed_count'] -class PowerFeedSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): +class PowerFeedSerializer( + TaggedObjectSerializer, + CableTerminationSerializer, + ConnectedEndpointSerializer, + CustomFieldModelSerializer +): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerfeed-detail') power_panel = NestedPowerPanelSerializer() rack = NestedRackSerializer( @@ -788,5 +866,7 @@ class Meta: model = PowerFeed fields = [ 'id', 'url', 'power_panel', 'rack', 'name', 'status', 'type', 'supply', 'phase', 'voltage', 'amperage', - 'max_utilization', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'cable', + 'max_utilization', 'comments', 'cable', 'cable_peer', 'cable_peer_type', 'connected_endpoint', + 'connected_endpoint_type', 'connected_endpoint_reachable', 'tags', 'custom_fields', 'created', + 'last_updated', ] diff --git a/netbox/dcim/api/urls.py b/netbox/dcim/api/urls.py index e8c4fbe1d3..689cb7aa10 100644 --- a/netbox/dcim/api/urls.py +++ b/netbox/dcim/api/urls.py @@ -1,4 +1,4 @@ -from utilities.api import OrderedDefaultRouter +from netbox.api import OrderedDefaultRouter from . import views diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 0e0e074e12..071174c76c 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -17,21 +17,20 @@ from circuits.models import Circuit from dcim import filters from dcim.models import ( - Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay, + Cable, CablePath, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay, DeviceBayTemplate, DeviceRole, DeviceType, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate, Manufacturer, InventoryItem, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, PowerPort, PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site, VirtualChassis, ) -from extras.api.serializers import RenderedGraphSerializer from extras.api.views import ConfigContextQuerySetMixin, CustomFieldModelViewSet -from extras.models import Graph from ipam.models import Prefix, VLAN -from utilities.api import ( - get_serializer_for_model, IsAuthenticatedOrLoginNotRequired, ModelViewSet, ServiceUnavailable, -) +from netbox.api.views import ModelViewSet +from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired +from netbox.api.exceptions import ServiceUnavailable +from netbox.api.metadata import ContentTypeMetadata +from utilities.api import get_serializer_for_model from utilities.utils import get_subquery -from utilities.metadata import ContentTypeMetadata from virtualization.models import VirtualMachine from . import serializers from .exceptions import MissingFilterException @@ -47,7 +46,7 @@ def get_view_name(self): # Mixins -class CableTraceMixin(object): +class PathEndpointMixin(object): @action(detail=True, url_path='trace') def trace(self, request, pk): @@ -59,7 +58,10 @@ def trace(self, request, pk): # Initialize the path array path = [] - for near_end, cable, far_end in obj.trace()[0]: + for near_end, cable, far_end in obj.trace(): + if near_end is None: + # Split paths + break # Serialize each object serializer_a = get_serializer_for_model(near_end, prefix='Nested') @@ -79,6 +81,20 @@ def trace(self, request, pk): return Response(path) +class PassThroughPortMixin(object): + + @action(detail=True, url_path='paths') + def paths(self, request, pk): + """ + Return all CablePaths which traverse a given pass-through port. + """ + obj = get_object_or_404(self.queryset, pk=pk) + cablepaths = CablePath.objects.filter(path__contains=obj).prefetch_related('origin', 'destination') + serializer = serializers.CablePathSerializer(cablepaths, context={'request': request}, many=True) + + return Response(serializer.data) + + # # Regions # @@ -113,16 +129,6 @@ class SiteViewSet(CustomFieldModelViewSet): serializer_class = serializers.SiteSerializer filterset_class = filters.SiteFilterSet - @action(detail=True) - def graphs(self, request, pk): - """ - A convenience method for rendering graphs for a particular site. - """ - site = get_object_or_404(self.queryset, pk=pk) - queryset = Graph.objects.restrict(request.user).filter(type__model='site') - serializer = RenderedGraphSerializer(queryset, many=True, context={'graphed_object': site}) - return Response(serializer.data) - # # Rack groups @@ -363,17 +369,6 @@ def get_serializer_class(self): return serializers.DeviceWithConfigContextSerializer - @action(detail=True) - def graphs(self, request, pk): - """ - A convenience method for rendering graphs for a particular Device. - """ - device = get_object_or_404(self.queryset, pk=pk) - queryset = Graph.objects.restrict(request.user).filter(type__model='device') - serializer = RenderedGraphSerializer(queryset, many=True, context={'graphed_object': device}) - - return Response(serializer.data) - @swagger_auto_schema( manual_parameters=[ Parameter( @@ -494,59 +489,47 @@ def napalm(self, request, pk): # Device components # -class ConsolePortViewSet(CableTraceMixin, ModelViewSet): - queryset = ConsolePort.objects.prefetch_related('device', 'connected_endpoint__device', 'cable', 'tags') +class ConsolePortViewSet(PathEndpointMixin, ModelViewSet): + queryset = ConsolePort.objects.prefetch_related('device', '_path__destination', 'cable', '_cable_peer', 'tags') serializer_class = serializers.ConsolePortSerializer filterset_class = filters.ConsolePortFilterSet -class ConsoleServerPortViewSet(CableTraceMixin, ModelViewSet): - queryset = ConsoleServerPort.objects.prefetch_related('device', 'connected_endpoint__device', 'cable', 'tags') +class ConsoleServerPortViewSet(PathEndpointMixin, ModelViewSet): + queryset = ConsoleServerPort.objects.prefetch_related( + 'device', '_path__destination', 'cable', '_cable_peer', 'tags' + ) serializer_class = serializers.ConsoleServerPortSerializer filterset_class = filters.ConsoleServerPortFilterSet -class PowerPortViewSet(CableTraceMixin, ModelViewSet): - queryset = PowerPort.objects.prefetch_related( - 'device', '_connected_poweroutlet__device', '_connected_powerfeed', 'cable', 'tags' - ) +class PowerPortViewSet(PathEndpointMixin, ModelViewSet): + queryset = PowerPort.objects.prefetch_related('device', '_path__destination', 'cable', '_cable_peer', 'tags') serializer_class = serializers.PowerPortSerializer filterset_class = filters.PowerPortFilterSet -class PowerOutletViewSet(CableTraceMixin, ModelViewSet): - queryset = PowerOutlet.objects.prefetch_related('device', 'connected_endpoint__device', 'cable', 'tags') +class PowerOutletViewSet(PathEndpointMixin, ModelViewSet): + queryset = PowerOutlet.objects.prefetch_related('device', '_path__destination', 'cable', '_cable_peer', 'tags') serializer_class = serializers.PowerOutletSerializer filterset_class = filters.PowerOutletFilterSet -class InterfaceViewSet(CableTraceMixin, ModelViewSet): +class InterfaceViewSet(PathEndpointMixin, ModelViewSet): queryset = Interface.objects.prefetch_related( - 'device', '_connected_interface', '_connected_circuittermination', 'cable', 'ip_addresses', 'tags' - ).filter( - device__isnull=False + 'device', '_path__destination', 'cable', '_cable_peer', 'ip_addresses', 'tags' ) serializer_class = serializers.InterfaceSerializer filterset_class = filters.InterfaceFilterSet - @action(detail=True) - def graphs(self, request, pk): - """ - A convenience method for rendering graphs for a particular interface. - """ - interface = get_object_or_404(self.queryset, pk=pk) - queryset = Graph.objects.restrict(request.user).filter(type__model='interface') - serializer = RenderedGraphSerializer(queryset, many=True, context={'graphed_object': interface}) - return Response(serializer.data) - -class FrontPortViewSet(CableTraceMixin, ModelViewSet): +class FrontPortViewSet(PassThroughPortMixin, ModelViewSet): queryset = FrontPort.objects.prefetch_related('device__device_type__manufacturer', 'rear_port', 'cable', 'tags') serializer_class = serializers.FrontPortSerializer filterset_class = filters.FrontPortFilterSet -class RearPortViewSet(CableTraceMixin, ModelViewSet): +class RearPortViewSet(PassThroughPortMixin, ModelViewSet): queryset = RearPort.objects.prefetch_related('device__device_type__manufacturer', 'cable', 'tags') serializer_class = serializers.RearPortSerializer filterset_class = filters.RearPortFilterSet @@ -569,32 +552,26 @@ class InventoryItemViewSet(ModelViewSet): # class ConsoleConnectionViewSet(ListModelMixin, GenericViewSet): - queryset = ConsolePort.objects.prefetch_related( - 'device', 'connected_endpoint__device' - ).filter( - connected_endpoint__isnull=False + queryset = ConsolePort.objects.prefetch_related('device', '_path').filter( + _path__destination_id__isnull=False ) serializer_class = serializers.ConsolePortSerializer filterset_class = filters.ConsoleConnectionFilterSet class PowerConnectionViewSet(ListModelMixin, GenericViewSet): - queryset = PowerPort.objects.prefetch_related( - 'device', 'connected_endpoint__device' - ).filter( - _connected_poweroutlet__isnull=False + queryset = PowerPort.objects.prefetch_related('device', '_path').filter( + _path__destination_id__isnull=False ) serializer_class = serializers.PowerPortSerializer filterset_class = filters.PowerConnectionFilterSet class InterfaceConnectionViewSet(ListModelMixin, GenericViewSet): - queryset = Interface.objects.prefetch_related( - 'device', '_connected_interface__device' - ).filter( + queryset = Interface.objects.prefetch_related('device', '_path').filter( # Avoid duplicate connections by only selecting the lower PK in a connected pair - _connected_interface__isnull=False, - pk__lt=F('_connected_interface') + _path__destination_id__isnull=False, + pk__lt=F('_path__destination_id') ) serializer_class = serializers.InterfaceConnectionSerializer filterset_class = filters.InterfaceConnectionFilterSet @@ -643,8 +620,10 @@ class PowerPanelViewSet(ModelViewSet): # Power feeds # -class PowerFeedViewSet(CustomFieldModelViewSet): - queryset = PowerFeed.objects.prefetch_related('power_panel', 'rack', 'tags') +class PowerFeedViewSet(PathEndpointMixin, CustomFieldModelViewSet): + queryset = PowerFeed.objects.prefetch_related( + 'power_panel', 'rack', '_path__destination', 'cable', '_cable_peer', 'tags' + ) serializer_class = serializers.PowerFeedSerializer filterset_class = filters.PowerFeedFilterSet @@ -699,7 +678,7 @@ def list(self, request): device__name=peer_device_name, name=peer_interface_name ) - local_interface = peer_interface._connected_interface + local_interface = peer_interface.connected_endpoint if local_interface is None: return Response() diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index 3b7c7d04e9..d8f8e3e275 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -21,6 +21,14 @@ class SiteStatusChoices(ChoiceSet): (STATUS_RETIRED, 'Retired'), ) + CSS_CLASSES = { + STATUS_PLANNED: 'info', + STATUS_STAGING: 'primary', + STATUS_ACTIVE: 'success', + STATUS_DECOMMISSIONING: 'warning', + STATUS_RETIRED: 'danger', + } + # # Racks @@ -74,6 +82,14 @@ class RackStatusChoices(ChoiceSet): (STATUS_DEPRECATED, 'Deprecated'), ) + CSS_CLASSES = { + STATUS_RESERVED: 'warning', + STATUS_AVAILABLE: 'success', + STATUS_PLANNED: 'info', + STATUS_ACTIVE: 'primary', + STATUS_DEPRECATED: 'danger', + } + class RackDimensionUnitChoices(ChoiceSet): @@ -147,6 +163,16 @@ class DeviceStatusChoices(ChoiceSet): (STATUS_DECOMMISSIONING, 'Decommissioning'), ) + CSS_CLASSES = { + STATUS_OFFLINE: 'warning', + STATUS_ACTIVE: 'success', + STATUS_PLANNED: 'info', + STATUS_STAGED: 'primary', + STATUS_FAILED: 'danger', + STATUS_INVENTORY: 'default', + STATUS_DECOMMISSIONING: 'warning', + } + # # ConsolePorts @@ -969,6 +995,12 @@ class CableStatusChoices(ChoiceSet): (STATUS_DECOMMISSIONING, 'Decommissioning'), ) + CSS_CLASSES = { + STATUS_CONNECTED: 'success', + STATUS_PLANNED: 'info', + STATUS_DECOMMISSIONING: 'warning', + } + class CableLengthUnitChoices(ChoiceSet): @@ -1003,6 +1035,13 @@ class PowerFeedStatusChoices(ChoiceSet): (STATUS_FAILED, 'Failed'), ) + CSS_CLASSES = { + STATUS_OFFLINE: 'warning', + STATUS_ACTIVE: 'success', + STATUS_PLANNED: 'info', + STATUS_FAILED: 'danger', + } + class PowerFeedTypeChoices(ChoiceSet): @@ -1014,6 +1053,11 @@ class PowerFeedTypeChoices(ChoiceSet): (TYPE_REDUNDANT, 'Redundant'), ) + CSS_CLASSES = { + TYPE_PRIMARY: 'success', + TYPE_REDUNDANT: 'info', + } + class PowerFeedSupplyChoices(ChoiceSet): diff --git a/netbox/dcim/constants.py b/netbox/dcim/constants.py index 961c458e0e..0fc69be3bb 100644 --- a/netbox/dcim/constants.py +++ b/netbox/dcim/constants.py @@ -59,12 +59,6 @@ # Cabling and connections # -# Console/power/interface connection statuses -CONNECTION_STATUS_CHOICES = [ - [False, 'Not Connected'], - [True, 'Connected'], -] - # Cable endpoint types CABLE_TERMINATION_MODELS = Q( Q(app_label='circuits', model__in=( @@ -83,12 +77,13 @@ ) COMPATIBLE_TERMINATION_TYPES = { + 'circuittermination': ['interface', 'frontport', 'rearport', 'circuittermination'], 'consoleport': ['consoleserverport', 'frontport', 'rearport'], 'consoleserverport': ['consoleport', 'frontport', 'rearport'], - 'powerport': ['poweroutlet', 'powerfeed'], - 'poweroutlet': ['powerport'], 'interface': ['interface', 'circuittermination', 'frontport', 'rearport'], 'frontport': ['consoleport', 'consoleserverport', 'interface', 'frontport', 'rearport', 'circuittermination'], + 'powerfeed': ['powerport'], + 'poweroutlet': ['powerport'], + 'powerport': ['poweroutlet', 'powerfeed'], 'rearport': ['consoleport', 'consoleserverport', 'interface', 'frontport', 'rearport', 'circuittermination'], - 'circuittermination': ['interface', 'frontport', 'rearport', 'circuittermination'], } diff --git a/netbox/dcim/exceptions.py b/netbox/dcim/exceptions.py deleted file mode 100644 index 18e42318b9..0000000000 --- a/netbox/dcim/exceptions.py +++ /dev/null @@ -1,14 +0,0 @@ -class LoopDetected(Exception): - """ - A loop has been detected while tracing a cable path. - """ - pass - - -class CableTraceSplit(Exception): - """ - A cable trace cannot be completed because a RearPort maps to multiple FrontPorts and - we don't know which one to follow. - """ - def __init__(self, termination, *args, **kwargs): - self.termination = termination diff --git a/netbox/dcim/fields.py b/netbox/dcim/fields.py index 3acd0d4a1f..21af2ed145 100644 --- a/netbox/dcim/fields.py +++ b/netbox/dcim/fields.py @@ -1,9 +1,11 @@ +from django.contrib.postgres.fields import ArrayField from django.core.exceptions import ValidationError from django.core.validators import MinValueValidator, MaxValueValidator from django.db import models from netaddr import AddrFormatError, EUI, mac_unix_expanded from ipam.constants import BGP_ASN_MAX, BGP_ASN_MIN +from .lookups import PathContains class ASNField(models.BigIntegerField): @@ -50,3 +52,15 @@ def get_prep_value(self, value): if not value: return None return str(self.to_python(value)) + + +class PathField(ArrayField): + """ + An ArrayField which holds a set of objects, each identified by a (type, ID) tuple. + """ + def __init__(self, **kwargs): + kwargs['base_field'] = models.CharField(max_length=40) + super().__init__(**kwargs) + + +PathField.register_lookup(PathContains) diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 773b33f747..3f104ef188 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -1,7 +1,8 @@ import django_filters from django.contrib.auth.models import User +from django.db.models import Count -from extras.filters import CustomFieldFilterSet, LocalConfigContextFilterSet, CreatedUpdatedFilterSet +from extras.filters import CustomFieldModelFilterSet, LocalConfigContextFilterSet, CreatedUpdatedFilterSet from tenancy.filters import TenancyFilterSet from tenancy.models import Tenant from utilities.choices import ColorChoices @@ -23,6 +24,7 @@ __all__ = ( 'CableFilterSet', + 'CableTerminationFilterSet', 'ConsoleConnectionFilterSet', 'ConsolePortFilterSet', 'ConsolePortTemplateFilterSet', @@ -40,6 +42,7 @@ 'InterfaceTemplateFilterSet', 'InventoryItemFilterSet', 'ManufacturerFilterSet', + 'PathEndpointFilterSet', 'PlatformFilterSet', 'PowerConnectionFilterSet', 'PowerFeedFilterSet', @@ -77,7 +80,7 @@ class Meta: fields = ['id', 'name', 'slug', 'description'] -class SiteFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet): +class SiteFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): q = django_filters.CharFilter( method='search', label='Search', @@ -176,7 +179,7 @@ class Meta: fields = ['id', 'name', 'slug', 'color'] -class RackFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet): +class RackFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): q = django_filters.CharFilter( method='search', label='Search', @@ -322,7 +325,7 @@ class Meta: fields = ['id', 'name', 'slug', 'description'] -class DeviceTypeFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet): +class DeviceTypeFilterSet(BaseFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): q = django_filters.CharFilter( method='search', label='Search', @@ -501,7 +504,7 @@ class DeviceFilterSet( BaseFilterSet, TenancyFilterSet, LocalConfigContextFilterSet, - CustomFieldFilterSet, + CustomFieldModelFilterSet, CreatedUpdatedFilterSet ): q = django_filters.CharFilter( @@ -746,71 +749,76 @@ def search(self, queryset, name, value): ) -class ConsolePortFilterSet(BaseFilterSet, DeviceComponentFilterSet): - type = django_filters.MultipleChoiceFilter( - choices=ConsolePortTypeChoices, - null_value=None - ) +class CableTerminationFilterSet(django_filters.FilterSet): cabled = django_filters.BooleanFilter( field_name='cable', lookup_expr='isnull', exclude=True ) + +class PathEndpointFilterSet(django_filters.FilterSet): + connected = django_filters.BooleanFilter( + method='filter_connected' + ) + + def filter_connected(self, queryset, name, value): + if value: + return queryset.filter(_path__is_active=True) + else: + return queryset.filter(Q(_path__isnull=True) | Q(_path__is_active=False)) + + +class ConsolePortFilterSet(BaseFilterSet, DeviceComponentFilterSet, CableTerminationFilterSet, PathEndpointFilterSet): + type = django_filters.MultipleChoiceFilter( + choices=ConsolePortTypeChoices, + null_value=None + ) + class Meta: model = ConsolePort - fields = ['id', 'name', 'description', 'connection_status'] + fields = ['id', 'name', 'description'] -class ConsoleServerPortFilterSet(BaseFilterSet, DeviceComponentFilterSet): +class ConsoleServerPortFilterSet( + BaseFilterSet, + DeviceComponentFilterSet, + CableTerminationFilterSet, + PathEndpointFilterSet +): type = django_filters.MultipleChoiceFilter( choices=ConsolePortTypeChoices, null_value=None ) - cabled = django_filters.BooleanFilter( - field_name='cable', - lookup_expr='isnull', - exclude=True - ) class Meta: model = ConsoleServerPort - fields = ['id', 'name', 'description', 'connection_status'] + fields = ['id', 'name', 'description'] -class PowerPortFilterSet(BaseFilterSet, DeviceComponentFilterSet): +class PowerPortFilterSet(BaseFilterSet, DeviceComponentFilterSet, CableTerminationFilterSet, PathEndpointFilterSet): type = django_filters.MultipleChoiceFilter( choices=PowerPortTypeChoices, null_value=None ) - cabled = django_filters.BooleanFilter( - field_name='cable', - lookup_expr='isnull', - exclude=True - ) class Meta: model = PowerPort - fields = ['id', 'name', 'maximum_draw', 'allocated_draw', 'description', 'connection_status'] + fields = ['id', 'name', 'maximum_draw', 'allocated_draw', 'description'] -class PowerOutletFilterSet(BaseFilterSet, DeviceComponentFilterSet): +class PowerOutletFilterSet(BaseFilterSet, DeviceComponentFilterSet, CableTerminationFilterSet, PathEndpointFilterSet): type = django_filters.MultipleChoiceFilter( choices=PowerOutletTypeChoices, null_value=None ) - cabled = django_filters.BooleanFilter( - field_name='cable', - lookup_expr='isnull', - exclude=True - ) class Meta: model = PowerOutlet - fields = ['id', 'name', 'feed_leg', 'description', 'connection_status'] + fields = ['id', 'name', 'feed_leg', 'description'] -class InterfaceFilterSet(BaseFilterSet, DeviceComponentFilterSet): +class InterfaceFilterSet(BaseFilterSet, DeviceComponentFilterSet, CableTerminationFilterSet, PathEndpointFilterSet): q = django_filters.CharFilter( method='search', label='Search', @@ -827,11 +835,6 @@ class InterfaceFilterSet(BaseFilterSet, DeviceComponentFilterSet): field_name='pk', label='Device (ID)', ) - cabled = django_filters.BooleanFilter( - field_name='cable', - lookup_expr='isnull', - exclude=True - ) kind = django_filters.CharFilter( method='filter_kind', label='Kind of interface', @@ -858,7 +861,7 @@ class InterfaceFilterSet(BaseFilterSet, DeviceComponentFilterSet): class Meta: model = Interface - fields = ['id', 'name', 'connection_status', 'type', 'enabled', 'mtu', 'mgmt_only', 'mode', 'description'] + fields = ['id', 'name', 'type', 'enabled', 'mtu', 'mgmt_only', 'mode', 'description'] def filter_device(self, queryset, name, value): try: @@ -908,24 +911,14 @@ def filter_kind(self, queryset, name, value): }.get(value, queryset.none()) -class FrontPortFilterSet(BaseFilterSet, DeviceComponentFilterSet): - cabled = django_filters.BooleanFilter( - field_name='cable', - lookup_expr='isnull', - exclude=True - ) +class FrontPortFilterSet(BaseFilterSet, DeviceComponentFilterSet, CableTerminationFilterSet): class Meta: model = FrontPort fields = ['id', 'name', 'type', 'description'] -class RearPortFilterSet(BaseFilterSet, DeviceComponentFilterSet): - cabled = django_filters.BooleanFilter( - field_name='cable', - lookup_expr='isnull', - exclude=True - ) +class RearPortFilterSet(BaseFilterSet, DeviceComponentFilterSet, CableTerminationFilterSet): class Meta: model = RearPort @@ -1133,7 +1126,20 @@ def filter_device(self, queryset, name, value): return queryset -class ConsoleConnectionFilterSet(BaseFilterSet): +class ConnectionFilterSet: + + def filter_site(self, queryset, name, value): + if not value.strip(): + return queryset + return queryset.filter(device__site__slug=value) + + def filter_device(self, queryset, name, value): + if not value: + return queryset + return queryset.filter(device_id__in=value) + + +class ConsoleConnectionFilterSet(ConnectionFilterSet, BaseFilterSet): site = django_filters.CharFilter( method='filter_site', label='Site (slug)', @@ -1148,23 +1154,10 @@ class ConsoleConnectionFilterSet(BaseFilterSet): class Meta: model = ConsolePort - fields = ['name', 'connection_status'] + fields = ['name'] - def filter_site(self, queryset, name, value): - if not value.strip(): - return queryset - return queryset.filter(connected_endpoint__device__site__slug=value) - - def filter_device(self, queryset, name, value): - if not value: - return queryset - return queryset.filter( - Q(**{'{}__in'.format(name): value}) | - Q(**{'connected_endpoint__{}__in'.format(name): value}) - ) - -class PowerConnectionFilterSet(BaseFilterSet): +class PowerConnectionFilterSet(ConnectionFilterSet, BaseFilterSet): site = django_filters.CharFilter( method='filter_site', label='Site (slug)', @@ -1179,23 +1172,10 @@ class PowerConnectionFilterSet(BaseFilterSet): class Meta: model = PowerPort - fields = ['name', 'connection_status'] - - def filter_site(self, queryset, name, value): - if not value.strip(): - return queryset - return queryset.filter(_connected_poweroutlet__device__site__slug=value) - - def filter_device(self, queryset, name, value): - if not value: - return queryset - return queryset.filter( - Q(**{'{}__in'.format(name): value}) | - Q(**{'_connected_poweroutlet__{}__in'.format(name): value}) - ) + fields = ['name'] -class InterfaceConnectionFilterSet(BaseFilterSet): +class InterfaceConnectionFilterSet(ConnectionFilterSet, BaseFilterSet): site = django_filters.CharFilter( method='filter_site', label='Site (slug)', @@ -1210,23 +1190,7 @@ class InterfaceConnectionFilterSet(BaseFilterSet): class Meta: model = Interface - fields = ['connection_status'] - - def filter_site(self, queryset, name, value): - if not value.strip(): - return queryset - return queryset.filter( - Q(device__site__slug=value) | - Q(_connected_interface__device__site__slug=value) - ) - - def filter_device(self, queryset, name, value): - if not value: - return queryset - return queryset.filter( - Q(**{'{}__in'.format(name): value}) | - Q(**{'_connected_interface__{}__in'.format(name): value}) - ) + fields = [] class PowerPanelFilterSet(BaseFilterSet): @@ -1278,7 +1242,13 @@ def search(self, queryset, name, value): return queryset.filter(qs_filter) -class PowerFeedFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet): +class PowerFeedFilterSet( + BaseFilterSet, + CableTerminationFilterSet, + PathEndpointFilterSet, + CustomFieldModelFilterSet, + CreatedUpdatedFilterSet +): q = django_filters.CharFilter( method='search', label='Search', diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index e566052506..ca7602bf21 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -22,9 +22,10 @@ from tenancy.models import Tenant, TenantGroup from utilities.forms import ( APISelect, add_blank_choice, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, - ColorSelect, CommentField, CSVChoiceField, CSVModelChoiceField, CSVModelForm, DynamicModelChoiceField, - DynamicModelMultipleChoiceField, ExpandableNameField, form_from_model, JSONField, NumericArrayField, SelectWithPK, - SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, + ColorSelect, CommentField, CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, CSVModelForm, + DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableNameField, form_from_model, JSONField, + NumericArrayField, SelectWithPK, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, + BOOLEAN_WITH_BLANK_CHOICES, ) from virtualization.models import Cluster, ClusterGroup from .choices import * @@ -88,13 +89,12 @@ class DeviceComponentFilterForm(BootstrapMixin, forms.Form): ) -class InterfaceCommonForm: +class InterfaceCommonForm(forms.Form): def clean(self): - super().clean() - # Validate VLAN assignments + parent_field = 'device' if 'device' in self.cleaned_data else 'virtual_machine' tagged_vlans = self.cleaned_data['tagged_vlans'] # Untagged interfaces cannot be assigned tagged VLANs @@ -109,13 +109,13 @@ def clean(self): # Validate tagged VLANs; must be a global VLAN or in the same site elif self.cleaned_data['mode'] == InterfaceModeChoices.MODE_TAGGED: - valid_sites = [None, self.cleaned_data['device'].site] + valid_sites = [None, self.cleaned_data[parent_field].site] invalid_vlans = [str(v) for v in tagged_vlans if v.site not in valid_sites] if invalid_vlans: raise forms.ValidationError({ - 'tagged_vlans': "The tagged VLANs ({}) must belong to the same site as the interface's parent " - "device/VM, or they must be global".format(', '.join(invalid_vlans)) + 'tagged_vlans': f"The tagged VLANs ({', '.join(invalid_vlans)}) must belong to the same site as " + f"the interface's parent device/VM, or they must be global" }) @@ -721,7 +721,7 @@ class RackElevationFilterForm(RackFilterForm): # Rack reservations # -class RackReservationForm(BootstrapMixin, TenancyForm, forms.ModelForm): +class RackReservationForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): region = DynamicModelChoiceField( queryset=Region.objects.all(), required=False, @@ -2688,7 +2688,7 @@ class InterfaceFilterForm(DeviceComponentFilterForm): tag = TagFilterField(model) -class InterfaceForm(InterfaceCommonForm, BootstrapMixin, forms.ModelForm): +class InterfaceForm(BootstrapMixin, InterfaceCommonForm, forms.ModelForm): untagged_vlan = DynamicModelChoiceField( queryset=VLAN.objects.all(), required=False, @@ -3361,6 +3361,13 @@ class InventoryItemForm(BootstrapMixin, forms.ModelForm): queryset=Device.objects.all(), display_field='display_name' ) + parent = DynamicModelChoiceField( + queryset=InventoryItem.objects.all(), + required=False, + query_params={ + 'device_id': '$device' + } + ) manufacturer = DynamicModelChoiceField( queryset=Manufacturer.objects.all(), required=False @@ -3373,7 +3380,8 @@ class InventoryItemForm(BootstrapMixin, forms.ModelForm): class Meta: model = InventoryItem fields = [ - 'name', 'label', 'device', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'tags', + 'device', 'parent', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', + 'tags', ] @@ -3382,6 +3390,13 @@ class InventoryItemCreateForm(ComponentCreateForm): queryset=Manufacturer.objects.all(), required=False ) + parent = DynamicModelChoiceField( + queryset=InventoryItem.objects.all(), + required=False, + query_params={ + 'device_id': '$device' + } + ) part_id = forms.CharField( max_length=50, required=False, @@ -3396,8 +3411,8 @@ class InventoryItemCreateForm(ComponentCreateForm): required=False, ) field_order = ( - 'device', 'name_pattern', 'label_pattern', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', - 'tags', + 'device', 'parent', 'name_pattern', 'label_pattern', 'manufacturer', 'part_id', 'serial', 'asset_tag', + 'description', 'tags', ) @@ -3472,7 +3487,7 @@ class InventoryItemFilterForm(DeviceComponentFilterForm): # Cables # -class ConnectCableToDeviceForm(BootstrapMixin, forms.ModelForm): +class ConnectCableToDeviceForm(BootstrapMixin, CustomFieldModelForm): """ Base form for connecting a Cable to a Device component """ @@ -3609,7 +3624,7 @@ class ConnectCableToRearPortForm(ConnectCableToDeviceForm): ) -class ConnectCableToCircuitTerminationForm(BootstrapMixin, forms.ModelForm): +class ConnectCableToCircuitTerminationForm(BootstrapMixin, CustomFieldModelForm): termination_b_provider = DynamicModelChoiceField( queryset=Provider.objects.all(), label='Provider', @@ -3663,7 +3678,7 @@ def clean_termination_b_id(self): return getattr(self.cleaned_data['termination_b_id'], 'pk', None) -class ConnectCableToPowerFeedForm(BootstrapMixin, forms.ModelForm): +class ConnectCableToPowerFeedForm(BootstrapMixin, CustomFieldModelForm): termination_b_region = DynamicModelChoiceField( queryset=Region.objects.all(), label='Region', @@ -3720,7 +3735,7 @@ def clean_termination_b_id(self): return getattr(self.cleaned_data['termination_b_id'], 'pk', None) -class CableForm(BootstrapMixin, forms.ModelForm): +class CableForm(BootstrapMixin, CustomFieldModelForm): tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False @@ -3750,10 +3765,9 @@ class CableCSVForm(CSVModelForm): to_field_name='name', help_text='Side A device' ) - side_a_type = CSVModelChoiceField( + side_a_type = CSVContentTypeField( queryset=ContentType.objects.all(), limit_choices_to=CABLE_TERMINATION_MODELS, - to_field_name='model', help_text='Side A type' ) side_a_name = forms.CharField( @@ -3766,10 +3780,9 @@ class CableCSVForm(CSVModelForm): to_field_name='name', help_text='Side B device' ) - side_b_type = CSVModelChoiceField( + side_b_type = CSVContentTypeField( queryset=ContentType.objects.all(), limit_choices_to=CABLE_TERMINATION_MODELS, - to_field_name='model', help_text='Side B type' ) side_b_name = forms.CharField( @@ -3803,58 +3816,36 @@ class Meta: 'color': mark_safe('RGB color in hexadecimal (e.g. 00ff00)'), } - # TODO: Merge the clean() methods for either end - def clean_side_a_name(self): + def _clean_side(self, side): + """ + Derive a Cable's A/B termination objects. + + :param side: 'a' or 'b' + """ + assert side in 'ab', f"Invalid side designation: {side}" - device = self.cleaned_data.get('side_a_device') - content_type = self.cleaned_data.get('side_a_type') - name = self.cleaned_data.get('side_a_name') + device = self.cleaned_data.get(f'side_{side}_device') + content_type = self.cleaned_data.get(f'side_{side}_type') + name = self.cleaned_data.get(f'side_{side}_name') if not device or not content_type or not name: return None model = content_type.model_class() try: - termination_object = model.objects.get( - device=device, - name=name - ) + termination_object = model.objects.get(device=device, name=name) if termination_object.cable is not None: - raise forms.ValidationError( - "Side A: {} {} is already connected".format(device, termination_object) - ) + raise forms.ValidationError(f"Side {side.upper()}: {device} {termination_object} is already connected") except ObjectDoesNotExist: - raise forms.ValidationError( - "A side termination not found: {} {}".format(device, name) - ) + raise forms.ValidationError(f"{side.upper()} side termination not found: {device} {name}") - self.instance.termination_a = termination_object + setattr(self.instance, f'termination_{side}', termination_object) return termination_object - def clean_side_b_name(self): - - device = self.cleaned_data.get('side_b_device') - content_type = self.cleaned_data.get('side_b_type') - name = self.cleaned_data.get('side_b_name') - if not device or not content_type or not name: - return None - - model = content_type.model_class() - try: - termination_object = model.objects.get( - device=device, - name=name - ) - if termination_object.cable is not None: - raise forms.ValidationError( - "Side B: {} {} is already connected".format(device, termination_object) - ) - except ObjectDoesNotExist: - raise forms.ValidationError( - "B side termination not found: {} {}".format(device, name) - ) + def clean_side_a_name(self): + return self._clean_side('a') - self.instance.termination_b = termination_object - return termination_object + def clean_side_b_name(self): + return self._clean_side('b') def clean_length_unit(self): # Avoid trying to save as NULL @@ -4063,7 +4054,7 @@ class DeviceSelectionForm(forms.Form): ) -class VirtualChassisCreateForm(BootstrapMixin, forms.ModelForm): +class VirtualChassisCreateForm(BootstrapMixin, CustomFieldModelForm): region = DynamicModelChoiceField( queryset=Region.objects.all(), required=False, @@ -4126,7 +4117,7 @@ def save(self, *args, **kwargs): return instance -class VirtualChassisForm(BootstrapMixin, forms.ModelForm): +class VirtualChassisForm(BootstrapMixin, CustomFieldModelForm): master = forms.ModelChoiceField( queryset=Device.objects.all(), required=False, @@ -4316,7 +4307,7 @@ class VirtualChassisFilterForm(BootstrapMixin, CustomFieldFilterForm): # Power panels # -class PowerPanelForm(BootstrapMixin, forms.ModelForm): +class PowerPanelForm(BootstrapMixin, CustomFieldModelForm): region = DynamicModelChoiceField( queryset=Region.objects.all(), required=False, diff --git a/netbox/dcim/lookups.py b/netbox/dcim/lookups.py new file mode 100644 index 0000000000..03acc478a3 --- /dev/null +++ b/netbox/dcim/lookups.py @@ -0,0 +1,10 @@ +from django.contrib.postgres.fields.array import ArrayContains + +from dcim.utils import object_to_path_node + + +class PathContains(ArrayContains): + + def get_prep_lookup(self): + self.rhs = [object_to_path_node(self.rhs)] + return super().get_prep_lookup() diff --git a/netbox/dcim/management/__init__.py b/netbox/dcim/management/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/netbox/dcim/management/commands/__init__.py b/netbox/dcim/management/commands/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/netbox/dcim/management/commands/trace_paths.py b/netbox/dcim/management/commands/trace_paths.py new file mode 100644 index 0000000000..06b5bdec03 --- /dev/null +++ b/netbox/dcim/management/commands/trace_paths.py @@ -0,0 +1,88 @@ +from django.core.management.base import BaseCommand +from django.core.management.color import no_style +from django.db import connection + +from circuits.models import CircuitTermination +from dcim.models import CablePath, ConsolePort, ConsoleServerPort, Interface, PowerFeed, PowerOutlet, PowerPort +from dcim.signals import create_cablepath + +ENDPOINT_MODELS = ( + CircuitTermination, + ConsolePort, + ConsoleServerPort, + Interface, + PowerFeed, + PowerOutlet, + PowerPort +) + + +class Command(BaseCommand): + help = "Generate any missing cable paths among all cable termination objects in NetBox" + + def add_arguments(self, parser): + parser.add_argument( + "--force", action='store_true', dest='force', + help="Force recalculation of all existing cable paths" + ) + parser.add_argument( + "--no-input", action='store_true', dest='no_input', + help="Do not prompt user for any input/confirmation" + ) + + def draw_progress_bar(self, percentage): + """ + Draw a simple progress bar 20 increments wide illustrating the specified percentage. + """ + bar_size = int(percentage / 5) + self.stdout.write(f"\r [{'#' * bar_size}{' ' * (20-bar_size)}] {int(percentage)}%", ending='') + + def handle(self, *model_names, **options): + + # If --force was passed, first delete all existing CablePaths + if options['force']: + cable_paths = CablePath.objects.all() + paths_count = cable_paths.count() + + # Prompt the user to confirm recalculation of all paths + if paths_count and not options['no_input']: + self.stdout.write(self.style.ERROR("WARNING: Forcing recalculation of all cable paths.")) + self.stdout.write( + f"This will delete and recalculate all {paths_count} existing cable paths. Are you sure?" + ) + confirmation = input("Type yes to confirm: ") + if confirmation != 'yes': + self.stdout.write(self.style.SUCCESS("Aborting")) + return + + # Delete all existing CablePath instances + self.stdout.write(f"Deleting {paths_count} existing cable paths...") + deleted_count, _ = CablePath.objects.all().delete() + self.stdout.write((self.style.SUCCESS(f' Deleted {deleted_count} paths'))) + + # Reinitialize the model's PK sequence + self.stdout.write(f'Resetting database sequence for CablePath model') + sequence_sql = connection.ops.sequence_reset_sql(no_style(), [CablePath]) + with connection.cursor() as cursor: + for sql in sequence_sql: + cursor.execute(sql) + + # Retrace paths + for model in ENDPOINT_MODELS: + origins = model.objects.filter(cable__isnull=False) + if not options['force']: + origins = origins.filter(_path__isnull=True) + origins_count = origins.count() + if not origins_count: + self.stdout.write(f'Found no missing {model._meta.verbose_name} paths; skipping') + continue + self.stdout.write(f'Retracing {origins_count} cabled {model._meta.verbose_name_plural}...') + i = 0 + for i, obj in enumerate(origins, start=1): + create_cablepath(obj) + if not i % 100: + self.draw_progress_bar(i * 100 / origins_count) + self.draw_progress_bar(100) + self.stdout.write(self.style.SUCCESS(f'\n Retraced {i} {model._meta.verbose_name_plural}')) + + self.stdout.write(self.style.SUCCESS('Finished.')) diff --git a/netbox/dcim/migrations/0117_custom_field_data.py b/netbox/dcim/migrations/0117_custom_field_data.py new file mode 100644 index 0000000000..36933cc469 --- /dev/null +++ b/netbox/dcim/migrations/0117_custom_field_data.py @@ -0,0 +1,60 @@ +import django.core.serializers.json +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0116_rearport_max_positions'), + ] + + operations = [ + # Original CustomFieldModels + migrations.AddField( + model_name='device', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AddField( + model_name='devicetype', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AddField( + model_name='powerfeed', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AddField( + model_name='rack', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AddField( + model_name='site', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + + # Added under #5146 + migrations.AddField( + model_name='cable', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AddField( + model_name='powerpanel', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AddField( + model_name='rackreservation', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AddField( + model_name='virtualchassis', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + ] diff --git a/netbox/dcim/migrations/0118_inventoryitem_mptt.py b/netbox/dcim/migrations/0118_inventoryitem_mptt.py new file mode 100644 index 0000000000..844e00136e --- /dev/null +++ b/netbox/dcim/migrations/0118_inventoryitem_mptt.py @@ -0,0 +1,44 @@ +from django.db import migrations, models +import django.db.models.deletion +import mptt.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0117_custom_field_data'), + ] + + operations = [ + # The MPTT will be rebuilt in the following migration. Using dummy values for now. + migrations.AddField( + model_name='inventoryitem', + name='level', + field=models.PositiveIntegerField(default=0, editable=False), + preserve_default=False, + ), + migrations.AddField( + model_name='inventoryitem', + name='lft', + field=models.PositiveIntegerField(default=0, editable=False), + preserve_default=False, + ), + migrations.AddField( + model_name='inventoryitem', + name='rght', + field=models.PositiveIntegerField(default=0, editable=False), + preserve_default=False, + ), + migrations.AddField( + model_name='inventoryitem', + name='tree_id', + field=models.PositiveIntegerField(db_index=True, default=0, editable=False), + preserve_default=False, + ), + # Convert ForeignKey to TreeForeignKey + migrations.AlterField( + model_name='inventoryitem', + name='parent', + field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='child_items', to='dcim.inventoryitem'), + ), + ] diff --git a/netbox/dcim/migrations/0119_inventoryitem_mptt_rebuild.py b/netbox/dcim/migrations/0119_inventoryitem_mptt_rebuild.py new file mode 100644 index 0000000000..d3bdb3025f --- /dev/null +++ b/netbox/dcim/migrations/0119_inventoryitem_mptt_rebuild.py @@ -0,0 +1,26 @@ +from django.db import migrations +import mptt +import mptt.managers + + +def rebuild_mptt(apps, schema_editor): + manager = mptt.managers.TreeManager() + InventoryItem = apps.get_model('dcim', 'InventoryItem') + manager.model = InventoryItem + mptt.register(InventoryItem) + manager.contribute_to_class(InventoryItem, 'objects') + manager.rebuild() + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0118_inventoryitem_mptt'), + ] + + operations = [ + migrations.RunPython( + code=rebuild_mptt, + reverse_code=migrations.RunPython.noop + ), + ] diff --git a/netbox/dcim/migrations/0120_cache_cable_peer.py b/netbox/dcim/migrations/0120_cache_cable_peer.py new file mode 100644 index 0000000000..c45d033968 --- /dev/null +++ b/netbox/dcim/migrations/0120_cache_cable_peer.py @@ -0,0 +1,141 @@ +import sys + +from django.db import migrations, models +import django.db.models.deletion + + +def cache_cable_peers(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + Cable = apps.get_model('dcim', 'Cable') + ConsolePort = apps.get_model('dcim', 'ConsolePort') + ConsoleServerPort = apps.get_model('dcim', 'ConsoleServerPort') + PowerPort = apps.get_model('dcim', 'PowerPort') + PowerOutlet = apps.get_model('dcim', 'PowerOutlet') + Interface = apps.get_model('dcim', 'Interface') + FrontPort = apps.get_model('dcim', 'FrontPort') + RearPort = apps.get_model('dcim', 'RearPort') + PowerFeed = apps.get_model('dcim', 'PowerFeed') + + models = ( + ConsolePort, + ConsoleServerPort, + PowerPort, + PowerOutlet, + Interface, + FrontPort, + RearPort, + PowerFeed + ) + + if 'test' not in sys.argv: + print("\n", end="") + + for model in models: + if 'test' not in sys.argv: + print(f" Updating {model._meta.verbose_name} cable peers...", flush=True) + ct = ContentType.objects.get_for_model(model) + for cable in Cable.objects.filter(termination_a_type=ct): + model.objects.filter(pk=cable.termination_a_id).update( + _cable_peer_type_id=cable.termination_b_type_id, + _cable_peer_id=cable.termination_b_id + ) + for cable in Cable.objects.filter(termination_b_type=ct): + model.objects.filter(pk=cable.termination_b_id).update( + _cable_peer_type_id=cable.termination_a_type_id, + _cable_peer_id=cable.termination_a_id + ) + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('dcim', '0119_inventoryitem_mptt_rebuild'), + ] + + operations = [ + migrations.AddField( + model_name='consoleport', + name='_cable_peer_id', + field=models.PositiveIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='consoleport', + name='_cable_peer_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + ), + migrations.AddField( + model_name='consoleserverport', + name='_cable_peer_id', + field=models.PositiveIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='consoleserverport', + name='_cable_peer_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + ), + migrations.AddField( + model_name='frontport', + name='_cable_peer_id', + field=models.PositiveIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='frontport', + name='_cable_peer_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + ), + migrations.AddField( + model_name='interface', + name='_cable_peer_id', + field=models.PositiveIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='interface', + name='_cable_peer_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + ), + migrations.AddField( + model_name='powerfeed', + name='_cable_peer_id', + field=models.PositiveIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='powerfeed', + name='_cable_peer_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + ), + migrations.AddField( + model_name='poweroutlet', + name='_cable_peer_id', + field=models.PositiveIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='poweroutlet', + name='_cable_peer_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + ), + migrations.AddField( + model_name='powerport', + name='_cable_peer_id', + field=models.PositiveIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='powerport', + name='_cable_peer_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + ), + migrations.AddField( + model_name='rearport', + name='_cable_peer_id', + field=models.PositiveIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='rearport', + name='_cable_peer_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='contenttypes.contenttype'), + ), + migrations.RunPython( + code=cache_cable_peers, + reverse_code=migrations.RunPython.noop + ), + ] diff --git a/netbox/dcim/migrations/0121_cablepath.py b/netbox/dcim/migrations/0121_cablepath.py new file mode 100644 index 0000000000..69411415d7 --- /dev/null +++ b/netbox/dcim/migrations/0121_cablepath.py @@ -0,0 +1,108 @@ +import dcim.fields +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('dcim', '0120_cache_cable_peer'), + ] + + operations = [ + migrations.CreateModel( + name='CablePath', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ('origin_id', models.PositiveIntegerField()), + ('destination_id', models.PositiveIntegerField(blank=True, null=True)), + ('path', dcim.fields.PathField(base_field=models.CharField(max_length=40), size=None)), + ('is_active', models.BooleanField(default=False)), + ('is_split', models.BooleanField(default=False)), + ('destination_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype')), + ('origin_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype')), + ], + options={ + 'unique_together': {('origin_type', 'origin_id')}, + }, + ), + migrations.AddField( + model_name='consoleport', + name='_path', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'), + ), + migrations.AddField( + model_name='consoleserverport', + name='_path', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'), + ), + migrations.AddField( + model_name='interface', + name='_path', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'), + ), + migrations.AddField( + model_name='powerfeed', + name='_path', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'), + ), + migrations.AddField( + model_name='poweroutlet', + name='_path', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'), + ), + migrations.AddField( + model_name='powerport', + name='_path', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dcim.cablepath'), + ), + migrations.RemoveField( + model_name='consoleport', + name='connected_endpoint', + ), + migrations.RemoveField( + model_name='consoleport', + name='connection_status', + ), + migrations.RemoveField( + model_name='consoleserverport', + name='connection_status', + ), + migrations.RemoveField( + model_name='interface', + name='_connected_circuittermination', + ), + migrations.RemoveField( + model_name='interface', + name='_connected_interface', + ), + migrations.RemoveField( + model_name='interface', + name='connection_status', + ), + migrations.RemoveField( + model_name='powerfeed', + name='connected_endpoint', + ), + migrations.RemoveField( + model_name='powerfeed', + name='connection_status', + ), + migrations.RemoveField( + model_name='poweroutlet', + name='connection_status', + ), + migrations.RemoveField( + model_name='powerport', + name='_connected_powerfeed', + ), + migrations.RemoveField( + model_name='powerport', + name='_connected_poweroutlet', + ), + migrations.RemoveField( + model_name='powerport', + name='connection_status', + ), + ] diff --git a/netbox/dcim/migrations/0122_standardize_name_length.py b/netbox/dcim/migrations/0122_standardize_name_length.py new file mode 100644 index 0000000000..6c805f2ee6 --- /dev/null +++ b/netbox/dcim/migrations/0122_standardize_name_length.py @@ -0,0 +1,98 @@ +# Generated by Django 3.1 on 2020-10-15 19:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0121_cablepath'), + ] + + operations = [ + migrations.AlterField( + model_name='devicerole', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='devicerole', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='devicetype', + name='model', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='devicetype', + name='slug', + field=models.SlugField(max_length=100), + ), + migrations.AlterField( + model_name='manufacturer', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='manufacturer', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='powerfeed', + name='name', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='powerpanel', + name='name', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='rack', + name='name', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='rackgroup', + name='name', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='rackgroup', + name='slug', + field=models.SlugField(max_length=100), + ), + migrations.AlterField( + model_name='rackrole', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='rackrole', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='region', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='region', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='site', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='site', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + ] diff --git a/netbox/dcim/models/__init__.py b/netbox/dcim/models/__init__.py index e50fa2eda2..513c074388 100644 --- a/netbox/dcim/models/__init__.py +++ b/netbox/dcim/models/__init__.py @@ -1,3 +1,4 @@ +from .cables import * from .device_component_templates import * from .device_components import * from .devices import * @@ -8,6 +9,7 @@ __all__ = ( 'BaseInterface', 'Cable', + 'CablePath', 'CableTermination', 'ConsolePort', 'ConsolePortTemplate', diff --git a/netbox/dcim/models/cables.py b/netbox/dcim/models/cables.py new file mode 100644 index 0000000000..7a9f2dc2c7 --- /dev/null +++ b/netbox/dcim/models/cables.py @@ -0,0 +1,495 @@ +from collections import defaultdict + +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ObjectDoesNotExist, ValidationError +from django.db import models +from django.db.models import Sum +from django.urls import reverse +from taggit.managers import TaggableManager + +from dcim.choices import * +from dcim.constants import * +from dcim.fields import PathField +from dcim.utils import decompile_path_node, object_to_path_node, path_node_to_object +from extras.models import ChangeLoggedModel, CustomFieldModel, TaggedItem +from extras.utils import extras_features +from utilities.fields import ColorField +from utilities.querysets import RestrictedQuerySet +from utilities.utils import to_meters +from .devices import Device +from .device_components import FrontPort, RearPort + + +__all__ = ( + 'Cable', + 'CablePath', +) + + +# +# Cables +# + +@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') +class Cable(ChangeLoggedModel, CustomFieldModel): + """ + A physical connection between two endpoints. + """ + termination_a_type = models.ForeignKey( + to=ContentType, + limit_choices_to=CABLE_TERMINATION_MODELS, + on_delete=models.PROTECT, + related_name='+' + ) + termination_a_id = models.PositiveIntegerField() + termination_a = GenericForeignKey( + ct_field='termination_a_type', + fk_field='termination_a_id' + ) + termination_b_type = models.ForeignKey( + to=ContentType, + limit_choices_to=CABLE_TERMINATION_MODELS, + on_delete=models.PROTECT, + related_name='+' + ) + termination_b_id = models.PositiveIntegerField() + termination_b = GenericForeignKey( + ct_field='termination_b_type', + fk_field='termination_b_id' + ) + type = models.CharField( + max_length=50, + choices=CableTypeChoices, + blank=True + ) + status = models.CharField( + max_length=50, + choices=CableStatusChoices, + default=CableStatusChoices.STATUS_CONNECTED + ) + label = models.CharField( + max_length=100, + blank=True + ) + color = ColorField( + blank=True + ) + length = models.PositiveSmallIntegerField( + blank=True, + null=True + ) + length_unit = models.CharField( + max_length=50, + choices=CableLengthUnitChoices, + blank=True, + ) + # Stores the normalized length (in meters) for database ordering + _abs_length = models.DecimalField( + max_digits=10, + decimal_places=4, + blank=True, + null=True + ) + # Cache the associated device (where applicable) for the A and B terminations. This enables filtering of Cables by + # their associated Devices. + _termination_a_device = models.ForeignKey( + to=Device, + on_delete=models.CASCADE, + related_name='+', + blank=True, + null=True + ) + _termination_b_device = models.ForeignKey( + to=Device, + on_delete=models.CASCADE, + related_name='+', + blank=True, + null=True + ) + tags = TaggableManager(through=TaggedItem) + + objects = RestrictedQuerySet.as_manager() + + csv_headers = [ + 'termination_a_type', 'termination_a_id', 'termination_b_type', 'termination_b_id', 'type', 'status', 'label', + 'color', 'length', 'length_unit', + ] + + class Meta: + ordering = ['pk'] + unique_together = ( + ('termination_a_type', 'termination_a_id'), + ('termination_b_type', 'termination_b_id'), + ) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # A copy of the PK to be used by __str__ in case the object is deleted + self._pk = self.pk + + # Cache the original status so we can check later if it's been changed + self._orig_status = self.status + + @classmethod + def from_db(cls, db, field_names, values): + """ + Cache the original A and B terminations of existing Cable instances for later reference inside clean(). + """ + instance = super().from_db(db, field_names, values) + + instance._orig_termination_a_type_id = instance.termination_a_type_id + instance._orig_termination_a_id = instance.termination_a_id + instance._orig_termination_b_type_id = instance.termination_b_type_id + instance._orig_termination_b_id = instance.termination_b_id + + return instance + + def __str__(self): + return self.label or '#{}'.format(self._pk) + + def get_absolute_url(self): + return reverse('dcim:cable', args=[self.pk]) + + def clean(self): + from circuits.models import CircuitTermination + + super().clean() + + # Validate that termination A exists + if not hasattr(self, 'termination_a_type'): + raise ValidationError('Termination A type has not been specified') + try: + self.termination_a_type.model_class().objects.get(pk=self.termination_a_id) + except ObjectDoesNotExist: + raise ValidationError({ + 'termination_a': 'Invalid ID for type {}'.format(self.termination_a_type) + }) + + # Validate that termination B exists + if not hasattr(self, 'termination_b_type'): + raise ValidationError('Termination B type has not been specified') + try: + self.termination_b_type.model_class().objects.get(pk=self.termination_b_id) + except ObjectDoesNotExist: + raise ValidationError({ + 'termination_b': 'Invalid ID for type {}'.format(self.termination_b_type) + }) + + # If editing an existing Cable instance, check that neither termination has been modified. + if self.pk: + err_msg = 'Cable termination points may not be modified. Delete and recreate the cable instead.' + if ( + self.termination_a_type_id != self._orig_termination_a_type_id or + self.termination_a_id != self._orig_termination_a_id + ): + raise ValidationError({ + 'termination_a': err_msg + }) + if ( + self.termination_b_type_id != self._orig_termination_b_type_id or + self.termination_b_id != self._orig_termination_b_id + ): + raise ValidationError({ + 'termination_b': err_msg + }) + + type_a = self.termination_a_type.model + type_b = self.termination_b_type.model + + # Validate interface types + if type_a == 'interface' and self.termination_a.type in NONCONNECTABLE_IFACE_TYPES: + raise ValidationError({ + 'termination_a_id': 'Cables cannot be terminated to {} interfaces'.format( + self.termination_a.get_type_display() + ) + }) + if type_b == 'interface' and self.termination_b.type in NONCONNECTABLE_IFACE_TYPES: + raise ValidationError({ + 'termination_b_id': 'Cables cannot be terminated to {} interfaces'.format( + self.termination_b.get_type_display() + ) + }) + + # Check that termination types are compatible + if type_b not in COMPATIBLE_TERMINATION_TYPES.get(type_a): + raise ValidationError( + f"Incompatible termination types: {self.termination_a_type} and {self.termination_b_type}" + ) + + # Check that two connected RearPorts have the same number of positions (if both are >1) + if isinstance(self.termination_a, RearPort) and isinstance(self.termination_b, RearPort): + if self.termination_a.positions > 1 and self.termination_b.positions > 1: + if self.termination_a.positions != self.termination_b.positions: + raise ValidationError( + f"{self.termination_a} has {self.termination_a.positions} position(s) but " + f"{self.termination_b} has {self.termination_b.positions}. " + f"Both terminations must have the same number of positions (if greater than one)." + ) + + # A termination point cannot be connected to itself + if self.termination_a == self.termination_b: + raise ValidationError(f"Cannot connect {self.termination_a_type} to itself") + + # A front port cannot be connected to its corresponding rear port + if ( + type_a in ['frontport', 'rearport'] and + type_b in ['frontport', 'rearport'] and + ( + getattr(self.termination_a, 'rear_port', None) == self.termination_b or + getattr(self.termination_b, 'rear_port', None) == self.termination_a + ) + ): + raise ValidationError("A front port cannot be connected to it corresponding rear port") + + # Check for an existing Cable connected to either termination object + if self.termination_a.cable not in (None, self): + raise ValidationError("{} already has a cable attached (#{})".format( + self.termination_a, self.termination_a.cable_id + )) + if self.termination_b.cable not in (None, self): + raise ValidationError("{} already has a cable attached (#{})".format( + self.termination_b, self.termination_b.cable_id + )) + + # Validate length and length_unit + if self.length is not None and not self.length_unit: + raise ValidationError("Must specify a unit when setting a cable length") + elif self.length is None: + self.length_unit = '' + + def save(self, *args, **kwargs): + + # Store the given length (if any) in meters for use in database ordering + if self.length and self.length_unit: + self._abs_length = to_meters(self.length, self.length_unit) + else: + self._abs_length = None + + # Store the parent Device for the A and B terminations (if applicable) to enable filtering + if hasattr(self.termination_a, 'device'): + self._termination_a_device = self.termination_a.device + if hasattr(self.termination_b, 'device'): + self._termination_b_device = self.termination_b.device + + super().save(*args, **kwargs) + + # Update the private pk used in __str__ in case this is a new object (i.e. just got its pk) + self._pk = self.pk + + def to_csv(self): + return ( + '{}.{}'.format(self.termination_a_type.app_label, self.termination_a_type.model), + self.termination_a_id, + '{}.{}'.format(self.termination_b_type.app_label, self.termination_b_type.model), + self.termination_b_id, + self.get_type_display(), + self.get_status_display(), + self.label, + self.color, + self.length, + self.length_unit, + ) + + def get_status_class(self): + return CableStatusChoices.CSS_CLASSES.get(self.status) + + def get_compatible_types(self): + """ + Return all termination types compatible with termination A. + """ + if self.termination_a is None: + return + return COMPATIBLE_TERMINATION_TYPES[self.termination_a._meta.model_name] + + +class CablePath(models.Model): + """ + A CablePath instance represents the physical path from an origin to a destination, including all intermediate + elements in the path. Every instance must specify an `origin`, whereas `destination` may be null (for paths which do + not terminate on a PathEndpoint). + + `path` contains a list of nodes within the path, each represented by a tuple of (type, ID). The first element in the + path must be a Cable instance, followed by a pair of pass-through ports. For example, consider the following + topology: + + 1 2 3 + Interface A --- Front Port A | Rear Port A --- Rear Port B | Front Port B --- Interface B + + This path would be expressed as: + + CablePath( + origin = Interface A + destination = Interface B + path = [Cable 1, Front Port A, Rear Port A, Cable 2, Rear Port B, Front Port B, Cable 3] + ) + + `is_active` is set to True only if 1) `destination` is not null, and 2) every Cable within the path has a status of + "connected". + """ + origin_type = models.ForeignKey( + to=ContentType, + on_delete=models.CASCADE, + related_name='+' + ) + origin_id = models.PositiveIntegerField() + origin = GenericForeignKey( + ct_field='origin_type', + fk_field='origin_id' + ) + destination_type = models.ForeignKey( + to=ContentType, + on_delete=models.CASCADE, + related_name='+', + blank=True, + null=True + ) + destination_id = models.PositiveIntegerField( + blank=True, + null=True + ) + destination = GenericForeignKey( + ct_field='destination_type', + fk_field='destination_id' + ) + path = PathField() + is_active = models.BooleanField( + default=False + ) + is_split = models.BooleanField( + default=False + ) + + class Meta: + unique_together = ('origin_type', 'origin_id') + + def __str__(self): + status = ' (active)' if self.is_active else ' (split)' if self.is_split else '' + return f"Path #{self.pk}: {self.origin} to {self.destination} via {len(self.path)} nodes{status}" + + def save(self, *args, **kwargs): + super().save(*args, **kwargs) + + # Record a direct reference to this CablePath on its originating object + model = self.origin._meta.model + model.objects.filter(pk=self.origin.pk).update(_path=self.pk) + + @property + def segment_count(self): + total_length = 1 + len(self.path) + (1 if self.destination else 0) + return int(total_length / 3) + + @classmethod + def from_origin(cls, origin): + """ + Create a new CablePath instance as traced from the given path origin. + """ + if origin is None or origin.cable is None: + return None + + destination = None + path = [] + position_stack = [] + is_active = True + is_split = False + + node = origin + while node.cable is not None: + if node.cable.status != CableStatusChoices.STATUS_CONNECTED: + is_active = False + + # Follow the cable to its far-end termination + path.append(object_to_path_node(node.cable)) + peer_termination = node.get_cable_peer() + + # Follow a FrontPort to its corresponding RearPort + if isinstance(peer_termination, FrontPort): + path.append(object_to_path_node(peer_termination)) + node = peer_termination.rear_port + if node.positions > 1: + position_stack.append(peer_termination.rear_port_position) + path.append(object_to_path_node(node)) + + # Follow a RearPort to its corresponding FrontPort (if any) + elif isinstance(peer_termination, RearPort): + path.append(object_to_path_node(peer_termination)) + + # Determine the peer FrontPort's position + if peer_termination.positions == 1: + position = 1 + elif position_stack: + position = position_stack.pop() + else: + # No position indicated: path has split, so we stop at the RearPort + is_split = True + break + + try: + node = FrontPort.objects.get(rear_port=peer_termination, rear_port_position=position) + path.append(object_to_path_node(node)) + except ObjectDoesNotExist: + # No corresponding FrontPort found for the RearPort + break + + # Anything else marks the end of the path + else: + destination = peer_termination + break + + if destination is None: + is_active = False + + return cls( + origin=origin, + destination=destination, + path=path, + is_active=is_active, + is_split=is_split + ) + + def get_path(self): + """ + Return the path as a list of prefetched objects. + """ + # Compile a list of IDs to prefetch for each type of model in the path + to_prefetch = defaultdict(list) + for node in self.path: + ct_id, object_id = decompile_path_node(node) + to_prefetch[ct_id].append(object_id) + + # Prefetch path objects using one query per model type. Prefetch related devices where appropriate. + prefetched = {} + for ct_id, object_ids in to_prefetch.items(): + model_class = ContentType.objects.get_for_id(ct_id).model_class() + queryset = model_class.objects.filter(pk__in=object_ids) + if hasattr(model_class, 'device'): + queryset = queryset.prefetch_related('device') + prefetched[ct_id] = { + obj.id: obj for obj in queryset + } + + # Replicate the path using the prefetched objects. + path = [] + for node in self.path: + ct_id, object_id = decompile_path_node(node) + path.append(prefetched[ct_id][object_id]) + + return path + + def get_total_length(self): + """ + Return the sum of the length of each cable in the path. + """ + cable_ids = [ + # Starting from the first element, every third element in the path should be a Cable + decompile_path_node(self.path[i])[1] for i in range(0, len(self.path), 3) + ] + return Cable.objects.filter(id__in=cable_ids).aggregate(total=Sum('_abs_length'))['total'] + + def get_split_nodes(self): + """ + Return all available next segments in a split cable path. + """ + rearport = path_node_to_object(self.path[-1]) + return FrontPort.objects.filter(rear_port=rearport) diff --git a/netbox/dcim/models/device_components.py b/netbox/dcim/models/device_components.py index d596b6ca58..5d5825f5fa 100644 --- a/netbox/dcim/models/device_components.py +++ b/netbox/dcim/models/device_components.py @@ -1,20 +1,20 @@ -import logging - -from django.contrib.contenttypes.fields import GenericRelation +from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation +from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.db.models import Sum from django.urls import reverse +from mptt.models import MPTTModel, TreeForeignKey from taggit.managers import TaggableManager from dcim.choices import * from dcim.constants import * -from dcim.exceptions import CableTraceSplit from dcim.fields import MACAddressField from extras.models import ObjectChange, TaggedItem from extras.utils import extras_features from utilities.fields import NaturalOrderingField +from utilities.mptt import TreeManager from utilities.ordering import naturalize_interface from utilities.querysets import RestrictedQuerySet from utilities.query_functions import CollateAsChar @@ -30,6 +30,7 @@ 'FrontPort', 'Interface', 'InventoryItem', + 'PathEndpoint', 'PowerOutlet', 'PowerPort', 'RearPort', @@ -37,6 +38,9 @@ class ComponentModel(models.Model): + """ + An abstract model inherited by any model which has a parent Device. + """ device = models.ForeignKey( to='dcim.Device', on_delete=models.CASCADE, @@ -91,6 +95,14 @@ def parent(self): class CableTermination(models.Model): + """ + An abstract model inherited by all models to which a Cable can terminate (certain device components, PowerFeed, and + CircuitTermination instances). The `cable` field indicates the Cable instance which is terminated to this instance. + + `_cable_peer` is a GenericForeignKey used to cache the far-end CableTermination on the local instance; this is a + shortcut to referencing `cable.termination_b`, for example. `_cable_peer` is set or cleared by the receivers in + dcim.signals when a Cable instance is created or deleted, respectively. + """ cable = models.ForeignKey( to='dcim.Cable', on_delete=models.SET_NULL, @@ -98,6 +110,21 @@ class CableTermination(models.Model): blank=True, null=True ) + _cable_peer_type = models.ForeignKey( + to=ContentType, + on_delete=models.SET_NULL, + related_name='+', + blank=True, + null=True + ) + _cable_peer_id = models.PositiveIntegerField( + blank=True, + null=True + ) + _cable_peer = GenericForeignKey( + ct_field='_cable_peer_type', + fk_field='_cable_peer_id' + ) # Generic relations to Cable. These ensure that an attached Cable is deleted if the terminated object is deleted. _cabled_as_a = GenericRelation( @@ -111,141 +138,60 @@ class CableTermination(models.Model): object_id_field='termination_b_id' ) + class Meta: + abstract = True + + def get_cable_peer(self): + return self._cable_peer + + +class PathEndpoint(models.Model): + """ + An abstract model inherited by any CableTermination subclass which represents the end of a CablePath; specifically, + these include ConsolePort, ConsoleServerPort, PowerPort, PowerOutlet, Interface, PowerFeed, and CircuitTermination. + + `_path` references the CablePath originating from this instance, if any. It is set or cleared by the receivers in + dcim.signals in response to changes in the cable path, and complements the `origin` GenericForeignKey field on the + CablePath model. `_path` should not be accessed directly; rather, use the `path` property. + + `connected_endpoint()` is a convenience method for returning the destination of the associated CablePath, if any. + """ + _path = models.ForeignKey( + to='dcim.CablePath', + on_delete=models.SET_NULL, + null=True, + blank=True + ) + class Meta: abstract = True def trace(self): - """ - Return three items: the traceable portion of a cable path, the termination points where it splits (if any), and - the remaining positions on the position stack (if any). Splits occur when the trace is initiated from a midpoint - along a path which traverses a RearPort. In cases where the originating endpoint is unknown, it is not possible - to know which corresponding FrontPort to follow. Remaining positions occur when tracing a path that traverses - a FrontPort without traversing a RearPort again. - - The path is a list representing a complete cable path, with each individual segment represented as a - three-tuple: - - [ - (termination A, cable, termination B), - (termination C, cable, termination D), - (termination E, cable, termination F) - ] - """ - endpoint = self - path = [] - position_stack = [] - - def get_peer_port(termination): - from circuits.models import CircuitTermination - - # Map a front port to its corresponding rear port - if isinstance(termination, FrontPort): - # Retrieve the corresponding RearPort from database to ensure we have an up-to-date instance - peer_port = RearPort.objects.get(pk=termination.rear_port.pk) - - # Don't use the stack for RearPorts with a single position. Only remember the position at - # many-to-one points so we can select the correct FrontPort when we reach the corresponding - # one-to-many point. - if peer_port.positions > 1: - position_stack.append(termination) - - return peer_port - - # Map a rear port/position to its corresponding front port - elif isinstance(termination, RearPort): - if termination.positions > 1: - # Can't map to a FrontPort without a position if there are multiple options - if not position_stack: - raise CableTraceSplit(termination) - - front_port = position_stack.pop() - position = front_port.rear_port_position - - # Validate the position - if position not in range(1, termination.positions + 1): - raise Exception("Invalid position for {} ({} positions): {})".format( - termination, termination.positions, position - )) - else: - # Don't use the stack for RearPorts with a single position. The only possible position is 1. - position = 1 - - try: - peer_port = FrontPort.objects.get( - rear_port=termination, - rear_port_position=position, - ) - return peer_port - except ObjectDoesNotExist: - return None - - # Follow a circuit to its other termination - elif isinstance(termination, CircuitTermination): - peer_termination = termination.get_peer_termination() - if peer_termination is None: - return None - return peer_termination - - # Termination is not a pass-through port - else: - return None - - logger = logging.getLogger('netbox.dcim.cable.trace') - logger.debug("Tracing cable from {} {}".format(self.parent, self)) - - while endpoint is not None: - - # No cable connected; nothing to trace - if not endpoint.cable: - path.append((endpoint, None, None)) - logger.debug("No cable connected") - return path, None, position_stack - - # Check for loops - if endpoint.cable in [segment[1] for segment in path]: - logger.debug("Loop detected!") - return path, None, position_stack - - # Record the current segment in the path - far_end = endpoint.get_cable_peer() - path.append((endpoint, endpoint.cable, far_end)) - logger.debug("{}[{}] --- Cable {} ---> {}[{}]".format( - endpoint.parent, endpoint, endpoint.cable.pk, far_end.parent, far_end - )) + if self._path is None: + return [] - # Get the peer port of the far end termination - try: - endpoint = get_peer_port(far_end) - except CableTraceSplit as e: - return path, e.termination.frontports.all(), position_stack + # Construct the complete path + path = [self, *self._path.get_path()] + while (len(path) + 1) % 3: + # Pad to ensure we have complete three-tuples (e.g. for paths that end at a RearPort) + path.append(None) + path.append(self._path.destination) - if endpoint is None: - return path, None, position_stack + # Return the path as a list of three-tuples (A termination, cable, B termination) + return list(zip(*[iter(path)] * 3)) - def get_cable_peer(self): - if self.cable is None: - return None - if self._cabled_as_a.exists(): - return self.cable.termination_b - if self._cabled_as_b.exists(): - return self.cable.termination_a - - def get_path_endpoints(self): + @property + def path(self): + return self._path + + @property + def connected_endpoint(self): """ - Return all endpoints of paths which traverse this object. + Caching accessor for the attached CablePath's destination (if any) """ - endpoints = [] - - # Get the far end of the last path segment - path, split_ends, position_stack = self.trace() - endpoint = path[-1][2] - if split_ends is not None: - for termination in split_ends: - endpoints.extend(termination.get_path_endpoints()) - elif endpoint is not None: - endpoints.append(endpoint) - - return endpoints + if not hasattr(self, '_connected_endpoint'): + self._connected_endpoint = self._path.destination if self._path else None + return self._connected_endpoint # @@ -253,7 +199,7 @@ def get_path_endpoints(self): # @extras_features('export_templates', 'webhooks') -class ConsolePort(CableTermination, ComponentModel): +class ConsolePort(CableTermination, PathEndpoint, ComponentModel): """ A physical console port within a Device. ConsolePorts connect to ConsoleServerPorts. """ @@ -263,18 +209,6 @@ class ConsolePort(CableTermination, ComponentModel): blank=True, help_text='Physical port type' ) - connected_endpoint = models.OneToOneField( - to='dcim.ConsoleServerPort', - on_delete=models.SET_NULL, - related_name='connected_endpoint', - blank=True, - null=True - ) - connection_status = models.BooleanField( - choices=CONNECTION_STATUS_CHOICES, - blank=True, - null=True - ) tags = TaggableManager(through=TaggedItem) csv_headers = ['device', 'name', 'label', 'type', 'description'] @@ -301,7 +235,7 @@ def to_csv(self): # @extras_features('webhooks') -class ConsoleServerPort(CableTermination, ComponentModel): +class ConsoleServerPort(CableTermination, PathEndpoint, ComponentModel): """ A physical port within a Device (typically a designated console server) which provides access to ConsolePorts. """ @@ -311,11 +245,6 @@ class ConsoleServerPort(CableTermination, ComponentModel): blank=True, help_text='Physical port type' ) - connection_status = models.BooleanField( - choices=CONNECTION_STATUS_CHOICES, - blank=True, - null=True - ) tags = TaggableManager(through=TaggedItem) csv_headers = ['device', 'name', 'label', 'type', 'description'] @@ -342,7 +271,7 @@ def to_csv(self): # @extras_features('export_templates', 'webhooks') -class PowerPort(CableTermination, ComponentModel): +class PowerPort(CableTermination, PathEndpoint, ComponentModel): """ A physical power supply (intake) port within a Device. PowerPorts connect to PowerOutlets. """ @@ -364,25 +293,6 @@ class PowerPort(CableTermination, ComponentModel): validators=[MinValueValidator(1)], help_text="Allocated power draw (watts)" ) - _connected_poweroutlet = models.OneToOneField( - to='dcim.PowerOutlet', - on_delete=models.SET_NULL, - related_name='connected_endpoint', - blank=True, - null=True - ) - _connected_powerfeed = models.OneToOneField( - to='dcim.PowerFeed', - on_delete=models.SET_NULL, - related_name='+', - blank=True, - null=True - ) - connection_status = models.BooleanField( - choices=CONNECTION_STATUS_CHOICES, - blank=True, - null=True - ) tags = TaggableManager(through=TaggedItem) csv_headers = ['device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description'] @@ -413,51 +323,18 @@ def clean(self): 'allocated_draw': f"Allocated draw cannot exceed the maximum draw ({self.maximum_draw}W)." }) - @property - def connected_endpoint(self): - """ - Return the connected PowerOutlet, if it exists, or the connected PowerFeed, if it exists. We have to check for - ObjectDoesNotExist in case the referenced object has been deleted from the database. - """ - try: - if self._connected_poweroutlet: - return self._connected_poweroutlet - except ObjectDoesNotExist: - pass - try: - if self._connected_powerfeed: - return self._connected_powerfeed - except ObjectDoesNotExist: - pass - return None - - @connected_endpoint.setter - def connected_endpoint(self, value): - # TODO: Fix circular import - from . import PowerFeed - - if value is None: - self._connected_poweroutlet = None - self._connected_powerfeed = None - elif isinstance(value, PowerOutlet): - self._connected_poweroutlet = value - self._connected_powerfeed = None - elif isinstance(value, PowerFeed): - self._connected_poweroutlet = None - self._connected_powerfeed = value - else: - raise ValueError( - "Connected endpoint must be a PowerOutlet or PowerFeed, not {}.".format(type(value)) - ) - def get_power_draw(self): """ Return the allocated and maximum power draw (in VA) and child PowerOutlet count for this PowerPort. """ # Calculate aggregate draw of all child power outlets if no numbers have been defined manually if self.allocated_draw is None and self.maximum_draw is None: + poweroutlet_ct = ContentType.objects.get_for_model(PowerOutlet) outlet_ids = PowerOutlet.objects.filter(power_port=self).values_list('pk', flat=True) - utilization = PowerPort.objects.filter(_connected_poweroutlet_id__in=outlet_ids).aggregate( + utilization = PowerPort.objects.filter( + _cable_peer_type=poweroutlet_ct, + _cable_peer_id__in=outlet_ids + ).aggregate( maximum_draw_total=Sum('maximum_draw'), allocated_draw_total=Sum('allocated_draw'), ) @@ -469,10 +346,13 @@ def get_power_draw(self): } # Calculate per-leg aggregates for three-phase feeds - if self._connected_powerfeed and self._connected_powerfeed.phase == PowerFeedPhaseChoices.PHASE_3PHASE: + if getattr(self._cable_peer, 'phase', None) == PowerFeedPhaseChoices.PHASE_3PHASE: for leg, leg_name in PowerOutletFeedLegChoices: outlet_ids = PowerOutlet.objects.filter(power_port=self, feed_leg=leg).values_list('pk', flat=True) - utilization = PowerPort.objects.filter(_connected_poweroutlet_id__in=outlet_ids).aggregate( + utilization = PowerPort.objects.filter( + _cable_peer_type=poweroutlet_ct, + _cable_peer_id__in=outlet_ids + ).aggregate( maximum_draw_total=Sum('maximum_draw'), allocated_draw_total=Sum('allocated_draw'), ) @@ -499,7 +379,7 @@ def get_power_draw(self): # @extras_features('webhooks') -class PowerOutlet(CableTermination, ComponentModel): +class PowerOutlet(CableTermination, PathEndpoint, ComponentModel): """ A physical power outlet (output) within a Device which provides power to a PowerPort. """ @@ -522,11 +402,6 @@ class PowerOutlet(CableTermination, ComponentModel): blank=True, help_text="Phase (for three-phase feeds)" ) - connection_status = models.BooleanField( - choices=CONNECTION_STATUS_CHOICES, - blank=True, - null=True - ) tags = TaggableManager(through=TaggedItem) csv_headers = ['device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description'] @@ -602,8 +477,8 @@ def save(self, *args, **kwargs): return super().save(*args, **kwargs) -@extras_features('graphs', 'export_templates', 'webhooks') -class Interface(CableTermination, ComponentModel, BaseInterface): +@extras_features('export_templates', 'webhooks') +class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface): """ A network interface within a Device. A physical Interface can connect to exactly one other Interface. """ @@ -614,25 +489,6 @@ class Interface(CableTermination, ComponentModel, BaseInterface): max_length=100, blank=True ) - _connected_interface = models.OneToOneField( - to='self', - on_delete=models.SET_NULL, - related_name='+', - blank=True, - null=True - ) - _connected_circuittermination = models.OneToOneField( - to='circuits.CircuitTermination', - on_delete=models.SET_NULL, - related_name='+', - blank=True, - null=True - ) - connection_status = models.BooleanField( - choices=CONNECTION_STATUS_CHOICES, - blank=True, - null=True - ) lag = models.ForeignKey( to='self', on_delete=models.SET_NULL, @@ -736,42 +592,6 @@ def clean(self): "device, or it must be global".format(self.untagged_vlan) }) - @property - def connected_endpoint(self): - """ - Return the connected Interface, if it exists, or the connected CircuitTermination, if it exists. We have to - check for ObjectDoesNotExist in case the referenced object has been deleted from the database. - """ - try: - if self._connected_interface: - return self._connected_interface - except ObjectDoesNotExist: - pass - try: - if self._connected_circuittermination: - return self._connected_circuittermination - except ObjectDoesNotExist: - pass - return None - - @connected_endpoint.setter - def connected_endpoint(self, value): - from circuits.models import CircuitTermination - - if value is None: - self._connected_interface = None - self._connected_circuittermination = None - elif isinstance(value, Interface): - self._connected_interface = value - self._connected_circuittermination = None - elif isinstance(value, CircuitTermination): - self._connected_interface = None - self._connected_circuittermination = value - else: - raise ValueError( - "Connected endpoint must be an Interface or CircuitTermination, not {}.".format(type(value)) - ) - @property def parent(self): return self.device @@ -975,17 +795,18 @@ def clean(self): # @extras_features('export_templates', 'webhooks') -class InventoryItem(ComponentModel): +class InventoryItem(MPTTModel, ComponentModel): """ An InventoryItem represents a serialized piece of hardware within a Device, such as a line card or power supply. InventoryItems are used only for inventory purposes. """ - parent = models.ForeignKey( + parent = TreeForeignKey( to='self', on_delete=models.CASCADE, related_name='child_items', blank=True, - null=True + null=True, + db_index=True ) manufacturer = models.ForeignKey( to='dcim.Manufacturer', @@ -1020,6 +841,8 @@ class InventoryItem(ComponentModel): tags = TaggableManager(through=TaggedItem) + objects = TreeManager() + csv_headers = [ 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'discovered', 'description', ] diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index 6fe2cea2f8..5b685057eb 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -2,9 +2,8 @@ import yaml from django.conf import settings -from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation -from django.contrib.contenttypes.models import ContentType -from django.core.exceptions import ObjectDoesNotExist, ValidationError +from django.contrib.contenttypes.fields import GenericRelation +from django.core.exceptions import ValidationError from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.db.models import F, ProtectedError @@ -20,12 +19,10 @@ from utilities.choices import ColorChoices from utilities.fields import ColorField, NaturalOrderingField from utilities.querysets import RestrictedQuerySet -from utilities.utils import to_meters from .device_components import * __all__ = ( - 'Cable', 'Device', 'DeviceRole', 'DeviceType', @@ -45,10 +42,11 @@ class Manufacturer(ChangeLoggedModel): A Manufacturer represents a company which produces hardware devices; for example, Juniper or Dell. """ name = models.CharField( - max_length=50, + max_length=100, unique=True ) slug = models.SlugField( + max_length=100, unique=True ) description = models.CharField( @@ -99,9 +97,11 @@ class DeviceType(ChangeLoggedModel, CustomFieldModel): related_name='device_types' ) model = models.CharField( - max_length=50 + max_length=100 + ) + slug = models.SlugField( + max_length=100 ) - slug = models.SlugField() part_number = models.CharField( max_length=50, blank=True, @@ -135,11 +135,6 @@ class DeviceType(ChangeLoggedModel, CustomFieldModel): comments = models.TextField( blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) tags = TaggableManager(through=TaggedItem) objects = RestrictedQuerySet.as_manager() @@ -259,6 +254,7 @@ def to_yaml(self): return yaml.dump(dict(data), sort_keys=False) def clean(self): + super().clean() # If editing an existing DeviceType to have a larger u_height, first validate that *all* instances of it have # room to expand within their racks. This validation will impose a very high performance penalty when there are @@ -349,10 +345,11 @@ class DeviceRole(ChangeLoggedModel): virtual machines as well. """ name = models.CharField( - max_length=50, + max_length=100, unique=True ) slug = models.SlugField( + max_length=100, unique=True ) color = ColorField( @@ -399,8 +396,8 @@ class Platform(ChangeLoggedModel): unique=True ) slug = models.SlugField( - unique=True, - max_length=100 + max_length=100, + unique=True ) manufacturer = models.ForeignKey( to='dcim.Manufacturer', @@ -451,7 +448,7 @@ def to_csv(self): ) -@extras_features('custom_fields', 'custom_links', 'graphs', 'export_templates', 'webhooks') +@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel): """ A Device represents a piece of physical hardware mounted within a Rack. Each Device is assigned a DeviceType, @@ -585,14 +582,15 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel): comments = models.TextField( blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) images = GenericRelation( to='extras.ImageAttachment' ) + secrets = GenericRelation( + to='secrets.Secret', + content_type_field='assigned_object_type', + object_id_field='assigned_object_id', + related_query_name='device' + ) tags = TaggableManager(through=TaggedItem) objects = ConfigContextModelQuerySet.as_manager() @@ -605,16 +603,6 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel): 'device_type', 'device_role', 'tenant', 'platform', 'site', 'rack', 'status', 'cluster', ] - STATUS_CLASS_MAP = { - DeviceStatusChoices.STATUS_OFFLINE: 'warning', - DeviceStatusChoices.STATUS_ACTIVE: 'success', - DeviceStatusChoices.STATUS_PLANNED: 'info', - DeviceStatusChoices.STATUS_STAGED: 'primary', - DeviceStatusChoices.STATUS_FAILED: 'danger', - DeviceStatusChoices.STATUS_INVENTORY: 'default', - DeviceStatusChoices.STATUS_DECOMMISSIONING: 'warning', - } - class Meta: ordering = ('_name', 'pk') # Name may be null unique_together = ( @@ -647,7 +635,6 @@ def validate_unique(self, exclude=None): super().validate_unique(exclude) def clean(self): - super().clean() # Validate site/rack combination @@ -868,6 +855,7 @@ def get_cables(self, pk_list=False): """ Return a QuerySet or PK list matching all Cables connected to a component of this Device. """ + from .cables import Cable cable_pks = [] for component_model in [ ConsolePort, ConsoleServerPort, PowerPort, PowerOutlet, Interface, FrontPort, RearPort @@ -886,301 +874,15 @@ def get_children(self): return Device.objects.filter(parent_bay__device=self.pk) def get_status_class(self): - return self.STATUS_CLASS_MAP.get(self.status) - - -# -# Cables -# - -@extras_features('custom_links', 'export_templates', 'webhooks') -class Cable(ChangeLoggedModel): - """ - A physical connection between two endpoints. - """ - termination_a_type = models.ForeignKey( - to=ContentType, - limit_choices_to=CABLE_TERMINATION_MODELS, - on_delete=models.PROTECT, - related_name='+' - ) - termination_a_id = models.PositiveIntegerField() - termination_a = GenericForeignKey( - ct_field='termination_a_type', - fk_field='termination_a_id' - ) - termination_b_type = models.ForeignKey( - to=ContentType, - limit_choices_to=CABLE_TERMINATION_MODELS, - on_delete=models.PROTECT, - related_name='+' - ) - termination_b_id = models.PositiveIntegerField() - termination_b = GenericForeignKey( - ct_field='termination_b_type', - fk_field='termination_b_id' - ) - type = models.CharField( - max_length=50, - choices=CableTypeChoices, - blank=True - ) - status = models.CharField( - max_length=50, - choices=CableStatusChoices, - default=CableStatusChoices.STATUS_CONNECTED - ) - label = models.CharField( - max_length=100, - blank=True - ) - color = ColorField( - blank=True - ) - length = models.PositiveSmallIntegerField( - blank=True, - null=True - ) - length_unit = models.CharField( - max_length=50, - choices=CableLengthUnitChoices, - blank=True, - ) - # Stores the normalized length (in meters) for database ordering - _abs_length = models.DecimalField( - max_digits=10, - decimal_places=4, - blank=True, - null=True - ) - # Cache the associated device (where applicable) for the A and B terminations. This enables filtering of Cables by - # their associated Devices. - _termination_a_device = models.ForeignKey( - to=Device, - on_delete=models.CASCADE, - related_name='+', - blank=True, - null=True - ) - _termination_b_device = models.ForeignKey( - to=Device, - on_delete=models.CASCADE, - related_name='+', - blank=True, - null=True - ) - tags = TaggableManager(through=TaggedItem) - - objects = RestrictedQuerySet.as_manager() - - csv_headers = [ - 'termination_a_type', 'termination_a_id', 'termination_b_type', 'termination_b_id', 'type', 'status', 'label', - 'color', 'length', 'length_unit', - ] - - STATUS_CLASS_MAP = { - CableStatusChoices.STATUS_CONNECTED: 'success', - CableStatusChoices.STATUS_PLANNED: 'info', - CableStatusChoices.STATUS_DECOMMISSIONING: 'warning', - } - - class Meta: - ordering = ['pk'] - unique_together = ( - ('termination_a_type', 'termination_a_id'), - ('termination_b_type', 'termination_b_id'), - ) - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # A copy of the PK to be used by __str__ in case the object is deleted - self._pk = self.pk - - @classmethod - def from_db(cls, db, field_names, values): - """ - Cache the original A and B terminations of existing Cable instances for later reference inside clean(). - """ - instance = super().from_db(db, field_names, values) - - instance._orig_termination_a_type_id = instance.termination_a_type_id - instance._orig_termination_a_id = instance.termination_a_id - instance._orig_termination_b_type_id = instance.termination_b_type_id - instance._orig_termination_b_id = instance.termination_b_id - - return instance - - def __str__(self): - return self.label or '#{}'.format(self._pk) - - def get_absolute_url(self): - return reverse('dcim:cable', args=[self.pk]) - - def clean(self): - from circuits.models import CircuitTermination - - # Validate that termination A exists - if not hasattr(self, 'termination_a_type'): - raise ValidationError('Termination A type has not been specified') - try: - self.termination_a_type.model_class().objects.get(pk=self.termination_a_id) - except ObjectDoesNotExist: - raise ValidationError({ - 'termination_a': 'Invalid ID for type {}'.format(self.termination_a_type) - }) - - # Validate that termination B exists - if not hasattr(self, 'termination_b_type'): - raise ValidationError('Termination B type has not been specified') - try: - self.termination_b_type.model_class().objects.get(pk=self.termination_b_id) - except ObjectDoesNotExist: - raise ValidationError({ - 'termination_b': 'Invalid ID for type {}'.format(self.termination_b_type) - }) - - # If editing an existing Cable instance, check that neither termination has been modified. - if self.pk: - err_msg = 'Cable termination points may not be modified. Delete and recreate the cable instead.' - if ( - self.termination_a_type_id != self._orig_termination_a_type_id or - self.termination_a_id != self._orig_termination_a_id - ): - raise ValidationError({ - 'termination_a': err_msg - }) - if ( - self.termination_b_type_id != self._orig_termination_b_type_id or - self.termination_b_id != self._orig_termination_b_id - ): - raise ValidationError({ - 'termination_b': err_msg - }) - - type_a = self.termination_a_type.model - type_b = self.termination_b_type.model - - # Validate interface types - if type_a == 'interface' and self.termination_a.type in NONCONNECTABLE_IFACE_TYPES: - raise ValidationError({ - 'termination_a_id': 'Cables cannot be terminated to {} interfaces'.format( - self.termination_a.get_type_display() - ) - }) - if type_b == 'interface' and self.termination_b.type in NONCONNECTABLE_IFACE_TYPES: - raise ValidationError({ - 'termination_b_id': 'Cables cannot be terminated to {} interfaces'.format( - self.termination_b.get_type_display() - ) - }) - - # Check that termination types are compatible - if type_b not in COMPATIBLE_TERMINATION_TYPES.get(type_a): - raise ValidationError( - f"Incompatible termination types: {self.termination_a_type} and {self.termination_b_type}" - ) - - # Check that a RearPort with multiple positions isn't connected to an endpoint - # or a RearPort with a different number of positions. - for term_a, term_b in [ - (self.termination_a, self.termination_b), - (self.termination_b, self.termination_a) - ]: - if isinstance(term_a, RearPort) and term_a.positions > 1: - if not isinstance(term_b, (FrontPort, RearPort, CircuitTermination)): - raise ValidationError( - "Rear ports with multiple positions may only be connected to other pass-through ports" - ) - if isinstance(term_b, RearPort) and term_b.positions > 1 and term_a.positions != term_b.positions: - raise ValidationError( - f"{term_a} of {term_a.device} has {term_a.positions} position(s) but " - f"{term_b} of {term_b.device} has {term_b.positions}. " - f"Both terminations must have the same number of positions." - ) - - # A termination point cannot be connected to itself - if self.termination_a == self.termination_b: - raise ValidationError(f"Cannot connect {self.termination_a_type} to itself") - - # A front port cannot be connected to its corresponding rear port - if ( - type_a in ['frontport', 'rearport'] and - type_b in ['frontport', 'rearport'] and - ( - getattr(self.termination_a, 'rear_port', None) == self.termination_b or - getattr(self.termination_b, 'rear_port', None) == self.termination_a - ) - ): - raise ValidationError("A front port cannot be connected to it corresponding rear port") - - # Check for an existing Cable connected to either termination object - if self.termination_a.cable not in (None, self): - raise ValidationError("{} already has a cable attached (#{})".format( - self.termination_a, self.termination_a.cable_id - )) - if self.termination_b.cable not in (None, self): - raise ValidationError("{} already has a cable attached (#{})".format( - self.termination_b, self.termination_b.cable_id - )) - - # Validate length and length_unit - if self.length is not None and not self.length_unit: - raise ValidationError("Must specify a unit when setting a cable length") - elif self.length is None: - self.length_unit = '' - - def save(self, *args, **kwargs): - - # Store the given length (if any) in meters for use in database ordering - if self.length and self.length_unit: - self._abs_length = to_meters(self.length, self.length_unit) - else: - self._abs_length = None - - # Store the parent Device for the A and B terminations (if applicable) to enable filtering - if hasattr(self.termination_a, 'device'): - self._termination_a_device = self.termination_a.device - if hasattr(self.termination_b, 'device'): - self._termination_b_device = self.termination_b.device - - super().save(*args, **kwargs) - - # Update the private pk used in __str__ in case this is a new object (i.e. just got its pk) - self._pk = self.pk - - def to_csv(self): - return ( - '{}.{}'.format(self.termination_a_type.app_label, self.termination_a_type.model), - self.termination_a_id, - '{}.{}'.format(self.termination_b_type.app_label, self.termination_b_type.model), - self.termination_b_id, - self.get_type_display(), - self.get_status_display(), - self.label, - self.color, - self.length, - self.length_unit, - ) - - def get_status_class(self): - return self.STATUS_CLASS_MAP.get(self.status) - - def get_compatible_types(self): - """ - Return all termination types compatible with termination A. - """ - if self.termination_a is None: - return - return COMPATIBLE_TERMINATION_TYPES[self.termination_a._meta.model_name] + return DeviceStatusChoices.CSS_CLASSES.get(self.status) # # Virtual chassis # -@extras_features('custom_links', 'export_templates', 'webhooks') -class VirtualChassis(ChangeLoggedModel): +@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') +class VirtualChassis(ChangeLoggedModel, CustomFieldModel): """ A collection of Devices which operate with a shared control plane (e.g. a switch stack). """ @@ -1215,6 +917,7 @@ def get_absolute_url(self): return reverse('dcim:virtualchassis', kwargs={'pk': self.pk}) def clean(self): + super().clean() # Verify that the selected master device has been assigned to this VirtualChassis. (Skip when creating a new # VirtualChassis.) diff --git a/netbox/dcim/models/power.py b/netbox/dcim/models/power.py index f760fea132..1215ced4cc 100644 --- a/netbox/dcim/models/power.py +++ b/netbox/dcim/models/power.py @@ -1,4 +1,3 @@ -from django.contrib.contenttypes.fields import GenericRelation from django.core.exceptions import ValidationError from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models @@ -11,7 +10,7 @@ from extras.utils import extras_features from utilities.querysets import RestrictedQuerySet from utilities.validators import ExclusionValidator -from .device_components import CableTermination +from .device_components import CableTermination, PathEndpoint __all__ = ( 'PowerFeed', @@ -23,8 +22,8 @@ # Power # -@extras_features('custom_links', 'export_templates', 'webhooks') -class PowerPanel(ChangeLoggedModel): +@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') +class PowerPanel(ChangeLoggedModel, CustomFieldModel): """ A distribution point for electrical power; e.g. a data center RPP. """ @@ -39,7 +38,7 @@ class PowerPanel(ChangeLoggedModel): null=True ) name = models.CharField( - max_length=50 + max_length=100 ) tags = TaggableManager(through=TaggedItem) @@ -65,6 +64,7 @@ def to_csv(self): ) def clean(self): + super().clean() # RackGroup must belong to assigned Site if self.rack_group and self.rack_group.site != self.site: @@ -74,7 +74,7 @@ def clean(self): @extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') -class PowerFeed(ChangeLoggedModel, CableTermination, CustomFieldModel): +class PowerFeed(ChangeLoggedModel, PathEndpoint, CableTermination, CustomFieldModel): """ An electrical circuit delivered from a PowerPanel. """ @@ -89,20 +89,8 @@ class PowerFeed(ChangeLoggedModel, CableTermination, CustomFieldModel): blank=True, null=True ) - connected_endpoint = models.OneToOneField( - to='dcim.PowerPort', - on_delete=models.SET_NULL, - related_name='+', - blank=True, - null=True - ) - connection_status = models.BooleanField( - choices=CONNECTION_STATUS_CHOICES, - blank=True, - null=True - ) name = models.CharField( - max_length=50 + max_length=100 ) status = models.CharField( max_length=50, @@ -144,11 +132,6 @@ class PowerFeed(ChangeLoggedModel, CableTermination, CustomFieldModel): comments = models.TextField( blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) tags = TaggableManager(through=TaggedItem) objects = RestrictedQuerySet.as_manager() @@ -162,18 +145,6 @@ class PowerFeed(ChangeLoggedModel, CableTermination, CustomFieldModel): 'available_power', ] - STATUS_CLASS_MAP = { - PowerFeedStatusChoices.STATUS_OFFLINE: 'warning', - PowerFeedStatusChoices.STATUS_ACTIVE: 'success', - PowerFeedStatusChoices.STATUS_PLANNED: 'info', - PowerFeedStatusChoices.STATUS_FAILED: 'danger', - } - - TYPE_CLASS_MAP = { - PowerFeedTypeChoices.TYPE_PRIMARY: 'success', - PowerFeedTypeChoices.TYPE_REDUNDANT: 'info', - } - class Meta: ordering = ['power_panel', 'name'] unique_together = ['power_panel', 'name'] @@ -202,6 +173,7 @@ def to_csv(self): ) def clean(self): + super().clean() # Rack must belong to same Site as PowerPanel if self.rack and self.rack.site != self.power_panel.site: @@ -231,7 +203,7 @@ def parent(self): return self.power_panel def get_type_class(self): - return self.TYPE_CLASS_MAP.get(self.type) + return PowerFeedTypeChoices.CSS_CLASSES.get(self.type) def get_status_class(self): - return self.STATUS_CLASS_MAP.get(self.status) + return PowerFeedStatusChoices.CSS_CLASSES.get(self.status) diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py index 6c5ab08b99..cad20241b0 100644 --- a/netbox/dcim/models/racks.py +++ b/netbox/dcim/models/racks.py @@ -1,9 +1,9 @@ from collections import OrderedDict -from itertools import count, groupby from django.conf import settings from django.contrib.auth.models import User from django.contrib.contenttypes.fields import GenericRelation +from django.contrib.contenttypes.models import ContentType from django.contrib.postgres.fields import ArrayField from django.core.exceptions import ValidationError from django.core.validators import MaxValueValidator, MinValueValidator @@ -22,7 +22,8 @@ from utilities.fields import ColorField, NaturalOrderingField from utilities.querysets import RestrictedQuerySet from utilities.mptt import TreeManager -from utilities.utils import serialize_object +from utilities.utils import array_to_string, serialize_object +from .device_components import PowerOutlet, PowerPort from .devices import Device from .power import PowerFeed @@ -46,9 +47,11 @@ class RackGroup(MPTTModel, ChangeLoggedModel): campus. If a Site instead represents a single building, a RackGroup might represent a single room or floor. """ name = models.CharField( - max_length=50 + max_length=100 + ) + slug = models.SlugField( + max_length=100 ) - slug = models.SlugField() site = models.ForeignKey( to='dcim.Site', on_delete=models.CASCADE, @@ -117,10 +120,11 @@ class RackRole(ChangeLoggedModel): Racks can be organized by functional role, similar to Devices. """ name = models.CharField( - max_length=50, + max_length=100, unique=True ) slug = models.SlugField( + max_length=100, unique=True ) color = ColorField( @@ -160,7 +164,7 @@ class Rack(ChangeLoggedModel, CustomFieldModel): Each Rack is assigned to a Site and (optionally) a RackGroup. """ name = models.CharField( - max_length=50 + max_length=100 ) _name = NaturalOrderingField( target_field='name', @@ -261,11 +265,6 @@ class Rack(ChangeLoggedModel, CustomFieldModel): comments = models.TextField( blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) images = GenericRelation( to='extras.ImageAttachment' ) @@ -282,14 +281,6 @@ class Rack(ChangeLoggedModel, CustomFieldModel): 'outer_depth', 'outer_unit', ] - STATUS_CLASS_MAP = { - RackStatusChoices.STATUS_RESERVED: 'warning', - RackStatusChoices.STATUS_AVAILABLE: 'success', - RackStatusChoices.STATUS_PLANNED: 'info', - RackStatusChoices.STATUS_ACTIVE: 'primary', - RackStatusChoices.STATUS_DEPRECATED: 'danger', - } - class Meta: ordering = ('site', 'group', '_name', 'pk') # (site, group, name) may be non-unique unique_together = ( @@ -305,6 +296,7 @@ def get_absolute_url(self): return reverse('dcim:rack', args=[self.pk]) def clean(self): + super().clean() # Validate outer dimensions and unit if (self.outer_width is not None or self.outer_depth is not None) and not self.outer_unit: @@ -385,7 +377,7 @@ def display_name(self): return self.name def get_status_class(self): - return self.STATUS_CLASS_MAP.get(self.status) + return RackStatusChoices.CSS_CLASSES.get(self.status) def get_rack_units(self, user=None, face=DeviceFaceChoices.FACE_FRONT, exclude=None, expand_devices=True): """ @@ -550,24 +542,26 @@ def get_power_utilization(self): """ Determine the utilization rate of power in the rack and return it as a percentage. """ - power_stats = PowerFeed.objects.filter( - rack=self - ).annotate( - allocated_draw_total=Sum('connected_endpoint__poweroutlets__connected_endpoint__allocated_draw'), - ).values( - 'allocated_draw_total', - 'available_power' + powerfeeds = PowerFeed.objects.filter(rack=self) + available_power_total = sum(pf.available_power for pf in powerfeeds) + if not available_power_total: + return 0 + + pf_powerports = PowerPort.objects.filter( + _cable_peer_type=ContentType.objects.get_for_model(PowerFeed), + _cable_peer_id__in=powerfeeds.values_list('id', flat=True) ) + poweroutlets = PowerOutlet.objects.filter(power_port_id__in=pf_powerports) + allocated_draw_total = PowerPort.objects.filter( + _cable_peer_type=ContentType.objects.get_for_model(PowerOutlet), + _cable_peer_id__in=poweroutlets.values_list('id', flat=True) + ).aggregate(Sum('allocated_draw'))['allocated_draw__sum'] or 0 - if power_stats: - allocated_draw_total = sum(x['allocated_draw_total'] or 0 for x in power_stats) - available_power_total = sum(x['available_power'] for x in power_stats) - return int(allocated_draw_total / available_power_total * 100) or 0 - return 0 + return int(allocated_draw_total / available_power_total * 100) -@extras_features('custom_links', 'export_templates', 'webhooks') -class RackReservation(ChangeLoggedModel): +@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') +class RackReservation(ChangeLoggedModel, CustomFieldModel): """ One or more reserved units within a Rack. """ @@ -609,6 +603,7 @@ def get_absolute_url(self): return reverse('dcim:rackreservation', args=[self.pk]) def clean(self): + super().clean() if hasattr(self, 'rack') and self.units: @@ -647,9 +642,4 @@ def to_csv(self): @property def unit_list(self): - """ - Express the assigned units as a string of summarized ranges. For example: - [0, 1, 2, 10, 14, 15, 16] => "0-2, 10, 14-16" - """ - group = (list(x) for _, x in groupby(sorted(self.units), lambda x, c=count(): next(c) - x)) - return ', '.join('-'.join(map(str, (g[0], g[-1])[:len(g)])) for g in group) + return array_to_string(self.units) diff --git a/netbox/dcim/models/sites.py b/netbox/dcim/models/sites.py index daf7055db6..923b33124f 100644 --- a/netbox/dcim/models/sites.py +++ b/netbox/dcim/models/sites.py @@ -39,10 +39,11 @@ class Region(MPTTModel, ChangeLoggedModel): db_index=True ) name = models.CharField( - max_length=50, + max_length=100, unique=True ) slug = models.SlugField( + max_length=100, unique=True ) description = models.CharField( @@ -91,14 +92,14 @@ def to_objectchange(self, action): # Sites # -@extras_features('custom_fields', 'custom_links', 'graphs', 'export_templates', 'webhooks') +@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') class Site(ChangeLoggedModel, CustomFieldModel): """ A Site represents a geographic location within a network; typically a building or campus. The optional facility field can be used to include an external designation, such as a data center name (e.g. Equinix SV6). """ name = models.CharField( - max_length=50, + max_length=100, unique=True ) _name = NaturalOrderingField( @@ -107,6 +108,7 @@ class Site(ChangeLoggedModel, CustomFieldModel): blank=True ) slug = models.SlugField( + max_length=100, unique=True ) status = models.CharField( @@ -183,11 +185,6 @@ class Site(ChangeLoggedModel, CustomFieldModel): comments = models.TextField( blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) images = GenericRelation( to='extras.ImageAttachment' ) @@ -204,14 +201,6 @@ class Site(ChangeLoggedModel, CustomFieldModel): 'shipping_address', 'latitude', 'longitude', 'contact_name', 'contact_phone', 'contact_email', ] - STATUS_CLASS_MAP = { - SiteStatusChoices.STATUS_PLANNED: 'info', - SiteStatusChoices.STATUS_STAGING: 'primary', - SiteStatusChoices.STATUS_ACTIVE: 'success', - SiteStatusChoices.STATUS_DECOMMISSIONING: 'warning', - SiteStatusChoices.STATUS_RETIRED: 'danger', - } - class Meta: ordering = ('_name',) @@ -243,4 +232,4 @@ def to_csv(self): ) def get_status_class(self): - return self.STATUS_CLASS_MAP.get(self.status) + return SiteStatusChoices.CSS_CLASSES.get(self.status) diff --git a/netbox/dcim/signals.py b/netbox/dcim/signals.py index 172c366b51..4a5340748d 100644 --- a/netbox/dcim/signals.py +++ b/netbox/dcim/signals.py @@ -1,10 +1,37 @@ import logging -from django.db.models.signals import post_save, pre_delete +from django.contrib.contenttypes.models import ContentType +from django.db.models.signals import post_save, post_delete, pre_delete +from django.db import transaction from django.dispatch import receiver from .choices import CableStatusChoices -from .models import Cable, CableTermination, Device, FrontPort, RearPort, VirtualChassis +from .models import Cable, CablePath, Device, PathEndpoint, VirtualChassis + + +def create_cablepath(node): + """ + Create CablePaths for all paths originating from the specified node. + """ + cp = CablePath.from_origin(node) + if cp: + try: + cp.save() + except Exception as e: + print(node, node.pk) + raise e + + +def rebuild_paths(obj): + """ + Rebuild all CablePaths which traverse the specified node + """ + cable_paths = CablePath.objects.filter(path__contains=obj) + + with transaction.atomic(): + for cp in cable_paths: + cp.delete() + create_cablepath(cp.origin) @receiver(post_save, sender=VirtualChassis) @@ -32,71 +59,73 @@ def clear_virtualchassis_members(instance, **kwargs): @receiver(post_save, sender=Cable) -def update_connected_endpoints(instance, **kwargs): +def update_connected_endpoints(instance, created, raw=False, **kwargs): """ When a Cable is saved, check for and update its two connected endpoints """ logger = logging.getLogger('netbox.dcim.cable') + if raw: + logger.debug(f"Skipping endpoint updates for imported cable {instance}") + return # Cache the Cable on its two termination points if instance.termination_a.cable != instance: - logger.debug("Updating termination A for cable {}".format(instance)) + logger.debug(f"Updating termination A for cable {instance}") instance.termination_a.cable = instance + instance.termination_a._cable_peer = instance.termination_b instance.termination_a.save() if instance.termination_b.cable != instance: - logger.debug("Updating termination B for cable {}".format(instance)) + logger.debug(f"Updating termination B for cable {instance}") instance.termination_b.cable = instance + instance.termination_b._cable_peer = instance.termination_a instance.termination_b.save() - # Update any endpoints for this Cable. - endpoints = instance.termination_a.get_path_endpoints() + instance.termination_b.get_path_endpoints() - for endpoint in endpoints: - path, split_ends, position_stack = endpoint.trace() - # Determine overall path status (connected or planned) - path_status = True - for segment in path: - if segment[1] is None or segment[1].status != CableStatusChoices.STATUS_CONNECTED: - path_status = False - break - - endpoint_a = path[0][0] - endpoint_b = path[-1][2] if not split_ends and not position_stack else None - - # Patch panel ports are not connected endpoints, all other cable terminations are - if isinstance(endpoint_a, CableTermination) and not isinstance(endpoint_a, (FrontPort, RearPort)) and \ - isinstance(endpoint_b, CableTermination) and not isinstance(endpoint_b, (FrontPort, RearPort)): - logger.debug("Updating path endpoints: {} <---> {}".format(endpoint_a, endpoint_b)) - endpoint_a.connected_endpoint = endpoint_b - endpoint_a.connection_status = path_status - endpoint_a.save() - endpoint_b.connected_endpoint = endpoint_a - endpoint_b.connection_status = path_status - endpoint_b.save() - - -@receiver(pre_delete, sender=Cable) + # Create/update cable paths + if created: + for termination in (instance.termination_a, instance.termination_b): + if isinstance(termination, PathEndpoint): + create_cablepath(termination) + else: + rebuild_paths(termination) + elif instance.status != instance._orig_status: + # We currently don't support modifying either termination of an existing Cable. (This + # may change in the future.) However, we do need to capture status changes and update + # any CablePaths accordingly. + if instance.status != CableStatusChoices.STATUS_CONNECTED: + CablePath.objects.filter(path__contains=instance).update(is_active=False) + else: + rebuild_paths(instance) + + +@receiver(post_delete, sender=Cable) def nullify_connected_endpoints(instance, **kwargs): """ When a Cable is deleted, check for and update its two connected endpoints """ logger = logging.getLogger('netbox.dcim.cable') - endpoints = instance.termination_a.get_path_endpoints() + instance.termination_b.get_path_endpoints() - # Disassociate the Cable from its termination points if instance.termination_a is not None: - logger.debug("Nullifying termination A for cable {}".format(instance)) + logger.debug(f"Nullifying termination A for cable {instance}") instance.termination_a.cable = None + instance.termination_a._cable_peer = None instance.termination_a.save() if instance.termination_b is not None: - logger.debug("Nullifying termination B for cable {}".format(instance)) + logger.debug(f"Nullifying termination B for cable {instance}") instance.termination_b.cable = None + instance.termination_b._cable_peer = None instance.termination_b.save() - # If this Cable was part of any complete end-to-end paths, tear them down. - for endpoint in endpoints: - logger.debug(f"Removing path information for {endpoint}") - if hasattr(endpoint, 'connected_endpoint'): - endpoint.connected_endpoint = None - endpoint.connection_status = None - endpoint.save() + # Delete and retrace any dependent cable paths + for cablepath in CablePath.objects.filter(path__contains=instance): + cp = CablePath.from_origin(cablepath.origin) + if cp: + CablePath.objects.filter(pk=cablepath.pk).update( + path=cp.path, + destination_type=ContentType.objects.get_for_model(cp.destination) if cp.destination else None, + destination_id=cp.destination.pk if cp.destination else None, + is_active=cp.is_active, + is_split=cp.is_split + ) + else: + cablepath.delete() diff --git a/netbox/dcim/tables.py b/netbox/dcim/tables.py deleted file mode 100644 index 08235997d8..0000000000 --- a/netbox/dcim/tables.py +++ /dev/null @@ -1,1100 +0,0 @@ -import django_tables2 as tables -from django_tables2.utils import Accessor - -from tenancy.tables import COL_TENANT -from utilities.tables import ( - BaseTable, BooleanColumn, ButtonsColumn, ColorColumn, ColoredLabelColumn, TagColumn, ToggleColumn, -) -from .models import ( - Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay, - DeviceBayTemplate, DeviceRole, DeviceType, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate, - InventoryItem, Manufacturer, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, PowerPort, - PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site, - VirtualChassis, -) - -MPTT_LINK = """ -{% if record.get_children %} - -{% else %} - -{% endif %} - {{ record.name }} - -""" - -SITE_REGION_LINK = """ -{% if record.region %} - {{ record.region }} -{% else %} - — -{% endif %} -""" - -COLOR_LABEL = """ -{% load helpers %} - -""" - -DEVICE_LINK = """ - - {{ record.name|default:'Unnamed device' }} - -""" - -RACKGROUP_ELEVATIONS = """ - - - -""" - -RACK_DEVICE_COUNT = """ -{{ value }} -""" - -DEVICE_COUNT = """ -{{ value|default:0 }} -""" - -RACKRESERVATION_ACTIONS = """ - - - -{% if perms.dcim.change_rackreservation %} - -{% endif %} -""" - -MANUFACTURER_ACTIONS = """ - - - -{% if perms.dcim.change_manufacturer %} - -{% endif %} -""" - -DEVICEROLE_DEVICE_COUNT = """ -{{ value|default:0 }} -""" - -DEVICEROLE_VM_COUNT = """ -{{ value|default:0 }} -""" - -DEVICEROLE_ACTIONS = """ - - - -{% if perms.dcim.change_devicerole %} - -{% endif %} -""" - -PLATFORM_DEVICE_COUNT = """ -{{ value|default:0 }} -""" - -PLATFORM_VM_COUNT = """ -{{ value|default:0 }} -""" - -STATUS_LABEL = """ -{{ record.get_status_display }} -""" - -TYPE_LABEL = """ -{{ record.get_type_display }} -""" - -DEVICE_PRIMARY_IP = """ -{{ record.primary_ip6.address.ip|default:"" }} -{% if record.primary_ip6 and record.primary_ip4 %}
{% endif %} -{{ record.primary_ip4.address.ip|default:"" }} -""" - -DEVICETYPE_INSTANCES_TEMPLATE = """ -{{ record.instance_count }} -""" - -UTILIZATION_GRAPH = """ -{% load helpers %} -{% utilization_graph value %} -""" - -CABLE_TERMINATION_PARENT = """ -{% if value.device %} - {{ value.device }} -{% elif value.circuit %} - {{ value.circuit }} -{% elif value.power_panel %} - {{ value.power_panel }} -{% endif %} -""" - -CABLE_LENGTH = """ -{% if record.length %}{{ record.length }} {{ record.get_length_unit_display }}{% else %}—{% endif %} -""" - -POWERPANEL_POWERFEED_COUNT = """ -{{ value }} -""" - -INTERFACE_IPADDRESSES = """ -{% for ip in record.ip_addresses.all %} - {{ ip }}
-{% endfor %} -""" - -INTERFACE_TAGGED_VLANS = """ -{% for vlan in record.tagged_vlans.unrestricted %} - {{ vlan }}
-{% endfor %} -""" - -CONNECTION_STATUS = """ -{{ record.get_connection_status_display }} -""" - - -# -# Regions -# - -class RegionTable(BaseTable): - pk = ToggleColumn() - name = tables.TemplateColumn( - template_code=MPTT_LINK, - orderable=False - ) - site_count = tables.Column( - verbose_name='Sites' - ) - actions = ButtonsColumn(Region) - - class Meta(BaseTable.Meta): - model = Region - fields = ('pk', 'name', 'slug', 'site_count', 'description', 'actions') - default_columns = ('pk', 'name', 'site_count', 'description', 'actions') - - -# -# Sites -# - -class SiteTable(BaseTable): - pk = ToggleColumn() - name = tables.LinkColumn( - order_by=('_name',) - ) - status = tables.TemplateColumn( - template_code=STATUS_LABEL - ) - region = tables.TemplateColumn( - template_code=SITE_REGION_LINK - ) - tenant = tables.TemplateColumn( - template_code=COL_TENANT - ) - tags = TagColumn( - url_name='dcim:site_list' - ) - - class Meta(BaseTable.Meta): - model = Site - fields = ( - 'pk', 'name', 'slug', 'status', 'facility', 'region', 'tenant', 'asn', 'time_zone', 'description', - 'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name', 'contact_phone', - 'contact_email', 'tags', - ) - default_columns = ('pk', 'name', 'status', 'facility', 'region', 'tenant', 'asn', 'description') - - -# -# Rack groups -# - -class RackGroupTable(BaseTable): - pk = ToggleColumn() - name = tables.TemplateColumn( - template_code=MPTT_LINK, - orderable=False - ) - site = tables.LinkColumn( - viewname='dcim:site', - args=[Accessor('site__slug')], - verbose_name='Site' - ) - rack_count = tables.Column( - verbose_name='Racks' - ) - actions = ButtonsColumn( - model=RackGroup, - prepend_template=RACKGROUP_ELEVATIONS - ) - - class Meta(BaseTable.Meta): - model = RackGroup - fields = ('pk', 'name', 'site', 'rack_count', 'description', 'slug', 'actions') - default_columns = ('pk', 'name', 'site', 'rack_count', 'description', 'actions') - - -# -# Rack roles -# - -class RackRoleTable(BaseTable): - pk = ToggleColumn() - name = tables.Column(linkify=True) - rack_count = tables.Column(verbose_name='Racks') - color = tables.TemplateColumn(COLOR_LABEL) - actions = ButtonsColumn(RackRole) - - class Meta(BaseTable.Meta): - model = RackRole - fields = ('pk', 'name', 'rack_count', 'color', 'description', 'slug', 'actions') - default_columns = ('pk', 'name', 'rack_count', 'color', 'description', 'actions') - - -# -# Racks -# - -class RackTable(BaseTable): - pk = ToggleColumn() - name = tables.Column( - order_by=('_name',), - linkify=True - ) - group = tables.Column( - linkify=True - ) - site = tables.Column( - linkify=True - ) - tenant = tables.TemplateColumn( - template_code=COL_TENANT - ) - status = tables.TemplateColumn( - template_code=STATUS_LABEL - ) - role = ColoredLabelColumn() - u_height = tables.TemplateColumn( - template_code="{{ record.u_height }}U", - verbose_name='Height' - ) - - class Meta(BaseTable.Meta): - model = Rack - fields = ( - 'pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'serial', 'asset_tag', 'type', - 'width', 'u_height', - ) - default_columns = ('pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'u_height') - - -class RackDetailTable(RackTable): - device_count = tables.TemplateColumn( - template_code=RACK_DEVICE_COUNT, - verbose_name='Devices' - ) - get_utilization = tables.TemplateColumn( - template_code=UTILIZATION_GRAPH, - orderable=False, - verbose_name='Space' - ) - get_power_utilization = tables.TemplateColumn( - template_code=UTILIZATION_GRAPH, - orderable=False, - verbose_name='Power' - ) - tags = TagColumn( - url_name='dcim:rack_list' - ) - - class Meta(RackTable.Meta): - fields = ( - 'pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'serial', 'asset_tag', 'type', - 'width', 'u_height', 'device_count', 'get_utilization', 'get_power_utilization', 'tags', - ) - default_columns = ( - 'pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'u_height', 'device_count', - 'get_utilization', 'get_power_utilization', - ) - - -# -# Rack reservations -# - -class RackReservationTable(BaseTable): - pk = ToggleColumn() - reservation = tables.Column( - accessor='pk', - linkify=True - ) - site = tables.Column( - accessor=Accessor('rack__site'), - linkify=True - ) - tenant = tables.TemplateColumn( - template_code=COL_TENANT - ) - rack = tables.Column( - linkify=True - ) - unit_list = tables.Column( - orderable=False, - verbose_name='Units' - ) - tags = TagColumn( - url_name='dcim:rackreservation_list' - ) - actions = ButtonsColumn(RackReservation) - - class Meta(BaseTable.Meta): - model = RackReservation - fields = ( - 'pk', 'reservation', 'site', 'rack', 'unit_list', 'user', 'created', 'tenant', 'description', 'tags', - 'actions', - ) - default_columns = ( - 'pk', 'reservation', 'site', 'rack', 'unit_list', 'user', 'description', 'actions', - ) - - -# -# Manufacturers -# - -class ManufacturerTable(BaseTable): - pk = ToggleColumn() - name = tables.LinkColumn() - devicetype_count = tables.Column( - verbose_name='Device Types' - ) - inventoryitem_count = tables.Column( - verbose_name='Inventory Items' - ) - platform_count = tables.Column( - verbose_name='Platforms' - ) - slug = tables.Column() - actions = ButtonsColumn(Manufacturer, pk_field='slug') - - class Meta(BaseTable.Meta): - model = Manufacturer - fields = ( - 'pk', 'name', 'devicetype_count', 'inventoryitem_count', 'platform_count', 'description', 'slug', 'actions', - ) - - -# -# Device types -# - -class DeviceTypeTable(BaseTable): - pk = ToggleColumn() - model = tables.Column( - linkify=True, - verbose_name='Device Type' - ) - is_full_depth = BooleanColumn( - verbose_name='Full Depth' - ) - instance_count = tables.TemplateColumn( - template_code=DEVICETYPE_INSTANCES_TEMPLATE, - verbose_name='Instances' - ) - tags = TagColumn( - url_name='dcim:devicetype_list' - ) - - class Meta(BaseTable.Meta): - model = DeviceType - fields = ( - 'pk', 'model', 'manufacturer', 'slug', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role', - 'instance_count', 'tags', - ) - default_columns = ( - 'pk', 'model', 'manufacturer', 'part_number', 'u_height', 'is_full_depth', 'instance_count', - ) - - -# -# Device type components -# - -class ComponentTemplateTable(BaseTable): - pk = ToggleColumn() - name = tables.Column( - order_by=('_name',) - ) - - -class ConsolePortTemplateTable(ComponentTemplateTable): - actions = ButtonsColumn( - model=ConsolePortTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_consoleports' - ) - - class Meta(BaseTable.Meta): - model = ConsolePortTemplate - fields = ('pk', 'name', 'label', 'type', 'description', 'actions') - empty_text = "None" - - -class ConsoleServerPortTemplateTable(ComponentTemplateTable): - actions = ButtonsColumn( - model=ConsoleServerPortTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_consoleserverports' - ) - - class Meta(BaseTable.Meta): - model = ConsoleServerPortTemplate - fields = ('pk', 'name', 'label', 'type', 'description', 'actions') - empty_text = "None" - - -class PowerPortTemplateTable(ComponentTemplateTable): - actions = ButtonsColumn( - model=PowerPortTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_powerports' - ) - - class Meta(BaseTable.Meta): - model = PowerPortTemplate - fields = ('pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'actions') - empty_text = "None" - - -class PowerOutletTemplateTable(ComponentTemplateTable): - actions = ButtonsColumn( - model=PowerOutletTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_poweroutlets' - ) - - class Meta(BaseTable.Meta): - model = PowerOutletTemplate - fields = ('pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'actions') - empty_text = "None" - - -class InterfaceTemplateTable(ComponentTemplateTable): - mgmt_only = BooleanColumn( - verbose_name='Management Only' - ) - actions = ButtonsColumn( - model=InterfaceTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_interfaces' - ) - - class Meta(BaseTable.Meta): - model = InterfaceTemplate - fields = ('pk', 'name', 'label', 'mgmt_only', 'type', 'description', 'actions') - empty_text = "None" - - -class FrontPortTemplateTable(ComponentTemplateTable): - rear_port_position = tables.Column( - verbose_name='Position' - ) - actions = ButtonsColumn( - model=FrontPortTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_frontports' - ) - - class Meta(BaseTable.Meta): - model = FrontPortTemplate - fields = ('pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'actions') - empty_text = "None" - - -class RearPortTemplateTable(ComponentTemplateTable): - actions = ButtonsColumn( - model=RearPortTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_rearports' - ) - - class Meta(BaseTable.Meta): - model = RearPortTemplate - fields = ('pk', 'name', 'label', 'type', 'positions', 'description', 'actions') - empty_text = "None" - - -class DeviceBayTemplateTable(ComponentTemplateTable): - actions = ButtonsColumn( - model=DeviceBayTemplate, - buttons=('edit', 'delete'), - return_url_extra='%23tab_devicebays' - ) - - class Meta(BaseTable.Meta): - model = DeviceBayTemplate - fields = ('pk', 'name', 'label', 'description', 'actions') - empty_text = "None" - - -# -# Device roles -# - -class DeviceRoleTable(BaseTable): - pk = ToggleColumn() - device_count = tables.TemplateColumn( - template_code=DEVICEROLE_DEVICE_COUNT, - verbose_name='Devices' - ) - vm_count = tables.TemplateColumn( - template_code=DEVICEROLE_VM_COUNT, - verbose_name='VMs' - ) - color = tables.TemplateColumn( - template_code=COLOR_LABEL, - verbose_name='Label' - ) - vm_role = BooleanColumn() - actions = ButtonsColumn(DeviceRole, pk_field='slug') - - class Meta(BaseTable.Meta): - model = DeviceRole - fields = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'slug', 'actions') - default_columns = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'actions') - - -# -# Platforms -# - -class PlatformTable(BaseTable): - pk = ToggleColumn() - device_count = tables.TemplateColumn( - template_code=PLATFORM_DEVICE_COUNT, - verbose_name='Devices' - ) - vm_count = tables.TemplateColumn( - template_code=PLATFORM_VM_COUNT, - verbose_name='VMs' - ) - actions = ButtonsColumn(Platform, pk_field='slug') - - class Meta(BaseTable.Meta): - model = Platform - fields = ( - 'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'slug', 'napalm_driver', 'napalm_args', - 'description', 'actions', - ) - default_columns = ( - 'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'napalm_driver', 'description', 'actions', - ) - - -# -# Devices -# - -class DeviceTable(BaseTable): - pk = ToggleColumn() - name = tables.TemplateColumn( - order_by=('_name',), - template_code=DEVICE_LINK - ) - status = tables.TemplateColumn( - template_code=STATUS_LABEL - ) - tenant = tables.TemplateColumn( - template_code=COL_TENANT - ) - site = tables.Column( - linkify=True - ) - rack = tables.Column( - linkify=True - ) - device_role = ColoredLabelColumn( - verbose_name='Role' - ) - device_type = tables.LinkColumn( - viewname='dcim:devicetype', - args=[Accessor('device_type__pk')], - verbose_name='Type', - text=lambda record: record.device_type.display_name - ) - primary_ip = tables.TemplateColumn( - template_code=DEVICE_PRIMARY_IP, - orderable=False, - verbose_name='IP Address' - ) - primary_ip4 = tables.Column( - linkify=True, - verbose_name='IPv4 Address' - ) - primary_ip6 = tables.Column( - linkify=True, - verbose_name='IPv6 Address' - ) - cluster = tables.LinkColumn( - viewname='virtualization:cluster', - args=[Accessor('cluster__pk')] - ) - virtual_chassis = tables.LinkColumn( - viewname='dcim:virtualchassis', - args=[Accessor('virtual_chassis__pk')] - ) - vc_position = tables.Column( - verbose_name='VC Position' - ) - vc_priority = tables.Column( - verbose_name='VC Priority' - ) - tags = TagColumn( - url_name='dcim:device_list' - ) - - class Meta(BaseTable.Meta): - model = Device - fields = ( - 'pk', 'name', 'status', 'tenant', 'device_role', 'device_type', 'platform', 'serial', 'asset_tag', 'site', - 'rack', 'position', 'face', 'primary_ip', 'primary_ip4', 'primary_ip6', 'cluster', 'virtual_chassis', - 'vc_position', 'vc_priority', 'tags', - ) - default_columns = ( - 'pk', 'name', 'status', 'tenant', 'site', 'rack', 'device_role', 'device_type', 'primary_ip', - ) - - -class DeviceImportTable(BaseTable): - name = tables.TemplateColumn( - template_code=DEVICE_LINK - ) - status = tables.TemplateColumn( - template_code=STATUS_LABEL - ) - tenant = tables.TemplateColumn( - template_code=COL_TENANT - ) - site = tables.Column( - linkify=True - ) - rack = tables.Column( - linkify=True - ) - device_role = tables.Column( - verbose_name='Role' - ) - device_type = tables.Column( - verbose_name='Type' - ) - - class Meta(BaseTable.Meta): - model = Device - fields = ('name', 'status', 'tenant', 'site', 'rack', 'position', 'device_role', 'device_type') - empty_text = False - - -# -# Device components -# - -class DeviceComponentTable(BaseTable): - pk = ToggleColumn() - device = tables.Column( - linkify=True - ) - name = tables.Column( - linkify=True, - order_by=('_name',) - ) - cable = tables.Column( - linkify=True - ) - - class Meta(BaseTable.Meta): - order_by = ('device', 'name') - - -class ConsolePortTable(DeviceComponentTable): - tags = TagColumn( - url_name='dcim:consoleport_list' - ) - - class Meta(DeviceComponentTable.Meta): - model = ConsolePort - fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'tags') - default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') - - -class ConsoleServerPortTable(DeviceComponentTable): - tags = TagColumn( - url_name='dcim:consoleserverport_list' - ) - - class Meta(DeviceComponentTable.Meta): - model = ConsoleServerPort - fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'tags') - default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') - - -class PowerPortTable(DeviceComponentTable): - tags = TagColumn( - url_name='dcim:powerport_list' - ) - - class Meta(DeviceComponentTable.Meta): - model = PowerPort - fields = ( - 'pk', 'device', 'name', 'label', 'type', 'description', 'maximum_draw', 'allocated_draw', 'cable', 'tags', - ) - default_columns = ('pk', 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description') - - -class PowerOutletTable(DeviceComponentTable): - tags = TagColumn( - url_name='dcim:poweroutlet_list' - ) - - class Meta(DeviceComponentTable.Meta): - model = PowerOutlet - fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'power_port', 'feed_leg', 'cable', 'tags') - default_columns = ('pk', 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description') - - -class BaseInterfaceTable(BaseTable): - enabled = BooleanColumn() - ip_addresses = tables.TemplateColumn( - template_code=INTERFACE_IPADDRESSES, - orderable=False, - verbose_name='IP Addresses' - ) - untagged_vlan = tables.Column(linkify=True) - tagged_vlans = tables.TemplateColumn( - template_code=INTERFACE_TAGGED_VLANS, - orderable=False, - verbose_name='Tagged VLANs' - ) - - -class InterfaceTable(DeviceComponentTable, BaseInterfaceTable): - tags = TagColumn( - url_name='dcim:interface_list' - ) - - class Meta(DeviceComponentTable.Meta): - model = Interface - fields = ( - 'pk', 'device', 'name', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address', - 'description', 'cable', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans', - ) - default_columns = ('pk', 'device', 'name', 'label', 'enabled', 'type', 'description') - - -class FrontPortTable(DeviceComponentTable): - rear_port_position = tables.Column( - verbose_name='Position' - ) - tags = TagColumn( - url_name='dcim:frontport_list' - ) - - class Meta(DeviceComponentTable.Meta): - model = FrontPort - fields = ( - 'pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'tags', - ) - default_columns = ('pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description') - - -class RearPortTable(DeviceComponentTable): - tags = TagColumn( - url_name='dcim:rearport_list' - ) - - class Meta(DeviceComponentTable.Meta): - model = RearPort - fields = ('pk', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable', 'tags') - default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') - - -class DeviceBayTable(DeviceComponentTable): - installed_device = tables.Column( - linkify=True - ) - tags = TagColumn( - url_name='dcim:devicebay_list' - ) - - class Meta(DeviceComponentTable.Meta): - model = DeviceBay - fields = ('pk', 'device', 'name', 'label', 'installed_device', 'description', 'tags') - default_columns = ('pk', 'device', 'name', 'label', 'installed_device', 'description') - - -class InventoryItemTable(DeviceComponentTable): - manufacturer = tables.Column( - linkify=True - ) - discovered = BooleanColumn() - tags = TagColumn( - url_name='dcim:inventoryitem_list' - ) - cable = None # Override DeviceComponentTable - - class Meta(DeviceComponentTable.Meta): - model = InventoryItem - fields = ( - 'pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', - 'discovered', 'tags', - ) - default_columns = ('pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag') - - -# -# Cables -# - -class CableTable(BaseTable): - pk = ToggleColumn() - id = tables.Column( - linkify=True, - verbose_name='ID' - ) - termination_a_parent = tables.TemplateColumn( - template_code=CABLE_TERMINATION_PARENT, - accessor=Accessor('termination_a'), - orderable=False, - verbose_name='Side A' - ) - termination_a = tables.LinkColumn( - accessor=Accessor('termination_a'), - orderable=False, - verbose_name='Termination A' - ) - termination_b_parent = tables.TemplateColumn( - template_code=CABLE_TERMINATION_PARENT, - accessor=Accessor('termination_b'), - orderable=False, - verbose_name='Side B' - ) - termination_b = tables.LinkColumn( - accessor=Accessor('termination_b'), - orderable=False, - verbose_name='Termination B' - ) - status = tables.TemplateColumn( - template_code=STATUS_LABEL - ) - length = tables.TemplateColumn( - template_code=CABLE_LENGTH, - order_by='_abs_length' - ) - color = ColorColumn() - tags = TagColumn( - url_name='dcim:cable_list' - ) - - class Meta(BaseTable.Meta): - model = Cable - fields = ( - 'pk', 'id', 'label', 'termination_a_parent', 'termination_a', 'termination_b_parent', 'termination_b', - 'status', 'type', 'color', 'length', 'tags', - ) - default_columns = ( - 'pk', 'id', 'label', 'termination_a_parent', 'termination_a', 'termination_b_parent', 'termination_b', - 'status', 'type', - ) - - -# -# Device connections -# - -class ConsoleConnectionTable(BaseTable): - console_server = tables.LinkColumn( - viewname='dcim:device', - accessor=Accessor('connected_endpoint__device'), - args=[Accessor('connected_endpoint__device__pk')], - verbose_name='Console Server' - ) - connected_endpoint = tables.Column( - linkify=True, - verbose_name='Port' - ) - device = tables.Column( - linkify=True - ) - name = tables.Column( - linkify=True, - verbose_name='Console Port' - ) - connection_status = tables.TemplateColumn( - template_code=CONNECTION_STATUS, - verbose_name='Status' - ) - - class Meta(BaseTable.Meta): - model = ConsolePort - fields = ('console_server', 'connected_endpoint', 'device', 'name', 'connection_status') - - -class PowerConnectionTable(BaseTable): - pdu = tables.LinkColumn( - viewname='dcim:device', - accessor=Accessor('connected_endpoint__device'), - args=[Accessor('connected_endpoint__device__pk')], - order_by='_connected_poweroutlet__device', - verbose_name='PDU' - ) - outlet = tables.Column( - accessor=Accessor('_connected_poweroutlet'), - linkify=True, - verbose_name='Outlet' - ) - device = tables.Column( - linkify=True - ) - name = tables.Column( - linkify=True, - verbose_name='Power Port' - ) - connection_status = tables.TemplateColumn( - template_code=CONNECTION_STATUS, - verbose_name='Status' - ) - - class Meta(BaseTable.Meta): - model = PowerPort - fields = ('pdu', 'outlet', 'device', 'name', 'connection_status') - - -class InterfaceConnectionTable(BaseTable): - device_a = tables.LinkColumn( - viewname='dcim:device', - accessor=Accessor('device'), - args=[Accessor('device__pk')], - verbose_name='Device A' - ) - interface_a = tables.LinkColumn( - viewname='dcim:interface', - accessor=Accessor('name'), - args=[Accessor('pk')], - verbose_name='Interface A' - ) - device_b = tables.LinkColumn( - viewname='dcim:device', - accessor=Accessor('_connected_interface__device'), - args=[Accessor('_connected_interface__device__pk')], - verbose_name='Device B' - ) - interface_b = tables.LinkColumn( - viewname='dcim:interface', - accessor=Accessor('_connected_interface'), - args=[Accessor('_connected_interface__pk')], - verbose_name='Interface B' - ) - connection_status = tables.TemplateColumn( - template_code=CONNECTION_STATUS, - verbose_name='Status' - ) - - class Meta(BaseTable.Meta): - model = Interface - fields = ( - 'device_a', 'interface_a', 'device_b', 'interface_b', 'connection_status', - ) - - -# -# Virtual chassis -# - -class VirtualChassisTable(BaseTable): - pk = ToggleColumn() - name = tables.Column( - linkify=True - ) - master = tables.Column( - linkify=True - ) - member_count = tables.Column( - verbose_name='Members' - ) - tags = TagColumn( - url_name='dcim:virtualchassis_list' - ) - - class Meta(BaseTable.Meta): - model = VirtualChassis - fields = ('pk', 'name', 'domain', 'master', 'member_count', 'tags') - default_columns = ('pk', 'name', 'domain', 'master', 'member_count') - - -# -# Power panels -# - -class PowerPanelTable(BaseTable): - pk = ToggleColumn() - name = tables.LinkColumn() - site = tables.LinkColumn( - viewname='dcim:site', - args=[Accessor('site__slug')] - ) - powerfeed_count = tables.TemplateColumn( - template_code=POWERPANEL_POWERFEED_COUNT, - verbose_name='Feeds' - ) - tags = TagColumn( - url_name='dcim:powerpanel_list' - ) - - class Meta(BaseTable.Meta): - model = PowerPanel - fields = ('pk', 'name', 'site', 'rack_group', 'powerfeed_count', 'tags') - default_columns = ('pk', 'name', 'site', 'rack_group', 'powerfeed_count') - - -# -# Power feeds -# - -class PowerFeedTable(BaseTable): - pk = ToggleColumn() - name = tables.LinkColumn() - power_panel = tables.Column( - linkify=True - ) - rack = tables.Column( - linkify=True - ) - status = tables.TemplateColumn( - template_code=STATUS_LABEL - ) - type = tables.TemplateColumn( - template_code=TYPE_LABEL - ) - max_utilization = tables.TemplateColumn( - template_code="{{ value }}%" - ) - available_power = tables.Column( - verbose_name='Available power (VA)' - ) - tags = TagColumn( - url_name='dcim:powerfeed_list' - ) - - class Meta(BaseTable.Meta): - model = PowerFeed - fields = ( - 'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase', - 'max_utilization', 'available_power', 'tags', - ) - default_columns = ( - 'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase', - ) diff --git a/netbox/dcim/tables/__init__.py b/netbox/dcim/tables/__init__.py new file mode 100644 index 0000000000..8a861c8c20 --- /dev/null +++ b/netbox/dcim/tables/__init__.py @@ -0,0 +1,108 @@ +import django_tables2 as tables +from django_tables2.utils import Accessor + +from utilities.tables import BaseTable, BooleanColumn +from dcim.models import ConsolePort, Interface, PowerPort +from .cables import * +from .devices import * +from .devicetypes import * +from .power import * +from .racks import * +from .sites import * + + +# +# Device connections +# + +class ConsoleConnectionTable(BaseTable): + console_server = tables.Column( + accessor=Accessor('_path__destination__device'), + orderable=False, + linkify=True, + verbose_name='Console Server' + ) + console_server_port = tables.Column( + accessor=Accessor('_path__destination'), + orderable=False, + linkify=True, + verbose_name='Port' + ) + device = tables.Column( + linkify=True + ) + name = tables.Column( + linkify=True, + verbose_name='Console Port' + ) + reachable = BooleanColumn( + accessor=Accessor('_path__is_active'), + verbose_name='Reachable' + ) + + class Meta(BaseTable.Meta): + model = ConsolePort + fields = ('device', 'name', 'console_server', 'console_server_port', 'reachable') + + +class PowerConnectionTable(BaseTable): + pdu = tables.Column( + accessor=Accessor('_path__destination__device'), + orderable=False, + linkify=True, + verbose_name='PDU' + ) + outlet = tables.Column( + accessor=Accessor('_path__destination'), + orderable=False, + linkify=True, + verbose_name='Outlet' + ) + device = tables.Column( + linkify=True + ) + name = tables.Column( + linkify=True, + verbose_name='Power Port' + ) + reachable = BooleanColumn( + accessor=Accessor('_path__is_active'), + verbose_name='Reachable' + ) + + class Meta(BaseTable.Meta): + model = PowerPort + fields = ('device', 'name', 'pdu', 'outlet', 'reachable') + + +class InterfaceConnectionTable(BaseTable): + device_a = tables.Column( + accessor=Accessor('device'), + linkify=True, + verbose_name='Device A' + ) + interface_a = tables.Column( + accessor=Accessor('name'), + linkify=True, + verbose_name='Interface A' + ) + device_b = tables.Column( + accessor=Accessor('_path__destination__device'), + orderable=False, + linkify=True, + verbose_name='Device B' + ) + interface_b = tables.Column( + accessor=Accessor('_path__destination'), + orderable=False, + linkify=True, + verbose_name='Interface B' + ) + reachable = BooleanColumn( + accessor=Accessor('_path__is_active'), + verbose_name='Reachable' + ) + + class Meta(BaseTable.Meta): + model = Interface + fields = ('device_a', 'interface_a', 'device_b', 'interface_b', 'reachable') diff --git a/netbox/dcim/tables/cables.py b/netbox/dcim/tables/cables.py new file mode 100644 index 0000000000..cdb79f4e12 --- /dev/null +++ b/netbox/dcim/tables/cables.py @@ -0,0 +1,64 @@ +import django_tables2 as tables +from django_tables2.utils import Accessor + +from dcim.models import Cable +from utilities.tables import BaseTable, ChoiceFieldColumn, ColorColumn, TagColumn, ToggleColumn +from .template_code import CABLE_LENGTH, CABLE_TERMINATION_PARENT + +__all__ = ( + 'CableTable', +) + + +# +# Cables +# + +class CableTable(BaseTable): + pk = ToggleColumn() + id = tables.Column( + linkify=True, + verbose_name='ID' + ) + termination_a_parent = tables.TemplateColumn( + template_code=CABLE_TERMINATION_PARENT, + accessor=Accessor('termination_a'), + orderable=False, + verbose_name='Side A' + ) + termination_a = tables.LinkColumn( + accessor=Accessor('termination_a'), + orderable=False, + verbose_name='Termination A' + ) + termination_b_parent = tables.TemplateColumn( + template_code=CABLE_TERMINATION_PARENT, + accessor=Accessor('termination_b'), + orderable=False, + verbose_name='Side B' + ) + termination_b = tables.LinkColumn( + accessor=Accessor('termination_b'), + orderable=False, + verbose_name='Termination B' + ) + status = ChoiceFieldColumn() + length = tables.TemplateColumn( + template_code=CABLE_LENGTH, + order_by='_abs_length' + ) + color = ColorColumn() + tags = TagColumn( + url_name='dcim:cable_list' + ) + + class Meta(BaseTable.Meta): + model = Cable + fields = ( + 'pk', 'id', 'label', 'termination_a_parent', 'termination_a', 'termination_b_parent', 'termination_b', + 'status', 'type', 'color', 'length', 'tags', + ) + default_columns = ( + 'pk', 'id', 'label', 'termination_a_parent', 'termination_a', 'termination_b_parent', 'termination_b', + 'status', 'type', + ) diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py new file mode 100644 index 0000000000..536be66d93 --- /dev/null +++ b/netbox/dcim/tables/devices.py @@ -0,0 +1,642 @@ +import django_tables2 as tables +from django_tables2.utils import Accessor + +from dcim.models import ( + ConsolePort, ConsoleServerPort, Device, DeviceBay, DeviceRole, FrontPort, Interface, InventoryItem, Platform, + PowerOutlet, PowerPort, RearPort, VirtualChassis, +) +from tenancy.tables import COL_TENANT +from utilities.tables import ( + BaseTable, BooleanColumn, ButtonsColumn, ChoiceFieldColumn, ColorColumn, ColoredLabelColumn, LinkedCountColumn, + TagColumn, ToggleColumn, +) +from .template_code import ( + CABLETERMINATION, CONSOLEPORT_BUTTONS, CONSOLESERVERPORT_BUTTONS, DEVICE_LINK, DEVICEBAY_BUTTONS, DEVICEBAY_STATUS, + FRONTPORT_BUTTONS, INTERFACE_BUTTONS, INTERFACE_IPADDRESSES, INTERFACE_TAGGED_VLANS, POWEROUTLET_BUTTONS, + POWERPORT_BUTTONS, REARPORT_BUTTONS, +) + +__all__ = ( + 'ConsolePortTable', + 'ConsoleServerPortTable', + 'DeviceBayTable', + 'DeviceConsolePortTable', + 'DeviceConsoleServerPortTable', + 'DeviceDeviceBayTable', + 'DeviceFrontPortTable', + 'DeviceImportTable', + 'DeviceInterfaceTable', + 'DeviceInventoryItemTable', + 'DevicePowerPortTable', + 'DevicePowerOutletTable', + 'DeviceRearPortTable', + 'DeviceRoleTable', + 'DeviceTable', + 'FrontPortTable', + 'InterfaceTable', + 'InventoryItemTable', + 'PlatformTable', + 'PowerOutletTable', + 'PowerPortTable', + 'RearPortTable', + 'VirtualChassisTable', +) + + +# +# Device roles +# + +class DeviceRoleTable(BaseTable): + pk = ToggleColumn() + device_count = LinkedCountColumn( + viewname='dcim:device_list', + url_params={'role': 'slug'}, + verbose_name='Devices' + ) + vm_count = LinkedCountColumn( + viewname='virtualization:virtualmachine_list', + url_params={'role': 'slug'}, + verbose_name='VMs' + ) + color = ColorColumn() + vm_role = BooleanColumn() + actions = ButtonsColumn(DeviceRole, pk_field='slug') + + class Meta(BaseTable.Meta): + model = DeviceRole + fields = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'slug', 'actions') + default_columns = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'actions') + + +# +# Platforms +# + +class PlatformTable(BaseTable): + pk = ToggleColumn() + device_count = LinkedCountColumn( + viewname='dcim:device_list', + url_params={'platform': 'slug'}, + verbose_name='Devices' + ) + vm_count = LinkedCountColumn( + viewname='virtualization:virtualmachine_list', + url_params={'platform': 'slug'}, + verbose_name='VMs' + ) + actions = ButtonsColumn(Platform, pk_field='slug') + + class Meta(BaseTable.Meta): + model = Platform + fields = ( + 'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'slug', 'napalm_driver', 'napalm_args', + 'description', 'actions', + ) + default_columns = ( + 'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'napalm_driver', 'description', 'actions', + ) + + +# +# Devices +# + +class DeviceTable(BaseTable): + pk = ToggleColumn() + name = tables.TemplateColumn( + order_by=('_name',), + template_code=DEVICE_LINK + ) + status = ChoiceFieldColumn() + tenant = tables.TemplateColumn( + template_code=COL_TENANT + ) + site = tables.Column( + linkify=True + ) + rack = tables.Column( + linkify=True + ) + device_role = ColoredLabelColumn( + verbose_name='Role' + ) + device_type = tables.LinkColumn( + viewname='dcim:devicetype', + args=[Accessor('device_type__pk')], + verbose_name='Type', + text=lambda record: record.device_type.display_name + ) + primary_ip = tables.Column( + linkify=True, + verbose_name='IP Address' + ) + primary_ip4 = tables.Column( + linkify=True, + verbose_name='IPv4 Address' + ) + primary_ip6 = tables.Column( + linkify=True, + verbose_name='IPv6 Address' + ) + cluster = tables.LinkColumn( + viewname='virtualization:cluster', + args=[Accessor('cluster__pk')] + ) + virtual_chassis = tables.LinkColumn( + viewname='dcim:virtualchassis', + args=[Accessor('virtual_chassis__pk')] + ) + vc_position = tables.Column( + verbose_name='VC Position' + ) + vc_priority = tables.Column( + verbose_name='VC Priority' + ) + tags = TagColumn( + url_name='dcim:device_list' + ) + + class Meta(BaseTable.Meta): + model = Device + fields = ( + 'pk', 'name', 'status', 'tenant', 'device_role', 'device_type', 'platform', 'serial', 'asset_tag', 'site', + 'rack', 'position', 'face', 'primary_ip', 'primary_ip4', 'primary_ip6', 'cluster', 'virtual_chassis', + 'vc_position', 'vc_priority', 'tags', + ) + default_columns = ( + 'pk', 'name', 'status', 'tenant', 'site', 'rack', 'device_role', 'device_type', 'primary_ip', + ) + + +class DeviceImportTable(BaseTable): + name = tables.TemplateColumn( + template_code=DEVICE_LINK + ) + status = ChoiceFieldColumn() + tenant = tables.TemplateColumn( + template_code=COL_TENANT + ) + site = tables.Column( + linkify=True + ) + rack = tables.Column( + linkify=True + ) + device_role = tables.Column( + verbose_name='Role' + ) + device_type = tables.Column( + verbose_name='Type' + ) + + class Meta(BaseTable.Meta): + model = Device + fields = ('name', 'status', 'tenant', 'site', 'rack', 'position', 'device_role', 'device_type') + empty_text = False + + +# +# Device components +# + +class DeviceComponentTable(BaseTable): + pk = ToggleColumn() + device = tables.Column( + linkify=True + ) + name = tables.Column( + linkify=True, + order_by=('_name',) + ) + cable = tables.Column( + linkify=True + ) + + class Meta(BaseTable.Meta): + order_by = ('device', 'name') + + +class CableTerminationTable(BaseTable): + cable = tables.Column( + linkify=True + ) + cable_peer = tables.TemplateColumn( + accessor='_cable_peer', + template_code=CABLETERMINATION, + orderable=False, + verbose_name='Cable Peer' + ) + + +class PathEndpointTable(CableTerminationTable): + connection = tables.TemplateColumn( + accessor='_path.destination', + template_code=CABLETERMINATION, + verbose_name='Connection', + orderable=False + ) + + +class ConsolePortTable(DeviceComponentTable, PathEndpointTable): + tags = TagColumn( + url_name='dcim:consoleport_list' + ) + + class Meta(DeviceComponentTable.Meta): + model = ConsolePort + fields = ( + 'pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags', + ) + default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') + + +class DeviceConsolePortTable(ConsolePortTable): + name = tables.TemplateColumn( + template_code=' {{ value }}', + attrs={'td': {'class': 'text-nowrap'}} + ) + actions = ButtonsColumn( + model=ConsolePort, + buttons=('edit', 'delete'), + prepend_template=CONSOLEPORT_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = ConsolePort + fields = ( + 'pk', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags', 'actions' + ) + default_columns = ('pk', 'name', 'label', 'type', 'description', 'cable', 'connection', 'actions') + row_attrs = { + 'class': lambda record: record.cable.get_status_class() if record.cable else '' + } + + +class ConsoleServerPortTable(DeviceComponentTable, PathEndpointTable): + tags = TagColumn( + url_name='dcim:consoleserverport_list' + ) + + class Meta(DeviceComponentTable.Meta): + model = ConsoleServerPort + fields = ('pk', 'device', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags') + default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') + + +class DeviceConsoleServerPortTable(ConsoleServerPortTable): + name = tables.TemplateColumn( + template_code=' ' + '{{ value }}', + attrs={'td': {'class': 'text-nowrap'}} + ) + actions = ButtonsColumn( + model=ConsoleServerPort, + buttons=('edit', 'delete'), + prepend_template=CONSOLESERVERPORT_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = ConsoleServerPort + fields = ( + 'pk', 'name', 'label', 'type', 'description', 'cable', 'cable_peer', 'connection', 'tags', 'actions' + ) + default_columns = ('pk', 'name', 'label', 'type', 'description', 'cable', 'connection', 'actions') + row_attrs = { + 'class': lambda record: record.cable.get_status_class() if record.cable else '' + } + + +class PowerPortTable(DeviceComponentTable, PathEndpointTable): + tags = TagColumn( + url_name='dcim:powerport_list' + ) + + class Meta(DeviceComponentTable.Meta): + model = PowerPort + fields = ( + 'pk', 'device', 'name', 'label', 'type', 'description', 'maximum_draw', 'allocated_draw', 'cable', + 'cable_peer', 'connection', 'tags', + ) + default_columns = ('pk', 'device', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description') + + +class DevicePowerPortTable(PowerPortTable): + name = tables.TemplateColumn( + template_code=' ' + '{{ value }}', + attrs={'td': {'class': 'text-nowrap'}} + ) + actions = ButtonsColumn( + model=PowerPort, + buttons=('edit', 'delete'), + prepend_template=POWERPORT_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = PowerPort + fields = ( + 'pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'cable', 'cable_peer', + 'connection', 'tags', 'actions', + ) + default_columns = ( + 'pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'cable', 'connection', + 'actions', + ) + row_attrs = { + 'class': lambda record: record.cable.get_status_class() if record.cable else '' + } + + +class PowerOutletTable(DeviceComponentTable, PathEndpointTable): + power_port = tables.Column( + linkify=True + ) + tags = TagColumn( + url_name='dcim:poweroutlet_list' + ) + + class Meta(DeviceComponentTable.Meta): + model = PowerOutlet + fields = ( + 'pk', 'device', 'name', 'label', 'type', 'description', 'power_port', 'feed_leg', 'cable', 'cable_peer', + 'connection', 'tags', + ) + default_columns = ('pk', 'device', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description') + + +class DevicePowerOutletTable(PowerOutletTable): + name = tables.TemplateColumn( + template_code=' {{ value }}', + attrs={'td': {'class': 'text-nowrap'}} + ) + actions = ButtonsColumn( + model=PowerOutlet, + buttons=('edit', 'delete'), + prepend_template=POWEROUTLET_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = PowerOutlet + fields = ( + 'pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'cable', 'cable_peer', 'connection', + 'tags', 'actions', + ) + default_columns = ( + 'pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'cable', 'connection', 'actions', + ) + row_attrs = { + 'class': lambda record: record.cable.get_status_class() if record.cable else '' + } + + +class BaseInterfaceTable(BaseTable): + enabled = BooleanColumn() + ip_addresses = tables.TemplateColumn( + template_code=INTERFACE_IPADDRESSES, + orderable=False, + verbose_name='IP Addresses' + ) + untagged_vlan = tables.Column(linkify=True) + tagged_vlans = tables.TemplateColumn( + template_code=INTERFACE_TAGGED_VLANS, + orderable=False, + verbose_name='Tagged VLANs' + ) + + +class InterfaceTable(DeviceComponentTable, BaseInterfaceTable, PathEndpointTable): + tags = TagColumn( + url_name='dcim:interface_list' + ) + + class Meta(DeviceComponentTable.Meta): + model = Interface + fields = ( + 'pk', 'device', 'name', 'label', 'enabled', 'type', 'mgmt_only', 'mtu', 'mode', 'mac_address', + 'description', 'cable', 'cable_peer', 'connection', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans', + ) + default_columns = ('pk', 'device', 'name', 'label', 'enabled', 'type', 'description') + + +class DeviceInterfaceTable(InterfaceTable): + name = tables.TemplateColumn( + template_code=' {{ value }}', + attrs={'td': {'class': 'text-nowrap'}} + ) + lag = tables.Column( + linkify=True, + verbose_name='LAG' + ) + actions = ButtonsColumn( + model=Interface, + buttons=('edit', 'delete'), + prepend_template=INTERFACE_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = Interface + fields = ( + 'pk', 'name', 'label', 'enabled', 'type', 'lag', 'mgmt_only', 'mtu', 'mode', 'mac_address', 'description', + 'cable', 'cable_peer', 'connection', 'tags', 'ip_addresses', 'untagged_vlan', 'tagged_vlans', 'actions', + ) + default_columns = ( + 'pk', 'name', 'label', 'enabled', 'type', 'lag', 'mtu', 'mode', 'description', 'ip_addresses', 'cable', + 'connection', 'actions', + ) + row_attrs = { + 'class': lambda record: record.cable.get_status_class() if record.cable else '' + } + + +class FrontPortTable(DeviceComponentTable, CableTerminationTable): + rear_port_position = tables.Column( + verbose_name='Position' + ) + rear_port = tables.Column( + linkify=True + ) + tags = TagColumn( + url_name='dcim:frontport_list' + ) + + class Meta(DeviceComponentTable.Meta): + model = FrontPort + fields = ( + 'pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', + 'cable_peer', 'tags', + ) + default_columns = ('pk', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description') + + +class DeviceFrontPortTable(FrontPortTable): + name = tables.TemplateColumn( + template_code=' ' + '{{ value }}', + attrs={'td': {'class': 'text-nowrap'}} + ) + actions = ButtonsColumn( + model=FrontPort, + buttons=('edit', 'delete'), + prepend_template=FRONTPORT_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = FrontPort + fields = ( + 'pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'cable_peer', + 'tags', 'actions', + ) + default_columns = ( + 'pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'cable', 'cable_peer', + 'actions', + ) + row_attrs = { + 'class': lambda record: record.cable.get_status_class() if record.cable else '' + } + + +class RearPortTable(DeviceComponentTable, CableTerminationTable): + tags = TagColumn( + url_name='dcim:rearport_list' + ) + + class Meta(DeviceComponentTable.Meta): + model = RearPort + fields = ('pk', 'device', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'tags') + default_columns = ('pk', 'device', 'name', 'label', 'type', 'description') + + +class DeviceRearPortTable(RearPortTable): + name = tables.TemplateColumn( + template_code=' ' + '{{ value }}', + attrs={'td': {'class': 'text-nowrap'}} + ) + actions = ButtonsColumn( + model=RearPort, + buttons=('edit', 'delete'), + prepend_template=REARPORT_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = RearPort + fields = ( + 'pk', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'tags', 'actions', + ) + default_columns = ( + 'pk', 'name', 'label', 'type', 'positions', 'description', 'cable', 'cable_peer', 'actions', + ) + row_attrs = { + 'class': lambda record: record.cable.get_status_class() if record.cable else '' + } + + +class DeviceBayTable(DeviceComponentTable): + status = tables.TemplateColumn( + template_code=DEVICEBAY_STATUS + ) + installed_device = tables.Column( + linkify=True + ) + tags = TagColumn( + url_name='dcim:devicebay_list' + ) + + class Meta(DeviceComponentTable.Meta): + model = DeviceBay + fields = ('pk', 'device', 'name', 'label', 'status', 'installed_device', 'description', 'tags') + default_columns = ('pk', 'device', 'name', 'label', 'status', 'installed_device', 'description') + + +class DeviceDeviceBayTable(DeviceBayTable): + name = tables.TemplateColumn( + template_code=' {{ value }}', + attrs={'td': {'class': 'text-nowrap'}} + ) + actions = ButtonsColumn( + model=DeviceBay, + buttons=('edit', 'delete'), + prepend_template=DEVICEBAY_BUTTONS + ) + + class Meta(DeviceComponentTable.Meta): + model = DeviceBay + fields = ( + 'pk', 'name', 'label', 'status', 'installed_device', 'description', 'tags', 'actions', + ) + default_columns = ( + 'pk', 'name', 'label', 'status', 'installed_device', 'description', 'actions', + ) + + +class InventoryItemTable(DeviceComponentTable): + manufacturer = tables.Column( + linkify=True + ) + discovered = BooleanColumn() + tags = TagColumn( + url_name='dcim:inventoryitem_list' + ) + cable = None # Override DeviceComponentTable + + class Meta(DeviceComponentTable.Meta): + model = InventoryItem + fields = ( + 'pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', + 'discovered', 'tags', + ) + default_columns = ('pk', 'device', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag') + + +class DeviceInventoryItemTable(InventoryItemTable): + name = tables.TemplateColumn( + template_code='' + '{{ value }}', + attrs={'td': {'class': 'text-nowrap'}} + ) + actions = ButtonsColumn( + model=InventoryItem, + buttons=('edit', 'delete') + ) + + class Meta(DeviceComponentTable.Meta): + model = InventoryItem + fields = ( + 'pk', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'discovered', + 'tags', 'actions', + ) + default_columns = ( + 'pk', 'name', 'label', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'discovered', + 'actions', + ) + + +# +# Virtual chassis +# + +class VirtualChassisTable(BaseTable): + pk = ToggleColumn() + name = tables.Column( + linkify=True + ) + master = tables.Column( + linkify=True + ) + member_count = LinkedCountColumn( + viewname='dcim:device_list', + url_params={'virtual_chassis_id': 'pk'}, + verbose_name='Members' + ) + tags = TagColumn( + url_name='dcim:virtualchassis_list' + ) + + class Meta(BaseTable.Meta): + model = VirtualChassis + fields = ('pk', 'name', 'domain', 'master', 'member_count', 'tags') + default_columns = ('pk', 'name', 'domain', 'master', 'member_count') diff --git a/netbox/dcim/tables/devicetypes.py b/netbox/dcim/tables/devicetypes.py new file mode 100644 index 0000000000..c4d618cd73 --- /dev/null +++ b/netbox/dcim/tables/devicetypes.py @@ -0,0 +1,200 @@ +import django_tables2 as tables + +from dcim.models import ( + ConsolePortTemplate, ConsoleServerPortTemplate, DeviceBayTemplate, DeviceType, FrontPortTemplate, InterfaceTemplate, + Manufacturer, PowerOutletTemplate, PowerPortTemplate, RearPortTemplate, +) +from utilities.tables import BaseTable, BooleanColumn, ButtonsColumn, LinkedCountColumn, TagColumn, ToggleColumn + +__all__ = ( + 'ConsolePortTemplateTable', + 'ConsoleServerPortTemplateTable', + 'DeviceBayTemplateTable', + 'DeviceTypeTable', + 'FrontPortTemplateTable', + 'InterfaceTemplateTable', + 'ManufacturerTable', + 'PowerOutletTemplateTable', + 'PowerPortTemplateTable', + 'RearPortTemplateTable', +) + + +# +# Manufacturers +# + +class ManufacturerTable(BaseTable): + pk = ToggleColumn() + name = tables.LinkColumn() + devicetype_count = tables.Column( + verbose_name='Device Types' + ) + inventoryitem_count = tables.Column( + verbose_name='Inventory Items' + ) + platform_count = tables.Column( + verbose_name='Platforms' + ) + slug = tables.Column() + actions = ButtonsColumn(Manufacturer, pk_field='slug') + + class Meta(BaseTable.Meta): + model = Manufacturer + fields = ( + 'pk', 'name', 'devicetype_count', 'inventoryitem_count', 'platform_count', 'description', 'slug', 'actions', + ) + + +# +# Device types +# + +class DeviceTypeTable(BaseTable): + pk = ToggleColumn() + model = tables.Column( + linkify=True, + verbose_name='Device Type' + ) + is_full_depth = BooleanColumn( + verbose_name='Full Depth' + ) + instance_count = LinkedCountColumn( + viewname='dcim:device_list', + url_params={'device_type_id': 'pk'}, + verbose_name='Instances' + ) + tags = TagColumn( + url_name='dcim:devicetype_list' + ) + + class Meta(BaseTable.Meta): + model = DeviceType + fields = ( + 'pk', 'model', 'manufacturer', 'slug', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role', + 'instance_count', 'tags', + ) + default_columns = ( + 'pk', 'model', 'manufacturer', 'part_number', 'u_height', 'is_full_depth', 'instance_count', + ) + + +# +# Device type components +# + +class ComponentTemplateTable(BaseTable): + pk = ToggleColumn() + name = tables.Column( + order_by=('_name',) + ) + + +class ConsolePortTemplateTable(ComponentTemplateTable): + actions = ButtonsColumn( + model=ConsolePortTemplate, + buttons=('edit', 'delete'), + return_url_extra='%23tab_consoleports' + ) + + class Meta(BaseTable.Meta): + model = ConsolePortTemplate + fields = ('pk', 'name', 'label', 'type', 'description', 'actions') + empty_text = "None" + + +class ConsoleServerPortTemplateTable(ComponentTemplateTable): + actions = ButtonsColumn( + model=ConsoleServerPortTemplate, + buttons=('edit', 'delete'), + return_url_extra='%23tab_consoleserverports' + ) + + class Meta(BaseTable.Meta): + model = ConsoleServerPortTemplate + fields = ('pk', 'name', 'label', 'type', 'description', 'actions') + empty_text = "None" + + +class PowerPortTemplateTable(ComponentTemplateTable): + actions = ButtonsColumn( + model=PowerPortTemplate, + buttons=('edit', 'delete'), + return_url_extra='%23tab_powerports' + ) + + class Meta(BaseTable.Meta): + model = PowerPortTemplate + fields = ('pk', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'actions') + empty_text = "None" + + +class PowerOutletTemplateTable(ComponentTemplateTable): + actions = ButtonsColumn( + model=PowerOutletTemplate, + buttons=('edit', 'delete'), + return_url_extra='%23tab_poweroutlets' + ) + + class Meta(BaseTable.Meta): + model = PowerOutletTemplate + fields = ('pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'actions') + empty_text = "None" + + +class InterfaceTemplateTable(ComponentTemplateTable): + mgmt_only = BooleanColumn( + verbose_name='Management Only' + ) + actions = ButtonsColumn( + model=InterfaceTemplate, + buttons=('edit', 'delete'), + return_url_extra='%23tab_interfaces' + ) + + class Meta(BaseTable.Meta): + model = InterfaceTemplate + fields = ('pk', 'name', 'label', 'mgmt_only', 'type', 'description', 'actions') + empty_text = "None" + + +class FrontPortTemplateTable(ComponentTemplateTable): + rear_port_position = tables.Column( + verbose_name='Position' + ) + actions = ButtonsColumn( + model=FrontPortTemplate, + buttons=('edit', 'delete'), + return_url_extra='%23tab_frontports' + ) + + class Meta(BaseTable.Meta): + model = FrontPortTemplate + fields = ('pk', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description', 'actions') + empty_text = "None" + + +class RearPortTemplateTable(ComponentTemplateTable): + actions = ButtonsColumn( + model=RearPortTemplate, + buttons=('edit', 'delete'), + return_url_extra='%23tab_rearports' + ) + + class Meta(BaseTable.Meta): + model = RearPortTemplate + fields = ('pk', 'name', 'label', 'type', 'positions', 'description', 'actions') + empty_text = "None" + + +class DeviceBayTemplateTable(ComponentTemplateTable): + actions = ButtonsColumn( + model=DeviceBayTemplate, + buttons=('edit', 'delete'), + return_url_extra='%23tab_devicebays' + ) + + class Meta(BaseTable.Meta): + model = DeviceBayTemplate + fields = ('pk', 'name', 'label', 'description', 'actions') + empty_text = "None" diff --git a/netbox/dcim/tables/power.py b/netbox/dcim/tables/power.py new file mode 100644 index 0000000000..ae5c2a5c81 --- /dev/null +++ b/netbox/dcim/tables/power.py @@ -0,0 +1,77 @@ +import django_tables2 as tables +from django_tables2.utils import Accessor + +from dcim.models import PowerFeed, PowerPanel +from utilities.tables import BaseTable, ChoiceFieldColumn, LinkedCountColumn, TagColumn, ToggleColumn +from .devices import CableTerminationTable +from .template_code import POWERFEED_CABLE, POWERFEED_CABLETERMINATION + +__all__ = ( + 'PowerFeedTable', + 'PowerPanelTable', +) + + +# +# Power panels +# + +class PowerPanelTable(BaseTable): + pk = ToggleColumn() + name = tables.LinkColumn() + site = tables.LinkColumn( + viewname='dcim:site', + args=[Accessor('site__slug')] + ) + powerfeed_count = LinkedCountColumn( + viewname='dcim:powerfeed_list', + url_params={'power_panel_id': 'pk'}, + verbose_name='Feeds' + ) + tags = TagColumn( + url_name='dcim:powerpanel_list' + ) + + class Meta(BaseTable.Meta): + model = PowerPanel + fields = ('pk', 'name', 'site', 'rack_group', 'powerfeed_count', 'tags') + default_columns = ('pk', 'name', 'site', 'rack_group', 'powerfeed_count') + + +# +# Power feeds +# + +# We're not using PathEndpointTable for PowerFeed because power connections +# cannot traverse pass-through ports. +class PowerFeedTable(CableTerminationTable): + pk = ToggleColumn() + name = tables.LinkColumn() + power_panel = tables.Column( + linkify=True + ) + rack = tables.Column( + linkify=True + ) + status = ChoiceFieldColumn() + type = ChoiceFieldColumn() + max_utilization = tables.TemplateColumn( + template_code="{{ value }}%" + ) + available_power = tables.Column( + verbose_name='Available power (VA)' + ) + tags = TagColumn( + url_name='dcim:powerfeed_list' + ) + + class Meta(BaseTable.Meta): + model = PowerFeed + fields = ( + 'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase', + 'max_utilization', 'cable', 'cable_peer', 'connection', 'available_power', 'tags', + ) + default_columns = ( + 'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase', 'cable', + 'cable_peer', + ) diff --git a/netbox/dcim/tables/racks.py b/netbox/dcim/tables/racks.py new file mode 100644 index 0000000000..85943dd0d0 --- /dev/null +++ b/netbox/dcim/tables/racks.py @@ -0,0 +1,170 @@ +import django_tables2 as tables +from django_tables2.utils import Accessor + +from dcim.models import Rack, RackGroup, RackReservation, RackRole +from tenancy.tables import COL_TENANT +from utilities.tables import ( + BaseTable, ButtonsColumn, ChoiceFieldColumn, ColorColumn, ColoredLabelColumn, LinkedCountColumn, TagColumn, + ToggleColumn, +) +from .template_code import MPTT_LINK, RACKGROUP_ELEVATIONS, UTILIZATION_GRAPH + +__all__ = ( + 'RackTable', + 'RackDetailTable', + 'RackGroupTable', + 'RackReservationTable', + 'RackRoleTable', +) + + +# +# Rack groups +# + +class RackGroupTable(BaseTable): + pk = ToggleColumn() + name = tables.TemplateColumn( + template_code=MPTT_LINK, + orderable=False + ) + site = tables.LinkColumn( + viewname='dcim:site', + args=[Accessor('site__slug')], + verbose_name='Site' + ) + rack_count = tables.Column( + verbose_name='Racks' + ) + actions = ButtonsColumn( + model=RackGroup, + prepend_template=RACKGROUP_ELEVATIONS + ) + + class Meta(BaseTable.Meta): + model = RackGroup + fields = ('pk', 'name', 'site', 'rack_count', 'description', 'slug', 'actions') + default_columns = ('pk', 'name', 'site', 'rack_count', 'description', 'actions') + + +# +# Rack roles +# + +class RackRoleTable(BaseTable): + pk = ToggleColumn() + name = tables.Column(linkify=True) + rack_count = tables.Column(verbose_name='Racks') + color = ColorColumn() + actions = ButtonsColumn(RackRole) + + class Meta(BaseTable.Meta): + model = RackRole + fields = ('pk', 'name', 'rack_count', 'color', 'description', 'slug', 'actions') + default_columns = ('pk', 'name', 'rack_count', 'color', 'description', 'actions') + + +# +# Racks +# + +class RackTable(BaseTable): + pk = ToggleColumn() + name = tables.Column( + order_by=('_name',), + linkify=True + ) + group = tables.Column( + linkify=True + ) + site = tables.Column( + linkify=True + ) + tenant = tables.TemplateColumn( + template_code=COL_TENANT + ) + status = ChoiceFieldColumn() + role = ColoredLabelColumn() + u_height = tables.TemplateColumn( + template_code="{{ record.u_height }}U", + verbose_name='Height' + ) + + class Meta(BaseTable.Meta): + model = Rack + fields = ( + 'pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'serial', 'asset_tag', 'type', + 'width', 'u_height', + ) + default_columns = ('pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'u_height') + + +class RackDetailTable(RackTable): + device_count = LinkedCountColumn( + viewname='dcim:device_list', + url_params={'rack_id': 'pk'}, + verbose_name='Devices' + ) + get_utilization = tables.TemplateColumn( + template_code=UTILIZATION_GRAPH, + orderable=False, + verbose_name='Space' + ) + get_power_utilization = tables.TemplateColumn( + template_code=UTILIZATION_GRAPH, + orderable=False, + verbose_name='Power' + ) + tags = TagColumn( + url_name='dcim:rack_list' + ) + + class Meta(RackTable.Meta): + fields = ( + 'pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'serial', 'asset_tag', 'type', + 'width', 'u_height', 'device_count', 'get_utilization', 'get_power_utilization', 'tags', + ) + default_columns = ( + 'pk', 'name', 'site', 'group', 'status', 'facility_id', 'tenant', 'role', 'u_height', 'device_count', + 'get_utilization', 'get_power_utilization', + ) + + +# +# Rack reservations +# + +class RackReservationTable(BaseTable): + pk = ToggleColumn() + reservation = tables.Column( + accessor='pk', + linkify=True + ) + site = tables.Column( + accessor=Accessor('rack__site'), + linkify=True + ) + tenant = tables.TemplateColumn( + template_code=COL_TENANT + ) + rack = tables.Column( + linkify=True + ) + unit_list = tables.Column( + orderable=False, + verbose_name='Units' + ) + tags = TagColumn( + url_name='dcim:rackreservation_list' + ) + actions = ButtonsColumn(RackReservation) + + class Meta(BaseTable.Meta): + model = RackReservation + fields = ( + 'pk', 'reservation', 'site', 'rack', 'unit_list', 'user', 'created', 'tenant', 'description', 'tags', + 'actions', + ) + default_columns = ( + 'pk', 'reservation', 'site', 'rack', 'unit_list', 'user', 'description', 'actions', + ) diff --git a/netbox/dcim/tables/sites.py b/netbox/dcim/tables/sites.py new file mode 100644 index 0000000000..76f30f507c --- /dev/null +++ b/netbox/dcim/tables/sites.py @@ -0,0 +1,62 @@ +import django_tables2 as tables + +from dcim.models import Region, Site +from tenancy.tables import COL_TENANT +from utilities.tables import BaseTable, ButtonsColumn, ChoiceFieldColumn, TagColumn, ToggleColumn +from .template_code import MPTT_LINK + +__all__ = ( + 'RegionTable', + 'SiteTable', +) + + +# +# Regions +# + +class RegionTable(BaseTable): + pk = ToggleColumn() + name = tables.TemplateColumn( + template_code=MPTT_LINK, + orderable=False + ) + site_count = tables.Column( + verbose_name='Sites' + ) + actions = ButtonsColumn(Region) + + class Meta(BaseTable.Meta): + model = Region + fields = ('pk', 'name', 'slug', 'site_count', 'description', 'actions') + default_columns = ('pk', 'name', 'site_count', 'description', 'actions') + + +# +# Sites +# + +class SiteTable(BaseTable): + pk = ToggleColumn() + name = tables.LinkColumn( + order_by=('_name',) + ) + status = ChoiceFieldColumn() + region = tables.Column( + linkify=True + ) + tenant = tables.TemplateColumn( + template_code=COL_TENANT + ) + tags = TagColumn( + url_name='dcim:site_list' + ) + + class Meta(BaseTable.Meta): + model = Site + fields = ( + 'pk', 'name', 'slug', 'status', 'facility', 'region', 'tenant', 'asn', 'time_zone', 'description', + 'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name', 'contact_phone', + 'contact_email', 'tags', + ) + default_columns = ('pk', 'name', 'status', 'facility', 'region', 'tenant', 'asn', 'description') diff --git a/netbox/dcim/tables/template_code.py b/netbox/dcim/tables/template_code.py new file mode 100644 index 0000000000..4a5aedb29a --- /dev/null +++ b/netbox/dcim/tables/template_code.py @@ -0,0 +1,251 @@ +CABLETERMINATION = """ +{% if value %} + {{ value.parent }} + + {{ value }} +{% else %} + — +{% endif %} +""" + +CABLE_LENGTH = """ +{% if record.length %}{{ record.length }} {{ record.get_length_unit_display }}{% else %}—{% endif %} +""" + +CABLE_TERMINATION_PARENT = """ +{% if value.device %} + {{ value.device }} +{% elif value.circuit %} + {{ value.circuit }} +{% elif value.power_panel %} + {{ value.power_panel }} +{% endif %} +""" + +DEVICE_LINK = """ + + {{ record.name|default:'Unnamed device' }} + +""" + +DEVICEBAY_STATUS = """ +{% if record.installed_device_id %} + + {{ record.installed_device.get_status_display }} + +{% else %} + Vacant +{% endif %} +""" + +INTERFACE_IPADDRESSES = """ +{% for ip in record.ip_addresses.all %} + {{ ip }}
+{% endfor %} +""" + +INTERFACE_TAGGED_VLANS = """ +{% if record.mode == 'tagged' %} + {% for vlan in record.tagged_vlans.all %} + {{ vlan }}
+ {% endfor %} +{% elif record.mode == 'tagged-all' %} + All +{% else %} + — +{% endif %} +""" + +MPTT_LINK = """ +{% if record.get_children %} + +{% else %} + +{% endif %} + {{ record.name }} + +""" + +POWERFEED_CABLE = """ +{{ value }} + + + +""" + +POWERFEED_CABLETERMINATION = """ +{{ value.parent }} + +{{ value }} +""" + +RACKGROUP_ELEVATIONS = """ + + + +""" + +UTILIZATION_GRAPH = """ +{% load helpers %} +{% utilization_graph value %} +""" + +# +# Device component buttons +# + +CONSOLEPORT_BUTTONS = """ +{% if record.cable %} + + {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} +{% elif perms.dcim.add_cable %} + + + + + + +{% endif %} +""" + +CONSOLESERVERPORT_BUTTONS = """ +{% if record.cable %} + + {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} +{% elif perms.dcim.add_cable %} + + + + + + +{% endif %} +""" + +POWERPORT_BUTTONS = """ +{% if record.cable %} + + {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} +{% elif perms.dcim.add_cable %} + + + + + + +{% endif %} +""" + +POWEROUTLET_BUTTONS = """ +{% if record.cable %} + + {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} +{% elif perms.dcim.add_cable %} + + + + + +{% endif %} +""" + +INTERFACE_BUTTONS = """ +{% if perms.ipam.add_ipaddress %} + + + +{% endif %} +{% if record.cable %} + + {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} +{% elif record.is_connectable and perms.dcim.add_cable %} + + + + + + +{% endif %} +""" + +FRONTPORT_BUTTONS = """ +{% if record.cable %} + + {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} +{% elif perms.dcim.add_cable %} + + + + + + +{% endif %} +""" + +REARPORT_BUTTONS = """ +{% if record.cable %} + + {% include 'dcim/inc/cable_toggle_buttons.html' with cable=record.cable %} +{% elif perms.dcim.add_cable %} + + + + + + +{% endif %} +""" + +DEVICEBAY_BUTTONS = """ +{% if perms.dcim.change_devicebay %} + {% if record.installed_device %} + + + + {% else %} + + + + {% endif %} +{% endif %} +""" diff --git a/netbox/dcim/tests/test_api.py b/netbox/dcim/tests/test_api.py index c3ffecdfff..77c3b47862 100644 --- a/netbox/dcim/tests/test_api.py +++ b/netbox/dcim/tests/test_api.py @@ -1,10 +1,7 @@ from django.contrib.auth.models import User -from django.contrib.contenttypes.models import ContentType -from django.test import override_settings from django.urls import reverse from rest_framework import status -from circuits.models import Circuit, CircuitTermination, CircuitType, Provider from dcim.choices import * from dcim.constants import * from dcim.models import ( @@ -14,7 +11,6 @@ Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site, VirtualChassis, ) from ipam.models import VLAN -from extras.models import Graph from utilities.testing import APITestCase, APIViewTestCases from virtualization.models import Cluster, ClusterType @@ -83,6 +79,9 @@ class RegionTest(APIViewTestCases.APIViewTestCase): 'slug': 'region-6', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -95,6 +94,9 @@ def setUpTestData(cls): class SiteTest(APIViewTestCases.APIViewTestCase): model = Site brief_fields = ['id', 'name', 'slug', 'url'] + bulk_update_data = { + 'status': 'planned', + } @classmethod def setUpTestData(cls): @@ -132,30 +134,13 @@ def setUpTestData(cls): }, ] - @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) - def test_get_site_graphs(self): - """ - Test retrieval of Graphs assigned to Sites. - """ - ct = ContentType.objects.get_for_model(Site) - graphs = ( - Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?site={{ obj.slug }}&foo=1'), - Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?site={{ obj.slug }}&foo=2'), - Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?site={{ obj.slug }}&foo=3'), - ) - Graph.objects.bulk_create(graphs) - - self.add_permissions('dcim.view_site') - url = reverse('dcim-api:site-graphs', kwargs={'pk': Site.objects.first().pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(len(response.data), 3) - self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?site=site-1&foo=1') - class RackGroupTest(APIViewTestCases.APIViewTestCase): model = RackGroup brief_fields = ['_depth', 'id', 'name', 'rack_count', 'slug', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -217,6 +202,9 @@ class RackRoleTest(APIViewTestCases.APIViewTestCase): 'color': 'ffff00', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -232,6 +220,9 @@ def setUpTestData(cls): class RackTest(APIViewTestCases.APIViewTestCase): model = Rack brief_fields = ['device_count', 'display_name', 'id', 'name', 'url'] + bulk_update_data = { + 'status': 'planned', + } @classmethod def setUpTestData(cls): @@ -317,6 +308,9 @@ def test_get_rack_elevation_svg(self): class RackReservationTest(APIViewTestCases.APIViewTestCase): model = RackReservation brief_fields = ['id', 'units', 'url', 'user'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -379,6 +373,9 @@ class ManufacturerTest(APIViewTestCases.APIViewTestCase): 'slug': 'manufacturer-6', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -394,6 +391,9 @@ def setUpTestData(cls): class DeviceTypeTest(APIViewTestCases.APIViewTestCase): model = DeviceType brief_fields = ['device_count', 'display_name', 'id', 'manufacturer', 'model', 'slug', 'url'] + bulk_update_data = { + 'part_number': 'ABC123', + } @classmethod def setUpTestData(cls): @@ -433,6 +433,9 @@ def setUpTestData(cls): class ConsolePortTemplateTest(APIViewTestCases.APIViewTestCase): model = ConsolePortTemplate brief_fields = ['id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -467,6 +470,9 @@ def setUpTestData(cls): class ConsoleServerPortTemplateTest(APIViewTestCases.APIViewTestCase): model = ConsoleServerPortTemplate brief_fields = ['id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -501,6 +507,9 @@ def setUpTestData(cls): class PowerPortTemplateTest(APIViewTestCases.APIViewTestCase): model = PowerPortTemplate brief_fields = ['id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -535,6 +544,9 @@ def setUpTestData(cls): class PowerOutletTemplateTest(APIViewTestCases.APIViewTestCase): model = PowerOutletTemplate brief_fields = ['id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -569,6 +581,9 @@ def setUpTestData(cls): class InterfaceTemplateTest(APIViewTestCases.APIViewTestCase): model = InterfaceTemplate brief_fields = ['id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -606,6 +621,9 @@ def setUpTestData(cls): class FrontPortTemplateTest(APIViewTestCases.APIViewTestCase): model = FrontPortTemplate brief_fields = ['id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -652,21 +670,21 @@ def setUpTestData(cls): 'name': 'Front Port Template 4', 'type': PortTypeChoices.TYPE_8P8C, 'rear_port': rear_port_templates[3].pk, - 'position': 1, + 'rear_port_position': 1, }, { 'device_type': devicetype.pk, 'name': 'Front Port Template 5', 'type': PortTypeChoices.TYPE_8P8C, 'rear_port': rear_port_templates[4].pk, - 'position': 1, + 'rear_port_position': 1, }, { 'device_type': devicetype.pk, 'name': 'Front Port Template 6', 'type': PortTypeChoices.TYPE_8P8C, 'rear_port': rear_port_templates[5].pk, - 'position': 1, + 'rear_port_position': 1, }, ] @@ -674,6 +692,9 @@ def setUpTestData(cls): class RearPortTemplateTest(APIViewTestCases.APIViewTestCase): model = RearPortTemplate brief_fields = ['id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -711,6 +732,9 @@ def setUpTestData(cls): class DeviceBayTemplateTest(APIViewTestCases.APIViewTestCase): model = DeviceBayTemplate brief_fields = ['id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -762,6 +786,9 @@ class DeviceRoleTest(APIViewTestCases.APIViewTestCase): 'color': 'ffff00', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -791,6 +818,9 @@ class PlatformTest(APIViewTestCases.APIViewTestCase): 'slug': 'platform-6', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -806,6 +836,9 @@ def setUpTestData(cls): class DeviceTest(APIViewTestCases.APIViewTestCase): model = Device brief_fields = ['display_name', 'id', 'name', 'url'] + bulk_update_data = { + 'status': 'failed', + } @classmethod def setUpTestData(cls): @@ -902,26 +935,6 @@ def setUpTestData(cls): }, ] - @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) - def test_get_device_graphs(self): - """ - Test retrieval of Graphs assigned to Devices. - """ - ct = ContentType.objects.get_for_model(Device) - graphs = ( - Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?device={{ obj.name }}&foo=1'), - Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?device={{ obj.name }}&foo=2'), - Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?device={{ obj.name }}&foo=3'), - ) - Graph.objects.bulk_create(graphs) - - self.add_permissions('dcim.view_device') - url = reverse('dcim-api:device-graphs', kwargs={'pk': Device.objects.first().pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(len(response.data), 3) - self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?device=Device 1&foo=1') - def test_config_context_included_by_default_in_list_view(self): """ Check that config context data is included by default in the devices list. @@ -963,7 +976,10 @@ def test_unique_name_per_site_constraint(self): class ConsolePortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): model = ConsolePort - brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url'] + brief_fields = ['cable', 'device', 'id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } peer_termination_type = ConsoleServerPort @classmethod @@ -999,7 +1015,10 @@ def setUpTestData(cls): class ConsoleServerPortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): model = ConsoleServerPort - brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url'] + brief_fields = ['cable', 'device', 'id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } peer_termination_type = ConsolePort @classmethod @@ -1035,7 +1054,10 @@ def setUpTestData(cls): class PowerPortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): model = PowerPort - brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url'] + brief_fields = ['cable', 'device', 'id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } peer_termination_type = PowerOutlet @classmethod @@ -1071,7 +1093,10 @@ def setUpTestData(cls): class PowerOutletTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): model = PowerOutlet - brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url'] + brief_fields = ['cable', 'device', 'id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } peer_termination_type = PowerPort @classmethod @@ -1107,7 +1132,10 @@ def setUpTestData(cls): class InterfaceTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): model = Interface - brief_fields = ['cable', 'connection_status', 'device', 'id', 'name', 'url'] + brief_fields = ['cable', 'device', 'id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } peer_termination_type = Interface @classmethod @@ -1159,30 +1187,13 @@ def setUpTestData(cls): }, ] - @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) - def test_get_interface_graphs(self): - """ - Test retrieval of Graphs assigned to Devices. - """ - ct = ContentType.objects.get_for_model(Interface) - graphs = ( - Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?interface={{ obj.name }}&foo=1'), - Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?interface={{ obj.name }}&foo=2'), - Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?interface={{ obj.name }}&foo=3'), - ) - Graph.objects.bulk_create(graphs) - - self.add_permissions('dcim.view_interface') - url = reverse('dcim-api:interface-graphs', kwargs={'pk': Interface.objects.first().pk}) - response = self.client.get(url, **self.header) - - self.assertEqual(len(response.data), 3) - self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?interface=Interface 1&foo=1') - -class FrontPortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): +class FrontPortTest(APIViewTestCases.APIViewTestCase): model = FrontPort brief_fields = ['cable', 'device', 'id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } peer_termination_type = Interface @classmethod @@ -1235,9 +1246,12 @@ def setUpTestData(cls): ] -class RearPortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase): +class RearPortTest(APIViewTestCases.APIViewTestCase): model = RearPort brief_fields = ['cable', 'device', 'id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } peer_termination_type = Interface @classmethod @@ -1277,6 +1291,9 @@ def setUpTestData(cls): class DeviceBayTest(APIViewTestCases.APIViewTestCase): model = DeviceBay brief_fields = ['device', 'id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -1336,7 +1353,10 @@ def setUpTestData(cls): class InventoryItemTest(APIViewTestCases.APIViewTestCase): model = InventoryItem - brief_fields = ['device', 'id', 'name', 'url'] + brief_fields = ['_depth', 'device', 'id', 'name', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -1346,12 +1366,9 @@ def setUpTestData(cls): devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000') device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site) - inventory_items = ( - InventoryItem(device=device, name='Inventory Item 1', manufacturer=manufacturer), - InventoryItem(device=device, name='Inventory Item 2', manufacturer=manufacturer), - InventoryItem(device=device, name='Inventory Item 3', manufacturer=manufacturer), - ) - InventoryItem.objects.bulk_create(inventory_items) + InventoryItem.objects.create(device=device, name='Inventory Item 1', manufacturer=manufacturer) + InventoryItem.objects.create(device=device, name='Inventory Item 2', manufacturer=manufacturer) + InventoryItem.objects.create(device=device, name='Inventory Item 3', manufacturer=manufacturer) cls.create_data = [ { @@ -1375,6 +1392,10 @@ def setUpTestData(cls): class CableTest(APIViewTestCases.APIViewTestCase): model = Cable brief_fields = ['id', 'label', 'url'] + bulk_update_data = { + 'length': 100, + 'length_unit': 'm', + } # TODO: Allow updating cable terminations test_update_object = None @@ -1431,377 +1452,6 @@ def setUpTestData(cls): ] -class ConnectionTest(APITestCase): - - def setUp(self): - - super().setUp() - - self.site = Site.objects.create( - name='Test Site 1', slug='test-site-1' - ) - manufacturer = Manufacturer.objects.create( - name='Test Manufacturer 1', slug='test-manufacturer-1' - ) - devicetype = DeviceType.objects.create( - manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1' - ) - devicerole = DeviceRole.objects.create( - name='Test Device Role 1', slug='test-device-role-1', color='ff0000' - ) - self.device1 = Device.objects.create( - device_type=devicetype, device_role=devicerole, name='Test Device 1', site=self.site - ) - self.device2 = Device.objects.create( - device_type=devicetype, device_role=devicerole, name='Test Device 2', site=self.site - ) - self.panel1 = Device.objects.create( - device_type=devicetype, device_role=devicerole, name='Test Panel 1', site=self.site - ) - self.panel2 = Device.objects.create( - device_type=devicetype, device_role=devicerole, name='Test Panel 2', site=self.site - ) - - def test_create_direct_console_connection(self): - - consoleport1 = ConsolePort.objects.create( - device=self.device1, name='Test Console Port 1' - ) - consoleserverport1 = ConsoleServerPort.objects.create( - device=self.device2, name='Test Console Server Port 1' - ) - - data = { - 'termination_a_type': 'dcim.consoleport', - 'termination_a_id': consoleport1.pk, - 'termination_b_type': 'dcim.consoleserverport', - 'termination_b_id': consoleserverport1.pk, - } - - self.add_permissions('dcim.add_cable') - url = reverse('dcim-api:cable-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Cable.objects.count(), 1) - - cable = Cable.objects.get(pk=response.data['id']) - consoleport1 = ConsolePort.objects.get(pk=consoleport1.pk) - consoleserverport1 = ConsoleServerPort.objects.get(pk=consoleserverport1.pk) - - self.assertEqual(cable.termination_a, consoleport1) - self.assertEqual(cable.termination_b, consoleserverport1) - self.assertEqual(consoleport1.cable, cable) - self.assertEqual(consoleserverport1.cable, cable) - self.assertEqual(consoleport1.connected_endpoint, consoleserverport1) - self.assertEqual(consoleserverport1.connected_endpoint, consoleport1) - - def test_create_patched_console_connection(self): - - consoleport1 = ConsolePort.objects.create( - device=self.device1, name='Test Console Port 1' - ) - consoleserverport1 = ConsoleServerPort.objects.create( - device=self.device2, name='Test Console Server Port 1' - ) - rearport1 = RearPort.objects.create( - device=self.panel1, name='Test Rear Port 1', type=PortTypeChoices.TYPE_8P8C - ) - frontport1 = FrontPort.objects.create( - device=self.panel1, name='Test Front Port 1', type=PortTypeChoices.TYPE_8P8C, rear_port=rearport1 - ) - rearport2 = RearPort.objects.create( - device=self.panel2, name='Test Rear Port 2', type=PortTypeChoices.TYPE_8P8C - ) - frontport2 = FrontPort.objects.create( - device=self.panel2, name='Test Front Port 2', type=PortTypeChoices.TYPE_8P8C, rear_port=rearport2 - ) - - self.add_permissions('dcim.add_cable') - url = reverse('dcim-api:cable-list') - cables = [ - # Console port to panel1 front - { - 'termination_a_type': 'dcim.consoleport', - 'termination_a_id': consoleport1.pk, - 'termination_b_type': 'dcim.frontport', - 'termination_b_id': frontport1.pk, - }, - # Panel1 rear to panel2 rear - { - 'termination_a_type': 'dcim.rearport', - 'termination_a_id': rearport1.pk, - 'termination_b_type': 'dcim.rearport', - 'termination_b_id': rearport2.pk, - }, - # Panel2 front to console server port - { - 'termination_a_type': 'dcim.frontport', - 'termination_a_id': frontport2.pk, - 'termination_b_type': 'dcim.consoleserverport', - 'termination_b_id': consoleserverport1.pk, - }, - ] - - for data in cables: - - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - - cable = Cable.objects.get(pk=response.data['id']) - self.assertEqual(cable.termination_a.cable, cable) - self.assertEqual(cable.termination_b.cable, cable) - - consoleport1 = ConsolePort.objects.get(pk=consoleport1.pk) - consoleserverport1 = ConsoleServerPort.objects.get(pk=consoleserverport1.pk) - self.assertEqual(consoleport1.connected_endpoint, consoleserverport1) - self.assertEqual(consoleserverport1.connected_endpoint, consoleport1) - - def test_create_direct_power_connection(self): - - powerport1 = PowerPort.objects.create( - device=self.device1, name='Test Power Port 1' - ) - poweroutlet1 = PowerOutlet.objects.create( - device=self.device2, name='Test Power Outlet 1' - ) - - data = { - 'termination_a_type': 'dcim.powerport', - 'termination_a_id': powerport1.pk, - 'termination_b_type': 'dcim.poweroutlet', - 'termination_b_id': poweroutlet1.pk, - } - - self.add_permissions('dcim.add_cable') - url = reverse('dcim-api:cable-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Cable.objects.count(), 1) - - cable = Cable.objects.get(pk=response.data['id']) - powerport1 = PowerPort.objects.get(pk=powerport1.pk) - poweroutlet1 = PowerOutlet.objects.get(pk=poweroutlet1.pk) - - self.assertEqual(cable.termination_a, powerport1) - self.assertEqual(cable.termination_b, poweroutlet1) - self.assertEqual(powerport1.cable, cable) - self.assertEqual(poweroutlet1.cable, cable) - self.assertEqual(powerport1.connected_endpoint, poweroutlet1) - self.assertEqual(poweroutlet1.connected_endpoint, powerport1) - - # Note: Power connections via patch ports are not supported. - - def test_create_direct_interface_connection(self): - - interface1 = Interface.objects.create( - device=self.device1, name='Test Interface 1' - ) - interface2 = Interface.objects.create( - device=self.device2, name='Test Interface 2' - ) - - data = { - 'termination_a_type': 'dcim.interface', - 'termination_a_id': interface1.pk, - 'termination_b_type': 'dcim.interface', - 'termination_b_id': interface2.pk, - } - - self.add_permissions('dcim.add_cable') - url = reverse('dcim-api:cable-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Cable.objects.count(), 1) - - cable = Cable.objects.get(pk=response.data['id']) - interface1 = Interface.objects.get(pk=interface1.pk) - interface2 = Interface.objects.get(pk=interface2.pk) - - self.assertEqual(cable.termination_a, interface1) - self.assertEqual(cable.termination_b, interface2) - self.assertEqual(interface1.cable, cable) - self.assertEqual(interface2.cable, cable) - self.assertEqual(interface1.connected_endpoint, interface2) - self.assertEqual(interface2.connected_endpoint, interface1) - - def test_create_patched_interface_connection(self): - - interface1 = Interface.objects.create( - device=self.device1, name='Test Interface 1' - ) - interface2 = Interface.objects.create( - device=self.device2, name='Test Interface 2' - ) - rearport1 = RearPort.objects.create( - device=self.panel1, name='Test Rear Port 1', type=PortTypeChoices.TYPE_8P8C - ) - frontport1 = FrontPort.objects.create( - device=self.panel1, name='Test Front Port 1', type=PortTypeChoices.TYPE_8P8C, rear_port=rearport1 - ) - rearport2 = RearPort.objects.create( - device=self.panel2, name='Test Rear Port 2', type=PortTypeChoices.TYPE_8P8C - ) - frontport2 = FrontPort.objects.create( - device=self.panel2, name='Test Front Port 2', type=PortTypeChoices.TYPE_8P8C, rear_port=rearport2 - ) - - self.add_permissions('dcim.add_cable') - url = reverse('dcim-api:cable-list') - cables = [ - # Interface1 to panel1 front - { - 'termination_a_type': 'dcim.interface', - 'termination_a_id': interface1.pk, - 'termination_b_type': 'dcim.frontport', - 'termination_b_id': frontport1.pk, - }, - # Panel1 rear to panel2 rear - { - 'termination_a_type': 'dcim.rearport', - 'termination_a_id': rearport1.pk, - 'termination_b_type': 'dcim.rearport', - 'termination_b_id': rearport2.pk, - }, - # Panel2 front to interface2 - { - 'termination_a_type': 'dcim.frontport', - 'termination_a_id': frontport2.pk, - 'termination_b_type': 'dcim.interface', - 'termination_b_id': interface2.pk, - }, - ] - - for data in cables: - - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - - cable = Cable.objects.get(pk=response.data['id']) - self.assertEqual(cable.termination_a.cable, cable) - self.assertEqual(cable.termination_b.cable, cable) - - interface1 = Interface.objects.get(pk=interface1.pk) - interface2 = Interface.objects.get(pk=interface2.pk) - self.assertEqual(interface1.connected_endpoint, interface2) - self.assertEqual(interface2.connected_endpoint, interface1) - - def test_create_direct_circuittermination_connection(self): - - provider = Provider.objects.create( - name='Test Provider 1', slug='test-provider-1' - ) - circuittype = CircuitType.objects.create( - name='Test Circuit Type 1', slug='test-circuit-type-1' - ) - circuit = Circuit.objects.create( - provider=provider, type=circuittype, cid='Test Circuit 1' - ) - interface1 = Interface.objects.create( - device=self.device1, name='Test Interface 1' - ) - circuittermination1 = CircuitTermination.objects.create( - circuit=circuit, term_side='A', site=self.site, port_speed=10000 - ) - - data = { - 'termination_a_type': 'dcim.interface', - 'termination_a_id': interface1.pk, - 'termination_b_type': 'circuits.circuittermination', - 'termination_b_id': circuittermination1.pk, - } - - self.add_permissions('dcim.add_cable') - url = reverse('dcim-api:cable-list') - response = self.client.post(url, data, format='json', **self.header) - - self.assertHttpStatus(response, status.HTTP_201_CREATED) - self.assertEqual(Cable.objects.count(), 1) - - cable = Cable.objects.get(pk=response.data['id']) - interface1 = Interface.objects.get(pk=interface1.pk) - circuittermination1 = CircuitTermination.objects.get(pk=circuittermination1.pk) - - self.assertEqual(cable.termination_a, interface1) - self.assertEqual(cable.termination_b, circuittermination1) - self.assertEqual(interface1.cable, cable) - self.assertEqual(circuittermination1.cable, cable) - self.assertEqual(interface1.connected_endpoint, circuittermination1) - self.assertEqual(circuittermination1.connected_endpoint, interface1) - - def test_create_patched_circuittermination_connection(self): - - provider = Provider.objects.create( - name='Test Provider 1', slug='test-provider-1' - ) - circuittype = CircuitType.objects.create( - name='Test Circuit Type 1', slug='test-circuit-type-1' - ) - circuit = Circuit.objects.create( - provider=provider, type=circuittype, cid='Test Circuit 1' - ) - interface1 = Interface.objects.create( - device=self.device1, name='Test Interface 1' - ) - circuittermination1 = CircuitTermination.objects.create( - circuit=circuit, term_side='A', site=self.site, port_speed=10000 - ) - rearport1 = RearPort.objects.create( - device=self.panel1, name='Test Rear Port 1', type=PortTypeChoices.TYPE_8P8C - ) - frontport1 = FrontPort.objects.create( - device=self.panel1, name='Test Front Port 1', type=PortTypeChoices.TYPE_8P8C, rear_port=rearport1 - ) - rearport2 = RearPort.objects.create( - device=self.panel2, name='Test Rear Port 2', type=PortTypeChoices.TYPE_8P8C - ) - frontport2 = FrontPort.objects.create( - device=self.panel2, name='Test Front Port 2', type=PortTypeChoices.TYPE_8P8C, rear_port=rearport2 - ) - - self.add_permissions('dcim.add_cable') - url = reverse('dcim-api:cable-list') - cables = [ - # Interface to panel1 front - { - 'termination_a_type': 'dcim.interface', - 'termination_a_id': interface1.pk, - 'termination_b_type': 'dcim.frontport', - 'termination_b_id': frontport1.pk, - }, - # Panel1 rear to panel2 rear - { - 'termination_a_type': 'dcim.rearport', - 'termination_a_id': rearport1.pk, - 'termination_b_type': 'dcim.rearport', - 'termination_b_id': rearport2.pk, - }, - # Panel2 front to circuit termination - { - 'termination_a_type': 'dcim.frontport', - 'termination_a_id': frontport2.pk, - 'termination_b_type': 'circuits.circuittermination', - 'termination_b_id': circuittermination1.pk, - }, - ] - - for data in cables: - - response = self.client.post(url, data, format='json', **self.header) - self.assertHttpStatus(response, status.HTTP_201_CREATED) - - cable = Cable.objects.get(pk=response.data['id']) - self.assertEqual(cable.termination_a.cable, cable) - self.assertEqual(cable.termination_b.cable, cable) - - interface1 = Interface.objects.get(pk=interface1.pk) - circuittermination1 = CircuitTermination.objects.get(pk=circuittermination1.pk) - self.assertEqual(interface1.connected_endpoint, circuittermination1) - self.assertEqual(circuittermination1.connected_endpoint, interface1) - - class ConnectedDeviceTest(APITestCase): def setUp(self): @@ -1888,10 +1538,13 @@ def setUpTestData(cls): VirtualChassis(name='Virtual Chassis 3', master=devices[6], domain='domain-3'), ) VirtualChassis.objects.bulk_create(virtual_chassis) + Device.objects.filter(pk=devices[0].pk).update(virtual_chassis=virtual_chassis[0], vc_position=1) Device.objects.filter(pk=devices[1].pk).update(virtual_chassis=virtual_chassis[0], vc_position=2) Device.objects.filter(pk=devices[2].pk).update(virtual_chassis=virtual_chassis[0], vc_position=3) + Device.objects.filter(pk=devices[3].pk).update(virtual_chassis=virtual_chassis[1], vc_position=1) Device.objects.filter(pk=devices[4].pk).update(virtual_chassis=virtual_chassis[1], vc_position=2) Device.objects.filter(pk=devices[5].pk).update(virtual_chassis=virtual_chassis[1], vc_position=3) + Device.objects.filter(pk=devices[6].pk).update(virtual_chassis=virtual_chassis[2], vc_position=1) Device.objects.filter(pk=devices[7].pk).update(virtual_chassis=virtual_chassis[2], vc_position=2) Device.objects.filter(pk=devices[8].pk).update(virtual_chassis=virtual_chassis[2], vc_position=3) @@ -1916,6 +1569,10 @@ def setUpTestData(cls): }, ] + cls.bulk_update_data = { + 'domain': 'newdomain', + } + class PowerPanelTest(APIViewTestCases.APIViewTestCase): model = PowerPanel @@ -1923,43 +1580,55 @@ class PowerPanelTest(APIViewTestCases.APIViewTestCase): @classmethod def setUpTestData(cls): - site = Site.objects.create(name='Site 1', slug='site-1') + sites = ( + Site.objects.create(name='Site 1', slug='site-1'), + Site.objects.create(name='Site 2', slug='site-2'), + ) rack_groups = ( - RackGroup.objects.create(name='Rack Group 1', slug='rack-group-1', site=site), - RackGroup.objects.create(name='Rack Group 2', slug='rack-group-2', site=site), - RackGroup.objects.create(name='Rack Group 3', slug='rack-group-3', site=site), + RackGroup.objects.create(name='Rack Group 1', slug='rack-group-1', site=sites[0]), + RackGroup.objects.create(name='Rack Group 2', slug='rack-group-2', site=sites[0]), + RackGroup.objects.create(name='Rack Group 3', slug='rack-group-3', site=sites[0]), + RackGroup.objects.create(name='Rack Group 4', slug='rack-group-3', site=sites[1]), ) power_panels = ( - PowerPanel(site=site, rack_group=rack_groups[0], name='Power Panel 1'), - PowerPanel(site=site, rack_group=rack_groups[1], name='Power Panel 2'), - PowerPanel(site=site, rack_group=rack_groups[2], name='Power Panel 3'), + PowerPanel(site=sites[0], rack_group=rack_groups[0], name='Power Panel 1'), + PowerPanel(site=sites[0], rack_group=rack_groups[1], name='Power Panel 2'), + PowerPanel(site=sites[0], rack_group=rack_groups[2], name='Power Panel 3'), ) PowerPanel.objects.bulk_create(power_panels) cls.create_data = [ { 'name': 'Power Panel 4', - 'site': site.pk, + 'site': sites[0].pk, 'rack_group': rack_groups[0].pk, }, { 'name': 'Power Panel 5', - 'site': site.pk, + 'site': sites[0].pk, 'rack_group': rack_groups[1].pk, }, { 'name': 'Power Panel 6', - 'site': site.pk, + 'site': sites[0].pk, 'rack_group': rack_groups[2].pk, }, ] + cls.bulk_update_data = { + 'site': sites[1].pk, + 'rack_group': rack_groups[3].pk + } + class PowerFeedTest(APIViewTestCases.APIViewTestCase): model = PowerFeed brief_fields = ['cable', 'id', 'name', 'url'] + bulk_update_data = { + 'status': 'planned', + } @classmethod def setUpTestData(cls): diff --git a/netbox/dcim/tests/test_cablepaths.py b/netbox/dcim/tests/test_cablepaths.py new file mode 100644 index 0000000000..37d7014f1f --- /dev/null +++ b/netbox/dcim/tests/test_cablepaths.py @@ -0,0 +1,923 @@ +from django.contrib.contenttypes.models import ContentType +from django.test import TestCase + +from circuits.models import * +from dcim.choices import CableStatusChoices +from dcim.models import * +from dcim.utils import object_to_path_node + + +class CablePathTestCase(TestCase): + """ + Test NetBox's ability to trace and retrace CablePaths in response to data model changes. Tests are numbered + as follows: + + 1XX: Test direct connections between different endpoint types + 2XX: Test different cable topologies + 3XX: Test responses to changes in existing objects + """ + @classmethod + def setUpTestData(cls): + + # Create a single device that will hold all components + cls.site = Site.objects.create(name='Site', slug='site') + + manufacturer = Manufacturer.objects.create(name='Generic', slug='generic') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Test Device') + device_role = DeviceRole.objects.create(name='Device Role', slug='device-role') + cls.device = Device.objects.create(site=cls.site, device_type=device_type, device_role=device_role, name='Test Device') + + cls.powerpanel = PowerPanel.objects.create(site=cls.site, name='Power Panel') + + provider = Provider.objects.create(name='Provider', slug='provider') + circuit_type = CircuitType.objects.create(name='Circuit Type', slug='circuit-type') + cls.circuit = Circuit.objects.create(provider=provider, type=circuit_type, cid='Circuit 1') + + def assertPathExists(self, origin, destination, path=None, is_active=None, msg=None): + """ + Assert that a CablePath from origin to destination with a specific intermediate path exists. + + :param origin: Originating endpoint + :param destination: Terminating endpoint, or None + :param path: Sequence of objects comprising the intermediate path (optional) + :param is_active: Boolean indicating whether the end-to-end path is complete and active (optional) + :param msg: Custom failure message (optional) + + :return: The matching CablePath (if any) + """ + kwargs = { + 'origin_type': ContentType.objects.get_for_model(origin), + 'origin_id': origin.pk, + } + if destination is not None: + kwargs['destination_type'] = ContentType.objects.get_for_model(destination) + kwargs['destination_id'] = destination.pk + else: + kwargs['destination_type__isnull'] = True + kwargs['destination_id__isnull'] = True + if path is not None: + kwargs['path'] = [object_to_path_node(obj) for obj in path] + if is_active is not None: + kwargs['is_active'] = is_active + if msg is None: + if destination is not None: + msg = f"Missing path from {origin} to {destination}" + else: + msg = f"Missing partial path originating from {origin}" + + cablepath = CablePath.objects.filter(**kwargs).first() + self.assertIsNotNone(cablepath, msg=msg) + + return cablepath + + def assertPathIsSet(self, origin, cablepath, msg=None): + """ + Assert that a specific CablePath instance is set as the path on the origin. + + :param origin: The originating path endpoint + :param cablepath: The CablePath instance originating from this endpoint + :param msg: Custom failure message (optional) + """ + if msg is None: + msg = f"Path #{cablepath.pk} not set on originating endpoint {origin}" + self.assertEqual(origin._path_id, cablepath.pk, msg=msg) + + def assertPathIsNotSet(self, origin, msg=None): + """ + Assert that a specific CablePath instance is set as the path on the origin. + + :param origin: The originating path endpoint + :param msg: Custom failure message (optional) + """ + if msg is None: + msg = f"Path #{origin._path_id} set as origin on {origin}; should be None!" + self.assertIsNone(origin._path_id, msg=msg) + + def test_101_interface_to_interface(self): + """ + [IF1] --C1-- [IF2] + """ + interface1 = Interface.objects.create(device=self.device, name='Interface 1') + interface2 = Interface.objects.create(device=self.device, name='Interface 2') + + # Create cable 1 + cable1 = Cable(termination_a=interface1, termination_b=interface2) + cable1.save() + path1 = self.assertPathExists( + origin=interface1, + destination=interface2, + path=(cable1,), + is_active=True + ) + path2 = self.assertPathExists( + origin=interface2, + destination=interface1, + path=(cable1,), + is_active=True + ) + self.assertEqual(CablePath.objects.count(), 2) + interface1.refresh_from_db() + interface2.refresh_from_db() + self.assertPathIsSet(interface1, path1) + self.assertPathIsSet(interface2, path2) + + # Delete cable 1 + cable1.delete() + + # Check that all CablePaths have been deleted + self.assertEqual(CablePath.objects.count(), 0) + + def test_102_consoleport_to_consoleserverport(self): + """ + [CP1] --C1-- [CSP1] + """ + consoleport1 = ConsolePort.objects.create(device=self.device, name='Console Port 1') + consoleserverport1 = ConsoleServerPort.objects.create(device=self.device, name='Console Server Port 1') + + # Create cable 1 + cable1 = Cable(termination_a=consoleport1, termination_b=consoleserverport1) + cable1.save() + path1 = self.assertPathExists( + origin=consoleport1, + destination=consoleserverport1, + path=(cable1,), + is_active=True + ) + path2 = self.assertPathExists( + origin=consoleserverport1, + destination=consoleport1, + path=(cable1,), + is_active=True + ) + self.assertEqual(CablePath.objects.count(), 2) + consoleport1.refresh_from_db() + consoleserverport1.refresh_from_db() + self.assertPathIsSet(consoleport1, path1) + self.assertPathIsSet(consoleserverport1, path2) + + # Delete cable 1 + cable1.delete() + + # Check that all CablePaths have been deleted + self.assertEqual(CablePath.objects.count(), 0) + + def test_103_powerport_to_poweroutlet(self): + """ + [PP1] --C1-- [PO1] + """ + powerport1 = PowerPort.objects.create(device=self.device, name='Power Port 1') + poweroutlet1 = PowerOutlet.objects.create(device=self.device, name='Power Outlet 1') + + # Create cable 1 + cable1 = Cable(termination_a=powerport1, termination_b=poweroutlet1) + cable1.save() + path1 = self.assertPathExists( + origin=powerport1, + destination=poweroutlet1, + path=(cable1,), + is_active=True + ) + path2 = self.assertPathExists( + origin=poweroutlet1, + destination=powerport1, + path=(cable1,), + is_active=True + ) + self.assertEqual(CablePath.objects.count(), 2) + powerport1.refresh_from_db() + poweroutlet1.refresh_from_db() + self.assertPathIsSet(powerport1, path1) + self.assertPathIsSet(poweroutlet1, path2) + + # Delete cable 1 + cable1.delete() + + # Check that all CablePaths have been deleted + self.assertEqual(CablePath.objects.count(), 0) + + def test_104_powerport_to_powerfeed(self): + """ + [PP1] --C1-- [PF1] + """ + powerport1 = PowerPort.objects.create(device=self.device, name='Power Port 1') + powerfeed1 = PowerFeed.objects.create(power_panel=self.powerpanel, name='Power Feed 1') + + # Create cable 1 + cable1 = Cable(termination_a=powerport1, termination_b=powerfeed1) + cable1.save() + path1 = self.assertPathExists( + origin=powerport1, + destination=powerfeed1, + path=(cable1,), + is_active=True + ) + path2 = self.assertPathExists( + origin=powerfeed1, + destination=powerport1, + path=(cable1,), + is_active=True + ) + self.assertEqual(CablePath.objects.count(), 2) + powerport1.refresh_from_db() + powerfeed1.refresh_from_db() + self.assertPathIsSet(powerport1, path1) + self.assertPathIsSet(powerfeed1, path2) + + # Delete cable 1 + cable1.delete() + + # Check that all CablePaths have been deleted + self.assertEqual(CablePath.objects.count(), 0) + + def test_105_interface_to_circuittermination(self): + """ + [IF1] --C1-- [CT1A] + """ + interface1 = Interface.objects.create(device=self.device, name='Interface 1') + circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=self.site, term_side='A') + + # Create cable 1 + cable1 = Cable(termination_a=interface1, termination_b=circuittermination1) + cable1.save() + path1 = self.assertPathExists( + origin=interface1, + destination=circuittermination1, + path=(cable1,), + is_active=True + ) + path2 = self.assertPathExists( + origin=circuittermination1, + destination=interface1, + path=(cable1,), + is_active=True + ) + self.assertEqual(CablePath.objects.count(), 2) + interface1.refresh_from_db() + circuittermination1.refresh_from_db() + self.assertPathIsSet(interface1, path1) + self.assertPathIsSet(circuittermination1, path2) + + # Delete cable 1 + cable1.delete() + + # Check that all CablePaths have been deleted + self.assertEqual(CablePath.objects.count(), 0) + + def test_201_single_path_via_pass_through(self): + """ + [IF1] --C1-- [FP1] [RP1] --C2-- [IF2] + """ + interface1 = Interface.objects.create(device=self.device, name='Interface 1') + interface2 = Interface.objects.create(device=self.device, name='Interface 2') + rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=1) + frontport1 = FrontPort.objects.create( + device=self.device, name='Front Port 1', rear_port=rearport1, rear_port_position=1 + ) + + # Create cable 1 + cable1 = Cable(termination_a=interface1, termination_b=frontport1) + cable1.save() + self.assertPathExists( + origin=interface1, + destination=None, + path=(cable1, frontport1, rearport1), + is_active=False + ) + self.assertEqual(CablePath.objects.count(), 1) + + # Create cable 2 + cable2 = Cable(termination_a=rearport1, termination_b=interface2) + cable2.save() + self.assertPathExists( + origin=interface1, + destination=interface2, + path=(cable1, frontport1, rearport1, cable2), + is_active=True + ) + self.assertPathExists( + origin=interface2, + destination=interface1, + path=(cable2, rearport1, frontport1, cable1), + is_active=True + ) + self.assertEqual(CablePath.objects.count(), 2) + + # Delete cable 2 + cable2.delete() + path1 = self.assertPathExists( + origin=interface1, + destination=None, + path=(cable1, frontport1, rearport1), + is_active=False + ) + self.assertEqual(CablePath.objects.count(), 1) + interface1.refresh_from_db() + interface2.refresh_from_db() + self.assertPathIsSet(interface1, path1) + self.assertPathIsNotSet(interface2) + + def test_202_multiple_paths_via_pass_through(self): + """ + [IF1] --C1-- [FP1:1] [RP1] --C3-- [RP2] [FP2:1] --C4-- [IF3] + [IF2] --C2-- [FP1:2] [FP2:2] --C5-- [IF4] + """ + interface1 = Interface.objects.create(device=self.device, name='Interface 1') + interface2 = Interface.objects.create(device=self.device, name='Interface 2') + interface3 = Interface.objects.create(device=self.device, name='Interface 3') + interface4 = Interface.objects.create(device=self.device, name='Interface 4') + rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4) + rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4) + frontport1_1 = FrontPort.objects.create( + device=self.device, name='Front Port 1:1', rear_port=rearport1, rear_port_position=1 + ) + frontport1_2 = FrontPort.objects.create( + device=self.device, name='Front Port 1:2', rear_port=rearport1, rear_port_position=2 + ) + frontport2_1 = FrontPort.objects.create( + device=self.device, name='Front Port 2:1', rear_port=rearport2, rear_port_position=1 + ) + frontport2_2 = FrontPort.objects.create( + device=self.device, name='Front Port 2:2', rear_port=rearport2, rear_port_position=2 + ) + + # Create cables 1-2 + cable1 = Cable(termination_a=interface1, termination_b=frontport1_1) + cable1.save() + cable2 = Cable(termination_a=interface2, termination_b=frontport1_2) + cable2.save() + self.assertPathExists( + origin=interface1, + destination=None, + path=(cable1, frontport1_1, rearport1), + is_active=False + ) + self.assertPathExists( + origin=interface2, + destination=None, + path=(cable2, frontport1_2, rearport1), + is_active=False + ) + self.assertEqual(CablePath.objects.count(), 2) + + # Create cable 3 + cable3 = Cable(termination_a=rearport1, termination_b=rearport2) + cable3.save() + self.assertPathExists( + origin=interface1, + destination=None, + path=(cable1, frontport1_1, rearport1, cable3, rearport2, frontport2_1), + is_active=False + ) + self.assertPathExists( + origin=interface2, + destination=None, + path=(cable2, frontport1_2, rearport1, cable3, rearport2, frontport2_2), + is_active=False + ) + self.assertEqual(CablePath.objects.count(), 2) + + # Create cables 4-5 + cable4 = Cable(termination_a=frontport2_1, termination_b=interface3) + cable4.save() + cable5 = Cable(termination_a=frontport2_2, termination_b=interface4) + cable5.save() + path1 = self.assertPathExists( + origin=interface1, + destination=interface3, + path=( + cable1, frontport1_1, rearport1, cable3, rearport2, frontport2_1, + cable4, + ), + is_active=True + ) + path2 = self.assertPathExists( + origin=interface2, + destination=interface4, + path=( + cable2, frontport1_2, rearport1, cable3, rearport2, frontport2_2, + cable5, + ), + is_active=True + ) + path3 = self.assertPathExists( + origin=interface3, + destination=interface1, + path=( + cable4, frontport2_1, rearport2, cable3, rearport1, frontport1_1, + cable1 + ), + is_active=True + ) + path4 = self.assertPathExists( + origin=interface4, + destination=interface2, + path=( + cable5, frontport2_2, rearport2, cable3, rearport1, frontport1_2, + cable2 + ), + is_active=True + ) + self.assertEqual(CablePath.objects.count(), 4) + + # Delete cable 3 + cable3.delete() + + # Check for four partial paths; one from each interface + self.assertEqual(CablePath.objects.filter(destination_id__isnull=True).count(), 4) + self.assertEqual(CablePath.objects.filter(destination_id__isnull=False).count(), 0) + interface1.refresh_from_db() + interface2.refresh_from_db() + interface3.refresh_from_db() + interface4.refresh_from_db() + self.assertPathIsSet(interface1, path1) + self.assertPathIsSet(interface2, path2) + self.assertPathIsSet(interface3, path3) + self.assertPathIsSet(interface4, path4) + + def test_203_multiple_paths_via_nested_pass_throughs(self): + """ + [IF1] --C1-- [FP1:1] [RP1] --C3-- [FP2] [RP2] --C4-- [RP3] [FP3] --C5-- [RP4] [FP4:1] --C6-- [IF3] + [IF2] --C2-- [FP1:2] [FP4:2] --C7-- [IF4] + """ + interface1 = Interface.objects.create(device=self.device, name='Interface 1') + interface2 = Interface.objects.create(device=self.device, name='Interface 2') + interface3 = Interface.objects.create(device=self.device, name='Interface 3') + interface4 = Interface.objects.create(device=self.device, name='Interface 4') + rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4) + rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=1) + rearport3 = RearPort.objects.create(device=self.device, name='Rear Port 3', positions=1) + rearport4 = RearPort.objects.create(device=self.device, name='Rear Port 4', positions=4) + frontport1_1 = FrontPort.objects.create( + device=self.device, name='Front Port 1:1', rear_port=rearport1, rear_port_position=1 + ) + frontport1_2 = FrontPort.objects.create( + device=self.device, name='Front Port 1:2', rear_port=rearport1, rear_port_position=2 + ) + frontport2 = FrontPort.objects.create( + device=self.device, name='Front Port 2', rear_port=rearport2, rear_port_position=1 + ) + frontport3 = FrontPort.objects.create( + device=self.device, name='Front Port 3', rear_port=rearport3, rear_port_position=1 + ) + frontport4_1 = FrontPort.objects.create( + device=self.device, name='Front Port 4:1', rear_port=rearport4, rear_port_position=1 + ) + frontport4_2 = FrontPort.objects.create( + device=self.device, name='Front Port 4:2', rear_port=rearport4, rear_port_position=2 + ) + + # Create cables 1-2, 6-7 + cable1 = Cable(termination_a=interface1, termination_b=frontport1_1) + cable1.save() + cable2 = Cable(termination_a=interface2, termination_b=frontport1_2) + cable2.save() + cable6 = Cable(termination_a=interface3, termination_b=frontport4_1) + cable6.save() + cable7 = Cable(termination_a=interface4, termination_b=frontport4_2) + cable7.save() + self.assertEqual(CablePath.objects.count(), 4) # Four partial paths; one from each interface + + # Create cables 3 and 5 + cable3 = Cable(termination_a=rearport1, termination_b=frontport2) + cable3.save() + cable5 = Cable(termination_a=rearport4, termination_b=frontport3) + cable5.save() + self.assertEqual(CablePath.objects.count(), 4) # Four (longer) partial paths; one from each interface + + # Create cable 4 + cable4 = Cable(termination_a=rearport2, termination_b=rearport3) + cable4.save() + self.assertPathExists( + origin=interface1, + destination=interface3, + path=( + cable1, frontport1_1, rearport1, cable3, frontport2, rearport2, + cable4, rearport3, frontport3, cable5, rearport4, frontport4_1, + cable6 + ), + is_active=True + ) + self.assertPathExists( + origin=interface2, + destination=interface4, + path=( + cable2, frontport1_2, rearport1, cable3, frontport2, rearport2, + cable4, rearport3, frontport3, cable5, rearport4, frontport4_2, + cable7 + ), + is_active=True + ) + self.assertPathExists( + origin=interface3, + destination=interface1, + path=( + cable6, frontport4_1, rearport4, cable5, frontport3, rearport3, + cable4, rearport2, frontport2, cable3, rearport1, frontport1_1, + cable1 + ), + is_active=True + ) + self.assertPathExists( + origin=interface4, + destination=interface2, + path=( + cable7, frontport4_2, rearport4, cable5, frontport3, rearport3, + cable4, rearport2, frontport2, cable3, rearport1, frontport1_2, + cable2 + ), + is_active=True + ) + self.assertEqual(CablePath.objects.count(), 4) + + # Delete cable 3 + cable3.delete() + + # Check for four partial paths; one from each interface + self.assertEqual(CablePath.objects.filter(destination_id__isnull=True).count(), 4) + self.assertEqual(CablePath.objects.filter(destination_id__isnull=False).count(), 0) + + def test_204_multiple_paths_via_multiple_pass_throughs(self): + """ + [IF1] --C1-- [FP1:1] [RP1] --C3-- [RP2] [FP2:1] --C4-- [FP3:1] [RP3] --C6-- [RP4] [FP4:1] --C7-- [IF3] + [IF2] --C2-- [FP1:2] [FP2:1] --C5-- [FP3:1] [FP4:2] --C8-- [IF4] + """ + interface1 = Interface.objects.create(device=self.device, name='Interface 1') + interface2 = Interface.objects.create(device=self.device, name='Interface 2') + interface3 = Interface.objects.create(device=self.device, name='Interface 3') + interface4 = Interface.objects.create(device=self.device, name='Interface 4') + rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4) + rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4) + rearport3 = RearPort.objects.create(device=self.device, name='Rear Port 3', positions=4) + rearport4 = RearPort.objects.create(device=self.device, name='Rear Port 4', positions=4) + frontport1_1 = FrontPort.objects.create( + device=self.device, name='Front Port 1:1', rear_port=rearport1, rear_port_position=1 + ) + frontport1_2 = FrontPort.objects.create( + device=self.device, name='Front Port 1:2', rear_port=rearport1, rear_port_position=2 + ) + frontport2_1 = FrontPort.objects.create( + device=self.device, name='Front Port 2:1', rear_port=rearport2, rear_port_position=1 + ) + frontport2_2 = FrontPort.objects.create( + device=self.device, name='Front Port 2:2', rear_port=rearport2, rear_port_position=2 + ) + frontport3_1 = FrontPort.objects.create( + device=self.device, name='Front Port 3:1', rear_port=rearport3, rear_port_position=1 + ) + frontport3_2 = FrontPort.objects.create( + device=self.device, name='Front Port 3:2', rear_port=rearport3, rear_port_position=2 + ) + frontport4_1 = FrontPort.objects.create( + device=self.device, name='Front Port 4:1', rear_port=rearport4, rear_port_position=1 + ) + frontport4_2 = FrontPort.objects.create( + device=self.device, name='Front Port 4:2', rear_port=rearport4, rear_port_position=2 + ) + + # Create cables 1-3, 6-8 + cable1 = Cable(termination_a=interface1, termination_b=frontport1_1) + cable1.save() + cable2 = Cable(termination_a=interface2, termination_b=frontport1_2) + cable2.save() + cable3 = Cable(termination_a=rearport1, termination_b=rearport2) + cable3.save() + cable6 = Cable(termination_a=rearport3, termination_b=rearport4) + cable6.save() + cable7 = Cable(termination_a=interface3, termination_b=frontport4_1) + cable7.save() + cable8 = Cable(termination_a=interface4, termination_b=frontport4_2) + cable8.save() + self.assertEqual(CablePath.objects.count(), 4) # Four partial paths; one from each interface + + # Create cables 4 and 5 + cable4 = Cable(termination_a=frontport2_1, termination_b=frontport3_1) + cable4.save() + cable5 = Cable(termination_a=frontport2_2, termination_b=frontport3_2) + cable5.save() + self.assertPathExists( + origin=interface1, + destination=interface3, + path=( + cable1, frontport1_1, rearport1, cable3, rearport2, frontport2_1, + cable4, frontport3_1, rearport3, cable6, rearport4, frontport4_1, + cable7 + ), + is_active=True + ) + self.assertPathExists( + origin=interface2, + destination=interface4, + path=( + cable2, frontport1_2, rearport1, cable3, rearport2, frontport2_2, + cable5, frontport3_2, rearport3, cable6, rearport4, frontport4_2, + cable8 + ), + is_active=True + ) + self.assertPathExists( + origin=interface3, + destination=interface1, + path=( + cable7, frontport4_1, rearport4, cable6, rearport3, frontport3_1, + cable4, frontport2_1, rearport2, cable3, rearport1, frontport1_1, + cable1 + ), + is_active=True + ) + self.assertPathExists( + origin=interface4, + destination=interface2, + path=( + cable8, frontport4_2, rearport4, cable6, rearport3, frontport3_2, + cable5, frontport2_2, rearport2, cable3, rearport1, frontport1_2, + cable2 + ), + is_active=True + ) + self.assertEqual(CablePath.objects.count(), 4) + + # Delete cable 5 + cable5.delete() + + # Check for two complete paths (IF1 <--> IF2) and two partial (IF3 <--> IF4) + self.assertEqual(CablePath.objects.filter(destination_id__isnull=True).count(), 2) + self.assertEqual(CablePath.objects.filter(destination_id__isnull=False).count(), 2) + + def test_205_multiple_paths_via_patched_pass_throughs(self): + """ + [IF1] --C1-- [FP1:1] [RP1] --C3-- [FP2] [RP2] --C4-- [RP3] [FP3:1] --C5-- [IF3] + [IF2] --C2-- [FP1:2] [FP3:2] --C6-- [IF4] + """ + interface1 = Interface.objects.create(device=self.device, name='Interface 1') + interface2 = Interface.objects.create(device=self.device, name='Interface 2') + interface3 = Interface.objects.create(device=self.device, name='Interface 3') + interface4 = Interface.objects.create(device=self.device, name='Interface 4') + rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4) + rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 5', positions=1) + rearport3 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4) + frontport1_1 = FrontPort.objects.create( + device=self.device, name='Front Port 1:1', rear_port=rearport1, rear_port_position=1 + ) + frontport1_2 = FrontPort.objects.create( + device=self.device, name='Front Port 1:2', rear_port=rearport1, rear_port_position=2 + ) + frontport2 = FrontPort.objects.create( + device=self.device, name='Front Port 5', rear_port=rearport2, rear_port_position=1 + ) + frontport3_1 = FrontPort.objects.create( + device=self.device, name='Front Port 2:1', rear_port=rearport3, rear_port_position=1 + ) + frontport3_2 = FrontPort.objects.create( + device=self.device, name='Front Port 2:2', rear_port=rearport3, rear_port_position=2 + ) + + # Create cables 1-2, 5-6 + cable1 = Cable(termination_a=interface1, termination_b=frontport1_1) # IF1 -> FP1:1 + cable1.save() + cable2 = Cable(termination_a=interface2, termination_b=frontport1_2) # IF2 -> FP1:2 + cable2.save() + cable5 = Cable(termination_a=interface3, termination_b=frontport3_1) # IF3 -> FP3:1 + cable5.save() + cable6 = Cable(termination_a=interface4, termination_b=frontport3_2) # IF4 -> FP3:2 + cable6.save() + self.assertEqual(CablePath.objects.count(), 4) # Four partial paths; one from each interface + + # Create cables 3-4 + cable3 = Cable(termination_a=rearport1, termination_b=frontport2) # RP1 -> FP2 + cable3.save() + cable4 = Cable(termination_a=rearport2, termination_b=rearport3) # RP2 -> RP3 + cable4.save() + self.assertPathExists( + origin=interface1, + destination=interface3, + path=( + cable1, frontport1_1, rearport1, cable3, frontport2, rearport2, + cable4, rearport3, frontport3_1, cable5 + ), + is_active=True + ) + self.assertPathExists( + origin=interface2, + destination=interface4, + path=( + cable2, frontport1_2, rearport1, cable3, frontport2, rearport2, + cable4, rearport3, frontport3_2, cable6 + ), + is_active=True + ) + self.assertPathExists( + origin=interface3, + destination=interface1, + path=( + cable5, frontport3_1, rearport3, cable4, rearport2, frontport2, + cable3, rearport1, frontport1_1, cable1 + ), + is_active=True + ) + self.assertPathExists( + origin=interface4, + destination=interface2, + path=( + cable6, frontport3_2, rearport3, cable4, rearport2, frontport2, + cable3, rearport1, frontport1_2, cable2 + ), + is_active=True + ) + self.assertEqual(CablePath.objects.count(), 4) + + # Delete cable 3 + cable3.delete() + + # Check for four partial paths; one from each interface + self.assertEqual(CablePath.objects.filter(destination_id__isnull=True).count(), 4) + self.assertEqual(CablePath.objects.filter(destination_id__isnull=False).count(), 0) + + def test_206_unidirectional_split_paths(self): + """ + [IF1] --C1-- [RP1] [FP1:1] --C2-- [IF2] + [FP1:2] --C3-- [IF3] + """ + interface1 = Interface.objects.create(device=self.device, name='Interface 1') + interface2 = Interface.objects.create(device=self.device, name='Interface 2') + interface3 = Interface.objects.create(device=self.device, name='Interface 3') + rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4) + frontport1_1 = FrontPort.objects.create( + device=self.device, name='Front Port 1:1', rear_port=rearport1, rear_port_position=1 + ) + frontport1_2 = FrontPort.objects.create( + device=self.device, name='Front Port 1:2', rear_port=rearport1, rear_port_position=2 + ) + + # Create cables 1 + cable1 = Cable(termination_a=interface1, termination_b=rearport1) + cable1.save() + self.assertPathExists( + origin=interface1, + destination=None, + path=(cable1, rearport1), + is_active=False + ) + self.assertEqual(CablePath.objects.count(), 1) + + # Create cables 2-3 + cable2 = Cable(termination_a=interface2, termination_b=frontport1_1) + cable2.save() + cable3 = Cable(termination_a=interface3, termination_b=frontport1_2) + cable3.save() + self.assertPathExists( + origin=interface2, + destination=interface1, + path=(cable2, frontport1_1, rearport1, cable1), + is_active=True + ) + self.assertPathExists( + origin=interface3, + destination=interface1, + path=(cable3, frontport1_2, rearport1, cable1), + is_active=True + ) + self.assertEqual(CablePath.objects.count(), 3) + + # Delete cable 1 + cable1.delete() + + # Check that the partial path was deleted and the two complete paths are now partial + self.assertPathExists( + origin=interface2, + destination=None, + path=(cable2, frontport1_1, rearport1), + is_active=False + ) + self.assertPathExists( + origin=interface3, + destination=None, + path=(cable3, frontport1_2, rearport1), + is_active=False + ) + self.assertEqual(CablePath.objects.count(), 2) + + def test_207_rearport_without_frontport(self): + """ + [IF1] --C1-- [FP1] [RP1] --C2-- [RP2] + """ + interface1 = Interface.objects.create(device=self.device, name='Interface 1') + rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=1) + rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=1) + frontport1 = FrontPort.objects.create( + device=self.device, name='Front Port 1', rear_port=rearport1, rear_port_position=1 + ) + + # Create cables + cable1 = Cable(termination_a=interface1, termination_b=frontport1) + cable1.save() + cable2 = Cable(termination_a=rearport1, termination_b=rearport2) + cable2.save() + self.assertPathExists( + origin=interface1, + destination=None, + path=(cable1, frontport1, rearport1, cable2, rearport2), + is_active=False + ) + self.assertEqual(CablePath.objects.count(), 1) + + def test_301_create_path_via_existing_cable(self): + """ + [IF1] --C1-- [FP1] [RP2] --C2-- [RP2] [FP2] --C3-- [IF2] + """ + interface1 = Interface.objects.create(device=self.device, name='Interface 1') + interface2 = Interface.objects.create(device=self.device, name='Interface 2') + rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=1) + rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=1) + frontport1 = FrontPort.objects.create( + device=self.device, name='Front Port 1', rear_port=rearport1, rear_port_position=1 + ) + frontport2 = FrontPort.objects.create( + device=self.device, name='Front Port 2', rear_port=rearport2, rear_port_position=1 + ) + + # Create cable 2 + cable2 = Cable(termination_a=rearport1, termination_b=rearport2) + cable2.save() + self.assertEqual(CablePath.objects.count(), 0) + + # Create cable1 + cable1 = Cable(termination_a=interface1, termination_b=frontport1) + cable1.save() + self.assertPathExists( + origin=interface1, + destination=None, + path=(cable1, frontport1, rearport1, cable2, rearport2, frontport2), + is_active=False + ) + self.assertEqual(CablePath.objects.count(), 1) + + # Create cable 3 + cable3 = Cable(termination_a=frontport2, termination_b=interface2) + cable3.save() + self.assertPathExists( + origin=interface1, + destination=interface2, + path=(cable1, frontport1, rearport1, cable2, rearport2, frontport2, cable3), + is_active=True + ) + self.assertPathExists( + origin=interface2, + destination=interface1, + path=(cable3, frontport2, rearport2, cable2, rearport1, frontport1, cable1), + is_active=True + ) + self.assertEqual(CablePath.objects.count(), 2) + + def test_302_update_path_on_cable_status_change(self): + """ + [IF1] --C1-- [FP1] [RP1] --C2-- [IF2] + """ + interface1 = Interface.objects.create(device=self.device, name='Interface 1') + interface2 = Interface.objects.create(device=self.device, name='Interface 2') + rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=1) + frontport1 = FrontPort.objects.create( + device=self.device, name='Front Port 1', rear_port=rearport1, rear_port_position=1 + ) + + # Create cables 1 and 2 + cable1 = Cable(termination_a=interface1, termination_b=frontport1) + cable1.save() + cable2 = Cable(termination_a=rearport1, termination_b=interface2) + cable2.save() + self.assertEqual(CablePath.objects.filter(is_active=True).count(), 2) + self.assertEqual(CablePath.objects.count(), 2) + + # Change cable 2's status to "planned" + cable2.status = CableStatusChoices.STATUS_PLANNED + cable2.save() + self.assertPathExists( + origin=interface1, + destination=interface2, + path=(cable1, frontport1, rearport1, cable2), + is_active=False + ) + self.assertPathExists( + origin=interface2, + destination=interface1, + path=(cable2, rearport1, frontport1, cable1), + is_active=False + ) + self.assertEqual(CablePath.objects.count(), 2) + + # Change cable 2's status to "connected" + cable2 = Cable.objects.get(pk=cable2.pk) + cable2.status = CableStatusChoices.STATUS_CONNECTED + cable2.save() + self.assertPathExists( + origin=interface1, + destination=interface2, + path=(cable1, frontport1, rearport1, cable2), + is_active=True + ) + self.assertPathExists( + origin=interface2, + destination=interface1, + path=(cable2, rearport1, frontport1, cable1), + is_active=True + ) + self.assertEqual(CablePath.objects.count(), 2) diff --git a/netbox/dcim/tests/test_filters.py b/netbox/dcim/tests/test_filters.py index d4504d5862..f209cd1f48 100644 --- a/netbox/dcim/tests/test_filters.py +++ b/netbox/dcim/tests/test_filters.py @@ -1514,10 +1514,11 @@ def test_description(self): params = {'description': ['First', 'Second']} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - # TODO: Fix boolean value - def test_connection_status(self): - params = {'connection_status': 'True'} + def test_connected(self): + params = {'connected': True} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'connected': False} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) def test_region(self): regions = Region.objects.all()[:2] @@ -1609,10 +1610,11 @@ def test_description(self): params = {'description': ['First', 'Second']} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - # TODO: Fix boolean value - def test_connection_status(self): - params = {'connection_status': 'True'} + def test_connected(self): + params = {'connected': True} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'connected': False} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) def test_region(self): regions = Region.objects.all()[:2] @@ -1712,10 +1714,11 @@ def test_allocated_draw(self): params = {'allocated_draw': [50, 100]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - # TODO: Fix boolean value - def test_connection_status(self): - params = {'connection_status': 'True'} + def test_connected(self): + params = {'connected': True} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'connected': False} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) def test_region(self): regions = Region.objects.all()[:2] @@ -1812,10 +1815,11 @@ def test_feed_leg(self): params = {'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_A} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) - # TODO: Fix boolean value - def test_connection_status(self): - params = {'connection_status': 'True'} + def test_connected(self): + params = {'connected': True} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'connected': False} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) def test_region(self): regions = Region.objects.all()[:2] @@ -1900,10 +1904,11 @@ def test_name(self): params = {'name': ['Interface 1', 'Interface 2']} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - # TODO: Fix boolean value - def test_connection_status(self): - params = {'connection_status': 'True'} + def test_connected(self): + params = {'connected': True} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'connected': False} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_enabled(self): params = {'enabled': 'true'} @@ -2285,14 +2290,16 @@ def setUpTestData(cls): InventoryItem(device=devices[1], manufacturer=manufacturers[1], name='Inventory Item 2', part_id='1002', serial='DEF', asset_tag='1002', discovered=True, description='Second'), InventoryItem(device=devices[2], manufacturer=manufacturers[2], name='Inventory Item 3', part_id='1003', serial='GHI', asset_tag='1003', discovered=False, description='Third'), ) - InventoryItem.objects.bulk_create(inventory_items) + for i in inventory_items: + i.save() child_inventory_items = ( InventoryItem(device=devices[0], name='Inventory Item 1A', parent=inventory_items[0]), InventoryItem(device=devices[1], name='Inventory Item 2A', parent=inventory_items[1]), InventoryItem(device=devices[2], name='Inventory Item 3A', parent=inventory_items[2]), ) - InventoryItem.objects.bulk_create(child_inventory_items) + for i in child_inventory_items: + i.save() def test_id(self): params = {'id': self.queryset.values_list('pk', flat=True)[:2]} @@ -2660,6 +2667,18 @@ def setUpTestData(cls): ) PowerFeed.objects.bulk_create(power_feeds) + manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer') + device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Model', slug='model') + device_role = DeviceRole.objects.create(name='Device Role', slug='device-role') + device = Device.objects.create(name='Device', device_type=device_type, device_role=device_role, site=sites[0]) + power_ports = [ + PowerPort(device=device, name='Power Port 1'), + PowerPort(device=device, name='Power Port 2'), + ] + PowerPort.objects.bulk_create(power_ports) + Cable(termination_a=power_feeds[0], termination_b=power_ports[0]).save() + Cable(termination_a=power_feeds[1], termination_b=power_ports[1]).save() + def test_id(self): params = {'id': self.queryset.values_list('pk', flat=True)[:2]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) @@ -2721,5 +2740,17 @@ def test_rack_id(self): params = {'rack_id': [racks[0].pk, racks[1].pk]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + def test_cabled(self): + params = {'cabled': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'cabled': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + + def test_connected(self): + params = {'connected': True} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'connected': False} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + # TODO: Connection filters diff --git a/netbox/dcim/tests/test_models.py b/netbox/dcim/tests/test_models.py index c55d099c91..b20e211026 100644 --- a/netbox/dcim/tests/test_models.py +++ b/netbox/dcim/tests/test_models.py @@ -390,17 +390,19 @@ def setUp(self): self.provider = Provider.objects.create(name='Provider 1', slug='provider-1') self.circuittype = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1') self.circuit = Circuit.objects.create(provider=self.provider, type=self.circuittype, cid='1') - self.circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=site, term_side='A', port_speed=1000) - self.circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, site=site, term_side='Z', port_speed=1000) + self.circuittermination1 = CircuitTermination.objects.create(circuit=self.circuit, site=site, term_side='A') + self.circuittermination2 = CircuitTermination.objects.create(circuit=self.circuit, site=site, term_side='Z') def test_cable_creation(self): """ When a new Cable is created, it must be cached on either termination point. """ interface1 = Interface.objects.get(pk=self.interface1.pk) - self.assertEqual(self.cable.termination_a, interface1) interface2 = Interface.objects.get(pk=self.interface2.pk) + self.assertEqual(self.cable.termination_a, interface1) + self.assertEqual(interface1._cable_peer, interface2) self.assertEqual(self.cable.termination_b, interface2) + self.assertEqual(interface2._cable_peer, interface1) def test_cable_deletion(self): """ @@ -412,8 +414,10 @@ def test_cable_deletion(self): self.assertNotEqual(str(self.cable), '#None') interface1 = Interface.objects.get(pk=self.interface1.pk) self.assertIsNone(interface1.cable) + self.assertIsNone(interface1._cable_peer) interface2 = Interface.objects.get(pk=self.interface2.pk) self.assertIsNone(interface2.cable) + self.assertIsNone(interface2._cable_peer) def test_cabletermination_deletion(self): """ @@ -457,21 +461,9 @@ def test_cable_cannot_terminate_to_an_existing_connection(self): with self.assertRaises(ValidationError): cable.clean() - def test_connection_via_single_position_rearport(self): + def test_rearport_connections(self): """ - A RearPort with one position can be connected to anything. - - [CableTermination X]---[RP(pos=1) FP]---[CableTermination Y] - - is allowed anywhere - - [CableTermination X]---[CableTermination Y] - - is allowed. - - A RearPort with multiple positions may not be directly connected to a path endpoint or another RearPort - with a different number of positions. RearPorts with a single position on the other hand may be connected - to such CableTerminations. Check that this is indeed allowed. + Test various combinations of RearPort connections. """ # Connecting a single-position RearPort to a multi-position RearPort is ok Cable(termination_a=self.rear_port1, termination_b=self.rear_port2).full_clean() @@ -482,68 +474,22 @@ def test_connection_via_single_position_rearport(self): # Connecting a single-position RearPort to a CircuitTermination is ok Cable(termination_a=self.rear_port1, termination_b=self.circuittermination1).full_clean() - def test_connection_via_multi_position_rearport(self): - """ - A RearPort with multiple positions may not be directly connected to a path endpoint or another RearPort - with a different number of positions. - - The following scenario's are allowed (with x>1): - - ~----------+ +---------~ - | | - RP2(pos=x)|---|RP(pos=x) - | | - ~----------+ +---------~ - - ~----------+ +---------~ - | | - RP2(pos=x)|---|RP(pos=1) - | | - ~----------+ +---------~ - - ~----------+ +------------------~ - | | - RP2(pos=x)|---|CircuitTermination - | | - ~----------+ +------------------~ - - These scenarios are NOT allowed (with x>1): - - ~----------+ +----------~ - | | - RP2(pos=x)|---|RP(pos!=x) - | | - ~----------+ +----------~ - - ~----------+ +----------~ - | | - RP2(pos=x)|---|Interface - | | - ~----------+ +----------~ - - These scenarios are tested in this order below. - """ # Connecting a multi-position RearPort to another RearPort with the same number of positions is ok Cable(termination_a=self.rear_port3, termination_b=self.rear_port4).full_clean() - # Connecting a multi-position RearPort to a single-position RearPort is ok - Cable(termination_a=self.rear_port2, termination_b=self.rear_port1).full_clean() + # Connecting a multi-position RearPort to an Interface is ok + Cable(termination_a=self.rear_port2, termination_b=self.interface3).full_clean() # Connecting a multi-position RearPort to a CircuitTermination is ok Cable(termination_a=self.rear_port2, termination_b=self.circuittermination1).full_clean() + # Connecting a two-position RearPort to a three-position RearPort is NOT ok with self.assertRaises( ValidationError, msg='Connecting a 2-position RearPort to a 3-position RearPort should fail' ): Cable(termination_a=self.rear_port2, termination_b=self.rear_port3).full_clean() - with self.assertRaises( - ValidationError, - msg='Connecting a multi-position RearPort to an Interface should fail' - ): - Cable(termination_a=self.rear_port2, termination_b=self.interface3).full_clean() - def test_cable_cannot_terminate_to_a_virtual_interface(self): """ A cable cannot terminate to a virtual interface @@ -561,628 +507,3 @@ def test_cable_cannot_terminate_to_a_wireless_interface(self): cable = Cable(termination_a=self.interface2, termination_b=wireless_interface) with self.assertRaises(ValidationError): cable.clean() - - -class CablePathTestCase(TestCase): - - @classmethod - def setUpTestData(cls): - - site = Site.objects.create(name='Site 1', slug='site-1') - manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') - devicetype = DeviceType.objects.create( - manufacturer=manufacturer, model='Device Type 1', slug='device-type-1' - ) - devicerole = DeviceRole.objects.create( - name='Device Role 1', slug='device-role-1', color='ff0000' - ) - provider = Provider.objects.create(name='Provider 1', slug='provider-1') - circuittype = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1') - circuit = Circuit.objects.create(provider=provider, type=circuittype, cid='1') - CircuitTermination.objects.bulk_create(( - CircuitTermination(circuit=circuit, site=site, term_side='A', port_speed=1000), - CircuitTermination(circuit=circuit, site=site, term_side='Z', port_speed=1000), - )) - - # Create four network devices with four interfaces each - devices = ( - Device(device_type=devicetype, device_role=devicerole, name='Device 1', site=site), - Device(device_type=devicetype, device_role=devicerole, name='Device 2', site=site), - Device(device_type=devicetype, device_role=devicerole, name='Device 3', site=site), - Device(device_type=devicetype, device_role=devicerole, name='Device 4', site=site), - ) - Device.objects.bulk_create(devices) - for device in devices: - Interface.objects.bulk_create(( - Interface(device=device, name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED), - Interface(device=device, name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED), - Interface(device=device, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED), - Interface(device=device, name='Interface 4', type=InterfaceTypeChoices.TYPE_1GE_FIXED), - )) - - # Create four patch panels, each with one rear port and four front ports - patch_panels = ( - Device(device_type=devicetype, device_role=devicerole, name='Panel 1', site=site), - Device(device_type=devicetype, device_role=devicerole, name='Panel 2', site=site), - Device(device_type=devicetype, device_role=devicerole, name='Panel 3', site=site), - Device(device_type=devicetype, device_role=devicerole, name='Panel 4', site=site), - Device(device_type=devicetype, device_role=devicerole, name='Panel 5', site=site), - Device(device_type=devicetype, device_role=devicerole, name='Panel 6', site=site), - ) - Device.objects.bulk_create(patch_panels) - - # Create patch panels with 4 positions - for patch_panel in patch_panels[:4]: - rearport = RearPort.objects.create(device=patch_panel, name='Rear Port 1', positions=4, type=PortTypeChoices.TYPE_8P8C) - FrontPort.objects.bulk_create(( - FrontPort(device=patch_panel, name='Front Port 1', rear_port=rearport, rear_port_position=1, type=PortTypeChoices.TYPE_8P8C), - FrontPort(device=patch_panel, name='Front Port 2', rear_port=rearport, rear_port_position=2, type=PortTypeChoices.TYPE_8P8C), - FrontPort(device=patch_panel, name='Front Port 3', rear_port=rearport, rear_port_position=3, type=PortTypeChoices.TYPE_8P8C), - FrontPort(device=patch_panel, name='Front Port 4', rear_port=rearport, rear_port_position=4, type=PortTypeChoices.TYPE_8P8C), - )) - - # Create 1-on-1 patch panels - for patch_panel in patch_panels[4:]: - rearport = RearPort.objects.create(device=patch_panel, name='Rear Port 1', positions=1, type=PortTypeChoices.TYPE_8P8C) - FrontPort.objects.create(device=patch_panel, name='Front Port 1', rear_port=rearport, rear_port_position=1, type=PortTypeChoices.TYPE_8P8C) - - def test_direct_connection(self): - """ - Test a direct connection between two interfaces. - - [Device 1] ----- [Device 2] - Iface1 Iface1 - """ - # Create cable - cable = Cable( - termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'), - termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1') - ) - cable.full_clean() - cable.save() - - # Retrieve endpoints - endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1') - endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1') - - # Validate connections - self.assertEqual(endpoint_a.connected_endpoint, endpoint_b) - self.assertEqual(endpoint_b.connected_endpoint, endpoint_a) - self.assertTrue(endpoint_a.connection_status) - self.assertTrue(endpoint_b.connection_status) - - # Delete cable - cable.delete() - - # Refresh endpoints - endpoint_a.refresh_from_db() - endpoint_b.refresh_from_db() - - # Check that connections have been nullified - self.assertIsNone(endpoint_a.connected_endpoint) - self.assertIsNone(endpoint_b.connected_endpoint) - self.assertIsNone(endpoint_a.connection_status) - self.assertIsNone(endpoint_b.connection_status) - - def test_connection_via_single_rear_port(self): - """ - Test a connection which passes through a rear port with exactly one front port. - - 1 2 - [Device 1] ----- [Panel 5] ----- [Device 2] - Iface1 FP1 RP1 Iface1 - """ - # Create cables (FP first, RP second) - cable1 = Cable( - termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'), - termination_b=FrontPort.objects.get(device__name='Panel 5', name='Front Port 1') - ) - cable1.full_clean() - cable1.save() - cable2 = Cable( - termination_a=RearPort.objects.get(device__name='Panel 5', name='Rear Port 1'), - termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1') - ) - self.assertEqual(cable2.termination_a.positions, 1) # Sanity check - cable2.full_clean() - cable2.save() - - # Retrieve endpoints - endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1') - endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1') - - # Validate connections - self.assertEqual(endpoint_a.connected_endpoint, endpoint_b) - self.assertEqual(endpoint_b.connected_endpoint, endpoint_a) - self.assertTrue(endpoint_a.connection_status) - self.assertTrue(endpoint_b.connection_status) - - # Delete cable 1 - cable1.delete() - - # Refresh endpoints - endpoint_a.refresh_from_db() - endpoint_b.refresh_from_db() - - # Check that connections have been nullified - self.assertIsNone(endpoint_a.connected_endpoint) - self.assertIsNone(endpoint_b.connected_endpoint) - self.assertIsNone(endpoint_a.connection_status) - self.assertIsNone(endpoint_b.connection_status) - - def test_connections_via_nested_single_position_rearport(self): - """ - Test a connection which passes through a single front/rear port pair between two multi-position rear ports. - - Test two connections via patched rear ports: - Device 1 <---> Device 2 - Device 3 <---> Device 4 - - 1 2 - [Device 1] -----------+ +----------- [Device 2] - Iface1 | | Iface1 - FP1 | 3 4 | FP1 - [Panel 1] ----- [Panel 5] ----- [Panel 2] - FP2 | RP1 RP1 FP1 RP1 | FP2 - Iface1 | | Iface1 - [Device 3] -----------+ +----------- [Device 4] - 5 6 - """ - # Create cables (Panel 5 RP first, FP second) - cable1 = Cable( - termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'), - termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 1') - ) - cable1.full_clean() - cable1.save() - cable2 = Cable( - termination_b=FrontPort.objects.get(device__name='Panel 2', name='Front Port 1'), - termination_a=Interface.objects.get(device__name='Device 2', name='Interface 1') - ) - cable2.full_clean() - cable2.save() - cable3 = Cable( - termination_b=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'), - termination_a=RearPort.objects.get(device__name='Panel 5', name='Rear Port 1') - ) - cable3.full_clean() - cable3.save() - cable4 = Cable( - termination_b=FrontPort.objects.get(device__name='Panel 5', name='Front Port 1'), - termination_a=RearPort.objects.get(device__name='Panel 2', name='Rear Port 1') - ) - cable4.full_clean() - cable4.save() - cable5 = Cable( - termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 2'), - termination_a=Interface.objects.get(device__name='Device 3', name='Interface 1') - ) - cable5.full_clean() - cable5.save() - cable6 = Cable( - termination_b=FrontPort.objects.get(device__name='Panel 2', name='Front Port 2'), - termination_a=Interface.objects.get(device__name='Device 4', name='Interface 1') - ) - cable6.full_clean() - cable6.save() - - # Retrieve endpoints - endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1') - endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1') - endpoint_c = Interface.objects.get(device__name='Device 3', name='Interface 1') - endpoint_d = Interface.objects.get(device__name='Device 4', name='Interface 1') - - # Validate connections - self.assertEqual(endpoint_a.connected_endpoint, endpoint_b) - self.assertEqual(endpoint_b.connected_endpoint, endpoint_a) - self.assertEqual(endpoint_c.connected_endpoint, endpoint_d) - self.assertEqual(endpoint_d.connected_endpoint, endpoint_c) - self.assertTrue(endpoint_a.connection_status) - self.assertTrue(endpoint_b.connection_status) - self.assertTrue(endpoint_c.connection_status) - self.assertTrue(endpoint_d.connection_status) - - # Delete cable 3 - cable3.delete() - - # Refresh endpoints - endpoint_a.refresh_from_db() - endpoint_b.refresh_from_db() - endpoint_c.refresh_from_db() - endpoint_d.refresh_from_db() - - # Check that connections have been nullified - self.assertIsNone(endpoint_a.connected_endpoint) - self.assertIsNone(endpoint_b.connected_endpoint) - self.assertIsNone(endpoint_c.connected_endpoint) - self.assertIsNone(endpoint_d.connected_endpoint) - self.assertIsNone(endpoint_a.connection_status) - self.assertIsNone(endpoint_b.connection_status) - self.assertIsNone(endpoint_c.connection_status) - self.assertIsNone(endpoint_d.connection_status) - - def test_connections_via_patch(self): - """ - Test two connections via patched rear ports: - Device 1 <---> Device 2 - Device 3 <---> Device 4 - - 1 2 - [Device 1] -----------+ +----------- [Device 2] - Iface1 | | Iface1 - FP1 | 3 | FP1 - [Panel 1] ----- [Panel 2] - FP2 | RP1 RP1 | FP2 - Iface1 | | Iface1 - [Device 3] -----------+ +----------- [Device 4] - 4 5 - """ - # Create cables - cable1 = Cable( - termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'), - termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 1') - ) - cable1.full_clean() - cable1.save() - cable2 = Cable( - termination_a=Interface.objects.get(device__name='Device 2', name='Interface 1'), - termination_b=FrontPort.objects.get(device__name='Panel 2', name='Front Port 1') - ) - cable2.full_clean() - cable2.save() - - cable3 = Cable( - termination_a=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'), - termination_b=RearPort.objects.get(device__name='Panel 2', name='Rear Port 1') - ) - cable3.full_clean() - cable3.save() - - cable4 = Cable( - termination_a=Interface.objects.get(device__name='Device 3', name='Interface 1'), - termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 2') - ) - cable4.full_clean() - cable4.save() - cable5 = Cable( - termination_a=Interface.objects.get(device__name='Device 4', name='Interface 1'), - termination_b=FrontPort.objects.get(device__name='Panel 2', name='Front Port 2') - ) - cable5.full_clean() - cable5.save() - - # Retrieve endpoints - endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1') - endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1') - endpoint_c = Interface.objects.get(device__name='Device 3', name='Interface 1') - endpoint_d = Interface.objects.get(device__name='Device 4', name='Interface 1') - - # Validate connections - self.assertEqual(endpoint_a.connected_endpoint, endpoint_b) - self.assertEqual(endpoint_b.connected_endpoint, endpoint_a) - self.assertEqual(endpoint_c.connected_endpoint, endpoint_d) - self.assertEqual(endpoint_d.connected_endpoint, endpoint_c) - self.assertTrue(endpoint_a.connection_status) - self.assertTrue(endpoint_b.connection_status) - self.assertTrue(endpoint_c.connection_status) - self.assertTrue(endpoint_d.connection_status) - - # Delete cable 3 - cable3.delete() - - # Refresh endpoints - endpoint_a.refresh_from_db() - endpoint_b.refresh_from_db() - endpoint_c.refresh_from_db() - endpoint_d.refresh_from_db() - - # Check that connections have been nullified - self.assertIsNone(endpoint_a.connected_endpoint) - self.assertIsNone(endpoint_b.connected_endpoint) - self.assertIsNone(endpoint_c.connected_endpoint) - self.assertIsNone(endpoint_d.connected_endpoint) - self.assertIsNone(endpoint_a.connection_status) - self.assertIsNone(endpoint_b.connection_status) - self.assertIsNone(endpoint_c.connection_status) - self.assertIsNone(endpoint_d.connection_status) - - def test_connections_via_multiple_patches(self): - """ - Test two connections via patched rear ports: - Device 1 <---> Device 2 - Device 3 <---> Device 4 - - 1 2 3 - [Device 1] -----------+ +---------------+ +----------- [Device 2] - Iface1 | | | | Iface1 - FP1 | 4 | FP1 FP1 | 5 | FP1 - [Panel 1] ----- [Panel 2] [Panel 3] ----- [Panel 4] - FP2 | RP1 RP1 | FP2 FP2 | RP1 RP1 | FP2 - Iface1 | | | | Iface1 - [Device 3] -----------+ +---------------+ +----------- [Device 4] - 6 7 8 - """ - # Create cables - cable1 = Cable( - termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'), - termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 1') - ) - cable1.full_clean() - cable1.save() - cable2 = Cable( - termination_a=FrontPort.objects.get(device__name='Panel 2', name='Front Port 1'), - termination_b=FrontPort.objects.get(device__name='Panel 3', name='Front Port 1') - ) - cable2.full_clean() - cable2.save() - cable3 = Cable( - termination_a=FrontPort.objects.get(device__name='Panel 4', name='Front Port 1'), - termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1') - ) - cable3.full_clean() - cable3.save() - - cable4 = Cable( - termination_a=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'), - termination_b=RearPort.objects.get(device__name='Panel 2', name='Rear Port 1') - ) - cable4.full_clean() - cable4.save() - cable5 = Cable( - termination_a=RearPort.objects.get(device__name='Panel 3', name='Rear Port 1'), - termination_b=RearPort.objects.get(device__name='Panel 4', name='Rear Port 1') - ) - cable5.full_clean() - cable5.save() - - cable6 = Cable( - termination_a=Interface.objects.get(device__name='Device 3', name='Interface 1'), - termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 2') - ) - cable6.full_clean() - cable6.save() - cable7 = Cable( - termination_a=FrontPort.objects.get(device__name='Panel 2', name='Front Port 2'), - termination_b=FrontPort.objects.get(device__name='Panel 3', name='Front Port 2') - ) - cable7.full_clean() - cable7.save() - cable8 = Cable( - termination_a=FrontPort.objects.get(device__name='Panel 4', name='Front Port 2'), - termination_b=Interface.objects.get(device__name='Device 4', name='Interface 1') - ) - cable8.full_clean() - cable8.save() - - # Retrieve endpoints - endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1') - endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1') - endpoint_c = Interface.objects.get(device__name='Device 3', name='Interface 1') - endpoint_d = Interface.objects.get(device__name='Device 4', name='Interface 1') - - # Validate connections - self.assertEqual(endpoint_a.connected_endpoint, endpoint_b) - self.assertEqual(endpoint_b.connected_endpoint, endpoint_a) - self.assertEqual(endpoint_c.connected_endpoint, endpoint_d) - self.assertEqual(endpoint_d.connected_endpoint, endpoint_c) - self.assertTrue(endpoint_a.connection_status) - self.assertTrue(endpoint_b.connection_status) - self.assertTrue(endpoint_c.connection_status) - self.assertTrue(endpoint_d.connection_status) - - # Delete cables 4 and 5 - cable4.delete() - cable5.delete() - - # Refresh endpoints - endpoint_a.refresh_from_db() - endpoint_b.refresh_from_db() - endpoint_c.refresh_from_db() - endpoint_d.refresh_from_db() - - # Check that connections have been nullified - self.assertIsNone(endpoint_a.connected_endpoint) - self.assertIsNone(endpoint_b.connected_endpoint) - self.assertIsNone(endpoint_c.connected_endpoint) - self.assertIsNone(endpoint_d.connected_endpoint) - self.assertIsNone(endpoint_a.connection_status) - self.assertIsNone(endpoint_b.connection_status) - self.assertIsNone(endpoint_c.connection_status) - self.assertIsNone(endpoint_d.connection_status) - - def test_connections_via_nested_rear_ports(self): - """ - Test two connections via nested rear ports: - Device 1 <---> Device 2 - Device 3 <---> Device 4 - - 1 2 - [Device 1] -----------+ +----------- [Device 2] - Iface1 | | Iface1 - FP1 | 3 4 5 | FP1 - [Panel 1] ----- [Panel 2] ----- [Panel 3] ----- [Panel 4] - FP2 | RP1 FP1 RP1 RP1 FP1 RP1 | FP2 - Iface1 | | Iface1 - [Device 3] -----------+ +----------- [Device 4] - 6 7 - """ - # Create cables - cable1 = Cable( - termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'), - termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 1') - ) - cable1.full_clean() - cable1.save() - cable2 = Cable( - termination_a=FrontPort.objects.get(device__name='Panel 4', name='Front Port 1'), - termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1') - ) - cable2.full_clean() - cable2.save() - - cable3 = Cable( - termination_a=RearPort.objects.get(device__name='Panel 1', name='Rear Port 1'), - termination_b=FrontPort.objects.get(device__name='Panel 2', name='Front Port 1') - ) - cable3.full_clean() - cable3.save() - cable4 = Cable( - termination_a=RearPort.objects.get(device__name='Panel 2', name='Rear Port 1'), - termination_b=RearPort.objects.get(device__name='Panel 3', name='Rear Port 1') - ) - cable4.full_clean() - cable4.save() - cable5 = Cable( - termination_a=FrontPort.objects.get(device__name='Panel 3', name='Front Port 1'), - termination_b=RearPort.objects.get(device__name='Panel 4', name='Rear Port 1') - ) - cable5.full_clean() - cable5.save() - - cable6 = Cable( - termination_a=Interface.objects.get(device__name='Device 3', name='Interface 1'), - termination_b=FrontPort.objects.get(device__name='Panel 1', name='Front Port 2') - ) - cable6.full_clean() - cable6.save() - cable7 = Cable( - termination_a=FrontPort.objects.get(device__name='Panel 4', name='Front Port 2'), - termination_b=Interface.objects.get(device__name='Device 4', name='Interface 1') - ) - cable7.full_clean() - cable7.save() - - # Retrieve endpoints - endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1') - endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1') - endpoint_c = Interface.objects.get(device__name='Device 3', name='Interface 1') - endpoint_d = Interface.objects.get(device__name='Device 4', name='Interface 1') - - # Validate connections - self.assertEqual(endpoint_a.connected_endpoint, endpoint_b) - self.assertEqual(endpoint_b.connected_endpoint, endpoint_a) - self.assertEqual(endpoint_c.connected_endpoint, endpoint_d) - self.assertEqual(endpoint_d.connected_endpoint, endpoint_c) - self.assertTrue(endpoint_a.connection_status) - self.assertTrue(endpoint_b.connection_status) - self.assertTrue(endpoint_c.connection_status) - self.assertTrue(endpoint_d.connection_status) - - # Delete cable 4 - cable4.delete() - - # Refresh endpoints - endpoint_a.refresh_from_db() - endpoint_b.refresh_from_db() - endpoint_c.refresh_from_db() - endpoint_d.refresh_from_db() - - # Check that connections have been nullified - self.assertIsNone(endpoint_a.connected_endpoint) - self.assertIsNone(endpoint_b.connected_endpoint) - self.assertIsNone(endpoint_c.connected_endpoint) - self.assertIsNone(endpoint_d.connected_endpoint) - self.assertIsNone(endpoint_a.connection_status) - self.assertIsNone(endpoint_b.connection_status) - self.assertIsNone(endpoint_c.connection_status) - self.assertIsNone(endpoint_d.connection_status) - - def test_connection_via_circuit(self): - """ - 1 2 - [Device 1] ----- [Circuit] ----- [Device 2] - Iface1 A Z Iface1 - - """ - # Create cables - cable1 = Cable( - termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'), - termination_b=CircuitTermination.objects.get(term_side='A') - ) - cable1.full_clean() - cable1.save() - cable2 = Cable( - termination_a=CircuitTermination.objects.get(term_side='Z'), - termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1') - ) - cable2.full_clean() - cable2.save() - - # Retrieve endpoints - endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1') - endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1') - - # Validate connections - self.assertEqual(endpoint_a.connected_endpoint, endpoint_b) - self.assertEqual(endpoint_b.connected_endpoint, endpoint_a) - self.assertTrue(endpoint_a.connection_status) - self.assertTrue(endpoint_b.connection_status) - - # Delete circuit - circuit = Circuit.objects.first().delete() - - # Refresh endpoints - endpoint_a.refresh_from_db() - endpoint_b.refresh_from_db() - - # Check that connections have been nullified - self.assertIsNone(endpoint_a.connected_endpoint) - self.assertIsNone(endpoint_b.connected_endpoint) - self.assertIsNone(endpoint_a.connection_status) - self.assertIsNone(endpoint_b.connection_status) - - def test_connection_via_patched_circuit(self): - """ - 1 2 3 4 - [Device 1] ----- [Panel 5] ----- [Circuit] ----- [Panel 6] ----- [Device 2] - Iface1 FP1 RP1 A Z RP1 FP1 Iface1 - - """ - # Create cables - cable1 = Cable( - termination_a=Interface.objects.get(device__name='Device 1', name='Interface 1'), - termination_b=FrontPort.objects.get(device__name='Panel 5', name='Front Port 1') - ) - cable1.full_clean() - cable1.save() - cable2 = Cable( - termination_a=RearPort.objects.get(device__name='Panel 5', name='Rear Port 1'), - termination_b=CircuitTermination.objects.get(term_side='A') - ) - cable2.full_clean() - cable2.save() - cable3 = Cable( - termination_a=CircuitTermination.objects.get(term_side='Z'), - termination_b=RearPort.objects.get(device__name='Panel 6', name='Rear Port 1') - ) - cable3.full_clean() - cable3.save() - cable4 = Cable( - termination_a=FrontPort.objects.get(device__name='Panel 6', name='Front Port 1'), - termination_b=Interface.objects.get(device__name='Device 2', name='Interface 1') - ) - cable4.full_clean() - cable4.save() - - # Retrieve endpoints - endpoint_a = Interface.objects.get(device__name='Device 1', name='Interface 1') - endpoint_b = Interface.objects.get(device__name='Device 2', name='Interface 1') - - # Validate connections - self.assertEqual(endpoint_a.connected_endpoint, endpoint_b) - self.assertEqual(endpoint_b.connected_endpoint, endpoint_a) - self.assertTrue(endpoint_a.connection_status) - self.assertTrue(endpoint_b.connection_status) - - # Delete circuit - circuit = Circuit.objects.first().delete() - - # Refresh endpoints - endpoint_a.refresh_from_db() - endpoint_b.refresh_from_db() - - # Check that connections have been nullified - self.assertIsNone(endpoint_a.connected_endpoint) - self.assertIsNone(endpoint_b.connected_endpoint) - self.assertIsNone(endpoint_a.connection_status) - self.assertIsNone(endpoint_b.connection_status) diff --git a/netbox/dcim/tests/test_views.py b/netbox/dcim/tests/test_views.py index 066ea1b029..97a4f37058 100644 --- a/netbox/dcim/tests/test_views.py +++ b/netbox/dcim/tests/test_views.py @@ -101,10 +101,10 @@ def setUpTestData(cls): } cls.csv_data = ( - "name,slug", - "Site 4,site-4", - "Site 5,site-5", - "Site 6,site-6", + "name,slug,status", + "Site 4,site-4,planned", + "Site 5,site-5,active", + "Site 6,site-6,staging", ) cls.bulk_edit_data = { @@ -983,9 +983,9 @@ def setUpTestData(cls): cls.csv_data = ( "device_role,manufacturer,device_type,status,name,site,rack_group,rack,position,face", - "Device Role 1,Manufacturer 1,Device Type 1,Active,Device 4,Site 1,Rack Group 1,Rack 1,10,Front", - "Device Role 1,Manufacturer 1,Device Type 1,Active,Device 5,Site 1,Rack Group 1,Rack 1,20,Front", - "Device Role 1,Manufacturer 1,Device Type 1,Active,Device 6,Site 1,Rack Group 1,Rack 1,30,Front", + "Device Role 1,Manufacturer 1,Device Type 1,active,Device 4,Site 1,Rack Group 1,Rack 1,10,front", + "Device Role 1,Manufacturer 1,Device Type 1,active,Device 5,Site 1,Rack Group 1,Rack 1,20,front", + "Device Role 1,Manufacturer 1,Device Type 1,active,Device 6,Site 1,Rack Group 1,Rack 1,30,front", ) cls.bulk_edit_data = { @@ -997,6 +997,130 @@ def setUpTestData(cls): 'status': DeviceStatusChoices.STATUS_DECOMMISSIONING, } + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) + def test_device_consoleports(self): + device = Device.objects.first() + console_ports = ( + ConsolePort(device=device, name='Console Port 1'), + ConsolePort(device=device, name='Console Port 2'), + ConsolePort(device=device, name='Console Port 3'), + ) + ConsolePort.objects.bulk_create(console_ports) + + url = reverse('dcim:device_consoleports', kwargs={'pk': device.pk}) + self.assertHttpStatus(self.client.get(url), 200) + + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) + def test_device_consoleserverports(self): + device = Device.objects.first() + console_server_ports = ( + ConsoleServerPort(device=device, name='Console Server Port 1'), + ConsoleServerPort(device=device, name='Console Server Port 2'), + ConsoleServerPort(device=device, name='Console Server Port 3'), + ) + ConsoleServerPort.objects.bulk_create(console_server_ports) + + url = reverse('dcim:device_consoleserverports', kwargs={'pk': device.pk}) + self.assertHttpStatus(self.client.get(url), 200) + + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) + def test_device_powerports(self): + device = Device.objects.first() + power_ports = ( + PowerPort(device=device, name='Power Port 1'), + PowerPort(device=device, name='Power Port 2'), + PowerPort(device=device, name='Power Port 3'), + ) + PowerPort.objects.bulk_create(power_ports) + + url = reverse('dcim:device_powerports', kwargs={'pk': device.pk}) + self.assertHttpStatus(self.client.get(url), 200) + + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) + def test_device_poweroutlets(self): + device = Device.objects.first() + power_outlets = ( + PowerOutlet(device=device, name='Power Outlet 1'), + PowerOutlet(device=device, name='Power Outlet 2'), + PowerOutlet(device=device, name='Power Outlet 3'), + ) + PowerOutlet.objects.bulk_create(power_outlets) + + url = reverse('dcim:device_poweroutlets', kwargs={'pk': device.pk}) + self.assertHttpStatus(self.client.get(url), 200) + + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) + def test_device_interfaces(self): + device = Device.objects.first() + interfaces = ( + Interface(device=device, name='Interface 1'), + Interface(device=device, name='Interface 2'), + Interface(device=device, name='Interface 3'), + ) + Interface.objects.bulk_create(interfaces) + + url = reverse('dcim:device_interfaces', kwargs={'pk': device.pk}) + self.assertHttpStatus(self.client.get(url), 200) + + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) + def test_device_rearports(self): + device = Device.objects.first() + rear_ports = ( + RearPort(device=device, name='Rear Port 1'), + RearPort(device=device, name='Rear Port 2'), + RearPort(device=device, name='Rear Port 3'), + ) + RearPort.objects.bulk_create(rear_ports) + + url = reverse('dcim:device_rearports', kwargs={'pk': device.pk}) + self.assertHttpStatus(self.client.get(url), 200) + + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) + def test_device_frontports(self): + device = Device.objects.first() + rear_ports = ( + RearPort(device=device, name='Rear Port 1'), + RearPort(device=device, name='Rear Port 2'), + RearPort(device=device, name='Rear Port 3'), + ) + RearPort.objects.bulk_create(rear_ports) + front_ports = ( + FrontPort(device=device, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1), + FrontPort(device=device, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1), + FrontPort(device=device, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1), + ) + FrontPort.objects.bulk_create(front_ports) + + url = reverse('dcim:device_frontports', kwargs={'pk': device.pk}) + self.assertHttpStatus(self.client.get(url), 200) + + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) + def test_device_devicebays(self): + device = Device.objects.first() + device_bays = ( + DeviceBay(device=device, name='Device Bay 1'), + DeviceBay(device=device, name='Device Bay 2'), + DeviceBay(device=device, name='Device Bay 3'), + ) + DeviceBay.objects.bulk_create(device_bays) + + url = reverse('dcim:device_devicebays', kwargs={'pk': device.pk}) + self.assertHttpStatus(self.client.get(url), 200) + + @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) + def test_device_inventory(self): + device = Device.objects.first() + inventory_items = ( + InventoryItem(device=device, name='Inventory Item 1'), + InventoryItem(device=device, name='Inventory Item 2'), + InventoryItem(device=device, name='Inventory Item 3'), + ) + for item in inventory_items: + item.save() + + url = reverse('dcim:device_inventory', kwargs={'pk': device.pk}) + self.assertHttpStatus(self.client.get(url), 200) + class ConsolePortTestCase(ViewTestCases.DeviceComponentViewTestCase): model = ConsolePort @@ -1267,9 +1391,9 @@ def setUpTestData(cls): cls.csv_data = ( "device,name,type", - "Device 1,Interface 4,1000BASE-T (1GE)", - "Device 1,Interface 5,1000BASE-T (1GE)", - "Device 1,Interface 6,1000BASE-T (1GE)", + "Device 1,Interface 4,1000base-t", + "Device 1,Interface 5,1000base-t", + "Device 1,Interface 6,1000base-t", ) @@ -1326,9 +1450,9 @@ def setUpTestData(cls): cls.csv_data = ( "device,name,type,rear_port,rear_port_position", - "Device 1,Front Port 4,8P8C,Rear Port 4,1", - "Device 1,Front Port 5,8P8C,Rear Port 5,1", - "Device 1,Front Port 6,8P8C,Rear Port 6,1", + "Device 1,Front Port 4,8p8c,Rear Port 4,1", + "Device 1,Front Port 5,8p8c,Rear Port 5,1", + "Device 1,Front Port 6,8p8c,Rear Port 6,1", ) @@ -1372,9 +1496,9 @@ def setUpTestData(cls): cls.csv_data = ( "device,name,type,positions", - "Device 1,Rear Port 4,8P8C,1", - "Device 1,Rear Port 5,8P8C,1", - "Device 1,Rear Port 6,8P8C,1", + "Device 1,Rear Port 4,8p8c,1", + "Device 1,Rear Port 5,8p8c,1", + "Device 1,Rear Port 6,8p8c,1", ) @@ -1430,11 +1554,9 @@ def setUpTestData(cls): device = create_test_device('Device 1') manufacturer, _ = Manufacturer.objects.get_or_create(name='Manufacturer 1', slug='manufacturer-1') - InventoryItem.objects.bulk_create([ - InventoryItem(device=device, name='Inventory Item 1'), - InventoryItem(device=device, name='Inventory Item 2'), - InventoryItem(device=device, name='Inventory Item 3'), - ]) + InventoryItem.objects.create(device=device, name='Inventory Item 1') + InventoryItem.objects.create(device=device, name='Inventory Item 2') + InventoryItem.objects.create(device=device, name='Inventory Item 3') tags = cls.create_tags('Alpha', 'Bravo', 'Charlie') @@ -1546,9 +1668,9 @@ def setUpTestData(cls): cls.csv_data = ( "side_a_device,side_a_type,side_a_name,side_b_device,side_b_type,side_b_name", - "Device 3,interface,Interface 1,Device 4,interface,Interface 1", - "Device 3,interface,Interface 2,Device 4,interface,Interface 2", - "Device 3,interface,Interface 3,Device 4,interface,Interface 3", + "Device 3,dcim.interface,Interface 1,Device 4,dcim.interface,Interface 1", + "Device 3,dcim.interface,Interface 2,Device 4,dcim.interface,Interface 2", + "Device 3,dcim.interface,Interface 3,Device 4,dcim.interface,Interface 3", ) cls.bulk_edit_data = { @@ -1716,11 +1838,6 @@ def setUpTestData(cls): 'max_utilization': 50, 'comments': 'New comments', 'tags': [t.pk for t in tags], - - # Connection - 'cable': None, - 'connected_endpoint': None, - 'connection_status': None, } cls.csv_data = ( diff --git a/netbox/dcim/urls.py b/netbox/dcim/urls.py index 63ae5d2a43..d167ebdb71 100644 --- a/netbox/dcim/urls.py +++ b/netbox/dcim/urls.py @@ -187,9 +187,17 @@ path('devices//', views.DeviceView.as_view(), name='device'), path('devices//edit/', views.DeviceEditView.as_view(), name='device_edit'), path('devices//delete/', views.DeviceDeleteView.as_view(), name='device_delete'), - path('devices//config-context/', views.DeviceConfigContextView.as_view(), name='device_configcontext'), - path('devices//changelog/', ObjectChangeLogView.as_view(), name='device_changelog', kwargs={'model': Device}), + path('devices//console-ports/', views.DeviceConsolePortsView.as_view(), name='device_consoleports'), + path('devices//console-server-ports/', views.DeviceConsoleServerPortsView.as_view(), name='device_consoleserverports'), + path('devices//power-ports/', views.DevicePowerPortsView.as_view(), name='device_powerports'), + path('devices//power-outlets/', views.DevicePowerOutletsView.as_view(), name='device_poweroutlets'), + path('devices//interfaces/', views.DeviceInterfacesView.as_view(), name='device_interfaces'), + path('devices//front-ports/', views.DeviceFrontPortsView.as_view(), name='device_frontports'), + path('devices//rear-ports/', views.DeviceRearPortsView.as_view(), name='device_rearports'), + path('devices//device-bays/', views.DeviceDeviceBaysView.as_view(), name='device_devicebays'), path('devices//inventory/', views.DeviceInventoryView.as_view(), name='device_inventory'), + path('devices//config-context/', views.DeviceConfigContextView.as_view(), name='device_configcontext'), + path('devices//changelog/', views.DeviceChangeLogView.as_view(), name='device_changelog', kwargs={'model': Device}), path('devices//status/', views.DeviceStatusView.as_view(), name='device_status'), path('devices//lldp-neighbors/', views.DeviceLLDPNeighborsView.as_view(), name='device_lldp_neighbors'), path('devices//config/', views.DeviceConfigView.as_view(), name='device_config'), @@ -208,7 +216,7 @@ path('console-ports//edit/', views.ConsolePortEditView.as_view(), name='consoleport_edit'), path('console-ports//delete/', views.ConsolePortDeleteView.as_view(), name='consoleport_delete'), path('console-ports//changelog/', ObjectChangeLogView.as_view(), name='consoleport_changelog', kwargs={'model': ConsolePort}), - path('console-ports//trace/', views.CableTraceView.as_view(), name='consoleport_trace', kwargs={'model': ConsolePort}), + path('console-ports//trace/', views.PathTraceView.as_view(), name='consoleport_trace', kwargs={'model': ConsolePort}), path('console-ports//connect//', views.CableCreateView.as_view(), name='consoleport_connect', kwargs={'termination_a_type': ConsolePort}), path('devices/console-ports/add/', views.DeviceBulkAddConsolePortView.as_view(), name='device_bulk_add_consoleport'), @@ -224,7 +232,7 @@ path('console-server-ports//edit/', views.ConsoleServerPortEditView.as_view(), name='consoleserverport_edit'), path('console-server-ports//delete/', views.ConsoleServerPortDeleteView.as_view(), name='consoleserverport_delete'), path('console-server-ports//changelog/', ObjectChangeLogView.as_view(), name='consoleserverport_changelog', kwargs={'model': ConsoleServerPort}), - path('console-server-ports//trace/', views.CableTraceView.as_view(), name='consoleserverport_trace', kwargs={'model': ConsoleServerPort}), + path('console-server-ports//trace/', views.PathTraceView.as_view(), name='consoleserverport_trace', kwargs={'model': ConsoleServerPort}), path('console-server-ports//connect//', views.CableCreateView.as_view(), name='consoleserverport_connect', kwargs={'termination_a_type': ConsoleServerPort}), path('devices/console-server-ports/add/', views.DeviceBulkAddConsoleServerPortView.as_view(), name='device_bulk_add_consoleserverport'), @@ -240,7 +248,7 @@ path('power-ports//edit/', views.PowerPortEditView.as_view(), name='powerport_edit'), path('power-ports//delete/', views.PowerPortDeleteView.as_view(), name='powerport_delete'), path('power-ports//changelog/', ObjectChangeLogView.as_view(), name='powerport_changelog', kwargs={'model': PowerPort}), - path('power-ports//trace/', views.CableTraceView.as_view(), name='powerport_trace', kwargs={'model': PowerPort}), + path('power-ports//trace/', views.PathTraceView.as_view(), name='powerport_trace', kwargs={'model': PowerPort}), path('power-ports//connect//', views.CableCreateView.as_view(), name='powerport_connect', kwargs={'termination_a_type': PowerPort}), path('devices/power-ports/add/', views.DeviceBulkAddPowerPortView.as_view(), name='device_bulk_add_powerport'), @@ -256,7 +264,7 @@ path('power-outlets//edit/', views.PowerOutletEditView.as_view(), name='poweroutlet_edit'), path('power-outlets//delete/', views.PowerOutletDeleteView.as_view(), name='poweroutlet_delete'), path('power-outlets//changelog/', ObjectChangeLogView.as_view(), name='poweroutlet_changelog', kwargs={'model': PowerOutlet}), - path('power-outlets//trace/', views.CableTraceView.as_view(), name='poweroutlet_trace', kwargs={'model': PowerOutlet}), + path('power-outlets//trace/', views.PathTraceView.as_view(), name='poweroutlet_trace', kwargs={'model': PowerOutlet}), path('power-outlets//connect//', views.CableCreateView.as_view(), name='poweroutlet_connect', kwargs={'termination_a_type': PowerOutlet}), path('devices/power-outlets/add/', views.DeviceBulkAddPowerOutletView.as_view(), name='device_bulk_add_poweroutlet'), @@ -272,7 +280,7 @@ path('interfaces//edit/', views.InterfaceEditView.as_view(), name='interface_edit'), path('interfaces//delete/', views.InterfaceDeleteView.as_view(), name='interface_delete'), path('interfaces//changelog/', ObjectChangeLogView.as_view(), name='interface_changelog', kwargs={'model': Interface}), - path('interfaces//trace/', views.CableTraceView.as_view(), name='interface_trace', kwargs={'model': Interface}), + path('interfaces//trace/', views.PathTraceView.as_view(), name='interface_trace', kwargs={'model': Interface}), path('interfaces//connect//', views.CableCreateView.as_view(), name='interface_connect', kwargs={'termination_a_type': Interface}), path('devices/interfaces/add/', views.DeviceBulkAddInterfaceView.as_view(), name='device_bulk_add_interface'), @@ -288,7 +296,7 @@ path('front-ports//edit/', views.FrontPortEditView.as_view(), name='frontport_edit'), path('front-ports//delete/', views.FrontPortDeleteView.as_view(), name='frontport_delete'), path('front-ports//changelog/', ObjectChangeLogView.as_view(), name='frontport_changelog', kwargs={'model': FrontPort}), - path('front-ports//trace/', views.CableTraceView.as_view(), name='frontport_trace', kwargs={'model': FrontPort}), + path('front-ports//trace/', views.PathTraceView.as_view(), name='frontport_trace', kwargs={'model': FrontPort}), path('front-ports//connect//', views.CableCreateView.as_view(), name='frontport_connect', kwargs={'termination_a_type': FrontPort}), # path('devices/front-ports/add/', views.DeviceBulkAddFrontPortView.as_view(), name='device_bulk_add_frontport'), @@ -304,7 +312,7 @@ path('rear-ports//edit/', views.RearPortEditView.as_view(), name='rearport_edit'), path('rear-ports//delete/', views.RearPortDeleteView.as_view(), name='rearport_delete'), path('rear-ports//changelog/', ObjectChangeLogView.as_view(), name='rearport_changelog', kwargs={'model': RearPort}), - path('rear-ports//trace/', views.CableTraceView.as_view(), name='rearport_trace', kwargs={'model': RearPort}), + path('rear-ports//trace/', views.PathTraceView.as_view(), name='rearport_trace', kwargs={'model': RearPort}), path('rear-ports//connect//', views.CableCreateView.as_view(), name='rearport_connect', kwargs={'termination_a_type': RearPort}), path('devices/rear-ports/add/', views.DeviceBulkAddRearPortView.as_view(), name='device_bulk_add_rearport'), @@ -384,6 +392,8 @@ path('power-feeds//', views.PowerFeedView.as_view(), name='powerfeed'), path('power-feeds//edit/', views.PowerFeedEditView.as_view(), name='powerfeed_edit'), path('power-feeds//delete/', views.PowerFeedDeleteView.as_view(), name='powerfeed_delete'), + path('power-feeds//trace/', views.PathTraceView.as_view(), name='powerfeed_trace', kwargs={'model': PowerFeed}), path('power-feeds//changelog/', ObjectChangeLogView.as_view(), name='powerfeed_changelog', kwargs={'model': PowerFeed}), + path('power-feeds//connect//', views.CableCreateView.as_view(), name='powerfeed_connect', kwargs={'termination_a_type': PowerFeed}), ] diff --git a/netbox/dcim/utils.py b/netbox/dcim/utils.py new file mode 100644 index 0000000000..91c5c7c772 --- /dev/null +++ b/netbox/dcim/utils.py @@ -0,0 +1,28 @@ +from django.contrib.contenttypes.models import ContentType + + +def compile_path_node(ct_id, object_id): + return f'{ct_id}:{object_id}' + + +def decompile_path_node(repr): + ct_id, object_id = repr.split(':') + return int(ct_id), int(object_id) + + +def object_to_path_node(obj): + """ + Return a representation of an object suitable for inclusion in a CablePath path. Node representation is in the + form :. + """ + ct = ContentType.objects.get_for_model(obj) + return compile_path_node(ct.pk, obj.pk) + + +def path_node_to_object(repr): + """ + Given the string representation of a path node, return the corresponding instance. + """ + ct_id, object_id = decompile_path_node(repr) + ct = ContentType.objects.get_for_id(ct_id) + return ct.model_class().objects.get(pk=object_id) diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 200581f4af..9f8e4c13fa 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -7,35 +7,30 @@ from django.db.models import F, Prefetch from django.forms import ModelMultipleChoiceField, MultipleHiddenInput, modelformset_factory from django.shortcuts import get_object_or_404, redirect, render -from django.urls import reverse from django.utils.html import escape from django.utils.safestring import mark_safe from django.views.generic import View from circuits.models import Circuit -from extras.models import Graph -from extras.views import ObjectConfigContextView +from extras.views import ObjectChangeLogView, ObjectConfigContextView from ipam.models import IPAddress, Prefix, Service, VLAN from ipam.tables import InterfaceIPAddressTable, InterfaceVLANTable +from netbox.views import generic from secrets.models import Secret from utilities.forms import ConfirmationForm from utilities.paginator import EnhancedPaginator, get_paginate_count from utilities.permissions import get_permission_for_model from utilities.utils import csv_format, get_subquery -from utilities.views import ( - BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, BulkRenameView, ComponentCreateView, - GetReturnURLMixin, ObjectView, ObjectImportView, ObjectDeleteView, ObjectEditView, ObjectListView, - ObjectPermissionRequiredMixin, -) +from utilities.views import GetReturnURLMixin, ObjectPermissionRequiredMixin from virtualization.models import VirtualMachine from . import filters, forms, tables from .choices import DeviceFaceChoices from .constants import NONCONNECTABLE_IFACE_TYPES from .models import ( - Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay, + Cable, CablePath, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay, DeviceBayTemplate, DeviceRole, DeviceType, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate, - InventoryItem, Manufacturer, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, PowerPort, - PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site, + InventoryItem, Manufacturer, PathEndpoint, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, + PowerPort, PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site, VirtualChassis, ) @@ -103,7 +98,7 @@ def post(self, request): # Regions # -class RegionListView(ObjectListView): +class RegionListView(generic.ObjectListView): queryset = Region.objects.add_related_count( Region.objects.all(), Site, @@ -116,22 +111,22 @@ class RegionListView(ObjectListView): table = tables.RegionTable -class RegionEditView(ObjectEditView): +class RegionEditView(generic.ObjectEditView): queryset = Region.objects.all() model_form = forms.RegionForm -class RegionDeleteView(ObjectDeleteView): +class RegionDeleteView(generic.ObjectDeleteView): queryset = Region.objects.all() -class RegionBulkImportView(BulkImportView): +class RegionBulkImportView(generic.BulkImportView): queryset = Region.objects.all() model_form = forms.RegionCSVForm table = tables.RegionTable -class RegionBulkDeleteView(BulkDeleteView): +class RegionBulkDeleteView(generic.BulkDeleteView): queryset = Region.objects.add_related_count( Region.objects.all(), Site, @@ -147,26 +142,24 @@ class RegionBulkDeleteView(BulkDeleteView): # Sites # -class SiteListView(ObjectListView): - queryset = Site.objects.prefetch_related('region', 'tenant') +class SiteListView(generic.ObjectListView): + queryset = Site.objects.all() filterset = filters.SiteFilterSet filterset_form = forms.SiteFilterForm table = tables.SiteTable -class SiteView(ObjectView): +class SiteView(generic.ObjectView): queryset = Site.objects.prefetch_related('region', 'tenant__group') - def get(self, request, slug): - - site = get_object_or_404(self.queryset, slug=slug) + def get_extra_context(self, request, instance): stats = { - 'rack_count': Rack.objects.restrict(request.user, 'view').filter(site=site).count(), - 'device_count': Device.objects.restrict(request.user, 'view').filter(site=site).count(), - 'prefix_count': Prefix.objects.restrict(request.user, 'view').filter(site=site).count(), - 'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(site=site).count(), - 'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(terminations__site=site).count(), - 'vm_count': VirtualMachine.objects.restrict(request.user, 'view').filter(cluster__site=site).count(), + 'rack_count': Rack.objects.restrict(request.user, 'view').filter(site=instance).count(), + 'device_count': Device.objects.restrict(request.user, 'view').filter(site=instance).count(), + 'prefix_count': Prefix.objects.restrict(request.user, 'view').filter(site=instance).count(), + 'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(site=instance).count(), + 'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(terminations__site=instance).count(), + 'vm_count': VirtualMachine.objects.restrict(request.user, 'view').filter(cluster__site=instance).count(), } rack_groups = RackGroup.objects.add_related_count( RackGroup.objects.all(), @@ -174,41 +167,38 @@ def get(self, request, slug): 'group', 'rack_count', cumulative=True - ).restrict(request.user, 'view').filter(site=site) - show_graphs = Graph.objects.filter(type__model='site').exists() + ).restrict(request.user, 'view').filter(site=instance) - return render(request, 'dcim/site.html', { - 'site': site, + return { 'stats': stats, 'rack_groups': rack_groups, - 'show_graphs': show_graphs, - }) + } -class SiteEditView(ObjectEditView): +class SiteEditView(generic.ObjectEditView): queryset = Site.objects.all() model_form = forms.SiteForm template_name = 'dcim/site_edit.html' -class SiteDeleteView(ObjectDeleteView): +class SiteDeleteView(generic.ObjectDeleteView): queryset = Site.objects.all() -class SiteBulkImportView(BulkImportView): +class SiteBulkImportView(generic.BulkImportView): queryset = Site.objects.all() model_form = forms.SiteCSVForm table = tables.SiteTable -class SiteBulkEditView(BulkEditView): +class SiteBulkEditView(generic.BulkEditView): queryset = Site.objects.prefetch_related('region', 'tenant') filterset = filters.SiteFilterSet table = tables.SiteTable form = forms.SiteBulkEditForm -class SiteBulkDeleteView(BulkDeleteView): +class SiteBulkDeleteView(generic.BulkDeleteView): queryset = Site.objects.prefetch_related('region', 'tenant') filterset = filters.SiteFilterSet table = tables.SiteTable @@ -218,35 +208,35 @@ class SiteBulkDeleteView(BulkDeleteView): # Rack groups # -class RackGroupListView(ObjectListView): +class RackGroupListView(generic.ObjectListView): queryset = RackGroup.objects.add_related_count( RackGroup.objects.all(), Rack, 'group', 'rack_count', cumulative=True - ).prefetch_related('site') + ) filterset = filters.RackGroupFilterSet filterset_form = forms.RackGroupFilterForm table = tables.RackGroupTable -class RackGroupEditView(ObjectEditView): +class RackGroupEditView(generic.ObjectEditView): queryset = RackGroup.objects.all() model_form = forms.RackGroupForm -class RackGroupDeleteView(ObjectDeleteView): +class RackGroupDeleteView(generic.ObjectDeleteView): queryset = RackGroup.objects.all() -class RackGroupBulkImportView(BulkImportView): +class RackGroupBulkImportView(generic.BulkImportView): queryset = RackGroup.objects.all() model_form = forms.RackGroupCSVForm table = tables.RackGroupTable -class RackGroupBulkDeleteView(BulkDeleteView): +class RackGroupBulkDeleteView(generic.BulkDeleteView): queryset = RackGroup.objects.add_related_count( RackGroup.objects.all(), Rack, @@ -262,29 +252,29 @@ class RackGroupBulkDeleteView(BulkDeleteView): # Rack roles # -class RackRoleListView(ObjectListView): +class RackRoleListView(generic.ObjectListView): queryset = RackRole.objects.annotate( rack_count=get_subquery(Rack, 'role') ) table = tables.RackRoleTable -class RackRoleEditView(ObjectEditView): +class RackRoleEditView(generic.ObjectEditView): queryset = RackRole.objects.all() model_form = forms.RackRoleForm -class RackRoleDeleteView(ObjectDeleteView): +class RackRoleDeleteView(generic.ObjectDeleteView): queryset = RackRole.objects.all() -class RackRoleBulkImportView(BulkImportView): +class RackRoleBulkImportView(generic.BulkImportView): queryset = RackRole.objects.all() model_form = forms.RackRoleCSVForm table = tables.RackRoleTable -class RackRoleBulkDeleteView(BulkDeleteView): +class RackRoleBulkDeleteView(generic.BulkDeleteView): queryset = RackRole.objects.annotate( rack_count=get_subquery(Rack, 'role') ) @@ -295,7 +285,7 @@ class RackRoleBulkDeleteView(BulkDeleteView): # Racks # -class RackListView(ObjectListView): +class RackListView(generic.ObjectListView): queryset = Rack.objects.prefetch_related( 'site', 'group', 'tenant', 'role', 'devices__device_type' ).annotate( @@ -306,7 +296,7 @@ class RackListView(ObjectListView): table = tables.RackDetailTable -class RackElevationListView(ObjectListView): +class RackElevationListView(generic.ObjectListView): """ Display a set of rack elevations side-by-side. """ @@ -348,65 +338,66 @@ def get(self, request): }) -class RackView(ObjectView): +class RackView(generic.ObjectView): queryset = Rack.objects.prefetch_related('site__region', 'tenant__group', 'group', 'role') - def get(self, request, pk): - rack = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Get 0U and child devices located within the rack nonracked_devices = Device.objects.filter( - rack=rack, + rack=instance, position__isnull=True ).prefetch_related('device_type__manufacturer') - peer_racks = Rack.objects.restrict(request.user, 'view').filter(site=rack.site) + peer_racks = Rack.objects.restrict(request.user, 'view').filter(site=instance.site) - if rack.group: - peer_racks = peer_racks.filter(group=rack.group) + if instance.group: + peer_racks = peer_racks.filter(group=instance.group) else: peer_racks = peer_racks.filter(group__isnull=True) - next_rack = peer_racks.filter(name__gt=rack.name).order_by('name').first() - prev_rack = peer_racks.filter(name__lt=rack.name).order_by('-name').first() + next_rack = peer_racks.filter(name__gt=instance.name).order_by('name').first() + prev_rack = peer_racks.filter(name__lt=instance.name).order_by('-name').first() + + reservations = RackReservation.objects.restrict(request.user, 'view').filter(rack=instance) + power_feeds = PowerFeed.objects.restrict(request.user, 'view').filter(rack=instance).prefetch_related( + 'power_panel' + ) - reservations = RackReservation.objects.restrict(request.user, 'view').filter(rack=rack) - power_feeds = PowerFeed.objects.restrict(request.user, 'view').filter(rack=rack).prefetch_related('power_panel') + device_count = Device.objects.restrict(request.user, 'view').filter(rack=instance).count() - return render(request, 'dcim/rack.html', { - 'rack': rack, - 'device_count': Device.objects.restrict(request.user, 'view').filter(rack=rack).count(), + return { + 'device_count': device_count, 'reservations': reservations, 'power_feeds': power_feeds, 'nonracked_devices': nonracked_devices, 'next_rack': next_rack, 'prev_rack': prev_rack, - }) + } -class RackEditView(ObjectEditView): +class RackEditView(generic.ObjectEditView): queryset = Rack.objects.all() model_form = forms.RackForm template_name = 'dcim/rack_edit.html' -class RackDeleteView(ObjectDeleteView): +class RackDeleteView(generic.ObjectDeleteView): queryset = Rack.objects.all() -class RackBulkImportView(BulkImportView): +class RackBulkImportView(generic.BulkImportView): queryset = Rack.objects.all() model_form = forms.RackCSVForm table = tables.RackTable -class RackBulkEditView(BulkEditView): +class RackBulkEditView(generic.BulkEditView): queryset = Rack.objects.prefetch_related('site', 'group', 'tenant', 'role') filterset = filters.RackFilterSet table = tables.RackTable form = forms.RackBulkEditForm -class RackBulkDeleteView(BulkDeleteView): +class RackBulkDeleteView(generic.BulkDeleteView): queryset = Rack.objects.prefetch_related('site', 'group', 'tenant', 'role') filterset = filters.RackFilterSet table = tables.RackTable @@ -416,26 +407,18 @@ class RackBulkDeleteView(BulkDeleteView): # Rack reservations # -class RackReservationListView(ObjectListView): - queryset = RackReservation.objects.prefetch_related('rack__site') +class RackReservationListView(generic.ObjectListView): + queryset = RackReservation.objects.all() filterset = filters.RackReservationFilterSet filterset_form = forms.RackReservationFilterForm table = tables.RackReservationTable -class RackReservationView(ObjectView): +class RackReservationView(generic.ObjectView): queryset = RackReservation.objects.prefetch_related('rack') - def get(self, request, pk): - - rackreservation = get_object_or_404(self.queryset, pk=pk) - - return render(request, 'dcim/rackreservation.html', { - 'rackreservation': rackreservation, - }) - -class RackReservationEditView(ObjectEditView): +class RackReservationEditView(generic.ObjectEditView): queryset = RackReservation.objects.all() model_form = forms.RackReservationForm template_name = 'dcim/rackreservation_edit.html' @@ -448,11 +431,11 @@ def alter_obj(self, obj, request, args, kwargs): return obj -class RackReservationDeleteView(ObjectDeleteView): +class RackReservationDeleteView(generic.ObjectDeleteView): queryset = RackReservation.objects.all() -class RackReservationImportView(BulkImportView): +class RackReservationImportView(generic.BulkImportView): queryset = RackReservation.objects.all() model_form = forms.RackReservationCSVForm table = tables.RackReservationTable @@ -468,14 +451,14 @@ def _save_obj(self, obj_form, request): return instance -class RackReservationBulkEditView(BulkEditView): +class RackReservationBulkEditView(generic.BulkEditView): queryset = RackReservation.objects.prefetch_related('rack', 'user') filterset = filters.RackReservationFilterSet table = tables.RackReservationTable form = forms.RackReservationBulkEditForm -class RackReservationBulkDeleteView(BulkDeleteView): +class RackReservationBulkDeleteView(generic.BulkDeleteView): queryset = RackReservation.objects.prefetch_related('rack', 'user') filterset = filters.RackReservationFilterSet table = tables.RackReservationTable @@ -485,7 +468,7 @@ class RackReservationBulkDeleteView(BulkDeleteView): # Manufacturers # -class ManufacturerListView(ObjectListView): +class ManufacturerListView(generic.ObjectListView): queryset = Manufacturer.objects.annotate( devicetype_count=get_subquery(DeviceType, 'manufacturer'), inventoryitem_count=get_subquery(InventoryItem, 'manufacturer'), @@ -494,22 +477,22 @@ class ManufacturerListView(ObjectListView): table = tables.ManufacturerTable -class ManufacturerEditView(ObjectEditView): +class ManufacturerEditView(generic.ObjectEditView): queryset = Manufacturer.objects.all() model_form = forms.ManufacturerForm -class ManufacturerDeleteView(ObjectDeleteView): +class ManufacturerDeleteView(generic.ObjectDeleteView): queryset = Manufacturer.objects.all() -class ManufacturerBulkImportView(BulkImportView): +class ManufacturerBulkImportView(generic.BulkImportView): queryset = Manufacturer.objects.all() model_form = forms.ManufacturerCSVForm table = tables.ManufacturerTable -class ManufacturerBulkDeleteView(BulkDeleteView): +class ManufacturerBulkDeleteView(generic.BulkDeleteView): queryset = Manufacturer.objects.annotate( devicetype_count=get_subquery(DeviceType, 'manufacturer') ) @@ -520,7 +503,7 @@ class ManufacturerBulkDeleteView(BulkDeleteView): # Device types # -class DeviceTypeListView(ObjectListView): +class DeviceTypeListView(generic.ObjectListView): queryset = DeviceType.objects.prefetch_related('manufacturer').annotate( instance_count=get_subquery(Device, 'device_type') ) @@ -529,45 +512,43 @@ class DeviceTypeListView(ObjectListView): table = tables.DeviceTypeTable -class DeviceTypeView(ObjectView): +class DeviceTypeView(generic.ObjectView): queryset = DeviceType.objects.prefetch_related('manufacturer') - def get(self, request, pk): - - devicetype = get_object_or_404(self.queryset, pk=pk) - instance_count = Device.objects.restrict(request.user).filter(device_type=devicetype).count() + def get_extra_context(self, request, instance): + instance_count = Device.objects.restrict(request.user).filter(device_type=instance).count() # Component tables consoleport_table = tables.ConsolePortTemplateTable( - ConsolePortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype), + ConsolePortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance), orderable=False ) consoleserverport_table = tables.ConsoleServerPortTemplateTable( - ConsoleServerPortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype), + ConsoleServerPortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance), orderable=False ) powerport_table = tables.PowerPortTemplateTable( - PowerPortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype), + PowerPortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance), orderable=False ) poweroutlet_table = tables.PowerOutletTemplateTable( - PowerOutletTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype), + PowerOutletTemplate.objects.restrict(request.user, 'view').filter(device_type=instance), orderable=False ) interface_table = tables.InterfaceTemplateTable( - list(InterfaceTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype)), + list(InterfaceTemplate.objects.restrict(request.user, 'view').filter(device_type=instance)), orderable=False ) front_port_table = tables.FrontPortTemplateTable( - FrontPortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype), + FrontPortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance), orderable=False ) rear_port_table = tables.RearPortTemplateTable( - RearPortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype), + RearPortTemplate.objects.restrict(request.user, 'view').filter(device_type=instance), orderable=False ) devicebay_table = tables.DeviceBayTemplateTable( - DeviceBayTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype), + DeviceBayTemplate.objects.restrict(request.user, 'view').filter(device_type=instance), orderable=False ) if request.user.has_perm('dcim.change_devicetype'): @@ -580,8 +561,7 @@ def get(self, request, pk): rear_port_table.columns.show('pk') devicebay_table.columns.show('pk') - return render(request, 'dcim/devicetype.html', { - 'devicetype': devicetype, + return { 'instance_count': instance_count, 'consoleport_table': consoleport_table, 'consoleserverport_table': consoleserverport_table, @@ -591,20 +571,20 @@ def get(self, request, pk): 'front_port_table': front_port_table, 'rear_port_table': rear_port_table, 'devicebay_table': devicebay_table, - }) + } -class DeviceTypeEditView(ObjectEditView): +class DeviceTypeEditView(generic.ObjectEditView): queryset = DeviceType.objects.all() model_form = forms.DeviceTypeForm template_name = 'dcim/devicetype_edit.html' -class DeviceTypeDeleteView(ObjectDeleteView): +class DeviceTypeDeleteView(generic.ObjectDeleteView): queryset = DeviceType.objects.all() -class DeviceTypeImportView(ObjectImportView): +class DeviceTypeImportView(generic.ObjectImportView): additional_permissions = [ 'dcim.add_devicetype', 'dcim.add_consoleporttemplate', @@ -630,7 +610,7 @@ class DeviceTypeImportView(ObjectImportView): )) -class DeviceTypeBulkEditView(BulkEditView): +class DeviceTypeBulkEditView(generic.BulkEditView): queryset = DeviceType.objects.prefetch_related('manufacturer').annotate( instance_count=get_subquery(Device, 'device_type') ) @@ -639,7 +619,7 @@ class DeviceTypeBulkEditView(BulkEditView): form = forms.DeviceTypeBulkEditForm -class DeviceTypeBulkDeleteView(BulkDeleteView): +class DeviceTypeBulkDeleteView(generic.BulkDeleteView): queryset = DeviceType.objects.prefetch_related('manufacturer').annotate( instance_count=get_subquery(Device, 'device_type') ) @@ -651,33 +631,33 @@ class DeviceTypeBulkDeleteView(BulkDeleteView): # Console port templates # -class ConsolePortTemplateCreateView(ComponentCreateView): +class ConsolePortTemplateCreateView(generic.ComponentCreateView): queryset = ConsolePortTemplate.objects.all() form = forms.ConsolePortTemplateCreateForm model_form = forms.ConsolePortTemplateForm template_name = 'dcim/device_component_add.html' -class ConsolePortTemplateEditView(ObjectEditView): +class ConsolePortTemplateEditView(generic.ObjectEditView): queryset = ConsolePortTemplate.objects.all() model_form = forms.ConsolePortTemplateForm -class ConsolePortTemplateDeleteView(ObjectDeleteView): +class ConsolePortTemplateDeleteView(generic.ObjectDeleteView): queryset = ConsolePortTemplate.objects.all() -class ConsolePortTemplateBulkEditView(BulkEditView): +class ConsolePortTemplateBulkEditView(generic.BulkEditView): queryset = ConsolePortTemplate.objects.all() table = tables.ConsolePortTemplateTable form = forms.ConsolePortTemplateBulkEditForm -class ConsolePortTemplateBulkRenameView(BulkRenameView): +class ConsolePortTemplateBulkRenameView(generic.BulkRenameView): queryset = ConsolePortTemplate.objects.all() -class ConsolePortTemplateBulkDeleteView(BulkDeleteView): +class ConsolePortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = ConsolePortTemplate.objects.all() table = tables.ConsolePortTemplateTable @@ -686,33 +666,33 @@ class ConsolePortTemplateBulkDeleteView(BulkDeleteView): # Console server port templates # -class ConsoleServerPortTemplateCreateView(ComponentCreateView): +class ConsoleServerPortTemplateCreateView(generic.ComponentCreateView): queryset = ConsoleServerPortTemplate.objects.all() form = forms.ConsoleServerPortTemplateCreateForm model_form = forms.ConsoleServerPortTemplateForm template_name = 'dcim/device_component_add.html' -class ConsoleServerPortTemplateEditView(ObjectEditView): +class ConsoleServerPortTemplateEditView(generic.ObjectEditView): queryset = ConsoleServerPortTemplate.objects.all() model_form = forms.ConsoleServerPortTemplateForm -class ConsoleServerPortTemplateDeleteView(ObjectDeleteView): +class ConsoleServerPortTemplateDeleteView(generic.ObjectDeleteView): queryset = ConsoleServerPortTemplate.objects.all() -class ConsoleServerPortTemplateBulkEditView(BulkEditView): +class ConsoleServerPortTemplateBulkEditView(generic.BulkEditView): queryset = ConsoleServerPortTemplate.objects.all() table = tables.ConsoleServerPortTemplateTable form = forms.ConsoleServerPortTemplateBulkEditForm -class ConsoleServerPortTemplateBulkRenameView(BulkRenameView): +class ConsoleServerPortTemplateBulkRenameView(generic.BulkRenameView): queryset = ConsoleServerPortTemplate.objects.all() -class ConsoleServerPortTemplateBulkDeleteView(BulkDeleteView): +class ConsoleServerPortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = ConsoleServerPortTemplate.objects.all() table = tables.ConsoleServerPortTemplateTable @@ -721,33 +701,33 @@ class ConsoleServerPortTemplateBulkDeleteView(BulkDeleteView): # Power port templates # -class PowerPortTemplateCreateView(ComponentCreateView): +class PowerPortTemplateCreateView(generic.ComponentCreateView): queryset = PowerPortTemplate.objects.all() form = forms.PowerPortTemplateCreateForm model_form = forms.PowerPortTemplateForm template_name = 'dcim/device_component_add.html' -class PowerPortTemplateEditView(ObjectEditView): +class PowerPortTemplateEditView(generic.ObjectEditView): queryset = PowerPortTemplate.objects.all() model_form = forms.PowerPortTemplateForm -class PowerPortTemplateDeleteView(ObjectDeleteView): +class PowerPortTemplateDeleteView(generic.ObjectDeleteView): queryset = PowerPortTemplate.objects.all() -class PowerPortTemplateBulkEditView(BulkEditView): +class PowerPortTemplateBulkEditView(generic.BulkEditView): queryset = PowerPortTemplate.objects.all() table = tables.PowerPortTemplateTable form = forms.PowerPortTemplateBulkEditForm -class PowerPortTemplateBulkRenameView(BulkRenameView): +class PowerPortTemplateBulkRenameView(generic.BulkRenameView): queryset = PowerPortTemplate.objects.all() -class PowerPortTemplateBulkDeleteView(BulkDeleteView): +class PowerPortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = PowerPortTemplate.objects.all() table = tables.PowerPortTemplateTable @@ -756,33 +736,33 @@ class PowerPortTemplateBulkDeleteView(BulkDeleteView): # Power outlet templates # -class PowerOutletTemplateCreateView(ComponentCreateView): +class PowerOutletTemplateCreateView(generic.ComponentCreateView): queryset = PowerOutletTemplate.objects.all() form = forms.PowerOutletTemplateCreateForm model_form = forms.PowerOutletTemplateForm template_name = 'dcim/device_component_add.html' -class PowerOutletTemplateEditView(ObjectEditView): +class PowerOutletTemplateEditView(generic.ObjectEditView): queryset = PowerOutletTemplate.objects.all() model_form = forms.PowerOutletTemplateForm -class PowerOutletTemplateDeleteView(ObjectDeleteView): +class PowerOutletTemplateDeleteView(generic.ObjectDeleteView): queryset = PowerOutletTemplate.objects.all() -class PowerOutletTemplateBulkEditView(BulkEditView): +class PowerOutletTemplateBulkEditView(generic.BulkEditView): queryset = PowerOutletTemplate.objects.all() table = tables.PowerOutletTemplateTable form = forms.PowerOutletTemplateBulkEditForm -class PowerOutletTemplateBulkRenameView(BulkRenameView): +class PowerOutletTemplateBulkRenameView(generic.BulkRenameView): queryset = PowerOutletTemplate.objects.all() -class PowerOutletTemplateBulkDeleteView(BulkDeleteView): +class PowerOutletTemplateBulkDeleteView(generic.BulkDeleteView): queryset = PowerOutletTemplate.objects.all() table = tables.PowerOutletTemplateTable @@ -791,33 +771,33 @@ class PowerOutletTemplateBulkDeleteView(BulkDeleteView): # Interface templates # -class InterfaceTemplateCreateView(ComponentCreateView): +class InterfaceTemplateCreateView(generic.ComponentCreateView): queryset = InterfaceTemplate.objects.all() form = forms.InterfaceTemplateCreateForm model_form = forms.InterfaceTemplateForm template_name = 'dcim/device_component_add.html' -class InterfaceTemplateEditView(ObjectEditView): +class InterfaceTemplateEditView(generic.ObjectEditView): queryset = InterfaceTemplate.objects.all() model_form = forms.InterfaceTemplateForm -class InterfaceTemplateDeleteView(ObjectDeleteView): +class InterfaceTemplateDeleteView(generic.ObjectDeleteView): queryset = InterfaceTemplate.objects.all() -class InterfaceTemplateBulkEditView(BulkEditView): +class InterfaceTemplateBulkEditView(generic.BulkEditView): queryset = InterfaceTemplate.objects.all() table = tables.InterfaceTemplateTable form = forms.InterfaceTemplateBulkEditForm -class InterfaceTemplateBulkRenameView(BulkRenameView): +class InterfaceTemplateBulkRenameView(generic.BulkRenameView): queryset = InterfaceTemplate.objects.all() -class InterfaceTemplateBulkDeleteView(BulkDeleteView): +class InterfaceTemplateBulkDeleteView(generic.BulkDeleteView): queryset = InterfaceTemplate.objects.all() table = tables.InterfaceTemplateTable @@ -826,33 +806,33 @@ class InterfaceTemplateBulkDeleteView(BulkDeleteView): # Front port templates # -class FrontPortTemplateCreateView(ComponentCreateView): +class FrontPortTemplateCreateView(generic.ComponentCreateView): queryset = FrontPortTemplate.objects.all() form = forms.FrontPortTemplateCreateForm model_form = forms.FrontPortTemplateForm template_name = 'dcim/device_component_add.html' -class FrontPortTemplateEditView(ObjectEditView): +class FrontPortTemplateEditView(generic.ObjectEditView): queryset = FrontPortTemplate.objects.all() model_form = forms.FrontPortTemplateForm -class FrontPortTemplateDeleteView(ObjectDeleteView): +class FrontPortTemplateDeleteView(generic.ObjectDeleteView): queryset = FrontPortTemplate.objects.all() -class FrontPortTemplateBulkEditView(BulkEditView): +class FrontPortTemplateBulkEditView(generic.BulkEditView): queryset = FrontPortTemplate.objects.all() table = tables.FrontPortTemplateTable form = forms.FrontPortTemplateBulkEditForm -class FrontPortTemplateBulkRenameView(BulkRenameView): +class FrontPortTemplateBulkRenameView(generic.BulkRenameView): queryset = FrontPortTemplate.objects.all() -class FrontPortTemplateBulkDeleteView(BulkDeleteView): +class FrontPortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = FrontPortTemplate.objects.all() table = tables.FrontPortTemplateTable @@ -861,33 +841,33 @@ class FrontPortTemplateBulkDeleteView(BulkDeleteView): # Rear port templates # -class RearPortTemplateCreateView(ComponentCreateView): +class RearPortTemplateCreateView(generic.ComponentCreateView): queryset = RearPortTemplate.objects.all() form = forms.RearPortTemplateCreateForm model_form = forms.RearPortTemplateForm template_name = 'dcim/device_component_add.html' -class RearPortTemplateEditView(ObjectEditView): +class RearPortTemplateEditView(generic.ObjectEditView): queryset = RearPortTemplate.objects.all() model_form = forms.RearPortTemplateForm -class RearPortTemplateDeleteView(ObjectDeleteView): +class RearPortTemplateDeleteView(generic.ObjectDeleteView): queryset = RearPortTemplate.objects.all() -class RearPortTemplateBulkEditView(BulkEditView): +class RearPortTemplateBulkEditView(generic.BulkEditView): queryset = RearPortTemplate.objects.all() table = tables.RearPortTemplateTable form = forms.RearPortTemplateBulkEditForm -class RearPortTemplateBulkRenameView(BulkRenameView): +class RearPortTemplateBulkRenameView(generic.BulkRenameView): queryset = RearPortTemplate.objects.all() -class RearPortTemplateBulkDeleteView(BulkDeleteView): +class RearPortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = RearPortTemplate.objects.all() table = tables.RearPortTemplateTable @@ -896,33 +876,33 @@ class RearPortTemplateBulkDeleteView(BulkDeleteView): # Device bay templates # -class DeviceBayTemplateCreateView(ComponentCreateView): +class DeviceBayTemplateCreateView(generic.ComponentCreateView): queryset = DeviceBayTemplate.objects.all() form = forms.DeviceBayTemplateCreateForm model_form = forms.DeviceBayTemplateForm template_name = 'dcim/device_component_add.html' -class DeviceBayTemplateEditView(ObjectEditView): +class DeviceBayTemplateEditView(generic.ObjectEditView): queryset = DeviceBayTemplate.objects.all() model_form = forms.DeviceBayTemplateForm -class DeviceBayTemplateDeleteView(ObjectDeleteView): +class DeviceBayTemplateDeleteView(generic.ObjectDeleteView): queryset = DeviceBayTemplate.objects.all() -class DeviceBayTemplateBulkEditView(BulkEditView): +class DeviceBayTemplateBulkEditView(generic.BulkEditView): queryset = DeviceBayTemplate.objects.all() table = tables.DeviceBayTemplateTable form = forms.DeviceBayTemplateBulkEditForm -class DeviceBayTemplateBulkRenameView(BulkRenameView): +class DeviceBayTemplateBulkRenameView(generic.BulkRenameView): queryset = DeviceBayTemplate.objects.all() -class DeviceBayTemplateBulkDeleteView(BulkDeleteView): +class DeviceBayTemplateBulkDeleteView(generic.BulkDeleteView): queryset = DeviceBayTemplate.objects.all() table = tables.DeviceBayTemplateTable @@ -931,7 +911,7 @@ class DeviceBayTemplateBulkDeleteView(BulkDeleteView): # Device roles # -class DeviceRoleListView(ObjectListView): +class DeviceRoleListView(generic.ObjectListView): queryset = DeviceRole.objects.annotate( device_count=get_subquery(Device, 'device_role'), vm_count=get_subquery(VirtualMachine, 'role') @@ -939,22 +919,22 @@ class DeviceRoleListView(ObjectListView): table = tables.DeviceRoleTable -class DeviceRoleEditView(ObjectEditView): +class DeviceRoleEditView(generic.ObjectEditView): queryset = DeviceRole.objects.all() model_form = forms.DeviceRoleForm -class DeviceRoleDeleteView(ObjectDeleteView): +class DeviceRoleDeleteView(generic.ObjectDeleteView): queryset = DeviceRole.objects.all() -class DeviceRoleBulkImportView(BulkImportView): +class DeviceRoleBulkImportView(generic.BulkImportView): queryset = DeviceRole.objects.all() model_form = forms.DeviceRoleCSVForm table = tables.DeviceRoleTable -class DeviceRoleBulkDeleteView(BulkDeleteView): +class DeviceRoleBulkDeleteView(generic.BulkDeleteView): queryset = DeviceRole.objects.all() table = tables.DeviceRoleTable @@ -963,7 +943,7 @@ class DeviceRoleBulkDeleteView(BulkDeleteView): # Platforms # -class PlatformListView(ObjectListView): +class PlatformListView(generic.ObjectListView): queryset = Platform.objects.annotate( device_count=get_subquery(Device, 'platform'), vm_count=get_subquery(VirtualMachine, 'platform') @@ -971,22 +951,22 @@ class PlatformListView(ObjectListView): table = tables.PlatformTable -class PlatformEditView(ObjectEditView): +class PlatformEditView(generic.ObjectEditView): queryset = Platform.objects.all() model_form = forms.PlatformForm -class PlatformDeleteView(ObjectDeleteView): +class PlatformDeleteView(generic.ObjectDeleteView): queryset = Platform.objects.all() -class PlatformBulkImportView(BulkImportView): +class PlatformBulkImportView(generic.BulkImportView): queryset = Platform.objects.all() model_form = forms.PlatformCSVForm table = tables.PlatformTable -class PlatformBulkDeleteView(BulkDeleteView): +class PlatformBulkDeleteView(generic.BulkDeleteView): queryset = Platform.objects.all() table = tables.PlatformTable @@ -995,200 +975,320 @@ class PlatformBulkDeleteView(BulkDeleteView): # Devices # -class DeviceListView(ObjectListView): - queryset = Device.objects.prefetch_related( - 'device_type__manufacturer', 'device_role', 'tenant', 'site', 'rack', 'primary_ip4', 'primary_ip6' - ) +class DeviceListView(generic.ObjectListView): + queryset = Device.objects.all() filterset = filters.DeviceFilterSet filterset_form = forms.DeviceFilterForm table = tables.DeviceTable template_name = 'dcim/device_list.html' -class DeviceView(ObjectView): +class DeviceView(generic.ObjectView): queryset = Device.objects.prefetch_related( 'site__region', 'rack__group', 'tenant__group', 'device_role', 'platform', 'primary_ip4', 'primary_ip6' ) - def get(self, request, pk): - - device = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # VirtualChassis members - if device.virtual_chassis is not None: + if instance.virtual_chassis is not None: vc_members = Device.objects.restrict(request.user, 'view').filter( - virtual_chassis=device.virtual_chassis + virtual_chassis=instance.virtual_chassis ).order_by('vc_position') else: vc_members = [] - # Console ports - consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( - 'connected_endpoint__device', 'cable', + # Services + services = Service.objects.restrict(request.user, 'view').filter(device=instance) + + # Secrets + secrets = Secret.objects.restrict(request.user, 'view').filter(device=instance) + + # Find up to ten devices in the same site with the same functional role for quick reference. + related_devices = Device.objects.restrict(request.user, 'view').filter( + site=instance.site, device_role=instance.device_role + ).exclude( + pk=instance.pk + ).prefetch_related( + 'rack', 'device_type__manufacturer' + )[:10] + + return { + 'services': services, + 'secrets': secrets, + 'vc_members': vc_members, + 'related_devices': related_devices, + 'active_tab': 'device', + } + + +class DeviceConsolePortsView(generic.ObjectView): + queryset = Device.objects.all() + template_name = 'dcim/device/consoleports.html' + + def get_extra_context(self, request, instance): + consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related( + 'cable', '_path__destination', ) + consoleport_table = tables.DeviceConsolePortTable( + data=consoleports, + user=request.user, + orderable=False + ) + if request.user.has_perm('dcim.change_consoleport') or request.user.has_perm('dcim.delete_consoleport'): + consoleport_table.columns.show('pk') + + return { + 'consoleport_table': consoleport_table, + 'active_tab': 'console-ports', + } + - # Console server ports +class DeviceConsoleServerPortsView(generic.ObjectView): + queryset = Device.objects.all() + template_name = 'dcim/device/consoleserverports.html' + + def get_extra_context(self, request, instance): consoleserverports = ConsoleServerPort.objects.restrict(request.user, 'view').filter( - device=device + device=instance ).prefetch_related( - 'connected_endpoint__device', 'cable', + 'cable', '_path__destination', + ) + consoleserverport_table = tables.DeviceConsoleServerPortTable( + data=consoleserverports, + user=request.user, + orderable=False ) + if request.user.has_perm('dcim.change_consoleserverport') or \ + request.user.has_perm('dcim.delete_consoleserverport'): + consoleserverport_table.columns.show('pk') + + return { + 'consoleserverport_table': consoleserverport_table, + 'active_tab': 'console-server-ports', + } + + +class DevicePowerPortsView(generic.ObjectView): + queryset = Device.objects.all() + template_name = 'dcim/device/powerports.html' - # Power ports - powerports = PowerPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( - '_connected_poweroutlet__device', 'cable', + def get_extra_context(self, request, instance): + powerports = PowerPort.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related( + 'cable', '_path__destination', ) + powerport_table = tables.DevicePowerPortTable( + data=powerports, + user=request.user, + orderable=False + ) + if request.user.has_perm('dcim.change_powerport') or request.user.has_perm('dcim.delete_powerport'): + powerport_table.columns.show('pk') - # Power outlets - poweroutlets = PowerOutlet.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( - 'connected_endpoint__device', 'cable', 'power_port', + return { + 'powerport_table': powerport_table, + 'active_tab': 'power-ports', + } + + +class DevicePowerOutletsView(generic.ObjectView): + queryset = Device.objects.all() + template_name = 'dcim/device/poweroutlets.html' + + def get_extra_context(self, request, instance): + poweroutlets = PowerOutlet.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related( + 'cable', 'power_port', '_path__destination', + ) + poweroutlet_table = tables.DevicePowerOutletTable( + data=poweroutlets, + user=request.user, + orderable=False ) + if request.user.has_perm('dcim.change_poweroutlet') or request.user.has_perm('dcim.delete_poweroutlet'): + poweroutlet_table.columns.show('pk') + + return { + 'poweroutlet_table': poweroutlet_table, + 'active_tab': 'power-outlets', + } + + +class DeviceInterfacesView(generic.ObjectView): + queryset = Device.objects.all() + template_name = 'dcim/device/interfaces.html' - # Interfaces - interfaces = device.vc_interfaces.restrict(request.user, 'view').prefetch_related( + def get_extra_context(self, request, instance): + interfaces = instance.vc_interfaces.restrict(request.user, 'view').prefetch_related( Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)), Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user)), - 'lag', '_connected_interface__device', '_connected_circuittermination__circuit', 'cable', - 'cable__termination_a', 'cable__termination_b', 'tags' + 'lag', 'cable', '_path__destination', 'tags', ) - - # Front ports - frontports = FrontPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( - 'rear_port', 'cable', + interface_table = tables.DeviceInterfaceTable( + data=interfaces, + user=request.user, + orderable=False ) + if request.user.has_perm('dcim.change_interface') or request.user.has_perm('dcim.delete_interface'): + interface_table.columns.show('pk') + + return { + 'interface_table': interface_table, + 'active_tab': 'interfaces', + } - # Rear ports - rearports = RearPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related('cable') - # Device bays - devicebays = DeviceBay.objects.restrict(request.user, 'view').filter(device=device).prefetch_related( - 'installed_device__device_type__manufacturer', +class DeviceFrontPortsView(generic.ObjectView): + queryset = Device.objects.all() + template_name = 'dcim/device/frontports.html' + + def get_extra_context(self, request, instance): + frontports = FrontPort.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related( + 'rear_port', 'cable', + ) + frontport_table = tables.DeviceFrontPortTable( + data=frontports, + user=request.user, + orderable=False ) + if request.user.has_perm('dcim.change_frontport') or request.user.has_perm('dcim.delete_frontport'): + frontport_table.columns.show('pk') - # Services - services = Service.objects.restrict(request.user, 'view').filter(device=device) + return { + 'frontport_table': frontport_table, + 'active_tab': 'front-ports', + } - # Secrets - secrets = Secret.objects.restrict(request.user, 'view').filter(device=device) - # Find up to ten devices in the same site with the same functional role for quick reference. - related_devices = Device.objects.restrict(request.user, 'view').filter( - site=device.site, device_role=device.device_role - ).exclude( - pk=device.pk - ).prefetch_related( - 'rack', 'device_type__manufacturer' - )[:10] +class DeviceRearPortsView(generic.ObjectView): + queryset = Device.objects.all() + template_name = 'dcim/device/rearports.html' - return render(request, 'dcim/device.html', { - 'device': device, - 'consoleports': consoleports, - 'consoleserverports': consoleserverports, - 'powerports': powerports, - 'poweroutlets': poweroutlets, - 'interfaces': interfaces, - 'devicebays': devicebays, - 'frontports': frontports, - 'rearports': rearports, - 'services': services, - 'secrets': secrets, - 'vc_members': vc_members, - 'related_devices': related_devices, - 'show_graphs': Graph.objects.filter(type__model='device').exists(), - 'show_interface_graphs': Graph.objects.filter(type__model='interface').exists(), - }) + def get_extra_context(self, request, instance): + rearports = RearPort.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related('cable') + rearport_table = tables.DeviceRearPortTable( + data=rearports, + user=request.user, + orderable=False + ) + if request.user.has_perm('dcim.change_rearport') or request.user.has_perm('dcim.delete_rearport'): + rearport_table.columns.show('pk') + + return { + 'rearport_table': rearport_table, + 'active_tab': 'rear-ports', + } -class DeviceInventoryView(ObjectView): +class DeviceDeviceBaysView(generic.ObjectView): queryset = Device.objects.all() + template_name = 'dcim/device/devicebays.html' - def get(self, request, pk): + def get_extra_context(self, request, instance): + devicebays = DeviceBay.objects.restrict(request.user, 'view').filter(device=instance).prefetch_related( + 'installed_device__device_type__manufacturer', + ) + devicebay_table = tables.DeviceDeviceBayTable( + data=devicebays, + user=request.user, + orderable=False + ) + if request.user.has_perm('dcim.change_devicebay') or request.user.has_perm('dcim.delete_devicebay'): + devicebay_table.columns.show('pk') - device = get_object_or_404(self.queryset, pk=pk) - inventory_items = InventoryItem.objects.restrict(request.user, 'view').filter( - device=device, parent=None - ).prefetch_related( - 'manufacturer', 'child_items' + return { + 'devicebay_table': devicebay_table, + 'active_tab': 'device-bays', + } + + +class DeviceInventoryView(generic.ObjectView): + queryset = Device.objects.all() + template_name = 'dcim/device/inventory.html' + + def get_extra_context(self, request, instance): + inventoryitems = InventoryItem.objects.restrict(request.user, 'view').filter( + device=instance + ).prefetch_related('manufacturer') + inventoryitem_table = tables.DeviceInventoryItemTable( + data=inventoryitems, + user=request.user, + orderable=False ) + if request.user.has_perm('dcim.change_inventoryitem') or request.user.has_perm('dcim.delete_inventoryitem'): + inventoryitem_table.columns.show('pk') - return render(request, 'dcim/device_inventory.html', { - 'device': device, - 'inventory_items': inventory_items, + return { + 'inventoryitem_table': inventoryitem_table, 'active_tab': 'inventory', - }) + } -class DeviceStatusView(ObjectView): +class DeviceStatusView(generic.ObjectView): additional_permissions = ['dcim.napalm_read_device'] queryset = Device.objects.all() + template_name = 'dcim/device/status.html' - def get(self, request, pk): - - device = get_object_or_404(self.queryset, pk=pk) - - return render(request, 'dcim/device_status.html', { - 'device': device, + def get_extra_context(self, request, instance): + return { 'active_tab': 'status', - }) + } -class DeviceLLDPNeighborsView(ObjectView): +class DeviceLLDPNeighborsView(generic.ObjectView): additional_permissions = ['dcim.napalm_read_device'] queryset = Device.objects.all() + template_name = 'dcim/device/lldp_neighbors.html' - def get(self, request, pk): - - device = get_object_or_404(self.queryset, pk=pk) - interfaces = device.vc_interfaces.restrict(request.user, 'view').exclude( + def get_extra_context(self, request, instance): + interfaces = instance.vc_interfaces.restrict(request.user, 'view').prefetch_related( + '_path__destination' + ).exclude( type__in=NONCONNECTABLE_IFACE_TYPES - ).prefetch_related( - '_connected_interface__device' ) - return render(request, 'dcim/device_lldp_neighbors.html', { - 'device': device, + return { 'interfaces': interfaces, 'active_tab': 'lldp-neighbors', - }) + } -class DeviceConfigView(ObjectView): +class DeviceConfigView(generic.ObjectView): additional_permissions = ['dcim.napalm_read_device'] queryset = Device.objects.all() + template_name = 'dcim/device/config.html' - def get(self, request, pk): - - device = get_object_or_404(self.queryset, pk=pk) - - return render(request, 'dcim/device_config.html', { - 'device': device, + def get_extra_context(self, request, instance): + return { 'active_tab': 'config', - }) + } class DeviceConfigContextView(ObjectConfigContextView): queryset = Device.objects.annotate_config_context_data() - base_template = 'dcim/device.html' + base_template = 'dcim/device/base.html' + +class DeviceChangeLogView(ObjectChangeLogView): + base_template = 'dcim/device/base.html' -class DeviceEditView(ObjectEditView): + +class DeviceEditView(generic.ObjectEditView): queryset = Device.objects.all() model_form = forms.DeviceForm template_name = 'dcim/device_edit.html' -class DeviceDeleteView(ObjectDeleteView): +class DeviceDeleteView(generic.ObjectDeleteView): queryset = Device.objects.all() -class DeviceBulkImportView(BulkImportView): +class DeviceBulkImportView(generic.BulkImportView): queryset = Device.objects.all() model_form = forms.DeviceCSVForm table = tables.DeviceImportTable template_name = 'dcim/device_import.html' -class ChildDeviceBulkImportView(BulkImportView): +class ChildDeviceBulkImportView(generic.BulkImportView): queryset = Device.objects.all() model_form = forms.ChildDeviceCSVForm table = tables.DeviceImportTable @@ -1206,14 +1306,14 @@ def _save_obj(self, obj_form, request): return obj -class DeviceBulkEditView(BulkEditView): +class DeviceBulkEditView(generic.BulkEditView): queryset = Device.objects.prefetch_related('tenant', 'site', 'rack', 'device_role', 'device_type__manufacturer') filterset = filters.DeviceFilterSet table = tables.DeviceTable form = forms.DeviceBulkEditForm -class DeviceBulkDeleteView(BulkDeleteView): +class DeviceBulkDeleteView(generic.BulkDeleteView): queryset = Device.objects.prefetch_related('tenant', 'site', 'rack', 'device_role', 'device_type__manufacturer') filterset = filters.DeviceFilterSet table = tables.DeviceTable @@ -1223,49 +1323,54 @@ class DeviceBulkDeleteView(BulkDeleteView): # Console ports # -class ConsolePortListView(ObjectListView): - queryset = ConsolePort.objects.prefetch_related('device', 'cable') +class ConsolePortListView(generic.ObjectListView): + queryset = ConsolePort.objects.all() filterset = filters.ConsolePortFilterSet filterset_form = forms.ConsolePortFilterForm table = tables.ConsolePortTable action_buttons = ('import', 'export') -class ConsolePortView(ObjectView): +class ConsolePortView(generic.ObjectView): queryset = ConsolePort.objects.all() + def get_extra_context(self, request, instance): + return { + 'breadcrumb_url': 'dcim:device_consoleports' + } + -class ConsolePortCreateView(ComponentCreateView): +class ConsolePortCreateView(generic.ComponentCreateView): queryset = ConsolePort.objects.all() form = forms.ConsolePortCreateForm model_form = forms.ConsolePortForm template_name = 'dcim/device_component_add.html' -class ConsolePortEditView(ObjectEditView): +class ConsolePortEditView(generic.ObjectEditView): queryset = ConsolePort.objects.all() model_form = forms.ConsolePortForm template_name = 'dcim/device_component_edit.html' -class ConsolePortDeleteView(ObjectDeleteView): +class ConsolePortDeleteView(generic.ObjectDeleteView): queryset = ConsolePort.objects.all() -class ConsolePortBulkImportView(BulkImportView): +class ConsolePortBulkImportView(generic.BulkImportView): queryset = ConsolePort.objects.all() model_form = forms.ConsolePortCSVForm table = tables.ConsolePortTable -class ConsolePortBulkEditView(BulkEditView): +class ConsolePortBulkEditView(generic.BulkEditView): queryset = ConsolePort.objects.all() filterset = filters.ConsolePortFilterSet table = tables.ConsolePortTable form = forms.ConsolePortBulkEditForm -class ConsolePortBulkRenameView(BulkRenameView): +class ConsolePortBulkRenameView(generic.BulkRenameView): queryset = ConsolePort.objects.all() @@ -1273,7 +1378,7 @@ class ConsolePortBulkDisconnectView(BulkDisconnectView): queryset = ConsolePort.objects.all() -class ConsolePortBulkDeleteView(BulkDeleteView): +class ConsolePortBulkDeleteView(generic.BulkDeleteView): queryset = ConsolePort.objects.all() filterset = filters.ConsolePortFilterSet table = tables.ConsolePortTable @@ -1283,49 +1388,54 @@ class ConsolePortBulkDeleteView(BulkDeleteView): # Console server ports # -class ConsoleServerPortListView(ObjectListView): - queryset = ConsoleServerPort.objects.prefetch_related('device', 'cable') +class ConsoleServerPortListView(generic.ObjectListView): + queryset = ConsoleServerPort.objects.all() filterset = filters.ConsoleServerPortFilterSet filterset_form = forms.ConsoleServerPortFilterForm table = tables.ConsoleServerPortTable action_buttons = ('import', 'export') -class ConsoleServerPortView(ObjectView): +class ConsoleServerPortView(generic.ObjectView): queryset = ConsoleServerPort.objects.all() + def get_extra_context(self, request, instance): + return { + 'breadcrumb_url': 'dcim:device_consoleserverports' + } + -class ConsoleServerPortCreateView(ComponentCreateView): +class ConsoleServerPortCreateView(generic.ComponentCreateView): queryset = ConsoleServerPort.objects.all() form = forms.ConsoleServerPortCreateForm model_form = forms.ConsoleServerPortForm template_name = 'dcim/device_component_add.html' -class ConsoleServerPortEditView(ObjectEditView): +class ConsoleServerPortEditView(generic.ObjectEditView): queryset = ConsoleServerPort.objects.all() model_form = forms.ConsoleServerPortForm template_name = 'dcim/device_component_edit.html' -class ConsoleServerPortDeleteView(ObjectDeleteView): +class ConsoleServerPortDeleteView(generic.ObjectDeleteView): queryset = ConsoleServerPort.objects.all() -class ConsoleServerPortBulkImportView(BulkImportView): +class ConsoleServerPortBulkImportView(generic.BulkImportView): queryset = ConsoleServerPort.objects.all() model_form = forms.ConsoleServerPortCSVForm table = tables.ConsoleServerPortTable -class ConsoleServerPortBulkEditView(BulkEditView): +class ConsoleServerPortBulkEditView(generic.BulkEditView): queryset = ConsoleServerPort.objects.all() filterset = filters.ConsoleServerPortFilterSet table = tables.ConsoleServerPortTable form = forms.ConsoleServerPortBulkEditForm -class ConsoleServerPortBulkRenameView(BulkRenameView): +class ConsoleServerPortBulkRenameView(generic.BulkRenameView): queryset = ConsoleServerPort.objects.all() @@ -1333,7 +1443,7 @@ class ConsoleServerPortBulkDisconnectView(BulkDisconnectView): queryset = ConsoleServerPort.objects.all() -class ConsoleServerPortBulkDeleteView(BulkDeleteView): +class ConsoleServerPortBulkDeleteView(generic.BulkDeleteView): queryset = ConsoleServerPort.objects.all() filterset = filters.ConsoleServerPortFilterSet table = tables.ConsoleServerPortTable @@ -1343,49 +1453,54 @@ class ConsoleServerPortBulkDeleteView(BulkDeleteView): # Power ports # -class PowerPortListView(ObjectListView): - queryset = PowerPort.objects.prefetch_related('device', 'cable') +class PowerPortListView(generic.ObjectListView): + queryset = PowerPort.objects.all() filterset = filters.PowerPortFilterSet filterset_form = forms.PowerPortFilterForm table = tables.PowerPortTable action_buttons = ('import', 'export') -class PowerPortView(ObjectView): +class PowerPortView(generic.ObjectView): queryset = PowerPort.objects.all() + def get_extra_context(self, request, instance): + return { + 'breadcrumb_url': 'dcim:device_powerports' + } + -class PowerPortCreateView(ComponentCreateView): +class PowerPortCreateView(generic.ComponentCreateView): queryset = PowerPort.objects.all() form = forms.PowerPortCreateForm model_form = forms.PowerPortForm template_name = 'dcim/device_component_add.html' -class PowerPortEditView(ObjectEditView): +class PowerPortEditView(generic.ObjectEditView): queryset = PowerPort.objects.all() model_form = forms.PowerPortForm template_name = 'dcim/device_component_edit.html' -class PowerPortDeleteView(ObjectDeleteView): +class PowerPortDeleteView(generic.ObjectDeleteView): queryset = PowerPort.objects.all() -class PowerPortBulkImportView(BulkImportView): +class PowerPortBulkImportView(generic.BulkImportView): queryset = PowerPort.objects.all() model_form = forms.PowerPortCSVForm table = tables.PowerPortTable -class PowerPortBulkEditView(BulkEditView): +class PowerPortBulkEditView(generic.BulkEditView): queryset = PowerPort.objects.all() filterset = filters.PowerPortFilterSet table = tables.PowerPortTable form = forms.PowerPortBulkEditForm -class PowerPortBulkRenameView(BulkRenameView): +class PowerPortBulkRenameView(generic.BulkRenameView): queryset = PowerPort.objects.all() @@ -1393,7 +1508,7 @@ class PowerPortBulkDisconnectView(BulkDisconnectView): queryset = PowerPort.objects.all() -class PowerPortBulkDeleteView(BulkDeleteView): +class PowerPortBulkDeleteView(generic.BulkDeleteView): queryset = PowerPort.objects.all() filterset = filters.PowerPortFilterSet table = tables.PowerPortTable @@ -1403,49 +1518,54 @@ class PowerPortBulkDeleteView(BulkDeleteView): # Power outlets # -class PowerOutletListView(ObjectListView): - queryset = PowerOutlet.objects.prefetch_related('device', 'cable') +class PowerOutletListView(generic.ObjectListView): + queryset = PowerOutlet.objects.all() filterset = filters.PowerOutletFilterSet filterset_form = forms.PowerOutletFilterForm table = tables.PowerOutletTable action_buttons = ('import', 'export') -class PowerOutletView(ObjectView): +class PowerOutletView(generic.ObjectView): queryset = PowerOutlet.objects.all() + def get_extra_context(self, request, instance): + return { + 'breadcrumb_url': 'dcim:device_poweroutlets' + } + -class PowerOutletCreateView(ComponentCreateView): +class PowerOutletCreateView(generic.ComponentCreateView): queryset = PowerOutlet.objects.all() form = forms.PowerOutletCreateForm model_form = forms.PowerOutletForm template_name = 'dcim/device_component_add.html' -class PowerOutletEditView(ObjectEditView): +class PowerOutletEditView(generic.ObjectEditView): queryset = PowerOutlet.objects.all() model_form = forms.PowerOutletForm template_name = 'dcim/device_component_edit.html' -class PowerOutletDeleteView(ObjectDeleteView): +class PowerOutletDeleteView(generic.ObjectDeleteView): queryset = PowerOutlet.objects.all() -class PowerOutletBulkImportView(BulkImportView): +class PowerOutletBulkImportView(generic.BulkImportView): queryset = PowerOutlet.objects.all() model_form = forms.PowerOutletCSVForm table = tables.PowerOutletTable -class PowerOutletBulkEditView(BulkEditView): +class PowerOutletBulkEditView(generic.BulkEditView): queryset = PowerOutlet.objects.all() filterset = filters.PowerOutletFilterSet table = tables.PowerOutletTable form = forms.PowerOutletBulkEditForm -class PowerOutletBulkRenameView(BulkRenameView): +class PowerOutletBulkRenameView(generic.BulkRenameView): queryset = PowerOutlet.objects.all() @@ -1453,7 +1573,7 @@ class PowerOutletBulkDisconnectView(BulkDisconnectView): queryset = PowerOutlet.objects.all() -class PowerOutletBulkDeleteView(BulkDeleteView): +class PowerOutletBulkDeleteView(generic.BulkDeleteView): queryset = PowerOutlet.objects.all() filterset = filters.PowerOutletFilterSet table = tables.PowerOutletTable @@ -1463,81 +1583,76 @@ class PowerOutletBulkDeleteView(BulkDeleteView): # Interfaces # -class InterfaceListView(ObjectListView): - queryset = Interface.objects.prefetch_related('device', 'cable') +class InterfaceListView(generic.ObjectListView): + queryset = Interface.objects.all() filterset = filters.InterfaceFilterSet filterset_form = forms.InterfaceFilterForm table = tables.InterfaceTable action_buttons = ('import', 'export') -class InterfaceView(ObjectView): +class InterfaceView(generic.ObjectView): queryset = Interface.objects.all() - def get(self, request, pk): - - interface = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Get assigned IP addresses ipaddress_table = InterfaceIPAddressTable( - data=interface.ip_addresses.restrict(request.user, 'view').prefetch_related('vrf', 'tenant'), + data=instance.ip_addresses.restrict(request.user, 'view').prefetch_related('vrf', 'tenant'), orderable=False ) # Get assigned VLANs and annotate whether each is tagged or untagged vlans = [] - if interface.untagged_vlan is not None: - vlans.append(interface.untagged_vlan) + if instance.untagged_vlan is not None: + vlans.append(instance.untagged_vlan) vlans[0].tagged = False - for vlan in interface.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'): + for vlan in instance.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'): vlan.tagged = True vlans.append(vlan) vlan_table = InterfaceVLANTable( - interface=interface, + interface=instance, data=vlans, orderable=False ) - return render(request, 'dcim/interface.html', { - 'instance': interface, - 'connected_interface': interface._connected_interface, - 'connected_circuittermination': interface._connected_circuittermination, + return { 'ipaddress_table': ipaddress_table, 'vlan_table': vlan_table, - }) + 'breadcrumb_url': 'dcim:device_interfaces' + } -class InterfaceCreateView(ComponentCreateView): +class InterfaceCreateView(generic.ComponentCreateView): queryset = Interface.objects.all() form = forms.InterfaceCreateForm model_form = forms.InterfaceForm template_name = 'dcim/device_component_add.html' -class InterfaceEditView(ObjectEditView): +class InterfaceEditView(generic.ObjectEditView): queryset = Interface.objects.all() model_form = forms.InterfaceForm template_name = 'dcim/interface_edit.html' -class InterfaceDeleteView(ObjectDeleteView): +class InterfaceDeleteView(generic.ObjectDeleteView): queryset = Interface.objects.all() -class InterfaceBulkImportView(BulkImportView): +class InterfaceBulkImportView(generic.BulkImportView): queryset = Interface.objects.all() model_form = forms.InterfaceCSVForm table = tables.InterfaceTable -class InterfaceBulkEditView(BulkEditView): +class InterfaceBulkEditView(generic.BulkEditView): queryset = Interface.objects.all() filterset = filters.InterfaceFilterSet table = tables.InterfaceTable form = forms.InterfaceBulkEditForm -class InterfaceBulkRenameView(BulkRenameView): +class InterfaceBulkRenameView(generic.BulkRenameView): queryset = Interface.objects.all() @@ -1545,7 +1660,7 @@ class InterfaceBulkDisconnectView(BulkDisconnectView): queryset = Interface.objects.all() -class InterfaceBulkDeleteView(BulkDeleteView): +class InterfaceBulkDeleteView(generic.BulkDeleteView): queryset = Interface.objects.all() filterset = filters.InterfaceFilterSet table = tables.InterfaceTable @@ -1555,49 +1670,54 @@ class InterfaceBulkDeleteView(BulkDeleteView): # Front ports # -class FrontPortListView(ObjectListView): - queryset = FrontPort.objects.prefetch_related('device', 'cable') +class FrontPortListView(generic.ObjectListView): + queryset = FrontPort.objects.all() filterset = filters.FrontPortFilterSet filterset_form = forms.FrontPortFilterForm table = tables.FrontPortTable action_buttons = ('import', 'export') -class FrontPortView(ObjectView): +class FrontPortView(generic.ObjectView): queryset = FrontPort.objects.all() + def get_extra_context(self, request, instance): + return { + 'breadcrumb_url': 'dcim:device_frontports' + } + -class FrontPortCreateView(ComponentCreateView): +class FrontPortCreateView(generic.ComponentCreateView): queryset = FrontPort.objects.all() form = forms.FrontPortCreateForm model_form = forms.FrontPortForm template_name = 'dcim/device_component_add.html' -class FrontPortEditView(ObjectEditView): +class FrontPortEditView(generic.ObjectEditView): queryset = FrontPort.objects.all() model_form = forms.FrontPortForm template_name = 'dcim/device_component_edit.html' -class FrontPortDeleteView(ObjectDeleteView): +class FrontPortDeleteView(generic.ObjectDeleteView): queryset = FrontPort.objects.all() -class FrontPortBulkImportView(BulkImportView): +class FrontPortBulkImportView(generic.BulkImportView): queryset = FrontPort.objects.all() model_form = forms.FrontPortCSVForm table = tables.FrontPortTable -class FrontPortBulkEditView(BulkEditView): +class FrontPortBulkEditView(generic.BulkEditView): queryset = FrontPort.objects.all() filterset = filters.FrontPortFilterSet table = tables.FrontPortTable form = forms.FrontPortBulkEditForm -class FrontPortBulkRenameView(BulkRenameView): +class FrontPortBulkRenameView(generic.BulkRenameView): queryset = FrontPort.objects.all() @@ -1605,7 +1725,7 @@ class FrontPortBulkDisconnectView(BulkDisconnectView): queryset = FrontPort.objects.all() -class FrontPortBulkDeleteView(BulkDeleteView): +class FrontPortBulkDeleteView(generic.BulkDeleteView): queryset = FrontPort.objects.all() filterset = filters.FrontPortFilterSet table = tables.FrontPortTable @@ -1615,49 +1735,54 @@ class FrontPortBulkDeleteView(BulkDeleteView): # Rear ports # -class RearPortListView(ObjectListView): - queryset = RearPort.objects.prefetch_related('device', 'cable') +class RearPortListView(generic.ObjectListView): + queryset = RearPort.objects.all() filterset = filters.RearPortFilterSet filterset_form = forms.RearPortFilterForm table = tables.RearPortTable action_buttons = ('import', 'export') -class RearPortView(ObjectView): +class RearPortView(generic.ObjectView): queryset = RearPort.objects.all() + def get_extra_context(self, request, instance): + return { + 'breadcrumb_url': 'dcim:device_rearports' + } + -class RearPortCreateView(ComponentCreateView): +class RearPortCreateView(generic.ComponentCreateView): queryset = RearPort.objects.all() form = forms.RearPortCreateForm model_form = forms.RearPortForm template_name = 'dcim/device_component_add.html' -class RearPortEditView(ObjectEditView): +class RearPortEditView(generic.ObjectEditView): queryset = RearPort.objects.all() model_form = forms.RearPortForm template_name = 'dcim/device_component_edit.html' -class RearPortDeleteView(ObjectDeleteView): +class RearPortDeleteView(generic.ObjectDeleteView): queryset = RearPort.objects.all() -class RearPortBulkImportView(BulkImportView): +class RearPortBulkImportView(generic.BulkImportView): queryset = RearPort.objects.all() model_form = forms.RearPortCSVForm table = tables.RearPortTable -class RearPortBulkEditView(BulkEditView): +class RearPortBulkEditView(generic.BulkEditView): queryset = RearPort.objects.all() filterset = filters.RearPortFilterSet table = tables.RearPortTable form = forms.RearPortBulkEditForm -class RearPortBulkRenameView(BulkRenameView): +class RearPortBulkRenameView(generic.BulkRenameView): queryset = RearPort.objects.all() @@ -1665,7 +1790,7 @@ class RearPortBulkDisconnectView(BulkDisconnectView): queryset = RearPort.objects.all() -class RearPortBulkDeleteView(BulkDeleteView): +class RearPortBulkDeleteView(generic.BulkDeleteView): queryset = RearPort.objects.all() filterset = filters.RearPortFilterSet table = tables.RearPortTable @@ -1675,36 +1800,41 @@ class RearPortBulkDeleteView(BulkDeleteView): # Device bays # -class DeviceBayListView(ObjectListView): - queryset = DeviceBay.objects.prefetch_related('device', 'installed_device') +class DeviceBayListView(generic.ObjectListView): + queryset = DeviceBay.objects.all() filterset = filters.DeviceBayFilterSet filterset_form = forms.DeviceBayFilterForm table = tables.DeviceBayTable action_buttons = ('import', 'export') -class DeviceBayView(ObjectView): +class DeviceBayView(generic.ObjectView): queryset = DeviceBay.objects.all() + def get_extra_context(self, request, instance): + return { + 'breadcrumb_url': 'dcim:device_devicebays' + } + -class DeviceBayCreateView(ComponentCreateView): +class DeviceBayCreateView(generic.ComponentCreateView): queryset = DeviceBay.objects.all() form = forms.DeviceBayCreateForm model_form = forms.DeviceBayForm template_name = 'dcim/device_component_add.html' -class DeviceBayEditView(ObjectEditView): +class DeviceBayEditView(generic.ObjectEditView): queryset = DeviceBay.objects.all() model_form = forms.DeviceBayForm template_name = 'dcim/device_component_edit.html' -class DeviceBayDeleteView(ObjectDeleteView): +class DeviceBayDeleteView(generic.ObjectDeleteView): queryset = DeviceBay.objects.all() -class DeviceBayPopulateView(ObjectEditView): +class DeviceBayPopulateView(generic.ObjectEditView): queryset = DeviceBay.objects.all() def get(self, request, pk): @@ -1714,7 +1844,7 @@ def get(self, request, pk): return render(request, 'dcim/devicebay_populate.html', { 'device_bay': device_bay, 'form': form, - 'return_url': reverse('dcim:device', kwargs={'pk': device_bay.device.pk}), + 'return_url': self.get_return_url(request, device_bay), }) def post(self, request, pk): @@ -1732,26 +1862,24 @@ def post(self, request, pk): return render(request, 'dcim/devicebay_populate.html', { 'device_bay': device_bay, 'form': form, - 'return_url': reverse('dcim:device', kwargs={'pk': device_bay.device.pk}), + 'return_url': self.get_return_url(request, device_bay), }) -class DeviceBayDepopulateView(ObjectEditView): +class DeviceBayDepopulateView(generic.ObjectEditView): queryset = DeviceBay.objects.all() def get(self, request, pk): - device_bay = get_object_or_404(self.queryset, pk=pk) form = ConfirmationForm() return render(request, 'dcim/devicebay_depopulate.html', { 'device_bay': device_bay, 'form': form, - 'return_url': reverse('dcim:device', kwargs={'pk': device_bay.device.pk}), + 'return_url': self.get_return_url(request, device_bay), }) def post(self, request, pk): - device_bay = get_object_or_404(self.queryset, pk=pk) form = ConfirmationForm(request.POST) @@ -1767,28 +1895,28 @@ def post(self, request, pk): return render(request, 'dcim/devicebay_depopulate.html', { 'device_bay': device_bay, 'form': form, - 'return_url': reverse('dcim:device', kwargs={'pk': device_bay.device.pk}), + 'return_url': self.get_return_url(request, device_bay), }) -class DeviceBayBulkImportView(BulkImportView): +class DeviceBayBulkImportView(generic.BulkImportView): queryset = DeviceBay.objects.all() model_form = forms.DeviceBayCSVForm table = tables.DeviceBayTable -class DeviceBayBulkEditView(BulkEditView): +class DeviceBayBulkEditView(generic.BulkEditView): queryset = DeviceBay.objects.all() filterset = filters.DeviceBayFilterSet table = tables.DeviceBayTable form = forms.DeviceBayBulkEditForm -class DeviceBayBulkRenameView(BulkRenameView): +class DeviceBayBulkRenameView(generic.BulkRenameView): queryset = DeviceBay.objects.all() -class DeviceBayBulkDeleteView(BulkDeleteView): +class DeviceBayBulkDeleteView(generic.BulkDeleteView): queryset = DeviceBay.objects.all() filterset = filters.DeviceBayFilterSet table = tables.DeviceBayTable @@ -1798,52 +1926,57 @@ class DeviceBayBulkDeleteView(BulkDeleteView): # Inventory items # -class InventoryItemListView(ObjectListView): - queryset = InventoryItem.objects.prefetch_related('device', 'manufacturer') +class InventoryItemListView(generic.ObjectListView): + queryset = InventoryItem.objects.all() filterset = filters.InventoryItemFilterSet filterset_form = forms.InventoryItemFilterForm table = tables.InventoryItemTable action_buttons = ('import', 'export') -class InventoryItemView(ObjectView): +class InventoryItemView(generic.ObjectView): queryset = InventoryItem.objects.all() + def get_extra_context(self, request, instance): + return { + 'breadcrumb_url': 'dcim:device_inventory' + } + -class InventoryItemEditView(ObjectEditView): +class InventoryItemEditView(generic.ObjectEditView): queryset = InventoryItem.objects.all() model_form = forms.InventoryItemForm -class InventoryItemCreateView(ComponentCreateView): +class InventoryItemCreateView(generic.ComponentCreateView): queryset = InventoryItem.objects.all() form = forms.InventoryItemCreateForm model_form = forms.InventoryItemForm template_name = 'dcim/device_component_add.html' -class InventoryItemDeleteView(ObjectDeleteView): +class InventoryItemDeleteView(generic.ObjectDeleteView): queryset = InventoryItem.objects.all() -class InventoryItemBulkImportView(BulkImportView): +class InventoryItemBulkImportView(generic.BulkImportView): queryset = InventoryItem.objects.all() model_form = forms.InventoryItemCSVForm table = tables.InventoryItemTable -class InventoryItemBulkEditView(BulkEditView): +class InventoryItemBulkEditView(generic.BulkEditView): queryset = InventoryItem.objects.prefetch_related('device', 'manufacturer') filterset = filters.InventoryItemFilterSet table = tables.InventoryItemTable form = forms.InventoryItemBulkEditForm -class InventoryItemBulkRenameView(BulkRenameView): +class InventoryItemBulkRenameView(generic.BulkRenameView): queryset = InventoryItem.objects.all() -class InventoryItemBulkDeleteView(BulkDeleteView): +class InventoryItemBulkDeleteView(generic.BulkDeleteView): queryset = InventoryItem.objects.prefetch_related('device', 'manufacturer') table = tables.InventoryItemTable template_name = 'dcim/inventoryitem_bulk_delete.html' @@ -1853,7 +1986,7 @@ class InventoryItemBulkDeleteView(BulkDeleteView): # Bulk Device component creation # -class DeviceBulkAddConsolePortView(BulkComponentCreateView): +class DeviceBulkAddConsolePortView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.ConsolePortBulkCreateForm @@ -1864,7 +1997,7 @@ class DeviceBulkAddConsolePortView(BulkComponentCreateView): default_return_url = 'dcim:device_list' -class DeviceBulkAddConsoleServerPortView(BulkComponentCreateView): +class DeviceBulkAddConsoleServerPortView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.ConsoleServerPortBulkCreateForm @@ -1875,7 +2008,7 @@ class DeviceBulkAddConsoleServerPortView(BulkComponentCreateView): default_return_url = 'dcim:device_list' -class DeviceBulkAddPowerPortView(BulkComponentCreateView): +class DeviceBulkAddPowerPortView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.PowerPortBulkCreateForm @@ -1886,7 +2019,7 @@ class DeviceBulkAddPowerPortView(BulkComponentCreateView): default_return_url = 'dcim:device_list' -class DeviceBulkAddPowerOutletView(BulkComponentCreateView): +class DeviceBulkAddPowerOutletView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.PowerOutletBulkCreateForm @@ -1897,7 +2030,7 @@ class DeviceBulkAddPowerOutletView(BulkComponentCreateView): default_return_url = 'dcim:device_list' -class DeviceBulkAddInterfaceView(BulkComponentCreateView): +class DeviceBulkAddInterfaceView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.InterfaceBulkCreateForm @@ -1908,7 +2041,7 @@ class DeviceBulkAddInterfaceView(BulkComponentCreateView): default_return_url = 'dcim:device_list' -# class DeviceBulkAddFrontPortView(BulkComponentCreateView): +# class DeviceBulkAddFrontPortView(generic.BulkComponentCreateView): # parent_model = Device # parent_field = 'device' # form = forms.FrontPortBulkCreateForm @@ -1919,7 +2052,7 @@ class DeviceBulkAddInterfaceView(BulkComponentCreateView): # default_return_url = 'dcim:device_list' -class DeviceBulkAddRearPortView(BulkComponentCreateView): +class DeviceBulkAddRearPortView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.RearPortBulkCreateForm @@ -1930,7 +2063,7 @@ class DeviceBulkAddRearPortView(BulkComponentCreateView): default_return_url = 'dcim:device_list' -class DeviceBulkAddDeviceBayView(BulkComponentCreateView): +class DeviceBulkAddDeviceBayView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.DeviceBayBulkCreateForm @@ -1941,7 +2074,7 @@ class DeviceBulkAddDeviceBayView(BulkComponentCreateView): default_return_url = 'dcim:device_list' -class DeviceBulkAddInventoryItemView(BulkComponentCreateView): +class DeviceBulkAddInventoryItemView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.InventoryItemBulkCreateForm @@ -1956,33 +2089,24 @@ class DeviceBulkAddInventoryItemView(BulkComponentCreateView): # Cables # -class CableListView(ObjectListView): - queryset = Cable.objects.prefetch_related( - 'termination_a', 'termination_b' - ) +class CableListView(generic.ObjectListView): + queryset = Cable.objects.all() filterset = filters.CableFilterSet filterset_form = forms.CableFilterForm table = tables.CableTable action_buttons = ('import', 'export') -class CableView(ObjectView): +class CableView(generic.ObjectView): queryset = Cable.objects.all() - def get(self, request, pk): - - cable = get_object_or_404(self.queryset, pk=pk) - return render(request, 'dcim/cable.html', { - 'cable': cable, - }) - - -class CableTraceView(ObjectView): +class PathTraceView(generic.ObjectView): """ - Trace a cable path beginning from the given termination. + Trace a cable path beginning from the given path endpoint (origin). """ additional_permissions = ['dcim.view_cable'] + template_name = 'dcim/cable_trace.html' def dispatch(self, request, *args, **kwargs): model = kwargs.pop('model') @@ -1990,24 +2114,34 @@ def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) - def get(self, request, pk): + def get_extra_context(self, request, instance): + related_paths = [] - obj = get_object_or_404(self.queryset, pk=pk) - path, split_ends, position_stack = obj.trace() - total_length = sum( - [entry[1]._abs_length for entry in path if entry[1] and entry[1]._abs_length] - ) + # If tracing a PathEndpoint, locate the CablePath (if one exists) by its origin + if isinstance(instance, PathEndpoint): + path = instance._path - return render(request, 'dcim/cable_trace.html', { - 'obj': obj, - 'trace': path, - 'split_ends': split_ends, - 'position_stack': position_stack, - 'total_length': total_length, - }) + # Otherwise, find all CablePaths which traverse the specified object + else: + related_paths = CablePath.objects.filter(path__contains=instance).prefetch_related('origin') + # Check for specification of a particular path (when tracing pass-through ports) + try: + path_id = int(request.GET.get('cablepath_id')) + except TypeError: + path_id = None + if path_id in list(related_paths.values_list('pk', flat=True)): + path = CablePath.objects.get(pk=path_id) + else: + path = related_paths.first() + + return { + 'path': path, + 'related_paths': related_paths, + 'total_length': path.get_total_length() if path else None, + } -class CableCreateView(ObjectEditView): +class CableCreateView(generic.ObjectEditView): queryset = Cable.objects.all() template_name = 'dcim/cable_connect.html' @@ -2066,30 +2200,30 @@ def get(self, request, *args, **kwargs): }) -class CableEditView(ObjectEditView): +class CableEditView(generic.ObjectEditView): queryset = Cable.objects.all() model_form = forms.CableForm template_name = 'dcim/cable_edit.html' -class CableDeleteView(ObjectDeleteView): +class CableDeleteView(generic.ObjectDeleteView): queryset = Cable.objects.all() -class CableBulkImportView(BulkImportView): +class CableBulkImportView(generic.BulkImportView): queryset = Cable.objects.all() model_form = forms.CableCSVForm table = tables.CableTable -class CableBulkEditView(BulkEditView): +class CableBulkEditView(generic.BulkEditView): queryset = Cable.objects.prefetch_related('termination_a', 'termination_b') filterset = filters.CableFilterSet table = tables.CableTable form = forms.CableBulkEditForm -class CableBulkDeleteView(BulkDeleteView): +class CableBulkDeleteView(generic.BulkDeleteView): queryset = Cable.objects.prefetch_related('termination_a', 'termination_b') filterset = filters.CableFilterSet table = tables.CableTable @@ -2099,108 +2233,107 @@ class CableBulkDeleteView(BulkDeleteView): # Connections # -class ConsoleConnectionsListView(ObjectListView): - queryset = ConsolePort.objects.prefetch_related( - 'device', 'connected_endpoint__device' - ).filter( - connected_endpoint__isnull=False - ).order_by( - 'cable', 'connected_endpoint__device__name', 'connected_endpoint__name' - ) +class ConsoleConnectionsListView(generic.ObjectListView): + queryset = ConsolePort.objects.filter(_path__isnull=False).order_by('device') filterset = filters.ConsoleConnectionFilterSet filterset_form = forms.ConsoleConnectionFilterForm table = tables.ConsoleConnectionTable - template_name = 'dcim/console_connections_list.html' + template_name = 'dcim/connections_list.html' def queryset_to_csv(self): csv_data = [ # Headers - ','.join(['console_server', 'port', 'device', 'console_port', 'connection_status']) + ','.join(['console_server', 'port', 'device', 'console_port', 'reachable']) ] for obj in self.queryset: csv = csv_format([ - obj.connected_endpoint.device.identifier if obj.connected_endpoint else None, - obj.connected_endpoint.name if obj.connected_endpoint else None, + obj._path.destination.device.identifier if obj._path.destination else None, + obj._path.destination.name if obj._path.destination else None, obj.device.identifier, obj.name, - obj.get_connection_status_display(), + obj._path.is_active ]) csv_data.append(csv) return '\n'.join(csv_data) + def extra_context(self): + return { + 'title': 'Console Connections' + } + -class PowerConnectionsListView(ObjectListView): - queryset = PowerPort.objects.prefetch_related( - 'device', '_connected_poweroutlet__device' - ).filter( - _connected_poweroutlet__isnull=False - ).order_by( - 'cable', '_connected_poweroutlet__device__name', '_connected_poweroutlet__name' - ) +class PowerConnectionsListView(generic.ObjectListView): + queryset = PowerPort.objects.filter(_path__isnull=False).order_by('device') filterset = filters.PowerConnectionFilterSet filterset_form = forms.PowerConnectionFilterForm table = tables.PowerConnectionTable - template_name = 'dcim/power_connections_list.html' + template_name = 'dcim/connections_list.html' def queryset_to_csv(self): csv_data = [ # Headers - ','.join(['pdu', 'outlet', 'device', 'power_port', 'connection_status']) + ','.join(['pdu', 'outlet', 'device', 'power_port', 'reachable']) ] for obj in self.queryset: csv = csv_format([ - obj.connected_endpoint.device.identifier if obj.connected_endpoint else None, - obj.connected_endpoint.name if obj.connected_endpoint else None, + obj._path.destination.device.identifier if obj._path.destination else None, + obj._path.destination.name if obj._path.destination else None, obj.device.identifier, obj.name, - obj.get_connection_status_display(), + obj._path.is_active ]) csv_data.append(csv) return '\n'.join(csv_data) + def extra_context(self): + return { + 'title': 'Power Connections' + } + -class InterfaceConnectionsListView(ObjectListView): - queryset = Interface.objects.prefetch_related( - 'device', 'cable', '_connected_interface__device' - ).filter( +class InterfaceConnectionsListView(generic.ObjectListView): + queryset = Interface.objects.filter( # Avoid duplicate connections by only selecting the lower PK in a connected pair - _connected_interface__isnull=False, - pk__lt=F('_connected_interface') - ).order_by( - 'device' - ) + _path__isnull=False, + pk__lt=F('_path__destination_id') + ).order_by('device') filterset = filters.InterfaceConnectionFilterSet filterset_form = forms.InterfaceConnectionFilterForm table = tables.InterfaceConnectionTable - template_name = 'dcim/interface_connections_list.html' + template_name = 'dcim/connections_list.html' def queryset_to_csv(self): csv_data = [ # Headers ','.join([ - 'device_a', 'interface_a', 'device_b', 'interface_b', 'connection_status' + 'device_a', 'interface_a', 'device_b', 'interface_b', 'reachable' ]) ] for obj in self.queryset: csv = csv_format([ - obj.connected_endpoint.device.identifier if obj.connected_endpoint else None, - obj.connected_endpoint.name if obj.connected_endpoint else None, + obj._path.destination.device.identifier if obj._path.destination else None, + obj._path.destination.name if obj._path.destination else None, obj.device.identifier, obj.name, - obj.get_connection_status_display(), + obj._path.is_active ]) csv_data.append(csv) return '\n'.join(csv_data) + def extra_context(self): + return { + 'title': 'Interface Connections' + } + # # Virtual chassis # -class VirtualChassisListView(ObjectListView): +class VirtualChassisListView(generic.ObjectListView): queryset = VirtualChassis.objects.prefetch_related('master').annotate( member_count=get_subquery(Device, 'virtual_chassis') ) @@ -2209,20 +2342,18 @@ class VirtualChassisListView(ObjectListView): filterset_form = forms.VirtualChassisFilterForm -class VirtualChassisView(ObjectView): +class VirtualChassisView(generic.ObjectView): queryset = VirtualChassis.objects.all() - def get(self, request, pk): - virtualchassis = get_object_or_404(self.queryset, pk=pk) - members = Device.objects.restrict(request.user).filter(virtual_chassis=virtualchassis) + def get_extra_context(self, request, instance): + members = Device.objects.restrict(request.user).filter(virtual_chassis=instance) - return render(request, 'dcim/virtualchassis.html', { - 'virtualchassis': virtualchassis, + return { 'members': members, - }) + } -class VirtualChassisCreateView(ObjectEditView): +class VirtualChassisCreateView(generic.ObjectEditView): queryset = VirtualChassis.objects.all() model_form = forms.VirtualChassisCreateForm template_name = 'dcim/virtualchassis_add.html' @@ -2296,7 +2427,7 @@ def post(self, request, pk): }) -class VirtualChassisDeleteView(ObjectDeleteView): +class VirtualChassisDeleteView(generic.ObjectDeleteView): queryset = VirtualChassis.objects.all() @@ -2407,20 +2538,20 @@ def post(self, request, pk): }) -class VirtualChassisBulkImportView(BulkImportView): +class VirtualChassisBulkImportView(generic.BulkImportView): queryset = VirtualChassis.objects.all() model_form = forms.VirtualChassisCSVForm table = tables.VirtualChassisTable -class VirtualChassisBulkEditView(BulkEditView): +class VirtualChassisBulkEditView(generic.BulkEditView): queryset = VirtualChassis.objects.all() filterset = filters.VirtualChassisFilterSet table = tables.VirtualChassisTable form = forms.VirtualChassisBulkEditForm -class VirtualChassisBulkDeleteView(BulkDeleteView): +class VirtualChassisBulkDeleteView(generic.BulkDeleteView): queryset = VirtualChassis.objects.all() filterset = filters.VirtualChassisFilterSet table = tables.VirtualChassisTable @@ -2430,7 +2561,7 @@ class VirtualChassisBulkDeleteView(BulkDeleteView): # Power panels # -class PowerPanelListView(ObjectListView): +class PowerPanelListView(generic.ObjectListView): queryset = PowerPanel.objects.prefetch_related( 'site', 'rack_group' ).annotate( @@ -2441,48 +2572,46 @@ class PowerPanelListView(ObjectListView): table = tables.PowerPanelTable -class PowerPanelView(ObjectView): +class PowerPanelView(generic.ObjectView): queryset = PowerPanel.objects.prefetch_related('site', 'rack_group') - def get(self, request, pk): - - powerpanel = get_object_or_404(self.queryset, pk=pk) - power_feeds = PowerFeed.objects.restrict(request.user).filter(power_panel=powerpanel).prefetch_related('rack') + def get_extra_context(self, request, instance): + power_feeds = PowerFeed.objects.restrict(request.user).filter(power_panel=instance).prefetch_related('rack') powerfeed_table = tables.PowerFeedTable( data=power_feeds, orderable=False ) powerfeed_table.exclude = ['power_panel'] - return render(request, 'dcim/powerpanel.html', { - 'powerpanel': powerpanel, + return { 'powerfeed_table': powerfeed_table, - }) + } -class PowerPanelEditView(ObjectEditView): +class PowerPanelEditView(generic.ObjectEditView): queryset = PowerPanel.objects.all() model_form = forms.PowerPanelForm + template_name = 'dcim/powerpanel_edit.html' -class PowerPanelDeleteView(ObjectDeleteView): +class PowerPanelDeleteView(generic.ObjectDeleteView): queryset = PowerPanel.objects.all() -class PowerPanelBulkImportView(BulkImportView): +class PowerPanelBulkImportView(generic.BulkImportView): queryset = PowerPanel.objects.all() model_form = forms.PowerPanelCSVForm table = tables.PowerPanelTable -class PowerPanelBulkEditView(BulkEditView): +class PowerPanelBulkEditView(generic.BulkEditView): queryset = PowerPanel.objects.prefetch_related('site', 'rack_group') filterset = filters.PowerPanelFilterSet table = tables.PowerPanelTable form = forms.PowerPanelBulkEditForm -class PowerPanelBulkDeleteView(BulkDeleteView): +class PowerPanelBulkDeleteView(generic.BulkDeleteView): queryset = PowerPanel.objects.prefetch_related( 'site', 'rack_group' ).annotate( @@ -2496,51 +2625,41 @@ class PowerPanelBulkDeleteView(BulkDeleteView): # Power feeds # -class PowerFeedListView(ObjectListView): - queryset = PowerFeed.objects.prefetch_related( - 'power_panel', 'rack' - ) +class PowerFeedListView(generic.ObjectListView): + queryset = PowerFeed.objects.all() filterset = filters.PowerFeedFilterSet filterset_form = forms.PowerFeedFilterForm table = tables.PowerFeedTable -class PowerFeedView(ObjectView): +class PowerFeedView(generic.ObjectView): queryset = PowerFeed.objects.prefetch_related('power_panel', 'rack') - def get(self, request, pk): - - powerfeed = get_object_or_404(self.queryset, pk=pk) - - return render(request, 'dcim/powerfeed.html', { - 'powerfeed': powerfeed, - }) - -class PowerFeedEditView(ObjectEditView): +class PowerFeedEditView(generic.ObjectEditView): queryset = PowerFeed.objects.all() model_form = forms.PowerFeedForm template_name = 'dcim/powerfeed_edit.html' -class PowerFeedDeleteView(ObjectDeleteView): +class PowerFeedDeleteView(generic.ObjectDeleteView): queryset = PowerFeed.objects.all() -class PowerFeedBulkImportView(BulkImportView): +class PowerFeedBulkImportView(generic.BulkImportView): queryset = PowerFeed.objects.all() model_form = forms.PowerFeedCSVForm table = tables.PowerFeedTable -class PowerFeedBulkEditView(BulkEditView): +class PowerFeedBulkEditView(generic.BulkEditView): queryset = PowerFeed.objects.prefetch_related('power_panel', 'rack') filterset = filters.PowerFeedFilterSet table = tables.PowerFeedTable form = forms.PowerFeedBulkEditForm -class PowerFeedBulkDeleteView(BulkDeleteView): +class PowerFeedBulkDeleteView(generic.BulkDeleteView): queryset = PowerFeed.objects.prefetch_related('power_panel', 'rack') filterset = filters.PowerFeedFilterSet table = tables.PowerFeedTable diff --git a/netbox/extras/admin.py b/netbox/extras/admin.py index a198d03d56..a4786610dc 100644 --- a/netbox/extras/admin.py +++ b/netbox/extras/admin.py @@ -2,7 +2,7 @@ from django.contrib import admin from utilities.forms import LaxURLField -from .models import CustomField, CustomFieldChoice, CustomLink, Graph, ExportTemplate, JobResult, Webhook +from .models import CustomField, CustomLink, ExportTemplate, JobResult, Webhook def order_content_types(field): @@ -29,8 +29,8 @@ class Meta: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - if 'obj_type' in self.fields: - order_content_types(self.fields['obj_type']) + if 'content_types' in self.fields: + order_content_types(self.fields['content_types']) @admin.register(Webhook) @@ -40,12 +40,12 @@ class WebhookAdmin(admin.ModelAdmin): 'ssl_verification', ] list_filter = [ - 'enabled', 'type_create', 'type_update', 'type_delete', 'obj_type', + 'enabled', 'type_create', 'type_update', 'type_delete', 'content_types', ] form = WebhookForm fieldsets = ( (None, { - 'fields': ('name', 'obj_type', 'enabled') + 'fields': ('name', 'content_types', 'enabled') }), ('Events', { 'fields': ('type_create', 'type_update', 'type_delete') @@ -62,7 +62,7 @@ class WebhookAdmin(admin.ModelAdmin): ) def models(self, obj): - return ', '.join([ct.name for ct in obj.obj_type.all()]) + return ', '.join([ct.name for ct in obj.content_types.all()]) # @@ -74,31 +74,52 @@ class CustomFieldForm(forms.ModelForm): class Meta: model = CustomField exclude = [] + widgets = { + 'default': forms.TextInput(), + 'validation_regex': forms.Textarea( + attrs={ + 'cols': 80, + 'rows': 3, + } + ) + } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - order_content_types(self.fields['obj_type']) - - -class CustomFieldChoiceAdmin(admin.TabularInline): - model = CustomFieldChoice - extra = 5 + order_content_types(self.fields['content_types']) @admin.register(CustomField) class CustomFieldAdmin(admin.ModelAdmin): - inlines = [CustomFieldChoiceAdmin] + actions = None + form = CustomFieldForm list_display = [ 'name', 'models', 'type', 'required', 'filter_logic', 'default', 'weight', 'description', ] list_filter = [ - 'type', 'required', 'obj_type', + 'type', 'required', 'content_types', ] - form = CustomFieldForm + fieldsets = ( + ('Custom Field', { + 'fields': ('type', 'name', 'weight', 'label', 'description', 'required', 'default', 'filter_logic') + }), + ('Assignment', { + 'description': 'A custom field must be assigned to one or more object types.', + 'fields': ('content_types',) + }), + ('Validation Rules', { + 'fields': ('validation_minimum', 'validation_maximum', 'validation_regex'), + 'classes': ('monospace',) + }), + ('Choices', { + 'description': 'A selection field must have two or more choices assigned to it.', + 'fields': ('choices',) + }) + ) def models(self, obj): - return ', '.join([ct.name for ct in obj.obj_type.all()]) + return ', '.join([ct.name for ct in obj.content_types.all()]) # @@ -150,45 +171,6 @@ class CustomLinkAdmin(admin.ModelAdmin): form = CustomLinkForm -# -# Graphs -# - -class GraphForm(forms.ModelForm): - - class Meta: - model = Graph - exclude = () - help_texts = { - 'template_language': "Jinja2 is strongly recommended for " - "new graphs." - } - widgets = { - 'source': forms.Textarea, - 'link': forms.Textarea, - } - - -@admin.register(Graph) -class GraphAdmin(admin.ModelAdmin): - fieldsets = ( - ('Graph', { - 'fields': ('type', 'name', 'weight') - }), - ('Templates', { - 'fields': ('template_language', 'source', 'link'), - 'classes': ('monospace',) - }) - ) - form = GraphForm - list_display = [ - 'name', 'type', 'weight', 'template_language', 'source', - ] - list_filter = [ - 'type', 'template_language', - ] - - # # Export templates # @@ -198,11 +180,6 @@ class ExportTemplateForm(forms.ModelForm): class Meta: model = ExportTemplate exclude = [] - help_texts = { - 'template_language': "Warning: Support for Django templating will be dropped in NetBox " - "v2.10. Jinja2 is strongly " - "recommended." - } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -219,7 +196,7 @@ class ExportTemplateAdmin(admin.ModelAdmin): 'fields': ('content_type', 'name', 'description', 'mime_type', 'file_extension') }), ('Content', { - 'fields': ('template_language', 'template_code'), + 'fields': ('template_code',), 'classes': ('monospace',) }) ) diff --git a/netbox/extras/api/customfields.py b/netbox/extras/api/customfields.py index ba59e529ac..c8c4ba89ee 100644 --- a/netbox/extras/api/customfields.py +++ b/netbox/extras/api/customfields.py @@ -1,15 +1,9 @@ -from datetime import datetime - from django.contrib.contenttypes.models import ContentType -from django.core.exceptions import ObjectDoesNotExist -from django.db import transaction -from rest_framework import serializers -from rest_framework.exceptions import ValidationError -from rest_framework.fields import CreateOnlyDefault +from rest_framework.fields import CreateOnlyDefault, Field from extras.choices import * -from extras.models import CustomField, CustomFieldChoice, CustomFieldValue -from utilities.api import ValidatedModelSerializer +from extras.models import CustomField +from netbox.api import ValidatedModelSerializer # @@ -27,104 +21,39 @@ def __call__(self, serializer_field): # Retrieve the CustomFields for the parent model content_type = ContentType.objects.get_for_model(self.model) - fields = CustomField.objects.filter(obj_type=content_type) + fields = CustomField.objects.filter(content_types=content_type) # Populate the default value for each CustomField value = {} for field in fields: - if field.default: - if field.type == CustomFieldTypeChoices.TYPE_INTEGER: - field_value = int(field.default) - elif field.type == CustomFieldTypeChoices.TYPE_BOOLEAN: - # TODO: Fix default value assignment for boolean custom fields - field_value = False if field.default.lower() == 'false' else bool(field.default) - elif field.type == CustomFieldTypeChoices.TYPE_SELECT: - try: - field_value = field.choices.get(value=field.default).pk - except ObjectDoesNotExist: - # Invalid default value - field_value = None - else: - field_value = field.default - value[field.name] = field_value + if field.default is not None: + value[field.name] = field.default else: value[field.name] = None return value -class CustomFieldsSerializer(serializers.BaseSerializer): - - def to_representation(self, obj): - return obj +class CustomFieldsDataField(Field): - def to_internal_value(self, data): + def _get_custom_fields(self): + """ + Cache CustomFields assigned to this model to avoid redundant database queries + """ + if not hasattr(self, '_custom_fields'): + content_type = ContentType.objects.get_for_model(self.parent.Meta.model) + self._custom_fields = CustomField.objects.filter(content_types=content_type) + return self._custom_fields - content_type = ContentType.objects.get_for_model(self.parent.Meta.model) - custom_fields = { - field.name: field for field in CustomField.objects.filter(obj_type=content_type) + def to_representation(self, obj): + return { + cf.name: obj.get(cf.name) for cf in self._get_custom_fields() } - for field_name, value in data.items(): - - try: - cf = custom_fields[field_name] - except KeyError: - raise ValidationError( - "Invalid custom field for {} objects: {}".format(content_type, field_name) - ) - - # Data validation - if value not in [None, '']: - - # Validate integer - if cf.type == CustomFieldTypeChoices.TYPE_INTEGER: - try: - int(value) - except ValueError: - raise ValidationError( - "Invalid value for integer field {}: {}".format(field_name, value) - ) - - # Validate boolean - if cf.type == CustomFieldTypeChoices.TYPE_BOOLEAN and value not in [True, False, 1, 0]: - raise ValidationError( - "Invalid value for boolean field {}: {}".format(field_name, value) - ) - - # Validate date - if cf.type == CustomFieldTypeChoices.TYPE_DATE: - try: - datetime.strptime(value, '%Y-%m-%d') - except ValueError: - raise ValidationError( - "Invalid date for field {}: {}. (Required format is YYYY-MM-DD.)".format(field_name, value) - ) - - # Validate selected choice - if cf.type == CustomFieldTypeChoices.TYPE_SELECT: - try: - value = int(value) - except ValueError: - raise ValidationError( - "{}: Choice selections must be passed as integers.".format(field_name) - ) - valid_choices = [c.pk for c in cf.choices.all()] - if value not in valid_choices: - raise ValidationError( - "Invalid choice for field {}: {}".format(field_name, value) - ) - - elif cf.required: - raise ValidationError("Required field {} cannot be empty.".format(field_name)) - - # Check for missing required fields - missing_fields = [] - for field_name, field in custom_fields.items(): - if field.required and field_name not in data: - missing_fields.append(field_name) - if missing_fields: - raise ValidationError("Missing required fields: {}".format(u", ".join(missing_fields))) + def to_internal_value(self, data): + # If updating an existing instance, start with existing custom_field_data + if self.parent.instance: + data = {**self.parent.instance.custom_field_data, **data} return data @@ -133,8 +62,8 @@ class CustomFieldModelSerializer(ValidatedModelSerializer): """ Extends ModelSerializer to render any CustomFields and their values associated with an object. """ - custom_fields = CustomFieldsSerializer( - required=False, + custom_fields = CustomFieldsDataField( + source='custom_field_data', default=CreateOnlyDefault(CustomFieldDefaultValues()) ) @@ -145,73 +74,16 @@ def __init__(self, *args, **kwargs): # Retrieve the set of CustomFields which apply to this type of object content_type = ContentType.objects.get_for_model(self.Meta.model) - fields = CustomField.objects.filter(obj_type=content_type) + fields = CustomField.objects.filter(content_types=content_type) # Populate CustomFieldValues for each instance from database - try: + if type(self.instance) in (list, tuple): for obj in self.instance: self._populate_custom_fields(obj, fields) - except TypeError: + else: self._populate_custom_fields(self.instance, fields) def _populate_custom_fields(self, instance, custom_fields): instance.custom_fields = {} for field in custom_fields: - value = instance.cf.get(field.name) - if field.type == CustomFieldTypeChoices.TYPE_SELECT and type(value) is CustomFieldChoice: - instance.custom_fields[field.name] = CustomFieldChoiceSerializer(value).data - else: - instance.custom_fields[field.name] = value - - def _save_custom_fields(self, instance, custom_fields): - content_type = ContentType.objects.get_for_model(self.Meta.model) - for field_name, value in custom_fields.items(): - custom_field = CustomField.objects.get(name=field_name) - CustomFieldValue.objects.update_or_create( - field=custom_field, - obj_type=content_type, - obj_id=instance.pk, - defaults={'serialized_value': custom_field.serialize_value(value)}, - ) - - def create(self, validated_data): - - with transaction.atomic(): - - instance = super().create(validated_data) - - # Save custom fields - custom_fields = validated_data.get('custom_fields') - if custom_fields is not None: - self._save_custom_fields(instance, custom_fields) - instance.custom_fields = custom_fields - - return instance - - def update(self, instance, validated_data): - - with transaction.atomic(): - - custom_fields = validated_data.get('custom_fields') - instance._cf = custom_fields - - instance = super().update(instance, validated_data) - - # Save custom fields - if custom_fields is not None: - self._save_custom_fields(instance, custom_fields) - instance.custom_fields = custom_fields - - return instance - - -class CustomFieldChoiceSerializer(serializers.ModelSerializer): - """ - Imitate utilities.api.ChoiceFieldSerializer - """ - value = serializers.IntegerField(source='pk') - label = serializers.CharField(source='value') - - class Meta: - model = CustomFieldChoice - fields = ['value', 'label'] + instance.custom_fields[field.name] = instance.cf.get(field.name) diff --git a/netbox/extras/api/nested_serializers.py b/netbox/extras/api/nested_serializers.py index 198a5d2f84..5635f401b8 100644 --- a/netbox/extras/api/nested_serializers.py +++ b/netbox/extras/api/nested_serializers.py @@ -1,19 +1,27 @@ from rest_framework import serializers from extras import choices, models +from netbox.api import ChoiceField, WritableNestedSerializer from users.api.nested_serializers import NestedUserSerializer -from utilities.api import ChoiceField, WritableNestedSerializer __all__ = [ 'NestedConfigContextSerializer', + 'NestedCustomFieldSerializer', 'NestedExportTemplateSerializer', - 'NestedGraphSerializer', 'NestedImageAttachmentSerializer', 'NestedJobResultSerializer', 'NestedTagSerializer', ] +class NestedCustomFieldSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='extras-api:customfield-detail') + + class Meta: + model = models.CustomField + fields = ['id', 'url', 'name'] + + class NestedConfigContextSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='extras-api:configcontext-detail') @@ -30,14 +38,6 @@ class Meta: fields = ['id', 'url', 'name'] -class NestedGraphSerializer(WritableNestedSerializer): - url = serializers.HyperlinkedIdentityField(view_name='extras-api:graph-detail') - - class Meta: - model = models.Graph - fields = ['id', 'url', 'name'] - - class NestedImageAttachmentSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='extras-api:imageattachment-detail') diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py index 3cc2d19916..a85ca05b77 100644 --- a/netbox/extras/api/serializers.py +++ b/netbox/extras/api/serializers.py @@ -10,56 +10,39 @@ from dcim.models import Device, DeviceRole, Platform, Rack, Region, Site from extras.choices import * from extras.models import ( - ConfigContext, ExportTemplate, Graph, ImageAttachment, ObjectChange, JobResult, Tag, + ConfigContext, CustomField, ExportTemplate, ImageAttachment, ObjectChange, JobResult, Tag, ) from extras.utils import FeatureQuery +from netbox.api import ChoiceField, ContentTypeField, SerializedPKRelatedField, ValidatedModelSerializer +from netbox.api.exceptions import SerializerNotFound from tenancy.api.nested_serializers import NestedTenantSerializer, NestedTenantGroupSerializer from tenancy.models import Tenant, TenantGroup from users.api.nested_serializers import NestedUserSerializer -from utilities.api import ( - ChoiceField, ContentTypeField, get_serializer_for_model, SerializerNotFound, SerializedPKRelatedField, - ValidatedModelSerializer, -) +from utilities.api import get_serializer_for_model from virtualization.api.nested_serializers import NestedClusterGroupSerializer, NestedClusterSerializer from virtualization.models import Cluster, ClusterGroup from .nested_serializers import * # -# Graphs +# Custom fields # -class GraphSerializer(ValidatedModelSerializer): - url = serializers.HyperlinkedIdentityField(view_name='extras-api:graph-detail') - type = ContentTypeField( - queryset=ContentType.objects.filter(FeatureQuery('graphs').get_query()), - ) - - class Meta: - model = Graph - fields = ['id', 'url', 'type', 'weight', 'name', 'template_language', 'source', 'link'] - - -class RenderedGraphSerializer(serializers.ModelSerializer): - embed_url = serializers.SerializerMethodField( - read_only=True - ) - embed_link = serializers.SerializerMethodField( - read_only=True - ) - type = ContentTypeField( - read_only=True +class CustomFieldSerializer(ValidatedModelSerializer): + url = serializers.HyperlinkedIdentityField(view_name='extras-api:customfield-detail') + content_types = ContentTypeField( + queryset=ContentType.objects.filter(FeatureQuery('custom_fields').get_query()), + many=True ) + type = ChoiceField(choices=CustomFieldTypeChoices) + filter_logic = ChoiceField(choices=CustomFieldFilterLogicChoices, required=False) class Meta: - model = Graph - fields = ['id', 'type', 'weight', 'name', 'embed_url', 'embed_link'] - - def get_embed_url(self, obj): - return obj.embed_url(self.context['graphed_object']) - - def get_embed_link(self, obj): - return obj.embed_link(self.context['graphed_object']) + model = CustomField + fields = [ + 'id', 'url', 'content_types', 'type', 'name', 'label', 'description', 'required', 'filter_logic', + 'default', 'weight', 'validation_minimum', 'validation_maximum', 'validation_regex', 'choices', + ] # @@ -71,17 +54,10 @@ class ExportTemplateSerializer(ValidatedModelSerializer): content_type = ContentTypeField( queryset=ContentType.objects.filter(FeatureQuery('export_templates').get_query()), ) - template_language = ChoiceField( - choices=TemplateLanguageChoices, - default=TemplateLanguageChoices.LANGUAGE_JINJA2 - ) class Meta: model = ExportTemplate - fields = [ - 'id', 'url', 'content_type', 'name', 'description', 'template_language', 'template_code', 'mime_type', - 'file_extension', - ] + fields = ['id', 'url', 'content_type', 'name', 'description', 'template_code', 'mime_type', 'file_extension'] # @@ -383,3 +359,20 @@ def get_changed_object(self, obj): data = serializer(obj.changed_object, context=context).data return data + + +# +# ContentTypes +# + +class ContentTypeSerializer(serializers.ModelSerializer): + url = serializers.HyperlinkedIdentityField(view_name='extras-api:contenttype-detail') + display_name = serializers.SerializerMethodField() + + class Meta: + model = ContentType + fields = ['id', 'url', 'app_label', 'model', 'display_name'] + + @swagger_serializer_method(serializer_or_field=serializers.CharField) + def get_display_name(self, obj): + return obj.app_labeled_name diff --git a/netbox/extras/api/urls.py b/netbox/extras/api/urls.py index 9c50c9a45c..da62b3d72f 100644 --- a/netbox/extras/api/urls.py +++ b/netbox/extras/api/urls.py @@ -1,15 +1,12 @@ -from utilities.api import OrderedDefaultRouter +from netbox.api import OrderedDefaultRouter from . import views router = OrderedDefaultRouter() router.APIRootView = views.ExtrasRootView -# Custom field choices -router.register('_custom_field_choices', views.CustomFieldChoicesViewSet, basename='custom-field-choice') - -# Graphs -router.register('graphs', views.GraphViewSet) +# Custom fields +router.register('custom-fields', views.CustomFieldViewSet) # Export templates router.register('export-templates', views.ExportTemplateViewSet) @@ -35,5 +32,8 @@ # Job Results router.register('job-results', views.JobResultViewSet) +# ContentTypes +router.register('content-types', views.ContentTypeViewSet) + app_name = 'extras-api' urlpatterns = router.urls diff --git a/netbox/extras/api/views.py b/netbox/extras/api/views.py index 6efcc65a6a..38077c89a6 100644 --- a/netbox/extras/api/views.py +++ b/netbox/extras/api/views.py @@ -1,5 +1,3 @@ -from collections import OrderedDict - from django.contrib.contenttypes.models import ContentType from django.http import Http404 from django_rq.queues import get_connection @@ -14,17 +12,27 @@ from extras import filters from extras.choices import JobResultStatusChoices from extras.models import ( - ConfigContext, CustomFieldChoice, ExportTemplate, Graph, ImageAttachment, ObjectChange, JobResult, Tag, TaggedItem, + ConfigContext, ExportTemplate, ImageAttachment, ObjectChange, JobResult, Tag, TaggedItem, ) +from extras.models import CustomField from extras.reports import get_report, get_reports, run_report from extras.scripts import get_script, get_scripts, run_script -from utilities.api import IsAuthenticatedOrLoginNotRequired, ModelViewSet +from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired +from netbox.api.metadata import ContentTypeMetadata +from netbox.api.views import ModelViewSet from utilities.exceptions import RQWorkerNotRunningException -from utilities.metadata import ContentTypeMetadata from utilities.utils import copy_safe_request, get_subquery from . import serializers +class ExtrasRootView(APIRootView): + """ + Extras API root view + """ + def get_view_name(self): + return 'Extras' + + class ConfigContextQuerySetMixin: """ Used by views that work with config context models (device and virtual machine). @@ -48,48 +56,17 @@ def get_queryset(self): return self.queryset.annotate_config_context_data() -class ExtrasRootView(APIRootView): - """ - Extras API root view - """ - def get_view_name(self): - return 'Extras' - - # -# Custom field choices +# Custom fields # -class CustomFieldChoicesViewSet(ViewSet): - """ - """ - permission_classes = [IsAuthenticatedOrLoginNotRequired] - - def __init__(self, *args, **kwargs): - super(CustomFieldChoicesViewSet, self).__init__(*args, **kwargs) - - self._fields = OrderedDict() - - for cfc in CustomFieldChoice.objects.all(): - self._fields.setdefault(cfc.field.name, {}) - self._fields[cfc.field.name][cfc.value] = cfc.pk - - def list(self, request): - return Response(self._fields) - - def retrieve(self, request, pk): - if pk not in self._fields: - raise Http404 - return Response(self._fields[pk]) - - def get_view_name(self): - return "Custom Field choices" +class CustomFieldViewSet(ModelViewSet): + metadata_class = ContentTypeMetadata + queryset = CustomField.objects.all() + serializer_class = serializers.CustomFieldSerializer + filterset_class = filters.CustomFieldFilterSet -# -# Custom fields -# - class CustomFieldModelViewSet(ModelViewSet): """ Include the applicable set of CustomFields in the ModelViewSet context. @@ -99,37 +76,14 @@ def get_serializer_context(self): # Gather all custom fields for the model content_type = ContentType.objects.get_for_model(self.queryset.model) - custom_fields = content_type.custom_fields.prefetch_related('choices') - - # Cache all relevant CustomFieldChoices. This saves us from having to do a lookup per select field per object. - custom_field_choices = {} - for field in custom_fields: - for cfc in field.choices.all(): - custom_field_choices[cfc.id] = cfc.value - custom_field_choices = custom_field_choices + custom_fields = content_type.custom_fields.all() context = super().get_serializer_context() context.update({ 'custom_fields': custom_fields, - 'custom_field_choices': custom_field_choices, }) return context - def get_queryset(self): - # Prefetch custom field values - return super().get_queryset().prefetch_related('custom_field_values__field') - - -# -# Graphs -# - -class GraphViewSet(ModelViewSet): - metadata_class = ContentTypeMetadata - queryset = Graph.objects.all() - serializer_class = serializers.GraphSerializer - filterset_class = filters.GraphFilterSet - # # Export templates @@ -388,3 +342,16 @@ class JobResultViewSet(ReadOnlyModelViewSet): queryset = JobResult.objects.prefetch_related('user') serializer_class = serializers.JobResultSerializer filterset_class = filters.JobResultFilterSet + + +# +# ContentTypes +# + +class ContentTypeViewSet(ReadOnlyModelViewSet): + """ + Read-only list of ContentTypes. Limit results to ContentTypes pertinent to NetBox objects. + """ + queryset = ContentType.objects.order_by('app_label', 'model') + serializer_class = serializers.ContentTypeSerializer + filterset_class = filters.ContentTypeFilterSet diff --git a/netbox/extras/choices.py b/netbox/extras/choices.py index b147481354..45f8ac31f8 100644 --- a/netbox/extras/choices.py +++ b/netbox/extras/choices.py @@ -78,20 +78,11 @@ class ObjectChangeActionChoices(ChoiceSet): (ACTION_DELETE, 'Deleted'), ) - -# -# ExportTemplates -# - -class TemplateLanguageChoices(ChoiceSet): - - LANGUAGE_JINJA2 = 'jinja2' - LANGUAGE_DJANGO = 'django' - - CHOICES = ( - (LANGUAGE_JINJA2, 'Jinja2'), - (LANGUAGE_DJANGO, 'Django (Legacy)'), - ) + CSS_CLASSES = { + ACTION_CREATE: 'success', + ACTION_UPDATE: 'primary', + ACTION_DELETE: 'danger', + } # @@ -114,13 +105,13 @@ class LogLevelChoices(ChoiceSet): (LOG_FAILURE, 'Failure'), ) - CLASS_MAP = ( - (LOG_DEFAULT, 'default'), - (LOG_SUCCESS, 'success'), - (LOG_INFO, 'info'), - (LOG_WARNING, 'warning'), - (LOG_FAILURE, 'danger'), - ) + CSS_CLASSES = { + LOG_DEFAULT: 'default', + LOG_SUCCESS: 'success', + LOG_INFO: 'info', + LOG_WARNING: 'warning', + LOG_FAILURE: 'danger', + } # diff --git a/netbox/extras/constants.py b/netbox/extras/constants.py index a506d5867d..190e68c36e 100644 --- a/netbox/extras/constants.py +++ b/netbox/extras/constants.py @@ -6,7 +6,6 @@ 'custom_fields', 'custom_links', 'export_templates', - 'graphs', 'job_results', 'webhooks' ] diff --git a/netbox/extras/filters.py b/netbox/extras/filters.py index 865c693e73..7b341f74dc 100644 --- a/netbox/extras/filters.py +++ b/netbox/extras/filters.py @@ -5,34 +5,39 @@ from dcim.models import DeviceRole, Platform, Region, Site from tenancy.models import Tenant, TenantGroup -from utilities.filters import BaseFilterSet +from utilities.filters import BaseFilterSet, ContentTypeFilter from virtualization.models import Cluster, ClusterGroup from .choices import * -from .models import ConfigContext, CustomField, ExportTemplate, Graph, ImageAttachment, JobResult, ObjectChange, Tag +from .models import ConfigContext, CustomField, ExportTemplate, ImageAttachment, JobResult, ObjectChange, Tag __all__ = ( 'ConfigContextFilterSet', + 'ContentTypeFilterSet', 'CreatedUpdatedFilterSet', 'CustomFieldFilter', - 'CustomFieldFilterSet', + 'CustomFieldModelFilterSet', 'ExportTemplateFilterSet', - 'GraphFilterSet', 'ImageAttachmentFilterSet', 'LocalConfigContextFilterSet', 'ObjectChangeFilterSet', 'TagFilterSet', ) +EXACT_FILTER_TYPES = ( + CustomFieldTypeChoices.TYPE_BOOLEAN, + CustomFieldTypeChoices.TYPE_DATE, + CustomFieldTypeChoices.TYPE_INTEGER, + CustomFieldTypeChoices.TYPE_SELECT, +) + class CustomFieldFilter(django_filters.Filter): """ Filter objects by the presence of a CustomFieldValue. The filter's name is used as the CustomField name. """ - def __init__(self, custom_field, *args, **kwargs): - self.cf_type = custom_field.type - self.filter_logic = custom_field.filter_logic + self.custom_field = custom_field super().__init__(*args, **kwargs) def filter(self, queryset, value): @@ -41,50 +46,27 @@ def filter(self, queryset, value): if value is None or not value.strip(): return queryset - # Selection fields get special treatment (values must be integers) - if self.cf_type == CustomFieldTypeChoices.TYPE_SELECT: - try: - # Treat 0 as None - if int(value) == 0: - return queryset.exclude( - custom_field_values__field__name=self.field_name, - ) - # Match on exact CustomFieldChoice PK - else: - return queryset.filter( - custom_field_values__field__name=self.field_name, - custom_field_values__serialized_value=value, - ) - except ValueError: - return queryset.none() - # Apply the assigned filter logic (exact or loose) - if (self.cf_type == CustomFieldTypeChoices.TYPE_BOOLEAN or - self.filter_logic == CustomFieldFilterLogicChoices.FILTER_EXACT): - queryset = queryset.filter( - custom_field_values__field__name=self.field_name, - custom_field_values__serialized_value=value - ) + if ( + self.custom_field.type in EXACT_FILTER_TYPES or + self.custom_field.filter_logic == CustomFieldFilterLogicChoices.FILTER_EXACT + ): + kwargs = {f'custom_field_data__{self.field_name}': value} else: - queryset = queryset.filter( - custom_field_values__field__name=self.field_name, - custom_field_values__serialized_value__icontains=value - ) + kwargs = {f'custom_field_data__{self.field_name}__icontains': value} - return queryset + return queryset.filter(**kwargs) -class CustomFieldFilterSet(django_filters.FilterSet): +class CustomFieldModelFilterSet(django_filters.FilterSet): """ Dynamically add a Filter for each CustomField applicable to the parent model. """ - def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - obj_type = ContentType.objects.get_for_model(self._meta.model) custom_fields = CustomField.objects.filter( - obj_type=obj_type + content_types=ContentType.objects.get_for_model(self._meta.model) ).exclude( filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED ) @@ -92,25 +74,26 @@ def __init__(self, *args, **kwargs): self.filters['cf_{}'.format(cf.name)] = CustomFieldFilter(field_name=cf.name, custom_field=cf) -class GraphFilterSet(BaseFilterSet): +class CustomFieldFilterSet(django_filters.FilterSet): class Meta: - model = Graph - fields = ['id', 'type', 'name', 'template_language'] + model = CustomField + fields = ['id', 'content_types', 'name', 'required', 'filter_logic', 'weight'] class ExportTemplateFilterSet(BaseFilterSet): class Meta: model = ExportTemplate - fields = ['id', 'content_type', 'name', 'template_language'] + fields = ['id', 'content_type', 'name'] class ImageAttachmentFilterSet(BaseFilterSet): + content_type = ContentTypeFilter() class Meta: model = ImageAttachment - fields = ['id', 'content_type', 'object_id', 'name'] + fields = ['id', 'content_type_id', 'object_id', 'name'] class TagFilterSet(BaseFilterSet): @@ -260,6 +243,7 @@ class ObjectChangeFilterSet(BaseFilterSet): label='Search', ) time = django_filters.DateTimeFromToRangeFilter() + changed_object_type = ContentTypeFilter() user_id = django_filters.ModelMultipleChoiceFilter( queryset=User.objects.all(), label='User (ID)', @@ -274,7 +258,8 @@ class ObjectChangeFilterSet(BaseFilterSet): class Meta: model = ObjectChange fields = [ - 'id', 'user_name', 'request_id', 'action', 'changed_object_type', 'changed_object_id', 'object_repr', + 'id', 'user', 'user_name', 'request_id', 'action', 'changed_object_type_id', 'changed_object_id', + 'object_repr', ] def search(self, queryset, name, value): @@ -335,3 +320,14 @@ def search(self, queryset, name, value): return queryset.filter( Q(user__username__icontains=value) ) + + +# +# ContentTypes +# + +class ContentTypeFilterSet(django_filters.FilterSet): + + class Meta: + model = ContentType + fields = ['id', 'app_label', 'model'] diff --git a/netbox/extras/forms.py b/netbox/extras/forms.py index c88e662620..eee54076b9 100644 --- a/netbox/extras/forms.py +++ b/netbox/extras/forms.py @@ -12,7 +12,7 @@ ) from virtualization.models import Cluster, ClusterGroup from .choices import * -from .models import ConfigContext, CustomField, CustomFieldValue, ImageAttachment, ObjectChange, Tag +from .models import ConfigContext, CustomField, ImageAttachment, ObjectChange, Tag # @@ -25,78 +25,34 @@ def __init__(self, *args, **kwargs): self.obj_type = ContentType.objects.get_for_model(self._meta.model) self.custom_fields = [] - self.custom_field_values = {} super().__init__(*args, **kwargs) - if self.instance._cf is None: - self.instance._cf = {} - self._append_customfield_fields() def _append_customfield_fields(self): """ Append form fields for all CustomFields assigned to this model. """ - # Retrieve initial CustomField values for the instance - if self.instance.pk: - for cfv in CustomFieldValue.objects.filter( - obj_type=self.obj_type, - obj_id=self.instance.pk - ).prefetch_related('field'): - self.custom_field_values[cfv.field.name] = cfv.serialized_value - # Append form fields; assign initial values if modifying and existing object - for cf in CustomField.objects.filter(obj_type=self.obj_type): + for cf in CustomField.objects.filter(content_types=self.obj_type): field_name = 'cf_{}'.format(cf.name) if self.instance.pk: self.fields[field_name] = cf.to_form_field(set_initial=False) - value = self.custom_field_values.get(cf.name) - self.fields[field_name].initial = value - self.instance._cf[cf.name] = value + self.fields[field_name].initial = self.instance.custom_field_data.get(cf.name) else: self.fields[field_name] = cf.to_form_field() - self.instance._cf[cf.name] = self.fields[field_name].initial # Annotate the field in the list of CustomField form fields self.custom_fields.append(field_name) - def _save_custom_fields(self): - - for field_name in self.custom_fields: - try: - cfv = CustomFieldValue.objects.prefetch_related('field').get( - field=self.fields[field_name].model, - obj_type=self.obj_type, - obj_id=self.instance.pk - ) - except CustomFieldValue.DoesNotExist: - # Skip this field if none exists already and its value is empty - if self.cleaned_data[field_name] in [None, '']: - continue - cfv = CustomFieldValue( - field=self.fields[field_name].model, - obj_type=self.obj_type, - obj_id=self.instance.pk - ) - cfv.value = self.cleaned_data[field_name] - cfv.save() - def save(self, commit=True): - # Cache custom field values on object prior to save to ensure change logging + # Save custom field data on instance for cf_name in self.custom_fields: - self.instance._cf[cf_name[3:]] = self.cleaned_data.get(cf_name) - - obj = super().save(commit) + self.instance.custom_field_data[cf_name[3:]] = self.cleaned_data.get(cf_name) - # Handle custom fields the same way we do M2M fields - if commit: - self._save_custom_fields() - else: - obj.save_custom_fields = self._save_custom_fields - - return obj + return super().save(commit) class CustomFieldModelCSVForm(CSVModelForm, CustomFieldModelForm): @@ -104,7 +60,7 @@ class CustomFieldModelCSVForm(CSVModelForm, CustomFieldModelForm): def _append_customfield_fields(self): # Append form fields - for cf in CustomField.objects.filter(obj_type=self.obj_type): + for cf in CustomField.objects.filter(content_types=self.obj_type): field_name = 'cf_{}'.format(cf.name) self.fields[field_name] = cf.to_form_field(for_csv_import=True) @@ -121,7 +77,7 @@ def __init__(self, *args, **kwargs): self.obj_type = ContentType.objects.get_for_model(self.model) # Add all applicable CustomFields to the form - custom_fields = CustomField.objects.filter(obj_type=self.obj_type) + custom_fields = CustomField.objects.filter(content_types=self.obj_type) for cf in custom_fields: # Annotate non-required custom fields as nullable if not cf.required: @@ -140,7 +96,7 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Add all applicable CustomFields to the form - custom_fields = CustomField.objects.filter(obj_type=self.obj_type).exclude( + custom_fields = CustomField.objects.filter(content_types=self.obj_type).exclude( filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED ) for cf in custom_fields: @@ -406,11 +362,14 @@ class ObjectChangeFilterForm(BootstrapMixin, forms.Form): api_url='/api/users/users/', ) ) - changed_object_type = forms.ModelChoiceField( - queryset=ContentType.objects.order_by('model'), + changed_object_type_id = DynamicModelMultipleChoiceField( + queryset=ContentType.objects.all(), required=False, - widget=ContentTypeSelect(), - label='Object Type' + display_field='display_name', + label='Object Type', + widget=APISelectMultiple( + api_url='/api/extras/content-types/', + ) ) diff --git a/netbox/extras/middleware.py b/netbox/extras/middleware.py deleted file mode 100644 index f7be829cd9..0000000000 --- a/netbox/extras/middleware.py +++ /dev/null @@ -1,32 +0,0 @@ -import uuid - -from .context_managers import change_logging - - -class ObjectChangeMiddleware(object): - """ - This middleware performs three functions in response to an object being created, updated, or deleted: - - 1. Create an ObjectChange to reflect the modification to the object in the changelog. - 2. Enqueue any relevant webhooks. - 3. Increment the metric counter for the event type. - - The post_save and post_delete signals are employed to catch object modifications, however changes are recorded a bit - differently for each. Objects being saved are cached into thread-local storage for action *after* the response has - completed. This ensures that serialization of the object is performed only after any related objects (e.g. tags) - have been created. Conversely, deletions are acted upon immediately, so that the serialized representation of the - object is recorded before it (and any related objects) are actually deleted from the database. - """ - def __init__(self, get_response): - self.get_response = get_response - - def __call__(self, request): - # Assign a random unique ID to the request. This will be used to associate multiple object changes made during - # the same request. - request.id = uuid.uuid4() - - # Process the request with change logging enabled - with change_logging(request): - response = self.get_response(request) - - return response diff --git a/netbox/extras/migrations/0048_exporttemplate_remove_template_language.py b/netbox/extras/migrations/0048_exporttemplate_remove_template_language.py new file mode 100644 index 0000000000..68ff8f5ab1 --- /dev/null +++ b/netbox/extras/migrations/0048_exporttemplate_remove_template_language.py @@ -0,0 +1,17 @@ +# Generated by Django 3.1 on 2020-08-21 15:13 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('extras', '0047_tag_ordering'), + ] + + operations = [ + migrations.RemoveField( + model_name='exporttemplate', + name='template_language', + ), + ] diff --git a/netbox/extras/migrations/0049_remove_graph.py b/netbox/extras/migrations/0049_remove_graph.py new file mode 100644 index 0000000000..c884c8f823 --- /dev/null +++ b/netbox/extras/migrations/0049_remove_graph.py @@ -0,0 +1,16 @@ +# Generated by Django 3.1 on 2020-08-21 15:47 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('extras', '0048_exporttemplate_remove_template_language'), + ] + + operations = [ + migrations.DeleteModel( + name='Graph', + ), + ] diff --git a/netbox/extras/migrations/0050_customfield_changes.py b/netbox/extras/migrations/0050_customfield_changes.py new file mode 100644 index 0000000000..711b21041b --- /dev/null +++ b/netbox/extras/migrations/0050_customfield_changes.py @@ -0,0 +1,65 @@ +import django.contrib.postgres.fields +import django.core.validators +from django.db import migrations, models + +import utilities.validators + + +class Migration(migrations.Migration): + + dependencies = [ + ('extras', '0049_remove_graph'), + ] + + operations = [ + # Rename reverse relation on CustomFieldChoice + migrations.AlterField( + model_name='customfieldchoice', + name='field', + field=models.ForeignKey( + limit_choices_to={'type': 'select'}, + on_delete=django.db.models.deletion.CASCADE, + related_name='_choices', + to='extras.customfield' + ), + ), + # Add choices field to CustomField + migrations.AddField( + model_name='customfield', + name='choices', + field=django.contrib.postgres.fields.ArrayField( + base_field=models.CharField(max_length=100), + blank=True, + null=True, + size=None + ), + ), + # Introduce new default field (to be renamed later) + migrations.AddField( + model_name='customfield', + name='default2', + field=models.JSONField(blank=True, null=True), + ), + # Rename obj_type to content_types + migrations.RenameField( + model_name='customfield', + old_name='obj_type', + new_name='content_types', + ), + # Add validation fields + migrations.AddField( + model_name='customfield', + name='validation_maximum', + field=models.PositiveIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='customfield', + name='validation_minimum', + field=models.PositiveIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='customfield', + name='validation_regex', + field=models.CharField(blank=True, max_length=500, validators=[utilities.validators.validate_regex]), + ), + ] diff --git a/netbox/extras/migrations/0051_migrate_customfields.py b/netbox/extras/migrations/0051_migrate_customfields.py new file mode 100644 index 0000000000..2c992c700d --- /dev/null +++ b/netbox/extras/migrations/0051_migrate_customfields.py @@ -0,0 +1,110 @@ +from django.db import migrations + +from extras.choices import CustomFieldTypeChoices + + +def deserialize_value(field, value): + """ + Convert serialized values to JSON equivalents. + """ + if field.type in (CustomFieldTypeChoices.TYPE_INTEGER): + return int(value) + if field.type == CustomFieldTypeChoices.TYPE_BOOLEAN: + return bool(int(value)) + if field.type == CustomFieldTypeChoices.TYPE_SELECT: + return field._choices.get(pk=int(value)).value + return value + + +def migrate_customfield_defaults(apps, schema_editor): + """ + Copy old serialized defaults to native JSON types. + """ + CustomField = apps.get_model('extras', 'CustomField') + + for customfield in CustomField.objects.exclude(default=''): + try: + if customfield.type == CustomFieldTypeChoices.TYPE_INTEGER: + value = int(customfield.default) + elif customfield.type == CustomFieldTypeChoices.TYPE_BOOLEAN: + value = customfield.default in ['true', 'yes', '1'] + else: + value = customfield.default + except ValueError: + raise ValueError( + f'Invalid default value "{customfield.default}" found for {customfield.type} ' + f'custom field {customfield.name}' + ) + CustomField.objects.filter(pk=customfield.pk).update(default2=value) + + +def migrate_customfieldchoices(apps, schema_editor): + """ + Collect all CustomFieldChoices for each applicable CustomField, and save them locally as an array on + the CustomField instance. + """ + CustomField = apps.get_model('extras', 'CustomField') + CustomFieldChoice = apps.get_model('extras', 'CustomFieldChoice') + + for cf in CustomField.objects.filter(type='select'): + cf.choices = [ + cfc.value for cfc in CustomFieldChoice.objects.filter(field=cf).order_by('weight', 'value') + ] + cf.save() + + +def migrate_customfieldvalues(apps, schema_editor): + """ + Copy data from CustomFieldValues into the custom_field_data JSON field on each model instance. + """ + CustomFieldValue = apps.get_model('extras', 'CustomFieldValue') + + for cfv in CustomFieldValue.objects.prefetch_related('field').exclude(serialized_value=''): + model = apps.get_model(cfv.obj_type.app_label, cfv.obj_type.model) + + # Read and update custom field value for each instance + # TODO: This can be done more efficiently once .update() is supported for JSON fields + cf_data = model.objects.filter(pk=cfv.obj_id).values('custom_field_data').first() + try: + cf_data['custom_field_data'][cfv.field.name] = deserialize_value(cfv.field, cfv.serialized_value) + except ValueError as e: + print(f'{cfv.field.name} ({cfv.field.type}): {cfv.serialized_value} ({cfv.pk})') + raise e + model.objects.filter(pk=cfv.obj_id).update(**cf_data) + + +def fix_filter_logic_values(apps, schema_editor): + """ + Fix invalid values for CustomField.filter_logic (see #5376) + """ + CustomField = apps.get_model('extras', 'CustomField') + + CustomField.objects.filter(filter_logic="integer").update(filter_logic="loose") + + +class Migration(migrations.Migration): + + dependencies = [ + ('circuits', '0020_custom_field_data'), + ('dcim', '0117_custom_field_data'), + ('extras', '0050_customfield_changes'), + ('ipam', '0038_custom_field_data'), + ('secrets', '0010_custom_field_data'), + ('tenancy', '0010_custom_field_data'), + ('virtualization', '0018_custom_field_data'), + ] + + operations = [ + migrations.RunPython( + code=migrate_customfield_defaults + ), + migrations.RunPython( + code=migrate_customfieldchoices + ), + migrations.RunPython( + code=migrate_customfieldvalues + ), + migrations.RunPython( + code=fix_filter_logic_values + ), + ] diff --git a/netbox/extras/migrations/0052_customfield_cleanup.py b/netbox/extras/migrations/0052_customfield_cleanup.py new file mode 100644 index 0000000000..543cdee971 --- /dev/null +++ b/netbox/extras/migrations/0052_customfield_cleanup.py @@ -0,0 +1,26 @@ +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('extras', '0051_migrate_customfields'), + ] + + operations = [ + migrations.RemoveField( + model_name='CustomField', + name='default', + ), + migrations.RenameField( + model_name='CustomField', + old_name='default2', + new_name='default' + ), + migrations.DeleteModel( + name='CustomFieldChoice', + ), + migrations.DeleteModel( + name='CustomFieldValue', + ), + ] diff --git a/netbox/extras/migrations/0053_rename_webhook_obj_type.py b/netbox/extras/migrations/0053_rename_webhook_obj_type.py new file mode 100644 index 0000000000..05bbebad8c --- /dev/null +++ b/netbox/extras/migrations/0053_rename_webhook_obj_type.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1 on 2020-12-02 19:41 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('extras', '0052_customfield_cleanup'), + ] + + operations = [ + migrations.RenameField( + model_name='webhook', + old_name='obj_type', + new_name='content_types', + ), + ] diff --git a/netbox/extras/models/__init__.py b/netbox/extras/models/__init__.py index e520581573..c6191bbd22 100644 --- a/netbox/extras/models/__init__.py +++ b/netbox/extras/models/__init__.py @@ -1,7 +1,7 @@ from .change_logging import ChangeLoggedModel, ObjectChange -from .customfields import CustomField, CustomFieldChoice, CustomFieldModel, CustomFieldValue +from .customfields import CustomField, CustomFieldModel from .models import ( - ConfigContext, ConfigContextModel, CustomLink, ExportTemplate, Graph, ImageAttachment, JobResult, Report, Script, + ConfigContext, ConfigContextModel, CustomLink, ExportTemplate, ImageAttachment, JobResult, Report, Script, Webhook, ) from .tags import Tag, TaggedItem @@ -11,12 +11,9 @@ 'ConfigContext', 'ConfigContextModel', 'CustomField', - 'CustomFieldChoice', 'CustomFieldModel', - 'CustomFieldValue', 'CustomLink', 'ExportTemplate', - 'Graph', 'ImageAttachment', 'JobResult', 'ObjectChange', diff --git a/netbox/extras/models/change_logging.py b/netbox/extras/models/change_logging.py index bec8e2b752..52ffd38f99 100644 --- a/netbox/extras/models/change_logging.py +++ b/netbox/extras/models/change_logging.py @@ -35,7 +35,7 @@ class Meta: def to_objectchange(self, action): """ Return a new ObjectChange representing a change made to this object. This will typically be called automatically - by extras.middleware.ChangeLoggingMiddleware. + by ChangeLoggingMiddleware. """ return ObjectChange( changed_object=self, @@ -152,3 +152,6 @@ def to_csv(self): self.object_repr, self.object_data, ) + + def get_action_class(self): + return ObjectChangeActionChoices.CSS_CLASSES.get(self.action) diff --git a/netbox/extras/models/customfields.py b/netbox/extras/models/customfields.py index 2bf4b5c86f..be06eea8a5 100644 --- a/netbox/extras/models/customfields.py +++ b/netbox/extras/models/customfields.py @@ -1,63 +1,70 @@ +import re from collections import OrderedDict -from datetime import date +from datetime import datetime from django import forms -from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType -from django.core.validators import ValidationError +from django.contrib.postgres.fields import ArrayField +from django.core.serializers.json import DjangoJSONEncoder +from django.core.validators import RegexValidator, ValidationError from django.db import models +from django.utils.safestring import mark_safe -from utilities.forms import CSVChoiceField, DatePicker, LaxURLField, StaticSelect2, add_blank_choice from extras.choices import * from extras.utils import FeatureQuery +from utilities.forms import CSVChoiceField, DatePicker, LaxURLField, StaticSelect2, add_blank_choice +from utilities.querysets import RestrictedQuerySet +from utilities.validators import validate_regex -# -# Custom fields -# - class CustomFieldModel(models.Model): + """ + Abstract class for any model which may have custom fields associated with it. + """ + custom_field_data = models.JSONField( + encoder=DjangoJSONEncoder, + blank=True, + default=dict + ) class Meta: abstract = True - def __init__(self, *args, custom_fields=None, **kwargs): - self._cf = custom_fields - super().__init__(*args, **kwargs) - - def cache_custom_fields(self): - """ - Cache all custom field values for this instance - """ - self._cf = { - field.name: value for field, value in self.get_custom_fields().items() - } - @property def cf(self): """ - Name-based CustomFieldValue accessor for use in templates + Convenience wrapper for custom field data. """ - if self._cf is None: - self.cache_custom_fields() - return self._cf + return self.custom_field_data def get_custom_fields(self): """ Return a dictionary of custom fields for a single object in the form {: value}. """ fields = CustomField.objects.get_for_model(self) + return OrderedDict([ + (field, self.custom_field_data.get(field.name)) for field in fields + ]) - # If the object exists, populate its custom fields with values - if hasattr(self, 'pk'): - values = self.custom_field_values.all() - values_dict = {cfv.field_id: cfv.value for cfv in values} - return OrderedDict([(field, values_dict.get(field.pk)) for field in fields]) - else: - return OrderedDict([(field, None) for field in fields]) + def clean(self): + custom_fields = {cf.name: cf for cf in CustomField.objects.get_for_model(self)} + # Validate all field values + for field_name, value in self.custom_field_data.items(): + if field_name not in custom_fields: + raise ValidationError(f"Unknown field name '{field_name}' in custom field data.") + try: + custom_fields[field_name].validate(value) + except ValidationError as e: + raise ValidationError(f"Invalid value for custom field '{field_name}': {e.message}") -class CustomFieldManager(models.Manager): + # Check for missing required values + for cf in custom_fields.values(): + if cf.required and cf.name not in self.custom_field_data: + raise ValidationError(f"Missing required custom field '{cf.name}'.") + + +class CustomFieldManager(models.Manager.from_queryset(RestrictedQuerySet)): use_in_migrations = True def get_for_model(self, model): @@ -65,11 +72,11 @@ def get_for_model(self, model): Return all CustomFields assigned to the given model. """ content_type = ContentType.objects.get_for_model(model._meta.concrete_model) - return self.get_queryset().filter(obj_type=content_type) + return self.get_queryset().filter(content_types=content_type) class CustomField(models.Model): - obj_type = models.ManyToManyField( + content_types = models.ManyToManyField( to=ContentType, related_name='custom_fields', verbose_name='Object(s)', @@ -83,7 +90,8 @@ class CustomField(models.Model): ) name = models.CharField( max_length=50, - unique=True + unique=True, + help_text='Internal field name' ) label = models.CharField( max_length=50, @@ -107,15 +115,42 @@ class CustomField(models.Model): help_text='Loose matches any instance of a given string; exact ' 'matches the entire field.' ) - default = models.CharField( - max_length=100, + default = models.JSONField( blank=True, - help_text='Default value for the field. Use "true" or "false" for booleans.' + null=True, + help_text='Default value for the field (must be a JSON value). Encapsulate ' + 'strings with double quotes (e.g. "Foo").' ) weight = models.PositiveSmallIntegerField( default=100, help_text='Fields with higher weights appear lower in a form.' ) + validation_minimum = models.PositiveIntegerField( + blank=True, + null=True, + verbose_name='Minimum value', + help_text='Minimum allowed value (for numeric fields)' + ) + validation_maximum = models.PositiveIntegerField( + blank=True, + null=True, + verbose_name='Maximum value', + help_text='Maximum allowed value (for numeric fields)' + ) + validation_regex = models.CharField( + blank=True, + validators=[validate_regex], + max_length=500, + verbose_name='Validation regex', + help_text='Regular expression to enforce on text field values. Use ^ and $ to force matching of entire string. ' + 'For example, ^[A-Z]{3}$ will limit values to exactly three uppercase letters.' + ) + choices = ArrayField( + base_field=models.CharField(max_length=100), + blank=True, + null=True, + help_text='Comma-separated list of available choices (for selection fields)' + ) objects = CustomFieldManager() @@ -125,41 +160,60 @@ class Meta: def __str__(self): return self.label or self.name.replace('_', ' ').capitalize() - def serialize_value(self, value): + def remove_stale_data(self, content_types): """ - Serialize the given value to a string suitable for storage as a CustomFieldValue + Delete custom field data which is no longer relevant (either because the CustomField is + no longer assigned to a model, or because it has been deleted). """ - if value is None: - return '' - if self.type == CustomFieldTypeChoices.TYPE_BOOLEAN: - return str(int(bool(value))) - if self.type == CustomFieldTypeChoices.TYPE_DATE: - # Could be date/datetime object or string + for ct in content_types: + model = ct.model_class() + for obj in model.objects.filter(**{f'custom_field_data__{self.name}__isnull': False}): + del(obj.custom_field_data[self.name]) + obj.save() + + def clean(self): + # Validate the field's default value (if any) + if self.default is not None: try: - return value.strftime('%Y-%m-%d') - except AttributeError: - return value - if self.type == CustomFieldTypeChoices.TYPE_SELECT: - # Could be ModelChoiceField or TypedChoiceField - return str(value.id) if hasattr(value, 'id') else str(value) - return value - - def deserialize_value(self, serialized_value): - """ - Convert a string into the object it represents depending on the type of field - """ - if serialized_value == '': - return None - if self.type == CustomFieldTypeChoices.TYPE_INTEGER: - return int(serialized_value) - if self.type == CustomFieldTypeChoices.TYPE_BOOLEAN: - return bool(int(serialized_value)) - if self.type == CustomFieldTypeChoices.TYPE_DATE: - # Read date as YYYY-MM-DD - return date(*[int(n) for n in serialized_value.split('-')]) - if self.type == CustomFieldTypeChoices.TYPE_SELECT: - return self.choices.get(pk=int(serialized_value)) - return serialized_value + self.validate(self.default) + except ValidationError as err: + raise ValidationError({ + 'default': f'Invalid default value "{self.default}": {err.message}' + }) + + # Minimum/maximum values can be set only for numeric fields + if self.validation_minimum is not None and self.type != CustomFieldTypeChoices.TYPE_INTEGER: + raise ValidationError({ + 'validation_minimum': "A minimum value may be set only for numeric fields" + }) + if self.validation_maximum is not None and self.type != CustomFieldTypeChoices.TYPE_INTEGER: + raise ValidationError({ + 'validation_maximum': "A maximum value may be set only for numeric fields" + }) + + # Regex validation can be set only for text fields + if self.validation_regex and self.type != CustomFieldTypeChoices.TYPE_TEXT: + raise ValidationError({ + 'validation_regex': "Regular expression validation is supported only for text and URL fields" + }) + + # Choices can be set only on selection fields + if self.choices and self.type != CustomFieldTypeChoices.TYPE_SELECT: + raise ValidationError({ + 'choices': "Choices may be set only for custom selection fields." + }) + + # A selection field must have at least two choices defined + if self.type == CustomFieldTypeChoices.TYPE_SELECT and self.choices and len(self.choices) < 2: + raise ValidationError({ + 'choices': "Selection fields must specify at least two choices." + }) + + # A selection field's default (if any) must be present in its available choices + if self.type == CustomFieldTypeChoices.TYPE_SELECT and self.default and self.default not in self.choices: + raise ValidationError({ + 'default': f"The specified default value ({self.default}) is not listed as an available choice." + }) def to_form_field(self, set_initial=True, enforce_required=True, for_csv_import=False): """ @@ -174,21 +228,20 @@ def to_form_field(self, set_initial=True, enforce_required=True, for_csv_import= # Integer if self.type == CustomFieldTypeChoices.TYPE_INTEGER: - field = forms.IntegerField(required=required, initial=initial) + field = forms.IntegerField( + required=required, + initial=initial, + min_value=self.validation_minimum, + max_value=self.validation_maximum + ) # Boolean elif self.type == CustomFieldTypeChoices.TYPE_BOOLEAN: choices = ( (None, '---------'), - (1, 'True'), - (0, 'False'), + (True, 'True'), + (False, 'False'), ) - if initial is not None and initial.lower() in ['true', 'yes', '1']: - initial = 1 - elif initial is not None and initial.lower() in ['false', 'no', '0']: - initial = 0 - else: - initial = None field = forms.NullBooleanField( required=required, initial=initial, widget=StaticSelect2(choices=choices) ) @@ -199,15 +252,15 @@ def to_form_field(self, set_initial=True, enforce_required=True, for_csv_import= # Select elif self.type == CustomFieldTypeChoices.TYPE_SELECT: - choices = [(cfc.pk, cfc.value) for cfc in self.choices.all()] - default_choice = self.choices.filter(value=self.default).first() + choices = [(c, c) for c in self.choices] + default_choice = self.default if self.default in self.choices else None if not required or default_choice is None: choices = add_blank_choice(choices) - # Set the initial value to the PK of the default choice, if any + # Set the initial value to the first available choice (if any) if set_initial and default_choice: - initial = default_choice.pk + initial = default_choice field_class = CSVChoiceField if for_csv_import else forms.ChoiceField field = field_class( @@ -221,89 +274,60 @@ def to_form_field(self, set_initial=True, enforce_required=True, for_csv_import= # Text else: field = forms.CharField(max_length=255, required=required, initial=initial) + if self.validation_regex: + field.validators = [ + RegexValidator( + regex=self.validation_regex, + message=mark_safe(f"Values must match this regex: {self.validation_regex}") + ) + ] field.model = self - field.label = self.label if self.label else self.name.replace('_', ' ').capitalize() + field.label = str(self) if self.description: field.help_text = self.description return field - -class CustomFieldValue(models.Model): - field = models.ForeignKey( - to='extras.CustomField', - on_delete=models.CASCADE, - related_name='values' - ) - obj_type = models.ForeignKey( - to=ContentType, - on_delete=models.PROTECT, - related_name='+' - ) - obj_id = models.PositiveIntegerField() - obj = GenericForeignKey( - ct_field='obj_type', - fk_field='obj_id' - ) - serialized_value = models.CharField( - max_length=255 - ) - - class Meta: - ordering = ('obj_type', 'obj_id', 'pk') # (obj_type, obj_id) may be non-unique - unique_together = ('field', 'obj_type', 'obj_id') - - def __str__(self): - return '{} {}'.format(self.obj, self.field) - - @property - def value(self): - return self.field.deserialize_value(self.serialized_value) - - @value.setter - def value(self, value): - self.serialized_value = self.field.serialize_value(value) - - def save(self, *args, **kwargs): - # Delete this object if it no longer has a value to store - if self.pk and self.value is None: - self.delete() - else: - super().save(*args, **kwargs) - - -class CustomFieldChoice(models.Model): - field = models.ForeignKey( - to='extras.CustomField', - on_delete=models.CASCADE, - related_name='choices', - limit_choices_to={'type': CustomFieldTypeChoices.TYPE_SELECT} - ) - value = models.CharField( - max_length=100 - ) - weight = models.PositiveSmallIntegerField( - default=100, - help_text='Higher weights appear lower in the list' - ) - - class Meta: - ordering = ['field', 'weight', 'value'] - unique_together = ['field', 'value'] - - def __str__(self): - return self.value - - def clean(self): - if self.field.type != CustomFieldTypeChoices.TYPE_SELECT: - raise ValidationError("Custom field choices can only be assigned to selection fields.") - - def delete(self, using=None, keep_parents=False): - # When deleting a CustomFieldChoice, delete all CustomFieldValues which point to it - pk = self.pk - super().delete(using, keep_parents) - CustomFieldValue.objects.filter( - field__type=CustomFieldTypeChoices.TYPE_SELECT, - serialized_value=str(pk) - ).delete() + def validate(self, value): + """ + Validate a value according to the field's type validation rules. + """ + if value not in [None, '']: + + # Validate text field + if self.type == CustomFieldTypeChoices.TYPE_TEXT and self.validation_regex: + if not re.match(self.validation_regex, value): + raise ValidationError(f"Value must match regex '{self.validation_regex}'") + + # Validate integer + if self.type == CustomFieldTypeChoices.TYPE_INTEGER: + try: + int(value) + except ValueError: + raise ValidationError("Value must be an integer.") + if self.validation_minimum is not None and value < self.validation_minimum: + raise ValidationError(f"Value must be at least {self.validation_minimum}") + if self.validation_maximum is not None and value > self.validation_maximum: + raise ValidationError(f"Value must not exceed {self.validation_maximum}") + + # Validate boolean + if self.type == CustomFieldTypeChoices.TYPE_BOOLEAN and value not in [True, False, 1, 0]: + raise ValidationError("Value must be true or false.") + + # Validate date + if self.type == CustomFieldTypeChoices.TYPE_DATE: + try: + datetime.strptime(value, '%Y-%m-%d') + except ValueError: + raise ValidationError("Date values must be in the format YYYY-MM-DD.") + + # Validate selected choice + if self.type == CustomFieldTypeChoices.TYPE_SELECT: + if value not in self.choices: + raise ValidationError( + f"Invalid choice ({value}). Available choices are: {', '.join(self.choices)}" + ) + + elif self.required: + raise ValidationError("Required field cannot be empty.") diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index fe4531b51f..8934d97322 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -8,7 +8,6 @@ from django.core.validators import ValidationError from django.db import models from django.http import HttpResponse -from django.template import Template, Context from django.urls import reverse from django.utils import timezone from rest_framework.utils.encoders import JSONEncoder @@ -32,7 +31,7 @@ class Webhook(models.Model): delete in NetBox. The request will contain a representation of the object, which the remote application can act on. Each Webhook can be limited to firing only on certain actions or certain object types. """ - obj_type = models.ManyToManyField( + content_types = models.ManyToManyField( to=ContentType, related_name='webhooks', verbose_name='Object types', @@ -203,69 +202,6 @@ def __str__(self): return self.name -# -# Graphs -# - -class Graph(models.Model): - type = models.ForeignKey( - to=ContentType, - on_delete=models.CASCADE, - limit_choices_to=FeatureQuery('graphs') - ) - weight = models.PositiveSmallIntegerField( - default=1000 - ) - name = models.CharField( - max_length=100, - verbose_name='Name' - ) - template_language = models.CharField( - max_length=50, - choices=TemplateLanguageChoices, - default=TemplateLanguageChoices.LANGUAGE_JINJA2 - ) - source = models.CharField( - max_length=500, - verbose_name='Source URL' - ) - link = models.URLField( - blank=True, - verbose_name='Link URL' - ) - - objects = RestrictedQuerySet.as_manager() - - class Meta: - ordering = ('type', 'weight', 'name', 'pk') # (type, weight, name) may be non-unique - - def __str__(self): - return self.name - - def embed_url(self, obj): - context = {'obj': obj} - - if self.template_language == TemplateLanguageChoices.LANGUAGE_DJANGO: - template = Template(self.source) - return template.render(Context(context)) - - elif self.template_language == TemplateLanguageChoices.LANGUAGE_JINJA2: - return render_jinja2(self.source, context) - - def embed_link(self, obj): - if self.link is None: - return '' - - context = {'obj': obj} - - if self.template_language == TemplateLanguageChoices.LANGUAGE_DJANGO: - template = Template(self.link) - return template.render(Context(context)) - - elif self.template_language == TemplateLanguageChoices.LANGUAGE_JINJA2: - return render_jinja2(self.link, context) - - # # Export templates # @@ -283,11 +219,6 @@ class ExportTemplate(models.Model): max_length=200, blank=True ) - template_language = models.CharField( - max_length=50, - choices=TemplateLanguageChoices, - default=TemplateLanguageChoices.LANGUAGE_JINJA2 - ) template_code = models.TextField( help_text='The list of objects being exported is passed as a context variable named queryset.' ) @@ -321,16 +252,7 @@ def render(self, queryset): context = { 'queryset': queryset } - - if self.template_language == TemplateLanguageChoices.LANGUAGE_DJANGO: - template = Template(self.template_code) - output = template.render(Context(context)) - - elif self.template_language == TemplateLanguageChoices.LANGUAGE_JINJA2: - output = render_jinja2(self.template_code, context) - - else: - return None + output = render_jinja2(self.template_code, context) # Replace CRLF-style line terminators output = output.replace('\r\n', '\n') diff --git a/netbox/extras/querysets.py b/netbox/extras/querysets.py index f75b01cc9f..8276787db5 100644 --- a/netbox/extras/querysets.py +++ b/netbox/extras/querysets.py @@ -1,5 +1,3 @@ -from collections import OrderedDict - from django.db.models import OuterRef, Subquery, Q from extras.models.tags import TaggedItem @@ -7,22 +5,6 @@ from utilities.querysets import RestrictedQuerySet -class CustomFieldQueryset: - """ - Annotate custom fields on objects within a QuerySet. - """ - def __init__(self, queryset, custom_fields): - self.queryset = queryset - self.model = queryset.model - self.custom_fields = custom_fields - - def __iter__(self): - for obj in self.queryset: - values_dict = {cfv.field_id: cfv.value for cfv in obj.custom_field_values.all()} - obj.custom_fields = OrderedDict([(field, values_dict.get(field.pk)) for field in self.custom_fields]) - yield obj - - class ConfigContextQuerySet(RestrictedQuerySet): def get_for_object(self, obj, aggregate_data=False): diff --git a/netbox/extras/scripts.py b/netbox/extras/scripts.py index f63f027822..3ef8741a57 100644 --- a/netbox/extras/scripts.py +++ b/netbox/extras/scripts.py @@ -428,19 +428,6 @@ def run_script(data, request, commit=True, *args, **kwargs): # Add the current request as a property of the script script.request = request - # TODO: Drop backward-compatibility for absent 'commit' argument in v2.10 - # Determine whether the script accepts a 'commit' argument (this was introduced in v2.7.8) - kwargs = { - 'data': data - } - if 'commit' in inspect.signature(script.run).parameters: - kwargs['commit'] = commit - else: - warnings.warn( - f"The run() method of script {script} should support a 'commit' argument. This will be required beginning " - f"with NetBox v2.10." - ) - def _run_script(): """ Core script execution task. We capture this within a subfunction to allow for conditionally wrapping it with @@ -448,7 +435,7 @@ def _run_script(): """ try: with transaction.atomic(): - script.output = script.run(**kwargs) + script.output = script.run(data=data, commit=commit) job_result.set_status(JobResultStatusChoices.STATUS_COMPLETED) if not commit: diff --git a/netbox/extras/signals.py b/netbox/extras/signals.py index e10c41d34d..0d6295e5b2 100644 --- a/netbox/extras/signals.py +++ b/netbox/extras/signals.py @@ -3,12 +3,14 @@ from cacheops.signals import cache_invalidated, cache_read from django.conf import settings +from django.contrib.contenttypes.models import ContentType +from django.db.models.signals import m2m_changed, pre_delete from django.utils import timezone from django_prometheus.models import model_deletes, model_inserts, model_updates from prometheus_client import Counter from .choices import ObjectChangeActionChoices -from .models import ObjectChange +from .models import CustomField, ObjectChange from .webhooks import enqueue_webhooks @@ -71,6 +73,29 @@ def _handle_deleted_object(request, sender, instance, **kwargs): model_deletes.labels(instance._meta.model_name).inc() +# +# Custom fields +# + +def handle_cf_removed_obj_types(instance, action, pk_set, **kwargs): + """ + Handle the cleanup of old custom field data when a CustomField is removed from one or more ContentTypes. + """ + if action == 'post_remove': + instance.remove_stale_data(ContentType.objects.filter(pk__in=pk_set)) + + +def handle_cf_deleted(instance, **kwargs): + """ + Handle the cleanup of old custom field data when a CustomField is deleted. + """ + instance.remove_stale_data(instance.content_types.all()) + + +m2m_changed.connect(handle_cf_removed_obj_types, sender=CustomField.content_types.through) +pre_delete.connect(handle_cf_deleted, sender=CustomField) + + # # Caching # diff --git a/netbox/extras/tables.py b/netbox/extras/tables.py index b883c468a1..cccb56c0a1 100644 --- a/netbox/extras/tables.py +++ b/netbox/extras/tables.py @@ -1,6 +1,7 @@ import django_tables2 as tables +from django.conf import settings -from utilities.tables import BaseTable, BooleanColumn, ButtonsColumn, ColorColumn, ToggleColumn +from utilities.tables import BaseTable, BooleanColumn, ButtonsColumn, ChoiceFieldColumn, ColorColumn, ToggleColumn from .models import ConfigContext, ObjectChange, Tag, TaggedItem TAGGED_ITEM = """ @@ -13,24 +14,10 @@ CONFIGCONTEXT_ACTIONS = """ {% if perms.extras.change_configcontext %} - + {% endif %} {% if perms.extras.delete_configcontext %} - -{% endif %} -""" - -OBJECTCHANGE_TIME = """ -{{ value|date:"SHORT_DATETIME_FORMAT" }} -""" - -OBJECTCHANGE_ACTION = """ -{% if record.action == 'create' %} - Created -{% elif record.action == 'update' %} - Updated -{% elif record.action == 'delete' %} - Deleted + {% endif %} """ @@ -89,12 +76,11 @@ class Meta(BaseTable.Meta): class ObjectChangeTable(BaseTable): - time = tables.TemplateColumn( - template_code=OBJECTCHANGE_TIME - ) - action = tables.TemplateColumn( - template_code=OBJECTCHANGE_ACTION + time = tables.DateTimeColumn( + linkify=True, + format=settings.SHORT_DATETIME_FORMAT ) + action = ChoiceFieldColumn() changed_object_type = tables.Column( verbose_name='Type' ) diff --git a/netbox/extras/templatetags/custom_links.py b/netbox/extras/templatetags/custom_links.py index 78630336ed..30375c5627 100644 --- a/netbox/extras/templatetags/custom_links.py +++ b/netbox/extras/templatetags/custom_links.py @@ -61,7 +61,7 @@ def custom_links(context, obj): ) except Exception as e: template_code += '' \ - ' {}\n'.format(e, cl.name) + ' {}\n'.format(e, cl.name) # Add grouped links to template for group, links in group_names.items(): @@ -80,7 +80,7 @@ def custom_links(context, obj): except Exception as e: links_rendered.append( '
  • ' - ' {}
  • '.format(e, cl.name) + ' {}'.format(e, cl.name) ) if links_rendered: diff --git a/netbox/extras/templatetags/log_levels.py b/netbox/extras/templatetags/log_levels.py index c92ff8cdfd..050a6996de 100644 --- a/netbox/extras/templatetags/log_levels.py +++ b/netbox/extras/templatetags/log_levels.py @@ -13,5 +13,5 @@ def log_level(level): """ return { 'name': LogLevelChoices.as_dict()[level], - 'class': dict(LogLevelChoices.CLASS_MAP)[level] + 'class': LogLevelChoices.CSS_CLASSES.get(level) } diff --git a/netbox/extras/tests/dummy_plugin/navigation.py b/netbox/extras/tests/dummy_plugin/navigation.py index feeb38b695..88ac3f7c92 100644 --- a/netbox/extras/tests/dummy_plugin/navigation.py +++ b/netbox/extras/tests/dummy_plugin/navigation.py @@ -9,12 +9,12 @@ PluginMenuButton( link='admin:dummy_plugin_dummymodel_add', title='Add a new dummy model', - icon_class='fa fa-plus', + icon_class='mdi mdi-plus-thick', ), PluginMenuButton( link='admin:dummy_plugin_dummymodel_add', title='Add a new dummy model', - icon_class='fa fa-plus', + icon_class='mdi mdi-plus-thick', ), ) ), diff --git a/netbox/extras/tests/test_api.py b/netbox/extras/tests/test_api.py index 9e9c418f91..bcc95467a8 100644 --- a/netbox/extras/tests/test_api.py +++ b/netbox/extras/tests/test_api.py @@ -2,6 +2,7 @@ from unittest import skipIf from django.contrib.contenttypes.models import ContentType +from django.test import override_settings from django.urls import reverse from django.utils.timezone import make_aware from django_rq.queues import get_connection @@ -10,7 +11,7 @@ from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Rack, RackGroup, RackRole, Site from extras.api.views import ReportViewSet, ScriptViewSet -from extras.models import ConfigContext, ExportTemplate, Graph, ImageAttachment, Tag +from extras.models import ConfigContext, CustomField, ExportTemplate, ImageAttachment, Tag from extras.reports import Report from extras.scripts import BooleanVar, IntegerVar, Script, StringVar from utilities.testing import APITestCase, APIViewTestCases @@ -29,37 +30,51 @@ def test_root(self): self.assertEqual(response.status_code, 200) -class GraphTest(APIViewTestCases.APIViewTestCase): - model = Graph +class CustomFieldTest(APIViewTestCases.APIViewTestCase): + model = CustomField brief_fields = ['id', 'name', 'url'] create_data = [ { - 'type': 'dcim.site', - 'name': 'Graph 4', - 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=4', + 'content_types': ['dcim.site'], + 'name': 'cf4', + 'type': 'date', }, { - 'type': 'dcim.site', - 'name': 'Graph 5', - 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=5', + 'content_types': ['dcim.site'], + 'name': 'cf5', + 'type': 'url', }, { - 'type': 'dcim.site', - 'name': 'Graph 6', - 'source': 'http://example.com/graphs.py?site={{ obj.name }}&foo=6', + 'content_types': ['dcim.site'], + 'name': 'cf6', + 'type': 'select', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): - ct = ContentType.objects.get_for_model(Site) + site_ct = ContentType.objects.get_for_model(Site) - graphs = ( - Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?site={{ obj.name }}&foo=1'), - Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?site={{ obj.name }}&foo=2'), - Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?site={{ obj.name }}&foo=3'), + custom_fields = ( + CustomField( + name='cf1', + type='text' + ), + CustomField( + name='cf2', + type='integer' + ), + CustomField( + name='cf3', + type='boolean' + ), ) - Graph.objects.bulk_create(graphs) + CustomField.objects.bulk_create(custom_fields) + for cf in custom_fields: + cf.content_types.add(site_ct) class ExportTemplateTest(APIViewTestCases.APIViewTestCase): @@ -82,6 +97,9 @@ class ExportTemplateTest(APIViewTestCases.APIViewTestCase): 'template_code': '{% for obj in queryset %}{{ obj.name }}\n{% endfor %}', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -124,6 +142,9 @@ class TagTest(APIViewTestCases.APIViewTestCase): 'slug': 'tag-6', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -197,6 +218,9 @@ class ConfigContextTest(APIViewTestCases.APIViewTestCase): 'data': {'more_baz': None}, }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -420,3 +444,21 @@ def test_get_rack_last_updated_lte(self): self.assertEqual(response.data['count'], 1) self.assertEqual(response.data['results'][0]['id'], self.rack2.pk) + + +class ContentTypeTest(APITestCase): + + @override_settings(EXEMPT_VIEW_PERMISSIONS=['contenttypes.contenttype']) + def test_list_objects(self): + contenttype_count = ContentType.objects.count() + + response = self.client.get(reverse('extras-api:contenttype-list'), **self.header) + self.assertHttpStatus(response, status.HTTP_200_OK) + self.assertEqual(response.data['count'], contenttype_count) + + @override_settings(EXEMPT_VIEW_PERMISSIONS=['contenttypes.contenttype']) + def test_get_object(self): + contenttype = ContentType.objects.first() + + url = reverse('extras-api:contenttype-detail', kwargs={'pk': contenttype.pk}) + self.assertHttpStatus(self.client.get(url, **self.header), status.HTTP_200_OK) diff --git a/netbox/extras/tests/test_changelog.py b/netbox/extras/tests/test_changelog.py index 8c9d09564e..dbdbb53439 100644 --- a/netbox/extras/tests/test_changelog.py +++ b/netbox/extras/tests/test_changelog.py @@ -5,7 +5,7 @@ from dcim.choices import SiteStatusChoices from dcim.models import Site from extras.choices import * -from extras.models import CustomField, CustomFieldValue, ObjectChange, Tag +from extras.models import CustomField, ObjectChange, Tag from utilities.testing import APITestCase from utilities.testing.utils import post_data from utilities.testing.views import ModelViewTestCase @@ -25,7 +25,7 @@ def setUpTestData(cls): required=False ) cf.save() - cf.obj_type.set([ct]) + cf.content_types.set([ct]) def test_create_object(self): tags = self.create_tags('Tag 1', 'Tag 2') @@ -93,16 +93,14 @@ def test_update_object(self): def test_delete_object(self): site = Site( name='Test Site 1', - slug='test-site-1' + slug='test-site-1', + custom_field_data={ + 'my_field': 'ABC' + } ) site.save() self.create_tags('Tag 1', 'Tag 2') site.tags.set('Tag 1', 'Tag 2') - CustomFieldValue.objects.create( - field=CustomField.objects.get(name='my_field'), - obj=site, - value='ABC' - ) request = { 'path': self._get_url('delete', instance=site), @@ -133,7 +131,7 @@ def setUp(self): required=False ) cf.save() - cf.obj_type.set([ct]) + cf.content_types.set([ct]) # Create some tags tags = ( @@ -209,15 +207,13 @@ def test_update_object(self): def test_delete_object(self): site = Site( name='Test Site 1', - slug='test-site-1' + slug='test-site-1', + custom_field_data={ + 'my_field': 'ABC' + } ) site.save() site.tags.set(*Tag.objects.all()[:2]) - CustomFieldValue.objects.create( - field=CustomField.objects.get(name='my_field'), - obj=site, - value='ABC' - ) self.assertEqual(ObjectChange.objects.count(), 0) self.add_permissions('dcim.delete_site') url = reverse('dcim-api:site-detail', kwargs={'pk': site.pk}) diff --git a/netbox/extras/tests/test_customfields.py b/netbox/extras/tests/test_customfields.py index e543b63e3c..fe56027dc1 100644 --- a/netbox/extras/tests/test_customfields.py +++ b/netbox/extras/tests/test_customfields.py @@ -1,13 +1,12 @@ -from datetime import date - from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ValidationError from django.urls import reverse from rest_framework import status from dcim.forms import SiteCSVForm -from dcim.models import Site +from dcim.models import Site, Rack from extras.choices import * -from extras.models import CustomField, CustomFieldValue, CustomFieldChoice +from extras.models import CustomField from utilities.testing import APITestCase, TestCase from virtualization.models import VirtualMachine @@ -23,14 +22,13 @@ def setUp(self): ]) def test_simple_fields(self): - DATA = ( {'field_type': CustomFieldTypeChoices.TYPE_TEXT, 'field_value': 'Foobar!', 'empty_value': ''}, {'field_type': CustomFieldTypeChoices.TYPE_INTEGER, 'field_value': 0, 'empty_value': None}, {'field_type': CustomFieldTypeChoices.TYPE_INTEGER, 'field_value': 42, 'empty_value': None}, {'field_type': CustomFieldTypeChoices.TYPE_BOOLEAN, 'field_value': True, 'empty_value': None}, {'field_type': CustomFieldTypeChoices.TYPE_BOOLEAN, 'field_value': False, 'empty_value': None}, - {'field_type': CustomFieldTypeChoices.TYPE_DATE, 'field_value': date(2016, 6, 23), 'empty_value': None}, + {'field_type': CustomFieldTypeChoices.TYPE_DATE, 'field_value': '2016-06-23', 'empty_value': None}, {'field_type': CustomFieldTypeChoices.TYPE_URL, 'field_value': 'http://example.com/', 'empty_value': ''}, ) @@ -41,58 +39,53 @@ def test_simple_fields(self): # Create a custom field cf = CustomField(type=data['field_type'], name='my_field', required=False) cf.save() - cf.obj_type.set([obj_type]) - cf.save() + cf.content_types.set([obj_type]) # Assign a value to the first Site site = Site.objects.first() - cfv = CustomFieldValue(field=cf, obj_type=obj_type, obj_id=site.id) - cfv.value = data['field_value'] - cfv.save() + site.custom_field_data[cf.name] = data['field_value'] + site.save() # Retrieve the stored value - cfv = CustomFieldValue.objects.filter(obj_type=obj_type, obj_id=site.pk).first() - self.assertEqual(cfv.value, data['field_value']) + site.refresh_from_db() + self.assertEqual(site.custom_field_data[cf.name], data['field_value']) # Delete the stored value - cfv.value = data['empty_value'] - cfv.save() - self.assertEqual(CustomFieldValue.objects.filter(obj_type=obj_type, obj_id=site.pk).count(), 0) + site.custom_field_data.pop(cf.name) + site.save() + site.refresh_from_db() + self.assertIsNone(site.custom_field_data.get(cf.name)) # Delete the custom field cf.delete() def test_select_field(self): - obj_type = ContentType.objects.get_for_model(Site) # Create a custom field - cf = CustomField(type=CustomFieldTypeChoices.TYPE_SELECT, name='my_field', required=False) - cf.save() - cf.obj_type.set([obj_type]) + cf = CustomField( + type=CustomFieldTypeChoices.TYPE_SELECT, + name='my_field', + required=False, + choices=['Option A', 'Option B', 'Option C'] + ) cf.save() - - # Create some choices for the field - CustomFieldChoice.objects.bulk_create([ - CustomFieldChoice(field=cf, value='Option A'), - CustomFieldChoice(field=cf, value='Option B'), - CustomFieldChoice(field=cf, value='Option C'), - ]) + cf.content_types.set([obj_type]) # Assign a value to the first Site site = Site.objects.first() - cfv = CustomFieldValue(field=cf, obj_type=obj_type, obj_id=site.id) - cfv.value = cf.choices.first() - cfv.save() + site.custom_field_data[cf.name] = 'Option A' + site.save() # Retrieve the stored value - cfv = CustomFieldValue.objects.filter(obj_type=obj_type, obj_id=site.pk).first() - self.assertEqual(str(cfv.value), 'Option A') + site.refresh_from_db() + self.assertEqual(site.custom_field_data[cf.name], 'Option A') # Delete the stored value - cfv.value = None - cfv.save() - self.assertEqual(CustomFieldValue.objects.filter(obj_type=obj_type, obj_id=site.pk).count(), 0) + site.custom_field_data.pop(cf.name) + site.save() + site.refresh_from_db() + self.assertIsNone(site.custom_field_data.get(cf.name)) # Delete the custom field cf.delete() @@ -104,7 +97,7 @@ def setUp(self): content_type = ContentType.objects.get_for_model(Site) custom_field = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='text_field', default='foo') custom_field.save() - custom_field.obj_type.set([content_type]) + custom_field.content_types.set([content_type]) def test_get_for_model(self): self.assertEqual(CustomField.objects.get_for_model(Site).count(), 1) @@ -120,41 +113,33 @@ def setUpTestData(cls): # Text custom field cls.cf_text = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='text_field', default='foo') cls.cf_text.save() - cls.cf_text.obj_type.set([content_type]) + cls.cf_text.content_types.set([content_type]) # Integer custom field cls.cf_integer = CustomField(type=CustomFieldTypeChoices.TYPE_INTEGER, name='number_field', default=123) cls.cf_integer.save() - cls.cf_integer.obj_type.set([content_type]) + cls.cf_integer.content_types.set([content_type]) # Boolean custom field cls.cf_boolean = CustomField(type=CustomFieldTypeChoices.TYPE_BOOLEAN, name='boolean_field', default=False) cls.cf_boolean.save() - cls.cf_boolean.obj_type.set([content_type]) + cls.cf_boolean.content_types.set([content_type]) # Date custom field cls.cf_date = CustomField(type=CustomFieldTypeChoices.TYPE_DATE, name='date_field', default='2020-01-01') cls.cf_date.save() - cls.cf_date.obj_type.set([content_type]) + cls.cf_date.content_types.set([content_type]) # URL custom field cls.cf_url = CustomField(type=CustomFieldTypeChoices.TYPE_URL, name='url_field', default='http://example.com/1') cls.cf_url.save() - cls.cf_url.obj_type.set([content_type]) + cls.cf_url.content_types.set([content_type]) # Select custom field - cls.cf_select = CustomField(type=CustomFieldTypeChoices.TYPE_SELECT, name='choice_field') - cls.cf_select.save() - cls.cf_select.obj_type.set([content_type]) - cls.cf_select_choice1 = CustomFieldChoice(field=cls.cf_select, value='Foo') - cls.cf_select_choice1.save() - cls.cf_select_choice2 = CustomFieldChoice(field=cls.cf_select, value='Bar') - cls.cf_select_choice2.save() - cls.cf_select_choice3 = CustomFieldChoice(field=cls.cf_select, value='Baz') - cls.cf_select_choice3.save() - - cls.cf_select.default = cls.cf_select_choice1.value + cls.cf_select = CustomField(type=CustomFieldTypeChoices.TYPE_SELECT, name='choice_field', choices=['Foo', 'Bar', 'Baz']) + cls.cf_select.default = 'Foo' cls.cf_select.save() + cls.cf_select.content_types.set([content_type]) # Create some sites cls.sites = ( @@ -164,20 +149,17 @@ def setUpTestData(cls): Site.objects.bulk_create(cls.sites) # Assign custom field values for site 2 - site2_cfvs = { - cls.cf_text: 'bar', - cls.cf_integer: 456, - cls.cf_boolean: True, - cls.cf_date: '2020-01-02', - cls.cf_url: 'http://example.com/2', - cls.cf_select: cls.cf_select_choice2.pk, + cls.sites[1].custom_field_data = { + cls.cf_text.name: 'bar', + cls.cf_integer.name: 456, + cls.cf_boolean.name: True, + cls.cf_date.name: '2020-01-02', + cls.cf_url.name: 'http://example.com/2', + cls.cf_select.name: 'Bar', } - for field, value in site2_cfvs.items(): - cfv = CustomFieldValue(field=field, obj=cls.sites[1]) - cfv.value = value - cfv.save() + cls.sites[1].save() - def test_get_single_object_without_custom_field_values(self): + def test_get_single_object_without_custom_field_data(self): """ Validate that custom fields are present on an object even if it has no values defined. """ @@ -195,13 +177,11 @@ def test_get_single_object_without_custom_field_values(self): 'choice_field': None, }) - def test_get_single_object_with_custom_field_values(self): + def test_get_single_object_with_custom_field_data(self): """ Validate that custom fields are present and correctly set for an object with values defined. """ - site2_cfvs = { - cfv.field.name: cfv.value for cfv in self.sites[1].custom_field_values.all() - } + site2_cfvs = self.sites[1].custom_field_data url = reverse('dcim-api:site-detail', kwargs={'pk': self.sites[1].pk}) self.add_permissions('dcim.view_site') @@ -212,7 +192,7 @@ def test_get_single_object_with_custom_field_values(self): self.assertEqual(response.data['custom_fields']['boolean_field'], site2_cfvs['boolean_field']) self.assertEqual(response.data['custom_fields']['date_field'], site2_cfvs['date_field']) self.assertEqual(response.data['custom_fields']['url_field'], site2_cfvs['url_field']) - self.assertEqual(response.data['custom_fields']['choice_field']['label'], self.cf_select_choice2.value) + self.assertEqual(response.data['custom_fields']['choice_field'], site2_cfvs['choice_field']) def test_create_single_object_with_defaults(self): """ @@ -235,19 +215,16 @@ def test_create_single_object_with_defaults(self): self.assertEqual(response_cf['boolean_field'], self.cf_boolean.default) self.assertEqual(response_cf['date_field'], self.cf_date.default) self.assertEqual(response_cf['url_field'], self.cf_url.default) - self.assertEqual(response_cf['choice_field'], self.cf_select_choice1.pk) + self.assertEqual(response_cf['choice_field'], self.cf_select.default) # Validate database data site = Site.objects.get(pk=response.data['id']) - cfvs = { - cfv.field.name: cfv.value for cfv in site.custom_field_values.all() - } - self.assertEqual(cfvs['text_field'], self.cf_text.default) - self.assertEqual(cfvs['number_field'], self.cf_integer.default) - self.assertEqual(cfvs['boolean_field'], self.cf_boolean.default) - self.assertEqual(str(cfvs['date_field']), self.cf_date.default) - self.assertEqual(cfvs['url_field'], self.cf_url.default) - self.assertEqual(cfvs['choice_field'].pk, self.cf_select_choice1.pk) + self.assertEqual(site.custom_field_data['text_field'], self.cf_text.default) + self.assertEqual(site.custom_field_data['number_field'], self.cf_integer.default) + self.assertEqual(site.custom_field_data['boolean_field'], self.cf_boolean.default) + self.assertEqual(str(site.custom_field_data['date_field']), self.cf_date.default) + self.assertEqual(site.custom_field_data['url_field'], self.cf_url.default) + self.assertEqual(site.custom_field_data['choice_field'], self.cf_select.default) def test_create_single_object_with_values(self): """ @@ -262,7 +239,7 @@ def test_create_single_object_with_values(self): 'boolean_field': True, 'date_field': '2020-01-02', 'url_field': 'http://example.com/2', - 'choice_field': self.cf_select_choice2.pk, + 'choice_field': 'Bar', }, } url = reverse('dcim-api:site-list') @@ -283,15 +260,12 @@ def test_create_single_object_with_values(self): # Validate database data site = Site.objects.get(pk=response.data['id']) - cfvs = { - cfv.field.name: cfv.value for cfv in site.custom_field_values.all() - } - self.assertEqual(cfvs['text_field'], data_cf['text_field']) - self.assertEqual(cfvs['number_field'], data_cf['number_field']) - self.assertEqual(cfvs['boolean_field'], data_cf['boolean_field']) - self.assertEqual(str(cfvs['date_field']), data_cf['date_field']) - self.assertEqual(cfvs['url_field'], data_cf['url_field']) - self.assertEqual(cfvs['choice_field'].pk, data_cf['choice_field']) + self.assertEqual(site.custom_field_data['text_field'], data_cf['text_field']) + self.assertEqual(site.custom_field_data['number_field'], data_cf['number_field']) + self.assertEqual(site.custom_field_data['boolean_field'], data_cf['boolean_field']) + self.assertEqual(str(site.custom_field_data['date_field']), data_cf['date_field']) + self.assertEqual(site.custom_field_data['url_field'], data_cf['url_field']) + self.assertEqual(site.custom_field_data['choice_field'], data_cf['choice_field']) def test_create_multiple_objects_with_defaults(self): """ @@ -328,19 +302,16 @@ def test_create_multiple_objects_with_defaults(self): self.assertEqual(response_cf['boolean_field'], self.cf_boolean.default) self.assertEqual(response_cf['date_field'], self.cf_date.default) self.assertEqual(response_cf['url_field'], self.cf_url.default) - self.assertEqual(response_cf['choice_field'], self.cf_select_choice1.pk) + self.assertEqual(response_cf['choice_field'], self.cf_select.default) # Validate database data site = Site.objects.get(pk=response.data[i]['id']) - cfvs = { - cfv.field.name: cfv.value for cfv in site.custom_field_values.all() - } - self.assertEqual(cfvs['text_field'], self.cf_text.default) - self.assertEqual(cfvs['number_field'], self.cf_integer.default) - self.assertEqual(cfvs['boolean_field'], self.cf_boolean.default) - self.assertEqual(str(cfvs['date_field']), self.cf_date.default) - self.assertEqual(cfvs['url_field'], self.cf_url.default) - self.assertEqual(cfvs['choice_field'].pk, self.cf_select_choice1.pk) + self.assertEqual(site.custom_field_data['text_field'], self.cf_text.default) + self.assertEqual(site.custom_field_data['number_field'], self.cf_integer.default) + self.assertEqual(site.custom_field_data['boolean_field'], self.cf_boolean.default) + self.assertEqual(str(site.custom_field_data['date_field']), self.cf_date.default) + self.assertEqual(site.custom_field_data['url_field'], self.cf_url.default) + self.assertEqual(site.custom_field_data['choice_field'], self.cf_select.default) def test_create_multiple_objects_with_values(self): """ @@ -352,7 +323,7 @@ def test_create_multiple_objects_with_values(self): 'boolean_field': True, 'date_field': '2020-01-02', 'url_field': 'http://example.com/2', - 'choice_field': self.cf_select_choice2.pk, + 'choice_field': 'Bar', } data = ( { @@ -391,24 +362,20 @@ def test_create_multiple_objects_with_values(self): # Validate database data site = Site.objects.get(pk=response.data[i]['id']) - cfvs = { - cfv.field.name: cfv.value for cfv in site.custom_field_values.all() - } - self.assertEqual(cfvs['text_field'], custom_field_data['text_field']) - self.assertEqual(cfvs['number_field'], custom_field_data['number_field']) - self.assertEqual(cfvs['boolean_field'], custom_field_data['boolean_field']) - self.assertEqual(str(cfvs['date_field']), custom_field_data['date_field']) - self.assertEqual(cfvs['url_field'], custom_field_data['url_field']) - self.assertEqual(cfvs['choice_field'].pk, custom_field_data['choice_field']) + self.assertEqual(site.custom_field_data['text_field'], custom_field_data['text_field']) + self.assertEqual(site.custom_field_data['number_field'], custom_field_data['number_field']) + self.assertEqual(site.custom_field_data['boolean_field'], custom_field_data['boolean_field']) + self.assertEqual(str(site.custom_field_data['date_field']), custom_field_data['date_field']) + self.assertEqual(site.custom_field_data['url_field'], custom_field_data['url_field']) + self.assertEqual(site.custom_field_data['choice_field'], custom_field_data['choice_field']) def test_update_single_object_with_values(self): """ Update an object with existing custom field values. Ensure that only the updated custom field values are modified. """ - site2_original_cfvs = { - cfv.field.name: cfv.value for cfv in self.sites[1].custom_field_values.all() - } + site = self.sites[1] + original_cfvs = {**site.custom_field_data} data = { 'custom_fields': { 'text_field': 'ABCD', @@ -423,55 +390,60 @@ def test_update_single_object_with_values(self): # Validate response data response_cf = response.data['custom_fields'] - data_cf = data['custom_fields'] - self.assertEqual(response_cf['text_field'], data_cf['text_field']) - self.assertEqual(response_cf['number_field'], data_cf['number_field']) - # TODO: Non-updated fields are missing from the response data - # self.assertEqual(response_cf['boolean_field'], site2_original_cfvs['boolean_field']) - # self.assertEqual(response_cf['date_field'], site2_original_cfvs['date_field']) - # self.assertEqual(response_cf['url_field'], site2_original_cfvs['url_field']) - # self.assertEqual(response_cf['choice_field']['label'], site2_original_cfvs['choice_field'].value) + self.assertEqual(response_cf['text_field'], data['custom_fields']['text_field']) + self.assertEqual(response_cf['number_field'], data['custom_fields']['number_field']) + self.assertEqual(response_cf['boolean_field'], original_cfvs['boolean_field']) + self.assertEqual(response_cf['date_field'], original_cfvs['date_field']) + self.assertEqual(response_cf['url_field'], original_cfvs['url_field']) + self.assertEqual(response_cf['choice_field'], original_cfvs['choice_field']) # Validate database data - site2_updated_cfvs = { - cfv.field.name: cfv.value for cfv in self.sites[1].custom_field_values.all() - } - self.assertEqual(site2_updated_cfvs['text_field'], data_cf['text_field']) - self.assertEqual(site2_updated_cfvs['number_field'], data_cf['number_field']) - self.assertEqual(site2_updated_cfvs['boolean_field'], site2_original_cfvs['boolean_field']) - self.assertEqual(site2_updated_cfvs['date_field'], site2_original_cfvs['date_field']) - self.assertEqual(site2_updated_cfvs['url_field'], site2_original_cfvs['url_field']) - self.assertEqual(site2_updated_cfvs['choice_field'], site2_original_cfvs['choice_field']) + site.refresh_from_db() + self.assertEqual(site.custom_field_data['text_field'], data['custom_fields']['text_field']) + self.assertEqual(site.custom_field_data['number_field'], data['custom_fields']['number_field']) + self.assertEqual(site.custom_field_data['boolean_field'], original_cfvs['boolean_field']) + self.assertEqual(site.custom_field_data['date_field'], original_cfvs['date_field']) + self.assertEqual(site.custom_field_data['url_field'], original_cfvs['url_field']) + self.assertEqual(site.custom_field_data['choice_field'], original_cfvs['choice_field']) + + def test_minimum_maximum_values_validation(self): + url = reverse('dcim-api:site-detail', kwargs={'pk': self.sites[1].pk}) + self.add_permissions('dcim.change_site') + self.cf_integer.validation_minimum = 10 + self.cf_integer.validation_maximum = 20 + self.cf_integer.save() -class CustomFieldChoiceAPITest(APITestCase): - def setUp(self): - super().setUp() + data = {'custom_fields': {'number_field': 9}} + response = self.client.patch(url, data, format='json', **self.header) + self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) - vm_content_type = ContentType.objects.get_for_model(VirtualMachine) + data = {'custom_fields': {'number_field': 21}} + response = self.client.patch(url, data, format='json', **self.header) + self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) - self.cf_1 = CustomField.objects.create(name="cf_1", type=CustomFieldTypeChoices.TYPE_SELECT) - self.cf_2 = CustomField.objects.create(name="cf_2", type=CustomFieldTypeChoices.TYPE_SELECT) + data = {'custom_fields': {'number_field': 15}} + response = self.client.patch(url, data, format='json', **self.header) + self.assertHttpStatus(response, status.HTTP_200_OK) - self.cf_choice_1 = CustomFieldChoice.objects.create(field=self.cf_1, value="cf_field_1", weight=100) - self.cf_choice_2 = CustomFieldChoice.objects.create(field=self.cf_1, value="cf_field_2", weight=50) - self.cf_choice_3 = CustomFieldChoice.objects.create(field=self.cf_2, value="cf_field_3", weight=10) + def test_regex_validation(self): + url = reverse('dcim-api:site-detail', kwargs={'pk': self.sites[1].pk}) + self.add_permissions('dcim.change_site') - def test_list_cfc(self): - url = reverse('extras-api:custom-field-choice-list') - response = self.client.get(url, **self.header) + self.cf_text.validation_regex = r'^[A-Z]{3}$' # Three uppercase letters + self.cf_text.save() - self.assertEqual(len(response.data), 2) - self.assertEqual(len(response.data[self.cf_1.name]), 2) - self.assertEqual(len(response.data[self.cf_2.name]), 1) + data = {'custom_fields': {'text_field': 'ABC123'}} + response = self.client.patch(url, data, format='json', **self.header) + self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) - self.assertTrue(self.cf_choice_1.value in response.data[self.cf_1.name]) - self.assertTrue(self.cf_choice_2.value in response.data[self.cf_1.name]) - self.assertTrue(self.cf_choice_3.value in response.data[self.cf_2.name]) + data = {'custom_fields': {'text_field': 'abc'}} + response = self.client.patch(url, data, format='json', **self.header) + self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) - self.assertEqual(self.cf_choice_1.pk, response.data[self.cf_1.name][self.cf_choice_1.value]) - self.assertEqual(self.cf_choice_2.pk, response.data[self.cf_1.name][self.cf_choice_2.value]) - self.assertEqual(self.cf_choice_3.pk, response.data[self.cf_2.name][self.cf_choice_3.value]) + data = {'custom_fields': {'text_field': 'ABC'}} + response = self.client.patch(url, data, format='json', **self.header) + self.assertHttpStatus(response, status.HTTP_200_OK) class CustomFieldImportTest(TestCase): @@ -489,17 +461,11 @@ def setUpTestData(cls): CustomField(name='boolean', type=CustomFieldTypeChoices.TYPE_BOOLEAN), CustomField(name='date', type=CustomFieldTypeChoices.TYPE_DATE), CustomField(name='url', type=CustomFieldTypeChoices.TYPE_URL), - CustomField(name='select', type=CustomFieldTypeChoices.TYPE_SELECT), + CustomField(name='select', type=CustomFieldTypeChoices.TYPE_SELECT, choices=['Choice A', 'Choice B', 'Choice C']), ) for cf in custom_fields: cf.save() - cf.obj_type.set([ContentType.objects.get_for_model(Site)]) - - CustomFieldChoice.objects.bulk_create(( - CustomFieldChoice(field=custom_fields[5], value='Choice A'), - CustomFieldChoice(field=custom_fields[5], value='Choice B'), - CustomFieldChoice(field=custom_fields[5], value='Choice C'), - )) + cf.content_types.set([ContentType.objects.get_for_model(Site)]) def test_import(self): """ @@ -517,34 +483,28 @@ def test_import(self): self.assertEqual(response.status_code, 200) # Validate data for site 1 - custom_field_values = { - cf.name: value for cf, value in Site.objects.get(name='Site 1').get_custom_fields().items() - } - self.assertEqual(len(custom_field_values), 6) - self.assertEqual(custom_field_values['text'], 'ABC') - self.assertEqual(custom_field_values['integer'], 123) - self.assertEqual(custom_field_values['boolean'], True) - self.assertEqual(custom_field_values['date'], date(2020, 1, 1)) - self.assertEqual(custom_field_values['url'], 'http://example.com/1') - self.assertEqual(custom_field_values['select'].value, 'Choice A') + site1 = Site.objects.get(name='Site 1') + self.assertEqual(len(site1.custom_field_data), 6) + self.assertEqual(site1.custom_field_data['text'], 'ABC') + self.assertEqual(site1.custom_field_data['integer'], 123) + self.assertEqual(site1.custom_field_data['boolean'], True) + self.assertEqual(site1.custom_field_data['date'], '2020-01-01') + self.assertEqual(site1.custom_field_data['url'], 'http://example.com/1') + self.assertEqual(site1.custom_field_data['select'], 'Choice A') # Validate data for site 2 - custom_field_values = { - cf.name: value for cf, value in Site.objects.get(name='Site 2').get_custom_fields().items() - } - self.assertEqual(len(custom_field_values), 6) - self.assertEqual(custom_field_values['text'], 'DEF') - self.assertEqual(custom_field_values['integer'], 456) - self.assertEqual(custom_field_values['boolean'], False) - self.assertEqual(custom_field_values['date'], date(2020, 1, 2)) - self.assertEqual(custom_field_values['url'], 'http://example.com/2') - self.assertEqual(custom_field_values['select'].value, 'Choice B') - - # No CustomFieldValues should be created for site 3 - obj_type = ContentType.objects.get_for_model(Site) + site2 = Site.objects.get(name='Site 2') + self.assertEqual(len(site2.custom_field_data), 6) + self.assertEqual(site2.custom_field_data['text'], 'DEF') + self.assertEqual(site2.custom_field_data['integer'], 456) + self.assertEqual(site2.custom_field_data['boolean'], False) + self.assertEqual(site2.custom_field_data['date'], '2020-01-02') + self.assertEqual(site2.custom_field_data['url'], 'http://example.com/2') + self.assertEqual(site2.custom_field_data['select'], 'Choice B') + + # No custom field data should be set for site 3 site3 = Site.objects.get(name='Site 3') - self.assertFalse(CustomFieldValue.objects.filter(obj_type=obj_type, obj_id=site3.pk).exists()) - self.assertEqual(CustomFieldValue.objects.count(), 12) # Sanity check + self.assertFalse(any(site3.custom_field_data.values())) def test_import_missing_required(self): """ @@ -575,3 +535,65 @@ def test_import_invalid_choice(self): form = SiteCSVForm(data=form_data) self.assertFalse(form.is_valid()) self.assertIn('cf_select', form.errors) + + +class CustomFieldModelTest(TestCase): + + @classmethod + def setUpTestData(cls): + cf1 = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='foo') + cf1.save() + cf1.content_types.set([ContentType.objects.get_for_model(Site)]) + + cf2 = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='bar') + cf2.save() + cf2.content_types.set([ContentType.objects.get_for_model(Rack)]) + + def test_cf_data(self): + """ + Check that custom field data is present on the instance immediately after being set and after being fetched + from the database. + """ + site = Site(name='Test Site', slug='test-site') + + # Check custom field data on new instance + site.cf['foo'] = 'abc' + self.assertEqual(site.cf['foo'], 'abc') + + # Check custom field data from database + site.save() + site = Site.objects.get(name='Test Site') + self.assertEqual(site.cf['foo'], 'abc') + + def test_invalid_data(self): + """ + Setting custom field data for a non-applicable (or non-existent) CustomField should raise a ValidationError. + """ + site = Site(name='Test Site', slug='test-site') + + # Set custom field data + site.cf['foo'] = 'abc' + site.cf['bar'] = 'def' + with self.assertRaises(ValidationError): + site.clean() + + del(site.cf['bar']) + site.clean() + + def test_missing_required_field(self): + """ + Check that a ValidationError is raised if any required custom fields are not present. + """ + cf3 = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='baz', required=True) + cf3.save() + cf3.content_types.set([ContentType.objects.get_for_model(Site)]) + + site = Site(name='Test Site', slug='test-site') + + # Set custom field data with a required field omitted + site.cf['foo'] = 'abc' + with self.assertRaises(ValidationError): + site.clean() + + site.cf['baz'] = 'def' + site.clean() diff --git a/netbox/extras/tests/test_filters.py b/netbox/extras/tests/test_filters.py index d6e077db46..7bcd83e816 100644 --- a/netbox/extras/tests/test_filters.py +++ b/netbox/extras/tests/test_filters.py @@ -1,50 +1,18 @@ +import uuid + +from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from django.test import TestCase from dcim.models import DeviceRole, Platform, Rack, Region, Site -from extras.choices import * +from extras.choices import ObjectChangeActionChoices from extras.filters import * -from extras.utils import FeatureQuery -from extras.models import ConfigContext, ExportTemplate, Graph, ImageAttachment, Tag +from extras.models import ConfigContext, ExportTemplate, ImageAttachment, ObjectChange, Tag +from ipam.models import IPAddress from tenancy.models import Tenant, TenantGroup from virtualization.models import Cluster, ClusterGroup, ClusterType -class GraphTestCase(TestCase): - queryset = Graph.objects.all() - filterset = GraphFilterSet - - @classmethod - def setUpTestData(cls): - - # Get the first three available types - content_types = ContentType.objects.filter(FeatureQuery('graphs').get_query())[:3] - - graphs = ( - Graph(name='Graph 1', type=content_types[0], template_language=TemplateLanguageChoices.LANGUAGE_DJANGO, source='http://example.com/1'), - Graph(name='Graph 2', type=content_types[1], template_language=TemplateLanguageChoices.LANGUAGE_JINJA2, source='http://example.com/2'), - Graph(name='Graph 3', type=content_types[2], template_language=TemplateLanguageChoices.LANGUAGE_JINJA2, source='http://example.com/3'), - ) - Graph.objects.bulk_create(graphs) - - def test_id(self): - params = {'id': self.queryset.values_list('pk', flat=True)[:2]} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - - def test_name(self): - params = {'name': ['Graph 1', 'Graph 2']} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - - def test_type(self): - content_type = ContentType.objects.filter(FeatureQuery('graphs').get_query()).first() - params = {'type': content_type.pk} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) - - def test_template_language(self): - params = {'template_language': TemplateLanguageChoices.LANGUAGE_JINJA2} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - - class ExportTemplateTestCase(TestCase): queryset = ExportTemplate.objects.all() filterset = ExportTemplateFilterSet @@ -55,9 +23,9 @@ def setUpTestData(cls): content_types = ContentType.objects.filter(model__in=['site', 'rack', 'device']) export_templates = ( - ExportTemplate(name='Export Template 1', content_type=content_types[0], template_language=TemplateLanguageChoices.LANGUAGE_DJANGO, template_code='TESTING'), - ExportTemplate(name='Export Template 2', content_type=content_types[1], template_language=TemplateLanguageChoices.LANGUAGE_JINJA2, template_code='TESTING'), - ExportTemplate(name='Export Template 3', content_type=content_types[2], template_language=TemplateLanguageChoices.LANGUAGE_JINJA2, template_code='TESTING'), + ExportTemplate(name='Export Template 1', content_type=content_types[0], template_code='TESTING'), + ExportTemplate(name='Export Template 2', content_type=content_types[1], template_code='TESTING'), + ExportTemplate(name='Export Template 3', content_type=content_types[2], template_code='TESTING'), ) ExportTemplate.objects.bulk_create(export_templates) @@ -73,10 +41,6 @@ def test_content_type(self): params = {'content_type': ContentType.objects.get(model='site').pk} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) - def test_template_language(self): - params = {'template_language': TemplateLanguageChoices.LANGUAGE_JINJA2} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - class ImageAttachmentTestCase(TestCase): queryset = ImageAttachment.objects.all() @@ -145,12 +109,12 @@ def test_name(self): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) def test_content_type(self): - params = {'content_type': ContentType.objects.get(app_label='dcim', model='site').pk} + params = {'content_type': 'dcim.site'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - def test_content_type_and_object_id(self): + def test_content_type_id_and_object_id(self): params = { - 'content_type': ContentType.objects.get(app_label='dcim', model='site').pk, + 'content_type_id': ContentType.objects.get(app_label='dcim', model='site').pk, 'object_id': [Site.objects.first().pk], } self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) @@ -339,4 +303,98 @@ def test_color(self): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) -# TODO: ObjectChangeFilter test +class ObjectChangeTestCase(TestCase): + queryset = ObjectChange.objects.all() + filterset = ObjectChangeFilterSet + + @classmethod + def setUpTestData(cls): + users = ( + User(username='user1'), + User(username='user2'), + User(username='user3'), + ) + User.objects.bulk_create(users) + + site = Site.objects.create(name='Test Site 1', slug='test-site-1') + ipaddress = IPAddress.objects.create(address='192.0.2.1/24') + + object_changes = ( + ObjectChange( + user=users[0], + user_name=users[0].username, + request_id=uuid.uuid4(), + action=ObjectChangeActionChoices.ACTION_CREATE, + changed_object=site, + object_repr=str(site), + object_data={'name': site.name, 'slug': site.slug} + ), + ObjectChange( + user=users[0], + user_name=users[0].username, + request_id=uuid.uuid4(), + action=ObjectChangeActionChoices.ACTION_UPDATE, + changed_object=site, + object_repr=str(site), + object_data={'name': site.name, 'slug': site.slug} + ), + ObjectChange( + user=users[1], + user_name=users[1].username, + request_id=uuid.uuid4(), + action=ObjectChangeActionChoices.ACTION_DELETE, + changed_object=site, + object_repr=str(site), + object_data={'name': site.name, 'slug': site.slug} + ), + ObjectChange( + user=users[1], + user_name=users[1].username, + request_id=uuid.uuid4(), + action=ObjectChangeActionChoices.ACTION_CREATE, + changed_object=ipaddress, + object_repr=str(ipaddress), + object_data={'address': ipaddress.address, 'status': ipaddress.status} + ), + ObjectChange( + user=users[2], + user_name=users[2].username, + request_id=uuid.uuid4(), + action=ObjectChangeActionChoices.ACTION_UPDATE, + changed_object=ipaddress, + object_repr=str(ipaddress), + object_data={'address': ipaddress.address, 'status': ipaddress.status} + ), + ObjectChange( + user=users[2], + user_name=users[2].username, + request_id=uuid.uuid4(), + action=ObjectChangeActionChoices.ACTION_DELETE, + changed_object=ipaddress, + object_repr=str(ipaddress), + object_data={'address': ipaddress.address, 'status': ipaddress.status} + ), + ) + ObjectChange.objects.bulk_create(object_changes) + + def test_id(self): + params = {'id': self.queryset.values_list('pk', flat=True)[:3]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_user(self): + params = {'user_id': User.objects.filter(username__in=['user1', 'user2']).values_list('pk', flat=True)} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'user': ['user1', 'user2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_user_name(self): + params = {'user_name': ['user1', 'user2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_changed_object_type(self): + params = {'changed_object_type': 'dcim.site'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_changed_object_type_id(self): + params = {'changed_object_type_id': ContentType.objects.get(app_label='dcim', model='site').pk} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) diff --git a/netbox/extras/tests/test_models.py b/netbox/extras/tests/test_models.py index d55f1ddd36..645fb86185 100644 --- a/netbox/extras/tests/test_models.py +++ b/netbox/extras/tests/test_models.py @@ -1,53 +1,11 @@ -from django.contrib.contenttypes.models import ContentType from django.test import TestCase from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Platform, Site, Region -from extras.choices import TemplateLanguageChoices -from extras.models import ConfigContext, Graph, Tag +from extras.models import ConfigContext, Tag from tenancy.models import Tenant, TenantGroup from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine -class GraphTest(TestCase): - - def setUp(self): - - self.site = Site(name='Site 1', slug='site-1') - - def test_graph_render_django(self): - - # Using the pluralize filter as a sanity check (it's only available in Django) - TEMPLATE_TEXT = "{{ obj.name|lower }} thing{{ 2|pluralize }}" - RENDERED_TEXT = "site 1 things" - - graph = Graph( - type=ContentType.objects.get(app_label='dcim', model='site'), - name='Graph 1', - template_language=TemplateLanguageChoices.LANGUAGE_DJANGO, - source=TEMPLATE_TEXT, - link=TEMPLATE_TEXT - ) - - self.assertEqual(graph.embed_url(self.site), RENDERED_TEXT) - self.assertEqual(graph.embed_link(self.site), RENDERED_TEXT) - - def test_graph_render_jinja2(self): - - TEMPLATE_TEXT = "{{ [obj.name, obj.slug]|join(',') }}" - RENDERED_TEXT = "Site 1,site-1" - - graph = Graph( - type=ContentType.objects.get(app_label='dcim', model='site'), - name='Graph 1', - template_language=TemplateLanguageChoices.LANGUAGE_JINJA2, - source=TEMPLATE_TEXT, - link=TEMPLATE_TEXT - ) - - self.assertEqual(graph.embed_url(self.site), RENDERED_TEXT) - self.assertEqual(graph.embed_link(self.site), RENDERED_TEXT) - - class TagTest(TestCase): def test_create_tag_unicode(self): diff --git a/netbox/extras/tests/test_webhooks.py b/netbox/extras/tests/test_webhooks.py index 8f741bbc2d..d8f30e26e0 100644 --- a/netbox/extras/tests/test_webhooks.py +++ b/netbox/extras/tests/test_webhooks.py @@ -39,7 +39,7 @@ def setUpTestData(cls): Webhook(name='Site Delete Webhook', type_delete=True, payload_url=DUMMY_URL, secret=DUMMY_SECRET), )) for webhook in webhooks: - webhook.obj_type.set([site_ct]) + webhook.content_types.set([site_ct]) def test_enqueue_webhook_create(self): # Create an object via the REST API diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 4aa2969dff..99295de1ae 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -1,7 +1,7 @@ from django import template from django.contrib import messages from django.contrib.contenttypes.models import ContentType -from django.db.models import Prefetch, Q +from django.db.models import Q from django.http import Http404, HttpResponseForbidden from django.shortcuts import get_object_or_404, redirect, render from django.views.generic import View @@ -9,16 +9,11 @@ from django_tables2 import RequestConfig from rq import Worker -from dcim.models import DeviceRole, Platform, Region, Site -from tenancy.models import Tenant, TenantGroup +from netbox.views import generic from utilities.forms import ConfirmationForm from utilities.paginator import EnhancedPaginator, get_paginate_count from utilities.utils import copy_safe_request, get_subquery, shallow_compare_dict -from utilities.views import ( - BulkDeleteView, BulkEditView, BulkImportView, ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView, - ContentTypePermissionRequiredMixin, -) -from virtualization.models import Cluster, ClusterGroup +from utilities.views import ContentTypePermissionRequiredMixin from . import filters, forms, tables from .choices import JobResultStatusChoices from .models import ConfigContext, ImageAttachment, ObjectChange, JobResult, Tag, TaggedItem @@ -30,7 +25,7 @@ # Tags # -class TagListView(ObjectListView): +class TagListView(generic.ObjectListView): queryset = Tag.objects.annotate( items=get_subquery(TaggedItem, 'tag') ) @@ -39,23 +34,23 @@ class TagListView(ObjectListView): table = tables.TagTable -class TagEditView(ObjectEditView): +class TagEditView(generic.ObjectEditView): queryset = Tag.objects.all() model_form = forms.TagForm template_name = 'extras/tag_edit.html' -class TagDeleteView(ObjectDeleteView): +class TagDeleteView(generic.ObjectDeleteView): queryset = Tag.objects.all() -class TagBulkImportView(BulkImportView): +class TagBulkImportView(generic.BulkImportView): queryset = Tag.objects.all() model_form = forms.TagCSVForm table = tables.TagTable -class TagBulkEditView(BulkEditView): +class TagBulkEditView(generic.BulkEditView): queryset = Tag.objects.annotate( items=get_subquery(TaggedItem, 'tag') ) @@ -63,7 +58,7 @@ class TagBulkEditView(BulkEditView): form = forms.TagBulkEditForm -class TagBulkDeleteView(BulkDeleteView): +class TagBulkDeleteView(generic.BulkDeleteView): queryset = Tag.objects.annotate( items=get_subquery(TaggedItem, 'tag') ) @@ -74,7 +69,7 @@ class TagBulkDeleteView(BulkDeleteView): # Config contexts # -class ConfigContextListView(ObjectListView): +class ConfigContextListView(generic.ObjectListView): queryset = ConfigContext.objects.all() filterset = filters.ConfigContextFilterSet filterset_form = forms.ConfigContextFilterForm @@ -82,24 +77,10 @@ class ConfigContextListView(ObjectListView): action_buttons = ('add',) -class ConfigContextView(ObjectView): +class ConfigContextView(generic.ObjectView): queryset = ConfigContext.objects.all() - def get(self, request, pk): - # Extend queryset to prefetch related objects - self.queryset = self.queryset.prefetch_related( - Prefetch('regions', queryset=Region.objects.restrict(request.user)), - Prefetch('sites', queryset=Site.objects.restrict(request.user)), - Prefetch('roles', queryset=DeviceRole.objects.restrict(request.user)), - Prefetch('platforms', queryset=Platform.objects.restrict(request.user)), - Prefetch('clusters', queryset=Cluster.objects.restrict(request.user)), - Prefetch('cluster_groups', queryset=ClusterGroup.objects.restrict(request.user)), - Prefetch('tenants', queryset=Tenant.objects.restrict(request.user)), - Prefetch('tenant_groups', queryset=TenantGroup.objects.restrict(request.user)), - ) - - configcontext = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Determine user's preferred output format if request.GET.get('format') in ['json', 'yaml']: format = request.GET.get('format') @@ -110,42 +91,39 @@ def get(self, request, pk): else: format = 'json' - return render(request, 'extras/configcontext.html', { - 'configcontext': configcontext, + return { 'format': format, - }) + } -class ConfigContextEditView(ObjectEditView): +class ConfigContextEditView(generic.ObjectEditView): queryset = ConfigContext.objects.all() model_form = forms.ConfigContextForm template_name = 'extras/configcontext_edit.html' -class ConfigContextBulkEditView(BulkEditView): +class ConfigContextBulkEditView(generic.BulkEditView): queryset = ConfigContext.objects.all() filterset = filters.ConfigContextFilterSet table = tables.ConfigContextTable form = forms.ConfigContextBulkEditForm -class ConfigContextDeleteView(ObjectDeleteView): +class ConfigContextDeleteView(generic.ObjectDeleteView): queryset = ConfigContext.objects.all() -class ConfigContextBulkDeleteView(BulkDeleteView): +class ConfigContextBulkDeleteView(generic.BulkDeleteView): queryset = ConfigContext.objects.all() table = tables.ConfigContextTable -class ObjectConfigContextView(ObjectView): +class ObjectConfigContextView(generic.ObjectView): base_template = None + template_name = 'extras/object_configcontext.html' - def get(self, request, pk): - - obj = get_object_or_404(self.queryset, pk=pk) - source_contexts = ConfigContext.objects.restrict(request.user, 'view').get_for_object(obj) - model_name = self.queryset.model._meta.model_name + def get_extra_context(self, request, instance): + source_contexts = ConfigContext.objects.restrict(request.user, 'view').get_for_object(instance) # Determine user's preferred output format if request.GET.get('format') in ['json', 'yaml']: @@ -157,23 +135,21 @@ def get(self, request, pk): else: format = 'json' - return render(request, 'extras/object_configcontext.html', { - model_name: obj, - 'obj': obj, - 'rendered_context': obj.get_config_context(), + return { + 'rendered_context': instance.get_config_context(), 'source_contexts': source_contexts, 'format': format, 'base_template': self.base_template, 'active_tab': 'config-context', - }) + } # # Change logging # -class ObjectChangeListView(ObjectListView): - queryset = ObjectChange.objects.prefetch_related('user', 'changed_object_type') +class ObjectChangeListView(generic.ObjectListView): + queryset = ObjectChange.objects.all() filterset = filters.ObjectChangeFilterSet filterset_form = forms.ObjectChangeFilterForm table = tables.ObjectChangeTable @@ -181,17 +157,14 @@ class ObjectChangeListView(ObjectListView): action_buttons = ('export',) -class ObjectChangeView(ObjectView): +class ObjectChangeView(generic.ObjectView): queryset = ObjectChange.objects.all() - def get(self, request, pk): - - objectchange = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): related_changes = ObjectChange.objects.restrict(request.user, 'view').filter( - request_id=objectchange.request_id + request_id=instance.request_id ).exclude( - pk=objectchange.pk + pk=instance.pk ) related_changes_table = tables.ObjectChangeTable( data=related_changes[:50], @@ -199,39 +172,41 @@ def get(self, request, pk): ) objectchanges = ObjectChange.objects.restrict(request.user, 'view').filter( - changed_object_type=objectchange.changed_object_type, - changed_object_id=objectchange.changed_object_id, + changed_object_type=instance.changed_object_type, + changed_object_id=instance.changed_object_id, ) - next_change = objectchanges.filter(time__gt=objectchange.time).order_by('time').first() - prev_change = objectchanges.filter(time__lt=objectchange.time).order_by('-time').first() + next_change = objectchanges.filter(time__gt=instance.time).order_by('time').first() + prev_change = objectchanges.filter(time__lt=instance.time).order_by('-time').first() if prev_change: diff_added = shallow_compare_dict( prev_change.object_data, - objectchange.object_data, + instance.object_data, exclude=['last_updated'], ) diff_removed = {x: prev_change.object_data.get(x) for x in diff_added} else: # No previous change; this is the initial change that added the object - diff_added = diff_removed = objectchange.object_data + diff_added = diff_removed = instance.object_data - return render(request, 'extras/objectchange.html', { - 'objectchange': objectchange, + return { 'diff_added': diff_added, 'diff_removed': diff_removed, 'next_change': next_change, 'prev_change': prev_change, 'related_changes_table': related_changes_table, 'related_changes_count': related_changes.count() - }) + } class ObjectChangeLogView(View): """ Present a history of changes made to a particular object. + + base_template: The name of the template to extend. If not provided, "/.html" will be used. """ + base_template = None def get(self, request, model, **kwargs): @@ -261,20 +236,20 @@ def get(self, request, model, **kwargs): } RequestConfig(request, paginate).configure(objectchanges_table) - # Check whether a header template exists for this model - base_template = '{}/{}.html'.format(model._meta.app_label, model._meta.model_name) - try: - template.loader.get_template(base_template) - object_var = model._meta.model_name - except template.TemplateDoesNotExist: - base_template = 'base.html' - object_var = 'obj' + # Default to using "/.html" as the template, if it exists. Otherwise, + # fall back to using base.html. + if self.base_template is None: + self.base_template = f"{model._meta.app_label}/{model._meta.model_name}.html" + # TODO: This can be removed once an object view has been established for every model. + try: + template.loader.get_template(self.base_template) + except template.TemplateDoesNotExist: + self.base_template = 'base.html' return render(request, 'extras/object_changelog.html', { - object_var: obj, - 'instance': obj, # We'll eventually standardize on 'instance` for the object variable name + 'object': obj, 'table': objectchanges_table, - 'base_template': base_template, + 'base_template': self.base_template, 'active_tab': 'changelog', }) @@ -283,7 +258,7 @@ def get(self, request, model, **kwargs): # Image attachments # -class ImageAttachmentEditView(ObjectEditView): +class ImageAttachmentEditView(generic.ObjectEditView): queryset = ImageAttachment.objects.all() model_form = forms.ImageAttachmentForm @@ -298,7 +273,7 @@ def get_return_url(self, request, imageattachment): return imageattachment.parent.get_absolute_url() -class ImageAttachmentDeleteView(ObjectDeleteView): +class ImageAttachmentDeleteView(generic.ObjectDeleteView): queryset = ImageAttachment.objects.all() def get_return_url(self, request, imageattachment): diff --git a/netbox/extras/webhooks.py b/netbox/extras/webhooks.py index 9166c463a5..f062e5752e 100644 --- a/netbox/extras/webhooks.py +++ b/netbox/extras/webhooks.py @@ -35,13 +35,13 @@ def enqueue_webhooks(instance, user, request_id, action): return # Retrieve any applicable Webhooks - obj_type = ContentType.objects.get_for_model(instance) + content_type = ContentType.objects.get_for_model(instance) action_flag = { ObjectChangeActionChoices.ACTION_CREATE: 'type_create', ObjectChangeActionChoices.ACTION_UPDATE: 'type_update', ObjectChangeActionChoices.ACTION_DELETE: 'type_delete', }[action] - webhooks = Webhook.objects.filter(obj_type=obj_type, enabled=True, **{action_flag: True}) + webhooks = Webhook.objects.filter(content_types=content_type, enabled=True, **{action_flag: True}) if webhooks.exists(): # Get the Model's API serializer class and serialize the object diff --git a/netbox/ipam/api/nested_serializers.py b/netbox/ipam/api/nested_serializers.py index 18f42186f5..660db2b22d 100644 --- a/netbox/ipam/api/nested_serializers.py +++ b/netbox/ipam/api/nested_serializers.py @@ -1,7 +1,7 @@ from rest_framework import serializers from ipam import models -from utilities.api import WritableNestedSerializer +from netbox.api import WritableNestedSerializer __all__ = [ 'NestedAggregateSerializer', @@ -9,6 +9,7 @@ 'NestedPrefixSerializer', 'NestedRIRSerializer', 'NestedRoleSerializer', + 'NestedRouteTargetSerializer', 'NestedServiceSerializer', 'NestedVLANGroupSerializer', 'NestedVLANSerializer', @@ -29,6 +30,18 @@ class Meta: fields = ['id', 'url', 'name', 'rd', 'display_name', 'prefix_count'] +# +# Route targets +# + +class NestedRouteTargetSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='ipam-api:routetarget-detail') + + class Meta: + model = models.RouteTarget + fields = ['id', 'url', 'name'] + + # # RIRs/aggregates # @@ -117,4 +130,4 @@ class NestedServiceSerializer(WritableNestedSerializer): class Meta: model = models.Service - fields = ['id', 'url', 'name', 'protocol', 'port'] + fields = ['id', 'url', 'name', 'protocol', 'ports'] diff --git a/netbox/ipam/api/serializers.py b/netbox/ipam/api/serializers.py index ea84191f13..7552ae0d21 100644 --- a/netbox/ipam/api/serializers.py +++ b/netbox/ipam/api/serializers.py @@ -3,21 +3,17 @@ from django.contrib.contenttypes.models import ContentType from drf_yasg.utils import swagger_serializer_method from rest_framework import serializers -from rest_framework.reverse import reverse from rest_framework.validators import UniqueTogetherValidator from dcim.api.nested_serializers import NestedDeviceSerializer, NestedSiteSerializer -from dcim.models import Interface from extras.api.customfields import CustomFieldModelSerializer from extras.api.serializers import TaggedObjectSerializer from ipam.choices import * from ipam.constants import IPADDRESS_ASSIGNMENT_MODELS -from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF +from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, RouteTarget, Service, VLAN, VLANGroup, VRF +from netbox.api import ChoiceField, ContentTypeField, SerializedPKRelatedField, ValidatedModelSerializer from tenancy.api.nested_serializers import NestedTenantSerializer -from utilities.api import ( - ChoiceField, ContentTypeField, SerializedPKRelatedField, ValidatedModelSerializer, WritableNestedSerializer, - get_serializer_for_model, -) +from utilities.api import get_serializer_for_model from virtualization.api.nested_serializers import NestedVirtualMachineSerializer from .nested_serializers import * @@ -29,14 +25,31 @@ class VRFSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vrf-detail') tenant = NestedTenantSerializer(required=False, allow_null=True) + import_targets = NestedRouteTargetSerializer(required=False, allow_null=True, many=True) + export_targets = NestedRouteTargetSerializer(required=False, allow_null=True, many=True) ipaddress_count = serializers.IntegerField(read_only=True) prefix_count = serializers.IntegerField(read_only=True) class Meta: model = VRF fields = [ - 'id', 'url', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'tags', 'display_name', - 'custom_fields', 'created', 'last_updated', 'ipaddress_count', 'prefix_count', + 'id', 'url', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'import_targets', 'export_targets', + 'tags', 'display_name', 'custom_fields', 'created', 'last_updated', 'ipaddress_count', 'prefix_count', + ] + + +# +# Route targets +# + +class RouteTargetSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): + url = serializers.HyperlinkedIdentityField(view_name='ipam-api:routetarget-detail') + tenant = NestedTenantSerializer(required=False, allow_null=True) + + class Meta: + model = RouteTarget + fields = [ + 'id', 'url', 'name', 'tenant', 'description', 'tags', 'custom_fields', 'created', 'last_updated', ] @@ -57,11 +70,12 @@ class AggregateSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='ipam-api:aggregate-detail') family = ChoiceField(choices=IPAddressFamilyChoices, read_only=True) rir = NestedRIRSerializer() + tenant = NestedTenantSerializer(required=False, allow_null=True) class Meta: model = Aggregate fields = [ - 'id', 'url', 'family', 'prefix', 'rir', 'date_added', 'description', 'tags', 'custom_fields', 'created', + 'id', 'url', 'family', 'prefix', 'rir', 'tenant', 'date_added', 'description', 'tags', 'custom_fields', 'created', 'last_updated', ] read_only_fields = ['family'] @@ -283,6 +297,6 @@ class ServiceSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): class Meta: model = Service fields = [ - 'id', 'url', 'device', 'virtual_machine', 'name', 'port', 'protocol', 'ipaddresses', 'description', 'tags', + 'id', 'url', 'device', 'virtual_machine', 'name', 'ports', 'protocol', 'ipaddresses', 'description', 'tags', 'custom_fields', 'created', 'last_updated', ] diff --git a/netbox/ipam/api/urls.py b/netbox/ipam/api/urls.py index e297d64512..13a1bc7700 100644 --- a/netbox/ipam/api/urls.py +++ b/netbox/ipam/api/urls.py @@ -1,4 +1,4 @@ -from utilities.api import OrderedDefaultRouter +from netbox.api import OrderedDefaultRouter from . import views @@ -8,6 +8,9 @@ # VRFs router.register('vrfs', views.VRFViewSet) +# Route targets +router.register('route-targets', views.RouteTargetViewSet) + # RIRs router.register('rirs', views.RIRViewSet) diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index eab1af929e..9d09bbe03c 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -9,8 +9,8 @@ from extras.api.views import CustomFieldModelViewSet from ipam import filters -from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF -from utilities.api import ModelViewSet +from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, RouteTarget, Service, VLAN, VLANGroup, VRF +from netbox.api.views import ModelViewSet from utilities.constants import ADVISORY_LOCK_KEYS from utilities.utils import get_subquery from . import serializers @@ -29,7 +29,9 @@ def get_view_name(self): # class VRFViewSet(CustomFieldModelViewSet): - queryset = VRF.objects.prefetch_related('tenant').prefetch_related('tags').annotate( + queryset = VRF.objects.prefetch_related('tenant').prefetch_related( + 'import_targets', 'export_targets', 'tags' + ).annotate( ipaddress_count=get_subquery(IPAddress, 'vrf'), prefix_count=get_subquery(Prefix, 'vrf') ) @@ -37,6 +39,16 @@ class VRFViewSet(CustomFieldModelViewSet): filterset_class = filters.VRFFilterSet +# +# Route targets +# + +class RouteTargetViewSet(CustomFieldModelViewSet): + queryset = RouteTarget.objects.prefetch_related('tenant').prefetch_related('tags') + serializer_class = serializers.RouteTargetSerializer + filterset_class = filters.RouteTargetFilterSet + + # # RIRs # diff --git a/netbox/ipam/choices.py b/netbox/ipam/choices.py index f3ff19ddc2..5b7dd16bd8 100644 --- a/netbox/ipam/choices.py +++ b/netbox/ipam/choices.py @@ -30,6 +30,13 @@ class PrefixStatusChoices(ChoiceSet): (STATUS_DEPRECATED, 'Deprecated'), ) + CSS_CLASSES = { + STATUS_CONTAINER: 'default', + STATUS_ACTIVE: 'primary', + STATUS_RESERVED: 'info', + STATUS_DEPRECATED: 'danger', + } + # # IPAddresses @@ -51,6 +58,14 @@ class IPAddressStatusChoices(ChoiceSet): (STATUS_SLAAC, 'SLAAC'), ) + CSS_CLASSES = { + STATUS_ACTIVE: 'primary', + STATUS_RESERVED: 'info', + STATUS_DEPRECATED: 'danger', + STATUS_DHCP: 'success', + STATUS_SLAAC: 'success', + } + class IPAddressRoleChoices(ChoiceSet): @@ -74,6 +89,17 @@ class IPAddressRoleChoices(ChoiceSet): (ROLE_CARP, 'CARP'), ) + CSS_CLASSES = { + ROLE_LOOPBACK: 'default', + ROLE_SECONDARY: 'primary', + ROLE_ANYCAST: 'warning', + ROLE_VIP: 'success', + ROLE_VRRP: 'success', + ROLE_HSRP: 'success', + ROLE_GLBP: 'success', + ROLE_CARP: 'success', + } + # # VLANs @@ -91,6 +117,12 @@ class VLANStatusChoices(ChoiceSet): (STATUS_DEPRECATED, 'Deprecated'), ) + CSS_CLASSES = { + STATUS_ACTIVE: 'primary', + STATUS_RESERVED: 'info', + STATUS_DEPRECATED: 'danger', + } + # # Services diff --git a/netbox/ipam/constants.py b/netbox/ipam/constants.py index 1ad355aec5..e8825ad18e 100644 --- a/netbox/ipam/constants.py +++ b/netbox/ipam/constants.py @@ -16,6 +16,7 @@ # * Type 1 (32-bit IPv4 address : 16-bit integer) # * Type 2 (32-bit AS number : 16-bit integer) # 21 characters are sufficient to convey the longest possible string value (255.255.255.255:65535) +# Also used for RouteTargets VRF_RD_MAX_LENGTH = 21 diff --git a/netbox/ipam/filters.py b/netbox/ipam/filters.py index 79fc053341..176d77a88e 100644 --- a/netbox/ipam/filters.py +++ b/netbox/ipam/filters.py @@ -5,15 +5,15 @@ from netaddr.core import AddrFormatError from dcim.models import Device, Interface, Region, Site -from extras.filters import CustomFieldFilterSet, CreatedUpdatedFilterSet +from extras.filters import CustomFieldModelFilterSet, CreatedUpdatedFilterSet from tenancy.filters import TenancyFilterSet from utilities.filters import ( - BaseFilterSet, MultiValueCharFilter, MultiValueNumberFilter, NameSlugSearchFilterSet, TagFilter, + BaseFilterSet, MultiValueCharFilter, MultiValueNumberFilter, NameSlugSearchFilterSet, NumericArrayFilter, TagFilter, TreeNodeMultipleChoiceFilter, ) from virtualization.models import VirtualMachine, VMInterface from .choices import * -from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF +from .models import Aggregate, IPAddress, Prefix, RIR, Role, RouteTarget, Service, VLAN, VLANGroup, VRF __all__ = ( @@ -22,6 +22,7 @@ 'PrefixFilterSet', 'RIRFilterSet', 'RoleFilterSet', + 'RouteTargetFilterSet', 'ServiceFilterSet', 'VLANFilterSet', 'VLANGroupFilterSet', @@ -29,11 +30,33 @@ ) -class VRFFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet): +class VRFFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): q = django_filters.CharFilter( method='search', label='Search', ) + import_target_id = django_filters.ModelMultipleChoiceFilter( + field_name='import_targets', + queryset=RouteTarget.objects.all(), + label='Import target', + ) + import_target = django_filters.ModelMultipleChoiceFilter( + field_name='import_targets__name', + queryset=RouteTarget.objects.all(), + to_field_name='name', + label='Import target (name)', + ) + export_target_id = django_filters.ModelMultipleChoiceFilter( + field_name='export_targets', + queryset=RouteTarget.objects.all(), + label='Export target', + ) + export_target = django_filters.ModelMultipleChoiceFilter( + field_name='export_targets__name', + queryset=RouteTarget.objects.all(), + to_field_name='name', + label='Export target (name)', + ) tag = TagFilter() def search(self, queryset, name, value): @@ -50,6 +73,48 @@ class Meta: fields = ['id', 'name', 'rd', 'enforce_unique'] +class RouteTargetFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): + q = django_filters.CharFilter( + method='search', + label='Search', + ) + importing_vrf_id = django_filters.ModelMultipleChoiceFilter( + field_name='importing_vrfs', + queryset=VRF.objects.all(), + label='Importing VRF', + ) + importing_vrf = django_filters.ModelMultipleChoiceFilter( + field_name='importing_vrfs__rd', + queryset=VRF.objects.all(), + to_field_name='rd', + label='Import VRF (RD)', + ) + exporting_vrf_id = django_filters.ModelMultipleChoiceFilter( + field_name='exporting_vrfs', + queryset=VRF.objects.all(), + label='Exporting VRF', + ) + exporting_vrf = django_filters.ModelMultipleChoiceFilter( + field_name='exporting_vrfs__rd', + queryset=VRF.objects.all(), + to_field_name='rd', + label='Export VRF (RD)', + ) + tag = TagFilter() + + def search(self, queryset, name, value): + if not value.strip(): + return queryset + return queryset.filter( + Q(name__icontains=value) | + Q(description__icontains=value) + ) + + class Meta: + model = RouteTarget + fields = ['id', 'name'] + + class RIRFilterSet(BaseFilterSet, NameSlugSearchFilterSet): class Meta: @@ -57,7 +122,7 @@ class Meta: fields = ['id', 'name', 'slug', 'is_private', 'description'] -class AggregateFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet): +class AggregateFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): q = django_filters.CharFilter( method='search', label='Search', @@ -118,7 +183,7 @@ class Meta: fields = ['id', 'name', 'slug'] -class PrefixFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet): +class PrefixFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): q = django_filters.CharFilter( method='search', label='Search', @@ -165,6 +230,17 @@ class PrefixFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, Cre to_field_name='rd', label='VRF (RD)', ) + present_in_vrf_id = django_filters.ModelChoiceFilter( + queryset=VRF.objects.all(), + method='filter_present_in_vrf', + label='VRF' + ) + present_in_vrf = django_filters.ModelChoiceFilter( + queryset=VRF.objects.all(), + method='filter_present_in_vrf', + to_field_name='rd', + label='VRF (RD)', + ) region_id = TreeNodeMultipleChoiceFilter( queryset=Region.objects.all(), field_name='site__region', @@ -270,8 +346,16 @@ def search_contains(self, queryset, name, value): except (AddrFormatError, ValueError): return queryset.none() + def filter_present_in_vrf(self, queryset, name, vrf): + if vrf is None: + return queryset.none + return queryset.filter( + Q(vrf=vrf) | + Q(vrf__export_targets__in=vrf.import_targets.all()) + ) -class IPAddressFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet): + +class IPAddressFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): q = django_filters.CharFilter( method='search', label='Search', @@ -302,6 +386,17 @@ class IPAddressFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, to_field_name='rd', label='VRF (RD)', ) + present_in_vrf_id = django_filters.ModelChoiceFilter( + queryset=VRF.objects.all(), + method='filter_present_in_vrf', + label='VRF' + ) + present_in_vrf = django_filters.ModelChoiceFilter( + queryset=VRF.objects.all(), + method='filter_present_in_vrf', + to_field_name='rd', + label='VRF (RD)', + ) device = MultiValueCharFilter( method='filter_device', field_name='name', @@ -392,6 +487,14 @@ def filter_mask_length(self, queryset, name, value): return queryset return queryset.filter(address__net_mask_length=value) + def filter_present_in_vrf(self, queryset, name, vrf): + if vrf is None: + return queryset.none + return queryset.filter( + Q(vrf=vrf) | + Q(vrf__export_targets__in=vrf.import_targets.all()) + ) + def filter_device(self, queryset, name, value): devices = Device.objects.filter(**{'{}__in'.format(name): value}) if not devices.exists(): @@ -448,7 +551,7 @@ class Meta: fields = ['id', 'name', 'slug', 'description'] -class VLANFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet): +class VLANFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): q = django_filters.CharFilter( method='search', label='Search', @@ -542,11 +645,15 @@ class ServiceFilterSet(BaseFilterSet, CreatedUpdatedFilterSet): to_field_name='name', label='Virtual machine (name)', ) + port = NumericArrayFilter( + field_name='ports', + lookup_expr='contains' + ) tag = TagFilter() class Meta: model = Service - fields = ['id', 'name', 'protocol', 'port'] + fields = ['id', 'name', 'protocol'] def search(self, queryset, name, value): if not value.strip(): diff --git a/netbox/ipam/forms.py b/netbox/ipam/forms.py index 641f72a950..29a6d295ea 100644 --- a/netbox/ipam/forms.py +++ b/netbox/ipam/forms.py @@ -1,5 +1,4 @@ from django import forms -from django.core.validators import MaxValueValidator, MinValueValidator from dcim.models import Device, Interface, Rack, Region, Site from extras.forms import ( @@ -10,13 +9,13 @@ from tenancy.models import Tenant from utilities.forms import ( add_blank_choice, BootstrapMixin, BulkEditNullBooleanSelect, CSVChoiceField, CSVModelChoiceField, CSVModelForm, - DatePicker, DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableIPAddressField, ReturnURLForm, - SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, + DatePicker, DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableIPAddressField, NumericArrayField, + ReturnURLForm, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, ) from virtualization.models import Cluster, VirtualMachine, VMInterface from .choices import * from .constants import * -from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF +from .models import Aggregate, IPAddress, Prefix, RIR, Role, RouteTarget, Service, VLAN, VLANGroup, VRF PREFIX_MASK_LENGTH_CHOICES = add_blank_choice([ (i, i) for i in range(PREFIX_LENGTH_MIN, PREFIX_LENGTH_MAX + 1) @@ -32,6 +31,14 @@ # class VRFForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): + import_targets = DynamicModelMultipleChoiceField( + queryset=RouteTarget.objects.all(), + required=False + ) + export_targets = DynamicModelMultipleChoiceField( + queryset=RouteTarget.objects.all(), + required=False + ) tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False @@ -40,7 +47,8 @@ class VRFForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): class Meta: model = VRF fields = [ - 'name', 'rd', 'enforce_unique', 'description', 'tenant_group', 'tenant', 'tags', + 'name', 'rd', 'enforce_unique', 'description', 'import_targets', 'export_targets', 'tenant_group', 'tenant', + 'tags', ] labels = { 'rd': "RD", @@ -90,11 +98,91 @@ class Meta: class VRFFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = VRF - field_order = ['q', 'tenant_group', 'tenant'] + field_order = ['q', 'import_target', 'export_target', 'tenant_group', 'tenant'] q = forms.CharField( required=False, label='Search' ) + import_target = DynamicModelMultipleChoiceField( + queryset=RouteTarget.objects.all(), + to_field_name='name', + required=False + ) + export_target = DynamicModelMultipleChoiceField( + queryset=RouteTarget.objects.all(), + to_field_name='name', + required=False + ) + tag = TagFilterField(model) + + +# +# Route targets +# + +class RouteTargetForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): + tags = DynamicModelMultipleChoiceField( + queryset=Tag.objects.all(), + required=False + ) + + class Meta: + model = RouteTarget + fields = [ + 'name', 'description', 'tenant_group', 'tenant', 'tags', + ] + + +class RouteTargetCSVForm(CustomFieldModelCSVForm): + tenant = CSVModelChoiceField( + queryset=Tenant.objects.all(), + required=False, + to_field_name='name', + help_text='Assigned tenant' + ) + + class Meta: + model = RouteTarget + fields = RouteTarget.csv_headers + + +class RouteTargetBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm): + pk = forms.ModelMultipleChoiceField( + queryset=RouteTarget.objects.all(), + widget=forms.MultipleHiddenInput() + ) + tenant = DynamicModelChoiceField( + queryset=Tenant.objects.all(), + required=False + ) + description = forms.CharField( + max_length=200, + required=False + ) + + class Meta: + nullable_fields = [ + 'tenant', 'description', + ] + + +class RouteTargetFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): + model = RouteTarget + field_order = ['q', 'name', 'tenant_group', 'tenant', 'importing_vrfs', 'exporting_vrfs'] + q = forms.CharField( + required=False, + label='Search' + ) + importing_vrf_id = DynamicModelMultipleChoiceField( + queryset=VRF.objects.all(), + required=False, + label='Imported by VRF' + ) + exporting_vrf_id = DynamicModelMultipleChoiceField( + queryset=VRF.objects.all(), + required=False, + label='Exported by VRF' + ) tag = TagFilterField(model) @@ -137,9 +225,10 @@ class RIRFilterForm(BootstrapMixin, forms.Form): # Aggregates # -class AggregateForm(BootstrapMixin, CustomFieldModelForm): +class AggregateForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): rir = DynamicModelChoiceField( - queryset=RIR.objects.all() + queryset=RIR.objects.all(), + label='RIR' ) tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -149,7 +238,7 @@ class AggregateForm(BootstrapMixin, CustomFieldModelForm): class Meta: model = Aggregate fields = [ - 'prefix', 'rir', 'date_added', 'description', 'tags', + 'prefix', 'rir', 'date_added', 'description', 'tenant_group', 'tenant', 'tags', ] help_texts = { 'prefix': "IPv4 or IPv6 network", @@ -166,6 +255,12 @@ class AggregateCSVForm(CustomFieldModelCSVForm): to_field_name='name', help_text='Assigned RIR' ) + tenant = CSVModelChoiceField( + queryset=Tenant.objects.all(), + required=False, + to_field_name='name', + help_text='Assigned tenant' + ) class Meta: model = Aggregate @@ -182,6 +277,10 @@ class AggregateBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd required=False, label='RIR' ) + tenant = DynamicModelChoiceField( + queryset=Tenant.objects.all(), + required=False + ) date_added = forms.DateField( required=False ) @@ -199,7 +298,7 @@ class Meta: } -class AggregateFilterForm(BootstrapMixin, CustomFieldFilterForm): +class AggregateFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = Aggregate q = forms.CharField( required=False, @@ -434,8 +533,8 @@ class Meta: class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = Prefix field_order = [ - 'q', 'within_include', 'family', 'mask_length', 'vrf_id', 'status', 'region', 'site', 'role', 'tenant_group', - 'tenant', 'is_pool', 'expand', + 'q', 'within_include', 'family', 'mask_length', 'vrf_id', 'present_in_vrf_id', 'status', 'region', 'site', + 'role', 'tenant_group', 'tenant', 'is_pool', 'expand', ] mask_length__lte = forms.IntegerField( widget=forms.HiddenInput() @@ -468,9 +567,14 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm) vrf_id = DynamicModelMultipleChoiceField( queryset=VRF.objects.all(), required=False, - label='VRF', + label='Assigned VRF', null_option='Global' ) + present_in_vrf_id = DynamicModelChoiceField( + queryset=VRF.objects.all(), + required=False, + label='Present in VRF' + ) status = forms.MultipleChoiceField( choices=PrefixStatusChoices, required=False, @@ -752,6 +856,7 @@ class IPAddressCSVForm(CustomFieldModelCSVForm): ) status = CSVChoiceField( choices=IPAddressStatusChoices, + required=False, help_text='Operational status' ) role = CSVChoiceField( @@ -784,7 +889,10 @@ class IPAddressCSVForm(CustomFieldModelCSVForm): class Meta: model = IPAddress - fields = IPAddress.csv_headers + fields = [ + 'address', 'vrf', 'tenant', 'status', 'role', 'device', 'virtual_machine', 'interface', 'is_primary', + 'dns_name', 'description', + ] def __init__(self, data=None, *args, **kwargs): super().__init__(data, *args, **kwargs) @@ -895,8 +1003,8 @@ class IPAddressAssignForm(BootstrapMixin, forms.Form): class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = IPAddress field_order = [ - 'q', 'parent', 'family', 'mask_length', 'vrf_id', 'status', 'role', 'assigned_to_interface', 'tenant_group', - 'tenant', + 'q', 'parent', 'family', 'mask_length', 'vrf_id', 'present_in_vrf_id', 'status', 'role', + 'assigned_to_interface', 'tenant_group', 'tenant', ] q = forms.CharField( required=False, @@ -926,9 +1034,14 @@ class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterFo vrf_id = DynamicModelMultipleChoiceField( queryset=VRF.objects.all(), required=False, - label='VRF', + label='Assigned VRF', null_option='Global' ) + present_in_vrf_id = DynamicModelChoiceField( + queryset=VRF.objects.all(), + required=False, + label='Present in VRF' + ) status = forms.MultipleChoiceField( choices=IPAddressStatusChoices, required=False, @@ -1207,9 +1320,12 @@ class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): # class ServiceForm(BootstrapMixin, CustomFieldModelForm): - port = forms.IntegerField( - min_value=SERVICE_PORT_MIN, - max_value=SERVICE_PORT_MAX + ports = NumericArrayField( + base_field=forms.IntegerField( + min_value=SERVICE_PORT_MIN, + max_value=SERVICE_PORT_MAX + ), + help_text="Comma-separated list of one or more port numbers. A range may be specified using a hyphen." ) tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), @@ -1219,7 +1335,7 @@ class ServiceForm(BootstrapMixin, CustomFieldModelForm): class Meta: model = Service fields = [ - 'name', 'protocol', 'port', 'ipaddresses', 'description', 'tags', + 'name', 'protocol', 'ports', 'ipaddresses', 'description', 'tags', ] help_texts = { 'ipaddresses': "IP address assignment is optional. If no IPs are selected, the service is assumed to be " @@ -1296,11 +1412,11 @@ class ServiceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit required=False, widget=StaticSelect2() ) - port = forms.IntegerField( - validators=[ - MinValueValidator(1), - MaxValueValidator(65535), - ], + ports = NumericArrayField( + base_field=forms.IntegerField( + min_value=SERVICE_PORT_MIN, + max_value=SERVICE_PORT_MAX + ), required=False ) description = forms.CharField( diff --git a/netbox/ipam/migrations/0038_custom_field_data.py b/netbox/ipam/migrations/0038_custom_field_data.py new file mode 100644 index 0000000000..86d51e9b8e --- /dev/null +++ b/netbox/ipam/migrations/0038_custom_field_data.py @@ -0,0 +1,42 @@ +import django.core.serializers.json +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipam', '0037_ipaddress_assignment'), + ] + + operations = [ + migrations.AddField( + model_name='aggregate', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AddField( + model_name='ipaddress', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AddField( + model_name='prefix', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AddField( + model_name='service', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AddField( + model_name='vlan', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AddField( + model_name='vrf', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + ] diff --git a/netbox/ipam/migrations/0039_service_ports_array.py b/netbox/ipam/migrations/0039_service_ports_array.py new file mode 100644 index 0000000000..63e592c032 --- /dev/null +++ b/netbox/ipam/migrations/0039_service_ports_array.py @@ -0,0 +1,43 @@ +import django.contrib.postgres.fields +import django.core.validators +from django.db import migrations, models + + +def replicate_ports(apps, schema_editor): + Service = apps.get_model('ipam', 'Service') + # TODO: Figure out how to cast IntegerField to an array so we can use .update() + for service in Service.objects.all(): + Service.objects.filter(pk=service.pk).update(ports=[service.port]) + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipam', '0038_custom_field_data'), + ] + + operations = [ + migrations.AddField( + model_name='service', + name='ports', + field=django.contrib.postgres.fields.ArrayField( + base_field=models.PositiveIntegerField( + validators=[ + django.core.validators.MinValueValidator(1), + django.core.validators.MaxValueValidator(65535) + ] + ), + default=[], + size=None + ), + preserve_default=False, + ), + + migrations.AlterModelOptions( + name='service', + options={'ordering': ('protocol', 'ports', 'pk')}, + ), + migrations.RunPython( + code=replicate_ports + ), + ] diff --git a/netbox/ipam/migrations/0040_service_drop_port.py b/netbox/ipam/migrations/0040_service_drop_port.py new file mode 100644 index 0000000000..d1db82678e --- /dev/null +++ b/netbox/ipam/migrations/0040_service_drop_port.py @@ -0,0 +1,15 @@ +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipam', '0039_service_ports_array'), + ] + + operations = [ + migrations.RemoveField( + model_name='service', + name='port', + ), + ] diff --git a/netbox/ipam/migrations/0041_routetarget.py b/netbox/ipam/migrations/0041_routetarget.py new file mode 100644 index 0000000000..2c2909279e --- /dev/null +++ b/netbox/ipam/migrations/0041_routetarget.py @@ -0,0 +1,44 @@ +# Generated by Django 3.1 on 2020-09-24 15:19 + +import django.core.serializers.json +from django.db import migrations, models +import django.db.models.deletion +import taggit.managers + + +class Migration(migrations.Migration): + + dependencies = [ + ('tenancy', '0010_custom_field_data'), + ('extras', '0052_customfield_cleanup'), + ('ipam', '0040_service_drop_port'), + ] + + operations = [ + migrations.CreateModel( + name='RouteTarget', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ('created', models.DateField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder)), + ('name', models.CharField(max_length=21, unique=True)), + ('description', models.CharField(blank=True, max_length=200)), + ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), + ('tenant', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='route_targets', to='tenancy.tenant')), + ], + options={ + 'ordering': ['name'], + }, + ), + migrations.AddField( + model_name='vrf', + name='export_targets', + field=models.ManyToManyField(blank=True, related_name='exporting_vrfs', to='ipam.RouteTarget'), + ), + migrations.AddField( + model_name='vrf', + name='import_targets', + field=models.ManyToManyField(blank=True, related_name='importing_vrfs', to='ipam.RouteTarget'), + ), + ] diff --git a/netbox/ipam/migrations/0042_standardize_name_length.py b/netbox/ipam/migrations/0042_standardize_name_length.py new file mode 100644 index 0000000000..09bfdda6e6 --- /dev/null +++ b/netbox/ipam/migrations/0042_standardize_name_length.py @@ -0,0 +1,53 @@ +# Generated by Django 3.1 on 2020-10-15 19:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipam', '0041_routetarget'), + ] + + operations = [ + migrations.AlterField( + model_name='rir', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='rir', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='role', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='role', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='service', + name='name', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='vlangroup', + name='name', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='vlangroup', + name='slug', + field=models.SlugField(max_length=100), + ), + migrations.AlterField( + model_name='vrf', + name='name', + field=models.CharField(max_length=100), + ), + ] diff --git a/netbox/ipam/migrations/0043_add_tenancy_to_aggregates.py b/netbox/ipam/migrations/0043_add_tenancy_to_aggregates.py new file mode 100644 index 0000000000..a5ec9013b0 --- /dev/null +++ b/netbox/ipam/migrations/0043_add_tenancy_to_aggregates.py @@ -0,0 +1,20 @@ +# Generated by Django 3.1 on 2020-10-16 01:24 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('tenancy', '0011_standardize_name_length'), + ('ipam', '0042_standardize_name_length'), + ] + + operations = [ + migrations.AddField( + model_name='aggregate', + name='tenant', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='aggregates', to='tenancy.tenant'), + ), + ] diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index a69d235bea..0ae9db7b24 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -1,7 +1,8 @@ import netaddr from django.conf import settings -from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation +from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType +from django.contrib.postgres.fields import ArrayField from django.core.exceptions import ValidationError from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models @@ -13,7 +14,7 @@ from extras.models import ChangeLoggedModel, CustomFieldModel, ObjectChange, TaggedItem from extras.utils import extras_features from utilities.querysets import RestrictedQuerySet -from utilities.utils import serialize_object +from utilities.utils import array_to_string, serialize_object from virtualization.models import VirtualMachine, VMInterface from .choices import * from .constants import * @@ -29,6 +30,7 @@ 'Prefix', 'RIR', 'Role', + 'RouteTarget', 'Service', 'VLAN', 'VLANGroup', @@ -44,7 +46,7 @@ class VRF(ChangeLoggedModel, CustomFieldModel): are said to exist in the "global" table.) """ name = models.CharField( - max_length=50 + max_length=100 ) rd = models.CharField( max_length=VRF_RD_MAX_LENGTH, @@ -70,10 +72,15 @@ class VRF(ChangeLoggedModel, CustomFieldModel): max_length=200, blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' + import_targets = models.ManyToManyField( + to='ipam.RouteTarget', + related_name='importing_vrfs', + blank=True + ) + export_targets = models.ManyToManyField( + to='ipam.RouteTarget', + related_name='exporting_vrfs', + blank=True ) tags = TaggableManager(through=TaggedItem) @@ -111,16 +118,61 @@ def display_name(self): return self.name +@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') +class RouteTarget(ChangeLoggedModel, CustomFieldModel): + """ + A BGP extended community used to control the redistribution of routes among VRFs, as defined in RFC 4364. + """ + name = models.CharField( + max_length=VRF_RD_MAX_LENGTH, # Same format options as VRF RD (RFC 4360 section 4) + unique=True, + help_text='Route target value (formatted in accordance with RFC 4360)' + ) + description = models.CharField( + max_length=200, + blank=True + ) + tenant = models.ForeignKey( + to='tenancy.Tenant', + on_delete=models.PROTECT, + related_name='route_targets', + blank=True, + null=True + ) + tags = TaggableManager(through=TaggedItem) + + objects = RestrictedQuerySet.as_manager() + + csv_headers = ['name', 'description', 'tenant'] + + class Meta: + ordering = ['name'] + + def __str__(self): + return self.name + + def get_absolute_url(self): + return reverse('ipam:routetarget', args=[self.pk]) + + def to_csv(self): + return ( + self.name, + self.description, + self.tenant.name if self.tenant else None, + ) + + class RIR(ChangeLoggedModel): """ A Regional Internet Registry (RIR) is responsible for the allocation of a large portion of the global IP address space. This can be an organization like ARIN or RIPE, or a governing standard such as RFC 1918. """ name = models.CharField( - max_length=50, + max_length=100, unique=True ) slug = models.SlugField( + max_length=100, unique=True ) is_private = models.BooleanField( @@ -170,6 +222,13 @@ class Aggregate(ChangeLoggedModel, CustomFieldModel): related_name='aggregates', verbose_name='RIR' ) + tenant = models.ForeignKey( + to='tenancy.Tenant', + on_delete=models.PROTECT, + related_name='aggregates', + blank=True, + null=True + ) date_added = models.DateField( blank=True, null=True @@ -178,18 +237,13 @@ class Aggregate(ChangeLoggedModel, CustomFieldModel): max_length=200, blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) tags = TaggableManager(through=TaggedItem) objects = RestrictedQuerySet.as_manager() - csv_headers = ['prefix', 'rir', 'date_added', 'description'] + csv_headers = ['prefix', 'rir', 'tenant', 'date_added', 'description'] clone_fields = [ - 'rir', 'date_added', 'description', + 'rir', 'tenant', 'date_added', 'description', ] class Meta: @@ -202,6 +256,7 @@ def get_absolute_url(self): return reverse('ipam:aggregate', args=[self.pk]) def clean(self): + super().clean() if self.prefix: @@ -242,6 +297,7 @@ def to_csv(self): return ( self.prefix, self.rir.name, + self.tenant.name if self.tenant else None, self.date_added, self.description, ) @@ -267,10 +323,11 @@ class Role(ChangeLoggedModel): "Management." """ name = models.CharField( - max_length=50, + max_length=100, unique=True ) slug = models.SlugField( + max_length=100, unique=True ) weight = models.PositiveSmallIntegerField( @@ -364,11 +421,6 @@ class Prefix(ChangeLoggedModel, CustomFieldModel): max_length=200, blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) tags = TaggableManager(through=TaggedItem) objects = PrefixQuerySet.as_manager() @@ -380,13 +432,6 @@ class Prefix(ChangeLoggedModel, CustomFieldModel): 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'is_pool', 'description', ] - STATUS_CLASS_MAP = { - 'container': 'default', - 'active': 'primary', - 'reserved': 'info', - 'deprecated': 'danger', - } - class Meta: ordering = (F('vrf').asc(nulls_first=True), 'prefix', 'pk') # (vrf, prefix) may be non-unique verbose_name_plural = 'prefixes' @@ -398,6 +443,7 @@ def get_absolute_url(self): return reverse('ipam:prefix', args=[self.pk]) def clean(self): + super().clean() if self.prefix: @@ -467,7 +513,7 @@ def _set_prefix_length(self, value): prefix_length = property(fset=_set_prefix_length) def get_status_class(self): - return self.STATUS_CLASS_MAP.get(self.status) + return PrefixStatusChoices.CSS_CLASSES.get(self.status) def get_duplicates(self): return Prefix.objects.filter(vrf=self.vrf, prefix=str(self.prefix)).exclude(pk=self.pk) @@ -647,11 +693,6 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel): max_length=200, blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) tags = TaggableManager(through=TaggedItem) objects = IPAddressManager() @@ -664,25 +705,6 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel): 'vrf', 'tenant', 'status', 'role', 'description', ] - STATUS_CLASS_MAP = { - 'active': 'primary', - 'reserved': 'info', - 'deprecated': 'danger', - 'dhcp': 'success', - 'slaac': 'success', - } - - ROLE_CLASS_MAP = { - 'loopback': 'default', - 'secondary': 'primary', - 'anycast': 'warning', - 'vip': 'success', - 'vrrp': 'success', - 'hsrp': 'success', - 'glbp': 'success', - 'carp': 'success', - } - class Meta: ordering = ('address', 'pk') # address may be non-unique verbose_name = 'IP address' @@ -701,6 +723,7 @@ def get_duplicates(self): ).exclude(pk=self.pk) def clean(self): + super().clean() if self.address: @@ -805,10 +828,10 @@ def _set_mask_length(self, value): mask_length = property(fset=_set_mask_length) def get_status_class(self): - return self.STATUS_CLASS_MAP.get(self.status) + return IPAddressStatusChoices.CSS_CLASSES.get(self.status) def get_role_class(self): - return self.ROLE_CLASS_MAP[self.role] + return IPAddressRoleChoices.CSS_CLASSES.get(self.role) class VLANGroup(ChangeLoggedModel): @@ -816,9 +839,11 @@ class VLANGroup(ChangeLoggedModel): A VLAN group is an arbitrary collection of VLANs within which VLAN IDs and names must be unique. """ name = models.CharField( - max_length=50 + max_length=100 + ) + slug = models.SlugField( + max_length=100 ) - slug = models.SlugField() site = models.ForeignKey( to='dcim.Site', on_delete=models.PROTECT, @@ -923,11 +948,6 @@ class VLAN(ChangeLoggedModel, CustomFieldModel): max_length=200, blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) tags = TaggableManager(through=TaggedItem) objects = RestrictedQuerySet.as_manager() @@ -937,12 +957,6 @@ class VLAN(ChangeLoggedModel, CustomFieldModel): 'site', 'group', 'tenant', 'status', 'role', 'description', ] - STATUS_CLASS_MAP = { - 'active': 'primary', - 'reserved': 'info', - 'deprecated': 'danger', - } - class Meta: ordering = ('site', 'group', 'vid', 'pk') # (site, group, vid) may be non-unique unique_together = [ @@ -959,6 +973,7 @@ def get_absolute_url(self): return reverse('ipam:vlan', args=[self.pk]) def clean(self): + super().clean() # Validate VLAN group if self.group and self.group.site != self.site: @@ -983,7 +998,7 @@ def display_name(self): return f'{self.name} ({self.vid})' def get_status_class(self): - return self.STATUS_CLASS_MAP[self.status] + return VLANStatusChoices.CSS_CLASSES.get(self.status) def get_interfaces(self): # Return all device interfaces assigned to this VLAN @@ -1022,18 +1037,20 @@ class Service(ChangeLoggedModel, CustomFieldModel): blank=True ) name = models.CharField( - max_length=30 + max_length=100 ) protocol = models.CharField( max_length=50, choices=ServiceProtocolChoices ) - port = models.PositiveIntegerField( - validators=[ - MinValueValidator(SERVICE_PORT_MIN), - MaxValueValidator(SERVICE_PORT_MAX) - ], - verbose_name='Port number' + ports = ArrayField( + base_field=models.PositiveIntegerField( + validators=[ + MinValueValidator(SERVICE_PORT_MIN), + MaxValueValidator(SERVICE_PORT_MAX) + ] + ), + verbose_name='Port numbers' ) ipaddresses = models.ManyToManyField( to='ipam.IPAddress', @@ -1045,22 +1062,17 @@ class Service(ChangeLoggedModel, CustomFieldModel): max_length=200, blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) tags = TaggableManager(through=TaggedItem) objects = RestrictedQuerySet.as_manager() - csv_headers = ['device', 'virtual_machine', 'name', 'protocol', 'port', 'description'] + csv_headers = ['device', 'virtual_machine', 'name', 'protocol', 'ports', 'description'] class Meta: - ordering = ('protocol', 'port', 'pk') # (protocol, port) may be non-unique + ordering = ('protocol', 'ports', 'pk') # (protocol, port) may be non-unique def __str__(self): - return '{} ({}/{})'.format(self.name, self.port, self.get_protocol_display()) + return f'{self.name} ({self.get_protocol_display()}/{self.port_list})' def get_absolute_url(self): return reverse('ipam:service', args=[self.pk]) @@ -1070,6 +1082,7 @@ def parent(self): return self.device or self.virtual_machine def clean(self): + super().clean() # A Service must belong to a Device *or* to a VirtualMachine if self.device and self.virtual_machine: @@ -1083,6 +1096,10 @@ def to_csv(self): self.virtual_machine.name if self.virtual_machine else None, self.name, self.get_protocol_display(), - self.port, + self.ports, self.description, ) + + @property + def port_list(self): + return array_to_string(self.ports) diff --git a/netbox/ipam/tables.py b/netbox/ipam/tables.py index ba09475b00..02196198c0 100644 --- a/netbox/ipam/tables.py +++ b/netbox/ipam/tables.py @@ -1,47 +1,25 @@ import django_tables2 as tables +from django.utils.safestring import mark_safe from django_tables2.utils import Accessor from dcim.models import Interface from tenancy.tables import COL_TENANT -from utilities.tables import BaseTable, BooleanColumn, ButtonsColumn, TagColumn, ToggleColumn +from utilities.tables import ( + BaseTable, BooleanColumn, ButtonsColumn, ChoiceFieldColumn, LinkedCountColumn, TagColumn, ToggleColumn, +) from virtualization.models import VMInterface -from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF - -RIR_UTILIZATION = """ -
    - {% if record.stats.total %} -
    - {{ record.stats.percentages.active }}% -
    -
    - {{ record.stats.percentages.reserved }}% -
    -
    - {{ record.stats.percentages.deprecated }}% -
    -
    - {{ record.stats.percentages.available }}% -
    - {% endif %} -
    -""" +from .models import Aggregate, IPAddress, Prefix, RIR, Role, RouteTarget, Service, VLAN, VLANGroup, VRF + +AVAILABLE_LABEL = mark_safe('Available') UTILIZATION_GRAPH = """ {% load helpers %} {% if record.pk %}{% utilization_graph record.get_utilization %}{% else %}—{% endif %} """ -ROLE_PREFIX_COUNT = """ -{{ value|default:0 }} -""" - -ROLE_VLAN_COUNT = """ -{{ value|default:0 }} -""" - PREFIX_LINK = """ {% if record.children %} - + {% else %} {% endif %} @@ -81,12 +59,12 @@ {% endif %} """ -STATUS_LABEL = """ -{% if record.pk %} - {{ record.get_status_display }} -{% else %} - Available -{% endif %} +VRF_TARGETS = """ +{% for rt in value.all %} + {{ rt }}{% if not forloop.last %}
    {% endif %} +{% empty %} + — +{% endfor %} """ VLAN_LINK = """ @@ -119,7 +97,7 @@ {% with next_vid=record.get_next_available_vid %} {% if next_vid and perms.ipam.add_vlan %} - + {% endif %} {% endwith %} @@ -127,15 +105,9 @@ VLAN_MEMBER_TAGGED = """ {% if record.untagged_vlan_id == vlan.pk %} - + {% else %} - -{% endif %} -""" - -VLAN_MEMBER_ACTIONS = """ -{% if perms.dcim.change_interface %} - + {% endif %} """ @@ -166,16 +138,46 @@ class VRFTable(BaseTable): enforce_unique = BooleanColumn( verbose_name='Unique' ) + import_targets = tables.TemplateColumn( + template_code=VRF_TARGETS, + orderable=False + ) + export_targets = tables.TemplateColumn( + template_code=VRF_TARGETS, + orderable=False + ) tags = TagColumn( url_name='ipam:vrf_list' ) class Meta(BaseTable.Meta): model = VRF - fields = ('pk', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'tags') + fields = ( + 'pk', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'import_targets', 'export_targets', 'tags', + ) default_columns = ('pk', 'name', 'rd', 'tenant', 'description') +# +# Route targets +# + +class RouteTargetTable(BaseTable): + pk = ToggleColumn() + name = tables.LinkColumn() + tenant = tables.TemplateColumn( + template_code=COL_TENANT + ) + tags = TagColumn( + url_name='ipam:vrf_list' + ) + + class Meta(BaseTable.Meta): + model = RouteTarget + fields = ('pk', 'name', 'tenant', 'description', 'tags') + default_columns = ('pk', 'name', 'tenant', 'description') + + # # RIRs # @@ -186,7 +188,9 @@ class RIRTable(BaseTable): is_private = BooleanColumn( verbose_name='Private' ) - aggregate_count = tables.Column( + aggregate_count = LinkedCountColumn( + viewname='ipam:aggregate_list', + url_params={'rir': 'slug'}, verbose_name='Aggregates' ) actions = ButtonsColumn(RIR, pk_field='slug') @@ -197,48 +201,6 @@ class Meta(BaseTable.Meta): default_columns = ('pk', 'name', 'is_private', 'aggregate_count', 'description', 'actions') -class RIRDetailTable(RIRTable): - stats_total = tables.Column( - accessor='stats.total', - verbose_name='Total', - footer=lambda table: sum(r.stats['total'] for r in table.data) - ) - stats_active = tables.Column( - accessor='stats.active', - verbose_name='Active', - footer=lambda table: sum(r.stats['active'] for r in table.data) - ) - stats_reserved = tables.Column( - accessor='stats.reserved', - verbose_name='Reserved', - footer=lambda table: sum(r.stats['reserved'] for r in table.data) - ) - stats_deprecated = tables.Column( - accessor='stats.deprecated', - verbose_name='Deprecated', - footer=lambda table: sum(r.stats['deprecated'] for r in table.data) - ) - stats_available = tables.Column( - accessor='stats.available', - verbose_name='Available', - footer=lambda table: sum(r.stats['available'] for r in table.data) - ) - utilization = tables.TemplateColumn( - template_code=RIR_UTILIZATION, - verbose_name='Utilization' - ) - - class Meta(RIRTable.Meta): - fields = ( - 'pk', 'name', 'slug', 'is_private', 'aggregate_count', 'stats_total', 'stats_active', 'stats_reserved', - 'stats_deprecated', 'stats_available', 'utilization', 'actions', - ) - default_columns = ( - 'pk', 'name', 'is_private', 'aggregate_count', 'stats_total', 'stats_active', 'stats_reserved', - 'stats_deprecated', 'stats_available', 'utilization', 'actions', - ) - - # # Aggregates # @@ -248,6 +210,9 @@ class AggregateTable(BaseTable): prefix = tables.LinkColumn( verbose_name='Aggregate' ) + tenant = tables.TemplateColumn( + template_code=TENANT_LINK + ) date_added = tables.DateColumn( format="Y-m-d", verbose_name='Added' @@ -255,7 +220,7 @@ class AggregateTable(BaseTable): class Meta(BaseTable.Meta): model = Aggregate - fields = ('pk', 'prefix', 'rir', 'date_added', 'description') + fields = ('pk', 'prefix', 'rir', 'tenant', 'date_added', 'description') class AggregateDetailTable(AggregateTable): @@ -271,8 +236,8 @@ class AggregateDetailTable(AggregateTable): ) class Meta(AggregateTable.Meta): - fields = ('pk', 'prefix', 'rir', 'child_count', 'utilization', 'date_added', 'description', 'tags') - default_columns = ('pk', 'prefix', 'rir', 'child_count', 'utilization', 'date_added', 'description') + fields = ('pk', 'prefix', 'rir', 'tenant', 'child_count', 'utilization', 'date_added', 'description', 'tags') + default_columns = ('pk', 'prefix', 'rir', 'tenant', 'child_count', 'utilization', 'date_added', 'description') # @@ -281,12 +246,14 @@ class Meta(AggregateTable.Meta): class RoleTable(BaseTable): pk = ToggleColumn() - prefix_count = tables.TemplateColumn( - template_code=ROLE_PREFIX_COUNT, + prefix_count = LinkedCountColumn( + viewname='ipam:prefix_list', + url_params={'role': 'slug'}, verbose_name='Prefixes' ) - vlan_count = tables.TemplateColumn( - template_code=ROLE_VLAN_COUNT, + vlan_count = LinkedCountColumn( + viewname='ipam:vlan_list', + url_params={'role': 'slug'}, verbose_name='VLANs' ) actions = ButtonsColumn(Role, pk_field='slug') @@ -307,8 +274,8 @@ class PrefixTable(BaseTable): template_code=PREFIX_LINK, attrs={'th': {'style': 'padding-left: 17px'}} ) - status = tables.TemplateColumn( - template_code=STATUS_LABEL + status = ChoiceFieldColumn( + default=AVAILABLE_LABEL ) vrf = tables.TemplateColumn( template_code=VRF_LINK, @@ -331,8 +298,6 @@ class PrefixTable(BaseTable): verbose_name='Pool' ) - add_prefetch = False - class Meta(BaseTable.Meta): model = Prefix fields = ( @@ -380,9 +345,10 @@ class IPAddressTable(BaseTable): template_code=VRF_LINK, verbose_name='VRF' ) - status = tables.TemplateColumn( - template_code=STATUS_LABEL + status = ChoiceFieldColumn( + default=AVAILABLE_LABEL ) + role = ChoiceFieldColumn() tenant = tables.TemplateColumn( template_code=TENANT_LINK ) @@ -441,9 +407,7 @@ class IPAddressAssignTable(BaseTable): template_code=IPADDRESS_ASSIGN_LINK, verbose_name='IP Address' ) - status = tables.TemplateColumn( - template_code=STATUS_LABEL - ) + status = ChoiceFieldColumn() assigned_object = tables.Column( orderable=False ) @@ -465,9 +429,7 @@ class InterfaceIPAddressTable(BaseTable): template_code=VRF_LINK, verbose_name='VRF' ) - status = tables.TemplateColumn( - template_code=STATUS_LABEL - ) + status = ChoiceFieldColumn() tenant = tables.TemplateColumn( template_code=TENANT_LINK ) @@ -488,7 +450,9 @@ class VLANGroupTable(BaseTable): viewname='dcim:site', args=[Accessor('site__slug')] ) - vlan_count = tables.Column( + vlan_count = LinkedCountColumn( + viewname='ipam:vlan_list', + url_params={'group': 'slug'}, verbose_name='VLANs' ) actions = ButtonsColumn( @@ -523,8 +487,8 @@ class VLANTable(BaseTable): tenant = tables.TemplateColumn( template_code=COL_TENANT ) - status = tables.TemplateColumn( - template_code=STATUS_LABEL + status = ChoiceFieldColumn( + default=AVAILABLE_LABEL ) role = tables.TemplateColumn( template_code=VLAN_ROLE_LINK @@ -567,15 +531,11 @@ class VLANMembersTable(BaseTable): template_code=VLAN_MEMBER_TAGGED, orderable=False ) - actions = tables.TemplateColumn( - template_code=VLAN_MEMBER_ACTIONS, - attrs={'td': {'class': 'text-right noprint'}}, - verbose_name='' - ) class VLANDevicesTable(VLANMembersTable): device = tables.LinkColumn() + actions = ButtonsColumn(Interface, buttons=['edit']) class Meta(BaseTable.Meta): model = Interface @@ -584,6 +544,7 @@ class Meta(BaseTable.Meta): class VLANVirtualMachinesTable(VLANMembersTable): virtual_machine = tables.LinkColumn() + actions = ButtonsColumn(VMInterface, buttons=['edit']) class Meta(BaseTable.Meta): model = VMInterface @@ -610,9 +571,7 @@ class InterfaceVLANTable(BaseTable): tenant = tables.TemplateColumn( template_code=COL_TENANT ) - status = tables.TemplateColumn( - template_code=STATUS_LABEL - ) + status = ChoiceFieldColumn() role = tables.TemplateColumn( template_code=VLAN_ROLE_LINK ) @@ -638,11 +597,15 @@ class ServiceTable(BaseTable): parent = tables.LinkColumn( order_by=('device', 'virtual_machine') ) + ports = tables.TemplateColumn( + template_code='{{ record.port_list }}', + verbose_name='Ports' + ) tags = TagColumn( url_name='ipam:service_list' ) class Meta(BaseTable.Meta): model = Service - fields = ('pk', 'name', 'parent', 'protocol', 'port', 'ipaddresses', 'description', 'tags') - default_columns = ('pk', 'name', 'parent', 'protocol', 'port', 'description') + fields = ('pk', 'name', 'parent', 'protocol', 'ports', 'ipaddresses', 'description', 'tags') + default_columns = ('pk', 'name', 'parent', 'protocol', 'ports', 'description') diff --git a/netbox/ipam/tests/test_api.py b/netbox/ipam/tests/test_api.py index 3f2ac470de..db98713d03 100644 --- a/netbox/ipam/tests/test_api.py +++ b/netbox/ipam/tests/test_api.py @@ -6,7 +6,7 @@ from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site from ipam.choices import * -from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF +from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, RouteTarget, Service, VLAN, VLANGroup, VRF from utilities.testing import APITestCase, APIViewTestCases, disable_warnings @@ -37,6 +37,9 @@ class VRFTest(APIViewTestCases.APIViewTestCase): 'rd': '65000:6', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -49,6 +52,35 @@ def setUpTestData(cls): VRF.objects.bulk_create(vrfs) +class RouteTargetTest(APIViewTestCases.APIViewTestCase): + model = RouteTarget + brief_fields = ['id', 'name', 'url'] + create_data = [ + { + 'name': '65000:1004', + }, + { + 'name': '65000:1005', + }, + { + 'name': '65000:1006', + }, + ] + bulk_update_data = { + 'description': 'New description', + } + + @classmethod + def setUpTestData(cls): + + route_targets = ( + RouteTarget(name='65000:1001'), + RouteTarget(name='65000:1002'), + RouteTarget(name='65000:1003'), + ) + RouteTarget.objects.bulk_create(route_targets) + + class RIRTest(APIViewTestCases.APIViewTestCase): model = RIR brief_fields = ['aggregate_count', 'id', 'name', 'slug', 'url'] @@ -66,6 +98,9 @@ class RIRTest(APIViewTestCases.APIViewTestCase): 'slug': 'rir-6', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -81,6 +116,9 @@ def setUpTestData(cls): class AggregateTest(APIViewTestCases.APIViewTestCase): model = Aggregate brief_fields = ['family', 'id', 'prefix', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -131,6 +169,9 @@ class RoleTest(APIViewTestCases.APIViewTestCase): 'slug': 'role-6', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -157,6 +198,9 @@ class PrefixTest(APIViewTestCases.APIViewTestCase): 'prefix': '192.168.6.0/24', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -328,6 +372,9 @@ class IPAddressTest(APIViewTestCases.APIViewTestCase): 'address': '192.168.0.6/24', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -357,6 +404,9 @@ class VLANGroupTest(APIViewTestCases.APIViewTestCase): 'slug': 'vlan-group-6', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -372,6 +422,9 @@ def setUpTestData(cls): class VLANTest(APIViewTestCases.APIViewTestCase): model = VLAN brief_fields = ['display_name', 'id', 'name', 'url', 'vid'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -428,7 +481,10 @@ def test_delete_vlan_with_prefix(self): class ServiceTest(APIViewTestCases.APIViewTestCase): model = Service - brief_fields = ['id', 'name', 'port', 'protocol', 'url'] + brief_fields = ['id', 'name', 'ports', 'protocol', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -444,9 +500,9 @@ def setUpTestData(cls): Device.objects.bulk_create(devices) services = ( - Service(device=devices[0], name='Service 1', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=1), - Service(device=devices[0], name='Service 2', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=2), - Service(device=devices[0], name='Service 3', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=3), + Service(device=devices[0], name='Service 1', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[1]), + Service(device=devices[0], name='Service 2', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[2]), + Service(device=devices[0], name='Service 3', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[3]), ) Service.objects.bulk_create(services) @@ -455,18 +511,18 @@ def setUpTestData(cls): 'device': devices[1].pk, 'name': 'Service 4', 'protocol': ServiceProtocolChoices.PROTOCOL_TCP, - 'port': 4, + 'ports': [4], }, { 'device': devices[1].pk, 'name': 'Service 5', 'protocol': ServiceProtocolChoices.PROTOCOL_TCP, - 'port': 5, + 'ports': [5], }, { 'device': devices[1].pk, 'name': 'Service 6', 'protocol': ServiceProtocolChoices.PROTOCOL_TCP, - 'port': 6, + 'ports': [6], }, ] diff --git a/netbox/ipam/tests/test_filters.py b/netbox/ipam/tests/test_filters.py index 560313f0ab..2fead3d933 100644 --- a/netbox/ipam/tests/test_filters.py +++ b/netbox/ipam/tests/test_filters.py @@ -3,7 +3,7 @@ from dcim.models import Device, DeviceRole, DeviceType, Interface, Manufacturer, Region, Site from ipam.choices import * from ipam.filters import * -from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF +from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, RouteTarget, Service, VLAN, VLANGroup, VRF from virtualization.models import Cluster, ClusterType, VirtualMachine, VMInterface from tenancy.models import Tenant, TenantGroup @@ -15,6 +15,13 @@ class VRFTestCase(TestCase): @classmethod def setUpTestData(cls): + route_targets = ( + RouteTarget(name='65000:1001'), + RouteTarget(name='65000:1002'), + RouteTarget(name='65000:1003'), + ) + RouteTarget.objects.bulk_create(route_targets) + tenant_groups = ( TenantGroup(name='Tenant group 1', slug='tenant-group-1'), TenantGroup(name='Tenant group 2', slug='tenant-group-2'), @@ -39,6 +46,12 @@ def setUpTestData(cls): VRF(name='VRF 6', rd='65000:600', tenant=tenants[2], enforce_unique=True), ) VRF.objects.bulk_create(vrfs) + vrfs[0].import_targets.add(route_targets[0]) + vrfs[0].export_targets.add(route_targets[0]) + vrfs[1].import_targets.add(route_targets[1]) + vrfs[1].export_targets.add(route_targets[1]) + vrfs[2].import_targets.add(route_targets[2]) + vrfs[2].export_targets.add(route_targets[2]) def test_id(self): params = {'id': self.queryset.values_list('pk', flat=True)[:2]} @@ -58,6 +71,20 @@ def test_enforce_unique(self): params = {'enforce_unique': 'false'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + def test_import_target(self): + route_targets = RouteTarget.objects.all()[:2] + params = {'import_target_id': [route_targets[0].pk, route_targets[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'import_target': [route_targets[0].name, route_targets[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_export_target(self): + route_targets = RouteTarget.objects.all()[:2] + params = {'export_target_id': [route_targets[0].pk, route_targets[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'export_target': [route_targets[0].name, route_targets[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + def test_tenant(self): tenants = Tenant.objects.all()[:2] params = {'tenant_id': [tenants[0].pk, tenants[1].pk]} @@ -73,6 +100,92 @@ def test_tenant_group(self): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) +class RouteTargetTestCase(TestCase): + queryset = RouteTarget.objects.all() + filterset = RouteTargetFilterSet + + @classmethod + def setUpTestData(cls): + + tenant_groups = ( + TenantGroup(name='Tenant group 1', slug='tenant-group-1'), + TenantGroup(name='Tenant group 2', slug='tenant-group-2'), + TenantGroup(name='Tenant group 3', slug='tenant-group-3'), + ) + for tenantgroup in tenant_groups: + tenantgroup.save() + + tenants = ( + Tenant(name='Tenant 1', slug='tenant-1', group=tenant_groups[0]), + Tenant(name='Tenant 2', slug='tenant-2', group=tenant_groups[1]), + Tenant(name='Tenant 3', slug='tenant-3', group=tenant_groups[2]), + ) + Tenant.objects.bulk_create(tenants) + + route_targets = ( + RouteTarget(name='65000:1001', tenant=tenants[0]), + RouteTarget(name='65000:1002', tenant=tenants[0]), + RouteTarget(name='65000:1003', tenant=tenants[0]), + RouteTarget(name='65000:1004', tenant=tenants[0]), + RouteTarget(name='65000:2001', tenant=tenants[1]), + RouteTarget(name='65000:2002', tenant=tenants[1]), + RouteTarget(name='65000:2003', tenant=tenants[1]), + RouteTarget(name='65000:2004', tenant=tenants[1]), + RouteTarget(name='65000:3001', tenant=tenants[2]), + RouteTarget(name='65000:3002', tenant=tenants[2]), + RouteTarget(name='65000:3003', tenant=tenants[2]), + RouteTarget(name='65000:3004', tenant=tenants[2]), + ) + RouteTarget.objects.bulk_create(route_targets) + + vrfs = ( + VRF(name='VRF 1', rd='65000:100'), + VRF(name='VRF 2', rd='65000:200'), + VRF(name='VRF 3', rd='65000:300'), + ) + VRF.objects.bulk_create(vrfs) + vrfs[0].import_targets.add(route_targets[0], route_targets[1]) + vrfs[0].export_targets.add(route_targets[2], route_targets[3]) + vrfs[1].import_targets.add(route_targets[4], route_targets[5]) + vrfs[1].export_targets.add(route_targets[6], route_targets[7]) + + def test_id(self): + params = {'id': self.queryset.values_list('pk', flat=True)[:2]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_name(self): + params = {'name': ['65000:1001', '65000:1002', '65000:1003']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_importing_vrf(self): + vrfs = VRF.objects.all()[:2] + params = {'importing_vrf_id': [vrfs[0].pk, vrfs[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'importing_vrf': [vrfs[0].rd, vrfs[1].rd]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_exporting_vrf(self): + vrfs = VRF.objects.all()[:2] + params = {'exporting_vrf_id': [vrfs[0].pk, vrfs[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'exporting_vrf': [vrfs[0].rd, vrfs[1].rd]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_tenant(self): + tenants = Tenant.objects.all()[:2] + params = {'tenant_id': [tenants[0].pk, tenants[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 8) + params = {'tenant': [tenants[0].slug, tenants[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 8) + + def test_tenant_group(self): + tenant_groups = TenantGroup.objects.all()[:2] + params = {'tenant_group_id': [tenant_groups[0].pk, tenant_groups[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 8) + params = {'tenant_group': [tenant_groups[0].slug, tenant_groups[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 8) + + class RIRTestCase(TestCase): queryset = RIR.objects.all() filterset = RIRFilterSet @@ -127,13 +240,28 @@ def setUpTestData(cls): ) RIR.objects.bulk_create(rirs) + tenant_groups = ( + TenantGroup(name='Tenant group 1', slug='tenant-group-1'), + TenantGroup(name='Tenant group 2', slug='tenant-group-2'), + TenantGroup(name='Tenant group 3', slug='tenant-group-3'), + ) + for tenantgroup in tenant_groups: + tenantgroup.save() + + tenants = ( + Tenant(name='Tenant 1', slug='tenant-1', group=tenant_groups[0]), + Tenant(name='Tenant 2', slug='tenant-2', group=tenant_groups[1]), + Tenant(name='Tenant 3', slug='tenant-3', group=tenant_groups[2]), + ) + Tenant.objects.bulk_create(tenants) + aggregates = ( - Aggregate(prefix='10.1.0.0/16', rir=rirs[0], date_added='2020-01-01'), - Aggregate(prefix='10.2.0.0/16', rir=rirs[0], date_added='2020-01-02'), - Aggregate(prefix='10.3.0.0/16', rir=rirs[1], date_added='2020-01-03'), - Aggregate(prefix='2001:db8:1::/48', rir=rirs[1], date_added='2020-01-04'), - Aggregate(prefix='2001:db8:2::/48', rir=rirs[2], date_added='2020-01-05'), - Aggregate(prefix='2001:db8:3::/48', rir=rirs[2], date_added='2020-01-06'), + Aggregate(prefix='10.1.0.0/16', rir=rirs[0], tenant=tenants[0], date_added='2020-01-01'), + Aggregate(prefix='10.2.0.0/16', rir=rirs[0], tenant=tenants[1], date_added='2020-01-02'), + Aggregate(prefix='10.3.0.0/16', rir=rirs[1], tenant=tenants[2], date_added='2020-01-03'), + Aggregate(prefix='2001:db8:1::/48', rir=rirs[1], tenant=tenants[0], date_added='2020-01-04'), + Aggregate(prefix='2001:db8:2::/48', rir=rirs[2], tenant=tenants[1], date_added='2020-01-05'), + Aggregate(prefix='2001:db8:3::/48', rir=rirs[2], tenant=tenants[2], date_added='2020-01-06'), ) Aggregate.objects.bulk_create(aggregates) @@ -161,6 +289,20 @@ def test_rir(self): params = {'rir': [rirs[0].slug, rirs[1].slug]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + def test_tenant(self): + tenants = Tenant.objects.all()[:2] + params = {'tenant_id': [tenants[0].pk, tenants[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'tenant': [tenants[0].slug, tenants[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_tenant_group(self): + tenant_groups = TenantGroup.objects.all()[:2] + params = {'tenant_group_id': [tenant_groups[0].pk, tenant_groups[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + params = {'tenant_group': [tenant_groups[0].slug, tenant_groups[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + class RoleTestCase(TestCase): queryset = Role.objects.all() @@ -212,12 +354,22 @@ def setUpTestData(cls): ) Site.objects.bulk_create(sites) + route_targets = ( + RouteTarget(name='65000:100'), + RouteTarget(name='65000:200'), + RouteTarget(name='65000:300'), + ) + RouteTarget.objects.bulk_create(route_targets) + vrfs = ( VRF(name='VRF 1', rd='65000:100'), VRF(name='VRF 2', rd='65000:200'), VRF(name='VRF 3', rd='65000:300'), ) VRF.objects.bulk_create(vrfs) + vrfs[0].import_targets.add(route_targets[0], route_targets[1], route_targets[2]) + vrfs[1].export_targets.add(route_targets[1]) + vrfs[2].export_targets.add(route_targets[2]) vlans = ( VLAN(vid=1, name='VLAN 1'), @@ -301,6 +453,14 @@ def test_vrf(self): params = {'vrf': [vrfs[0].rd, vrfs[1].rd]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + def test_present_in_vrf(self): + vrf1 = VRF.objects.get(name='VRF 1') + vrf2 = VRF.objects.get(name='VRF 2') + self.assertEqual(self.filterset({'present_in_vrf_id': vrf1.pk}, self.queryset).qs.count(), 6) + self.assertEqual(self.filterset({'present_in_vrf_id': vrf2.pk}, self.queryset).qs.count(), 2) + self.assertEqual(self.filterset({'present_in_vrf': vrf1.rd}, self.queryset).qs.count(), 6) + self.assertEqual(self.filterset({'present_in_vrf': vrf2.rd}, self.queryset).qs.count(), 2) + def test_region(self): regions = Region.objects.all()[:2] params = {'region_id': [regions[0].pk, regions[1].pk]} @@ -742,12 +902,12 @@ def setUpTestData(cls): VirtualMachine.objects.bulk_create(virtual_machines) services = ( - Service(device=devices[0], name='Service 1', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=1001), - Service(device=devices[1], name='Service 2', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=1002), - Service(device=devices[2], name='Service 3', protocol=ServiceProtocolChoices.PROTOCOL_UDP, port=1003), - Service(virtual_machine=virtual_machines[0], name='Service 4', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=2001), - Service(virtual_machine=virtual_machines[1], name='Service 5', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=2002), - Service(virtual_machine=virtual_machines[2], name='Service 6', protocol=ServiceProtocolChoices.PROTOCOL_UDP, port=2003), + Service(device=devices[0], name='Service 1', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[1001]), + Service(device=devices[1], name='Service 2', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[1002]), + Service(device=devices[2], name='Service 3', protocol=ServiceProtocolChoices.PROTOCOL_UDP, ports=[1003]), + Service(virtual_machine=virtual_machines[0], name='Service 4', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[2001]), + Service(virtual_machine=virtual_machines[1], name='Service 5', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[2002]), + Service(virtual_machine=virtual_machines[2], name='Service 6', protocol=ServiceProtocolChoices.PROTOCOL_UDP, ports=[2003]), ) Service.objects.bulk_create(services) @@ -764,8 +924,8 @@ def test_protocol(self): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) def test_port(self): - params = {'port': ['1001', '1002', '1003']} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + params = {'port': '1001'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) def test_device(self): devices = Device.objects.all()[:2] diff --git a/netbox/ipam/tests/test_views.py b/netbox/ipam/tests/test_views.py index 35bae013a9..db96bb896e 100644 --- a/netbox/ipam/tests/test_views.py +++ b/netbox/ipam/tests/test_views.py @@ -4,7 +4,7 @@ from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site from ipam.choices import * -from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF +from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, RouteTarget, Service, VLAN, VLANGroup, VRF from tenancy.models import Tenant from utilities.testing import ViewTestCases @@ -52,6 +52,46 @@ def setUpTestData(cls): } +class RouteTargetTestCase(ViewTestCases.PrimaryObjectViewTestCase): + model = RouteTarget + + @classmethod + def setUpTestData(cls): + + tenants = ( + Tenant(name='Tenant A', slug='tenant-a'), + Tenant(name='Tenant B', slug='tenant-b'), + ) + Tenant.objects.bulk_create(tenants) + + tags = cls.create_tags('Alpha', 'Bravo', 'Charlie') + + route_targets = ( + RouteTarget(name='65000:1001', tenant=tenants[0]), + RouteTarget(name='65000:1002', tenant=tenants[1]), + RouteTarget(name='65000:1003'), + ) + RouteTarget.objects.bulk_create(route_targets) + + cls.form_data = { + 'name': '65000:100', + 'description': 'A new route target', + 'tags': [t.pk for t in tags], + } + + cls.csv_data = ( + "name,tenant,description", + "65000:1004,Tenant A,Foo", + "65000:1005,Tenant B,Bar", + "65000:1006,,No tenant", + ) + + cls.bulk_edit_data = { + 'tenant': tenants[1].pk, + 'description': 'New description', + } + + class RIRTestCase(ViewTestCases.OrganizationalObjectViewTestCase): model = RIR @@ -194,9 +234,9 @@ def setUpTestData(cls): cls.csv_data = ( "vrf,prefix,status", - "VRF 1,10.4.0.0/16,Active", - "VRF 1,10.5.0.0/16,Active", - "VRF 1,10.6.0.0/16,Active", + "VRF 1,10.4.0.0/16,active", + "VRF 1,10.5.0.0/16,active", + "VRF 1,10.6.0.0/16,active", ) cls.bulk_edit_data = { @@ -244,9 +284,9 @@ def setUpTestData(cls): cls.csv_data = ( "vrf,address,status", - "VRF 1,192.0.2.4/24,Active", - "VRF 1,192.0.2.5/24,Active", - "VRF 1,192.0.2.6/24,Active", + "VRF 1,192.0.2.4/24,active", + "VRF 1,192.0.2.5/24,active", + "VRF 1,192.0.2.6/24,active", ) cls.bulk_edit_data = { @@ -334,9 +374,9 @@ def setUpTestData(cls): cls.csv_data = ( "vid,name,status", - "104,VLAN104,Active", - "105,VLAN105,Active", - "106,VLAN106,Active", + "104,VLAN104,active", + "105,VLAN105,active", + "106,VLAN106,active", ) cls.bulk_edit_data = { @@ -373,9 +413,9 @@ def setUpTestData(cls): device = Device.objects.create(name='Device 1', site=site, device_type=devicetype, device_role=devicerole) Service.objects.bulk_create([ - Service(device=device, name='Service 1', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=101), - Service(device=device, name='Service 2', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=102), - Service(device=device, name='Service 3', protocol=ServiceProtocolChoices.PROTOCOL_TCP, port=103), + Service(device=device, name='Service 1', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[101]), + Service(device=device, name='Service 2', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[102]), + Service(device=device, name='Service 3', protocol=ServiceProtocolChoices.PROTOCOL_TCP, ports=[103]), ]) tags = cls.create_tags('Alpha', 'Bravo', 'Charlie') @@ -385,21 +425,21 @@ def setUpTestData(cls): 'virtual_machine': None, 'name': 'Service X', 'protocol': ServiceProtocolChoices.PROTOCOL_TCP, - 'port': 999, + 'ports': '104,105', 'ipaddresses': [], 'description': 'A new service', 'tags': [t.pk for t in tags], } cls.csv_data = ( - "device,name,protocol,port,description", - "Device 1,Service 1,TCP,1,First service", - "Device 1,Service 2,TCP,2,Second service", - "Device 1,Service 3,UDP,3,Third service", + "device,name,protocol,ports,description", + "Device 1,Service 1,tcp,1,First service", + "Device 1,Service 2,tcp,2,Second service", + "Device 1,Service 3,udp,3,Third service", ) cls.bulk_edit_data = { 'protocol': ServiceProtocolChoices.PROTOCOL_UDP, - 'port': 888, + 'ports': '106,107', 'description': 'New description', } diff --git a/netbox/ipam/urls.py b/netbox/ipam/urls.py index 5333358167..9b0dc581bd 100644 --- a/netbox/ipam/urls.py +++ b/netbox/ipam/urls.py @@ -2,7 +2,7 @@ from extras.views import ObjectChangeLogView from . import views -from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF +from .models import Aggregate, IPAddress, Prefix, RIR, Role, RouteTarget, Service, VLAN, VLANGroup, VRF app_name = 'ipam' urlpatterns = [ @@ -18,6 +18,17 @@ path('vrfs//delete/', views.VRFDeleteView.as_view(), name='vrf_delete'), path('vrfs//changelog/', ObjectChangeLogView.as_view(), name='vrf_changelog', kwargs={'model': VRF}), + # Route targets + path('route-targets/', views.RouteTargetListView.as_view(), name='routetarget_list'), + path('route-targets/add/', views.RouteTargetEditView.as_view(), name='routetarget_add'), + path('route-targets/import/', views.RouteTargetBulkImportView.as_view(), name='routetarget_import'), + path('route-targets/edit/', views.RouteTargetBulkEditView.as_view(), name='routetarget_bulk_edit'), + path('route-targets/delete/', views.RouteTargetBulkDeleteView.as_view(), name='routetarget_bulk_delete'), + path('route-targets//', views.RouteTargetView.as_view(), name='routetarget'), + path('route-targets//edit/', views.RouteTargetEditView.as_view(), name='routetarget_edit'), + path('route-targets//delete/', views.RouteTargetDeleteView.as_view(), name='routetarget_delete'), + path('route-targets//changelog/', ObjectChangeLogView.as_view(), name='routetarget_changelog', kwargs={'model': RouteTarget}), + # RIRs path('rirs/', views.RIRListView.as_view(), name='rir_list'), path('rirs/add/', views.RIREditView.as_view(), name='rir_add'), diff --git a/netbox/ipam/utils.py b/netbox/ipam/utils.py index f3cc0cb528..0414a01e08 100644 --- a/netbox/ipam/utils.py +++ b/netbox/ipam/utils.py @@ -11,7 +11,7 @@ def add_available_prefixes(parent, prefix_list): # Find all unallocated space available_prefixes = netaddr.IPSet(parent) ^ netaddr.IPSet([p.prefix for p in prefix_list]) - available_prefixes = [Prefix(prefix=p) for p in available_prefixes.iter_cidrs()] + available_prefixes = [Prefix(prefix=p, status=None) for p in available_prefixes.iter_cidrs()] # Concatenate and sort complete list of children prefix_list = list(prefix_list) + available_prefixes diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 8dad91d09c..1cbac27f65 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -1,21 +1,16 @@ -import netaddr from django.db.models import Prefetch from django.db.models.expressions import RawSQL from django.shortcuts import get_object_or_404, redirect, render from django_tables2 import RequestConfig from dcim.models import Device, Interface +from netbox.views import generic from utilities.paginator import EnhancedPaginator, get_paginate_count from utilities.utils import get_subquery -from utilities.views import ( - BulkCreateView, BulkDeleteView, BulkEditView, BulkImportView, ObjectView, ObjectDeleteView, ObjectEditView, - ObjectListView, -) from virtualization.models import VirtualMachine, VMInterface from . import filters, forms, tables -from .choices import * from .constants import * -from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF +from .models import Aggregate, IPAddress, Prefix, RIR, Role, RouteTarget, Service, VLAN, VLANGroup, VRF from .utils import add_available_ipaddresses, add_available_prefixes, add_available_vlans @@ -23,156 +18,152 @@ # VRFs # -class VRFListView(ObjectListView): - queryset = VRF.objects.prefetch_related('tenant') +class VRFListView(generic.ObjectListView): + queryset = VRF.objects.all() filterset = filters.VRFFilterSet filterset_form = forms.VRFFilterForm table = tables.VRFTable -class VRFView(ObjectView): +class VRFView(generic.ObjectView): queryset = VRF.objects.all() - def get(self, request, pk): + def get_extra_context(self, request, instance): + prefix_count = Prefix.objects.restrict(request.user, 'view').filter(vrf=instance).count() - vrf = get_object_or_404(self.queryset, pk=pk) - prefix_count = Prefix.objects.restrict(request.user, 'view').filter(vrf=vrf).count() + import_targets_table = tables.RouteTargetTable( + instance.import_targets.prefetch_related('tenant'), + orderable=False + ) + export_targets_table = tables.RouteTargetTable( + instance.export_targets.prefetch_related('tenant'), + orderable=False + ) - return render(request, 'ipam/vrf.html', { - 'vrf': vrf, + return { 'prefix_count': prefix_count, - }) + 'import_targets_table': import_targets_table, + 'export_targets_table': export_targets_table, + } -class VRFEditView(ObjectEditView): +class VRFEditView(generic.ObjectEditView): queryset = VRF.objects.all() model_form = forms.VRFForm template_name = 'ipam/vrf_edit.html' -class VRFDeleteView(ObjectDeleteView): +class VRFDeleteView(generic.ObjectDeleteView): queryset = VRF.objects.all() -class VRFBulkImportView(BulkImportView): +class VRFBulkImportView(generic.BulkImportView): queryset = VRF.objects.all() model_form = forms.VRFCSVForm table = tables.VRFTable -class VRFBulkEditView(BulkEditView): +class VRFBulkEditView(generic.BulkEditView): queryset = VRF.objects.prefetch_related('tenant') filterset = filters.VRFFilterSet table = tables.VRFTable form = forms.VRFBulkEditForm -class VRFBulkDeleteView(BulkDeleteView): +class VRFBulkDeleteView(generic.BulkDeleteView): queryset = VRF.objects.prefetch_related('tenant') filterset = filters.VRFFilterSet table = tables.VRFTable +# +# Route targets +# + +class RouteTargetListView(generic.ObjectListView): + queryset = RouteTarget.objects.all() + filterset = filters.RouteTargetFilterSet + filterset_form = forms.RouteTargetFilterForm + table = tables.RouteTargetTable + + +class RouteTargetView(generic.ObjectView): + queryset = RouteTarget.objects.all() + + def get_extra_context(self, request, instance): + importing_vrfs_table = tables.VRFTable( + instance.importing_vrfs.prefetch_related('tenant'), + orderable=False + ) + exporting_vrfs_table = tables.VRFTable( + instance.exporting_vrfs.prefetch_related('tenant'), + orderable=False + ) + + return { + 'importing_vrfs_table': importing_vrfs_table, + 'exporting_vrfs_table': exporting_vrfs_table, + } + + +class RouteTargetEditView(generic.ObjectEditView): + queryset = RouteTarget.objects.all() + model_form = forms.RouteTargetForm + + +class RouteTargetDeleteView(generic.ObjectDeleteView): + queryset = RouteTarget.objects.all() + + +class RouteTargetBulkImportView(generic.BulkImportView): + queryset = RouteTarget.objects.all() + model_form = forms.RouteTargetCSVForm + table = tables.RouteTargetTable + + +class RouteTargetBulkEditView(generic.BulkEditView): + queryset = RouteTarget.objects.prefetch_related('tenant') + filterset = filters.RouteTargetFilterSet + table = tables.RouteTargetTable + form = forms.RouteTargetBulkEditForm + + +class RouteTargetBulkDeleteView(generic.BulkDeleteView): + queryset = RouteTarget.objects.prefetch_related('tenant') + filterset = filters.RouteTargetFilterSet + table = tables.RouteTargetTable + + # # RIRs # -class RIRListView(ObjectListView): +class RIRListView(generic.ObjectListView): queryset = RIR.objects.annotate( aggregate_count=get_subquery(Aggregate, 'rir') ) filterset = filters.RIRFilterSet filterset_form = forms.RIRFilterForm - table = tables.RIRDetailTable + table = tables.RIRTable template_name = 'ipam/rir_list.html' - def alter_queryset(self, request): - - if request.GET.get('family') == '6': - family = 6 - denominator = 2 ** 64 # Count /64s for IPv6 rather than individual IPs - else: - family = 4 - denominator = 1 - - rirs = [] - for rir in self.queryset: - - stats = { - 'total': 0, - 'active': 0, - 'reserved': 0, - 'deprecated': 0, - 'available': 0, - } - aggregate_list = Aggregate.objects.restrict(request.user).filter(prefix__family=family, rir=rir) - for aggregate in aggregate_list: - - queryset = Prefix.objects.restrict(request.user).filter( - prefix__net_contained_or_equal=str(aggregate.prefix) - ) - - # Find all consumed space for each prefix status (we ignore containers for this purpose). - active_prefixes = netaddr.cidr_merge( - [p.prefix for p in queryset.filter(status=PrefixStatusChoices.STATUS_ACTIVE)] - ) - reserved_prefixes = netaddr.cidr_merge( - [p.prefix for p in queryset.filter(status=PrefixStatusChoices.STATUS_RESERVED)] - ) - deprecated_prefixes = netaddr.cidr_merge( - [p.prefix for p in queryset.filter(status=PrefixStatusChoices.STATUS_DEPRECATED)] - ) - - # Find all available prefixes by subtracting each of the existing prefix sets from the aggregate prefix. - available_prefixes = ( - netaddr.IPSet([aggregate.prefix]) - - netaddr.IPSet(active_prefixes) - - netaddr.IPSet(reserved_prefixes) - - netaddr.IPSet(deprecated_prefixes) - ) - - # Add the size of each metric to the RIR total. - stats['total'] += int(aggregate.prefix.size / denominator) - stats['active'] += int(netaddr.IPSet(active_prefixes).size / denominator) - stats['reserved'] += int(netaddr.IPSet(reserved_prefixes).size / denominator) - stats['deprecated'] += int(netaddr.IPSet(deprecated_prefixes).size / denominator) - stats['available'] += int(available_prefixes.size / denominator) - - # Calculate the percentage of total space for each prefix status. - total = float(stats['total']) - stats['percentages'] = { - 'active': float('{:.2f}'.format(stats['active'] / total * 100)) if total else 0, - 'reserved': float('{:.2f}'.format(stats['reserved'] / total * 100)) if total else 0, - 'deprecated': float('{:.2f}'.format(stats['deprecated'] / total * 100)) if total else 0, - } - stats['percentages']['available'] = ( - 100 - - stats['percentages']['active'] - - stats['percentages']['reserved'] - - stats['percentages']['deprecated'] - ) - rir.stats = stats - rirs.append(rir) - - return rirs - -class RIREditView(ObjectEditView): +class RIREditView(generic.ObjectEditView): queryset = RIR.objects.all() model_form = forms.RIRForm -class RIRDeleteView(ObjectDeleteView): +class RIRDeleteView(generic.ObjectDeleteView): queryset = RIR.objects.all() -class RIRBulkImportView(BulkImportView): +class RIRBulkImportView(generic.BulkImportView): queryset = RIR.objects.all() model_form = forms.RIRCSVForm table = tables.RIRTable -class RIRBulkDeleteView(BulkDeleteView): +class RIRBulkDeleteView(generic.BulkDeleteView): queryset = RIR.objects.annotate( aggregate_count=get_subquery(Aggregate, 'rir') ) @@ -184,8 +175,8 @@ class RIRBulkDeleteView(BulkDeleteView): # Aggregates # -class AggregateListView(ObjectListView): - queryset = Aggregate.objects.prefetch_related('rir').annotate( +class AggregateListView(generic.ObjectListView): + queryset = Aggregate.objects.annotate( child_count=RawSQL('SELECT COUNT(*) FROM ipam_prefix WHERE ipam_prefix.prefix <<= ipam_aggregate.prefix', ()) ) filterset = filters.AggregateFilterSet @@ -210,16 +201,13 @@ def extra_context(self): } -class AggregateView(ObjectView): +class AggregateView(generic.ObjectView): queryset = Aggregate.objects.all() - def get(self, request, pk): - - aggregate = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Find all child prefixes contained by this aggregate child_prefixes = Prefix.objects.restrict(request.user, 'view').filter( - prefix__net_contained_or_equal=str(aggregate.prefix) + prefix__net_contained_or_equal=str(instance.prefix) ).prefetch_related( 'site', 'role' ).order_by( @@ -228,7 +216,7 @@ def get(self, request, pk): # Add available prefixes to the table if requested if request.GET.get('show_available', 'true') == 'true': - child_prefixes = add_available_prefixes(aggregate.prefix, child_prefixes) + child_prefixes = add_available_prefixes(instance.prefix, child_prefixes) prefix_table = tables.PrefixDetailTable(child_prefixes) if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'): @@ -247,38 +235,37 @@ def get(self, request, pk): 'delete': request.user.has_perm('ipam.delete_prefix'), } - return render(request, 'ipam/aggregate.html', { - 'aggregate': aggregate, + return { 'prefix_table': prefix_table, 'permissions': permissions, 'show_available': request.GET.get('show_available', 'true') == 'true', - }) + } -class AggregateEditView(ObjectEditView): +class AggregateEditView(generic.ObjectEditView): queryset = Aggregate.objects.all() model_form = forms.AggregateForm template_name = 'ipam/aggregate_edit.html' -class AggregateDeleteView(ObjectDeleteView): +class AggregateDeleteView(generic.ObjectDeleteView): queryset = Aggregate.objects.all() -class AggregateBulkImportView(BulkImportView): +class AggregateBulkImportView(generic.BulkImportView): queryset = Aggregate.objects.all() model_form = forms.AggregateCSVForm table = tables.AggregateTable -class AggregateBulkEditView(BulkEditView): +class AggregateBulkEditView(generic.BulkEditView): queryset = Aggregate.objects.prefetch_related('rir') filterset = filters.AggregateFilterSet table = tables.AggregateTable form = forms.AggregateBulkEditForm -class AggregateBulkDeleteView(BulkDeleteView): +class AggregateBulkDeleteView(generic.BulkDeleteView): queryset = Aggregate.objects.prefetch_related('rir') filterset = filters.AggregateFilterSet table = tables.AggregateTable @@ -288,7 +275,7 @@ class AggregateBulkDeleteView(BulkDeleteView): # Prefix/VLAN roles # -class RoleListView(ObjectListView): +class RoleListView(generic.ObjectListView): queryset = Role.objects.annotate( prefix_count=get_subquery(Prefix, 'role'), vlan_count=get_subquery(VLAN, 'role') @@ -296,22 +283,22 @@ class RoleListView(ObjectListView): table = tables.RoleTable -class RoleEditView(ObjectEditView): +class RoleEditView(generic.ObjectEditView): queryset = Role.objects.all() model_form = forms.RoleForm -class RoleDeleteView(ObjectDeleteView): +class RoleDeleteView(generic.ObjectDeleteView): queryset = Role.objects.all() -class RoleBulkImportView(BulkImportView): +class RoleBulkImportView(generic.BulkImportView): queryset = Role.objects.all() model_form = forms.RoleCSVForm table = tables.RoleTable -class RoleBulkDeleteView(BulkDeleteView): +class RoleBulkDeleteView(generic.BulkDeleteView): queryset = Role.objects.all() table = tables.RoleTable @@ -320,33 +307,30 @@ class RoleBulkDeleteView(BulkDeleteView): # Prefixes # -class PrefixListView(ObjectListView): - queryset = Prefix.objects.prefetch_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role').annotate_tree() +class PrefixListView(generic.ObjectListView): + queryset = Prefix.objects.annotate_tree() filterset = filters.PrefixFilterSet filterset_form = forms.PrefixFilterForm table = tables.PrefixDetailTable template_name = 'ipam/prefix_list.html' -class PrefixView(ObjectView): +class PrefixView(generic.ObjectView): queryset = Prefix.objects.prefetch_related('vrf', 'site__region', 'tenant__group', 'vlan__group', 'role') - def get(self, request, pk): - - prefix = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): try: aggregate = Aggregate.objects.restrict(request.user, 'view').get( - prefix__net_contains_or_equals=str(prefix.prefix) + prefix__net_contains_or_equals=str(instance.prefix) ) except Aggregate.DoesNotExist: aggregate = None # Parent prefixes table parent_prefixes = Prefix.objects.restrict(request.user, 'view').filter( - Q(vrf=prefix.vrf) | Q(vrf__isnull=True) + Q(vrf=instance.vrf) | Q(vrf__isnull=True) ).filter( - prefix__net_contains=str(prefix.prefix) + prefix__net_contains=str(instance.prefix) ).prefetch_related( 'site', 'role' ).annotate_tree() @@ -355,38 +339,35 @@ def get(self, request, pk): # Duplicate prefixes table duplicate_prefixes = Prefix.objects.restrict(request.user, 'view').filter( - vrf=prefix.vrf, prefix=str(prefix.prefix) + vrf=instance.vrf, prefix=str(instance.prefix) ).exclude( - pk=prefix.pk + pk=instance.pk ).prefetch_related( 'site', 'role' ) duplicate_prefix_table = tables.PrefixTable(list(duplicate_prefixes), orderable=False) duplicate_prefix_table.exclude = ('vrf',) - return render(request, 'ipam/prefix.html', { - 'prefix': prefix, + return { 'aggregate': aggregate, 'parent_prefix_table': parent_prefix_table, 'duplicate_prefix_table': duplicate_prefix_table, - }) + } -class PrefixPrefixesView(ObjectView): +class PrefixPrefixesView(generic.ObjectView): queryset = Prefix.objects.all() + template_name = 'ipam/prefix_prefixes.html' - def get(self, request, pk): - - prefix = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Child prefixes table - child_prefixes = prefix.get_child_prefixes().restrict(request.user, 'view').prefetch_related( + child_prefixes = instance.get_child_prefixes().restrict(request.user, 'view').prefetch_related( 'site', 'vlan', 'role', ).annotate_tree() # Add available prefixes to the table if requested if child_prefixes and request.GET.get('show_available', 'true') == 'true': - child_prefixes = add_available_prefixes(prefix.prefix, child_prefixes) + child_prefixes = add_available_prefixes(instance.prefix, child_prefixes) prefix_table = tables.PrefixDetailTable(child_prefixes) if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'): @@ -405,32 +386,31 @@ def get(self, request, pk): 'delete': request.user.has_perm('ipam.delete_prefix'), } - return render(request, 'ipam/prefix_prefixes.html', { - 'prefix': prefix, - 'first_available_prefix': prefix.get_first_available_prefix(), + bulk_querystring = 'vrf_id={}&within={}'.format(instance.vrf.pk if instance.vrf else '0', instance.prefix) + + return { + 'first_available_prefix': instance.get_first_available_prefix(), 'prefix_table': prefix_table, 'permissions': permissions, - 'bulk_querystring': 'vrf_id={}&within={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), + 'bulk_querystring': bulk_querystring, 'active_tab': 'prefixes', 'show_available': request.GET.get('show_available', 'true') == 'true', - }) + } -class PrefixIPAddressesView(ObjectView): +class PrefixIPAddressesView(generic.ObjectView): queryset = Prefix.objects.all() + template_name = 'ipam/prefix_ipaddresses.html' - def get(self, request, pk): - - prefix = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Find all IPAddresses belonging to this Prefix - ipaddresses = prefix.get_child_ips().restrict(request.user, 'view').prefetch_related( + ipaddresses = instance.get_child_ips().restrict(request.user, 'view').prefetch_related( 'vrf', 'primary_ip4_for', 'primary_ip6_for' ) # Add available IP addresses to the table if requested if request.GET.get('show_available', 'true') == 'true': - ipaddresses = add_available_ipaddresses(prefix.prefix, ipaddresses, prefix.is_pool) + ipaddresses = add_available_ipaddresses(instance.prefix, ipaddresses, instance.is_pool) ip_table = tables.IPAddressTable(ipaddresses) if request.user.has_perm('ipam.change_ipaddress') or request.user.has_perm('ipam.delete_ipaddress'): @@ -449,42 +429,43 @@ def get(self, request, pk): 'delete': request.user.has_perm('ipam.delete_ipaddress'), } - return render(request, 'ipam/prefix_ipaddresses.html', { - 'prefix': prefix, - 'first_available_ip': prefix.get_first_available_ip(), + bulk_querystring = 'vrf_id={}&parent={}'.format(instance.vrf.pk if instance.vrf else '0', instance.prefix) + + return { + 'first_available_ip': instance.get_first_available_ip(), 'ip_table': ip_table, 'permissions': permissions, - 'bulk_querystring': 'vrf_id={}&parent={}'.format(prefix.vrf.pk if prefix.vrf else '0', prefix.prefix), + 'bulk_querystring': bulk_querystring, 'active_tab': 'ip-addresses', 'show_available': request.GET.get('show_available', 'true') == 'true', - }) + } -class PrefixEditView(ObjectEditView): +class PrefixEditView(generic.ObjectEditView): queryset = Prefix.objects.all() model_form = forms.PrefixForm template_name = 'ipam/prefix_edit.html' -class PrefixDeleteView(ObjectDeleteView): +class PrefixDeleteView(generic.ObjectDeleteView): queryset = Prefix.objects.all() template_name = 'ipam/prefix_delete.html' -class PrefixBulkImportView(BulkImportView): +class PrefixBulkImportView(generic.BulkImportView): queryset = Prefix.objects.all() model_form = forms.PrefixCSVForm table = tables.PrefixTable -class PrefixBulkEditView(BulkEditView): +class PrefixBulkEditView(generic.BulkEditView): queryset = Prefix.objects.prefetch_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role') filterset = filters.PrefixFilterSet table = tables.PrefixTable form = forms.PrefixBulkEditForm -class PrefixBulkDeleteView(BulkDeleteView): +class PrefixBulkDeleteView(generic.BulkDeleteView): queryset = Prefix.objects.prefetch_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role') filterset = filters.PrefixFilterSet table = tables.PrefixTable @@ -494,25 +475,21 @@ class PrefixBulkDeleteView(BulkDeleteView): # IP addresses # -class IPAddressListView(ObjectListView): - queryset = IPAddress.objects.prefetch_related( - 'vrf__tenant', 'tenant', 'nat_inside', 'assigned_object' - ) +class IPAddressListView(generic.ObjectListView): + queryset = IPAddress.objects.all() filterset = filters.IPAddressFilterSet filterset_form = forms.IPAddressFilterForm table = tables.IPAddressDetailTable -class IPAddressView(ObjectView): +class IPAddressView(generic.ObjectView): queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant') - def get(self, request, pk): - - ipaddress = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Parent prefixes table parent_prefixes = Prefix.objects.restrict(request.user, 'view').filter( - vrf=ipaddress.vrf, prefix__net_contains=str(ipaddress.address.ip) + vrf=instance.vrf, + prefix__net_contains=str(instance.address.ip) ).prefetch_related( 'site', 'role' ) @@ -521,23 +498,24 @@ def get(self, request, pk): # Duplicate IPs table duplicate_ips = IPAddress.objects.restrict(request.user, 'view').filter( - vrf=ipaddress.vrf, address=str(ipaddress.address) + vrf=instance.vrf, + address=str(instance.address) ).exclude( - pk=ipaddress.pk + pk=instance.pk ).prefetch_related( 'nat_inside' ) # Exclude anycast IPs if this IP is anycast - if ipaddress.role == IPAddressRoleChoices.ROLE_ANYCAST: + if instance.role == IPAddressRoleChoices.ROLE_ANYCAST: duplicate_ips = duplicate_ips.exclude(role=IPAddressRoleChoices.ROLE_ANYCAST) # Limit to a maximum of 10 duplicates displayed here duplicate_ips_table = tables.IPAddressTable(duplicate_ips[:10], orderable=False) # Related IP table related_ips = IPAddress.objects.restrict(request.user, 'view').exclude( - address=str(ipaddress.address) + address=str(instance.address) ).filter( - vrf=ipaddress.vrf, address__net_contained_or_equal=str(ipaddress.address) + vrf=instance.vrf, address__net_contained_or_equal=str(instance.address) ) related_ips_table = tables.IPAddressTable(related_ips, orderable=False) @@ -547,16 +525,15 @@ def get(self, request, pk): } RequestConfig(request, paginate).configure(related_ips_table) - return render(request, 'ipam/ipaddress.html', { - 'ipaddress': ipaddress, + return { 'parent_prefixes_table': parent_prefixes_table, 'duplicate_ips_table': duplicate_ips_table, 'more_duplicate_ips': duplicate_ips.count() > 10, 'related_ips_table': related_ips_table, - }) + } -class IPAddressEditView(ObjectEditView): +class IPAddressEditView(generic.ObjectEditView): queryset = IPAddress.objects.all() model_form = forms.IPAddressForm template_name = 'ipam/ipaddress_edit.html' @@ -578,7 +555,8 @@ def alter_obj(self, obj, request, url_args, url_kwargs): return obj -class IPAddressAssignView(ObjectView): +# TODO: Standardize or remove this view +class IPAddressAssignView(generic.ObjectView): """ Search for IPAddresses to be assigned to an Interface. """ @@ -618,11 +596,11 @@ def post(self, request): }) -class IPAddressDeleteView(ObjectDeleteView): +class IPAddressDeleteView(generic.ObjectDeleteView): queryset = IPAddress.objects.all() -class IPAddressBulkCreateView(BulkCreateView): +class IPAddressBulkCreateView(generic.BulkCreateView): queryset = IPAddress.objects.all() form = forms.IPAddressBulkCreateForm model_form = forms.IPAddressBulkAddForm @@ -630,20 +608,20 @@ class IPAddressBulkCreateView(BulkCreateView): template_name = 'ipam/ipaddress_bulk_add.html' -class IPAddressBulkImportView(BulkImportView): +class IPAddressBulkImportView(generic.BulkImportView): queryset = IPAddress.objects.all() model_form = forms.IPAddressCSVForm table = tables.IPAddressTable -class IPAddressBulkEditView(BulkEditView): +class IPAddressBulkEditView(generic.BulkEditView): queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant') filterset = filters.IPAddressFilterSet table = tables.IPAddressTable form = forms.IPAddressBulkEditForm -class IPAddressBulkDeleteView(BulkDeleteView): +class IPAddressBulkDeleteView(generic.BulkDeleteView): queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant') filterset = filters.IPAddressFilterSet table = tables.IPAddressTable @@ -653,7 +631,7 @@ class IPAddressBulkDeleteView(BulkDeleteView): # VLAN groups # -class VLANGroupListView(ObjectListView): +class VLANGroupListView(generic.ObjectListView): queryset = VLANGroup.objects.prefetch_related('site').annotate( vlan_count=get_subquery(VLAN, 'group') ) @@ -662,22 +640,22 @@ class VLANGroupListView(ObjectListView): table = tables.VLANGroupTable -class VLANGroupEditView(ObjectEditView): +class VLANGroupEditView(generic.ObjectEditView): queryset = VLANGroup.objects.all() model_form = forms.VLANGroupForm -class VLANGroupDeleteView(ObjectDeleteView): +class VLANGroupDeleteView(generic.ObjectDeleteView): queryset = VLANGroup.objects.all() -class VLANGroupBulkImportView(BulkImportView): +class VLANGroupBulkImportView(generic.BulkImportView): queryset = VLANGroup.objects.all() model_form = forms.VLANGroupCSVForm table = tables.VLANGroupTable -class VLANGroupBulkDeleteView(BulkDeleteView): +class VLANGroupBulkDeleteView(generic.BulkDeleteView): queryset = VLANGroup.objects.prefetch_related('site').annotate( vlan_count=get_subquery(VLAN, 'group') ) @@ -685,16 +663,15 @@ class VLANGroupBulkDeleteView(BulkDeleteView): table = tables.VLANGroupTable -class VLANGroupVLANsView(ObjectView): +class VLANGroupVLANsView(generic.ObjectView): queryset = VLANGroup.objects.all() + template_name = 'ipam/vlangroup_vlans.html' - def get(self, request, pk): - vlan_group = get_object_or_404(self.queryset, pk=pk) - - vlans = VLAN.objects.restrict(request.user, 'view').filter(group_id=pk).prefetch_related( + def get_extra_context(self, request, instance): + vlans = VLAN.objects.restrict(request.user, 'view').filter(group=instance).prefetch_related( Prefetch('prefixes', queryset=Prefix.objects.restrict(request.user)) ) - vlans = add_available_vlans(vlan_group, vlans) + vlans = add_available_vlans(instance, vlans) vlan_table = tables.VLANDetailTable(vlans) if request.user.has_perm('ipam.change_vlan') or request.user.has_perm('ipam.delete_vlan'): @@ -715,52 +692,46 @@ def get(self, request, pk): 'delete': request.user.has_perm('ipam.delete_vlan'), } - return render(request, 'ipam/vlangroup_vlans.html', { - 'vlan_group': vlan_group, - 'first_available_vlan': vlan_group.get_next_available_vid(), - 'bulk_querystring': 'group_id={}'.format(vlan_group.pk), + return { + 'first_available_vlan': instance.get_next_available_vid(), + 'bulk_querystring': f'group_id={instance.pk}', 'vlan_table': vlan_table, 'permissions': permissions, - }) + } # # VLANs # -class VLANListView(ObjectListView): - queryset = VLAN.objects.prefetch_related( - 'site', 'group', 'tenant', 'role', 'prefixes' - ) +class VLANListView(generic.ObjectListView): + queryset = VLAN.objects.all() filterset = filters.VLANFilterSet filterset_form = forms.VLANFilterForm table = tables.VLANDetailTable -class VLANView(ObjectView): +class VLANView(generic.ObjectView): queryset = VLAN.objects.prefetch_related('site__region', 'tenant__group', 'role') - def get(self, request, pk): - - vlan = get_object_or_404(self.queryset, pk=pk) - prefixes = Prefix.objects.restrict(request.user, 'view').filter(vlan=vlan).prefetch_related( + def get_extra_context(self, request, instance): + prefixes = Prefix.objects.restrict(request.user, 'view').filter(vlan=instance).prefetch_related( 'vrf', 'site', 'role' ) prefix_table = tables.PrefixTable(list(prefixes), orderable=False) prefix_table.exclude = ('vlan',) - return render(request, 'ipam/vlan.html', { - 'vlan': vlan, + return { 'prefix_table': prefix_table, - }) + } -class VLANInterfacesView(ObjectView): +class VLANInterfacesView(generic.ObjectView): queryset = VLAN.objects.all() + template_name = 'ipam/vlan_interfaces.html' - def get(self, request, pk): - vlan = get_object_or_404(self.queryset, pk=pk) - interfaces = vlan.get_interfaces().prefetch_related('device') + def get_extra_context(self, request, instance): + interfaces = instance.get_interfaces().prefetch_related('device') members_table = tables.VLANDevicesTable(interfaces) paginate = { @@ -769,19 +740,18 @@ def get(self, request, pk): } RequestConfig(request, paginate).configure(members_table) - return render(request, 'ipam/vlan_interfaces.html', { - 'vlan': vlan, + return { 'members_table': members_table, 'active_tab': 'interfaces', - }) + } -class VLANVMInterfacesView(ObjectView): +class VLANVMInterfacesView(generic.ObjectView): queryset = VLAN.objects.all() + template_name = 'ipam/vlan_vminterfaces.html' - def get(self, request, pk): - vlan = get_object_or_404(self.queryset, pk=pk) - interfaces = vlan.get_vminterfaces().prefetch_related('virtual_machine') + def get_extra_context(self, request, instance): + interfaces = instance.get_vminterfaces().prefetch_related('virtual_machine') members_table = tables.VLANVirtualMachinesTable(interfaces) paginate = { @@ -790,37 +760,36 @@ def get(self, request, pk): } RequestConfig(request, paginate).configure(members_table) - return render(request, 'ipam/vlan_vminterfaces.html', { - 'vlan': vlan, + return { 'members_table': members_table, 'active_tab': 'vminterfaces', - }) + } -class VLANEditView(ObjectEditView): +class VLANEditView(generic.ObjectEditView): queryset = VLAN.objects.all() model_form = forms.VLANForm template_name = 'ipam/vlan_edit.html' -class VLANDeleteView(ObjectDeleteView): +class VLANDeleteView(generic.ObjectDeleteView): queryset = VLAN.objects.all() -class VLANBulkImportView(BulkImportView): +class VLANBulkImportView(generic.BulkImportView): queryset = VLAN.objects.all() model_form = forms.VLANCSVForm table = tables.VLANTable -class VLANBulkEditView(BulkEditView): +class VLANBulkEditView(generic.BulkEditView): queryset = VLAN.objects.prefetch_related('site', 'group', 'tenant', 'role') filterset = filters.VLANFilterSet table = tables.VLANTable form = forms.VLANBulkEditForm -class VLANBulkDeleteView(BulkDeleteView): +class VLANBulkDeleteView(generic.BulkDeleteView): queryset = VLAN.objects.prefetch_related('site', 'group', 'tenant', 'role') filterset = filters.VLANFilterSet table = tables.VLANTable @@ -830,27 +799,19 @@ class VLANBulkDeleteView(BulkDeleteView): # Services # -class ServiceListView(ObjectListView): - queryset = Service.objects.prefetch_related('device', 'virtual_machine') +class ServiceListView(generic.ObjectListView): + queryset = Service.objects.all() filterset = filters.ServiceFilterSet filterset_form = forms.ServiceFilterForm table = tables.ServiceTable action_buttons = ('export',) -class ServiceView(ObjectView): +class ServiceView(generic.ObjectView): queryset = Service.objects.prefetch_related('ipaddresses') - def get(self, request, pk): - service = get_object_or_404(self.queryset, pk=pk) - - return render(request, 'ipam/service.html', { - 'service': service, - }) - - -class ServiceEditView(ObjectEditView): +class ServiceEditView(generic.ObjectEditView): queryset = Service.objects.prefetch_related('ipaddresses') model_form = forms.ServiceForm template_name = 'ipam/service_edit.html' @@ -868,28 +829,25 @@ def alter_obj(self, obj, request, url_args, url_kwargs): ) return obj - def get_return_url(self, request, service): - return service.parent.get_absolute_url() - -class ServiceBulkImportView(BulkImportView): +class ServiceBulkImportView(generic.BulkImportView): queryset = Service.objects.all() model_form = forms.ServiceCSVForm table = tables.ServiceTable -class ServiceDeleteView(ObjectDeleteView): +class ServiceDeleteView(generic.ObjectDeleteView): queryset = Service.objects.all() -class ServiceBulkEditView(BulkEditView): +class ServiceBulkEditView(generic.BulkEditView): queryset = Service.objects.prefetch_related('device', 'virtual_machine') filterset = filters.ServiceFilterSet table = tables.ServiceTable form = forms.ServiceBulkEditForm -class ServiceBulkDeleteView(BulkDeleteView): +class ServiceBulkDeleteView(generic.BulkDeleteView): queryset = Service.objects.prefetch_related('device', 'virtual_machine') filterset = filters.ServiceFilterSet table = tables.ServiceTable diff --git a/netbox/netbox/api.py b/netbox/netbox/api.py deleted file mode 100644 index 28403f1818..0000000000 --- a/netbox/netbox/api.py +++ /dev/null @@ -1,193 +0,0 @@ -from django.conf import settings -from django.db.models import QuerySet -from rest_framework import authentication, exceptions -from rest_framework.pagination import LimitOffsetPagination -from rest_framework.permissions import DjangoObjectPermissions, SAFE_METHODS -from rest_framework.renderers import BrowsableAPIRenderer -from rest_framework.utils import formatting - -from users.models import Token - - -# -# Renderers -# - -class FormlessBrowsableAPIRenderer(BrowsableAPIRenderer): - """ - Override the built-in BrowsableAPIRenderer to disable HTML forms. - """ - def show_form_for_method(self, *args, **kwargs): - return False - - def get_filter_form(self, data, view, request): - return None - - -# -# Authentication -# - -class TokenAuthentication(authentication.TokenAuthentication): - """ - A custom authentication scheme which enforces Token expiration times. - """ - model = Token - - def authenticate_credentials(self, key): - model = self.get_model() - try: - token = model.objects.prefetch_related('user').get(key=key) - except model.DoesNotExist: - raise exceptions.AuthenticationFailed("Invalid token") - - # Enforce the Token's expiration time, if one has been set. - if token.is_expired: - raise exceptions.AuthenticationFailed("Token expired") - - if not token.user.is_active: - raise exceptions.AuthenticationFailed("User inactive") - - return token.user, token - - -class TokenPermissions(DjangoObjectPermissions): - """ - Custom permissions handler which extends the built-in DjangoModelPermissions to validate a Token's write ability - for unsafe requests (POST/PUT/PATCH/DELETE). - """ - # Override the stock perm_map to enforce view permissions - perms_map = { - 'GET': ['%(app_label)s.view_%(model_name)s'], - 'OPTIONS': [], - 'HEAD': ['%(app_label)s.view_%(model_name)s'], - 'POST': ['%(app_label)s.add_%(model_name)s'], - 'PUT': ['%(app_label)s.change_%(model_name)s'], - 'PATCH': ['%(app_label)s.change_%(model_name)s'], - 'DELETE': ['%(app_label)s.delete_%(model_name)s'], - } - - def __init__(self): - - # LOGIN_REQUIRED determines whether read-only access is provided to anonymous users. - self.authenticated_users_only = settings.LOGIN_REQUIRED - - super().__init__() - - def _verify_write_permission(self, request): - - # If token authentication is in use, verify that the token allows write operations (for unsafe methods). - if request.method in SAFE_METHODS or request.auth.write_enabled: - return True - - def has_permission(self, request, view): - - # Enforce Token write ability - if isinstance(request.auth, Token) and not self._verify_write_permission(request): - return False - - return super().has_permission(request, view) - - def has_object_permission(self, request, view, obj): - - # Enforce Token write ability - if isinstance(request.auth, Token) and not self._verify_write_permission(request): - return False - - return super().has_object_permission(request, view, obj) - - -# -# Pagination -# - -class OptionalLimitOffsetPagination(LimitOffsetPagination): - """ - Override the stock paginator to allow setting limit=0 to disable pagination for a request. This returns all objects - matching a query, but retains the same format as a paginated request. The limit can only be disabled if - MAX_PAGE_SIZE has been set to 0 or None. - """ - - def paginate_queryset(self, queryset, request, view=None): - - if isinstance(queryset, QuerySet): - self.count = queryset.count() - else: - # We're dealing with an iterable, not a QuerySet - self.count = len(queryset) - - self.limit = self.get_limit(request) - self.offset = self.get_offset(request) - self.request = request - - if self.limit and self.count > self.limit and self.template is not None: - self.display_page_controls = True - - if self.count == 0 or self.offset > self.count: - return list() - - if self.limit: - return list(queryset[self.offset:self.offset + self.limit]) - else: - return list(queryset[self.offset:]) - - def get_limit(self, request): - - if self.limit_query_param: - try: - limit = int(request.query_params[self.limit_query_param]) - if limit < 0: - raise ValueError() - # Enforce maximum page size, if defined - if settings.MAX_PAGE_SIZE: - if limit == 0: - return settings.MAX_PAGE_SIZE - else: - return min(limit, settings.MAX_PAGE_SIZE) - return limit - except (KeyError, ValueError): - pass - - return self.default_limit - - def get_next_link(self): - - # Pagination has been disabled - if not self.limit: - return None - - return super().get_next_link() - - def get_previous_link(self): - - # Pagination has been disabled - if not self.limit: - return None - - return super().get_previous_link() - - -# -# Miscellaneous -# - -def get_view_name(view, suffix=None): - """ - Derive the view name from its associated model, if it has one. Fall back to DRF's built-in `get_view_name`. - """ - if hasattr(view, 'queryset'): - # Determine the model name from the queryset. - name = view.queryset.model._meta.verbose_name - name = ' '.join([w[0].upper() + w[1:] for w in name.split()]) # Capitalize each word - - else: - # Replicate DRF's built-in behavior. - name = view.__class__.__name__ - name = formatting.remove_trailing_string(name, 'View') - name = formatting.remove_trailing_string(name, 'ViewSet') - name = formatting.camelcase_to_spaces(name) - - if suffix: - name += ' ' + suffix - - return name diff --git a/netbox/netbox/api/__init__.py b/netbox/netbox/api/__init__.py new file mode 100644 index 0000000000..78ab7431d5 --- /dev/null +++ b/netbox/netbox/api/__init__.py @@ -0,0 +1,15 @@ +from .fields import ChoiceField, ContentTypeField, SerializedPKRelatedField, TimeZoneField +from .routers import OrderedDefaultRouter +from .serializers import BulkOperationSerializer, ValidatedModelSerializer, WritableNestedSerializer + + +__all__ = ( + 'BulkOperationSerializer', + 'ChoiceField', + 'ContentTypeField', + 'OrderedDefaultRouter', + 'SerializedPKRelatedField', + 'TimeZoneField', + 'ValidatedModelSerializer', + 'WritableNestedSerializer', +) diff --git a/netbox/netbox/api/authentication.py b/netbox/netbox/api/authentication.py new file mode 100644 index 0000000000..1cb32c1e42 --- /dev/null +++ b/netbox/netbox/api/authentication.py @@ -0,0 +1,84 @@ +from django.conf import settings +from rest_framework import authentication, exceptions +from rest_framework.permissions import BasePermission, DjangoObjectPermissions, SAFE_METHODS + +from users.models import Token + + +class TokenAuthentication(authentication.TokenAuthentication): + """ + A custom authentication scheme which enforces Token expiration times. + """ + model = Token + + def authenticate_credentials(self, key): + model = self.get_model() + try: + token = model.objects.prefetch_related('user').get(key=key) + except model.DoesNotExist: + raise exceptions.AuthenticationFailed("Invalid token") + + # Enforce the Token's expiration time, if one has been set. + if token.is_expired: + raise exceptions.AuthenticationFailed("Token expired") + + if not token.user.is_active: + raise exceptions.AuthenticationFailed("User inactive") + + return token.user, token + + +class TokenPermissions(DjangoObjectPermissions): + """ + Custom permissions handler which extends the built-in DjangoModelPermissions to validate a Token's write ability + for unsafe requests (POST/PUT/PATCH/DELETE). + """ + # Override the stock perm_map to enforce view permissions + perms_map = { + 'GET': ['%(app_label)s.view_%(model_name)s'], + 'OPTIONS': [], + 'HEAD': ['%(app_label)s.view_%(model_name)s'], + 'POST': ['%(app_label)s.add_%(model_name)s'], + 'PUT': ['%(app_label)s.change_%(model_name)s'], + 'PATCH': ['%(app_label)s.change_%(model_name)s'], + 'DELETE': ['%(app_label)s.delete_%(model_name)s'], + } + + def __init__(self): + + # LOGIN_REQUIRED determines whether read-only access is provided to anonymous users. + self.authenticated_users_only = settings.LOGIN_REQUIRED + + super().__init__() + + def _verify_write_permission(self, request): + + # If token authentication is in use, verify that the token allows write operations (for unsafe methods). + if request.method in SAFE_METHODS or request.auth.write_enabled: + return True + + def has_permission(self, request, view): + + # Enforce Token write ability + if isinstance(request.auth, Token) and not self._verify_write_permission(request): + return False + + return super().has_permission(request, view) + + def has_object_permission(self, request, view, obj): + + # Enforce Token write ability + if isinstance(request.auth, Token) and not self._verify_write_permission(request): + return False + + return super().has_object_permission(request, view, obj) + + +class IsAuthenticatedOrLoginNotRequired(BasePermission): + """ + Returns True if the user is authenticated or LOGIN_REQUIRED is False. + """ + def has_permission(self, request, view): + if not settings.LOGIN_REQUIRED: + return True + return request.user.is_authenticated diff --git a/netbox/netbox/api/exceptions.py b/netbox/netbox/api/exceptions.py new file mode 100644 index 0000000000..8c62eee4c6 --- /dev/null +++ b/netbox/netbox/api/exceptions.py @@ -0,0 +1,10 @@ +from rest_framework.exceptions import APIException + + +class ServiceUnavailable(APIException): + status_code = 503 + default_detail = "Service temporarily unavailable, please try again later." + + +class SerializerNotFound(Exception): + pass diff --git a/netbox/netbox/api/fields.py b/netbox/netbox/api/fields.py new file mode 100644 index 0000000000..fb3eef76ff --- /dev/null +++ b/netbox/netbox/api/fields.py @@ -0,0 +1,133 @@ +from collections import OrderedDict + +import pytz +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ObjectDoesNotExist +from rest_framework import serializers +from rest_framework.exceptions import ValidationError +from rest_framework.relations import PrimaryKeyRelatedField, RelatedField + + +class ChoiceField(serializers.Field): + """ + Represent a ChoiceField as {'value': , 'label': }. Accepts a single value on write. + + :param choices: An iterable of choices in the form (value, key). + :param allow_blank: Allow blank values in addition to the listed choices. + """ + def __init__(self, choices, allow_blank=False, **kwargs): + self.choiceset = choices + self.allow_blank = allow_blank + self._choices = dict() + + # Unpack grouped choices + for k, v in choices: + if type(v) in [list, tuple]: + for k2, v2 in v: + self._choices[k2] = v2 + else: + self._choices[k] = v + + super().__init__(**kwargs) + + def validate_empty_values(self, data): + # Convert null to an empty string unless allow_null == True + if data is None: + if self.allow_null: + return True, None + else: + data = '' + return super().validate_empty_values(data) + + def to_representation(self, obj): + if obj == '': + return None + return OrderedDict([ + ('value', obj), + ('label', self._choices[obj]) + ]) + + def to_internal_value(self, data): + if data == '': + if self.allow_blank: + return data + raise ValidationError("This field may not be blank.") + + # Provide an explicit error message if the request is trying to write a dict or list + if isinstance(data, (dict, list)): + raise ValidationError('Value must be passed directly (e.g. "foo": 123); do not use a dictionary or list.') + + # Check for string representations of boolean/integer values + if hasattr(data, 'lower'): + if data.lower() == 'true': + data = True + elif data.lower() == 'false': + data = False + else: + try: + data = int(data) + except ValueError: + pass + + try: + if data in self._choices: + return data + except TypeError: # Input is an unhashable type + pass + + raise ValidationError(f"{data} is not a valid choice.") + + @property + def choices(self): + return self._choices + + +class ContentTypeField(RelatedField): + """ + Represent a ContentType as '.' + """ + default_error_messages = { + "does_not_exist": "Invalid content type: {content_type}", + "invalid": "Invalid value. Specify a content type as '.'.", + } + + def to_internal_value(self, data): + try: + app_label, model = data.split('.') + return self.queryset.get(app_label=app_label, model=model) + except ObjectDoesNotExist: + self.fail('does_not_exist', content_type=data) + except (AttributeError, TypeError, ValueError): + self.fail('invalid') + + def to_representation(self, obj): + return f"{obj.app_label}.{obj.model}" + + +class TimeZoneField(serializers.Field): + """ + Represent a pytz time zone. + """ + def to_representation(self, obj): + return obj.zone if obj else None + + def to_internal_value(self, data): + if not data: + return "" + if data not in pytz.common_timezones: + raise ValidationError('Unknown time zone "{}" (see pytz.common_timezones for all options)'.format(data)) + return pytz.timezone(data) + + +class SerializedPKRelatedField(PrimaryKeyRelatedField): + """ + Extends PrimaryKeyRelatedField to return a serialized object on read. This is useful for representing related + objects in a ManyToManyField while still allowing a set of primary keys to be written. + """ + def __init__(self, serializer, **kwargs): + self.serializer = serializer + self.pk_field = kwargs.pop('pk_field', None) + super().__init__(**kwargs) + + def to_representation(self, value): + return self.serializer(value, context={'request': self.context['request']}).data diff --git a/netbox/utilities/metadata.py b/netbox/netbox/api/metadata.py similarity index 94% rename from netbox/utilities/metadata.py rename to netbox/netbox/api/metadata.py index 8fd664d5ac..1d0397e4d6 100644 --- a/netbox/utilities/metadata.py +++ b/netbox/netbox/api/metadata.py @@ -1,6 +1,7 @@ -from rest_framework.metadata import SimpleMetadata from django.utils.encoding import force_str -from utilities.api import ContentTypeField +from rest_framework.metadata import SimpleMetadata + +from netbox.api import ContentTypeField class ContentTypeMetadata(SimpleMetadata): diff --git a/netbox/netbox/api/pagination.py b/netbox/netbox/api/pagination.py new file mode 100644 index 0000000000..d489ce9510 --- /dev/null +++ b/netbox/netbox/api/pagination.py @@ -0,0 +1,69 @@ +from django.conf import settings +from django.db.models import QuerySet +from rest_framework.pagination import LimitOffsetPagination + + +class OptionalLimitOffsetPagination(LimitOffsetPagination): + """ + Override the stock paginator to allow setting limit=0 to disable pagination for a request. This returns all objects + matching a query, but retains the same format as a paginated request. The limit can only be disabled if + MAX_PAGE_SIZE has been set to 0 or None. + """ + + def paginate_queryset(self, queryset, request, view=None): + + if isinstance(queryset, QuerySet): + self.count = queryset.count() + else: + # We're dealing with an iterable, not a QuerySet + self.count = len(queryset) + + self.limit = self.get_limit(request) + self.offset = self.get_offset(request) + self.request = request + + if self.limit and self.count > self.limit and self.template is not None: + self.display_page_controls = True + + if self.count == 0 or self.offset > self.count: + return list() + + if self.limit: + return list(queryset[self.offset:self.offset + self.limit]) + else: + return list(queryset[self.offset:]) + + def get_limit(self, request): + + if self.limit_query_param: + try: + limit = int(request.query_params[self.limit_query_param]) + if limit < 0: + raise ValueError() + # Enforce maximum page size, if defined + if settings.MAX_PAGE_SIZE: + if limit == 0: + return settings.MAX_PAGE_SIZE + else: + return min(limit, settings.MAX_PAGE_SIZE) + return limit + except (KeyError, ValueError): + pass + + return self.default_limit + + def get_next_link(self): + + # Pagination has been disabled + if not self.limit: + return None + + return super().get_next_link() + + def get_previous_link(self): + + # Pagination has been disabled + if not self.limit: + return None + + return super().get_previous_link() diff --git a/netbox/netbox/api/renderers.py b/netbox/netbox/api/renderers.py new file mode 100644 index 0000000000..c492510fb6 --- /dev/null +++ b/netbox/netbox/api/renderers.py @@ -0,0 +1,12 @@ +from rest_framework.renderers import BrowsableAPIRenderer + + +class FormlessBrowsableAPIRenderer(BrowsableAPIRenderer): + """ + Override the built-in BrowsableAPIRenderer to disable HTML forms. + """ + def show_form_for_method(self, *args, **kwargs): + return False + + def get_filter_form(self, data, view, request): + return None diff --git a/netbox/netbox/api/routers.py b/netbox/netbox/api/routers.py new file mode 100644 index 0000000000..71df1796e8 --- /dev/null +++ b/netbox/netbox/api/routers.py @@ -0,0 +1,27 @@ +from collections import OrderedDict + +from rest_framework.routers import DefaultRouter + + +class OrderedDefaultRouter(DefaultRouter): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Extend the list view mappings to support the DELETE operation + self.routes[0].mapping.update({ + 'put': 'bulk_update', + 'patch': 'bulk_partial_update', + 'delete': 'bulk_destroy', + }) + + def get_api_root_view(self, api_urls=None): + """ + Wrap DRF's DefaultRouter to return an alphabetized list of endpoints. + """ + api_root_dict = OrderedDict() + list_name = self.routes[0].name + for prefix, viewset, basename in sorted(self.registry, key=lambda x: x[0]): + api_root_dict[prefix] = list_name.format(basename=basename) + + return self.APIRootView.as_view(api_root_dict=api_root_dict) diff --git a/netbox/netbox/api/serializers.py b/netbox/netbox/api/serializers.py new file mode 100644 index 0000000000..3a8641efcb --- /dev/null +++ b/netbox/netbox/api/serializers.py @@ -0,0 +1,89 @@ +from django.core.exceptions import FieldError, MultipleObjectsReturned, ObjectDoesNotExist +from django.db.models import ManyToManyField +from rest_framework import serializers +from rest_framework.exceptions import ValidationError + +from utilities.utils import dict_to_filter_params + + +class ValidatedModelSerializer(serializers.ModelSerializer): + """ + Extends the built-in ModelSerializer to enforce calling full_clean() on a copy of the associated instance during + validation. (DRF does not do this by default; see https://github.com/encode/django-rest-framework/issues/3144) + """ + def validate(self, data): + + # Remove custom fields data and tags (if any) prior to model validation + attrs = data.copy() + attrs.pop('custom_fields', None) + attrs.pop('tags', None) + + # Skip ManyToManyFields + for field in self.Meta.model._meta.get_fields(): + if isinstance(field, ManyToManyField): + attrs.pop(field.name, None) + + # Run clean() on an instance of the model + if self.instance is None: + instance = self.Meta.model(**attrs) + else: + instance = self.instance + for k, v in attrs.items(): + setattr(instance, k, v) + instance.full_clean() + + return data + + +class WritableNestedSerializer(serializers.ModelSerializer): + """ + Returns a nested representation of an object on read, but accepts only a primary key on write. + """ + + def to_internal_value(self, data): + + if data is None: + return None + + # Dictionary of related object attributes + if isinstance(data, dict): + params = dict_to_filter_params(data) + queryset = self.Meta.model.objects + try: + return queryset.get(**params) + except ObjectDoesNotExist: + raise ValidationError( + "Related object not found using the provided attributes: {}".format(params) + ) + except MultipleObjectsReturned: + raise ValidationError( + "Multiple objects match the provided attributes: {}".format(params) + ) + except FieldError as e: + raise ValidationError(e) + + # Integer PK of related object + if isinstance(data, int): + pk = data + else: + try: + # PK might have been mistakenly passed as a string + pk = int(data) + except (TypeError, ValueError): + raise ValidationError( + "Related objects must be referenced by numeric ID or by dictionary of attributes. Received an " + "unrecognized value: {}".format(data) + ) + + # Look up object by PK + queryset = self.Meta.model.objects + try: + return queryset.get(pk=int(data)) + except ObjectDoesNotExist: + raise ValidationError( + "Related object not found using the provided numeric ID: {}".format(pk) + ) + + +class BulkOperationSerializer(serializers.Serializer): + id = serializers.IntegerField() diff --git a/netbox/netbox/api/views.py b/netbox/netbox/api/views.py new file mode 100644 index 0000000000..881effd711 --- /dev/null +++ b/netbox/netbox/api/views.py @@ -0,0 +1,301 @@ +import logging +import platform +from collections import OrderedDict + +from django import __version__ as DJANGO_VERSION +from django.apps import apps +from django.conf import settings +from django.core.exceptions import ObjectDoesNotExist, PermissionDenied +from django.db import transaction +from django.db.models import ProtectedError +from django_rq.queues import get_connection +from rest_framework import mixins, status +from rest_framework.response import Response +from rest_framework.reverse import reverse +from rest_framework.views import APIView +from rest_framework.viewsets import GenericViewSet +from rq.worker import Worker + +from netbox.api import BulkOperationSerializer +from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired +from netbox.api.exceptions import SerializerNotFound +from utilities.api import get_serializer_for_model + +HTTP_ACTIONS = { + 'GET': 'view', + 'OPTIONS': None, + 'HEAD': 'view', + 'POST': 'add', + 'PUT': 'change', + 'PATCH': 'change', + 'DELETE': 'delete', +} + + +# +# Mixins +# + +class BulkUpdateModelMixin: + """ + Support bulk modification of objects using the list endpoint for a model. Accepts a PATCH action with a list of one + or more JSON objects, each specifying the numeric ID of an object to be updated as well as the attributes to be set. + For example: + + PATCH /api/dcim/sites/ + [ + { + "id": 123, + "name": "New name" + }, + { + "id": 456, + "status": "planned" + } + ] + """ + def bulk_update(self, request, *args, **kwargs): + partial = kwargs.pop('partial', False) + serializer = BulkOperationSerializer(data=request.data, many=True) + serializer.is_valid(raise_exception=True) + qs = self.get_queryset().filter( + pk__in=[o['id'] for o in serializer.data] + ) + + # Map update data by object ID + update_data = { + obj.pop('id'): obj for obj in request.data + } + + data = self.perform_bulk_update(qs, update_data, partial=partial) + + return Response(data, status=status.HTTP_200_OK) + + def perform_bulk_update(self, objects, update_data, partial): + with transaction.atomic(): + data_list = [] + for obj in objects: + data = update_data.get(obj.id) + serializer = self.get_serializer(obj, data=data, partial=partial) + serializer.is_valid(raise_exception=True) + self.perform_update(serializer) + data_list.append(serializer.data) + + return data_list + + def bulk_partial_update(self, request, *args, **kwargs): + kwargs['partial'] = True + return self.bulk_update(request, *args, **kwargs) + + +class BulkDestroyModelMixin: + """ + Support bulk deletion of objects using the list endpoint for a model. Accepts a DELETE action with a list of one + or more JSON objects, each specifying the numeric ID of an object to be deleted. For example: + + DELETE /api/dcim/sites/ + [ + {"id": 123}, + {"id": 456} + ] + """ + def bulk_destroy(self, request, *args, **kwargs): + serializer = BulkOperationSerializer(data=request.data, many=True) + serializer.is_valid(raise_exception=True) + qs = self.get_queryset().filter( + pk__in=[o['id'] for o in serializer.data] + ) + + self.perform_bulk_destroy(qs) + + return Response(status=status.HTTP_204_NO_CONTENT) + + def perform_bulk_destroy(self, objects): + with transaction.atomic(): + for obj in objects: + self.perform_destroy(obj) + + +# +# Viewsets +# + +class ModelViewSet(mixins.CreateModelMixin, + mixins.RetrieveModelMixin, + mixins.UpdateModelMixin, + mixins.DestroyModelMixin, + mixins.ListModelMixin, + BulkUpdateModelMixin, + BulkDestroyModelMixin, + GenericViewSet): + """ + Accept either a single object or a list of objects to create. + """ + def get_serializer(self, *args, **kwargs): + + # If a list of objects has been provided, initialize the serializer with many=True + if isinstance(kwargs.get('data', {}), list): + kwargs['many'] = True + + return super().get_serializer(*args, **kwargs) + + def get_serializer_class(self): + logger = logging.getLogger('netbox.api.views.ModelViewSet') + + # If 'brief' has been passed as a query param, find and return the nested serializer for this model, if one + # exists + request = self.get_serializer_context()['request'] + if request.query_params.get('brief'): + logger.debug("Request is for 'brief' format; initializing nested serializer") + try: + serializer = get_serializer_for_model(self.queryset.model, prefix='Nested') + logger.debug(f"Using serializer {serializer}") + return serializer + except SerializerNotFound: + pass + + # Fall back to the hard-coded serializer class + logger.debug(f"Using serializer {self.serializer_class}") + return self.serializer_class + + def initial(self, request, *args, **kwargs): + super().initial(request, *args, **kwargs) + + if not request.user.is_authenticated: + return + + # Restrict the view's QuerySet to allow only the permitted objects + action = HTTP_ACTIONS[request.method] + if action: + self.queryset = self.queryset.restrict(request.user, action) + + def dispatch(self, request, *args, **kwargs): + logger = logging.getLogger('netbox.api.views.ModelViewSet') + + try: + return super().dispatch(request, *args, **kwargs) + except ProtectedError as e: + protected_objects = list(e.protected_objects) + msg = f'Unable to delete object. {len(protected_objects)} dependent objects were found: ' + msg += ', '.join([f'{obj} ({obj.pk})' for obj in protected_objects]) + logger.warning(msg) + return self.finalize_response( + request, + Response({'detail': msg}, status=409), + *args, + **kwargs + ) + + def _validate_objects(self, instance): + """ + Check that the provided instance or list of instances are matched by the current queryset. This confirms that + any newly created or modified objects abide by the attributes granted by any applicable ObjectPermissions. + """ + if type(instance) is list: + # Check that all instances are still included in the view's queryset + conforming_count = self.queryset.filter(pk__in=[obj.pk for obj in instance]).count() + if conforming_count != len(instance): + raise ObjectDoesNotExist + else: + # Check that the instance is matched by the view's queryset + self.queryset.get(pk=instance.pk) + + def perform_create(self, serializer): + model = self.queryset.model + logger = logging.getLogger('netbox.api.views.ModelViewSet') + logger.info(f"Creating new {model._meta.verbose_name}") + + # Enforce object-level permissions on save() + try: + with transaction.atomic(): + instance = serializer.save() + self._validate_objects(instance) + except ObjectDoesNotExist: + raise PermissionDenied() + + def perform_update(self, serializer): + model = self.queryset.model + logger = logging.getLogger('netbox.api.views.ModelViewSet') + logger.info(f"Updating {model._meta.verbose_name} {serializer.instance} (PK: {serializer.instance.pk})") + + # Enforce object-level permissions on save() + try: + with transaction.atomic(): + instance = serializer.save() + self._validate_objects(instance) + except ObjectDoesNotExist: + raise PermissionDenied() + + def perform_destroy(self, instance): + model = self.queryset.model + logger = logging.getLogger('netbox.api.views.ModelViewSet') + logger.info(f"Deleting {model._meta.verbose_name} {instance} (PK: {instance.pk})") + + return super().perform_destroy(instance) + + +# +# Views +# + +class APIRootView(APIView): + """ + This is the root of NetBox's REST API. API endpoints are arranged by app and model name; e.g. `/api/dcim/sites/`. + """ + _ignore_model_permissions = True + exclude_from_schema = True + swagger_schema = None + + def get_view_name(self): + return "API Root" + + def get(self, request, format=None): + + return Response(OrderedDict(( + ('circuits', reverse('circuits-api:api-root', request=request, format=format)), + ('dcim', reverse('dcim-api:api-root', request=request, format=format)), + ('extras', reverse('extras-api:api-root', request=request, format=format)), + ('ipam', reverse('ipam-api:api-root', request=request, format=format)), + ('plugins', reverse('plugins-api:api-root', request=request, format=format)), + ('secrets', reverse('secrets-api:api-root', request=request, format=format)), + ('status', reverse('api-status', request=request, format=format)), + ('tenancy', reverse('tenancy-api:api-root', request=request, format=format)), + ('users', reverse('users-api:api-root', request=request, format=format)), + ('virtualization', reverse('virtualization-api:api-root', request=request, format=format)), + ))) + + +class StatusView(APIView): + """ + A lightweight read-only endpoint for conveying NetBox's current operational status. + """ + permission_classes = [IsAuthenticatedOrLoginNotRequired] + + def get(self, request): + # Gather the version numbers from all installed Django apps + installed_apps = {} + for app_config in apps.get_app_configs(): + app = app_config.module + version = getattr(app, 'VERSION', getattr(app, '__version__', None)) + if version: + if type(version) is tuple: + version = '.'.join(str(n) for n in version) + installed_apps[app_config.name] = version + installed_apps = {k: v for k, v in sorted(installed_apps.items())} + + # Gather installed plugins + plugins = {} + for plugin_name in settings.PLUGINS: + plugin_name = plugin_name.rsplit('.', 1)[-1] + plugin_config = apps.get_app_config(plugin_name) + plugins[plugin_name] = getattr(plugin_config, 'version', None) + plugins = {k: v for k, v in sorted(plugins.items())} + + return Response({ + 'django-version': DJANGO_VERSION, + 'installed-apps': installed_apps, + 'netbox-version': settings.VERSION, + 'plugins': plugins, + 'python-version': platform.python_version(), + 'rq-workers-running': Worker.count(get_connection('default')), + }) diff --git a/netbox/netbox/constants.py b/netbox/netbox/constants.py new file mode 100644 index 0000000000..a074bde4e2 --- /dev/null +++ b/netbox/netbox/constants.py @@ -0,0 +1,174 @@ +from collections import OrderedDict + +from django.db.models import Count + +from circuits.filters import CircuitFilterSet, ProviderFilterSet +from circuits.models import Circuit, Provider +from circuits.tables import CircuitTable, ProviderTable +from dcim.filters import ( + CableFilterSet, DeviceFilterSet, DeviceTypeFilterSet, PowerFeedFilterSet, RackFilterSet, RackGroupFilterSet, + SiteFilterSet, VirtualChassisFilterSet, +) +from dcim.models import Cable, Device, DeviceType, PowerFeed, Rack, RackGroup, Site, VirtualChassis +from dcim.tables import ( + CableTable, DeviceTable, DeviceTypeTable, PowerFeedTable, RackTable, RackGroupTable, SiteTable, + VirtualChassisTable, +) +from ipam.filters import AggregateFilterSet, IPAddressFilterSet, PrefixFilterSet, VLANFilterSet, VRFFilterSet +from ipam.models import Aggregate, IPAddress, Prefix, VLAN, VRF +from ipam.tables import AggregateTable, IPAddressTable, PrefixTable, VLANTable, VRFTable +from secrets.filters import SecretFilterSet +from secrets.models import Secret +from secrets.tables import SecretTable +from tenancy.filters import TenantFilterSet +from tenancy.models import Tenant +from tenancy.tables import TenantTable +from utilities.utils import get_subquery +from virtualization.filters import ClusterFilterSet, VirtualMachineFilterSet +from virtualization.models import Cluster, VirtualMachine +from virtualization.tables import ClusterTable, VirtualMachineDetailTable + +SEARCH_MAX_RESULTS = 15 +SEARCH_TYPES = OrderedDict(( + # Circuits + ('provider', { + 'queryset': Provider.objects.annotate( + count_circuits=get_subquery(Circuit, 'provider') + ), + 'filterset': ProviderFilterSet, + 'table': ProviderTable, + 'url': 'circuits:provider_list', + }), + ('circuit', { + 'queryset': Circuit.objects.prefetch_related( + 'type', 'provider', 'tenant', 'terminations__site' + ).annotate_sites(), + 'filterset': CircuitFilterSet, + 'table': CircuitTable, + 'url': 'circuits:circuit_list', + }), + # DCIM + ('site', { + 'queryset': Site.objects.prefetch_related('region', 'tenant'), + 'filterset': SiteFilterSet, + 'table': SiteTable, + 'url': 'dcim:site_list', + }), + ('rack', { + 'queryset': Rack.objects.prefetch_related('site', 'group', 'tenant', 'role'), + 'filterset': RackFilterSet, + 'table': RackTable, + 'url': 'dcim:rack_list', + }), + ('rackgroup', { + 'queryset': RackGroup.objects.add_related_count( + RackGroup.objects.all(), + Rack, + 'group', + 'rack_count', + cumulative=True + ).prefetch_related('site'), + 'filterset': RackGroupFilterSet, + 'table': RackGroupTable, + 'url': 'dcim:rackgroup_list', + }), + ('devicetype', { + 'queryset': DeviceType.objects.prefetch_related('manufacturer').annotate( + instance_count=get_subquery(Device, 'device_type') + ), + 'filterset': DeviceTypeFilterSet, + 'table': DeviceTypeTable, + 'url': 'dcim:devicetype_list', + }), + ('device', { + 'queryset': Device.objects.prefetch_related( + 'device_type__manufacturer', 'device_role', 'tenant', 'site', 'rack', 'primary_ip4', 'primary_ip6', + ), + 'filterset': DeviceFilterSet, + 'table': DeviceTable, + 'url': 'dcim:device_list', + }), + ('virtualchassis', { + 'queryset': VirtualChassis.objects.prefetch_related('master').annotate( + member_count=get_subquery(Device, 'virtual_chassis') + ), + 'filterset': VirtualChassisFilterSet, + 'table': VirtualChassisTable, + 'url': 'dcim:virtualchassis_list', + }), + ('cable', { + 'queryset': Cable.objects.all(), + 'filterset': CableFilterSet, + 'table': CableTable, + 'url': 'dcim:cable_list', + }), + ('powerfeed', { + 'queryset': PowerFeed.objects.all(), + 'filterset': PowerFeedFilterSet, + 'table': PowerFeedTable, + 'url': 'dcim:powerfeed_list', + }), + # Virtualization + ('cluster', { + 'queryset': Cluster.objects.prefetch_related('type', 'group').annotate( + device_count=get_subquery(Device, 'cluster'), + vm_count=get_subquery(VirtualMachine, 'cluster') + ), + 'filterset': ClusterFilterSet, + 'table': ClusterTable, + 'url': 'virtualization:cluster_list', + }), + ('virtualmachine', { + 'queryset': VirtualMachine.objects.prefetch_related( + 'cluster', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', + ), + 'filterset': VirtualMachineFilterSet, + 'table': VirtualMachineDetailTable, + 'url': 'virtualization:virtualmachine_list', + }), + # IPAM + ('vrf', { + 'queryset': VRF.objects.prefetch_related('tenant'), + 'filterset': VRFFilterSet, + 'table': VRFTable, + 'url': 'ipam:vrf_list', + }), + ('aggregate', { + 'queryset': Aggregate.objects.prefetch_related('rir'), + 'filterset': AggregateFilterSet, + 'table': AggregateTable, + 'url': 'ipam:aggregate_list', + }), + ('prefix', { + 'queryset': Prefix.objects.prefetch_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role'), + 'filterset': PrefixFilterSet, + 'table': PrefixTable, + 'url': 'ipam:prefix_list', + }), + ('ipaddress', { + 'queryset': IPAddress.objects.prefetch_related('vrf__tenant', 'tenant'), + 'filterset': IPAddressFilterSet, + 'table': IPAddressTable, + 'url': 'ipam:ipaddress_list', + }), + ('vlan', { + 'queryset': VLAN.objects.prefetch_related('site', 'group', 'tenant', 'role'), + 'filterset': VLANFilterSet, + 'table': VLANTable, + 'url': 'ipam:vlan_list', + }), + # Secrets + ('secret', { + 'queryset': Secret.objects.prefetch_related('role', 'device'), + 'filterset': SecretFilterSet, + 'table': SecretTable, + 'url': 'secrets:secret_list', + }), + # Tenancy + ('tenant', { + 'queryset': Tenant.objects.prefetch_related('group'), + 'filterset': TenantFilterSet, + 'table': TenantTable, + 'url': 'tenancy:tenant_list', + }), +)) diff --git a/netbox/utilities/context_processors.py b/netbox/netbox/context_processors.py similarity index 100% rename from netbox/utilities/context_processors.py rename to netbox/netbox/context_processors.py diff --git a/netbox/utilities/middleware.py b/netbox/netbox/middleware.py similarity index 70% rename from netbox/utilities/middleware.py rename to netbox/netbox/middleware.py index 605f10e423..1395cbd1fd 100644 --- a/netbox/utilities/middleware.py +++ b/netbox/netbox/middleware.py @@ -1,3 +1,4 @@ +import uuid from urllib import parse from django.conf import settings @@ -6,8 +7,9 @@ from django.http import Http404, HttpResponseRedirect from django.urls import reverse -from .api import is_api_request -from .views import server_error, rest_api_server_error +from extras.context_managers import change_logging +from netbox.views import server_error +from utilities.api import is_api_request, rest_api_server_error class LoginRequiredMiddleware(object): @@ -51,6 +53,35 @@ def process_request(self, request): return super().process_request(request) +class ObjectChangeMiddleware(object): + """ + This middleware performs three functions in response to an object being created, updated, or deleted: + + 1. Create an ObjectChange to reflect the modification to the object in the changelog. + 2. Enqueue any relevant webhooks. + 3. Increment the metric counter for the event type. + + The post_save and post_delete signals are employed to catch object modifications, however changes are recorded a bit + differently for each. Objects being saved are cached into thread-local storage for action *after* the response has + completed. This ensures that serialization of the object is performed only after any related objects (e.g. tags) + have been created. Conversely, deletions are acted upon immediately, so that the serialized representation of the + object is recorded before it (and any related objects) are actually deleted from the database. + """ + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + # Assign a random unique ID to the request. This will be used to associate multiple object changes made during + # the same request. + request.id = uuid.uuid4() + + # Process the request with change logging enabled + with change_logging(request): + response = self.get_response(request) + + return response + + class APIVersionMiddleware(object): """ If the request is for an API endpoint, include the API version as a response header. diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 72e0f4d350..4021b25c69 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -16,7 +16,7 @@ # Environment setup # -VERSION = '2.9.11' +VERSION = '2.10.0' # Hostname HOSTNAME = platform.node() @@ -135,24 +135,6 @@ if RELEASE_CHECK_TIMEOUT < 3600: raise ImproperlyConfigured("RELEASE_CHECK_TIMEOUT has to be at least 3600 seconds (1 hour)") -# TODO: Remove in v2.10 -# Backward compatibility for REMOTE_AUTH_DEFAULT_PERMISSIONS -if type(REMOTE_AUTH_DEFAULT_PERMISSIONS) is not dict: - try: - REMOTE_AUTH_DEFAULT_PERMISSIONS = {perm: None for perm in REMOTE_AUTH_DEFAULT_PERMISSIONS} - warnings.warn( - "REMOTE_AUTH_DEFAULT_PERMISSIONS should be a dictionary. Backward compatibility will be removed in v2.10." - ) - except TypeError: - raise ImproperlyConfigured("REMOTE_AUTH_DEFAULT_PERMISSIONS must be a dictionary.") -# Backward compatibility for REMOTE_AUTH_BACKEND -if REMOTE_AUTH_BACKEND == 'utilities.auth_backends.RemoteUserBackend': - warnings.warn( - "RemoteUserBackend has moved! Please update your configuration to:\n" - " REMOTE_AUTH_BACKEND='netbox.authentication.RemoteUserBackend'" - ) - REMOTE_AUTH_BACKEND = 'netbox.authentication.RemoteUserBackend' - # # Database @@ -229,9 +211,6 @@ def _setting(name, default=None): TASKS_REDIS_PASSWORD = TASKS_REDIS.get('PASSWORD', '') TASKS_REDIS_DATABASE = TASKS_REDIS.get('DATABASE', 0) TASKS_REDIS_SSL = TASKS_REDIS.get('SSL', False) -# TODO: Remove in v2.10 (see #5171) -if 'DEFAULT_TIMEOUT' in TASKS_REDIS: - warnings.warn('DEFAULT_TIMEOUT is no longer supported under REDIS configuration. Set RQ_DEFAULT_TIMEOUT instead.') # Caching if 'caching' not in REDIS: @@ -327,11 +306,11 @@ def _setting(name, default=None): 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.security.SecurityMiddleware', - 'utilities.middleware.ExceptionHandlingMiddleware', - 'utilities.middleware.RemoteUserMiddleware', - 'utilities.middleware.LoginRequiredMiddleware', - 'utilities.middleware.APIVersionMiddleware', - 'extras.middleware.ObjectChangeMiddleware', + 'netbox.middleware.ExceptionHandlingMiddleware', + 'netbox.middleware.RemoteUserMiddleware', + 'netbox.middleware.LoginRequiredMiddleware', + 'netbox.middleware.APIVersionMiddleware', + 'netbox.middleware.ObjectChangeMiddleware', 'django_prometheus.middleware.PrometheusAfterMiddleware', ] @@ -350,7 +329,7 @@ def _setting(name, default=None): 'django.template.context_processors.media', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', - 'utilities.context_processors.settings_and_registry', + 'netbox.context_processors.settings_and_registry', ], }, }, @@ -444,14 +423,15 @@ def _setting(name, default=None): 'auth.*': {'ops': ('fetch', 'get')}, 'auth.permission': {'ops': 'all'}, 'circuits.*': {'ops': 'all'}, - 'dcim.region': None, # MPTT models are exempt due to raw sql - 'dcim.rackgroup': None, # MPTT models are exempt due to raw sql + 'dcim.inventoryitem': None, # MPTT models are exempt due to raw SQL + 'dcim.region': None, # MPTT models are exempt due to raw SQL + 'dcim.rackgroup': None, # MPTT models are exempt due to raw SQL 'dcim.*': {'ops': 'all'}, 'ipam.*': {'ops': 'all'}, 'extras.*': {'ops': 'all'}, 'secrets.*': {'ops': 'all'}, 'users.*': {'ops': 'all'}, - 'tenancy.tenantgroup': None, # MPTT models are exempt due to raw sql + 'tenancy.tenantgroup': None, # MPTT models are exempt due to raw SQL 'tenancy.*': {'ops': 'all'}, 'virtualization.*': {'ops': 'all'}, } @@ -482,23 +462,30 @@ def _setting(name, default=None): 'ALLOWED_VERSIONS': [REST_FRAMEWORK_VERSION], 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', - 'netbox.api.TokenAuthentication', + 'netbox.api.authentication.TokenAuthentication', ), 'DEFAULT_FILTER_BACKENDS': ( 'django_filters.rest_framework.DjangoFilterBackend', ), - 'DEFAULT_PAGINATION_CLASS': 'netbox.api.OptionalLimitOffsetPagination', + 'DEFAULT_PAGINATION_CLASS': 'netbox.api.pagination.OptionalLimitOffsetPagination', 'DEFAULT_PERMISSION_CLASSES': ( - 'netbox.api.TokenPermissions', + 'netbox.api.authentication.TokenPermissions', ), 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework.renderers.JSONRenderer', - 'netbox.api.FormlessBrowsableAPIRenderer', + 'netbox.api.renderers.FormlessBrowsableAPIRenderer', ), 'DEFAULT_VERSION': REST_FRAMEWORK_VERSION, 'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning', 'PAGE_SIZE': PAGINATE_COUNT, - 'VIEW_NAME_FUNCTION': 'netbox.api.get_view_name', + 'SCHEMA_COERCE_METHOD_NAMES': { + # Default mappings + 'retrieve': 'read', + 'destroy': 'delete', + # Custom operations + 'bulk_destroy': 'bulk_delete', + }, + 'VIEW_NAME_FUNCTION': 'utilities.api.get_view_name', } @@ -509,9 +496,10 @@ def _setting(name, default=None): SWAGGER_SETTINGS = { 'DEFAULT_AUTO_SCHEMA_CLASS': 'utilities.custom_inspectors.NetBoxSwaggerAutoSchema', 'DEFAULT_FIELD_INSPECTORS': [ + 'utilities.custom_inspectors.CustomFieldsDataFieldInspector', 'utilities.custom_inspectors.JSONFieldInspector', 'utilities.custom_inspectors.NullableBooleanFieldInspector', - 'utilities.custom_inspectors.CustomChoiceFieldInspector', + 'utilities.custom_inspectors.ChoiceFieldInspector', 'utilities.custom_inspectors.SerializedPKRelatedFieldInspector', 'drf_yasg.inspectors.CamelCaseJSONFilter', 'drf_yasg.inspectors.ReferencingSerializerInspector', diff --git a/netbox/netbox/tests/test_api.py b/netbox/netbox/tests/test_api.py index 0ee2d78dc1..2ea12e72f6 100644 --- a/netbox/netbox/tests/test_api.py +++ b/netbox/netbox/tests/test_api.py @@ -6,8 +6,13 @@ class AppTest(APITestCase): def test_root(self): - url = reverse('api-root') response = self.client.get('{}?format=api'.format(url), **self.header) self.assertEqual(response.status_code, 200) + + def test_status(self): + url = reverse('api-status') + response = self.client.get('{}?format=api'.format(url), **self.header) + + self.assertEqual(response.status_code, 200) diff --git a/netbox/netbox/tests/test_authentication.py b/netbox/netbox/tests/test_authentication.py index 3ae203c296..6b30d044d9 100644 --- a/netbox/netbox/tests/test_authentication.py +++ b/netbox/netbox/tests/test_authentication.py @@ -212,6 +212,7 @@ def test_get_object(self): # Assign object permission obj_perm = ObjectPermission( + name='Test permission', constraints={'site__name': 'Site 1'}, actions=['view'] ) @@ -239,6 +240,7 @@ def test_list_objects(self): # Assign object permission obj_perm = ObjectPermission( + name='Test permission', constraints={'site__name': 'Site 1'}, actions=['view'] ) @@ -266,6 +268,7 @@ def test_create_object(self): # Assign object permission obj_perm = ObjectPermission( + name='Test permission', constraints={'site__name': 'Site 1'}, actions=['add'] ) @@ -295,6 +298,7 @@ def test_edit_object(self): # Assign object permission obj_perm = ObjectPermission( + name='Test permission', constraints={'site__name': 'Site 1'}, actions=['change'] ) @@ -330,6 +334,7 @@ def test_delete_object(self): # Assign object permission obj_perm = ObjectPermission( + name='Test permission', constraints={'site__name': 'Site 1'}, actions=['delete'] ) diff --git a/netbox/netbox/urls.py b/netbox/netbox/urls.py index 4878729b06..8215afe1ca 100644 --- a/netbox/netbox/urls.py +++ b/netbox/netbox/urls.py @@ -6,7 +6,8 @@ from drf_yasg.views import get_schema_view from extras.plugins.urls import plugin_admin_patterns, plugin_patterns, plugin_api_patterns -from netbox.views import APIRootView, HomeView, StaticMediaFailureView, SearchView +from netbox.api.views import APIRootView, StatusView +from netbox.views import HomeView, StaticMediaFailureView, SearchView from users.views import LoginView, LogoutView from .admin import admin_site @@ -55,6 +56,7 @@ path('api/tenancy/', include('tenancy.api.urls')), path('api/users/', include('users.api.urls')), path('api/virtualization/', include('virtualization.api.urls')), + path('api/status/', StatusView.as_view(), name='api-status'), path('api/docs/', schema_view.with_ui('swagger'), name='api_docs'), path('api/redoc/', schema_view.with_ui('redoc'), name='api_redocs'), re_path(r'^api/swagger(?P.json|.yaml)$', schema_view.without_ui(), name='schema_swagger'), @@ -92,4 +94,4 @@ path('{}'.format(settings.BASE_PATH), include(_patterns)) ] -handler500 = 'utilities.views.server_error' +handler500 = 'netbox.views.server_error' diff --git a/netbox/netbox/views.py b/netbox/netbox/views.py deleted file mode 100644 index e58d214ced..0000000000 --- a/netbox/netbox/views.py +++ /dev/null @@ -1,352 +0,0 @@ -from collections import OrderedDict - -from django.conf import settings -from django.contrib.contenttypes.models import ContentType -from django.db.models import Count, F -from django.shortcuts import render -from django.views.generic import View -from packaging import version -from rest_framework.response import Response -from rest_framework.reverse import reverse -from rest_framework.views import APIView - -from circuits.filters import CircuitFilterSet, ProviderFilterSet -from circuits.models import Circuit, Provider -from circuits.tables import CircuitTable, ProviderTable -from dcim.filters import ( - CableFilterSet, DeviceFilterSet, DeviceTypeFilterSet, PowerFeedFilterSet, RackFilterSet, RackGroupFilterSet, - SiteFilterSet, VirtualChassisFilterSet, -) -from dcim.models import ( - Cable, ConsolePort, Device, DeviceType, Interface, PowerPanel, PowerFeed, PowerPort, Rack, RackGroup, Site, - VirtualChassis, -) -from dcim.tables import ( - CableTable, DeviceTable, DeviceTypeTable, PowerFeedTable, RackTable, RackGroupTable, SiteTable, - VirtualChassisTable, -) -from extras.choices import JobResultStatusChoices -from extras.models import ObjectChange, JobResult -from ipam.filters import AggregateFilterSet, IPAddressFilterSet, PrefixFilterSet, VLANFilterSet, VRFFilterSet -from ipam.models import Aggregate, IPAddress, Prefix, VLAN, VRF -from ipam.tables import AggregateTable, IPAddressTable, PrefixTable, VLANTable, VRFTable -from netbox.releases import get_latest_release -from secrets.filters import SecretFilterSet -from secrets.models import Secret -from secrets.tables import SecretTable -from tenancy.filters import TenantFilterSet -from tenancy.models import Tenant -from tenancy.tables import TenantTable -from utilities.utils import get_subquery -from virtualization.filters import ClusterFilterSet, VirtualMachineFilterSet -from virtualization.models import Cluster, VirtualMachine -from virtualization.tables import ClusterTable, VirtualMachineDetailTable -from .forms import SearchForm - -SEARCH_MAX_RESULTS = 15 -SEARCH_TYPES = OrderedDict(( - # Circuits - ('provider', { - 'queryset': Provider.objects.annotate( - count_circuits=get_subquery(Circuit, 'provider') - ), - 'filterset': ProviderFilterSet, - 'table': ProviderTable, - 'url': 'circuits:provider_list', - }), - ('circuit', { - 'queryset': Circuit.objects.prefetch_related( - 'type', 'provider', 'tenant', 'terminations__site' - ).annotate_sites(), - 'filterset': CircuitFilterSet, - 'table': CircuitTable, - 'url': 'circuits:circuit_list', - }), - # DCIM - ('site', { - 'queryset': Site.objects.prefetch_related('region', 'tenant'), - 'filterset': SiteFilterSet, - 'table': SiteTable, - 'url': 'dcim:site_list', - }), - ('rack', { - 'queryset': Rack.objects.prefetch_related('site', 'group', 'tenant', 'role'), - 'filterset': RackFilterSet, - 'table': RackTable, - 'url': 'dcim:rack_list', - }), - ('rackgroup', { - 'queryset': RackGroup.objects.add_related_count( - RackGroup.objects.all(), - Rack, - 'group', - 'rack_count', - cumulative=True - ).prefetch_related('site'), - 'filterset': RackGroupFilterSet, - 'table': RackGroupTable, - 'url': 'dcim:rackgroup_list', - }), - ('devicetype', { - 'queryset': DeviceType.objects.prefetch_related('manufacturer').annotate( - instance_count=get_subquery(Device, 'device_type') - ), - 'filterset': DeviceTypeFilterSet, - 'table': DeviceTypeTable, - 'url': 'dcim:devicetype_list', - }), - ('device', { - 'queryset': Device.objects.prefetch_related( - 'device_type__manufacturer', 'device_role', 'tenant', 'site', 'rack', 'primary_ip4', 'primary_ip6', - ), - 'filterset': DeviceFilterSet, - 'table': DeviceTable, - 'url': 'dcim:device_list', - }), - ('virtualchassis', { - 'queryset': VirtualChassis.objects.prefetch_related('master').annotate( - member_count=get_subquery(Device, 'virtual_chassis') - ), - 'filterset': VirtualChassisFilterSet, - 'table': VirtualChassisTable, - 'url': 'dcim:virtualchassis_list', - }), - ('cable', { - 'queryset': Cable.objects.all(), - 'filterset': CableFilterSet, - 'table': CableTable, - 'url': 'dcim:cable_list', - }), - ('powerfeed', { - 'queryset': PowerFeed.objects.all(), - 'filterset': PowerFeedFilterSet, - 'table': PowerFeedTable, - 'url': 'dcim:powerfeed_list', - }), - # Virtualization - ('cluster', { - 'queryset': Cluster.objects.prefetch_related('type', 'group').annotate( - device_count=get_subquery(Device, 'cluster'), - vm_count=get_subquery(VirtualMachine, 'cluster') - ), - 'filterset': ClusterFilterSet, - 'table': ClusterTable, - 'url': 'virtualization:cluster_list', - }), - ('virtualmachine', { - 'queryset': VirtualMachine.objects.prefetch_related( - 'cluster', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', - ), - 'filterset': VirtualMachineFilterSet, - 'table': VirtualMachineDetailTable, - 'url': 'virtualization:virtualmachine_list', - }), - # IPAM - ('vrf', { - 'queryset': VRF.objects.prefetch_related('tenant'), - 'filterset': VRFFilterSet, - 'table': VRFTable, - 'url': 'ipam:vrf_list', - }), - ('aggregate', { - 'queryset': Aggregate.objects.prefetch_related('rir'), - 'filterset': AggregateFilterSet, - 'table': AggregateTable, - 'url': 'ipam:aggregate_list', - }), - ('prefix', { - 'queryset': Prefix.objects.prefetch_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role'), - 'filterset': PrefixFilterSet, - 'table': PrefixTable, - 'url': 'ipam:prefix_list', - }), - ('ipaddress', { - 'queryset': IPAddress.objects.prefetch_related('vrf__tenant', 'tenant'), - 'filterset': IPAddressFilterSet, - 'table': IPAddressTable, - 'url': 'ipam:ipaddress_list', - }), - ('vlan', { - 'queryset': VLAN.objects.prefetch_related('site', 'group', 'tenant', 'role'), - 'filterset': VLANFilterSet, - 'table': VLANTable, - 'url': 'ipam:vlan_list', - }), - # Secrets - ('secret', { - 'queryset': Secret.objects.prefetch_related('role', 'device'), - 'filterset': SecretFilterSet, - 'table': SecretTable, - 'url': 'secrets:secret_list', - }), - # Tenancy - ('tenant', { - 'queryset': Tenant.objects.prefetch_related('group'), - 'filterset': TenantFilterSet, - 'table': TenantTable, - 'url': 'tenancy:tenant_list', - }), -)) - - -class HomeView(View): - template_name = 'home.html' - - def get(self, request): - - connected_consoleports = ConsolePort.objects.restrict(request.user, 'view').filter( - connected_endpoint__isnull=False - ) - connected_powerports = PowerPort.objects.restrict(request.user, 'view').filter( - _connected_poweroutlet__isnull=False - ) - connected_interfaces = Interface.objects.restrict(request.user, 'view').filter( - _connected_interface__isnull=False, - pk__lt=F('_connected_interface') - ) - - # Report Results - report_content_type = ContentType.objects.get(app_label='extras', model='report') - report_results = JobResult.objects.filter( - obj_type=report_content_type, - status__in=JobResultStatusChoices.TERMINAL_STATE_CHOICES - ).defer('data')[:10] - - stats = { - - # Organization - 'site_count': Site.objects.restrict(request.user, 'view').count(), - 'tenant_count': Tenant.objects.restrict(request.user, 'view').count(), - - # DCIM - 'rack_count': Rack.objects.restrict(request.user, 'view').count(), - 'devicetype_count': DeviceType.objects.restrict(request.user, 'view').count(), - 'device_count': Device.objects.restrict(request.user, 'view').count(), - 'interface_connections_count': connected_interfaces.count(), - 'cable_count': Cable.objects.restrict(request.user, 'view').count(), - 'console_connections_count': connected_consoleports.count(), - 'power_connections_count': connected_powerports.count(), - 'powerpanel_count': PowerPanel.objects.restrict(request.user, 'view').count(), - 'powerfeed_count': PowerFeed.objects.restrict(request.user, 'view').count(), - - # IPAM - 'vrf_count': VRF.objects.restrict(request.user, 'view').count(), - 'aggregate_count': Aggregate.objects.restrict(request.user, 'view').count(), - 'prefix_count': Prefix.objects.restrict(request.user, 'view').count(), - 'ipaddress_count': IPAddress.objects.restrict(request.user, 'view').count(), - 'vlan_count': VLAN.objects.restrict(request.user, 'view').count(), - - # Circuits - 'provider_count': Provider.objects.restrict(request.user, 'view').count(), - 'circuit_count': Circuit.objects.restrict(request.user, 'view').count(), - - # Secrets - 'secret_count': Secret.objects.restrict(request.user, 'view').count(), - - # Virtualization - 'cluster_count': Cluster.objects.restrict(request.user, 'view').count(), - 'virtualmachine_count': VirtualMachine.objects.restrict(request.user, 'view').count(), - - } - - changelog = ObjectChange.objects.restrict(request.user, 'view').prefetch_related('user', 'changed_object_type') - - # Check whether a new release is available. (Only for staff/superusers.) - new_release = None - if request.user.is_staff or request.user.is_superuser: - latest_release, release_url = get_latest_release() - if isinstance(latest_release, version.Version): - current_version = version.parse(settings.VERSION) - if latest_release > current_version: - new_release = { - 'version': str(latest_release), - 'url': release_url, - } - - return render(request, self.template_name, { - 'search_form': SearchForm(), - 'stats': stats, - 'report_results': report_results, - 'changelog': changelog[:15], - 'new_release': new_release, - }) - - -class SearchView(View): - - def get(self, request): - - # No query - if 'q' not in request.GET: - return render(request, 'search.html', { - 'form': SearchForm(), - }) - - form = SearchForm(request.GET) - results = [] - - if form.is_valid(): - - if form.cleaned_data['obj_type']: - # Searching for a single type of object - obj_types = [form.cleaned_data['obj_type']] - else: - # Searching all object types - obj_types = SEARCH_TYPES.keys() - - for obj_type in obj_types: - - queryset = SEARCH_TYPES[obj_type]['queryset'].restrict(request.user, 'view') - filterset = SEARCH_TYPES[obj_type]['filterset'] - table = SEARCH_TYPES[obj_type]['table'] - url = SEARCH_TYPES[obj_type]['url'] - - # Construct the results table for this object type - filtered_queryset = filterset({'q': form.cleaned_data['q']}, queryset=queryset).qs - table = table(filtered_queryset, orderable=False) - table.paginate(per_page=SEARCH_MAX_RESULTS) - - if table.page: - results.append({ - 'name': queryset.model._meta.verbose_name_plural, - 'table': table, - 'url': '{}?q={}'.format(reverse(url), form.cleaned_data['q']) - }) - - return render(request, 'search.html', { - 'form': form, - 'results': results, - }) - - -class StaticMediaFailureView(View): - """ - Display a user-friendly error message with troubleshooting tips when a static media file fails to load. - """ - def get(self, request): - return render(request, 'media_failure.html', { - 'filename': request.GET.get('filename') - }) - - -class APIRootView(APIView): - _ignore_model_permissions = True - exclude_from_schema = True - swagger_schema = None - - def get_view_name(self): - return "API Root" - - def get(self, request, format=None): - - return Response(OrderedDict(( - ('circuits', reverse('circuits-api:api-root', request=request, format=format)), - ('dcim', reverse('dcim-api:api-root', request=request, format=format)), - ('extras', reverse('extras-api:api-root', request=request, format=format)), - ('ipam', reverse('ipam-api:api-root', request=request, format=format)), - ('plugins', reverse('plugins-api:api-root', request=request, format=format)), - ('secrets', reverse('secrets-api:api-root', request=request, format=format)), - ('tenancy', reverse('tenancy-api:api-root', request=request, format=format)), - ('users', reverse('users-api:api-root', request=request, format=format)), - ('virtualization', reverse('virtualization-api:api-root', request=request, format=format)), - ))) diff --git a/netbox/netbox/views/__init__.py b/netbox/netbox/views/__init__.py new file mode 100644 index 0000000000..5406e72069 --- /dev/null +++ b/netbox/netbox/views/__init__.py @@ -0,0 +1,188 @@ +import platform +import sys + +from django.conf import settings +from django.contrib.contenttypes.models import ContentType +from django.db.models import F +from django.http import HttpResponseServerError +from django.shortcuts import render +from django.template import loader +from django.template.exceptions import TemplateDoesNotExist +from django.urls import reverse +from django.views.decorators.csrf import requires_csrf_token +from django.views.defaults import ERROR_500_TEMPLATE_NAME +from django.views.generic import View +from packaging import version + +from circuits.models import Circuit, Provider +from dcim.models import ( + Cable, ConsolePort, Device, DeviceType, Interface, PowerPanel, PowerFeed, PowerPort, Rack, Site, +) +from extras.choices import JobResultStatusChoices +from extras.models import ObjectChange, JobResult +from ipam.models import Aggregate, IPAddress, Prefix, VLAN, VRF +from netbox.constants import SEARCH_MAX_RESULTS, SEARCH_TYPES +from netbox.forms import SearchForm +from netbox.releases import get_latest_release +from secrets.models import Secret +from tenancy.models import Tenant +from virtualization.models import Cluster, VirtualMachine + + +class HomeView(View): + template_name = 'home.html' + + def get(self, request): + + connected_consoleports = ConsolePort.objects.restrict(request.user, 'view').prefetch_related('_path').filter( + _path__destination_id__isnull=False + ) + connected_powerports = PowerPort.objects.restrict(request.user, 'view').prefetch_related('_path').filter( + _path__destination_id__isnull=False + ) + connected_interfaces = Interface.objects.restrict(request.user, 'view').prefetch_related('_path').filter( + _path__destination_id__isnull=False, + pk__lt=F('_path__destination_id') + ) + + # Report Results + report_content_type = ContentType.objects.get(app_label='extras', model='report') + report_results = JobResult.objects.filter( + obj_type=report_content_type, + status__in=JobResultStatusChoices.TERMINAL_STATE_CHOICES + ).defer('data')[:10] + + stats = { + + # Organization + 'site_count': Site.objects.restrict(request.user, 'view').count(), + 'tenant_count': Tenant.objects.restrict(request.user, 'view').count(), + + # DCIM + 'rack_count': Rack.objects.restrict(request.user, 'view').count(), + 'devicetype_count': DeviceType.objects.restrict(request.user, 'view').count(), + 'device_count': Device.objects.restrict(request.user, 'view').count(), + 'interface_connections_count': connected_interfaces.count(), + 'cable_count': Cable.objects.restrict(request.user, 'view').count(), + 'console_connections_count': connected_consoleports.count(), + 'power_connections_count': connected_powerports.count(), + 'powerpanel_count': PowerPanel.objects.restrict(request.user, 'view').count(), + 'powerfeed_count': PowerFeed.objects.restrict(request.user, 'view').count(), + + # IPAM + 'vrf_count': VRF.objects.restrict(request.user, 'view').count(), + 'aggregate_count': Aggregate.objects.restrict(request.user, 'view').count(), + 'prefix_count': Prefix.objects.restrict(request.user, 'view').count(), + 'ipaddress_count': IPAddress.objects.restrict(request.user, 'view').count(), + 'vlan_count': VLAN.objects.restrict(request.user, 'view').count(), + + # Circuits + 'provider_count': Provider.objects.restrict(request.user, 'view').count(), + 'circuit_count': Circuit.objects.restrict(request.user, 'view').count(), + + # Secrets + 'secret_count': Secret.objects.restrict(request.user, 'view').count(), + + # Virtualization + 'cluster_count': Cluster.objects.restrict(request.user, 'view').count(), + 'virtualmachine_count': VirtualMachine.objects.restrict(request.user, 'view').count(), + + } + + changelog = ObjectChange.objects.restrict(request.user, 'view').prefetch_related('user', 'changed_object_type') + + # Check whether a new release is available. (Only for staff/superusers.) + new_release = None + if request.user.is_staff or request.user.is_superuser: + latest_release, release_url = get_latest_release() + if isinstance(latest_release, version.Version): + current_version = version.parse(settings.VERSION) + if latest_release > current_version: + new_release = { + 'version': str(latest_release), + 'url': release_url, + } + + return render(request, self.template_name, { + 'search_form': SearchForm(), + 'stats': stats, + 'report_results': report_results, + 'changelog': changelog[:15], + 'new_release': new_release, + }) + + +class SearchView(View): + + def get(self, request): + + # No query + if 'q' not in request.GET: + return render(request, 'search.html', { + 'form': SearchForm(), + }) + + form = SearchForm(request.GET) + results = [] + + if form.is_valid(): + + if form.cleaned_data['obj_type']: + # Searching for a single type of object + obj_types = [form.cleaned_data['obj_type']] + else: + # Searching all object types + obj_types = SEARCH_TYPES.keys() + + for obj_type in obj_types: + + queryset = SEARCH_TYPES[obj_type]['queryset'].restrict(request.user, 'view') + filterset = SEARCH_TYPES[obj_type]['filterset'] + table = SEARCH_TYPES[obj_type]['table'] + url = SEARCH_TYPES[obj_type]['url'] + + # Construct the results table for this object type + filtered_queryset = filterset({'q': form.cleaned_data['q']}, queryset=queryset).qs + table = table(filtered_queryset, orderable=False) + table.paginate(per_page=SEARCH_MAX_RESULTS) + + if table.page: + results.append({ + 'name': queryset.model._meta.verbose_name_plural, + 'table': table, + 'url': f"{reverse(url)}?q={form.cleaned_data.get('q')}" + }) + + return render(request, 'search.html', { + 'form': form, + 'results': results, + }) + + +class StaticMediaFailureView(View): + """ + Display a user-friendly error message with troubleshooting tips when a static media file fails to load. + """ + def get(self, request): + return render(request, 'media_failure.html', { + 'filename': request.GET.get('filename') + }) + + +@requires_csrf_token +def server_error(request, template_name=ERROR_500_TEMPLATE_NAME): + """ + Custom 500 handler to provide additional context when rendering 500.html. + """ + try: + template = loader.get_template(template_name) + except TemplateDoesNotExist: + return HttpResponseServerError('

    Server Error (500)

    ', content_type='text/html') + type_, error, traceback = sys.exc_info() + + return HttpResponseServerError(template.render({ + 'error': error, + 'exception': str(type_), + 'netbox_version': settings.VERSION, + 'python_version': platform.python_version(), + })) diff --git a/netbox/netbox/views/generic.py b/netbox/netbox/views/generic.py new file mode 100644 index 0000000000..eb7b2542f3 --- /dev/null +++ b/netbox/netbox/views/generic.py @@ -0,0 +1,1235 @@ +import logging +import re +from copy import deepcopy + +from django.contrib import messages +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist, ValidationError +from django.db import transaction, IntegrityError +from django.db.models import ManyToManyField, ProtectedError +from django.forms import Form, ModelMultipleChoiceField, MultipleHiddenInput, Textarea +from django.http import HttpResponse +from django.shortcuts import get_object_or_404, redirect, render +from django.utils.html import escape +from django.utils.http import is_safe_url +from django.utils.safestring import mark_safe +from django.views.generic import View +from django_tables2 import RequestConfig + +from extras.models import CustomField, ExportTemplate +from utilities.error_handlers import handle_protectederror +from utilities.exceptions import AbortTransaction +from utilities.forms import ( + BootstrapMixin, BulkRenameForm, ConfirmationForm, CSVDataField, ImportForm, TableConfigForm, restrict_form_fields, +) +from utilities.paginator import EnhancedPaginator, get_paginate_count +from utilities.permissions import get_permission_for_model +from utilities.utils import csv_format, normalize_querydict, prepare_cloned_fields +from utilities.views import GetReturnURLMixin, ObjectPermissionRequiredMixin + + +class ObjectView(ObjectPermissionRequiredMixin, View): + """ + Retrieve a single object for display. + + queryset: The base queryset for retrieving the object + template_name: Name of the template to use + """ + queryset = None + template_name = None + + def get_required_permission(self): + return get_permission_for_model(self.queryset.model, 'view') + + def get_template_name(self): + """ + Return self.template_name if set. Otherwise, resolve the template path by model app_label and name. + """ + if self.template_name is not None: + return self.template_name + model_opts = self.queryset.model._meta + return f'{model_opts.app_label}/{model_opts.model_name}.html' + + def get_extra_context(self, request, instance): + """ + Return any additional context data for the template. + + request: The current request + instance: The object being viewed + """ + return {} + + def get(self, request, *args, **kwargs): + """ + Generic GET handler for accessing an object by PK or slug + """ + instance = get_object_or_404(self.queryset, **kwargs) + + return render(request, self.get_template_name(), { + 'object': instance, + **self.get_extra_context(request, instance), + }) + + +class ObjectListView(ObjectPermissionRequiredMixin, View): + """ + List a series of objects. + + queryset: The queryset of objects to display. Note: Prefetching related objects is not necessary, as the + table will prefetch objects as needed depending on the columns being displayed. + filter: A django-filter FilterSet that is applied to the queryset + filter_form: The form used to render filter options + table: The django-tables2 Table used to render the objects list + template_name: The name of the template + """ + queryset = None + filterset = None + filterset_form = None + table = None + template_name = 'generic/object_list.html' + action_buttons = ('add', 'import', 'export') + + def get_required_permission(self): + return get_permission_for_model(self.queryset.model, 'view') + + def queryset_to_yaml(self): + """ + Export the queryset of objects as concatenated YAML documents. + """ + yaml_data = [obj.to_yaml() for obj in self.queryset] + + return '---\n'.join(yaml_data) + + def queryset_to_csv(self): + """ + Export the queryset of objects as comma-separated value (CSV), using the model's to_csv() method. + """ + csv_data = [] + custom_fields = [] + + # Start with the column headers + headers = self.queryset.model.csv_headers.copy() + + # Add custom field headers, if any + if hasattr(self.queryset.model, 'custom_field_data'): + for custom_field in CustomField.objects.get_for_model(self.queryset.model): + headers.append(custom_field.name) + custom_fields.append(custom_field.name) + + csv_data.append(','.join(headers)) + + # Iterate through the queryset appending each object + for obj in self.queryset: + data = obj.to_csv() + + for custom_field in custom_fields: + data += (obj.cf.get(custom_field, ''),) + + csv_data.append(csv_format(data)) + + return '\n'.join(csv_data) + + def get(self, request): + + model = self.queryset.model + content_type = ContentType.objects.get_for_model(model) + + if self.filterset: + self.queryset = self.filterset(request.GET, self.queryset).qs + + # Check for export template rendering + if request.GET.get('export'): + et = get_object_or_404(ExportTemplate, content_type=content_type, name=request.GET.get('export')) + try: + return et.render_to_response(self.queryset) + except Exception as e: + messages.error( + request, + "There was an error rendering the selected export template ({}): {}".format( + et.name, e + ) + ) + + # Check for YAML export support + elif 'export' in request.GET and hasattr(model, 'to_yaml'): + response = HttpResponse(self.queryset_to_yaml(), content_type='text/yaml') + filename = 'netbox_{}.yaml'.format(self.queryset.model._meta.verbose_name_plural) + response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename) + return response + + # Fall back to built-in CSV formatting if export requested but no template specified + elif 'export' in request.GET and hasattr(model, 'to_csv'): + response = HttpResponse(self.queryset_to_csv(), content_type='text/csv') + filename = 'netbox_{}.csv'.format(self.queryset.model._meta.verbose_name_plural) + response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename) + return response + + # Compile a dictionary indicating which permissions are available to the current user for this model + permissions = {} + for action in ('add', 'change', 'delete', 'view'): + perm_name = get_permission_for_model(model, action) + permissions[action] = request.user.has_perm(perm_name) + + # Construct the objects table + table = self.table(self.queryset, user=request.user) + if 'pk' in table.base_columns and (permissions['change'] or permissions['delete']): + table.columns.show('pk') + + # Apply the request context + paginate = { + 'paginator_class': EnhancedPaginator, + 'per_page': get_paginate_count(request) + } + RequestConfig(request, paginate).configure(table) + + context = { + 'content_type': content_type, + 'table': table, + 'permissions': permissions, + 'action_buttons': self.action_buttons, + 'table_config_form': TableConfigForm(table=table), + 'filter_form': self.filterset_form(request.GET, label_suffix='') if self.filterset_form else None, + } + context.update(self.extra_context()) + + return render(request, self.template_name, context) + + def extra_context(self): + return {} + + +class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): + """ + Create or edit a single object. + + queryset: The base queryset for the object being modified + model_form: The form used to create or edit the object + template_name: The name of the template + """ + queryset = None + model_form = None + template_name = 'generic/object_edit.html' + + def get_required_permission(self): + # self._permission_action is set by dispatch() to either "add" or "change" depending on whether + # we are modifying an existing object or creating a new one. + return get_permission_for_model(self.queryset.model, self._permission_action) + + def get_object(self, kwargs): + # Look up an existing object by slug or PK, if provided. + if 'slug' in kwargs: + return get_object_or_404(self.queryset, slug=kwargs['slug']) + elif 'pk' in kwargs: + return get_object_or_404(self.queryset, pk=kwargs['pk']) + # Otherwise, return a new instance. + return self.queryset.model() + + def alter_obj(self, obj, request, url_args, url_kwargs): + # Allow views to add extra info to an object before it is processed. For example, a parent object can be defined + # given some parameter from the request URL. + return obj + + def dispatch(self, request, *args, **kwargs): + # Determine required permission based on whether we are editing an existing object + self._permission_action = 'change' if kwargs else 'add' + + return super().dispatch(request, *args, **kwargs) + + def get(self, request, *args, **kwargs): + obj = self.alter_obj(self.get_object(kwargs), request, args, kwargs) + + initial_data = normalize_querydict(request.GET) + form = self.model_form(instance=obj, initial=initial_data) + restrict_form_fields(form, request.user) + + return render(request, self.template_name, { + 'obj': obj, + 'obj_type': self.queryset.model._meta.verbose_name, + 'form': form, + 'return_url': self.get_return_url(request, obj), + }) + + def post(self, request, *args, **kwargs): + logger = logging.getLogger('netbox.views.ObjectEditView') + obj = self.alter_obj(self.get_object(kwargs), request, args, kwargs) + form = self.model_form( + data=request.POST, + files=request.FILES, + instance=obj + ) + restrict_form_fields(form, request.user) + + if form.is_valid(): + logger.debug("Form validation was successful") + + try: + with transaction.atomic(): + object_created = form.instance.pk is None + obj = form.save() + + # Check that the new object conforms with any assigned object-level permissions + self.queryset.get(pk=obj.pk) + + msg = '{} {}'.format( + 'Created' if object_created else 'Modified', + self.queryset.model._meta.verbose_name + ) + logger.info(f"{msg} {obj} (PK: {obj.pk})") + if hasattr(obj, 'get_absolute_url'): + msg = '{} {}'.format(msg, obj.get_absolute_url(), escape(obj)) + else: + msg = '{} {}'.format(msg, escape(obj)) + messages.success(request, mark_safe(msg)) + + if '_addanother' in request.POST: + + # If the object has clone_fields, pre-populate a new instance of the form + if hasattr(obj, 'clone_fields'): + url = '{}?{}'.format(request.path, prepare_cloned_fields(obj)) + return redirect(url) + + return redirect(request.get_full_path()) + + return_url = form.cleaned_data.get('return_url') + if return_url is not None and is_safe_url(url=return_url, allowed_hosts=request.get_host()): + return redirect(return_url) + else: + return redirect(self.get_return_url(request, obj)) + + except ObjectDoesNotExist: + msg = "Object save failed due to object-level permissions violation" + logger.debug(msg) + form.add_error(None, msg) + + else: + logger.debug("Form validation failed") + + return render(request, self.template_name, { + 'obj': obj, + 'obj_type': self.queryset.model._meta.verbose_name, + 'form': form, + 'return_url': self.get_return_url(request, obj), + }) + + +class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): + """ + Delete a single object. + + queryset: The base queryset for the object being deleted + template_name: The name of the template + """ + queryset = None + template_name = 'generic/object_delete.html' + + def get_required_permission(self): + return get_permission_for_model(self.queryset.model, 'delete') + + def get_object(self, kwargs): + # Look up object by slug if one has been provided. Otherwise, use PK. + if 'slug' in kwargs: + return get_object_or_404(self.queryset, slug=kwargs['slug']) + else: + return get_object_or_404(self.queryset, pk=kwargs['pk']) + + def get(self, request, **kwargs): + obj = self.get_object(kwargs) + form = ConfirmationForm(initial=request.GET) + + return render(request, self.template_name, { + 'obj': obj, + 'form': form, + 'obj_type': self.queryset.model._meta.verbose_name, + 'return_url': self.get_return_url(request, obj), + }) + + def post(self, request, **kwargs): + logger = logging.getLogger('netbox.views.ObjectDeleteView') + obj = self.get_object(kwargs) + form = ConfirmationForm(request.POST) + + if form.is_valid(): + logger.debug("Form validation was successful") + + try: + obj.delete() + except ProtectedError as e: + logger.info("Caught ProtectedError while attempting to delete object") + handle_protectederror([obj], request, e) + return redirect(obj.get_absolute_url()) + + msg = 'Deleted {} {}'.format(self.queryset.model._meta.verbose_name, obj) + logger.info(msg) + messages.success(request, msg) + + return_url = form.cleaned_data.get('return_url') + if return_url is not None and is_safe_url(url=return_url, allowed_hosts=request.get_host()): + return redirect(return_url) + else: + return redirect(self.get_return_url(request, obj)) + + else: + logger.debug("Form validation failed") + + return render(request, self.template_name, { + 'obj': obj, + 'form': form, + 'obj_type': self.queryset.model._meta.verbose_name, + 'return_url': self.get_return_url(request, obj), + }) + + +class BulkCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): + """ + Create new objects in bulk. + + queryset: Base queryset for the objects being created + form: Form class which provides the `pattern` field + model_form: The ModelForm used to create individual objects + pattern_target: Name of the field to be evaluated as a pattern (if any) + template_name: The name of the template + """ + queryset = None + form = None + model_form = None + pattern_target = '' + template_name = None + + def get_required_permission(self): + return get_permission_for_model(self.queryset.model, 'add') + + def get(self, request): + # Set initial values for visible form fields from query args + initial = {} + for field in getattr(self.model_form._meta, 'fields', []): + if request.GET.get(field): + initial[field] = request.GET[field] + + form = self.form() + model_form = self.model_form(initial=initial) + + return render(request, self.template_name, { + 'obj_type': self.model_form._meta.model._meta.verbose_name, + 'form': form, + 'model_form': model_form, + 'return_url': self.get_return_url(request), + }) + + def post(self, request): + logger = logging.getLogger('netbox.views.BulkCreateView') + model = self.queryset.model + form = self.form(request.POST) + model_form = self.model_form(request.POST) + + if form.is_valid(): + logger.debug("Form validation was successful") + pattern = form.cleaned_data['pattern'] + new_objs = [] + + try: + with transaction.atomic(): + + # Create objects from the expanded. Abort the transaction on the first validation error. + for value in pattern: + + # Reinstantiate the model form each time to avoid overwriting the same instance. Use a mutable + # copy of the POST QueryDict so that we can update the target field value. + model_form = self.model_form(request.POST.copy()) + model_form.data[self.pattern_target] = value + + # Validate each new object independently. + if model_form.is_valid(): + obj = model_form.save() + logger.debug(f"Created {obj} (PK: {obj.pk})") + new_objs.append(obj) + else: + # Copy any errors on the pattern target field to the pattern form. + errors = model_form.errors.as_data() + if errors.get(self.pattern_target): + form.add_error('pattern', errors[self.pattern_target]) + # Raise an IntegrityError to break the for loop and abort the transaction. + raise IntegrityError() + + # Enforce object-level permissions + if self.queryset.filter(pk__in=[obj.pk for obj in new_objs]).count() != len(new_objs): + raise ObjectDoesNotExist + + # If we make it to this point, validation has succeeded on all new objects. + msg = "Added {} {}".format(len(new_objs), model._meta.verbose_name_plural) + logger.info(msg) + messages.success(request, msg) + + if '_addanother' in request.POST: + return redirect(request.path) + return redirect(self.get_return_url(request)) + + except IntegrityError: + pass + + except ObjectDoesNotExist: + msg = "Object creation failed due to object-level permissions violation" + logger.debug(msg) + form.add_error(None, msg) + + else: + logger.debug("Form validation failed") + + return render(request, self.template_name, { + 'form': form, + 'model_form': model_form, + 'obj_type': model._meta.verbose_name, + 'return_url': self.get_return_url(request), + }) + + +class ObjectImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): + """ + Import a single object (YAML or JSON format). + + queryset: Base queryset for the objects being created + model_form: The ModelForm used to create individual objects + related_object_forms: A dictionary mapping of forms to be used for the creation of related (child) objects + template_name: The name of the template + """ + queryset = None + model_form = None + related_object_forms = dict() + template_name = 'generic/object_import.html' + + def get_required_permission(self): + return get_permission_for_model(self.queryset.model, 'add') + + def get(self, request): + form = ImportForm() + + return render(request, self.template_name, { + 'form': form, + 'obj_type': self.queryset.model._meta.verbose_name, + 'return_url': self.get_return_url(request), + }) + + def post(self, request): + logger = logging.getLogger('netbox.views.ObjectImportView') + form = ImportForm(request.POST) + + if form.is_valid(): + logger.debug("Import form validation was successful") + + # Initialize model form + data = form.cleaned_data['data'] + model_form = self.model_form(data) + restrict_form_fields(model_form, request.user) + + # Assign default values for any fields which were not specified. We have to do this manually because passing + # 'initial=' to the form on initialization merely sets default values for the widgets. Since widgets are not + # used for YAML/JSON import, we first bind the imported data normally, then update the form's data with the + # applicable field defaults as needed prior to form validation. + for field_name, field in model_form.fields.items(): + if field_name not in data and hasattr(field, 'initial'): + model_form.data[field_name] = field.initial + + if model_form.is_valid(): + + try: + with transaction.atomic(): + + # Save the primary object + obj = model_form.save() + + # Enforce object-level permissions + self.queryset.get(pk=obj.pk) + + logger.debug(f"Created {obj} (PK: {obj.pk})") + + # Iterate through the related object forms (if any), validating and saving each instance. + for field_name, related_object_form in self.related_object_forms.items(): + logger.debug("Processing form for related objects: {related_object_form}") + + related_obj_pks = [] + for i, rel_obj_data in enumerate(data.get(field_name, list())): + + f = related_object_form(obj, rel_obj_data) + + for subfield_name, field in f.fields.items(): + if subfield_name not in rel_obj_data and hasattr(field, 'initial'): + f.data[subfield_name] = field.initial + + if f.is_valid(): + related_obj = f.save() + related_obj_pks.append(related_obj.pk) + else: + # Replicate errors on the related object form to the primary form for display + for subfield_name, errors in f.errors.items(): + for err in errors: + err_msg = "{}[{}] {}: {}".format(field_name, i, subfield_name, err) + model_form.add_error(None, err_msg) + raise AbortTransaction() + + # Enforce object-level permissions on related objects + model = related_object_form.Meta.model + if model.objects.filter(pk__in=related_obj_pks).count() != len(related_obj_pks): + raise ObjectDoesNotExist + + except AbortTransaction: + pass + + except ObjectDoesNotExist: + msg = "Object creation failed due to object-level permissions violation" + logger.debug(msg) + form.add_error(None, msg) + + if not model_form.errors: + logger.info(f"Import object {obj} (PK: {obj.pk})") + messages.success(request, mark_safe('Imported object: {}'.format( + obj.get_absolute_url(), obj + ))) + + if '_addanother' in request.POST: + return redirect(request.get_full_path()) + + return_url = form.cleaned_data.get('return_url') + if return_url is not None and is_safe_url(url=return_url, allowed_hosts=request.get_host()): + return redirect(return_url) + else: + return redirect(self.get_return_url(request, obj)) + + else: + logger.debug("Model form validation failed") + + # Replicate model form errors for display + for field, errors in model_form.errors.items(): + for err in errors: + if field == '__all__': + form.add_error(None, err) + else: + form.add_error(None, "{}: {}".format(field, err)) + + else: + logger.debug("Import form validation failed") + + return render(request, self.template_name, { + 'form': form, + 'obj_type': self.queryset.model._meta.verbose_name, + 'return_url': self.get_return_url(request), + }) + + +class BulkImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): + """ + Import objects in bulk (CSV format). + + queryset: Base queryset for the model + model_form: The form used to create each imported object + table: The django-tables2 Table used to render the list of imported objects + template_name: The name of the template + widget_attrs: A dict of attributes to apply to the import widget (e.g. to require a session key) + """ + queryset = None + model_form = None + table = None + template_name = 'generic/object_bulk_import.html' + widget_attrs = {} + + def _import_form(self, *args, **kwargs): + + class ImportForm(BootstrapMixin, Form): + csv = CSVDataField( + from_form=self.model_form, + widget=Textarea(attrs=self.widget_attrs) + ) + + return ImportForm(*args, **kwargs) + + def _save_obj(self, obj_form, request): + """ + Provide a hook to modify the object immediately before saving it (e.g. to encrypt secret data). + """ + return obj_form.save() + + def get_required_permission(self): + return get_permission_for_model(self.queryset.model, 'add') + + def get(self, request): + + return render(request, self.template_name, { + 'form': self._import_form(), + 'fields': self.model_form().fields, + 'obj_type': self.model_form._meta.model._meta.verbose_name, + 'return_url': self.get_return_url(request), + }) + + def post(self, request): + logger = logging.getLogger('netbox.views.BulkImportView') + new_objs = [] + form = self._import_form(request.POST) + + if form.is_valid(): + logger.debug("Form validation was successful") + + try: + # Iterate through CSV data and bind each row to a new model form instance. + with transaction.atomic(): + headers, records = form.cleaned_data['csv'] + for row, data in enumerate(records, start=1): + obj_form = self.model_form(data, headers=headers) + restrict_form_fields(obj_form, request.user) + + if obj_form.is_valid(): + obj = self._save_obj(obj_form, request) + new_objs.append(obj) + else: + for field, err in obj_form.errors.items(): + form.add_error('csv', "Row {} {}: {}".format(row, field, err[0])) + raise ValidationError("") + + # Enforce object-level permissions + if self.queryset.filter(pk__in=[obj.pk for obj in new_objs]).count() != len(new_objs): + raise ObjectDoesNotExist + + # Compile a table containing the imported objects + obj_table = self.table(new_objs) + + if new_objs: + msg = 'Imported {} {}'.format(len(new_objs), new_objs[0]._meta.verbose_name_plural) + logger.info(msg) + messages.success(request, msg) + + return render(request, "import_success.html", { + 'table': obj_table, + 'return_url': self.get_return_url(request), + }) + + except ValidationError: + pass + + except ObjectDoesNotExist: + msg = "Object import failed due to object-level permissions violation" + logger.debug(msg) + form.add_error(None, msg) + + else: + logger.debug("Form validation failed") + + return render(request, self.template_name, { + 'form': form, + 'fields': self.model_form().fields, + 'obj_type': self.model_form._meta.model._meta.verbose_name, + 'return_url': self.get_return_url(request), + }) + + +class BulkEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): + """ + Edit objects in bulk. + + queryset: Custom queryset to use when retrieving objects (e.g. to select related objects) + filter: FilterSet to apply when deleting by QuerySet + table: The table used to display devices being edited + form: The form class used to edit objects in bulk + template_name: The name of the template + """ + queryset = None + filterset = None + table = None + form = None + template_name = 'generic/object_bulk_edit.html' + + def get_required_permission(self): + return get_permission_for_model(self.queryset.model, 'change') + + def get(self, request): + return redirect(self.get_return_url(request)) + + def post(self, request, **kwargs): + logger = logging.getLogger('netbox.views.BulkEditView') + model = self.queryset.model + + # If we are editing *all* objects in the queryset, replace the PK list with all matched objects. + if request.POST.get('_all') and self.filterset is not None: + pk_list = [ + obj.pk for obj in self.filterset(request.GET, self.queryset.only('pk')).qs + ] + else: + pk_list = request.POST.getlist('pk') + + if '_apply' in request.POST: + form = self.form(model, request.POST) + restrict_form_fields(form, request.user) + + if form.is_valid(): + logger.debug("Form validation was successful") + custom_fields = form.custom_fields if hasattr(form, 'custom_fields') else [] + standard_fields = [ + field for field in form.fields if field not in custom_fields + ['pk'] + ] + nullified_fields = request.POST.getlist('_nullify') + + try: + + with transaction.atomic(): + + updated_objects = [] + for obj in self.queryset.filter(pk__in=form.cleaned_data['pk']): + + # Update standard fields. If a field is listed in _nullify, delete its value. + for name in standard_fields: + + try: + model_field = model._meta.get_field(name) + except FieldDoesNotExist: + # This form field is used to modify a field rather than set its value directly + model_field = None + + # Handle nullification + if name in form.nullable_fields and name in nullified_fields: + if isinstance(model_field, ManyToManyField): + getattr(obj, name).set([]) + else: + setattr(obj, name, None if model_field.null else '') + + # ManyToManyFields + elif isinstance(model_field, ManyToManyField): + if form.cleaned_data[name]: + getattr(obj, name).set(form.cleaned_data[name]) + # Normal fields + elif form.cleaned_data[name] not in (None, ''): + setattr(obj, name, form.cleaned_data[name]) + + # Update custom fields + for name in custom_fields: + if name in form.nullable_fields and name in nullified_fields: + obj.custom_field_data.pop(name, None) + else: + obj.custom_field_data[name] = form.cleaned_data[name] + + obj.full_clean() + obj.save() + updated_objects.append(obj) + logger.debug(f"Saved {obj} (PK: {obj.pk})") + + # Add/remove tags + if form.cleaned_data.get('add_tags', None): + obj.tags.add(*form.cleaned_data['add_tags']) + if form.cleaned_data.get('remove_tags', None): + obj.tags.remove(*form.cleaned_data['remove_tags']) + + # Enforce object-level permissions + if self.queryset.filter(pk__in=[obj.pk for obj in updated_objects]).count() != len(updated_objects): + raise ObjectDoesNotExist + + if updated_objects: + msg = 'Updated {} {}'.format(len(updated_objects), model._meta.verbose_name_plural) + logger.info(msg) + messages.success(self.request, msg) + + return redirect(self.get_return_url(request)) + + except ValidationError as e: + messages.error(self.request, "{} failed validation: {}".format(obj, e)) + + except ObjectDoesNotExist: + msg = "Object update failed due to object-level permissions violation" + logger.debug(msg) + form.add_error(None, msg) + + else: + logger.debug("Form validation failed") + + else: + # Include the PK list as initial data for the form + initial_data = {'pk': pk_list} + + # Check for other contextual data needed for the form. We avoid passing all of request.GET because the + # filter values will conflict with the bulk edit form fields. + # TODO: Find a better way to accomplish this + if 'device' in request.GET: + initial_data['device'] = request.GET.get('device') + elif 'device_type' in request.GET: + initial_data['device_type'] = request.GET.get('device_type') + + form = self.form(model, initial=initial_data) + restrict_form_fields(form, request.user) + + # Retrieve objects being edited + table = self.table(self.queryset.filter(pk__in=pk_list), orderable=False) + if not table.rows: + messages.warning(request, "No {} were selected.".format(model._meta.verbose_name_plural)) + return redirect(self.get_return_url(request)) + + return render(request, self.template_name, { + 'form': form, + 'table': table, + 'obj_type_plural': model._meta.verbose_name_plural, + 'return_url': self.get_return_url(request), + }) + + +class BulkRenameView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): + """ + An extendable view for renaming objects in bulk. + """ + queryset = None + template_name = 'generic/object_bulk_rename.html' + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Create a new Form class from BulkRenameForm + class _Form(BulkRenameForm): + pk = ModelMultipleChoiceField( + queryset=self.queryset, + widget=MultipleHiddenInput() + ) + + self.form = _Form + + def get_required_permission(self): + return get_permission_for_model(self.queryset.model, 'change') + + def post(self, request): + logger = logging.getLogger('netbox.views.BulkRenameView') + + if '_preview' in request.POST or '_apply' in request.POST: + form = self.form(request.POST, initial={'pk': request.POST.getlist('pk')}) + selected_objects = self.queryset.filter(pk__in=form.initial['pk']) + + if form.is_valid(): + try: + with transaction.atomic(): + renamed_pks = [] + for obj in selected_objects: + find = form.cleaned_data['find'] + replace = form.cleaned_data['replace'] + if form.cleaned_data['use_regex']: + try: + obj.new_name = re.sub(find, replace, obj.name) + # Catch regex group reference errors + except re.error: + obj.new_name = obj.name + else: + obj.new_name = obj.name.replace(find, replace) + renamed_pks.append(obj.pk) + + if '_apply' in request.POST: + for obj in selected_objects: + obj.name = obj.new_name + obj.save() + + # Enforce constrained permissions + if self.queryset.filter(pk__in=renamed_pks).count() != len(selected_objects): + raise ObjectDoesNotExist + + messages.success(request, "Renamed {} {}".format( + len(selected_objects), + self.queryset.model._meta.verbose_name_plural + )) + return redirect(self.get_return_url(request)) + + except ObjectDoesNotExist: + msg = "Object update failed due to object-level permissions violation" + logger.debug(msg) + form.add_error(None, msg) + + else: + form = self.form(initial={'pk': request.POST.getlist('pk')}) + selected_objects = self.queryset.filter(pk__in=form.initial['pk']) + + return render(request, self.template_name, { + 'form': form, + 'obj_type_plural': self.queryset.model._meta.verbose_name_plural, + 'selected_objects': selected_objects, + 'return_url': self.get_return_url(request), + }) + + +class BulkDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): + """ + Delete objects in bulk. + + queryset: Custom queryset to use when retrieving objects (e.g. to select related objects) + filter: FilterSet to apply when deleting by QuerySet + table: The table used to display devices being deleted + form: The form class used to delete objects in bulk + template_name: The name of the template + """ + queryset = None + filterset = None + table = None + form = None + template_name = 'generic/object_bulk_delete.html' + + def get_required_permission(self): + return get_permission_for_model(self.queryset.model, 'delete') + + def get(self, request): + return redirect(self.get_return_url(request)) + + def post(self, request, **kwargs): + logger = logging.getLogger('netbox.views.BulkDeleteView') + model = self.queryset.model + + # Are we deleting *all* objects in the queryset or just a selected subset? + if request.POST.get('_all'): + if self.filterset is not None: + pk_list = [obj.pk for obj in self.filterset(request.GET, model.objects.only('pk')).qs] + else: + pk_list = model.objects.values_list('pk', flat=True) + else: + pk_list = [int(pk) for pk in request.POST.getlist('pk')] + + form_cls = self.get_form() + + if '_confirm' in request.POST: + form = form_cls(request.POST) + if form.is_valid(): + logger.debug("Form validation was successful") + + # Delete objects + queryset = self.queryset.filter(pk__in=pk_list) + try: + deleted_count = queryset.delete()[1][model._meta.label] + except ProtectedError as e: + logger.info("Caught ProtectedError while attempting to delete objects") + handle_protectederror(queryset, request, e) + return redirect(self.get_return_url(request)) + + msg = 'Deleted {} {}'.format(deleted_count, model._meta.verbose_name_plural) + logger.info(msg) + messages.success(request, msg) + return redirect(self.get_return_url(request)) + + else: + logger.debug("Form validation failed") + + else: + form = form_cls(initial={ + 'pk': pk_list, + 'return_url': self.get_return_url(request), + }) + + # Retrieve objects being deleted + table = self.table(self.queryset.filter(pk__in=pk_list), orderable=False) + if not table.rows: + messages.warning(request, "No {} were selected for deletion.".format(model._meta.verbose_name_plural)) + return redirect(self.get_return_url(request)) + + return render(request, self.template_name, { + 'form': form, + 'obj_type_plural': model._meta.verbose_name_plural, + 'table': table, + 'return_url': self.get_return_url(request), + }) + + def get_form(self): + """ + Provide a standard bulk delete form if none has been specified for the view + """ + class BulkDeleteForm(ConfirmationForm): + pk = ModelMultipleChoiceField(queryset=self.queryset, widget=MultipleHiddenInput) + + if self.form: + return self.form + + return BulkDeleteForm + + +# +# Device/VirtualMachine components +# + +# TODO: Replace with BulkCreateView +class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): + """ + Add one or more components (e.g. interfaces, console ports, etc.) to a Device or VirtualMachine. + """ + queryset = None + form = None + model_form = None + template_name = None + + def get_required_permission(self): + return get_permission_for_model(self.queryset.model, 'add') + + def get(self, request): + + form = self.form(initial=request.GET) + + return render(request, self.template_name, { + 'component_type': self.queryset.model._meta.verbose_name, + 'form': form, + 'return_url': self.get_return_url(request), + }) + + def post(self, request): + logger = logging.getLogger('netbox.views.ComponentCreateView') + form = self.form(request.POST, initial=request.GET) + + if form.is_valid(): + + new_components = [] + data = deepcopy(request.POST) + + names = form.cleaned_data['name_pattern'] + labels = form.cleaned_data.get('label_pattern') + for i, name in enumerate(names): + label = labels[i] if labels else None + # Initialize the individual component form + data['name'] = name + data['label'] = label + if hasattr(form, 'get_iterative_data'): + data.update(form.get_iterative_data(i)) + component_form = self.model_form(data) + + if component_form.is_valid(): + new_components.append(component_form) + else: + for field, errors in component_form.errors.as_data().items(): + # Assign errors on the child form's name/label field to name_pattern/label_pattern on the parent form + if field == 'name': + field = 'name_pattern' + elif field == 'label': + field = 'label_pattern' + for e in errors: + form.add_error(field, '{}: {}'.format(name, ', '.join(e))) + + if not form.errors: + + try: + + with transaction.atomic(): + + # Create the new components + new_objs = [] + for component_form in new_components: + obj = component_form.save() + new_objs.append(obj) + + # Enforce object-level permissions + if self.queryset.filter(pk__in=[obj.pk for obj in new_objs]).count() != len(new_objs): + raise ObjectDoesNotExist + + messages.success(request, "Added {} {}".format( + len(new_components), self.queryset.model._meta.verbose_name_plural + )) + if '_addanother' in request.POST: + return redirect(request.get_full_path()) + else: + return redirect(self.get_return_url(request)) + + except ObjectDoesNotExist: + msg = "Component creation failed due to object-level permissions violation" + logger.debug(msg) + form.add_error(None, msg) + + return render(request, self.template_name, { + 'component_type': self.queryset.model._meta.verbose_name, + 'form': form, + 'return_url': self.get_return_url(request), + }) + + +class BulkComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): + """ + Add one or more components (e.g. interfaces, console ports, etc.) to a set of Devices or VirtualMachines. + """ + parent_model = None + parent_field = None + form = None + queryset = None + model_form = None + filterset = None + table = None + template_name = 'generic/object_bulk_add_component.html' + + def get_required_permission(self): + return f'dcim.add_{self.queryset.model._meta.model_name}' + + def post(self, request): + logger = logging.getLogger('netbox.views.BulkComponentCreateView') + parent_model_name = self.parent_model._meta.verbose_name_plural + model_name = self.queryset.model._meta.verbose_name_plural + + # Are we editing *all* objects in the queryset or just a selected subset? + if request.POST.get('_all') and self.filterset is not None: + pk_list = [obj.pk for obj in self.filterset(request.GET, self.parent_model.objects.only('pk')).qs] + else: + pk_list = [int(pk) for pk in request.POST.getlist('pk')] + + selected_objects = self.parent_model.objects.filter(pk__in=pk_list) + if not selected_objects: + messages.warning(request, "No {} were selected.".format(self.parent_model._meta.verbose_name_plural)) + return redirect(self.get_return_url(request)) + table = self.table(selected_objects) + + if '_create' in request.POST: + form = self.form(request.POST) + + if form.is_valid(): + logger.debug("Form validation was successful") + + new_components = [] + data = deepcopy(form.cleaned_data) + + try: + with transaction.atomic(): + + for obj in data['pk']: + + names = data['name_pattern'] + labels = data['label_pattern'] if 'label_pattern' in data else None + for i, name in enumerate(names): + label = labels[i] if labels else None + + component_data = { + self.parent_field: obj.pk, + 'name': name, + 'label': label + } + component_data.update(data) + component_form = self.model_form(component_data) + if component_form.is_valid(): + instance = component_form.save() + logger.debug(f"Created {instance} on {instance.parent}") + new_components.append(instance) + else: + for field, errors in component_form.errors.as_data().items(): + for e in errors: + form.add_error(field, '{} {}: {}'.format(obj, name, ', '.join(e))) + + # Enforce object-level permissions + if self.queryset.filter(pk__in=[obj.pk for obj in new_components]).count() != len(new_components): + raise ObjectDoesNotExist + + except IntegrityError: + pass + + except ObjectDoesNotExist: + msg = "Component creation failed due to object-level permissions violation" + logger.debug(msg) + form.add_error(None, msg) + + if not form.errors: + msg = "Added {} {} to {} {}.".format( + len(new_components), + model_name, + len(form.cleaned_data['pk']), + parent_model_name + ) + logger.info(msg) + messages.success(request, msg) + + return redirect(self.get_return_url(request)) + + else: + logger.debug("Form validation failed") + + else: + form = self.form(initial={'pk': pk_list}) + + return render(request, self.template_name, { + 'form': form, + 'parent_model_name': parent_model_name, + 'model_name': model_name, + 'table': table, + 'return_url': self.get_return_url(request), + }) diff --git a/netbox/project-static/css/base.css b/netbox/project-static/css/base.css index 9a7ad35ab4..681565b9e6 100644 --- a/netbox/project-static/css/base.css +++ b/netbox/project-static/css/base.css @@ -11,10 +11,6 @@ html, body { body { padding-top: 70px; } -.container { - width: auto; - max-width: 1600px; -} .wrapper { min-height: 100%; height: auto !important; @@ -37,6 +33,11 @@ footer p { #navbar_search { padding: 0 8px; } +.right-side-panel { + max-width: 400px; + min-width: 300px; + padding-right: 0; +} /* Hide the username in the navigation menu on displays less than 1400px wide */ @media (max-width: 1399px) { @@ -120,9 +121,6 @@ footer p { } /* Navigation menu */ -li.subnav > a { - padding-left: 30px; -} ul.dropdown-menu { width: 250px; } @@ -130,9 +128,6 @@ ul.dropdown-menu div.buttons { padding-right: 10px; padding-top: 2px; } -ul.dropdown-menu div.buttons a { - width: 26px; -} ul.dropdown-menu > li > a { clear: left; } @@ -193,10 +188,6 @@ table.component-list td.subtable td { padding-bottom: 6px; padding-top: 6px; } -table.interface-ips th { - font-size: 80%; - font-weight: normal; -} /* Reports */ table.reports td.method { @@ -233,6 +224,46 @@ table.report th a { margin-bottom: 0; } +/* Cable tracing */ +.cable-trace { + max-width: 600px; + margin: 16px auto; + text-align: center; +} +.cable-trace .node { + background-color: #f0f0f0; + border: 1px solid #909090; + border-radius: 8px; + padding: 24px 16px; + position: relative; + z-index: 1; +} +.cable-trace .termination { + background-color: #f7f7f7; + border: 1px solid #909090; + border-radius: 4px; + margin: -16px auto; + padding: 12px; + position: relative; + width: 60%; + z-index: 2; +} +.cable-trace .active { + border: 3px solid #30C030; +} +.cable-trace .cable { + border-left-style: solid; + border-left-width: 4px; + margin: 12px 0 12px 50%; + padding: 24px; + text-align: left; + width: 50%; +} +.cable-trace .trace-end { + margin-top: 48px; + text-align: center; +} + /* Admonition (docs) */ .admonition { margin-bottom: 10px; @@ -346,6 +377,9 @@ table.report th a { ul.nav-tabs, ul.nav-pills { margin-bottom: 20px; } +ul.nav-tabs li a { + padding: 8px 10px; +} /* Fix progress bar margin inside table cells */ td .progress { margin-bottom: 0; @@ -354,3 +388,79 @@ td .progress { textarea { font-family: Consolas, Lucida Console, monospace; } + +/* MDI icons */ +.mdi::before { + font-size: 20px; + line-height: 20px; + position: relative; + top: 2px; +} +.btn .mdi { + margin: 0 -2px; +} +.btn .mdi::before { + font-size: 20px; + line-height: 14px; + position: relative; + top: 2px; +} +.btn-xs .mdi::before { + font-size: 18px; + top: 3px; +} +.btn-sm .mdi::before { + font-size: 18px; + top: 3px; +} +.dropdown-menu .mdi { + margin-left: 2px; +} +.nav .mdi::before { + left: -2px; + position: relative; + top: 2px; +} +.navbar .navbar-toggle .mdi::before { + position: relative; + top: 4px; + color: #FFF; +} +.breadcrumb .mdi::before { + position: relative; + top: 4px; +} +.breadcrumb a:hover { + text-decoration: none; +} +.breadcrumb a:hover span { + text-decoration: underline; +} +.alert .mdi::before { + position: relative; + top: 4px; + margin-right: 2px; +} +.input-group-addon .mdi::before { + position: relative; + top: 3px; +} +.input-group-btn .mdi::before { + font-size: 20px; +} +.navbar-brand .mdi::before { + position: relative; + top: 2px; + margin-right: 2px; +} +.list-group-item .mdi::before { + position: relative; + top: 3px; + left: -3px +} +.badge .mdi::before { + font-size: 12px; + left: 0; + line-height: 12px; + top: 0; +} diff --git a/netbox/project-static/font-awesome-4.7.0/css/font-awesome.css b/netbox/project-static/font-awesome-4.7.0/css/font-awesome.css deleted file mode 100644 index ee906a8196..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/css/font-awesome.css +++ /dev/null @@ -1,2337 +0,0 @@ -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */ -/* FONT PATH - * -------------------------- */ -@font-face { - font-family: 'FontAwesome'; - src: url('../fonts/fontawesome-webfont.eot?v=4.7.0'); - src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); - font-weight: normal; - font-style: normal; -} -.fa { - display: inline-block; - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -/* makes the font 33% larger relative to the icon container */ -.fa-lg { - font-size: 1.33333333em; - line-height: 0.75em; - vertical-align: -15%; -} -.fa-2x { - font-size: 2em; -} -.fa-3x { - font-size: 3em; -} -.fa-4x { - font-size: 4em; -} -.fa-5x { - font-size: 5em; -} -.fa-fw { - width: 1.28571429em; - text-align: center; -} -.fa-ul { - padding-left: 0; - margin-left: 2.14285714em; - list-style-type: none; -} -.fa-ul > li { - position: relative; -} -.fa-li { - position: absolute; - left: -2.14285714em; - width: 2.14285714em; - top: 0.14285714em; - text-align: center; -} -.fa-li.fa-lg { - left: -1.85714286em; -} -.fa-border { - padding: .2em .25em .15em; - border: solid 0.08em #eeeeee; - border-radius: .1em; -} -.fa-pull-left { - float: left; -} -.fa-pull-right { - float: right; -} -.fa.fa-pull-left { - margin-right: .3em; -} -.fa.fa-pull-right { - margin-left: .3em; -} -/* Deprecated as of 4.4.0 */ -.pull-right { - float: right; -} -.pull-left { - float: left; -} -.fa.pull-left { - margin-right: .3em; -} -.fa.pull-right { - margin-left: .3em; -} -.fa-spin { - -webkit-animation: fa-spin 2s infinite linear; - animation: fa-spin 2s infinite linear; -} -.fa-pulse { - -webkit-animation: fa-spin 1s infinite steps(8); - animation: fa-spin 1s infinite steps(8); -} -@-webkit-keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -.fa-rotate-90 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; - -webkit-transform: rotate(90deg); - -ms-transform: rotate(90deg); - transform: rotate(90deg); -} -.fa-rotate-180 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; - -webkit-transform: rotate(180deg); - -ms-transform: rotate(180deg); - transform: rotate(180deg); -} -.fa-rotate-270 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; - -webkit-transform: rotate(270deg); - -ms-transform: rotate(270deg); - transform: rotate(270deg); -} -.fa-flip-horizontal { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; - -webkit-transform: scale(-1, 1); - -ms-transform: scale(-1, 1); - transform: scale(-1, 1); -} -.fa-flip-vertical { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; - -webkit-transform: scale(1, -1); - -ms-transform: scale(1, -1); - transform: scale(1, -1); -} -:root .fa-rotate-90, -:root .fa-rotate-180, -:root .fa-rotate-270, -:root .fa-flip-horizontal, -:root .fa-flip-vertical { - filter: none; -} -.fa-stack { - position: relative; - display: inline-block; - width: 2em; - height: 2em; - line-height: 2em; - vertical-align: middle; -} -.fa-stack-1x, -.fa-stack-2x { - position: absolute; - left: 0; - width: 100%; - text-align: center; -} -.fa-stack-1x { - line-height: inherit; -} -.fa-stack-2x { - font-size: 2em; -} -.fa-inverse { - color: #ffffff; -} -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen - readers do not read off random characters that represent icons */ -.fa-glass:before { - content: "\f000"; -} -.fa-music:before { - content: "\f001"; -} -.fa-search:before { - content: "\f002"; -} -.fa-envelope-o:before { - content: "\f003"; -} -.fa-heart:before { - content: "\f004"; -} -.fa-star:before { - content: "\f005"; -} -.fa-star-o:before { - content: "\f006"; -} -.fa-user:before { - content: "\f007"; -} -.fa-film:before { - content: "\f008"; -} -.fa-th-large:before { - content: "\f009"; -} -.fa-th:before { - content: "\f00a"; -} -.fa-th-list:before { - content: "\f00b"; -} -.fa-check:before { - content: "\f00c"; -} -.fa-remove:before, -.fa-close:before, -.fa-times:before { - content: "\f00d"; -} -.fa-search-plus:before { - content: "\f00e"; -} -.fa-search-minus:before { - content: "\f010"; -} -.fa-power-off:before { - content: "\f011"; -} -.fa-signal:before { - content: "\f012"; -} -.fa-gear:before, -.fa-cog:before { - content: "\f013"; -} -.fa-trash-o:before { - content: "\f014"; -} -.fa-home:before { - content: "\f015"; -} -.fa-file-o:before { - content: "\f016"; -} -.fa-clock-o:before { - content: "\f017"; -} -.fa-road:before { - content: "\f018"; -} -.fa-download:before { - content: "\f019"; -} -.fa-arrow-circle-o-down:before { - content: "\f01a"; -} -.fa-arrow-circle-o-up:before { - content: "\f01b"; -} -.fa-inbox:before { - content: "\f01c"; -} -.fa-play-circle-o:before { - content: "\f01d"; -} -.fa-rotate-right:before, -.fa-repeat:before { - content: "\f01e"; -} -.fa-refresh:before { - content: "\f021"; -} -.fa-list-alt:before { - content: "\f022"; -} -.fa-lock:before { - content: "\f023"; -} -.fa-flag:before { - content: "\f024"; -} -.fa-headphones:before { - content: "\f025"; -} -.fa-volume-off:before { - content: "\f026"; -} -.fa-volume-down:before { - content: "\f027"; -} -.fa-volume-up:before { - content: "\f028"; -} -.fa-qrcode:before { - content: "\f029"; -} -.fa-barcode:before { - content: "\f02a"; -} -.fa-tag:before { - content: "\f02b"; -} -.fa-tags:before { - content: "\f02c"; -} -.fa-book:before { - content: "\f02d"; -} -.fa-bookmark:before { - content: "\f02e"; -} -.fa-print:before { - content: "\f02f"; -} -.fa-camera:before { - content: "\f030"; -} -.fa-font:before { - content: "\f031"; -} -.fa-bold:before { - content: "\f032"; -} -.fa-italic:before { - content: "\f033"; -} -.fa-text-height:before { - content: "\f034"; -} -.fa-text-width:before { - content: "\f035"; -} -.fa-align-left:before { - content: "\f036"; -} -.fa-align-center:before { - content: "\f037"; -} -.fa-align-right:before { - content: "\f038"; -} -.fa-align-justify:before { - content: "\f039"; -} -.fa-list:before { - content: "\f03a"; -} -.fa-dedent:before, -.fa-outdent:before { - content: "\f03b"; -} -.fa-indent:before { - content: "\f03c"; -} -.fa-video-camera:before { - content: "\f03d"; -} -.fa-photo:before, -.fa-image:before, -.fa-picture-o:before { - content: "\f03e"; -} -.fa-pencil:before { - content: "\f040"; -} -.fa-map-marker:before { - content: "\f041"; -} -.fa-adjust:before { - content: "\f042"; -} -.fa-tint:before { - content: "\f043"; -} -.fa-edit:before, -.fa-pencil-square-o:before { - content: "\f044"; -} -.fa-share-square-o:before { - content: "\f045"; -} -.fa-check-square-o:before { - content: "\f046"; -} -.fa-arrows:before { - content: "\f047"; -} -.fa-step-backward:before { - content: "\f048"; -} -.fa-fast-backward:before { - content: "\f049"; -} -.fa-backward:before { - content: "\f04a"; -} -.fa-play:before { - content: "\f04b"; -} -.fa-pause:before { - content: "\f04c"; -} -.fa-stop:before { - content: "\f04d"; -} -.fa-forward:before { - content: "\f04e"; -} -.fa-fast-forward:before { - content: "\f050"; -} -.fa-step-forward:before { - content: "\f051"; -} -.fa-eject:before { - content: "\f052"; -} -.fa-chevron-left:before { - content: "\f053"; -} -.fa-chevron-right:before { - content: "\f054"; -} -.fa-plus-circle:before { - content: "\f055"; -} -.fa-minus-circle:before { - content: "\f056"; -} -.fa-times-circle:before { - content: "\f057"; -} -.fa-check-circle:before { - content: "\f058"; -} -.fa-question-circle:before { - content: "\f059"; -} -.fa-info-circle:before { - content: "\f05a"; -} -.fa-crosshairs:before { - content: "\f05b"; -} -.fa-times-circle-o:before { - content: "\f05c"; -} -.fa-check-circle-o:before { - content: "\f05d"; -} -.fa-ban:before { - content: "\f05e"; -} -.fa-arrow-left:before { - content: "\f060"; -} -.fa-arrow-right:before { - content: "\f061"; -} -.fa-arrow-up:before { - content: "\f062"; -} -.fa-arrow-down:before { - content: "\f063"; -} -.fa-mail-forward:before, -.fa-share:before { - content: "\f064"; -} -.fa-expand:before { - content: "\f065"; -} -.fa-compress:before { - content: "\f066"; -} -.fa-plus:before { - content: "\f067"; -} -.fa-minus:before { - content: "\f068"; -} -.fa-asterisk:before { - content: "\f069"; -} -.fa-exclamation-circle:before { - content: "\f06a"; -} -.fa-gift:before { - content: "\f06b"; -} -.fa-leaf:before { - content: "\f06c"; -} -.fa-fire:before { - content: "\f06d"; -} -.fa-eye:before { - content: "\f06e"; -} -.fa-eye-slash:before { - content: "\f070"; -} -.fa-warning:before, -.fa-exclamation-triangle:before { - content: "\f071"; -} -.fa-plane:before { - content: "\f072"; -} -.fa-calendar:before { - content: "\f073"; -} -.fa-random:before { - content: "\f074"; -} -.fa-comment:before { - content: "\f075"; -} -.fa-magnet:before { - content: "\f076"; -} -.fa-chevron-up:before { - content: "\f077"; -} -.fa-chevron-down:before { - content: "\f078"; -} -.fa-retweet:before { - content: "\f079"; -} -.fa-shopping-cart:before { - content: "\f07a"; -} -.fa-folder:before { - content: "\f07b"; -} -.fa-folder-open:before { - content: "\f07c"; -} -.fa-arrows-v:before { - content: "\f07d"; -} -.fa-arrows-h:before { - content: "\f07e"; -} -.fa-bar-chart-o:before, -.fa-bar-chart:before { - content: "\f080"; -} -.fa-twitter-square:before { - content: "\f081"; -} -.fa-facebook-square:before { - content: "\f082"; -} -.fa-camera-retro:before { - content: "\f083"; -} -.fa-key:before { - content: "\f084"; -} -.fa-gears:before, -.fa-cogs:before { - content: "\f085"; -} -.fa-comments:before { - content: "\f086"; -} -.fa-thumbs-o-up:before { - content: "\f087"; -} -.fa-thumbs-o-down:before { - content: "\f088"; -} -.fa-star-half:before { - content: "\f089"; -} -.fa-heart-o:before { - content: "\f08a"; -} -.fa-sign-out:before { - content: "\f08b"; -} -.fa-linkedin-square:before { - content: "\f08c"; -} -.fa-thumb-tack:before { - content: "\f08d"; -} -.fa-external-link:before { - content: "\f08e"; -} -.fa-sign-in:before { - content: "\f090"; -} -.fa-trophy:before { - content: "\f091"; -} -.fa-github-square:before { - content: "\f092"; -} -.fa-upload:before { - content: "\f093"; -} -.fa-lemon-o:before { - content: "\f094"; -} -.fa-phone:before { - content: "\f095"; -} -.fa-square-o:before { - content: "\f096"; -} -.fa-bookmark-o:before { - content: "\f097"; -} -.fa-phone-square:before { - content: "\f098"; -} -.fa-twitter:before { - content: "\f099"; -} -.fa-facebook-f:before, -.fa-facebook:before { - content: "\f09a"; -} -.fa-github:before { - content: "\f09b"; -} -.fa-unlock:before { - content: "\f09c"; -} -.fa-credit-card:before { - content: "\f09d"; -} -.fa-feed:before, -.fa-rss:before { - content: "\f09e"; -} -.fa-hdd-o:before { - content: "\f0a0"; -} -.fa-bullhorn:before { - content: "\f0a1"; -} -.fa-bell:before { - content: "\f0f3"; -} -.fa-certificate:before { - content: "\f0a3"; -} -.fa-hand-o-right:before { - content: "\f0a4"; -} -.fa-hand-o-left:before { - content: "\f0a5"; -} -.fa-hand-o-up:before { - content: "\f0a6"; -} -.fa-hand-o-down:before { - content: "\f0a7"; -} -.fa-arrow-circle-left:before { - content: "\f0a8"; -} -.fa-arrow-circle-right:before { - content: "\f0a9"; -} -.fa-arrow-circle-up:before { - content: "\f0aa"; -} -.fa-arrow-circle-down:before { - content: "\f0ab"; -} -.fa-globe:before { - content: "\f0ac"; -} -.fa-wrench:before { - content: "\f0ad"; -} -.fa-tasks:before { - content: "\f0ae"; -} -.fa-filter:before { - content: "\f0b0"; -} -.fa-briefcase:before { - content: "\f0b1"; -} -.fa-arrows-alt:before { - content: "\f0b2"; -} -.fa-group:before, -.fa-users:before { - content: "\f0c0"; -} -.fa-chain:before, -.fa-link:before { - content: "\f0c1"; -} -.fa-cloud:before { - content: "\f0c2"; -} -.fa-flask:before { - content: "\f0c3"; -} -.fa-cut:before, -.fa-scissors:before { - content: "\f0c4"; -} -.fa-copy:before, -.fa-files-o:before { - content: "\f0c5"; -} -.fa-paperclip:before { - content: "\f0c6"; -} -.fa-save:before, -.fa-floppy-o:before { - content: "\f0c7"; -} -.fa-square:before { - content: "\f0c8"; -} -.fa-navicon:before, -.fa-reorder:before, -.fa-bars:before { - content: "\f0c9"; -} -.fa-list-ul:before { - content: "\f0ca"; -} -.fa-list-ol:before { - content: "\f0cb"; -} -.fa-strikethrough:before { - content: "\f0cc"; -} -.fa-underline:before { - content: "\f0cd"; -} -.fa-table:before { - content: "\f0ce"; -} -.fa-magic:before { - content: "\f0d0"; -} -.fa-truck:before { - content: "\f0d1"; -} -.fa-pinterest:before { - content: "\f0d2"; -} -.fa-pinterest-square:before { - content: "\f0d3"; -} -.fa-google-plus-square:before { - content: "\f0d4"; -} -.fa-google-plus:before { - content: "\f0d5"; -} -.fa-money:before { - content: "\f0d6"; -} -.fa-caret-down:before { - content: "\f0d7"; -} -.fa-caret-up:before { - content: "\f0d8"; -} -.fa-caret-left:before { - content: "\f0d9"; -} -.fa-caret-right:before { - content: "\f0da"; -} -.fa-columns:before { - content: "\f0db"; -} -.fa-unsorted:before, -.fa-sort:before { - content: "\f0dc"; -} -.fa-sort-down:before, -.fa-sort-desc:before { - content: "\f0dd"; -} -.fa-sort-up:before, -.fa-sort-asc:before { - content: "\f0de"; -} -.fa-envelope:before { - content: "\f0e0"; -} -.fa-linkedin:before { - content: "\f0e1"; -} -.fa-rotate-left:before, -.fa-undo:before { - content: "\f0e2"; -} -.fa-legal:before, -.fa-gavel:before { - content: "\f0e3"; -} -.fa-dashboard:before, -.fa-tachometer:before { - content: "\f0e4"; -} -.fa-comment-o:before { - content: "\f0e5"; -} -.fa-comments-o:before { - content: "\f0e6"; -} -.fa-flash:before, -.fa-bolt:before { - content: "\f0e7"; -} -.fa-sitemap:before { - content: "\f0e8"; -} -.fa-umbrella:before { - content: "\f0e9"; -} -.fa-paste:before, -.fa-clipboard:before { - content: "\f0ea"; -} -.fa-lightbulb-o:before { - content: "\f0eb"; -} -.fa-exchange:before { - content: "\f0ec"; -} -.fa-cloud-download:before { - content: "\f0ed"; -} -.fa-cloud-upload:before { - content: "\f0ee"; -} -.fa-user-md:before { - content: "\f0f0"; -} -.fa-stethoscope:before { - content: "\f0f1"; -} -.fa-suitcase:before { - content: "\f0f2"; -} -.fa-bell-o:before { - content: "\f0a2"; -} -.fa-coffee:before { - content: "\f0f4"; -} -.fa-cutlery:before { - content: "\f0f5"; -} -.fa-file-text-o:before { - content: "\f0f6"; -} -.fa-building-o:before { - content: "\f0f7"; -} -.fa-hospital-o:before { - content: "\f0f8"; -} -.fa-ambulance:before { - content: "\f0f9"; -} -.fa-medkit:before { - content: "\f0fa"; -} -.fa-fighter-jet:before { - content: "\f0fb"; -} -.fa-beer:before { - content: "\f0fc"; -} -.fa-h-square:before { - content: "\f0fd"; -} -.fa-plus-square:before { - content: "\f0fe"; -} -.fa-angle-double-left:before { - content: "\f100"; -} -.fa-angle-double-right:before { - content: "\f101"; -} -.fa-angle-double-up:before { - content: "\f102"; -} -.fa-angle-double-down:before { - content: "\f103"; -} -.fa-angle-left:before { - content: "\f104"; -} -.fa-angle-right:before { - content: "\f105"; -} -.fa-angle-up:before { - content: "\f106"; -} -.fa-angle-down:before { - content: "\f107"; -} -.fa-desktop:before { - content: "\f108"; -} -.fa-laptop:before { - content: "\f109"; -} -.fa-tablet:before { - content: "\f10a"; -} -.fa-mobile-phone:before, -.fa-mobile:before { - content: "\f10b"; -} -.fa-circle-o:before { - content: "\f10c"; -} -.fa-quote-left:before { - content: "\f10d"; -} -.fa-quote-right:before { - content: "\f10e"; -} -.fa-spinner:before { - content: "\f110"; -} -.fa-circle:before { - content: "\f111"; -} -.fa-mail-reply:before, -.fa-reply:before { - content: "\f112"; -} -.fa-github-alt:before { - content: "\f113"; -} -.fa-folder-o:before { - content: "\f114"; -} -.fa-folder-open-o:before { - content: "\f115"; -} -.fa-smile-o:before { - content: "\f118"; -} -.fa-frown-o:before { - content: "\f119"; -} -.fa-meh-o:before { - content: "\f11a"; -} -.fa-gamepad:before { - content: "\f11b"; -} -.fa-keyboard-o:before { - content: "\f11c"; -} -.fa-flag-o:before { - content: "\f11d"; -} -.fa-flag-checkered:before { - content: "\f11e"; -} -.fa-terminal:before { - content: "\f120"; -} -.fa-code:before { - content: "\f121"; -} -.fa-mail-reply-all:before, -.fa-reply-all:before { - content: "\f122"; -} -.fa-star-half-empty:before, -.fa-star-half-full:before, -.fa-star-half-o:before { - content: "\f123"; -} -.fa-location-arrow:before { - content: "\f124"; -} -.fa-crop:before { - content: "\f125"; -} -.fa-code-fork:before { - content: "\f126"; -} -.fa-unlink:before, -.fa-chain-broken:before { - content: "\f127"; -} -.fa-question:before { - content: "\f128"; -} -.fa-info:before { - content: "\f129"; -} -.fa-exclamation:before { - content: "\f12a"; -} -.fa-superscript:before { - content: "\f12b"; -} -.fa-subscript:before { - content: "\f12c"; -} -.fa-eraser:before { - content: "\f12d"; -} -.fa-puzzle-piece:before { - content: "\f12e"; -} -.fa-microphone:before { - content: "\f130"; -} -.fa-microphone-slash:before { - content: "\f131"; -} -.fa-shield:before { - content: "\f132"; -} -.fa-calendar-o:before { - content: "\f133"; -} -.fa-fire-extinguisher:before { - content: "\f134"; -} -.fa-rocket:before { - content: "\f135"; -} -.fa-maxcdn:before { - content: "\f136"; -} -.fa-chevron-circle-left:before { - content: "\f137"; -} -.fa-chevron-circle-right:before { - content: "\f138"; -} -.fa-chevron-circle-up:before { - content: "\f139"; -} -.fa-chevron-circle-down:before { - content: "\f13a"; -} -.fa-html5:before { - content: "\f13b"; -} -.fa-css3:before { - content: "\f13c"; -} -.fa-anchor:before { - content: "\f13d"; -} -.fa-unlock-alt:before { - content: "\f13e"; -} -.fa-bullseye:before { - content: "\f140"; -} -.fa-ellipsis-h:before { - content: "\f141"; -} -.fa-ellipsis-v:before { - content: "\f142"; -} -.fa-rss-square:before { - content: "\f143"; -} -.fa-play-circle:before { - content: "\f144"; -} -.fa-ticket:before { - content: "\f145"; -} -.fa-minus-square:before { - content: "\f146"; -} -.fa-minus-square-o:before { - content: "\f147"; -} -.fa-level-up:before { - content: "\f148"; -} -.fa-level-down:before { - content: "\f149"; -} -.fa-check-square:before { - content: "\f14a"; -} -.fa-pencil-square:before { - content: "\f14b"; -} -.fa-external-link-square:before { - content: "\f14c"; -} -.fa-share-square:before { - content: "\f14d"; -} -.fa-compass:before { - content: "\f14e"; -} -.fa-toggle-down:before, -.fa-caret-square-o-down:before { - content: "\f150"; -} -.fa-toggle-up:before, -.fa-caret-square-o-up:before { - content: "\f151"; -} -.fa-toggle-right:before, -.fa-caret-square-o-right:before { - content: "\f152"; -} -.fa-euro:before, -.fa-eur:before { - content: "\f153"; -} -.fa-gbp:before { - content: "\f154"; -} -.fa-dollar:before, -.fa-usd:before { - content: "\f155"; -} -.fa-rupee:before, -.fa-inr:before { - content: "\f156"; -} -.fa-cny:before, -.fa-rmb:before, -.fa-yen:before, -.fa-jpy:before { - content: "\f157"; -} -.fa-ruble:before, -.fa-rouble:before, -.fa-rub:before { - content: "\f158"; -} -.fa-won:before, -.fa-krw:before { - content: "\f159"; -} -.fa-bitcoin:before, -.fa-btc:before { - content: "\f15a"; -} -.fa-file:before { - content: "\f15b"; -} -.fa-file-text:before { - content: "\f15c"; -} -.fa-sort-alpha-asc:before { - content: "\f15d"; -} -.fa-sort-alpha-desc:before { - content: "\f15e"; -} -.fa-sort-amount-asc:before { - content: "\f160"; -} -.fa-sort-amount-desc:before { - content: "\f161"; -} -.fa-sort-numeric-asc:before { - content: "\f162"; -} -.fa-sort-numeric-desc:before { - content: "\f163"; -} -.fa-thumbs-up:before { - content: "\f164"; -} -.fa-thumbs-down:before { - content: "\f165"; -} -.fa-youtube-square:before { - content: "\f166"; -} -.fa-youtube:before { - content: "\f167"; -} -.fa-xing:before { - content: "\f168"; -} -.fa-xing-square:before { - content: "\f169"; -} -.fa-youtube-play:before { - content: "\f16a"; -} -.fa-dropbox:before { - content: "\f16b"; -} -.fa-stack-overflow:before { - content: "\f16c"; -} -.fa-instagram:before { - content: "\f16d"; -} -.fa-flickr:before { - content: "\f16e"; -} -.fa-adn:before { - content: "\f170"; -} -.fa-bitbucket:before { - content: "\f171"; -} -.fa-bitbucket-square:before { - content: "\f172"; -} -.fa-tumblr:before { - content: "\f173"; -} -.fa-tumblr-square:before { - content: "\f174"; -} -.fa-long-arrow-down:before { - content: "\f175"; -} -.fa-long-arrow-up:before { - content: "\f176"; -} -.fa-long-arrow-left:before { - content: "\f177"; -} -.fa-long-arrow-right:before { - content: "\f178"; -} -.fa-apple:before { - content: "\f179"; -} -.fa-windows:before { - content: "\f17a"; -} -.fa-android:before { - content: "\f17b"; -} -.fa-linux:before { - content: "\f17c"; -} -.fa-dribbble:before { - content: "\f17d"; -} -.fa-skype:before { - content: "\f17e"; -} -.fa-foursquare:before { - content: "\f180"; -} -.fa-trello:before { - content: "\f181"; -} -.fa-female:before { - content: "\f182"; -} -.fa-male:before { - content: "\f183"; -} -.fa-gittip:before, -.fa-gratipay:before { - content: "\f184"; -} -.fa-sun-o:before { - content: "\f185"; -} -.fa-moon-o:before { - content: "\f186"; -} -.fa-archive:before { - content: "\f187"; -} -.fa-bug:before { - content: "\f188"; -} -.fa-vk:before { - content: "\f189"; -} -.fa-weibo:before { - content: "\f18a"; -} -.fa-renren:before { - content: "\f18b"; -} -.fa-pagelines:before { - content: "\f18c"; -} -.fa-stack-exchange:before { - content: "\f18d"; -} -.fa-arrow-circle-o-right:before { - content: "\f18e"; -} -.fa-arrow-circle-o-left:before { - content: "\f190"; -} -.fa-toggle-left:before, -.fa-caret-square-o-left:before { - content: "\f191"; -} -.fa-dot-circle-o:before { - content: "\f192"; -} -.fa-wheelchair:before { - content: "\f193"; -} -.fa-vimeo-square:before { - content: "\f194"; -} -.fa-turkish-lira:before, -.fa-try:before { - content: "\f195"; -} -.fa-plus-square-o:before { - content: "\f196"; -} -.fa-space-shuttle:before { - content: "\f197"; -} -.fa-slack:before { - content: "\f198"; -} -.fa-envelope-square:before { - content: "\f199"; -} -.fa-wordpress:before { - content: "\f19a"; -} -.fa-openid:before { - content: "\f19b"; -} -.fa-institution:before, -.fa-bank:before, -.fa-university:before { - content: "\f19c"; -} -.fa-mortar-board:before, -.fa-graduation-cap:before { - content: "\f19d"; -} -.fa-yahoo:before { - content: "\f19e"; -} -.fa-google:before { - content: "\f1a0"; -} -.fa-reddit:before { - content: "\f1a1"; -} -.fa-reddit-square:before { - content: "\f1a2"; -} -.fa-stumbleupon-circle:before { - content: "\f1a3"; -} -.fa-stumbleupon:before { - content: "\f1a4"; -} -.fa-delicious:before { - content: "\f1a5"; -} -.fa-digg:before { - content: "\f1a6"; -} -.fa-pied-piper-pp:before { - content: "\f1a7"; -} -.fa-pied-piper-alt:before { - content: "\f1a8"; -} -.fa-drupal:before { - content: "\f1a9"; -} -.fa-joomla:before { - content: "\f1aa"; -} -.fa-language:before { - content: "\f1ab"; -} -.fa-fax:before { - content: "\f1ac"; -} -.fa-building:before { - content: "\f1ad"; -} -.fa-child:before { - content: "\f1ae"; -} -.fa-paw:before { - content: "\f1b0"; -} -.fa-spoon:before { - content: "\f1b1"; -} -.fa-cube:before { - content: "\f1b2"; -} -.fa-cubes:before { - content: "\f1b3"; -} -.fa-behance:before { - content: "\f1b4"; -} -.fa-behance-square:before { - content: "\f1b5"; -} -.fa-steam:before { - content: "\f1b6"; -} -.fa-steam-square:before { - content: "\f1b7"; -} -.fa-recycle:before { - content: "\f1b8"; -} -.fa-automobile:before, -.fa-car:before { - content: "\f1b9"; -} -.fa-cab:before, -.fa-taxi:before { - content: "\f1ba"; -} -.fa-tree:before { - content: "\f1bb"; -} -.fa-spotify:before { - content: "\f1bc"; -} -.fa-deviantart:before { - content: "\f1bd"; -} -.fa-soundcloud:before { - content: "\f1be"; -} -.fa-database:before { - content: "\f1c0"; -} -.fa-file-pdf-o:before { - content: "\f1c1"; -} -.fa-file-word-o:before { - content: "\f1c2"; -} -.fa-file-excel-o:before { - content: "\f1c3"; -} -.fa-file-powerpoint-o:before { - content: "\f1c4"; -} -.fa-file-photo-o:before, -.fa-file-picture-o:before, -.fa-file-image-o:before { - content: "\f1c5"; -} -.fa-file-zip-o:before, -.fa-file-archive-o:before { - content: "\f1c6"; -} -.fa-file-sound-o:before, -.fa-file-audio-o:before { - content: "\f1c7"; -} -.fa-file-movie-o:before, -.fa-file-video-o:before { - content: "\f1c8"; -} -.fa-file-code-o:before { - content: "\f1c9"; -} -.fa-vine:before { - content: "\f1ca"; -} -.fa-codepen:before { - content: "\f1cb"; -} -.fa-jsfiddle:before { - content: "\f1cc"; -} -.fa-life-bouy:before, -.fa-life-buoy:before, -.fa-life-saver:before, -.fa-support:before, -.fa-life-ring:before { - content: "\f1cd"; -} -.fa-circle-o-notch:before { - content: "\f1ce"; -} -.fa-ra:before, -.fa-resistance:before, -.fa-rebel:before { - content: "\f1d0"; -} -.fa-ge:before, -.fa-empire:before { - content: "\f1d1"; -} -.fa-git-square:before { - content: "\f1d2"; -} -.fa-git:before { - content: "\f1d3"; -} -.fa-y-combinator-square:before, -.fa-yc-square:before, -.fa-hacker-news:before { - content: "\f1d4"; -} -.fa-tencent-weibo:before { - content: "\f1d5"; -} -.fa-qq:before { - content: "\f1d6"; -} -.fa-wechat:before, -.fa-weixin:before { - content: "\f1d7"; -} -.fa-send:before, -.fa-paper-plane:before { - content: "\f1d8"; -} -.fa-send-o:before, -.fa-paper-plane-o:before { - content: "\f1d9"; -} -.fa-history:before { - content: "\f1da"; -} -.fa-circle-thin:before { - content: "\f1db"; -} -.fa-header:before { - content: "\f1dc"; -} -.fa-paragraph:before { - content: "\f1dd"; -} -.fa-sliders:before { - content: "\f1de"; -} -.fa-share-alt:before { - content: "\f1e0"; -} -.fa-share-alt-square:before { - content: "\f1e1"; -} -.fa-bomb:before { - content: "\f1e2"; -} -.fa-soccer-ball-o:before, -.fa-futbol-o:before { - content: "\f1e3"; -} -.fa-tty:before { - content: "\f1e4"; -} -.fa-binoculars:before { - content: "\f1e5"; -} -.fa-plug:before { - content: "\f1e6"; -} -.fa-slideshare:before { - content: "\f1e7"; -} -.fa-twitch:before { - content: "\f1e8"; -} -.fa-yelp:before { - content: "\f1e9"; -} -.fa-newspaper-o:before { - content: "\f1ea"; -} -.fa-wifi:before { - content: "\f1eb"; -} -.fa-calculator:before { - content: "\f1ec"; -} -.fa-paypal:before { - content: "\f1ed"; -} -.fa-google-wallet:before { - content: "\f1ee"; -} -.fa-cc-visa:before { - content: "\f1f0"; -} -.fa-cc-mastercard:before { - content: "\f1f1"; -} -.fa-cc-discover:before { - content: "\f1f2"; -} -.fa-cc-amex:before { - content: "\f1f3"; -} -.fa-cc-paypal:before { - content: "\f1f4"; -} -.fa-cc-stripe:before { - content: "\f1f5"; -} -.fa-bell-slash:before { - content: "\f1f6"; -} -.fa-bell-slash-o:before { - content: "\f1f7"; -} -.fa-trash:before { - content: "\f1f8"; -} -.fa-copyright:before { - content: "\f1f9"; -} -.fa-at:before { - content: "\f1fa"; -} -.fa-eyedropper:before { - content: "\f1fb"; -} -.fa-paint-brush:before { - content: "\f1fc"; -} -.fa-birthday-cake:before { - content: "\f1fd"; -} -.fa-area-chart:before { - content: "\f1fe"; -} -.fa-pie-chart:before { - content: "\f200"; -} -.fa-line-chart:before { - content: "\f201"; -} -.fa-lastfm:before { - content: "\f202"; -} -.fa-lastfm-square:before { - content: "\f203"; -} -.fa-toggle-off:before { - content: "\f204"; -} -.fa-toggle-on:before { - content: "\f205"; -} -.fa-bicycle:before { - content: "\f206"; -} -.fa-bus:before { - content: "\f207"; -} -.fa-ioxhost:before { - content: "\f208"; -} -.fa-angellist:before { - content: "\f209"; -} -.fa-cc:before { - content: "\f20a"; -} -.fa-shekel:before, -.fa-sheqel:before, -.fa-ils:before { - content: "\f20b"; -} -.fa-meanpath:before { - content: "\f20c"; -} -.fa-buysellads:before { - content: "\f20d"; -} -.fa-connectdevelop:before { - content: "\f20e"; -} -.fa-dashcube:before { - content: "\f210"; -} -.fa-forumbee:before { - content: "\f211"; -} -.fa-leanpub:before { - content: "\f212"; -} -.fa-sellsy:before { - content: "\f213"; -} -.fa-shirtsinbulk:before { - content: "\f214"; -} -.fa-simplybuilt:before { - content: "\f215"; -} -.fa-skyatlas:before { - content: "\f216"; -} -.fa-cart-plus:before { - content: "\f217"; -} -.fa-cart-arrow-down:before { - content: "\f218"; -} -.fa-diamond:before { - content: "\f219"; -} -.fa-ship:before { - content: "\f21a"; -} -.fa-user-secret:before { - content: "\f21b"; -} -.fa-motorcycle:before { - content: "\f21c"; -} -.fa-street-view:before { - content: "\f21d"; -} -.fa-heartbeat:before { - content: "\f21e"; -} -.fa-venus:before { - content: "\f221"; -} -.fa-mars:before { - content: "\f222"; -} -.fa-mercury:before { - content: "\f223"; -} -.fa-intersex:before, -.fa-transgender:before { - content: "\f224"; -} -.fa-transgender-alt:before { - content: "\f225"; -} -.fa-venus-double:before { - content: "\f226"; -} -.fa-mars-double:before { - content: "\f227"; -} -.fa-venus-mars:before { - content: "\f228"; -} -.fa-mars-stroke:before { - content: "\f229"; -} -.fa-mars-stroke-v:before { - content: "\f22a"; -} -.fa-mars-stroke-h:before { - content: "\f22b"; -} -.fa-neuter:before { - content: "\f22c"; -} -.fa-genderless:before { - content: "\f22d"; -} -.fa-facebook-official:before { - content: "\f230"; -} -.fa-pinterest-p:before { - content: "\f231"; -} -.fa-whatsapp:before { - content: "\f232"; -} -.fa-server:before { - content: "\f233"; -} -.fa-user-plus:before { - content: "\f234"; -} -.fa-user-times:before { - content: "\f235"; -} -.fa-hotel:before, -.fa-bed:before { - content: "\f236"; -} -.fa-viacoin:before { - content: "\f237"; -} -.fa-train:before { - content: "\f238"; -} -.fa-subway:before { - content: "\f239"; -} -.fa-medium:before { - content: "\f23a"; -} -.fa-yc:before, -.fa-y-combinator:before { - content: "\f23b"; -} -.fa-optin-monster:before { - content: "\f23c"; -} -.fa-opencart:before { - content: "\f23d"; -} -.fa-expeditedssl:before { - content: "\f23e"; -} -.fa-battery-4:before, -.fa-battery:before, -.fa-battery-full:before { - content: "\f240"; -} -.fa-battery-3:before, -.fa-battery-three-quarters:before { - content: "\f241"; -} -.fa-battery-2:before, -.fa-battery-half:before { - content: "\f242"; -} -.fa-battery-1:before, -.fa-battery-quarter:before { - content: "\f243"; -} -.fa-battery-0:before, -.fa-battery-empty:before { - content: "\f244"; -} -.fa-mouse-pointer:before { - content: "\f245"; -} -.fa-i-cursor:before { - content: "\f246"; -} -.fa-object-group:before { - content: "\f247"; -} -.fa-object-ungroup:before { - content: "\f248"; -} -.fa-sticky-note:before { - content: "\f249"; -} -.fa-sticky-note-o:before { - content: "\f24a"; -} -.fa-cc-jcb:before { - content: "\f24b"; -} -.fa-cc-diners-club:before { - content: "\f24c"; -} -.fa-clone:before { - content: "\f24d"; -} -.fa-balance-scale:before { - content: "\f24e"; -} -.fa-hourglass-o:before { - content: "\f250"; -} -.fa-hourglass-1:before, -.fa-hourglass-start:before { - content: "\f251"; -} -.fa-hourglass-2:before, -.fa-hourglass-half:before { - content: "\f252"; -} -.fa-hourglass-3:before, -.fa-hourglass-end:before { - content: "\f253"; -} -.fa-hourglass:before { - content: "\f254"; -} -.fa-hand-grab-o:before, -.fa-hand-rock-o:before { - content: "\f255"; -} -.fa-hand-stop-o:before, -.fa-hand-paper-o:before { - content: "\f256"; -} -.fa-hand-scissors-o:before { - content: "\f257"; -} -.fa-hand-lizard-o:before { - content: "\f258"; -} -.fa-hand-spock-o:before { - content: "\f259"; -} -.fa-hand-pointer-o:before { - content: "\f25a"; -} -.fa-hand-peace-o:before { - content: "\f25b"; -} -.fa-trademark:before { - content: "\f25c"; -} -.fa-registered:before { - content: "\f25d"; -} -.fa-creative-commons:before { - content: "\f25e"; -} -.fa-gg:before { - content: "\f260"; -} -.fa-gg-circle:before { - content: "\f261"; -} -.fa-tripadvisor:before { - content: "\f262"; -} -.fa-odnoklassniki:before { - content: "\f263"; -} -.fa-odnoklassniki-square:before { - content: "\f264"; -} -.fa-get-pocket:before { - content: "\f265"; -} -.fa-wikipedia-w:before { - content: "\f266"; -} -.fa-safari:before { - content: "\f267"; -} -.fa-chrome:before { - content: "\f268"; -} -.fa-firefox:before { - content: "\f269"; -} -.fa-opera:before { - content: "\f26a"; -} -.fa-internet-explorer:before { - content: "\f26b"; -} -.fa-tv:before, -.fa-television:before { - content: "\f26c"; -} -.fa-contao:before { - content: "\f26d"; -} -.fa-500px:before { - content: "\f26e"; -} -.fa-amazon:before { - content: "\f270"; -} -.fa-calendar-plus-o:before { - content: "\f271"; -} -.fa-calendar-minus-o:before { - content: "\f272"; -} -.fa-calendar-times-o:before { - content: "\f273"; -} -.fa-calendar-check-o:before { - content: "\f274"; -} -.fa-industry:before { - content: "\f275"; -} -.fa-map-pin:before { - content: "\f276"; -} -.fa-map-signs:before { - content: "\f277"; -} -.fa-map-o:before { - content: "\f278"; -} -.fa-map:before { - content: "\f279"; -} -.fa-commenting:before { - content: "\f27a"; -} -.fa-commenting-o:before { - content: "\f27b"; -} -.fa-houzz:before { - content: "\f27c"; -} -.fa-vimeo:before { - content: "\f27d"; -} -.fa-black-tie:before { - content: "\f27e"; -} -.fa-fonticons:before { - content: "\f280"; -} -.fa-reddit-alien:before { - content: "\f281"; -} -.fa-edge:before { - content: "\f282"; -} -.fa-credit-card-alt:before { - content: "\f283"; -} -.fa-codiepie:before { - content: "\f284"; -} -.fa-modx:before { - content: "\f285"; -} -.fa-fort-awesome:before { - content: "\f286"; -} -.fa-usb:before { - content: "\f287"; -} -.fa-product-hunt:before { - content: "\f288"; -} -.fa-mixcloud:before { - content: "\f289"; -} -.fa-scribd:before { - content: "\f28a"; -} -.fa-pause-circle:before { - content: "\f28b"; -} -.fa-pause-circle-o:before { - content: "\f28c"; -} -.fa-stop-circle:before { - content: "\f28d"; -} -.fa-stop-circle-o:before { - content: "\f28e"; -} -.fa-shopping-bag:before { - content: "\f290"; -} -.fa-shopping-basket:before { - content: "\f291"; -} -.fa-hashtag:before { - content: "\f292"; -} -.fa-bluetooth:before { - content: "\f293"; -} -.fa-bluetooth-b:before { - content: "\f294"; -} -.fa-percent:before { - content: "\f295"; -} -.fa-gitlab:before { - content: "\f296"; -} -.fa-wpbeginner:before { - content: "\f297"; -} -.fa-wpforms:before { - content: "\f298"; -} -.fa-envira:before { - content: "\f299"; -} -.fa-universal-access:before { - content: "\f29a"; -} -.fa-wheelchair-alt:before { - content: "\f29b"; -} -.fa-question-circle-o:before { - content: "\f29c"; -} -.fa-blind:before { - content: "\f29d"; -} -.fa-audio-description:before { - content: "\f29e"; -} -.fa-volume-control-phone:before { - content: "\f2a0"; -} -.fa-braille:before { - content: "\f2a1"; -} -.fa-assistive-listening-systems:before { - content: "\f2a2"; -} -.fa-asl-interpreting:before, -.fa-american-sign-language-interpreting:before { - content: "\f2a3"; -} -.fa-deafness:before, -.fa-hard-of-hearing:before, -.fa-deaf:before { - content: "\f2a4"; -} -.fa-glide:before { - content: "\f2a5"; -} -.fa-glide-g:before { - content: "\f2a6"; -} -.fa-signing:before, -.fa-sign-language:before { - content: "\f2a7"; -} -.fa-low-vision:before { - content: "\f2a8"; -} -.fa-viadeo:before { - content: "\f2a9"; -} -.fa-viadeo-square:before { - content: "\f2aa"; -} -.fa-snapchat:before { - content: "\f2ab"; -} -.fa-snapchat-ghost:before { - content: "\f2ac"; -} -.fa-snapchat-square:before { - content: "\f2ad"; -} -.fa-pied-piper:before { - content: "\f2ae"; -} -.fa-first-order:before { - content: "\f2b0"; -} -.fa-yoast:before { - content: "\f2b1"; -} -.fa-themeisle:before { - content: "\f2b2"; -} -.fa-google-plus-circle:before, -.fa-google-plus-official:before { - content: "\f2b3"; -} -.fa-fa:before, -.fa-font-awesome:before { - content: "\f2b4"; -} -.fa-handshake-o:before { - content: "\f2b5"; -} -.fa-envelope-open:before { - content: "\f2b6"; -} -.fa-envelope-open-o:before { - content: "\f2b7"; -} -.fa-linode:before { - content: "\f2b8"; -} -.fa-address-book:before { - content: "\f2b9"; -} -.fa-address-book-o:before { - content: "\f2ba"; -} -.fa-vcard:before, -.fa-address-card:before { - content: "\f2bb"; -} -.fa-vcard-o:before, -.fa-address-card-o:before { - content: "\f2bc"; -} -.fa-user-circle:before { - content: "\f2bd"; -} -.fa-user-circle-o:before { - content: "\f2be"; -} -.fa-user-o:before { - content: "\f2c0"; -} -.fa-id-badge:before { - content: "\f2c1"; -} -.fa-drivers-license:before, -.fa-id-card:before { - content: "\f2c2"; -} -.fa-drivers-license-o:before, -.fa-id-card-o:before { - content: "\f2c3"; -} -.fa-quora:before { - content: "\f2c4"; -} -.fa-free-code-camp:before { - content: "\f2c5"; -} -.fa-telegram:before { - content: "\f2c6"; -} -.fa-thermometer-4:before, -.fa-thermometer:before, -.fa-thermometer-full:before { - content: "\f2c7"; -} -.fa-thermometer-3:before, -.fa-thermometer-three-quarters:before { - content: "\f2c8"; -} -.fa-thermometer-2:before, -.fa-thermometer-half:before { - content: "\f2c9"; -} -.fa-thermometer-1:before, -.fa-thermometer-quarter:before { - content: "\f2ca"; -} -.fa-thermometer-0:before, -.fa-thermometer-empty:before { - content: "\f2cb"; -} -.fa-shower:before { - content: "\f2cc"; -} -.fa-bathtub:before, -.fa-s15:before, -.fa-bath:before { - content: "\f2cd"; -} -.fa-podcast:before { - content: "\f2ce"; -} -.fa-window-maximize:before { - content: "\f2d0"; -} -.fa-window-minimize:before { - content: "\f2d1"; -} -.fa-window-restore:before { - content: "\f2d2"; -} -.fa-times-rectangle:before, -.fa-window-close:before { - content: "\f2d3"; -} -.fa-times-rectangle-o:before, -.fa-window-close-o:before { - content: "\f2d4"; -} -.fa-bandcamp:before { - content: "\f2d5"; -} -.fa-grav:before { - content: "\f2d6"; -} -.fa-etsy:before { - content: "\f2d7"; -} -.fa-imdb:before { - content: "\f2d8"; -} -.fa-ravelry:before { - content: "\f2d9"; -} -.fa-eercast:before { - content: "\f2da"; -} -.fa-microchip:before { - content: "\f2db"; -} -.fa-snowflake-o:before { - content: "\f2dc"; -} -.fa-superpowers:before { - content: "\f2dd"; -} -.fa-wpexplorer:before { - content: "\f2de"; -} -.fa-meetup:before { - content: "\f2e0"; -} -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} -.sr-only-focusable:active, -.sr-only-focusable:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; -} diff --git a/netbox/project-static/font-awesome-4.7.0/css/font-awesome.min.css b/netbox/project-static/font-awesome-4.7.0/css/font-awesome.min.css deleted file mode 100644 index 540440ce89..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/css/font-awesome.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/netbox/project-static/font-awesome-4.7.0/fonts/FontAwesome.otf b/netbox/project-static/font-awesome-4.7.0/fonts/FontAwesome.otf deleted file mode 100644 index 401ec0f36e..0000000000 Binary files a/netbox/project-static/font-awesome-4.7.0/fonts/FontAwesome.otf and /dev/null differ diff --git a/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.eot b/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.eot deleted file mode 100644 index e9f60ca953..0000000000 Binary files a/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.svg b/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.svg deleted file mode 100644 index 855c845e53..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,2671 +0,0 @@ - - - - -Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 - By ,,, -Copyright Dave Gandy 2016. All rights reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf b/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf deleted file mode 100644 index 35acda2fa1..0000000000 Binary files a/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf and /dev/null differ diff --git a/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.woff b/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.woff deleted file mode 100644 index 400014a4b0..0000000000 Binary files a/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2 b/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2 deleted file mode 100644 index 4d13fc6040..0000000000 Binary files a/netbox/project-static/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2 and /dev/null differ diff --git a/netbox/project-static/font-awesome-4.7.0/less/animated.less b/netbox/project-static/font-awesome-4.7.0/less/animated.less deleted file mode 100644 index 66ad52a5ba..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/less/animated.less +++ /dev/null @@ -1,34 +0,0 @@ -// Animated Icons -// -------------------------- - -.@{fa-css-prefix}-spin { - -webkit-animation: fa-spin 2s infinite linear; - animation: fa-spin 2s infinite linear; -} - -.@{fa-css-prefix}-pulse { - -webkit-animation: fa-spin 1s infinite steps(8); - animation: fa-spin 1s infinite steps(8); -} - -@-webkit-keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} - -@keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} diff --git a/netbox/project-static/font-awesome-4.7.0/less/bordered-pulled.less b/netbox/project-static/font-awesome-4.7.0/less/bordered-pulled.less deleted file mode 100644 index f1c8ad75f5..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/less/bordered-pulled.less +++ /dev/null @@ -1,25 +0,0 @@ -// Bordered & Pulled -// ------------------------- - -.@{fa-css-prefix}-border { - padding: .2em .25em .15em; - border: solid .08em @fa-border-color; - border-radius: .1em; -} - -.@{fa-css-prefix}-pull-left { float: left; } -.@{fa-css-prefix}-pull-right { float: right; } - -.@{fa-css-prefix} { - &.@{fa-css-prefix}-pull-left { margin-right: .3em; } - &.@{fa-css-prefix}-pull-right { margin-left: .3em; } -} - -/* Deprecated as of 4.4.0 */ -.pull-right { float: right; } -.pull-left { float: left; } - -.@{fa-css-prefix} { - &.pull-left { margin-right: .3em; } - &.pull-right { margin-left: .3em; } -} diff --git a/netbox/project-static/font-awesome-4.7.0/less/fixed-width.less b/netbox/project-static/font-awesome-4.7.0/less/fixed-width.less deleted file mode 100644 index 110289f2f4..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/less/fixed-width.less +++ /dev/null @@ -1,6 +0,0 @@ -// Fixed Width Icons -// ------------------------- -.@{fa-css-prefix}-fw { - width: (18em / 14); - text-align: center; -} diff --git a/netbox/project-static/font-awesome-4.7.0/less/font-awesome.less b/netbox/project-static/font-awesome-4.7.0/less/font-awesome.less deleted file mode 100644 index c3677def31..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/less/font-awesome.less +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */ - -@import "variables.less"; -@import "mixins.less"; -@import "path.less"; -@import "core.less"; -@import "larger.less"; -@import "fixed-width.less"; -@import "list.less"; -@import "bordered-pulled.less"; -@import "animated.less"; -@import "rotated-flipped.less"; -@import "stacked.less"; -@import "icons.less"; -@import "screen-reader.less"; diff --git a/netbox/project-static/font-awesome-4.7.0/less/icons.less b/netbox/project-static/font-awesome-4.7.0/less/icons.less deleted file mode 100644 index 159d600425..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/less/icons.less +++ /dev/null @@ -1,789 +0,0 @@ -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen - readers do not read off random characters that represent icons */ - -.@{fa-css-prefix}-glass:before { content: @fa-var-glass; } -.@{fa-css-prefix}-music:before { content: @fa-var-music; } -.@{fa-css-prefix}-search:before { content: @fa-var-search; } -.@{fa-css-prefix}-envelope-o:before { content: @fa-var-envelope-o; } -.@{fa-css-prefix}-heart:before { content: @fa-var-heart; } -.@{fa-css-prefix}-star:before { content: @fa-var-star; } -.@{fa-css-prefix}-star-o:before { content: @fa-var-star-o; } -.@{fa-css-prefix}-user:before { content: @fa-var-user; } -.@{fa-css-prefix}-film:before { content: @fa-var-film; } -.@{fa-css-prefix}-th-large:before { content: @fa-var-th-large; } -.@{fa-css-prefix}-th:before { content: @fa-var-th; } -.@{fa-css-prefix}-th-list:before { content: @fa-var-th-list; } -.@{fa-css-prefix}-check:before { content: @fa-var-check; } -.@{fa-css-prefix}-remove:before, -.@{fa-css-prefix}-close:before, -.@{fa-css-prefix}-times:before { content: @fa-var-times; } -.@{fa-css-prefix}-search-plus:before { content: @fa-var-search-plus; } -.@{fa-css-prefix}-search-minus:before { content: @fa-var-search-minus; } -.@{fa-css-prefix}-power-off:before { content: @fa-var-power-off; } -.@{fa-css-prefix}-signal:before { content: @fa-var-signal; } -.@{fa-css-prefix}-gear:before, -.@{fa-css-prefix}-cog:before { content: @fa-var-cog; } -.@{fa-css-prefix}-trash-o:before { content: @fa-var-trash-o; } -.@{fa-css-prefix}-home:before { content: @fa-var-home; } -.@{fa-css-prefix}-file-o:before { content: @fa-var-file-o; } -.@{fa-css-prefix}-clock-o:before { content: @fa-var-clock-o; } -.@{fa-css-prefix}-road:before { content: @fa-var-road; } -.@{fa-css-prefix}-download:before { content: @fa-var-download; } -.@{fa-css-prefix}-arrow-circle-o-down:before { content: @fa-var-arrow-circle-o-down; } -.@{fa-css-prefix}-arrow-circle-o-up:before { content: @fa-var-arrow-circle-o-up; } -.@{fa-css-prefix}-inbox:before { content: @fa-var-inbox; } -.@{fa-css-prefix}-play-circle-o:before { content: @fa-var-play-circle-o; } -.@{fa-css-prefix}-rotate-right:before, -.@{fa-css-prefix}-repeat:before { content: @fa-var-repeat; } -.@{fa-css-prefix}-refresh:before { content: @fa-var-refresh; } -.@{fa-css-prefix}-list-alt:before { content: @fa-var-list-alt; } -.@{fa-css-prefix}-lock:before { content: @fa-var-lock; } -.@{fa-css-prefix}-flag:before { content: @fa-var-flag; } -.@{fa-css-prefix}-headphones:before { content: @fa-var-headphones; } -.@{fa-css-prefix}-volume-off:before { content: @fa-var-volume-off; } -.@{fa-css-prefix}-volume-down:before { content: @fa-var-volume-down; } -.@{fa-css-prefix}-volume-up:before { content: @fa-var-volume-up; } -.@{fa-css-prefix}-qrcode:before { content: @fa-var-qrcode; } -.@{fa-css-prefix}-barcode:before { content: @fa-var-barcode; } -.@{fa-css-prefix}-tag:before { content: @fa-var-tag; } -.@{fa-css-prefix}-tags:before { content: @fa-var-tags; } -.@{fa-css-prefix}-book:before { content: @fa-var-book; } -.@{fa-css-prefix}-bookmark:before { content: @fa-var-bookmark; } -.@{fa-css-prefix}-print:before { content: @fa-var-print; } -.@{fa-css-prefix}-camera:before { content: @fa-var-camera; } -.@{fa-css-prefix}-font:before { content: @fa-var-font; } -.@{fa-css-prefix}-bold:before { content: @fa-var-bold; } -.@{fa-css-prefix}-italic:before { content: @fa-var-italic; } -.@{fa-css-prefix}-text-height:before { content: @fa-var-text-height; } -.@{fa-css-prefix}-text-width:before { content: @fa-var-text-width; } -.@{fa-css-prefix}-align-left:before { content: @fa-var-align-left; } -.@{fa-css-prefix}-align-center:before { content: @fa-var-align-center; } -.@{fa-css-prefix}-align-right:before { content: @fa-var-align-right; } -.@{fa-css-prefix}-align-justify:before { content: @fa-var-align-justify; } -.@{fa-css-prefix}-list:before { content: @fa-var-list; } -.@{fa-css-prefix}-dedent:before, -.@{fa-css-prefix}-outdent:before { content: @fa-var-outdent; } -.@{fa-css-prefix}-indent:before { content: @fa-var-indent; } -.@{fa-css-prefix}-video-camera:before { content: @fa-var-video-camera; } -.@{fa-css-prefix}-photo:before, -.@{fa-css-prefix}-image:before, -.@{fa-css-prefix}-picture-o:before { content: @fa-var-picture-o; } -.@{fa-css-prefix}-pencil:before { content: @fa-var-pencil; } -.@{fa-css-prefix}-map-marker:before { content: @fa-var-map-marker; } -.@{fa-css-prefix}-adjust:before { content: @fa-var-adjust; } -.@{fa-css-prefix}-tint:before { content: @fa-var-tint; } -.@{fa-css-prefix}-edit:before, -.@{fa-css-prefix}-pencil-square-o:before { content: @fa-var-pencil-square-o; } -.@{fa-css-prefix}-share-square-o:before { content: @fa-var-share-square-o; } -.@{fa-css-prefix}-check-square-o:before { content: @fa-var-check-square-o; } -.@{fa-css-prefix}-arrows:before { content: @fa-var-arrows; } -.@{fa-css-prefix}-step-backward:before { content: @fa-var-step-backward; } -.@{fa-css-prefix}-fast-backward:before { content: @fa-var-fast-backward; } -.@{fa-css-prefix}-backward:before { content: @fa-var-backward; } -.@{fa-css-prefix}-play:before { content: @fa-var-play; } -.@{fa-css-prefix}-pause:before { content: @fa-var-pause; } -.@{fa-css-prefix}-stop:before { content: @fa-var-stop; } -.@{fa-css-prefix}-forward:before { content: @fa-var-forward; } -.@{fa-css-prefix}-fast-forward:before { content: @fa-var-fast-forward; } -.@{fa-css-prefix}-step-forward:before { content: @fa-var-step-forward; } -.@{fa-css-prefix}-eject:before { content: @fa-var-eject; } -.@{fa-css-prefix}-chevron-left:before { content: @fa-var-chevron-left; } -.@{fa-css-prefix}-chevron-right:before { content: @fa-var-chevron-right; } -.@{fa-css-prefix}-plus-circle:before { content: @fa-var-plus-circle; } -.@{fa-css-prefix}-minus-circle:before { content: @fa-var-minus-circle; } -.@{fa-css-prefix}-times-circle:before { content: @fa-var-times-circle; } -.@{fa-css-prefix}-check-circle:before { content: @fa-var-check-circle; } -.@{fa-css-prefix}-question-circle:before { content: @fa-var-question-circle; } -.@{fa-css-prefix}-info-circle:before { content: @fa-var-info-circle; } -.@{fa-css-prefix}-crosshairs:before { content: @fa-var-crosshairs; } -.@{fa-css-prefix}-times-circle-o:before { content: @fa-var-times-circle-o; } -.@{fa-css-prefix}-check-circle-o:before { content: @fa-var-check-circle-o; } -.@{fa-css-prefix}-ban:before { content: @fa-var-ban; } -.@{fa-css-prefix}-arrow-left:before { content: @fa-var-arrow-left; } -.@{fa-css-prefix}-arrow-right:before { content: @fa-var-arrow-right; } -.@{fa-css-prefix}-arrow-up:before { content: @fa-var-arrow-up; } -.@{fa-css-prefix}-arrow-down:before { content: @fa-var-arrow-down; } -.@{fa-css-prefix}-mail-forward:before, -.@{fa-css-prefix}-share:before { content: @fa-var-share; } -.@{fa-css-prefix}-expand:before { content: @fa-var-expand; } -.@{fa-css-prefix}-compress:before { content: @fa-var-compress; } -.@{fa-css-prefix}-plus:before { content: @fa-var-plus; } -.@{fa-css-prefix}-minus:before { content: @fa-var-minus; } -.@{fa-css-prefix}-asterisk:before { content: @fa-var-asterisk; } -.@{fa-css-prefix}-exclamation-circle:before { content: @fa-var-exclamation-circle; } -.@{fa-css-prefix}-gift:before { content: @fa-var-gift; } -.@{fa-css-prefix}-leaf:before { content: @fa-var-leaf; } -.@{fa-css-prefix}-fire:before { content: @fa-var-fire; } -.@{fa-css-prefix}-eye:before { content: @fa-var-eye; } -.@{fa-css-prefix}-eye-slash:before { content: @fa-var-eye-slash; } -.@{fa-css-prefix}-warning:before, -.@{fa-css-prefix}-exclamation-triangle:before { content: @fa-var-exclamation-triangle; } -.@{fa-css-prefix}-plane:before { content: @fa-var-plane; } -.@{fa-css-prefix}-calendar:before { content: @fa-var-calendar; } -.@{fa-css-prefix}-random:before { content: @fa-var-random; } -.@{fa-css-prefix}-comment:before { content: @fa-var-comment; } -.@{fa-css-prefix}-magnet:before { content: @fa-var-magnet; } -.@{fa-css-prefix}-chevron-up:before { content: @fa-var-chevron-up; } -.@{fa-css-prefix}-chevron-down:before { content: @fa-var-chevron-down; } -.@{fa-css-prefix}-retweet:before { content: @fa-var-retweet; } -.@{fa-css-prefix}-shopping-cart:before { content: @fa-var-shopping-cart; } -.@{fa-css-prefix}-folder:before { content: @fa-var-folder; } -.@{fa-css-prefix}-folder-open:before { content: @fa-var-folder-open; } -.@{fa-css-prefix}-arrows-v:before { content: @fa-var-arrows-v; } -.@{fa-css-prefix}-arrows-h:before { content: @fa-var-arrows-h; } -.@{fa-css-prefix}-bar-chart-o:before, -.@{fa-css-prefix}-bar-chart:before { content: @fa-var-bar-chart; } -.@{fa-css-prefix}-twitter-square:before { content: @fa-var-twitter-square; } -.@{fa-css-prefix}-facebook-square:before { content: @fa-var-facebook-square; } -.@{fa-css-prefix}-camera-retro:before { content: @fa-var-camera-retro; } -.@{fa-css-prefix}-key:before { content: @fa-var-key; } -.@{fa-css-prefix}-gears:before, -.@{fa-css-prefix}-cogs:before { content: @fa-var-cogs; } -.@{fa-css-prefix}-comments:before { content: @fa-var-comments; } -.@{fa-css-prefix}-thumbs-o-up:before { content: @fa-var-thumbs-o-up; } -.@{fa-css-prefix}-thumbs-o-down:before { content: @fa-var-thumbs-o-down; } -.@{fa-css-prefix}-star-half:before { content: @fa-var-star-half; } -.@{fa-css-prefix}-heart-o:before { content: @fa-var-heart-o; } -.@{fa-css-prefix}-sign-out:before { content: @fa-var-sign-out; } -.@{fa-css-prefix}-linkedin-square:before { content: @fa-var-linkedin-square; } -.@{fa-css-prefix}-thumb-tack:before { content: @fa-var-thumb-tack; } -.@{fa-css-prefix}-external-link:before { content: @fa-var-external-link; } -.@{fa-css-prefix}-sign-in:before { content: @fa-var-sign-in; } -.@{fa-css-prefix}-trophy:before { content: @fa-var-trophy; } -.@{fa-css-prefix}-github-square:before { content: @fa-var-github-square; } -.@{fa-css-prefix}-upload:before { content: @fa-var-upload; } -.@{fa-css-prefix}-lemon-o:before { content: @fa-var-lemon-o; } -.@{fa-css-prefix}-phone:before { content: @fa-var-phone; } -.@{fa-css-prefix}-square-o:before { content: @fa-var-square-o; } -.@{fa-css-prefix}-bookmark-o:before { content: @fa-var-bookmark-o; } -.@{fa-css-prefix}-phone-square:before { content: @fa-var-phone-square; } -.@{fa-css-prefix}-twitter:before { content: @fa-var-twitter; } -.@{fa-css-prefix}-facebook-f:before, -.@{fa-css-prefix}-facebook:before { content: @fa-var-facebook; } -.@{fa-css-prefix}-github:before { content: @fa-var-github; } -.@{fa-css-prefix}-unlock:before { content: @fa-var-unlock; } -.@{fa-css-prefix}-credit-card:before { content: @fa-var-credit-card; } -.@{fa-css-prefix}-feed:before, -.@{fa-css-prefix}-rss:before { content: @fa-var-rss; } -.@{fa-css-prefix}-hdd-o:before { content: @fa-var-hdd-o; } -.@{fa-css-prefix}-bullhorn:before { content: @fa-var-bullhorn; } -.@{fa-css-prefix}-bell:before { content: @fa-var-bell; } -.@{fa-css-prefix}-certificate:before { content: @fa-var-certificate; } -.@{fa-css-prefix}-hand-o-right:before { content: @fa-var-hand-o-right; } -.@{fa-css-prefix}-hand-o-left:before { content: @fa-var-hand-o-left; } -.@{fa-css-prefix}-hand-o-up:before { content: @fa-var-hand-o-up; } -.@{fa-css-prefix}-hand-o-down:before { content: @fa-var-hand-o-down; } -.@{fa-css-prefix}-arrow-circle-left:before { content: @fa-var-arrow-circle-left; } -.@{fa-css-prefix}-arrow-circle-right:before { content: @fa-var-arrow-circle-right; } -.@{fa-css-prefix}-arrow-circle-up:before { content: @fa-var-arrow-circle-up; } -.@{fa-css-prefix}-arrow-circle-down:before { content: @fa-var-arrow-circle-down; } -.@{fa-css-prefix}-globe:before { content: @fa-var-globe; } -.@{fa-css-prefix}-wrench:before { content: @fa-var-wrench; } -.@{fa-css-prefix}-tasks:before { content: @fa-var-tasks; } -.@{fa-css-prefix}-filter:before { content: @fa-var-filter; } -.@{fa-css-prefix}-briefcase:before { content: @fa-var-briefcase; } -.@{fa-css-prefix}-arrows-alt:before { content: @fa-var-arrows-alt; } -.@{fa-css-prefix}-group:before, -.@{fa-css-prefix}-users:before { content: @fa-var-users; } -.@{fa-css-prefix}-chain:before, -.@{fa-css-prefix}-link:before { content: @fa-var-link; } -.@{fa-css-prefix}-cloud:before { content: @fa-var-cloud; } -.@{fa-css-prefix}-flask:before { content: @fa-var-flask; } -.@{fa-css-prefix}-cut:before, -.@{fa-css-prefix}-scissors:before { content: @fa-var-scissors; } -.@{fa-css-prefix}-copy:before, -.@{fa-css-prefix}-files-o:before { content: @fa-var-files-o; } -.@{fa-css-prefix}-paperclip:before { content: @fa-var-paperclip; } -.@{fa-css-prefix}-save:before, -.@{fa-css-prefix}-floppy-o:before { content: @fa-var-floppy-o; } -.@{fa-css-prefix}-square:before { content: @fa-var-square; } -.@{fa-css-prefix}-navicon:before, -.@{fa-css-prefix}-reorder:before, -.@{fa-css-prefix}-bars:before { content: @fa-var-bars; } -.@{fa-css-prefix}-list-ul:before { content: @fa-var-list-ul; } -.@{fa-css-prefix}-list-ol:before { content: @fa-var-list-ol; } -.@{fa-css-prefix}-strikethrough:before { content: @fa-var-strikethrough; } -.@{fa-css-prefix}-underline:before { content: @fa-var-underline; } -.@{fa-css-prefix}-table:before { content: @fa-var-table; } -.@{fa-css-prefix}-magic:before { content: @fa-var-magic; } -.@{fa-css-prefix}-truck:before { content: @fa-var-truck; } -.@{fa-css-prefix}-pinterest:before { content: @fa-var-pinterest; } -.@{fa-css-prefix}-pinterest-square:before { content: @fa-var-pinterest-square; } -.@{fa-css-prefix}-google-plus-square:before { content: @fa-var-google-plus-square; } -.@{fa-css-prefix}-google-plus:before { content: @fa-var-google-plus; } -.@{fa-css-prefix}-money:before { content: @fa-var-money; } -.@{fa-css-prefix}-caret-down:before { content: @fa-var-caret-down; } -.@{fa-css-prefix}-caret-up:before { content: @fa-var-caret-up; } -.@{fa-css-prefix}-caret-left:before { content: @fa-var-caret-left; } -.@{fa-css-prefix}-caret-right:before { content: @fa-var-caret-right; } -.@{fa-css-prefix}-columns:before { content: @fa-var-columns; } -.@{fa-css-prefix}-unsorted:before, -.@{fa-css-prefix}-sort:before { content: @fa-var-sort; } -.@{fa-css-prefix}-sort-down:before, -.@{fa-css-prefix}-sort-desc:before { content: @fa-var-sort-desc; } -.@{fa-css-prefix}-sort-up:before, -.@{fa-css-prefix}-sort-asc:before { content: @fa-var-sort-asc; } -.@{fa-css-prefix}-envelope:before { content: @fa-var-envelope; } -.@{fa-css-prefix}-linkedin:before { content: @fa-var-linkedin; } -.@{fa-css-prefix}-rotate-left:before, -.@{fa-css-prefix}-undo:before { content: @fa-var-undo; } -.@{fa-css-prefix}-legal:before, -.@{fa-css-prefix}-gavel:before { content: @fa-var-gavel; } -.@{fa-css-prefix}-dashboard:before, -.@{fa-css-prefix}-tachometer:before { content: @fa-var-tachometer; } -.@{fa-css-prefix}-comment-o:before { content: @fa-var-comment-o; } -.@{fa-css-prefix}-comments-o:before { content: @fa-var-comments-o; } -.@{fa-css-prefix}-flash:before, -.@{fa-css-prefix}-bolt:before { content: @fa-var-bolt; } -.@{fa-css-prefix}-sitemap:before { content: @fa-var-sitemap; } -.@{fa-css-prefix}-umbrella:before { content: @fa-var-umbrella; } -.@{fa-css-prefix}-paste:before, -.@{fa-css-prefix}-clipboard:before { content: @fa-var-clipboard; } -.@{fa-css-prefix}-lightbulb-o:before { content: @fa-var-lightbulb-o; } -.@{fa-css-prefix}-exchange:before { content: @fa-var-exchange; } -.@{fa-css-prefix}-cloud-download:before { content: @fa-var-cloud-download; } -.@{fa-css-prefix}-cloud-upload:before { content: @fa-var-cloud-upload; } -.@{fa-css-prefix}-user-md:before { content: @fa-var-user-md; } -.@{fa-css-prefix}-stethoscope:before { content: @fa-var-stethoscope; } -.@{fa-css-prefix}-suitcase:before { content: @fa-var-suitcase; } -.@{fa-css-prefix}-bell-o:before { content: @fa-var-bell-o; } -.@{fa-css-prefix}-coffee:before { content: @fa-var-coffee; } -.@{fa-css-prefix}-cutlery:before { content: @fa-var-cutlery; } -.@{fa-css-prefix}-file-text-o:before { content: @fa-var-file-text-o; } -.@{fa-css-prefix}-building-o:before { content: @fa-var-building-o; } -.@{fa-css-prefix}-hospital-o:before { content: @fa-var-hospital-o; } -.@{fa-css-prefix}-ambulance:before { content: @fa-var-ambulance; } -.@{fa-css-prefix}-medkit:before { content: @fa-var-medkit; } -.@{fa-css-prefix}-fighter-jet:before { content: @fa-var-fighter-jet; } -.@{fa-css-prefix}-beer:before { content: @fa-var-beer; } -.@{fa-css-prefix}-h-square:before { content: @fa-var-h-square; } -.@{fa-css-prefix}-plus-square:before { content: @fa-var-plus-square; } -.@{fa-css-prefix}-angle-double-left:before { content: @fa-var-angle-double-left; } -.@{fa-css-prefix}-angle-double-right:before { content: @fa-var-angle-double-right; } -.@{fa-css-prefix}-angle-double-up:before { content: @fa-var-angle-double-up; } -.@{fa-css-prefix}-angle-double-down:before { content: @fa-var-angle-double-down; } -.@{fa-css-prefix}-angle-left:before { content: @fa-var-angle-left; } -.@{fa-css-prefix}-angle-right:before { content: @fa-var-angle-right; } -.@{fa-css-prefix}-angle-up:before { content: @fa-var-angle-up; } -.@{fa-css-prefix}-angle-down:before { content: @fa-var-angle-down; } -.@{fa-css-prefix}-desktop:before { content: @fa-var-desktop; } -.@{fa-css-prefix}-laptop:before { content: @fa-var-laptop; } -.@{fa-css-prefix}-tablet:before { content: @fa-var-tablet; } -.@{fa-css-prefix}-mobile-phone:before, -.@{fa-css-prefix}-mobile:before { content: @fa-var-mobile; } -.@{fa-css-prefix}-circle-o:before { content: @fa-var-circle-o; } -.@{fa-css-prefix}-quote-left:before { content: @fa-var-quote-left; } -.@{fa-css-prefix}-quote-right:before { content: @fa-var-quote-right; } -.@{fa-css-prefix}-spinner:before { content: @fa-var-spinner; } -.@{fa-css-prefix}-circle:before { content: @fa-var-circle; } -.@{fa-css-prefix}-mail-reply:before, -.@{fa-css-prefix}-reply:before { content: @fa-var-reply; } -.@{fa-css-prefix}-github-alt:before { content: @fa-var-github-alt; } -.@{fa-css-prefix}-folder-o:before { content: @fa-var-folder-o; } -.@{fa-css-prefix}-folder-open-o:before { content: @fa-var-folder-open-o; } -.@{fa-css-prefix}-smile-o:before { content: @fa-var-smile-o; } -.@{fa-css-prefix}-frown-o:before { content: @fa-var-frown-o; } -.@{fa-css-prefix}-meh-o:before { content: @fa-var-meh-o; } -.@{fa-css-prefix}-gamepad:before { content: @fa-var-gamepad; } -.@{fa-css-prefix}-keyboard-o:before { content: @fa-var-keyboard-o; } -.@{fa-css-prefix}-flag-o:before { content: @fa-var-flag-o; } -.@{fa-css-prefix}-flag-checkered:before { content: @fa-var-flag-checkered; } -.@{fa-css-prefix}-terminal:before { content: @fa-var-terminal; } -.@{fa-css-prefix}-code:before { content: @fa-var-code; } -.@{fa-css-prefix}-mail-reply-all:before, -.@{fa-css-prefix}-reply-all:before { content: @fa-var-reply-all; } -.@{fa-css-prefix}-star-half-empty:before, -.@{fa-css-prefix}-star-half-full:before, -.@{fa-css-prefix}-star-half-o:before { content: @fa-var-star-half-o; } -.@{fa-css-prefix}-location-arrow:before { content: @fa-var-location-arrow; } -.@{fa-css-prefix}-crop:before { content: @fa-var-crop; } -.@{fa-css-prefix}-code-fork:before { content: @fa-var-code-fork; } -.@{fa-css-prefix}-unlink:before, -.@{fa-css-prefix}-chain-broken:before { content: @fa-var-chain-broken; } -.@{fa-css-prefix}-question:before { content: @fa-var-question; } -.@{fa-css-prefix}-info:before { content: @fa-var-info; } -.@{fa-css-prefix}-exclamation:before { content: @fa-var-exclamation; } -.@{fa-css-prefix}-superscript:before { content: @fa-var-superscript; } -.@{fa-css-prefix}-subscript:before { content: @fa-var-subscript; } -.@{fa-css-prefix}-eraser:before { content: @fa-var-eraser; } -.@{fa-css-prefix}-puzzle-piece:before { content: @fa-var-puzzle-piece; } -.@{fa-css-prefix}-microphone:before { content: @fa-var-microphone; } -.@{fa-css-prefix}-microphone-slash:before { content: @fa-var-microphone-slash; } -.@{fa-css-prefix}-shield:before { content: @fa-var-shield; } -.@{fa-css-prefix}-calendar-o:before { content: @fa-var-calendar-o; } -.@{fa-css-prefix}-fire-extinguisher:before { content: @fa-var-fire-extinguisher; } -.@{fa-css-prefix}-rocket:before { content: @fa-var-rocket; } -.@{fa-css-prefix}-maxcdn:before { content: @fa-var-maxcdn; } -.@{fa-css-prefix}-chevron-circle-left:before { content: @fa-var-chevron-circle-left; } -.@{fa-css-prefix}-chevron-circle-right:before { content: @fa-var-chevron-circle-right; } -.@{fa-css-prefix}-chevron-circle-up:before { content: @fa-var-chevron-circle-up; } -.@{fa-css-prefix}-chevron-circle-down:before { content: @fa-var-chevron-circle-down; } -.@{fa-css-prefix}-html5:before { content: @fa-var-html5; } -.@{fa-css-prefix}-css3:before { content: @fa-var-css3; } -.@{fa-css-prefix}-anchor:before { content: @fa-var-anchor; } -.@{fa-css-prefix}-unlock-alt:before { content: @fa-var-unlock-alt; } -.@{fa-css-prefix}-bullseye:before { content: @fa-var-bullseye; } -.@{fa-css-prefix}-ellipsis-h:before { content: @fa-var-ellipsis-h; } -.@{fa-css-prefix}-ellipsis-v:before { content: @fa-var-ellipsis-v; } -.@{fa-css-prefix}-rss-square:before { content: @fa-var-rss-square; } -.@{fa-css-prefix}-play-circle:before { content: @fa-var-play-circle; } -.@{fa-css-prefix}-ticket:before { content: @fa-var-ticket; } -.@{fa-css-prefix}-minus-square:before { content: @fa-var-minus-square; } -.@{fa-css-prefix}-minus-square-o:before { content: @fa-var-minus-square-o; } -.@{fa-css-prefix}-level-up:before { content: @fa-var-level-up; } -.@{fa-css-prefix}-level-down:before { content: @fa-var-level-down; } -.@{fa-css-prefix}-check-square:before { content: @fa-var-check-square; } -.@{fa-css-prefix}-pencil-square:before { content: @fa-var-pencil-square; } -.@{fa-css-prefix}-external-link-square:before { content: @fa-var-external-link-square; } -.@{fa-css-prefix}-share-square:before { content: @fa-var-share-square; } -.@{fa-css-prefix}-compass:before { content: @fa-var-compass; } -.@{fa-css-prefix}-toggle-down:before, -.@{fa-css-prefix}-caret-square-o-down:before { content: @fa-var-caret-square-o-down; } -.@{fa-css-prefix}-toggle-up:before, -.@{fa-css-prefix}-caret-square-o-up:before { content: @fa-var-caret-square-o-up; } -.@{fa-css-prefix}-toggle-right:before, -.@{fa-css-prefix}-caret-square-o-right:before { content: @fa-var-caret-square-o-right; } -.@{fa-css-prefix}-euro:before, -.@{fa-css-prefix}-eur:before { content: @fa-var-eur; } -.@{fa-css-prefix}-gbp:before { content: @fa-var-gbp; } -.@{fa-css-prefix}-dollar:before, -.@{fa-css-prefix}-usd:before { content: @fa-var-usd; } -.@{fa-css-prefix}-rupee:before, -.@{fa-css-prefix}-inr:before { content: @fa-var-inr; } -.@{fa-css-prefix}-cny:before, -.@{fa-css-prefix}-rmb:before, -.@{fa-css-prefix}-yen:before, -.@{fa-css-prefix}-jpy:before { content: @fa-var-jpy; } -.@{fa-css-prefix}-ruble:before, -.@{fa-css-prefix}-rouble:before, -.@{fa-css-prefix}-rub:before { content: @fa-var-rub; } -.@{fa-css-prefix}-won:before, -.@{fa-css-prefix}-krw:before { content: @fa-var-krw; } -.@{fa-css-prefix}-bitcoin:before, -.@{fa-css-prefix}-btc:before { content: @fa-var-btc; } -.@{fa-css-prefix}-file:before { content: @fa-var-file; } -.@{fa-css-prefix}-file-text:before { content: @fa-var-file-text; } -.@{fa-css-prefix}-sort-alpha-asc:before { content: @fa-var-sort-alpha-asc; } -.@{fa-css-prefix}-sort-alpha-desc:before { content: @fa-var-sort-alpha-desc; } -.@{fa-css-prefix}-sort-amount-asc:before { content: @fa-var-sort-amount-asc; } -.@{fa-css-prefix}-sort-amount-desc:before { content: @fa-var-sort-amount-desc; } -.@{fa-css-prefix}-sort-numeric-asc:before { content: @fa-var-sort-numeric-asc; } -.@{fa-css-prefix}-sort-numeric-desc:before { content: @fa-var-sort-numeric-desc; } -.@{fa-css-prefix}-thumbs-up:before { content: @fa-var-thumbs-up; } -.@{fa-css-prefix}-thumbs-down:before { content: @fa-var-thumbs-down; } -.@{fa-css-prefix}-youtube-square:before { content: @fa-var-youtube-square; } -.@{fa-css-prefix}-youtube:before { content: @fa-var-youtube; } -.@{fa-css-prefix}-xing:before { content: @fa-var-xing; } -.@{fa-css-prefix}-xing-square:before { content: @fa-var-xing-square; } -.@{fa-css-prefix}-youtube-play:before { content: @fa-var-youtube-play; } -.@{fa-css-prefix}-dropbox:before { content: @fa-var-dropbox; } -.@{fa-css-prefix}-stack-overflow:before { content: @fa-var-stack-overflow; } -.@{fa-css-prefix}-instagram:before { content: @fa-var-instagram; } -.@{fa-css-prefix}-flickr:before { content: @fa-var-flickr; } -.@{fa-css-prefix}-adn:before { content: @fa-var-adn; } -.@{fa-css-prefix}-bitbucket:before { content: @fa-var-bitbucket; } -.@{fa-css-prefix}-bitbucket-square:before { content: @fa-var-bitbucket-square; } -.@{fa-css-prefix}-tumblr:before { content: @fa-var-tumblr; } -.@{fa-css-prefix}-tumblr-square:before { content: @fa-var-tumblr-square; } -.@{fa-css-prefix}-long-arrow-down:before { content: @fa-var-long-arrow-down; } -.@{fa-css-prefix}-long-arrow-up:before { content: @fa-var-long-arrow-up; } -.@{fa-css-prefix}-long-arrow-left:before { content: @fa-var-long-arrow-left; } -.@{fa-css-prefix}-long-arrow-right:before { content: @fa-var-long-arrow-right; } -.@{fa-css-prefix}-apple:before { content: @fa-var-apple; } -.@{fa-css-prefix}-windows:before { content: @fa-var-windows; } -.@{fa-css-prefix}-android:before { content: @fa-var-android; } -.@{fa-css-prefix}-linux:before { content: @fa-var-linux; } -.@{fa-css-prefix}-dribbble:before { content: @fa-var-dribbble; } -.@{fa-css-prefix}-skype:before { content: @fa-var-skype; } -.@{fa-css-prefix}-foursquare:before { content: @fa-var-foursquare; } -.@{fa-css-prefix}-trello:before { content: @fa-var-trello; } -.@{fa-css-prefix}-female:before { content: @fa-var-female; } -.@{fa-css-prefix}-male:before { content: @fa-var-male; } -.@{fa-css-prefix}-gittip:before, -.@{fa-css-prefix}-gratipay:before { content: @fa-var-gratipay; } -.@{fa-css-prefix}-sun-o:before { content: @fa-var-sun-o; } -.@{fa-css-prefix}-moon-o:before { content: @fa-var-moon-o; } -.@{fa-css-prefix}-archive:before { content: @fa-var-archive; } -.@{fa-css-prefix}-bug:before { content: @fa-var-bug; } -.@{fa-css-prefix}-vk:before { content: @fa-var-vk; } -.@{fa-css-prefix}-weibo:before { content: @fa-var-weibo; } -.@{fa-css-prefix}-renren:before { content: @fa-var-renren; } -.@{fa-css-prefix}-pagelines:before { content: @fa-var-pagelines; } -.@{fa-css-prefix}-stack-exchange:before { content: @fa-var-stack-exchange; } -.@{fa-css-prefix}-arrow-circle-o-right:before { content: @fa-var-arrow-circle-o-right; } -.@{fa-css-prefix}-arrow-circle-o-left:before { content: @fa-var-arrow-circle-o-left; } -.@{fa-css-prefix}-toggle-left:before, -.@{fa-css-prefix}-caret-square-o-left:before { content: @fa-var-caret-square-o-left; } -.@{fa-css-prefix}-dot-circle-o:before { content: @fa-var-dot-circle-o; } -.@{fa-css-prefix}-wheelchair:before { content: @fa-var-wheelchair; } -.@{fa-css-prefix}-vimeo-square:before { content: @fa-var-vimeo-square; } -.@{fa-css-prefix}-turkish-lira:before, -.@{fa-css-prefix}-try:before { content: @fa-var-try; } -.@{fa-css-prefix}-plus-square-o:before { content: @fa-var-plus-square-o; } -.@{fa-css-prefix}-space-shuttle:before { content: @fa-var-space-shuttle; } -.@{fa-css-prefix}-slack:before { content: @fa-var-slack; } -.@{fa-css-prefix}-envelope-square:before { content: @fa-var-envelope-square; } -.@{fa-css-prefix}-wordpress:before { content: @fa-var-wordpress; } -.@{fa-css-prefix}-openid:before { content: @fa-var-openid; } -.@{fa-css-prefix}-institution:before, -.@{fa-css-prefix}-bank:before, -.@{fa-css-prefix}-university:before { content: @fa-var-university; } -.@{fa-css-prefix}-mortar-board:before, -.@{fa-css-prefix}-graduation-cap:before { content: @fa-var-graduation-cap; } -.@{fa-css-prefix}-yahoo:before { content: @fa-var-yahoo; } -.@{fa-css-prefix}-google:before { content: @fa-var-google; } -.@{fa-css-prefix}-reddit:before { content: @fa-var-reddit; } -.@{fa-css-prefix}-reddit-square:before { content: @fa-var-reddit-square; } -.@{fa-css-prefix}-stumbleupon-circle:before { content: @fa-var-stumbleupon-circle; } -.@{fa-css-prefix}-stumbleupon:before { content: @fa-var-stumbleupon; } -.@{fa-css-prefix}-delicious:before { content: @fa-var-delicious; } -.@{fa-css-prefix}-digg:before { content: @fa-var-digg; } -.@{fa-css-prefix}-pied-piper-pp:before { content: @fa-var-pied-piper-pp; } -.@{fa-css-prefix}-pied-piper-alt:before { content: @fa-var-pied-piper-alt; } -.@{fa-css-prefix}-drupal:before { content: @fa-var-drupal; } -.@{fa-css-prefix}-joomla:before { content: @fa-var-joomla; } -.@{fa-css-prefix}-language:before { content: @fa-var-language; } -.@{fa-css-prefix}-fax:before { content: @fa-var-fax; } -.@{fa-css-prefix}-building:before { content: @fa-var-building; } -.@{fa-css-prefix}-child:before { content: @fa-var-child; } -.@{fa-css-prefix}-paw:before { content: @fa-var-paw; } -.@{fa-css-prefix}-spoon:before { content: @fa-var-spoon; } -.@{fa-css-prefix}-cube:before { content: @fa-var-cube; } -.@{fa-css-prefix}-cubes:before { content: @fa-var-cubes; } -.@{fa-css-prefix}-behance:before { content: @fa-var-behance; } -.@{fa-css-prefix}-behance-square:before { content: @fa-var-behance-square; } -.@{fa-css-prefix}-steam:before { content: @fa-var-steam; } -.@{fa-css-prefix}-steam-square:before { content: @fa-var-steam-square; } -.@{fa-css-prefix}-recycle:before { content: @fa-var-recycle; } -.@{fa-css-prefix}-automobile:before, -.@{fa-css-prefix}-car:before { content: @fa-var-car; } -.@{fa-css-prefix}-cab:before, -.@{fa-css-prefix}-taxi:before { content: @fa-var-taxi; } -.@{fa-css-prefix}-tree:before { content: @fa-var-tree; } -.@{fa-css-prefix}-spotify:before { content: @fa-var-spotify; } -.@{fa-css-prefix}-deviantart:before { content: @fa-var-deviantart; } -.@{fa-css-prefix}-soundcloud:before { content: @fa-var-soundcloud; } -.@{fa-css-prefix}-database:before { content: @fa-var-database; } -.@{fa-css-prefix}-file-pdf-o:before { content: @fa-var-file-pdf-o; } -.@{fa-css-prefix}-file-word-o:before { content: @fa-var-file-word-o; } -.@{fa-css-prefix}-file-excel-o:before { content: @fa-var-file-excel-o; } -.@{fa-css-prefix}-file-powerpoint-o:before { content: @fa-var-file-powerpoint-o; } -.@{fa-css-prefix}-file-photo-o:before, -.@{fa-css-prefix}-file-picture-o:before, -.@{fa-css-prefix}-file-image-o:before { content: @fa-var-file-image-o; } -.@{fa-css-prefix}-file-zip-o:before, -.@{fa-css-prefix}-file-archive-o:before { content: @fa-var-file-archive-o; } -.@{fa-css-prefix}-file-sound-o:before, -.@{fa-css-prefix}-file-audio-o:before { content: @fa-var-file-audio-o; } -.@{fa-css-prefix}-file-movie-o:before, -.@{fa-css-prefix}-file-video-o:before { content: @fa-var-file-video-o; } -.@{fa-css-prefix}-file-code-o:before { content: @fa-var-file-code-o; } -.@{fa-css-prefix}-vine:before { content: @fa-var-vine; } -.@{fa-css-prefix}-codepen:before { content: @fa-var-codepen; } -.@{fa-css-prefix}-jsfiddle:before { content: @fa-var-jsfiddle; } -.@{fa-css-prefix}-life-bouy:before, -.@{fa-css-prefix}-life-buoy:before, -.@{fa-css-prefix}-life-saver:before, -.@{fa-css-prefix}-support:before, -.@{fa-css-prefix}-life-ring:before { content: @fa-var-life-ring; } -.@{fa-css-prefix}-circle-o-notch:before { content: @fa-var-circle-o-notch; } -.@{fa-css-prefix}-ra:before, -.@{fa-css-prefix}-resistance:before, -.@{fa-css-prefix}-rebel:before { content: @fa-var-rebel; } -.@{fa-css-prefix}-ge:before, -.@{fa-css-prefix}-empire:before { content: @fa-var-empire; } -.@{fa-css-prefix}-git-square:before { content: @fa-var-git-square; } -.@{fa-css-prefix}-git:before { content: @fa-var-git; } -.@{fa-css-prefix}-y-combinator-square:before, -.@{fa-css-prefix}-yc-square:before, -.@{fa-css-prefix}-hacker-news:before { content: @fa-var-hacker-news; } -.@{fa-css-prefix}-tencent-weibo:before { content: @fa-var-tencent-weibo; } -.@{fa-css-prefix}-qq:before { content: @fa-var-qq; } -.@{fa-css-prefix}-wechat:before, -.@{fa-css-prefix}-weixin:before { content: @fa-var-weixin; } -.@{fa-css-prefix}-send:before, -.@{fa-css-prefix}-paper-plane:before { content: @fa-var-paper-plane; } -.@{fa-css-prefix}-send-o:before, -.@{fa-css-prefix}-paper-plane-o:before { content: @fa-var-paper-plane-o; } -.@{fa-css-prefix}-history:before { content: @fa-var-history; } -.@{fa-css-prefix}-circle-thin:before { content: @fa-var-circle-thin; } -.@{fa-css-prefix}-header:before { content: @fa-var-header; } -.@{fa-css-prefix}-paragraph:before { content: @fa-var-paragraph; } -.@{fa-css-prefix}-sliders:before { content: @fa-var-sliders; } -.@{fa-css-prefix}-share-alt:before { content: @fa-var-share-alt; } -.@{fa-css-prefix}-share-alt-square:before { content: @fa-var-share-alt-square; } -.@{fa-css-prefix}-bomb:before { content: @fa-var-bomb; } -.@{fa-css-prefix}-soccer-ball-o:before, -.@{fa-css-prefix}-futbol-o:before { content: @fa-var-futbol-o; } -.@{fa-css-prefix}-tty:before { content: @fa-var-tty; } -.@{fa-css-prefix}-binoculars:before { content: @fa-var-binoculars; } -.@{fa-css-prefix}-plug:before { content: @fa-var-plug; } -.@{fa-css-prefix}-slideshare:before { content: @fa-var-slideshare; } -.@{fa-css-prefix}-twitch:before { content: @fa-var-twitch; } -.@{fa-css-prefix}-yelp:before { content: @fa-var-yelp; } -.@{fa-css-prefix}-newspaper-o:before { content: @fa-var-newspaper-o; } -.@{fa-css-prefix}-wifi:before { content: @fa-var-wifi; } -.@{fa-css-prefix}-calculator:before { content: @fa-var-calculator; } -.@{fa-css-prefix}-paypal:before { content: @fa-var-paypal; } -.@{fa-css-prefix}-google-wallet:before { content: @fa-var-google-wallet; } -.@{fa-css-prefix}-cc-visa:before { content: @fa-var-cc-visa; } -.@{fa-css-prefix}-cc-mastercard:before { content: @fa-var-cc-mastercard; } -.@{fa-css-prefix}-cc-discover:before { content: @fa-var-cc-discover; } -.@{fa-css-prefix}-cc-amex:before { content: @fa-var-cc-amex; } -.@{fa-css-prefix}-cc-paypal:before { content: @fa-var-cc-paypal; } -.@{fa-css-prefix}-cc-stripe:before { content: @fa-var-cc-stripe; } -.@{fa-css-prefix}-bell-slash:before { content: @fa-var-bell-slash; } -.@{fa-css-prefix}-bell-slash-o:before { content: @fa-var-bell-slash-o; } -.@{fa-css-prefix}-trash:before { content: @fa-var-trash; } -.@{fa-css-prefix}-copyright:before { content: @fa-var-copyright; } -.@{fa-css-prefix}-at:before { content: @fa-var-at; } -.@{fa-css-prefix}-eyedropper:before { content: @fa-var-eyedropper; } -.@{fa-css-prefix}-paint-brush:before { content: @fa-var-paint-brush; } -.@{fa-css-prefix}-birthday-cake:before { content: @fa-var-birthday-cake; } -.@{fa-css-prefix}-area-chart:before { content: @fa-var-area-chart; } -.@{fa-css-prefix}-pie-chart:before { content: @fa-var-pie-chart; } -.@{fa-css-prefix}-line-chart:before { content: @fa-var-line-chart; } -.@{fa-css-prefix}-lastfm:before { content: @fa-var-lastfm; } -.@{fa-css-prefix}-lastfm-square:before { content: @fa-var-lastfm-square; } -.@{fa-css-prefix}-toggle-off:before { content: @fa-var-toggle-off; } -.@{fa-css-prefix}-toggle-on:before { content: @fa-var-toggle-on; } -.@{fa-css-prefix}-bicycle:before { content: @fa-var-bicycle; } -.@{fa-css-prefix}-bus:before { content: @fa-var-bus; } -.@{fa-css-prefix}-ioxhost:before { content: @fa-var-ioxhost; } -.@{fa-css-prefix}-angellist:before { content: @fa-var-angellist; } -.@{fa-css-prefix}-cc:before { content: @fa-var-cc; } -.@{fa-css-prefix}-shekel:before, -.@{fa-css-prefix}-sheqel:before, -.@{fa-css-prefix}-ils:before { content: @fa-var-ils; } -.@{fa-css-prefix}-meanpath:before { content: @fa-var-meanpath; } -.@{fa-css-prefix}-buysellads:before { content: @fa-var-buysellads; } -.@{fa-css-prefix}-connectdevelop:before { content: @fa-var-connectdevelop; } -.@{fa-css-prefix}-dashcube:before { content: @fa-var-dashcube; } -.@{fa-css-prefix}-forumbee:before { content: @fa-var-forumbee; } -.@{fa-css-prefix}-leanpub:before { content: @fa-var-leanpub; } -.@{fa-css-prefix}-sellsy:before { content: @fa-var-sellsy; } -.@{fa-css-prefix}-shirtsinbulk:before { content: @fa-var-shirtsinbulk; } -.@{fa-css-prefix}-simplybuilt:before { content: @fa-var-simplybuilt; } -.@{fa-css-prefix}-skyatlas:before { content: @fa-var-skyatlas; } -.@{fa-css-prefix}-cart-plus:before { content: @fa-var-cart-plus; } -.@{fa-css-prefix}-cart-arrow-down:before { content: @fa-var-cart-arrow-down; } -.@{fa-css-prefix}-diamond:before { content: @fa-var-diamond; } -.@{fa-css-prefix}-ship:before { content: @fa-var-ship; } -.@{fa-css-prefix}-user-secret:before { content: @fa-var-user-secret; } -.@{fa-css-prefix}-motorcycle:before { content: @fa-var-motorcycle; } -.@{fa-css-prefix}-street-view:before { content: @fa-var-street-view; } -.@{fa-css-prefix}-heartbeat:before { content: @fa-var-heartbeat; } -.@{fa-css-prefix}-venus:before { content: @fa-var-venus; } -.@{fa-css-prefix}-mars:before { content: @fa-var-mars; } -.@{fa-css-prefix}-mercury:before { content: @fa-var-mercury; } -.@{fa-css-prefix}-intersex:before, -.@{fa-css-prefix}-transgender:before { content: @fa-var-transgender; } -.@{fa-css-prefix}-transgender-alt:before { content: @fa-var-transgender-alt; } -.@{fa-css-prefix}-venus-double:before { content: @fa-var-venus-double; } -.@{fa-css-prefix}-mars-double:before { content: @fa-var-mars-double; } -.@{fa-css-prefix}-venus-mars:before { content: @fa-var-venus-mars; } -.@{fa-css-prefix}-mars-stroke:before { content: @fa-var-mars-stroke; } -.@{fa-css-prefix}-mars-stroke-v:before { content: @fa-var-mars-stroke-v; } -.@{fa-css-prefix}-mars-stroke-h:before { content: @fa-var-mars-stroke-h; } -.@{fa-css-prefix}-neuter:before { content: @fa-var-neuter; } -.@{fa-css-prefix}-genderless:before { content: @fa-var-genderless; } -.@{fa-css-prefix}-facebook-official:before { content: @fa-var-facebook-official; } -.@{fa-css-prefix}-pinterest-p:before { content: @fa-var-pinterest-p; } -.@{fa-css-prefix}-whatsapp:before { content: @fa-var-whatsapp; } -.@{fa-css-prefix}-server:before { content: @fa-var-server; } -.@{fa-css-prefix}-user-plus:before { content: @fa-var-user-plus; } -.@{fa-css-prefix}-user-times:before { content: @fa-var-user-times; } -.@{fa-css-prefix}-hotel:before, -.@{fa-css-prefix}-bed:before { content: @fa-var-bed; } -.@{fa-css-prefix}-viacoin:before { content: @fa-var-viacoin; } -.@{fa-css-prefix}-train:before { content: @fa-var-train; } -.@{fa-css-prefix}-subway:before { content: @fa-var-subway; } -.@{fa-css-prefix}-medium:before { content: @fa-var-medium; } -.@{fa-css-prefix}-yc:before, -.@{fa-css-prefix}-y-combinator:before { content: @fa-var-y-combinator; } -.@{fa-css-prefix}-optin-monster:before { content: @fa-var-optin-monster; } -.@{fa-css-prefix}-opencart:before { content: @fa-var-opencart; } -.@{fa-css-prefix}-expeditedssl:before { content: @fa-var-expeditedssl; } -.@{fa-css-prefix}-battery-4:before, -.@{fa-css-prefix}-battery:before, -.@{fa-css-prefix}-battery-full:before { content: @fa-var-battery-full; } -.@{fa-css-prefix}-battery-3:before, -.@{fa-css-prefix}-battery-three-quarters:before { content: @fa-var-battery-three-quarters; } -.@{fa-css-prefix}-battery-2:before, -.@{fa-css-prefix}-battery-half:before { content: @fa-var-battery-half; } -.@{fa-css-prefix}-battery-1:before, -.@{fa-css-prefix}-battery-quarter:before { content: @fa-var-battery-quarter; } -.@{fa-css-prefix}-battery-0:before, -.@{fa-css-prefix}-battery-empty:before { content: @fa-var-battery-empty; } -.@{fa-css-prefix}-mouse-pointer:before { content: @fa-var-mouse-pointer; } -.@{fa-css-prefix}-i-cursor:before { content: @fa-var-i-cursor; } -.@{fa-css-prefix}-object-group:before { content: @fa-var-object-group; } -.@{fa-css-prefix}-object-ungroup:before { content: @fa-var-object-ungroup; } -.@{fa-css-prefix}-sticky-note:before { content: @fa-var-sticky-note; } -.@{fa-css-prefix}-sticky-note-o:before { content: @fa-var-sticky-note-o; } -.@{fa-css-prefix}-cc-jcb:before { content: @fa-var-cc-jcb; } -.@{fa-css-prefix}-cc-diners-club:before { content: @fa-var-cc-diners-club; } -.@{fa-css-prefix}-clone:before { content: @fa-var-clone; } -.@{fa-css-prefix}-balance-scale:before { content: @fa-var-balance-scale; } -.@{fa-css-prefix}-hourglass-o:before { content: @fa-var-hourglass-o; } -.@{fa-css-prefix}-hourglass-1:before, -.@{fa-css-prefix}-hourglass-start:before { content: @fa-var-hourglass-start; } -.@{fa-css-prefix}-hourglass-2:before, -.@{fa-css-prefix}-hourglass-half:before { content: @fa-var-hourglass-half; } -.@{fa-css-prefix}-hourglass-3:before, -.@{fa-css-prefix}-hourglass-end:before { content: @fa-var-hourglass-end; } -.@{fa-css-prefix}-hourglass:before { content: @fa-var-hourglass; } -.@{fa-css-prefix}-hand-grab-o:before, -.@{fa-css-prefix}-hand-rock-o:before { content: @fa-var-hand-rock-o; } -.@{fa-css-prefix}-hand-stop-o:before, -.@{fa-css-prefix}-hand-paper-o:before { content: @fa-var-hand-paper-o; } -.@{fa-css-prefix}-hand-scissors-o:before { content: @fa-var-hand-scissors-o; } -.@{fa-css-prefix}-hand-lizard-o:before { content: @fa-var-hand-lizard-o; } -.@{fa-css-prefix}-hand-spock-o:before { content: @fa-var-hand-spock-o; } -.@{fa-css-prefix}-hand-pointer-o:before { content: @fa-var-hand-pointer-o; } -.@{fa-css-prefix}-hand-peace-o:before { content: @fa-var-hand-peace-o; } -.@{fa-css-prefix}-trademark:before { content: @fa-var-trademark; } -.@{fa-css-prefix}-registered:before { content: @fa-var-registered; } -.@{fa-css-prefix}-creative-commons:before { content: @fa-var-creative-commons; } -.@{fa-css-prefix}-gg:before { content: @fa-var-gg; } -.@{fa-css-prefix}-gg-circle:before { content: @fa-var-gg-circle; } -.@{fa-css-prefix}-tripadvisor:before { content: @fa-var-tripadvisor; } -.@{fa-css-prefix}-odnoklassniki:before { content: @fa-var-odnoklassniki; } -.@{fa-css-prefix}-odnoklassniki-square:before { content: @fa-var-odnoklassniki-square; } -.@{fa-css-prefix}-get-pocket:before { content: @fa-var-get-pocket; } -.@{fa-css-prefix}-wikipedia-w:before { content: @fa-var-wikipedia-w; } -.@{fa-css-prefix}-safari:before { content: @fa-var-safari; } -.@{fa-css-prefix}-chrome:before { content: @fa-var-chrome; } -.@{fa-css-prefix}-firefox:before { content: @fa-var-firefox; } -.@{fa-css-prefix}-opera:before { content: @fa-var-opera; } -.@{fa-css-prefix}-internet-explorer:before { content: @fa-var-internet-explorer; } -.@{fa-css-prefix}-tv:before, -.@{fa-css-prefix}-television:before { content: @fa-var-television; } -.@{fa-css-prefix}-contao:before { content: @fa-var-contao; } -.@{fa-css-prefix}-500px:before { content: @fa-var-500px; } -.@{fa-css-prefix}-amazon:before { content: @fa-var-amazon; } -.@{fa-css-prefix}-calendar-plus-o:before { content: @fa-var-calendar-plus-o; } -.@{fa-css-prefix}-calendar-minus-o:before { content: @fa-var-calendar-minus-o; } -.@{fa-css-prefix}-calendar-times-o:before { content: @fa-var-calendar-times-o; } -.@{fa-css-prefix}-calendar-check-o:before { content: @fa-var-calendar-check-o; } -.@{fa-css-prefix}-industry:before { content: @fa-var-industry; } -.@{fa-css-prefix}-map-pin:before { content: @fa-var-map-pin; } -.@{fa-css-prefix}-map-signs:before { content: @fa-var-map-signs; } -.@{fa-css-prefix}-map-o:before { content: @fa-var-map-o; } -.@{fa-css-prefix}-map:before { content: @fa-var-map; } -.@{fa-css-prefix}-commenting:before { content: @fa-var-commenting; } -.@{fa-css-prefix}-commenting-o:before { content: @fa-var-commenting-o; } -.@{fa-css-prefix}-houzz:before { content: @fa-var-houzz; } -.@{fa-css-prefix}-vimeo:before { content: @fa-var-vimeo; } -.@{fa-css-prefix}-black-tie:before { content: @fa-var-black-tie; } -.@{fa-css-prefix}-fonticons:before { content: @fa-var-fonticons; } -.@{fa-css-prefix}-reddit-alien:before { content: @fa-var-reddit-alien; } -.@{fa-css-prefix}-edge:before { content: @fa-var-edge; } -.@{fa-css-prefix}-credit-card-alt:before { content: @fa-var-credit-card-alt; } -.@{fa-css-prefix}-codiepie:before { content: @fa-var-codiepie; } -.@{fa-css-prefix}-modx:before { content: @fa-var-modx; } -.@{fa-css-prefix}-fort-awesome:before { content: @fa-var-fort-awesome; } -.@{fa-css-prefix}-usb:before { content: @fa-var-usb; } -.@{fa-css-prefix}-product-hunt:before { content: @fa-var-product-hunt; } -.@{fa-css-prefix}-mixcloud:before { content: @fa-var-mixcloud; } -.@{fa-css-prefix}-scribd:before { content: @fa-var-scribd; } -.@{fa-css-prefix}-pause-circle:before { content: @fa-var-pause-circle; } -.@{fa-css-prefix}-pause-circle-o:before { content: @fa-var-pause-circle-o; } -.@{fa-css-prefix}-stop-circle:before { content: @fa-var-stop-circle; } -.@{fa-css-prefix}-stop-circle-o:before { content: @fa-var-stop-circle-o; } -.@{fa-css-prefix}-shopping-bag:before { content: @fa-var-shopping-bag; } -.@{fa-css-prefix}-shopping-basket:before { content: @fa-var-shopping-basket; } -.@{fa-css-prefix}-hashtag:before { content: @fa-var-hashtag; } -.@{fa-css-prefix}-bluetooth:before { content: @fa-var-bluetooth; } -.@{fa-css-prefix}-bluetooth-b:before { content: @fa-var-bluetooth-b; } -.@{fa-css-prefix}-percent:before { content: @fa-var-percent; } -.@{fa-css-prefix}-gitlab:before { content: @fa-var-gitlab; } -.@{fa-css-prefix}-wpbeginner:before { content: @fa-var-wpbeginner; } -.@{fa-css-prefix}-wpforms:before { content: @fa-var-wpforms; } -.@{fa-css-prefix}-envira:before { content: @fa-var-envira; } -.@{fa-css-prefix}-universal-access:before { content: @fa-var-universal-access; } -.@{fa-css-prefix}-wheelchair-alt:before { content: @fa-var-wheelchair-alt; } -.@{fa-css-prefix}-question-circle-o:before { content: @fa-var-question-circle-o; } -.@{fa-css-prefix}-blind:before { content: @fa-var-blind; } -.@{fa-css-prefix}-audio-description:before { content: @fa-var-audio-description; } -.@{fa-css-prefix}-volume-control-phone:before { content: @fa-var-volume-control-phone; } -.@{fa-css-prefix}-braille:before { content: @fa-var-braille; } -.@{fa-css-prefix}-assistive-listening-systems:before { content: @fa-var-assistive-listening-systems; } -.@{fa-css-prefix}-asl-interpreting:before, -.@{fa-css-prefix}-american-sign-language-interpreting:before { content: @fa-var-american-sign-language-interpreting; } -.@{fa-css-prefix}-deafness:before, -.@{fa-css-prefix}-hard-of-hearing:before, -.@{fa-css-prefix}-deaf:before { content: @fa-var-deaf; } -.@{fa-css-prefix}-glide:before { content: @fa-var-glide; } -.@{fa-css-prefix}-glide-g:before { content: @fa-var-glide-g; } -.@{fa-css-prefix}-signing:before, -.@{fa-css-prefix}-sign-language:before { content: @fa-var-sign-language; } -.@{fa-css-prefix}-low-vision:before { content: @fa-var-low-vision; } -.@{fa-css-prefix}-viadeo:before { content: @fa-var-viadeo; } -.@{fa-css-prefix}-viadeo-square:before { content: @fa-var-viadeo-square; } -.@{fa-css-prefix}-snapchat:before { content: @fa-var-snapchat; } -.@{fa-css-prefix}-snapchat-ghost:before { content: @fa-var-snapchat-ghost; } -.@{fa-css-prefix}-snapchat-square:before { content: @fa-var-snapchat-square; } -.@{fa-css-prefix}-pied-piper:before { content: @fa-var-pied-piper; } -.@{fa-css-prefix}-first-order:before { content: @fa-var-first-order; } -.@{fa-css-prefix}-yoast:before { content: @fa-var-yoast; } -.@{fa-css-prefix}-themeisle:before { content: @fa-var-themeisle; } -.@{fa-css-prefix}-google-plus-circle:before, -.@{fa-css-prefix}-google-plus-official:before { content: @fa-var-google-plus-official; } -.@{fa-css-prefix}-fa:before, -.@{fa-css-prefix}-font-awesome:before { content: @fa-var-font-awesome; } -.@{fa-css-prefix}-handshake-o:before { content: @fa-var-handshake-o; } -.@{fa-css-prefix}-envelope-open:before { content: @fa-var-envelope-open; } -.@{fa-css-prefix}-envelope-open-o:before { content: @fa-var-envelope-open-o; } -.@{fa-css-prefix}-linode:before { content: @fa-var-linode; } -.@{fa-css-prefix}-address-book:before { content: @fa-var-address-book; } -.@{fa-css-prefix}-address-book-o:before { content: @fa-var-address-book-o; } -.@{fa-css-prefix}-vcard:before, -.@{fa-css-prefix}-address-card:before { content: @fa-var-address-card; } -.@{fa-css-prefix}-vcard-o:before, -.@{fa-css-prefix}-address-card-o:before { content: @fa-var-address-card-o; } -.@{fa-css-prefix}-user-circle:before { content: @fa-var-user-circle; } -.@{fa-css-prefix}-user-circle-o:before { content: @fa-var-user-circle-o; } -.@{fa-css-prefix}-user-o:before { content: @fa-var-user-o; } -.@{fa-css-prefix}-id-badge:before { content: @fa-var-id-badge; } -.@{fa-css-prefix}-drivers-license:before, -.@{fa-css-prefix}-id-card:before { content: @fa-var-id-card; } -.@{fa-css-prefix}-drivers-license-o:before, -.@{fa-css-prefix}-id-card-o:before { content: @fa-var-id-card-o; } -.@{fa-css-prefix}-quora:before { content: @fa-var-quora; } -.@{fa-css-prefix}-free-code-camp:before { content: @fa-var-free-code-camp; } -.@{fa-css-prefix}-telegram:before { content: @fa-var-telegram; } -.@{fa-css-prefix}-thermometer-4:before, -.@{fa-css-prefix}-thermometer:before, -.@{fa-css-prefix}-thermometer-full:before { content: @fa-var-thermometer-full; } -.@{fa-css-prefix}-thermometer-3:before, -.@{fa-css-prefix}-thermometer-three-quarters:before { content: @fa-var-thermometer-three-quarters; } -.@{fa-css-prefix}-thermometer-2:before, -.@{fa-css-prefix}-thermometer-half:before { content: @fa-var-thermometer-half; } -.@{fa-css-prefix}-thermometer-1:before, -.@{fa-css-prefix}-thermometer-quarter:before { content: @fa-var-thermometer-quarter; } -.@{fa-css-prefix}-thermometer-0:before, -.@{fa-css-prefix}-thermometer-empty:before { content: @fa-var-thermometer-empty; } -.@{fa-css-prefix}-shower:before { content: @fa-var-shower; } -.@{fa-css-prefix}-bathtub:before, -.@{fa-css-prefix}-s15:before, -.@{fa-css-prefix}-bath:before { content: @fa-var-bath; } -.@{fa-css-prefix}-podcast:before { content: @fa-var-podcast; } -.@{fa-css-prefix}-window-maximize:before { content: @fa-var-window-maximize; } -.@{fa-css-prefix}-window-minimize:before { content: @fa-var-window-minimize; } -.@{fa-css-prefix}-window-restore:before { content: @fa-var-window-restore; } -.@{fa-css-prefix}-times-rectangle:before, -.@{fa-css-prefix}-window-close:before { content: @fa-var-window-close; } -.@{fa-css-prefix}-times-rectangle-o:before, -.@{fa-css-prefix}-window-close-o:before { content: @fa-var-window-close-o; } -.@{fa-css-prefix}-bandcamp:before { content: @fa-var-bandcamp; } -.@{fa-css-prefix}-grav:before { content: @fa-var-grav; } -.@{fa-css-prefix}-etsy:before { content: @fa-var-etsy; } -.@{fa-css-prefix}-imdb:before { content: @fa-var-imdb; } -.@{fa-css-prefix}-ravelry:before { content: @fa-var-ravelry; } -.@{fa-css-prefix}-eercast:before { content: @fa-var-eercast; } -.@{fa-css-prefix}-microchip:before { content: @fa-var-microchip; } -.@{fa-css-prefix}-snowflake-o:before { content: @fa-var-snowflake-o; } -.@{fa-css-prefix}-superpowers:before { content: @fa-var-superpowers; } -.@{fa-css-prefix}-wpexplorer:before { content: @fa-var-wpexplorer; } -.@{fa-css-prefix}-meetup:before { content: @fa-var-meetup; } diff --git a/netbox/project-static/font-awesome-4.7.0/less/larger.less b/netbox/project-static/font-awesome-4.7.0/less/larger.less deleted file mode 100644 index c9d646770e..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/less/larger.less +++ /dev/null @@ -1,13 +0,0 @@ -// Icon Sizes -// ------------------------- - -/* makes the font 33% larger relative to the icon container */ -.@{fa-css-prefix}-lg { - font-size: (4em / 3); - line-height: (3em / 4); - vertical-align: -15%; -} -.@{fa-css-prefix}-2x { font-size: 2em; } -.@{fa-css-prefix}-3x { font-size: 3em; } -.@{fa-css-prefix}-4x { font-size: 4em; } -.@{fa-css-prefix}-5x { font-size: 5em; } diff --git a/netbox/project-static/font-awesome-4.7.0/less/list.less b/netbox/project-static/font-awesome-4.7.0/less/list.less deleted file mode 100644 index 0b440382f6..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/less/list.less +++ /dev/null @@ -1,19 +0,0 @@ -// List Icons -// ------------------------- - -.@{fa-css-prefix}-ul { - padding-left: 0; - margin-left: @fa-li-width; - list-style-type: none; - > li { position: relative; } -} -.@{fa-css-prefix}-li { - position: absolute; - left: -@fa-li-width; - width: @fa-li-width; - top: (2em / 14); - text-align: center; - &.@{fa-css-prefix}-lg { - left: (-@fa-li-width + (4em / 14)); - } -} diff --git a/netbox/project-static/font-awesome-4.7.0/less/mixins.less b/netbox/project-static/font-awesome-4.7.0/less/mixins.less deleted file mode 100644 index beef231d0e..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/less/mixins.less +++ /dev/null @@ -1,60 +0,0 @@ -// Mixins -// -------------------------- - -.fa-icon() { - display: inline-block; - font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration - font-size: inherit; // can't have font-size inherit on line above, so need to override - text-rendering: auto; // optimizelegibility throws things off #1094 - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -} - -.fa-icon-rotate(@degrees, @rotation) { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation})"; - -webkit-transform: rotate(@degrees); - -ms-transform: rotate(@degrees); - transform: rotate(@degrees); -} - -.fa-icon-flip(@horiz, @vert, @rotation) { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation}, mirror=1)"; - -webkit-transform: scale(@horiz, @vert); - -ms-transform: scale(@horiz, @vert); - transform: scale(@horiz, @vert); -} - - -// Only display content to screen readers. A la Bootstrap 4. -// -// See: http://a11yproject.com/posts/how-to-hide-content/ - -.sr-only() { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0,0,0,0); - border: 0; -} - -// Use in conjunction with .sr-only to only display content when it's focused. -// -// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 -// -// Credit: HTML5 Boilerplate - -.sr-only-focusable() { - &:active, - &:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; - } -} diff --git a/netbox/project-static/font-awesome-4.7.0/less/path.less b/netbox/project-static/font-awesome-4.7.0/less/path.less deleted file mode 100644 index 835be41f81..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/less/path.less +++ /dev/null @@ -1,15 +0,0 @@ -/* FONT PATH - * -------------------------- */ - -@font-face { - font-family: 'FontAwesome'; - src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); - src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), - url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'), - url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), - url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), - url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); - // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts - font-weight: normal; - font-style: normal; -} diff --git a/netbox/project-static/font-awesome-4.7.0/less/rotated-flipped.less b/netbox/project-static/font-awesome-4.7.0/less/rotated-flipped.less deleted file mode 100644 index f6ba81475b..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/less/rotated-flipped.less +++ /dev/null @@ -1,20 +0,0 @@ -// Rotated & Flipped Icons -// ------------------------- - -.@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } -.@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } -.@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } - -.@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } -.@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } - -// Hook for IE8-9 -// ------------------------- - -:root .@{fa-css-prefix}-rotate-90, -:root .@{fa-css-prefix}-rotate-180, -:root .@{fa-css-prefix}-rotate-270, -:root .@{fa-css-prefix}-flip-horizontal, -:root .@{fa-css-prefix}-flip-vertical { - filter: none; -} diff --git a/netbox/project-static/font-awesome-4.7.0/less/screen-reader.less b/netbox/project-static/font-awesome-4.7.0/less/screen-reader.less deleted file mode 100644 index 11c188196d..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/less/screen-reader.less +++ /dev/null @@ -1,5 +0,0 @@ -// Screen Readers -// ------------------------- - -.sr-only { .sr-only(); } -.sr-only-focusable { .sr-only-focusable(); } diff --git a/netbox/project-static/font-awesome-4.7.0/less/stacked.less b/netbox/project-static/font-awesome-4.7.0/less/stacked.less deleted file mode 100644 index fc53fb0e7a..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/less/stacked.less +++ /dev/null @@ -1,20 +0,0 @@ -// Stacked Icons -// ------------------------- - -.@{fa-css-prefix}-stack { - position: relative; - display: inline-block; - width: 2em; - height: 2em; - line-height: 2em; - vertical-align: middle; -} -.@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { - position: absolute; - left: 0; - width: 100%; - text-align: center; -} -.@{fa-css-prefix}-stack-1x { line-height: inherit; } -.@{fa-css-prefix}-stack-2x { font-size: 2em; } -.@{fa-css-prefix}-inverse { color: @fa-inverse; } diff --git a/netbox/project-static/font-awesome-4.7.0/less/variables.less b/netbox/project-static/font-awesome-4.7.0/less/variables.less deleted file mode 100644 index 7ddbbc0115..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/less/variables.less +++ /dev/null @@ -1,800 +0,0 @@ -// Variables -// -------------------------- - -@fa-font-path: "../fonts"; -@fa-font-size-base: 14px; -@fa-line-height-base: 1; -//@fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts"; // for referencing Bootstrap CDN font files directly -@fa-css-prefix: fa; -@fa-version: "4.7.0"; -@fa-border-color: #eee; -@fa-inverse: #fff; -@fa-li-width: (30em / 14); - -@fa-var-500px: "\f26e"; -@fa-var-address-book: "\f2b9"; -@fa-var-address-book-o: "\f2ba"; -@fa-var-address-card: "\f2bb"; -@fa-var-address-card-o: "\f2bc"; -@fa-var-adjust: "\f042"; -@fa-var-adn: "\f170"; -@fa-var-align-center: "\f037"; -@fa-var-align-justify: "\f039"; -@fa-var-align-left: "\f036"; -@fa-var-align-right: "\f038"; -@fa-var-amazon: "\f270"; -@fa-var-ambulance: "\f0f9"; -@fa-var-american-sign-language-interpreting: "\f2a3"; -@fa-var-anchor: "\f13d"; -@fa-var-android: "\f17b"; -@fa-var-angellist: "\f209"; -@fa-var-angle-double-down: "\f103"; -@fa-var-angle-double-left: "\f100"; -@fa-var-angle-double-right: "\f101"; -@fa-var-angle-double-up: "\f102"; -@fa-var-angle-down: "\f107"; -@fa-var-angle-left: "\f104"; -@fa-var-angle-right: "\f105"; -@fa-var-angle-up: "\f106"; -@fa-var-apple: "\f179"; -@fa-var-archive: "\f187"; -@fa-var-area-chart: "\f1fe"; -@fa-var-arrow-circle-down: "\f0ab"; -@fa-var-arrow-circle-left: "\f0a8"; -@fa-var-arrow-circle-o-down: "\f01a"; -@fa-var-arrow-circle-o-left: "\f190"; -@fa-var-arrow-circle-o-right: "\f18e"; -@fa-var-arrow-circle-o-up: "\f01b"; -@fa-var-arrow-circle-right: "\f0a9"; -@fa-var-arrow-circle-up: "\f0aa"; -@fa-var-arrow-down: "\f063"; -@fa-var-arrow-left: "\f060"; -@fa-var-arrow-right: "\f061"; -@fa-var-arrow-up: "\f062"; -@fa-var-arrows: "\f047"; -@fa-var-arrows-alt: "\f0b2"; -@fa-var-arrows-h: "\f07e"; -@fa-var-arrows-v: "\f07d"; -@fa-var-asl-interpreting: "\f2a3"; -@fa-var-assistive-listening-systems: "\f2a2"; -@fa-var-asterisk: "\f069"; -@fa-var-at: "\f1fa"; -@fa-var-audio-description: "\f29e"; -@fa-var-automobile: "\f1b9"; -@fa-var-backward: "\f04a"; -@fa-var-balance-scale: "\f24e"; -@fa-var-ban: "\f05e"; -@fa-var-bandcamp: "\f2d5"; -@fa-var-bank: "\f19c"; -@fa-var-bar-chart: "\f080"; -@fa-var-bar-chart-o: "\f080"; -@fa-var-barcode: "\f02a"; -@fa-var-bars: "\f0c9"; -@fa-var-bath: "\f2cd"; -@fa-var-bathtub: "\f2cd"; -@fa-var-battery: "\f240"; -@fa-var-battery-0: "\f244"; -@fa-var-battery-1: "\f243"; -@fa-var-battery-2: "\f242"; -@fa-var-battery-3: "\f241"; -@fa-var-battery-4: "\f240"; -@fa-var-battery-empty: "\f244"; -@fa-var-battery-full: "\f240"; -@fa-var-battery-half: "\f242"; -@fa-var-battery-quarter: "\f243"; -@fa-var-battery-three-quarters: "\f241"; -@fa-var-bed: "\f236"; -@fa-var-beer: "\f0fc"; -@fa-var-behance: "\f1b4"; -@fa-var-behance-square: "\f1b5"; -@fa-var-bell: "\f0f3"; -@fa-var-bell-o: "\f0a2"; -@fa-var-bell-slash: "\f1f6"; -@fa-var-bell-slash-o: "\f1f7"; -@fa-var-bicycle: "\f206"; -@fa-var-binoculars: "\f1e5"; -@fa-var-birthday-cake: "\f1fd"; -@fa-var-bitbucket: "\f171"; -@fa-var-bitbucket-square: "\f172"; -@fa-var-bitcoin: "\f15a"; -@fa-var-black-tie: "\f27e"; -@fa-var-blind: "\f29d"; -@fa-var-bluetooth: "\f293"; -@fa-var-bluetooth-b: "\f294"; -@fa-var-bold: "\f032"; -@fa-var-bolt: "\f0e7"; -@fa-var-bomb: "\f1e2"; -@fa-var-book: "\f02d"; -@fa-var-bookmark: "\f02e"; -@fa-var-bookmark-o: "\f097"; -@fa-var-braille: "\f2a1"; -@fa-var-briefcase: "\f0b1"; -@fa-var-btc: "\f15a"; -@fa-var-bug: "\f188"; -@fa-var-building: "\f1ad"; -@fa-var-building-o: "\f0f7"; -@fa-var-bullhorn: "\f0a1"; -@fa-var-bullseye: "\f140"; -@fa-var-bus: "\f207"; -@fa-var-buysellads: "\f20d"; -@fa-var-cab: "\f1ba"; -@fa-var-calculator: "\f1ec"; -@fa-var-calendar: "\f073"; -@fa-var-calendar-check-o: "\f274"; -@fa-var-calendar-minus-o: "\f272"; -@fa-var-calendar-o: "\f133"; -@fa-var-calendar-plus-o: "\f271"; -@fa-var-calendar-times-o: "\f273"; -@fa-var-camera: "\f030"; -@fa-var-camera-retro: "\f083"; -@fa-var-car: "\f1b9"; -@fa-var-caret-down: "\f0d7"; -@fa-var-caret-left: "\f0d9"; -@fa-var-caret-right: "\f0da"; -@fa-var-caret-square-o-down: "\f150"; -@fa-var-caret-square-o-left: "\f191"; -@fa-var-caret-square-o-right: "\f152"; -@fa-var-caret-square-o-up: "\f151"; -@fa-var-caret-up: "\f0d8"; -@fa-var-cart-arrow-down: "\f218"; -@fa-var-cart-plus: "\f217"; -@fa-var-cc: "\f20a"; -@fa-var-cc-amex: "\f1f3"; -@fa-var-cc-diners-club: "\f24c"; -@fa-var-cc-discover: "\f1f2"; -@fa-var-cc-jcb: "\f24b"; -@fa-var-cc-mastercard: "\f1f1"; -@fa-var-cc-paypal: "\f1f4"; -@fa-var-cc-stripe: "\f1f5"; -@fa-var-cc-visa: "\f1f0"; -@fa-var-certificate: "\f0a3"; -@fa-var-chain: "\f0c1"; -@fa-var-chain-broken: "\f127"; -@fa-var-check: "\f00c"; -@fa-var-check-circle: "\f058"; -@fa-var-check-circle-o: "\f05d"; -@fa-var-check-square: "\f14a"; -@fa-var-check-square-o: "\f046"; -@fa-var-chevron-circle-down: "\f13a"; -@fa-var-chevron-circle-left: "\f137"; -@fa-var-chevron-circle-right: "\f138"; -@fa-var-chevron-circle-up: "\f139"; -@fa-var-chevron-down: "\f078"; -@fa-var-chevron-left: "\f053"; -@fa-var-chevron-right: "\f054"; -@fa-var-chevron-up: "\f077"; -@fa-var-child: "\f1ae"; -@fa-var-chrome: "\f268"; -@fa-var-circle: "\f111"; -@fa-var-circle-o: "\f10c"; -@fa-var-circle-o-notch: "\f1ce"; -@fa-var-circle-thin: "\f1db"; -@fa-var-clipboard: "\f0ea"; -@fa-var-clock-o: "\f017"; -@fa-var-clone: "\f24d"; -@fa-var-close: "\f00d"; -@fa-var-cloud: "\f0c2"; -@fa-var-cloud-download: "\f0ed"; -@fa-var-cloud-upload: "\f0ee"; -@fa-var-cny: "\f157"; -@fa-var-code: "\f121"; -@fa-var-code-fork: "\f126"; -@fa-var-codepen: "\f1cb"; -@fa-var-codiepie: "\f284"; -@fa-var-coffee: "\f0f4"; -@fa-var-cog: "\f013"; -@fa-var-cogs: "\f085"; -@fa-var-columns: "\f0db"; -@fa-var-comment: "\f075"; -@fa-var-comment-o: "\f0e5"; -@fa-var-commenting: "\f27a"; -@fa-var-commenting-o: "\f27b"; -@fa-var-comments: "\f086"; -@fa-var-comments-o: "\f0e6"; -@fa-var-compass: "\f14e"; -@fa-var-compress: "\f066"; -@fa-var-connectdevelop: "\f20e"; -@fa-var-contao: "\f26d"; -@fa-var-copy: "\f0c5"; -@fa-var-copyright: "\f1f9"; -@fa-var-creative-commons: "\f25e"; -@fa-var-credit-card: "\f09d"; -@fa-var-credit-card-alt: "\f283"; -@fa-var-crop: "\f125"; -@fa-var-crosshairs: "\f05b"; -@fa-var-css3: "\f13c"; -@fa-var-cube: "\f1b2"; -@fa-var-cubes: "\f1b3"; -@fa-var-cut: "\f0c4"; -@fa-var-cutlery: "\f0f5"; -@fa-var-dashboard: "\f0e4"; -@fa-var-dashcube: "\f210"; -@fa-var-database: "\f1c0"; -@fa-var-deaf: "\f2a4"; -@fa-var-deafness: "\f2a4"; -@fa-var-dedent: "\f03b"; -@fa-var-delicious: "\f1a5"; -@fa-var-desktop: "\f108"; -@fa-var-deviantart: "\f1bd"; -@fa-var-diamond: "\f219"; -@fa-var-digg: "\f1a6"; -@fa-var-dollar: "\f155"; -@fa-var-dot-circle-o: "\f192"; -@fa-var-download: "\f019"; -@fa-var-dribbble: "\f17d"; -@fa-var-drivers-license: "\f2c2"; -@fa-var-drivers-license-o: "\f2c3"; -@fa-var-dropbox: "\f16b"; -@fa-var-drupal: "\f1a9"; -@fa-var-edge: "\f282"; -@fa-var-edit: "\f044"; -@fa-var-eercast: "\f2da"; -@fa-var-eject: "\f052"; -@fa-var-ellipsis-h: "\f141"; -@fa-var-ellipsis-v: "\f142"; -@fa-var-empire: "\f1d1"; -@fa-var-envelope: "\f0e0"; -@fa-var-envelope-o: "\f003"; -@fa-var-envelope-open: "\f2b6"; -@fa-var-envelope-open-o: "\f2b7"; -@fa-var-envelope-square: "\f199"; -@fa-var-envira: "\f299"; -@fa-var-eraser: "\f12d"; -@fa-var-etsy: "\f2d7"; -@fa-var-eur: "\f153"; -@fa-var-euro: "\f153"; -@fa-var-exchange: "\f0ec"; -@fa-var-exclamation: "\f12a"; -@fa-var-exclamation-circle: "\f06a"; -@fa-var-exclamation-triangle: "\f071"; -@fa-var-expand: "\f065"; -@fa-var-expeditedssl: "\f23e"; -@fa-var-external-link: "\f08e"; -@fa-var-external-link-square: "\f14c"; -@fa-var-eye: "\f06e"; -@fa-var-eye-slash: "\f070"; -@fa-var-eyedropper: "\f1fb"; -@fa-var-fa: "\f2b4"; -@fa-var-facebook: "\f09a"; -@fa-var-facebook-f: "\f09a"; -@fa-var-facebook-official: "\f230"; -@fa-var-facebook-square: "\f082"; -@fa-var-fast-backward: "\f049"; -@fa-var-fast-forward: "\f050"; -@fa-var-fax: "\f1ac"; -@fa-var-feed: "\f09e"; -@fa-var-female: "\f182"; -@fa-var-fighter-jet: "\f0fb"; -@fa-var-file: "\f15b"; -@fa-var-file-archive-o: "\f1c6"; -@fa-var-file-audio-o: "\f1c7"; -@fa-var-file-code-o: "\f1c9"; -@fa-var-file-excel-o: "\f1c3"; -@fa-var-file-image-o: "\f1c5"; -@fa-var-file-movie-o: "\f1c8"; -@fa-var-file-o: "\f016"; -@fa-var-file-pdf-o: "\f1c1"; -@fa-var-file-photo-o: "\f1c5"; -@fa-var-file-picture-o: "\f1c5"; -@fa-var-file-powerpoint-o: "\f1c4"; -@fa-var-file-sound-o: "\f1c7"; -@fa-var-file-text: "\f15c"; -@fa-var-file-text-o: "\f0f6"; -@fa-var-file-video-o: "\f1c8"; -@fa-var-file-word-o: "\f1c2"; -@fa-var-file-zip-o: "\f1c6"; -@fa-var-files-o: "\f0c5"; -@fa-var-film: "\f008"; -@fa-var-filter: "\f0b0"; -@fa-var-fire: "\f06d"; -@fa-var-fire-extinguisher: "\f134"; -@fa-var-firefox: "\f269"; -@fa-var-first-order: "\f2b0"; -@fa-var-flag: "\f024"; -@fa-var-flag-checkered: "\f11e"; -@fa-var-flag-o: "\f11d"; -@fa-var-flash: "\f0e7"; -@fa-var-flask: "\f0c3"; -@fa-var-flickr: "\f16e"; -@fa-var-floppy-o: "\f0c7"; -@fa-var-folder: "\f07b"; -@fa-var-folder-o: "\f114"; -@fa-var-folder-open: "\f07c"; -@fa-var-folder-open-o: "\f115"; -@fa-var-font: "\f031"; -@fa-var-font-awesome: "\f2b4"; -@fa-var-fonticons: "\f280"; -@fa-var-fort-awesome: "\f286"; -@fa-var-forumbee: "\f211"; -@fa-var-forward: "\f04e"; -@fa-var-foursquare: "\f180"; -@fa-var-free-code-camp: "\f2c5"; -@fa-var-frown-o: "\f119"; -@fa-var-futbol-o: "\f1e3"; -@fa-var-gamepad: "\f11b"; -@fa-var-gavel: "\f0e3"; -@fa-var-gbp: "\f154"; -@fa-var-ge: "\f1d1"; -@fa-var-gear: "\f013"; -@fa-var-gears: "\f085"; -@fa-var-genderless: "\f22d"; -@fa-var-get-pocket: "\f265"; -@fa-var-gg: "\f260"; -@fa-var-gg-circle: "\f261"; -@fa-var-gift: "\f06b"; -@fa-var-git: "\f1d3"; -@fa-var-git-square: "\f1d2"; -@fa-var-github: "\f09b"; -@fa-var-github-alt: "\f113"; -@fa-var-github-square: "\f092"; -@fa-var-gitlab: "\f296"; -@fa-var-gittip: "\f184"; -@fa-var-glass: "\f000"; -@fa-var-glide: "\f2a5"; -@fa-var-glide-g: "\f2a6"; -@fa-var-globe: "\f0ac"; -@fa-var-google: "\f1a0"; -@fa-var-google-plus: "\f0d5"; -@fa-var-google-plus-circle: "\f2b3"; -@fa-var-google-plus-official: "\f2b3"; -@fa-var-google-plus-square: "\f0d4"; -@fa-var-google-wallet: "\f1ee"; -@fa-var-graduation-cap: "\f19d"; -@fa-var-gratipay: "\f184"; -@fa-var-grav: "\f2d6"; -@fa-var-group: "\f0c0"; -@fa-var-h-square: "\f0fd"; -@fa-var-hacker-news: "\f1d4"; -@fa-var-hand-grab-o: "\f255"; -@fa-var-hand-lizard-o: "\f258"; -@fa-var-hand-o-down: "\f0a7"; -@fa-var-hand-o-left: "\f0a5"; -@fa-var-hand-o-right: "\f0a4"; -@fa-var-hand-o-up: "\f0a6"; -@fa-var-hand-paper-o: "\f256"; -@fa-var-hand-peace-o: "\f25b"; -@fa-var-hand-pointer-o: "\f25a"; -@fa-var-hand-rock-o: "\f255"; -@fa-var-hand-scissors-o: "\f257"; -@fa-var-hand-spock-o: "\f259"; -@fa-var-hand-stop-o: "\f256"; -@fa-var-handshake-o: "\f2b5"; -@fa-var-hard-of-hearing: "\f2a4"; -@fa-var-hashtag: "\f292"; -@fa-var-hdd-o: "\f0a0"; -@fa-var-header: "\f1dc"; -@fa-var-headphones: "\f025"; -@fa-var-heart: "\f004"; -@fa-var-heart-o: "\f08a"; -@fa-var-heartbeat: "\f21e"; -@fa-var-history: "\f1da"; -@fa-var-home: "\f015"; -@fa-var-hospital-o: "\f0f8"; -@fa-var-hotel: "\f236"; -@fa-var-hourglass: "\f254"; -@fa-var-hourglass-1: "\f251"; -@fa-var-hourglass-2: "\f252"; -@fa-var-hourglass-3: "\f253"; -@fa-var-hourglass-end: "\f253"; -@fa-var-hourglass-half: "\f252"; -@fa-var-hourglass-o: "\f250"; -@fa-var-hourglass-start: "\f251"; -@fa-var-houzz: "\f27c"; -@fa-var-html5: "\f13b"; -@fa-var-i-cursor: "\f246"; -@fa-var-id-badge: "\f2c1"; -@fa-var-id-card: "\f2c2"; -@fa-var-id-card-o: "\f2c3"; -@fa-var-ils: "\f20b"; -@fa-var-image: "\f03e"; -@fa-var-imdb: "\f2d8"; -@fa-var-inbox: "\f01c"; -@fa-var-indent: "\f03c"; -@fa-var-industry: "\f275"; -@fa-var-info: "\f129"; -@fa-var-info-circle: "\f05a"; -@fa-var-inr: "\f156"; -@fa-var-instagram: "\f16d"; -@fa-var-institution: "\f19c"; -@fa-var-internet-explorer: "\f26b"; -@fa-var-intersex: "\f224"; -@fa-var-ioxhost: "\f208"; -@fa-var-italic: "\f033"; -@fa-var-joomla: "\f1aa"; -@fa-var-jpy: "\f157"; -@fa-var-jsfiddle: "\f1cc"; -@fa-var-key: "\f084"; -@fa-var-keyboard-o: "\f11c"; -@fa-var-krw: "\f159"; -@fa-var-language: "\f1ab"; -@fa-var-laptop: "\f109"; -@fa-var-lastfm: "\f202"; -@fa-var-lastfm-square: "\f203"; -@fa-var-leaf: "\f06c"; -@fa-var-leanpub: "\f212"; -@fa-var-legal: "\f0e3"; -@fa-var-lemon-o: "\f094"; -@fa-var-level-down: "\f149"; -@fa-var-level-up: "\f148"; -@fa-var-life-bouy: "\f1cd"; -@fa-var-life-buoy: "\f1cd"; -@fa-var-life-ring: "\f1cd"; -@fa-var-life-saver: "\f1cd"; -@fa-var-lightbulb-o: "\f0eb"; -@fa-var-line-chart: "\f201"; -@fa-var-link: "\f0c1"; -@fa-var-linkedin: "\f0e1"; -@fa-var-linkedin-square: "\f08c"; -@fa-var-linode: "\f2b8"; -@fa-var-linux: "\f17c"; -@fa-var-list: "\f03a"; -@fa-var-list-alt: "\f022"; -@fa-var-list-ol: "\f0cb"; -@fa-var-list-ul: "\f0ca"; -@fa-var-location-arrow: "\f124"; -@fa-var-lock: "\f023"; -@fa-var-long-arrow-down: "\f175"; -@fa-var-long-arrow-left: "\f177"; -@fa-var-long-arrow-right: "\f178"; -@fa-var-long-arrow-up: "\f176"; -@fa-var-low-vision: "\f2a8"; -@fa-var-magic: "\f0d0"; -@fa-var-magnet: "\f076"; -@fa-var-mail-forward: "\f064"; -@fa-var-mail-reply: "\f112"; -@fa-var-mail-reply-all: "\f122"; -@fa-var-male: "\f183"; -@fa-var-map: "\f279"; -@fa-var-map-marker: "\f041"; -@fa-var-map-o: "\f278"; -@fa-var-map-pin: "\f276"; -@fa-var-map-signs: "\f277"; -@fa-var-mars: "\f222"; -@fa-var-mars-double: "\f227"; -@fa-var-mars-stroke: "\f229"; -@fa-var-mars-stroke-h: "\f22b"; -@fa-var-mars-stroke-v: "\f22a"; -@fa-var-maxcdn: "\f136"; -@fa-var-meanpath: "\f20c"; -@fa-var-medium: "\f23a"; -@fa-var-medkit: "\f0fa"; -@fa-var-meetup: "\f2e0"; -@fa-var-meh-o: "\f11a"; -@fa-var-mercury: "\f223"; -@fa-var-microchip: "\f2db"; -@fa-var-microphone: "\f130"; -@fa-var-microphone-slash: "\f131"; -@fa-var-minus: "\f068"; -@fa-var-minus-circle: "\f056"; -@fa-var-minus-square: "\f146"; -@fa-var-minus-square-o: "\f147"; -@fa-var-mixcloud: "\f289"; -@fa-var-mobile: "\f10b"; -@fa-var-mobile-phone: "\f10b"; -@fa-var-modx: "\f285"; -@fa-var-money: "\f0d6"; -@fa-var-moon-o: "\f186"; -@fa-var-mortar-board: "\f19d"; -@fa-var-motorcycle: "\f21c"; -@fa-var-mouse-pointer: "\f245"; -@fa-var-music: "\f001"; -@fa-var-navicon: "\f0c9"; -@fa-var-neuter: "\f22c"; -@fa-var-newspaper-o: "\f1ea"; -@fa-var-object-group: "\f247"; -@fa-var-object-ungroup: "\f248"; -@fa-var-odnoklassniki: "\f263"; -@fa-var-odnoklassniki-square: "\f264"; -@fa-var-opencart: "\f23d"; -@fa-var-openid: "\f19b"; -@fa-var-opera: "\f26a"; -@fa-var-optin-monster: "\f23c"; -@fa-var-outdent: "\f03b"; -@fa-var-pagelines: "\f18c"; -@fa-var-paint-brush: "\f1fc"; -@fa-var-paper-plane: "\f1d8"; -@fa-var-paper-plane-o: "\f1d9"; -@fa-var-paperclip: "\f0c6"; -@fa-var-paragraph: "\f1dd"; -@fa-var-paste: "\f0ea"; -@fa-var-pause: "\f04c"; -@fa-var-pause-circle: "\f28b"; -@fa-var-pause-circle-o: "\f28c"; -@fa-var-paw: "\f1b0"; -@fa-var-paypal: "\f1ed"; -@fa-var-pencil: "\f040"; -@fa-var-pencil-square: "\f14b"; -@fa-var-pencil-square-o: "\f044"; -@fa-var-percent: "\f295"; -@fa-var-phone: "\f095"; -@fa-var-phone-square: "\f098"; -@fa-var-photo: "\f03e"; -@fa-var-picture-o: "\f03e"; -@fa-var-pie-chart: "\f200"; -@fa-var-pied-piper: "\f2ae"; -@fa-var-pied-piper-alt: "\f1a8"; -@fa-var-pied-piper-pp: "\f1a7"; -@fa-var-pinterest: "\f0d2"; -@fa-var-pinterest-p: "\f231"; -@fa-var-pinterest-square: "\f0d3"; -@fa-var-plane: "\f072"; -@fa-var-play: "\f04b"; -@fa-var-play-circle: "\f144"; -@fa-var-play-circle-o: "\f01d"; -@fa-var-plug: "\f1e6"; -@fa-var-plus: "\f067"; -@fa-var-plus-circle: "\f055"; -@fa-var-plus-square: "\f0fe"; -@fa-var-plus-square-o: "\f196"; -@fa-var-podcast: "\f2ce"; -@fa-var-power-off: "\f011"; -@fa-var-print: "\f02f"; -@fa-var-product-hunt: "\f288"; -@fa-var-puzzle-piece: "\f12e"; -@fa-var-qq: "\f1d6"; -@fa-var-qrcode: "\f029"; -@fa-var-question: "\f128"; -@fa-var-question-circle: "\f059"; -@fa-var-question-circle-o: "\f29c"; -@fa-var-quora: "\f2c4"; -@fa-var-quote-left: "\f10d"; -@fa-var-quote-right: "\f10e"; -@fa-var-ra: "\f1d0"; -@fa-var-random: "\f074"; -@fa-var-ravelry: "\f2d9"; -@fa-var-rebel: "\f1d0"; -@fa-var-recycle: "\f1b8"; -@fa-var-reddit: "\f1a1"; -@fa-var-reddit-alien: "\f281"; -@fa-var-reddit-square: "\f1a2"; -@fa-var-refresh: "\f021"; -@fa-var-registered: "\f25d"; -@fa-var-remove: "\f00d"; -@fa-var-renren: "\f18b"; -@fa-var-reorder: "\f0c9"; -@fa-var-repeat: "\f01e"; -@fa-var-reply: "\f112"; -@fa-var-reply-all: "\f122"; -@fa-var-resistance: "\f1d0"; -@fa-var-retweet: "\f079"; -@fa-var-rmb: "\f157"; -@fa-var-road: "\f018"; -@fa-var-rocket: "\f135"; -@fa-var-rotate-left: "\f0e2"; -@fa-var-rotate-right: "\f01e"; -@fa-var-rouble: "\f158"; -@fa-var-rss: "\f09e"; -@fa-var-rss-square: "\f143"; -@fa-var-rub: "\f158"; -@fa-var-ruble: "\f158"; -@fa-var-rupee: "\f156"; -@fa-var-s15: "\f2cd"; -@fa-var-safari: "\f267"; -@fa-var-save: "\f0c7"; -@fa-var-scissors: "\f0c4"; -@fa-var-scribd: "\f28a"; -@fa-var-search: "\f002"; -@fa-var-search-minus: "\f010"; -@fa-var-search-plus: "\f00e"; -@fa-var-sellsy: "\f213"; -@fa-var-send: "\f1d8"; -@fa-var-send-o: "\f1d9"; -@fa-var-server: "\f233"; -@fa-var-share: "\f064"; -@fa-var-share-alt: "\f1e0"; -@fa-var-share-alt-square: "\f1e1"; -@fa-var-share-square: "\f14d"; -@fa-var-share-square-o: "\f045"; -@fa-var-shekel: "\f20b"; -@fa-var-sheqel: "\f20b"; -@fa-var-shield: "\f132"; -@fa-var-ship: "\f21a"; -@fa-var-shirtsinbulk: "\f214"; -@fa-var-shopping-bag: "\f290"; -@fa-var-shopping-basket: "\f291"; -@fa-var-shopping-cart: "\f07a"; -@fa-var-shower: "\f2cc"; -@fa-var-sign-in: "\f090"; -@fa-var-sign-language: "\f2a7"; -@fa-var-sign-out: "\f08b"; -@fa-var-signal: "\f012"; -@fa-var-signing: "\f2a7"; -@fa-var-simplybuilt: "\f215"; -@fa-var-sitemap: "\f0e8"; -@fa-var-skyatlas: "\f216"; -@fa-var-skype: "\f17e"; -@fa-var-slack: "\f198"; -@fa-var-sliders: "\f1de"; -@fa-var-slideshare: "\f1e7"; -@fa-var-smile-o: "\f118"; -@fa-var-snapchat: "\f2ab"; -@fa-var-snapchat-ghost: "\f2ac"; -@fa-var-snapchat-square: "\f2ad"; -@fa-var-snowflake-o: "\f2dc"; -@fa-var-soccer-ball-o: "\f1e3"; -@fa-var-sort: "\f0dc"; -@fa-var-sort-alpha-asc: "\f15d"; -@fa-var-sort-alpha-desc: "\f15e"; -@fa-var-sort-amount-asc: "\f160"; -@fa-var-sort-amount-desc: "\f161"; -@fa-var-sort-asc: "\f0de"; -@fa-var-sort-desc: "\f0dd"; -@fa-var-sort-down: "\f0dd"; -@fa-var-sort-numeric-asc: "\f162"; -@fa-var-sort-numeric-desc: "\f163"; -@fa-var-sort-up: "\f0de"; -@fa-var-soundcloud: "\f1be"; -@fa-var-space-shuttle: "\f197"; -@fa-var-spinner: "\f110"; -@fa-var-spoon: "\f1b1"; -@fa-var-spotify: "\f1bc"; -@fa-var-square: "\f0c8"; -@fa-var-square-o: "\f096"; -@fa-var-stack-exchange: "\f18d"; -@fa-var-stack-overflow: "\f16c"; -@fa-var-star: "\f005"; -@fa-var-star-half: "\f089"; -@fa-var-star-half-empty: "\f123"; -@fa-var-star-half-full: "\f123"; -@fa-var-star-half-o: "\f123"; -@fa-var-star-o: "\f006"; -@fa-var-steam: "\f1b6"; -@fa-var-steam-square: "\f1b7"; -@fa-var-step-backward: "\f048"; -@fa-var-step-forward: "\f051"; -@fa-var-stethoscope: "\f0f1"; -@fa-var-sticky-note: "\f249"; -@fa-var-sticky-note-o: "\f24a"; -@fa-var-stop: "\f04d"; -@fa-var-stop-circle: "\f28d"; -@fa-var-stop-circle-o: "\f28e"; -@fa-var-street-view: "\f21d"; -@fa-var-strikethrough: "\f0cc"; -@fa-var-stumbleupon: "\f1a4"; -@fa-var-stumbleupon-circle: "\f1a3"; -@fa-var-subscript: "\f12c"; -@fa-var-subway: "\f239"; -@fa-var-suitcase: "\f0f2"; -@fa-var-sun-o: "\f185"; -@fa-var-superpowers: "\f2dd"; -@fa-var-superscript: "\f12b"; -@fa-var-support: "\f1cd"; -@fa-var-table: "\f0ce"; -@fa-var-tablet: "\f10a"; -@fa-var-tachometer: "\f0e4"; -@fa-var-tag: "\f02b"; -@fa-var-tags: "\f02c"; -@fa-var-tasks: "\f0ae"; -@fa-var-taxi: "\f1ba"; -@fa-var-telegram: "\f2c6"; -@fa-var-television: "\f26c"; -@fa-var-tencent-weibo: "\f1d5"; -@fa-var-terminal: "\f120"; -@fa-var-text-height: "\f034"; -@fa-var-text-width: "\f035"; -@fa-var-th: "\f00a"; -@fa-var-th-large: "\f009"; -@fa-var-th-list: "\f00b"; -@fa-var-themeisle: "\f2b2"; -@fa-var-thermometer: "\f2c7"; -@fa-var-thermometer-0: "\f2cb"; -@fa-var-thermometer-1: "\f2ca"; -@fa-var-thermometer-2: "\f2c9"; -@fa-var-thermometer-3: "\f2c8"; -@fa-var-thermometer-4: "\f2c7"; -@fa-var-thermometer-empty: "\f2cb"; -@fa-var-thermometer-full: "\f2c7"; -@fa-var-thermometer-half: "\f2c9"; -@fa-var-thermometer-quarter: "\f2ca"; -@fa-var-thermometer-three-quarters: "\f2c8"; -@fa-var-thumb-tack: "\f08d"; -@fa-var-thumbs-down: "\f165"; -@fa-var-thumbs-o-down: "\f088"; -@fa-var-thumbs-o-up: "\f087"; -@fa-var-thumbs-up: "\f164"; -@fa-var-ticket: "\f145"; -@fa-var-times: "\f00d"; -@fa-var-times-circle: "\f057"; -@fa-var-times-circle-o: "\f05c"; -@fa-var-times-rectangle: "\f2d3"; -@fa-var-times-rectangle-o: "\f2d4"; -@fa-var-tint: "\f043"; -@fa-var-toggle-down: "\f150"; -@fa-var-toggle-left: "\f191"; -@fa-var-toggle-off: "\f204"; -@fa-var-toggle-on: "\f205"; -@fa-var-toggle-right: "\f152"; -@fa-var-toggle-up: "\f151"; -@fa-var-trademark: "\f25c"; -@fa-var-train: "\f238"; -@fa-var-transgender: "\f224"; -@fa-var-transgender-alt: "\f225"; -@fa-var-trash: "\f1f8"; -@fa-var-trash-o: "\f014"; -@fa-var-tree: "\f1bb"; -@fa-var-trello: "\f181"; -@fa-var-tripadvisor: "\f262"; -@fa-var-trophy: "\f091"; -@fa-var-truck: "\f0d1"; -@fa-var-try: "\f195"; -@fa-var-tty: "\f1e4"; -@fa-var-tumblr: "\f173"; -@fa-var-tumblr-square: "\f174"; -@fa-var-turkish-lira: "\f195"; -@fa-var-tv: "\f26c"; -@fa-var-twitch: "\f1e8"; -@fa-var-twitter: "\f099"; -@fa-var-twitter-square: "\f081"; -@fa-var-umbrella: "\f0e9"; -@fa-var-underline: "\f0cd"; -@fa-var-undo: "\f0e2"; -@fa-var-universal-access: "\f29a"; -@fa-var-university: "\f19c"; -@fa-var-unlink: "\f127"; -@fa-var-unlock: "\f09c"; -@fa-var-unlock-alt: "\f13e"; -@fa-var-unsorted: "\f0dc"; -@fa-var-upload: "\f093"; -@fa-var-usb: "\f287"; -@fa-var-usd: "\f155"; -@fa-var-user: "\f007"; -@fa-var-user-circle: "\f2bd"; -@fa-var-user-circle-o: "\f2be"; -@fa-var-user-md: "\f0f0"; -@fa-var-user-o: "\f2c0"; -@fa-var-user-plus: "\f234"; -@fa-var-user-secret: "\f21b"; -@fa-var-user-times: "\f235"; -@fa-var-users: "\f0c0"; -@fa-var-vcard: "\f2bb"; -@fa-var-vcard-o: "\f2bc"; -@fa-var-venus: "\f221"; -@fa-var-venus-double: "\f226"; -@fa-var-venus-mars: "\f228"; -@fa-var-viacoin: "\f237"; -@fa-var-viadeo: "\f2a9"; -@fa-var-viadeo-square: "\f2aa"; -@fa-var-video-camera: "\f03d"; -@fa-var-vimeo: "\f27d"; -@fa-var-vimeo-square: "\f194"; -@fa-var-vine: "\f1ca"; -@fa-var-vk: "\f189"; -@fa-var-volume-control-phone: "\f2a0"; -@fa-var-volume-down: "\f027"; -@fa-var-volume-off: "\f026"; -@fa-var-volume-up: "\f028"; -@fa-var-warning: "\f071"; -@fa-var-wechat: "\f1d7"; -@fa-var-weibo: "\f18a"; -@fa-var-weixin: "\f1d7"; -@fa-var-whatsapp: "\f232"; -@fa-var-wheelchair: "\f193"; -@fa-var-wheelchair-alt: "\f29b"; -@fa-var-wifi: "\f1eb"; -@fa-var-wikipedia-w: "\f266"; -@fa-var-window-close: "\f2d3"; -@fa-var-window-close-o: "\f2d4"; -@fa-var-window-maximize: "\f2d0"; -@fa-var-window-minimize: "\f2d1"; -@fa-var-window-restore: "\f2d2"; -@fa-var-windows: "\f17a"; -@fa-var-won: "\f159"; -@fa-var-wordpress: "\f19a"; -@fa-var-wpbeginner: "\f297"; -@fa-var-wpexplorer: "\f2de"; -@fa-var-wpforms: "\f298"; -@fa-var-wrench: "\f0ad"; -@fa-var-xing: "\f168"; -@fa-var-xing-square: "\f169"; -@fa-var-y-combinator: "\f23b"; -@fa-var-y-combinator-square: "\f1d4"; -@fa-var-yahoo: "\f19e"; -@fa-var-yc: "\f23b"; -@fa-var-yc-square: "\f1d4"; -@fa-var-yelp: "\f1e9"; -@fa-var-yen: "\f157"; -@fa-var-yoast: "\f2b1"; -@fa-var-youtube: "\f167"; -@fa-var-youtube-play: "\f16a"; -@fa-var-youtube-square: "\f166"; - diff --git a/netbox/project-static/font-awesome-4.7.0/scss/_animated.scss b/netbox/project-static/font-awesome-4.7.0/scss/_animated.scss deleted file mode 100644 index 8a020dbfff..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/scss/_animated.scss +++ /dev/null @@ -1,34 +0,0 @@ -// Spinning Icons -// -------------------------- - -.#{$fa-css-prefix}-spin { - -webkit-animation: fa-spin 2s infinite linear; - animation: fa-spin 2s infinite linear; -} - -.#{$fa-css-prefix}-pulse { - -webkit-animation: fa-spin 1s infinite steps(8); - animation: fa-spin 1s infinite steps(8); -} - -@-webkit-keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} - -@keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} diff --git a/netbox/project-static/font-awesome-4.7.0/scss/_bordered-pulled.scss b/netbox/project-static/font-awesome-4.7.0/scss/_bordered-pulled.scss deleted file mode 100644 index d4b85a02f2..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/scss/_bordered-pulled.scss +++ /dev/null @@ -1,25 +0,0 @@ -// Bordered & Pulled -// ------------------------- - -.#{$fa-css-prefix}-border { - padding: .2em .25em .15em; - border: solid .08em $fa-border-color; - border-radius: .1em; -} - -.#{$fa-css-prefix}-pull-left { float: left; } -.#{$fa-css-prefix}-pull-right { float: right; } - -.#{$fa-css-prefix} { - &.#{$fa-css-prefix}-pull-left { margin-right: .3em; } - &.#{$fa-css-prefix}-pull-right { margin-left: .3em; } -} - -/* Deprecated as of 4.4.0 */ -.pull-right { float: right; } -.pull-left { float: left; } - -.#{$fa-css-prefix} { - &.pull-left { margin-right: .3em; } - &.pull-right { margin-left: .3em; } -} diff --git a/netbox/project-static/font-awesome-4.7.0/scss/_core.scss b/netbox/project-static/font-awesome-4.7.0/scss/_core.scss deleted file mode 100644 index 7425ef85fc..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/scss/_core.scss +++ /dev/null @@ -1,12 +0,0 @@ -// Base Class Definition -// ------------------------- - -.#{$fa-css-prefix} { - display: inline-block; - font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration - font-size: inherit; // can't have font-size inherit on line above, so need to override - text-rendering: auto; // optimizelegibility throws things off #1094 - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -} diff --git a/netbox/project-static/font-awesome-4.7.0/scss/_fixed-width.scss b/netbox/project-static/font-awesome-4.7.0/scss/_fixed-width.scss deleted file mode 100644 index b221c98133..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/scss/_fixed-width.scss +++ /dev/null @@ -1,6 +0,0 @@ -// Fixed Width Icons -// ------------------------- -.#{$fa-css-prefix}-fw { - width: (18em / 14); - text-align: center; -} diff --git a/netbox/project-static/font-awesome-4.7.0/scss/_icons.scss b/netbox/project-static/font-awesome-4.7.0/scss/_icons.scss deleted file mode 100644 index e63e702c4d..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/scss/_icons.scss +++ /dev/null @@ -1,789 +0,0 @@ -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen - readers do not read off random characters that represent icons */ - -.#{$fa-css-prefix}-glass:before { content: $fa-var-glass; } -.#{$fa-css-prefix}-music:before { content: $fa-var-music; } -.#{$fa-css-prefix}-search:before { content: $fa-var-search; } -.#{$fa-css-prefix}-envelope-o:before { content: $fa-var-envelope-o; } -.#{$fa-css-prefix}-heart:before { content: $fa-var-heart; } -.#{$fa-css-prefix}-star:before { content: $fa-var-star; } -.#{$fa-css-prefix}-star-o:before { content: $fa-var-star-o; } -.#{$fa-css-prefix}-user:before { content: $fa-var-user; } -.#{$fa-css-prefix}-film:before { content: $fa-var-film; } -.#{$fa-css-prefix}-th-large:before { content: $fa-var-th-large; } -.#{$fa-css-prefix}-th:before { content: $fa-var-th; } -.#{$fa-css-prefix}-th-list:before { content: $fa-var-th-list; } -.#{$fa-css-prefix}-check:before { content: $fa-var-check; } -.#{$fa-css-prefix}-remove:before, -.#{$fa-css-prefix}-close:before, -.#{$fa-css-prefix}-times:before { content: $fa-var-times; } -.#{$fa-css-prefix}-search-plus:before { content: $fa-var-search-plus; } -.#{$fa-css-prefix}-search-minus:before { content: $fa-var-search-minus; } -.#{$fa-css-prefix}-power-off:before { content: $fa-var-power-off; } -.#{$fa-css-prefix}-signal:before { content: $fa-var-signal; } -.#{$fa-css-prefix}-gear:before, -.#{$fa-css-prefix}-cog:before { content: $fa-var-cog; } -.#{$fa-css-prefix}-trash-o:before { content: $fa-var-trash-o; } -.#{$fa-css-prefix}-home:before { content: $fa-var-home; } -.#{$fa-css-prefix}-file-o:before { content: $fa-var-file-o; } -.#{$fa-css-prefix}-clock-o:before { content: $fa-var-clock-o; } -.#{$fa-css-prefix}-road:before { content: $fa-var-road; } -.#{$fa-css-prefix}-download:before { content: $fa-var-download; } -.#{$fa-css-prefix}-arrow-circle-o-down:before { content: $fa-var-arrow-circle-o-down; } -.#{$fa-css-prefix}-arrow-circle-o-up:before { content: $fa-var-arrow-circle-o-up; } -.#{$fa-css-prefix}-inbox:before { content: $fa-var-inbox; } -.#{$fa-css-prefix}-play-circle-o:before { content: $fa-var-play-circle-o; } -.#{$fa-css-prefix}-rotate-right:before, -.#{$fa-css-prefix}-repeat:before { content: $fa-var-repeat; } -.#{$fa-css-prefix}-refresh:before { content: $fa-var-refresh; } -.#{$fa-css-prefix}-list-alt:before { content: $fa-var-list-alt; } -.#{$fa-css-prefix}-lock:before { content: $fa-var-lock; } -.#{$fa-css-prefix}-flag:before { content: $fa-var-flag; } -.#{$fa-css-prefix}-headphones:before { content: $fa-var-headphones; } -.#{$fa-css-prefix}-volume-off:before { content: $fa-var-volume-off; } -.#{$fa-css-prefix}-volume-down:before { content: $fa-var-volume-down; } -.#{$fa-css-prefix}-volume-up:before { content: $fa-var-volume-up; } -.#{$fa-css-prefix}-qrcode:before { content: $fa-var-qrcode; } -.#{$fa-css-prefix}-barcode:before { content: $fa-var-barcode; } -.#{$fa-css-prefix}-tag:before { content: $fa-var-tag; } -.#{$fa-css-prefix}-tags:before { content: $fa-var-tags; } -.#{$fa-css-prefix}-book:before { content: $fa-var-book; } -.#{$fa-css-prefix}-bookmark:before { content: $fa-var-bookmark; } -.#{$fa-css-prefix}-print:before { content: $fa-var-print; } -.#{$fa-css-prefix}-camera:before { content: $fa-var-camera; } -.#{$fa-css-prefix}-font:before { content: $fa-var-font; } -.#{$fa-css-prefix}-bold:before { content: $fa-var-bold; } -.#{$fa-css-prefix}-italic:before { content: $fa-var-italic; } -.#{$fa-css-prefix}-text-height:before { content: $fa-var-text-height; } -.#{$fa-css-prefix}-text-width:before { content: $fa-var-text-width; } -.#{$fa-css-prefix}-align-left:before { content: $fa-var-align-left; } -.#{$fa-css-prefix}-align-center:before { content: $fa-var-align-center; } -.#{$fa-css-prefix}-align-right:before { content: $fa-var-align-right; } -.#{$fa-css-prefix}-align-justify:before { content: $fa-var-align-justify; } -.#{$fa-css-prefix}-list:before { content: $fa-var-list; } -.#{$fa-css-prefix}-dedent:before, -.#{$fa-css-prefix}-outdent:before { content: $fa-var-outdent; } -.#{$fa-css-prefix}-indent:before { content: $fa-var-indent; } -.#{$fa-css-prefix}-video-camera:before { content: $fa-var-video-camera; } -.#{$fa-css-prefix}-photo:before, -.#{$fa-css-prefix}-image:before, -.#{$fa-css-prefix}-picture-o:before { content: $fa-var-picture-o; } -.#{$fa-css-prefix}-pencil:before { content: $fa-var-pencil; } -.#{$fa-css-prefix}-map-marker:before { content: $fa-var-map-marker; } -.#{$fa-css-prefix}-adjust:before { content: $fa-var-adjust; } -.#{$fa-css-prefix}-tint:before { content: $fa-var-tint; } -.#{$fa-css-prefix}-edit:before, -.#{$fa-css-prefix}-pencil-square-o:before { content: $fa-var-pencil-square-o; } -.#{$fa-css-prefix}-share-square-o:before { content: $fa-var-share-square-o; } -.#{$fa-css-prefix}-check-square-o:before { content: $fa-var-check-square-o; } -.#{$fa-css-prefix}-arrows:before { content: $fa-var-arrows; } -.#{$fa-css-prefix}-step-backward:before { content: $fa-var-step-backward; } -.#{$fa-css-prefix}-fast-backward:before { content: $fa-var-fast-backward; } -.#{$fa-css-prefix}-backward:before { content: $fa-var-backward; } -.#{$fa-css-prefix}-play:before { content: $fa-var-play; } -.#{$fa-css-prefix}-pause:before { content: $fa-var-pause; } -.#{$fa-css-prefix}-stop:before { content: $fa-var-stop; } -.#{$fa-css-prefix}-forward:before { content: $fa-var-forward; } -.#{$fa-css-prefix}-fast-forward:before { content: $fa-var-fast-forward; } -.#{$fa-css-prefix}-step-forward:before { content: $fa-var-step-forward; } -.#{$fa-css-prefix}-eject:before { content: $fa-var-eject; } -.#{$fa-css-prefix}-chevron-left:before { content: $fa-var-chevron-left; } -.#{$fa-css-prefix}-chevron-right:before { content: $fa-var-chevron-right; } -.#{$fa-css-prefix}-plus-circle:before { content: $fa-var-plus-circle; } -.#{$fa-css-prefix}-minus-circle:before { content: $fa-var-minus-circle; } -.#{$fa-css-prefix}-times-circle:before { content: $fa-var-times-circle; } -.#{$fa-css-prefix}-check-circle:before { content: $fa-var-check-circle; } -.#{$fa-css-prefix}-question-circle:before { content: $fa-var-question-circle; } -.#{$fa-css-prefix}-info-circle:before { content: $fa-var-info-circle; } -.#{$fa-css-prefix}-crosshairs:before { content: $fa-var-crosshairs; } -.#{$fa-css-prefix}-times-circle-o:before { content: $fa-var-times-circle-o; } -.#{$fa-css-prefix}-check-circle-o:before { content: $fa-var-check-circle-o; } -.#{$fa-css-prefix}-ban:before { content: $fa-var-ban; } -.#{$fa-css-prefix}-arrow-left:before { content: $fa-var-arrow-left; } -.#{$fa-css-prefix}-arrow-right:before { content: $fa-var-arrow-right; } -.#{$fa-css-prefix}-arrow-up:before { content: $fa-var-arrow-up; } -.#{$fa-css-prefix}-arrow-down:before { content: $fa-var-arrow-down; } -.#{$fa-css-prefix}-mail-forward:before, -.#{$fa-css-prefix}-share:before { content: $fa-var-share; } -.#{$fa-css-prefix}-expand:before { content: $fa-var-expand; } -.#{$fa-css-prefix}-compress:before { content: $fa-var-compress; } -.#{$fa-css-prefix}-plus:before { content: $fa-var-plus; } -.#{$fa-css-prefix}-minus:before { content: $fa-var-minus; } -.#{$fa-css-prefix}-asterisk:before { content: $fa-var-asterisk; } -.#{$fa-css-prefix}-exclamation-circle:before { content: $fa-var-exclamation-circle; } -.#{$fa-css-prefix}-gift:before { content: $fa-var-gift; } -.#{$fa-css-prefix}-leaf:before { content: $fa-var-leaf; } -.#{$fa-css-prefix}-fire:before { content: $fa-var-fire; } -.#{$fa-css-prefix}-eye:before { content: $fa-var-eye; } -.#{$fa-css-prefix}-eye-slash:before { content: $fa-var-eye-slash; } -.#{$fa-css-prefix}-warning:before, -.#{$fa-css-prefix}-exclamation-triangle:before { content: $fa-var-exclamation-triangle; } -.#{$fa-css-prefix}-plane:before { content: $fa-var-plane; } -.#{$fa-css-prefix}-calendar:before { content: $fa-var-calendar; } -.#{$fa-css-prefix}-random:before { content: $fa-var-random; } -.#{$fa-css-prefix}-comment:before { content: $fa-var-comment; } -.#{$fa-css-prefix}-magnet:before { content: $fa-var-magnet; } -.#{$fa-css-prefix}-chevron-up:before { content: $fa-var-chevron-up; } -.#{$fa-css-prefix}-chevron-down:before { content: $fa-var-chevron-down; } -.#{$fa-css-prefix}-retweet:before { content: $fa-var-retweet; } -.#{$fa-css-prefix}-shopping-cart:before { content: $fa-var-shopping-cart; } -.#{$fa-css-prefix}-folder:before { content: $fa-var-folder; } -.#{$fa-css-prefix}-folder-open:before { content: $fa-var-folder-open; } -.#{$fa-css-prefix}-arrows-v:before { content: $fa-var-arrows-v; } -.#{$fa-css-prefix}-arrows-h:before { content: $fa-var-arrows-h; } -.#{$fa-css-prefix}-bar-chart-o:before, -.#{$fa-css-prefix}-bar-chart:before { content: $fa-var-bar-chart; } -.#{$fa-css-prefix}-twitter-square:before { content: $fa-var-twitter-square; } -.#{$fa-css-prefix}-facebook-square:before { content: $fa-var-facebook-square; } -.#{$fa-css-prefix}-camera-retro:before { content: $fa-var-camera-retro; } -.#{$fa-css-prefix}-key:before { content: $fa-var-key; } -.#{$fa-css-prefix}-gears:before, -.#{$fa-css-prefix}-cogs:before { content: $fa-var-cogs; } -.#{$fa-css-prefix}-comments:before { content: $fa-var-comments; } -.#{$fa-css-prefix}-thumbs-o-up:before { content: $fa-var-thumbs-o-up; } -.#{$fa-css-prefix}-thumbs-o-down:before { content: $fa-var-thumbs-o-down; } -.#{$fa-css-prefix}-star-half:before { content: $fa-var-star-half; } -.#{$fa-css-prefix}-heart-o:before { content: $fa-var-heart-o; } -.#{$fa-css-prefix}-sign-out:before { content: $fa-var-sign-out; } -.#{$fa-css-prefix}-linkedin-square:before { content: $fa-var-linkedin-square; } -.#{$fa-css-prefix}-thumb-tack:before { content: $fa-var-thumb-tack; } -.#{$fa-css-prefix}-external-link:before { content: $fa-var-external-link; } -.#{$fa-css-prefix}-sign-in:before { content: $fa-var-sign-in; } -.#{$fa-css-prefix}-trophy:before { content: $fa-var-trophy; } -.#{$fa-css-prefix}-github-square:before { content: $fa-var-github-square; } -.#{$fa-css-prefix}-upload:before { content: $fa-var-upload; } -.#{$fa-css-prefix}-lemon-o:before { content: $fa-var-lemon-o; } -.#{$fa-css-prefix}-phone:before { content: $fa-var-phone; } -.#{$fa-css-prefix}-square-o:before { content: $fa-var-square-o; } -.#{$fa-css-prefix}-bookmark-o:before { content: $fa-var-bookmark-o; } -.#{$fa-css-prefix}-phone-square:before { content: $fa-var-phone-square; } -.#{$fa-css-prefix}-twitter:before { content: $fa-var-twitter; } -.#{$fa-css-prefix}-facebook-f:before, -.#{$fa-css-prefix}-facebook:before { content: $fa-var-facebook; } -.#{$fa-css-prefix}-github:before { content: $fa-var-github; } -.#{$fa-css-prefix}-unlock:before { content: $fa-var-unlock; } -.#{$fa-css-prefix}-credit-card:before { content: $fa-var-credit-card; } -.#{$fa-css-prefix}-feed:before, -.#{$fa-css-prefix}-rss:before { content: $fa-var-rss; } -.#{$fa-css-prefix}-hdd-o:before { content: $fa-var-hdd-o; } -.#{$fa-css-prefix}-bullhorn:before { content: $fa-var-bullhorn; } -.#{$fa-css-prefix}-bell:before { content: $fa-var-bell; } -.#{$fa-css-prefix}-certificate:before { content: $fa-var-certificate; } -.#{$fa-css-prefix}-hand-o-right:before { content: $fa-var-hand-o-right; } -.#{$fa-css-prefix}-hand-o-left:before { content: $fa-var-hand-o-left; } -.#{$fa-css-prefix}-hand-o-up:before { content: $fa-var-hand-o-up; } -.#{$fa-css-prefix}-hand-o-down:before { content: $fa-var-hand-o-down; } -.#{$fa-css-prefix}-arrow-circle-left:before { content: $fa-var-arrow-circle-left; } -.#{$fa-css-prefix}-arrow-circle-right:before { content: $fa-var-arrow-circle-right; } -.#{$fa-css-prefix}-arrow-circle-up:before { content: $fa-var-arrow-circle-up; } -.#{$fa-css-prefix}-arrow-circle-down:before { content: $fa-var-arrow-circle-down; } -.#{$fa-css-prefix}-globe:before { content: $fa-var-globe; } -.#{$fa-css-prefix}-wrench:before { content: $fa-var-wrench; } -.#{$fa-css-prefix}-tasks:before { content: $fa-var-tasks; } -.#{$fa-css-prefix}-filter:before { content: $fa-var-filter; } -.#{$fa-css-prefix}-briefcase:before { content: $fa-var-briefcase; } -.#{$fa-css-prefix}-arrows-alt:before { content: $fa-var-arrows-alt; } -.#{$fa-css-prefix}-group:before, -.#{$fa-css-prefix}-users:before { content: $fa-var-users; } -.#{$fa-css-prefix}-chain:before, -.#{$fa-css-prefix}-link:before { content: $fa-var-link; } -.#{$fa-css-prefix}-cloud:before { content: $fa-var-cloud; } -.#{$fa-css-prefix}-flask:before { content: $fa-var-flask; } -.#{$fa-css-prefix}-cut:before, -.#{$fa-css-prefix}-scissors:before { content: $fa-var-scissors; } -.#{$fa-css-prefix}-copy:before, -.#{$fa-css-prefix}-files-o:before { content: $fa-var-files-o; } -.#{$fa-css-prefix}-paperclip:before { content: $fa-var-paperclip; } -.#{$fa-css-prefix}-save:before, -.#{$fa-css-prefix}-floppy-o:before { content: $fa-var-floppy-o; } -.#{$fa-css-prefix}-square:before { content: $fa-var-square; } -.#{$fa-css-prefix}-navicon:before, -.#{$fa-css-prefix}-reorder:before, -.#{$fa-css-prefix}-bars:before { content: $fa-var-bars; } -.#{$fa-css-prefix}-list-ul:before { content: $fa-var-list-ul; } -.#{$fa-css-prefix}-list-ol:before { content: $fa-var-list-ol; } -.#{$fa-css-prefix}-strikethrough:before { content: $fa-var-strikethrough; } -.#{$fa-css-prefix}-underline:before { content: $fa-var-underline; } -.#{$fa-css-prefix}-table:before { content: $fa-var-table; } -.#{$fa-css-prefix}-magic:before { content: $fa-var-magic; } -.#{$fa-css-prefix}-truck:before { content: $fa-var-truck; } -.#{$fa-css-prefix}-pinterest:before { content: $fa-var-pinterest; } -.#{$fa-css-prefix}-pinterest-square:before { content: $fa-var-pinterest-square; } -.#{$fa-css-prefix}-google-plus-square:before { content: $fa-var-google-plus-square; } -.#{$fa-css-prefix}-google-plus:before { content: $fa-var-google-plus; } -.#{$fa-css-prefix}-money:before { content: $fa-var-money; } -.#{$fa-css-prefix}-caret-down:before { content: $fa-var-caret-down; } -.#{$fa-css-prefix}-caret-up:before { content: $fa-var-caret-up; } -.#{$fa-css-prefix}-caret-left:before { content: $fa-var-caret-left; } -.#{$fa-css-prefix}-caret-right:before { content: $fa-var-caret-right; } -.#{$fa-css-prefix}-columns:before { content: $fa-var-columns; } -.#{$fa-css-prefix}-unsorted:before, -.#{$fa-css-prefix}-sort:before { content: $fa-var-sort; } -.#{$fa-css-prefix}-sort-down:before, -.#{$fa-css-prefix}-sort-desc:before { content: $fa-var-sort-desc; } -.#{$fa-css-prefix}-sort-up:before, -.#{$fa-css-prefix}-sort-asc:before { content: $fa-var-sort-asc; } -.#{$fa-css-prefix}-envelope:before { content: $fa-var-envelope; } -.#{$fa-css-prefix}-linkedin:before { content: $fa-var-linkedin; } -.#{$fa-css-prefix}-rotate-left:before, -.#{$fa-css-prefix}-undo:before { content: $fa-var-undo; } -.#{$fa-css-prefix}-legal:before, -.#{$fa-css-prefix}-gavel:before { content: $fa-var-gavel; } -.#{$fa-css-prefix}-dashboard:before, -.#{$fa-css-prefix}-tachometer:before { content: $fa-var-tachometer; } -.#{$fa-css-prefix}-comment-o:before { content: $fa-var-comment-o; } -.#{$fa-css-prefix}-comments-o:before { content: $fa-var-comments-o; } -.#{$fa-css-prefix}-flash:before, -.#{$fa-css-prefix}-bolt:before { content: $fa-var-bolt; } -.#{$fa-css-prefix}-sitemap:before { content: $fa-var-sitemap; } -.#{$fa-css-prefix}-umbrella:before { content: $fa-var-umbrella; } -.#{$fa-css-prefix}-paste:before, -.#{$fa-css-prefix}-clipboard:before { content: $fa-var-clipboard; } -.#{$fa-css-prefix}-lightbulb-o:before { content: $fa-var-lightbulb-o; } -.#{$fa-css-prefix}-exchange:before { content: $fa-var-exchange; } -.#{$fa-css-prefix}-cloud-download:before { content: $fa-var-cloud-download; } -.#{$fa-css-prefix}-cloud-upload:before { content: $fa-var-cloud-upload; } -.#{$fa-css-prefix}-user-md:before { content: $fa-var-user-md; } -.#{$fa-css-prefix}-stethoscope:before { content: $fa-var-stethoscope; } -.#{$fa-css-prefix}-suitcase:before { content: $fa-var-suitcase; } -.#{$fa-css-prefix}-bell-o:before { content: $fa-var-bell-o; } -.#{$fa-css-prefix}-coffee:before { content: $fa-var-coffee; } -.#{$fa-css-prefix}-cutlery:before { content: $fa-var-cutlery; } -.#{$fa-css-prefix}-file-text-o:before { content: $fa-var-file-text-o; } -.#{$fa-css-prefix}-building-o:before { content: $fa-var-building-o; } -.#{$fa-css-prefix}-hospital-o:before { content: $fa-var-hospital-o; } -.#{$fa-css-prefix}-ambulance:before { content: $fa-var-ambulance; } -.#{$fa-css-prefix}-medkit:before { content: $fa-var-medkit; } -.#{$fa-css-prefix}-fighter-jet:before { content: $fa-var-fighter-jet; } -.#{$fa-css-prefix}-beer:before { content: $fa-var-beer; } -.#{$fa-css-prefix}-h-square:before { content: $fa-var-h-square; } -.#{$fa-css-prefix}-plus-square:before { content: $fa-var-plus-square; } -.#{$fa-css-prefix}-angle-double-left:before { content: $fa-var-angle-double-left; } -.#{$fa-css-prefix}-angle-double-right:before { content: $fa-var-angle-double-right; } -.#{$fa-css-prefix}-angle-double-up:before { content: $fa-var-angle-double-up; } -.#{$fa-css-prefix}-angle-double-down:before { content: $fa-var-angle-double-down; } -.#{$fa-css-prefix}-angle-left:before { content: $fa-var-angle-left; } -.#{$fa-css-prefix}-angle-right:before { content: $fa-var-angle-right; } -.#{$fa-css-prefix}-angle-up:before { content: $fa-var-angle-up; } -.#{$fa-css-prefix}-angle-down:before { content: $fa-var-angle-down; } -.#{$fa-css-prefix}-desktop:before { content: $fa-var-desktop; } -.#{$fa-css-prefix}-laptop:before { content: $fa-var-laptop; } -.#{$fa-css-prefix}-tablet:before { content: $fa-var-tablet; } -.#{$fa-css-prefix}-mobile-phone:before, -.#{$fa-css-prefix}-mobile:before { content: $fa-var-mobile; } -.#{$fa-css-prefix}-circle-o:before { content: $fa-var-circle-o; } -.#{$fa-css-prefix}-quote-left:before { content: $fa-var-quote-left; } -.#{$fa-css-prefix}-quote-right:before { content: $fa-var-quote-right; } -.#{$fa-css-prefix}-spinner:before { content: $fa-var-spinner; } -.#{$fa-css-prefix}-circle:before { content: $fa-var-circle; } -.#{$fa-css-prefix}-mail-reply:before, -.#{$fa-css-prefix}-reply:before { content: $fa-var-reply; } -.#{$fa-css-prefix}-github-alt:before { content: $fa-var-github-alt; } -.#{$fa-css-prefix}-folder-o:before { content: $fa-var-folder-o; } -.#{$fa-css-prefix}-folder-open-o:before { content: $fa-var-folder-open-o; } -.#{$fa-css-prefix}-smile-o:before { content: $fa-var-smile-o; } -.#{$fa-css-prefix}-frown-o:before { content: $fa-var-frown-o; } -.#{$fa-css-prefix}-meh-o:before { content: $fa-var-meh-o; } -.#{$fa-css-prefix}-gamepad:before { content: $fa-var-gamepad; } -.#{$fa-css-prefix}-keyboard-o:before { content: $fa-var-keyboard-o; } -.#{$fa-css-prefix}-flag-o:before { content: $fa-var-flag-o; } -.#{$fa-css-prefix}-flag-checkered:before { content: $fa-var-flag-checkered; } -.#{$fa-css-prefix}-terminal:before { content: $fa-var-terminal; } -.#{$fa-css-prefix}-code:before { content: $fa-var-code; } -.#{$fa-css-prefix}-mail-reply-all:before, -.#{$fa-css-prefix}-reply-all:before { content: $fa-var-reply-all; } -.#{$fa-css-prefix}-star-half-empty:before, -.#{$fa-css-prefix}-star-half-full:before, -.#{$fa-css-prefix}-star-half-o:before { content: $fa-var-star-half-o; } -.#{$fa-css-prefix}-location-arrow:before { content: $fa-var-location-arrow; } -.#{$fa-css-prefix}-crop:before { content: $fa-var-crop; } -.#{$fa-css-prefix}-code-fork:before { content: $fa-var-code-fork; } -.#{$fa-css-prefix}-unlink:before, -.#{$fa-css-prefix}-chain-broken:before { content: $fa-var-chain-broken; } -.#{$fa-css-prefix}-question:before { content: $fa-var-question; } -.#{$fa-css-prefix}-info:before { content: $fa-var-info; } -.#{$fa-css-prefix}-exclamation:before { content: $fa-var-exclamation; } -.#{$fa-css-prefix}-superscript:before { content: $fa-var-superscript; } -.#{$fa-css-prefix}-subscript:before { content: $fa-var-subscript; } -.#{$fa-css-prefix}-eraser:before { content: $fa-var-eraser; } -.#{$fa-css-prefix}-puzzle-piece:before { content: $fa-var-puzzle-piece; } -.#{$fa-css-prefix}-microphone:before { content: $fa-var-microphone; } -.#{$fa-css-prefix}-microphone-slash:before { content: $fa-var-microphone-slash; } -.#{$fa-css-prefix}-shield:before { content: $fa-var-shield; } -.#{$fa-css-prefix}-calendar-o:before { content: $fa-var-calendar-o; } -.#{$fa-css-prefix}-fire-extinguisher:before { content: $fa-var-fire-extinguisher; } -.#{$fa-css-prefix}-rocket:before { content: $fa-var-rocket; } -.#{$fa-css-prefix}-maxcdn:before { content: $fa-var-maxcdn; } -.#{$fa-css-prefix}-chevron-circle-left:before { content: $fa-var-chevron-circle-left; } -.#{$fa-css-prefix}-chevron-circle-right:before { content: $fa-var-chevron-circle-right; } -.#{$fa-css-prefix}-chevron-circle-up:before { content: $fa-var-chevron-circle-up; } -.#{$fa-css-prefix}-chevron-circle-down:before { content: $fa-var-chevron-circle-down; } -.#{$fa-css-prefix}-html5:before { content: $fa-var-html5; } -.#{$fa-css-prefix}-css3:before { content: $fa-var-css3; } -.#{$fa-css-prefix}-anchor:before { content: $fa-var-anchor; } -.#{$fa-css-prefix}-unlock-alt:before { content: $fa-var-unlock-alt; } -.#{$fa-css-prefix}-bullseye:before { content: $fa-var-bullseye; } -.#{$fa-css-prefix}-ellipsis-h:before { content: $fa-var-ellipsis-h; } -.#{$fa-css-prefix}-ellipsis-v:before { content: $fa-var-ellipsis-v; } -.#{$fa-css-prefix}-rss-square:before { content: $fa-var-rss-square; } -.#{$fa-css-prefix}-play-circle:before { content: $fa-var-play-circle; } -.#{$fa-css-prefix}-ticket:before { content: $fa-var-ticket; } -.#{$fa-css-prefix}-minus-square:before { content: $fa-var-minus-square; } -.#{$fa-css-prefix}-minus-square-o:before { content: $fa-var-minus-square-o; } -.#{$fa-css-prefix}-level-up:before { content: $fa-var-level-up; } -.#{$fa-css-prefix}-level-down:before { content: $fa-var-level-down; } -.#{$fa-css-prefix}-check-square:before { content: $fa-var-check-square; } -.#{$fa-css-prefix}-pencil-square:before { content: $fa-var-pencil-square; } -.#{$fa-css-prefix}-external-link-square:before { content: $fa-var-external-link-square; } -.#{$fa-css-prefix}-share-square:before { content: $fa-var-share-square; } -.#{$fa-css-prefix}-compass:before { content: $fa-var-compass; } -.#{$fa-css-prefix}-toggle-down:before, -.#{$fa-css-prefix}-caret-square-o-down:before { content: $fa-var-caret-square-o-down; } -.#{$fa-css-prefix}-toggle-up:before, -.#{$fa-css-prefix}-caret-square-o-up:before { content: $fa-var-caret-square-o-up; } -.#{$fa-css-prefix}-toggle-right:before, -.#{$fa-css-prefix}-caret-square-o-right:before { content: $fa-var-caret-square-o-right; } -.#{$fa-css-prefix}-euro:before, -.#{$fa-css-prefix}-eur:before { content: $fa-var-eur; } -.#{$fa-css-prefix}-gbp:before { content: $fa-var-gbp; } -.#{$fa-css-prefix}-dollar:before, -.#{$fa-css-prefix}-usd:before { content: $fa-var-usd; } -.#{$fa-css-prefix}-rupee:before, -.#{$fa-css-prefix}-inr:before { content: $fa-var-inr; } -.#{$fa-css-prefix}-cny:before, -.#{$fa-css-prefix}-rmb:before, -.#{$fa-css-prefix}-yen:before, -.#{$fa-css-prefix}-jpy:before { content: $fa-var-jpy; } -.#{$fa-css-prefix}-ruble:before, -.#{$fa-css-prefix}-rouble:before, -.#{$fa-css-prefix}-rub:before { content: $fa-var-rub; } -.#{$fa-css-prefix}-won:before, -.#{$fa-css-prefix}-krw:before { content: $fa-var-krw; } -.#{$fa-css-prefix}-bitcoin:before, -.#{$fa-css-prefix}-btc:before { content: $fa-var-btc; } -.#{$fa-css-prefix}-file:before { content: $fa-var-file; } -.#{$fa-css-prefix}-file-text:before { content: $fa-var-file-text; } -.#{$fa-css-prefix}-sort-alpha-asc:before { content: $fa-var-sort-alpha-asc; } -.#{$fa-css-prefix}-sort-alpha-desc:before { content: $fa-var-sort-alpha-desc; } -.#{$fa-css-prefix}-sort-amount-asc:before { content: $fa-var-sort-amount-asc; } -.#{$fa-css-prefix}-sort-amount-desc:before { content: $fa-var-sort-amount-desc; } -.#{$fa-css-prefix}-sort-numeric-asc:before { content: $fa-var-sort-numeric-asc; } -.#{$fa-css-prefix}-sort-numeric-desc:before { content: $fa-var-sort-numeric-desc; } -.#{$fa-css-prefix}-thumbs-up:before { content: $fa-var-thumbs-up; } -.#{$fa-css-prefix}-thumbs-down:before { content: $fa-var-thumbs-down; } -.#{$fa-css-prefix}-youtube-square:before { content: $fa-var-youtube-square; } -.#{$fa-css-prefix}-youtube:before { content: $fa-var-youtube; } -.#{$fa-css-prefix}-xing:before { content: $fa-var-xing; } -.#{$fa-css-prefix}-xing-square:before { content: $fa-var-xing-square; } -.#{$fa-css-prefix}-youtube-play:before { content: $fa-var-youtube-play; } -.#{$fa-css-prefix}-dropbox:before { content: $fa-var-dropbox; } -.#{$fa-css-prefix}-stack-overflow:before { content: $fa-var-stack-overflow; } -.#{$fa-css-prefix}-instagram:before { content: $fa-var-instagram; } -.#{$fa-css-prefix}-flickr:before { content: $fa-var-flickr; } -.#{$fa-css-prefix}-adn:before { content: $fa-var-adn; } -.#{$fa-css-prefix}-bitbucket:before { content: $fa-var-bitbucket; } -.#{$fa-css-prefix}-bitbucket-square:before { content: $fa-var-bitbucket-square; } -.#{$fa-css-prefix}-tumblr:before { content: $fa-var-tumblr; } -.#{$fa-css-prefix}-tumblr-square:before { content: $fa-var-tumblr-square; } -.#{$fa-css-prefix}-long-arrow-down:before { content: $fa-var-long-arrow-down; } -.#{$fa-css-prefix}-long-arrow-up:before { content: $fa-var-long-arrow-up; } -.#{$fa-css-prefix}-long-arrow-left:before { content: $fa-var-long-arrow-left; } -.#{$fa-css-prefix}-long-arrow-right:before { content: $fa-var-long-arrow-right; } -.#{$fa-css-prefix}-apple:before { content: $fa-var-apple; } -.#{$fa-css-prefix}-windows:before { content: $fa-var-windows; } -.#{$fa-css-prefix}-android:before { content: $fa-var-android; } -.#{$fa-css-prefix}-linux:before { content: $fa-var-linux; } -.#{$fa-css-prefix}-dribbble:before { content: $fa-var-dribbble; } -.#{$fa-css-prefix}-skype:before { content: $fa-var-skype; } -.#{$fa-css-prefix}-foursquare:before { content: $fa-var-foursquare; } -.#{$fa-css-prefix}-trello:before { content: $fa-var-trello; } -.#{$fa-css-prefix}-female:before { content: $fa-var-female; } -.#{$fa-css-prefix}-male:before { content: $fa-var-male; } -.#{$fa-css-prefix}-gittip:before, -.#{$fa-css-prefix}-gratipay:before { content: $fa-var-gratipay; } -.#{$fa-css-prefix}-sun-o:before { content: $fa-var-sun-o; } -.#{$fa-css-prefix}-moon-o:before { content: $fa-var-moon-o; } -.#{$fa-css-prefix}-archive:before { content: $fa-var-archive; } -.#{$fa-css-prefix}-bug:before { content: $fa-var-bug; } -.#{$fa-css-prefix}-vk:before { content: $fa-var-vk; } -.#{$fa-css-prefix}-weibo:before { content: $fa-var-weibo; } -.#{$fa-css-prefix}-renren:before { content: $fa-var-renren; } -.#{$fa-css-prefix}-pagelines:before { content: $fa-var-pagelines; } -.#{$fa-css-prefix}-stack-exchange:before { content: $fa-var-stack-exchange; } -.#{$fa-css-prefix}-arrow-circle-o-right:before { content: $fa-var-arrow-circle-o-right; } -.#{$fa-css-prefix}-arrow-circle-o-left:before { content: $fa-var-arrow-circle-o-left; } -.#{$fa-css-prefix}-toggle-left:before, -.#{$fa-css-prefix}-caret-square-o-left:before { content: $fa-var-caret-square-o-left; } -.#{$fa-css-prefix}-dot-circle-o:before { content: $fa-var-dot-circle-o; } -.#{$fa-css-prefix}-wheelchair:before { content: $fa-var-wheelchair; } -.#{$fa-css-prefix}-vimeo-square:before { content: $fa-var-vimeo-square; } -.#{$fa-css-prefix}-turkish-lira:before, -.#{$fa-css-prefix}-try:before { content: $fa-var-try; } -.#{$fa-css-prefix}-plus-square-o:before { content: $fa-var-plus-square-o; } -.#{$fa-css-prefix}-space-shuttle:before { content: $fa-var-space-shuttle; } -.#{$fa-css-prefix}-slack:before { content: $fa-var-slack; } -.#{$fa-css-prefix}-envelope-square:before { content: $fa-var-envelope-square; } -.#{$fa-css-prefix}-wordpress:before { content: $fa-var-wordpress; } -.#{$fa-css-prefix}-openid:before { content: $fa-var-openid; } -.#{$fa-css-prefix}-institution:before, -.#{$fa-css-prefix}-bank:before, -.#{$fa-css-prefix}-university:before { content: $fa-var-university; } -.#{$fa-css-prefix}-mortar-board:before, -.#{$fa-css-prefix}-graduation-cap:before { content: $fa-var-graduation-cap; } -.#{$fa-css-prefix}-yahoo:before { content: $fa-var-yahoo; } -.#{$fa-css-prefix}-google:before { content: $fa-var-google; } -.#{$fa-css-prefix}-reddit:before { content: $fa-var-reddit; } -.#{$fa-css-prefix}-reddit-square:before { content: $fa-var-reddit-square; } -.#{$fa-css-prefix}-stumbleupon-circle:before { content: $fa-var-stumbleupon-circle; } -.#{$fa-css-prefix}-stumbleupon:before { content: $fa-var-stumbleupon; } -.#{$fa-css-prefix}-delicious:before { content: $fa-var-delicious; } -.#{$fa-css-prefix}-digg:before { content: $fa-var-digg; } -.#{$fa-css-prefix}-pied-piper-pp:before { content: $fa-var-pied-piper-pp; } -.#{$fa-css-prefix}-pied-piper-alt:before { content: $fa-var-pied-piper-alt; } -.#{$fa-css-prefix}-drupal:before { content: $fa-var-drupal; } -.#{$fa-css-prefix}-joomla:before { content: $fa-var-joomla; } -.#{$fa-css-prefix}-language:before { content: $fa-var-language; } -.#{$fa-css-prefix}-fax:before { content: $fa-var-fax; } -.#{$fa-css-prefix}-building:before { content: $fa-var-building; } -.#{$fa-css-prefix}-child:before { content: $fa-var-child; } -.#{$fa-css-prefix}-paw:before { content: $fa-var-paw; } -.#{$fa-css-prefix}-spoon:before { content: $fa-var-spoon; } -.#{$fa-css-prefix}-cube:before { content: $fa-var-cube; } -.#{$fa-css-prefix}-cubes:before { content: $fa-var-cubes; } -.#{$fa-css-prefix}-behance:before { content: $fa-var-behance; } -.#{$fa-css-prefix}-behance-square:before { content: $fa-var-behance-square; } -.#{$fa-css-prefix}-steam:before { content: $fa-var-steam; } -.#{$fa-css-prefix}-steam-square:before { content: $fa-var-steam-square; } -.#{$fa-css-prefix}-recycle:before { content: $fa-var-recycle; } -.#{$fa-css-prefix}-automobile:before, -.#{$fa-css-prefix}-car:before { content: $fa-var-car; } -.#{$fa-css-prefix}-cab:before, -.#{$fa-css-prefix}-taxi:before { content: $fa-var-taxi; } -.#{$fa-css-prefix}-tree:before { content: $fa-var-tree; } -.#{$fa-css-prefix}-spotify:before { content: $fa-var-spotify; } -.#{$fa-css-prefix}-deviantart:before { content: $fa-var-deviantart; } -.#{$fa-css-prefix}-soundcloud:before { content: $fa-var-soundcloud; } -.#{$fa-css-prefix}-database:before { content: $fa-var-database; } -.#{$fa-css-prefix}-file-pdf-o:before { content: $fa-var-file-pdf-o; } -.#{$fa-css-prefix}-file-word-o:before { content: $fa-var-file-word-o; } -.#{$fa-css-prefix}-file-excel-o:before { content: $fa-var-file-excel-o; } -.#{$fa-css-prefix}-file-powerpoint-o:before { content: $fa-var-file-powerpoint-o; } -.#{$fa-css-prefix}-file-photo-o:before, -.#{$fa-css-prefix}-file-picture-o:before, -.#{$fa-css-prefix}-file-image-o:before { content: $fa-var-file-image-o; } -.#{$fa-css-prefix}-file-zip-o:before, -.#{$fa-css-prefix}-file-archive-o:before { content: $fa-var-file-archive-o; } -.#{$fa-css-prefix}-file-sound-o:before, -.#{$fa-css-prefix}-file-audio-o:before { content: $fa-var-file-audio-o; } -.#{$fa-css-prefix}-file-movie-o:before, -.#{$fa-css-prefix}-file-video-o:before { content: $fa-var-file-video-o; } -.#{$fa-css-prefix}-file-code-o:before { content: $fa-var-file-code-o; } -.#{$fa-css-prefix}-vine:before { content: $fa-var-vine; } -.#{$fa-css-prefix}-codepen:before { content: $fa-var-codepen; } -.#{$fa-css-prefix}-jsfiddle:before { content: $fa-var-jsfiddle; } -.#{$fa-css-prefix}-life-bouy:before, -.#{$fa-css-prefix}-life-buoy:before, -.#{$fa-css-prefix}-life-saver:before, -.#{$fa-css-prefix}-support:before, -.#{$fa-css-prefix}-life-ring:before { content: $fa-var-life-ring; } -.#{$fa-css-prefix}-circle-o-notch:before { content: $fa-var-circle-o-notch; } -.#{$fa-css-prefix}-ra:before, -.#{$fa-css-prefix}-resistance:before, -.#{$fa-css-prefix}-rebel:before { content: $fa-var-rebel; } -.#{$fa-css-prefix}-ge:before, -.#{$fa-css-prefix}-empire:before { content: $fa-var-empire; } -.#{$fa-css-prefix}-git-square:before { content: $fa-var-git-square; } -.#{$fa-css-prefix}-git:before { content: $fa-var-git; } -.#{$fa-css-prefix}-y-combinator-square:before, -.#{$fa-css-prefix}-yc-square:before, -.#{$fa-css-prefix}-hacker-news:before { content: $fa-var-hacker-news; } -.#{$fa-css-prefix}-tencent-weibo:before { content: $fa-var-tencent-weibo; } -.#{$fa-css-prefix}-qq:before { content: $fa-var-qq; } -.#{$fa-css-prefix}-wechat:before, -.#{$fa-css-prefix}-weixin:before { content: $fa-var-weixin; } -.#{$fa-css-prefix}-send:before, -.#{$fa-css-prefix}-paper-plane:before { content: $fa-var-paper-plane; } -.#{$fa-css-prefix}-send-o:before, -.#{$fa-css-prefix}-paper-plane-o:before { content: $fa-var-paper-plane-o; } -.#{$fa-css-prefix}-history:before { content: $fa-var-history; } -.#{$fa-css-prefix}-circle-thin:before { content: $fa-var-circle-thin; } -.#{$fa-css-prefix}-header:before { content: $fa-var-header; } -.#{$fa-css-prefix}-paragraph:before { content: $fa-var-paragraph; } -.#{$fa-css-prefix}-sliders:before { content: $fa-var-sliders; } -.#{$fa-css-prefix}-share-alt:before { content: $fa-var-share-alt; } -.#{$fa-css-prefix}-share-alt-square:before { content: $fa-var-share-alt-square; } -.#{$fa-css-prefix}-bomb:before { content: $fa-var-bomb; } -.#{$fa-css-prefix}-soccer-ball-o:before, -.#{$fa-css-prefix}-futbol-o:before { content: $fa-var-futbol-o; } -.#{$fa-css-prefix}-tty:before { content: $fa-var-tty; } -.#{$fa-css-prefix}-binoculars:before { content: $fa-var-binoculars; } -.#{$fa-css-prefix}-plug:before { content: $fa-var-plug; } -.#{$fa-css-prefix}-slideshare:before { content: $fa-var-slideshare; } -.#{$fa-css-prefix}-twitch:before { content: $fa-var-twitch; } -.#{$fa-css-prefix}-yelp:before { content: $fa-var-yelp; } -.#{$fa-css-prefix}-newspaper-o:before { content: $fa-var-newspaper-o; } -.#{$fa-css-prefix}-wifi:before { content: $fa-var-wifi; } -.#{$fa-css-prefix}-calculator:before { content: $fa-var-calculator; } -.#{$fa-css-prefix}-paypal:before { content: $fa-var-paypal; } -.#{$fa-css-prefix}-google-wallet:before { content: $fa-var-google-wallet; } -.#{$fa-css-prefix}-cc-visa:before { content: $fa-var-cc-visa; } -.#{$fa-css-prefix}-cc-mastercard:before { content: $fa-var-cc-mastercard; } -.#{$fa-css-prefix}-cc-discover:before { content: $fa-var-cc-discover; } -.#{$fa-css-prefix}-cc-amex:before { content: $fa-var-cc-amex; } -.#{$fa-css-prefix}-cc-paypal:before { content: $fa-var-cc-paypal; } -.#{$fa-css-prefix}-cc-stripe:before { content: $fa-var-cc-stripe; } -.#{$fa-css-prefix}-bell-slash:before { content: $fa-var-bell-slash; } -.#{$fa-css-prefix}-bell-slash-o:before { content: $fa-var-bell-slash-o; } -.#{$fa-css-prefix}-trash:before { content: $fa-var-trash; } -.#{$fa-css-prefix}-copyright:before { content: $fa-var-copyright; } -.#{$fa-css-prefix}-at:before { content: $fa-var-at; } -.#{$fa-css-prefix}-eyedropper:before { content: $fa-var-eyedropper; } -.#{$fa-css-prefix}-paint-brush:before { content: $fa-var-paint-brush; } -.#{$fa-css-prefix}-birthday-cake:before { content: $fa-var-birthday-cake; } -.#{$fa-css-prefix}-area-chart:before { content: $fa-var-area-chart; } -.#{$fa-css-prefix}-pie-chart:before { content: $fa-var-pie-chart; } -.#{$fa-css-prefix}-line-chart:before { content: $fa-var-line-chart; } -.#{$fa-css-prefix}-lastfm:before { content: $fa-var-lastfm; } -.#{$fa-css-prefix}-lastfm-square:before { content: $fa-var-lastfm-square; } -.#{$fa-css-prefix}-toggle-off:before { content: $fa-var-toggle-off; } -.#{$fa-css-prefix}-toggle-on:before { content: $fa-var-toggle-on; } -.#{$fa-css-prefix}-bicycle:before { content: $fa-var-bicycle; } -.#{$fa-css-prefix}-bus:before { content: $fa-var-bus; } -.#{$fa-css-prefix}-ioxhost:before { content: $fa-var-ioxhost; } -.#{$fa-css-prefix}-angellist:before { content: $fa-var-angellist; } -.#{$fa-css-prefix}-cc:before { content: $fa-var-cc; } -.#{$fa-css-prefix}-shekel:before, -.#{$fa-css-prefix}-sheqel:before, -.#{$fa-css-prefix}-ils:before { content: $fa-var-ils; } -.#{$fa-css-prefix}-meanpath:before { content: $fa-var-meanpath; } -.#{$fa-css-prefix}-buysellads:before { content: $fa-var-buysellads; } -.#{$fa-css-prefix}-connectdevelop:before { content: $fa-var-connectdevelop; } -.#{$fa-css-prefix}-dashcube:before { content: $fa-var-dashcube; } -.#{$fa-css-prefix}-forumbee:before { content: $fa-var-forumbee; } -.#{$fa-css-prefix}-leanpub:before { content: $fa-var-leanpub; } -.#{$fa-css-prefix}-sellsy:before { content: $fa-var-sellsy; } -.#{$fa-css-prefix}-shirtsinbulk:before { content: $fa-var-shirtsinbulk; } -.#{$fa-css-prefix}-simplybuilt:before { content: $fa-var-simplybuilt; } -.#{$fa-css-prefix}-skyatlas:before { content: $fa-var-skyatlas; } -.#{$fa-css-prefix}-cart-plus:before { content: $fa-var-cart-plus; } -.#{$fa-css-prefix}-cart-arrow-down:before { content: $fa-var-cart-arrow-down; } -.#{$fa-css-prefix}-diamond:before { content: $fa-var-diamond; } -.#{$fa-css-prefix}-ship:before { content: $fa-var-ship; } -.#{$fa-css-prefix}-user-secret:before { content: $fa-var-user-secret; } -.#{$fa-css-prefix}-motorcycle:before { content: $fa-var-motorcycle; } -.#{$fa-css-prefix}-street-view:before { content: $fa-var-street-view; } -.#{$fa-css-prefix}-heartbeat:before { content: $fa-var-heartbeat; } -.#{$fa-css-prefix}-venus:before { content: $fa-var-venus; } -.#{$fa-css-prefix}-mars:before { content: $fa-var-mars; } -.#{$fa-css-prefix}-mercury:before { content: $fa-var-mercury; } -.#{$fa-css-prefix}-intersex:before, -.#{$fa-css-prefix}-transgender:before { content: $fa-var-transgender; } -.#{$fa-css-prefix}-transgender-alt:before { content: $fa-var-transgender-alt; } -.#{$fa-css-prefix}-venus-double:before { content: $fa-var-venus-double; } -.#{$fa-css-prefix}-mars-double:before { content: $fa-var-mars-double; } -.#{$fa-css-prefix}-venus-mars:before { content: $fa-var-venus-mars; } -.#{$fa-css-prefix}-mars-stroke:before { content: $fa-var-mars-stroke; } -.#{$fa-css-prefix}-mars-stroke-v:before { content: $fa-var-mars-stroke-v; } -.#{$fa-css-prefix}-mars-stroke-h:before { content: $fa-var-mars-stroke-h; } -.#{$fa-css-prefix}-neuter:before { content: $fa-var-neuter; } -.#{$fa-css-prefix}-genderless:before { content: $fa-var-genderless; } -.#{$fa-css-prefix}-facebook-official:before { content: $fa-var-facebook-official; } -.#{$fa-css-prefix}-pinterest-p:before { content: $fa-var-pinterest-p; } -.#{$fa-css-prefix}-whatsapp:before { content: $fa-var-whatsapp; } -.#{$fa-css-prefix}-server:before { content: $fa-var-server; } -.#{$fa-css-prefix}-user-plus:before { content: $fa-var-user-plus; } -.#{$fa-css-prefix}-user-times:before { content: $fa-var-user-times; } -.#{$fa-css-prefix}-hotel:before, -.#{$fa-css-prefix}-bed:before { content: $fa-var-bed; } -.#{$fa-css-prefix}-viacoin:before { content: $fa-var-viacoin; } -.#{$fa-css-prefix}-train:before { content: $fa-var-train; } -.#{$fa-css-prefix}-subway:before { content: $fa-var-subway; } -.#{$fa-css-prefix}-medium:before { content: $fa-var-medium; } -.#{$fa-css-prefix}-yc:before, -.#{$fa-css-prefix}-y-combinator:before { content: $fa-var-y-combinator; } -.#{$fa-css-prefix}-optin-monster:before { content: $fa-var-optin-monster; } -.#{$fa-css-prefix}-opencart:before { content: $fa-var-opencart; } -.#{$fa-css-prefix}-expeditedssl:before { content: $fa-var-expeditedssl; } -.#{$fa-css-prefix}-battery-4:before, -.#{$fa-css-prefix}-battery:before, -.#{$fa-css-prefix}-battery-full:before { content: $fa-var-battery-full; } -.#{$fa-css-prefix}-battery-3:before, -.#{$fa-css-prefix}-battery-three-quarters:before { content: $fa-var-battery-three-quarters; } -.#{$fa-css-prefix}-battery-2:before, -.#{$fa-css-prefix}-battery-half:before { content: $fa-var-battery-half; } -.#{$fa-css-prefix}-battery-1:before, -.#{$fa-css-prefix}-battery-quarter:before { content: $fa-var-battery-quarter; } -.#{$fa-css-prefix}-battery-0:before, -.#{$fa-css-prefix}-battery-empty:before { content: $fa-var-battery-empty; } -.#{$fa-css-prefix}-mouse-pointer:before { content: $fa-var-mouse-pointer; } -.#{$fa-css-prefix}-i-cursor:before { content: $fa-var-i-cursor; } -.#{$fa-css-prefix}-object-group:before { content: $fa-var-object-group; } -.#{$fa-css-prefix}-object-ungroup:before { content: $fa-var-object-ungroup; } -.#{$fa-css-prefix}-sticky-note:before { content: $fa-var-sticky-note; } -.#{$fa-css-prefix}-sticky-note-o:before { content: $fa-var-sticky-note-o; } -.#{$fa-css-prefix}-cc-jcb:before { content: $fa-var-cc-jcb; } -.#{$fa-css-prefix}-cc-diners-club:before { content: $fa-var-cc-diners-club; } -.#{$fa-css-prefix}-clone:before { content: $fa-var-clone; } -.#{$fa-css-prefix}-balance-scale:before { content: $fa-var-balance-scale; } -.#{$fa-css-prefix}-hourglass-o:before { content: $fa-var-hourglass-o; } -.#{$fa-css-prefix}-hourglass-1:before, -.#{$fa-css-prefix}-hourglass-start:before { content: $fa-var-hourglass-start; } -.#{$fa-css-prefix}-hourglass-2:before, -.#{$fa-css-prefix}-hourglass-half:before { content: $fa-var-hourglass-half; } -.#{$fa-css-prefix}-hourglass-3:before, -.#{$fa-css-prefix}-hourglass-end:before { content: $fa-var-hourglass-end; } -.#{$fa-css-prefix}-hourglass:before { content: $fa-var-hourglass; } -.#{$fa-css-prefix}-hand-grab-o:before, -.#{$fa-css-prefix}-hand-rock-o:before { content: $fa-var-hand-rock-o; } -.#{$fa-css-prefix}-hand-stop-o:before, -.#{$fa-css-prefix}-hand-paper-o:before { content: $fa-var-hand-paper-o; } -.#{$fa-css-prefix}-hand-scissors-o:before { content: $fa-var-hand-scissors-o; } -.#{$fa-css-prefix}-hand-lizard-o:before { content: $fa-var-hand-lizard-o; } -.#{$fa-css-prefix}-hand-spock-o:before { content: $fa-var-hand-spock-o; } -.#{$fa-css-prefix}-hand-pointer-o:before { content: $fa-var-hand-pointer-o; } -.#{$fa-css-prefix}-hand-peace-o:before { content: $fa-var-hand-peace-o; } -.#{$fa-css-prefix}-trademark:before { content: $fa-var-trademark; } -.#{$fa-css-prefix}-registered:before { content: $fa-var-registered; } -.#{$fa-css-prefix}-creative-commons:before { content: $fa-var-creative-commons; } -.#{$fa-css-prefix}-gg:before { content: $fa-var-gg; } -.#{$fa-css-prefix}-gg-circle:before { content: $fa-var-gg-circle; } -.#{$fa-css-prefix}-tripadvisor:before { content: $fa-var-tripadvisor; } -.#{$fa-css-prefix}-odnoklassniki:before { content: $fa-var-odnoklassniki; } -.#{$fa-css-prefix}-odnoklassniki-square:before { content: $fa-var-odnoklassniki-square; } -.#{$fa-css-prefix}-get-pocket:before { content: $fa-var-get-pocket; } -.#{$fa-css-prefix}-wikipedia-w:before { content: $fa-var-wikipedia-w; } -.#{$fa-css-prefix}-safari:before { content: $fa-var-safari; } -.#{$fa-css-prefix}-chrome:before { content: $fa-var-chrome; } -.#{$fa-css-prefix}-firefox:before { content: $fa-var-firefox; } -.#{$fa-css-prefix}-opera:before { content: $fa-var-opera; } -.#{$fa-css-prefix}-internet-explorer:before { content: $fa-var-internet-explorer; } -.#{$fa-css-prefix}-tv:before, -.#{$fa-css-prefix}-television:before { content: $fa-var-television; } -.#{$fa-css-prefix}-contao:before { content: $fa-var-contao; } -.#{$fa-css-prefix}-500px:before { content: $fa-var-500px; } -.#{$fa-css-prefix}-amazon:before { content: $fa-var-amazon; } -.#{$fa-css-prefix}-calendar-plus-o:before { content: $fa-var-calendar-plus-o; } -.#{$fa-css-prefix}-calendar-minus-o:before { content: $fa-var-calendar-minus-o; } -.#{$fa-css-prefix}-calendar-times-o:before { content: $fa-var-calendar-times-o; } -.#{$fa-css-prefix}-calendar-check-o:before { content: $fa-var-calendar-check-o; } -.#{$fa-css-prefix}-industry:before { content: $fa-var-industry; } -.#{$fa-css-prefix}-map-pin:before { content: $fa-var-map-pin; } -.#{$fa-css-prefix}-map-signs:before { content: $fa-var-map-signs; } -.#{$fa-css-prefix}-map-o:before { content: $fa-var-map-o; } -.#{$fa-css-prefix}-map:before { content: $fa-var-map; } -.#{$fa-css-prefix}-commenting:before { content: $fa-var-commenting; } -.#{$fa-css-prefix}-commenting-o:before { content: $fa-var-commenting-o; } -.#{$fa-css-prefix}-houzz:before { content: $fa-var-houzz; } -.#{$fa-css-prefix}-vimeo:before { content: $fa-var-vimeo; } -.#{$fa-css-prefix}-black-tie:before { content: $fa-var-black-tie; } -.#{$fa-css-prefix}-fonticons:before { content: $fa-var-fonticons; } -.#{$fa-css-prefix}-reddit-alien:before { content: $fa-var-reddit-alien; } -.#{$fa-css-prefix}-edge:before { content: $fa-var-edge; } -.#{$fa-css-prefix}-credit-card-alt:before { content: $fa-var-credit-card-alt; } -.#{$fa-css-prefix}-codiepie:before { content: $fa-var-codiepie; } -.#{$fa-css-prefix}-modx:before { content: $fa-var-modx; } -.#{$fa-css-prefix}-fort-awesome:before { content: $fa-var-fort-awesome; } -.#{$fa-css-prefix}-usb:before { content: $fa-var-usb; } -.#{$fa-css-prefix}-product-hunt:before { content: $fa-var-product-hunt; } -.#{$fa-css-prefix}-mixcloud:before { content: $fa-var-mixcloud; } -.#{$fa-css-prefix}-scribd:before { content: $fa-var-scribd; } -.#{$fa-css-prefix}-pause-circle:before { content: $fa-var-pause-circle; } -.#{$fa-css-prefix}-pause-circle-o:before { content: $fa-var-pause-circle-o; } -.#{$fa-css-prefix}-stop-circle:before { content: $fa-var-stop-circle; } -.#{$fa-css-prefix}-stop-circle-o:before { content: $fa-var-stop-circle-o; } -.#{$fa-css-prefix}-shopping-bag:before { content: $fa-var-shopping-bag; } -.#{$fa-css-prefix}-shopping-basket:before { content: $fa-var-shopping-basket; } -.#{$fa-css-prefix}-hashtag:before { content: $fa-var-hashtag; } -.#{$fa-css-prefix}-bluetooth:before { content: $fa-var-bluetooth; } -.#{$fa-css-prefix}-bluetooth-b:before { content: $fa-var-bluetooth-b; } -.#{$fa-css-prefix}-percent:before { content: $fa-var-percent; } -.#{$fa-css-prefix}-gitlab:before { content: $fa-var-gitlab; } -.#{$fa-css-prefix}-wpbeginner:before { content: $fa-var-wpbeginner; } -.#{$fa-css-prefix}-wpforms:before { content: $fa-var-wpforms; } -.#{$fa-css-prefix}-envira:before { content: $fa-var-envira; } -.#{$fa-css-prefix}-universal-access:before { content: $fa-var-universal-access; } -.#{$fa-css-prefix}-wheelchair-alt:before { content: $fa-var-wheelchair-alt; } -.#{$fa-css-prefix}-question-circle-o:before { content: $fa-var-question-circle-o; } -.#{$fa-css-prefix}-blind:before { content: $fa-var-blind; } -.#{$fa-css-prefix}-audio-description:before { content: $fa-var-audio-description; } -.#{$fa-css-prefix}-volume-control-phone:before { content: $fa-var-volume-control-phone; } -.#{$fa-css-prefix}-braille:before { content: $fa-var-braille; } -.#{$fa-css-prefix}-assistive-listening-systems:before { content: $fa-var-assistive-listening-systems; } -.#{$fa-css-prefix}-asl-interpreting:before, -.#{$fa-css-prefix}-american-sign-language-interpreting:before { content: $fa-var-american-sign-language-interpreting; } -.#{$fa-css-prefix}-deafness:before, -.#{$fa-css-prefix}-hard-of-hearing:before, -.#{$fa-css-prefix}-deaf:before { content: $fa-var-deaf; } -.#{$fa-css-prefix}-glide:before { content: $fa-var-glide; } -.#{$fa-css-prefix}-glide-g:before { content: $fa-var-glide-g; } -.#{$fa-css-prefix}-signing:before, -.#{$fa-css-prefix}-sign-language:before { content: $fa-var-sign-language; } -.#{$fa-css-prefix}-low-vision:before { content: $fa-var-low-vision; } -.#{$fa-css-prefix}-viadeo:before { content: $fa-var-viadeo; } -.#{$fa-css-prefix}-viadeo-square:before { content: $fa-var-viadeo-square; } -.#{$fa-css-prefix}-snapchat:before { content: $fa-var-snapchat; } -.#{$fa-css-prefix}-snapchat-ghost:before { content: $fa-var-snapchat-ghost; } -.#{$fa-css-prefix}-snapchat-square:before { content: $fa-var-snapchat-square; } -.#{$fa-css-prefix}-pied-piper:before { content: $fa-var-pied-piper; } -.#{$fa-css-prefix}-first-order:before { content: $fa-var-first-order; } -.#{$fa-css-prefix}-yoast:before { content: $fa-var-yoast; } -.#{$fa-css-prefix}-themeisle:before { content: $fa-var-themeisle; } -.#{$fa-css-prefix}-google-plus-circle:before, -.#{$fa-css-prefix}-google-plus-official:before { content: $fa-var-google-plus-official; } -.#{$fa-css-prefix}-fa:before, -.#{$fa-css-prefix}-font-awesome:before { content: $fa-var-font-awesome; } -.#{$fa-css-prefix}-handshake-o:before { content: $fa-var-handshake-o; } -.#{$fa-css-prefix}-envelope-open:before { content: $fa-var-envelope-open; } -.#{$fa-css-prefix}-envelope-open-o:before { content: $fa-var-envelope-open-o; } -.#{$fa-css-prefix}-linode:before { content: $fa-var-linode; } -.#{$fa-css-prefix}-address-book:before { content: $fa-var-address-book; } -.#{$fa-css-prefix}-address-book-o:before { content: $fa-var-address-book-o; } -.#{$fa-css-prefix}-vcard:before, -.#{$fa-css-prefix}-address-card:before { content: $fa-var-address-card; } -.#{$fa-css-prefix}-vcard-o:before, -.#{$fa-css-prefix}-address-card-o:before { content: $fa-var-address-card-o; } -.#{$fa-css-prefix}-user-circle:before { content: $fa-var-user-circle; } -.#{$fa-css-prefix}-user-circle-o:before { content: $fa-var-user-circle-o; } -.#{$fa-css-prefix}-user-o:before { content: $fa-var-user-o; } -.#{$fa-css-prefix}-id-badge:before { content: $fa-var-id-badge; } -.#{$fa-css-prefix}-drivers-license:before, -.#{$fa-css-prefix}-id-card:before { content: $fa-var-id-card; } -.#{$fa-css-prefix}-drivers-license-o:before, -.#{$fa-css-prefix}-id-card-o:before { content: $fa-var-id-card-o; } -.#{$fa-css-prefix}-quora:before { content: $fa-var-quora; } -.#{$fa-css-prefix}-free-code-camp:before { content: $fa-var-free-code-camp; } -.#{$fa-css-prefix}-telegram:before { content: $fa-var-telegram; } -.#{$fa-css-prefix}-thermometer-4:before, -.#{$fa-css-prefix}-thermometer:before, -.#{$fa-css-prefix}-thermometer-full:before { content: $fa-var-thermometer-full; } -.#{$fa-css-prefix}-thermometer-3:before, -.#{$fa-css-prefix}-thermometer-three-quarters:before { content: $fa-var-thermometer-three-quarters; } -.#{$fa-css-prefix}-thermometer-2:before, -.#{$fa-css-prefix}-thermometer-half:before { content: $fa-var-thermometer-half; } -.#{$fa-css-prefix}-thermometer-1:before, -.#{$fa-css-prefix}-thermometer-quarter:before { content: $fa-var-thermometer-quarter; } -.#{$fa-css-prefix}-thermometer-0:before, -.#{$fa-css-prefix}-thermometer-empty:before { content: $fa-var-thermometer-empty; } -.#{$fa-css-prefix}-shower:before { content: $fa-var-shower; } -.#{$fa-css-prefix}-bathtub:before, -.#{$fa-css-prefix}-s15:before, -.#{$fa-css-prefix}-bath:before { content: $fa-var-bath; } -.#{$fa-css-prefix}-podcast:before { content: $fa-var-podcast; } -.#{$fa-css-prefix}-window-maximize:before { content: $fa-var-window-maximize; } -.#{$fa-css-prefix}-window-minimize:before { content: $fa-var-window-minimize; } -.#{$fa-css-prefix}-window-restore:before { content: $fa-var-window-restore; } -.#{$fa-css-prefix}-times-rectangle:before, -.#{$fa-css-prefix}-window-close:before { content: $fa-var-window-close; } -.#{$fa-css-prefix}-times-rectangle-o:before, -.#{$fa-css-prefix}-window-close-o:before { content: $fa-var-window-close-o; } -.#{$fa-css-prefix}-bandcamp:before { content: $fa-var-bandcamp; } -.#{$fa-css-prefix}-grav:before { content: $fa-var-grav; } -.#{$fa-css-prefix}-etsy:before { content: $fa-var-etsy; } -.#{$fa-css-prefix}-imdb:before { content: $fa-var-imdb; } -.#{$fa-css-prefix}-ravelry:before { content: $fa-var-ravelry; } -.#{$fa-css-prefix}-eercast:before { content: $fa-var-eercast; } -.#{$fa-css-prefix}-microchip:before { content: $fa-var-microchip; } -.#{$fa-css-prefix}-snowflake-o:before { content: $fa-var-snowflake-o; } -.#{$fa-css-prefix}-superpowers:before { content: $fa-var-superpowers; } -.#{$fa-css-prefix}-wpexplorer:before { content: $fa-var-wpexplorer; } -.#{$fa-css-prefix}-meetup:before { content: $fa-var-meetup; } diff --git a/netbox/project-static/font-awesome-4.7.0/scss/_larger.scss b/netbox/project-static/font-awesome-4.7.0/scss/_larger.scss deleted file mode 100644 index 41e9a8184a..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/scss/_larger.scss +++ /dev/null @@ -1,13 +0,0 @@ -// Icon Sizes -// ------------------------- - -/* makes the font 33% larger relative to the icon container */ -.#{$fa-css-prefix}-lg { - font-size: (4em / 3); - line-height: (3em / 4); - vertical-align: -15%; -} -.#{$fa-css-prefix}-2x { font-size: 2em; } -.#{$fa-css-prefix}-3x { font-size: 3em; } -.#{$fa-css-prefix}-4x { font-size: 4em; } -.#{$fa-css-prefix}-5x { font-size: 5em; } diff --git a/netbox/project-static/font-awesome-4.7.0/scss/_list.scss b/netbox/project-static/font-awesome-4.7.0/scss/_list.scss deleted file mode 100644 index 7d1e4d54d6..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/scss/_list.scss +++ /dev/null @@ -1,19 +0,0 @@ -// List Icons -// ------------------------- - -.#{$fa-css-prefix}-ul { - padding-left: 0; - margin-left: $fa-li-width; - list-style-type: none; - > li { position: relative; } -} -.#{$fa-css-prefix}-li { - position: absolute; - left: -$fa-li-width; - width: $fa-li-width; - top: (2em / 14); - text-align: center; - &.#{$fa-css-prefix}-lg { - left: -$fa-li-width + (4em / 14); - } -} diff --git a/netbox/project-static/font-awesome-4.7.0/scss/_mixins.scss b/netbox/project-static/font-awesome-4.7.0/scss/_mixins.scss deleted file mode 100644 index c3bbd5745d..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/scss/_mixins.scss +++ /dev/null @@ -1,60 +0,0 @@ -// Mixins -// -------------------------- - -@mixin fa-icon() { - display: inline-block; - font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration - font-size: inherit; // can't have font-size inherit on line above, so need to override - text-rendering: auto; // optimizelegibility throws things off #1094 - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -} - -@mixin fa-icon-rotate($degrees, $rotation) { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})"; - -webkit-transform: rotate($degrees); - -ms-transform: rotate($degrees); - transform: rotate($degrees); -} - -@mixin fa-icon-flip($horiz, $vert, $rotation) { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)"; - -webkit-transform: scale($horiz, $vert); - -ms-transform: scale($horiz, $vert); - transform: scale($horiz, $vert); -} - - -// Only display content to screen readers. A la Bootstrap 4. -// -// See: http://a11yproject.com/posts/how-to-hide-content/ - -@mixin sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0,0,0,0); - border: 0; -} - -// Use in conjunction with .sr-only to only display content when it's focused. -// -// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 -// -// Credit: HTML5 Boilerplate - -@mixin sr-only-focusable { - &:active, - &:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; - } -} diff --git a/netbox/project-static/font-awesome-4.7.0/scss/_path.scss b/netbox/project-static/font-awesome-4.7.0/scss/_path.scss deleted file mode 100644 index bb457c23a8..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/scss/_path.scss +++ /dev/null @@ -1,15 +0,0 @@ -/* FONT PATH - * -------------------------- */ - -@font-face { - font-family: 'FontAwesome'; - src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); - src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), - url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), - url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), - url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), - url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); -// src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts - font-weight: normal; - font-style: normal; -} diff --git a/netbox/project-static/font-awesome-4.7.0/scss/_rotated-flipped.scss b/netbox/project-static/font-awesome-4.7.0/scss/_rotated-flipped.scss deleted file mode 100644 index a3558fd09c..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/scss/_rotated-flipped.scss +++ /dev/null @@ -1,20 +0,0 @@ -// Rotated & Flipped Icons -// ------------------------- - -.#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } -.#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } -.#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } - -.#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } -.#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } - -// Hook for IE8-9 -// ------------------------- - -:root .#{$fa-css-prefix}-rotate-90, -:root .#{$fa-css-prefix}-rotate-180, -:root .#{$fa-css-prefix}-rotate-270, -:root .#{$fa-css-prefix}-flip-horizontal, -:root .#{$fa-css-prefix}-flip-vertical { - filter: none; -} diff --git a/netbox/project-static/font-awesome-4.7.0/scss/_screen-reader.scss b/netbox/project-static/font-awesome-4.7.0/scss/_screen-reader.scss deleted file mode 100644 index 637426f0da..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/scss/_screen-reader.scss +++ /dev/null @@ -1,5 +0,0 @@ -// Screen Readers -// ------------------------- - -.sr-only { @include sr-only(); } -.sr-only-focusable { @include sr-only-focusable(); } diff --git a/netbox/project-static/font-awesome-4.7.0/scss/_stacked.scss b/netbox/project-static/font-awesome-4.7.0/scss/_stacked.scss deleted file mode 100644 index aef7403660..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/scss/_stacked.scss +++ /dev/null @@ -1,20 +0,0 @@ -// Stacked Icons -// ------------------------- - -.#{$fa-css-prefix}-stack { - position: relative; - display: inline-block; - width: 2em; - height: 2em; - line-height: 2em; - vertical-align: middle; -} -.#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { - position: absolute; - left: 0; - width: 100%; - text-align: center; -} -.#{$fa-css-prefix}-stack-1x { line-height: inherit; } -.#{$fa-css-prefix}-stack-2x { font-size: 2em; } -.#{$fa-css-prefix}-inverse { color: $fa-inverse; } diff --git a/netbox/project-static/font-awesome-4.7.0/scss/_variables.scss b/netbox/project-static/font-awesome-4.7.0/scss/_variables.scss deleted file mode 100644 index 498fc4a087..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/scss/_variables.scss +++ /dev/null @@ -1,800 +0,0 @@ -// Variables -// -------------------------- - -$fa-font-path: "../fonts" !default; -$fa-font-size-base: 14px !default; -$fa-line-height-base: 1 !default; -//$fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts" !default; // for referencing Bootstrap CDN font files directly -$fa-css-prefix: fa !default; -$fa-version: "4.7.0" !default; -$fa-border-color: #eee !default; -$fa-inverse: #fff !default; -$fa-li-width: (30em / 14) !default; - -$fa-var-500px: "\f26e"; -$fa-var-address-book: "\f2b9"; -$fa-var-address-book-o: "\f2ba"; -$fa-var-address-card: "\f2bb"; -$fa-var-address-card-o: "\f2bc"; -$fa-var-adjust: "\f042"; -$fa-var-adn: "\f170"; -$fa-var-align-center: "\f037"; -$fa-var-align-justify: "\f039"; -$fa-var-align-left: "\f036"; -$fa-var-align-right: "\f038"; -$fa-var-amazon: "\f270"; -$fa-var-ambulance: "\f0f9"; -$fa-var-american-sign-language-interpreting: "\f2a3"; -$fa-var-anchor: "\f13d"; -$fa-var-android: "\f17b"; -$fa-var-angellist: "\f209"; -$fa-var-angle-double-down: "\f103"; -$fa-var-angle-double-left: "\f100"; -$fa-var-angle-double-right: "\f101"; -$fa-var-angle-double-up: "\f102"; -$fa-var-angle-down: "\f107"; -$fa-var-angle-left: "\f104"; -$fa-var-angle-right: "\f105"; -$fa-var-angle-up: "\f106"; -$fa-var-apple: "\f179"; -$fa-var-archive: "\f187"; -$fa-var-area-chart: "\f1fe"; -$fa-var-arrow-circle-down: "\f0ab"; -$fa-var-arrow-circle-left: "\f0a8"; -$fa-var-arrow-circle-o-down: "\f01a"; -$fa-var-arrow-circle-o-left: "\f190"; -$fa-var-arrow-circle-o-right: "\f18e"; -$fa-var-arrow-circle-o-up: "\f01b"; -$fa-var-arrow-circle-right: "\f0a9"; -$fa-var-arrow-circle-up: "\f0aa"; -$fa-var-arrow-down: "\f063"; -$fa-var-arrow-left: "\f060"; -$fa-var-arrow-right: "\f061"; -$fa-var-arrow-up: "\f062"; -$fa-var-arrows: "\f047"; -$fa-var-arrows-alt: "\f0b2"; -$fa-var-arrows-h: "\f07e"; -$fa-var-arrows-v: "\f07d"; -$fa-var-asl-interpreting: "\f2a3"; -$fa-var-assistive-listening-systems: "\f2a2"; -$fa-var-asterisk: "\f069"; -$fa-var-at: "\f1fa"; -$fa-var-audio-description: "\f29e"; -$fa-var-automobile: "\f1b9"; -$fa-var-backward: "\f04a"; -$fa-var-balance-scale: "\f24e"; -$fa-var-ban: "\f05e"; -$fa-var-bandcamp: "\f2d5"; -$fa-var-bank: "\f19c"; -$fa-var-bar-chart: "\f080"; -$fa-var-bar-chart-o: "\f080"; -$fa-var-barcode: "\f02a"; -$fa-var-bars: "\f0c9"; -$fa-var-bath: "\f2cd"; -$fa-var-bathtub: "\f2cd"; -$fa-var-battery: "\f240"; -$fa-var-battery-0: "\f244"; -$fa-var-battery-1: "\f243"; -$fa-var-battery-2: "\f242"; -$fa-var-battery-3: "\f241"; -$fa-var-battery-4: "\f240"; -$fa-var-battery-empty: "\f244"; -$fa-var-battery-full: "\f240"; -$fa-var-battery-half: "\f242"; -$fa-var-battery-quarter: "\f243"; -$fa-var-battery-three-quarters: "\f241"; -$fa-var-bed: "\f236"; -$fa-var-beer: "\f0fc"; -$fa-var-behance: "\f1b4"; -$fa-var-behance-square: "\f1b5"; -$fa-var-bell: "\f0f3"; -$fa-var-bell-o: "\f0a2"; -$fa-var-bell-slash: "\f1f6"; -$fa-var-bell-slash-o: "\f1f7"; -$fa-var-bicycle: "\f206"; -$fa-var-binoculars: "\f1e5"; -$fa-var-birthday-cake: "\f1fd"; -$fa-var-bitbucket: "\f171"; -$fa-var-bitbucket-square: "\f172"; -$fa-var-bitcoin: "\f15a"; -$fa-var-black-tie: "\f27e"; -$fa-var-blind: "\f29d"; -$fa-var-bluetooth: "\f293"; -$fa-var-bluetooth-b: "\f294"; -$fa-var-bold: "\f032"; -$fa-var-bolt: "\f0e7"; -$fa-var-bomb: "\f1e2"; -$fa-var-book: "\f02d"; -$fa-var-bookmark: "\f02e"; -$fa-var-bookmark-o: "\f097"; -$fa-var-braille: "\f2a1"; -$fa-var-briefcase: "\f0b1"; -$fa-var-btc: "\f15a"; -$fa-var-bug: "\f188"; -$fa-var-building: "\f1ad"; -$fa-var-building-o: "\f0f7"; -$fa-var-bullhorn: "\f0a1"; -$fa-var-bullseye: "\f140"; -$fa-var-bus: "\f207"; -$fa-var-buysellads: "\f20d"; -$fa-var-cab: "\f1ba"; -$fa-var-calculator: "\f1ec"; -$fa-var-calendar: "\f073"; -$fa-var-calendar-check-o: "\f274"; -$fa-var-calendar-minus-o: "\f272"; -$fa-var-calendar-o: "\f133"; -$fa-var-calendar-plus-o: "\f271"; -$fa-var-calendar-times-o: "\f273"; -$fa-var-camera: "\f030"; -$fa-var-camera-retro: "\f083"; -$fa-var-car: "\f1b9"; -$fa-var-caret-down: "\f0d7"; -$fa-var-caret-left: "\f0d9"; -$fa-var-caret-right: "\f0da"; -$fa-var-caret-square-o-down: "\f150"; -$fa-var-caret-square-o-left: "\f191"; -$fa-var-caret-square-o-right: "\f152"; -$fa-var-caret-square-o-up: "\f151"; -$fa-var-caret-up: "\f0d8"; -$fa-var-cart-arrow-down: "\f218"; -$fa-var-cart-plus: "\f217"; -$fa-var-cc: "\f20a"; -$fa-var-cc-amex: "\f1f3"; -$fa-var-cc-diners-club: "\f24c"; -$fa-var-cc-discover: "\f1f2"; -$fa-var-cc-jcb: "\f24b"; -$fa-var-cc-mastercard: "\f1f1"; -$fa-var-cc-paypal: "\f1f4"; -$fa-var-cc-stripe: "\f1f5"; -$fa-var-cc-visa: "\f1f0"; -$fa-var-certificate: "\f0a3"; -$fa-var-chain: "\f0c1"; -$fa-var-chain-broken: "\f127"; -$fa-var-check: "\f00c"; -$fa-var-check-circle: "\f058"; -$fa-var-check-circle-o: "\f05d"; -$fa-var-check-square: "\f14a"; -$fa-var-check-square-o: "\f046"; -$fa-var-chevron-circle-down: "\f13a"; -$fa-var-chevron-circle-left: "\f137"; -$fa-var-chevron-circle-right: "\f138"; -$fa-var-chevron-circle-up: "\f139"; -$fa-var-chevron-down: "\f078"; -$fa-var-chevron-left: "\f053"; -$fa-var-chevron-right: "\f054"; -$fa-var-chevron-up: "\f077"; -$fa-var-child: "\f1ae"; -$fa-var-chrome: "\f268"; -$fa-var-circle: "\f111"; -$fa-var-circle-o: "\f10c"; -$fa-var-circle-o-notch: "\f1ce"; -$fa-var-circle-thin: "\f1db"; -$fa-var-clipboard: "\f0ea"; -$fa-var-clock-o: "\f017"; -$fa-var-clone: "\f24d"; -$fa-var-close: "\f00d"; -$fa-var-cloud: "\f0c2"; -$fa-var-cloud-download: "\f0ed"; -$fa-var-cloud-upload: "\f0ee"; -$fa-var-cny: "\f157"; -$fa-var-code: "\f121"; -$fa-var-code-fork: "\f126"; -$fa-var-codepen: "\f1cb"; -$fa-var-codiepie: "\f284"; -$fa-var-coffee: "\f0f4"; -$fa-var-cog: "\f013"; -$fa-var-cogs: "\f085"; -$fa-var-columns: "\f0db"; -$fa-var-comment: "\f075"; -$fa-var-comment-o: "\f0e5"; -$fa-var-commenting: "\f27a"; -$fa-var-commenting-o: "\f27b"; -$fa-var-comments: "\f086"; -$fa-var-comments-o: "\f0e6"; -$fa-var-compass: "\f14e"; -$fa-var-compress: "\f066"; -$fa-var-connectdevelop: "\f20e"; -$fa-var-contao: "\f26d"; -$fa-var-copy: "\f0c5"; -$fa-var-copyright: "\f1f9"; -$fa-var-creative-commons: "\f25e"; -$fa-var-credit-card: "\f09d"; -$fa-var-credit-card-alt: "\f283"; -$fa-var-crop: "\f125"; -$fa-var-crosshairs: "\f05b"; -$fa-var-css3: "\f13c"; -$fa-var-cube: "\f1b2"; -$fa-var-cubes: "\f1b3"; -$fa-var-cut: "\f0c4"; -$fa-var-cutlery: "\f0f5"; -$fa-var-dashboard: "\f0e4"; -$fa-var-dashcube: "\f210"; -$fa-var-database: "\f1c0"; -$fa-var-deaf: "\f2a4"; -$fa-var-deafness: "\f2a4"; -$fa-var-dedent: "\f03b"; -$fa-var-delicious: "\f1a5"; -$fa-var-desktop: "\f108"; -$fa-var-deviantart: "\f1bd"; -$fa-var-diamond: "\f219"; -$fa-var-digg: "\f1a6"; -$fa-var-dollar: "\f155"; -$fa-var-dot-circle-o: "\f192"; -$fa-var-download: "\f019"; -$fa-var-dribbble: "\f17d"; -$fa-var-drivers-license: "\f2c2"; -$fa-var-drivers-license-o: "\f2c3"; -$fa-var-dropbox: "\f16b"; -$fa-var-drupal: "\f1a9"; -$fa-var-edge: "\f282"; -$fa-var-edit: "\f044"; -$fa-var-eercast: "\f2da"; -$fa-var-eject: "\f052"; -$fa-var-ellipsis-h: "\f141"; -$fa-var-ellipsis-v: "\f142"; -$fa-var-empire: "\f1d1"; -$fa-var-envelope: "\f0e0"; -$fa-var-envelope-o: "\f003"; -$fa-var-envelope-open: "\f2b6"; -$fa-var-envelope-open-o: "\f2b7"; -$fa-var-envelope-square: "\f199"; -$fa-var-envira: "\f299"; -$fa-var-eraser: "\f12d"; -$fa-var-etsy: "\f2d7"; -$fa-var-eur: "\f153"; -$fa-var-euro: "\f153"; -$fa-var-exchange: "\f0ec"; -$fa-var-exclamation: "\f12a"; -$fa-var-exclamation-circle: "\f06a"; -$fa-var-exclamation-triangle: "\f071"; -$fa-var-expand: "\f065"; -$fa-var-expeditedssl: "\f23e"; -$fa-var-external-link: "\f08e"; -$fa-var-external-link-square: "\f14c"; -$fa-var-eye: "\f06e"; -$fa-var-eye-slash: "\f070"; -$fa-var-eyedropper: "\f1fb"; -$fa-var-fa: "\f2b4"; -$fa-var-facebook: "\f09a"; -$fa-var-facebook-f: "\f09a"; -$fa-var-facebook-official: "\f230"; -$fa-var-facebook-square: "\f082"; -$fa-var-fast-backward: "\f049"; -$fa-var-fast-forward: "\f050"; -$fa-var-fax: "\f1ac"; -$fa-var-feed: "\f09e"; -$fa-var-female: "\f182"; -$fa-var-fighter-jet: "\f0fb"; -$fa-var-file: "\f15b"; -$fa-var-file-archive-o: "\f1c6"; -$fa-var-file-audio-o: "\f1c7"; -$fa-var-file-code-o: "\f1c9"; -$fa-var-file-excel-o: "\f1c3"; -$fa-var-file-image-o: "\f1c5"; -$fa-var-file-movie-o: "\f1c8"; -$fa-var-file-o: "\f016"; -$fa-var-file-pdf-o: "\f1c1"; -$fa-var-file-photo-o: "\f1c5"; -$fa-var-file-picture-o: "\f1c5"; -$fa-var-file-powerpoint-o: "\f1c4"; -$fa-var-file-sound-o: "\f1c7"; -$fa-var-file-text: "\f15c"; -$fa-var-file-text-o: "\f0f6"; -$fa-var-file-video-o: "\f1c8"; -$fa-var-file-word-o: "\f1c2"; -$fa-var-file-zip-o: "\f1c6"; -$fa-var-files-o: "\f0c5"; -$fa-var-film: "\f008"; -$fa-var-filter: "\f0b0"; -$fa-var-fire: "\f06d"; -$fa-var-fire-extinguisher: "\f134"; -$fa-var-firefox: "\f269"; -$fa-var-first-order: "\f2b0"; -$fa-var-flag: "\f024"; -$fa-var-flag-checkered: "\f11e"; -$fa-var-flag-o: "\f11d"; -$fa-var-flash: "\f0e7"; -$fa-var-flask: "\f0c3"; -$fa-var-flickr: "\f16e"; -$fa-var-floppy-o: "\f0c7"; -$fa-var-folder: "\f07b"; -$fa-var-folder-o: "\f114"; -$fa-var-folder-open: "\f07c"; -$fa-var-folder-open-o: "\f115"; -$fa-var-font: "\f031"; -$fa-var-font-awesome: "\f2b4"; -$fa-var-fonticons: "\f280"; -$fa-var-fort-awesome: "\f286"; -$fa-var-forumbee: "\f211"; -$fa-var-forward: "\f04e"; -$fa-var-foursquare: "\f180"; -$fa-var-free-code-camp: "\f2c5"; -$fa-var-frown-o: "\f119"; -$fa-var-futbol-o: "\f1e3"; -$fa-var-gamepad: "\f11b"; -$fa-var-gavel: "\f0e3"; -$fa-var-gbp: "\f154"; -$fa-var-ge: "\f1d1"; -$fa-var-gear: "\f013"; -$fa-var-gears: "\f085"; -$fa-var-genderless: "\f22d"; -$fa-var-get-pocket: "\f265"; -$fa-var-gg: "\f260"; -$fa-var-gg-circle: "\f261"; -$fa-var-gift: "\f06b"; -$fa-var-git: "\f1d3"; -$fa-var-git-square: "\f1d2"; -$fa-var-github: "\f09b"; -$fa-var-github-alt: "\f113"; -$fa-var-github-square: "\f092"; -$fa-var-gitlab: "\f296"; -$fa-var-gittip: "\f184"; -$fa-var-glass: "\f000"; -$fa-var-glide: "\f2a5"; -$fa-var-glide-g: "\f2a6"; -$fa-var-globe: "\f0ac"; -$fa-var-google: "\f1a0"; -$fa-var-google-plus: "\f0d5"; -$fa-var-google-plus-circle: "\f2b3"; -$fa-var-google-plus-official: "\f2b3"; -$fa-var-google-plus-square: "\f0d4"; -$fa-var-google-wallet: "\f1ee"; -$fa-var-graduation-cap: "\f19d"; -$fa-var-gratipay: "\f184"; -$fa-var-grav: "\f2d6"; -$fa-var-group: "\f0c0"; -$fa-var-h-square: "\f0fd"; -$fa-var-hacker-news: "\f1d4"; -$fa-var-hand-grab-o: "\f255"; -$fa-var-hand-lizard-o: "\f258"; -$fa-var-hand-o-down: "\f0a7"; -$fa-var-hand-o-left: "\f0a5"; -$fa-var-hand-o-right: "\f0a4"; -$fa-var-hand-o-up: "\f0a6"; -$fa-var-hand-paper-o: "\f256"; -$fa-var-hand-peace-o: "\f25b"; -$fa-var-hand-pointer-o: "\f25a"; -$fa-var-hand-rock-o: "\f255"; -$fa-var-hand-scissors-o: "\f257"; -$fa-var-hand-spock-o: "\f259"; -$fa-var-hand-stop-o: "\f256"; -$fa-var-handshake-o: "\f2b5"; -$fa-var-hard-of-hearing: "\f2a4"; -$fa-var-hashtag: "\f292"; -$fa-var-hdd-o: "\f0a0"; -$fa-var-header: "\f1dc"; -$fa-var-headphones: "\f025"; -$fa-var-heart: "\f004"; -$fa-var-heart-o: "\f08a"; -$fa-var-heartbeat: "\f21e"; -$fa-var-history: "\f1da"; -$fa-var-home: "\f015"; -$fa-var-hospital-o: "\f0f8"; -$fa-var-hotel: "\f236"; -$fa-var-hourglass: "\f254"; -$fa-var-hourglass-1: "\f251"; -$fa-var-hourglass-2: "\f252"; -$fa-var-hourglass-3: "\f253"; -$fa-var-hourglass-end: "\f253"; -$fa-var-hourglass-half: "\f252"; -$fa-var-hourglass-o: "\f250"; -$fa-var-hourglass-start: "\f251"; -$fa-var-houzz: "\f27c"; -$fa-var-html5: "\f13b"; -$fa-var-i-cursor: "\f246"; -$fa-var-id-badge: "\f2c1"; -$fa-var-id-card: "\f2c2"; -$fa-var-id-card-o: "\f2c3"; -$fa-var-ils: "\f20b"; -$fa-var-image: "\f03e"; -$fa-var-imdb: "\f2d8"; -$fa-var-inbox: "\f01c"; -$fa-var-indent: "\f03c"; -$fa-var-industry: "\f275"; -$fa-var-info: "\f129"; -$fa-var-info-circle: "\f05a"; -$fa-var-inr: "\f156"; -$fa-var-instagram: "\f16d"; -$fa-var-institution: "\f19c"; -$fa-var-internet-explorer: "\f26b"; -$fa-var-intersex: "\f224"; -$fa-var-ioxhost: "\f208"; -$fa-var-italic: "\f033"; -$fa-var-joomla: "\f1aa"; -$fa-var-jpy: "\f157"; -$fa-var-jsfiddle: "\f1cc"; -$fa-var-key: "\f084"; -$fa-var-keyboard-o: "\f11c"; -$fa-var-krw: "\f159"; -$fa-var-language: "\f1ab"; -$fa-var-laptop: "\f109"; -$fa-var-lastfm: "\f202"; -$fa-var-lastfm-square: "\f203"; -$fa-var-leaf: "\f06c"; -$fa-var-leanpub: "\f212"; -$fa-var-legal: "\f0e3"; -$fa-var-lemon-o: "\f094"; -$fa-var-level-down: "\f149"; -$fa-var-level-up: "\f148"; -$fa-var-life-bouy: "\f1cd"; -$fa-var-life-buoy: "\f1cd"; -$fa-var-life-ring: "\f1cd"; -$fa-var-life-saver: "\f1cd"; -$fa-var-lightbulb-o: "\f0eb"; -$fa-var-line-chart: "\f201"; -$fa-var-link: "\f0c1"; -$fa-var-linkedin: "\f0e1"; -$fa-var-linkedin-square: "\f08c"; -$fa-var-linode: "\f2b8"; -$fa-var-linux: "\f17c"; -$fa-var-list: "\f03a"; -$fa-var-list-alt: "\f022"; -$fa-var-list-ol: "\f0cb"; -$fa-var-list-ul: "\f0ca"; -$fa-var-location-arrow: "\f124"; -$fa-var-lock: "\f023"; -$fa-var-long-arrow-down: "\f175"; -$fa-var-long-arrow-left: "\f177"; -$fa-var-long-arrow-right: "\f178"; -$fa-var-long-arrow-up: "\f176"; -$fa-var-low-vision: "\f2a8"; -$fa-var-magic: "\f0d0"; -$fa-var-magnet: "\f076"; -$fa-var-mail-forward: "\f064"; -$fa-var-mail-reply: "\f112"; -$fa-var-mail-reply-all: "\f122"; -$fa-var-male: "\f183"; -$fa-var-map: "\f279"; -$fa-var-map-marker: "\f041"; -$fa-var-map-o: "\f278"; -$fa-var-map-pin: "\f276"; -$fa-var-map-signs: "\f277"; -$fa-var-mars: "\f222"; -$fa-var-mars-double: "\f227"; -$fa-var-mars-stroke: "\f229"; -$fa-var-mars-stroke-h: "\f22b"; -$fa-var-mars-stroke-v: "\f22a"; -$fa-var-maxcdn: "\f136"; -$fa-var-meanpath: "\f20c"; -$fa-var-medium: "\f23a"; -$fa-var-medkit: "\f0fa"; -$fa-var-meetup: "\f2e0"; -$fa-var-meh-o: "\f11a"; -$fa-var-mercury: "\f223"; -$fa-var-microchip: "\f2db"; -$fa-var-microphone: "\f130"; -$fa-var-microphone-slash: "\f131"; -$fa-var-minus: "\f068"; -$fa-var-minus-circle: "\f056"; -$fa-var-minus-square: "\f146"; -$fa-var-minus-square-o: "\f147"; -$fa-var-mixcloud: "\f289"; -$fa-var-mobile: "\f10b"; -$fa-var-mobile-phone: "\f10b"; -$fa-var-modx: "\f285"; -$fa-var-money: "\f0d6"; -$fa-var-moon-o: "\f186"; -$fa-var-mortar-board: "\f19d"; -$fa-var-motorcycle: "\f21c"; -$fa-var-mouse-pointer: "\f245"; -$fa-var-music: "\f001"; -$fa-var-navicon: "\f0c9"; -$fa-var-neuter: "\f22c"; -$fa-var-newspaper-o: "\f1ea"; -$fa-var-object-group: "\f247"; -$fa-var-object-ungroup: "\f248"; -$fa-var-odnoklassniki: "\f263"; -$fa-var-odnoklassniki-square: "\f264"; -$fa-var-opencart: "\f23d"; -$fa-var-openid: "\f19b"; -$fa-var-opera: "\f26a"; -$fa-var-optin-monster: "\f23c"; -$fa-var-outdent: "\f03b"; -$fa-var-pagelines: "\f18c"; -$fa-var-paint-brush: "\f1fc"; -$fa-var-paper-plane: "\f1d8"; -$fa-var-paper-plane-o: "\f1d9"; -$fa-var-paperclip: "\f0c6"; -$fa-var-paragraph: "\f1dd"; -$fa-var-paste: "\f0ea"; -$fa-var-pause: "\f04c"; -$fa-var-pause-circle: "\f28b"; -$fa-var-pause-circle-o: "\f28c"; -$fa-var-paw: "\f1b0"; -$fa-var-paypal: "\f1ed"; -$fa-var-pencil: "\f040"; -$fa-var-pencil-square: "\f14b"; -$fa-var-pencil-square-o: "\f044"; -$fa-var-percent: "\f295"; -$fa-var-phone: "\f095"; -$fa-var-phone-square: "\f098"; -$fa-var-photo: "\f03e"; -$fa-var-picture-o: "\f03e"; -$fa-var-pie-chart: "\f200"; -$fa-var-pied-piper: "\f2ae"; -$fa-var-pied-piper-alt: "\f1a8"; -$fa-var-pied-piper-pp: "\f1a7"; -$fa-var-pinterest: "\f0d2"; -$fa-var-pinterest-p: "\f231"; -$fa-var-pinterest-square: "\f0d3"; -$fa-var-plane: "\f072"; -$fa-var-play: "\f04b"; -$fa-var-play-circle: "\f144"; -$fa-var-play-circle-o: "\f01d"; -$fa-var-plug: "\f1e6"; -$fa-var-plus: "\f067"; -$fa-var-plus-circle: "\f055"; -$fa-var-plus-square: "\f0fe"; -$fa-var-plus-square-o: "\f196"; -$fa-var-podcast: "\f2ce"; -$fa-var-power-off: "\f011"; -$fa-var-print: "\f02f"; -$fa-var-product-hunt: "\f288"; -$fa-var-puzzle-piece: "\f12e"; -$fa-var-qq: "\f1d6"; -$fa-var-qrcode: "\f029"; -$fa-var-question: "\f128"; -$fa-var-question-circle: "\f059"; -$fa-var-question-circle-o: "\f29c"; -$fa-var-quora: "\f2c4"; -$fa-var-quote-left: "\f10d"; -$fa-var-quote-right: "\f10e"; -$fa-var-ra: "\f1d0"; -$fa-var-random: "\f074"; -$fa-var-ravelry: "\f2d9"; -$fa-var-rebel: "\f1d0"; -$fa-var-recycle: "\f1b8"; -$fa-var-reddit: "\f1a1"; -$fa-var-reddit-alien: "\f281"; -$fa-var-reddit-square: "\f1a2"; -$fa-var-refresh: "\f021"; -$fa-var-registered: "\f25d"; -$fa-var-remove: "\f00d"; -$fa-var-renren: "\f18b"; -$fa-var-reorder: "\f0c9"; -$fa-var-repeat: "\f01e"; -$fa-var-reply: "\f112"; -$fa-var-reply-all: "\f122"; -$fa-var-resistance: "\f1d0"; -$fa-var-retweet: "\f079"; -$fa-var-rmb: "\f157"; -$fa-var-road: "\f018"; -$fa-var-rocket: "\f135"; -$fa-var-rotate-left: "\f0e2"; -$fa-var-rotate-right: "\f01e"; -$fa-var-rouble: "\f158"; -$fa-var-rss: "\f09e"; -$fa-var-rss-square: "\f143"; -$fa-var-rub: "\f158"; -$fa-var-ruble: "\f158"; -$fa-var-rupee: "\f156"; -$fa-var-s15: "\f2cd"; -$fa-var-safari: "\f267"; -$fa-var-save: "\f0c7"; -$fa-var-scissors: "\f0c4"; -$fa-var-scribd: "\f28a"; -$fa-var-search: "\f002"; -$fa-var-search-minus: "\f010"; -$fa-var-search-plus: "\f00e"; -$fa-var-sellsy: "\f213"; -$fa-var-send: "\f1d8"; -$fa-var-send-o: "\f1d9"; -$fa-var-server: "\f233"; -$fa-var-share: "\f064"; -$fa-var-share-alt: "\f1e0"; -$fa-var-share-alt-square: "\f1e1"; -$fa-var-share-square: "\f14d"; -$fa-var-share-square-o: "\f045"; -$fa-var-shekel: "\f20b"; -$fa-var-sheqel: "\f20b"; -$fa-var-shield: "\f132"; -$fa-var-ship: "\f21a"; -$fa-var-shirtsinbulk: "\f214"; -$fa-var-shopping-bag: "\f290"; -$fa-var-shopping-basket: "\f291"; -$fa-var-shopping-cart: "\f07a"; -$fa-var-shower: "\f2cc"; -$fa-var-sign-in: "\f090"; -$fa-var-sign-language: "\f2a7"; -$fa-var-sign-out: "\f08b"; -$fa-var-signal: "\f012"; -$fa-var-signing: "\f2a7"; -$fa-var-simplybuilt: "\f215"; -$fa-var-sitemap: "\f0e8"; -$fa-var-skyatlas: "\f216"; -$fa-var-skype: "\f17e"; -$fa-var-slack: "\f198"; -$fa-var-sliders: "\f1de"; -$fa-var-slideshare: "\f1e7"; -$fa-var-smile-o: "\f118"; -$fa-var-snapchat: "\f2ab"; -$fa-var-snapchat-ghost: "\f2ac"; -$fa-var-snapchat-square: "\f2ad"; -$fa-var-snowflake-o: "\f2dc"; -$fa-var-soccer-ball-o: "\f1e3"; -$fa-var-sort: "\f0dc"; -$fa-var-sort-alpha-asc: "\f15d"; -$fa-var-sort-alpha-desc: "\f15e"; -$fa-var-sort-amount-asc: "\f160"; -$fa-var-sort-amount-desc: "\f161"; -$fa-var-sort-asc: "\f0de"; -$fa-var-sort-desc: "\f0dd"; -$fa-var-sort-down: "\f0dd"; -$fa-var-sort-numeric-asc: "\f162"; -$fa-var-sort-numeric-desc: "\f163"; -$fa-var-sort-up: "\f0de"; -$fa-var-soundcloud: "\f1be"; -$fa-var-space-shuttle: "\f197"; -$fa-var-spinner: "\f110"; -$fa-var-spoon: "\f1b1"; -$fa-var-spotify: "\f1bc"; -$fa-var-square: "\f0c8"; -$fa-var-square-o: "\f096"; -$fa-var-stack-exchange: "\f18d"; -$fa-var-stack-overflow: "\f16c"; -$fa-var-star: "\f005"; -$fa-var-star-half: "\f089"; -$fa-var-star-half-empty: "\f123"; -$fa-var-star-half-full: "\f123"; -$fa-var-star-half-o: "\f123"; -$fa-var-star-o: "\f006"; -$fa-var-steam: "\f1b6"; -$fa-var-steam-square: "\f1b7"; -$fa-var-step-backward: "\f048"; -$fa-var-step-forward: "\f051"; -$fa-var-stethoscope: "\f0f1"; -$fa-var-sticky-note: "\f249"; -$fa-var-sticky-note-o: "\f24a"; -$fa-var-stop: "\f04d"; -$fa-var-stop-circle: "\f28d"; -$fa-var-stop-circle-o: "\f28e"; -$fa-var-street-view: "\f21d"; -$fa-var-strikethrough: "\f0cc"; -$fa-var-stumbleupon: "\f1a4"; -$fa-var-stumbleupon-circle: "\f1a3"; -$fa-var-subscript: "\f12c"; -$fa-var-subway: "\f239"; -$fa-var-suitcase: "\f0f2"; -$fa-var-sun-o: "\f185"; -$fa-var-superpowers: "\f2dd"; -$fa-var-superscript: "\f12b"; -$fa-var-support: "\f1cd"; -$fa-var-table: "\f0ce"; -$fa-var-tablet: "\f10a"; -$fa-var-tachometer: "\f0e4"; -$fa-var-tag: "\f02b"; -$fa-var-tags: "\f02c"; -$fa-var-tasks: "\f0ae"; -$fa-var-taxi: "\f1ba"; -$fa-var-telegram: "\f2c6"; -$fa-var-television: "\f26c"; -$fa-var-tencent-weibo: "\f1d5"; -$fa-var-terminal: "\f120"; -$fa-var-text-height: "\f034"; -$fa-var-text-width: "\f035"; -$fa-var-th: "\f00a"; -$fa-var-th-large: "\f009"; -$fa-var-th-list: "\f00b"; -$fa-var-themeisle: "\f2b2"; -$fa-var-thermometer: "\f2c7"; -$fa-var-thermometer-0: "\f2cb"; -$fa-var-thermometer-1: "\f2ca"; -$fa-var-thermometer-2: "\f2c9"; -$fa-var-thermometer-3: "\f2c8"; -$fa-var-thermometer-4: "\f2c7"; -$fa-var-thermometer-empty: "\f2cb"; -$fa-var-thermometer-full: "\f2c7"; -$fa-var-thermometer-half: "\f2c9"; -$fa-var-thermometer-quarter: "\f2ca"; -$fa-var-thermometer-three-quarters: "\f2c8"; -$fa-var-thumb-tack: "\f08d"; -$fa-var-thumbs-down: "\f165"; -$fa-var-thumbs-o-down: "\f088"; -$fa-var-thumbs-o-up: "\f087"; -$fa-var-thumbs-up: "\f164"; -$fa-var-ticket: "\f145"; -$fa-var-times: "\f00d"; -$fa-var-times-circle: "\f057"; -$fa-var-times-circle-o: "\f05c"; -$fa-var-times-rectangle: "\f2d3"; -$fa-var-times-rectangle-o: "\f2d4"; -$fa-var-tint: "\f043"; -$fa-var-toggle-down: "\f150"; -$fa-var-toggle-left: "\f191"; -$fa-var-toggle-off: "\f204"; -$fa-var-toggle-on: "\f205"; -$fa-var-toggle-right: "\f152"; -$fa-var-toggle-up: "\f151"; -$fa-var-trademark: "\f25c"; -$fa-var-train: "\f238"; -$fa-var-transgender: "\f224"; -$fa-var-transgender-alt: "\f225"; -$fa-var-trash: "\f1f8"; -$fa-var-trash-o: "\f014"; -$fa-var-tree: "\f1bb"; -$fa-var-trello: "\f181"; -$fa-var-tripadvisor: "\f262"; -$fa-var-trophy: "\f091"; -$fa-var-truck: "\f0d1"; -$fa-var-try: "\f195"; -$fa-var-tty: "\f1e4"; -$fa-var-tumblr: "\f173"; -$fa-var-tumblr-square: "\f174"; -$fa-var-turkish-lira: "\f195"; -$fa-var-tv: "\f26c"; -$fa-var-twitch: "\f1e8"; -$fa-var-twitter: "\f099"; -$fa-var-twitter-square: "\f081"; -$fa-var-umbrella: "\f0e9"; -$fa-var-underline: "\f0cd"; -$fa-var-undo: "\f0e2"; -$fa-var-universal-access: "\f29a"; -$fa-var-university: "\f19c"; -$fa-var-unlink: "\f127"; -$fa-var-unlock: "\f09c"; -$fa-var-unlock-alt: "\f13e"; -$fa-var-unsorted: "\f0dc"; -$fa-var-upload: "\f093"; -$fa-var-usb: "\f287"; -$fa-var-usd: "\f155"; -$fa-var-user: "\f007"; -$fa-var-user-circle: "\f2bd"; -$fa-var-user-circle-o: "\f2be"; -$fa-var-user-md: "\f0f0"; -$fa-var-user-o: "\f2c0"; -$fa-var-user-plus: "\f234"; -$fa-var-user-secret: "\f21b"; -$fa-var-user-times: "\f235"; -$fa-var-users: "\f0c0"; -$fa-var-vcard: "\f2bb"; -$fa-var-vcard-o: "\f2bc"; -$fa-var-venus: "\f221"; -$fa-var-venus-double: "\f226"; -$fa-var-venus-mars: "\f228"; -$fa-var-viacoin: "\f237"; -$fa-var-viadeo: "\f2a9"; -$fa-var-viadeo-square: "\f2aa"; -$fa-var-video-camera: "\f03d"; -$fa-var-vimeo: "\f27d"; -$fa-var-vimeo-square: "\f194"; -$fa-var-vine: "\f1ca"; -$fa-var-vk: "\f189"; -$fa-var-volume-control-phone: "\f2a0"; -$fa-var-volume-down: "\f027"; -$fa-var-volume-off: "\f026"; -$fa-var-volume-up: "\f028"; -$fa-var-warning: "\f071"; -$fa-var-wechat: "\f1d7"; -$fa-var-weibo: "\f18a"; -$fa-var-weixin: "\f1d7"; -$fa-var-whatsapp: "\f232"; -$fa-var-wheelchair: "\f193"; -$fa-var-wheelchair-alt: "\f29b"; -$fa-var-wifi: "\f1eb"; -$fa-var-wikipedia-w: "\f266"; -$fa-var-window-close: "\f2d3"; -$fa-var-window-close-o: "\f2d4"; -$fa-var-window-maximize: "\f2d0"; -$fa-var-window-minimize: "\f2d1"; -$fa-var-window-restore: "\f2d2"; -$fa-var-windows: "\f17a"; -$fa-var-won: "\f159"; -$fa-var-wordpress: "\f19a"; -$fa-var-wpbeginner: "\f297"; -$fa-var-wpexplorer: "\f2de"; -$fa-var-wpforms: "\f298"; -$fa-var-wrench: "\f0ad"; -$fa-var-xing: "\f168"; -$fa-var-xing-square: "\f169"; -$fa-var-y-combinator: "\f23b"; -$fa-var-y-combinator-square: "\f1d4"; -$fa-var-yahoo: "\f19e"; -$fa-var-yc: "\f23b"; -$fa-var-yc-square: "\f1d4"; -$fa-var-yelp: "\f1e9"; -$fa-var-yen: "\f157"; -$fa-var-yoast: "\f2b1"; -$fa-var-youtube: "\f167"; -$fa-var-youtube-play: "\f16a"; -$fa-var-youtube-square: "\f166"; - diff --git a/netbox/project-static/font-awesome-4.7.0/scss/font-awesome.scss b/netbox/project-static/font-awesome-4.7.0/scss/font-awesome.scss deleted file mode 100644 index f1c83aaa5d..0000000000 --- a/netbox/project-static/font-awesome-4.7.0/scss/font-awesome.scss +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */ - -@import "variables"; -@import "mixins"; -@import "path"; -@import "core"; -@import "larger"; -@import "fixed-width"; -@import "list"; -@import "bordered-pulled"; -@import "animated"; -@import "rotated-flipped"; -@import "stacked"; -@import "icons"; -@import "screen-reader"; diff --git a/netbox/project-static/js/connection_toggles.js b/netbox/project-static/js/connection_toggles.js new file mode 100644 index 0000000000..c10b0b8eba --- /dev/null +++ b/netbox/project-static/js/connection_toggles.js @@ -0,0 +1,46 @@ +function toggleConnection(elem) { + var url = netbox_api_path + "dcim/cables/" + elem.attr('data') + "/"; + if (elem.hasClass('connected')) { + $.ajax({ + url: url, + method: 'PATCH', + dataType: 'json', + beforeSend: function(xhr, settings) { + xhr.setRequestHeader("X-CSRFToken", netbox_csrf_token); + }, + data: { + 'status': 'planned' + }, + context: this, + success: function() { + elem.parents('tr').removeClass('success').addClass('info'); + elem.removeClass('connected btn-warning').addClass('btn-success'); + elem.attr('title', 'Mark installed'); + elem.children('i').removeClass('mdi mdi-lan-disconnect').addClass('mdi mdi-lan-connect') + } + }); + } else { + $.ajax({ + url: url, + method: 'PATCH', + dataType: 'json', + beforeSend: function(xhr, settings) { + xhr.setRequestHeader("X-CSRFToken", netbox_csrf_token); + }, + data: { + 'status': 'connected' + }, + context: this, + success: function() { + elem.parents('tr').removeClass('info').addClass('success'); + elem.removeClass('btn-success').addClass('connected btn-warning'); + elem.attr('title', 'Mark planned'); + elem.children('i').removeClass('mdi mdi-lan-connect').addClass('mdi mdi-lan-disconnect') + } + }); + } + return false; +} +$(".cable-toggle").click(function() { + return toggleConnection($(this)); +}); diff --git a/netbox/project-static/js/graphs.js b/netbox/project-static/js/graphs.js deleted file mode 100644 index 4405c29034..0000000000 --- a/netbox/project-static/js/graphs.js +++ /dev/null @@ -1,26 +0,0 @@ -$('#graphs_modal').on('show.bs.modal', function (event) { - var button = $(event.relatedTarget); - var obj = button.data('obj'); - var url = button.data('url'); - var modal_title = $(this).find('.modal-title'); - var modal_body = $(this).find('.modal-body'); - modal_title.text(obj); - modal_body.empty(); - $.ajax({ - url: url, - dataType: 'json', - success: function(json) { - $.each(json, function(i, graph) { - // Build in a 500ms delay per graph to avoid hammering the server - setTimeout(function() { - modal_body.append('

    ' + graph.name + '

    '); - if (graph.embed_link) { - modal_body.append(''); - } else { - modal_body.append(''); - } - }, i*500); - }) - } - }); -}); diff --git a/netbox/project-static/js/interface_filtering.js b/netbox/project-static/js/interface_filtering.js new file mode 100644 index 0000000000..fecb156f4b --- /dev/null +++ b/netbox/project-static/js/interface_filtering.js @@ -0,0 +1,18 @@ +// Inteface filtering +$('input.interface-filter').on('input', function() { + var filter = new RegExp(this.value); + var interface; + + for (interface of $('table > tbody > tr')) { + // Slice off 'interface_' at the start of the ID + if (filter.test(interface.id.slice(10))) { + // Match the toggle in case the filter now matches the interface + $(interface).find('input:checkbox[name=pk]').prop('checked', $('input.toggle').prop('checked')); + $(interface).show(); + } else { + // Uncheck to prevent actions from including it when it doesn't match + $(interface).find('input:checkbox[name=pk]').prop('checked', false); + $(interface).hide(); + } + } +}); diff --git a/netbox/project-static/js/interface_toggles.js b/netbox/project-static/js/interface_toggles.js deleted file mode 100644 index df8ac064b7..0000000000 --- a/netbox/project-static/js/interface_toggles.js +++ /dev/null @@ -1,35 +0,0 @@ -// Toggle the display of IP addresses under interfaces -$('button.toggle-ips').click(function() { - var selected = $(this).attr('selected'); - if (selected) { - $('#interfaces_table tr.interface:visible + tr.ipaddresses').hide(); - } else { - $('#interfaces_table tr.interface:visible + tr.ipaddresses').show(); - } - $(this).attr('selected', !selected); - $(this).children('span').toggleClass('glyphicon-check glyphicon-unchecked'); - return false; -}); - -// Inteface filtering -$('input.interface-filter').on('input', function() { - var filter = new RegExp(this.value); - var interface; - - for (interface of $('#interfaces_table > tbody > tr.interface')) { - // Slice off 'interface_' at the start of the ID - if (filter.test(interface.id.slice(10))) { - // Match the toggle in case the filter now matches the interface - $(interface).find('input:checkbox[name=pk]').prop('checked', $('input.toggle').prop('checked')); - $(interface).show(); - if ($('button.toggle-ips').attr('selected')) { - $(interface).next('tr.ipaddresses').show(); - } - } else { - // Uncheck to prevent actions from including it when it doesn't match - $(interface).find('input:checkbox[name=pk]').prop('checked', false); - $(interface).hide(); - $(interface).next('tr.ipaddresses').hide(); - } - } -}); diff --git a/netbox/project-static/js/rack_elevations.js b/netbox/project-static/js/rack_elevations.js index 9c58b82e3f..ef21eefd7b 100644 --- a/netbox/project-static/js/rack_elevations.js +++ b/netbox/project-static/js/rack_elevations.js @@ -8,6 +8,6 @@ $('button.toggle-images').click(function() { $('.device-image', rack_elevation.contents()).removeClass('hidden'); } $(this).attr('selected', !selected); - $(this).children('span').toggleClass('glyphicon-check glyphicon-unchecked'); + $(this).children('span').toggleClass('mdi-checkbox-marked-circle-outline mdi-checkbox-blank-circle-outline'); return false; }); diff --git a/netbox/project-static/js/tableconfig.js b/netbox/project-static/js/tableconfig.js new file mode 100644 index 0000000000..8f4692ea49 --- /dev/null +++ b/netbox/project-static/js/tableconfig.js @@ -0,0 +1,47 @@ +$(document).ready(function() { + $('form.userconfigform input.reset').click(function(event) { + // Deselect all columns when the reset button is clicked + $('select[name="columns"]').val([]); + }); + + $('form.userconfigform').submit(function(event) { + event.preventDefault(); + + // Derive an array from the dotted path to the config root + let path = this.getAttribute('data-config-root').split('.'); + let data = {}; + let pointer = data; + + // Construct a nested JSON object from the path + let node; + for (node of path) { + pointer[node] = {}; + pointer = pointer[node]; + } + + // Assign the form data to the child node + let field; + $.each($(this).find('[id^="id_"]:input'), function(index, value) { + field = $(value); + pointer[field.attr("name")] = field.val(); + }); + + // Make the REST API request + $.ajax({ + url: netbox_api_path + 'users/config/', + async: true, + contentType: 'application/json', + dataType: 'json', + type: 'PATCH', + beforeSend: function(xhr, settings) { + xhr.setRequestHeader("X-CSRFToken", netbox_csrf_token); + }, + data: JSON.stringify(data), + }).done(function () { + // Reload the page + window.location.reload(true); + }).fail(function (xhr, status, error) { + alert("Failed to update user config (" + status + "): " + error); + }); + }); +}); diff --git a/netbox/project-static/materialdesignicons-5.4.55/.github/ISSUE_TEMPLATE.md b/netbox/project-static/materialdesignicons-5.4.55/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000..905dffe2dd --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,3 @@ +Disclaimer: +Hi there, thanks for contributing! Before anything else, please ensure you didn't mean to create an issue on the main MaterialDesign repo instead. +If this is intentional, just erase this message. Thanks! diff --git a/netbox/project-static/materialdesignicons-5.4.55/LICENSE b/netbox/project-static/materialdesignicons-5.4.55/LICENSE new file mode 100644 index 0000000000..382f8a138a --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/LICENSE @@ -0,0 +1,20 @@ +Pictogrammers Free License +-------------------------- + +This icon collection is released as free, open source, and GPL friendly by +the [Pictogrammers](http://pictogrammers.com/) icon group. You may use it +for commercial projects, open source projects, or anything really. + +# Icons: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) +Some of the icons are redistributed under the Apache 2.0 license. All other +icons are either redistributed under their respective licenses or are +distributed under the Apache 2.0 license. + +# Fonts: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) +All web and desktop fonts are distributed under the Apache 2.0 license. Web +and desktop fonts contain some icons that are redistributed under the Apache +2.0 license. All other icons are either redistributed under their respective +licenses or are distributed under the Apache 2.0 license. + +# Code: MIT (https://opensource.org/licenses/MIT) +The MIT license applies to all non-font and non-icon files. diff --git a/netbox/project-static/materialdesignicons-5.4.55/README.md b/netbox/project-static/materialdesignicons-5.4.55/README.md new file mode 100644 index 0000000000..2ffefd6c47 --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/README.md @@ -0,0 +1,25 @@ +> *Note:* Please use the main [MaterialDesign](https://github.com/Templarian/MaterialDesign/issues) repo to report issues. This repo is for distribution of the Webfont files only. + +# Webfont - Material Design Icons + +Webfont distribution for the [Material Design Icons](https://materialdesignicons.com). + +``` +npm install @mdi/font +``` + +> Package built with [@mdi/font-build](https://github.com/Templarian/MaterialDesign-Font-Build). + +## Related Packages + +[NPM @MDI Organization](https://npmjs.com/org/mdi) + +- JavaScript/Typescript: [MaterialDesign-JS](https://github.com/Templarian/MaterialDesign-JS) +- SVG: [MaterialDesign-SVG](https://github.com/Templarian/MaterialDesign-SVG) +- Font-Build [MaterialDesign-Font-Build](https://github.com/Templarian/MaterialDesign-Font-Build) +- Desktop Font: [MaterialDesign-Font](https://github.com/Templarian/MaterialDesign-Font) + +## Learn More + +- [MaterialDesignIcons.com](https://materialdesignicons.com) +- https://github.com/Templarian/MaterialDesign diff --git a/netbox/project-static/materialdesignicons-5.4.55/css/materialdesignicons.css b/netbox/project-static/materialdesignicons-5.4.55/css/materialdesignicons.css new file mode 100644 index 0000000000..a0dd6aba97 --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/css/materialdesignicons.css @@ -0,0 +1,23694 @@ +/* MaterialDesignIcons.com */ +@font-face { + font-family: "Material Design Icons"; + src: url("../fonts/materialdesignicons-webfont.eot?v=5.8.55"); + src: url("../fonts/materialdesignicons-webfont.eot?#iefix&v=5.8.55") format("embedded-opentype"), url("../fonts/materialdesignicons-webfont.woff2?v=5.8.55") format("woff2"), url("../fonts/materialdesignicons-webfont.woff?v=5.8.55") format("woff"), url("../fonts/materialdesignicons-webfont.ttf?v=5.8.55") format("truetype"); + font-weight: normal; + font-style: normal; +} + +.mdi:before, +.mdi-set { + display: inline-block; + font: normal normal normal 24px/1 "Material Design Icons"; + font-size: inherit; + text-rendering: auto; + line-height: inherit; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.mdi-ab-testing::before { + content: "\F01C9"; +} + +.mdi-abjad-arabic::before { + content: "\F1328"; +} + +.mdi-abjad-hebrew::before { + content: "\F1329"; +} + +.mdi-abugida-devanagari::before { + content: "\F132A"; +} + +.mdi-abugida-thai::before { + content: "\F132B"; +} + +.mdi-access-point::before { + content: "\F0003"; +} + +.mdi-access-point-check::before { + content: "\F1538"; +} + +.mdi-access-point-minus::before { + content: "\F1539"; +} + +.mdi-access-point-network::before { + content: "\F0002"; +} + +.mdi-access-point-network-off::before { + content: "\F0BE1"; +} + +.mdi-access-point-off::before { + content: "\F1511"; +} + +.mdi-access-point-plus::before { + content: "\F153A"; +} + +.mdi-access-point-remove::before { + content: "\F153B"; +} + +.mdi-account::before { + content: "\F0004"; +} + +.mdi-account-alert::before { + content: "\F0005"; +} + +.mdi-account-alert-outline::before { + content: "\F0B50"; +} + +.mdi-account-arrow-left::before { + content: "\F0B51"; +} + +.mdi-account-arrow-left-outline::before { + content: "\F0B52"; +} + +.mdi-account-arrow-right::before { + content: "\F0B53"; +} + +.mdi-account-arrow-right-outline::before { + content: "\F0B54"; +} + +.mdi-account-box::before { + content: "\F0006"; +} + +.mdi-account-box-multiple::before { + content: "\F0934"; +} + +.mdi-account-box-multiple-outline::before { + content: "\F100A"; +} + +.mdi-account-box-outline::before { + content: "\F0007"; +} + +.mdi-account-cancel::before { + content: "\F12DF"; +} + +.mdi-account-cancel-outline::before { + content: "\F12E0"; +} + +.mdi-account-cash::before { + content: "\F1097"; +} + +.mdi-account-cash-outline::before { + content: "\F1098"; +} + +.mdi-account-check::before { + content: "\F0008"; +} + +.mdi-account-check-outline::before { + content: "\F0BE2"; +} + +.mdi-account-child::before { + content: "\F0A89"; +} + +.mdi-account-child-circle::before { + content: "\F0A8A"; +} + +.mdi-account-child-outline::before { + content: "\F10C8"; +} + +.mdi-account-circle::before { + content: "\F0009"; +} + +.mdi-account-circle-outline::before { + content: "\F0B55"; +} + +.mdi-account-clock::before { + content: "\F0B56"; +} + +.mdi-account-clock-outline::before { + content: "\F0B57"; +} + +.mdi-account-cog::before { + content: "\F1370"; +} + +.mdi-account-cog-outline::before { + content: "\F1371"; +} + +.mdi-account-convert::before { + content: "\F000A"; +} + +.mdi-account-convert-outline::before { + content: "\F1301"; +} + +.mdi-account-cowboy-hat::before { + content: "\F0E9B"; +} + +.mdi-account-details::before { + content: "\F0631"; +} + +.mdi-account-details-outline::before { + content: "\F1372"; +} + +.mdi-account-edit::before { + content: "\F06BC"; +} + +.mdi-account-edit-outline::before { + content: "\F0FFB"; +} + +.mdi-account-group::before { + content: "\F0849"; +} + +.mdi-account-group-outline::before { + content: "\F0B58"; +} + +.mdi-account-hard-hat::before { + content: "\F05B5"; +} + +.mdi-account-heart::before { + content: "\F0899"; +} + +.mdi-account-heart-outline::before { + content: "\F0BE3"; +} + +.mdi-account-key::before { + content: "\F000B"; +} + +.mdi-account-key-outline::before { + content: "\F0BE4"; +} + +.mdi-account-lock::before { + content: "\F115E"; +} + +.mdi-account-lock-outline::before { + content: "\F115F"; +} + +.mdi-account-minus::before { + content: "\F000D"; +} + +.mdi-account-minus-outline::before { + content: "\F0AEC"; +} + +.mdi-account-multiple::before { + content: "\F000E"; +} + +.mdi-account-multiple-check::before { + content: "\F08C5"; +} + +.mdi-account-multiple-check-outline::before { + content: "\F11FE"; +} + +.mdi-account-multiple-minus::before { + content: "\F05D3"; +} + +.mdi-account-multiple-minus-outline::before { + content: "\F0BE5"; +} + +.mdi-account-multiple-outline::before { + content: "\F000F"; +} + +.mdi-account-multiple-plus::before { + content: "\F0010"; +} + +.mdi-account-multiple-plus-outline::before { + content: "\F0800"; +} + +.mdi-account-multiple-remove::before { + content: "\F120A"; +} + +.mdi-account-multiple-remove-outline::before { + content: "\F120B"; +} + +.mdi-account-music::before { + content: "\F0803"; +} + +.mdi-account-music-outline::before { + content: "\F0CE9"; +} + +.mdi-account-network::before { + content: "\F0011"; +} + +.mdi-account-network-outline::before { + content: "\F0BE6"; +} + +.mdi-account-off::before { + content: "\F0012"; +} + +.mdi-account-off-outline::before { + content: "\F0BE7"; +} + +.mdi-account-outline::before { + content: "\F0013"; +} + +.mdi-account-plus::before { + content: "\F0014"; +} + +.mdi-account-plus-outline::before { + content: "\F0801"; +} + +.mdi-account-question::before { + content: "\F0B59"; +} + +.mdi-account-question-outline::before { + content: "\F0B5A"; +} + +.mdi-account-reactivate::before { + content: "\F152B"; +} + +.mdi-account-reactivate-outline::before { + content: "\F152C"; +} + +.mdi-account-remove::before { + content: "\F0015"; +} + +.mdi-account-remove-outline::before { + content: "\F0AED"; +} + +.mdi-account-search::before { + content: "\F0016"; +} + +.mdi-account-search-outline::before { + content: "\F0935"; +} + +.mdi-account-settings::before { + content: "\F0630"; +} + +.mdi-account-settings-outline::before { + content: "\F10C9"; +} + +.mdi-account-star::before { + content: "\F0017"; +} + +.mdi-account-star-outline::before { + content: "\F0BE8"; +} + +.mdi-account-supervisor::before { + content: "\F0A8B"; +} + +.mdi-account-supervisor-circle::before { + content: "\F0A8C"; +} + +.mdi-account-supervisor-circle-outline::before { + content: "\F14EC"; +} + +.mdi-account-supervisor-outline::before { + content: "\F112D"; +} + +.mdi-account-switch::before { + content: "\F0019"; +} + +.mdi-account-switch-outline::before { + content: "\F04CB"; +} + +.mdi-account-tie::before { + content: "\F0CE3"; +} + +.mdi-account-tie-outline::before { + content: "\F10CA"; +} + +.mdi-account-tie-voice::before { + content: "\F1308"; +} + +.mdi-account-tie-voice-off::before { + content: "\F130A"; +} + +.mdi-account-tie-voice-off-outline::before { + content: "\F130B"; +} + +.mdi-account-tie-voice-outline::before { + content: "\F1309"; +} + +.mdi-account-voice::before { + content: "\F05CB"; +} + +.mdi-adjust::before { + content: "\F001A"; +} + +.mdi-adobe::before { + content: "\F0936"; +} + +.mdi-adobe-acrobat::before { + content: "\F0F9D"; +} + +.mdi-air-conditioner::before { + content: "\F001B"; +} + +.mdi-air-filter::before { + content: "\F0D43"; +} + +.mdi-air-horn::before { + content: "\F0DAC"; +} + +.mdi-air-humidifier::before { + content: "\F1099"; +} + +.mdi-air-humidifier-off::before { + content: "\F1466"; +} + +.mdi-air-purifier::before { + content: "\F0D44"; +} + +.mdi-airbag::before { + content: "\F0BE9"; +} + +.mdi-airballoon::before { + content: "\F001C"; +} + +.mdi-airballoon-outline::before { + content: "\F100B"; +} + +.mdi-airplane::before { + content: "\F001D"; +} + +.mdi-airplane-landing::before { + content: "\F05D4"; +} + +.mdi-airplane-off::before { + content: "\F001E"; +} + +.mdi-airplane-takeoff::before { + content: "\F05D5"; +} + +.mdi-airport::before { + content: "\F084B"; +} + +.mdi-alarm::before { + content: "\F0020"; +} + +.mdi-alarm-bell::before { + content: "\F078E"; +} + +.mdi-alarm-check::before { + content: "\F0021"; +} + +.mdi-alarm-light::before { + content: "\F078F"; +} + +.mdi-alarm-light-outline::before { + content: "\F0BEA"; +} + +.mdi-alarm-multiple::before { + content: "\F0022"; +} + +.mdi-alarm-note::before { + content: "\F0E71"; +} + +.mdi-alarm-note-off::before { + content: "\F0E72"; +} + +.mdi-alarm-off::before { + content: "\F0023"; +} + +.mdi-alarm-panel::before { + content: "\F15C4"; +} + +.mdi-alarm-panel-outline::before { + content: "\F15C5"; +} + +.mdi-alarm-plus::before { + content: "\F0024"; +} + +.mdi-alarm-snooze::before { + content: "\F068E"; +} + +.mdi-album::before { + content: "\F0025"; +} + +.mdi-alert::before { + content: "\F0026"; +} + +.mdi-alert-box::before { + content: "\F0027"; +} + +.mdi-alert-box-outline::before { + content: "\F0CE4"; +} + +.mdi-alert-circle::before { + content: "\F0028"; +} + +.mdi-alert-circle-check::before { + content: "\F11ED"; +} + +.mdi-alert-circle-check-outline::before { + content: "\F11EE"; +} + +.mdi-alert-circle-outline::before { + content: "\F05D6"; +} + +.mdi-alert-decagram::before { + content: "\F06BD"; +} + +.mdi-alert-decagram-outline::before { + content: "\F0CE5"; +} + +.mdi-alert-minus::before { + content: "\F14BB"; +} + +.mdi-alert-minus-outline::before { + content: "\F14BE"; +} + +.mdi-alert-octagon::before { + content: "\F0029"; +} + +.mdi-alert-octagon-outline::before { + content: "\F0CE6"; +} + +.mdi-alert-octagram::before { + content: "\F0767"; +} + +.mdi-alert-octagram-outline::before { + content: "\F0CE7"; +} + +.mdi-alert-outline::before { + content: "\F002A"; +} + +.mdi-alert-plus::before { + content: "\F14BA"; +} + +.mdi-alert-plus-outline::before { + content: "\F14BD"; +} + +.mdi-alert-remove::before { + content: "\F14BC"; +} + +.mdi-alert-remove-outline::before { + content: "\F14BF"; +} + +.mdi-alert-rhombus::before { + content: "\F11CE"; +} + +.mdi-alert-rhombus-outline::before { + content: "\F11CF"; +} + +.mdi-alien::before { + content: "\F089A"; +} + +.mdi-alien-outline::before { + content: "\F10CB"; +} + +.mdi-align-horizontal-center::before { + content: "\F11C3"; +} + +.mdi-align-horizontal-left::before { + content: "\F11C2"; +} + +.mdi-align-horizontal-right::before { + content: "\F11C4"; +} + +.mdi-align-vertical-bottom::before { + content: "\F11C5"; +} + +.mdi-align-vertical-center::before { + content: "\F11C6"; +} + +.mdi-align-vertical-top::before { + content: "\F11C7"; +} + +.mdi-all-inclusive::before { + content: "\F06BE"; +} + +.mdi-allergy::before { + content: "\F1258"; +} + +.mdi-alpha::before { + content: "\F002B"; +} + +.mdi-alpha-a::before { + content: "\F0AEE"; +} + +.mdi-alpha-a-box::before { + content: "\F0B08"; +} + +.mdi-alpha-a-box-outline::before { + content: "\F0BEB"; +} + +.mdi-alpha-a-circle::before { + content: "\F0BEC"; +} + +.mdi-alpha-a-circle-outline::before { + content: "\F0BED"; +} + +.mdi-alpha-b::before { + content: "\F0AEF"; +} + +.mdi-alpha-b-box::before { + content: "\F0B09"; +} + +.mdi-alpha-b-box-outline::before { + content: "\F0BEE"; +} + +.mdi-alpha-b-circle::before { + content: "\F0BEF"; +} + +.mdi-alpha-b-circle-outline::before { + content: "\F0BF0"; +} + +.mdi-alpha-c::before { + content: "\F0AF0"; +} + +.mdi-alpha-c-box::before { + content: "\F0B0A"; +} + +.mdi-alpha-c-box-outline::before { + content: "\F0BF1"; +} + +.mdi-alpha-c-circle::before { + content: "\F0BF2"; +} + +.mdi-alpha-c-circle-outline::before { + content: "\F0BF3"; +} + +.mdi-alpha-d::before { + content: "\F0AF1"; +} + +.mdi-alpha-d-box::before { + content: "\F0B0B"; +} + +.mdi-alpha-d-box-outline::before { + content: "\F0BF4"; +} + +.mdi-alpha-d-circle::before { + content: "\F0BF5"; +} + +.mdi-alpha-d-circle-outline::before { + content: "\F0BF6"; +} + +.mdi-alpha-e::before { + content: "\F0AF2"; +} + +.mdi-alpha-e-box::before { + content: "\F0B0C"; +} + +.mdi-alpha-e-box-outline::before { + content: "\F0BF7"; +} + +.mdi-alpha-e-circle::before { + content: "\F0BF8"; +} + +.mdi-alpha-e-circle-outline::before { + content: "\F0BF9"; +} + +.mdi-alpha-f::before { + content: "\F0AF3"; +} + +.mdi-alpha-f-box::before { + content: "\F0B0D"; +} + +.mdi-alpha-f-box-outline::before { + content: "\F0BFA"; +} + +.mdi-alpha-f-circle::before { + content: "\F0BFB"; +} + +.mdi-alpha-f-circle-outline::before { + content: "\F0BFC"; +} + +.mdi-alpha-g::before { + content: "\F0AF4"; +} + +.mdi-alpha-g-box::before { + content: "\F0B0E"; +} + +.mdi-alpha-g-box-outline::before { + content: "\F0BFD"; +} + +.mdi-alpha-g-circle::before { + content: "\F0BFE"; +} + +.mdi-alpha-g-circle-outline::before { + content: "\F0BFF"; +} + +.mdi-alpha-h::before { + content: "\F0AF5"; +} + +.mdi-alpha-h-box::before { + content: "\F0B0F"; +} + +.mdi-alpha-h-box-outline::before { + content: "\F0C00"; +} + +.mdi-alpha-h-circle::before { + content: "\F0C01"; +} + +.mdi-alpha-h-circle-outline::before { + content: "\F0C02"; +} + +.mdi-alpha-i::before { + content: "\F0AF6"; +} + +.mdi-alpha-i-box::before { + content: "\F0B10"; +} + +.mdi-alpha-i-box-outline::before { + content: "\F0C03"; +} + +.mdi-alpha-i-circle::before { + content: "\F0C04"; +} + +.mdi-alpha-i-circle-outline::before { + content: "\F0C05"; +} + +.mdi-alpha-j::before { + content: "\F0AF7"; +} + +.mdi-alpha-j-box::before { + content: "\F0B11"; +} + +.mdi-alpha-j-box-outline::before { + content: "\F0C06"; +} + +.mdi-alpha-j-circle::before { + content: "\F0C07"; +} + +.mdi-alpha-j-circle-outline::before { + content: "\F0C08"; +} + +.mdi-alpha-k::before { + content: "\F0AF8"; +} + +.mdi-alpha-k-box::before { + content: "\F0B12"; +} + +.mdi-alpha-k-box-outline::before { + content: "\F0C09"; +} + +.mdi-alpha-k-circle::before { + content: "\F0C0A"; +} + +.mdi-alpha-k-circle-outline::before { + content: "\F0C0B"; +} + +.mdi-alpha-l::before { + content: "\F0AF9"; +} + +.mdi-alpha-l-box::before { + content: "\F0B13"; +} + +.mdi-alpha-l-box-outline::before { + content: "\F0C0C"; +} + +.mdi-alpha-l-circle::before { + content: "\F0C0D"; +} + +.mdi-alpha-l-circle-outline::before { + content: "\F0C0E"; +} + +.mdi-alpha-m::before { + content: "\F0AFA"; +} + +.mdi-alpha-m-box::before { + content: "\F0B14"; +} + +.mdi-alpha-m-box-outline::before { + content: "\F0C0F"; +} + +.mdi-alpha-m-circle::before { + content: "\F0C10"; +} + +.mdi-alpha-m-circle-outline::before { + content: "\F0C11"; +} + +.mdi-alpha-n::before { + content: "\F0AFB"; +} + +.mdi-alpha-n-box::before { + content: "\F0B15"; +} + +.mdi-alpha-n-box-outline::before { + content: "\F0C12"; +} + +.mdi-alpha-n-circle::before { + content: "\F0C13"; +} + +.mdi-alpha-n-circle-outline::before { + content: "\F0C14"; +} + +.mdi-alpha-o::before { + content: "\F0AFC"; +} + +.mdi-alpha-o-box::before { + content: "\F0B16"; +} + +.mdi-alpha-o-box-outline::before { + content: "\F0C15"; +} + +.mdi-alpha-o-circle::before { + content: "\F0C16"; +} + +.mdi-alpha-o-circle-outline::before { + content: "\F0C17"; +} + +.mdi-alpha-p::before { + content: "\F0AFD"; +} + +.mdi-alpha-p-box::before { + content: "\F0B17"; +} + +.mdi-alpha-p-box-outline::before { + content: "\F0C18"; +} + +.mdi-alpha-p-circle::before { + content: "\F0C19"; +} + +.mdi-alpha-p-circle-outline::before { + content: "\F0C1A"; +} + +.mdi-alpha-q::before { + content: "\F0AFE"; +} + +.mdi-alpha-q-box::before { + content: "\F0B18"; +} + +.mdi-alpha-q-box-outline::before { + content: "\F0C1B"; +} + +.mdi-alpha-q-circle::before { + content: "\F0C1C"; +} + +.mdi-alpha-q-circle-outline::before { + content: "\F0C1D"; +} + +.mdi-alpha-r::before { + content: "\F0AFF"; +} + +.mdi-alpha-r-box::before { + content: "\F0B19"; +} + +.mdi-alpha-r-box-outline::before { + content: "\F0C1E"; +} + +.mdi-alpha-r-circle::before { + content: "\F0C1F"; +} + +.mdi-alpha-r-circle-outline::before { + content: "\F0C20"; +} + +.mdi-alpha-s::before { + content: "\F0B00"; +} + +.mdi-alpha-s-box::before { + content: "\F0B1A"; +} + +.mdi-alpha-s-box-outline::before { + content: "\F0C21"; +} + +.mdi-alpha-s-circle::before { + content: "\F0C22"; +} + +.mdi-alpha-s-circle-outline::before { + content: "\F0C23"; +} + +.mdi-alpha-t::before { + content: "\F0B01"; +} + +.mdi-alpha-t-box::before { + content: "\F0B1B"; +} + +.mdi-alpha-t-box-outline::before { + content: "\F0C24"; +} + +.mdi-alpha-t-circle::before { + content: "\F0C25"; +} + +.mdi-alpha-t-circle-outline::before { + content: "\F0C26"; +} + +.mdi-alpha-u::before { + content: "\F0B02"; +} + +.mdi-alpha-u-box::before { + content: "\F0B1C"; +} + +.mdi-alpha-u-box-outline::before { + content: "\F0C27"; +} + +.mdi-alpha-u-circle::before { + content: "\F0C28"; +} + +.mdi-alpha-u-circle-outline::before { + content: "\F0C29"; +} + +.mdi-alpha-v::before { + content: "\F0B03"; +} + +.mdi-alpha-v-box::before { + content: "\F0B1D"; +} + +.mdi-alpha-v-box-outline::before { + content: "\F0C2A"; +} + +.mdi-alpha-v-circle::before { + content: "\F0C2B"; +} + +.mdi-alpha-v-circle-outline::before { + content: "\F0C2C"; +} + +.mdi-alpha-w::before { + content: "\F0B04"; +} + +.mdi-alpha-w-box::before { + content: "\F0B1E"; +} + +.mdi-alpha-w-box-outline::before { + content: "\F0C2D"; +} + +.mdi-alpha-w-circle::before { + content: "\F0C2E"; +} + +.mdi-alpha-w-circle-outline::before { + content: "\F0C2F"; +} + +.mdi-alpha-x::before { + content: "\F0B05"; +} + +.mdi-alpha-x-box::before { + content: "\F0B1F"; +} + +.mdi-alpha-x-box-outline::before { + content: "\F0C30"; +} + +.mdi-alpha-x-circle::before { + content: "\F0C31"; +} + +.mdi-alpha-x-circle-outline::before { + content: "\F0C32"; +} + +.mdi-alpha-y::before { + content: "\F0B06"; +} + +.mdi-alpha-y-box::before { + content: "\F0B20"; +} + +.mdi-alpha-y-box-outline::before { + content: "\F0C33"; +} + +.mdi-alpha-y-circle::before { + content: "\F0C34"; +} + +.mdi-alpha-y-circle-outline::before { + content: "\F0C35"; +} + +.mdi-alpha-z::before { + content: "\F0B07"; +} + +.mdi-alpha-z-box::before { + content: "\F0B21"; +} + +.mdi-alpha-z-box-outline::before { + content: "\F0C36"; +} + +.mdi-alpha-z-circle::before { + content: "\F0C37"; +} + +.mdi-alpha-z-circle-outline::before { + content: "\F0C38"; +} + +.mdi-alphabet-aurebesh::before { + content: "\F132C"; +} + +.mdi-alphabet-cyrillic::before { + content: "\F132D"; +} + +.mdi-alphabet-greek::before { + content: "\F132E"; +} + +.mdi-alphabet-latin::before { + content: "\F132F"; +} + +.mdi-alphabet-piqad::before { + content: "\F1330"; +} + +.mdi-alphabet-tengwar::before { + content: "\F1337"; +} + +.mdi-alphabetical::before { + content: "\F002C"; +} + +.mdi-alphabetical-off::before { + content: "\F100C"; +} + +.mdi-alphabetical-variant::before { + content: "\F100D"; +} + +.mdi-alphabetical-variant-off::before { + content: "\F100E"; +} + +.mdi-altimeter::before { + content: "\F05D7"; +} + +.mdi-amazon::before { + content: "\F002D"; +} + +.mdi-amazon-alexa::before { + content: "\F08C6"; +} + +.mdi-ambulance::before { + content: "\F002F"; +} + +.mdi-ammunition::before { + content: "\F0CE8"; +} + +.mdi-ampersand::before { + content: "\F0A8D"; +} + +.mdi-amplifier::before { + content: "\F0030"; +} + +.mdi-amplifier-off::before { + content: "\F11B5"; +} + +.mdi-anchor::before { + content: "\F0031"; +} + +.mdi-android::before { + content: "\F0032"; +} + +.mdi-android-auto::before { + content: "\F0A8E"; +} + +.mdi-android-debug-bridge::before { + content: "\F0033"; +} + +.mdi-android-messages::before { + content: "\F0D45"; +} + +.mdi-android-studio::before { + content: "\F0034"; +} + +.mdi-angle-acute::before { + content: "\F0937"; +} + +.mdi-angle-obtuse::before { + content: "\F0938"; +} + +.mdi-angle-right::before { + content: "\F0939"; +} + +.mdi-angular::before { + content: "\F06B2"; +} + +.mdi-angularjs::before { + content: "\F06BF"; +} + +.mdi-animation::before { + content: "\F05D8"; +} + +.mdi-animation-outline::before { + content: "\F0A8F"; +} + +.mdi-animation-play::before { + content: "\F093A"; +} + +.mdi-animation-play-outline::before { + content: "\F0A90"; +} + +.mdi-ansible::before { + content: "\F109A"; +} + +.mdi-antenna::before { + content: "\F1119"; +} + +.mdi-anvil::before { + content: "\F089B"; +} + +.mdi-apache-kafka::before { + content: "\F100F"; +} + +.mdi-api::before { + content: "\F109B"; +} + +.mdi-api-off::before { + content: "\F1257"; +} + +.mdi-apple::before { + content: "\F0035"; +} + +.mdi-apple-airplay::before { + content: "\F001F"; +} + +.mdi-apple-finder::before { + content: "\F0036"; +} + +.mdi-apple-icloud::before { + content: "\F0038"; +} + +.mdi-apple-ios::before { + content: "\F0037"; +} + +.mdi-apple-keyboard-caps::before { + content: "\F0632"; +} + +.mdi-apple-keyboard-command::before { + content: "\F0633"; +} + +.mdi-apple-keyboard-control::before { + content: "\F0634"; +} + +.mdi-apple-keyboard-option::before { + content: "\F0635"; +} + +.mdi-apple-keyboard-shift::before { + content: "\F0636"; +} + +.mdi-apple-safari::before { + content: "\F0039"; +} + +.mdi-application::before { + content: "\F0614"; +} + +.mdi-application-cog::before { + content: "\F1577"; +} + +.mdi-application-export::before { + content: "\F0DAD"; +} + +.mdi-application-import::before { + content: "\F0DAE"; +} + +.mdi-application-settings::before { + content: "\F1555"; +} + +.mdi-approximately-equal::before { + content: "\F0F9E"; +} + +.mdi-approximately-equal-box::before { + content: "\F0F9F"; +} + +.mdi-apps::before { + content: "\F003B"; +} + +.mdi-apps-box::before { + content: "\F0D46"; +} + +.mdi-arch::before { + content: "\F08C7"; +} + +.mdi-archive::before { + content: "\F003C"; +} + +.mdi-archive-alert::before { + content: "\F14FD"; +} + +.mdi-archive-alert-outline::before { + content: "\F14FE"; +} + +.mdi-archive-arrow-down::before { + content: "\F1259"; +} + +.mdi-archive-arrow-down-outline::before { + content: "\F125A"; +} + +.mdi-archive-arrow-up::before { + content: "\F125B"; +} + +.mdi-archive-arrow-up-outline::before { + content: "\F125C"; +} + +.mdi-archive-outline::before { + content: "\F120E"; +} + +.mdi-arm-flex::before { + content: "\F0FD7"; +} + +.mdi-arm-flex-outline::before { + content: "\F0FD6"; +} + +.mdi-arrange-bring-forward::before { + content: "\F003D"; +} + +.mdi-arrange-bring-to-front::before { + content: "\F003E"; +} + +.mdi-arrange-send-backward::before { + content: "\F003F"; +} + +.mdi-arrange-send-to-back::before { + content: "\F0040"; +} + +.mdi-arrow-all::before { + content: "\F0041"; +} + +.mdi-arrow-bottom-left::before { + content: "\F0042"; +} + +.mdi-arrow-bottom-left-bold-outline::before { + content: "\F09B7"; +} + +.mdi-arrow-bottom-left-thick::before { + content: "\F09B8"; +} + +.mdi-arrow-bottom-left-thin-circle-outline::before { + content: "\F1596"; +} + +.mdi-arrow-bottom-right::before { + content: "\F0043"; +} + +.mdi-arrow-bottom-right-bold-outline::before { + content: "\F09B9"; +} + +.mdi-arrow-bottom-right-thick::before { + content: "\F09BA"; +} + +.mdi-arrow-bottom-right-thin-circle-outline::before { + content: "\F1595"; +} + +.mdi-arrow-collapse::before { + content: "\F0615"; +} + +.mdi-arrow-collapse-all::before { + content: "\F0044"; +} + +.mdi-arrow-collapse-down::before { + content: "\F0792"; +} + +.mdi-arrow-collapse-horizontal::before { + content: "\F084C"; +} + +.mdi-arrow-collapse-left::before { + content: "\F0793"; +} + +.mdi-arrow-collapse-right::before { + content: "\F0794"; +} + +.mdi-arrow-collapse-up::before { + content: "\F0795"; +} + +.mdi-arrow-collapse-vertical::before { + content: "\F084D"; +} + +.mdi-arrow-decision::before { + content: "\F09BB"; +} + +.mdi-arrow-decision-auto::before { + content: "\F09BC"; +} + +.mdi-arrow-decision-auto-outline::before { + content: "\F09BD"; +} + +.mdi-arrow-decision-outline::before { + content: "\F09BE"; +} + +.mdi-arrow-down::before { + content: "\F0045"; +} + +.mdi-arrow-down-bold::before { + content: "\F072E"; +} + +.mdi-arrow-down-bold-box::before { + content: "\F072F"; +} + +.mdi-arrow-down-bold-box-outline::before { + content: "\F0730"; +} + +.mdi-arrow-down-bold-circle::before { + content: "\F0047"; +} + +.mdi-arrow-down-bold-circle-outline::before { + content: "\F0048"; +} + +.mdi-arrow-down-bold-hexagon-outline::before { + content: "\F0049"; +} + +.mdi-arrow-down-bold-outline::before { + content: "\F09BF"; +} + +.mdi-arrow-down-box::before { + content: "\F06C0"; +} + +.mdi-arrow-down-circle::before { + content: "\F0CDB"; +} + +.mdi-arrow-down-circle-outline::before { + content: "\F0CDC"; +} + +.mdi-arrow-down-drop-circle::before { + content: "\F004A"; +} + +.mdi-arrow-down-drop-circle-outline::before { + content: "\F004B"; +} + +.mdi-arrow-down-thick::before { + content: "\F0046"; +} + +.mdi-arrow-down-thin-circle-outline::before { + content: "\F1599"; +} + +.mdi-arrow-expand::before { + content: "\F0616"; +} + +.mdi-arrow-expand-all::before { + content: "\F004C"; +} + +.mdi-arrow-expand-down::before { + content: "\F0796"; +} + +.mdi-arrow-expand-horizontal::before { + content: "\F084E"; +} + +.mdi-arrow-expand-left::before { + content: "\F0797"; +} + +.mdi-arrow-expand-right::before { + content: "\F0798"; +} + +.mdi-arrow-expand-up::before { + content: "\F0799"; +} + +.mdi-arrow-expand-vertical::before { + content: "\F084F"; +} + +.mdi-arrow-horizontal-lock::before { + content: "\F115B"; +} + +.mdi-arrow-left::before { + content: "\F004D"; +} + +.mdi-arrow-left-bold::before { + content: "\F0731"; +} + +.mdi-arrow-left-bold-box::before { + content: "\F0732"; +} + +.mdi-arrow-left-bold-box-outline::before { + content: "\F0733"; +} + +.mdi-arrow-left-bold-circle::before { + content: "\F004F"; +} + +.mdi-arrow-left-bold-circle-outline::before { + content: "\F0050"; +} + +.mdi-arrow-left-bold-hexagon-outline::before { + content: "\F0051"; +} + +.mdi-arrow-left-bold-outline::before { + content: "\F09C0"; +} + +.mdi-arrow-left-box::before { + content: "\F06C1"; +} + +.mdi-arrow-left-circle::before { + content: "\F0CDD"; +} + +.mdi-arrow-left-circle-outline::before { + content: "\F0CDE"; +} + +.mdi-arrow-left-drop-circle::before { + content: "\F0052"; +} + +.mdi-arrow-left-drop-circle-outline::before { + content: "\F0053"; +} + +.mdi-arrow-left-right::before { + content: "\F0E73"; +} + +.mdi-arrow-left-right-bold::before { + content: "\F0E74"; +} + +.mdi-arrow-left-right-bold-outline::before { + content: "\F09C1"; +} + +.mdi-arrow-left-thick::before { + content: "\F004E"; +} + +.mdi-arrow-left-thin-circle-outline::before { + content: "\F159A"; +} + +.mdi-arrow-right::before { + content: "\F0054"; +} + +.mdi-arrow-right-bold::before { + content: "\F0734"; +} + +.mdi-arrow-right-bold-box::before { + content: "\F0735"; +} + +.mdi-arrow-right-bold-box-outline::before { + content: "\F0736"; +} + +.mdi-arrow-right-bold-circle::before { + content: "\F0056"; +} + +.mdi-arrow-right-bold-circle-outline::before { + content: "\F0057"; +} + +.mdi-arrow-right-bold-hexagon-outline::before { + content: "\F0058"; +} + +.mdi-arrow-right-bold-outline::before { + content: "\F09C2"; +} + +.mdi-arrow-right-box::before { + content: "\F06C2"; +} + +.mdi-arrow-right-circle::before { + content: "\F0CDF"; +} + +.mdi-arrow-right-circle-outline::before { + content: "\F0CE0"; +} + +.mdi-arrow-right-drop-circle::before { + content: "\F0059"; +} + +.mdi-arrow-right-drop-circle-outline::before { + content: "\F005A"; +} + +.mdi-arrow-right-thick::before { + content: "\F0055"; +} + +.mdi-arrow-right-thin-circle-outline::before { + content: "\F1598"; +} + +.mdi-arrow-split-horizontal::before { + content: "\F093B"; +} + +.mdi-arrow-split-vertical::before { + content: "\F093C"; +} + +.mdi-arrow-top-left::before { + content: "\F005B"; +} + +.mdi-arrow-top-left-bold-outline::before { + content: "\F09C3"; +} + +.mdi-arrow-top-left-bottom-right::before { + content: "\F0E75"; +} + +.mdi-arrow-top-left-bottom-right-bold::before { + content: "\F0E76"; +} + +.mdi-arrow-top-left-thick::before { + content: "\F09C4"; +} + +.mdi-arrow-top-left-thin-circle-outline::before { + content: "\F1593"; +} + +.mdi-arrow-top-right::before { + content: "\F005C"; +} + +.mdi-arrow-top-right-bold-outline::before { + content: "\F09C5"; +} + +.mdi-arrow-top-right-bottom-left::before { + content: "\F0E77"; +} + +.mdi-arrow-top-right-bottom-left-bold::before { + content: "\F0E78"; +} + +.mdi-arrow-top-right-thick::before { + content: "\F09C6"; +} + +.mdi-arrow-top-right-thin-circle-outline::before { + content: "\F1594"; +} + +.mdi-arrow-up::before { + content: "\F005D"; +} + +.mdi-arrow-up-bold::before { + content: "\F0737"; +} + +.mdi-arrow-up-bold-box::before { + content: "\F0738"; +} + +.mdi-arrow-up-bold-box-outline::before { + content: "\F0739"; +} + +.mdi-arrow-up-bold-circle::before { + content: "\F005F"; +} + +.mdi-arrow-up-bold-circle-outline::before { + content: "\F0060"; +} + +.mdi-arrow-up-bold-hexagon-outline::before { + content: "\F0061"; +} + +.mdi-arrow-up-bold-outline::before { + content: "\F09C7"; +} + +.mdi-arrow-up-box::before { + content: "\F06C3"; +} + +.mdi-arrow-up-circle::before { + content: "\F0CE1"; +} + +.mdi-arrow-up-circle-outline::before { + content: "\F0CE2"; +} + +.mdi-arrow-up-down::before { + content: "\F0E79"; +} + +.mdi-arrow-up-down-bold::before { + content: "\F0E7A"; +} + +.mdi-arrow-up-down-bold-outline::before { + content: "\F09C8"; +} + +.mdi-arrow-up-drop-circle::before { + content: "\F0062"; +} + +.mdi-arrow-up-drop-circle-outline::before { + content: "\F0063"; +} + +.mdi-arrow-up-thick::before { + content: "\F005E"; +} + +.mdi-arrow-up-thin-circle-outline::before { + content: "\F1597"; +} + +.mdi-arrow-vertical-lock::before { + content: "\F115C"; +} + +.mdi-artstation::before { + content: "\F0B5B"; +} + +.mdi-aspect-ratio::before { + content: "\F0A24"; +} + +.mdi-assistant::before { + content: "\F0064"; +} + +.mdi-asterisk::before { + content: "\F06C4"; +} + +.mdi-at::before { + content: "\F0065"; +} + +.mdi-atlassian::before { + content: "\F0804"; +} + +.mdi-atm::before { + content: "\F0D47"; +} + +.mdi-atom::before { + content: "\F0768"; +} + +.mdi-atom-variant::before { + content: "\F0E7B"; +} + +.mdi-attachment::before { + content: "\F0066"; +} + +.mdi-audio-video::before { + content: "\F093D"; +} + +.mdi-audio-video-off::before { + content: "\F11B6"; +} + +.mdi-augmented-reality::before { + content: "\F0850"; +} + +.mdi-auto-download::before { + content: "\F137E"; +} + +.mdi-auto-fix::before { + content: "\F0068"; +} + +.mdi-auto-upload::before { + content: "\F0069"; +} + +.mdi-autorenew::before { + content: "\F006A"; +} + +.mdi-av-timer::before { + content: "\F006B"; +} + +.mdi-aws::before { + content: "\F0E0F"; +} + +.mdi-axe::before { + content: "\F08C8"; +} + +.mdi-axis::before { + content: "\F0D48"; +} + +.mdi-axis-arrow::before { + content: "\F0D49"; +} + +.mdi-axis-arrow-info::before { + content: "\F140E"; +} + +.mdi-axis-arrow-lock::before { + content: "\F0D4A"; +} + +.mdi-axis-lock::before { + content: "\F0D4B"; +} + +.mdi-axis-x-arrow::before { + content: "\F0D4C"; +} + +.mdi-axis-x-arrow-lock::before { + content: "\F0D4D"; +} + +.mdi-axis-x-rotate-clockwise::before { + content: "\F0D4E"; +} + +.mdi-axis-x-rotate-counterclockwise::before { + content: "\F0D4F"; +} + +.mdi-axis-x-y-arrow-lock::before { + content: "\F0D50"; +} + +.mdi-axis-y-arrow::before { + content: "\F0D51"; +} + +.mdi-axis-y-arrow-lock::before { + content: "\F0D52"; +} + +.mdi-axis-y-rotate-clockwise::before { + content: "\F0D53"; +} + +.mdi-axis-y-rotate-counterclockwise::before { + content: "\F0D54"; +} + +.mdi-axis-z-arrow::before { + content: "\F0D55"; +} + +.mdi-axis-z-arrow-lock::before { + content: "\F0D56"; +} + +.mdi-axis-z-rotate-clockwise::before { + content: "\F0D57"; +} + +.mdi-axis-z-rotate-counterclockwise::before { + content: "\F0D58"; +} + +.mdi-babel::before { + content: "\F0A25"; +} + +.mdi-baby::before { + content: "\F006C"; +} + +.mdi-baby-bottle::before { + content: "\F0F39"; +} + +.mdi-baby-bottle-outline::before { + content: "\F0F3A"; +} + +.mdi-baby-buggy::before { + content: "\F13E0"; +} + +.mdi-baby-carriage::before { + content: "\F068F"; +} + +.mdi-baby-carriage-off::before { + content: "\F0FA0"; +} + +.mdi-baby-face::before { + content: "\F0E7C"; +} + +.mdi-baby-face-outline::before { + content: "\F0E7D"; +} + +.mdi-backburger::before { + content: "\F006D"; +} + +.mdi-backspace::before { + content: "\F006E"; +} + +.mdi-backspace-outline::before { + content: "\F0B5C"; +} + +.mdi-backspace-reverse::before { + content: "\F0E7E"; +} + +.mdi-backspace-reverse-outline::before { + content: "\F0E7F"; +} + +.mdi-backup-restore::before { + content: "\F006F"; +} + +.mdi-bacteria::before { + content: "\F0ED5"; +} + +.mdi-bacteria-outline::before { + content: "\F0ED6"; +} + +.mdi-badge-account::before { + content: "\F0DA7"; +} + +.mdi-badge-account-alert::before { + content: "\F0DA8"; +} + +.mdi-badge-account-alert-outline::before { + content: "\F0DA9"; +} + +.mdi-badge-account-horizontal::before { + content: "\F0E0D"; +} + +.mdi-badge-account-horizontal-outline::before { + content: "\F0E0E"; +} + +.mdi-badge-account-outline::before { + content: "\F0DAA"; +} + +.mdi-badminton::before { + content: "\F0851"; +} + +.mdi-bag-carry-on::before { + content: "\F0F3B"; +} + +.mdi-bag-carry-on-check::before { + content: "\F0D65"; +} + +.mdi-bag-carry-on-off::before { + content: "\F0F3C"; +} + +.mdi-bag-checked::before { + content: "\F0F3D"; +} + +.mdi-bag-personal::before { + content: "\F0E10"; +} + +.mdi-bag-personal-off::before { + content: "\F0E11"; +} + +.mdi-bag-personal-off-outline::before { + content: "\F0E12"; +} + +.mdi-bag-personal-outline::before { + content: "\F0E13"; +} + +.mdi-bag-suitcase::before { + content: "\F158B"; +} + +.mdi-bag-suitcase-off::before { + content: "\F158D"; +} + +.mdi-bag-suitcase-off-outline::before { + content: "\F158E"; +} + +.mdi-bag-suitcase-outline::before { + content: "\F158C"; +} + +.mdi-baguette::before { + content: "\F0F3E"; +} + +.mdi-balloon::before { + content: "\F0A26"; +} + +.mdi-ballot::before { + content: "\F09C9"; +} + +.mdi-ballot-outline::before { + content: "\F09CA"; +} + +.mdi-ballot-recount::before { + content: "\F0C39"; +} + +.mdi-ballot-recount-outline::before { + content: "\F0C3A"; +} + +.mdi-bandage::before { + content: "\F0DAF"; +} + +.mdi-bandcamp::before { + content: "\F0675"; +} + +.mdi-bank::before { + content: "\F0070"; +} + +.mdi-bank-check::before { + content: "\F1655"; +} + +.mdi-bank-minus::before { + content: "\F0DB0"; +} + +.mdi-bank-off::before { + content: "\F1656"; +} + +.mdi-bank-off-outline::before { + content: "\F1657"; +} + +.mdi-bank-outline::before { + content: "\F0E80"; +} + +.mdi-bank-plus::before { + content: "\F0DB1"; +} + +.mdi-bank-remove::before { + content: "\F0DB2"; +} + +.mdi-bank-transfer::before { + content: "\F0A27"; +} + +.mdi-bank-transfer-in::before { + content: "\F0A28"; +} + +.mdi-bank-transfer-out::before { + content: "\F0A29"; +} + +.mdi-barcode::before { + content: "\F0071"; +} + +.mdi-barcode-off::before { + content: "\F1236"; +} + +.mdi-barcode-scan::before { + content: "\F0072"; +} + +.mdi-barley::before { + content: "\F0073"; +} + +.mdi-barley-off::before { + content: "\F0B5D"; +} + +.mdi-barn::before { + content: "\F0B5E"; +} + +.mdi-barrel::before { + content: "\F0074"; +} + +.mdi-baseball::before { + content: "\F0852"; +} + +.mdi-baseball-bat::before { + content: "\F0853"; +} + +.mdi-baseball-diamond::before { + content: "\F15EC"; +} + +.mdi-baseball-diamond-outline::before { + content: "\F15ED"; +} + +.mdi-bash::before { + content: "\F1183"; +} + +.mdi-basket::before { + content: "\F0076"; +} + +.mdi-basket-fill::before { + content: "\F0077"; +} + +.mdi-basket-minus::before { + content: "\F1523"; +} + +.mdi-basket-minus-outline::before { + content: "\F1524"; +} + +.mdi-basket-off::before { + content: "\F1525"; +} + +.mdi-basket-off-outline::before { + content: "\F1526"; +} + +.mdi-basket-outline::before { + content: "\F1181"; +} + +.mdi-basket-plus::before { + content: "\F1527"; +} + +.mdi-basket-plus-outline::before { + content: "\F1528"; +} + +.mdi-basket-remove::before { + content: "\F1529"; +} + +.mdi-basket-remove-outline::before { + content: "\F152A"; +} + +.mdi-basket-unfill::before { + content: "\F0078"; +} + +.mdi-basketball::before { + content: "\F0806"; +} + +.mdi-basketball-hoop::before { + content: "\F0C3B"; +} + +.mdi-basketball-hoop-outline::before { + content: "\F0C3C"; +} + +.mdi-bat::before { + content: "\F0B5F"; +} + +.mdi-battery::before { + content: "\F0079"; +} + +.mdi-battery-10::before { + content: "\F007A"; +} + +.mdi-battery-10-bluetooth::before { + content: "\F093E"; +} + +.mdi-battery-20::before { + content: "\F007B"; +} + +.mdi-battery-20-bluetooth::before { + content: "\F093F"; +} + +.mdi-battery-30::before { + content: "\F007C"; +} + +.mdi-battery-30-bluetooth::before { + content: "\F0940"; +} + +.mdi-battery-40::before { + content: "\F007D"; +} + +.mdi-battery-40-bluetooth::before { + content: "\F0941"; +} + +.mdi-battery-50::before { + content: "\F007E"; +} + +.mdi-battery-50-bluetooth::before { + content: "\F0942"; +} + +.mdi-battery-60::before { + content: "\F007F"; +} + +.mdi-battery-60-bluetooth::before { + content: "\F0943"; +} + +.mdi-battery-70::before { + content: "\F0080"; +} + +.mdi-battery-70-bluetooth::before { + content: "\F0944"; +} + +.mdi-battery-80::before { + content: "\F0081"; +} + +.mdi-battery-80-bluetooth::before { + content: "\F0945"; +} + +.mdi-battery-90::before { + content: "\F0082"; +} + +.mdi-battery-90-bluetooth::before { + content: "\F0946"; +} + +.mdi-battery-alert::before { + content: "\F0083"; +} + +.mdi-battery-alert-bluetooth::before { + content: "\F0947"; +} + +.mdi-battery-alert-variant::before { + content: "\F10CC"; +} + +.mdi-battery-alert-variant-outline::before { + content: "\F10CD"; +} + +.mdi-battery-bluetooth::before { + content: "\F0948"; +} + +.mdi-battery-bluetooth-variant::before { + content: "\F0949"; +} + +.mdi-battery-charging::before { + content: "\F0084"; +} + +.mdi-battery-charging-10::before { + content: "\F089C"; +} + +.mdi-battery-charging-100::before { + content: "\F0085"; +} + +.mdi-battery-charging-20::before { + content: "\F0086"; +} + +.mdi-battery-charging-30::before { + content: "\F0087"; +} + +.mdi-battery-charging-40::before { + content: "\F0088"; +} + +.mdi-battery-charging-50::before { + content: "\F089D"; +} + +.mdi-battery-charging-60::before { + content: "\F0089"; +} + +.mdi-battery-charging-70::before { + content: "\F089E"; +} + +.mdi-battery-charging-80::before { + content: "\F008A"; +} + +.mdi-battery-charging-90::before { + content: "\F008B"; +} + +.mdi-battery-charging-high::before { + content: "\F12A6"; +} + +.mdi-battery-charging-low::before { + content: "\F12A4"; +} + +.mdi-battery-charging-medium::before { + content: "\F12A5"; +} + +.mdi-battery-charging-outline::before { + content: "\F089F"; +} + +.mdi-battery-charging-wireless::before { + content: "\F0807"; +} + +.mdi-battery-charging-wireless-10::before { + content: "\F0808"; +} + +.mdi-battery-charging-wireless-20::before { + content: "\F0809"; +} + +.mdi-battery-charging-wireless-30::before { + content: "\F080A"; +} + +.mdi-battery-charging-wireless-40::before { + content: "\F080B"; +} + +.mdi-battery-charging-wireless-50::before { + content: "\F080C"; +} + +.mdi-battery-charging-wireless-60::before { + content: "\F080D"; +} + +.mdi-battery-charging-wireless-70::before { + content: "\F080E"; +} + +.mdi-battery-charging-wireless-80::before { + content: "\F080F"; +} + +.mdi-battery-charging-wireless-90::before { + content: "\F0810"; +} + +.mdi-battery-charging-wireless-alert::before { + content: "\F0811"; +} + +.mdi-battery-charging-wireless-outline::before { + content: "\F0812"; +} + +.mdi-battery-heart::before { + content: "\F120F"; +} + +.mdi-battery-heart-outline::before { + content: "\F1210"; +} + +.mdi-battery-heart-variant::before { + content: "\F1211"; +} + +.mdi-battery-high::before { + content: "\F12A3"; +} + +.mdi-battery-low::before { + content: "\F12A1"; +} + +.mdi-battery-medium::before { + content: "\F12A2"; +} + +.mdi-battery-minus::before { + content: "\F008C"; +} + +.mdi-battery-negative::before { + content: "\F008D"; +} + +.mdi-battery-off::before { + content: "\F125D"; +} + +.mdi-battery-off-outline::before { + content: "\F125E"; +} + +.mdi-battery-outline::before { + content: "\F008E"; +} + +.mdi-battery-plus::before { + content: "\F008F"; +} + +.mdi-battery-positive::before { + content: "\F0090"; +} + +.mdi-battery-unknown::before { + content: "\F0091"; +} + +.mdi-battery-unknown-bluetooth::before { + content: "\F094A"; +} + +.mdi-battlenet::before { + content: "\F0B60"; +} + +.mdi-beach::before { + content: "\F0092"; +} + +.mdi-beaker::before { + content: "\F0CEA"; +} + +.mdi-beaker-alert::before { + content: "\F1229"; +} + +.mdi-beaker-alert-outline::before { + content: "\F122A"; +} + +.mdi-beaker-check::before { + content: "\F122B"; +} + +.mdi-beaker-check-outline::before { + content: "\F122C"; +} + +.mdi-beaker-minus::before { + content: "\F122D"; +} + +.mdi-beaker-minus-outline::before { + content: "\F122E"; +} + +.mdi-beaker-outline::before { + content: "\F0690"; +} + +.mdi-beaker-plus::before { + content: "\F122F"; +} + +.mdi-beaker-plus-outline::before { + content: "\F1230"; +} + +.mdi-beaker-question::before { + content: "\F1231"; +} + +.mdi-beaker-question-outline::before { + content: "\F1232"; +} + +.mdi-beaker-remove::before { + content: "\F1233"; +} + +.mdi-beaker-remove-outline::before { + content: "\F1234"; +} + +.mdi-bed::before { + content: "\F02E3"; +} + +.mdi-bed-double::before { + content: "\F0FD4"; +} + +.mdi-bed-double-outline::before { + content: "\F0FD3"; +} + +.mdi-bed-empty::before { + content: "\F08A0"; +} + +.mdi-bed-king::before { + content: "\F0FD2"; +} + +.mdi-bed-king-outline::before { + content: "\F0FD1"; +} + +.mdi-bed-outline::before { + content: "\F0099"; +} + +.mdi-bed-queen::before { + content: "\F0FD0"; +} + +.mdi-bed-queen-outline::before { + content: "\F0FDB"; +} + +.mdi-bed-single::before { + content: "\F106D"; +} + +.mdi-bed-single-outline::before { + content: "\F106E"; +} + +.mdi-bee::before { + content: "\F0FA1"; +} + +.mdi-bee-flower::before { + content: "\F0FA2"; +} + +.mdi-beehive-off-outline::before { + content: "\F13ED"; +} + +.mdi-beehive-outline::before { + content: "\F10CE"; +} + +.mdi-beekeeper::before { + content: "\F14E2"; +} + +.mdi-beer::before { + content: "\F0098"; +} + +.mdi-beer-outline::before { + content: "\F130C"; +} + +.mdi-bell::before { + content: "\F009A"; +} + +.mdi-bell-alert::before { + content: "\F0D59"; +} + +.mdi-bell-alert-outline::before { + content: "\F0E81"; +} + +.mdi-bell-cancel::before { + content: "\F13E7"; +} + +.mdi-bell-cancel-outline::before { + content: "\F13E8"; +} + +.mdi-bell-check::before { + content: "\F11E5"; +} + +.mdi-bell-check-outline::before { + content: "\F11E6"; +} + +.mdi-bell-circle::before { + content: "\F0D5A"; +} + +.mdi-bell-circle-outline::before { + content: "\F0D5B"; +} + +.mdi-bell-minus::before { + content: "\F13E9"; +} + +.mdi-bell-minus-outline::before { + content: "\F13EA"; +} + +.mdi-bell-off::before { + content: "\F009B"; +} + +.mdi-bell-off-outline::before { + content: "\F0A91"; +} + +.mdi-bell-outline::before { + content: "\F009C"; +} + +.mdi-bell-plus::before { + content: "\F009D"; +} + +.mdi-bell-plus-outline::before { + content: "\F0A92"; +} + +.mdi-bell-remove::before { + content: "\F13EB"; +} + +.mdi-bell-remove-outline::before { + content: "\F13EC"; +} + +.mdi-bell-ring::before { + content: "\F009E"; +} + +.mdi-bell-ring-outline::before { + content: "\F009F"; +} + +.mdi-bell-sleep::before { + content: "\F00A0"; +} + +.mdi-bell-sleep-outline::before { + content: "\F0A93"; +} + +.mdi-beta::before { + content: "\F00A1"; +} + +.mdi-betamax::before { + content: "\F09CB"; +} + +.mdi-biathlon::before { + content: "\F0E14"; +} + +.mdi-bicycle::before { + content: "\F109C"; +} + +.mdi-bicycle-basket::before { + content: "\F1235"; +} + +.mdi-bicycle-electric::before { + content: "\F15B4"; +} + +.mdi-bicycle-penny-farthing::before { + content: "\F15E9"; +} + +.mdi-bike::before { + content: "\F00A3"; +} + +.mdi-bike-fast::before { + content: "\F111F"; +} + +.mdi-billboard::before { + content: "\F1010"; +} + +.mdi-billiards::before { + content: "\F0B61"; +} + +.mdi-billiards-rack::before { + content: "\F0B62"; +} + +.mdi-binoculars::before { + content: "\F00A5"; +} + +.mdi-bio::before { + content: "\F00A6"; +} + +.mdi-biohazard::before { + content: "\F00A7"; +} + +.mdi-bird::before { + content: "\F15C6"; +} + +.mdi-bitbucket::before { + content: "\F00A8"; +} + +.mdi-bitcoin::before { + content: "\F0813"; +} + +.mdi-black-mesa::before { + content: "\F00A9"; +} + +.mdi-blender::before { + content: "\F0CEB"; +} + +.mdi-blender-software::before { + content: "\F00AB"; +} + +.mdi-blinds::before { + content: "\F00AC"; +} + +.mdi-blinds-open::before { + content: "\F1011"; +} + +.mdi-block-helper::before { + content: "\F00AD"; +} + +.mdi-blogger::before { + content: "\F00AE"; +} + +.mdi-blood-bag::before { + content: "\F0CEC"; +} + +.mdi-bluetooth::before { + content: "\F00AF"; +} + +.mdi-bluetooth-audio::before { + content: "\F00B0"; +} + +.mdi-bluetooth-connect::before { + content: "\F00B1"; +} + +.mdi-bluetooth-off::before { + content: "\F00B2"; +} + +.mdi-bluetooth-settings::before { + content: "\F00B3"; +} + +.mdi-bluetooth-transfer::before { + content: "\F00B4"; +} + +.mdi-blur::before { + content: "\F00B5"; +} + +.mdi-blur-linear::before { + content: "\F00B6"; +} + +.mdi-blur-off::before { + content: "\F00B7"; +} + +.mdi-blur-radial::before { + content: "\F00B8"; +} + +.mdi-bolnisi-cross::before { + content: "\F0CED"; +} + +.mdi-bolt::before { + content: "\F0DB3"; +} + +.mdi-bomb::before { + content: "\F0691"; +} + +.mdi-bomb-off::before { + content: "\F06C5"; +} + +.mdi-bone::before { + content: "\F00B9"; +} + +.mdi-book::before { + content: "\F00BA"; +} + +.mdi-book-account::before { + content: "\F13AD"; +} + +.mdi-book-account-outline::before { + content: "\F13AE"; +} + +.mdi-book-alert::before { + content: "\F167C"; +} + +.mdi-book-alert-outline::before { + content: "\F167D"; +} + +.mdi-book-alphabet::before { + content: "\F061D"; +} + +.mdi-book-arrow-down::before { + content: "\F167E"; +} + +.mdi-book-arrow-down-outline::before { + content: "\F167F"; +} + +.mdi-book-arrow-left::before { + content: "\F1680"; +} + +.mdi-book-arrow-left-outline::before { + content: "\F1681"; +} + +.mdi-book-arrow-right::before { + content: "\F1682"; +} + +.mdi-book-arrow-right-outline::before { + content: "\F1683"; +} + +.mdi-book-arrow-up::before { + content: "\F1684"; +} + +.mdi-book-arrow-up-outline::before { + content: "\F1685"; +} + +.mdi-book-cancel::before { + content: "\F1686"; +} + +.mdi-book-cancel-outline::before { + content: "\F1687"; +} + +.mdi-book-check::before { + content: "\F14F3"; +} + +.mdi-book-check-outline::before { + content: "\F14F4"; +} + +.mdi-book-clock::before { + content: "\F1688"; +} + +.mdi-book-clock-outline::before { + content: "\F1689"; +} + +.mdi-book-cog::before { + content: "\F168A"; +} + +.mdi-book-cog-outline::before { + content: "\F168B"; +} + +.mdi-book-cross::before { + content: "\F00A2"; +} + +.mdi-book-edit::before { + content: "\F168C"; +} + +.mdi-book-edit-outline::before { + content: "\F168D"; +} + +.mdi-book-education::before { + content: "\F16C9"; +} + +.mdi-book-education-outline::before { + content: "\F16CA"; +} + +.mdi-book-information-variant::before { + content: "\F106F"; +} + +.mdi-book-lock::before { + content: "\F079A"; +} + +.mdi-book-lock-open::before { + content: "\F079B"; +} + +.mdi-book-lock-open-outline::before { + content: "\F168E"; +} + +.mdi-book-lock-outline::before { + content: "\F168F"; +} + +.mdi-book-marker::before { + content: "\F1690"; +} + +.mdi-book-marker-outline::before { + content: "\F1691"; +} + +.mdi-book-minus::before { + content: "\F05D9"; +} + +.mdi-book-minus-multiple::before { + content: "\F0A94"; +} + +.mdi-book-minus-multiple-outline::before { + content: "\F090B"; +} + +.mdi-book-minus-outline::before { + content: "\F1692"; +} + +.mdi-book-multiple::before { + content: "\F00BB"; +} + +.mdi-book-multiple-outline::before { + content: "\F0436"; +} + +.mdi-book-music::before { + content: "\F0067"; +} + +.mdi-book-music-outline::before { + content: "\F1693"; +} + +.mdi-book-off::before { + content: "\F1694"; +} + +.mdi-book-off-outline::before { + content: "\F1695"; +} + +.mdi-book-open::before { + content: "\F00BD"; +} + +.mdi-book-open-blank-variant::before { + content: "\F00BE"; +} + +.mdi-book-open-outline::before { + content: "\F0B63"; +} + +.mdi-book-open-page-variant::before { + content: "\F05DA"; +} + +.mdi-book-open-page-variant-outline::before { + content: "\F15D6"; +} + +.mdi-book-open-variant::before { + content: "\F14F7"; +} + +.mdi-book-outline::before { + content: "\F0B64"; +} + +.mdi-book-play::before { + content: "\F0E82"; +} + +.mdi-book-play-outline::before { + content: "\F0E83"; +} + +.mdi-book-plus::before { + content: "\F05DB"; +} + +.mdi-book-plus-multiple::before { + content: "\F0A95"; +} + +.mdi-book-plus-multiple-outline::before { + content: "\F0ADE"; +} + +.mdi-book-plus-outline::before { + content: "\F1696"; +} + +.mdi-book-refresh::before { + content: "\F1697"; +} + +.mdi-book-refresh-outline::before { + content: "\F1698"; +} + +.mdi-book-remove::before { + content: "\F0A97"; +} + +.mdi-book-remove-multiple::before { + content: "\F0A96"; +} + +.mdi-book-remove-multiple-outline::before { + content: "\F04CA"; +} + +.mdi-book-remove-outline::before { + content: "\F1699"; +} + +.mdi-book-search::before { + content: "\F0E84"; +} + +.mdi-book-search-outline::before { + content: "\F0E85"; +} + +.mdi-book-settings::before { + content: "\F169A"; +} + +.mdi-book-settings-outline::before { + content: "\F169B"; +} + +.mdi-book-sync::before { + content: "\F169C"; +} + +.mdi-book-sync-outline::before { + content: "\F16C8"; +} + +.mdi-book-variant::before { + content: "\F00BF"; +} + +.mdi-book-variant-multiple::before { + content: "\F00BC"; +} + +.mdi-bookmark::before { + content: "\F00C0"; +} + +.mdi-bookmark-check::before { + content: "\F00C1"; +} + +.mdi-bookmark-check-outline::before { + content: "\F137B"; +} + +.mdi-bookmark-minus::before { + content: "\F09CC"; +} + +.mdi-bookmark-minus-outline::before { + content: "\F09CD"; +} + +.mdi-bookmark-multiple::before { + content: "\F0E15"; +} + +.mdi-bookmark-multiple-outline::before { + content: "\F0E16"; +} + +.mdi-bookmark-music::before { + content: "\F00C2"; +} + +.mdi-bookmark-music-outline::before { + content: "\F1379"; +} + +.mdi-bookmark-off::before { + content: "\F09CE"; +} + +.mdi-bookmark-off-outline::before { + content: "\F09CF"; +} + +.mdi-bookmark-outline::before { + content: "\F00C3"; +} + +.mdi-bookmark-plus::before { + content: "\F00C5"; +} + +.mdi-bookmark-plus-outline::before { + content: "\F00C4"; +} + +.mdi-bookmark-remove::before { + content: "\F00C6"; +} + +.mdi-bookmark-remove-outline::before { + content: "\F137A"; +} + +.mdi-bookshelf::before { + content: "\F125F"; +} + +.mdi-boom-gate::before { + content: "\F0E86"; +} + +.mdi-boom-gate-alert::before { + content: "\F0E87"; +} + +.mdi-boom-gate-alert-outline::before { + content: "\F0E88"; +} + +.mdi-boom-gate-down::before { + content: "\F0E89"; +} + +.mdi-boom-gate-down-outline::before { + content: "\F0E8A"; +} + +.mdi-boom-gate-outline::before { + content: "\F0E8B"; +} + +.mdi-boom-gate-up::before { + content: "\F0E8C"; +} + +.mdi-boom-gate-up-outline::before { + content: "\F0E8D"; +} + +.mdi-boombox::before { + content: "\F05DC"; +} + +.mdi-boomerang::before { + content: "\F10CF"; +} + +.mdi-bootstrap::before { + content: "\F06C6"; +} + +.mdi-border-all::before { + content: "\F00C7"; +} + +.mdi-border-all-variant::before { + content: "\F08A1"; +} + +.mdi-border-bottom::before { + content: "\F00C8"; +} + +.mdi-border-bottom-variant::before { + content: "\F08A2"; +} + +.mdi-border-color::before { + content: "\F00C9"; +} + +.mdi-border-horizontal::before { + content: "\F00CA"; +} + +.mdi-border-inside::before { + content: "\F00CB"; +} + +.mdi-border-left::before { + content: "\F00CC"; +} + +.mdi-border-left-variant::before { + content: "\F08A3"; +} + +.mdi-border-none::before { + content: "\F00CD"; +} + +.mdi-border-none-variant::before { + content: "\F08A4"; +} + +.mdi-border-outside::before { + content: "\F00CE"; +} + +.mdi-border-right::before { + content: "\F00CF"; +} + +.mdi-border-right-variant::before { + content: "\F08A5"; +} + +.mdi-border-style::before { + content: "\F00D0"; +} + +.mdi-border-top::before { + content: "\F00D1"; +} + +.mdi-border-top-variant::before { + content: "\F08A6"; +} + +.mdi-border-vertical::before { + content: "\F00D2"; +} + +.mdi-bottle-soda::before { + content: "\F1070"; +} + +.mdi-bottle-soda-classic::before { + content: "\F1071"; +} + +.mdi-bottle-soda-classic-outline::before { + content: "\F1363"; +} + +.mdi-bottle-soda-outline::before { + content: "\F1072"; +} + +.mdi-bottle-tonic::before { + content: "\F112E"; +} + +.mdi-bottle-tonic-outline::before { + content: "\F112F"; +} + +.mdi-bottle-tonic-plus::before { + content: "\F1130"; +} + +.mdi-bottle-tonic-plus-outline::before { + content: "\F1131"; +} + +.mdi-bottle-tonic-skull::before { + content: "\F1132"; +} + +.mdi-bottle-tonic-skull-outline::before { + content: "\F1133"; +} + +.mdi-bottle-wine::before { + content: "\F0854"; +} + +.mdi-bottle-wine-outline::before { + content: "\F1310"; +} + +.mdi-bow-tie::before { + content: "\F0678"; +} + +.mdi-bowl::before { + content: "\F028E"; +} + +.mdi-bowl-mix::before { + content: "\F0617"; +} + +.mdi-bowl-mix-outline::before { + content: "\F02E4"; +} + +.mdi-bowl-outline::before { + content: "\F02A9"; +} + +.mdi-bowling::before { + content: "\F00D3"; +} + +.mdi-box::before { + content: "\F00D4"; +} + +.mdi-box-cutter::before { + content: "\F00D5"; +} + +.mdi-box-cutter-off::before { + content: "\F0B4A"; +} + +.mdi-box-shadow::before { + content: "\F0637"; +} + +.mdi-boxing-glove::before { + content: "\F0B65"; +} + +.mdi-braille::before { + content: "\F09D0"; +} + +.mdi-brain::before { + content: "\F09D1"; +} + +.mdi-bread-slice::before { + content: "\F0CEE"; +} + +.mdi-bread-slice-outline::before { + content: "\F0CEF"; +} + +.mdi-bridge::before { + content: "\F0618"; +} + +.mdi-briefcase::before { + content: "\F00D6"; +} + +.mdi-briefcase-account::before { + content: "\F0CF0"; +} + +.mdi-briefcase-account-outline::before { + content: "\F0CF1"; +} + +.mdi-briefcase-check::before { + content: "\F00D7"; +} + +.mdi-briefcase-check-outline::before { + content: "\F131E"; +} + +.mdi-briefcase-clock::before { + content: "\F10D0"; +} + +.mdi-briefcase-clock-outline::before { + content: "\F10D1"; +} + +.mdi-briefcase-download::before { + content: "\F00D8"; +} + +.mdi-briefcase-download-outline::before { + content: "\F0C3D"; +} + +.mdi-briefcase-edit::before { + content: "\F0A98"; +} + +.mdi-briefcase-edit-outline::before { + content: "\F0C3E"; +} + +.mdi-briefcase-minus::before { + content: "\F0A2A"; +} + +.mdi-briefcase-minus-outline::before { + content: "\F0C3F"; +} + +.mdi-briefcase-off::before { + content: "\F1658"; +} + +.mdi-briefcase-off-outline::before { + content: "\F1659"; +} + +.mdi-briefcase-outline::before { + content: "\F0814"; +} + +.mdi-briefcase-plus::before { + content: "\F0A2B"; +} + +.mdi-briefcase-plus-outline::before { + content: "\F0C40"; +} + +.mdi-briefcase-remove::before { + content: "\F0A2C"; +} + +.mdi-briefcase-remove-outline::before { + content: "\F0C41"; +} + +.mdi-briefcase-search::before { + content: "\F0A2D"; +} + +.mdi-briefcase-search-outline::before { + content: "\F0C42"; +} + +.mdi-briefcase-upload::before { + content: "\F00D9"; +} + +.mdi-briefcase-upload-outline::before { + content: "\F0C43"; +} + +.mdi-briefcase-variant::before { + content: "\F1494"; +} + +.mdi-briefcase-variant-off::before { + content: "\F165A"; +} + +.mdi-briefcase-variant-off-outline::before { + content: "\F165B"; +} + +.mdi-briefcase-variant-outline::before { + content: "\F1495"; +} + +.mdi-brightness-1::before { + content: "\F00DA"; +} + +.mdi-brightness-2::before { + content: "\F00DB"; +} + +.mdi-brightness-3::before { + content: "\F00DC"; +} + +.mdi-brightness-4::before { + content: "\F00DD"; +} + +.mdi-brightness-5::before { + content: "\F00DE"; +} + +.mdi-brightness-6::before { + content: "\F00DF"; +} + +.mdi-brightness-7::before { + content: "\F00E0"; +} + +.mdi-brightness-auto::before { + content: "\F00E1"; +} + +.mdi-brightness-percent::before { + content: "\F0CF2"; +} + +.mdi-broom::before { + content: "\F00E2"; +} + +.mdi-brush::before { + content: "\F00E3"; +} + +.mdi-bucket::before { + content: "\F1415"; +} + +.mdi-bucket-outline::before { + content: "\F1416"; +} + +.mdi-buddhism::before { + content: "\F094B"; +} + +.mdi-buffer::before { + content: "\F0619"; +} + +.mdi-buffet::before { + content: "\F0578"; +} + +.mdi-bug::before { + content: "\F00E4"; +} + +.mdi-bug-check::before { + content: "\F0A2E"; +} + +.mdi-bug-check-outline::before { + content: "\F0A2F"; +} + +.mdi-bug-outline::before { + content: "\F0A30"; +} + +.mdi-bugle::before { + content: "\F0DB4"; +} + +.mdi-bulldozer::before { + content: "\F0B22"; +} + +.mdi-bullet::before { + content: "\F0CF3"; +} + +.mdi-bulletin-board::before { + content: "\F00E5"; +} + +.mdi-bullhorn::before { + content: "\F00E6"; +} + +.mdi-bullhorn-outline::before { + content: "\F0B23"; +} + +.mdi-bullseye::before { + content: "\F05DD"; +} + +.mdi-bullseye-arrow::before { + content: "\F08C9"; +} + +.mdi-bulma::before { + content: "\F12E7"; +} + +.mdi-bunk-bed::before { + content: "\F1302"; +} + +.mdi-bunk-bed-outline::before { + content: "\F0097"; +} + +.mdi-bus::before { + content: "\F00E7"; +} + +.mdi-bus-alert::before { + content: "\F0A99"; +} + +.mdi-bus-articulated-end::before { + content: "\F079C"; +} + +.mdi-bus-articulated-front::before { + content: "\F079D"; +} + +.mdi-bus-clock::before { + content: "\F08CA"; +} + +.mdi-bus-double-decker::before { + content: "\F079E"; +} + +.mdi-bus-marker::before { + content: "\F1212"; +} + +.mdi-bus-multiple::before { + content: "\F0F3F"; +} + +.mdi-bus-school::before { + content: "\F079F"; +} + +.mdi-bus-side::before { + content: "\F07A0"; +} + +.mdi-bus-stop::before { + content: "\F1012"; +} + +.mdi-bus-stop-covered::before { + content: "\F1013"; +} + +.mdi-bus-stop-uncovered::before { + content: "\F1014"; +} + +.mdi-butterfly::before { + content: "\F1589"; +} + +.mdi-butterfly-outline::before { + content: "\F158A"; +} + +.mdi-cable-data::before { + content: "\F1394"; +} + +.mdi-cached::before { + content: "\F00E8"; +} + +.mdi-cactus::before { + content: "\F0DB5"; +} + +.mdi-cake::before { + content: "\F00E9"; +} + +.mdi-cake-layered::before { + content: "\F00EA"; +} + +.mdi-cake-variant::before { + content: "\F00EB"; +} + +.mdi-calculator::before { + content: "\F00EC"; +} + +.mdi-calculator-variant::before { + content: "\F0A9A"; +} + +.mdi-calculator-variant-outline::before { + content: "\F15A6"; +} + +.mdi-calendar::before { + content: "\F00ED"; +} + +.mdi-calendar-account::before { + content: "\F0ED7"; +} + +.mdi-calendar-account-outline::before { + content: "\F0ED8"; +} + +.mdi-calendar-alert::before { + content: "\F0A31"; +} + +.mdi-calendar-arrow-left::before { + content: "\F1134"; +} + +.mdi-calendar-arrow-right::before { + content: "\F1135"; +} + +.mdi-calendar-blank::before { + content: "\F00EE"; +} + +.mdi-calendar-blank-multiple::before { + content: "\F1073"; +} + +.mdi-calendar-blank-outline::before { + content: "\F0B66"; +} + +.mdi-calendar-check::before { + content: "\F00EF"; +} + +.mdi-calendar-check-outline::before { + content: "\F0C44"; +} + +.mdi-calendar-clock::before { + content: "\F00F0"; +} + +.mdi-calendar-cursor::before { + content: "\F157B"; +} + +.mdi-calendar-edit::before { + content: "\F08A7"; +} + +.mdi-calendar-end::before { + content: "\F166C"; +} + +.mdi-calendar-export::before { + content: "\F0B24"; +} + +.mdi-calendar-heart::before { + content: "\F09D2"; +} + +.mdi-calendar-import::before { + content: "\F0B25"; +} + +.mdi-calendar-lock::before { + content: "\F1641"; +} + +.mdi-calendar-lock-outline::before { + content: "\F1642"; +} + +.mdi-calendar-minus::before { + content: "\F0D5C"; +} + +.mdi-calendar-month::before { + content: "\F0E17"; +} + +.mdi-calendar-month-outline::before { + content: "\F0E18"; +} + +.mdi-calendar-multiple::before { + content: "\F00F1"; +} + +.mdi-calendar-multiple-check::before { + content: "\F00F2"; +} + +.mdi-calendar-multiselect::before { + content: "\F0A32"; +} + +.mdi-calendar-outline::before { + content: "\F0B67"; +} + +.mdi-calendar-plus::before { + content: "\F00F3"; +} + +.mdi-calendar-question::before { + content: "\F0692"; +} + +.mdi-calendar-range::before { + content: "\F0679"; +} + +.mdi-calendar-range-outline::before { + content: "\F0B68"; +} + +.mdi-calendar-refresh::before { + content: "\F01E1"; +} + +.mdi-calendar-refresh-outline::before { + content: "\F0203"; +} + +.mdi-calendar-remove::before { + content: "\F00F4"; +} + +.mdi-calendar-remove-outline::before { + content: "\F0C45"; +} + +.mdi-calendar-search::before { + content: "\F094C"; +} + +.mdi-calendar-star::before { + content: "\F09D3"; +} + +.mdi-calendar-start::before { + content: "\F166D"; +} + +.mdi-calendar-sync::before { + content: "\F0E8E"; +} + +.mdi-calendar-sync-outline::before { + content: "\F0E8F"; +} + +.mdi-calendar-text::before { + content: "\F00F5"; +} + +.mdi-calendar-text-outline::before { + content: "\F0C46"; +} + +.mdi-calendar-today::before { + content: "\F00F6"; +} + +.mdi-calendar-week::before { + content: "\F0A33"; +} + +.mdi-calendar-week-begin::before { + content: "\F0A34"; +} + +.mdi-calendar-weekend::before { + content: "\F0ED9"; +} + +.mdi-calendar-weekend-outline::before { + content: "\F0EDA"; +} + +.mdi-call-made::before { + content: "\F00F7"; +} + +.mdi-call-merge::before { + content: "\F00F8"; +} + +.mdi-call-missed::before { + content: "\F00F9"; +} + +.mdi-call-received::before { + content: "\F00FA"; +} + +.mdi-call-split::before { + content: "\F00FB"; +} + +.mdi-camcorder::before { + content: "\F00FC"; +} + +.mdi-camcorder-off::before { + content: "\F00FF"; +} + +.mdi-camera::before { + content: "\F0100"; +} + +.mdi-camera-account::before { + content: "\F08CB"; +} + +.mdi-camera-burst::before { + content: "\F0693"; +} + +.mdi-camera-control::before { + content: "\F0B69"; +} + +.mdi-camera-enhance::before { + content: "\F0101"; +} + +.mdi-camera-enhance-outline::before { + content: "\F0B6A"; +} + +.mdi-camera-flip::before { + content: "\F15D9"; +} + +.mdi-camera-flip-outline::before { + content: "\F15DA"; +} + +.mdi-camera-front::before { + content: "\F0102"; +} + +.mdi-camera-front-variant::before { + content: "\F0103"; +} + +.mdi-camera-gopro::before { + content: "\F07A1"; +} + +.mdi-camera-image::before { + content: "\F08CC"; +} + +.mdi-camera-iris::before { + content: "\F0104"; +} + +.mdi-camera-metering-center::before { + content: "\F07A2"; +} + +.mdi-camera-metering-matrix::before { + content: "\F07A3"; +} + +.mdi-camera-metering-partial::before { + content: "\F07A4"; +} + +.mdi-camera-metering-spot::before { + content: "\F07A5"; +} + +.mdi-camera-off::before { + content: "\F05DF"; +} + +.mdi-camera-outline::before { + content: "\F0D5D"; +} + +.mdi-camera-party-mode::before { + content: "\F0105"; +} + +.mdi-camera-plus::before { + content: "\F0EDB"; +} + +.mdi-camera-plus-outline::before { + content: "\F0EDC"; +} + +.mdi-camera-rear::before { + content: "\F0106"; +} + +.mdi-camera-rear-variant::before { + content: "\F0107"; +} + +.mdi-camera-retake::before { + content: "\F0E19"; +} + +.mdi-camera-retake-outline::before { + content: "\F0E1A"; +} + +.mdi-camera-switch::before { + content: "\F0108"; +} + +.mdi-camera-switch-outline::before { + content: "\F084A"; +} + +.mdi-camera-timer::before { + content: "\F0109"; +} + +.mdi-camera-wireless::before { + content: "\F0DB6"; +} + +.mdi-camera-wireless-outline::before { + content: "\F0DB7"; +} + +.mdi-campfire::before { + content: "\F0EDD"; +} + +.mdi-cancel::before { + content: "\F073A"; +} + +.mdi-candle::before { + content: "\F05E2"; +} + +.mdi-candycane::before { + content: "\F010A"; +} + +.mdi-cannabis::before { + content: "\F07A6"; +} + +.mdi-cannabis-off::before { + content: "\F166E"; +} + +.mdi-caps-lock::before { + content: "\F0A9B"; +} + +.mdi-car::before { + content: "\F010B"; +} + +.mdi-car-2-plus::before { + content: "\F1015"; +} + +.mdi-car-3-plus::before { + content: "\F1016"; +} + +.mdi-car-arrow-left::before { + content: "\F13B2"; +} + +.mdi-car-arrow-right::before { + content: "\F13B3"; +} + +.mdi-car-back::before { + content: "\F0E1B"; +} + +.mdi-car-battery::before { + content: "\F010C"; +} + +.mdi-car-brake-abs::before { + content: "\F0C47"; +} + +.mdi-car-brake-alert::before { + content: "\F0C48"; +} + +.mdi-car-brake-hold::before { + content: "\F0D5E"; +} + +.mdi-car-brake-parking::before { + content: "\F0D5F"; +} + +.mdi-car-brake-retarder::before { + content: "\F1017"; +} + +.mdi-car-child-seat::before { + content: "\F0FA3"; +} + +.mdi-car-clutch::before { + content: "\F1018"; +} + +.mdi-car-cog::before { + content: "\F13CC"; +} + +.mdi-car-connected::before { + content: "\F010D"; +} + +.mdi-car-convertible::before { + content: "\F07A7"; +} + +.mdi-car-coolant-level::before { + content: "\F1019"; +} + +.mdi-car-cruise-control::before { + content: "\F0D60"; +} + +.mdi-car-defrost-front::before { + content: "\F0D61"; +} + +.mdi-car-defrost-rear::before { + content: "\F0D62"; +} + +.mdi-car-door::before { + content: "\F0B6B"; +} + +.mdi-car-door-lock::before { + content: "\F109D"; +} + +.mdi-car-electric::before { + content: "\F0B6C"; +} + +.mdi-car-electric-outline::before { + content: "\F15B5"; +} + +.mdi-car-emergency::before { + content: "\F160F"; +} + +.mdi-car-esp::before { + content: "\F0C49"; +} + +.mdi-car-estate::before { + content: "\F07A8"; +} + +.mdi-car-hatchback::before { + content: "\F07A9"; +} + +.mdi-car-info::before { + content: "\F11BE"; +} + +.mdi-car-key::before { + content: "\F0B6D"; +} + +.mdi-car-lifted-pickup::before { + content: "\F152D"; +} + +.mdi-car-light-dimmed::before { + content: "\F0C4A"; +} + +.mdi-car-light-fog::before { + content: "\F0C4B"; +} + +.mdi-car-light-high::before { + content: "\F0C4C"; +} + +.mdi-car-limousine::before { + content: "\F08CD"; +} + +.mdi-car-multiple::before { + content: "\F0B6E"; +} + +.mdi-car-off::before { + content: "\F0E1C"; +} + +.mdi-car-outline::before { + content: "\F14ED"; +} + +.mdi-car-parking-lights::before { + content: "\F0D63"; +} + +.mdi-car-pickup::before { + content: "\F07AA"; +} + +.mdi-car-seat::before { + content: "\F0FA4"; +} + +.mdi-car-seat-cooler::before { + content: "\F0FA5"; +} + +.mdi-car-seat-heater::before { + content: "\F0FA6"; +} + +.mdi-car-settings::before { + content: "\F13CD"; +} + +.mdi-car-shift-pattern::before { + content: "\F0F40"; +} + +.mdi-car-side::before { + content: "\F07AB"; +} + +.mdi-car-sports::before { + content: "\F07AC"; +} + +.mdi-car-tire-alert::before { + content: "\F0C4D"; +} + +.mdi-car-traction-control::before { + content: "\F0D64"; +} + +.mdi-car-turbocharger::before { + content: "\F101A"; +} + +.mdi-car-wash::before { + content: "\F010E"; +} + +.mdi-car-windshield::before { + content: "\F101B"; +} + +.mdi-car-windshield-outline::before { + content: "\F101C"; +} + +.mdi-carabiner::before { + content: "\F14C0"; +} + +.mdi-caravan::before { + content: "\F07AD"; +} + +.mdi-card::before { + content: "\F0B6F"; +} + +.mdi-card-account-details::before { + content: "\F05D2"; +} + +.mdi-card-account-details-outline::before { + content: "\F0DAB"; +} + +.mdi-card-account-details-star::before { + content: "\F02A3"; +} + +.mdi-card-account-details-star-outline::before { + content: "\F06DB"; +} + +.mdi-card-account-mail::before { + content: "\F018E"; +} + +.mdi-card-account-mail-outline::before { + content: "\F0E98"; +} + +.mdi-card-account-phone::before { + content: "\F0E99"; +} + +.mdi-card-account-phone-outline::before { + content: "\F0E9A"; +} + +.mdi-card-bulleted::before { + content: "\F0B70"; +} + +.mdi-card-bulleted-off::before { + content: "\F0B71"; +} + +.mdi-card-bulleted-off-outline::before { + content: "\F0B72"; +} + +.mdi-card-bulleted-outline::before { + content: "\F0B73"; +} + +.mdi-card-bulleted-settings::before { + content: "\F0B74"; +} + +.mdi-card-bulleted-settings-outline::before { + content: "\F0B75"; +} + +.mdi-card-minus::before { + content: "\F1600"; +} + +.mdi-card-minus-outline::before { + content: "\F1601"; +} + +.mdi-card-off::before { + content: "\F1602"; +} + +.mdi-card-off-outline::before { + content: "\F1603"; +} + +.mdi-card-outline::before { + content: "\F0B76"; +} + +.mdi-card-plus::before { + content: "\F11FF"; +} + +.mdi-card-plus-outline::before { + content: "\F1200"; +} + +.mdi-card-remove::before { + content: "\F1604"; +} + +.mdi-card-remove-outline::before { + content: "\F1605"; +} + +.mdi-card-search::before { + content: "\F1074"; +} + +.mdi-card-search-outline::before { + content: "\F1075"; +} + +.mdi-card-text::before { + content: "\F0B77"; +} + +.mdi-card-text-outline::before { + content: "\F0B78"; +} + +.mdi-cards::before { + content: "\F0638"; +} + +.mdi-cards-club::before { + content: "\F08CE"; +} + +.mdi-cards-diamond::before { + content: "\F08CF"; +} + +.mdi-cards-diamond-outline::before { + content: "\F101D"; +} + +.mdi-cards-heart::before { + content: "\F08D0"; +} + +.mdi-cards-outline::before { + content: "\F0639"; +} + +.mdi-cards-playing-outline::before { + content: "\F063A"; +} + +.mdi-cards-spade::before { + content: "\F08D1"; +} + +.mdi-cards-variant::before { + content: "\F06C7"; +} + +.mdi-carrot::before { + content: "\F010F"; +} + +.mdi-cart::before { + content: "\F0110"; +} + +.mdi-cart-arrow-down::before { + content: "\F0D66"; +} + +.mdi-cart-arrow-right::before { + content: "\F0C4E"; +} + +.mdi-cart-arrow-up::before { + content: "\F0D67"; +} + +.mdi-cart-check::before { + content: "\F15EA"; +} + +.mdi-cart-minus::before { + content: "\F0D68"; +} + +.mdi-cart-off::before { + content: "\F066B"; +} + +.mdi-cart-outline::before { + content: "\F0111"; +} + +.mdi-cart-plus::before { + content: "\F0112"; +} + +.mdi-cart-remove::before { + content: "\F0D69"; +} + +.mdi-cart-variant::before { + content: "\F15EB"; +} + +.mdi-case-sensitive-alt::before { + content: "\F0113"; +} + +.mdi-cash::before { + content: "\F0114"; +} + +.mdi-cash-100::before { + content: "\F0115"; +} + +.mdi-cash-check::before { + content: "\F14EE"; +} + +.mdi-cash-lock::before { + content: "\F14EA"; +} + +.mdi-cash-lock-open::before { + content: "\F14EB"; +} + +.mdi-cash-marker::before { + content: "\F0DB8"; +} + +.mdi-cash-minus::before { + content: "\F1260"; +} + +.mdi-cash-multiple::before { + content: "\F0116"; +} + +.mdi-cash-plus::before { + content: "\F1261"; +} + +.mdi-cash-refund::before { + content: "\F0A9C"; +} + +.mdi-cash-register::before { + content: "\F0CF4"; +} + +.mdi-cash-remove::before { + content: "\F1262"; +} + +.mdi-cash-usd::before { + content: "\F1176"; +} + +.mdi-cash-usd-outline::before { + content: "\F0117"; +} + +.mdi-cassette::before { + content: "\F09D4"; +} + +.mdi-cast::before { + content: "\F0118"; +} + +.mdi-cast-audio::before { + content: "\F101E"; +} + +.mdi-cast-connected::before { + content: "\F0119"; +} + +.mdi-cast-education::before { + content: "\F0E1D"; +} + +.mdi-cast-off::before { + content: "\F078A"; +} + +.mdi-castle::before { + content: "\F011A"; +} + +.mdi-cat::before { + content: "\F011B"; +} + +.mdi-cctv::before { + content: "\F07AE"; +} + +.mdi-ceiling-light::before { + content: "\F0769"; +} + +.mdi-cellphone::before { + content: "\F011C"; +} + +.mdi-cellphone-android::before { + content: "\F011D"; +} + +.mdi-cellphone-arrow-down::before { + content: "\F09D5"; +} + +.mdi-cellphone-basic::before { + content: "\F011E"; +} + +.mdi-cellphone-charging::before { + content: "\F1397"; +} + +.mdi-cellphone-cog::before { + content: "\F0951"; +} + +.mdi-cellphone-dock::before { + content: "\F011F"; +} + +.mdi-cellphone-erase::before { + content: "\F094D"; +} + +.mdi-cellphone-information::before { + content: "\F0F41"; +} + +.mdi-cellphone-iphone::before { + content: "\F0120"; +} + +.mdi-cellphone-key::before { + content: "\F094E"; +} + +.mdi-cellphone-link::before { + content: "\F0121"; +} + +.mdi-cellphone-link-off::before { + content: "\F0122"; +} + +.mdi-cellphone-lock::before { + content: "\F094F"; +} + +.mdi-cellphone-message::before { + content: "\F08D3"; +} + +.mdi-cellphone-message-off::before { + content: "\F10D2"; +} + +.mdi-cellphone-nfc::before { + content: "\F0E90"; +} + +.mdi-cellphone-nfc-off::before { + content: "\F12D8"; +} + +.mdi-cellphone-off::before { + content: "\F0950"; +} + +.mdi-cellphone-play::before { + content: "\F101F"; +} + +.mdi-cellphone-screenshot::before { + content: "\F0A35"; +} + +.mdi-cellphone-settings::before { + content: "\F0123"; +} + +.mdi-cellphone-sound::before { + content: "\F0952"; +} + +.mdi-cellphone-text::before { + content: "\F08D2"; +} + +.mdi-cellphone-wireless::before { + content: "\F0815"; +} + +.mdi-celtic-cross::before { + content: "\F0CF5"; +} + +.mdi-centos::before { + content: "\F111A"; +} + +.mdi-certificate::before { + content: "\F0124"; +} + +.mdi-certificate-outline::before { + content: "\F1188"; +} + +.mdi-chair-rolling::before { + content: "\F0F48"; +} + +.mdi-chair-school::before { + content: "\F0125"; +} + +.mdi-charity::before { + content: "\F0C4F"; +} + +.mdi-chart-arc::before { + content: "\F0126"; +} + +.mdi-chart-areaspline::before { + content: "\F0127"; +} + +.mdi-chart-areaspline-variant::before { + content: "\F0E91"; +} + +.mdi-chart-bar::before { + content: "\F0128"; +} + +.mdi-chart-bar-stacked::before { + content: "\F076A"; +} + +.mdi-chart-bell-curve::before { + content: "\F0C50"; +} + +.mdi-chart-bell-curve-cumulative::before { + content: "\F0FA7"; +} + +.mdi-chart-box::before { + content: "\F154D"; +} + +.mdi-chart-box-outline::before { + content: "\F154E"; +} + +.mdi-chart-box-plus-outline::before { + content: "\F154F"; +} + +.mdi-chart-bubble::before { + content: "\F05E3"; +} + +.mdi-chart-donut::before { + content: "\F07AF"; +} + +.mdi-chart-donut-variant::before { + content: "\F07B0"; +} + +.mdi-chart-gantt::before { + content: "\F066C"; +} + +.mdi-chart-histogram::before { + content: "\F0129"; +} + +.mdi-chart-line::before { + content: "\F012A"; +} + +.mdi-chart-line-stacked::before { + content: "\F076B"; +} + +.mdi-chart-line-variant::before { + content: "\F07B1"; +} + +.mdi-chart-multiline::before { + content: "\F08D4"; +} + +.mdi-chart-multiple::before { + content: "\F1213"; +} + +.mdi-chart-pie::before { + content: "\F012B"; +} + +.mdi-chart-ppf::before { + content: "\F1380"; +} + +.mdi-chart-sankey::before { + content: "\F11DF"; +} + +.mdi-chart-sankey-variant::before { + content: "\F11E0"; +} + +.mdi-chart-scatter-plot::before { + content: "\F0E92"; +} + +.mdi-chart-scatter-plot-hexbin::before { + content: "\F066D"; +} + +.mdi-chart-timeline::before { + content: "\F066E"; +} + +.mdi-chart-timeline-variant::before { + content: "\F0E93"; +} + +.mdi-chart-timeline-variant-shimmer::before { + content: "\F15B6"; +} + +.mdi-chart-tree::before { + content: "\F0E94"; +} + +.mdi-chat::before { + content: "\F0B79"; +} + +.mdi-chat-alert::before { + content: "\F0B7A"; +} + +.mdi-chat-alert-outline::before { + content: "\F12C9"; +} + +.mdi-chat-minus::before { + content: "\F1410"; +} + +.mdi-chat-minus-outline::before { + content: "\F1413"; +} + +.mdi-chat-outline::before { + content: "\F0EDE"; +} + +.mdi-chat-plus::before { + content: "\F140F"; +} + +.mdi-chat-plus-outline::before { + content: "\F1412"; +} + +.mdi-chat-processing::before { + content: "\F0B7B"; +} + +.mdi-chat-processing-outline::before { + content: "\F12CA"; +} + +.mdi-chat-remove::before { + content: "\F1411"; +} + +.mdi-chat-remove-outline::before { + content: "\F1414"; +} + +.mdi-chat-sleep::before { + content: "\F12D1"; +} + +.mdi-chat-sleep-outline::before { + content: "\F12D2"; +} + +.mdi-check::before { + content: "\F012C"; +} + +.mdi-check-all::before { + content: "\F012D"; +} + +.mdi-check-bold::before { + content: "\F0E1E"; +} + +.mdi-check-box-multiple-outline::before { + content: "\F0C51"; +} + +.mdi-check-box-outline::before { + content: "\F0C52"; +} + +.mdi-check-circle::before { + content: "\F05E0"; +} + +.mdi-check-circle-outline::before { + content: "\F05E1"; +} + +.mdi-check-decagram::before { + content: "\F0791"; +} + +.mdi-check-network::before { + content: "\F0C53"; +} + +.mdi-check-network-outline::before { + content: "\F0C54"; +} + +.mdi-check-outline::before { + content: "\F0855"; +} + +.mdi-check-underline::before { + content: "\F0E1F"; +} + +.mdi-check-underline-circle::before { + content: "\F0E20"; +} + +.mdi-check-underline-circle-outline::before { + content: "\F0E21"; +} + +.mdi-checkbook::before { + content: "\F0A9D"; +} + +.mdi-checkbox-blank::before { + content: "\F012E"; +} + +.mdi-checkbox-blank-circle::before { + content: "\F012F"; +} + +.mdi-checkbox-blank-circle-outline::before { + content: "\F0130"; +} + +.mdi-checkbox-blank-off::before { + content: "\F12EC"; +} + +.mdi-checkbox-blank-off-outline::before { + content: "\F12ED"; +} + +.mdi-checkbox-blank-outline::before { + content: "\F0131"; +} + +.mdi-checkbox-intermediate::before { + content: "\F0856"; +} + +.mdi-checkbox-marked::before { + content: "\F0132"; +} + +.mdi-checkbox-marked-circle::before { + content: "\F0133"; +} + +.mdi-checkbox-marked-circle-outline::before { + content: "\F0134"; +} + +.mdi-checkbox-marked-outline::before { + content: "\F0135"; +} + +.mdi-checkbox-multiple-blank::before { + content: "\F0136"; +} + +.mdi-checkbox-multiple-blank-circle::before { + content: "\F063B"; +} + +.mdi-checkbox-multiple-blank-circle-outline::before { + content: "\F063C"; +} + +.mdi-checkbox-multiple-blank-outline::before { + content: "\F0137"; +} + +.mdi-checkbox-multiple-marked::before { + content: "\F0138"; +} + +.mdi-checkbox-multiple-marked-circle::before { + content: "\F063D"; +} + +.mdi-checkbox-multiple-marked-circle-outline::before { + content: "\F063E"; +} + +.mdi-checkbox-multiple-marked-outline::before { + content: "\F0139"; +} + +.mdi-checkerboard::before { + content: "\F013A"; +} + +.mdi-checkerboard-minus::before { + content: "\F1202"; +} + +.mdi-checkerboard-plus::before { + content: "\F1201"; +} + +.mdi-checkerboard-remove::before { + content: "\F1203"; +} + +.mdi-cheese::before { + content: "\F12B9"; +} + +.mdi-cheese-off::before { + content: "\F13EE"; +} + +.mdi-chef-hat::before { + content: "\F0B7C"; +} + +.mdi-chemical-weapon::before { + content: "\F013B"; +} + +.mdi-chess-bishop::before { + content: "\F085C"; +} + +.mdi-chess-king::before { + content: "\F0857"; +} + +.mdi-chess-knight::before { + content: "\F0858"; +} + +.mdi-chess-pawn::before { + content: "\F0859"; +} + +.mdi-chess-queen::before { + content: "\F085A"; +} + +.mdi-chess-rook::before { + content: "\F085B"; +} + +.mdi-chevron-double-down::before { + content: "\F013C"; +} + +.mdi-chevron-double-left::before { + content: "\F013D"; +} + +.mdi-chevron-double-right::before { + content: "\F013E"; +} + +.mdi-chevron-double-up::before { + content: "\F013F"; +} + +.mdi-chevron-down::before { + content: "\F0140"; +} + +.mdi-chevron-down-box::before { + content: "\F09D6"; +} + +.mdi-chevron-down-box-outline::before { + content: "\F09D7"; +} + +.mdi-chevron-down-circle::before { + content: "\F0B26"; +} + +.mdi-chevron-down-circle-outline::before { + content: "\F0B27"; +} + +.mdi-chevron-left::before { + content: "\F0141"; +} + +.mdi-chevron-left-box::before { + content: "\F09D8"; +} + +.mdi-chevron-left-box-outline::before { + content: "\F09D9"; +} + +.mdi-chevron-left-circle::before { + content: "\F0B28"; +} + +.mdi-chevron-left-circle-outline::before { + content: "\F0B29"; +} + +.mdi-chevron-right::before { + content: "\F0142"; +} + +.mdi-chevron-right-box::before { + content: "\F09DA"; +} + +.mdi-chevron-right-box-outline::before { + content: "\F09DB"; +} + +.mdi-chevron-right-circle::before { + content: "\F0B2A"; +} + +.mdi-chevron-right-circle-outline::before { + content: "\F0B2B"; +} + +.mdi-chevron-triple-down::before { + content: "\F0DB9"; +} + +.mdi-chevron-triple-left::before { + content: "\F0DBA"; +} + +.mdi-chevron-triple-right::before { + content: "\F0DBB"; +} + +.mdi-chevron-triple-up::before { + content: "\F0DBC"; +} + +.mdi-chevron-up::before { + content: "\F0143"; +} + +.mdi-chevron-up-box::before { + content: "\F09DC"; +} + +.mdi-chevron-up-box-outline::before { + content: "\F09DD"; +} + +.mdi-chevron-up-circle::before { + content: "\F0B2C"; +} + +.mdi-chevron-up-circle-outline::before { + content: "\F0B2D"; +} + +.mdi-chili-hot::before { + content: "\F07B2"; +} + +.mdi-chili-medium::before { + content: "\F07B3"; +} + +.mdi-chili-mild::before { + content: "\F07B4"; +} + +.mdi-chili-off::before { + content: "\F1467"; +} + +.mdi-chip::before { + content: "\F061A"; +} + +.mdi-christianity::before { + content: "\F0953"; +} + +.mdi-christianity-outline::before { + content: "\F0CF6"; +} + +.mdi-church::before { + content: "\F0144"; +} + +.mdi-cigar::before { + content: "\F1189"; +} + +.mdi-cigar-off::before { + content: "\F141B"; +} + +.mdi-circle::before { + content: "\F0765"; +} + +.mdi-circle-box::before { + content: "\F15DC"; +} + +.mdi-circle-box-outline::before { + content: "\F15DD"; +} + +.mdi-circle-double::before { + content: "\F0E95"; +} + +.mdi-circle-edit-outline::before { + content: "\F08D5"; +} + +.mdi-circle-expand::before { + content: "\F0E96"; +} + +.mdi-circle-half::before { + content: "\F1395"; +} + +.mdi-circle-half-full::before { + content: "\F1396"; +} + +.mdi-circle-medium::before { + content: "\F09DE"; +} + +.mdi-circle-multiple::before { + content: "\F0B38"; +} + +.mdi-circle-multiple-outline::before { + content: "\F0695"; +} + +.mdi-circle-off-outline::before { + content: "\F10D3"; +} + +.mdi-circle-outline::before { + content: "\F0766"; +} + +.mdi-circle-slice-1::before { + content: "\F0A9E"; +} + +.mdi-circle-slice-2::before { + content: "\F0A9F"; +} + +.mdi-circle-slice-3::before { + content: "\F0AA0"; +} + +.mdi-circle-slice-4::before { + content: "\F0AA1"; +} + +.mdi-circle-slice-5::before { + content: "\F0AA2"; +} + +.mdi-circle-slice-6::before { + content: "\F0AA3"; +} + +.mdi-circle-slice-7::before { + content: "\F0AA4"; +} + +.mdi-circle-slice-8::before { + content: "\F0AA5"; +} + +.mdi-circle-small::before { + content: "\F09DF"; +} + +.mdi-circular-saw::before { + content: "\F0E22"; +} + +.mdi-city::before { + content: "\F0146"; +} + +.mdi-city-variant::before { + content: "\F0A36"; +} + +.mdi-city-variant-outline::before { + content: "\F0A37"; +} + +.mdi-clipboard::before { + content: "\F0147"; +} + +.mdi-clipboard-account::before { + content: "\F0148"; +} + +.mdi-clipboard-account-outline::before { + content: "\F0C55"; +} + +.mdi-clipboard-alert::before { + content: "\F0149"; +} + +.mdi-clipboard-alert-outline::before { + content: "\F0CF7"; +} + +.mdi-clipboard-arrow-down::before { + content: "\F014A"; +} + +.mdi-clipboard-arrow-down-outline::before { + content: "\F0C56"; +} + +.mdi-clipboard-arrow-left::before { + content: "\F014B"; +} + +.mdi-clipboard-arrow-left-outline::before { + content: "\F0CF8"; +} + +.mdi-clipboard-arrow-right::before { + content: "\F0CF9"; +} + +.mdi-clipboard-arrow-right-outline::before { + content: "\F0CFA"; +} + +.mdi-clipboard-arrow-up::before { + content: "\F0C57"; +} + +.mdi-clipboard-arrow-up-outline::before { + content: "\F0C58"; +} + +.mdi-clipboard-check::before { + content: "\F014E"; +} + +.mdi-clipboard-check-multiple::before { + content: "\F1263"; +} + +.mdi-clipboard-check-multiple-outline::before { + content: "\F1264"; +} + +.mdi-clipboard-check-outline::before { + content: "\F08A8"; +} + +.mdi-clipboard-edit::before { + content: "\F14E5"; +} + +.mdi-clipboard-edit-outline::before { + content: "\F14E6"; +} + +.mdi-clipboard-file::before { + content: "\F1265"; +} + +.mdi-clipboard-file-outline::before { + content: "\F1266"; +} + +.mdi-clipboard-flow::before { + content: "\F06C8"; +} + +.mdi-clipboard-flow-outline::before { + content: "\F1117"; +} + +.mdi-clipboard-list::before { + content: "\F10D4"; +} + +.mdi-clipboard-list-outline::before { + content: "\F10D5"; +} + +.mdi-clipboard-minus::before { + content: "\F1618"; +} + +.mdi-clipboard-minus-outline::before { + content: "\F1619"; +} + +.mdi-clipboard-multiple::before { + content: "\F1267"; +} + +.mdi-clipboard-multiple-outline::before { + content: "\F1268"; +} + +.mdi-clipboard-off::before { + content: "\F161A"; +} + +.mdi-clipboard-off-outline::before { + content: "\F161B"; +} + +.mdi-clipboard-outline::before { + content: "\F014C"; +} + +.mdi-clipboard-play::before { + content: "\F0C59"; +} + +.mdi-clipboard-play-multiple::before { + content: "\F1269"; +} + +.mdi-clipboard-play-multiple-outline::before { + content: "\F126A"; +} + +.mdi-clipboard-play-outline::before { + content: "\F0C5A"; +} + +.mdi-clipboard-plus::before { + content: "\F0751"; +} + +.mdi-clipboard-plus-outline::before { + content: "\F131F"; +} + +.mdi-clipboard-pulse::before { + content: "\F085D"; +} + +.mdi-clipboard-pulse-outline::before { + content: "\F085E"; +} + +.mdi-clipboard-remove::before { + content: "\F161C"; +} + +.mdi-clipboard-remove-outline::before { + content: "\F161D"; +} + +.mdi-clipboard-search::before { + content: "\F161E"; +} + +.mdi-clipboard-search-outline::before { + content: "\F161F"; +} + +.mdi-clipboard-text::before { + content: "\F014D"; +} + +.mdi-clipboard-text-multiple::before { + content: "\F126B"; +} + +.mdi-clipboard-text-multiple-outline::before { + content: "\F126C"; +} + +.mdi-clipboard-text-off::before { + content: "\F1620"; +} + +.mdi-clipboard-text-off-outline::before { + content: "\F1621"; +} + +.mdi-clipboard-text-outline::before { + content: "\F0A38"; +} + +.mdi-clipboard-text-play::before { + content: "\F0C5B"; +} + +.mdi-clipboard-text-play-outline::before { + content: "\F0C5C"; +} + +.mdi-clipboard-text-search::before { + content: "\F1622"; +} + +.mdi-clipboard-text-search-outline::before { + content: "\F1623"; +} + +.mdi-clippy::before { + content: "\F014F"; +} + +.mdi-clock::before { + content: "\F0954"; +} + +.mdi-clock-alert::before { + content: "\F0955"; +} + +.mdi-clock-alert-outline::before { + content: "\F05CE"; +} + +.mdi-clock-check::before { + content: "\F0FA8"; +} + +.mdi-clock-check-outline::before { + content: "\F0FA9"; +} + +.mdi-clock-digital::before { + content: "\F0E97"; +} + +.mdi-clock-end::before { + content: "\F0151"; +} + +.mdi-clock-fast::before { + content: "\F0152"; +} + +.mdi-clock-in::before { + content: "\F0153"; +} + +.mdi-clock-out::before { + content: "\F0154"; +} + +.mdi-clock-outline::before { + content: "\F0150"; +} + +.mdi-clock-start::before { + content: "\F0155"; +} + +.mdi-clock-time-eight::before { + content: "\F1446"; +} + +.mdi-clock-time-eight-outline::before { + content: "\F1452"; +} + +.mdi-clock-time-eleven::before { + content: "\F1449"; +} + +.mdi-clock-time-eleven-outline::before { + content: "\F1455"; +} + +.mdi-clock-time-five::before { + content: "\F1443"; +} + +.mdi-clock-time-five-outline::before { + content: "\F144F"; +} + +.mdi-clock-time-four::before { + content: "\F1442"; +} + +.mdi-clock-time-four-outline::before { + content: "\F144E"; +} + +.mdi-clock-time-nine::before { + content: "\F1447"; +} + +.mdi-clock-time-nine-outline::before { + content: "\F1453"; +} + +.mdi-clock-time-one::before { + content: "\F143F"; +} + +.mdi-clock-time-one-outline::before { + content: "\F144B"; +} + +.mdi-clock-time-seven::before { + content: "\F1445"; +} + +.mdi-clock-time-seven-outline::before { + content: "\F1451"; +} + +.mdi-clock-time-six::before { + content: "\F1444"; +} + +.mdi-clock-time-six-outline::before { + content: "\F1450"; +} + +.mdi-clock-time-ten::before { + content: "\F1448"; +} + +.mdi-clock-time-ten-outline::before { + content: "\F1454"; +} + +.mdi-clock-time-three::before { + content: "\F1441"; +} + +.mdi-clock-time-three-outline::before { + content: "\F144D"; +} + +.mdi-clock-time-twelve::before { + content: "\F144A"; +} + +.mdi-clock-time-twelve-outline::before { + content: "\F1456"; +} + +.mdi-clock-time-two::before { + content: "\F1440"; +} + +.mdi-clock-time-two-outline::before { + content: "\F144C"; +} + +.mdi-close::before { + content: "\F0156"; +} + +.mdi-close-box::before { + content: "\F0157"; +} + +.mdi-close-box-multiple::before { + content: "\F0C5D"; +} + +.mdi-close-box-multiple-outline::before { + content: "\F0C5E"; +} + +.mdi-close-box-outline::before { + content: "\F0158"; +} + +.mdi-close-circle::before { + content: "\F0159"; +} + +.mdi-close-circle-multiple::before { + content: "\F062A"; +} + +.mdi-close-circle-multiple-outline::before { + content: "\F0883"; +} + +.mdi-close-circle-outline::before { + content: "\F015A"; +} + +.mdi-close-network::before { + content: "\F015B"; +} + +.mdi-close-network-outline::before { + content: "\F0C5F"; +} + +.mdi-close-octagon::before { + content: "\F015C"; +} + +.mdi-close-octagon-outline::before { + content: "\F015D"; +} + +.mdi-close-outline::before { + content: "\F06C9"; +} + +.mdi-close-thick::before { + content: "\F1398"; +} + +.mdi-closed-caption::before { + content: "\F015E"; +} + +.mdi-closed-caption-outline::before { + content: "\F0DBD"; +} + +.mdi-cloud::before { + content: "\F015F"; +} + +.mdi-cloud-alert::before { + content: "\F09E0"; +} + +.mdi-cloud-braces::before { + content: "\F07B5"; +} + +.mdi-cloud-check::before { + content: "\F0160"; +} + +.mdi-cloud-check-outline::before { + content: "\F12CC"; +} + +.mdi-cloud-circle::before { + content: "\F0161"; +} + +.mdi-cloud-download::before { + content: "\F0162"; +} + +.mdi-cloud-download-outline::before { + content: "\F0B7D"; +} + +.mdi-cloud-lock::before { + content: "\F11F1"; +} + +.mdi-cloud-lock-outline::before { + content: "\F11F2"; +} + +.mdi-cloud-off-outline::before { + content: "\F0164"; +} + +.mdi-cloud-outline::before { + content: "\F0163"; +} + +.mdi-cloud-print::before { + content: "\F0165"; +} + +.mdi-cloud-print-outline::before { + content: "\F0166"; +} + +.mdi-cloud-question::before { + content: "\F0A39"; +} + +.mdi-cloud-refresh::before { + content: "\F052A"; +} + +.mdi-cloud-search::before { + content: "\F0956"; +} + +.mdi-cloud-search-outline::before { + content: "\F0957"; +} + +.mdi-cloud-sync::before { + content: "\F063F"; +} + +.mdi-cloud-sync-outline::before { + content: "\F12D6"; +} + +.mdi-cloud-tags::before { + content: "\F07B6"; +} + +.mdi-cloud-upload::before { + content: "\F0167"; +} + +.mdi-cloud-upload-outline::before { + content: "\F0B7E"; +} + +.mdi-clover::before { + content: "\F0816"; +} + +.mdi-coach-lamp::before { + content: "\F1020"; +} + +.mdi-coat-rack::before { + content: "\F109E"; +} + +.mdi-code-array::before { + content: "\F0168"; +} + +.mdi-code-braces::before { + content: "\F0169"; +} + +.mdi-code-braces-box::before { + content: "\F10D6"; +} + +.mdi-code-brackets::before { + content: "\F016A"; +} + +.mdi-code-equal::before { + content: "\F016B"; +} + +.mdi-code-greater-than::before { + content: "\F016C"; +} + +.mdi-code-greater-than-or-equal::before { + content: "\F016D"; +} + +.mdi-code-json::before { + content: "\F0626"; +} + +.mdi-code-less-than::before { + content: "\F016E"; +} + +.mdi-code-less-than-or-equal::before { + content: "\F016F"; +} + +.mdi-code-not-equal::before { + content: "\F0170"; +} + +.mdi-code-not-equal-variant::before { + content: "\F0171"; +} + +.mdi-code-parentheses::before { + content: "\F0172"; +} + +.mdi-code-parentheses-box::before { + content: "\F10D7"; +} + +.mdi-code-string::before { + content: "\F0173"; +} + +.mdi-code-tags::before { + content: "\F0174"; +} + +.mdi-code-tags-check::before { + content: "\F0694"; +} + +.mdi-codepen::before { + content: "\F0175"; +} + +.mdi-coffee::before { + content: "\F0176"; +} + +.mdi-coffee-maker::before { + content: "\F109F"; +} + +.mdi-coffee-off::before { + content: "\F0FAA"; +} + +.mdi-coffee-off-outline::before { + content: "\F0FAB"; +} + +.mdi-coffee-outline::before { + content: "\F06CA"; +} + +.mdi-coffee-to-go::before { + content: "\F0177"; +} + +.mdi-coffee-to-go-outline::before { + content: "\F130E"; +} + +.mdi-coffin::before { + content: "\F0B7F"; +} + +.mdi-cog::before { + content: "\F0493"; +} + +.mdi-cog-box::before { + content: "\F0494"; +} + +.mdi-cog-clockwise::before { + content: "\F11DD"; +} + +.mdi-cog-counterclockwise::before { + content: "\F11DE"; +} + +.mdi-cog-off::before { + content: "\F13CE"; +} + +.mdi-cog-off-outline::before { + content: "\F13CF"; +} + +.mdi-cog-outline::before { + content: "\F08BB"; +} + +.mdi-cog-refresh::before { + content: "\F145E"; +} + +.mdi-cog-refresh-outline::before { + content: "\F145F"; +} + +.mdi-cog-sync::before { + content: "\F1460"; +} + +.mdi-cog-sync-outline::before { + content: "\F1461"; +} + +.mdi-cog-transfer::before { + content: "\F105B"; +} + +.mdi-cog-transfer-outline::before { + content: "\F105C"; +} + +.mdi-cogs::before { + content: "\F08D6"; +} + +.mdi-collage::before { + content: "\F0640"; +} + +.mdi-collapse-all::before { + content: "\F0AA6"; +} + +.mdi-collapse-all-outline::before { + content: "\F0AA7"; +} + +.mdi-color-helper::before { + content: "\F0179"; +} + +.mdi-comma::before { + content: "\F0E23"; +} + +.mdi-comma-box::before { + content: "\F0E2B"; +} + +.mdi-comma-box-outline::before { + content: "\F0E24"; +} + +.mdi-comma-circle::before { + content: "\F0E25"; +} + +.mdi-comma-circle-outline::before { + content: "\F0E26"; +} + +.mdi-comment::before { + content: "\F017A"; +} + +.mdi-comment-account::before { + content: "\F017B"; +} + +.mdi-comment-account-outline::before { + content: "\F017C"; +} + +.mdi-comment-alert::before { + content: "\F017D"; +} + +.mdi-comment-alert-outline::before { + content: "\F017E"; +} + +.mdi-comment-arrow-left::before { + content: "\F09E1"; +} + +.mdi-comment-arrow-left-outline::before { + content: "\F09E2"; +} + +.mdi-comment-arrow-right::before { + content: "\F09E3"; +} + +.mdi-comment-arrow-right-outline::before { + content: "\F09E4"; +} + +.mdi-comment-bookmark::before { + content: "\F15AE"; +} + +.mdi-comment-bookmark-outline::before { + content: "\F15AF"; +} + +.mdi-comment-check::before { + content: "\F017F"; +} + +.mdi-comment-check-outline::before { + content: "\F0180"; +} + +.mdi-comment-edit::before { + content: "\F11BF"; +} + +.mdi-comment-edit-outline::before { + content: "\F12C4"; +} + +.mdi-comment-eye::before { + content: "\F0A3A"; +} + +.mdi-comment-eye-outline::before { + content: "\F0A3B"; +} + +.mdi-comment-flash::before { + content: "\F15B0"; +} + +.mdi-comment-flash-outline::before { + content: "\F15B1"; +} + +.mdi-comment-minus::before { + content: "\F15DF"; +} + +.mdi-comment-minus-outline::before { + content: "\F15E0"; +} + +.mdi-comment-multiple::before { + content: "\F085F"; +} + +.mdi-comment-multiple-outline::before { + content: "\F0181"; +} + +.mdi-comment-off::before { + content: "\F15E1"; +} + +.mdi-comment-off-outline::before { + content: "\F15E2"; +} + +.mdi-comment-outline::before { + content: "\F0182"; +} + +.mdi-comment-plus::before { + content: "\F09E5"; +} + +.mdi-comment-plus-outline::before { + content: "\F0183"; +} + +.mdi-comment-processing::before { + content: "\F0184"; +} + +.mdi-comment-processing-outline::before { + content: "\F0185"; +} + +.mdi-comment-question::before { + content: "\F0817"; +} + +.mdi-comment-question-outline::before { + content: "\F0186"; +} + +.mdi-comment-quote::before { + content: "\F1021"; +} + +.mdi-comment-quote-outline::before { + content: "\F1022"; +} + +.mdi-comment-remove::before { + content: "\F05DE"; +} + +.mdi-comment-remove-outline::before { + content: "\F0187"; +} + +.mdi-comment-search::before { + content: "\F0A3C"; +} + +.mdi-comment-search-outline::before { + content: "\F0A3D"; +} + +.mdi-comment-text::before { + content: "\F0188"; +} + +.mdi-comment-text-multiple::before { + content: "\F0860"; +} + +.mdi-comment-text-multiple-outline::before { + content: "\F0861"; +} + +.mdi-comment-text-outline::before { + content: "\F0189"; +} + +.mdi-compare::before { + content: "\F018A"; +} + +.mdi-compare-horizontal::before { + content: "\F1492"; +} + +.mdi-compare-vertical::before { + content: "\F1493"; +} + +.mdi-compass::before { + content: "\F018B"; +} + +.mdi-compass-off::before { + content: "\F0B80"; +} + +.mdi-compass-off-outline::before { + content: "\F0B81"; +} + +.mdi-compass-outline::before { + content: "\F018C"; +} + +.mdi-compass-rose::before { + content: "\F1382"; +} + +.mdi-concourse-ci::before { + content: "\F10A0"; +} + +.mdi-connection::before { + content: "\F1616"; +} + +.mdi-console::before { + content: "\F018D"; +} + +.mdi-console-line::before { + content: "\F07B7"; +} + +.mdi-console-network::before { + content: "\F08A9"; +} + +.mdi-console-network-outline::before { + content: "\F0C60"; +} + +.mdi-consolidate::before { + content: "\F10D8"; +} + +.mdi-contactless-payment::before { + content: "\F0D6A"; +} + +.mdi-contactless-payment-circle::before { + content: "\F0321"; +} + +.mdi-contactless-payment-circle-outline::before { + content: "\F0408"; +} + +.mdi-contacts::before { + content: "\F06CB"; +} + +.mdi-contacts-outline::before { + content: "\F05B8"; +} + +.mdi-contain::before { + content: "\F0A3E"; +} + +.mdi-contain-end::before { + content: "\F0A3F"; +} + +.mdi-contain-start::before { + content: "\F0A40"; +} + +.mdi-content-copy::before { + content: "\F018F"; +} + +.mdi-content-cut::before { + content: "\F0190"; +} + +.mdi-content-duplicate::before { + content: "\F0191"; +} + +.mdi-content-paste::before { + content: "\F0192"; +} + +.mdi-content-save::before { + content: "\F0193"; +} + +.mdi-content-save-alert::before { + content: "\F0F42"; +} + +.mdi-content-save-alert-outline::before { + content: "\F0F43"; +} + +.mdi-content-save-all::before { + content: "\F0194"; +} + +.mdi-content-save-all-outline::before { + content: "\F0F44"; +} + +.mdi-content-save-cog::before { + content: "\F145B"; +} + +.mdi-content-save-cog-outline::before { + content: "\F145C"; +} + +.mdi-content-save-edit::before { + content: "\F0CFB"; +} + +.mdi-content-save-edit-outline::before { + content: "\F0CFC"; +} + +.mdi-content-save-move::before { + content: "\F0E27"; +} + +.mdi-content-save-move-outline::before { + content: "\F0E28"; +} + +.mdi-content-save-off::before { + content: "\F1643"; +} + +.mdi-content-save-off-outline::before { + content: "\F1644"; +} + +.mdi-content-save-outline::before { + content: "\F0818"; +} + +.mdi-content-save-settings::before { + content: "\F061B"; +} + +.mdi-content-save-settings-outline::before { + content: "\F0B2E"; +} + +.mdi-contrast::before { + content: "\F0195"; +} + +.mdi-contrast-box::before { + content: "\F0196"; +} + +.mdi-contrast-circle::before { + content: "\F0197"; +} + +.mdi-controller-classic::before { + content: "\F0B82"; +} + +.mdi-controller-classic-outline::before { + content: "\F0B83"; +} + +.mdi-cookie::before { + content: "\F0198"; +} + +.mdi-cookie-alert::before { + content: "\F16D0"; +} + +.mdi-cookie-alert-outline::before { + content: "\F16D1"; +} + +.mdi-cookie-check::before { + content: "\F16D2"; +} + +.mdi-cookie-check-outline::before { + content: "\F16D3"; +} + +.mdi-cookie-cog::before { + content: "\F16D4"; +} + +.mdi-cookie-cog-outline::before { + content: "\F16D5"; +} + +.mdi-cookie-minus::before { + content: "\F16DA"; +} + +.mdi-cookie-minus-outline::before { + content: "\F16DB"; +} + +.mdi-cookie-outline::before { + content: "\F16DE"; +} + +.mdi-cookie-plus::before { + content: "\F16D6"; +} + +.mdi-cookie-plus-outline::before { + content: "\F16D7"; +} + +.mdi-cookie-remove::before { + content: "\F16D8"; +} + +.mdi-cookie-remove-outline::before { + content: "\F16D9"; +} + +.mdi-cookie-settings::before { + content: "\F16DC"; +} + +.mdi-cookie-settings-outline::before { + content: "\F16DD"; +} + +.mdi-coolant-temperature::before { + content: "\F03C8"; +} + +.mdi-copyright::before { + content: "\F05E6"; +} + +.mdi-cordova::before { + content: "\F0958"; +} + +.mdi-corn::before { + content: "\F07B8"; +} + +.mdi-corn-off::before { + content: "\F13EF"; +} + +.mdi-cosine-wave::before { + content: "\F1479"; +} + +.mdi-counter::before { + content: "\F0199"; +} + +.mdi-cow::before { + content: "\F019A"; +} + +.mdi-cpu-32-bit::before { + content: "\F0EDF"; +} + +.mdi-cpu-64-bit::before { + content: "\F0EE0"; +} + +.mdi-crane::before { + content: "\F0862"; +} + +.mdi-creation::before { + content: "\F0674"; +} + +.mdi-creative-commons::before { + content: "\F0D6B"; +} + +.mdi-credit-card::before { + content: "\F0FEF"; +} + +.mdi-credit-card-check::before { + content: "\F13D0"; +} + +.mdi-credit-card-check-outline::before { + content: "\F13D1"; +} + +.mdi-credit-card-clock::before { + content: "\F0EE1"; +} + +.mdi-credit-card-clock-outline::before { + content: "\F0EE2"; +} + +.mdi-credit-card-marker::before { + content: "\F06A8"; +} + +.mdi-credit-card-marker-outline::before { + content: "\F0DBE"; +} + +.mdi-credit-card-minus::before { + content: "\F0FAC"; +} + +.mdi-credit-card-minus-outline::before { + content: "\F0FAD"; +} + +.mdi-credit-card-multiple::before { + content: "\F0FF0"; +} + +.mdi-credit-card-multiple-outline::before { + content: "\F019C"; +} + +.mdi-credit-card-off::before { + content: "\F0FF1"; +} + +.mdi-credit-card-off-outline::before { + content: "\F05E4"; +} + +.mdi-credit-card-outline::before { + content: "\F019B"; +} + +.mdi-credit-card-plus::before { + content: "\F0FF2"; +} + +.mdi-credit-card-plus-outline::before { + content: "\F0676"; +} + +.mdi-credit-card-refresh::before { + content: "\F1645"; +} + +.mdi-credit-card-refresh-outline::before { + content: "\F1646"; +} + +.mdi-credit-card-refund::before { + content: "\F0FF3"; +} + +.mdi-credit-card-refund-outline::before { + content: "\F0AA8"; +} + +.mdi-credit-card-remove::before { + content: "\F0FAE"; +} + +.mdi-credit-card-remove-outline::before { + content: "\F0FAF"; +} + +.mdi-credit-card-scan::before { + content: "\F0FF4"; +} + +.mdi-credit-card-scan-outline::before { + content: "\F019D"; +} + +.mdi-credit-card-search::before { + content: "\F1647"; +} + +.mdi-credit-card-search-outline::before { + content: "\F1648"; +} + +.mdi-credit-card-settings::before { + content: "\F0FF5"; +} + +.mdi-credit-card-settings-outline::before { + content: "\F08D7"; +} + +.mdi-credit-card-sync::before { + content: "\F1649"; +} + +.mdi-credit-card-sync-outline::before { + content: "\F164A"; +} + +.mdi-credit-card-wireless::before { + content: "\F0802"; +} + +.mdi-credit-card-wireless-off::before { + content: "\F057A"; +} + +.mdi-credit-card-wireless-off-outline::before { + content: "\F057B"; +} + +.mdi-credit-card-wireless-outline::before { + content: "\F0D6C"; +} + +.mdi-cricket::before { + content: "\F0D6D"; +} + +.mdi-crop::before { + content: "\F019E"; +} + +.mdi-crop-free::before { + content: "\F019F"; +} + +.mdi-crop-landscape::before { + content: "\F01A0"; +} + +.mdi-crop-portrait::before { + content: "\F01A1"; +} + +.mdi-crop-rotate::before { + content: "\F0696"; +} + +.mdi-crop-square::before { + content: "\F01A2"; +} + +.mdi-crosshairs::before { + content: "\F01A3"; +} + +.mdi-crosshairs-gps::before { + content: "\F01A4"; +} + +.mdi-crosshairs-off::before { + content: "\F0F45"; +} + +.mdi-crosshairs-question::before { + content: "\F1136"; +} + +.mdi-crown::before { + content: "\F01A5"; +} + +.mdi-crown-outline::before { + content: "\F11D0"; +} + +.mdi-cryengine::before { + content: "\F0959"; +} + +.mdi-crystal-ball::before { + content: "\F0B2F"; +} + +.mdi-cube::before { + content: "\F01A6"; +} + +.mdi-cube-off::before { + content: "\F141C"; +} + +.mdi-cube-off-outline::before { + content: "\F141D"; +} + +.mdi-cube-outline::before { + content: "\F01A7"; +} + +.mdi-cube-scan::before { + content: "\F0B84"; +} + +.mdi-cube-send::before { + content: "\F01A8"; +} + +.mdi-cube-unfolded::before { + content: "\F01A9"; +} + +.mdi-cup::before { + content: "\F01AA"; +} + +.mdi-cup-off::before { + content: "\F05E5"; +} + +.mdi-cup-off-outline::before { + content: "\F137D"; +} + +.mdi-cup-outline::before { + content: "\F130F"; +} + +.mdi-cup-water::before { + content: "\F01AB"; +} + +.mdi-cupboard::before { + content: "\F0F46"; +} + +.mdi-cupboard-outline::before { + content: "\F0F47"; +} + +.mdi-cupcake::before { + content: "\F095A"; +} + +.mdi-curling::before { + content: "\F0863"; +} + +.mdi-currency-bdt::before { + content: "\F0864"; +} + +.mdi-currency-brl::before { + content: "\F0B85"; +} + +.mdi-currency-btc::before { + content: "\F01AC"; +} + +.mdi-currency-cny::before { + content: "\F07BA"; +} + +.mdi-currency-eth::before { + content: "\F07BB"; +} + +.mdi-currency-eur::before { + content: "\F01AD"; +} + +.mdi-currency-eur-off::before { + content: "\F1315"; +} + +.mdi-currency-gbp::before { + content: "\F01AE"; +} + +.mdi-currency-ils::before { + content: "\F0C61"; +} + +.mdi-currency-inr::before { + content: "\F01AF"; +} + +.mdi-currency-jpy::before { + content: "\F07BC"; +} + +.mdi-currency-krw::before { + content: "\F07BD"; +} + +.mdi-currency-kzt::before { + content: "\F0865"; +} + +.mdi-currency-mnt::before { + content: "\F1512"; +} + +.mdi-currency-ngn::before { + content: "\F01B0"; +} + +.mdi-currency-php::before { + content: "\F09E6"; +} + +.mdi-currency-rial::before { + content: "\F0E9C"; +} + +.mdi-currency-rub::before { + content: "\F01B1"; +} + +.mdi-currency-sign::before { + content: "\F07BE"; +} + +.mdi-currency-try::before { + content: "\F01B2"; +} + +.mdi-currency-twd::before { + content: "\F07BF"; +} + +.mdi-currency-usd::before { + content: "\F01C1"; +} + +.mdi-currency-usd-circle::before { + content: "\F116B"; +} + +.mdi-currency-usd-circle-outline::before { + content: "\F0178"; +} + +.mdi-currency-usd-off::before { + content: "\F067A"; +} + +.mdi-current-ac::before { + content: "\F1480"; +} + +.mdi-current-dc::before { + content: "\F095C"; +} + +.mdi-cursor-default::before { + content: "\F01C0"; +} + +.mdi-cursor-default-click::before { + content: "\F0CFD"; +} + +.mdi-cursor-default-click-outline::before { + content: "\F0CFE"; +} + +.mdi-cursor-default-gesture::before { + content: "\F1127"; +} + +.mdi-cursor-default-gesture-outline::before { + content: "\F1128"; +} + +.mdi-cursor-default-outline::before { + content: "\F01BF"; +} + +.mdi-cursor-move::before { + content: "\F01BE"; +} + +.mdi-cursor-pointer::before { + content: "\F01BD"; +} + +.mdi-cursor-text::before { + content: "\F05E7"; +} + +.mdi-dance-ballroom::before { + content: "\F15FB"; +} + +.mdi-dance-pole::before { + content: "\F1578"; +} + +.mdi-data-matrix::before { + content: "\F153C"; +} + +.mdi-data-matrix-edit::before { + content: "\F153D"; +} + +.mdi-data-matrix-minus::before { + content: "\F153E"; +} + +.mdi-data-matrix-plus::before { + content: "\F153F"; +} + +.mdi-data-matrix-remove::before { + content: "\F1540"; +} + +.mdi-data-matrix-scan::before { + content: "\F1541"; +} + +.mdi-database::before { + content: "\F01BC"; +} + +.mdi-database-alert::before { + content: "\F163A"; +} + +.mdi-database-alert-outline::before { + content: "\F1624"; +} + +.mdi-database-arrow-down::before { + content: "\F163B"; +} + +.mdi-database-arrow-down-outline::before { + content: "\F1625"; +} + +.mdi-database-arrow-left::before { + content: "\F163C"; +} + +.mdi-database-arrow-left-outline::before { + content: "\F1626"; +} + +.mdi-database-arrow-right::before { + content: "\F163D"; +} + +.mdi-database-arrow-right-outline::before { + content: "\F1627"; +} + +.mdi-database-arrow-up::before { + content: "\F163E"; +} + +.mdi-database-arrow-up-outline::before { + content: "\F1628"; +} + +.mdi-database-check::before { + content: "\F0AA9"; +} + +.mdi-database-check-outline::before { + content: "\F1629"; +} + +.mdi-database-clock::before { + content: "\F163F"; +} + +.mdi-database-clock-outline::before { + content: "\F162A"; +} + +.mdi-database-cog::before { + content: "\F164B"; +} + +.mdi-database-cog-outline::before { + content: "\F164C"; +} + +.mdi-database-edit::before { + content: "\F0B86"; +} + +.mdi-database-edit-outline::before { + content: "\F162B"; +} + +.mdi-database-export::before { + content: "\F095E"; +} + +.mdi-database-export-outline::before { + content: "\F162C"; +} + +.mdi-database-import::before { + content: "\F095D"; +} + +.mdi-database-import-outline::before { + content: "\F162D"; +} + +.mdi-database-lock::before { + content: "\F0AAA"; +} + +.mdi-database-lock-outline::before { + content: "\F162E"; +} + +.mdi-database-marker::before { + content: "\F12F6"; +} + +.mdi-database-marker-outline::before { + content: "\F162F"; +} + +.mdi-database-minus::before { + content: "\F01BB"; +} + +.mdi-database-minus-outline::before { + content: "\F1630"; +} + +.mdi-database-off::before { + content: "\F1640"; +} + +.mdi-database-off-outline::before { + content: "\F1631"; +} + +.mdi-database-outline::before { + content: "\F1632"; +} + +.mdi-database-plus::before { + content: "\F01BA"; +} + +.mdi-database-plus-outline::before { + content: "\F1633"; +} + +.mdi-database-refresh::before { + content: "\F05C2"; +} + +.mdi-database-refresh-outline::before { + content: "\F1634"; +} + +.mdi-database-remove::before { + content: "\F0D00"; +} + +.mdi-database-remove-outline::before { + content: "\F1635"; +} + +.mdi-database-search::before { + content: "\F0866"; +} + +.mdi-database-search-outline::before { + content: "\F1636"; +} + +.mdi-database-settings::before { + content: "\F0D01"; +} + +.mdi-database-settings-outline::before { + content: "\F1637"; +} + +.mdi-database-sync::before { + content: "\F0CFF"; +} + +.mdi-database-sync-outline::before { + content: "\F1638"; +} + +.mdi-death-star::before { + content: "\F08D8"; +} + +.mdi-death-star-variant::before { + content: "\F08D9"; +} + +.mdi-deathly-hallows::before { + content: "\F0B87"; +} + +.mdi-debian::before { + content: "\F08DA"; +} + +.mdi-debug-step-into::before { + content: "\F01B9"; +} + +.mdi-debug-step-out::before { + content: "\F01B8"; +} + +.mdi-debug-step-over::before { + content: "\F01B7"; +} + +.mdi-decagram::before { + content: "\F076C"; +} + +.mdi-decagram-outline::before { + content: "\F076D"; +} + +.mdi-decimal::before { + content: "\F10A1"; +} + +.mdi-decimal-comma::before { + content: "\F10A2"; +} + +.mdi-decimal-comma-decrease::before { + content: "\F10A3"; +} + +.mdi-decimal-comma-increase::before { + content: "\F10A4"; +} + +.mdi-decimal-decrease::before { + content: "\F01B6"; +} + +.mdi-decimal-increase::before { + content: "\F01B5"; +} + +.mdi-delete::before { + content: "\F01B4"; +} + +.mdi-delete-alert::before { + content: "\F10A5"; +} + +.mdi-delete-alert-outline::before { + content: "\F10A6"; +} + +.mdi-delete-circle::before { + content: "\F0683"; +} + +.mdi-delete-circle-outline::before { + content: "\F0B88"; +} + +.mdi-delete-clock::before { + content: "\F1556"; +} + +.mdi-delete-clock-outline::before { + content: "\F1557"; +} + +.mdi-delete-empty::before { + content: "\F06CC"; +} + +.mdi-delete-empty-outline::before { + content: "\F0E9D"; +} + +.mdi-delete-forever::before { + content: "\F05E8"; +} + +.mdi-delete-forever-outline::before { + content: "\F0B89"; +} + +.mdi-delete-off::before { + content: "\F10A7"; +} + +.mdi-delete-off-outline::before { + content: "\F10A8"; +} + +.mdi-delete-outline::before { + content: "\F09E7"; +} + +.mdi-delete-restore::before { + content: "\F0819"; +} + +.mdi-delete-sweep::before { + content: "\F05E9"; +} + +.mdi-delete-sweep-outline::before { + content: "\F0C62"; +} + +.mdi-delete-variant::before { + content: "\F01B3"; +} + +.mdi-delta::before { + content: "\F01C2"; +} + +.mdi-desk::before { + content: "\F1239"; +} + +.mdi-desk-lamp::before { + content: "\F095F"; +} + +.mdi-deskphone::before { + content: "\F01C3"; +} + +.mdi-desktop-classic::before { + content: "\F07C0"; +} + +.mdi-desktop-mac::before { + content: "\F01C4"; +} + +.mdi-desktop-mac-dashboard::before { + content: "\F09E8"; +} + +.mdi-desktop-tower::before { + content: "\F01C5"; +} + +.mdi-desktop-tower-monitor::before { + content: "\F0AAB"; +} + +.mdi-details::before { + content: "\F01C6"; +} + +.mdi-dev-to::before { + content: "\F0D6E"; +} + +.mdi-developer-board::before { + content: "\F0697"; +} + +.mdi-deviantart::before { + content: "\F01C7"; +} + +.mdi-devices::before { + content: "\F0FB0"; +} + +.mdi-diabetes::before { + content: "\F1126"; +} + +.mdi-dialpad::before { + content: "\F061C"; +} + +.mdi-diameter::before { + content: "\F0C63"; +} + +.mdi-diameter-outline::before { + content: "\F0C64"; +} + +.mdi-diameter-variant::before { + content: "\F0C65"; +} + +.mdi-diamond::before { + content: "\F0B8A"; +} + +.mdi-diamond-outline::before { + content: "\F0B8B"; +} + +.mdi-diamond-stone::before { + content: "\F01C8"; +} + +.mdi-dice-1::before { + content: "\F01CA"; +} + +.mdi-dice-1-outline::before { + content: "\F114A"; +} + +.mdi-dice-2::before { + content: "\F01CB"; +} + +.mdi-dice-2-outline::before { + content: "\F114B"; +} + +.mdi-dice-3::before { + content: "\F01CC"; +} + +.mdi-dice-3-outline::before { + content: "\F114C"; +} + +.mdi-dice-4::before { + content: "\F01CD"; +} + +.mdi-dice-4-outline::before { + content: "\F114D"; +} + +.mdi-dice-5::before { + content: "\F01CE"; +} + +.mdi-dice-5-outline::before { + content: "\F114E"; +} + +.mdi-dice-6::before { + content: "\F01CF"; +} + +.mdi-dice-6-outline::before { + content: "\F114F"; +} + +.mdi-dice-d10::before { + content: "\F1153"; +} + +.mdi-dice-d10-outline::before { + content: "\F076F"; +} + +.mdi-dice-d12::before { + content: "\F1154"; +} + +.mdi-dice-d12-outline::before { + content: "\F0867"; +} + +.mdi-dice-d20::before { + content: "\F1155"; +} + +.mdi-dice-d20-outline::before { + content: "\F05EA"; +} + +.mdi-dice-d4::before { + content: "\F1150"; +} + +.mdi-dice-d4-outline::before { + content: "\F05EB"; +} + +.mdi-dice-d6::before { + content: "\F1151"; +} + +.mdi-dice-d6-outline::before { + content: "\F05ED"; +} + +.mdi-dice-d8::before { + content: "\F1152"; +} + +.mdi-dice-d8-outline::before { + content: "\F05EC"; +} + +.mdi-dice-multiple::before { + content: "\F076E"; +} + +.mdi-dice-multiple-outline::before { + content: "\F1156"; +} + +.mdi-digital-ocean::before { + content: "\F1237"; +} + +.mdi-dip-switch::before { + content: "\F07C1"; +} + +.mdi-directions::before { + content: "\F01D0"; +} + +.mdi-directions-fork::before { + content: "\F0641"; +} + +.mdi-disc::before { + content: "\F05EE"; +} + +.mdi-disc-alert::before { + content: "\F01D1"; +} + +.mdi-disc-player::before { + content: "\F0960"; +} + +.mdi-discord::before { + content: "\F066F"; +} + +.mdi-dishwasher::before { + content: "\F0AAC"; +} + +.mdi-dishwasher-alert::before { + content: "\F11B8"; +} + +.mdi-dishwasher-off::before { + content: "\F11B9"; +} + +.mdi-disqus::before { + content: "\F01D2"; +} + +.mdi-distribute-horizontal-center::before { + content: "\F11C9"; +} + +.mdi-distribute-horizontal-left::before { + content: "\F11C8"; +} + +.mdi-distribute-horizontal-right::before { + content: "\F11CA"; +} + +.mdi-distribute-vertical-bottom::before { + content: "\F11CB"; +} + +.mdi-distribute-vertical-center::before { + content: "\F11CC"; +} + +.mdi-distribute-vertical-top::before { + content: "\F11CD"; +} + +.mdi-diving-flippers::before { + content: "\F0DBF"; +} + +.mdi-diving-helmet::before { + content: "\F0DC0"; +} + +.mdi-diving-scuba::before { + content: "\F0DC1"; +} + +.mdi-diving-scuba-flag::before { + content: "\F0DC2"; +} + +.mdi-diving-scuba-tank::before { + content: "\F0DC3"; +} + +.mdi-diving-scuba-tank-multiple::before { + content: "\F0DC4"; +} + +.mdi-diving-snorkel::before { + content: "\F0DC5"; +} + +.mdi-division::before { + content: "\F01D4"; +} + +.mdi-division-box::before { + content: "\F01D5"; +} + +.mdi-dlna::before { + content: "\F0A41"; +} + +.mdi-dna::before { + content: "\F0684"; +} + +.mdi-dns::before { + content: "\F01D6"; +} + +.mdi-dns-outline::before { + content: "\F0B8C"; +} + +.mdi-do-not-disturb::before { + content: "\F0698"; +} + +.mdi-do-not-disturb-off::before { + content: "\F0699"; +} + +.mdi-dock-bottom::before { + content: "\F10A9"; +} + +.mdi-dock-left::before { + content: "\F10AA"; +} + +.mdi-dock-right::before { + content: "\F10AB"; +} + +.mdi-dock-top::before { + content: "\F1513"; +} + +.mdi-dock-window::before { + content: "\F10AC"; +} + +.mdi-docker::before { + content: "\F0868"; +} + +.mdi-doctor::before { + content: "\F0A42"; +} + +.mdi-dog::before { + content: "\F0A43"; +} + +.mdi-dog-service::before { + content: "\F0AAD"; +} + +.mdi-dog-side::before { + content: "\F0A44"; +} + +.mdi-dolby::before { + content: "\F06B3"; +} + +.mdi-dolly::before { + content: "\F0E9E"; +} + +.mdi-domain::before { + content: "\F01D7"; +} + +.mdi-domain-off::before { + content: "\F0D6F"; +} + +.mdi-domain-plus::before { + content: "\F10AD"; +} + +.mdi-domain-remove::before { + content: "\F10AE"; +} + +.mdi-dome-light::before { + content: "\F141E"; +} + +.mdi-domino-mask::before { + content: "\F1023"; +} + +.mdi-donkey::before { + content: "\F07C2"; +} + +.mdi-door::before { + content: "\F081A"; +} + +.mdi-door-closed::before { + content: "\F081B"; +} + +.mdi-door-closed-lock::before { + content: "\F10AF"; +} + +.mdi-door-open::before { + content: "\F081C"; +} + +.mdi-doorbell::before { + content: "\F12E6"; +} + +.mdi-doorbell-video::before { + content: "\F0869"; +} + +.mdi-dot-net::before { + content: "\F0AAE"; +} + +.mdi-dots-grid::before { + content: "\F15FC"; +} + +.mdi-dots-hexagon::before { + content: "\F15FF"; +} + +.mdi-dots-horizontal::before { + content: "\F01D8"; +} + +.mdi-dots-horizontal-circle::before { + content: "\F07C3"; +} + +.mdi-dots-horizontal-circle-outline::before { + content: "\F0B8D"; +} + +.mdi-dots-square::before { + content: "\F15FD"; +} + +.mdi-dots-triangle::before { + content: "\F15FE"; +} + +.mdi-dots-vertical::before { + content: "\F01D9"; +} + +.mdi-dots-vertical-circle::before { + content: "\F07C4"; +} + +.mdi-dots-vertical-circle-outline::before { + content: "\F0B8E"; +} + +.mdi-douban::before { + content: "\F069A"; +} + +.mdi-download::before { + content: "\F01DA"; +} + +.mdi-download-box::before { + content: "\F1462"; +} + +.mdi-download-box-outline::before { + content: "\F1463"; +} + +.mdi-download-circle::before { + content: "\F1464"; +} + +.mdi-download-circle-outline::before { + content: "\F1465"; +} + +.mdi-download-lock::before { + content: "\F1320"; +} + +.mdi-download-lock-outline::before { + content: "\F1321"; +} + +.mdi-download-multiple::before { + content: "\F09E9"; +} + +.mdi-download-network::before { + content: "\F06F4"; +} + +.mdi-download-network-outline::before { + content: "\F0C66"; +} + +.mdi-download-off::before { + content: "\F10B0"; +} + +.mdi-download-off-outline::before { + content: "\F10B1"; +} + +.mdi-download-outline::before { + content: "\F0B8F"; +} + +.mdi-drag::before { + content: "\F01DB"; +} + +.mdi-drag-horizontal::before { + content: "\F01DC"; +} + +.mdi-drag-horizontal-variant::before { + content: "\F12F0"; +} + +.mdi-drag-variant::before { + content: "\F0B90"; +} + +.mdi-drag-vertical::before { + content: "\F01DD"; +} + +.mdi-drag-vertical-variant::before { + content: "\F12F1"; +} + +.mdi-drama-masks::before { + content: "\F0D02"; +} + +.mdi-draw::before { + content: "\F0F49"; +} + +.mdi-drawing::before { + content: "\F01DE"; +} + +.mdi-drawing-box::before { + content: "\F01DF"; +} + +.mdi-dresser::before { + content: "\F0F4A"; +} + +.mdi-dresser-outline::before { + content: "\F0F4B"; +} + +.mdi-drone::before { + content: "\F01E2"; +} + +.mdi-dropbox::before { + content: "\F01E3"; +} + +.mdi-drupal::before { + content: "\F01E4"; +} + +.mdi-duck::before { + content: "\F01E5"; +} + +.mdi-dumbbell::before { + content: "\F01E6"; +} + +.mdi-dump-truck::before { + content: "\F0C67"; +} + +.mdi-ear-hearing::before { + content: "\F07C5"; +} + +.mdi-ear-hearing-off::before { + content: "\F0A45"; +} + +.mdi-earth::before { + content: "\F01E7"; +} + +.mdi-earth-arrow-right::before { + content: "\F1311"; +} + +.mdi-earth-box::before { + content: "\F06CD"; +} + +.mdi-earth-box-minus::before { + content: "\F1407"; +} + +.mdi-earth-box-off::before { + content: "\F06CE"; +} + +.mdi-earth-box-plus::before { + content: "\F1406"; +} + +.mdi-earth-box-remove::before { + content: "\F1408"; +} + +.mdi-earth-minus::before { + content: "\F1404"; +} + +.mdi-earth-off::before { + content: "\F01E8"; +} + +.mdi-earth-plus::before { + content: "\F1403"; +} + +.mdi-earth-remove::before { + content: "\F1405"; +} + +.mdi-egg::before { + content: "\F0AAF"; +} + +.mdi-egg-easter::before { + content: "\F0AB0"; +} + +.mdi-egg-off::before { + content: "\F13F0"; +} + +.mdi-egg-off-outline::before { + content: "\F13F1"; +} + +.mdi-egg-outline::before { + content: "\F13F2"; +} + +.mdi-eiffel-tower::before { + content: "\F156B"; +} + +.mdi-eight-track::before { + content: "\F09EA"; +} + +.mdi-eject::before { + content: "\F01EA"; +} + +.mdi-eject-outline::before { + content: "\F0B91"; +} + +.mdi-electric-switch::before { + content: "\F0E9F"; +} + +.mdi-electric-switch-closed::before { + content: "\F10D9"; +} + +.mdi-electron-framework::before { + content: "\F1024"; +} + +.mdi-elephant::before { + content: "\F07C6"; +} + +.mdi-elevation-decline::before { + content: "\F01EB"; +} + +.mdi-elevation-rise::before { + content: "\F01EC"; +} + +.mdi-elevator::before { + content: "\F01ED"; +} + +.mdi-elevator-down::before { + content: "\F12C2"; +} + +.mdi-elevator-passenger::before { + content: "\F1381"; +} + +.mdi-elevator-up::before { + content: "\F12C1"; +} + +.mdi-ellipse::before { + content: "\F0EA0"; +} + +.mdi-ellipse-outline::before { + content: "\F0EA1"; +} + +.mdi-email::before { + content: "\F01EE"; +} + +.mdi-email-alert::before { + content: "\F06CF"; +} + +.mdi-email-alert-outline::before { + content: "\F0D42"; +} + +.mdi-email-box::before { + content: "\F0D03"; +} + +.mdi-email-check::before { + content: "\F0AB1"; +} + +.mdi-email-check-outline::before { + content: "\F0AB2"; +} + +.mdi-email-edit::before { + content: "\F0EE3"; +} + +.mdi-email-edit-outline::before { + content: "\F0EE4"; +} + +.mdi-email-lock::before { + content: "\F01F1"; +} + +.mdi-email-mark-as-unread::before { + content: "\F0B92"; +} + +.mdi-email-minus::before { + content: "\F0EE5"; +} + +.mdi-email-minus-outline::before { + content: "\F0EE6"; +} + +.mdi-email-multiple::before { + content: "\F0EE7"; +} + +.mdi-email-multiple-outline::before { + content: "\F0EE8"; +} + +.mdi-email-newsletter::before { + content: "\F0FB1"; +} + +.mdi-email-off::before { + content: "\F13E3"; +} + +.mdi-email-off-outline::before { + content: "\F13E4"; +} + +.mdi-email-open::before { + content: "\F01EF"; +} + +.mdi-email-open-multiple::before { + content: "\F0EE9"; +} + +.mdi-email-open-multiple-outline::before { + content: "\F0EEA"; +} + +.mdi-email-open-outline::before { + content: "\F05EF"; +} + +.mdi-email-outline::before { + content: "\F01F0"; +} + +.mdi-email-plus::before { + content: "\F09EB"; +} + +.mdi-email-plus-outline::before { + content: "\F09EC"; +} + +.mdi-email-receive::before { + content: "\F10DA"; +} + +.mdi-email-receive-outline::before { + content: "\F10DB"; +} + +.mdi-email-remove::before { + content: "\F1661"; +} + +.mdi-email-remove-outline::before { + content: "\F1662"; +} + +.mdi-email-search::before { + content: "\F0961"; +} + +.mdi-email-search-outline::before { + content: "\F0962"; +} + +.mdi-email-send::before { + content: "\F10DC"; +} + +.mdi-email-send-outline::before { + content: "\F10DD"; +} + +.mdi-email-sync::before { + content: "\F12C7"; +} + +.mdi-email-sync-outline::before { + content: "\F12C8"; +} + +.mdi-email-variant::before { + content: "\F05F0"; +} + +.mdi-ember::before { + content: "\F0B30"; +} + +.mdi-emby::before { + content: "\F06B4"; +} + +.mdi-emoticon::before { + content: "\F0C68"; +} + +.mdi-emoticon-angry::before { + content: "\F0C69"; +} + +.mdi-emoticon-angry-outline::before { + content: "\F0C6A"; +} + +.mdi-emoticon-confused::before { + content: "\F10DE"; +} + +.mdi-emoticon-confused-outline::before { + content: "\F10DF"; +} + +.mdi-emoticon-cool::before { + content: "\F0C6B"; +} + +.mdi-emoticon-cool-outline::before { + content: "\F01F3"; +} + +.mdi-emoticon-cry::before { + content: "\F0C6C"; +} + +.mdi-emoticon-cry-outline::before { + content: "\F0C6D"; +} + +.mdi-emoticon-dead::before { + content: "\F0C6E"; +} + +.mdi-emoticon-dead-outline::before { + content: "\F069B"; +} + +.mdi-emoticon-devil::before { + content: "\F0C6F"; +} + +.mdi-emoticon-devil-outline::before { + content: "\F01F4"; +} + +.mdi-emoticon-excited::before { + content: "\F0C70"; +} + +.mdi-emoticon-excited-outline::before { + content: "\F069C"; +} + +.mdi-emoticon-frown::before { + content: "\F0F4C"; +} + +.mdi-emoticon-frown-outline::before { + content: "\F0F4D"; +} + +.mdi-emoticon-happy::before { + content: "\F0C71"; +} + +.mdi-emoticon-happy-outline::before { + content: "\F01F5"; +} + +.mdi-emoticon-kiss::before { + content: "\F0C72"; +} + +.mdi-emoticon-kiss-outline::before { + content: "\F0C73"; +} + +.mdi-emoticon-lol::before { + content: "\F1214"; +} + +.mdi-emoticon-lol-outline::before { + content: "\F1215"; +} + +.mdi-emoticon-neutral::before { + content: "\F0C74"; +} + +.mdi-emoticon-neutral-outline::before { + content: "\F01F6"; +} + +.mdi-emoticon-outline::before { + content: "\F01F2"; +} + +.mdi-emoticon-poop::before { + content: "\F01F7"; +} + +.mdi-emoticon-poop-outline::before { + content: "\F0C75"; +} + +.mdi-emoticon-sad::before { + content: "\F0C76"; +} + +.mdi-emoticon-sad-outline::before { + content: "\F01F8"; +} + +.mdi-emoticon-sick::before { + content: "\F157C"; +} + +.mdi-emoticon-sick-outline::before { + content: "\F157D"; +} + +.mdi-emoticon-tongue::before { + content: "\F01F9"; +} + +.mdi-emoticon-tongue-outline::before { + content: "\F0C77"; +} + +.mdi-emoticon-wink::before { + content: "\F0C78"; +} + +.mdi-emoticon-wink-outline::before { + content: "\F0C79"; +} + +.mdi-engine::before { + content: "\F01FA"; +} + +.mdi-engine-off::before { + content: "\F0A46"; +} + +.mdi-engine-off-outline::before { + content: "\F0A47"; +} + +.mdi-engine-outline::before { + content: "\F01FB"; +} + +.mdi-epsilon::before { + content: "\F10E0"; +} + +.mdi-equal::before { + content: "\F01FC"; +} + +.mdi-equal-box::before { + content: "\F01FD"; +} + +.mdi-equalizer::before { + content: "\F0EA2"; +} + +.mdi-equalizer-outline::before { + content: "\F0EA3"; +} + +.mdi-eraser::before { + content: "\F01FE"; +} + +.mdi-eraser-variant::before { + content: "\F0642"; +} + +.mdi-escalator::before { + content: "\F01FF"; +} + +.mdi-escalator-box::before { + content: "\F1399"; +} + +.mdi-escalator-down::before { + content: "\F12C0"; +} + +.mdi-escalator-up::before { + content: "\F12BF"; +} + +.mdi-eslint::before { + content: "\F0C7A"; +} + +.mdi-et::before { + content: "\F0AB3"; +} + +.mdi-ethereum::before { + content: "\F086A"; +} + +.mdi-ethernet::before { + content: "\F0200"; +} + +.mdi-ethernet-cable::before { + content: "\F0201"; +} + +.mdi-ethernet-cable-off::before { + content: "\F0202"; +} + +.mdi-ev-plug-ccs1::before { + content: "\F1519"; +} + +.mdi-ev-plug-ccs2::before { + content: "\F151A"; +} + +.mdi-ev-plug-chademo::before { + content: "\F151B"; +} + +.mdi-ev-plug-tesla::before { + content: "\F151C"; +} + +.mdi-ev-plug-type1::before { + content: "\F151D"; +} + +.mdi-ev-plug-type2::before { + content: "\F151E"; +} + +.mdi-ev-station::before { + content: "\F05F1"; +} + +.mdi-evernote::before { + content: "\F0204"; +} + +.mdi-excavator::before { + content: "\F1025"; +} + +.mdi-exclamation::before { + content: "\F0205"; +} + +.mdi-exclamation-thick::before { + content: "\F1238"; +} + +.mdi-exit-run::before { + content: "\F0A48"; +} + +.mdi-exit-to-app::before { + content: "\F0206"; +} + +.mdi-expand-all::before { + content: "\F0AB4"; +} + +.mdi-expand-all-outline::before { + content: "\F0AB5"; +} + +.mdi-expansion-card::before { + content: "\F08AE"; +} + +.mdi-expansion-card-variant::before { + content: "\F0FB2"; +} + +.mdi-exponent::before { + content: "\F0963"; +} + +.mdi-exponent-box::before { + content: "\F0964"; +} + +.mdi-export::before { + content: "\F0207"; +} + +.mdi-export-variant::before { + content: "\F0B93"; +} + +.mdi-eye::before { + content: "\F0208"; +} + +.mdi-eye-check::before { + content: "\F0D04"; +} + +.mdi-eye-check-outline::before { + content: "\F0D05"; +} + +.mdi-eye-circle::before { + content: "\F0B94"; +} + +.mdi-eye-circle-outline::before { + content: "\F0B95"; +} + +.mdi-eye-minus::before { + content: "\F1026"; +} + +.mdi-eye-minus-outline::before { + content: "\F1027"; +} + +.mdi-eye-off::before { + content: "\F0209"; +} + +.mdi-eye-off-outline::before { + content: "\F06D1"; +} + +.mdi-eye-outline::before { + content: "\F06D0"; +} + +.mdi-eye-plus::before { + content: "\F086B"; +} + +.mdi-eye-plus-outline::before { + content: "\F086C"; +} + +.mdi-eye-remove::before { + content: "\F15E3"; +} + +.mdi-eye-remove-outline::before { + content: "\F15E4"; +} + +.mdi-eye-settings::before { + content: "\F086D"; +} + +.mdi-eye-settings-outline::before { + content: "\F086E"; +} + +.mdi-eyedropper::before { + content: "\F020A"; +} + +.mdi-eyedropper-minus::before { + content: "\F13DD"; +} + +.mdi-eyedropper-off::before { + content: "\F13DF"; +} + +.mdi-eyedropper-plus::before { + content: "\F13DC"; +} + +.mdi-eyedropper-remove::before { + content: "\F13DE"; +} + +.mdi-eyedropper-variant::before { + content: "\F020B"; +} + +.mdi-face::before { + content: "\F0643"; +} + +.mdi-face-agent::before { + content: "\F0D70"; +} + +.mdi-face-mask::before { + content: "\F1586"; +} + +.mdi-face-mask-outline::before { + content: "\F1587"; +} + +.mdi-face-outline::before { + content: "\F0B96"; +} + +.mdi-face-profile::before { + content: "\F0644"; +} + +.mdi-face-profile-woman::before { + content: "\F1076"; +} + +.mdi-face-recognition::before { + content: "\F0C7B"; +} + +.mdi-face-shimmer::before { + content: "\F15CC"; +} + +.mdi-face-shimmer-outline::before { + content: "\F15CD"; +} + +.mdi-face-woman::before { + content: "\F1077"; +} + +.mdi-face-woman-outline::before { + content: "\F1078"; +} + +.mdi-face-woman-shimmer::before { + content: "\F15CE"; +} + +.mdi-face-woman-shimmer-outline::before { + content: "\F15CF"; +} + +.mdi-facebook::before { + content: "\F020C"; +} + +.mdi-facebook-gaming::before { + content: "\F07DD"; +} + +.mdi-facebook-messenger::before { + content: "\F020E"; +} + +.mdi-facebook-workplace::before { + content: "\F0B31"; +} + +.mdi-factory::before { + content: "\F020F"; +} + +.mdi-family-tree::before { + content: "\F160E"; +} + +.mdi-fan::before { + content: "\F0210"; +} + +.mdi-fan-alert::before { + content: "\F146C"; +} + +.mdi-fan-chevron-down::before { + content: "\F146D"; +} + +.mdi-fan-chevron-up::before { + content: "\F146E"; +} + +.mdi-fan-minus::before { + content: "\F1470"; +} + +.mdi-fan-off::before { + content: "\F081D"; +} + +.mdi-fan-plus::before { + content: "\F146F"; +} + +.mdi-fan-remove::before { + content: "\F1471"; +} + +.mdi-fan-speed-1::before { + content: "\F1472"; +} + +.mdi-fan-speed-2::before { + content: "\F1473"; +} + +.mdi-fan-speed-3::before { + content: "\F1474"; +} + +.mdi-fast-forward::before { + content: "\F0211"; +} + +.mdi-fast-forward-10::before { + content: "\F0D71"; +} + +.mdi-fast-forward-30::before { + content: "\F0D06"; +} + +.mdi-fast-forward-5::before { + content: "\F11F8"; +} + +.mdi-fast-forward-60::before { + content: "\F160B"; +} + +.mdi-fast-forward-outline::before { + content: "\F06D2"; +} + +.mdi-fax::before { + content: "\F0212"; +} + +.mdi-feather::before { + content: "\F06D3"; +} + +.mdi-feature-search::before { + content: "\F0A49"; +} + +.mdi-feature-search-outline::before { + content: "\F0A4A"; +} + +.mdi-fedora::before { + content: "\F08DB"; +} + +.mdi-fencing::before { + content: "\F14C1"; +} + +.mdi-ferris-wheel::before { + content: "\F0EA4"; +} + +.mdi-ferry::before { + content: "\F0213"; +} + +.mdi-file::before { + content: "\F0214"; +} + +.mdi-file-account::before { + content: "\F073B"; +} + +.mdi-file-account-outline::before { + content: "\F1028"; +} + +.mdi-file-alert::before { + content: "\F0A4B"; +} + +.mdi-file-alert-outline::before { + content: "\F0A4C"; +} + +.mdi-file-cabinet::before { + content: "\F0AB6"; +} + +.mdi-file-cad::before { + content: "\F0EEB"; +} + +.mdi-file-cad-box::before { + content: "\F0EEC"; +} + +.mdi-file-cancel::before { + content: "\F0DC6"; +} + +.mdi-file-cancel-outline::before { + content: "\F0DC7"; +} + +.mdi-file-certificate::before { + content: "\F1186"; +} + +.mdi-file-certificate-outline::before { + content: "\F1187"; +} + +.mdi-file-chart::before { + content: "\F0215"; +} + +.mdi-file-chart-outline::before { + content: "\F1029"; +} + +.mdi-file-check::before { + content: "\F0216"; +} + +.mdi-file-check-outline::before { + content: "\F0E29"; +} + +.mdi-file-clock::before { + content: "\F12E1"; +} + +.mdi-file-clock-outline::before { + content: "\F12E2"; +} + +.mdi-file-cloud::before { + content: "\F0217"; +} + +.mdi-file-cloud-outline::before { + content: "\F102A"; +} + +.mdi-file-code::before { + content: "\F022E"; +} + +.mdi-file-code-outline::before { + content: "\F102B"; +} + +.mdi-file-cog::before { + content: "\F107B"; +} + +.mdi-file-cog-outline::before { + content: "\F107C"; +} + +.mdi-file-compare::before { + content: "\F08AA"; +} + +.mdi-file-delimited::before { + content: "\F0218"; +} + +.mdi-file-delimited-outline::before { + content: "\F0EA5"; +} + +.mdi-file-document::before { + content: "\F0219"; +} + +.mdi-file-document-edit::before { + content: "\F0DC8"; +} + +.mdi-file-document-edit-outline::before { + content: "\F0DC9"; +} + +.mdi-file-document-multiple::before { + content: "\F1517"; +} + +.mdi-file-document-multiple-outline::before { + content: "\F1518"; +} + +.mdi-file-document-outline::before { + content: "\F09EE"; +} + +.mdi-file-download::before { + content: "\F0965"; +} + +.mdi-file-download-outline::before { + content: "\F0966"; +} + +.mdi-file-edit::before { + content: "\F11E7"; +} + +.mdi-file-edit-outline::before { + content: "\F11E8"; +} + +.mdi-file-excel::before { + content: "\F021B"; +} + +.mdi-file-excel-box::before { + content: "\F021C"; +} + +.mdi-file-excel-box-outline::before { + content: "\F102C"; +} + +.mdi-file-excel-outline::before { + content: "\F102D"; +} + +.mdi-file-export::before { + content: "\F021D"; +} + +.mdi-file-export-outline::before { + content: "\F102E"; +} + +.mdi-file-eye::before { + content: "\F0DCA"; +} + +.mdi-file-eye-outline::before { + content: "\F0DCB"; +} + +.mdi-file-find::before { + content: "\F021E"; +} + +.mdi-file-find-outline::before { + content: "\F0B97"; +} + +.mdi-file-hidden::before { + content: "\F0613"; +} + +.mdi-file-image::before { + content: "\F021F"; +} + +.mdi-file-image-outline::before { + content: "\F0EB0"; +} + +.mdi-file-import::before { + content: "\F0220"; +} + +.mdi-file-import-outline::before { + content: "\F102F"; +} + +.mdi-file-key::before { + content: "\F1184"; +} + +.mdi-file-key-outline::before { + content: "\F1185"; +} + +.mdi-file-link::before { + content: "\F1177"; +} + +.mdi-file-link-outline::before { + content: "\F1178"; +} + +.mdi-file-lock::before { + content: "\F0221"; +} + +.mdi-file-lock-outline::before { + content: "\F1030"; +} + +.mdi-file-move::before { + content: "\F0AB9"; +} + +.mdi-file-move-outline::before { + content: "\F1031"; +} + +.mdi-file-multiple::before { + content: "\F0222"; +} + +.mdi-file-multiple-outline::before { + content: "\F1032"; +} + +.mdi-file-music::before { + content: "\F0223"; +} + +.mdi-file-music-outline::before { + content: "\F0E2A"; +} + +.mdi-file-outline::before { + content: "\F0224"; +} + +.mdi-file-pdf::before { + content: "\F0225"; +} + +.mdi-file-pdf-box::before { + content: "\F0226"; +} + +.mdi-file-pdf-box-outline::before { + content: "\F0FB3"; +} + +.mdi-file-pdf-outline::before { + content: "\F0E2D"; +} + +.mdi-file-percent::before { + content: "\F081E"; +} + +.mdi-file-percent-outline::before { + content: "\F1033"; +} + +.mdi-file-phone::before { + content: "\F1179"; +} + +.mdi-file-phone-outline::before { + content: "\F117A"; +} + +.mdi-file-plus::before { + content: "\F0752"; +} + +.mdi-file-plus-outline::before { + content: "\F0EED"; +} + +.mdi-file-powerpoint::before { + content: "\F0227"; +} + +.mdi-file-powerpoint-box::before { + content: "\F0228"; +} + +.mdi-file-powerpoint-box-outline::before { + content: "\F1034"; +} + +.mdi-file-powerpoint-outline::before { + content: "\F1035"; +} + +.mdi-file-presentation-box::before { + content: "\F0229"; +} + +.mdi-file-question::before { + content: "\F086F"; +} + +.mdi-file-question-outline::before { + content: "\F1036"; +} + +.mdi-file-refresh::before { + content: "\F0918"; +} + +.mdi-file-refresh-outline::before { + content: "\F0541"; +} + +.mdi-file-remove::before { + content: "\F0B98"; +} + +.mdi-file-remove-outline::before { + content: "\F1037"; +} + +.mdi-file-replace::before { + content: "\F0B32"; +} + +.mdi-file-replace-outline::before { + content: "\F0B33"; +} + +.mdi-file-restore::before { + content: "\F0670"; +} + +.mdi-file-restore-outline::before { + content: "\F1038"; +} + +.mdi-file-search::before { + content: "\F0C7C"; +} + +.mdi-file-search-outline::before { + content: "\F0C7D"; +} + +.mdi-file-send::before { + content: "\F022A"; +} + +.mdi-file-send-outline::before { + content: "\F1039"; +} + +.mdi-file-settings::before { + content: "\F1079"; +} + +.mdi-file-settings-outline::before { + content: "\F107A"; +} + +.mdi-file-star::before { + content: "\F103A"; +} + +.mdi-file-star-outline::before { + content: "\F103B"; +} + +.mdi-file-swap::before { + content: "\F0FB4"; +} + +.mdi-file-swap-outline::before { + content: "\F0FB5"; +} + +.mdi-file-sync::before { + content: "\F1216"; +} + +.mdi-file-sync-outline::before { + content: "\F1217"; +} + +.mdi-file-table::before { + content: "\F0C7E"; +} + +.mdi-file-table-box::before { + content: "\F10E1"; +} + +.mdi-file-table-box-multiple::before { + content: "\F10E2"; +} + +.mdi-file-table-box-multiple-outline::before { + content: "\F10E3"; +} + +.mdi-file-table-box-outline::before { + content: "\F10E4"; +} + +.mdi-file-table-outline::before { + content: "\F0C7F"; +} + +.mdi-file-tree::before { + content: "\F0645"; +} + +.mdi-file-tree-outline::before { + content: "\F13D2"; +} + +.mdi-file-undo::before { + content: "\F08DC"; +} + +.mdi-file-undo-outline::before { + content: "\F103C"; +} + +.mdi-file-upload::before { + content: "\F0A4D"; +} + +.mdi-file-upload-outline::before { + content: "\F0A4E"; +} + +.mdi-file-video::before { + content: "\F022B"; +} + +.mdi-file-video-outline::before { + content: "\F0E2C"; +} + +.mdi-file-word::before { + content: "\F022C"; +} + +.mdi-file-word-box::before { + content: "\F022D"; +} + +.mdi-file-word-box-outline::before { + content: "\F103D"; +} + +.mdi-file-word-outline::before { + content: "\F103E"; +} + +.mdi-film::before { + content: "\F022F"; +} + +.mdi-filmstrip::before { + content: "\F0230"; +} + +.mdi-filmstrip-box::before { + content: "\F0332"; +} + +.mdi-filmstrip-box-multiple::before { + content: "\F0D18"; +} + +.mdi-filmstrip-off::before { + content: "\F0231"; +} + +.mdi-filter::before { + content: "\F0232"; +} + +.mdi-filter-menu::before { + content: "\F10E5"; +} + +.mdi-filter-menu-outline::before { + content: "\F10E6"; +} + +.mdi-filter-minus::before { + content: "\F0EEE"; +} + +.mdi-filter-minus-outline::before { + content: "\F0EEF"; +} + +.mdi-filter-off::before { + content: "\F14EF"; +} + +.mdi-filter-off-outline::before { + content: "\F14F0"; +} + +.mdi-filter-outline::before { + content: "\F0233"; +} + +.mdi-filter-plus::before { + content: "\F0EF0"; +} + +.mdi-filter-plus-outline::before { + content: "\F0EF1"; +} + +.mdi-filter-remove::before { + content: "\F0234"; +} + +.mdi-filter-remove-outline::before { + content: "\F0235"; +} + +.mdi-filter-variant::before { + content: "\F0236"; +} + +.mdi-filter-variant-minus::before { + content: "\F1112"; +} + +.mdi-filter-variant-plus::before { + content: "\F1113"; +} + +.mdi-filter-variant-remove::before { + content: "\F103F"; +} + +.mdi-finance::before { + content: "\F081F"; +} + +.mdi-find-replace::before { + content: "\F06D4"; +} + +.mdi-fingerprint::before { + content: "\F0237"; +} + +.mdi-fingerprint-off::before { + content: "\F0EB1"; +} + +.mdi-fire::before { + content: "\F0238"; +} + +.mdi-fire-alert::before { + content: "\F15D7"; +} + +.mdi-fire-extinguisher::before { + content: "\F0EF2"; +} + +.mdi-fire-hydrant::before { + content: "\F1137"; +} + +.mdi-fire-hydrant-alert::before { + content: "\F1138"; +} + +.mdi-fire-hydrant-off::before { + content: "\F1139"; +} + +.mdi-fire-truck::before { + content: "\F08AB"; +} + +.mdi-firebase::before { + content: "\F0967"; +} + +.mdi-firefox::before { + content: "\F0239"; +} + +.mdi-fireplace::before { + content: "\F0E2E"; +} + +.mdi-fireplace-off::before { + content: "\F0E2F"; +} + +.mdi-firework::before { + content: "\F0E30"; +} + +.mdi-fish::before { + content: "\F023A"; +} + +.mdi-fish-off::before { + content: "\F13F3"; +} + +.mdi-fishbowl::before { + content: "\F0EF3"; +} + +.mdi-fishbowl-outline::before { + content: "\F0EF4"; +} + +.mdi-fit-to-page::before { + content: "\F0EF5"; +} + +.mdi-fit-to-page-outline::before { + content: "\F0EF6"; +} + +.mdi-flag::before { + content: "\F023B"; +} + +.mdi-flag-checkered::before { + content: "\F023C"; +} + +.mdi-flag-minus::before { + content: "\F0B99"; +} + +.mdi-flag-minus-outline::before { + content: "\F10B2"; +} + +.mdi-flag-outline::before { + content: "\F023D"; +} + +.mdi-flag-plus::before { + content: "\F0B9A"; +} + +.mdi-flag-plus-outline::before { + content: "\F10B3"; +} + +.mdi-flag-remove::before { + content: "\F0B9B"; +} + +.mdi-flag-remove-outline::before { + content: "\F10B4"; +} + +.mdi-flag-triangle::before { + content: "\F023F"; +} + +.mdi-flag-variant::before { + content: "\F0240"; +} + +.mdi-flag-variant-outline::before { + content: "\F023E"; +} + +.mdi-flare::before { + content: "\F0D72"; +} + +.mdi-flash::before { + content: "\F0241"; +} + +.mdi-flash-alert::before { + content: "\F0EF7"; +} + +.mdi-flash-alert-outline::before { + content: "\F0EF8"; +} + +.mdi-flash-auto::before { + content: "\F0242"; +} + +.mdi-flash-circle::before { + content: "\F0820"; +} + +.mdi-flash-off::before { + content: "\F0243"; +} + +.mdi-flash-outline::before { + content: "\F06D5"; +} + +.mdi-flash-red-eye::before { + content: "\F067B"; +} + +.mdi-flashlight::before { + content: "\F0244"; +} + +.mdi-flashlight-off::before { + content: "\F0245"; +} + +.mdi-flask::before { + content: "\F0093"; +} + +.mdi-flask-empty::before { + content: "\F0094"; +} + +.mdi-flask-empty-minus::before { + content: "\F123A"; +} + +.mdi-flask-empty-minus-outline::before { + content: "\F123B"; +} + +.mdi-flask-empty-off::before { + content: "\F13F4"; +} + +.mdi-flask-empty-off-outline::before { + content: "\F13F5"; +} + +.mdi-flask-empty-outline::before { + content: "\F0095"; +} + +.mdi-flask-empty-plus::before { + content: "\F123C"; +} + +.mdi-flask-empty-plus-outline::before { + content: "\F123D"; +} + +.mdi-flask-empty-remove::before { + content: "\F123E"; +} + +.mdi-flask-empty-remove-outline::before { + content: "\F123F"; +} + +.mdi-flask-minus::before { + content: "\F1240"; +} + +.mdi-flask-minus-outline::before { + content: "\F1241"; +} + +.mdi-flask-off::before { + content: "\F13F6"; +} + +.mdi-flask-off-outline::before { + content: "\F13F7"; +} + +.mdi-flask-outline::before { + content: "\F0096"; +} + +.mdi-flask-plus::before { + content: "\F1242"; +} + +.mdi-flask-plus-outline::before { + content: "\F1243"; +} + +.mdi-flask-remove::before { + content: "\F1244"; +} + +.mdi-flask-remove-outline::before { + content: "\F1245"; +} + +.mdi-flask-round-bottom::before { + content: "\F124B"; +} + +.mdi-flask-round-bottom-empty::before { + content: "\F124C"; +} + +.mdi-flask-round-bottom-empty-outline::before { + content: "\F124D"; +} + +.mdi-flask-round-bottom-outline::before { + content: "\F124E"; +} + +.mdi-fleur-de-lis::before { + content: "\F1303"; +} + +.mdi-flip-horizontal::before { + content: "\F10E7"; +} + +.mdi-flip-to-back::before { + content: "\F0247"; +} + +.mdi-flip-to-front::before { + content: "\F0248"; +} + +.mdi-flip-vertical::before { + content: "\F10E8"; +} + +.mdi-floor-lamp::before { + content: "\F08DD"; +} + +.mdi-floor-lamp-dual::before { + content: "\F1040"; +} + +.mdi-floor-lamp-variant::before { + content: "\F1041"; +} + +.mdi-floor-plan::before { + content: "\F0821"; +} + +.mdi-floppy::before { + content: "\F0249"; +} + +.mdi-floppy-variant::before { + content: "\F09EF"; +} + +.mdi-flower::before { + content: "\F024A"; +} + +.mdi-flower-outline::before { + content: "\F09F0"; +} + +.mdi-flower-poppy::before { + content: "\F0D08"; +} + +.mdi-flower-tulip::before { + content: "\F09F1"; +} + +.mdi-flower-tulip-outline::before { + content: "\F09F2"; +} + +.mdi-focus-auto::before { + content: "\F0F4E"; +} + +.mdi-focus-field::before { + content: "\F0F4F"; +} + +.mdi-focus-field-horizontal::before { + content: "\F0F50"; +} + +.mdi-focus-field-vertical::before { + content: "\F0F51"; +} + +.mdi-folder::before { + content: "\F024B"; +} + +.mdi-folder-account::before { + content: "\F024C"; +} + +.mdi-folder-account-outline::before { + content: "\F0B9C"; +} + +.mdi-folder-alert::before { + content: "\F0DCC"; +} + +.mdi-folder-alert-outline::before { + content: "\F0DCD"; +} + +.mdi-folder-clock::before { + content: "\F0ABA"; +} + +.mdi-folder-clock-outline::before { + content: "\F0ABB"; +} + +.mdi-folder-cog::before { + content: "\F107F"; +} + +.mdi-folder-cog-outline::before { + content: "\F1080"; +} + +.mdi-folder-download::before { + content: "\F024D"; +} + +.mdi-folder-download-outline::before { + content: "\F10E9"; +} + +.mdi-folder-edit::before { + content: "\F08DE"; +} + +.mdi-folder-edit-outline::before { + content: "\F0DCE"; +} + +.mdi-folder-google-drive::before { + content: "\F024E"; +} + +.mdi-folder-heart::before { + content: "\F10EA"; +} + +.mdi-folder-heart-outline::before { + content: "\F10EB"; +} + +.mdi-folder-home::before { + content: "\F10B5"; +} + +.mdi-folder-home-outline::before { + content: "\F10B6"; +} + +.mdi-folder-image::before { + content: "\F024F"; +} + +.mdi-folder-information::before { + content: "\F10B7"; +} + +.mdi-folder-information-outline::before { + content: "\F10B8"; +} + +.mdi-folder-key::before { + content: "\F08AC"; +} + +.mdi-folder-key-network::before { + content: "\F08AD"; +} + +.mdi-folder-key-network-outline::before { + content: "\F0C80"; +} + +.mdi-folder-key-outline::before { + content: "\F10EC"; +} + +.mdi-folder-lock::before { + content: "\F0250"; +} + +.mdi-folder-lock-open::before { + content: "\F0251"; +} + +.mdi-folder-marker::before { + content: "\F126D"; +} + +.mdi-folder-marker-outline::before { + content: "\F126E"; +} + +.mdi-folder-move::before { + content: "\F0252"; +} + +.mdi-folder-move-outline::before { + content: "\F1246"; +} + +.mdi-folder-multiple::before { + content: "\F0253"; +} + +.mdi-folder-multiple-image::before { + content: "\F0254"; +} + +.mdi-folder-multiple-outline::before { + content: "\F0255"; +} + +.mdi-folder-multiple-plus::before { + content: "\F147E"; +} + +.mdi-folder-multiple-plus-outline::before { + content: "\F147F"; +} + +.mdi-folder-music::before { + content: "\F1359"; +} + +.mdi-folder-music-outline::before { + content: "\F135A"; +} + +.mdi-folder-network::before { + content: "\F0870"; +} + +.mdi-folder-network-outline::before { + content: "\F0C81"; +} + +.mdi-folder-open::before { + content: "\F0770"; +} + +.mdi-folder-open-outline::before { + content: "\F0DCF"; +} + +.mdi-folder-outline::before { + content: "\F0256"; +} + +.mdi-folder-plus::before { + content: "\F0257"; +} + +.mdi-folder-plus-outline::before { + content: "\F0B9D"; +} + +.mdi-folder-pound::before { + content: "\F0D09"; +} + +.mdi-folder-pound-outline::before { + content: "\F0D0A"; +} + +.mdi-folder-refresh::before { + content: "\F0749"; +} + +.mdi-folder-refresh-outline::before { + content: "\F0542"; +} + +.mdi-folder-remove::before { + content: "\F0258"; +} + +.mdi-folder-remove-outline::before { + content: "\F0B9E"; +} + +.mdi-folder-search::before { + content: "\F0968"; +} + +.mdi-folder-search-outline::before { + content: "\F0969"; +} + +.mdi-folder-settings::before { + content: "\F107D"; +} + +.mdi-folder-settings-outline::before { + content: "\F107E"; +} + +.mdi-folder-star::before { + content: "\F069D"; +} + +.mdi-folder-star-multiple::before { + content: "\F13D3"; +} + +.mdi-folder-star-multiple-outline::before { + content: "\F13D4"; +} + +.mdi-folder-star-outline::before { + content: "\F0B9F"; +} + +.mdi-folder-swap::before { + content: "\F0FB6"; +} + +.mdi-folder-swap-outline::before { + content: "\F0FB7"; +} + +.mdi-folder-sync::before { + content: "\F0D0B"; +} + +.mdi-folder-sync-outline::before { + content: "\F0D0C"; +} + +.mdi-folder-table::before { + content: "\F12E3"; +} + +.mdi-folder-table-outline::before { + content: "\F12E4"; +} + +.mdi-folder-text::before { + content: "\F0C82"; +} + +.mdi-folder-text-outline::before { + content: "\F0C83"; +} + +.mdi-folder-upload::before { + content: "\F0259"; +} + +.mdi-folder-upload-outline::before { + content: "\F10ED"; +} + +.mdi-folder-zip::before { + content: "\F06EB"; +} + +.mdi-folder-zip-outline::before { + content: "\F07B9"; +} + +.mdi-font-awesome::before { + content: "\F003A"; +} + +.mdi-food::before { + content: "\F025A"; +} + +.mdi-food-apple::before { + content: "\F025B"; +} + +.mdi-food-apple-outline::before { + content: "\F0C84"; +} + +.mdi-food-croissant::before { + content: "\F07C8"; +} + +.mdi-food-drumstick::before { + content: "\F141F"; +} + +.mdi-food-drumstick-off::before { + content: "\F1468"; +} + +.mdi-food-drumstick-off-outline::before { + content: "\F1469"; +} + +.mdi-food-drumstick-outline::before { + content: "\F1420"; +} + +.mdi-food-fork-drink::before { + content: "\F05F2"; +} + +.mdi-food-halal::before { + content: "\F1572"; +} + +.mdi-food-kosher::before { + content: "\F1573"; +} + +.mdi-food-off::before { + content: "\F05F3"; +} + +.mdi-food-steak::before { + content: "\F146A"; +} + +.mdi-food-steak-off::before { + content: "\F146B"; +} + +.mdi-food-variant::before { + content: "\F025C"; +} + +.mdi-food-variant-off::before { + content: "\F13E5"; +} + +.mdi-foot-print::before { + content: "\F0F52"; +} + +.mdi-football::before { + content: "\F025D"; +} + +.mdi-football-australian::before { + content: "\F025E"; +} + +.mdi-football-helmet::before { + content: "\F025F"; +} + +.mdi-forklift::before { + content: "\F07C9"; +} + +.mdi-form-dropdown::before { + content: "\F1400"; +} + +.mdi-form-select::before { + content: "\F1401"; +} + +.mdi-form-textarea::before { + content: "\F1095"; +} + +.mdi-form-textbox::before { + content: "\F060E"; +} + +.mdi-form-textbox-lock::before { + content: "\F135D"; +} + +.mdi-form-textbox-password::before { + content: "\F07F5"; +} + +.mdi-format-align-bottom::before { + content: "\F0753"; +} + +.mdi-format-align-center::before { + content: "\F0260"; +} + +.mdi-format-align-justify::before { + content: "\F0261"; +} + +.mdi-format-align-left::before { + content: "\F0262"; +} + +.mdi-format-align-middle::before { + content: "\F0754"; +} + +.mdi-format-align-right::before { + content: "\F0263"; +} + +.mdi-format-align-top::before { + content: "\F0755"; +} + +.mdi-format-annotation-minus::before { + content: "\F0ABC"; +} + +.mdi-format-annotation-plus::before { + content: "\F0646"; +} + +.mdi-format-bold::before { + content: "\F0264"; +} + +.mdi-format-clear::before { + content: "\F0265"; +} + +.mdi-format-color-fill::before { + content: "\F0266"; +} + +.mdi-format-color-highlight::before { + content: "\F0E31"; +} + +.mdi-format-color-marker-cancel::before { + content: "\F1313"; +} + +.mdi-format-color-text::before { + content: "\F069E"; +} + +.mdi-format-columns::before { + content: "\F08DF"; +} + +.mdi-format-float-center::before { + content: "\F0267"; +} + +.mdi-format-float-left::before { + content: "\F0268"; +} + +.mdi-format-float-none::before { + content: "\F0269"; +} + +.mdi-format-float-right::before { + content: "\F026A"; +} + +.mdi-format-font::before { + content: "\F06D6"; +} + +.mdi-format-font-size-decrease::before { + content: "\F09F3"; +} + +.mdi-format-font-size-increase::before { + content: "\F09F4"; +} + +.mdi-format-header-1::before { + content: "\F026B"; +} + +.mdi-format-header-2::before { + content: "\F026C"; +} + +.mdi-format-header-3::before { + content: "\F026D"; +} + +.mdi-format-header-4::before { + content: "\F026E"; +} + +.mdi-format-header-5::before { + content: "\F026F"; +} + +.mdi-format-header-6::before { + content: "\F0270"; +} + +.mdi-format-header-decrease::before { + content: "\F0271"; +} + +.mdi-format-header-equal::before { + content: "\F0272"; +} + +.mdi-format-header-increase::before { + content: "\F0273"; +} + +.mdi-format-header-pound::before { + content: "\F0274"; +} + +.mdi-format-horizontal-align-center::before { + content: "\F061E"; +} + +.mdi-format-horizontal-align-left::before { + content: "\F061F"; +} + +.mdi-format-horizontal-align-right::before { + content: "\F0620"; +} + +.mdi-format-indent-decrease::before { + content: "\F0275"; +} + +.mdi-format-indent-increase::before { + content: "\F0276"; +} + +.mdi-format-italic::before { + content: "\F0277"; +} + +.mdi-format-letter-case::before { + content: "\F0B34"; +} + +.mdi-format-letter-case-lower::before { + content: "\F0B35"; +} + +.mdi-format-letter-case-upper::before { + content: "\F0B36"; +} + +.mdi-format-letter-ends-with::before { + content: "\F0FB8"; +} + +.mdi-format-letter-matches::before { + content: "\F0FB9"; +} + +.mdi-format-letter-starts-with::before { + content: "\F0FBA"; +} + +.mdi-format-line-spacing::before { + content: "\F0278"; +} + +.mdi-format-line-style::before { + content: "\F05C8"; +} + +.mdi-format-line-weight::before { + content: "\F05C9"; +} + +.mdi-format-list-bulleted::before { + content: "\F0279"; +} + +.mdi-format-list-bulleted-square::before { + content: "\F0DD0"; +} + +.mdi-format-list-bulleted-triangle::before { + content: "\F0EB2"; +} + +.mdi-format-list-bulleted-type::before { + content: "\F027A"; +} + +.mdi-format-list-checkbox::before { + content: "\F096A"; +} + +.mdi-format-list-checks::before { + content: "\F0756"; +} + +.mdi-format-list-numbered::before { + content: "\F027B"; +} + +.mdi-format-list-numbered-rtl::before { + content: "\F0D0D"; +} + +.mdi-format-list-text::before { + content: "\F126F"; +} + +.mdi-format-overline::before { + content: "\F0EB3"; +} + +.mdi-format-page-break::before { + content: "\F06D7"; +} + +.mdi-format-paint::before { + content: "\F027C"; +} + +.mdi-format-paragraph::before { + content: "\F027D"; +} + +.mdi-format-pilcrow::before { + content: "\F06D8"; +} + +.mdi-format-quote-close::before { + content: "\F027E"; +} + +.mdi-format-quote-close-outline::before { + content: "\F11A8"; +} + +.mdi-format-quote-open::before { + content: "\F0757"; +} + +.mdi-format-quote-open-outline::before { + content: "\F11A7"; +} + +.mdi-format-rotate-90::before { + content: "\F06AA"; +} + +.mdi-format-section::before { + content: "\F069F"; +} + +.mdi-format-size::before { + content: "\F027F"; +} + +.mdi-format-strikethrough::before { + content: "\F0280"; +} + +.mdi-format-strikethrough-variant::before { + content: "\F0281"; +} + +.mdi-format-subscript::before { + content: "\F0282"; +} + +.mdi-format-superscript::before { + content: "\F0283"; +} + +.mdi-format-text::before { + content: "\F0284"; +} + +.mdi-format-text-rotation-angle-down::before { + content: "\F0FBB"; +} + +.mdi-format-text-rotation-angle-up::before { + content: "\F0FBC"; +} + +.mdi-format-text-rotation-down::before { + content: "\F0D73"; +} + +.mdi-format-text-rotation-down-vertical::before { + content: "\F0FBD"; +} + +.mdi-format-text-rotation-none::before { + content: "\F0D74"; +} + +.mdi-format-text-rotation-up::before { + content: "\F0FBE"; +} + +.mdi-format-text-rotation-vertical::before { + content: "\F0FBF"; +} + +.mdi-format-text-variant::before { + content: "\F0E32"; +} + +.mdi-format-text-variant-outline::before { + content: "\F150F"; +} + +.mdi-format-text-wrapping-clip::before { + content: "\F0D0E"; +} + +.mdi-format-text-wrapping-overflow::before { + content: "\F0D0F"; +} + +.mdi-format-text-wrapping-wrap::before { + content: "\F0D10"; +} + +.mdi-format-textbox::before { + content: "\F0D11"; +} + +.mdi-format-textdirection-l-to-r::before { + content: "\F0285"; +} + +.mdi-format-textdirection-r-to-l::before { + content: "\F0286"; +} + +.mdi-format-title::before { + content: "\F05F4"; +} + +.mdi-format-underline::before { + content: "\F0287"; +} + +.mdi-format-vertical-align-bottom::before { + content: "\F0621"; +} + +.mdi-format-vertical-align-center::before { + content: "\F0622"; +} + +.mdi-format-vertical-align-top::before { + content: "\F0623"; +} + +.mdi-format-wrap-inline::before { + content: "\F0288"; +} + +.mdi-format-wrap-square::before { + content: "\F0289"; +} + +.mdi-format-wrap-tight::before { + content: "\F028A"; +} + +.mdi-format-wrap-top-bottom::before { + content: "\F028B"; +} + +.mdi-forum::before { + content: "\F028C"; +} + +.mdi-forum-outline::before { + content: "\F0822"; +} + +.mdi-forward::before { + content: "\F028D"; +} + +.mdi-forwardburger::before { + content: "\F0D75"; +} + +.mdi-fountain::before { + content: "\F096B"; +} + +.mdi-fountain-pen::before { + content: "\F0D12"; +} + +.mdi-fountain-pen-tip::before { + content: "\F0D13"; +} + +.mdi-freebsd::before { + content: "\F08E0"; +} + +.mdi-frequently-asked-questions::before { + content: "\F0EB4"; +} + +.mdi-fridge::before { + content: "\F0290"; +} + +.mdi-fridge-alert::before { + content: "\F11B1"; +} + +.mdi-fridge-alert-outline::before { + content: "\F11B2"; +} + +.mdi-fridge-bottom::before { + content: "\F0292"; +} + +.mdi-fridge-industrial::before { + content: "\F15EE"; +} + +.mdi-fridge-industrial-alert::before { + content: "\F15EF"; +} + +.mdi-fridge-industrial-alert-outline::before { + content: "\F15F0"; +} + +.mdi-fridge-industrial-off::before { + content: "\F15F1"; +} + +.mdi-fridge-industrial-off-outline::before { + content: "\F15F2"; +} + +.mdi-fridge-industrial-outline::before { + content: "\F15F3"; +} + +.mdi-fridge-off::before { + content: "\F11AF"; +} + +.mdi-fridge-off-outline::before { + content: "\F11B0"; +} + +.mdi-fridge-outline::before { + content: "\F028F"; +} + +.mdi-fridge-top::before { + content: "\F0291"; +} + +.mdi-fridge-variant::before { + content: "\F15F4"; +} + +.mdi-fridge-variant-alert::before { + content: "\F15F5"; +} + +.mdi-fridge-variant-alert-outline::before { + content: "\F15F6"; +} + +.mdi-fridge-variant-off::before { + content: "\F15F7"; +} + +.mdi-fridge-variant-off-outline::before { + content: "\F15F8"; +} + +.mdi-fridge-variant-outline::before { + content: "\F15F9"; +} + +.mdi-fruit-cherries::before { + content: "\F1042"; +} + +.mdi-fruit-cherries-off::before { + content: "\F13F8"; +} + +.mdi-fruit-citrus::before { + content: "\F1043"; +} + +.mdi-fruit-citrus-off::before { + content: "\F13F9"; +} + +.mdi-fruit-grapes::before { + content: "\F1044"; +} + +.mdi-fruit-grapes-outline::before { + content: "\F1045"; +} + +.mdi-fruit-pineapple::before { + content: "\F1046"; +} + +.mdi-fruit-watermelon::before { + content: "\F1047"; +} + +.mdi-fuel::before { + content: "\F07CA"; +} + +.mdi-fullscreen::before { + content: "\F0293"; +} + +.mdi-fullscreen-exit::before { + content: "\F0294"; +} + +.mdi-function::before { + content: "\F0295"; +} + +.mdi-function-variant::before { + content: "\F0871"; +} + +.mdi-furigana-horizontal::before { + content: "\F1081"; +} + +.mdi-furigana-vertical::before { + content: "\F1082"; +} + +.mdi-fuse::before { + content: "\F0C85"; +} + +.mdi-fuse-alert::before { + content: "\F142D"; +} + +.mdi-fuse-blade::before { + content: "\F0C86"; +} + +.mdi-fuse-off::before { + content: "\F142C"; +} + +.mdi-gamepad::before { + content: "\F0296"; +} + +.mdi-gamepad-circle::before { + content: "\F0E33"; +} + +.mdi-gamepad-circle-down::before { + content: "\F0E34"; +} + +.mdi-gamepad-circle-left::before { + content: "\F0E35"; +} + +.mdi-gamepad-circle-outline::before { + content: "\F0E36"; +} + +.mdi-gamepad-circle-right::before { + content: "\F0E37"; +} + +.mdi-gamepad-circle-up::before { + content: "\F0E38"; +} + +.mdi-gamepad-down::before { + content: "\F0E39"; +} + +.mdi-gamepad-left::before { + content: "\F0E3A"; +} + +.mdi-gamepad-right::before { + content: "\F0E3B"; +} + +.mdi-gamepad-round::before { + content: "\F0E3C"; +} + +.mdi-gamepad-round-down::before { + content: "\F0E3D"; +} + +.mdi-gamepad-round-left::before { + content: "\F0E3E"; +} + +.mdi-gamepad-round-outline::before { + content: "\F0E3F"; +} + +.mdi-gamepad-round-right::before { + content: "\F0E40"; +} + +.mdi-gamepad-round-up::before { + content: "\F0E41"; +} + +.mdi-gamepad-square::before { + content: "\F0EB5"; +} + +.mdi-gamepad-square-outline::before { + content: "\F0EB6"; +} + +.mdi-gamepad-up::before { + content: "\F0E42"; +} + +.mdi-gamepad-variant::before { + content: "\F0297"; +} + +.mdi-gamepad-variant-outline::before { + content: "\F0EB7"; +} + +.mdi-gamma::before { + content: "\F10EE"; +} + +.mdi-gantry-crane::before { + content: "\F0DD1"; +} + +.mdi-garage::before { + content: "\F06D9"; +} + +.mdi-garage-alert::before { + content: "\F0872"; +} + +.mdi-garage-alert-variant::before { + content: "\F12D5"; +} + +.mdi-garage-open::before { + content: "\F06DA"; +} + +.mdi-garage-open-variant::before { + content: "\F12D4"; +} + +.mdi-garage-variant::before { + content: "\F12D3"; +} + +.mdi-gas-cylinder::before { + content: "\F0647"; +} + +.mdi-gas-station::before { + content: "\F0298"; +} + +.mdi-gas-station-off::before { + content: "\F1409"; +} + +.mdi-gas-station-off-outline::before { + content: "\F140A"; +} + +.mdi-gas-station-outline::before { + content: "\F0EB8"; +} + +.mdi-gate::before { + content: "\F0299"; +} + +.mdi-gate-and::before { + content: "\F08E1"; +} + +.mdi-gate-arrow-right::before { + content: "\F1169"; +} + +.mdi-gate-nand::before { + content: "\F08E2"; +} + +.mdi-gate-nor::before { + content: "\F08E3"; +} + +.mdi-gate-not::before { + content: "\F08E4"; +} + +.mdi-gate-open::before { + content: "\F116A"; +} + +.mdi-gate-or::before { + content: "\F08E5"; +} + +.mdi-gate-xnor::before { + content: "\F08E6"; +} + +.mdi-gate-xor::before { + content: "\F08E7"; +} + +.mdi-gatsby::before { + content: "\F0E43"; +} + +.mdi-gauge::before { + content: "\F029A"; +} + +.mdi-gauge-empty::before { + content: "\F0873"; +} + +.mdi-gauge-full::before { + content: "\F0874"; +} + +.mdi-gauge-low::before { + content: "\F0875"; +} + +.mdi-gavel::before { + content: "\F029B"; +} + +.mdi-gender-female::before { + content: "\F029C"; +} + +.mdi-gender-male::before { + content: "\F029D"; +} + +.mdi-gender-male-female::before { + content: "\F029E"; +} + +.mdi-gender-male-female-variant::before { + content: "\F113F"; +} + +.mdi-gender-non-binary::before { + content: "\F1140"; +} + +.mdi-gender-transgender::before { + content: "\F029F"; +} + +.mdi-gentoo::before { + content: "\F08E8"; +} + +.mdi-gesture::before { + content: "\F07CB"; +} + +.mdi-gesture-double-tap::before { + content: "\F073C"; +} + +.mdi-gesture-pinch::before { + content: "\F0ABD"; +} + +.mdi-gesture-spread::before { + content: "\F0ABE"; +} + +.mdi-gesture-swipe::before { + content: "\F0D76"; +} + +.mdi-gesture-swipe-down::before { + content: "\F073D"; +} + +.mdi-gesture-swipe-horizontal::before { + content: "\F0ABF"; +} + +.mdi-gesture-swipe-left::before { + content: "\F073E"; +} + +.mdi-gesture-swipe-right::before { + content: "\F073F"; +} + +.mdi-gesture-swipe-up::before { + content: "\F0740"; +} + +.mdi-gesture-swipe-vertical::before { + content: "\F0AC0"; +} + +.mdi-gesture-tap::before { + content: "\F0741"; +} + +.mdi-gesture-tap-box::before { + content: "\F12A9"; +} + +.mdi-gesture-tap-button::before { + content: "\F12A8"; +} + +.mdi-gesture-tap-hold::before { + content: "\F0D77"; +} + +.mdi-gesture-two-double-tap::before { + content: "\F0742"; +} + +.mdi-gesture-two-tap::before { + content: "\F0743"; +} + +.mdi-ghost::before { + content: "\F02A0"; +} + +.mdi-ghost-off::before { + content: "\F09F5"; +} + +.mdi-ghost-off-outline::before { + content: "\F165C"; +} + +.mdi-ghost-outline::before { + content: "\F165D"; +} + +.mdi-gif::before { + content: "\F0D78"; +} + +.mdi-gift::before { + content: "\F0E44"; +} + +.mdi-gift-outline::before { + content: "\F02A1"; +} + +.mdi-git::before { + content: "\F02A2"; +} + +.mdi-github::before { + content: "\F02A4"; +} + +.mdi-gitlab::before { + content: "\F0BA0"; +} + +.mdi-glass-cocktail::before { + content: "\F0356"; +} + +.mdi-glass-cocktail-off::before { + content: "\F15E6"; +} + +.mdi-glass-flute::before { + content: "\F02A5"; +} + +.mdi-glass-mug::before { + content: "\F02A6"; +} + +.mdi-glass-mug-off::before { + content: "\F15E7"; +} + +.mdi-glass-mug-variant::before { + content: "\F1116"; +} + +.mdi-glass-mug-variant-off::before { + content: "\F15E8"; +} + +.mdi-glass-pint-outline::before { + content: "\F130D"; +} + +.mdi-glass-stange::before { + content: "\F02A7"; +} + +.mdi-glass-tulip::before { + content: "\F02A8"; +} + +.mdi-glass-wine::before { + content: "\F0876"; +} + +.mdi-glasses::before { + content: "\F02AA"; +} + +.mdi-globe-light::before { + content: "\F12D7"; +} + +.mdi-globe-model::before { + content: "\F08E9"; +} + +.mdi-gmail::before { + content: "\F02AB"; +} + +.mdi-gnome::before { + content: "\F02AC"; +} + +.mdi-go-kart::before { + content: "\F0D79"; +} + +.mdi-go-kart-track::before { + content: "\F0D7A"; +} + +.mdi-gog::before { + content: "\F0BA1"; +} + +.mdi-gold::before { + content: "\F124F"; +} + +.mdi-golf::before { + content: "\F0823"; +} + +.mdi-golf-cart::before { + content: "\F11A4"; +} + +.mdi-golf-tee::before { + content: "\F1083"; +} + +.mdi-gondola::before { + content: "\F0686"; +} + +.mdi-goodreads::before { + content: "\F0D7B"; +} + +.mdi-google::before { + content: "\F02AD"; +} + +.mdi-google-ads::before { + content: "\F0C87"; +} + +.mdi-google-analytics::before { + content: "\F07CC"; +} + +.mdi-google-assistant::before { + content: "\F07CD"; +} + +.mdi-google-cardboard::before { + content: "\F02AE"; +} + +.mdi-google-chrome::before { + content: "\F02AF"; +} + +.mdi-google-circles::before { + content: "\F02B0"; +} + +.mdi-google-circles-communities::before { + content: "\F02B1"; +} + +.mdi-google-circles-extended::before { + content: "\F02B2"; +} + +.mdi-google-circles-group::before { + content: "\F02B3"; +} + +.mdi-google-classroom::before { + content: "\F02C0"; +} + +.mdi-google-cloud::before { + content: "\F11F6"; +} + +.mdi-google-controller::before { + content: "\F02B4"; +} + +.mdi-google-controller-off::before { + content: "\F02B5"; +} + +.mdi-google-downasaur::before { + content: "\F1362"; +} + +.mdi-google-drive::before { + content: "\F02B6"; +} + +.mdi-google-earth::before { + content: "\F02B7"; +} + +.mdi-google-fit::before { + content: "\F096C"; +} + +.mdi-google-glass::before { + content: "\F02B8"; +} + +.mdi-google-hangouts::before { + content: "\F02C9"; +} + +.mdi-google-home::before { + content: "\F0824"; +} + +.mdi-google-keep::before { + content: "\F06DC"; +} + +.mdi-google-lens::before { + content: "\F09F6"; +} + +.mdi-google-maps::before { + content: "\F05F5"; +} + +.mdi-google-my-business::before { + content: "\F1048"; +} + +.mdi-google-nearby::before { + content: "\F02B9"; +} + +.mdi-google-photos::before { + content: "\F06DD"; +} + +.mdi-google-play::before { + content: "\F02BC"; +} + +.mdi-google-plus::before { + content: "\F02BD"; +} + +.mdi-google-podcast::before { + content: "\F0EB9"; +} + +.mdi-google-spreadsheet::before { + content: "\F09F7"; +} + +.mdi-google-street-view::before { + content: "\F0C88"; +} + +.mdi-google-translate::before { + content: "\F02BF"; +} + +.mdi-gradient::before { + content: "\F06A0"; +} + +.mdi-grain::before { + content: "\F0D7C"; +} + +.mdi-graph::before { + content: "\F1049"; +} + +.mdi-graph-outline::before { + content: "\F104A"; +} + +.mdi-graphql::before { + content: "\F0877"; +} + +.mdi-grass::before { + content: "\F1510"; +} + +.mdi-grave-stone::before { + content: "\F0BA2"; +} + +.mdi-grease-pencil::before { + content: "\F0648"; +} + +.mdi-greater-than::before { + content: "\F096D"; +} + +.mdi-greater-than-or-equal::before { + content: "\F096E"; +} + +.mdi-grid::before { + content: "\F02C1"; +} + +.mdi-grid-large::before { + content: "\F0758"; +} + +.mdi-grid-off::before { + content: "\F02C2"; +} + +.mdi-grill::before { + content: "\F0E45"; +} + +.mdi-grill-outline::before { + content: "\F118A"; +} + +.mdi-group::before { + content: "\F02C3"; +} + +.mdi-guitar-acoustic::before { + content: "\F0771"; +} + +.mdi-guitar-electric::before { + content: "\F02C4"; +} + +.mdi-guitar-pick::before { + content: "\F02C5"; +} + +.mdi-guitar-pick-outline::before { + content: "\F02C6"; +} + +.mdi-guy-fawkes-mask::before { + content: "\F0825"; +} + +.mdi-hail::before { + content: "\F0AC1"; +} + +.mdi-hair-dryer::before { + content: "\F10EF"; +} + +.mdi-hair-dryer-outline::before { + content: "\F10F0"; +} + +.mdi-halloween::before { + content: "\F0BA3"; +} + +.mdi-hamburger::before { + content: "\F0685"; +} + +.mdi-hammer::before { + content: "\F08EA"; +} + +.mdi-hammer-screwdriver::before { + content: "\F1322"; +} + +.mdi-hammer-wrench::before { + content: "\F1323"; +} + +.mdi-hand::before { + content: "\F0A4F"; +} + +.mdi-hand-heart::before { + content: "\F10F1"; +} + +.mdi-hand-heart-outline::before { + content: "\F157E"; +} + +.mdi-hand-left::before { + content: "\F0E46"; +} + +.mdi-hand-okay::before { + content: "\F0A50"; +} + +.mdi-hand-peace::before { + content: "\F0A51"; +} + +.mdi-hand-peace-variant::before { + content: "\F0A52"; +} + +.mdi-hand-pointing-down::before { + content: "\F0A53"; +} + +.mdi-hand-pointing-left::before { + content: "\F0A54"; +} + +.mdi-hand-pointing-right::before { + content: "\F02C7"; +} + +.mdi-hand-pointing-up::before { + content: "\F0A55"; +} + +.mdi-hand-right::before { + content: "\F0E47"; +} + +.mdi-hand-saw::before { + content: "\F0E48"; +} + +.mdi-hand-wash::before { + content: "\F157F"; +} + +.mdi-hand-wash-outline::before { + content: "\F1580"; +} + +.mdi-hand-water::before { + content: "\F139F"; +} + +.mdi-handball::before { + content: "\F0F53"; +} + +.mdi-handcuffs::before { + content: "\F113E"; +} + +.mdi-handshake::before { + content: "\F1218"; +} + +.mdi-handshake-outline::before { + content: "\F15A1"; +} + +.mdi-hanger::before { + content: "\F02C8"; +} + +.mdi-hard-hat::before { + content: "\F096F"; +} + +.mdi-harddisk::before { + content: "\F02CA"; +} + +.mdi-harddisk-plus::before { + content: "\F104B"; +} + +.mdi-harddisk-remove::before { + content: "\F104C"; +} + +.mdi-hat-fedora::before { + content: "\F0BA4"; +} + +.mdi-hazard-lights::before { + content: "\F0C89"; +} + +.mdi-hdr::before { + content: "\F0D7D"; +} + +.mdi-hdr-off::before { + content: "\F0D7E"; +} + +.mdi-head::before { + content: "\F135E"; +} + +.mdi-head-alert::before { + content: "\F1338"; +} + +.mdi-head-alert-outline::before { + content: "\F1339"; +} + +.mdi-head-check::before { + content: "\F133A"; +} + +.mdi-head-check-outline::before { + content: "\F133B"; +} + +.mdi-head-cog::before { + content: "\F133C"; +} + +.mdi-head-cog-outline::before { + content: "\F133D"; +} + +.mdi-head-dots-horizontal::before { + content: "\F133E"; +} + +.mdi-head-dots-horizontal-outline::before { + content: "\F133F"; +} + +.mdi-head-flash::before { + content: "\F1340"; +} + +.mdi-head-flash-outline::before { + content: "\F1341"; +} + +.mdi-head-heart::before { + content: "\F1342"; +} + +.mdi-head-heart-outline::before { + content: "\F1343"; +} + +.mdi-head-lightbulb::before { + content: "\F1344"; +} + +.mdi-head-lightbulb-outline::before { + content: "\F1345"; +} + +.mdi-head-minus::before { + content: "\F1346"; +} + +.mdi-head-minus-outline::before { + content: "\F1347"; +} + +.mdi-head-outline::before { + content: "\F135F"; +} + +.mdi-head-plus::before { + content: "\F1348"; +} + +.mdi-head-plus-outline::before { + content: "\F1349"; +} + +.mdi-head-question::before { + content: "\F134A"; +} + +.mdi-head-question-outline::before { + content: "\F134B"; +} + +.mdi-head-remove::before { + content: "\F134C"; +} + +.mdi-head-remove-outline::before { + content: "\F134D"; +} + +.mdi-head-snowflake::before { + content: "\F134E"; +} + +.mdi-head-snowflake-outline::before { + content: "\F134F"; +} + +.mdi-head-sync::before { + content: "\F1350"; +} + +.mdi-head-sync-outline::before { + content: "\F1351"; +} + +.mdi-headphones::before { + content: "\F02CB"; +} + +.mdi-headphones-bluetooth::before { + content: "\F0970"; +} + +.mdi-headphones-box::before { + content: "\F02CC"; +} + +.mdi-headphones-off::before { + content: "\F07CE"; +} + +.mdi-headphones-settings::before { + content: "\F02CD"; +} + +.mdi-headset::before { + content: "\F02CE"; +} + +.mdi-headset-dock::before { + content: "\F02CF"; +} + +.mdi-headset-off::before { + content: "\F02D0"; +} + +.mdi-heart::before { + content: "\F02D1"; +} + +.mdi-heart-box::before { + content: "\F02D2"; +} + +.mdi-heart-box-outline::before { + content: "\F02D3"; +} + +.mdi-heart-broken::before { + content: "\F02D4"; +} + +.mdi-heart-broken-outline::before { + content: "\F0D14"; +} + +.mdi-heart-circle::before { + content: "\F0971"; +} + +.mdi-heart-circle-outline::before { + content: "\F0972"; +} + +.mdi-heart-cog::before { + content: "\F1663"; +} + +.mdi-heart-cog-outline::before { + content: "\F1664"; +} + +.mdi-heart-flash::before { + content: "\F0EF9"; +} + +.mdi-heart-half::before { + content: "\F06DF"; +} + +.mdi-heart-half-full::before { + content: "\F06DE"; +} + +.mdi-heart-half-outline::before { + content: "\F06E0"; +} + +.mdi-heart-minus::before { + content: "\F142F"; +} + +.mdi-heart-minus-outline::before { + content: "\F1432"; +} + +.mdi-heart-multiple::before { + content: "\F0A56"; +} + +.mdi-heart-multiple-outline::before { + content: "\F0A57"; +} + +.mdi-heart-off::before { + content: "\F0759"; +} + +.mdi-heart-off-outline::before { + content: "\F1434"; +} + +.mdi-heart-outline::before { + content: "\F02D5"; +} + +.mdi-heart-plus::before { + content: "\F142E"; +} + +.mdi-heart-plus-outline::before { + content: "\F1431"; +} + +.mdi-heart-pulse::before { + content: "\F05F6"; +} + +.mdi-heart-remove::before { + content: "\F1430"; +} + +.mdi-heart-remove-outline::before { + content: "\F1433"; +} + +.mdi-heart-settings::before { + content: "\F1665"; +} + +.mdi-heart-settings-outline::before { + content: "\F1666"; +} + +.mdi-helicopter::before { + content: "\F0AC2"; +} + +.mdi-help::before { + content: "\F02D6"; +} + +.mdi-help-box::before { + content: "\F078B"; +} + +.mdi-help-circle::before { + content: "\F02D7"; +} + +.mdi-help-circle-outline::before { + content: "\F0625"; +} + +.mdi-help-network::before { + content: "\F06F5"; +} + +.mdi-help-network-outline::before { + content: "\F0C8A"; +} + +.mdi-help-rhombus::before { + content: "\F0BA5"; +} + +.mdi-help-rhombus-outline::before { + content: "\F0BA6"; +} + +.mdi-hexadecimal::before { + content: "\F12A7"; +} + +.mdi-hexagon::before { + content: "\F02D8"; +} + +.mdi-hexagon-multiple::before { + content: "\F06E1"; +} + +.mdi-hexagon-multiple-outline::before { + content: "\F10F2"; +} + +.mdi-hexagon-outline::before { + content: "\F02D9"; +} + +.mdi-hexagon-slice-1::before { + content: "\F0AC3"; +} + +.mdi-hexagon-slice-2::before { + content: "\F0AC4"; +} + +.mdi-hexagon-slice-3::before { + content: "\F0AC5"; +} + +.mdi-hexagon-slice-4::before { + content: "\F0AC6"; +} + +.mdi-hexagon-slice-5::before { + content: "\F0AC7"; +} + +.mdi-hexagon-slice-6::before { + content: "\F0AC8"; +} + +.mdi-hexagram::before { + content: "\F0AC9"; +} + +.mdi-hexagram-outline::before { + content: "\F0ACA"; +} + +.mdi-high-definition::before { + content: "\F07CF"; +} + +.mdi-high-definition-box::before { + content: "\F0878"; +} + +.mdi-highway::before { + content: "\F05F7"; +} + +.mdi-hiking::before { + content: "\F0D7F"; +} + +.mdi-hinduism::before { + content: "\F0973"; +} + +.mdi-history::before { + content: "\F02DA"; +} + +.mdi-hockey-puck::before { + content: "\F0879"; +} + +.mdi-hockey-sticks::before { + content: "\F087A"; +} + +.mdi-hololens::before { + content: "\F02DB"; +} + +.mdi-home::before { + content: "\F02DC"; +} + +.mdi-home-account::before { + content: "\F0826"; +} + +.mdi-home-alert::before { + content: "\F087B"; +} + +.mdi-home-alert-outline::before { + content: "\F15D0"; +} + +.mdi-home-analytics::before { + content: "\F0EBA"; +} + +.mdi-home-assistant::before { + content: "\F07D0"; +} + +.mdi-home-automation::before { + content: "\F07D1"; +} + +.mdi-home-circle::before { + content: "\F07D2"; +} + +.mdi-home-circle-outline::before { + content: "\F104D"; +} + +.mdi-home-city::before { + content: "\F0D15"; +} + +.mdi-home-city-outline::before { + content: "\F0D16"; +} + +.mdi-home-currency-usd::before { + content: "\F08AF"; +} + +.mdi-home-edit::before { + content: "\F1159"; +} + +.mdi-home-edit-outline::before { + content: "\F115A"; +} + +.mdi-home-export-outline::before { + content: "\F0F9B"; +} + +.mdi-home-flood::before { + content: "\F0EFA"; +} + +.mdi-home-floor-0::before { + content: "\F0DD2"; +} + +.mdi-home-floor-1::before { + content: "\F0D80"; +} + +.mdi-home-floor-2::before { + content: "\F0D81"; +} + +.mdi-home-floor-3::before { + content: "\F0D82"; +} + +.mdi-home-floor-a::before { + content: "\F0D83"; +} + +.mdi-home-floor-b::before { + content: "\F0D84"; +} + +.mdi-home-floor-g::before { + content: "\F0D85"; +} + +.mdi-home-floor-l::before { + content: "\F0D86"; +} + +.mdi-home-floor-negative-1::before { + content: "\F0DD3"; +} + +.mdi-home-group::before { + content: "\F0DD4"; +} + +.mdi-home-heart::before { + content: "\F0827"; +} + +.mdi-home-import-outline::before { + content: "\F0F9C"; +} + +.mdi-home-lightbulb::before { + content: "\F1251"; +} + +.mdi-home-lightbulb-outline::before { + content: "\F1252"; +} + +.mdi-home-lock::before { + content: "\F08EB"; +} + +.mdi-home-lock-open::before { + content: "\F08EC"; +} + +.mdi-home-map-marker::before { + content: "\F05F8"; +} + +.mdi-home-minus::before { + content: "\F0974"; +} + +.mdi-home-minus-outline::before { + content: "\F13D5"; +} + +.mdi-home-modern::before { + content: "\F02DD"; +} + +.mdi-home-outline::before { + content: "\F06A1"; +} + +.mdi-home-plus::before { + content: "\F0975"; +} + +.mdi-home-plus-outline::before { + content: "\F13D6"; +} + +.mdi-home-remove::before { + content: "\F1247"; +} + +.mdi-home-remove-outline::before { + content: "\F13D7"; +} + +.mdi-home-roof::before { + content: "\F112B"; +} + +.mdi-home-search::before { + content: "\F13B0"; +} + +.mdi-home-search-outline::before { + content: "\F13B1"; +} + +.mdi-home-thermometer::before { + content: "\F0F54"; +} + +.mdi-home-thermometer-outline::before { + content: "\F0F55"; +} + +.mdi-home-variant::before { + content: "\F02DE"; +} + +.mdi-home-variant-outline::before { + content: "\F0BA7"; +} + +.mdi-hook::before { + content: "\F06E2"; +} + +.mdi-hook-off::before { + content: "\F06E3"; +} + +.mdi-hops::before { + content: "\F02DF"; +} + +.mdi-horizontal-rotate-clockwise::before { + content: "\F10F3"; +} + +.mdi-horizontal-rotate-counterclockwise::before { + content: "\F10F4"; +} + +.mdi-horse::before { + content: "\F15BF"; +} + +.mdi-horse-human::before { + content: "\F15C0"; +} + +.mdi-horse-variant::before { + content: "\F15C1"; +} + +.mdi-horseshoe::before { + content: "\F0A58"; +} + +.mdi-hospital::before { + content: "\F0FF6"; +} + +.mdi-hospital-box::before { + content: "\F02E0"; +} + +.mdi-hospital-box-outline::before { + content: "\F0FF7"; +} + +.mdi-hospital-building::before { + content: "\F02E1"; +} + +.mdi-hospital-marker::before { + content: "\F02E2"; +} + +.mdi-hot-tub::before { + content: "\F0828"; +} + +.mdi-hours-24::before { + content: "\F1478"; +} + +.mdi-hubspot::before { + content: "\F0D17"; +} + +.mdi-hulu::before { + content: "\F0829"; +} + +.mdi-human::before { + content: "\F02E6"; +} + +.mdi-human-baby-changing-table::before { + content: "\F138B"; +} + +.mdi-human-cane::before { + content: "\F1581"; +} + +.mdi-human-capacity-decrease::before { + content: "\F159B"; +} + +.mdi-human-capacity-increase::before { + content: "\F159C"; +} + +.mdi-human-child::before { + content: "\F02E7"; +} + +.mdi-human-edit::before { + content: "\F14E8"; +} + +.mdi-human-female::before { + content: "\F0649"; +} + +.mdi-human-female-boy::before { + content: "\F0A59"; +} + +.mdi-human-female-dance::before { + content: "\F15C9"; +} + +.mdi-human-female-female::before { + content: "\F0A5A"; +} + +.mdi-human-female-girl::before { + content: "\F0A5B"; +} + +.mdi-human-greeting::before { + content: "\F064A"; +} + +.mdi-human-greeting-proximity::before { + content: "\F159D"; +} + +.mdi-human-handsdown::before { + content: "\F064B"; +} + +.mdi-human-handsup::before { + content: "\F064C"; +} + +.mdi-human-male::before { + content: "\F064D"; +} + +.mdi-human-male-boy::before { + content: "\F0A5C"; +} + +.mdi-human-male-child::before { + content: "\F138C"; +} + +.mdi-human-male-female::before { + content: "\F02E8"; +} + +.mdi-human-male-girl::before { + content: "\F0A5D"; +} + +.mdi-human-male-height::before { + content: "\F0EFB"; +} + +.mdi-human-male-height-variant::before { + content: "\F0EFC"; +} + +.mdi-human-male-male::before { + content: "\F0A5E"; +} + +.mdi-human-pregnant::before { + content: "\F05CF"; +} + +.mdi-human-queue::before { + content: "\F1571"; +} + +.mdi-human-scooter::before { + content: "\F11E9"; +} + +.mdi-human-wheelchair::before { + content: "\F138D"; +} + +.mdi-humble-bundle::before { + content: "\F0744"; +} + +.mdi-hvac::before { + content: "\F1352"; +} + +.mdi-hvac-off::before { + content: "\F159E"; +} + +.mdi-hydraulic-oil-level::before { + content: "\F1324"; +} + +.mdi-hydraulic-oil-temperature::before { + content: "\F1325"; +} + +.mdi-hydro-power::before { + content: "\F12E5"; +} + +.mdi-ice-cream::before { + content: "\F082A"; +} + +.mdi-ice-cream-off::before { + content: "\F0E52"; +} + +.mdi-ice-pop::before { + content: "\F0EFD"; +} + +.mdi-id-card::before { + content: "\F0FC0"; +} + +.mdi-identifier::before { + content: "\F0EFE"; +} + +.mdi-ideogram-cjk::before { + content: "\F1331"; +} + +.mdi-ideogram-cjk-variant::before { + content: "\F1332"; +} + +.mdi-iframe::before { + content: "\F0C8B"; +} + +.mdi-iframe-array::before { + content: "\F10F5"; +} + +.mdi-iframe-array-outline::before { + content: "\F10F6"; +} + +.mdi-iframe-braces::before { + content: "\F10F7"; +} + +.mdi-iframe-braces-outline::before { + content: "\F10F8"; +} + +.mdi-iframe-outline::before { + content: "\F0C8C"; +} + +.mdi-iframe-parentheses::before { + content: "\F10F9"; +} + +.mdi-iframe-parentheses-outline::before { + content: "\F10FA"; +} + +.mdi-iframe-variable::before { + content: "\F10FB"; +} + +.mdi-iframe-variable-outline::before { + content: "\F10FC"; +} + +.mdi-image::before { + content: "\F02E9"; +} + +.mdi-image-album::before { + content: "\F02EA"; +} + +.mdi-image-area::before { + content: "\F02EB"; +} + +.mdi-image-area-close::before { + content: "\F02EC"; +} + +.mdi-image-auto-adjust::before { + content: "\F0FC1"; +} + +.mdi-image-broken::before { + content: "\F02ED"; +} + +.mdi-image-broken-variant::before { + content: "\F02EE"; +} + +.mdi-image-edit::before { + content: "\F11E3"; +} + +.mdi-image-edit-outline::before { + content: "\F11E4"; +} + +.mdi-image-filter-black-white::before { + content: "\F02F0"; +} + +.mdi-image-filter-center-focus::before { + content: "\F02F1"; +} + +.mdi-image-filter-center-focus-strong::before { + content: "\F0EFF"; +} + +.mdi-image-filter-center-focus-strong-outline::before { + content: "\F0F00"; +} + +.mdi-image-filter-center-focus-weak::before { + content: "\F02F2"; +} + +.mdi-image-filter-drama::before { + content: "\F02F3"; +} + +.mdi-image-filter-frames::before { + content: "\F02F4"; +} + +.mdi-image-filter-hdr::before { + content: "\F02F5"; +} + +.mdi-image-filter-none::before { + content: "\F02F6"; +} + +.mdi-image-filter-tilt-shift::before { + content: "\F02F7"; +} + +.mdi-image-filter-vintage::before { + content: "\F02F8"; +} + +.mdi-image-frame::before { + content: "\F0E49"; +} + +.mdi-image-minus::before { + content: "\F1419"; +} + +.mdi-image-move::before { + content: "\F09F8"; +} + +.mdi-image-multiple::before { + content: "\F02F9"; +} + +.mdi-image-multiple-outline::before { + content: "\F02EF"; +} + +.mdi-image-off::before { + content: "\F082B"; +} + +.mdi-image-off-outline::before { + content: "\F11D1"; +} + +.mdi-image-outline::before { + content: "\F0976"; +} + +.mdi-image-plus::before { + content: "\F087C"; +} + +.mdi-image-remove::before { + content: "\F1418"; +} + +.mdi-image-search::before { + content: "\F0977"; +} + +.mdi-image-search-outline::before { + content: "\F0978"; +} + +.mdi-image-size-select-actual::before { + content: "\F0C8D"; +} + +.mdi-image-size-select-large::before { + content: "\F0C8E"; +} + +.mdi-image-size-select-small::before { + content: "\F0C8F"; +} + +.mdi-image-text::before { + content: "\F160D"; +} + +.mdi-import::before { + content: "\F02FA"; +} + +.mdi-inbox::before { + content: "\F0687"; +} + +.mdi-inbox-arrow-down::before { + content: "\F02FB"; +} + +.mdi-inbox-arrow-down-outline::before { + content: "\F1270"; +} + +.mdi-inbox-arrow-up::before { + content: "\F03D1"; +} + +.mdi-inbox-arrow-up-outline::before { + content: "\F1271"; +} + +.mdi-inbox-full::before { + content: "\F1272"; +} + +.mdi-inbox-full-outline::before { + content: "\F1273"; +} + +.mdi-inbox-multiple::before { + content: "\F08B0"; +} + +.mdi-inbox-multiple-outline::before { + content: "\F0BA8"; +} + +.mdi-inbox-outline::before { + content: "\F1274"; +} + +.mdi-inbox-remove::before { + content: "\F159F"; +} + +.mdi-inbox-remove-outline::before { + content: "\F15A0"; +} + +.mdi-incognito::before { + content: "\F05F9"; +} + +.mdi-incognito-circle::before { + content: "\F1421"; +} + +.mdi-incognito-circle-off::before { + content: "\F1422"; +} + +.mdi-incognito-off::before { + content: "\F0075"; +} + +.mdi-infinity::before { + content: "\F06E4"; +} + +.mdi-information::before { + content: "\F02FC"; +} + +.mdi-information-outline::before { + content: "\F02FD"; +} + +.mdi-information-variant::before { + content: "\F064E"; +} + +.mdi-instagram::before { + content: "\F02FE"; +} + +.mdi-instrument-triangle::before { + content: "\F104E"; +} + +.mdi-invert-colors::before { + content: "\F0301"; +} + +.mdi-invert-colors-off::before { + content: "\F0E4A"; +} + +.mdi-iobroker::before { + content: "\F12E8"; +} + +.mdi-ip::before { + content: "\F0A5F"; +} + +.mdi-ip-network::before { + content: "\F0A60"; +} + +.mdi-ip-network-outline::before { + content: "\F0C90"; +} + +.mdi-ipod::before { + content: "\F0C91"; +} + +.mdi-islam::before { + content: "\F0979"; +} + +.mdi-island::before { + content: "\F104F"; +} + +.mdi-iv-bag::before { + content: "\F10B9"; +} + +.mdi-jabber::before { + content: "\F0DD5"; +} + +.mdi-jeepney::before { + content: "\F0302"; +} + +.mdi-jellyfish::before { + content: "\F0F01"; +} + +.mdi-jellyfish-outline::before { + content: "\F0F02"; +} + +.mdi-jira::before { + content: "\F0303"; +} + +.mdi-jquery::before { + content: "\F087D"; +} + +.mdi-jsfiddle::before { + content: "\F0304"; +} + +.mdi-judaism::before { + content: "\F097A"; +} + +.mdi-jump-rope::before { + content: "\F12FF"; +} + +.mdi-kabaddi::before { + content: "\F0D87"; +} + +.mdi-kangaroo::before { + content: "\F1558"; +} + +.mdi-karate::before { + content: "\F082C"; +} + +.mdi-keg::before { + content: "\F0305"; +} + +.mdi-kettle::before { + content: "\F05FA"; +} + +.mdi-kettle-alert::before { + content: "\F1317"; +} + +.mdi-kettle-alert-outline::before { + content: "\F1318"; +} + +.mdi-kettle-off::before { + content: "\F131B"; +} + +.mdi-kettle-off-outline::before { + content: "\F131C"; +} + +.mdi-kettle-outline::before { + content: "\F0F56"; +} + +.mdi-kettle-steam::before { + content: "\F1319"; +} + +.mdi-kettle-steam-outline::before { + content: "\F131A"; +} + +.mdi-kettlebell::before { + content: "\F1300"; +} + +.mdi-key::before { + content: "\F0306"; +} + +.mdi-key-arrow-right::before { + content: "\F1312"; +} + +.mdi-key-chain::before { + content: "\F1574"; +} + +.mdi-key-chain-variant::before { + content: "\F1575"; +} + +.mdi-key-change::before { + content: "\F0307"; +} + +.mdi-key-link::before { + content: "\F119F"; +} + +.mdi-key-minus::before { + content: "\F0308"; +} + +.mdi-key-outline::before { + content: "\F0DD6"; +} + +.mdi-key-plus::before { + content: "\F0309"; +} + +.mdi-key-remove::before { + content: "\F030A"; +} + +.mdi-key-star::before { + content: "\F119E"; +} + +.mdi-key-variant::before { + content: "\F030B"; +} + +.mdi-key-wireless::before { + content: "\F0FC2"; +} + +.mdi-keyboard::before { + content: "\F030C"; +} + +.mdi-keyboard-backspace::before { + content: "\F030D"; +} + +.mdi-keyboard-caps::before { + content: "\F030E"; +} + +.mdi-keyboard-close::before { + content: "\F030F"; +} + +.mdi-keyboard-esc::before { + content: "\F12B7"; +} + +.mdi-keyboard-f1::before { + content: "\F12AB"; +} + +.mdi-keyboard-f10::before { + content: "\F12B4"; +} + +.mdi-keyboard-f11::before { + content: "\F12B5"; +} + +.mdi-keyboard-f12::before { + content: "\F12B6"; +} + +.mdi-keyboard-f2::before { + content: "\F12AC"; +} + +.mdi-keyboard-f3::before { + content: "\F12AD"; +} + +.mdi-keyboard-f4::before { + content: "\F12AE"; +} + +.mdi-keyboard-f5::before { + content: "\F12AF"; +} + +.mdi-keyboard-f6::before { + content: "\F12B0"; +} + +.mdi-keyboard-f7::before { + content: "\F12B1"; +} + +.mdi-keyboard-f8::before { + content: "\F12B2"; +} + +.mdi-keyboard-f9::before { + content: "\F12B3"; +} + +.mdi-keyboard-off::before { + content: "\F0310"; +} + +.mdi-keyboard-off-outline::before { + content: "\F0E4B"; +} + +.mdi-keyboard-outline::before { + content: "\F097B"; +} + +.mdi-keyboard-return::before { + content: "\F0311"; +} + +.mdi-keyboard-settings::before { + content: "\F09F9"; +} + +.mdi-keyboard-settings-outline::before { + content: "\F09FA"; +} + +.mdi-keyboard-space::before { + content: "\F1050"; +} + +.mdi-keyboard-tab::before { + content: "\F0312"; +} + +.mdi-keyboard-variant::before { + content: "\F0313"; +} + +.mdi-khanda::before { + content: "\F10FD"; +} + +.mdi-kickstarter::before { + content: "\F0745"; +} + +.mdi-klingon::before { + content: "\F135B"; +} + +.mdi-knife::before { + content: "\F09FB"; +} + +.mdi-knife-military::before { + content: "\F09FC"; +} + +.mdi-kodi::before { + content: "\F0314"; +} + +.mdi-kubernetes::before { + content: "\F10FE"; +} + +.mdi-label::before { + content: "\F0315"; +} + +.mdi-label-multiple::before { + content: "\F1375"; +} + +.mdi-label-multiple-outline::before { + content: "\F1376"; +} + +.mdi-label-off::before { + content: "\F0ACB"; +} + +.mdi-label-off-outline::before { + content: "\F0ACC"; +} + +.mdi-label-outline::before { + content: "\F0316"; +} + +.mdi-label-percent::before { + content: "\F12EA"; +} + +.mdi-label-percent-outline::before { + content: "\F12EB"; +} + +.mdi-label-variant::before { + content: "\F0ACD"; +} + +.mdi-label-variant-outline::before { + content: "\F0ACE"; +} + +.mdi-ladder::before { + content: "\F15A2"; +} + +.mdi-ladybug::before { + content: "\F082D"; +} + +.mdi-lambda::before { + content: "\F0627"; +} + +.mdi-lamp::before { + content: "\F06B5"; +} + +.mdi-lamps::before { + content: "\F1576"; +} + +.mdi-lan::before { + content: "\F0317"; +} + +.mdi-lan-check::before { + content: "\F12AA"; +} + +.mdi-lan-connect::before { + content: "\F0318"; +} + +.mdi-lan-disconnect::before { + content: "\F0319"; +} + +.mdi-lan-pending::before { + content: "\F031A"; +} + +.mdi-language-c::before { + content: "\F0671"; +} + +.mdi-language-cpp::before { + content: "\F0672"; +} + +.mdi-language-csharp::before { + content: "\F031B"; +} + +.mdi-language-css3::before { + content: "\F031C"; +} + +.mdi-language-fortran::before { + content: "\F121A"; +} + +.mdi-language-go::before { + content: "\F07D3"; +} + +.mdi-language-haskell::before { + content: "\F0C92"; +} + +.mdi-language-html5::before { + content: "\F031D"; +} + +.mdi-language-java::before { + content: "\F0B37"; +} + +.mdi-language-javascript::before { + content: "\F031E"; +} + +.mdi-language-kotlin::before { + content: "\F1219"; +} + +.mdi-language-lua::before { + content: "\F08B1"; +} + +.mdi-language-markdown::before { + content: "\F0354"; +} + +.mdi-language-markdown-outline::before { + content: "\F0F5B"; +} + +.mdi-language-php::before { + content: "\F031F"; +} + +.mdi-language-python::before { + content: "\F0320"; +} + +.mdi-language-r::before { + content: "\F07D4"; +} + +.mdi-language-ruby::before { + content: "\F0D2D"; +} + +.mdi-language-ruby-on-rails::before { + content: "\F0ACF"; +} + +.mdi-language-rust::before { + content: "\F1617"; +} + +.mdi-language-swift::before { + content: "\F06E5"; +} + +.mdi-language-typescript::before { + content: "\F06E6"; +} + +.mdi-language-xaml::before { + content: "\F0673"; +} + +.mdi-laptop::before { + content: "\F0322"; +} + +.mdi-laptop-chromebook::before { + content: "\F0323"; +} + +.mdi-laptop-mac::before { + content: "\F0324"; +} + +.mdi-laptop-off::before { + content: "\F06E7"; +} + +.mdi-laptop-windows::before { + content: "\F0325"; +} + +.mdi-laravel::before { + content: "\F0AD0"; +} + +.mdi-laser-pointer::before { + content: "\F1484"; +} + +.mdi-lasso::before { + content: "\F0F03"; +} + +.mdi-lastpass::before { + content: "\F0446"; +} + +.mdi-latitude::before { + content: "\F0F57"; +} + +.mdi-launch::before { + content: "\F0327"; +} + +.mdi-lava-lamp::before { + content: "\F07D5"; +} + +.mdi-layers::before { + content: "\F0328"; +} + +.mdi-layers-minus::before { + content: "\F0E4C"; +} + +.mdi-layers-off::before { + content: "\F0329"; +} + +.mdi-layers-off-outline::before { + content: "\F09FD"; +} + +.mdi-layers-outline::before { + content: "\F09FE"; +} + +.mdi-layers-plus::before { + content: "\F0E4D"; +} + +.mdi-layers-remove::before { + content: "\F0E4E"; +} + +.mdi-layers-search::before { + content: "\F1206"; +} + +.mdi-layers-search-outline::before { + content: "\F1207"; +} + +.mdi-layers-triple::before { + content: "\F0F58"; +} + +.mdi-layers-triple-outline::before { + content: "\F0F59"; +} + +.mdi-lead-pencil::before { + content: "\F064F"; +} + +.mdi-leaf::before { + content: "\F032A"; +} + +.mdi-leaf-maple::before { + content: "\F0C93"; +} + +.mdi-leaf-maple-off::before { + content: "\F12DA"; +} + +.mdi-leaf-off::before { + content: "\F12D9"; +} + +.mdi-leak::before { + content: "\F0DD7"; +} + +.mdi-leak-off::before { + content: "\F0DD8"; +} + +.mdi-led-off::before { + content: "\F032B"; +} + +.mdi-led-on::before { + content: "\F032C"; +} + +.mdi-led-outline::before { + content: "\F032D"; +} + +.mdi-led-strip::before { + content: "\F07D6"; +} + +.mdi-led-strip-variant::before { + content: "\F1051"; +} + +.mdi-led-variant-off::before { + content: "\F032E"; +} + +.mdi-led-variant-on::before { + content: "\F032F"; +} + +.mdi-led-variant-outline::before { + content: "\F0330"; +} + +.mdi-leek::before { + content: "\F117D"; +} + +.mdi-less-than::before { + content: "\F097C"; +} + +.mdi-less-than-or-equal::before { + content: "\F097D"; +} + +.mdi-library::before { + content: "\F0331"; +} + +.mdi-library-shelves::before { + content: "\F0BA9"; +} + +.mdi-license::before { + content: "\F0FC3"; +} + +.mdi-lifebuoy::before { + content: "\F087E"; +} + +.mdi-light-switch::before { + content: "\F097E"; +} + +.mdi-lightbulb::before { + content: "\F0335"; +} + +.mdi-lightbulb-cfl::before { + content: "\F1208"; +} + +.mdi-lightbulb-cfl-off::before { + content: "\F1209"; +} + +.mdi-lightbulb-cfl-spiral::before { + content: "\F1275"; +} + +.mdi-lightbulb-cfl-spiral-off::before { + content: "\F12C3"; +} + +.mdi-lightbulb-group::before { + content: "\F1253"; +} + +.mdi-lightbulb-group-off::before { + content: "\F12CD"; +} + +.mdi-lightbulb-group-off-outline::before { + content: "\F12CE"; +} + +.mdi-lightbulb-group-outline::before { + content: "\F1254"; +} + +.mdi-lightbulb-multiple::before { + content: "\F1255"; +} + +.mdi-lightbulb-multiple-off::before { + content: "\F12CF"; +} + +.mdi-lightbulb-multiple-off-outline::before { + content: "\F12D0"; +} + +.mdi-lightbulb-multiple-outline::before { + content: "\F1256"; +} + +.mdi-lightbulb-off::before { + content: "\F0E4F"; +} + +.mdi-lightbulb-off-outline::before { + content: "\F0E50"; +} + +.mdi-lightbulb-on::before { + content: "\F06E8"; +} + +.mdi-lightbulb-on-outline::before { + content: "\F06E9"; +} + +.mdi-lightbulb-outline::before { + content: "\F0336"; +} + +.mdi-lighthouse::before { + content: "\F09FF"; +} + +.mdi-lighthouse-on::before { + content: "\F0A00"; +} + +.mdi-lightning-bolt::before { + content: "\F140B"; +} + +.mdi-lightning-bolt-outline::before { + content: "\F140C"; +} + +.mdi-lingerie::before { + content: "\F1476"; +} + +.mdi-link::before { + content: "\F0337"; +} + +.mdi-link-box::before { + content: "\F0D1A"; +} + +.mdi-link-box-outline::before { + content: "\F0D1B"; +} + +.mdi-link-box-variant::before { + content: "\F0D1C"; +} + +.mdi-link-box-variant-outline::before { + content: "\F0D1D"; +} + +.mdi-link-lock::before { + content: "\F10BA"; +} + +.mdi-link-off::before { + content: "\F0338"; +} + +.mdi-link-plus::before { + content: "\F0C94"; +} + +.mdi-link-variant::before { + content: "\F0339"; +} + +.mdi-link-variant-minus::before { + content: "\F10FF"; +} + +.mdi-link-variant-off::before { + content: "\F033A"; +} + +.mdi-link-variant-plus::before { + content: "\F1100"; +} + +.mdi-link-variant-remove::before { + content: "\F1101"; +} + +.mdi-linkedin::before { + content: "\F033B"; +} + +.mdi-linux::before { + content: "\F033D"; +} + +.mdi-linux-mint::before { + content: "\F08ED"; +} + +.mdi-lipstick::before { + content: "\F13B5"; +} + +.mdi-list-status::before { + content: "\F15AB"; +} + +.mdi-litecoin::before { + content: "\F0A61"; +} + +.mdi-loading::before { + content: "\F0772"; +} + +.mdi-location-enter::before { + content: "\F0FC4"; +} + +.mdi-location-exit::before { + content: "\F0FC5"; +} + +.mdi-lock::before { + content: "\F033E"; +} + +.mdi-lock-alert::before { + content: "\F08EE"; +} + +.mdi-lock-alert-outline::before { + content: "\F15D1"; +} + +.mdi-lock-check::before { + content: "\F139A"; +} + +.mdi-lock-check-outline::before { + content: "\F16A8"; +} + +.mdi-lock-clock::before { + content: "\F097F"; +} + +.mdi-lock-minus::before { + content: "\F16A9"; +} + +.mdi-lock-minus-outline::before { + content: "\F16AA"; +} + +.mdi-lock-off::before { + content: "\F1671"; +} + +.mdi-lock-off-outline::before { + content: "\F1672"; +} + +.mdi-lock-open::before { + content: "\F033F"; +} + +.mdi-lock-open-alert::before { + content: "\F139B"; +} + +.mdi-lock-open-alert-outline::before { + content: "\F15D2"; +} + +.mdi-lock-open-check::before { + content: "\F139C"; +} + +.mdi-lock-open-check-outline::before { + content: "\F16AB"; +} + +.mdi-lock-open-minus::before { + content: "\F16AC"; +} + +.mdi-lock-open-minus-outline::before { + content: "\F16AD"; +} + +.mdi-lock-open-outline::before { + content: "\F0340"; +} + +.mdi-lock-open-plus::before { + content: "\F16AE"; +} + +.mdi-lock-open-plus-outline::before { + content: "\F16AF"; +} + +.mdi-lock-open-remove::before { + content: "\F16B0"; +} + +.mdi-lock-open-remove-outline::before { + content: "\F16B1"; +} + +.mdi-lock-open-variant::before { + content: "\F0FC6"; +} + +.mdi-lock-open-variant-outline::before { + content: "\F0FC7"; +} + +.mdi-lock-outline::before { + content: "\F0341"; +} + +.mdi-lock-pattern::before { + content: "\F06EA"; +} + +.mdi-lock-plus::before { + content: "\F05FB"; +} + +.mdi-lock-plus-outline::before { + content: "\F16B2"; +} + +.mdi-lock-question::before { + content: "\F08EF"; +} + +.mdi-lock-remove::before { + content: "\F16B3"; +} + +.mdi-lock-remove-outline::before { + content: "\F16B4"; +} + +.mdi-lock-reset::before { + content: "\F0773"; +} + +.mdi-lock-smart::before { + content: "\F08B2"; +} + +.mdi-locker::before { + content: "\F07D7"; +} + +.mdi-locker-multiple::before { + content: "\F07D8"; +} + +.mdi-login::before { + content: "\F0342"; +} + +.mdi-login-variant::before { + content: "\F05FC"; +} + +.mdi-logout::before { + content: "\F0343"; +} + +.mdi-logout-variant::before { + content: "\F05FD"; +} + +.mdi-longitude::before { + content: "\F0F5A"; +} + +.mdi-looks::before { + content: "\F0344"; +} + +.mdi-lotion::before { + content: "\F1582"; +} + +.mdi-lotion-outline::before { + content: "\F1583"; +} + +.mdi-lotion-plus::before { + content: "\F1584"; +} + +.mdi-lotion-plus-outline::before { + content: "\F1585"; +} + +.mdi-loupe::before { + content: "\F0345"; +} + +.mdi-lumx::before { + content: "\F0346"; +} + +.mdi-lungs::before { + content: "\F1084"; +} + +.mdi-magnet::before { + content: "\F0347"; +} + +.mdi-magnet-on::before { + content: "\F0348"; +} + +.mdi-magnify::before { + content: "\F0349"; +} + +.mdi-magnify-close::before { + content: "\F0980"; +} + +.mdi-magnify-minus::before { + content: "\F034A"; +} + +.mdi-magnify-minus-cursor::before { + content: "\F0A62"; +} + +.mdi-magnify-minus-outline::before { + content: "\F06EC"; +} + +.mdi-magnify-plus::before { + content: "\F034B"; +} + +.mdi-magnify-plus-cursor::before { + content: "\F0A63"; +} + +.mdi-magnify-plus-outline::before { + content: "\F06ED"; +} + +.mdi-magnify-remove-cursor::before { + content: "\F120C"; +} + +.mdi-magnify-remove-outline::before { + content: "\F120D"; +} + +.mdi-magnify-scan::before { + content: "\F1276"; +} + +.mdi-mail::before { + content: "\F0EBB"; +} + +.mdi-mailbox::before { + content: "\F06EE"; +} + +.mdi-mailbox-open::before { + content: "\F0D88"; +} + +.mdi-mailbox-open-outline::before { + content: "\F0D89"; +} + +.mdi-mailbox-open-up::before { + content: "\F0D8A"; +} + +.mdi-mailbox-open-up-outline::before { + content: "\F0D8B"; +} + +.mdi-mailbox-outline::before { + content: "\F0D8C"; +} + +.mdi-mailbox-up::before { + content: "\F0D8D"; +} + +.mdi-mailbox-up-outline::before { + content: "\F0D8E"; +} + +.mdi-manjaro::before { + content: "\F160A"; +} + +.mdi-map::before { + content: "\F034D"; +} + +.mdi-map-check::before { + content: "\F0EBC"; +} + +.mdi-map-check-outline::before { + content: "\F0EBD"; +} + +.mdi-map-clock::before { + content: "\F0D1E"; +} + +.mdi-map-clock-outline::before { + content: "\F0D1F"; +} + +.mdi-map-legend::before { + content: "\F0A01"; +} + +.mdi-map-marker::before { + content: "\F034E"; +} + +.mdi-map-marker-alert::before { + content: "\F0F05"; +} + +.mdi-map-marker-alert-outline::before { + content: "\F0F06"; +} + +.mdi-map-marker-check::before { + content: "\F0C95"; +} + +.mdi-map-marker-check-outline::before { + content: "\F12FB"; +} + +.mdi-map-marker-circle::before { + content: "\F034F"; +} + +.mdi-map-marker-distance::before { + content: "\F08F0"; +} + +.mdi-map-marker-down::before { + content: "\F1102"; +} + +.mdi-map-marker-left::before { + content: "\F12DB"; +} + +.mdi-map-marker-left-outline::before { + content: "\F12DD"; +} + +.mdi-map-marker-minus::before { + content: "\F0650"; +} + +.mdi-map-marker-minus-outline::before { + content: "\F12F9"; +} + +.mdi-map-marker-multiple::before { + content: "\F0350"; +} + +.mdi-map-marker-multiple-outline::before { + content: "\F1277"; +} + +.mdi-map-marker-off::before { + content: "\F0351"; +} + +.mdi-map-marker-off-outline::before { + content: "\F12FD"; +} + +.mdi-map-marker-outline::before { + content: "\F07D9"; +} + +.mdi-map-marker-path::before { + content: "\F0D20"; +} + +.mdi-map-marker-plus::before { + content: "\F0651"; +} + +.mdi-map-marker-plus-outline::before { + content: "\F12F8"; +} + +.mdi-map-marker-question::before { + content: "\F0F07"; +} + +.mdi-map-marker-question-outline::before { + content: "\F0F08"; +} + +.mdi-map-marker-radius::before { + content: "\F0352"; +} + +.mdi-map-marker-radius-outline::before { + content: "\F12FC"; +} + +.mdi-map-marker-remove::before { + content: "\F0F09"; +} + +.mdi-map-marker-remove-outline::before { + content: "\F12FA"; +} + +.mdi-map-marker-remove-variant::before { + content: "\F0F0A"; +} + +.mdi-map-marker-right::before { + content: "\F12DC"; +} + +.mdi-map-marker-right-outline::before { + content: "\F12DE"; +} + +.mdi-map-marker-star::before { + content: "\F1608"; +} + +.mdi-map-marker-star-outline::before { + content: "\F1609"; +} + +.mdi-map-marker-up::before { + content: "\F1103"; +} + +.mdi-map-minus::before { + content: "\F0981"; +} + +.mdi-map-outline::before { + content: "\F0982"; +} + +.mdi-map-plus::before { + content: "\F0983"; +} + +.mdi-map-search::before { + content: "\F0984"; +} + +.mdi-map-search-outline::before { + content: "\F0985"; +} + +.mdi-mapbox::before { + content: "\F0BAA"; +} + +.mdi-margin::before { + content: "\F0353"; +} + +.mdi-marker::before { + content: "\F0652"; +} + +.mdi-marker-cancel::before { + content: "\F0DD9"; +} + +.mdi-marker-check::before { + content: "\F0355"; +} + +.mdi-mastodon::before { + content: "\F0AD1"; +} + +.mdi-material-design::before { + content: "\F0986"; +} + +.mdi-material-ui::before { + content: "\F0357"; +} + +.mdi-math-compass::before { + content: "\F0358"; +} + +.mdi-math-cos::before { + content: "\F0C96"; +} + +.mdi-math-integral::before { + content: "\F0FC8"; +} + +.mdi-math-integral-box::before { + content: "\F0FC9"; +} + +.mdi-math-log::before { + content: "\F1085"; +} + +.mdi-math-norm::before { + content: "\F0FCA"; +} + +.mdi-math-norm-box::before { + content: "\F0FCB"; +} + +.mdi-math-sin::before { + content: "\F0C97"; +} + +.mdi-math-tan::before { + content: "\F0C98"; +} + +.mdi-matrix::before { + content: "\F0628"; +} + +.mdi-medal::before { + content: "\F0987"; +} + +.mdi-medal-outline::before { + content: "\F1326"; +} + +.mdi-medical-bag::before { + content: "\F06EF"; +} + +.mdi-meditation::before { + content: "\F117B"; +} + +.mdi-memory::before { + content: "\F035B"; +} + +.mdi-menu::before { + content: "\F035C"; +} + +.mdi-menu-down::before { + content: "\F035D"; +} + +.mdi-menu-down-outline::before { + content: "\F06B6"; +} + +.mdi-menu-left::before { + content: "\F035E"; +} + +.mdi-menu-left-outline::before { + content: "\F0A02"; +} + +.mdi-menu-open::before { + content: "\F0BAB"; +} + +.mdi-menu-right::before { + content: "\F035F"; +} + +.mdi-menu-right-outline::before { + content: "\F0A03"; +} + +.mdi-menu-swap::before { + content: "\F0A64"; +} + +.mdi-menu-swap-outline::before { + content: "\F0A65"; +} + +.mdi-menu-up::before { + content: "\F0360"; +} + +.mdi-menu-up-outline::before { + content: "\F06B7"; +} + +.mdi-merge::before { + content: "\F0F5C"; +} + +.mdi-message::before { + content: "\F0361"; +} + +.mdi-message-alert::before { + content: "\F0362"; +} + +.mdi-message-alert-outline::before { + content: "\F0A04"; +} + +.mdi-message-arrow-left::before { + content: "\F12F2"; +} + +.mdi-message-arrow-left-outline::before { + content: "\F12F3"; +} + +.mdi-message-arrow-right::before { + content: "\F12F4"; +} + +.mdi-message-arrow-right-outline::before { + content: "\F12F5"; +} + +.mdi-message-bookmark::before { + content: "\F15AC"; +} + +.mdi-message-bookmark-outline::before { + content: "\F15AD"; +} + +.mdi-message-bulleted::before { + content: "\F06A2"; +} + +.mdi-message-bulleted-off::before { + content: "\F06A3"; +} + +.mdi-message-cog::before { + content: "\F06F1"; +} + +.mdi-message-cog-outline::before { + content: "\F1172"; +} + +.mdi-message-draw::before { + content: "\F0363"; +} + +.mdi-message-flash::before { + content: "\F15A9"; +} + +.mdi-message-flash-outline::before { + content: "\F15AA"; +} + +.mdi-message-image::before { + content: "\F0364"; +} + +.mdi-message-image-outline::before { + content: "\F116C"; +} + +.mdi-message-lock::before { + content: "\F0FCC"; +} + +.mdi-message-lock-outline::before { + content: "\F116D"; +} + +.mdi-message-minus::before { + content: "\F116E"; +} + +.mdi-message-minus-outline::before { + content: "\F116F"; +} + +.mdi-message-off::before { + content: "\F164D"; +} + +.mdi-message-off-outline::before { + content: "\F164E"; +} + +.mdi-message-outline::before { + content: "\F0365"; +} + +.mdi-message-plus::before { + content: "\F0653"; +} + +.mdi-message-plus-outline::before { + content: "\F10BB"; +} + +.mdi-message-processing::before { + content: "\F0366"; +} + +.mdi-message-processing-outline::before { + content: "\F1170"; +} + +.mdi-message-reply::before { + content: "\F0367"; +} + +.mdi-message-reply-text::before { + content: "\F0368"; +} + +.mdi-message-settings::before { + content: "\F06F0"; +} + +.mdi-message-settings-outline::before { + content: "\F1171"; +} + +.mdi-message-text::before { + content: "\F0369"; +} + +.mdi-message-text-clock::before { + content: "\F1173"; +} + +.mdi-message-text-clock-outline::before { + content: "\F1174"; +} + +.mdi-message-text-lock::before { + content: "\F0FCD"; +} + +.mdi-message-text-lock-outline::before { + content: "\F1175"; +} + +.mdi-message-text-outline::before { + content: "\F036A"; +} + +.mdi-message-video::before { + content: "\F036B"; +} + +.mdi-meteor::before { + content: "\F0629"; +} + +.mdi-metronome::before { + content: "\F07DA"; +} + +.mdi-metronome-tick::before { + content: "\F07DB"; +} + +.mdi-micro-sd::before { + content: "\F07DC"; +} + +.mdi-microphone::before { + content: "\F036C"; +} + +.mdi-microphone-minus::before { + content: "\F08B3"; +} + +.mdi-microphone-off::before { + content: "\F036D"; +} + +.mdi-microphone-outline::before { + content: "\F036E"; +} + +.mdi-microphone-plus::before { + content: "\F08B4"; +} + +.mdi-microphone-settings::before { + content: "\F036F"; +} + +.mdi-microphone-variant::before { + content: "\F0370"; +} + +.mdi-microphone-variant-off::before { + content: "\F0371"; +} + +.mdi-microscope::before { + content: "\F0654"; +} + +.mdi-microsoft::before { + content: "\F0372"; +} + +.mdi-microsoft-access::before { + content: "\F138E"; +} + +.mdi-microsoft-azure::before { + content: "\F0805"; +} + +.mdi-microsoft-azure-devops::before { + content: "\F0FD5"; +} + +.mdi-microsoft-bing::before { + content: "\F00A4"; +} + +.mdi-microsoft-dynamics-365::before { + content: "\F0988"; +} + +.mdi-microsoft-edge::before { + content: "\F01E9"; +} + +.mdi-microsoft-edge-legacy::before { + content: "\F1250"; +} + +.mdi-microsoft-excel::before { + content: "\F138F"; +} + +.mdi-microsoft-internet-explorer::before { + content: "\F0300"; +} + +.mdi-microsoft-office::before { + content: "\F03C6"; +} + +.mdi-microsoft-onedrive::before { + content: "\F03CA"; +} + +.mdi-microsoft-onenote::before { + content: "\F0747"; +} + +.mdi-microsoft-outlook::before { + content: "\F0D22"; +} + +.mdi-microsoft-powerpoint::before { + content: "\F1390"; +} + +.mdi-microsoft-sharepoint::before { + content: "\F1391"; +} + +.mdi-microsoft-teams::before { + content: "\F02BB"; +} + +.mdi-microsoft-visual-studio::before { + content: "\F0610"; +} + +.mdi-microsoft-visual-studio-code::before { + content: "\F0A1E"; +} + +.mdi-microsoft-windows::before { + content: "\F05B3"; +} + +.mdi-microsoft-windows-classic::before { + content: "\F0A21"; +} + +.mdi-microsoft-word::before { + content: "\F1392"; +} + +.mdi-microsoft-xbox::before { + content: "\F05B9"; +} + +.mdi-microsoft-xbox-controller::before { + content: "\F05BA"; +} + +.mdi-microsoft-xbox-controller-battery-alert::before { + content: "\F074B"; +} + +.mdi-microsoft-xbox-controller-battery-charging::before { + content: "\F0A22"; +} + +.mdi-microsoft-xbox-controller-battery-empty::before { + content: "\F074C"; +} + +.mdi-microsoft-xbox-controller-battery-full::before { + content: "\F074D"; +} + +.mdi-microsoft-xbox-controller-battery-low::before { + content: "\F074E"; +} + +.mdi-microsoft-xbox-controller-battery-medium::before { + content: "\F074F"; +} + +.mdi-microsoft-xbox-controller-battery-unknown::before { + content: "\F0750"; +} + +.mdi-microsoft-xbox-controller-menu::before { + content: "\F0E6F"; +} + +.mdi-microsoft-xbox-controller-off::before { + content: "\F05BB"; +} + +.mdi-microsoft-xbox-controller-view::before { + content: "\F0E70"; +} + +.mdi-microsoft-yammer::before { + content: "\F0789"; +} + +.mdi-microwave::before { + content: "\F0C99"; +} + +.mdi-microwave-off::before { + content: "\F1423"; +} + +.mdi-middleware::before { + content: "\F0F5D"; +} + +.mdi-middleware-outline::before { + content: "\F0F5E"; +} + +.mdi-midi::before { + content: "\F08F1"; +} + +.mdi-midi-port::before { + content: "\F08F2"; +} + +.mdi-mine::before { + content: "\F0DDA"; +} + +.mdi-minecraft::before { + content: "\F0373"; +} + +.mdi-mini-sd::before { + content: "\F0A05"; +} + +.mdi-minidisc::before { + content: "\F0A06"; +} + +.mdi-minus::before { + content: "\F0374"; +} + +.mdi-minus-box::before { + content: "\F0375"; +} + +.mdi-minus-box-multiple::before { + content: "\F1141"; +} + +.mdi-minus-box-multiple-outline::before { + content: "\F1142"; +} + +.mdi-minus-box-outline::before { + content: "\F06F2"; +} + +.mdi-minus-circle::before { + content: "\F0376"; +} + +.mdi-minus-circle-multiple::before { + content: "\F035A"; +} + +.mdi-minus-circle-multiple-outline::before { + content: "\F0AD3"; +} + +.mdi-minus-circle-off::before { + content: "\F1459"; +} + +.mdi-minus-circle-off-outline::before { + content: "\F145A"; +} + +.mdi-minus-circle-outline::before { + content: "\F0377"; +} + +.mdi-minus-network::before { + content: "\F0378"; +} + +.mdi-minus-network-outline::before { + content: "\F0C9A"; +} + +.mdi-minus-thick::before { + content: "\F1639"; +} + +.mdi-mirror::before { + content: "\F11FD"; +} + +.mdi-mixed-martial-arts::before { + content: "\F0D8F"; +} + +.mdi-mixed-reality::before { + content: "\F087F"; +} + +.mdi-molecule::before { + content: "\F0BAC"; +} + +.mdi-molecule-co::before { + content: "\F12FE"; +} + +.mdi-molecule-co2::before { + content: "\F07E4"; +} + +.mdi-monitor::before { + content: "\F0379"; +} + +.mdi-monitor-cellphone::before { + content: "\F0989"; +} + +.mdi-monitor-cellphone-star::before { + content: "\F098A"; +} + +.mdi-monitor-clean::before { + content: "\F1104"; +} + +.mdi-monitor-dashboard::before { + content: "\F0A07"; +} + +.mdi-monitor-edit::before { + content: "\F12C6"; +} + +.mdi-monitor-eye::before { + content: "\F13B4"; +} + +.mdi-monitor-lock::before { + content: "\F0DDB"; +} + +.mdi-monitor-multiple::before { + content: "\F037A"; +} + +.mdi-monitor-off::before { + content: "\F0D90"; +} + +.mdi-monitor-screenshot::before { + content: "\F0E51"; +} + +.mdi-monitor-share::before { + content: "\F1483"; +} + +.mdi-monitor-speaker::before { + content: "\F0F5F"; +} + +.mdi-monitor-speaker-off::before { + content: "\F0F60"; +} + +.mdi-monitor-star::before { + content: "\F0DDC"; +} + +.mdi-moon-first-quarter::before { + content: "\F0F61"; +} + +.mdi-moon-full::before { + content: "\F0F62"; +} + +.mdi-moon-last-quarter::before { + content: "\F0F63"; +} + +.mdi-moon-new::before { + content: "\F0F64"; +} + +.mdi-moon-waning-crescent::before { + content: "\F0F65"; +} + +.mdi-moon-waning-gibbous::before { + content: "\F0F66"; +} + +.mdi-moon-waxing-crescent::before { + content: "\F0F67"; +} + +.mdi-moon-waxing-gibbous::before { + content: "\F0F68"; +} + +.mdi-moped::before { + content: "\F1086"; +} + +.mdi-moped-electric::before { + content: "\F15B7"; +} + +.mdi-moped-electric-outline::before { + content: "\F15B8"; +} + +.mdi-moped-outline::before { + content: "\F15B9"; +} + +.mdi-more::before { + content: "\F037B"; +} + +.mdi-mother-heart::before { + content: "\F1314"; +} + +.mdi-mother-nurse::before { + content: "\F0D21"; +} + +.mdi-motion::before { + content: "\F15B2"; +} + +.mdi-motion-outline::before { + content: "\F15B3"; +} + +.mdi-motion-pause::before { + content: "\F1590"; +} + +.mdi-motion-pause-outline::before { + content: "\F1592"; +} + +.mdi-motion-play::before { + content: "\F158F"; +} + +.mdi-motion-play-outline::before { + content: "\F1591"; +} + +.mdi-motion-sensor::before { + content: "\F0D91"; +} + +.mdi-motion-sensor-off::before { + content: "\F1435"; +} + +.mdi-motorbike::before { + content: "\F037C"; +} + +.mdi-motorbike-electric::before { + content: "\F15BA"; +} + +.mdi-mouse::before { + content: "\F037D"; +} + +.mdi-mouse-bluetooth::before { + content: "\F098B"; +} + +.mdi-mouse-move-down::before { + content: "\F1550"; +} + +.mdi-mouse-move-up::before { + content: "\F1551"; +} + +.mdi-mouse-move-vertical::before { + content: "\F1552"; +} + +.mdi-mouse-off::before { + content: "\F037E"; +} + +.mdi-mouse-variant::before { + content: "\F037F"; +} + +.mdi-mouse-variant-off::before { + content: "\F0380"; +} + +.mdi-move-resize::before { + content: "\F0655"; +} + +.mdi-move-resize-variant::before { + content: "\F0656"; +} + +.mdi-movie::before { + content: "\F0381"; +} + +.mdi-movie-edit::before { + content: "\F1122"; +} + +.mdi-movie-edit-outline::before { + content: "\F1123"; +} + +.mdi-movie-filter::before { + content: "\F1124"; +} + +.mdi-movie-filter-outline::before { + content: "\F1125"; +} + +.mdi-movie-open::before { + content: "\F0FCE"; +} + +.mdi-movie-open-outline::before { + content: "\F0FCF"; +} + +.mdi-movie-outline::before { + content: "\F0DDD"; +} + +.mdi-movie-roll::before { + content: "\F07DE"; +} + +.mdi-movie-search::before { + content: "\F11D2"; +} + +.mdi-movie-search-outline::before { + content: "\F11D3"; +} + +.mdi-mower::before { + content: "\F166F"; +} + +.mdi-mower-bag::before { + content: "\F1670"; +} + +.mdi-muffin::before { + content: "\F098C"; +} + +.mdi-multiplication::before { + content: "\F0382"; +} + +.mdi-multiplication-box::before { + content: "\F0383"; +} + +.mdi-mushroom::before { + content: "\F07DF"; +} + +.mdi-mushroom-off::before { + content: "\F13FA"; +} + +.mdi-mushroom-off-outline::before { + content: "\F13FB"; +} + +.mdi-mushroom-outline::before { + content: "\F07E0"; +} + +.mdi-music::before { + content: "\F075A"; +} + +.mdi-music-accidental-double-flat::before { + content: "\F0F69"; +} + +.mdi-music-accidental-double-sharp::before { + content: "\F0F6A"; +} + +.mdi-music-accidental-flat::before { + content: "\F0F6B"; +} + +.mdi-music-accidental-natural::before { + content: "\F0F6C"; +} + +.mdi-music-accidental-sharp::before { + content: "\F0F6D"; +} + +.mdi-music-box::before { + content: "\F0384"; +} + +.mdi-music-box-multiple::before { + content: "\F0333"; +} + +.mdi-music-box-multiple-outline::before { + content: "\F0F04"; +} + +.mdi-music-box-outline::before { + content: "\F0385"; +} + +.mdi-music-circle::before { + content: "\F0386"; +} + +.mdi-music-circle-outline::before { + content: "\F0AD4"; +} + +.mdi-music-clef-alto::before { + content: "\F0F6E"; +} + +.mdi-music-clef-bass::before { + content: "\F0F6F"; +} + +.mdi-music-clef-treble::before { + content: "\F0F70"; +} + +.mdi-music-note::before { + content: "\F0387"; +} + +.mdi-music-note-bluetooth::before { + content: "\F05FE"; +} + +.mdi-music-note-bluetooth-off::before { + content: "\F05FF"; +} + +.mdi-music-note-eighth::before { + content: "\F0388"; +} + +.mdi-music-note-eighth-dotted::before { + content: "\F0F71"; +} + +.mdi-music-note-half::before { + content: "\F0389"; +} + +.mdi-music-note-half-dotted::before { + content: "\F0F72"; +} + +.mdi-music-note-off::before { + content: "\F038A"; +} + +.mdi-music-note-off-outline::before { + content: "\F0F73"; +} + +.mdi-music-note-outline::before { + content: "\F0F74"; +} + +.mdi-music-note-plus::before { + content: "\F0DDE"; +} + +.mdi-music-note-quarter::before { + content: "\F038B"; +} + +.mdi-music-note-quarter-dotted::before { + content: "\F0F75"; +} + +.mdi-music-note-sixteenth::before { + content: "\F038C"; +} + +.mdi-music-note-sixteenth-dotted::before { + content: "\F0F76"; +} + +.mdi-music-note-whole::before { + content: "\F038D"; +} + +.mdi-music-note-whole-dotted::before { + content: "\F0F77"; +} + +.mdi-music-off::before { + content: "\F075B"; +} + +.mdi-music-rest-eighth::before { + content: "\F0F78"; +} + +.mdi-music-rest-half::before { + content: "\F0F79"; +} + +.mdi-music-rest-quarter::before { + content: "\F0F7A"; +} + +.mdi-music-rest-sixteenth::before { + content: "\F0F7B"; +} + +.mdi-music-rest-whole::before { + content: "\F0F7C"; +} + +.mdi-mustache::before { + content: "\F15DE"; +} + +.mdi-nail::before { + content: "\F0DDF"; +} + +.mdi-nas::before { + content: "\F08F3"; +} + +.mdi-nativescript::before { + content: "\F0880"; +} + +.mdi-nature::before { + content: "\F038E"; +} + +.mdi-nature-people::before { + content: "\F038F"; +} + +.mdi-navigation::before { + content: "\F0390"; +} + +.mdi-navigation-outline::before { + content: "\F1607"; +} + +.mdi-near-me::before { + content: "\F05CD"; +} + +.mdi-necklace::before { + content: "\F0F0B"; +} + +.mdi-needle::before { + content: "\F0391"; +} + +.mdi-netflix::before { + content: "\F0746"; +} + +.mdi-network::before { + content: "\F06F3"; +} + +.mdi-network-off::before { + content: "\F0C9B"; +} + +.mdi-network-off-outline::before { + content: "\F0C9C"; +} + +.mdi-network-outline::before { + content: "\F0C9D"; +} + +.mdi-network-strength-1::before { + content: "\F08F4"; +} + +.mdi-network-strength-1-alert::before { + content: "\F08F5"; +} + +.mdi-network-strength-2::before { + content: "\F08F6"; +} + +.mdi-network-strength-2-alert::before { + content: "\F08F7"; +} + +.mdi-network-strength-3::before { + content: "\F08F8"; +} + +.mdi-network-strength-3-alert::before { + content: "\F08F9"; +} + +.mdi-network-strength-4::before { + content: "\F08FA"; +} + +.mdi-network-strength-4-alert::before { + content: "\F08FB"; +} + +.mdi-network-strength-off::before { + content: "\F08FC"; +} + +.mdi-network-strength-off-outline::before { + content: "\F08FD"; +} + +.mdi-network-strength-outline::before { + content: "\F08FE"; +} + +.mdi-new-box::before { + content: "\F0394"; +} + +.mdi-newspaper::before { + content: "\F0395"; +} + +.mdi-newspaper-minus::before { + content: "\F0F0C"; +} + +.mdi-newspaper-plus::before { + content: "\F0F0D"; +} + +.mdi-newspaper-variant::before { + content: "\F1001"; +} + +.mdi-newspaper-variant-multiple::before { + content: "\F1002"; +} + +.mdi-newspaper-variant-multiple-outline::before { + content: "\F1003"; +} + +.mdi-newspaper-variant-outline::before { + content: "\F1004"; +} + +.mdi-nfc::before { + content: "\F0396"; +} + +.mdi-nfc-search-variant::before { + content: "\F0E53"; +} + +.mdi-nfc-tap::before { + content: "\F0397"; +} + +.mdi-nfc-variant::before { + content: "\F0398"; +} + +.mdi-nfc-variant-off::before { + content: "\F0E54"; +} + +.mdi-ninja::before { + content: "\F0774"; +} + +.mdi-nintendo-game-boy::before { + content: "\F1393"; +} + +.mdi-nintendo-switch::before { + content: "\F07E1"; +} + +.mdi-nintendo-wii::before { + content: "\F05AB"; +} + +.mdi-nintendo-wiiu::before { + content: "\F072D"; +} + +.mdi-nix::before { + content: "\F1105"; +} + +.mdi-nodejs::before { + content: "\F0399"; +} + +.mdi-noodles::before { + content: "\F117E"; +} + +.mdi-not-equal::before { + content: "\F098D"; +} + +.mdi-not-equal-variant::before { + content: "\F098E"; +} + +.mdi-note::before { + content: "\F039A"; +} + +.mdi-note-minus::before { + content: "\F164F"; +} + +.mdi-note-minus-outline::before { + content: "\F1650"; +} + +.mdi-note-multiple::before { + content: "\F06B8"; +} + +.mdi-note-multiple-outline::before { + content: "\F06B9"; +} + +.mdi-note-outline::before { + content: "\F039B"; +} + +.mdi-note-plus::before { + content: "\F039C"; +} + +.mdi-note-plus-outline::before { + content: "\F039D"; +} + +.mdi-note-remove::before { + content: "\F1651"; +} + +.mdi-note-remove-outline::before { + content: "\F1652"; +} + +.mdi-note-search::before { + content: "\F1653"; +} + +.mdi-note-search-outline::before { + content: "\F1654"; +} + +.mdi-note-text::before { + content: "\F039E"; +} + +.mdi-note-text-outline::before { + content: "\F11D7"; +} + +.mdi-notebook::before { + content: "\F082E"; +} + +.mdi-notebook-check::before { + content: "\F14F5"; +} + +.mdi-notebook-check-outline::before { + content: "\F14F6"; +} + +.mdi-notebook-edit::before { + content: "\F14E7"; +} + +.mdi-notebook-edit-outline::before { + content: "\F14E9"; +} + +.mdi-notebook-minus::before { + content: "\F1610"; +} + +.mdi-notebook-minus-outline::before { + content: "\F1611"; +} + +.mdi-notebook-multiple::before { + content: "\F0E55"; +} + +.mdi-notebook-outline::before { + content: "\F0EBF"; +} + +.mdi-notebook-plus::before { + content: "\F1612"; +} + +.mdi-notebook-plus-outline::before { + content: "\F1613"; +} + +.mdi-notebook-remove::before { + content: "\F1614"; +} + +.mdi-notebook-remove-outline::before { + content: "\F1615"; +} + +.mdi-notification-clear-all::before { + content: "\F039F"; +} + +.mdi-npm::before { + content: "\F06F7"; +} + +.mdi-nuke::before { + content: "\F06A4"; +} + +.mdi-null::before { + content: "\F07E2"; +} + +.mdi-numeric::before { + content: "\F03A0"; +} + +.mdi-numeric-0::before { + content: "\F0B39"; +} + +.mdi-numeric-0-box::before { + content: "\F03A1"; +} + +.mdi-numeric-0-box-multiple::before { + content: "\F0F0E"; +} + +.mdi-numeric-0-box-multiple-outline::before { + content: "\F03A2"; +} + +.mdi-numeric-0-box-outline::before { + content: "\F03A3"; +} + +.mdi-numeric-0-circle::before { + content: "\F0C9E"; +} + +.mdi-numeric-0-circle-outline::before { + content: "\F0C9F"; +} + +.mdi-numeric-1::before { + content: "\F0B3A"; +} + +.mdi-numeric-1-box::before { + content: "\F03A4"; +} + +.mdi-numeric-1-box-multiple::before { + content: "\F0F0F"; +} + +.mdi-numeric-1-box-multiple-outline::before { + content: "\F03A5"; +} + +.mdi-numeric-1-box-outline::before { + content: "\F03A6"; +} + +.mdi-numeric-1-circle::before { + content: "\F0CA0"; +} + +.mdi-numeric-1-circle-outline::before { + content: "\F0CA1"; +} + +.mdi-numeric-10::before { + content: "\F0FE9"; +} + +.mdi-numeric-10-box::before { + content: "\F0F7D"; +} + +.mdi-numeric-10-box-multiple::before { + content: "\F0FEA"; +} + +.mdi-numeric-10-box-multiple-outline::before { + content: "\F0FEB"; +} + +.mdi-numeric-10-box-outline::before { + content: "\F0F7E"; +} + +.mdi-numeric-10-circle::before { + content: "\F0FEC"; +} + +.mdi-numeric-10-circle-outline::before { + content: "\F0FED"; +} + +.mdi-numeric-2::before { + content: "\F0B3B"; +} + +.mdi-numeric-2-box::before { + content: "\F03A7"; +} + +.mdi-numeric-2-box-multiple::before { + content: "\F0F10"; +} + +.mdi-numeric-2-box-multiple-outline::before { + content: "\F03A8"; +} + +.mdi-numeric-2-box-outline::before { + content: "\F03A9"; +} + +.mdi-numeric-2-circle::before { + content: "\F0CA2"; +} + +.mdi-numeric-2-circle-outline::before { + content: "\F0CA3"; +} + +.mdi-numeric-3::before { + content: "\F0B3C"; +} + +.mdi-numeric-3-box::before { + content: "\F03AA"; +} + +.mdi-numeric-3-box-multiple::before { + content: "\F0F11"; +} + +.mdi-numeric-3-box-multiple-outline::before { + content: "\F03AB"; +} + +.mdi-numeric-3-box-outline::before { + content: "\F03AC"; +} + +.mdi-numeric-3-circle::before { + content: "\F0CA4"; +} + +.mdi-numeric-3-circle-outline::before { + content: "\F0CA5"; +} + +.mdi-numeric-4::before { + content: "\F0B3D"; +} + +.mdi-numeric-4-box::before { + content: "\F03AD"; +} + +.mdi-numeric-4-box-multiple::before { + content: "\F0F12"; +} + +.mdi-numeric-4-box-multiple-outline::before { + content: "\F03B2"; +} + +.mdi-numeric-4-box-outline::before { + content: "\F03AE"; +} + +.mdi-numeric-4-circle::before { + content: "\F0CA6"; +} + +.mdi-numeric-4-circle-outline::before { + content: "\F0CA7"; +} + +.mdi-numeric-5::before { + content: "\F0B3E"; +} + +.mdi-numeric-5-box::before { + content: "\F03B1"; +} + +.mdi-numeric-5-box-multiple::before { + content: "\F0F13"; +} + +.mdi-numeric-5-box-multiple-outline::before { + content: "\F03AF"; +} + +.mdi-numeric-5-box-outline::before { + content: "\F03B0"; +} + +.mdi-numeric-5-circle::before { + content: "\F0CA8"; +} + +.mdi-numeric-5-circle-outline::before { + content: "\F0CA9"; +} + +.mdi-numeric-6::before { + content: "\F0B3F"; +} + +.mdi-numeric-6-box::before { + content: "\F03B3"; +} + +.mdi-numeric-6-box-multiple::before { + content: "\F0F14"; +} + +.mdi-numeric-6-box-multiple-outline::before { + content: "\F03B4"; +} + +.mdi-numeric-6-box-outline::before { + content: "\F03B5"; +} + +.mdi-numeric-6-circle::before { + content: "\F0CAA"; +} + +.mdi-numeric-6-circle-outline::before { + content: "\F0CAB"; +} + +.mdi-numeric-7::before { + content: "\F0B40"; +} + +.mdi-numeric-7-box::before { + content: "\F03B6"; +} + +.mdi-numeric-7-box-multiple::before { + content: "\F0F15"; +} + +.mdi-numeric-7-box-multiple-outline::before { + content: "\F03B7"; +} + +.mdi-numeric-7-box-outline::before { + content: "\F03B8"; +} + +.mdi-numeric-7-circle::before { + content: "\F0CAC"; +} + +.mdi-numeric-7-circle-outline::before { + content: "\F0CAD"; +} + +.mdi-numeric-8::before { + content: "\F0B41"; +} + +.mdi-numeric-8-box::before { + content: "\F03B9"; +} + +.mdi-numeric-8-box-multiple::before { + content: "\F0F16"; +} + +.mdi-numeric-8-box-multiple-outline::before { + content: "\F03BA"; +} + +.mdi-numeric-8-box-outline::before { + content: "\F03BB"; +} + +.mdi-numeric-8-circle::before { + content: "\F0CAE"; +} + +.mdi-numeric-8-circle-outline::before { + content: "\F0CAF"; +} + +.mdi-numeric-9::before { + content: "\F0B42"; +} + +.mdi-numeric-9-box::before { + content: "\F03BC"; +} + +.mdi-numeric-9-box-multiple::before { + content: "\F0F17"; +} + +.mdi-numeric-9-box-multiple-outline::before { + content: "\F03BD"; +} + +.mdi-numeric-9-box-outline::before { + content: "\F03BE"; +} + +.mdi-numeric-9-circle::before { + content: "\F0CB0"; +} + +.mdi-numeric-9-circle-outline::before { + content: "\F0CB1"; +} + +.mdi-numeric-9-plus::before { + content: "\F0FEE"; +} + +.mdi-numeric-9-plus-box::before { + content: "\F03BF"; +} + +.mdi-numeric-9-plus-box-multiple::before { + content: "\F0F18"; +} + +.mdi-numeric-9-plus-box-multiple-outline::before { + content: "\F03C0"; +} + +.mdi-numeric-9-plus-box-outline::before { + content: "\F03C1"; +} + +.mdi-numeric-9-plus-circle::before { + content: "\F0CB2"; +} + +.mdi-numeric-9-plus-circle-outline::before { + content: "\F0CB3"; +} + +.mdi-numeric-negative-1::before { + content: "\F1052"; +} + +.mdi-numeric-positive-1::before { + content: "\F15CB"; +} + +.mdi-nut::before { + content: "\F06F8"; +} + +.mdi-nutrition::before { + content: "\F03C2"; +} + +.mdi-nuxt::before { + content: "\F1106"; +} + +.mdi-oar::before { + content: "\F067C"; +} + +.mdi-ocarina::before { + content: "\F0DE0"; +} + +.mdi-oci::before { + content: "\F12E9"; +} + +.mdi-ocr::before { + content: "\F113A"; +} + +.mdi-octagon::before { + content: "\F03C3"; +} + +.mdi-octagon-outline::before { + content: "\F03C4"; +} + +.mdi-octagram::before { + content: "\F06F9"; +} + +.mdi-octagram-outline::before { + content: "\F0775"; +} + +.mdi-odnoklassniki::before { + content: "\F03C5"; +} + +.mdi-offer::before { + content: "\F121B"; +} + +.mdi-office-building::before { + content: "\F0991"; +} + +.mdi-office-building-marker::before { + content: "\F1520"; +} + +.mdi-office-building-marker-outline::before { + content: "\F1521"; +} + +.mdi-office-building-outline::before { + content: "\F151F"; +} + +.mdi-oil::before { + content: "\F03C7"; +} + +.mdi-oil-lamp::before { + content: "\F0F19"; +} + +.mdi-oil-level::before { + content: "\F1053"; +} + +.mdi-oil-temperature::before { + content: "\F0FF8"; +} + +.mdi-omega::before { + content: "\F03C9"; +} + +.mdi-one-up::before { + content: "\F0BAD"; +} + +.mdi-onepassword::before { + content: "\F0881"; +} + +.mdi-opacity::before { + content: "\F05CC"; +} + +.mdi-open-in-app::before { + content: "\F03CB"; +} + +.mdi-open-in-new::before { + content: "\F03CC"; +} + +.mdi-open-source-initiative::before { + content: "\F0BAE"; +} + +.mdi-openid::before { + content: "\F03CD"; +} + +.mdi-opera::before { + content: "\F03CE"; +} + +.mdi-orbit::before { + content: "\F0018"; +} + +.mdi-orbit-variant::before { + content: "\F15DB"; +} + +.mdi-order-alphabetical-ascending::before { + content: "\F020D"; +} + +.mdi-order-alphabetical-descending::before { + content: "\F0D07"; +} + +.mdi-order-bool-ascending::before { + content: "\F02BE"; +} + +.mdi-order-bool-ascending-variant::before { + content: "\F098F"; +} + +.mdi-order-bool-descending::before { + content: "\F1384"; +} + +.mdi-order-bool-descending-variant::before { + content: "\F0990"; +} + +.mdi-order-numeric-ascending::before { + content: "\F0545"; +} + +.mdi-order-numeric-descending::before { + content: "\F0546"; +} + +.mdi-origin::before { + content: "\F0B43"; +} + +.mdi-ornament::before { + content: "\F03CF"; +} + +.mdi-ornament-variant::before { + content: "\F03D0"; +} + +.mdi-outdoor-lamp::before { + content: "\F1054"; +} + +.mdi-overscan::before { + content: "\F1005"; +} + +.mdi-owl::before { + content: "\F03D2"; +} + +.mdi-pac-man::before { + content: "\F0BAF"; +} + +.mdi-package::before { + content: "\F03D3"; +} + +.mdi-package-down::before { + content: "\F03D4"; +} + +.mdi-package-up::before { + content: "\F03D5"; +} + +.mdi-package-variant::before { + content: "\F03D6"; +} + +.mdi-package-variant-closed::before { + content: "\F03D7"; +} + +.mdi-page-first::before { + content: "\F0600"; +} + +.mdi-page-last::before { + content: "\F0601"; +} + +.mdi-page-layout-body::before { + content: "\F06FA"; +} + +.mdi-page-layout-footer::before { + content: "\F06FB"; +} + +.mdi-page-layout-header::before { + content: "\F06FC"; +} + +.mdi-page-layout-header-footer::before { + content: "\F0F7F"; +} + +.mdi-page-layout-sidebar-left::before { + content: "\F06FD"; +} + +.mdi-page-layout-sidebar-right::before { + content: "\F06FE"; +} + +.mdi-page-next::before { + content: "\F0BB0"; +} + +.mdi-page-next-outline::before { + content: "\F0BB1"; +} + +.mdi-page-previous::before { + content: "\F0BB2"; +} + +.mdi-page-previous-outline::before { + content: "\F0BB3"; +} + +.mdi-pail::before { + content: "\F1417"; +} + +.mdi-pail-minus::before { + content: "\F1437"; +} + +.mdi-pail-minus-outline::before { + content: "\F143C"; +} + +.mdi-pail-off::before { + content: "\F1439"; +} + +.mdi-pail-off-outline::before { + content: "\F143E"; +} + +.mdi-pail-outline::before { + content: "\F143A"; +} + +.mdi-pail-plus::before { + content: "\F1436"; +} + +.mdi-pail-plus-outline::before { + content: "\F143B"; +} + +.mdi-pail-remove::before { + content: "\F1438"; +} + +.mdi-pail-remove-outline::before { + content: "\F143D"; +} + +.mdi-palette::before { + content: "\F03D8"; +} + +.mdi-palette-advanced::before { + content: "\F03D9"; +} + +.mdi-palette-outline::before { + content: "\F0E0C"; +} + +.mdi-palette-swatch::before { + content: "\F08B5"; +} + +.mdi-palette-swatch-outline::before { + content: "\F135C"; +} + +.mdi-palm-tree::before { + content: "\F1055"; +} + +.mdi-pan::before { + content: "\F0BB4"; +} + +.mdi-pan-bottom-left::before { + content: "\F0BB5"; +} + +.mdi-pan-bottom-right::before { + content: "\F0BB6"; +} + +.mdi-pan-down::before { + content: "\F0BB7"; +} + +.mdi-pan-horizontal::before { + content: "\F0BB8"; +} + +.mdi-pan-left::before { + content: "\F0BB9"; +} + +.mdi-pan-right::before { + content: "\F0BBA"; +} + +.mdi-pan-top-left::before { + content: "\F0BBB"; +} + +.mdi-pan-top-right::before { + content: "\F0BBC"; +} + +.mdi-pan-up::before { + content: "\F0BBD"; +} + +.mdi-pan-vertical::before { + content: "\F0BBE"; +} + +.mdi-panda::before { + content: "\F03DA"; +} + +.mdi-pandora::before { + content: "\F03DB"; +} + +.mdi-panorama::before { + content: "\F03DC"; +} + +.mdi-panorama-fisheye::before { + content: "\F03DD"; +} + +.mdi-panorama-horizontal::before { + content: "\F03DE"; +} + +.mdi-panorama-vertical::before { + content: "\F03DF"; +} + +.mdi-panorama-wide-angle::before { + content: "\F03E0"; +} + +.mdi-paper-cut-vertical::before { + content: "\F03E1"; +} + +.mdi-paper-roll::before { + content: "\F1157"; +} + +.mdi-paper-roll-outline::before { + content: "\F1158"; +} + +.mdi-paperclip::before { + content: "\F03E2"; +} + +.mdi-parachute::before { + content: "\F0CB4"; +} + +.mdi-parachute-outline::before { + content: "\F0CB5"; +} + +.mdi-parking::before { + content: "\F03E3"; +} + +.mdi-party-popper::before { + content: "\F1056"; +} + +.mdi-passport::before { + content: "\F07E3"; +} + +.mdi-passport-biometric::before { + content: "\F0DE1"; +} + +.mdi-pasta::before { + content: "\F1160"; +} + +.mdi-patio-heater::before { + content: "\F0F80"; +} + +.mdi-patreon::before { + content: "\F0882"; +} + +.mdi-pause::before { + content: "\F03E4"; +} + +.mdi-pause-circle::before { + content: "\F03E5"; +} + +.mdi-pause-circle-outline::before { + content: "\F03E6"; +} + +.mdi-pause-octagon::before { + content: "\F03E7"; +} + +.mdi-pause-octagon-outline::before { + content: "\F03E8"; +} + +.mdi-paw::before { + content: "\F03E9"; +} + +.mdi-paw-off::before { + content: "\F0657"; +} + +.mdi-paw-off-outline::before { + content: "\F1676"; +} + +.mdi-paw-outline::before { + content: "\F1675"; +} + +.mdi-pdf-box::before { + content: "\F0E56"; +} + +.mdi-peace::before { + content: "\F0884"; +} + +.mdi-peanut::before { + content: "\F0FFC"; +} + +.mdi-peanut-off::before { + content: "\F0FFD"; +} + +.mdi-peanut-off-outline::before { + content: "\F0FFF"; +} + +.mdi-peanut-outline::before { + content: "\F0FFE"; +} + +.mdi-pen::before { + content: "\F03EA"; +} + +.mdi-pen-lock::before { + content: "\F0DE2"; +} + +.mdi-pen-minus::before { + content: "\F0DE3"; +} + +.mdi-pen-off::before { + content: "\F0DE4"; +} + +.mdi-pen-plus::before { + content: "\F0DE5"; +} + +.mdi-pen-remove::before { + content: "\F0DE6"; +} + +.mdi-pencil::before { + content: "\F03EB"; +} + +.mdi-pencil-box::before { + content: "\F03EC"; +} + +.mdi-pencil-box-multiple::before { + content: "\F1144"; +} + +.mdi-pencil-box-multiple-outline::before { + content: "\F1145"; +} + +.mdi-pencil-box-outline::before { + content: "\F03ED"; +} + +.mdi-pencil-circle::before { + content: "\F06FF"; +} + +.mdi-pencil-circle-outline::before { + content: "\F0776"; +} + +.mdi-pencil-lock::before { + content: "\F03EE"; +} + +.mdi-pencil-lock-outline::before { + content: "\F0DE7"; +} + +.mdi-pencil-minus::before { + content: "\F0DE8"; +} + +.mdi-pencil-minus-outline::before { + content: "\F0DE9"; +} + +.mdi-pencil-off::before { + content: "\F03EF"; +} + +.mdi-pencil-off-outline::before { + content: "\F0DEA"; +} + +.mdi-pencil-outline::before { + content: "\F0CB6"; +} + +.mdi-pencil-plus::before { + content: "\F0DEB"; +} + +.mdi-pencil-plus-outline::before { + content: "\F0DEC"; +} + +.mdi-pencil-remove::before { + content: "\F0DED"; +} + +.mdi-pencil-remove-outline::before { + content: "\F0DEE"; +} + +.mdi-pencil-ruler::before { + content: "\F1353"; +} + +.mdi-penguin::before { + content: "\F0EC0"; +} + +.mdi-pentagon::before { + content: "\F0701"; +} + +.mdi-pentagon-outline::before { + content: "\F0700"; +} + +.mdi-pentagram::before { + content: "\F1667"; +} + +.mdi-percent::before { + content: "\F03F0"; +} + +.mdi-percent-outline::before { + content: "\F1278"; +} + +.mdi-periodic-table::before { + content: "\F08B6"; +} + +.mdi-perspective-less::before { + content: "\F0D23"; +} + +.mdi-perspective-more::before { + content: "\F0D24"; +} + +.mdi-pharmacy::before { + content: "\F03F1"; +} + +.mdi-phone::before { + content: "\F03F2"; +} + +.mdi-phone-alert::before { + content: "\F0F1A"; +} + +.mdi-phone-alert-outline::before { + content: "\F118E"; +} + +.mdi-phone-bluetooth::before { + content: "\F03F3"; +} + +.mdi-phone-bluetooth-outline::before { + content: "\F118F"; +} + +.mdi-phone-cancel::before { + content: "\F10BC"; +} + +.mdi-phone-cancel-outline::before { + content: "\F1190"; +} + +.mdi-phone-check::before { + content: "\F11A9"; +} + +.mdi-phone-check-outline::before { + content: "\F11AA"; +} + +.mdi-phone-classic::before { + content: "\F0602"; +} + +.mdi-phone-classic-off::before { + content: "\F1279"; +} + +.mdi-phone-dial::before { + content: "\F1559"; +} + +.mdi-phone-dial-outline::before { + content: "\F155A"; +} + +.mdi-phone-forward::before { + content: "\F03F4"; +} + +.mdi-phone-forward-outline::before { + content: "\F1191"; +} + +.mdi-phone-hangup::before { + content: "\F03F5"; +} + +.mdi-phone-hangup-outline::before { + content: "\F1192"; +} + +.mdi-phone-in-talk::before { + content: "\F03F6"; +} + +.mdi-phone-in-talk-outline::before { + content: "\F1182"; +} + +.mdi-phone-incoming::before { + content: "\F03F7"; +} + +.mdi-phone-incoming-outline::before { + content: "\F1193"; +} + +.mdi-phone-lock::before { + content: "\F03F8"; +} + +.mdi-phone-lock-outline::before { + content: "\F1194"; +} + +.mdi-phone-log::before { + content: "\F03F9"; +} + +.mdi-phone-log-outline::before { + content: "\F1195"; +} + +.mdi-phone-message::before { + content: "\F1196"; +} + +.mdi-phone-message-outline::before { + content: "\F1197"; +} + +.mdi-phone-minus::before { + content: "\F0658"; +} + +.mdi-phone-minus-outline::before { + content: "\F1198"; +} + +.mdi-phone-missed::before { + content: "\F03FA"; +} + +.mdi-phone-missed-outline::before { + content: "\F11A5"; +} + +.mdi-phone-off::before { + content: "\F0DEF"; +} + +.mdi-phone-off-outline::before { + content: "\F11A6"; +} + +.mdi-phone-outgoing::before { + content: "\F03FB"; +} + +.mdi-phone-outgoing-outline::before { + content: "\F1199"; +} + +.mdi-phone-outline::before { + content: "\F0DF0"; +} + +.mdi-phone-paused::before { + content: "\F03FC"; +} + +.mdi-phone-paused-outline::before { + content: "\F119A"; +} + +.mdi-phone-plus::before { + content: "\F0659"; +} + +.mdi-phone-plus-outline::before { + content: "\F119B"; +} + +.mdi-phone-remove::before { + content: "\F152F"; +} + +.mdi-phone-remove-outline::before { + content: "\F1530"; +} + +.mdi-phone-return::before { + content: "\F082F"; +} + +.mdi-phone-return-outline::before { + content: "\F119C"; +} + +.mdi-phone-ring::before { + content: "\F11AB"; +} + +.mdi-phone-ring-outline::before { + content: "\F11AC"; +} + +.mdi-phone-rotate-landscape::before { + content: "\F0885"; +} + +.mdi-phone-rotate-portrait::before { + content: "\F0886"; +} + +.mdi-phone-settings::before { + content: "\F03FD"; +} + +.mdi-phone-settings-outline::before { + content: "\F119D"; +} + +.mdi-phone-voip::before { + content: "\F03FE"; +} + +.mdi-pi::before { + content: "\F03FF"; +} + +.mdi-pi-box::before { + content: "\F0400"; +} + +.mdi-pi-hole::before { + content: "\F0DF1"; +} + +.mdi-piano::before { + content: "\F067D"; +} + +.mdi-pickaxe::before { + content: "\F08B7"; +} + +.mdi-picture-in-picture-bottom-right::before { + content: "\F0E57"; +} + +.mdi-picture-in-picture-bottom-right-outline::before { + content: "\F0E58"; +} + +.mdi-picture-in-picture-top-right::before { + content: "\F0E59"; +} + +.mdi-picture-in-picture-top-right-outline::before { + content: "\F0E5A"; +} + +.mdi-pier::before { + content: "\F0887"; +} + +.mdi-pier-crane::before { + content: "\F0888"; +} + +.mdi-pig::before { + content: "\F0401"; +} + +.mdi-pig-variant::before { + content: "\F1006"; +} + +.mdi-pig-variant-outline::before { + content: "\F1678"; +} + +.mdi-piggy-bank::before { + content: "\F1007"; +} + +.mdi-piggy-bank-outline::before { + content: "\F1679"; +} + +.mdi-pill::before { + content: "\F0402"; +} + +.mdi-pillar::before { + content: "\F0702"; +} + +.mdi-pin::before { + content: "\F0403"; +} + +.mdi-pin-off::before { + content: "\F0404"; +} + +.mdi-pin-off-outline::before { + content: "\F0930"; +} + +.mdi-pin-outline::before { + content: "\F0931"; +} + +.mdi-pine-tree::before { + content: "\F0405"; +} + +.mdi-pine-tree-box::before { + content: "\F0406"; +} + +.mdi-pine-tree-fire::before { + content: "\F141A"; +} + +.mdi-pinterest::before { + content: "\F0407"; +} + +.mdi-pinwheel::before { + content: "\F0AD5"; +} + +.mdi-pinwheel-outline::before { + content: "\F0AD6"; +} + +.mdi-pipe::before { + content: "\F07E5"; +} + +.mdi-pipe-disconnected::before { + content: "\F07E6"; +} + +.mdi-pipe-leak::before { + content: "\F0889"; +} + +.mdi-pipe-wrench::before { + content: "\F1354"; +} + +.mdi-pirate::before { + content: "\F0A08"; +} + +.mdi-pistol::before { + content: "\F0703"; +} + +.mdi-piston::before { + content: "\F088A"; +} + +.mdi-pitchfork::before { + content: "\F1553"; +} + +.mdi-pizza::before { + content: "\F0409"; +} + +.mdi-play::before { + content: "\F040A"; +} + +.mdi-play-box::before { + content: "\F127A"; +} + +.mdi-play-box-multiple::before { + content: "\F0D19"; +} + +.mdi-play-box-multiple-outline::before { + content: "\F13E6"; +} + +.mdi-play-box-outline::before { + content: "\F040B"; +} + +.mdi-play-circle::before { + content: "\F040C"; +} + +.mdi-play-circle-outline::before { + content: "\F040D"; +} + +.mdi-play-network::before { + content: "\F088B"; +} + +.mdi-play-network-outline::before { + content: "\F0CB7"; +} + +.mdi-play-outline::before { + content: "\F0F1B"; +} + +.mdi-play-pause::before { + content: "\F040E"; +} + +.mdi-play-protected-content::before { + content: "\F040F"; +} + +.mdi-play-speed::before { + content: "\F08FF"; +} + +.mdi-playlist-check::before { + content: "\F05C7"; +} + +.mdi-playlist-edit::before { + content: "\F0900"; +} + +.mdi-playlist-minus::before { + content: "\F0410"; +} + +.mdi-playlist-music::before { + content: "\F0CB8"; +} + +.mdi-playlist-music-outline::before { + content: "\F0CB9"; +} + +.mdi-playlist-play::before { + content: "\F0411"; +} + +.mdi-playlist-plus::before { + content: "\F0412"; +} + +.mdi-playlist-remove::before { + content: "\F0413"; +} + +.mdi-playlist-star::before { + content: "\F0DF2"; +} + +.mdi-plex::before { + content: "\F06BA"; +} + +.mdi-plus::before { + content: "\F0415"; +} + +.mdi-plus-box::before { + content: "\F0416"; +} + +.mdi-plus-box-multiple::before { + content: "\F0334"; +} + +.mdi-plus-box-multiple-outline::before { + content: "\F1143"; +} + +.mdi-plus-box-outline::before { + content: "\F0704"; +} + +.mdi-plus-circle::before { + content: "\F0417"; +} + +.mdi-plus-circle-multiple::before { + content: "\F034C"; +} + +.mdi-plus-circle-multiple-outline::before { + content: "\F0418"; +} + +.mdi-plus-circle-outline::before { + content: "\F0419"; +} + +.mdi-plus-minus::before { + content: "\F0992"; +} + +.mdi-plus-minus-box::before { + content: "\F0993"; +} + +.mdi-plus-minus-variant::before { + content: "\F14C9"; +} + +.mdi-plus-network::before { + content: "\F041A"; +} + +.mdi-plus-network-outline::before { + content: "\F0CBA"; +} + +.mdi-plus-one::before { + content: "\F041B"; +} + +.mdi-plus-outline::before { + content: "\F0705"; +} + +.mdi-plus-thick::before { + content: "\F11EC"; +} + +.mdi-podcast::before { + content: "\F0994"; +} + +.mdi-podium::before { + content: "\F0D25"; +} + +.mdi-podium-bronze::before { + content: "\F0D26"; +} + +.mdi-podium-gold::before { + content: "\F0D27"; +} + +.mdi-podium-silver::before { + content: "\F0D28"; +} + +.mdi-point-of-sale::before { + content: "\F0D92"; +} + +.mdi-pokeball::before { + content: "\F041D"; +} + +.mdi-pokemon-go::before { + content: "\F0A09"; +} + +.mdi-poker-chip::before { + content: "\F0830"; +} + +.mdi-polaroid::before { + content: "\F041E"; +} + +.mdi-police-badge::before { + content: "\F1167"; +} + +.mdi-police-badge-outline::before { + content: "\F1168"; +} + +.mdi-poll::before { + content: "\F041F"; +} + +.mdi-poll-box::before { + content: "\F0420"; +} + +.mdi-poll-box-outline::before { + content: "\F127B"; +} + +.mdi-polo::before { + content: "\F14C3"; +} + +.mdi-polymer::before { + content: "\F0421"; +} + +.mdi-pool::before { + content: "\F0606"; +} + +.mdi-popcorn::before { + content: "\F0422"; +} + +.mdi-post::before { + content: "\F1008"; +} + +.mdi-post-outline::before { + content: "\F1009"; +} + +.mdi-postage-stamp::before { + content: "\F0CBB"; +} + +.mdi-pot::before { + content: "\F02E5"; +} + +.mdi-pot-mix::before { + content: "\F065B"; +} + +.mdi-pot-mix-outline::before { + content: "\F0677"; +} + +.mdi-pot-outline::before { + content: "\F02FF"; +} + +.mdi-pot-steam::before { + content: "\F065A"; +} + +.mdi-pot-steam-outline::before { + content: "\F0326"; +} + +.mdi-pound::before { + content: "\F0423"; +} + +.mdi-pound-box::before { + content: "\F0424"; +} + +.mdi-pound-box-outline::before { + content: "\F117F"; +} + +.mdi-power::before { + content: "\F0425"; +} + +.mdi-power-cycle::before { + content: "\F0901"; +} + +.mdi-power-off::before { + content: "\F0902"; +} + +.mdi-power-on::before { + content: "\F0903"; +} + +.mdi-power-plug::before { + content: "\F06A5"; +} + +.mdi-power-plug-off::before { + content: "\F06A6"; +} + +.mdi-power-plug-off-outline::before { + content: "\F1424"; +} + +.mdi-power-plug-outline::before { + content: "\F1425"; +} + +.mdi-power-settings::before { + content: "\F0426"; +} + +.mdi-power-sleep::before { + content: "\F0904"; +} + +.mdi-power-socket::before { + content: "\F0427"; +} + +.mdi-power-socket-au::before { + content: "\F0905"; +} + +.mdi-power-socket-de::before { + content: "\F1107"; +} + +.mdi-power-socket-eu::before { + content: "\F07E7"; +} + +.mdi-power-socket-fr::before { + content: "\F1108"; +} + +.mdi-power-socket-it::before { + content: "\F14FF"; +} + +.mdi-power-socket-jp::before { + content: "\F1109"; +} + +.mdi-power-socket-uk::before { + content: "\F07E8"; +} + +.mdi-power-socket-us::before { + content: "\F07E9"; +} + +.mdi-power-standby::before { + content: "\F0906"; +} + +.mdi-powershell::before { + content: "\F0A0A"; +} + +.mdi-prescription::before { + content: "\F0706"; +} + +.mdi-presentation::before { + content: "\F0428"; +} + +.mdi-presentation-play::before { + content: "\F0429"; +} + +.mdi-pretzel::before { + content: "\F1562"; +} + +.mdi-printer::before { + content: "\F042A"; +} + +.mdi-printer-3d::before { + content: "\F042B"; +} + +.mdi-printer-3d-nozzle::before { + content: "\F0E5B"; +} + +.mdi-printer-3d-nozzle-alert::before { + content: "\F11C0"; +} + +.mdi-printer-3d-nozzle-alert-outline::before { + content: "\F11C1"; +} + +.mdi-printer-3d-nozzle-outline::before { + content: "\F0E5C"; +} + +.mdi-printer-alert::before { + content: "\F042C"; +} + +.mdi-printer-check::before { + content: "\F1146"; +} + +.mdi-printer-eye::before { + content: "\F1458"; +} + +.mdi-printer-off::before { + content: "\F0E5D"; +} + +.mdi-printer-pos::before { + content: "\F1057"; +} + +.mdi-printer-search::before { + content: "\F1457"; +} + +.mdi-printer-settings::before { + content: "\F0707"; +} + +.mdi-printer-wireless::before { + content: "\F0A0B"; +} + +.mdi-priority-high::before { + content: "\F0603"; +} + +.mdi-priority-low::before { + content: "\F0604"; +} + +.mdi-professional-hexagon::before { + content: "\F042D"; +} + +.mdi-progress-alert::before { + content: "\F0CBC"; +} + +.mdi-progress-check::before { + content: "\F0995"; +} + +.mdi-progress-clock::before { + content: "\F0996"; +} + +.mdi-progress-close::before { + content: "\F110A"; +} + +.mdi-progress-download::before { + content: "\F0997"; +} + +.mdi-progress-question::before { + content: "\F1522"; +} + +.mdi-progress-upload::before { + content: "\F0998"; +} + +.mdi-progress-wrench::before { + content: "\F0CBD"; +} + +.mdi-projector::before { + content: "\F042E"; +} + +.mdi-projector-screen::before { + content: "\F042F"; +} + +.mdi-propane-tank::before { + content: "\F1357"; +} + +.mdi-propane-tank-outline::before { + content: "\F1358"; +} + +.mdi-protocol::before { + content: "\F0FD8"; +} + +.mdi-publish::before { + content: "\F06A7"; +} + +.mdi-pulse::before { + content: "\F0430"; +} + +.mdi-pump::before { + content: "\F1402"; +} + +.mdi-pumpkin::before { + content: "\F0BBF"; +} + +.mdi-purse::before { + content: "\F0F1C"; +} + +.mdi-purse-outline::before { + content: "\F0F1D"; +} + +.mdi-puzzle::before { + content: "\F0431"; +} + +.mdi-puzzle-check::before { + content: "\F1426"; +} + +.mdi-puzzle-check-outline::before { + content: "\F1427"; +} + +.mdi-puzzle-edit::before { + content: "\F14D3"; +} + +.mdi-puzzle-edit-outline::before { + content: "\F14D9"; +} + +.mdi-puzzle-heart::before { + content: "\F14D4"; +} + +.mdi-puzzle-heart-outline::before { + content: "\F14DA"; +} + +.mdi-puzzle-minus::before { + content: "\F14D1"; +} + +.mdi-puzzle-minus-outline::before { + content: "\F14D7"; +} + +.mdi-puzzle-outline::before { + content: "\F0A66"; +} + +.mdi-puzzle-plus::before { + content: "\F14D0"; +} + +.mdi-puzzle-plus-outline::before { + content: "\F14D6"; +} + +.mdi-puzzle-remove::before { + content: "\F14D2"; +} + +.mdi-puzzle-remove-outline::before { + content: "\F14D8"; +} + +.mdi-puzzle-star::before { + content: "\F14D5"; +} + +.mdi-puzzle-star-outline::before { + content: "\F14DB"; +} + +.mdi-qi::before { + content: "\F0999"; +} + +.mdi-qqchat::before { + content: "\F0605"; +} + +.mdi-qrcode::before { + content: "\F0432"; +} + +.mdi-qrcode-edit::before { + content: "\F08B8"; +} + +.mdi-qrcode-minus::before { + content: "\F118C"; +} + +.mdi-qrcode-plus::before { + content: "\F118B"; +} + +.mdi-qrcode-remove::before { + content: "\F118D"; +} + +.mdi-qrcode-scan::before { + content: "\F0433"; +} + +.mdi-quadcopter::before { + content: "\F0434"; +} + +.mdi-quality-high::before { + content: "\F0435"; +} + +.mdi-quality-low::before { + content: "\F0A0C"; +} + +.mdi-quality-medium::before { + content: "\F0A0D"; +} + +.mdi-quora::before { + content: "\F0D29"; +} + +.mdi-rabbit::before { + content: "\F0907"; +} + +.mdi-racing-helmet::before { + content: "\F0D93"; +} + +.mdi-racquetball::before { + content: "\F0D94"; +} + +.mdi-radar::before { + content: "\F0437"; +} + +.mdi-radiator::before { + content: "\F0438"; +} + +.mdi-radiator-disabled::before { + content: "\F0AD7"; +} + +.mdi-radiator-off::before { + content: "\F0AD8"; +} + +.mdi-radio::before { + content: "\F0439"; +} + +.mdi-radio-am::before { + content: "\F0CBE"; +} + +.mdi-radio-fm::before { + content: "\F0CBF"; +} + +.mdi-radio-handheld::before { + content: "\F043A"; +} + +.mdi-radio-off::before { + content: "\F121C"; +} + +.mdi-radio-tower::before { + content: "\F043B"; +} + +.mdi-radioactive::before { + content: "\F043C"; +} + +.mdi-radioactive-off::before { + content: "\F0EC1"; +} + +.mdi-radiobox-blank::before { + content: "\F043D"; +} + +.mdi-radiobox-marked::before { + content: "\F043E"; +} + +.mdi-radiology-box::before { + content: "\F14C5"; +} + +.mdi-radiology-box-outline::before { + content: "\F14C6"; +} + +.mdi-radius::before { + content: "\F0CC0"; +} + +.mdi-radius-outline::before { + content: "\F0CC1"; +} + +.mdi-railroad-light::before { + content: "\F0F1E"; +} + +.mdi-rake::before { + content: "\F1544"; +} + +.mdi-raspberry-pi::before { + content: "\F043F"; +} + +.mdi-ray-end::before { + content: "\F0440"; +} + +.mdi-ray-end-arrow::before { + content: "\F0441"; +} + +.mdi-ray-start::before { + content: "\F0442"; +} + +.mdi-ray-start-arrow::before { + content: "\F0443"; +} + +.mdi-ray-start-end::before { + content: "\F0444"; +} + +.mdi-ray-start-vertex-end::before { + content: "\F15D8"; +} + +.mdi-ray-vertex::before { + content: "\F0445"; +} + +.mdi-react::before { + content: "\F0708"; +} + +.mdi-read::before { + content: "\F0447"; +} + +.mdi-receipt::before { + content: "\F0449"; +} + +.mdi-record::before { + content: "\F044A"; +} + +.mdi-record-circle::before { + content: "\F0EC2"; +} + +.mdi-record-circle-outline::before { + content: "\F0EC3"; +} + +.mdi-record-player::before { + content: "\F099A"; +} + +.mdi-record-rec::before { + content: "\F044B"; +} + +.mdi-rectangle::before { + content: "\F0E5E"; +} + +.mdi-rectangle-outline::before { + content: "\F0E5F"; +} + +.mdi-recycle::before { + content: "\F044C"; +} + +.mdi-recycle-variant::before { + content: "\F139D"; +} + +.mdi-reddit::before { + content: "\F044D"; +} + +.mdi-redhat::before { + content: "\F111B"; +} + +.mdi-redo::before { + content: "\F044E"; +} + +.mdi-redo-variant::before { + content: "\F044F"; +} + +.mdi-reflect-horizontal::before { + content: "\F0A0E"; +} + +.mdi-reflect-vertical::before { + content: "\F0A0F"; +} + +.mdi-refresh::before { + content: "\F0450"; +} + +.mdi-refresh-circle::before { + content: "\F1377"; +} + +.mdi-regex::before { + content: "\F0451"; +} + +.mdi-registered-trademark::before { + content: "\F0A67"; +} + +.mdi-reiterate::before { + content: "\F1588"; +} + +.mdi-relation-many-to-many::before { + content: "\F1496"; +} + +.mdi-relation-many-to-one::before { + content: "\F1497"; +} + +.mdi-relation-many-to-one-or-many::before { + content: "\F1498"; +} + +.mdi-relation-many-to-only-one::before { + content: "\F1499"; +} + +.mdi-relation-many-to-zero-or-many::before { + content: "\F149A"; +} + +.mdi-relation-many-to-zero-or-one::before { + content: "\F149B"; +} + +.mdi-relation-one-or-many-to-many::before { + content: "\F149C"; +} + +.mdi-relation-one-or-many-to-one::before { + content: "\F149D"; +} + +.mdi-relation-one-or-many-to-one-or-many::before { + content: "\F149E"; +} + +.mdi-relation-one-or-many-to-only-one::before { + content: "\F149F"; +} + +.mdi-relation-one-or-many-to-zero-or-many::before { + content: "\F14A0"; +} + +.mdi-relation-one-or-many-to-zero-or-one::before { + content: "\F14A1"; +} + +.mdi-relation-one-to-many::before { + content: "\F14A2"; +} + +.mdi-relation-one-to-one::before { + content: "\F14A3"; +} + +.mdi-relation-one-to-one-or-many::before { + content: "\F14A4"; +} + +.mdi-relation-one-to-only-one::before { + content: "\F14A5"; +} + +.mdi-relation-one-to-zero-or-many::before { + content: "\F14A6"; +} + +.mdi-relation-one-to-zero-or-one::before { + content: "\F14A7"; +} + +.mdi-relation-only-one-to-many::before { + content: "\F14A8"; +} + +.mdi-relation-only-one-to-one::before { + content: "\F14A9"; +} + +.mdi-relation-only-one-to-one-or-many::before { + content: "\F14AA"; +} + +.mdi-relation-only-one-to-only-one::before { + content: "\F14AB"; +} + +.mdi-relation-only-one-to-zero-or-many::before { + content: "\F14AC"; +} + +.mdi-relation-only-one-to-zero-or-one::before { + content: "\F14AD"; +} + +.mdi-relation-zero-or-many-to-many::before { + content: "\F14AE"; +} + +.mdi-relation-zero-or-many-to-one::before { + content: "\F14AF"; +} + +.mdi-relation-zero-or-many-to-one-or-many::before { + content: "\F14B0"; +} + +.mdi-relation-zero-or-many-to-only-one::before { + content: "\F14B1"; +} + +.mdi-relation-zero-or-many-to-zero-or-many::before { + content: "\F14B2"; +} + +.mdi-relation-zero-or-many-to-zero-or-one::before { + content: "\F14B3"; +} + +.mdi-relation-zero-or-one-to-many::before { + content: "\F14B4"; +} + +.mdi-relation-zero-or-one-to-one::before { + content: "\F14B5"; +} + +.mdi-relation-zero-or-one-to-one-or-many::before { + content: "\F14B6"; +} + +.mdi-relation-zero-or-one-to-only-one::before { + content: "\F14B7"; +} + +.mdi-relation-zero-or-one-to-zero-or-many::before { + content: "\F14B8"; +} + +.mdi-relation-zero-or-one-to-zero-or-one::before { + content: "\F14B9"; +} + +.mdi-relative-scale::before { + content: "\F0452"; +} + +.mdi-reload::before { + content: "\F0453"; +} + +.mdi-reload-alert::before { + content: "\F110B"; +} + +.mdi-reminder::before { + content: "\F088C"; +} + +.mdi-remote::before { + content: "\F0454"; +} + +.mdi-remote-desktop::before { + content: "\F08B9"; +} + +.mdi-remote-off::before { + content: "\F0EC4"; +} + +.mdi-remote-tv::before { + content: "\F0EC5"; +} + +.mdi-remote-tv-off::before { + content: "\F0EC6"; +} + +.mdi-rename-box::before { + content: "\F0455"; +} + +.mdi-reorder-horizontal::before { + content: "\F0688"; +} + +.mdi-reorder-vertical::before { + content: "\F0689"; +} + +.mdi-repeat::before { + content: "\F0456"; +} + +.mdi-repeat-off::before { + content: "\F0457"; +} + +.mdi-repeat-once::before { + content: "\F0458"; +} + +.mdi-replay::before { + content: "\F0459"; +} + +.mdi-reply::before { + content: "\F045A"; +} + +.mdi-reply-all::before { + content: "\F045B"; +} + +.mdi-reply-all-outline::before { + content: "\F0F1F"; +} + +.mdi-reply-circle::before { + content: "\F11AE"; +} + +.mdi-reply-outline::before { + content: "\F0F20"; +} + +.mdi-reproduction::before { + content: "\F045C"; +} + +.mdi-resistor::before { + content: "\F0B44"; +} + +.mdi-resistor-nodes::before { + content: "\F0B45"; +} + +.mdi-resize::before { + content: "\F0A68"; +} + +.mdi-resize-bottom-right::before { + content: "\F045D"; +} + +.mdi-responsive::before { + content: "\F045E"; +} + +.mdi-restart::before { + content: "\F0709"; +} + +.mdi-restart-alert::before { + content: "\F110C"; +} + +.mdi-restart-off::before { + content: "\F0D95"; +} + +.mdi-restore::before { + content: "\F099B"; +} + +.mdi-restore-alert::before { + content: "\F110D"; +} + +.mdi-rewind::before { + content: "\F045F"; +} + +.mdi-rewind-10::before { + content: "\F0D2A"; +} + +.mdi-rewind-30::before { + content: "\F0D96"; +} + +.mdi-rewind-5::before { + content: "\F11F9"; +} + +.mdi-rewind-60::before { + content: "\F160C"; +} + +.mdi-rewind-outline::before { + content: "\F070A"; +} + +.mdi-rhombus::before { + content: "\F070B"; +} + +.mdi-rhombus-medium::before { + content: "\F0A10"; +} + +.mdi-rhombus-medium-outline::before { + content: "\F14DC"; +} + +.mdi-rhombus-outline::before { + content: "\F070C"; +} + +.mdi-rhombus-split::before { + content: "\F0A11"; +} + +.mdi-rhombus-split-outline::before { + content: "\F14DD"; +} + +.mdi-ribbon::before { + content: "\F0460"; +} + +.mdi-rice::before { + content: "\F07EA"; +} + +.mdi-rickshaw::before { + content: "\F15BB"; +} + +.mdi-rickshaw-electric::before { + content: "\F15BC"; +} + +.mdi-ring::before { + content: "\F07EB"; +} + +.mdi-rivet::before { + content: "\F0E60"; +} + +.mdi-road::before { + content: "\F0461"; +} + +.mdi-road-variant::before { + content: "\F0462"; +} + +.mdi-robber::before { + content: "\F1058"; +} + +.mdi-robot::before { + content: "\F06A9"; +} + +.mdi-robot-angry::before { + content: "\F169D"; +} + +.mdi-robot-angry-outline::before { + content: "\F169E"; +} + +.mdi-robot-confused::before { + content: "\F169F"; +} + +.mdi-robot-confused-outline::before { + content: "\F16A0"; +} + +.mdi-robot-dead::before { + content: "\F16A1"; +} + +.mdi-robot-dead-outline::before { + content: "\F16A2"; +} + +.mdi-robot-excited::before { + content: "\F16A3"; +} + +.mdi-robot-excited-outline::before { + content: "\F16A4"; +} + +.mdi-robot-industrial::before { + content: "\F0B46"; +} + +.mdi-robot-love::before { + content: "\F16A5"; +} + +.mdi-robot-love-outline::before { + content: "\F16A6"; +} + +.mdi-robot-mower::before { + content: "\F11F7"; +} + +.mdi-robot-mower-outline::before { + content: "\F11F3"; +} + +.mdi-robot-off::before { + content: "\F16A7"; +} + +.mdi-robot-off-outline::before { + content: "\F167B"; +} + +.mdi-robot-outline::before { + content: "\F167A"; +} + +.mdi-robot-vacuum::before { + content: "\F070D"; +} + +.mdi-robot-vacuum-variant::before { + content: "\F0908"; +} + +.mdi-rocket::before { + content: "\F0463"; +} + +.mdi-rocket-launch::before { + content: "\F14DE"; +} + +.mdi-rocket-launch-outline::before { + content: "\F14DF"; +} + +.mdi-rocket-outline::before { + content: "\F13AF"; +} + +.mdi-rodent::before { + content: "\F1327"; +} + +.mdi-roller-skate::before { + content: "\F0D2B"; +} + +.mdi-roller-skate-off::before { + content: "\F0145"; +} + +.mdi-rollerblade::before { + content: "\F0D2C"; +} + +.mdi-rollerblade-off::before { + content: "\F002E"; +} + +.mdi-rollupjs::before { + content: "\F0BC0"; +} + +.mdi-roman-numeral-1::before { + content: "\F1088"; +} + +.mdi-roman-numeral-10::before { + content: "\F1091"; +} + +.mdi-roman-numeral-2::before { + content: "\F1089"; +} + +.mdi-roman-numeral-3::before { + content: "\F108A"; +} + +.mdi-roman-numeral-4::before { + content: "\F108B"; +} + +.mdi-roman-numeral-5::before { + content: "\F108C"; +} + +.mdi-roman-numeral-6::before { + content: "\F108D"; +} + +.mdi-roman-numeral-7::before { + content: "\F108E"; +} + +.mdi-roman-numeral-8::before { + content: "\F108F"; +} + +.mdi-roman-numeral-9::before { + content: "\F1090"; +} + +.mdi-room-service::before { + content: "\F088D"; +} + +.mdi-room-service-outline::before { + content: "\F0D97"; +} + +.mdi-rotate-3d::before { + content: "\F0EC7"; +} + +.mdi-rotate-3d-variant::before { + content: "\F0464"; +} + +.mdi-rotate-left::before { + content: "\F0465"; +} + +.mdi-rotate-left-variant::before { + content: "\F0466"; +} + +.mdi-rotate-orbit::before { + content: "\F0D98"; +} + +.mdi-rotate-right::before { + content: "\F0467"; +} + +.mdi-rotate-right-variant::before { + content: "\F0468"; +} + +.mdi-rounded-corner::before { + content: "\F0607"; +} + +.mdi-router::before { + content: "\F11E2"; +} + +.mdi-router-network::before { + content: "\F1087"; +} + +.mdi-router-wireless::before { + content: "\F0469"; +} + +.mdi-router-wireless-off::before { + content: "\F15A3"; +} + +.mdi-router-wireless-settings::before { + content: "\F0A69"; +} + +.mdi-routes::before { + content: "\F046A"; +} + +.mdi-routes-clock::before { + content: "\F1059"; +} + +.mdi-rowing::before { + content: "\F0608"; +} + +.mdi-rss::before { + content: "\F046B"; +} + +.mdi-rss-box::before { + content: "\F046C"; +} + +.mdi-rss-off::before { + content: "\F0F21"; +} + +.mdi-rug::before { + content: "\F1475"; +} + +.mdi-rugby::before { + content: "\F0D99"; +} + +.mdi-ruler::before { + content: "\F046D"; +} + +.mdi-ruler-square::before { + content: "\F0CC2"; +} + +.mdi-ruler-square-compass::before { + content: "\F0EBE"; +} + +.mdi-run::before { + content: "\F070E"; +} + +.mdi-run-fast::before { + content: "\F046E"; +} + +.mdi-rv-truck::before { + content: "\F11D4"; +} + +.mdi-sack::before { + content: "\F0D2E"; +} + +.mdi-sack-percent::before { + content: "\F0D2F"; +} + +.mdi-safe::before { + content: "\F0A6A"; +} + +.mdi-safe-square::before { + content: "\F127C"; +} + +.mdi-safe-square-outline::before { + content: "\F127D"; +} + +.mdi-safety-goggles::before { + content: "\F0D30"; +} + +.mdi-sail-boat::before { + content: "\F0EC8"; +} + +.mdi-sale::before { + content: "\F046F"; +} + +.mdi-salesforce::before { + content: "\F088E"; +} + +.mdi-sass::before { + content: "\F07EC"; +} + +.mdi-satellite::before { + content: "\F0470"; +} + +.mdi-satellite-uplink::before { + content: "\F0909"; +} + +.mdi-satellite-variant::before { + content: "\F0471"; +} + +.mdi-sausage::before { + content: "\F08BA"; +} + +.mdi-saw-blade::before { + content: "\F0E61"; +} + +.mdi-sawtooth-wave::before { + content: "\F147A"; +} + +.mdi-saxophone::before { + content: "\F0609"; +} + +.mdi-scale::before { + content: "\F0472"; +} + +.mdi-scale-balance::before { + content: "\F05D1"; +} + +.mdi-scale-bathroom::before { + content: "\F0473"; +} + +.mdi-scale-off::before { + content: "\F105A"; +} + +.mdi-scan-helper::before { + content: "\F13D8"; +} + +.mdi-scanner::before { + content: "\F06AB"; +} + +.mdi-scanner-off::before { + content: "\F090A"; +} + +.mdi-scatter-plot::before { + content: "\F0EC9"; +} + +.mdi-scatter-plot-outline::before { + content: "\F0ECA"; +} + +.mdi-school::before { + content: "\F0474"; +} + +.mdi-school-outline::before { + content: "\F1180"; +} + +.mdi-scissors-cutting::before { + content: "\F0A6B"; +} + +.mdi-scooter::before { + content: "\F15BD"; +} + +.mdi-scooter-electric::before { + content: "\F15BE"; +} + +.mdi-scoreboard::before { + content: "\F127E"; +} + +.mdi-scoreboard-outline::before { + content: "\F127F"; +} + +.mdi-screen-rotation::before { + content: "\F0475"; +} + +.mdi-screen-rotation-lock::before { + content: "\F0478"; +} + +.mdi-screw-flat-top::before { + content: "\F0DF3"; +} + +.mdi-screw-lag::before { + content: "\F0DF4"; +} + +.mdi-screw-machine-flat-top::before { + content: "\F0DF5"; +} + +.mdi-screw-machine-round-top::before { + content: "\F0DF6"; +} + +.mdi-screw-round-top::before { + content: "\F0DF7"; +} + +.mdi-screwdriver::before { + content: "\F0476"; +} + +.mdi-script::before { + content: "\F0BC1"; +} + +.mdi-script-outline::before { + content: "\F0477"; +} + +.mdi-script-text::before { + content: "\F0BC2"; +} + +.mdi-script-text-outline::before { + content: "\F0BC3"; +} + +.mdi-sd::before { + content: "\F0479"; +} + +.mdi-seal::before { + content: "\F047A"; +} + +.mdi-seal-variant::before { + content: "\F0FD9"; +} + +.mdi-search-web::before { + content: "\F070F"; +} + +.mdi-seat::before { + content: "\F0CC3"; +} + +.mdi-seat-flat::before { + content: "\F047B"; +} + +.mdi-seat-flat-angled::before { + content: "\F047C"; +} + +.mdi-seat-individual-suite::before { + content: "\F047D"; +} + +.mdi-seat-legroom-extra::before { + content: "\F047E"; +} + +.mdi-seat-legroom-normal::before { + content: "\F047F"; +} + +.mdi-seat-legroom-reduced::before { + content: "\F0480"; +} + +.mdi-seat-outline::before { + content: "\F0CC4"; +} + +.mdi-seat-passenger::before { + content: "\F1249"; +} + +.mdi-seat-recline-extra::before { + content: "\F0481"; +} + +.mdi-seat-recline-normal::before { + content: "\F0482"; +} + +.mdi-seatbelt::before { + content: "\F0CC5"; +} + +.mdi-security::before { + content: "\F0483"; +} + +.mdi-security-network::before { + content: "\F0484"; +} + +.mdi-seed::before { + content: "\F0E62"; +} + +.mdi-seed-off::before { + content: "\F13FD"; +} + +.mdi-seed-off-outline::before { + content: "\F13FE"; +} + +.mdi-seed-outline::before { + content: "\F0E63"; +} + +.mdi-seesaw::before { + content: "\F15A4"; +} + +.mdi-segment::before { + content: "\F0ECB"; +} + +.mdi-select::before { + content: "\F0485"; +} + +.mdi-select-all::before { + content: "\F0486"; +} + +.mdi-select-color::before { + content: "\F0D31"; +} + +.mdi-select-compare::before { + content: "\F0AD9"; +} + +.mdi-select-drag::before { + content: "\F0A6C"; +} + +.mdi-select-group::before { + content: "\F0F82"; +} + +.mdi-select-inverse::before { + content: "\F0487"; +} + +.mdi-select-marker::before { + content: "\F1280"; +} + +.mdi-select-multiple::before { + content: "\F1281"; +} + +.mdi-select-multiple-marker::before { + content: "\F1282"; +} + +.mdi-select-off::before { + content: "\F0488"; +} + +.mdi-select-place::before { + content: "\F0FDA"; +} + +.mdi-select-search::before { + content: "\F1204"; +} + +.mdi-selection::before { + content: "\F0489"; +} + +.mdi-selection-drag::before { + content: "\F0A6D"; +} + +.mdi-selection-ellipse::before { + content: "\F0D32"; +} + +.mdi-selection-ellipse-arrow-inside::before { + content: "\F0F22"; +} + +.mdi-selection-marker::before { + content: "\F1283"; +} + +.mdi-selection-multiple::before { + content: "\F1285"; +} + +.mdi-selection-multiple-marker::before { + content: "\F1284"; +} + +.mdi-selection-off::before { + content: "\F0777"; +} + +.mdi-selection-search::before { + content: "\F1205"; +} + +.mdi-semantic-web::before { + content: "\F1316"; +} + +.mdi-send::before { + content: "\F048A"; +} + +.mdi-send-check::before { + content: "\F1161"; +} + +.mdi-send-check-outline::before { + content: "\F1162"; +} + +.mdi-send-circle::before { + content: "\F0DF8"; +} + +.mdi-send-circle-outline::before { + content: "\F0DF9"; +} + +.mdi-send-clock::before { + content: "\F1163"; +} + +.mdi-send-clock-outline::before { + content: "\F1164"; +} + +.mdi-send-lock::before { + content: "\F07ED"; +} + +.mdi-send-lock-outline::before { + content: "\F1166"; +} + +.mdi-send-outline::before { + content: "\F1165"; +} + +.mdi-serial-port::before { + content: "\F065C"; +} + +.mdi-server::before { + content: "\F048B"; +} + +.mdi-server-minus::before { + content: "\F048C"; +} + +.mdi-server-network::before { + content: "\F048D"; +} + +.mdi-server-network-off::before { + content: "\F048E"; +} + +.mdi-server-off::before { + content: "\F048F"; +} + +.mdi-server-plus::before { + content: "\F0490"; +} + +.mdi-server-remove::before { + content: "\F0491"; +} + +.mdi-server-security::before { + content: "\F0492"; +} + +.mdi-set-all::before { + content: "\F0778"; +} + +.mdi-set-center::before { + content: "\F0779"; +} + +.mdi-set-center-right::before { + content: "\F077A"; +} + +.mdi-set-left::before { + content: "\F077B"; +} + +.mdi-set-left-center::before { + content: "\F077C"; +} + +.mdi-set-left-right::before { + content: "\F077D"; +} + +.mdi-set-merge::before { + content: "\F14E0"; +} + +.mdi-set-none::before { + content: "\F077E"; +} + +.mdi-set-right::before { + content: "\F077F"; +} + +.mdi-set-split::before { + content: "\F14E1"; +} + +.mdi-set-square::before { + content: "\F145D"; +} + +.mdi-set-top-box::before { + content: "\F099F"; +} + +.mdi-settings-helper::before { + content: "\F0A6E"; +} + +.mdi-shaker::before { + content: "\F110E"; +} + +.mdi-shaker-outline::before { + content: "\F110F"; +} + +.mdi-shape::before { + content: "\F0831"; +} + +.mdi-shape-circle-plus::before { + content: "\F065D"; +} + +.mdi-shape-outline::before { + content: "\F0832"; +} + +.mdi-shape-oval-plus::before { + content: "\F11FA"; +} + +.mdi-shape-plus::before { + content: "\F0495"; +} + +.mdi-shape-polygon-plus::before { + content: "\F065E"; +} + +.mdi-shape-rectangle-plus::before { + content: "\F065F"; +} + +.mdi-shape-square-plus::before { + content: "\F0660"; +} + +.mdi-shape-square-rounded-plus::before { + content: "\F14FA"; +} + +.mdi-share::before { + content: "\F0496"; +} + +.mdi-share-all::before { + content: "\F11F4"; +} + +.mdi-share-all-outline::before { + content: "\F11F5"; +} + +.mdi-share-circle::before { + content: "\F11AD"; +} + +.mdi-share-off::before { + content: "\F0F23"; +} + +.mdi-share-off-outline::before { + content: "\F0F24"; +} + +.mdi-share-outline::before { + content: "\F0932"; +} + +.mdi-share-variant::before { + content: "\F0497"; +} + +.mdi-share-variant-outline::before { + content: "\F1514"; +} + +.mdi-shark-fin::before { + content: "\F1673"; +} + +.mdi-shark-fin-outline::before { + content: "\F1674"; +} + +.mdi-sheep::before { + content: "\F0CC6"; +} + +.mdi-shield::before { + content: "\F0498"; +} + +.mdi-shield-account::before { + content: "\F088F"; +} + +.mdi-shield-account-outline::before { + content: "\F0A12"; +} + +.mdi-shield-account-variant::before { + content: "\F15A7"; +} + +.mdi-shield-account-variant-outline::before { + content: "\F15A8"; +} + +.mdi-shield-airplane::before { + content: "\F06BB"; +} + +.mdi-shield-airplane-outline::before { + content: "\F0CC7"; +} + +.mdi-shield-alert::before { + content: "\F0ECC"; +} + +.mdi-shield-alert-outline::before { + content: "\F0ECD"; +} + +.mdi-shield-bug::before { + content: "\F13DA"; +} + +.mdi-shield-bug-outline::before { + content: "\F13DB"; +} + +.mdi-shield-car::before { + content: "\F0F83"; +} + +.mdi-shield-check::before { + content: "\F0565"; +} + +.mdi-shield-check-outline::before { + content: "\F0CC8"; +} + +.mdi-shield-cross::before { + content: "\F0CC9"; +} + +.mdi-shield-cross-outline::before { + content: "\F0CCA"; +} + +.mdi-shield-edit::before { + content: "\F11A0"; +} + +.mdi-shield-edit-outline::before { + content: "\F11A1"; +} + +.mdi-shield-half::before { + content: "\F1360"; +} + +.mdi-shield-half-full::before { + content: "\F0780"; +} + +.mdi-shield-home::before { + content: "\F068A"; +} + +.mdi-shield-home-outline::before { + content: "\F0CCB"; +} + +.mdi-shield-key::before { + content: "\F0BC4"; +} + +.mdi-shield-key-outline::before { + content: "\F0BC5"; +} + +.mdi-shield-link-variant::before { + content: "\F0D33"; +} + +.mdi-shield-link-variant-outline::before { + content: "\F0D34"; +} + +.mdi-shield-lock::before { + content: "\F099D"; +} + +.mdi-shield-lock-outline::before { + content: "\F0CCC"; +} + +.mdi-shield-off::before { + content: "\F099E"; +} + +.mdi-shield-off-outline::before { + content: "\F099C"; +} + +.mdi-shield-outline::before { + content: "\F0499"; +} + +.mdi-shield-plus::before { + content: "\F0ADA"; +} + +.mdi-shield-plus-outline::before { + content: "\F0ADB"; +} + +.mdi-shield-refresh::before { + content: "\F00AA"; +} + +.mdi-shield-refresh-outline::before { + content: "\F01E0"; +} + +.mdi-shield-remove::before { + content: "\F0ADC"; +} + +.mdi-shield-remove-outline::before { + content: "\F0ADD"; +} + +.mdi-shield-search::before { + content: "\F0D9A"; +} + +.mdi-shield-star::before { + content: "\F113B"; +} + +.mdi-shield-star-outline::before { + content: "\F113C"; +} + +.mdi-shield-sun::before { + content: "\F105D"; +} + +.mdi-shield-sun-outline::before { + content: "\F105E"; +} + +.mdi-shield-sync::before { + content: "\F11A2"; +} + +.mdi-shield-sync-outline::before { + content: "\F11A3"; +} + +.mdi-ship-wheel::before { + content: "\F0833"; +} + +.mdi-shoe-ballet::before { + content: "\F15CA"; +} + +.mdi-shoe-cleat::before { + content: "\F15C7"; +} + +.mdi-shoe-formal::before { + content: "\F0B47"; +} + +.mdi-shoe-heel::before { + content: "\F0B48"; +} + +.mdi-shoe-print::before { + content: "\F0DFA"; +} + +.mdi-shoe-sneaker::before { + content: "\F15C8"; +} + +.mdi-shopping::before { + content: "\F049A"; +} + +.mdi-shopping-music::before { + content: "\F049B"; +} + +.mdi-shopping-outline::before { + content: "\F11D5"; +} + +.mdi-shopping-search::before { + content: "\F0F84"; +} + +.mdi-shore::before { + content: "\F14F9"; +} + +.mdi-shovel::before { + content: "\F0710"; +} + +.mdi-shovel-off::before { + content: "\F0711"; +} + +.mdi-shower::before { + content: "\F09A0"; +} + +.mdi-shower-head::before { + content: "\F09A1"; +} + +.mdi-shredder::before { + content: "\F049C"; +} + +.mdi-shuffle::before { + content: "\F049D"; +} + +.mdi-shuffle-disabled::before { + content: "\F049E"; +} + +.mdi-shuffle-variant::before { + content: "\F049F"; +} + +.mdi-shuriken::before { + content: "\F137F"; +} + +.mdi-sigma::before { + content: "\F04A0"; +} + +.mdi-sigma-lower::before { + content: "\F062B"; +} + +.mdi-sign-caution::before { + content: "\F04A1"; +} + +.mdi-sign-direction::before { + content: "\F0781"; +} + +.mdi-sign-direction-minus::before { + content: "\F1000"; +} + +.mdi-sign-direction-plus::before { + content: "\F0FDC"; +} + +.mdi-sign-direction-remove::before { + content: "\F0FDD"; +} + +.mdi-sign-pole::before { + content: "\F14F8"; +} + +.mdi-sign-real-estate::before { + content: "\F1118"; +} + +.mdi-sign-text::before { + content: "\F0782"; +} + +.mdi-signal::before { + content: "\F04A2"; +} + +.mdi-signal-2g::before { + content: "\F0712"; +} + +.mdi-signal-3g::before { + content: "\F0713"; +} + +.mdi-signal-4g::before { + content: "\F0714"; +} + +.mdi-signal-5g::before { + content: "\F0A6F"; +} + +.mdi-signal-cellular-1::before { + content: "\F08BC"; +} + +.mdi-signal-cellular-2::before { + content: "\F08BD"; +} + +.mdi-signal-cellular-3::before { + content: "\F08BE"; +} + +.mdi-signal-cellular-outline::before { + content: "\F08BF"; +} + +.mdi-signal-distance-variant::before { + content: "\F0E64"; +} + +.mdi-signal-hspa::before { + content: "\F0715"; +} + +.mdi-signal-hspa-plus::before { + content: "\F0716"; +} + +.mdi-signal-off::before { + content: "\F0783"; +} + +.mdi-signal-variant::before { + content: "\F060A"; +} + +.mdi-signature::before { + content: "\F0DFB"; +} + +.mdi-signature-freehand::before { + content: "\F0DFC"; +} + +.mdi-signature-image::before { + content: "\F0DFD"; +} + +.mdi-signature-text::before { + content: "\F0DFE"; +} + +.mdi-silo::before { + content: "\F0B49"; +} + +.mdi-silverware::before { + content: "\F04A3"; +} + +.mdi-silverware-clean::before { + content: "\F0FDE"; +} + +.mdi-silverware-fork::before { + content: "\F04A4"; +} + +.mdi-silverware-fork-knife::before { + content: "\F0A70"; +} + +.mdi-silverware-spoon::before { + content: "\F04A5"; +} + +.mdi-silverware-variant::before { + content: "\F04A6"; +} + +.mdi-sim::before { + content: "\F04A7"; +} + +.mdi-sim-alert::before { + content: "\F04A8"; +} + +.mdi-sim-alert-outline::before { + content: "\F15D3"; +} + +.mdi-sim-off::before { + content: "\F04A9"; +} + +.mdi-sim-off-outline::before { + content: "\F15D4"; +} + +.mdi-sim-outline::before { + content: "\F15D5"; +} + +.mdi-simple-icons::before { + content: "\F131D"; +} + +.mdi-sina-weibo::before { + content: "\F0ADF"; +} + +.mdi-sine-wave::before { + content: "\F095B"; +} + +.mdi-sitemap::before { + content: "\F04AA"; +} + +.mdi-size-l::before { + content: "\F13A6"; +} + +.mdi-size-m::before { + content: "\F13A5"; +} + +.mdi-size-s::before { + content: "\F13A4"; +} + +.mdi-size-xl::before { + content: "\F13A7"; +} + +.mdi-size-xs::before { + content: "\F13A3"; +} + +.mdi-size-xxl::before { + content: "\F13A8"; +} + +.mdi-size-xxs::before { + content: "\F13A2"; +} + +.mdi-size-xxxl::before { + content: "\F13A9"; +} + +.mdi-skate::before { + content: "\F0D35"; +} + +.mdi-skateboard::before { + content: "\F14C2"; +} + +.mdi-skew-less::before { + content: "\F0D36"; +} + +.mdi-skew-more::before { + content: "\F0D37"; +} + +.mdi-ski::before { + content: "\F1304"; +} + +.mdi-ski-cross-country::before { + content: "\F1305"; +} + +.mdi-ski-water::before { + content: "\F1306"; +} + +.mdi-skip-backward::before { + content: "\F04AB"; +} + +.mdi-skip-backward-outline::before { + content: "\F0F25"; +} + +.mdi-skip-forward::before { + content: "\F04AC"; +} + +.mdi-skip-forward-outline::before { + content: "\F0F26"; +} + +.mdi-skip-next::before { + content: "\F04AD"; +} + +.mdi-skip-next-circle::before { + content: "\F0661"; +} + +.mdi-skip-next-circle-outline::before { + content: "\F0662"; +} + +.mdi-skip-next-outline::before { + content: "\F0F27"; +} + +.mdi-skip-previous::before { + content: "\F04AE"; +} + +.mdi-skip-previous-circle::before { + content: "\F0663"; +} + +.mdi-skip-previous-circle-outline::before { + content: "\F0664"; +} + +.mdi-skip-previous-outline::before { + content: "\F0F28"; +} + +.mdi-skull::before { + content: "\F068C"; +} + +.mdi-skull-crossbones::before { + content: "\F0BC6"; +} + +.mdi-skull-crossbones-outline::before { + content: "\F0BC7"; +} + +.mdi-skull-outline::before { + content: "\F0BC8"; +} + +.mdi-skull-scan::before { + content: "\F14C7"; +} + +.mdi-skull-scan-outline::before { + content: "\F14C8"; +} + +.mdi-skype::before { + content: "\F04AF"; +} + +.mdi-skype-business::before { + content: "\F04B0"; +} + +.mdi-slack::before { + content: "\F04B1"; +} + +.mdi-slash-forward::before { + content: "\F0FDF"; +} + +.mdi-slash-forward-box::before { + content: "\F0FE0"; +} + +.mdi-sleep::before { + content: "\F04B2"; +} + +.mdi-sleep-off::before { + content: "\F04B3"; +} + +.mdi-slide::before { + content: "\F15A5"; +} + +.mdi-slope-downhill::before { + content: "\F0DFF"; +} + +.mdi-slope-uphill::before { + content: "\F0E00"; +} + +.mdi-slot-machine::before { + content: "\F1114"; +} + +.mdi-slot-machine-outline::before { + content: "\F1115"; +} + +.mdi-smart-card::before { + content: "\F10BD"; +} + +.mdi-smart-card-outline::before { + content: "\F10BE"; +} + +.mdi-smart-card-reader::before { + content: "\F10BF"; +} + +.mdi-smart-card-reader-outline::before { + content: "\F10C0"; +} + +.mdi-smog::before { + content: "\F0A71"; +} + +.mdi-smoke-detector::before { + content: "\F0392"; +} + +.mdi-smoking::before { + content: "\F04B4"; +} + +.mdi-smoking-off::before { + content: "\F04B5"; +} + +.mdi-smoking-pipe::before { + content: "\F140D"; +} + +.mdi-smoking-pipe-off::before { + content: "\F1428"; +} + +.mdi-snail::before { + content: "\F1677"; +} + +.mdi-snake::before { + content: "\F150E"; +} + +.mdi-snapchat::before { + content: "\F04B6"; +} + +.mdi-snowboard::before { + content: "\F1307"; +} + +.mdi-snowflake::before { + content: "\F0717"; +} + +.mdi-snowflake-alert::before { + content: "\F0F29"; +} + +.mdi-snowflake-melt::before { + content: "\F12CB"; +} + +.mdi-snowflake-off::before { + content: "\F14E3"; +} + +.mdi-snowflake-variant::before { + content: "\F0F2A"; +} + +.mdi-snowman::before { + content: "\F04B7"; +} + +.mdi-soccer::before { + content: "\F04B8"; +} + +.mdi-soccer-field::before { + content: "\F0834"; +} + +.mdi-social-distance-2-meters::before { + content: "\F1579"; +} + +.mdi-social-distance-6-feet::before { + content: "\F157A"; +} + +.mdi-sofa::before { + content: "\F04B9"; +} + +.mdi-sofa-outline::before { + content: "\F156D"; +} + +.mdi-sofa-single::before { + content: "\F156E"; +} + +.mdi-sofa-single-outline::before { + content: "\F156F"; +} + +.mdi-solar-panel::before { + content: "\F0D9B"; +} + +.mdi-solar-panel-large::before { + content: "\F0D9C"; +} + +.mdi-solar-power::before { + content: "\F0A72"; +} + +.mdi-soldering-iron::before { + content: "\F1092"; +} + +.mdi-solid::before { + content: "\F068D"; +} + +.mdi-sony-playstation::before { + content: "\F0414"; +} + +.mdi-sort::before { + content: "\F04BA"; +} + +.mdi-sort-alphabetical-ascending::before { + content: "\F05BD"; +} + +.mdi-sort-alphabetical-ascending-variant::before { + content: "\F1148"; +} + +.mdi-sort-alphabetical-descending::before { + content: "\F05BF"; +} + +.mdi-sort-alphabetical-descending-variant::before { + content: "\F1149"; +} + +.mdi-sort-alphabetical-variant::before { + content: "\F04BB"; +} + +.mdi-sort-ascending::before { + content: "\F04BC"; +} + +.mdi-sort-bool-ascending::before { + content: "\F1385"; +} + +.mdi-sort-bool-ascending-variant::before { + content: "\F1386"; +} + +.mdi-sort-bool-descending::before { + content: "\F1387"; +} + +.mdi-sort-bool-descending-variant::before { + content: "\F1388"; +} + +.mdi-sort-calendar-ascending::before { + content: "\F1547"; +} + +.mdi-sort-calendar-descending::before { + content: "\F1548"; +} + +.mdi-sort-clock-ascending::before { + content: "\F1549"; +} + +.mdi-sort-clock-ascending-outline::before { + content: "\F154A"; +} + +.mdi-sort-clock-descending::before { + content: "\F154B"; +} + +.mdi-sort-clock-descending-outline::before { + content: "\F154C"; +} + +.mdi-sort-descending::before { + content: "\F04BD"; +} + +.mdi-sort-numeric-ascending::before { + content: "\F1389"; +} + +.mdi-sort-numeric-ascending-variant::before { + content: "\F090D"; +} + +.mdi-sort-numeric-descending::before { + content: "\F138A"; +} + +.mdi-sort-numeric-descending-variant::before { + content: "\F0AD2"; +} + +.mdi-sort-numeric-variant::before { + content: "\F04BE"; +} + +.mdi-sort-reverse-variant::before { + content: "\F033C"; +} + +.mdi-sort-variant::before { + content: "\F04BF"; +} + +.mdi-sort-variant-lock::before { + content: "\F0CCD"; +} + +.mdi-sort-variant-lock-open::before { + content: "\F0CCE"; +} + +.mdi-sort-variant-remove::before { + content: "\F1147"; +} + +.mdi-soundcloud::before { + content: "\F04C0"; +} + +.mdi-source-branch::before { + content: "\F062C"; +} + +.mdi-source-branch-check::before { + content: "\F14CF"; +} + +.mdi-source-branch-minus::before { + content: "\F14CB"; +} + +.mdi-source-branch-plus::before { + content: "\F14CA"; +} + +.mdi-source-branch-refresh::before { + content: "\F14CD"; +} + +.mdi-source-branch-remove::before { + content: "\F14CC"; +} + +.mdi-source-branch-sync::before { + content: "\F14CE"; +} + +.mdi-source-commit::before { + content: "\F0718"; +} + +.mdi-source-commit-end::before { + content: "\F0719"; +} + +.mdi-source-commit-end-local::before { + content: "\F071A"; +} + +.mdi-source-commit-local::before { + content: "\F071B"; +} + +.mdi-source-commit-next-local::before { + content: "\F071C"; +} + +.mdi-source-commit-start::before { + content: "\F071D"; +} + +.mdi-source-commit-start-next-local::before { + content: "\F071E"; +} + +.mdi-source-fork::before { + content: "\F04C1"; +} + +.mdi-source-merge::before { + content: "\F062D"; +} + +.mdi-source-pull::before { + content: "\F04C2"; +} + +.mdi-source-repository::before { + content: "\F0CCF"; +} + +.mdi-source-repository-multiple::before { + content: "\F0CD0"; +} + +.mdi-soy-sauce::before { + content: "\F07EE"; +} + +.mdi-soy-sauce-off::before { + content: "\F13FC"; +} + +.mdi-spa::before { + content: "\F0CD1"; +} + +.mdi-spa-outline::before { + content: "\F0CD2"; +} + +.mdi-space-invaders::before { + content: "\F0BC9"; +} + +.mdi-space-station::before { + content: "\F1383"; +} + +.mdi-spade::before { + content: "\F0E65"; +} + +.mdi-sparkles::before { + content: "\F1545"; +} + +.mdi-speaker::before { + content: "\F04C3"; +} + +.mdi-speaker-bluetooth::before { + content: "\F09A2"; +} + +.mdi-speaker-multiple::before { + content: "\F0D38"; +} + +.mdi-speaker-off::before { + content: "\F04C4"; +} + +.mdi-speaker-wireless::before { + content: "\F071F"; +} + +.mdi-speedometer::before { + content: "\F04C5"; +} + +.mdi-speedometer-medium::before { + content: "\F0F85"; +} + +.mdi-speedometer-slow::before { + content: "\F0F86"; +} + +.mdi-spellcheck::before { + content: "\F04C6"; +} + +.mdi-spider::before { + content: "\F11EA"; +} + +.mdi-spider-thread::before { + content: "\F11EB"; +} + +.mdi-spider-web::before { + content: "\F0BCA"; +} + +.mdi-spirit-level::before { + content: "\F14F1"; +} + +.mdi-spoon-sugar::before { + content: "\F1429"; +} + +.mdi-spotify::before { + content: "\F04C7"; +} + +.mdi-spotlight::before { + content: "\F04C8"; +} + +.mdi-spotlight-beam::before { + content: "\F04C9"; +} + +.mdi-spray::before { + content: "\F0665"; +} + +.mdi-spray-bottle::before { + content: "\F0AE0"; +} + +.mdi-sprinkler::before { + content: "\F105F"; +} + +.mdi-sprinkler-variant::before { + content: "\F1060"; +} + +.mdi-sprout::before { + content: "\F0E66"; +} + +.mdi-sprout-outline::before { + content: "\F0E67"; +} + +.mdi-square::before { + content: "\F0764"; +} + +.mdi-square-circle::before { + content: "\F1500"; +} + +.mdi-square-edit-outline::before { + content: "\F090C"; +} + +.mdi-square-medium::before { + content: "\F0A13"; +} + +.mdi-square-medium-outline::before { + content: "\F0A14"; +} + +.mdi-square-off::before { + content: "\F12EE"; +} + +.mdi-square-off-outline::before { + content: "\F12EF"; +} + +.mdi-square-outline::before { + content: "\F0763"; +} + +.mdi-square-root::before { + content: "\F0784"; +} + +.mdi-square-root-box::before { + content: "\F09A3"; +} + +.mdi-square-rounded::before { + content: "\F14FB"; +} + +.mdi-square-rounded-outline::before { + content: "\F14FC"; +} + +.mdi-square-small::before { + content: "\F0A15"; +} + +.mdi-square-wave::before { + content: "\F147B"; +} + +.mdi-squeegee::before { + content: "\F0AE1"; +} + +.mdi-ssh::before { + content: "\F08C0"; +} + +.mdi-stack-exchange::before { + content: "\F060B"; +} + +.mdi-stack-overflow::before { + content: "\F04CC"; +} + +.mdi-stackpath::before { + content: "\F0359"; +} + +.mdi-stadium::before { + content: "\F0FF9"; +} + +.mdi-stadium-variant::before { + content: "\F0720"; +} + +.mdi-stairs::before { + content: "\F04CD"; +} + +.mdi-stairs-box::before { + content: "\F139E"; +} + +.mdi-stairs-down::before { + content: "\F12BE"; +} + +.mdi-stairs-up::before { + content: "\F12BD"; +} + +.mdi-stamper::before { + content: "\F0D39"; +} + +.mdi-standard-definition::before { + content: "\F07EF"; +} + +.mdi-star::before { + content: "\F04CE"; +} + +.mdi-star-box::before { + content: "\F0A73"; +} + +.mdi-star-box-multiple::before { + content: "\F1286"; +} + +.mdi-star-box-multiple-outline::before { + content: "\F1287"; +} + +.mdi-star-box-outline::before { + content: "\F0A74"; +} + +.mdi-star-check::before { + content: "\F1566"; +} + +.mdi-star-check-outline::before { + content: "\F156A"; +} + +.mdi-star-circle::before { + content: "\F04CF"; +} + +.mdi-star-circle-outline::before { + content: "\F09A4"; +} + +.mdi-star-cog::before { + content: "\F1668"; +} + +.mdi-star-cog-outline::before { + content: "\F1669"; +} + +.mdi-star-face::before { + content: "\F09A5"; +} + +.mdi-star-four-points::before { + content: "\F0AE2"; +} + +.mdi-star-four-points-outline::before { + content: "\F0AE3"; +} + +.mdi-star-half::before { + content: "\F0246"; +} + +.mdi-star-half-full::before { + content: "\F04D0"; +} + +.mdi-star-minus::before { + content: "\F1564"; +} + +.mdi-star-minus-outline::before { + content: "\F1568"; +} + +.mdi-star-off::before { + content: "\F04D1"; +} + +.mdi-star-off-outline::before { + content: "\F155B"; +} + +.mdi-star-outline::before { + content: "\F04D2"; +} + +.mdi-star-plus::before { + content: "\F1563"; +} + +.mdi-star-plus-outline::before { + content: "\F1567"; +} + +.mdi-star-remove::before { + content: "\F1565"; +} + +.mdi-star-remove-outline::before { + content: "\F1569"; +} + +.mdi-star-settings::before { + content: "\F166A"; +} + +.mdi-star-settings-outline::before { + content: "\F166B"; +} + +.mdi-star-three-points::before { + content: "\F0AE4"; +} + +.mdi-star-three-points-outline::before { + content: "\F0AE5"; +} + +.mdi-state-machine::before { + content: "\F11EF"; +} + +.mdi-steam::before { + content: "\F04D3"; +} + +.mdi-steering::before { + content: "\F04D4"; +} + +.mdi-steering-off::before { + content: "\F090E"; +} + +.mdi-step-backward::before { + content: "\F04D5"; +} + +.mdi-step-backward-2::before { + content: "\F04D6"; +} + +.mdi-step-forward::before { + content: "\F04D7"; +} + +.mdi-step-forward-2::before { + content: "\F04D8"; +} + +.mdi-stethoscope::before { + content: "\F04D9"; +} + +.mdi-sticker::before { + content: "\F1364"; +} + +.mdi-sticker-alert::before { + content: "\F1365"; +} + +.mdi-sticker-alert-outline::before { + content: "\F1366"; +} + +.mdi-sticker-check::before { + content: "\F1367"; +} + +.mdi-sticker-check-outline::before { + content: "\F1368"; +} + +.mdi-sticker-circle-outline::before { + content: "\F05D0"; +} + +.mdi-sticker-emoji::before { + content: "\F0785"; +} + +.mdi-sticker-minus::before { + content: "\F1369"; +} + +.mdi-sticker-minus-outline::before { + content: "\F136A"; +} + +.mdi-sticker-outline::before { + content: "\F136B"; +} + +.mdi-sticker-plus::before { + content: "\F136C"; +} + +.mdi-sticker-plus-outline::before { + content: "\F136D"; +} + +.mdi-sticker-remove::before { + content: "\F136E"; +} + +.mdi-sticker-remove-outline::before { + content: "\F136F"; +} + +.mdi-stocking::before { + content: "\F04DA"; +} + +.mdi-stomach::before { + content: "\F1093"; +} + +.mdi-stop::before { + content: "\F04DB"; +} + +.mdi-stop-circle::before { + content: "\F0666"; +} + +.mdi-stop-circle-outline::before { + content: "\F0667"; +} + +.mdi-store::before { + content: "\F04DC"; +} + +.mdi-store-24-hour::before { + content: "\F04DD"; +} + +.mdi-store-minus::before { + content: "\F165E"; +} + +.mdi-store-outline::before { + content: "\F1361"; +} + +.mdi-store-plus::before { + content: "\F165F"; +} + +.mdi-store-remove::before { + content: "\F1660"; +} + +.mdi-storefront::before { + content: "\F07C7"; +} + +.mdi-storefront-outline::before { + content: "\F10C1"; +} + +.mdi-stove::before { + content: "\F04DE"; +} + +.mdi-strategy::before { + content: "\F11D6"; +} + +.mdi-stretch-to-page::before { + content: "\F0F2B"; +} + +.mdi-stretch-to-page-outline::before { + content: "\F0F2C"; +} + +.mdi-string-lights::before { + content: "\F12BA"; +} + +.mdi-string-lights-off::before { + content: "\F12BB"; +} + +.mdi-subdirectory-arrow-left::before { + content: "\F060C"; +} + +.mdi-subdirectory-arrow-right::before { + content: "\F060D"; +} + +.mdi-submarine::before { + content: "\F156C"; +} + +.mdi-subtitles::before { + content: "\F0A16"; +} + +.mdi-subtitles-outline::before { + content: "\F0A17"; +} + +.mdi-subway::before { + content: "\F06AC"; +} + +.mdi-subway-alert-variant::before { + content: "\F0D9D"; +} + +.mdi-subway-variant::before { + content: "\F04DF"; +} + +.mdi-summit::before { + content: "\F0786"; +} + +.mdi-sunglasses::before { + content: "\F04E0"; +} + +.mdi-surround-sound::before { + content: "\F05C5"; +} + +.mdi-surround-sound-2-0::before { + content: "\F07F0"; +} + +.mdi-surround-sound-3-1::before { + content: "\F07F1"; +} + +.mdi-surround-sound-5-1::before { + content: "\F07F2"; +} + +.mdi-surround-sound-7-1::before { + content: "\F07F3"; +} + +.mdi-svg::before { + content: "\F0721"; +} + +.mdi-swap-horizontal::before { + content: "\F04E1"; +} + +.mdi-swap-horizontal-bold::before { + content: "\F0BCD"; +} + +.mdi-swap-horizontal-circle::before { + content: "\F0FE1"; +} + +.mdi-swap-horizontal-circle-outline::before { + content: "\F0FE2"; +} + +.mdi-swap-horizontal-variant::before { + content: "\F08C1"; +} + +.mdi-swap-vertical::before { + content: "\F04E2"; +} + +.mdi-swap-vertical-bold::before { + content: "\F0BCE"; +} + +.mdi-swap-vertical-circle::before { + content: "\F0FE3"; +} + +.mdi-swap-vertical-circle-outline::before { + content: "\F0FE4"; +} + +.mdi-swap-vertical-variant::before { + content: "\F08C2"; +} + +.mdi-swim::before { + content: "\F04E3"; +} + +.mdi-switch::before { + content: "\F04E4"; +} + +.mdi-sword::before { + content: "\F04E5"; +} + +.mdi-sword-cross::before { + content: "\F0787"; +} + +.mdi-syllabary-hangul::before { + content: "\F1333"; +} + +.mdi-syllabary-hiragana::before { + content: "\F1334"; +} + +.mdi-syllabary-katakana::before { + content: "\F1335"; +} + +.mdi-syllabary-katakana-halfwidth::before { + content: "\F1336"; +} + +.mdi-symbol::before { + content: "\F1501"; +} + +.mdi-symfony::before { + content: "\F0AE6"; +} + +.mdi-sync::before { + content: "\F04E6"; +} + +.mdi-sync-alert::before { + content: "\F04E7"; +} + +.mdi-sync-circle::before { + content: "\F1378"; +} + +.mdi-sync-off::before { + content: "\F04E8"; +} + +.mdi-tab::before { + content: "\F04E9"; +} + +.mdi-tab-minus::before { + content: "\F0B4B"; +} + +.mdi-tab-plus::before { + content: "\F075C"; +} + +.mdi-tab-remove::before { + content: "\F0B4C"; +} + +.mdi-tab-unselected::before { + content: "\F04EA"; +} + +.mdi-table::before { + content: "\F04EB"; +} + +.mdi-table-account::before { + content: "\F13B9"; +} + +.mdi-table-alert::before { + content: "\F13BA"; +} + +.mdi-table-arrow-down::before { + content: "\F13BB"; +} + +.mdi-table-arrow-left::before { + content: "\F13BC"; +} + +.mdi-table-arrow-right::before { + content: "\F13BD"; +} + +.mdi-table-arrow-up::before { + content: "\F13BE"; +} + +.mdi-table-border::before { + content: "\F0A18"; +} + +.mdi-table-cancel::before { + content: "\F13BF"; +} + +.mdi-table-chair::before { + content: "\F1061"; +} + +.mdi-table-check::before { + content: "\F13C0"; +} + +.mdi-table-clock::before { + content: "\F13C1"; +} + +.mdi-table-cog::before { + content: "\F13C2"; +} + +.mdi-table-column::before { + content: "\F0835"; +} + +.mdi-table-column-plus-after::before { + content: "\F04EC"; +} + +.mdi-table-column-plus-before::before { + content: "\F04ED"; +} + +.mdi-table-column-remove::before { + content: "\F04EE"; +} + +.mdi-table-column-width::before { + content: "\F04EF"; +} + +.mdi-table-edit::before { + content: "\F04F0"; +} + +.mdi-table-eye::before { + content: "\F1094"; +} + +.mdi-table-eye-off::before { + content: "\F13C3"; +} + +.mdi-table-furniture::before { + content: "\F05BC"; +} + +.mdi-table-headers-eye::before { + content: "\F121D"; +} + +.mdi-table-headers-eye-off::before { + content: "\F121E"; +} + +.mdi-table-heart::before { + content: "\F13C4"; +} + +.mdi-table-key::before { + content: "\F13C5"; +} + +.mdi-table-large::before { + content: "\F04F1"; +} + +.mdi-table-large-plus::before { + content: "\F0F87"; +} + +.mdi-table-large-remove::before { + content: "\F0F88"; +} + +.mdi-table-lock::before { + content: "\F13C6"; +} + +.mdi-table-merge-cells::before { + content: "\F09A6"; +} + +.mdi-table-minus::before { + content: "\F13C7"; +} + +.mdi-table-multiple::before { + content: "\F13C8"; +} + +.mdi-table-network::before { + content: "\F13C9"; +} + +.mdi-table-of-contents::before { + content: "\F0836"; +} + +.mdi-table-off::before { + content: "\F13CA"; +} + +.mdi-table-plus::before { + content: "\F0A75"; +} + +.mdi-table-refresh::before { + content: "\F13A0"; +} + +.mdi-table-remove::before { + content: "\F0A76"; +} + +.mdi-table-row::before { + content: "\F0837"; +} + +.mdi-table-row-height::before { + content: "\F04F2"; +} + +.mdi-table-row-plus-after::before { + content: "\F04F3"; +} + +.mdi-table-row-plus-before::before { + content: "\F04F4"; +} + +.mdi-table-row-remove::before { + content: "\F04F5"; +} + +.mdi-table-search::before { + content: "\F090F"; +} + +.mdi-table-settings::before { + content: "\F0838"; +} + +.mdi-table-split-cell::before { + content: "\F142A"; +} + +.mdi-table-star::before { + content: "\F13CB"; +} + +.mdi-table-sync::before { + content: "\F13A1"; +} + +.mdi-table-tennis::before { + content: "\F0E68"; +} + +.mdi-tablet::before { + content: "\F04F6"; +} + +.mdi-tablet-android::before { + content: "\F04F7"; +} + +.mdi-tablet-cellphone::before { + content: "\F09A7"; +} + +.mdi-tablet-dashboard::before { + content: "\F0ECE"; +} + +.mdi-tablet-ipad::before { + content: "\F04F8"; +} + +.mdi-taco::before { + content: "\F0762"; +} + +.mdi-tag::before { + content: "\F04F9"; +} + +.mdi-tag-faces::before { + content: "\F04FA"; +} + +.mdi-tag-heart::before { + content: "\F068B"; +} + +.mdi-tag-heart-outline::before { + content: "\F0BCF"; +} + +.mdi-tag-minus::before { + content: "\F0910"; +} + +.mdi-tag-minus-outline::before { + content: "\F121F"; +} + +.mdi-tag-multiple::before { + content: "\F04FB"; +} + +.mdi-tag-multiple-outline::before { + content: "\F12F7"; +} + +.mdi-tag-off::before { + content: "\F1220"; +} + +.mdi-tag-off-outline::before { + content: "\F1221"; +} + +.mdi-tag-outline::before { + content: "\F04FC"; +} + +.mdi-tag-plus::before { + content: "\F0722"; +} + +.mdi-tag-plus-outline::before { + content: "\F1222"; +} + +.mdi-tag-remove::before { + content: "\F0723"; +} + +.mdi-tag-remove-outline::before { + content: "\F1223"; +} + +.mdi-tag-text::before { + content: "\F1224"; +} + +.mdi-tag-text-outline::before { + content: "\F04FD"; +} + +.mdi-tailwind::before { + content: "\F13FF"; +} + +.mdi-tank::before { + content: "\F0D3A"; +} + +.mdi-tanker-truck::before { + content: "\F0FE5"; +} + +.mdi-tape-drive::before { + content: "\F16DF"; +} + +.mdi-tape-measure::before { + content: "\F0B4D"; +} + +.mdi-target::before { + content: "\F04FE"; +} + +.mdi-target-account::before { + content: "\F0BD0"; +} + +.mdi-target-variant::before { + content: "\F0A77"; +} + +.mdi-taxi::before { + content: "\F04FF"; +} + +.mdi-tea::before { + content: "\F0D9E"; +} + +.mdi-tea-outline::before { + content: "\F0D9F"; +} + +.mdi-teach::before { + content: "\F0890"; +} + +.mdi-teamviewer::before { + content: "\F0500"; +} + +.mdi-telegram::before { + content: "\F0501"; +} + +.mdi-telescope::before { + content: "\F0B4E"; +} + +.mdi-television::before { + content: "\F0502"; +} + +.mdi-television-ambient-light::before { + content: "\F1356"; +} + +.mdi-television-box::before { + content: "\F0839"; +} + +.mdi-television-classic::before { + content: "\F07F4"; +} + +.mdi-television-classic-off::before { + content: "\F083A"; +} + +.mdi-television-clean::before { + content: "\F1110"; +} + +.mdi-television-guide::before { + content: "\F0503"; +} + +.mdi-television-off::before { + content: "\F083B"; +} + +.mdi-television-pause::before { + content: "\F0F89"; +} + +.mdi-television-play::before { + content: "\F0ECF"; +} + +.mdi-television-stop::before { + content: "\F0F8A"; +} + +.mdi-temperature-celsius::before { + content: "\F0504"; +} + +.mdi-temperature-fahrenheit::before { + content: "\F0505"; +} + +.mdi-temperature-kelvin::before { + content: "\F0506"; +} + +.mdi-tennis::before { + content: "\F0DA0"; +} + +.mdi-tennis-ball::before { + content: "\F0507"; +} + +.mdi-tent::before { + content: "\F0508"; +} + +.mdi-terraform::before { + content: "\F1062"; +} + +.mdi-terrain::before { + content: "\F0509"; +} + +.mdi-test-tube::before { + content: "\F0668"; +} + +.mdi-test-tube-empty::before { + content: "\F0911"; +} + +.mdi-test-tube-off::before { + content: "\F0912"; +} + +.mdi-text::before { + content: "\F09A8"; +} + +.mdi-text-account::before { + content: "\F1570"; +} + +.mdi-text-box::before { + content: "\F021A"; +} + +.mdi-text-box-check::before { + content: "\F0EA6"; +} + +.mdi-text-box-check-outline::before { + content: "\F0EA7"; +} + +.mdi-text-box-minus::before { + content: "\F0EA8"; +} + +.mdi-text-box-minus-outline::before { + content: "\F0EA9"; +} + +.mdi-text-box-multiple::before { + content: "\F0AB7"; +} + +.mdi-text-box-multiple-outline::before { + content: "\F0AB8"; +} + +.mdi-text-box-outline::before { + content: "\F09ED"; +} + +.mdi-text-box-plus::before { + content: "\F0EAA"; +} + +.mdi-text-box-plus-outline::before { + content: "\F0EAB"; +} + +.mdi-text-box-remove::before { + content: "\F0EAC"; +} + +.mdi-text-box-remove-outline::before { + content: "\F0EAD"; +} + +.mdi-text-box-search::before { + content: "\F0EAE"; +} + +.mdi-text-box-search-outline::before { + content: "\F0EAF"; +} + +.mdi-text-recognition::before { + content: "\F113D"; +} + +.mdi-text-search::before { + content: "\F13B8"; +} + +.mdi-text-shadow::before { + content: "\F0669"; +} + +.mdi-text-short::before { + content: "\F09A9"; +} + +.mdi-text-subject::before { + content: "\F09AA"; +} + +.mdi-text-to-speech::before { + content: "\F050A"; +} + +.mdi-text-to-speech-off::before { + content: "\F050B"; +} + +.mdi-texture::before { + content: "\F050C"; +} + +.mdi-texture-box::before { + content: "\F0FE6"; +} + +.mdi-theater::before { + content: "\F050D"; +} + +.mdi-theme-light-dark::before { + content: "\F050E"; +} + +.mdi-thermometer::before { + content: "\F050F"; +} + +.mdi-thermometer-alert::before { + content: "\F0E01"; +} + +.mdi-thermometer-chevron-down::before { + content: "\F0E02"; +} + +.mdi-thermometer-chevron-up::before { + content: "\F0E03"; +} + +.mdi-thermometer-high::before { + content: "\F10C2"; +} + +.mdi-thermometer-lines::before { + content: "\F0510"; +} + +.mdi-thermometer-low::before { + content: "\F10C3"; +} + +.mdi-thermometer-minus::before { + content: "\F0E04"; +} + +.mdi-thermometer-off::before { + content: "\F1531"; +} + +.mdi-thermometer-plus::before { + content: "\F0E05"; +} + +.mdi-thermostat::before { + content: "\F0393"; +} + +.mdi-thermostat-box::before { + content: "\F0891"; +} + +.mdi-thought-bubble::before { + content: "\F07F6"; +} + +.mdi-thought-bubble-outline::before { + content: "\F07F7"; +} + +.mdi-thumb-down::before { + content: "\F0511"; +} + +.mdi-thumb-down-outline::before { + content: "\F0512"; +} + +.mdi-thumb-up::before { + content: "\F0513"; +} + +.mdi-thumb-up-outline::before { + content: "\F0514"; +} + +.mdi-thumbs-up-down::before { + content: "\F0515"; +} + +.mdi-ticket::before { + content: "\F0516"; +} + +.mdi-ticket-account::before { + content: "\F0517"; +} + +.mdi-ticket-confirmation::before { + content: "\F0518"; +} + +.mdi-ticket-confirmation-outline::before { + content: "\F13AA"; +} + +.mdi-ticket-outline::before { + content: "\F0913"; +} + +.mdi-ticket-percent::before { + content: "\F0724"; +} + +.mdi-ticket-percent-outline::before { + content: "\F142B"; +} + +.mdi-tie::before { + content: "\F0519"; +} + +.mdi-tilde::before { + content: "\F0725"; +} + +.mdi-timelapse::before { + content: "\F051A"; +} + +.mdi-timeline::before { + content: "\F0BD1"; +} + +.mdi-timeline-alert::before { + content: "\F0F95"; +} + +.mdi-timeline-alert-outline::before { + content: "\F0F98"; +} + +.mdi-timeline-check::before { + content: "\F1532"; +} + +.mdi-timeline-check-outline::before { + content: "\F1533"; +} + +.mdi-timeline-clock::before { + content: "\F11FB"; +} + +.mdi-timeline-clock-outline::before { + content: "\F11FC"; +} + +.mdi-timeline-help::before { + content: "\F0F99"; +} + +.mdi-timeline-help-outline::before { + content: "\F0F9A"; +} + +.mdi-timeline-minus::before { + content: "\F1534"; +} + +.mdi-timeline-minus-outline::before { + content: "\F1535"; +} + +.mdi-timeline-outline::before { + content: "\F0BD2"; +} + +.mdi-timeline-plus::before { + content: "\F0F96"; +} + +.mdi-timeline-plus-outline::before { + content: "\F0F97"; +} + +.mdi-timeline-remove::before { + content: "\F1536"; +} + +.mdi-timeline-remove-outline::before { + content: "\F1537"; +} + +.mdi-timeline-text::before { + content: "\F0BD3"; +} + +.mdi-timeline-text-outline::before { + content: "\F0BD4"; +} + +.mdi-timer::before { + content: "\F13AB"; +} + +.mdi-timer-10::before { + content: "\F051C"; +} + +.mdi-timer-3::before { + content: "\F051D"; +} + +.mdi-timer-off::before { + content: "\F13AC"; +} + +.mdi-timer-off-outline::before { + content: "\F051E"; +} + +.mdi-timer-outline::before { + content: "\F051B"; +} + +.mdi-timer-sand::before { + content: "\F051F"; +} + +.mdi-timer-sand-empty::before { + content: "\F06AD"; +} + +.mdi-timer-sand-full::before { + content: "\F078C"; +} + +.mdi-timetable::before { + content: "\F0520"; +} + +.mdi-toaster::before { + content: "\F1063"; +} + +.mdi-toaster-off::before { + content: "\F11B7"; +} + +.mdi-toaster-oven::before { + content: "\F0CD3"; +} + +.mdi-toggle-switch::before { + content: "\F0521"; +} + +.mdi-toggle-switch-off::before { + content: "\F0522"; +} + +.mdi-toggle-switch-off-outline::before { + content: "\F0A19"; +} + +.mdi-toggle-switch-outline::before { + content: "\F0A1A"; +} + +.mdi-toilet::before { + content: "\F09AB"; +} + +.mdi-toolbox::before { + content: "\F09AC"; +} + +.mdi-toolbox-outline::before { + content: "\F09AD"; +} + +.mdi-tools::before { + content: "\F1064"; +} + +.mdi-tooltip::before { + content: "\F0523"; +} + +.mdi-tooltip-account::before { + content: "\F000C"; +} + +.mdi-tooltip-check::before { + content: "\F155C"; +} + +.mdi-tooltip-check-outline::before { + content: "\F155D"; +} + +.mdi-tooltip-edit::before { + content: "\F0524"; +} + +.mdi-tooltip-edit-outline::before { + content: "\F12C5"; +} + +.mdi-tooltip-image::before { + content: "\F0525"; +} + +.mdi-tooltip-image-outline::before { + content: "\F0BD5"; +} + +.mdi-tooltip-minus::before { + content: "\F155E"; +} + +.mdi-tooltip-minus-outline::before { + content: "\F155F"; +} + +.mdi-tooltip-outline::before { + content: "\F0526"; +} + +.mdi-tooltip-plus::before { + content: "\F0BD6"; +} + +.mdi-tooltip-plus-outline::before { + content: "\F0527"; +} + +.mdi-tooltip-remove::before { + content: "\F1560"; +} + +.mdi-tooltip-remove-outline::before { + content: "\F1561"; +} + +.mdi-tooltip-text::before { + content: "\F0528"; +} + +.mdi-tooltip-text-outline::before { + content: "\F0BD7"; +} + +.mdi-tooth::before { + content: "\F08C3"; +} + +.mdi-tooth-outline::before { + content: "\F0529"; +} + +.mdi-toothbrush::before { + content: "\F1129"; +} + +.mdi-toothbrush-electric::before { + content: "\F112C"; +} + +.mdi-toothbrush-paste::before { + content: "\F112A"; +} + +.mdi-torch::before { + content: "\F1606"; +} + +.mdi-tortoise::before { + content: "\F0D3B"; +} + +.mdi-toslink::before { + content: "\F12B8"; +} + +.mdi-tournament::before { + content: "\F09AE"; +} + +.mdi-tow-truck::before { + content: "\F083C"; +} + +.mdi-tower-beach::before { + content: "\F0681"; +} + +.mdi-tower-fire::before { + content: "\F0682"; +} + +.mdi-toy-brick::before { + content: "\F1288"; +} + +.mdi-toy-brick-marker::before { + content: "\F1289"; +} + +.mdi-toy-brick-marker-outline::before { + content: "\F128A"; +} + +.mdi-toy-brick-minus::before { + content: "\F128B"; +} + +.mdi-toy-brick-minus-outline::before { + content: "\F128C"; +} + +.mdi-toy-brick-outline::before { + content: "\F128D"; +} + +.mdi-toy-brick-plus::before { + content: "\F128E"; +} + +.mdi-toy-brick-plus-outline::before { + content: "\F128F"; +} + +.mdi-toy-brick-remove::before { + content: "\F1290"; +} + +.mdi-toy-brick-remove-outline::before { + content: "\F1291"; +} + +.mdi-toy-brick-search::before { + content: "\F1292"; +} + +.mdi-toy-brick-search-outline::before { + content: "\F1293"; +} + +.mdi-track-light::before { + content: "\F0914"; +} + +.mdi-trackpad::before { + content: "\F07F8"; +} + +.mdi-trackpad-lock::before { + content: "\F0933"; +} + +.mdi-tractor::before { + content: "\F0892"; +} + +.mdi-tractor-variant::before { + content: "\F14C4"; +} + +.mdi-trademark::before { + content: "\F0A78"; +} + +.mdi-traffic-cone::before { + content: "\F137C"; +} + +.mdi-traffic-light::before { + content: "\F052B"; +} + +.mdi-train::before { + content: "\F052C"; +} + +.mdi-train-car::before { + content: "\F0BD8"; +} + +.mdi-train-variant::before { + content: "\F08C4"; +} + +.mdi-tram::before { + content: "\F052D"; +} + +.mdi-tram-side::before { + content: "\F0FE7"; +} + +.mdi-transcribe::before { + content: "\F052E"; +} + +.mdi-transcribe-close::before { + content: "\F052F"; +} + +.mdi-transfer::before { + content: "\F1065"; +} + +.mdi-transfer-down::before { + content: "\F0DA1"; +} + +.mdi-transfer-left::before { + content: "\F0DA2"; +} + +.mdi-transfer-right::before { + content: "\F0530"; +} + +.mdi-transfer-up::before { + content: "\F0DA3"; +} + +.mdi-transit-connection::before { + content: "\F0D3C"; +} + +.mdi-transit-connection-horizontal::before { + content: "\F1546"; +} + +.mdi-transit-connection-variant::before { + content: "\F0D3D"; +} + +.mdi-transit-detour::before { + content: "\F0F8B"; +} + +.mdi-transit-skip::before { + content: "\F1515"; +} + +.mdi-transit-transfer::before { + content: "\F06AE"; +} + +.mdi-transition::before { + content: "\F0915"; +} + +.mdi-transition-masked::before { + content: "\F0916"; +} + +.mdi-translate::before { + content: "\F05CA"; +} + +.mdi-translate-off::before { + content: "\F0E06"; +} + +.mdi-transmission-tower::before { + content: "\F0D3E"; +} + +.mdi-trash-can::before { + content: "\F0A79"; +} + +.mdi-trash-can-outline::before { + content: "\F0A7A"; +} + +.mdi-tray::before { + content: "\F1294"; +} + +.mdi-tray-alert::before { + content: "\F1295"; +} + +.mdi-tray-full::before { + content: "\F1296"; +} + +.mdi-tray-minus::before { + content: "\F1297"; +} + +.mdi-tray-plus::before { + content: "\F1298"; +} + +.mdi-tray-remove::before { + content: "\F1299"; +} + +.mdi-treasure-chest::before { + content: "\F0726"; +} + +.mdi-tree::before { + content: "\F0531"; +} + +.mdi-tree-outline::before { + content: "\F0E69"; +} + +.mdi-trello::before { + content: "\F0532"; +} + +.mdi-trending-down::before { + content: "\F0533"; +} + +.mdi-trending-neutral::before { + content: "\F0534"; +} + +.mdi-trending-up::before { + content: "\F0535"; +} + +.mdi-triangle::before { + content: "\F0536"; +} + +.mdi-triangle-outline::before { + content: "\F0537"; +} + +.mdi-triangle-wave::before { + content: "\F147C"; +} + +.mdi-triforce::before { + content: "\F0BD9"; +} + +.mdi-trophy::before { + content: "\F0538"; +} + +.mdi-trophy-award::before { + content: "\F0539"; +} + +.mdi-trophy-broken::before { + content: "\F0DA4"; +} + +.mdi-trophy-outline::before { + content: "\F053A"; +} + +.mdi-trophy-variant::before { + content: "\F053B"; +} + +.mdi-trophy-variant-outline::before { + content: "\F053C"; +} + +.mdi-truck::before { + content: "\F053D"; +} + +.mdi-truck-check::before { + content: "\F0CD4"; +} + +.mdi-truck-check-outline::before { + content: "\F129A"; +} + +.mdi-truck-delivery::before { + content: "\F053E"; +} + +.mdi-truck-delivery-outline::before { + content: "\F129B"; +} + +.mdi-truck-fast::before { + content: "\F0788"; +} + +.mdi-truck-fast-outline::before { + content: "\F129C"; +} + +.mdi-truck-outline::before { + content: "\F129D"; +} + +.mdi-truck-trailer::before { + content: "\F0727"; +} + +.mdi-trumpet::before { + content: "\F1096"; +} + +.mdi-tshirt-crew::before { + content: "\F0A7B"; +} + +.mdi-tshirt-crew-outline::before { + content: "\F053F"; +} + +.mdi-tshirt-v::before { + content: "\F0A7C"; +} + +.mdi-tshirt-v-outline::before { + content: "\F0540"; +} + +.mdi-tumble-dryer::before { + content: "\F0917"; +} + +.mdi-tumble-dryer-alert::before { + content: "\F11BA"; +} + +.mdi-tumble-dryer-off::before { + content: "\F11BB"; +} + +.mdi-tune::before { + content: "\F062E"; +} + +.mdi-tune-variant::before { + content: "\F1542"; +} + +.mdi-tune-vertical::before { + content: "\F066A"; +} + +.mdi-tune-vertical-variant::before { + content: "\F1543"; +} + +.mdi-turnstile::before { + content: "\F0CD5"; +} + +.mdi-turnstile-outline::before { + content: "\F0CD6"; +} + +.mdi-turtle::before { + content: "\F0CD7"; +} + +.mdi-twitch::before { + content: "\F0543"; +} + +.mdi-twitter::before { + content: "\F0544"; +} + +.mdi-twitter-retweet::before { + content: "\F0547"; +} + +.mdi-two-factor-authentication::before { + content: "\F09AF"; +} + +.mdi-typewriter::before { + content: "\F0F2D"; +} + +.mdi-ubisoft::before { + content: "\F0BDA"; +} + +.mdi-ubuntu::before { + content: "\F0548"; +} + +.mdi-ufo::before { + content: "\F10C4"; +} + +.mdi-ufo-outline::before { + content: "\F10C5"; +} + +.mdi-ultra-high-definition::before { + content: "\F07F9"; +} + +.mdi-umbraco::before { + content: "\F0549"; +} + +.mdi-umbrella::before { + content: "\F054A"; +} + +.mdi-umbrella-closed::before { + content: "\F09B0"; +} + +.mdi-umbrella-closed-outline::before { + content: "\F13E2"; +} + +.mdi-umbrella-closed-variant::before { + content: "\F13E1"; +} + +.mdi-umbrella-outline::before { + content: "\F054B"; +} + +.mdi-undo::before { + content: "\F054C"; +} + +.mdi-undo-variant::before { + content: "\F054D"; +} + +.mdi-unfold-less-horizontal::before { + content: "\F054E"; +} + +.mdi-unfold-less-vertical::before { + content: "\F0760"; +} + +.mdi-unfold-more-horizontal::before { + content: "\F054F"; +} + +.mdi-unfold-more-vertical::before { + content: "\F0761"; +} + +.mdi-ungroup::before { + content: "\F0550"; +} + +.mdi-unicode::before { + content: "\F0ED0"; +} + +.mdi-unicorn::before { + content: "\F15C2"; +} + +.mdi-unicorn-variant::before { + content: "\F15C3"; +} + +.mdi-unicycle::before { + content: "\F15E5"; +} + +.mdi-unity::before { + content: "\F06AF"; +} + +.mdi-unreal::before { + content: "\F09B1"; +} + +.mdi-untappd::before { + content: "\F0551"; +} + +.mdi-update::before { + content: "\F06B0"; +} + +.mdi-upload::before { + content: "\F0552"; +} + +.mdi-upload-lock::before { + content: "\F1373"; +} + +.mdi-upload-lock-outline::before { + content: "\F1374"; +} + +.mdi-upload-multiple::before { + content: "\F083D"; +} + +.mdi-upload-network::before { + content: "\F06F6"; +} + +.mdi-upload-network-outline::before { + content: "\F0CD8"; +} + +.mdi-upload-off::before { + content: "\F10C6"; +} + +.mdi-upload-off-outline::before { + content: "\F10C7"; +} + +.mdi-upload-outline::before { + content: "\F0E07"; +} + +.mdi-usb::before { + content: "\F0553"; +} + +.mdi-usb-flash-drive::before { + content: "\F129E"; +} + +.mdi-usb-flash-drive-outline::before { + content: "\F129F"; +} + +.mdi-usb-port::before { + content: "\F11F0"; +} + +.mdi-valve::before { + content: "\F1066"; +} + +.mdi-valve-closed::before { + content: "\F1067"; +} + +.mdi-valve-open::before { + content: "\F1068"; +} + +.mdi-van-passenger::before { + content: "\F07FA"; +} + +.mdi-van-utility::before { + content: "\F07FB"; +} + +.mdi-vanish::before { + content: "\F07FC"; +} + +.mdi-vanish-quarter::before { + content: "\F1554"; +} + +.mdi-vanity-light::before { + content: "\F11E1"; +} + +.mdi-variable::before { + content: "\F0AE7"; +} + +.mdi-variable-box::before { + content: "\F1111"; +} + +.mdi-vector-arrange-above::before { + content: "\F0554"; +} + +.mdi-vector-arrange-below::before { + content: "\F0555"; +} + +.mdi-vector-bezier::before { + content: "\F0AE8"; +} + +.mdi-vector-circle::before { + content: "\F0556"; +} + +.mdi-vector-circle-variant::before { + content: "\F0557"; +} + +.mdi-vector-combine::before { + content: "\F0558"; +} + +.mdi-vector-curve::before { + content: "\F0559"; +} + +.mdi-vector-difference::before { + content: "\F055A"; +} + +.mdi-vector-difference-ab::before { + content: "\F055B"; +} + +.mdi-vector-difference-ba::before { + content: "\F055C"; +} + +.mdi-vector-ellipse::before { + content: "\F0893"; +} + +.mdi-vector-intersection::before { + content: "\F055D"; +} + +.mdi-vector-line::before { + content: "\F055E"; +} + +.mdi-vector-link::before { + content: "\F0FE8"; +} + +.mdi-vector-point::before { + content: "\F055F"; +} + +.mdi-vector-polygon::before { + content: "\F0560"; +} + +.mdi-vector-polyline::before { + content: "\F0561"; +} + +.mdi-vector-polyline-edit::before { + content: "\F1225"; +} + +.mdi-vector-polyline-minus::before { + content: "\F1226"; +} + +.mdi-vector-polyline-plus::before { + content: "\F1227"; +} + +.mdi-vector-polyline-remove::before { + content: "\F1228"; +} + +.mdi-vector-radius::before { + content: "\F074A"; +} + +.mdi-vector-rectangle::before { + content: "\F05C6"; +} + +.mdi-vector-selection::before { + content: "\F0562"; +} + +.mdi-vector-square::before { + content: "\F0001"; +} + +.mdi-vector-triangle::before { + content: "\F0563"; +} + +.mdi-vector-union::before { + content: "\F0564"; +} + +.mdi-vhs::before { + content: "\F0A1B"; +} + +.mdi-vibrate::before { + content: "\F0566"; +} + +.mdi-vibrate-off::before { + content: "\F0CD9"; +} + +.mdi-video::before { + content: "\F0567"; +} + +.mdi-video-3d::before { + content: "\F07FD"; +} + +.mdi-video-3d-off::before { + content: "\F13D9"; +} + +.mdi-video-3d-variant::before { + content: "\F0ED1"; +} + +.mdi-video-4k-box::before { + content: "\F083E"; +} + +.mdi-video-account::before { + content: "\F0919"; +} + +.mdi-video-box::before { + content: "\F00FD"; +} + +.mdi-video-box-off::before { + content: "\F00FE"; +} + +.mdi-video-check::before { + content: "\F1069"; +} + +.mdi-video-check-outline::before { + content: "\F106A"; +} + +.mdi-video-high-definition::before { + content: "\F152E"; +} + +.mdi-video-image::before { + content: "\F091A"; +} + +.mdi-video-input-antenna::before { + content: "\F083F"; +} + +.mdi-video-input-component::before { + content: "\F0840"; +} + +.mdi-video-input-hdmi::before { + content: "\F0841"; +} + +.mdi-video-input-scart::before { + content: "\F0F8C"; +} + +.mdi-video-input-svideo::before { + content: "\F0842"; +} + +.mdi-video-minus::before { + content: "\F09B2"; +} + +.mdi-video-minus-outline::before { + content: "\F02BA"; +} + +.mdi-video-off::before { + content: "\F0568"; +} + +.mdi-video-off-outline::before { + content: "\F0BDB"; +} + +.mdi-video-outline::before { + content: "\F0BDC"; +} + +.mdi-video-plus::before { + content: "\F09B3"; +} + +.mdi-video-plus-outline::before { + content: "\F01D3"; +} + +.mdi-video-stabilization::before { + content: "\F091B"; +} + +.mdi-video-switch::before { + content: "\F0569"; +} + +.mdi-video-switch-outline::before { + content: "\F0790"; +} + +.mdi-video-vintage::before { + content: "\F0A1C"; +} + +.mdi-video-wireless::before { + content: "\F0ED2"; +} + +.mdi-video-wireless-outline::before { + content: "\F0ED3"; +} + +.mdi-view-agenda::before { + content: "\F056A"; +} + +.mdi-view-agenda-outline::before { + content: "\F11D8"; +} + +.mdi-view-array::before { + content: "\F056B"; +} + +.mdi-view-array-outline::before { + content: "\F1485"; +} + +.mdi-view-carousel::before { + content: "\F056C"; +} + +.mdi-view-carousel-outline::before { + content: "\F1486"; +} + +.mdi-view-column::before { + content: "\F056D"; +} + +.mdi-view-column-outline::before { + content: "\F1487"; +} + +.mdi-view-comfy::before { + content: "\F0E6A"; +} + +.mdi-view-comfy-outline::before { + content: "\F1488"; +} + +.mdi-view-compact::before { + content: "\F0E6B"; +} + +.mdi-view-compact-outline::before { + content: "\F0E6C"; +} + +.mdi-view-dashboard::before { + content: "\F056E"; +} + +.mdi-view-dashboard-outline::before { + content: "\F0A1D"; +} + +.mdi-view-dashboard-variant::before { + content: "\F0843"; +} + +.mdi-view-dashboard-variant-outline::before { + content: "\F1489"; +} + +.mdi-view-day::before { + content: "\F056F"; +} + +.mdi-view-day-outline::before { + content: "\F148A"; +} + +.mdi-view-grid::before { + content: "\F0570"; +} + +.mdi-view-grid-outline::before { + content: "\F11D9"; +} + +.mdi-view-grid-plus::before { + content: "\F0F8D"; +} + +.mdi-view-grid-plus-outline::before { + content: "\F11DA"; +} + +.mdi-view-headline::before { + content: "\F0571"; +} + +.mdi-view-list::before { + content: "\F0572"; +} + +.mdi-view-list-outline::before { + content: "\F148B"; +} + +.mdi-view-module::before { + content: "\F0573"; +} + +.mdi-view-module-outline::before { + content: "\F148C"; +} + +.mdi-view-parallel::before { + content: "\F0728"; +} + +.mdi-view-parallel-outline::before { + content: "\F148D"; +} + +.mdi-view-quilt::before { + content: "\F0574"; +} + +.mdi-view-quilt-outline::before { + content: "\F148E"; +} + +.mdi-view-sequential::before { + content: "\F0729"; +} + +.mdi-view-sequential-outline::before { + content: "\F148F"; +} + +.mdi-view-split-horizontal::before { + content: "\F0BCB"; +} + +.mdi-view-split-vertical::before { + content: "\F0BCC"; +} + +.mdi-view-stream::before { + content: "\F0575"; +} + +.mdi-view-stream-outline::before { + content: "\F1490"; +} + +.mdi-view-week::before { + content: "\F0576"; +} + +.mdi-view-week-outline::before { + content: "\F1491"; +} + +.mdi-vimeo::before { + content: "\F0577"; +} + +.mdi-violin::before { + content: "\F060F"; +} + +.mdi-virtual-reality::before { + content: "\F0894"; +} + +.mdi-virus::before { + content: "\F13B6"; +} + +.mdi-virus-outline::before { + content: "\F13B7"; +} + +.mdi-vk::before { + content: "\F0579"; +} + +.mdi-vlc::before { + content: "\F057C"; +} + +.mdi-voice-off::before { + content: "\F0ED4"; +} + +.mdi-voicemail::before { + content: "\F057D"; +} + +.mdi-volleyball::before { + content: "\F09B4"; +} + +.mdi-volume-high::before { + content: "\F057E"; +} + +.mdi-volume-low::before { + content: "\F057F"; +} + +.mdi-volume-medium::before { + content: "\F0580"; +} + +.mdi-volume-minus::before { + content: "\F075E"; +} + +.mdi-volume-mute::before { + content: "\F075F"; +} + +.mdi-volume-off::before { + content: "\F0581"; +} + +.mdi-volume-plus::before { + content: "\F075D"; +} + +.mdi-volume-source::before { + content: "\F1120"; +} + +.mdi-volume-variant-off::before { + content: "\F0E08"; +} + +.mdi-volume-vibrate::before { + content: "\F1121"; +} + +.mdi-vote::before { + content: "\F0A1F"; +} + +.mdi-vote-outline::before { + content: "\F0A20"; +} + +.mdi-vpn::before { + content: "\F0582"; +} + +.mdi-vuejs::before { + content: "\F0844"; +} + +.mdi-vuetify::before { + content: "\F0E6D"; +} + +.mdi-walk::before { + content: "\F0583"; +} + +.mdi-wall::before { + content: "\F07FE"; +} + +.mdi-wall-sconce::before { + content: "\F091C"; +} + +.mdi-wall-sconce-flat::before { + content: "\F091D"; +} + +.mdi-wall-sconce-flat-variant::before { + content: "\F041C"; +} + +.mdi-wall-sconce-round::before { + content: "\F0748"; +} + +.mdi-wall-sconce-round-variant::before { + content: "\F091E"; +} + +.mdi-wallet::before { + content: "\F0584"; +} + +.mdi-wallet-giftcard::before { + content: "\F0585"; +} + +.mdi-wallet-membership::before { + content: "\F0586"; +} + +.mdi-wallet-outline::before { + content: "\F0BDD"; +} + +.mdi-wallet-plus::before { + content: "\F0F8E"; +} + +.mdi-wallet-plus-outline::before { + content: "\F0F8F"; +} + +.mdi-wallet-travel::before { + content: "\F0587"; +} + +.mdi-wallpaper::before { + content: "\F0E09"; +} + +.mdi-wan::before { + content: "\F0588"; +} + +.mdi-wardrobe::before { + content: "\F0F90"; +} + +.mdi-wardrobe-outline::before { + content: "\F0F91"; +} + +.mdi-warehouse::before { + content: "\F0F81"; +} + +.mdi-washing-machine::before { + content: "\F072A"; +} + +.mdi-washing-machine-alert::before { + content: "\F11BC"; +} + +.mdi-washing-machine-off::before { + content: "\F11BD"; +} + +.mdi-watch::before { + content: "\F0589"; +} + +.mdi-watch-export::before { + content: "\F058A"; +} + +.mdi-watch-export-variant::before { + content: "\F0895"; +} + +.mdi-watch-import::before { + content: "\F058B"; +} + +.mdi-watch-import-variant::before { + content: "\F0896"; +} + +.mdi-watch-variant::before { + content: "\F0897"; +} + +.mdi-watch-vibrate::before { + content: "\F06B1"; +} + +.mdi-watch-vibrate-off::before { + content: "\F0CDA"; +} + +.mdi-water::before { + content: "\F058C"; +} + +.mdi-water-alert::before { + content: "\F1502"; +} + +.mdi-water-alert-outline::before { + content: "\F1503"; +} + +.mdi-water-boiler::before { + content: "\F0F92"; +} + +.mdi-water-boiler-alert::before { + content: "\F11B3"; +} + +.mdi-water-boiler-off::before { + content: "\F11B4"; +} + +.mdi-water-check::before { + content: "\F1504"; +} + +.mdi-water-check-outline::before { + content: "\F1505"; +} + +.mdi-water-minus::before { + content: "\F1506"; +} + +.mdi-water-minus-outline::before { + content: "\F1507"; +} + +.mdi-water-off::before { + content: "\F058D"; +} + +.mdi-water-off-outline::before { + content: "\F1508"; +} + +.mdi-water-outline::before { + content: "\F0E0A"; +} + +.mdi-water-percent::before { + content: "\F058E"; +} + +.mdi-water-percent-alert::before { + content: "\F1509"; +} + +.mdi-water-plus::before { + content: "\F150A"; +} + +.mdi-water-plus-outline::before { + content: "\F150B"; +} + +.mdi-water-polo::before { + content: "\F12A0"; +} + +.mdi-water-pump::before { + content: "\F058F"; +} + +.mdi-water-pump-off::before { + content: "\F0F93"; +} + +.mdi-water-remove::before { + content: "\F150C"; +} + +.mdi-water-remove-outline::before { + content: "\F150D"; +} + +.mdi-water-well::before { + content: "\F106B"; +} + +.mdi-water-well-outline::before { + content: "\F106C"; +} + +.mdi-watering-can::before { + content: "\F1481"; +} + +.mdi-watering-can-outline::before { + content: "\F1482"; +} + +.mdi-watermark::before { + content: "\F0612"; +} + +.mdi-wave::before { + content: "\F0F2E"; +} + +.mdi-waveform::before { + content: "\F147D"; +} + +.mdi-waves::before { + content: "\F078D"; +} + +.mdi-waze::before { + content: "\F0BDE"; +} + +.mdi-weather-cloudy::before { + content: "\F0590"; +} + +.mdi-weather-cloudy-alert::before { + content: "\F0F2F"; +} + +.mdi-weather-cloudy-arrow-right::before { + content: "\F0E6E"; +} + +.mdi-weather-fog::before { + content: "\F0591"; +} + +.mdi-weather-hail::before { + content: "\F0592"; +} + +.mdi-weather-hazy::before { + content: "\F0F30"; +} + +.mdi-weather-hurricane::before { + content: "\F0898"; +} + +.mdi-weather-lightning::before { + content: "\F0593"; +} + +.mdi-weather-lightning-rainy::before { + content: "\F067E"; +} + +.mdi-weather-night::before { + content: "\F0594"; +} + +.mdi-weather-night-partly-cloudy::before { + content: "\F0F31"; +} + +.mdi-weather-partly-cloudy::before { + content: "\F0595"; +} + +.mdi-weather-partly-lightning::before { + content: "\F0F32"; +} + +.mdi-weather-partly-rainy::before { + content: "\F0F33"; +} + +.mdi-weather-partly-snowy::before { + content: "\F0F34"; +} + +.mdi-weather-partly-snowy-rainy::before { + content: "\F0F35"; +} + +.mdi-weather-pouring::before { + content: "\F0596"; +} + +.mdi-weather-rainy::before { + content: "\F0597"; +} + +.mdi-weather-snowy::before { + content: "\F0598"; +} + +.mdi-weather-snowy-heavy::before { + content: "\F0F36"; +} + +.mdi-weather-snowy-rainy::before { + content: "\F067F"; +} + +.mdi-weather-sunny::before { + content: "\F0599"; +} + +.mdi-weather-sunny-alert::before { + content: "\F0F37"; +} + +.mdi-weather-sunny-off::before { + content: "\F14E4"; +} + +.mdi-weather-sunset::before { + content: "\F059A"; +} + +.mdi-weather-sunset-down::before { + content: "\F059B"; +} + +.mdi-weather-sunset-up::before { + content: "\F059C"; +} + +.mdi-weather-tornado::before { + content: "\F0F38"; +} + +.mdi-weather-windy::before { + content: "\F059D"; +} + +.mdi-weather-windy-variant::before { + content: "\F059E"; +} + +.mdi-web::before { + content: "\F059F"; +} + +.mdi-web-box::before { + content: "\F0F94"; +} + +.mdi-web-clock::before { + content: "\F124A"; +} + +.mdi-webcam::before { + content: "\F05A0"; +} + +.mdi-webhook::before { + content: "\F062F"; +} + +.mdi-webpack::before { + content: "\F072B"; +} + +.mdi-webrtc::before { + content: "\F1248"; +} + +.mdi-wechat::before { + content: "\F0611"; +} + +.mdi-weight::before { + content: "\F05A1"; +} + +.mdi-weight-gram::before { + content: "\F0D3F"; +} + +.mdi-weight-kilogram::before { + content: "\F05A2"; +} + +.mdi-weight-lifter::before { + content: "\F115D"; +} + +.mdi-weight-pound::before { + content: "\F09B5"; +} + +.mdi-whatsapp::before { + content: "\F05A3"; +} + +.mdi-wheel-barrow::before { + content: "\F14F2"; +} + +.mdi-wheelchair-accessibility::before { + content: "\F05A4"; +} + +.mdi-whistle::before { + content: "\F09B6"; +} + +.mdi-whistle-outline::before { + content: "\F12BC"; +} + +.mdi-white-balance-auto::before { + content: "\F05A5"; +} + +.mdi-white-balance-incandescent::before { + content: "\F05A6"; +} + +.mdi-white-balance-iridescent::before { + content: "\F05A7"; +} + +.mdi-white-balance-sunny::before { + content: "\F05A8"; +} + +.mdi-widgets::before { + content: "\F072C"; +} + +.mdi-widgets-outline::before { + content: "\F1355"; +} + +.mdi-wifi::before { + content: "\F05A9"; +} + +.mdi-wifi-alert::before { + content: "\F16B5"; +} + +.mdi-wifi-arrow-down::before { + content: "\F16B6"; +} + +.mdi-wifi-arrow-left::before { + content: "\F16B7"; +} + +.mdi-wifi-arrow-left-right::before { + content: "\F16B8"; +} + +.mdi-wifi-arrow-right::before { + content: "\F16B9"; +} + +.mdi-wifi-arrow-up::before { + content: "\F16BA"; +} + +.mdi-wifi-arrow-up-down::before { + content: "\F16BB"; +} + +.mdi-wifi-cancel::before { + content: "\F16BC"; +} + +.mdi-wifi-check::before { + content: "\F16BD"; +} + +.mdi-wifi-cog::before { + content: "\F16BE"; +} + +.mdi-wifi-lock::before { + content: "\F16BF"; +} + +.mdi-wifi-lock-open::before { + content: "\F16C0"; +} + +.mdi-wifi-marker::before { + content: "\F16C1"; +} + +.mdi-wifi-minus::before { + content: "\F16C2"; +} + +.mdi-wifi-off::before { + content: "\F05AA"; +} + +.mdi-wifi-plus::before { + content: "\F16C3"; +} + +.mdi-wifi-refresh::before { + content: "\F16C4"; +} + +.mdi-wifi-remove::before { + content: "\F16C5"; +} + +.mdi-wifi-settings::before { + content: "\F16C6"; +} + +.mdi-wifi-star::before { + content: "\F0E0B"; +} + +.mdi-wifi-strength-1::before { + content: "\F091F"; +} + +.mdi-wifi-strength-1-alert::before { + content: "\F0920"; +} + +.mdi-wifi-strength-1-lock::before { + content: "\F0921"; +} + +.mdi-wifi-strength-1-lock-open::before { + content: "\F16CB"; +} + +.mdi-wifi-strength-2::before { + content: "\F0922"; +} + +.mdi-wifi-strength-2-alert::before { + content: "\F0923"; +} + +.mdi-wifi-strength-2-lock::before { + content: "\F0924"; +} + +.mdi-wifi-strength-2-lock-open::before { + content: "\F16CC"; +} + +.mdi-wifi-strength-3::before { + content: "\F0925"; +} + +.mdi-wifi-strength-3-alert::before { + content: "\F0926"; +} + +.mdi-wifi-strength-3-lock::before { + content: "\F0927"; +} + +.mdi-wifi-strength-3-lock-open::before { + content: "\F16CD"; +} + +.mdi-wifi-strength-4::before { + content: "\F0928"; +} + +.mdi-wifi-strength-4-alert::before { + content: "\F0929"; +} + +.mdi-wifi-strength-4-lock::before { + content: "\F092A"; +} + +.mdi-wifi-strength-4-lock-open::before { + content: "\F16CE"; +} + +.mdi-wifi-strength-alert-outline::before { + content: "\F092B"; +} + +.mdi-wifi-strength-lock-open-outline::before { + content: "\F16CF"; +} + +.mdi-wifi-strength-lock-outline::before { + content: "\F092C"; +} + +.mdi-wifi-strength-off::before { + content: "\F092D"; +} + +.mdi-wifi-strength-off-outline::before { + content: "\F092E"; +} + +.mdi-wifi-strength-outline::before { + content: "\F092F"; +} + +.mdi-wifi-sync::before { + content: "\F16C7"; +} + +.mdi-wikipedia::before { + content: "\F05AC"; +} + +.mdi-wind-turbine::before { + content: "\F0DA5"; +} + +.mdi-window-close::before { + content: "\F05AD"; +} + +.mdi-window-closed::before { + content: "\F05AE"; +} + +.mdi-window-closed-variant::before { + content: "\F11DB"; +} + +.mdi-window-maximize::before { + content: "\F05AF"; +} + +.mdi-window-minimize::before { + content: "\F05B0"; +} + +.mdi-window-open::before { + content: "\F05B1"; +} + +.mdi-window-open-variant::before { + content: "\F11DC"; +} + +.mdi-window-restore::before { + content: "\F05B2"; +} + +.mdi-window-shutter::before { + content: "\F111C"; +} + +.mdi-window-shutter-alert::before { + content: "\F111D"; +} + +.mdi-window-shutter-open::before { + content: "\F111E"; +} + +.mdi-windsock::before { + content: "\F15FA"; +} + +.mdi-wiper::before { + content: "\F0AE9"; +} + +.mdi-wiper-wash::before { + content: "\F0DA6"; +} + +.mdi-wizard-hat::before { + content: "\F1477"; +} + +.mdi-wordpress::before { + content: "\F05B4"; +} + +.mdi-wrap::before { + content: "\F05B6"; +} + +.mdi-wrap-disabled::before { + content: "\F0BDF"; +} + +.mdi-wrench::before { + content: "\F05B7"; +} + +.mdi-wrench-outline::before { + content: "\F0BE0"; +} + +.mdi-xamarin::before { + content: "\F0845"; +} + +.mdi-xamarin-outline::before { + content: "\F0846"; +} + +.mdi-xing::before { + content: "\F05BE"; +} + +.mdi-xml::before { + content: "\F05C0"; +} + +.mdi-xmpp::before { + content: "\F07FF"; +} + +.mdi-y-combinator::before { + content: "\F0624"; +} + +.mdi-yahoo::before { + content: "\F0B4F"; +} + +.mdi-yeast::before { + content: "\F05C1"; +} + +.mdi-yin-yang::before { + content: "\F0680"; +} + +.mdi-yoga::before { + content: "\F117C"; +} + +.mdi-youtube::before { + content: "\F05C3"; +} + +.mdi-youtube-gaming::before { + content: "\F0848"; +} + +.mdi-youtube-studio::before { + content: "\F0847"; +} + +.mdi-youtube-subscription::before { + content: "\F0D40"; +} + +.mdi-youtube-tv::before { + content: "\F0448"; +} + +.mdi-yurt::before { + content: "\F1516"; +} + +.mdi-z-wave::before { + content: "\F0AEA"; +} + +.mdi-zend::before { + content: "\F0AEB"; +} + +.mdi-zigbee::before { + content: "\F0D41"; +} + +.mdi-zip-box::before { + content: "\F05C4"; +} + +.mdi-zip-box-outline::before { + content: "\F0FFA"; +} + +.mdi-zip-disk::before { + content: "\F0A23"; +} + +.mdi-zodiac-aquarius::before { + content: "\F0A7D"; +} + +.mdi-zodiac-aries::before { + content: "\F0A7E"; +} + +.mdi-zodiac-cancer::before { + content: "\F0A7F"; +} + +.mdi-zodiac-capricorn::before { + content: "\F0A80"; +} + +.mdi-zodiac-gemini::before { + content: "\F0A81"; +} + +.mdi-zodiac-leo::before { + content: "\F0A82"; +} + +.mdi-zodiac-libra::before { + content: "\F0A83"; +} + +.mdi-zodiac-pisces::before { + content: "\F0A84"; +} + +.mdi-zodiac-sagittarius::before { + content: "\F0A85"; +} + +.mdi-zodiac-scorpio::before { + content: "\F0A86"; +} + +.mdi-zodiac-taurus::before { + content: "\F0A87"; +} + +.mdi-zodiac-virgo::before { + content: "\F0A88"; +} + +.mdi-blank::before { + content: "\F68C"; + visibility: hidden; +} + +.mdi-18px.mdi-set, .mdi-18px.mdi:before { + font-size: 18px; +} + +.mdi-24px.mdi-set, .mdi-24px.mdi:before { + font-size: 24px; +} + +.mdi-36px.mdi-set, .mdi-36px.mdi:before { + font-size: 36px; +} + +.mdi-48px.mdi-set, .mdi-48px.mdi:before { + font-size: 48px; +} + +.mdi-dark:before { + color: rgba(0, 0, 0, 0.54); +} + +.mdi-dark.mdi-inactive:before { + color: rgba(0, 0, 0, 0.26); +} + +.mdi-light:before { + color: white; +} + +.mdi-light.mdi-inactive:before { + color: rgba(255, 255, 255, 0.3); +} + +.mdi-rotate-45 { + /* + // Not included in production + &.mdi-flip-h:before { + -webkit-transform: scaleX(-1) rotate(45deg); + transform: scaleX(-1) rotate(45deg); + filter: FlipH; + -ms-filter: "FlipH"; + } + &.mdi-flip-v:before { + -webkit-transform: scaleY(-1) rotate(45deg); + -ms-transform: rotate(45deg); + transform: scaleY(-1) rotate(45deg); + filter: FlipV; + -ms-filter: "FlipV"; + } + */ +} + +.mdi-rotate-45:before { + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); +} + +.mdi-rotate-90 { + /* + // Not included in production + &.mdi-flip-h:before { + -webkit-transform: scaleX(-1) rotate(90deg); + transform: scaleX(-1) rotate(90deg); + filter: FlipH; + -ms-filter: "FlipH"; + } + &.mdi-flip-v:before { + -webkit-transform: scaleY(-1) rotate(90deg); + -ms-transform: rotate(90deg); + transform: scaleY(-1) rotate(90deg); + filter: FlipV; + -ms-filter: "FlipV"; + } + */ +} + +.mdi-rotate-90:before { + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); +} + +.mdi-rotate-135 { + /* + // Not included in production + &.mdi-flip-h:before { + -webkit-transform: scaleX(-1) rotate(135deg); + transform: scaleX(-1) rotate(135deg); + filter: FlipH; + -ms-filter: "FlipH"; + } + &.mdi-flip-v:before { + -webkit-transform: scaleY(-1) rotate(135deg); + -ms-transform: rotate(135deg); + transform: scaleY(-1) rotate(135deg); + filter: FlipV; + -ms-filter: "FlipV"; + } + */ +} + +.mdi-rotate-135:before { + -webkit-transform: rotate(135deg); + -ms-transform: rotate(135deg); + transform: rotate(135deg); +} + +.mdi-rotate-180 { + /* + // Not included in production + &.mdi-flip-h:before { + -webkit-transform: scaleX(-1) rotate(180deg); + transform: scaleX(-1) rotate(180deg); + filter: FlipH; + -ms-filter: "FlipH"; + } + &.mdi-flip-v:before { + -webkit-transform: scaleY(-1) rotate(180deg); + -ms-transform: rotate(180deg); + transform: scaleY(-1) rotate(180deg); + filter: FlipV; + -ms-filter: "FlipV"; + } + */ +} + +.mdi-rotate-180:before { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.mdi-rotate-225 { + /* + // Not included in production + &.mdi-flip-h:before { + -webkit-transform: scaleX(-1) rotate(225deg); + transform: scaleX(-1) rotate(225deg); + filter: FlipH; + -ms-filter: "FlipH"; + } + &.mdi-flip-v:before { + -webkit-transform: scaleY(-1) rotate(225deg); + -ms-transform: rotate(225deg); + transform: scaleY(-1) rotate(225deg); + filter: FlipV; + -ms-filter: "FlipV"; + } + */ +} + +.mdi-rotate-225:before { + -webkit-transform: rotate(225deg); + -ms-transform: rotate(225deg); + transform: rotate(225deg); +} + +.mdi-rotate-270 { + /* + // Not included in production + &.mdi-flip-h:before { + -webkit-transform: scaleX(-1) rotate(270deg); + transform: scaleX(-1) rotate(270deg); + filter: FlipH; + -ms-filter: "FlipH"; + } + &.mdi-flip-v:before { + -webkit-transform: scaleY(-1) rotate(270deg); + -ms-transform: rotate(270deg); + transform: scaleY(-1) rotate(270deg); + filter: FlipV; + -ms-filter: "FlipV"; + } + */ +} + +.mdi-rotate-270:before { + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg); +} + +.mdi-rotate-315 { + /* + // Not included in production + &.mdi-flip-h:before { + -webkit-transform: scaleX(-1) rotate(315deg); + transform: scaleX(-1) rotate(315deg); + filter: FlipH; + -ms-filter: "FlipH"; + } + &.mdi-flip-v:before { + -webkit-transform: scaleY(-1) rotate(315deg); + -ms-transform: rotate(315deg); + transform: scaleY(-1) rotate(315deg); + filter: FlipV; + -ms-filter: "FlipV"; + } + */ +} + +.mdi-rotate-315:before { + -webkit-transform: rotate(315deg); + -ms-transform: rotate(315deg); + transform: rotate(315deg); +} + +.mdi-flip-h:before { + -webkit-transform: scaleX(-1); + transform: scaleX(-1); + filter: FlipH; + -ms-filter: "FlipH"; +} + +.mdi-flip-v:before { + -webkit-transform: scaleY(-1); + transform: scaleY(-1); + filter: FlipV; + -ms-filter: "FlipV"; +} + +.mdi-spin:before { + -webkit-animation: mdi-spin 2s infinite linear; + animation: mdi-spin 2s infinite linear; +} + +@-webkit-keyframes mdi-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + +@keyframes mdi-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + +/*# sourceMappingURL=materialdesignicons.css.map */ \ No newline at end of file diff --git a/netbox/project-static/materialdesignicons-5.4.55/css/materialdesignicons.css.map b/netbox/project-static/materialdesignicons-5.4.55/css/materialdesignicons.css.map new file mode 100644 index 0000000000..c67066589b --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/css/materialdesignicons.css.map @@ -0,0 +1,16 @@ +{ + "version": 3, + "file": "materialdesignicons.css", + "sources": [ + "../scss/materialdesignicons.scss", + "../scss/_variables.scss", + "../scss/_functions.scss", + "../scss/_path.scss", + "../scss/_core.scss", + "../scss/_icons.scss", + "../scss/_extras.scss", + "../scss/_animated.scss" + ], + "names": [], + "mappings": "AAAA,6BAA6B;AGA7B,UAAU;EACR,WAAW,EAAE,uBAAmB;EAChC,GAAG,EAAE,wDAAuE;EAC5E,GAAG,EAAE,+DAA8E,CAAC,2BAA2B,EAC7G,0DAAyE,CAAC,eAAe,EACzF,yDAAwE,CAAC,cAAc,EACvF,wDAAuE,CAAC,kBAAkB;EAC5F,WAAW,EAAE,MAAM;EACnB,UAAU,EAAE,MAAM;;;ACRpB,AAAA,IAAI,AAAA,OAAO;AACX,QAAQ,CAAgB;EACtB,OAAO,EAAE,YAAY;EACrB,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAwB,CAAC,uBAAmB;EACvE,SAAS,EAAE,OAAO;EAClB,cAAc,EAAE,IAAI;EACpB,WAAW,EAAE,OAAO;EACpB,sBAAsB,EAAE,WAAW;EACnC,uBAAuB,EAAE,SAAS;CACnC;;ACRG,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sCAAsC,AAAA,QAAQ,CAAV;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0CAA0C,AAAA,QAAQ,CAAd;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2CAA2C,AAAA,QAAQ,CAAf;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qCAAqC,AAAA,QAAQ,CAAT;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qCAAqC,AAAA,QAAQ,CAAT;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uCAAuC,AAAA,QAAQ,CAAX;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qCAAqC,AAAA,QAAQ,CAAT;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wCAAwC,AAAA,QAAQ,CAAZ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,OAAO,AAAA,QAAQ,CAAqB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qCAAqC,AAAA,QAAQ,CAAT;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sCAAsC,AAAA,QAAQ,CAAV;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sCAAsC,AAAA,QAAQ,CAAV;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2CAA2C,AAAA,QAAQ,CAAf;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4CAA4C,AAAA,QAAQ,CAAhB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qCAAqC,AAAA,QAAQ,CAAT;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qCAAqC,AAAA,QAAQ,CAAT;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uCAAuC,AAAA,QAAQ,CAAX;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qCAAqC,AAAA,QAAQ,CAAT;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,OAAO,AAAA,QAAQ,CAAqB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qCAAqC,AAAA,QAAQ,CAAT;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uCAAuC,AAAA,QAAQ,CAAX;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uCAAuC,AAAA,QAAQ,CAAX;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qCAAqC,AAAA,QAAQ,CAAT;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6CAA6C,AAAA,QAAQ,CAAjB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,OAAO,AAAA,QAAQ,CAAqB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4CAA4C,AAAA,QAAQ,CAAhB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+CAA+C,AAAA,QAAQ,CAAnB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4CAA4C,AAAA,QAAQ,CAAhB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2CAA2C,AAAA,QAAQ,CAAf;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0CAA0C,AAAA,QAAQ,CAAd;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6CAA6C,AAAA,QAAQ,CAAjB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8CAA8C,AAAA,QAAQ,CAAlB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uCAAuC,AAAA,QAAQ,CAAX;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wCAAwC,AAAA,QAAQ,CAAZ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,OAAO,AAAA,QAAQ,CAAqB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4CAA4C,AAAA,QAAQ,CAAhB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yCAAyC,AAAA,QAAQ,CAAb;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,OAAO,AAAA,QAAQ,CAAqB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wCAAwC,AAAA,QAAQ,CAAZ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qCAAqC,AAAA,QAAQ,CAAT;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yCAAyC,AAAA,QAAQ,CAAb;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wCAAwC,AAAA,QAAQ,CAAZ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qCAAqC,AAAA,QAAQ,CAAT;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sCAAsC,AAAA,QAAQ,CAAV;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qCAAqC,AAAA,QAAQ,CAAT;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yCAAyC,AAAA,QAAQ,CAAb;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sCAAsC,AAAA,QAAQ,CAAV;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0CAA0C,AAAA,QAAQ,CAAd;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yCAAyC,AAAA,QAAQ,CAAb;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wCAAwC,AAAA,QAAQ,CAAZ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qCAAqC,AAAA,QAAQ,CAAT;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yCAAyC,AAAA,QAAQ,CAAb;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wCAAwC,AAAA,QAAQ,CAAZ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,OAAO,AAAA,QAAQ,CAAqB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wCAAwC,AAAA,QAAQ,CAAZ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yCAAyC,AAAA,QAAQ,CAAb;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iCAAiC,AAAA,QAAQ,CAAL;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kCAAkC,AAAA,QAAQ,CAAN;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mCAAmC,AAAA,QAAQ,CAAP;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,2BAA2B,AAAA,QAAQ,CAAC;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,OAAO,AAAA,QAAQ,CAAqB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,4BAA4B,AAAA,QAAQ,CAAA;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,6BAA6B,AAAA,QAAQ,CAAD;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gCAAgC,AAAA,QAAQ,CAAJ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oCAAoC,AAAA,QAAQ,CAAR;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,+BAA+B,AAAA,QAAQ,CAAH;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,sBAAsB,AAAA,QAAQ,CAAM;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,8BAA8B,AAAA,QAAQ,CAAF;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,0BAA0B,AAAA,QAAQ,CAAE;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,gBAAgB,AAAA,QAAQ,CAAY;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,wBAAwB,AAAA,QAAQ,CAAI;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,cAAc,AAAA,QAAQ,CAAc;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,QAAQ,AAAA,QAAQ,CAAoB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,UAAU,AAAA,QAAQ,CAAkB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,yBAAyB,AAAA,QAAQ,CAAG;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,SAAS,AAAA,QAAQ,CAAmB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,WAAW,AAAA,QAAQ,CAAiB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,YAAY,AAAA,QAAQ,CAAgB;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,aAAa,AAAA,QAAQ,CAAe;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,oBAAoB,AAAA,QAAQ,CAAQ;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,qBAAqB,AAAA,QAAQ,CAAO;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,eAAe,AAAA,QAAQ,CAAa;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,uBAAuB,AAAA,QAAQ,CAAK;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,mBAAmB,AAAA,QAAQ,CAAS;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,kBAAkB,AAAA,QAAQ,CAAU;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAFD,AAAA,iBAAiB,AAAA,QAAQ,CAAW;EAChC,OAAO,EHAC,QAAmC;CGC9C;;AAGL,AAAA,UAAU,AAAA,QAAQ,CAAgB;EAC9B,OAAO,EAAE,OAAO;EAChB,UAAU,EAAE,MAAM;CACrB;;ACPG,AACI,SADK,AACJ,QAAQ,EADb,SAAS,AAEJ,IAAI,AAAA,OAAO,CAAgB;EACxB,SAAS,EAAE,IAAe;CAC7B;;AAJL,AACI,SADK,AACJ,QAAQ,EADb,SAAS,AAEJ,IAAI,AAAA,OAAO,CAAgB;EACxB,SAAS,EAAE,IAAe;CAC7B;;AAJL,AACI,SADK,AACJ,QAAQ,EADb,SAAS,AAEJ,IAAI,AAAA,OAAO,CAAgB;EACxB,SAAS,EAAE,IAAe;CAC7B;;AAJL,AACI,SADK,AACJ,QAAQ,EADb,SAAS,AAEJ,IAAI,AAAA,OAAO,CAAgB;EACxB,SAAS,EAAE,IAAe;CAC7B;;AAIT,AACI,SADK,AACJ,OAAO,CAAC;EACL,KAAK,EAAE,mBAAmB;CAC7B;;AAHL,AAII,SAJK,AAIJ,aAAa,AAAA,OAAO,CAAgB;EACjC,KAAK,EAAE,mBAAmB;CAC7B;;AAEL,AACI,UADM,AACL,OAAO,CAAC;EACL,KAAK,EAAE,KAAsB;CAChC;;AAHL,AAII,UAJM,AAIL,aAAa,AAAA,OAAO,CAAgB;EACjC,KAAK,EAAE,wBAAwB;CAClC;;AAKD,AAAA,cAAc,CAA2B;EAMrC;;;;;;;;;;;;;;;UAeE;CACL;;AAtBD,AACI,cADU,AACT,OAAO,CAAC;EACL,iBAAiB,EAAE,aAA4B;EAC/C,aAAa,EAAE,aAA4B;EAC3C,SAAS,EAAE,aAA4B;CAC1C;;AALL,AAAA,cAAc,CAA2B;EAMrC;;;;;;;;;;;;;;;UAeE;CACL;;AAtBD,AACI,cADU,AACT,OAAO,CAAC;EACL,iBAAiB,EAAE,aAA4B;EAC/C,aAAa,EAAE,aAA4B;EAC3C,SAAS,EAAE,aAA4B;CAC1C;;AALL,AAAA,eAAe,CAA0B;EAMrC;;;;;;;;;;;;;;;UAeE;CACL;;AAtBD,AACI,eADW,AACV,OAAO,CAAC;EACL,iBAAiB,EAAE,cAA4B;EAC/C,aAAa,EAAE,cAA4B;EAC3C,SAAS,EAAE,cAA4B;CAC1C;;AALL,AAAA,eAAe,CAA0B;EAMrC;;;;;;;;;;;;;;;UAeE;CACL;;AAtBD,AACI,eADW,AACV,OAAO,CAAC;EACL,iBAAiB,EAAE,cAA4B;EAC/C,aAAa,EAAE,cAA4B;EAC3C,SAAS,EAAE,cAA4B;CAC1C;;AALL,AAAA,eAAe,CAA0B;EAMrC;;;;;;;;;;;;;;;UAeE;CACL;;AAtBD,AACI,eADW,AACV,OAAO,CAAC;EACL,iBAAiB,EAAE,cAA4B;EAC/C,aAAa,EAAE,cAA4B;EAC3C,SAAS,EAAE,cAA4B;CAC1C;;AALL,AAAA,eAAe,CAA0B;EAMrC;;;;;;;;;;;;;;;UAeE;CACL;;AAtBD,AACI,eADW,AACV,OAAO,CAAC;EACL,iBAAiB,EAAE,cAA4B;EAC/C,aAAa,EAAE,cAA4B;EAC3C,SAAS,EAAE,cAA4B;CAC1C;;AALL,AAAA,eAAe,CAA0B;EAMrC;;;;;;;;;;;;;;;UAeE;CACL;;AAtBD,AACI,eADW,AACV,OAAO,CAAC;EACL,iBAAiB,EAAE,cAA4B;EAC/C,aAAa,EAAE,cAA4B;EAC3C,SAAS,EAAE,cAA4B;CAC1C;;AAmBT,AAAA,WAAW,AAAA,OAAO,CAAgB;EAC9B,iBAAiB,EAAE,UAAU;EAC7B,SAAS,EAAE,UAAU;EACrB,MAAM,EAAE,KAAK;EACb,UAAU,EAAE,OAAO;CACtB;;AACD,AAAA,WAAW,AAAA,OAAO,CAAgB;EAC9B,iBAAiB,EAAE,UAAU;EAC7B,SAAS,EAAE,UAAU;EACrB,MAAM,EAAE,KAAK;EACb,UAAU,EAAE,OAAO;CACtB;;AC/DD,AAAA,SAAS,AAAA,OAAO,CAAgB;EAC5B,iBAAiB,EAAE,QAA4B,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM;EAC1D,SAAS,EAAE,QAA4B,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM;CACrE;;AAED,kBAAkB,CAAlB,QAAkB;EACd,EAAE;IACA,iBAAiB,EAAE,YAAY;IACvB,SAAS,EAAE,YAAY;;EAEjC,IAAI;IACF,iBAAiB,EAAE,cAAc;IACzB,SAAS,EAAE,cAAc;;;;AAIvC,UAAU,CAAV,QAAU;EACN,EAAE;IACA,iBAAiB,EAAE,YAAY;IACvB,SAAS,EAAE,YAAY;;EAEjC,IAAI;IACF,iBAAiB,EAAE,cAAc;IACzB,SAAS,EAAE,cAAc" +} \ No newline at end of file diff --git a/netbox/project-static/materialdesignicons-5.4.55/css/materialdesignicons.min.css b/netbox/project-static/materialdesignicons-5.4.55/css/materialdesignicons.min.css new file mode 100644 index 0000000000..386b8a56b7 --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/css/materialdesignicons.min.css @@ -0,0 +1,3 @@ +@font-face{font-family:"Material Design Icons";src:url("../fonts/materialdesignicons-webfont.eot?v=5.8.55");src:url("../fonts/materialdesignicons-webfont.eot?#iefix&v=5.8.55") format("embedded-opentype"),url("../fonts/materialdesignicons-webfont.woff2?v=5.8.55") format("woff2"),url("../fonts/materialdesignicons-webfont.woff?v=5.8.55") format("woff"),url("../fonts/materialdesignicons-webfont.ttf?v=5.8.55") format("truetype");font-weight:normal;font-style:normal}.mdi:before,.mdi-set{display:inline-block;font:normal normal normal 24px/1 "Material Design Icons";font-size:inherit;text-rendering:auto;line-height:inherit;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.mdi-ab-testing::before{content:"\F01C9"}.mdi-abjad-arabic::before{content:"\F1328"}.mdi-abjad-hebrew::before{content:"\F1329"}.mdi-abugida-devanagari::before{content:"\F132A"}.mdi-abugida-thai::before{content:"\F132B"}.mdi-access-point::before{content:"\F0003"}.mdi-access-point-check::before{content:"\F1538"}.mdi-access-point-minus::before{content:"\F1539"}.mdi-access-point-network::before{content:"\F0002"}.mdi-access-point-network-off::before{content:"\F0BE1"}.mdi-access-point-off::before{content:"\F1511"}.mdi-access-point-plus::before{content:"\F153A"}.mdi-access-point-remove::before{content:"\F153B"}.mdi-account::before{content:"\F0004"}.mdi-account-alert::before{content:"\F0005"}.mdi-account-alert-outline::before{content:"\F0B50"}.mdi-account-arrow-left::before{content:"\F0B51"}.mdi-account-arrow-left-outline::before{content:"\F0B52"}.mdi-account-arrow-right::before{content:"\F0B53"}.mdi-account-arrow-right-outline::before{content:"\F0B54"}.mdi-account-box::before{content:"\F0006"}.mdi-account-box-multiple::before{content:"\F0934"}.mdi-account-box-multiple-outline::before{content:"\F100A"}.mdi-account-box-outline::before{content:"\F0007"}.mdi-account-cancel::before{content:"\F12DF"}.mdi-account-cancel-outline::before{content:"\F12E0"}.mdi-account-cash::before{content:"\F1097"}.mdi-account-cash-outline::before{content:"\F1098"}.mdi-account-check::before{content:"\F0008"}.mdi-account-check-outline::before{content:"\F0BE2"}.mdi-account-child::before{content:"\F0A89"}.mdi-account-child-circle::before{content:"\F0A8A"}.mdi-account-child-outline::before{content:"\F10C8"}.mdi-account-circle::before{content:"\F0009"}.mdi-account-circle-outline::before{content:"\F0B55"}.mdi-account-clock::before{content:"\F0B56"}.mdi-account-clock-outline::before{content:"\F0B57"}.mdi-account-cog::before{content:"\F1370"}.mdi-account-cog-outline::before{content:"\F1371"}.mdi-account-convert::before{content:"\F000A"}.mdi-account-convert-outline::before{content:"\F1301"}.mdi-account-cowboy-hat::before{content:"\F0E9B"}.mdi-account-details::before{content:"\F0631"}.mdi-account-details-outline::before{content:"\F1372"}.mdi-account-edit::before{content:"\F06BC"}.mdi-account-edit-outline::before{content:"\F0FFB"}.mdi-account-group::before{content:"\F0849"}.mdi-account-group-outline::before{content:"\F0B58"}.mdi-account-hard-hat::before{content:"\F05B5"}.mdi-account-heart::before{content:"\F0899"}.mdi-account-heart-outline::before{content:"\F0BE3"}.mdi-account-key::before{content:"\F000B"}.mdi-account-key-outline::before{content:"\F0BE4"}.mdi-account-lock::before{content:"\F115E"}.mdi-account-lock-outline::before{content:"\F115F"}.mdi-account-minus::before{content:"\F000D"}.mdi-account-minus-outline::before{content:"\F0AEC"}.mdi-account-multiple::before{content:"\F000E"}.mdi-account-multiple-check::before{content:"\F08C5"}.mdi-account-multiple-check-outline::before{content:"\F11FE"}.mdi-account-multiple-minus::before{content:"\F05D3"}.mdi-account-multiple-minus-outline::before{content:"\F0BE5"}.mdi-account-multiple-outline::before{content:"\F000F"}.mdi-account-multiple-plus::before{content:"\F0010"}.mdi-account-multiple-plus-outline::before{content:"\F0800"}.mdi-account-multiple-remove::before{content:"\F120A"}.mdi-account-multiple-remove-outline::before{content:"\F120B"}.mdi-account-music::before{content:"\F0803"}.mdi-account-music-outline::before{content:"\F0CE9"}.mdi-account-network::before{content:"\F0011"}.mdi-account-network-outline::before{content:"\F0BE6"}.mdi-account-off::before{content:"\F0012"}.mdi-account-off-outline::before{content:"\F0BE7"}.mdi-account-outline::before{content:"\F0013"}.mdi-account-plus::before{content:"\F0014"}.mdi-account-plus-outline::before{content:"\F0801"}.mdi-account-question::before{content:"\F0B59"}.mdi-account-question-outline::before{content:"\F0B5A"}.mdi-account-reactivate::before{content:"\F152B"}.mdi-account-reactivate-outline::before{content:"\F152C"}.mdi-account-remove::before{content:"\F0015"}.mdi-account-remove-outline::before{content:"\F0AED"}.mdi-account-search::before{content:"\F0016"}.mdi-account-search-outline::before{content:"\F0935"}.mdi-account-settings::before{content:"\F0630"}.mdi-account-settings-outline::before{content:"\F10C9"}.mdi-account-star::before{content:"\F0017"}.mdi-account-star-outline::before{content:"\F0BE8"}.mdi-account-supervisor::before{content:"\F0A8B"}.mdi-account-supervisor-circle::before{content:"\F0A8C"}.mdi-account-supervisor-circle-outline::before{content:"\F14EC"}.mdi-account-supervisor-outline::before{content:"\F112D"}.mdi-account-switch::before{content:"\F0019"}.mdi-account-switch-outline::before{content:"\F04CB"}.mdi-account-tie::before{content:"\F0CE3"}.mdi-account-tie-outline::before{content:"\F10CA"}.mdi-account-tie-voice::before{content:"\F1308"}.mdi-account-tie-voice-off::before{content:"\F130A"}.mdi-account-tie-voice-off-outline::before{content:"\F130B"}.mdi-account-tie-voice-outline::before{content:"\F1309"}.mdi-account-voice::before{content:"\F05CB"}.mdi-adjust::before{content:"\F001A"}.mdi-adobe::before{content:"\F0936"}.mdi-adobe-acrobat::before{content:"\F0F9D"}.mdi-air-conditioner::before{content:"\F001B"}.mdi-air-filter::before{content:"\F0D43"}.mdi-air-horn::before{content:"\F0DAC"}.mdi-air-humidifier::before{content:"\F1099"}.mdi-air-humidifier-off::before{content:"\F1466"}.mdi-air-purifier::before{content:"\F0D44"}.mdi-airbag::before{content:"\F0BE9"}.mdi-airballoon::before{content:"\F001C"}.mdi-airballoon-outline::before{content:"\F100B"}.mdi-airplane::before{content:"\F001D"}.mdi-airplane-landing::before{content:"\F05D4"}.mdi-airplane-off::before{content:"\F001E"}.mdi-airplane-takeoff::before{content:"\F05D5"}.mdi-airport::before{content:"\F084B"}.mdi-alarm::before{content:"\F0020"}.mdi-alarm-bell::before{content:"\F078E"}.mdi-alarm-check::before{content:"\F0021"}.mdi-alarm-light::before{content:"\F078F"}.mdi-alarm-light-outline::before{content:"\F0BEA"}.mdi-alarm-multiple::before{content:"\F0022"}.mdi-alarm-note::before{content:"\F0E71"}.mdi-alarm-note-off::before{content:"\F0E72"}.mdi-alarm-off::before{content:"\F0023"}.mdi-alarm-panel::before{content:"\F15C4"}.mdi-alarm-panel-outline::before{content:"\F15C5"}.mdi-alarm-plus::before{content:"\F0024"}.mdi-alarm-snooze::before{content:"\F068E"}.mdi-album::before{content:"\F0025"}.mdi-alert::before{content:"\F0026"}.mdi-alert-box::before{content:"\F0027"}.mdi-alert-box-outline::before{content:"\F0CE4"}.mdi-alert-circle::before{content:"\F0028"}.mdi-alert-circle-check::before{content:"\F11ED"}.mdi-alert-circle-check-outline::before{content:"\F11EE"}.mdi-alert-circle-outline::before{content:"\F05D6"}.mdi-alert-decagram::before{content:"\F06BD"}.mdi-alert-decagram-outline::before{content:"\F0CE5"}.mdi-alert-minus::before{content:"\F14BB"}.mdi-alert-minus-outline::before{content:"\F14BE"}.mdi-alert-octagon::before{content:"\F0029"}.mdi-alert-octagon-outline::before{content:"\F0CE6"}.mdi-alert-octagram::before{content:"\F0767"}.mdi-alert-octagram-outline::before{content:"\F0CE7"}.mdi-alert-outline::before{content:"\F002A"}.mdi-alert-plus::before{content:"\F14BA"}.mdi-alert-plus-outline::before{content:"\F14BD"}.mdi-alert-remove::before{content:"\F14BC"}.mdi-alert-remove-outline::before{content:"\F14BF"}.mdi-alert-rhombus::before{content:"\F11CE"}.mdi-alert-rhombus-outline::before{content:"\F11CF"}.mdi-alien::before{content:"\F089A"}.mdi-alien-outline::before{content:"\F10CB"}.mdi-align-horizontal-center::before{content:"\F11C3"}.mdi-align-horizontal-left::before{content:"\F11C2"}.mdi-align-horizontal-right::before{content:"\F11C4"}.mdi-align-vertical-bottom::before{content:"\F11C5"}.mdi-align-vertical-center::before{content:"\F11C6"}.mdi-align-vertical-top::before{content:"\F11C7"}.mdi-all-inclusive::before{content:"\F06BE"}.mdi-allergy::before{content:"\F1258"}.mdi-alpha::before{content:"\F002B"}.mdi-alpha-a::before{content:"\F0AEE"}.mdi-alpha-a-box::before{content:"\F0B08"}.mdi-alpha-a-box-outline::before{content:"\F0BEB"}.mdi-alpha-a-circle::before{content:"\F0BEC"}.mdi-alpha-a-circle-outline::before{content:"\F0BED"}.mdi-alpha-b::before{content:"\F0AEF"}.mdi-alpha-b-box::before{content:"\F0B09"}.mdi-alpha-b-box-outline::before{content:"\F0BEE"}.mdi-alpha-b-circle::before{content:"\F0BEF"}.mdi-alpha-b-circle-outline::before{content:"\F0BF0"}.mdi-alpha-c::before{content:"\F0AF0"}.mdi-alpha-c-box::before{content:"\F0B0A"}.mdi-alpha-c-box-outline::before{content:"\F0BF1"}.mdi-alpha-c-circle::before{content:"\F0BF2"}.mdi-alpha-c-circle-outline::before{content:"\F0BF3"}.mdi-alpha-d::before{content:"\F0AF1"}.mdi-alpha-d-box::before{content:"\F0B0B"}.mdi-alpha-d-box-outline::before{content:"\F0BF4"}.mdi-alpha-d-circle::before{content:"\F0BF5"}.mdi-alpha-d-circle-outline::before{content:"\F0BF6"}.mdi-alpha-e::before{content:"\F0AF2"}.mdi-alpha-e-box::before{content:"\F0B0C"}.mdi-alpha-e-box-outline::before{content:"\F0BF7"}.mdi-alpha-e-circle::before{content:"\F0BF8"}.mdi-alpha-e-circle-outline::before{content:"\F0BF9"}.mdi-alpha-f::before{content:"\F0AF3"}.mdi-alpha-f-box::before{content:"\F0B0D"}.mdi-alpha-f-box-outline::before{content:"\F0BFA"}.mdi-alpha-f-circle::before{content:"\F0BFB"}.mdi-alpha-f-circle-outline::before{content:"\F0BFC"}.mdi-alpha-g::before{content:"\F0AF4"}.mdi-alpha-g-box::before{content:"\F0B0E"}.mdi-alpha-g-box-outline::before{content:"\F0BFD"}.mdi-alpha-g-circle::before{content:"\F0BFE"}.mdi-alpha-g-circle-outline::before{content:"\F0BFF"}.mdi-alpha-h::before{content:"\F0AF5"}.mdi-alpha-h-box::before{content:"\F0B0F"}.mdi-alpha-h-box-outline::before{content:"\F0C00"}.mdi-alpha-h-circle::before{content:"\F0C01"}.mdi-alpha-h-circle-outline::before{content:"\F0C02"}.mdi-alpha-i::before{content:"\F0AF6"}.mdi-alpha-i-box::before{content:"\F0B10"}.mdi-alpha-i-box-outline::before{content:"\F0C03"}.mdi-alpha-i-circle::before{content:"\F0C04"}.mdi-alpha-i-circle-outline::before{content:"\F0C05"}.mdi-alpha-j::before{content:"\F0AF7"}.mdi-alpha-j-box::before{content:"\F0B11"}.mdi-alpha-j-box-outline::before{content:"\F0C06"}.mdi-alpha-j-circle::before{content:"\F0C07"}.mdi-alpha-j-circle-outline::before{content:"\F0C08"}.mdi-alpha-k::before{content:"\F0AF8"}.mdi-alpha-k-box::before{content:"\F0B12"}.mdi-alpha-k-box-outline::before{content:"\F0C09"}.mdi-alpha-k-circle::before{content:"\F0C0A"}.mdi-alpha-k-circle-outline::before{content:"\F0C0B"}.mdi-alpha-l::before{content:"\F0AF9"}.mdi-alpha-l-box::before{content:"\F0B13"}.mdi-alpha-l-box-outline::before{content:"\F0C0C"}.mdi-alpha-l-circle::before{content:"\F0C0D"}.mdi-alpha-l-circle-outline::before{content:"\F0C0E"}.mdi-alpha-m::before{content:"\F0AFA"}.mdi-alpha-m-box::before{content:"\F0B14"}.mdi-alpha-m-box-outline::before{content:"\F0C0F"}.mdi-alpha-m-circle::before{content:"\F0C10"}.mdi-alpha-m-circle-outline::before{content:"\F0C11"}.mdi-alpha-n::before{content:"\F0AFB"}.mdi-alpha-n-box::before{content:"\F0B15"}.mdi-alpha-n-box-outline::before{content:"\F0C12"}.mdi-alpha-n-circle::before{content:"\F0C13"}.mdi-alpha-n-circle-outline::before{content:"\F0C14"}.mdi-alpha-o::before{content:"\F0AFC"}.mdi-alpha-o-box::before{content:"\F0B16"}.mdi-alpha-o-box-outline::before{content:"\F0C15"}.mdi-alpha-o-circle::before{content:"\F0C16"}.mdi-alpha-o-circle-outline::before{content:"\F0C17"}.mdi-alpha-p::before{content:"\F0AFD"}.mdi-alpha-p-box::before{content:"\F0B17"}.mdi-alpha-p-box-outline::before{content:"\F0C18"}.mdi-alpha-p-circle::before{content:"\F0C19"}.mdi-alpha-p-circle-outline::before{content:"\F0C1A"}.mdi-alpha-q::before{content:"\F0AFE"}.mdi-alpha-q-box::before{content:"\F0B18"}.mdi-alpha-q-box-outline::before{content:"\F0C1B"}.mdi-alpha-q-circle::before{content:"\F0C1C"}.mdi-alpha-q-circle-outline::before{content:"\F0C1D"}.mdi-alpha-r::before{content:"\F0AFF"}.mdi-alpha-r-box::before{content:"\F0B19"}.mdi-alpha-r-box-outline::before{content:"\F0C1E"}.mdi-alpha-r-circle::before{content:"\F0C1F"}.mdi-alpha-r-circle-outline::before{content:"\F0C20"}.mdi-alpha-s::before{content:"\F0B00"}.mdi-alpha-s-box::before{content:"\F0B1A"}.mdi-alpha-s-box-outline::before{content:"\F0C21"}.mdi-alpha-s-circle::before{content:"\F0C22"}.mdi-alpha-s-circle-outline::before{content:"\F0C23"}.mdi-alpha-t::before{content:"\F0B01"}.mdi-alpha-t-box::before{content:"\F0B1B"}.mdi-alpha-t-box-outline::before{content:"\F0C24"}.mdi-alpha-t-circle::before{content:"\F0C25"}.mdi-alpha-t-circle-outline::before{content:"\F0C26"}.mdi-alpha-u::before{content:"\F0B02"}.mdi-alpha-u-box::before{content:"\F0B1C"}.mdi-alpha-u-box-outline::before{content:"\F0C27"}.mdi-alpha-u-circle::before{content:"\F0C28"}.mdi-alpha-u-circle-outline::before{content:"\F0C29"}.mdi-alpha-v::before{content:"\F0B03"}.mdi-alpha-v-box::before{content:"\F0B1D"}.mdi-alpha-v-box-outline::before{content:"\F0C2A"}.mdi-alpha-v-circle::before{content:"\F0C2B"}.mdi-alpha-v-circle-outline::before{content:"\F0C2C"}.mdi-alpha-w::before{content:"\F0B04"}.mdi-alpha-w-box::before{content:"\F0B1E"}.mdi-alpha-w-box-outline::before{content:"\F0C2D"}.mdi-alpha-w-circle::before{content:"\F0C2E"}.mdi-alpha-w-circle-outline::before{content:"\F0C2F"}.mdi-alpha-x::before{content:"\F0B05"}.mdi-alpha-x-box::before{content:"\F0B1F"}.mdi-alpha-x-box-outline::before{content:"\F0C30"}.mdi-alpha-x-circle::before{content:"\F0C31"}.mdi-alpha-x-circle-outline::before{content:"\F0C32"}.mdi-alpha-y::before{content:"\F0B06"}.mdi-alpha-y-box::before{content:"\F0B20"}.mdi-alpha-y-box-outline::before{content:"\F0C33"}.mdi-alpha-y-circle::before{content:"\F0C34"}.mdi-alpha-y-circle-outline::before{content:"\F0C35"}.mdi-alpha-z::before{content:"\F0B07"}.mdi-alpha-z-box::before{content:"\F0B21"}.mdi-alpha-z-box-outline::before{content:"\F0C36"}.mdi-alpha-z-circle::before{content:"\F0C37"}.mdi-alpha-z-circle-outline::before{content:"\F0C38"}.mdi-alphabet-aurebesh::before{content:"\F132C"}.mdi-alphabet-cyrillic::before{content:"\F132D"}.mdi-alphabet-greek::before{content:"\F132E"}.mdi-alphabet-latin::before{content:"\F132F"}.mdi-alphabet-piqad::before{content:"\F1330"}.mdi-alphabet-tengwar::before{content:"\F1337"}.mdi-alphabetical::before{content:"\F002C"}.mdi-alphabetical-off::before{content:"\F100C"}.mdi-alphabetical-variant::before{content:"\F100D"}.mdi-alphabetical-variant-off::before{content:"\F100E"}.mdi-altimeter::before{content:"\F05D7"}.mdi-amazon::before{content:"\F002D"}.mdi-amazon-alexa::before{content:"\F08C6"}.mdi-ambulance::before{content:"\F002F"}.mdi-ammunition::before{content:"\F0CE8"}.mdi-ampersand::before{content:"\F0A8D"}.mdi-amplifier::before{content:"\F0030"}.mdi-amplifier-off::before{content:"\F11B5"}.mdi-anchor::before{content:"\F0031"}.mdi-android::before{content:"\F0032"}.mdi-android-auto::before{content:"\F0A8E"}.mdi-android-debug-bridge::before{content:"\F0033"}.mdi-android-messages::before{content:"\F0D45"}.mdi-android-studio::before{content:"\F0034"}.mdi-angle-acute::before{content:"\F0937"}.mdi-angle-obtuse::before{content:"\F0938"}.mdi-angle-right::before{content:"\F0939"}.mdi-angular::before{content:"\F06B2"}.mdi-angularjs::before{content:"\F06BF"}.mdi-animation::before{content:"\F05D8"}.mdi-animation-outline::before{content:"\F0A8F"}.mdi-animation-play::before{content:"\F093A"}.mdi-animation-play-outline::before{content:"\F0A90"}.mdi-ansible::before{content:"\F109A"}.mdi-antenna::before{content:"\F1119"}.mdi-anvil::before{content:"\F089B"}.mdi-apache-kafka::before{content:"\F100F"}.mdi-api::before{content:"\F109B"}.mdi-api-off::before{content:"\F1257"}.mdi-apple::before{content:"\F0035"}.mdi-apple-airplay::before{content:"\F001F"}.mdi-apple-finder::before{content:"\F0036"}.mdi-apple-icloud::before{content:"\F0038"}.mdi-apple-ios::before{content:"\F0037"}.mdi-apple-keyboard-caps::before{content:"\F0632"}.mdi-apple-keyboard-command::before{content:"\F0633"}.mdi-apple-keyboard-control::before{content:"\F0634"}.mdi-apple-keyboard-option::before{content:"\F0635"}.mdi-apple-keyboard-shift::before{content:"\F0636"}.mdi-apple-safari::before{content:"\F0039"}.mdi-application::before{content:"\F0614"}.mdi-application-cog::before{content:"\F1577"}.mdi-application-export::before{content:"\F0DAD"}.mdi-application-import::before{content:"\F0DAE"}.mdi-application-settings::before{content:"\F1555"}.mdi-approximately-equal::before{content:"\F0F9E"}.mdi-approximately-equal-box::before{content:"\F0F9F"}.mdi-apps::before{content:"\F003B"}.mdi-apps-box::before{content:"\F0D46"}.mdi-arch::before{content:"\F08C7"}.mdi-archive::before{content:"\F003C"}.mdi-archive-alert::before{content:"\F14FD"}.mdi-archive-alert-outline::before{content:"\F14FE"}.mdi-archive-arrow-down::before{content:"\F1259"}.mdi-archive-arrow-down-outline::before{content:"\F125A"}.mdi-archive-arrow-up::before{content:"\F125B"}.mdi-archive-arrow-up-outline::before{content:"\F125C"}.mdi-archive-outline::before{content:"\F120E"}.mdi-arm-flex::before{content:"\F0FD7"}.mdi-arm-flex-outline::before{content:"\F0FD6"}.mdi-arrange-bring-forward::before{content:"\F003D"}.mdi-arrange-bring-to-front::before{content:"\F003E"}.mdi-arrange-send-backward::before{content:"\F003F"}.mdi-arrange-send-to-back::before{content:"\F0040"}.mdi-arrow-all::before{content:"\F0041"}.mdi-arrow-bottom-left::before{content:"\F0042"}.mdi-arrow-bottom-left-bold-outline::before{content:"\F09B7"}.mdi-arrow-bottom-left-thick::before{content:"\F09B8"}.mdi-arrow-bottom-left-thin-circle-outline::before{content:"\F1596"}.mdi-arrow-bottom-right::before{content:"\F0043"}.mdi-arrow-bottom-right-bold-outline::before{content:"\F09B9"}.mdi-arrow-bottom-right-thick::before{content:"\F09BA"}.mdi-arrow-bottom-right-thin-circle-outline::before{content:"\F1595"}.mdi-arrow-collapse::before{content:"\F0615"}.mdi-arrow-collapse-all::before{content:"\F0044"}.mdi-arrow-collapse-down::before{content:"\F0792"}.mdi-arrow-collapse-horizontal::before{content:"\F084C"}.mdi-arrow-collapse-left::before{content:"\F0793"}.mdi-arrow-collapse-right::before{content:"\F0794"}.mdi-arrow-collapse-up::before{content:"\F0795"}.mdi-arrow-collapse-vertical::before{content:"\F084D"}.mdi-arrow-decision::before{content:"\F09BB"}.mdi-arrow-decision-auto::before{content:"\F09BC"}.mdi-arrow-decision-auto-outline::before{content:"\F09BD"}.mdi-arrow-decision-outline::before{content:"\F09BE"}.mdi-arrow-down::before{content:"\F0045"}.mdi-arrow-down-bold::before{content:"\F072E"}.mdi-arrow-down-bold-box::before{content:"\F072F"}.mdi-arrow-down-bold-box-outline::before{content:"\F0730"}.mdi-arrow-down-bold-circle::before{content:"\F0047"}.mdi-arrow-down-bold-circle-outline::before{content:"\F0048"}.mdi-arrow-down-bold-hexagon-outline::before{content:"\F0049"}.mdi-arrow-down-bold-outline::before{content:"\F09BF"}.mdi-arrow-down-box::before{content:"\F06C0"}.mdi-arrow-down-circle::before{content:"\F0CDB"}.mdi-arrow-down-circle-outline::before{content:"\F0CDC"}.mdi-arrow-down-drop-circle::before{content:"\F004A"}.mdi-arrow-down-drop-circle-outline::before{content:"\F004B"}.mdi-arrow-down-thick::before{content:"\F0046"}.mdi-arrow-down-thin-circle-outline::before{content:"\F1599"}.mdi-arrow-expand::before{content:"\F0616"}.mdi-arrow-expand-all::before{content:"\F004C"}.mdi-arrow-expand-down::before{content:"\F0796"}.mdi-arrow-expand-horizontal::before{content:"\F084E"}.mdi-arrow-expand-left::before{content:"\F0797"}.mdi-arrow-expand-right::before{content:"\F0798"}.mdi-arrow-expand-up::before{content:"\F0799"}.mdi-arrow-expand-vertical::before{content:"\F084F"}.mdi-arrow-horizontal-lock::before{content:"\F115B"}.mdi-arrow-left::before{content:"\F004D"}.mdi-arrow-left-bold::before{content:"\F0731"}.mdi-arrow-left-bold-box::before{content:"\F0732"}.mdi-arrow-left-bold-box-outline::before{content:"\F0733"}.mdi-arrow-left-bold-circle::before{content:"\F004F"}.mdi-arrow-left-bold-circle-outline::before{content:"\F0050"}.mdi-arrow-left-bold-hexagon-outline::before{content:"\F0051"}.mdi-arrow-left-bold-outline::before{content:"\F09C0"}.mdi-arrow-left-box::before{content:"\F06C1"}.mdi-arrow-left-circle::before{content:"\F0CDD"}.mdi-arrow-left-circle-outline::before{content:"\F0CDE"}.mdi-arrow-left-drop-circle::before{content:"\F0052"}.mdi-arrow-left-drop-circle-outline::before{content:"\F0053"}.mdi-arrow-left-right::before{content:"\F0E73"}.mdi-arrow-left-right-bold::before{content:"\F0E74"}.mdi-arrow-left-right-bold-outline::before{content:"\F09C1"}.mdi-arrow-left-thick::before{content:"\F004E"}.mdi-arrow-left-thin-circle-outline::before{content:"\F159A"}.mdi-arrow-right::before{content:"\F0054"}.mdi-arrow-right-bold::before{content:"\F0734"}.mdi-arrow-right-bold-box::before{content:"\F0735"}.mdi-arrow-right-bold-box-outline::before{content:"\F0736"}.mdi-arrow-right-bold-circle::before{content:"\F0056"}.mdi-arrow-right-bold-circle-outline::before{content:"\F0057"}.mdi-arrow-right-bold-hexagon-outline::before{content:"\F0058"}.mdi-arrow-right-bold-outline::before{content:"\F09C2"}.mdi-arrow-right-box::before{content:"\F06C2"}.mdi-arrow-right-circle::before{content:"\F0CDF"}.mdi-arrow-right-circle-outline::before{content:"\F0CE0"}.mdi-arrow-right-drop-circle::before{content:"\F0059"}.mdi-arrow-right-drop-circle-outline::before{content:"\F005A"}.mdi-arrow-right-thick::before{content:"\F0055"}.mdi-arrow-right-thin-circle-outline::before{content:"\F1598"}.mdi-arrow-split-horizontal::before{content:"\F093B"}.mdi-arrow-split-vertical::before{content:"\F093C"}.mdi-arrow-top-left::before{content:"\F005B"}.mdi-arrow-top-left-bold-outline::before{content:"\F09C3"}.mdi-arrow-top-left-bottom-right::before{content:"\F0E75"}.mdi-arrow-top-left-bottom-right-bold::before{content:"\F0E76"}.mdi-arrow-top-left-thick::before{content:"\F09C4"}.mdi-arrow-top-left-thin-circle-outline::before{content:"\F1593"}.mdi-arrow-top-right::before{content:"\F005C"}.mdi-arrow-top-right-bold-outline::before{content:"\F09C5"}.mdi-arrow-top-right-bottom-left::before{content:"\F0E77"}.mdi-arrow-top-right-bottom-left-bold::before{content:"\F0E78"}.mdi-arrow-top-right-thick::before{content:"\F09C6"}.mdi-arrow-top-right-thin-circle-outline::before{content:"\F1594"}.mdi-arrow-up::before{content:"\F005D"}.mdi-arrow-up-bold::before{content:"\F0737"}.mdi-arrow-up-bold-box::before{content:"\F0738"}.mdi-arrow-up-bold-box-outline::before{content:"\F0739"}.mdi-arrow-up-bold-circle::before{content:"\F005F"}.mdi-arrow-up-bold-circle-outline::before{content:"\F0060"}.mdi-arrow-up-bold-hexagon-outline::before{content:"\F0061"}.mdi-arrow-up-bold-outline::before{content:"\F09C7"}.mdi-arrow-up-box::before{content:"\F06C3"}.mdi-arrow-up-circle::before{content:"\F0CE1"}.mdi-arrow-up-circle-outline::before{content:"\F0CE2"}.mdi-arrow-up-down::before{content:"\F0E79"}.mdi-arrow-up-down-bold::before{content:"\F0E7A"}.mdi-arrow-up-down-bold-outline::before{content:"\F09C8"}.mdi-arrow-up-drop-circle::before{content:"\F0062"}.mdi-arrow-up-drop-circle-outline::before{content:"\F0063"}.mdi-arrow-up-thick::before{content:"\F005E"}.mdi-arrow-up-thin-circle-outline::before{content:"\F1597"}.mdi-arrow-vertical-lock::before{content:"\F115C"}.mdi-artstation::before{content:"\F0B5B"}.mdi-aspect-ratio::before{content:"\F0A24"}.mdi-assistant::before{content:"\F0064"}.mdi-asterisk::before{content:"\F06C4"}.mdi-at::before{content:"\F0065"}.mdi-atlassian::before{content:"\F0804"}.mdi-atm::before{content:"\F0D47"}.mdi-atom::before{content:"\F0768"}.mdi-atom-variant::before{content:"\F0E7B"}.mdi-attachment::before{content:"\F0066"}.mdi-audio-video::before{content:"\F093D"}.mdi-audio-video-off::before{content:"\F11B6"}.mdi-augmented-reality::before{content:"\F0850"}.mdi-auto-download::before{content:"\F137E"}.mdi-auto-fix::before{content:"\F0068"}.mdi-auto-upload::before{content:"\F0069"}.mdi-autorenew::before{content:"\F006A"}.mdi-av-timer::before{content:"\F006B"}.mdi-aws::before{content:"\F0E0F"}.mdi-axe::before{content:"\F08C8"}.mdi-axis::before{content:"\F0D48"}.mdi-axis-arrow::before{content:"\F0D49"}.mdi-axis-arrow-info::before{content:"\F140E"}.mdi-axis-arrow-lock::before{content:"\F0D4A"}.mdi-axis-lock::before{content:"\F0D4B"}.mdi-axis-x-arrow::before{content:"\F0D4C"}.mdi-axis-x-arrow-lock::before{content:"\F0D4D"}.mdi-axis-x-rotate-clockwise::before{content:"\F0D4E"}.mdi-axis-x-rotate-counterclockwise::before{content:"\F0D4F"}.mdi-axis-x-y-arrow-lock::before{content:"\F0D50"}.mdi-axis-y-arrow::before{content:"\F0D51"}.mdi-axis-y-arrow-lock::before{content:"\F0D52"}.mdi-axis-y-rotate-clockwise::before{content:"\F0D53"}.mdi-axis-y-rotate-counterclockwise::before{content:"\F0D54"}.mdi-axis-z-arrow::before{content:"\F0D55"}.mdi-axis-z-arrow-lock::before{content:"\F0D56"}.mdi-axis-z-rotate-clockwise::before{content:"\F0D57"}.mdi-axis-z-rotate-counterclockwise::before{content:"\F0D58"}.mdi-babel::before{content:"\F0A25"}.mdi-baby::before{content:"\F006C"}.mdi-baby-bottle::before{content:"\F0F39"}.mdi-baby-bottle-outline::before{content:"\F0F3A"}.mdi-baby-buggy::before{content:"\F13E0"}.mdi-baby-carriage::before{content:"\F068F"}.mdi-baby-carriage-off::before{content:"\F0FA0"}.mdi-baby-face::before{content:"\F0E7C"}.mdi-baby-face-outline::before{content:"\F0E7D"}.mdi-backburger::before{content:"\F006D"}.mdi-backspace::before{content:"\F006E"}.mdi-backspace-outline::before{content:"\F0B5C"}.mdi-backspace-reverse::before{content:"\F0E7E"}.mdi-backspace-reverse-outline::before{content:"\F0E7F"}.mdi-backup-restore::before{content:"\F006F"}.mdi-bacteria::before{content:"\F0ED5"}.mdi-bacteria-outline::before{content:"\F0ED6"}.mdi-badge-account::before{content:"\F0DA7"}.mdi-badge-account-alert::before{content:"\F0DA8"}.mdi-badge-account-alert-outline::before{content:"\F0DA9"}.mdi-badge-account-horizontal::before{content:"\F0E0D"}.mdi-badge-account-horizontal-outline::before{content:"\F0E0E"}.mdi-badge-account-outline::before{content:"\F0DAA"}.mdi-badminton::before{content:"\F0851"}.mdi-bag-carry-on::before{content:"\F0F3B"}.mdi-bag-carry-on-check::before{content:"\F0D65"}.mdi-bag-carry-on-off::before{content:"\F0F3C"}.mdi-bag-checked::before{content:"\F0F3D"}.mdi-bag-personal::before{content:"\F0E10"}.mdi-bag-personal-off::before{content:"\F0E11"}.mdi-bag-personal-off-outline::before{content:"\F0E12"}.mdi-bag-personal-outline::before{content:"\F0E13"}.mdi-bag-suitcase::before{content:"\F158B"}.mdi-bag-suitcase-off::before{content:"\F158D"}.mdi-bag-suitcase-off-outline::before{content:"\F158E"}.mdi-bag-suitcase-outline::before{content:"\F158C"}.mdi-baguette::before{content:"\F0F3E"}.mdi-balloon::before{content:"\F0A26"}.mdi-ballot::before{content:"\F09C9"}.mdi-ballot-outline::before{content:"\F09CA"}.mdi-ballot-recount::before{content:"\F0C39"}.mdi-ballot-recount-outline::before{content:"\F0C3A"}.mdi-bandage::before{content:"\F0DAF"}.mdi-bandcamp::before{content:"\F0675"}.mdi-bank::before{content:"\F0070"}.mdi-bank-check::before{content:"\F1655"}.mdi-bank-minus::before{content:"\F0DB0"}.mdi-bank-off::before{content:"\F1656"}.mdi-bank-off-outline::before{content:"\F1657"}.mdi-bank-outline::before{content:"\F0E80"}.mdi-bank-plus::before{content:"\F0DB1"}.mdi-bank-remove::before{content:"\F0DB2"}.mdi-bank-transfer::before{content:"\F0A27"}.mdi-bank-transfer-in::before{content:"\F0A28"}.mdi-bank-transfer-out::before{content:"\F0A29"}.mdi-barcode::before{content:"\F0071"}.mdi-barcode-off::before{content:"\F1236"}.mdi-barcode-scan::before{content:"\F0072"}.mdi-barley::before{content:"\F0073"}.mdi-barley-off::before{content:"\F0B5D"}.mdi-barn::before{content:"\F0B5E"}.mdi-barrel::before{content:"\F0074"}.mdi-baseball::before{content:"\F0852"}.mdi-baseball-bat::before{content:"\F0853"}.mdi-baseball-diamond::before{content:"\F15EC"}.mdi-baseball-diamond-outline::before{content:"\F15ED"}.mdi-bash::before{content:"\F1183"}.mdi-basket::before{content:"\F0076"}.mdi-basket-fill::before{content:"\F0077"}.mdi-basket-minus::before{content:"\F1523"}.mdi-basket-minus-outline::before{content:"\F1524"}.mdi-basket-off::before{content:"\F1525"}.mdi-basket-off-outline::before{content:"\F1526"}.mdi-basket-outline::before{content:"\F1181"}.mdi-basket-plus::before{content:"\F1527"}.mdi-basket-plus-outline::before{content:"\F1528"}.mdi-basket-remove::before{content:"\F1529"}.mdi-basket-remove-outline::before{content:"\F152A"}.mdi-basket-unfill::before{content:"\F0078"}.mdi-basketball::before{content:"\F0806"}.mdi-basketball-hoop::before{content:"\F0C3B"}.mdi-basketball-hoop-outline::before{content:"\F0C3C"}.mdi-bat::before{content:"\F0B5F"}.mdi-battery::before{content:"\F0079"}.mdi-battery-10::before{content:"\F007A"}.mdi-battery-10-bluetooth::before{content:"\F093E"}.mdi-battery-20::before{content:"\F007B"}.mdi-battery-20-bluetooth::before{content:"\F093F"}.mdi-battery-30::before{content:"\F007C"}.mdi-battery-30-bluetooth::before{content:"\F0940"}.mdi-battery-40::before{content:"\F007D"}.mdi-battery-40-bluetooth::before{content:"\F0941"}.mdi-battery-50::before{content:"\F007E"}.mdi-battery-50-bluetooth::before{content:"\F0942"}.mdi-battery-60::before{content:"\F007F"}.mdi-battery-60-bluetooth::before{content:"\F0943"}.mdi-battery-70::before{content:"\F0080"}.mdi-battery-70-bluetooth::before{content:"\F0944"}.mdi-battery-80::before{content:"\F0081"}.mdi-battery-80-bluetooth::before{content:"\F0945"}.mdi-battery-90::before{content:"\F0082"}.mdi-battery-90-bluetooth::before{content:"\F0946"}.mdi-battery-alert::before{content:"\F0083"}.mdi-battery-alert-bluetooth::before{content:"\F0947"}.mdi-battery-alert-variant::before{content:"\F10CC"}.mdi-battery-alert-variant-outline::before{content:"\F10CD"}.mdi-battery-bluetooth::before{content:"\F0948"}.mdi-battery-bluetooth-variant::before{content:"\F0949"}.mdi-battery-charging::before{content:"\F0084"}.mdi-battery-charging-10::before{content:"\F089C"}.mdi-battery-charging-100::before{content:"\F0085"}.mdi-battery-charging-20::before{content:"\F0086"}.mdi-battery-charging-30::before{content:"\F0087"}.mdi-battery-charging-40::before{content:"\F0088"}.mdi-battery-charging-50::before{content:"\F089D"}.mdi-battery-charging-60::before{content:"\F0089"}.mdi-battery-charging-70::before{content:"\F089E"}.mdi-battery-charging-80::before{content:"\F008A"}.mdi-battery-charging-90::before{content:"\F008B"}.mdi-battery-charging-high::before{content:"\F12A6"}.mdi-battery-charging-low::before{content:"\F12A4"}.mdi-battery-charging-medium::before{content:"\F12A5"}.mdi-battery-charging-outline::before{content:"\F089F"}.mdi-battery-charging-wireless::before{content:"\F0807"}.mdi-battery-charging-wireless-10::before{content:"\F0808"}.mdi-battery-charging-wireless-20::before{content:"\F0809"}.mdi-battery-charging-wireless-30::before{content:"\F080A"}.mdi-battery-charging-wireless-40::before{content:"\F080B"}.mdi-battery-charging-wireless-50::before{content:"\F080C"}.mdi-battery-charging-wireless-60::before{content:"\F080D"}.mdi-battery-charging-wireless-70::before{content:"\F080E"}.mdi-battery-charging-wireless-80::before{content:"\F080F"}.mdi-battery-charging-wireless-90::before{content:"\F0810"}.mdi-battery-charging-wireless-alert::before{content:"\F0811"}.mdi-battery-charging-wireless-outline::before{content:"\F0812"}.mdi-battery-heart::before{content:"\F120F"}.mdi-battery-heart-outline::before{content:"\F1210"}.mdi-battery-heart-variant::before{content:"\F1211"}.mdi-battery-high::before{content:"\F12A3"}.mdi-battery-low::before{content:"\F12A1"}.mdi-battery-medium::before{content:"\F12A2"}.mdi-battery-minus::before{content:"\F008C"}.mdi-battery-negative::before{content:"\F008D"}.mdi-battery-off::before{content:"\F125D"}.mdi-battery-off-outline::before{content:"\F125E"}.mdi-battery-outline::before{content:"\F008E"}.mdi-battery-plus::before{content:"\F008F"}.mdi-battery-positive::before{content:"\F0090"}.mdi-battery-unknown::before{content:"\F0091"}.mdi-battery-unknown-bluetooth::before{content:"\F094A"}.mdi-battlenet::before{content:"\F0B60"}.mdi-beach::before{content:"\F0092"}.mdi-beaker::before{content:"\F0CEA"}.mdi-beaker-alert::before{content:"\F1229"}.mdi-beaker-alert-outline::before{content:"\F122A"}.mdi-beaker-check::before{content:"\F122B"}.mdi-beaker-check-outline::before{content:"\F122C"}.mdi-beaker-minus::before{content:"\F122D"}.mdi-beaker-minus-outline::before{content:"\F122E"}.mdi-beaker-outline::before{content:"\F0690"}.mdi-beaker-plus::before{content:"\F122F"}.mdi-beaker-plus-outline::before{content:"\F1230"}.mdi-beaker-question::before{content:"\F1231"}.mdi-beaker-question-outline::before{content:"\F1232"}.mdi-beaker-remove::before{content:"\F1233"}.mdi-beaker-remove-outline::before{content:"\F1234"}.mdi-bed::before{content:"\F02E3"}.mdi-bed-double::before{content:"\F0FD4"}.mdi-bed-double-outline::before{content:"\F0FD3"}.mdi-bed-empty::before{content:"\F08A0"}.mdi-bed-king::before{content:"\F0FD2"}.mdi-bed-king-outline::before{content:"\F0FD1"}.mdi-bed-outline::before{content:"\F0099"}.mdi-bed-queen::before{content:"\F0FD0"}.mdi-bed-queen-outline::before{content:"\F0FDB"}.mdi-bed-single::before{content:"\F106D"}.mdi-bed-single-outline::before{content:"\F106E"}.mdi-bee::before{content:"\F0FA1"}.mdi-bee-flower::before{content:"\F0FA2"}.mdi-beehive-off-outline::before{content:"\F13ED"}.mdi-beehive-outline::before{content:"\F10CE"}.mdi-beekeeper::before{content:"\F14E2"}.mdi-beer::before{content:"\F0098"}.mdi-beer-outline::before{content:"\F130C"}.mdi-bell::before{content:"\F009A"}.mdi-bell-alert::before{content:"\F0D59"}.mdi-bell-alert-outline::before{content:"\F0E81"}.mdi-bell-cancel::before{content:"\F13E7"}.mdi-bell-cancel-outline::before{content:"\F13E8"}.mdi-bell-check::before{content:"\F11E5"}.mdi-bell-check-outline::before{content:"\F11E6"}.mdi-bell-circle::before{content:"\F0D5A"}.mdi-bell-circle-outline::before{content:"\F0D5B"}.mdi-bell-minus::before{content:"\F13E9"}.mdi-bell-minus-outline::before{content:"\F13EA"}.mdi-bell-off::before{content:"\F009B"}.mdi-bell-off-outline::before{content:"\F0A91"}.mdi-bell-outline::before{content:"\F009C"}.mdi-bell-plus::before{content:"\F009D"}.mdi-bell-plus-outline::before{content:"\F0A92"}.mdi-bell-remove::before{content:"\F13EB"}.mdi-bell-remove-outline::before{content:"\F13EC"}.mdi-bell-ring::before{content:"\F009E"}.mdi-bell-ring-outline::before{content:"\F009F"}.mdi-bell-sleep::before{content:"\F00A0"}.mdi-bell-sleep-outline::before{content:"\F0A93"}.mdi-beta::before{content:"\F00A1"}.mdi-betamax::before{content:"\F09CB"}.mdi-biathlon::before{content:"\F0E14"}.mdi-bicycle::before{content:"\F109C"}.mdi-bicycle-basket::before{content:"\F1235"}.mdi-bicycle-electric::before{content:"\F15B4"}.mdi-bicycle-penny-farthing::before{content:"\F15E9"}.mdi-bike::before{content:"\F00A3"}.mdi-bike-fast::before{content:"\F111F"}.mdi-billboard::before{content:"\F1010"}.mdi-billiards::before{content:"\F0B61"}.mdi-billiards-rack::before{content:"\F0B62"}.mdi-binoculars::before{content:"\F00A5"}.mdi-bio::before{content:"\F00A6"}.mdi-biohazard::before{content:"\F00A7"}.mdi-bird::before{content:"\F15C6"}.mdi-bitbucket::before{content:"\F00A8"}.mdi-bitcoin::before{content:"\F0813"}.mdi-black-mesa::before{content:"\F00A9"}.mdi-blender::before{content:"\F0CEB"}.mdi-blender-software::before{content:"\F00AB"}.mdi-blinds::before{content:"\F00AC"}.mdi-blinds-open::before{content:"\F1011"}.mdi-block-helper::before{content:"\F00AD"}.mdi-blogger::before{content:"\F00AE"}.mdi-blood-bag::before{content:"\F0CEC"}.mdi-bluetooth::before{content:"\F00AF"}.mdi-bluetooth-audio::before{content:"\F00B0"}.mdi-bluetooth-connect::before{content:"\F00B1"}.mdi-bluetooth-off::before{content:"\F00B2"}.mdi-bluetooth-settings::before{content:"\F00B3"}.mdi-bluetooth-transfer::before{content:"\F00B4"}.mdi-blur::before{content:"\F00B5"}.mdi-blur-linear::before{content:"\F00B6"}.mdi-blur-off::before{content:"\F00B7"}.mdi-blur-radial::before{content:"\F00B8"}.mdi-bolnisi-cross::before{content:"\F0CED"}.mdi-bolt::before{content:"\F0DB3"}.mdi-bomb::before{content:"\F0691"}.mdi-bomb-off::before{content:"\F06C5"}.mdi-bone::before{content:"\F00B9"}.mdi-book::before{content:"\F00BA"}.mdi-book-account::before{content:"\F13AD"}.mdi-book-account-outline::before{content:"\F13AE"}.mdi-book-alert::before{content:"\F167C"}.mdi-book-alert-outline::before{content:"\F167D"}.mdi-book-alphabet::before{content:"\F061D"}.mdi-book-arrow-down::before{content:"\F167E"}.mdi-book-arrow-down-outline::before{content:"\F167F"}.mdi-book-arrow-left::before{content:"\F1680"}.mdi-book-arrow-left-outline::before{content:"\F1681"}.mdi-book-arrow-right::before{content:"\F1682"}.mdi-book-arrow-right-outline::before{content:"\F1683"}.mdi-book-arrow-up::before{content:"\F1684"}.mdi-book-arrow-up-outline::before{content:"\F1685"}.mdi-book-cancel::before{content:"\F1686"}.mdi-book-cancel-outline::before{content:"\F1687"}.mdi-book-check::before{content:"\F14F3"}.mdi-book-check-outline::before{content:"\F14F4"}.mdi-book-clock::before{content:"\F1688"}.mdi-book-clock-outline::before{content:"\F1689"}.mdi-book-cog::before{content:"\F168A"}.mdi-book-cog-outline::before{content:"\F168B"}.mdi-book-cross::before{content:"\F00A2"}.mdi-book-edit::before{content:"\F168C"}.mdi-book-edit-outline::before{content:"\F168D"}.mdi-book-education::before{content:"\F16C9"}.mdi-book-education-outline::before{content:"\F16CA"}.mdi-book-information-variant::before{content:"\F106F"}.mdi-book-lock::before{content:"\F079A"}.mdi-book-lock-open::before{content:"\F079B"}.mdi-book-lock-open-outline::before{content:"\F168E"}.mdi-book-lock-outline::before{content:"\F168F"}.mdi-book-marker::before{content:"\F1690"}.mdi-book-marker-outline::before{content:"\F1691"}.mdi-book-minus::before{content:"\F05D9"}.mdi-book-minus-multiple::before{content:"\F0A94"}.mdi-book-minus-multiple-outline::before{content:"\F090B"}.mdi-book-minus-outline::before{content:"\F1692"}.mdi-book-multiple::before{content:"\F00BB"}.mdi-book-multiple-outline::before{content:"\F0436"}.mdi-book-music::before{content:"\F0067"}.mdi-book-music-outline::before{content:"\F1693"}.mdi-book-off::before{content:"\F1694"}.mdi-book-off-outline::before{content:"\F1695"}.mdi-book-open::before{content:"\F00BD"}.mdi-book-open-blank-variant::before{content:"\F00BE"}.mdi-book-open-outline::before{content:"\F0B63"}.mdi-book-open-page-variant::before{content:"\F05DA"}.mdi-book-open-page-variant-outline::before{content:"\F15D6"}.mdi-book-open-variant::before{content:"\F14F7"}.mdi-book-outline::before{content:"\F0B64"}.mdi-book-play::before{content:"\F0E82"}.mdi-book-play-outline::before{content:"\F0E83"}.mdi-book-plus::before{content:"\F05DB"}.mdi-book-plus-multiple::before{content:"\F0A95"}.mdi-book-plus-multiple-outline::before{content:"\F0ADE"}.mdi-book-plus-outline::before{content:"\F1696"}.mdi-book-refresh::before{content:"\F1697"}.mdi-book-refresh-outline::before{content:"\F1698"}.mdi-book-remove::before{content:"\F0A97"}.mdi-book-remove-multiple::before{content:"\F0A96"}.mdi-book-remove-multiple-outline::before{content:"\F04CA"}.mdi-book-remove-outline::before{content:"\F1699"}.mdi-book-search::before{content:"\F0E84"}.mdi-book-search-outline::before{content:"\F0E85"}.mdi-book-settings::before{content:"\F169A"}.mdi-book-settings-outline::before{content:"\F169B"}.mdi-book-sync::before{content:"\F169C"}.mdi-book-sync-outline::before{content:"\F16C8"}.mdi-book-variant::before{content:"\F00BF"}.mdi-book-variant-multiple::before{content:"\F00BC"}.mdi-bookmark::before{content:"\F00C0"}.mdi-bookmark-check::before{content:"\F00C1"}.mdi-bookmark-check-outline::before{content:"\F137B"}.mdi-bookmark-minus::before{content:"\F09CC"}.mdi-bookmark-minus-outline::before{content:"\F09CD"}.mdi-bookmark-multiple::before{content:"\F0E15"}.mdi-bookmark-multiple-outline::before{content:"\F0E16"}.mdi-bookmark-music::before{content:"\F00C2"}.mdi-bookmark-music-outline::before{content:"\F1379"}.mdi-bookmark-off::before{content:"\F09CE"}.mdi-bookmark-off-outline::before{content:"\F09CF"}.mdi-bookmark-outline::before{content:"\F00C3"}.mdi-bookmark-plus::before{content:"\F00C5"}.mdi-bookmark-plus-outline::before{content:"\F00C4"}.mdi-bookmark-remove::before{content:"\F00C6"}.mdi-bookmark-remove-outline::before{content:"\F137A"}.mdi-bookshelf::before{content:"\F125F"}.mdi-boom-gate::before{content:"\F0E86"}.mdi-boom-gate-alert::before{content:"\F0E87"}.mdi-boom-gate-alert-outline::before{content:"\F0E88"}.mdi-boom-gate-down::before{content:"\F0E89"}.mdi-boom-gate-down-outline::before{content:"\F0E8A"}.mdi-boom-gate-outline::before{content:"\F0E8B"}.mdi-boom-gate-up::before{content:"\F0E8C"}.mdi-boom-gate-up-outline::before{content:"\F0E8D"}.mdi-boombox::before{content:"\F05DC"}.mdi-boomerang::before{content:"\F10CF"}.mdi-bootstrap::before{content:"\F06C6"}.mdi-border-all::before{content:"\F00C7"}.mdi-border-all-variant::before{content:"\F08A1"}.mdi-border-bottom::before{content:"\F00C8"}.mdi-border-bottom-variant::before{content:"\F08A2"}.mdi-border-color::before{content:"\F00C9"}.mdi-border-horizontal::before{content:"\F00CA"}.mdi-border-inside::before{content:"\F00CB"}.mdi-border-left::before{content:"\F00CC"}.mdi-border-left-variant::before{content:"\F08A3"}.mdi-border-none::before{content:"\F00CD"}.mdi-border-none-variant::before{content:"\F08A4"}.mdi-border-outside::before{content:"\F00CE"}.mdi-border-right::before{content:"\F00CF"}.mdi-border-right-variant::before{content:"\F08A5"}.mdi-border-style::before{content:"\F00D0"}.mdi-border-top::before{content:"\F00D1"}.mdi-border-top-variant::before{content:"\F08A6"}.mdi-border-vertical::before{content:"\F00D2"}.mdi-bottle-soda::before{content:"\F1070"}.mdi-bottle-soda-classic::before{content:"\F1071"}.mdi-bottle-soda-classic-outline::before{content:"\F1363"}.mdi-bottle-soda-outline::before{content:"\F1072"}.mdi-bottle-tonic::before{content:"\F112E"}.mdi-bottle-tonic-outline::before{content:"\F112F"}.mdi-bottle-tonic-plus::before{content:"\F1130"}.mdi-bottle-tonic-plus-outline::before{content:"\F1131"}.mdi-bottle-tonic-skull::before{content:"\F1132"}.mdi-bottle-tonic-skull-outline::before{content:"\F1133"}.mdi-bottle-wine::before{content:"\F0854"}.mdi-bottle-wine-outline::before{content:"\F1310"}.mdi-bow-tie::before{content:"\F0678"}.mdi-bowl::before{content:"\F028E"}.mdi-bowl-mix::before{content:"\F0617"}.mdi-bowl-mix-outline::before{content:"\F02E4"}.mdi-bowl-outline::before{content:"\F02A9"}.mdi-bowling::before{content:"\F00D3"}.mdi-box::before{content:"\F00D4"}.mdi-box-cutter::before{content:"\F00D5"}.mdi-box-cutter-off::before{content:"\F0B4A"}.mdi-box-shadow::before{content:"\F0637"}.mdi-boxing-glove::before{content:"\F0B65"}.mdi-braille::before{content:"\F09D0"}.mdi-brain::before{content:"\F09D1"}.mdi-bread-slice::before{content:"\F0CEE"}.mdi-bread-slice-outline::before{content:"\F0CEF"}.mdi-bridge::before{content:"\F0618"}.mdi-briefcase::before{content:"\F00D6"}.mdi-briefcase-account::before{content:"\F0CF0"}.mdi-briefcase-account-outline::before{content:"\F0CF1"}.mdi-briefcase-check::before{content:"\F00D7"}.mdi-briefcase-check-outline::before{content:"\F131E"}.mdi-briefcase-clock::before{content:"\F10D0"}.mdi-briefcase-clock-outline::before{content:"\F10D1"}.mdi-briefcase-download::before{content:"\F00D8"}.mdi-briefcase-download-outline::before{content:"\F0C3D"}.mdi-briefcase-edit::before{content:"\F0A98"}.mdi-briefcase-edit-outline::before{content:"\F0C3E"}.mdi-briefcase-minus::before{content:"\F0A2A"}.mdi-briefcase-minus-outline::before{content:"\F0C3F"}.mdi-briefcase-off::before{content:"\F1658"}.mdi-briefcase-off-outline::before{content:"\F1659"}.mdi-briefcase-outline::before{content:"\F0814"}.mdi-briefcase-plus::before{content:"\F0A2B"}.mdi-briefcase-plus-outline::before{content:"\F0C40"}.mdi-briefcase-remove::before{content:"\F0A2C"}.mdi-briefcase-remove-outline::before{content:"\F0C41"}.mdi-briefcase-search::before{content:"\F0A2D"}.mdi-briefcase-search-outline::before{content:"\F0C42"}.mdi-briefcase-upload::before{content:"\F00D9"}.mdi-briefcase-upload-outline::before{content:"\F0C43"}.mdi-briefcase-variant::before{content:"\F1494"}.mdi-briefcase-variant-off::before{content:"\F165A"}.mdi-briefcase-variant-off-outline::before{content:"\F165B"}.mdi-briefcase-variant-outline::before{content:"\F1495"}.mdi-brightness-1::before{content:"\F00DA"}.mdi-brightness-2::before{content:"\F00DB"}.mdi-brightness-3::before{content:"\F00DC"}.mdi-brightness-4::before{content:"\F00DD"}.mdi-brightness-5::before{content:"\F00DE"}.mdi-brightness-6::before{content:"\F00DF"}.mdi-brightness-7::before{content:"\F00E0"}.mdi-brightness-auto::before{content:"\F00E1"}.mdi-brightness-percent::before{content:"\F0CF2"}.mdi-broom::before{content:"\F00E2"}.mdi-brush::before{content:"\F00E3"}.mdi-bucket::before{content:"\F1415"}.mdi-bucket-outline::before{content:"\F1416"}.mdi-buddhism::before{content:"\F094B"}.mdi-buffer::before{content:"\F0619"}.mdi-buffet::before{content:"\F0578"}.mdi-bug::before{content:"\F00E4"}.mdi-bug-check::before{content:"\F0A2E"}.mdi-bug-check-outline::before{content:"\F0A2F"}.mdi-bug-outline::before{content:"\F0A30"}.mdi-bugle::before{content:"\F0DB4"}.mdi-bulldozer::before{content:"\F0B22"}.mdi-bullet::before{content:"\F0CF3"}.mdi-bulletin-board::before{content:"\F00E5"}.mdi-bullhorn::before{content:"\F00E6"}.mdi-bullhorn-outline::before{content:"\F0B23"}.mdi-bullseye::before{content:"\F05DD"}.mdi-bullseye-arrow::before{content:"\F08C9"}.mdi-bulma::before{content:"\F12E7"}.mdi-bunk-bed::before{content:"\F1302"}.mdi-bunk-bed-outline::before{content:"\F0097"}.mdi-bus::before{content:"\F00E7"}.mdi-bus-alert::before{content:"\F0A99"}.mdi-bus-articulated-end::before{content:"\F079C"}.mdi-bus-articulated-front::before{content:"\F079D"}.mdi-bus-clock::before{content:"\F08CA"}.mdi-bus-double-decker::before{content:"\F079E"}.mdi-bus-marker::before{content:"\F1212"}.mdi-bus-multiple::before{content:"\F0F3F"}.mdi-bus-school::before{content:"\F079F"}.mdi-bus-side::before{content:"\F07A0"}.mdi-bus-stop::before{content:"\F1012"}.mdi-bus-stop-covered::before{content:"\F1013"}.mdi-bus-stop-uncovered::before{content:"\F1014"}.mdi-butterfly::before{content:"\F1589"}.mdi-butterfly-outline::before{content:"\F158A"}.mdi-cable-data::before{content:"\F1394"}.mdi-cached::before{content:"\F00E8"}.mdi-cactus::before{content:"\F0DB5"}.mdi-cake::before{content:"\F00E9"}.mdi-cake-layered::before{content:"\F00EA"}.mdi-cake-variant::before{content:"\F00EB"}.mdi-calculator::before{content:"\F00EC"}.mdi-calculator-variant::before{content:"\F0A9A"}.mdi-calculator-variant-outline::before{content:"\F15A6"}.mdi-calendar::before{content:"\F00ED"}.mdi-calendar-account::before{content:"\F0ED7"}.mdi-calendar-account-outline::before{content:"\F0ED8"}.mdi-calendar-alert::before{content:"\F0A31"}.mdi-calendar-arrow-left::before{content:"\F1134"}.mdi-calendar-arrow-right::before{content:"\F1135"}.mdi-calendar-blank::before{content:"\F00EE"}.mdi-calendar-blank-multiple::before{content:"\F1073"}.mdi-calendar-blank-outline::before{content:"\F0B66"}.mdi-calendar-check::before{content:"\F00EF"}.mdi-calendar-check-outline::before{content:"\F0C44"}.mdi-calendar-clock::before{content:"\F00F0"}.mdi-calendar-cursor::before{content:"\F157B"}.mdi-calendar-edit::before{content:"\F08A7"}.mdi-calendar-end::before{content:"\F166C"}.mdi-calendar-export::before{content:"\F0B24"}.mdi-calendar-heart::before{content:"\F09D2"}.mdi-calendar-import::before{content:"\F0B25"}.mdi-calendar-lock::before{content:"\F1641"}.mdi-calendar-lock-outline::before{content:"\F1642"}.mdi-calendar-minus::before{content:"\F0D5C"}.mdi-calendar-month::before{content:"\F0E17"}.mdi-calendar-month-outline::before{content:"\F0E18"}.mdi-calendar-multiple::before{content:"\F00F1"}.mdi-calendar-multiple-check::before{content:"\F00F2"}.mdi-calendar-multiselect::before{content:"\F0A32"}.mdi-calendar-outline::before{content:"\F0B67"}.mdi-calendar-plus::before{content:"\F00F3"}.mdi-calendar-question::before{content:"\F0692"}.mdi-calendar-range::before{content:"\F0679"}.mdi-calendar-range-outline::before{content:"\F0B68"}.mdi-calendar-refresh::before{content:"\F01E1"}.mdi-calendar-refresh-outline::before{content:"\F0203"}.mdi-calendar-remove::before{content:"\F00F4"}.mdi-calendar-remove-outline::before{content:"\F0C45"}.mdi-calendar-search::before{content:"\F094C"}.mdi-calendar-star::before{content:"\F09D3"}.mdi-calendar-start::before{content:"\F166D"}.mdi-calendar-sync::before{content:"\F0E8E"}.mdi-calendar-sync-outline::before{content:"\F0E8F"}.mdi-calendar-text::before{content:"\F00F5"}.mdi-calendar-text-outline::before{content:"\F0C46"}.mdi-calendar-today::before{content:"\F00F6"}.mdi-calendar-week::before{content:"\F0A33"}.mdi-calendar-week-begin::before{content:"\F0A34"}.mdi-calendar-weekend::before{content:"\F0ED9"}.mdi-calendar-weekend-outline::before{content:"\F0EDA"}.mdi-call-made::before{content:"\F00F7"}.mdi-call-merge::before{content:"\F00F8"}.mdi-call-missed::before{content:"\F00F9"}.mdi-call-received::before{content:"\F00FA"}.mdi-call-split::before{content:"\F00FB"}.mdi-camcorder::before{content:"\F00FC"}.mdi-camcorder-off::before{content:"\F00FF"}.mdi-camera::before{content:"\F0100"}.mdi-camera-account::before{content:"\F08CB"}.mdi-camera-burst::before{content:"\F0693"}.mdi-camera-control::before{content:"\F0B69"}.mdi-camera-enhance::before{content:"\F0101"}.mdi-camera-enhance-outline::before{content:"\F0B6A"}.mdi-camera-flip::before{content:"\F15D9"}.mdi-camera-flip-outline::before{content:"\F15DA"}.mdi-camera-front::before{content:"\F0102"}.mdi-camera-front-variant::before{content:"\F0103"}.mdi-camera-gopro::before{content:"\F07A1"}.mdi-camera-image::before{content:"\F08CC"}.mdi-camera-iris::before{content:"\F0104"}.mdi-camera-metering-center::before{content:"\F07A2"}.mdi-camera-metering-matrix::before{content:"\F07A3"}.mdi-camera-metering-partial::before{content:"\F07A4"}.mdi-camera-metering-spot::before{content:"\F07A5"}.mdi-camera-off::before{content:"\F05DF"}.mdi-camera-outline::before{content:"\F0D5D"}.mdi-camera-party-mode::before{content:"\F0105"}.mdi-camera-plus::before{content:"\F0EDB"}.mdi-camera-plus-outline::before{content:"\F0EDC"}.mdi-camera-rear::before{content:"\F0106"}.mdi-camera-rear-variant::before{content:"\F0107"}.mdi-camera-retake::before{content:"\F0E19"}.mdi-camera-retake-outline::before{content:"\F0E1A"}.mdi-camera-switch::before{content:"\F0108"}.mdi-camera-switch-outline::before{content:"\F084A"}.mdi-camera-timer::before{content:"\F0109"}.mdi-camera-wireless::before{content:"\F0DB6"}.mdi-camera-wireless-outline::before{content:"\F0DB7"}.mdi-campfire::before{content:"\F0EDD"}.mdi-cancel::before{content:"\F073A"}.mdi-candle::before{content:"\F05E2"}.mdi-candycane::before{content:"\F010A"}.mdi-cannabis::before{content:"\F07A6"}.mdi-cannabis-off::before{content:"\F166E"}.mdi-caps-lock::before{content:"\F0A9B"}.mdi-car::before{content:"\F010B"}.mdi-car-2-plus::before{content:"\F1015"}.mdi-car-3-plus::before{content:"\F1016"}.mdi-car-arrow-left::before{content:"\F13B2"}.mdi-car-arrow-right::before{content:"\F13B3"}.mdi-car-back::before{content:"\F0E1B"}.mdi-car-battery::before{content:"\F010C"}.mdi-car-brake-abs::before{content:"\F0C47"}.mdi-car-brake-alert::before{content:"\F0C48"}.mdi-car-brake-hold::before{content:"\F0D5E"}.mdi-car-brake-parking::before{content:"\F0D5F"}.mdi-car-brake-retarder::before{content:"\F1017"}.mdi-car-child-seat::before{content:"\F0FA3"}.mdi-car-clutch::before{content:"\F1018"}.mdi-car-cog::before{content:"\F13CC"}.mdi-car-connected::before{content:"\F010D"}.mdi-car-convertible::before{content:"\F07A7"}.mdi-car-coolant-level::before{content:"\F1019"}.mdi-car-cruise-control::before{content:"\F0D60"}.mdi-car-defrost-front::before{content:"\F0D61"}.mdi-car-defrost-rear::before{content:"\F0D62"}.mdi-car-door::before{content:"\F0B6B"}.mdi-car-door-lock::before{content:"\F109D"}.mdi-car-electric::before{content:"\F0B6C"}.mdi-car-electric-outline::before{content:"\F15B5"}.mdi-car-emergency::before{content:"\F160F"}.mdi-car-esp::before{content:"\F0C49"}.mdi-car-estate::before{content:"\F07A8"}.mdi-car-hatchback::before{content:"\F07A9"}.mdi-car-info::before{content:"\F11BE"}.mdi-car-key::before{content:"\F0B6D"}.mdi-car-lifted-pickup::before{content:"\F152D"}.mdi-car-light-dimmed::before{content:"\F0C4A"}.mdi-car-light-fog::before{content:"\F0C4B"}.mdi-car-light-high::before{content:"\F0C4C"}.mdi-car-limousine::before{content:"\F08CD"}.mdi-car-multiple::before{content:"\F0B6E"}.mdi-car-off::before{content:"\F0E1C"}.mdi-car-outline::before{content:"\F14ED"}.mdi-car-parking-lights::before{content:"\F0D63"}.mdi-car-pickup::before{content:"\F07AA"}.mdi-car-seat::before{content:"\F0FA4"}.mdi-car-seat-cooler::before{content:"\F0FA5"}.mdi-car-seat-heater::before{content:"\F0FA6"}.mdi-car-settings::before{content:"\F13CD"}.mdi-car-shift-pattern::before{content:"\F0F40"}.mdi-car-side::before{content:"\F07AB"}.mdi-car-sports::before{content:"\F07AC"}.mdi-car-tire-alert::before{content:"\F0C4D"}.mdi-car-traction-control::before{content:"\F0D64"}.mdi-car-turbocharger::before{content:"\F101A"}.mdi-car-wash::before{content:"\F010E"}.mdi-car-windshield::before{content:"\F101B"}.mdi-car-windshield-outline::before{content:"\F101C"}.mdi-carabiner::before{content:"\F14C0"}.mdi-caravan::before{content:"\F07AD"}.mdi-card::before{content:"\F0B6F"}.mdi-card-account-details::before{content:"\F05D2"}.mdi-card-account-details-outline::before{content:"\F0DAB"}.mdi-card-account-details-star::before{content:"\F02A3"}.mdi-card-account-details-star-outline::before{content:"\F06DB"}.mdi-card-account-mail::before{content:"\F018E"}.mdi-card-account-mail-outline::before{content:"\F0E98"}.mdi-card-account-phone::before{content:"\F0E99"}.mdi-card-account-phone-outline::before{content:"\F0E9A"}.mdi-card-bulleted::before{content:"\F0B70"}.mdi-card-bulleted-off::before{content:"\F0B71"}.mdi-card-bulleted-off-outline::before{content:"\F0B72"}.mdi-card-bulleted-outline::before{content:"\F0B73"}.mdi-card-bulleted-settings::before{content:"\F0B74"}.mdi-card-bulleted-settings-outline::before{content:"\F0B75"}.mdi-card-minus::before{content:"\F1600"}.mdi-card-minus-outline::before{content:"\F1601"}.mdi-card-off::before{content:"\F1602"}.mdi-card-off-outline::before{content:"\F1603"}.mdi-card-outline::before{content:"\F0B76"}.mdi-card-plus::before{content:"\F11FF"}.mdi-card-plus-outline::before{content:"\F1200"}.mdi-card-remove::before{content:"\F1604"}.mdi-card-remove-outline::before{content:"\F1605"}.mdi-card-search::before{content:"\F1074"}.mdi-card-search-outline::before{content:"\F1075"}.mdi-card-text::before{content:"\F0B77"}.mdi-card-text-outline::before{content:"\F0B78"}.mdi-cards::before{content:"\F0638"}.mdi-cards-club::before{content:"\F08CE"}.mdi-cards-diamond::before{content:"\F08CF"}.mdi-cards-diamond-outline::before{content:"\F101D"}.mdi-cards-heart::before{content:"\F08D0"}.mdi-cards-outline::before{content:"\F0639"}.mdi-cards-playing-outline::before{content:"\F063A"}.mdi-cards-spade::before{content:"\F08D1"}.mdi-cards-variant::before{content:"\F06C7"}.mdi-carrot::before{content:"\F010F"}.mdi-cart::before{content:"\F0110"}.mdi-cart-arrow-down::before{content:"\F0D66"}.mdi-cart-arrow-right::before{content:"\F0C4E"}.mdi-cart-arrow-up::before{content:"\F0D67"}.mdi-cart-check::before{content:"\F15EA"}.mdi-cart-minus::before{content:"\F0D68"}.mdi-cart-off::before{content:"\F066B"}.mdi-cart-outline::before{content:"\F0111"}.mdi-cart-plus::before{content:"\F0112"}.mdi-cart-remove::before{content:"\F0D69"}.mdi-cart-variant::before{content:"\F15EB"}.mdi-case-sensitive-alt::before{content:"\F0113"}.mdi-cash::before{content:"\F0114"}.mdi-cash-100::before{content:"\F0115"}.mdi-cash-check::before{content:"\F14EE"}.mdi-cash-lock::before{content:"\F14EA"}.mdi-cash-lock-open::before{content:"\F14EB"}.mdi-cash-marker::before{content:"\F0DB8"}.mdi-cash-minus::before{content:"\F1260"}.mdi-cash-multiple::before{content:"\F0116"}.mdi-cash-plus::before{content:"\F1261"}.mdi-cash-refund::before{content:"\F0A9C"}.mdi-cash-register::before{content:"\F0CF4"}.mdi-cash-remove::before{content:"\F1262"}.mdi-cash-usd::before{content:"\F1176"}.mdi-cash-usd-outline::before{content:"\F0117"}.mdi-cassette::before{content:"\F09D4"}.mdi-cast::before{content:"\F0118"}.mdi-cast-audio::before{content:"\F101E"}.mdi-cast-connected::before{content:"\F0119"}.mdi-cast-education::before{content:"\F0E1D"}.mdi-cast-off::before{content:"\F078A"}.mdi-castle::before{content:"\F011A"}.mdi-cat::before{content:"\F011B"}.mdi-cctv::before{content:"\F07AE"}.mdi-ceiling-light::before{content:"\F0769"}.mdi-cellphone::before{content:"\F011C"}.mdi-cellphone-android::before{content:"\F011D"}.mdi-cellphone-arrow-down::before{content:"\F09D5"}.mdi-cellphone-basic::before{content:"\F011E"}.mdi-cellphone-charging::before{content:"\F1397"}.mdi-cellphone-cog::before{content:"\F0951"}.mdi-cellphone-dock::before{content:"\F011F"}.mdi-cellphone-erase::before{content:"\F094D"}.mdi-cellphone-information::before{content:"\F0F41"}.mdi-cellphone-iphone::before{content:"\F0120"}.mdi-cellphone-key::before{content:"\F094E"}.mdi-cellphone-link::before{content:"\F0121"}.mdi-cellphone-link-off::before{content:"\F0122"}.mdi-cellphone-lock::before{content:"\F094F"}.mdi-cellphone-message::before{content:"\F08D3"}.mdi-cellphone-message-off::before{content:"\F10D2"}.mdi-cellphone-nfc::before{content:"\F0E90"}.mdi-cellphone-nfc-off::before{content:"\F12D8"}.mdi-cellphone-off::before{content:"\F0950"}.mdi-cellphone-play::before{content:"\F101F"}.mdi-cellphone-screenshot::before{content:"\F0A35"}.mdi-cellphone-settings::before{content:"\F0123"}.mdi-cellphone-sound::before{content:"\F0952"}.mdi-cellphone-text::before{content:"\F08D2"}.mdi-cellphone-wireless::before{content:"\F0815"}.mdi-celtic-cross::before{content:"\F0CF5"}.mdi-centos::before{content:"\F111A"}.mdi-certificate::before{content:"\F0124"}.mdi-certificate-outline::before{content:"\F1188"}.mdi-chair-rolling::before{content:"\F0F48"}.mdi-chair-school::before{content:"\F0125"}.mdi-charity::before{content:"\F0C4F"}.mdi-chart-arc::before{content:"\F0126"}.mdi-chart-areaspline::before{content:"\F0127"}.mdi-chart-areaspline-variant::before{content:"\F0E91"}.mdi-chart-bar::before{content:"\F0128"}.mdi-chart-bar-stacked::before{content:"\F076A"}.mdi-chart-bell-curve::before{content:"\F0C50"}.mdi-chart-bell-curve-cumulative::before{content:"\F0FA7"}.mdi-chart-box::before{content:"\F154D"}.mdi-chart-box-outline::before{content:"\F154E"}.mdi-chart-box-plus-outline::before{content:"\F154F"}.mdi-chart-bubble::before{content:"\F05E3"}.mdi-chart-donut::before{content:"\F07AF"}.mdi-chart-donut-variant::before{content:"\F07B0"}.mdi-chart-gantt::before{content:"\F066C"}.mdi-chart-histogram::before{content:"\F0129"}.mdi-chart-line::before{content:"\F012A"}.mdi-chart-line-stacked::before{content:"\F076B"}.mdi-chart-line-variant::before{content:"\F07B1"}.mdi-chart-multiline::before{content:"\F08D4"}.mdi-chart-multiple::before{content:"\F1213"}.mdi-chart-pie::before{content:"\F012B"}.mdi-chart-ppf::before{content:"\F1380"}.mdi-chart-sankey::before{content:"\F11DF"}.mdi-chart-sankey-variant::before{content:"\F11E0"}.mdi-chart-scatter-plot::before{content:"\F0E92"}.mdi-chart-scatter-plot-hexbin::before{content:"\F066D"}.mdi-chart-timeline::before{content:"\F066E"}.mdi-chart-timeline-variant::before{content:"\F0E93"}.mdi-chart-timeline-variant-shimmer::before{content:"\F15B6"}.mdi-chart-tree::before{content:"\F0E94"}.mdi-chat::before{content:"\F0B79"}.mdi-chat-alert::before{content:"\F0B7A"}.mdi-chat-alert-outline::before{content:"\F12C9"}.mdi-chat-minus::before{content:"\F1410"}.mdi-chat-minus-outline::before{content:"\F1413"}.mdi-chat-outline::before{content:"\F0EDE"}.mdi-chat-plus::before{content:"\F140F"}.mdi-chat-plus-outline::before{content:"\F1412"}.mdi-chat-processing::before{content:"\F0B7B"}.mdi-chat-processing-outline::before{content:"\F12CA"}.mdi-chat-remove::before{content:"\F1411"}.mdi-chat-remove-outline::before{content:"\F1414"}.mdi-chat-sleep::before{content:"\F12D1"}.mdi-chat-sleep-outline::before{content:"\F12D2"}.mdi-check::before{content:"\F012C"}.mdi-check-all::before{content:"\F012D"}.mdi-check-bold::before{content:"\F0E1E"}.mdi-check-box-multiple-outline::before{content:"\F0C51"}.mdi-check-box-outline::before{content:"\F0C52"}.mdi-check-circle::before{content:"\F05E0"}.mdi-check-circle-outline::before{content:"\F05E1"}.mdi-check-decagram::before{content:"\F0791"}.mdi-check-network::before{content:"\F0C53"}.mdi-check-network-outline::before{content:"\F0C54"}.mdi-check-outline::before{content:"\F0855"}.mdi-check-underline::before{content:"\F0E1F"}.mdi-check-underline-circle::before{content:"\F0E20"}.mdi-check-underline-circle-outline::before{content:"\F0E21"}.mdi-checkbook::before{content:"\F0A9D"}.mdi-checkbox-blank::before{content:"\F012E"}.mdi-checkbox-blank-circle::before{content:"\F012F"}.mdi-checkbox-blank-circle-outline::before{content:"\F0130"}.mdi-checkbox-blank-off::before{content:"\F12EC"}.mdi-checkbox-blank-off-outline::before{content:"\F12ED"}.mdi-checkbox-blank-outline::before{content:"\F0131"}.mdi-checkbox-intermediate::before{content:"\F0856"}.mdi-checkbox-marked::before{content:"\F0132"}.mdi-checkbox-marked-circle::before{content:"\F0133"}.mdi-checkbox-marked-circle-outline::before{content:"\F0134"}.mdi-checkbox-marked-outline::before{content:"\F0135"}.mdi-checkbox-multiple-blank::before{content:"\F0136"}.mdi-checkbox-multiple-blank-circle::before{content:"\F063B"}.mdi-checkbox-multiple-blank-circle-outline::before{content:"\F063C"}.mdi-checkbox-multiple-blank-outline::before{content:"\F0137"}.mdi-checkbox-multiple-marked::before{content:"\F0138"}.mdi-checkbox-multiple-marked-circle::before{content:"\F063D"}.mdi-checkbox-multiple-marked-circle-outline::before{content:"\F063E"}.mdi-checkbox-multiple-marked-outline::before{content:"\F0139"}.mdi-checkerboard::before{content:"\F013A"}.mdi-checkerboard-minus::before{content:"\F1202"}.mdi-checkerboard-plus::before{content:"\F1201"}.mdi-checkerboard-remove::before{content:"\F1203"}.mdi-cheese::before{content:"\F12B9"}.mdi-cheese-off::before{content:"\F13EE"}.mdi-chef-hat::before{content:"\F0B7C"}.mdi-chemical-weapon::before{content:"\F013B"}.mdi-chess-bishop::before{content:"\F085C"}.mdi-chess-king::before{content:"\F0857"}.mdi-chess-knight::before{content:"\F0858"}.mdi-chess-pawn::before{content:"\F0859"}.mdi-chess-queen::before{content:"\F085A"}.mdi-chess-rook::before{content:"\F085B"}.mdi-chevron-double-down::before{content:"\F013C"}.mdi-chevron-double-left::before{content:"\F013D"}.mdi-chevron-double-right::before{content:"\F013E"}.mdi-chevron-double-up::before{content:"\F013F"}.mdi-chevron-down::before{content:"\F0140"}.mdi-chevron-down-box::before{content:"\F09D6"}.mdi-chevron-down-box-outline::before{content:"\F09D7"}.mdi-chevron-down-circle::before{content:"\F0B26"}.mdi-chevron-down-circle-outline::before{content:"\F0B27"}.mdi-chevron-left::before{content:"\F0141"}.mdi-chevron-left-box::before{content:"\F09D8"}.mdi-chevron-left-box-outline::before{content:"\F09D9"}.mdi-chevron-left-circle::before{content:"\F0B28"}.mdi-chevron-left-circle-outline::before{content:"\F0B29"}.mdi-chevron-right::before{content:"\F0142"}.mdi-chevron-right-box::before{content:"\F09DA"}.mdi-chevron-right-box-outline::before{content:"\F09DB"}.mdi-chevron-right-circle::before{content:"\F0B2A"}.mdi-chevron-right-circle-outline::before{content:"\F0B2B"}.mdi-chevron-triple-down::before{content:"\F0DB9"}.mdi-chevron-triple-left::before{content:"\F0DBA"}.mdi-chevron-triple-right::before{content:"\F0DBB"}.mdi-chevron-triple-up::before{content:"\F0DBC"}.mdi-chevron-up::before{content:"\F0143"}.mdi-chevron-up-box::before{content:"\F09DC"}.mdi-chevron-up-box-outline::before{content:"\F09DD"}.mdi-chevron-up-circle::before{content:"\F0B2C"}.mdi-chevron-up-circle-outline::before{content:"\F0B2D"}.mdi-chili-hot::before{content:"\F07B2"}.mdi-chili-medium::before{content:"\F07B3"}.mdi-chili-mild::before{content:"\F07B4"}.mdi-chili-off::before{content:"\F1467"}.mdi-chip::before{content:"\F061A"}.mdi-christianity::before{content:"\F0953"}.mdi-christianity-outline::before{content:"\F0CF6"}.mdi-church::before{content:"\F0144"}.mdi-cigar::before{content:"\F1189"}.mdi-cigar-off::before{content:"\F141B"}.mdi-circle::before{content:"\F0765"}.mdi-circle-box::before{content:"\F15DC"}.mdi-circle-box-outline::before{content:"\F15DD"}.mdi-circle-double::before{content:"\F0E95"}.mdi-circle-edit-outline::before{content:"\F08D5"}.mdi-circle-expand::before{content:"\F0E96"}.mdi-circle-half::before{content:"\F1395"}.mdi-circle-half-full::before{content:"\F1396"}.mdi-circle-medium::before{content:"\F09DE"}.mdi-circle-multiple::before{content:"\F0B38"}.mdi-circle-multiple-outline::before{content:"\F0695"}.mdi-circle-off-outline::before{content:"\F10D3"}.mdi-circle-outline::before{content:"\F0766"}.mdi-circle-slice-1::before{content:"\F0A9E"}.mdi-circle-slice-2::before{content:"\F0A9F"}.mdi-circle-slice-3::before{content:"\F0AA0"}.mdi-circle-slice-4::before{content:"\F0AA1"}.mdi-circle-slice-5::before{content:"\F0AA2"}.mdi-circle-slice-6::before{content:"\F0AA3"}.mdi-circle-slice-7::before{content:"\F0AA4"}.mdi-circle-slice-8::before{content:"\F0AA5"}.mdi-circle-small::before{content:"\F09DF"}.mdi-circular-saw::before{content:"\F0E22"}.mdi-city::before{content:"\F0146"}.mdi-city-variant::before{content:"\F0A36"}.mdi-city-variant-outline::before{content:"\F0A37"}.mdi-clipboard::before{content:"\F0147"}.mdi-clipboard-account::before{content:"\F0148"}.mdi-clipboard-account-outline::before{content:"\F0C55"}.mdi-clipboard-alert::before{content:"\F0149"}.mdi-clipboard-alert-outline::before{content:"\F0CF7"}.mdi-clipboard-arrow-down::before{content:"\F014A"}.mdi-clipboard-arrow-down-outline::before{content:"\F0C56"}.mdi-clipboard-arrow-left::before{content:"\F014B"}.mdi-clipboard-arrow-left-outline::before{content:"\F0CF8"}.mdi-clipboard-arrow-right::before{content:"\F0CF9"}.mdi-clipboard-arrow-right-outline::before{content:"\F0CFA"}.mdi-clipboard-arrow-up::before{content:"\F0C57"}.mdi-clipboard-arrow-up-outline::before{content:"\F0C58"}.mdi-clipboard-check::before{content:"\F014E"}.mdi-clipboard-check-multiple::before{content:"\F1263"}.mdi-clipboard-check-multiple-outline::before{content:"\F1264"}.mdi-clipboard-check-outline::before{content:"\F08A8"}.mdi-clipboard-edit::before{content:"\F14E5"}.mdi-clipboard-edit-outline::before{content:"\F14E6"}.mdi-clipboard-file::before{content:"\F1265"}.mdi-clipboard-file-outline::before{content:"\F1266"}.mdi-clipboard-flow::before{content:"\F06C8"}.mdi-clipboard-flow-outline::before{content:"\F1117"}.mdi-clipboard-list::before{content:"\F10D4"}.mdi-clipboard-list-outline::before{content:"\F10D5"}.mdi-clipboard-minus::before{content:"\F1618"}.mdi-clipboard-minus-outline::before{content:"\F1619"}.mdi-clipboard-multiple::before{content:"\F1267"}.mdi-clipboard-multiple-outline::before{content:"\F1268"}.mdi-clipboard-off::before{content:"\F161A"}.mdi-clipboard-off-outline::before{content:"\F161B"}.mdi-clipboard-outline::before{content:"\F014C"}.mdi-clipboard-play::before{content:"\F0C59"}.mdi-clipboard-play-multiple::before{content:"\F1269"}.mdi-clipboard-play-multiple-outline::before{content:"\F126A"}.mdi-clipboard-play-outline::before{content:"\F0C5A"}.mdi-clipboard-plus::before{content:"\F0751"}.mdi-clipboard-plus-outline::before{content:"\F131F"}.mdi-clipboard-pulse::before{content:"\F085D"}.mdi-clipboard-pulse-outline::before{content:"\F085E"}.mdi-clipboard-remove::before{content:"\F161C"}.mdi-clipboard-remove-outline::before{content:"\F161D"}.mdi-clipboard-search::before{content:"\F161E"}.mdi-clipboard-search-outline::before{content:"\F161F"}.mdi-clipboard-text::before{content:"\F014D"}.mdi-clipboard-text-multiple::before{content:"\F126B"}.mdi-clipboard-text-multiple-outline::before{content:"\F126C"}.mdi-clipboard-text-off::before{content:"\F1620"}.mdi-clipboard-text-off-outline::before{content:"\F1621"}.mdi-clipboard-text-outline::before{content:"\F0A38"}.mdi-clipboard-text-play::before{content:"\F0C5B"}.mdi-clipboard-text-play-outline::before{content:"\F0C5C"}.mdi-clipboard-text-search::before{content:"\F1622"}.mdi-clipboard-text-search-outline::before{content:"\F1623"}.mdi-clippy::before{content:"\F014F"}.mdi-clock::before{content:"\F0954"}.mdi-clock-alert::before{content:"\F0955"}.mdi-clock-alert-outline::before{content:"\F05CE"}.mdi-clock-check::before{content:"\F0FA8"}.mdi-clock-check-outline::before{content:"\F0FA9"}.mdi-clock-digital::before{content:"\F0E97"}.mdi-clock-end::before{content:"\F0151"}.mdi-clock-fast::before{content:"\F0152"}.mdi-clock-in::before{content:"\F0153"}.mdi-clock-out::before{content:"\F0154"}.mdi-clock-outline::before{content:"\F0150"}.mdi-clock-start::before{content:"\F0155"}.mdi-clock-time-eight::before{content:"\F1446"}.mdi-clock-time-eight-outline::before{content:"\F1452"}.mdi-clock-time-eleven::before{content:"\F1449"}.mdi-clock-time-eleven-outline::before{content:"\F1455"}.mdi-clock-time-five::before{content:"\F1443"}.mdi-clock-time-five-outline::before{content:"\F144F"}.mdi-clock-time-four::before{content:"\F1442"}.mdi-clock-time-four-outline::before{content:"\F144E"}.mdi-clock-time-nine::before{content:"\F1447"}.mdi-clock-time-nine-outline::before{content:"\F1453"}.mdi-clock-time-one::before{content:"\F143F"}.mdi-clock-time-one-outline::before{content:"\F144B"}.mdi-clock-time-seven::before{content:"\F1445"}.mdi-clock-time-seven-outline::before{content:"\F1451"}.mdi-clock-time-six::before{content:"\F1444"}.mdi-clock-time-six-outline::before{content:"\F1450"}.mdi-clock-time-ten::before{content:"\F1448"}.mdi-clock-time-ten-outline::before{content:"\F1454"}.mdi-clock-time-three::before{content:"\F1441"}.mdi-clock-time-three-outline::before{content:"\F144D"}.mdi-clock-time-twelve::before{content:"\F144A"}.mdi-clock-time-twelve-outline::before{content:"\F1456"}.mdi-clock-time-two::before{content:"\F1440"}.mdi-clock-time-two-outline::before{content:"\F144C"}.mdi-close::before{content:"\F0156"}.mdi-close-box::before{content:"\F0157"}.mdi-close-box-multiple::before{content:"\F0C5D"}.mdi-close-box-multiple-outline::before{content:"\F0C5E"}.mdi-close-box-outline::before{content:"\F0158"}.mdi-close-circle::before{content:"\F0159"}.mdi-close-circle-multiple::before{content:"\F062A"}.mdi-close-circle-multiple-outline::before{content:"\F0883"}.mdi-close-circle-outline::before{content:"\F015A"}.mdi-close-network::before{content:"\F015B"}.mdi-close-network-outline::before{content:"\F0C5F"}.mdi-close-octagon::before{content:"\F015C"}.mdi-close-octagon-outline::before{content:"\F015D"}.mdi-close-outline::before{content:"\F06C9"}.mdi-close-thick::before{content:"\F1398"}.mdi-closed-caption::before{content:"\F015E"}.mdi-closed-caption-outline::before{content:"\F0DBD"}.mdi-cloud::before{content:"\F015F"}.mdi-cloud-alert::before{content:"\F09E0"}.mdi-cloud-braces::before{content:"\F07B5"}.mdi-cloud-check::before{content:"\F0160"}.mdi-cloud-check-outline::before{content:"\F12CC"}.mdi-cloud-circle::before{content:"\F0161"}.mdi-cloud-download::before{content:"\F0162"}.mdi-cloud-download-outline::before{content:"\F0B7D"}.mdi-cloud-lock::before{content:"\F11F1"}.mdi-cloud-lock-outline::before{content:"\F11F2"}.mdi-cloud-off-outline::before{content:"\F0164"}.mdi-cloud-outline::before{content:"\F0163"}.mdi-cloud-print::before{content:"\F0165"}.mdi-cloud-print-outline::before{content:"\F0166"}.mdi-cloud-question::before{content:"\F0A39"}.mdi-cloud-refresh::before{content:"\F052A"}.mdi-cloud-search::before{content:"\F0956"}.mdi-cloud-search-outline::before{content:"\F0957"}.mdi-cloud-sync::before{content:"\F063F"}.mdi-cloud-sync-outline::before{content:"\F12D6"}.mdi-cloud-tags::before{content:"\F07B6"}.mdi-cloud-upload::before{content:"\F0167"}.mdi-cloud-upload-outline::before{content:"\F0B7E"}.mdi-clover::before{content:"\F0816"}.mdi-coach-lamp::before{content:"\F1020"}.mdi-coat-rack::before{content:"\F109E"}.mdi-code-array::before{content:"\F0168"}.mdi-code-braces::before{content:"\F0169"}.mdi-code-braces-box::before{content:"\F10D6"}.mdi-code-brackets::before{content:"\F016A"}.mdi-code-equal::before{content:"\F016B"}.mdi-code-greater-than::before{content:"\F016C"}.mdi-code-greater-than-or-equal::before{content:"\F016D"}.mdi-code-json::before{content:"\F0626"}.mdi-code-less-than::before{content:"\F016E"}.mdi-code-less-than-or-equal::before{content:"\F016F"}.mdi-code-not-equal::before{content:"\F0170"}.mdi-code-not-equal-variant::before{content:"\F0171"}.mdi-code-parentheses::before{content:"\F0172"}.mdi-code-parentheses-box::before{content:"\F10D7"}.mdi-code-string::before{content:"\F0173"}.mdi-code-tags::before{content:"\F0174"}.mdi-code-tags-check::before{content:"\F0694"}.mdi-codepen::before{content:"\F0175"}.mdi-coffee::before{content:"\F0176"}.mdi-coffee-maker::before{content:"\F109F"}.mdi-coffee-off::before{content:"\F0FAA"}.mdi-coffee-off-outline::before{content:"\F0FAB"}.mdi-coffee-outline::before{content:"\F06CA"}.mdi-coffee-to-go::before{content:"\F0177"}.mdi-coffee-to-go-outline::before{content:"\F130E"}.mdi-coffin::before{content:"\F0B7F"}.mdi-cog::before{content:"\F0493"}.mdi-cog-box::before{content:"\F0494"}.mdi-cog-clockwise::before{content:"\F11DD"}.mdi-cog-counterclockwise::before{content:"\F11DE"}.mdi-cog-off::before{content:"\F13CE"}.mdi-cog-off-outline::before{content:"\F13CF"}.mdi-cog-outline::before{content:"\F08BB"}.mdi-cog-refresh::before{content:"\F145E"}.mdi-cog-refresh-outline::before{content:"\F145F"}.mdi-cog-sync::before{content:"\F1460"}.mdi-cog-sync-outline::before{content:"\F1461"}.mdi-cog-transfer::before{content:"\F105B"}.mdi-cog-transfer-outline::before{content:"\F105C"}.mdi-cogs::before{content:"\F08D6"}.mdi-collage::before{content:"\F0640"}.mdi-collapse-all::before{content:"\F0AA6"}.mdi-collapse-all-outline::before{content:"\F0AA7"}.mdi-color-helper::before{content:"\F0179"}.mdi-comma::before{content:"\F0E23"}.mdi-comma-box::before{content:"\F0E2B"}.mdi-comma-box-outline::before{content:"\F0E24"}.mdi-comma-circle::before{content:"\F0E25"}.mdi-comma-circle-outline::before{content:"\F0E26"}.mdi-comment::before{content:"\F017A"}.mdi-comment-account::before{content:"\F017B"}.mdi-comment-account-outline::before{content:"\F017C"}.mdi-comment-alert::before{content:"\F017D"}.mdi-comment-alert-outline::before{content:"\F017E"}.mdi-comment-arrow-left::before{content:"\F09E1"}.mdi-comment-arrow-left-outline::before{content:"\F09E2"}.mdi-comment-arrow-right::before{content:"\F09E3"}.mdi-comment-arrow-right-outline::before{content:"\F09E4"}.mdi-comment-bookmark::before{content:"\F15AE"}.mdi-comment-bookmark-outline::before{content:"\F15AF"}.mdi-comment-check::before{content:"\F017F"}.mdi-comment-check-outline::before{content:"\F0180"}.mdi-comment-edit::before{content:"\F11BF"}.mdi-comment-edit-outline::before{content:"\F12C4"}.mdi-comment-eye::before{content:"\F0A3A"}.mdi-comment-eye-outline::before{content:"\F0A3B"}.mdi-comment-flash::before{content:"\F15B0"}.mdi-comment-flash-outline::before{content:"\F15B1"}.mdi-comment-minus::before{content:"\F15DF"}.mdi-comment-minus-outline::before{content:"\F15E0"}.mdi-comment-multiple::before{content:"\F085F"}.mdi-comment-multiple-outline::before{content:"\F0181"}.mdi-comment-off::before{content:"\F15E1"}.mdi-comment-off-outline::before{content:"\F15E2"}.mdi-comment-outline::before{content:"\F0182"}.mdi-comment-plus::before{content:"\F09E5"}.mdi-comment-plus-outline::before{content:"\F0183"}.mdi-comment-processing::before{content:"\F0184"}.mdi-comment-processing-outline::before{content:"\F0185"}.mdi-comment-question::before{content:"\F0817"}.mdi-comment-question-outline::before{content:"\F0186"}.mdi-comment-quote::before{content:"\F1021"}.mdi-comment-quote-outline::before{content:"\F1022"}.mdi-comment-remove::before{content:"\F05DE"}.mdi-comment-remove-outline::before{content:"\F0187"}.mdi-comment-search::before{content:"\F0A3C"}.mdi-comment-search-outline::before{content:"\F0A3D"}.mdi-comment-text::before{content:"\F0188"}.mdi-comment-text-multiple::before{content:"\F0860"}.mdi-comment-text-multiple-outline::before{content:"\F0861"}.mdi-comment-text-outline::before{content:"\F0189"}.mdi-compare::before{content:"\F018A"}.mdi-compare-horizontal::before{content:"\F1492"}.mdi-compare-vertical::before{content:"\F1493"}.mdi-compass::before{content:"\F018B"}.mdi-compass-off::before{content:"\F0B80"}.mdi-compass-off-outline::before{content:"\F0B81"}.mdi-compass-outline::before{content:"\F018C"}.mdi-compass-rose::before{content:"\F1382"}.mdi-concourse-ci::before{content:"\F10A0"}.mdi-connection::before{content:"\F1616"}.mdi-console::before{content:"\F018D"}.mdi-console-line::before{content:"\F07B7"}.mdi-console-network::before{content:"\F08A9"}.mdi-console-network-outline::before{content:"\F0C60"}.mdi-consolidate::before{content:"\F10D8"}.mdi-contactless-payment::before{content:"\F0D6A"}.mdi-contactless-payment-circle::before{content:"\F0321"}.mdi-contactless-payment-circle-outline::before{content:"\F0408"}.mdi-contacts::before{content:"\F06CB"}.mdi-contacts-outline::before{content:"\F05B8"}.mdi-contain::before{content:"\F0A3E"}.mdi-contain-end::before{content:"\F0A3F"}.mdi-contain-start::before{content:"\F0A40"}.mdi-content-copy::before{content:"\F018F"}.mdi-content-cut::before{content:"\F0190"}.mdi-content-duplicate::before{content:"\F0191"}.mdi-content-paste::before{content:"\F0192"}.mdi-content-save::before{content:"\F0193"}.mdi-content-save-alert::before{content:"\F0F42"}.mdi-content-save-alert-outline::before{content:"\F0F43"}.mdi-content-save-all::before{content:"\F0194"}.mdi-content-save-all-outline::before{content:"\F0F44"}.mdi-content-save-cog::before{content:"\F145B"}.mdi-content-save-cog-outline::before{content:"\F145C"}.mdi-content-save-edit::before{content:"\F0CFB"}.mdi-content-save-edit-outline::before{content:"\F0CFC"}.mdi-content-save-move::before{content:"\F0E27"}.mdi-content-save-move-outline::before{content:"\F0E28"}.mdi-content-save-off::before{content:"\F1643"}.mdi-content-save-off-outline::before{content:"\F1644"}.mdi-content-save-outline::before{content:"\F0818"}.mdi-content-save-settings::before{content:"\F061B"}.mdi-content-save-settings-outline::before{content:"\F0B2E"}.mdi-contrast::before{content:"\F0195"}.mdi-contrast-box::before{content:"\F0196"}.mdi-contrast-circle::before{content:"\F0197"}.mdi-controller-classic::before{content:"\F0B82"}.mdi-controller-classic-outline::before{content:"\F0B83"}.mdi-cookie::before{content:"\F0198"}.mdi-cookie-alert::before{content:"\F16D0"}.mdi-cookie-alert-outline::before{content:"\F16D1"}.mdi-cookie-check::before{content:"\F16D2"}.mdi-cookie-check-outline::before{content:"\F16D3"}.mdi-cookie-cog::before{content:"\F16D4"}.mdi-cookie-cog-outline::before{content:"\F16D5"}.mdi-cookie-minus::before{content:"\F16DA"}.mdi-cookie-minus-outline::before{content:"\F16DB"}.mdi-cookie-outline::before{content:"\F16DE"}.mdi-cookie-plus::before{content:"\F16D6"}.mdi-cookie-plus-outline::before{content:"\F16D7"}.mdi-cookie-remove::before{content:"\F16D8"}.mdi-cookie-remove-outline::before{content:"\F16D9"}.mdi-cookie-settings::before{content:"\F16DC"}.mdi-cookie-settings-outline::before{content:"\F16DD"}.mdi-coolant-temperature::before{content:"\F03C8"}.mdi-copyright::before{content:"\F05E6"}.mdi-cordova::before{content:"\F0958"}.mdi-corn::before{content:"\F07B8"}.mdi-corn-off::before{content:"\F13EF"}.mdi-cosine-wave::before{content:"\F1479"}.mdi-counter::before{content:"\F0199"}.mdi-cow::before{content:"\F019A"}.mdi-cpu-32-bit::before{content:"\F0EDF"}.mdi-cpu-64-bit::before{content:"\F0EE0"}.mdi-crane::before{content:"\F0862"}.mdi-creation::before{content:"\F0674"}.mdi-creative-commons::before{content:"\F0D6B"}.mdi-credit-card::before{content:"\F0FEF"}.mdi-credit-card-check::before{content:"\F13D0"}.mdi-credit-card-check-outline::before{content:"\F13D1"}.mdi-credit-card-clock::before{content:"\F0EE1"}.mdi-credit-card-clock-outline::before{content:"\F0EE2"}.mdi-credit-card-marker::before{content:"\F06A8"}.mdi-credit-card-marker-outline::before{content:"\F0DBE"}.mdi-credit-card-minus::before{content:"\F0FAC"}.mdi-credit-card-minus-outline::before{content:"\F0FAD"}.mdi-credit-card-multiple::before{content:"\F0FF0"}.mdi-credit-card-multiple-outline::before{content:"\F019C"}.mdi-credit-card-off::before{content:"\F0FF1"}.mdi-credit-card-off-outline::before{content:"\F05E4"}.mdi-credit-card-outline::before{content:"\F019B"}.mdi-credit-card-plus::before{content:"\F0FF2"}.mdi-credit-card-plus-outline::before{content:"\F0676"}.mdi-credit-card-refresh::before{content:"\F1645"}.mdi-credit-card-refresh-outline::before{content:"\F1646"}.mdi-credit-card-refund::before{content:"\F0FF3"}.mdi-credit-card-refund-outline::before{content:"\F0AA8"}.mdi-credit-card-remove::before{content:"\F0FAE"}.mdi-credit-card-remove-outline::before{content:"\F0FAF"}.mdi-credit-card-scan::before{content:"\F0FF4"}.mdi-credit-card-scan-outline::before{content:"\F019D"}.mdi-credit-card-search::before{content:"\F1647"}.mdi-credit-card-search-outline::before{content:"\F1648"}.mdi-credit-card-settings::before{content:"\F0FF5"}.mdi-credit-card-settings-outline::before{content:"\F08D7"}.mdi-credit-card-sync::before{content:"\F1649"}.mdi-credit-card-sync-outline::before{content:"\F164A"}.mdi-credit-card-wireless::before{content:"\F0802"}.mdi-credit-card-wireless-off::before{content:"\F057A"}.mdi-credit-card-wireless-off-outline::before{content:"\F057B"}.mdi-credit-card-wireless-outline::before{content:"\F0D6C"}.mdi-cricket::before{content:"\F0D6D"}.mdi-crop::before{content:"\F019E"}.mdi-crop-free::before{content:"\F019F"}.mdi-crop-landscape::before{content:"\F01A0"}.mdi-crop-portrait::before{content:"\F01A1"}.mdi-crop-rotate::before{content:"\F0696"}.mdi-crop-square::before{content:"\F01A2"}.mdi-crosshairs::before{content:"\F01A3"}.mdi-crosshairs-gps::before{content:"\F01A4"}.mdi-crosshairs-off::before{content:"\F0F45"}.mdi-crosshairs-question::before{content:"\F1136"}.mdi-crown::before{content:"\F01A5"}.mdi-crown-outline::before{content:"\F11D0"}.mdi-cryengine::before{content:"\F0959"}.mdi-crystal-ball::before{content:"\F0B2F"}.mdi-cube::before{content:"\F01A6"}.mdi-cube-off::before{content:"\F141C"}.mdi-cube-off-outline::before{content:"\F141D"}.mdi-cube-outline::before{content:"\F01A7"}.mdi-cube-scan::before{content:"\F0B84"}.mdi-cube-send::before{content:"\F01A8"}.mdi-cube-unfolded::before{content:"\F01A9"}.mdi-cup::before{content:"\F01AA"}.mdi-cup-off::before{content:"\F05E5"}.mdi-cup-off-outline::before{content:"\F137D"}.mdi-cup-outline::before{content:"\F130F"}.mdi-cup-water::before{content:"\F01AB"}.mdi-cupboard::before{content:"\F0F46"}.mdi-cupboard-outline::before{content:"\F0F47"}.mdi-cupcake::before{content:"\F095A"}.mdi-curling::before{content:"\F0863"}.mdi-currency-bdt::before{content:"\F0864"}.mdi-currency-brl::before{content:"\F0B85"}.mdi-currency-btc::before{content:"\F01AC"}.mdi-currency-cny::before{content:"\F07BA"}.mdi-currency-eth::before{content:"\F07BB"}.mdi-currency-eur::before{content:"\F01AD"}.mdi-currency-eur-off::before{content:"\F1315"}.mdi-currency-gbp::before{content:"\F01AE"}.mdi-currency-ils::before{content:"\F0C61"}.mdi-currency-inr::before{content:"\F01AF"}.mdi-currency-jpy::before{content:"\F07BC"}.mdi-currency-krw::before{content:"\F07BD"}.mdi-currency-kzt::before{content:"\F0865"}.mdi-currency-mnt::before{content:"\F1512"}.mdi-currency-ngn::before{content:"\F01B0"}.mdi-currency-php::before{content:"\F09E6"}.mdi-currency-rial::before{content:"\F0E9C"}.mdi-currency-rub::before{content:"\F01B1"}.mdi-currency-sign::before{content:"\F07BE"}.mdi-currency-try::before{content:"\F01B2"}.mdi-currency-twd::before{content:"\F07BF"}.mdi-currency-usd::before{content:"\F01C1"}.mdi-currency-usd-circle::before{content:"\F116B"}.mdi-currency-usd-circle-outline::before{content:"\F0178"}.mdi-currency-usd-off::before{content:"\F067A"}.mdi-current-ac::before{content:"\F1480"}.mdi-current-dc::before{content:"\F095C"}.mdi-cursor-default::before{content:"\F01C0"}.mdi-cursor-default-click::before{content:"\F0CFD"}.mdi-cursor-default-click-outline::before{content:"\F0CFE"}.mdi-cursor-default-gesture::before{content:"\F1127"}.mdi-cursor-default-gesture-outline::before{content:"\F1128"}.mdi-cursor-default-outline::before{content:"\F01BF"}.mdi-cursor-move::before{content:"\F01BE"}.mdi-cursor-pointer::before{content:"\F01BD"}.mdi-cursor-text::before{content:"\F05E7"}.mdi-dance-ballroom::before{content:"\F15FB"}.mdi-dance-pole::before{content:"\F1578"}.mdi-data-matrix::before{content:"\F153C"}.mdi-data-matrix-edit::before{content:"\F153D"}.mdi-data-matrix-minus::before{content:"\F153E"}.mdi-data-matrix-plus::before{content:"\F153F"}.mdi-data-matrix-remove::before{content:"\F1540"}.mdi-data-matrix-scan::before{content:"\F1541"}.mdi-database::before{content:"\F01BC"}.mdi-database-alert::before{content:"\F163A"}.mdi-database-alert-outline::before{content:"\F1624"}.mdi-database-arrow-down::before{content:"\F163B"}.mdi-database-arrow-down-outline::before{content:"\F1625"}.mdi-database-arrow-left::before{content:"\F163C"}.mdi-database-arrow-left-outline::before{content:"\F1626"}.mdi-database-arrow-right::before{content:"\F163D"}.mdi-database-arrow-right-outline::before{content:"\F1627"}.mdi-database-arrow-up::before{content:"\F163E"}.mdi-database-arrow-up-outline::before{content:"\F1628"}.mdi-database-check::before{content:"\F0AA9"}.mdi-database-check-outline::before{content:"\F1629"}.mdi-database-clock::before{content:"\F163F"}.mdi-database-clock-outline::before{content:"\F162A"}.mdi-database-cog::before{content:"\F164B"}.mdi-database-cog-outline::before{content:"\F164C"}.mdi-database-edit::before{content:"\F0B86"}.mdi-database-edit-outline::before{content:"\F162B"}.mdi-database-export::before{content:"\F095E"}.mdi-database-export-outline::before{content:"\F162C"}.mdi-database-import::before{content:"\F095D"}.mdi-database-import-outline::before{content:"\F162D"}.mdi-database-lock::before{content:"\F0AAA"}.mdi-database-lock-outline::before{content:"\F162E"}.mdi-database-marker::before{content:"\F12F6"}.mdi-database-marker-outline::before{content:"\F162F"}.mdi-database-minus::before{content:"\F01BB"}.mdi-database-minus-outline::before{content:"\F1630"}.mdi-database-off::before{content:"\F1640"}.mdi-database-off-outline::before{content:"\F1631"}.mdi-database-outline::before{content:"\F1632"}.mdi-database-plus::before{content:"\F01BA"}.mdi-database-plus-outline::before{content:"\F1633"}.mdi-database-refresh::before{content:"\F05C2"}.mdi-database-refresh-outline::before{content:"\F1634"}.mdi-database-remove::before{content:"\F0D00"}.mdi-database-remove-outline::before{content:"\F1635"}.mdi-database-search::before{content:"\F0866"}.mdi-database-search-outline::before{content:"\F1636"}.mdi-database-settings::before{content:"\F0D01"}.mdi-database-settings-outline::before{content:"\F1637"}.mdi-database-sync::before{content:"\F0CFF"}.mdi-database-sync-outline::before{content:"\F1638"}.mdi-death-star::before{content:"\F08D8"}.mdi-death-star-variant::before{content:"\F08D9"}.mdi-deathly-hallows::before{content:"\F0B87"}.mdi-debian::before{content:"\F08DA"}.mdi-debug-step-into::before{content:"\F01B9"}.mdi-debug-step-out::before{content:"\F01B8"}.mdi-debug-step-over::before{content:"\F01B7"}.mdi-decagram::before{content:"\F076C"}.mdi-decagram-outline::before{content:"\F076D"}.mdi-decimal::before{content:"\F10A1"}.mdi-decimal-comma::before{content:"\F10A2"}.mdi-decimal-comma-decrease::before{content:"\F10A3"}.mdi-decimal-comma-increase::before{content:"\F10A4"}.mdi-decimal-decrease::before{content:"\F01B6"}.mdi-decimal-increase::before{content:"\F01B5"}.mdi-delete::before{content:"\F01B4"}.mdi-delete-alert::before{content:"\F10A5"}.mdi-delete-alert-outline::before{content:"\F10A6"}.mdi-delete-circle::before{content:"\F0683"}.mdi-delete-circle-outline::before{content:"\F0B88"}.mdi-delete-clock::before{content:"\F1556"}.mdi-delete-clock-outline::before{content:"\F1557"}.mdi-delete-empty::before{content:"\F06CC"}.mdi-delete-empty-outline::before{content:"\F0E9D"}.mdi-delete-forever::before{content:"\F05E8"}.mdi-delete-forever-outline::before{content:"\F0B89"}.mdi-delete-off::before{content:"\F10A7"}.mdi-delete-off-outline::before{content:"\F10A8"}.mdi-delete-outline::before{content:"\F09E7"}.mdi-delete-restore::before{content:"\F0819"}.mdi-delete-sweep::before{content:"\F05E9"}.mdi-delete-sweep-outline::before{content:"\F0C62"}.mdi-delete-variant::before{content:"\F01B3"}.mdi-delta::before{content:"\F01C2"}.mdi-desk::before{content:"\F1239"}.mdi-desk-lamp::before{content:"\F095F"}.mdi-deskphone::before{content:"\F01C3"}.mdi-desktop-classic::before{content:"\F07C0"}.mdi-desktop-mac::before{content:"\F01C4"}.mdi-desktop-mac-dashboard::before{content:"\F09E8"}.mdi-desktop-tower::before{content:"\F01C5"}.mdi-desktop-tower-monitor::before{content:"\F0AAB"}.mdi-details::before{content:"\F01C6"}.mdi-dev-to::before{content:"\F0D6E"}.mdi-developer-board::before{content:"\F0697"}.mdi-deviantart::before{content:"\F01C7"}.mdi-devices::before{content:"\F0FB0"}.mdi-diabetes::before{content:"\F1126"}.mdi-dialpad::before{content:"\F061C"}.mdi-diameter::before{content:"\F0C63"}.mdi-diameter-outline::before{content:"\F0C64"}.mdi-diameter-variant::before{content:"\F0C65"}.mdi-diamond::before{content:"\F0B8A"}.mdi-diamond-outline::before{content:"\F0B8B"}.mdi-diamond-stone::before{content:"\F01C8"}.mdi-dice-1::before{content:"\F01CA"}.mdi-dice-1-outline::before{content:"\F114A"}.mdi-dice-2::before{content:"\F01CB"}.mdi-dice-2-outline::before{content:"\F114B"}.mdi-dice-3::before{content:"\F01CC"}.mdi-dice-3-outline::before{content:"\F114C"}.mdi-dice-4::before{content:"\F01CD"}.mdi-dice-4-outline::before{content:"\F114D"}.mdi-dice-5::before{content:"\F01CE"}.mdi-dice-5-outline::before{content:"\F114E"}.mdi-dice-6::before{content:"\F01CF"}.mdi-dice-6-outline::before{content:"\F114F"}.mdi-dice-d10::before{content:"\F1153"}.mdi-dice-d10-outline::before{content:"\F076F"}.mdi-dice-d12::before{content:"\F1154"}.mdi-dice-d12-outline::before{content:"\F0867"}.mdi-dice-d20::before{content:"\F1155"}.mdi-dice-d20-outline::before{content:"\F05EA"}.mdi-dice-d4::before{content:"\F1150"}.mdi-dice-d4-outline::before{content:"\F05EB"}.mdi-dice-d6::before{content:"\F1151"}.mdi-dice-d6-outline::before{content:"\F05ED"}.mdi-dice-d8::before{content:"\F1152"}.mdi-dice-d8-outline::before{content:"\F05EC"}.mdi-dice-multiple::before{content:"\F076E"}.mdi-dice-multiple-outline::before{content:"\F1156"}.mdi-digital-ocean::before{content:"\F1237"}.mdi-dip-switch::before{content:"\F07C1"}.mdi-directions::before{content:"\F01D0"}.mdi-directions-fork::before{content:"\F0641"}.mdi-disc::before{content:"\F05EE"}.mdi-disc-alert::before{content:"\F01D1"}.mdi-disc-player::before{content:"\F0960"}.mdi-discord::before{content:"\F066F"}.mdi-dishwasher::before{content:"\F0AAC"}.mdi-dishwasher-alert::before{content:"\F11B8"}.mdi-dishwasher-off::before{content:"\F11B9"}.mdi-disqus::before{content:"\F01D2"}.mdi-distribute-horizontal-center::before{content:"\F11C9"}.mdi-distribute-horizontal-left::before{content:"\F11C8"}.mdi-distribute-horizontal-right::before{content:"\F11CA"}.mdi-distribute-vertical-bottom::before{content:"\F11CB"}.mdi-distribute-vertical-center::before{content:"\F11CC"}.mdi-distribute-vertical-top::before{content:"\F11CD"}.mdi-diving-flippers::before{content:"\F0DBF"}.mdi-diving-helmet::before{content:"\F0DC0"}.mdi-diving-scuba::before{content:"\F0DC1"}.mdi-diving-scuba-flag::before{content:"\F0DC2"}.mdi-diving-scuba-tank::before{content:"\F0DC3"}.mdi-diving-scuba-tank-multiple::before{content:"\F0DC4"}.mdi-diving-snorkel::before{content:"\F0DC5"}.mdi-division::before{content:"\F01D4"}.mdi-division-box::before{content:"\F01D5"}.mdi-dlna::before{content:"\F0A41"}.mdi-dna::before{content:"\F0684"}.mdi-dns::before{content:"\F01D6"}.mdi-dns-outline::before{content:"\F0B8C"}.mdi-do-not-disturb::before{content:"\F0698"}.mdi-do-not-disturb-off::before{content:"\F0699"}.mdi-dock-bottom::before{content:"\F10A9"}.mdi-dock-left::before{content:"\F10AA"}.mdi-dock-right::before{content:"\F10AB"}.mdi-dock-top::before{content:"\F1513"}.mdi-dock-window::before{content:"\F10AC"}.mdi-docker::before{content:"\F0868"}.mdi-doctor::before{content:"\F0A42"}.mdi-dog::before{content:"\F0A43"}.mdi-dog-service::before{content:"\F0AAD"}.mdi-dog-side::before{content:"\F0A44"}.mdi-dolby::before{content:"\F06B3"}.mdi-dolly::before{content:"\F0E9E"}.mdi-domain::before{content:"\F01D7"}.mdi-domain-off::before{content:"\F0D6F"}.mdi-domain-plus::before{content:"\F10AD"}.mdi-domain-remove::before{content:"\F10AE"}.mdi-dome-light::before{content:"\F141E"}.mdi-domino-mask::before{content:"\F1023"}.mdi-donkey::before{content:"\F07C2"}.mdi-door::before{content:"\F081A"}.mdi-door-closed::before{content:"\F081B"}.mdi-door-closed-lock::before{content:"\F10AF"}.mdi-door-open::before{content:"\F081C"}.mdi-doorbell::before{content:"\F12E6"}.mdi-doorbell-video::before{content:"\F0869"}.mdi-dot-net::before{content:"\F0AAE"}.mdi-dots-grid::before{content:"\F15FC"}.mdi-dots-hexagon::before{content:"\F15FF"}.mdi-dots-horizontal::before{content:"\F01D8"}.mdi-dots-horizontal-circle::before{content:"\F07C3"}.mdi-dots-horizontal-circle-outline::before{content:"\F0B8D"}.mdi-dots-square::before{content:"\F15FD"}.mdi-dots-triangle::before{content:"\F15FE"}.mdi-dots-vertical::before{content:"\F01D9"}.mdi-dots-vertical-circle::before{content:"\F07C4"}.mdi-dots-vertical-circle-outline::before{content:"\F0B8E"}.mdi-douban::before{content:"\F069A"}.mdi-download::before{content:"\F01DA"}.mdi-download-box::before{content:"\F1462"}.mdi-download-box-outline::before{content:"\F1463"}.mdi-download-circle::before{content:"\F1464"}.mdi-download-circle-outline::before{content:"\F1465"}.mdi-download-lock::before{content:"\F1320"}.mdi-download-lock-outline::before{content:"\F1321"}.mdi-download-multiple::before{content:"\F09E9"}.mdi-download-network::before{content:"\F06F4"}.mdi-download-network-outline::before{content:"\F0C66"}.mdi-download-off::before{content:"\F10B0"}.mdi-download-off-outline::before{content:"\F10B1"}.mdi-download-outline::before{content:"\F0B8F"}.mdi-drag::before{content:"\F01DB"}.mdi-drag-horizontal::before{content:"\F01DC"}.mdi-drag-horizontal-variant::before{content:"\F12F0"}.mdi-drag-variant::before{content:"\F0B90"}.mdi-drag-vertical::before{content:"\F01DD"}.mdi-drag-vertical-variant::before{content:"\F12F1"}.mdi-drama-masks::before{content:"\F0D02"}.mdi-draw::before{content:"\F0F49"}.mdi-drawing::before{content:"\F01DE"}.mdi-drawing-box::before{content:"\F01DF"}.mdi-dresser::before{content:"\F0F4A"}.mdi-dresser-outline::before{content:"\F0F4B"}.mdi-drone::before{content:"\F01E2"}.mdi-dropbox::before{content:"\F01E3"}.mdi-drupal::before{content:"\F01E4"}.mdi-duck::before{content:"\F01E5"}.mdi-dumbbell::before{content:"\F01E6"}.mdi-dump-truck::before{content:"\F0C67"}.mdi-ear-hearing::before{content:"\F07C5"}.mdi-ear-hearing-off::before{content:"\F0A45"}.mdi-earth::before{content:"\F01E7"}.mdi-earth-arrow-right::before{content:"\F1311"}.mdi-earth-box::before{content:"\F06CD"}.mdi-earth-box-minus::before{content:"\F1407"}.mdi-earth-box-off::before{content:"\F06CE"}.mdi-earth-box-plus::before{content:"\F1406"}.mdi-earth-box-remove::before{content:"\F1408"}.mdi-earth-minus::before{content:"\F1404"}.mdi-earth-off::before{content:"\F01E8"}.mdi-earth-plus::before{content:"\F1403"}.mdi-earth-remove::before{content:"\F1405"}.mdi-egg::before{content:"\F0AAF"}.mdi-egg-easter::before{content:"\F0AB0"}.mdi-egg-off::before{content:"\F13F0"}.mdi-egg-off-outline::before{content:"\F13F1"}.mdi-egg-outline::before{content:"\F13F2"}.mdi-eiffel-tower::before{content:"\F156B"}.mdi-eight-track::before{content:"\F09EA"}.mdi-eject::before{content:"\F01EA"}.mdi-eject-outline::before{content:"\F0B91"}.mdi-electric-switch::before{content:"\F0E9F"}.mdi-electric-switch-closed::before{content:"\F10D9"}.mdi-electron-framework::before{content:"\F1024"}.mdi-elephant::before{content:"\F07C6"}.mdi-elevation-decline::before{content:"\F01EB"}.mdi-elevation-rise::before{content:"\F01EC"}.mdi-elevator::before{content:"\F01ED"}.mdi-elevator-down::before{content:"\F12C2"}.mdi-elevator-passenger::before{content:"\F1381"}.mdi-elevator-up::before{content:"\F12C1"}.mdi-ellipse::before{content:"\F0EA0"}.mdi-ellipse-outline::before{content:"\F0EA1"}.mdi-email::before{content:"\F01EE"}.mdi-email-alert::before{content:"\F06CF"}.mdi-email-alert-outline::before{content:"\F0D42"}.mdi-email-box::before{content:"\F0D03"}.mdi-email-check::before{content:"\F0AB1"}.mdi-email-check-outline::before{content:"\F0AB2"}.mdi-email-edit::before{content:"\F0EE3"}.mdi-email-edit-outline::before{content:"\F0EE4"}.mdi-email-lock::before{content:"\F01F1"}.mdi-email-mark-as-unread::before{content:"\F0B92"}.mdi-email-minus::before{content:"\F0EE5"}.mdi-email-minus-outline::before{content:"\F0EE6"}.mdi-email-multiple::before{content:"\F0EE7"}.mdi-email-multiple-outline::before{content:"\F0EE8"}.mdi-email-newsletter::before{content:"\F0FB1"}.mdi-email-off::before{content:"\F13E3"}.mdi-email-off-outline::before{content:"\F13E4"}.mdi-email-open::before{content:"\F01EF"}.mdi-email-open-multiple::before{content:"\F0EE9"}.mdi-email-open-multiple-outline::before{content:"\F0EEA"}.mdi-email-open-outline::before{content:"\F05EF"}.mdi-email-outline::before{content:"\F01F0"}.mdi-email-plus::before{content:"\F09EB"}.mdi-email-plus-outline::before{content:"\F09EC"}.mdi-email-receive::before{content:"\F10DA"}.mdi-email-receive-outline::before{content:"\F10DB"}.mdi-email-remove::before{content:"\F1661"}.mdi-email-remove-outline::before{content:"\F1662"}.mdi-email-search::before{content:"\F0961"}.mdi-email-search-outline::before{content:"\F0962"}.mdi-email-send::before{content:"\F10DC"}.mdi-email-send-outline::before{content:"\F10DD"}.mdi-email-sync::before{content:"\F12C7"}.mdi-email-sync-outline::before{content:"\F12C8"}.mdi-email-variant::before{content:"\F05F0"}.mdi-ember::before{content:"\F0B30"}.mdi-emby::before{content:"\F06B4"}.mdi-emoticon::before{content:"\F0C68"}.mdi-emoticon-angry::before{content:"\F0C69"}.mdi-emoticon-angry-outline::before{content:"\F0C6A"}.mdi-emoticon-confused::before{content:"\F10DE"}.mdi-emoticon-confused-outline::before{content:"\F10DF"}.mdi-emoticon-cool::before{content:"\F0C6B"}.mdi-emoticon-cool-outline::before{content:"\F01F3"}.mdi-emoticon-cry::before{content:"\F0C6C"}.mdi-emoticon-cry-outline::before{content:"\F0C6D"}.mdi-emoticon-dead::before{content:"\F0C6E"}.mdi-emoticon-dead-outline::before{content:"\F069B"}.mdi-emoticon-devil::before{content:"\F0C6F"}.mdi-emoticon-devil-outline::before{content:"\F01F4"}.mdi-emoticon-excited::before{content:"\F0C70"}.mdi-emoticon-excited-outline::before{content:"\F069C"}.mdi-emoticon-frown::before{content:"\F0F4C"}.mdi-emoticon-frown-outline::before{content:"\F0F4D"}.mdi-emoticon-happy::before{content:"\F0C71"}.mdi-emoticon-happy-outline::before{content:"\F01F5"}.mdi-emoticon-kiss::before{content:"\F0C72"}.mdi-emoticon-kiss-outline::before{content:"\F0C73"}.mdi-emoticon-lol::before{content:"\F1214"}.mdi-emoticon-lol-outline::before{content:"\F1215"}.mdi-emoticon-neutral::before{content:"\F0C74"}.mdi-emoticon-neutral-outline::before{content:"\F01F6"}.mdi-emoticon-outline::before{content:"\F01F2"}.mdi-emoticon-poop::before{content:"\F01F7"}.mdi-emoticon-poop-outline::before{content:"\F0C75"}.mdi-emoticon-sad::before{content:"\F0C76"}.mdi-emoticon-sad-outline::before{content:"\F01F8"}.mdi-emoticon-sick::before{content:"\F157C"}.mdi-emoticon-sick-outline::before{content:"\F157D"}.mdi-emoticon-tongue::before{content:"\F01F9"}.mdi-emoticon-tongue-outline::before{content:"\F0C77"}.mdi-emoticon-wink::before{content:"\F0C78"}.mdi-emoticon-wink-outline::before{content:"\F0C79"}.mdi-engine::before{content:"\F01FA"}.mdi-engine-off::before{content:"\F0A46"}.mdi-engine-off-outline::before{content:"\F0A47"}.mdi-engine-outline::before{content:"\F01FB"}.mdi-epsilon::before{content:"\F10E0"}.mdi-equal::before{content:"\F01FC"}.mdi-equal-box::before{content:"\F01FD"}.mdi-equalizer::before{content:"\F0EA2"}.mdi-equalizer-outline::before{content:"\F0EA3"}.mdi-eraser::before{content:"\F01FE"}.mdi-eraser-variant::before{content:"\F0642"}.mdi-escalator::before{content:"\F01FF"}.mdi-escalator-box::before{content:"\F1399"}.mdi-escalator-down::before{content:"\F12C0"}.mdi-escalator-up::before{content:"\F12BF"}.mdi-eslint::before{content:"\F0C7A"}.mdi-et::before{content:"\F0AB3"}.mdi-ethereum::before{content:"\F086A"}.mdi-ethernet::before{content:"\F0200"}.mdi-ethernet-cable::before{content:"\F0201"}.mdi-ethernet-cable-off::before{content:"\F0202"}.mdi-ev-plug-ccs1::before{content:"\F1519"}.mdi-ev-plug-ccs2::before{content:"\F151A"}.mdi-ev-plug-chademo::before{content:"\F151B"}.mdi-ev-plug-tesla::before{content:"\F151C"}.mdi-ev-plug-type1::before{content:"\F151D"}.mdi-ev-plug-type2::before{content:"\F151E"}.mdi-ev-station::before{content:"\F05F1"}.mdi-evernote::before{content:"\F0204"}.mdi-excavator::before{content:"\F1025"}.mdi-exclamation::before{content:"\F0205"}.mdi-exclamation-thick::before{content:"\F1238"}.mdi-exit-run::before{content:"\F0A48"}.mdi-exit-to-app::before{content:"\F0206"}.mdi-expand-all::before{content:"\F0AB4"}.mdi-expand-all-outline::before{content:"\F0AB5"}.mdi-expansion-card::before{content:"\F08AE"}.mdi-expansion-card-variant::before{content:"\F0FB2"}.mdi-exponent::before{content:"\F0963"}.mdi-exponent-box::before{content:"\F0964"}.mdi-export::before{content:"\F0207"}.mdi-export-variant::before{content:"\F0B93"}.mdi-eye::before{content:"\F0208"}.mdi-eye-check::before{content:"\F0D04"}.mdi-eye-check-outline::before{content:"\F0D05"}.mdi-eye-circle::before{content:"\F0B94"}.mdi-eye-circle-outline::before{content:"\F0B95"}.mdi-eye-minus::before{content:"\F1026"}.mdi-eye-minus-outline::before{content:"\F1027"}.mdi-eye-off::before{content:"\F0209"}.mdi-eye-off-outline::before{content:"\F06D1"}.mdi-eye-outline::before{content:"\F06D0"}.mdi-eye-plus::before{content:"\F086B"}.mdi-eye-plus-outline::before{content:"\F086C"}.mdi-eye-remove::before{content:"\F15E3"}.mdi-eye-remove-outline::before{content:"\F15E4"}.mdi-eye-settings::before{content:"\F086D"}.mdi-eye-settings-outline::before{content:"\F086E"}.mdi-eyedropper::before{content:"\F020A"}.mdi-eyedropper-minus::before{content:"\F13DD"}.mdi-eyedropper-off::before{content:"\F13DF"}.mdi-eyedropper-plus::before{content:"\F13DC"}.mdi-eyedropper-remove::before{content:"\F13DE"}.mdi-eyedropper-variant::before{content:"\F020B"}.mdi-face::before{content:"\F0643"}.mdi-face-agent::before{content:"\F0D70"}.mdi-face-mask::before{content:"\F1586"}.mdi-face-mask-outline::before{content:"\F1587"}.mdi-face-outline::before{content:"\F0B96"}.mdi-face-profile::before{content:"\F0644"}.mdi-face-profile-woman::before{content:"\F1076"}.mdi-face-recognition::before{content:"\F0C7B"}.mdi-face-shimmer::before{content:"\F15CC"}.mdi-face-shimmer-outline::before{content:"\F15CD"}.mdi-face-woman::before{content:"\F1077"}.mdi-face-woman-outline::before{content:"\F1078"}.mdi-face-woman-shimmer::before{content:"\F15CE"}.mdi-face-woman-shimmer-outline::before{content:"\F15CF"}.mdi-facebook::before{content:"\F020C"}.mdi-facebook-gaming::before{content:"\F07DD"}.mdi-facebook-messenger::before{content:"\F020E"}.mdi-facebook-workplace::before{content:"\F0B31"}.mdi-factory::before{content:"\F020F"}.mdi-family-tree::before{content:"\F160E"}.mdi-fan::before{content:"\F0210"}.mdi-fan-alert::before{content:"\F146C"}.mdi-fan-chevron-down::before{content:"\F146D"}.mdi-fan-chevron-up::before{content:"\F146E"}.mdi-fan-minus::before{content:"\F1470"}.mdi-fan-off::before{content:"\F081D"}.mdi-fan-plus::before{content:"\F146F"}.mdi-fan-remove::before{content:"\F1471"}.mdi-fan-speed-1::before{content:"\F1472"}.mdi-fan-speed-2::before{content:"\F1473"}.mdi-fan-speed-3::before{content:"\F1474"}.mdi-fast-forward::before{content:"\F0211"}.mdi-fast-forward-10::before{content:"\F0D71"}.mdi-fast-forward-30::before{content:"\F0D06"}.mdi-fast-forward-5::before{content:"\F11F8"}.mdi-fast-forward-60::before{content:"\F160B"}.mdi-fast-forward-outline::before{content:"\F06D2"}.mdi-fax::before{content:"\F0212"}.mdi-feather::before{content:"\F06D3"}.mdi-feature-search::before{content:"\F0A49"}.mdi-feature-search-outline::before{content:"\F0A4A"}.mdi-fedora::before{content:"\F08DB"}.mdi-fencing::before{content:"\F14C1"}.mdi-ferris-wheel::before{content:"\F0EA4"}.mdi-ferry::before{content:"\F0213"}.mdi-file::before{content:"\F0214"}.mdi-file-account::before{content:"\F073B"}.mdi-file-account-outline::before{content:"\F1028"}.mdi-file-alert::before{content:"\F0A4B"}.mdi-file-alert-outline::before{content:"\F0A4C"}.mdi-file-cabinet::before{content:"\F0AB6"}.mdi-file-cad::before{content:"\F0EEB"}.mdi-file-cad-box::before{content:"\F0EEC"}.mdi-file-cancel::before{content:"\F0DC6"}.mdi-file-cancel-outline::before{content:"\F0DC7"}.mdi-file-certificate::before{content:"\F1186"}.mdi-file-certificate-outline::before{content:"\F1187"}.mdi-file-chart::before{content:"\F0215"}.mdi-file-chart-outline::before{content:"\F1029"}.mdi-file-check::before{content:"\F0216"}.mdi-file-check-outline::before{content:"\F0E29"}.mdi-file-clock::before{content:"\F12E1"}.mdi-file-clock-outline::before{content:"\F12E2"}.mdi-file-cloud::before{content:"\F0217"}.mdi-file-cloud-outline::before{content:"\F102A"}.mdi-file-code::before{content:"\F022E"}.mdi-file-code-outline::before{content:"\F102B"}.mdi-file-cog::before{content:"\F107B"}.mdi-file-cog-outline::before{content:"\F107C"}.mdi-file-compare::before{content:"\F08AA"}.mdi-file-delimited::before{content:"\F0218"}.mdi-file-delimited-outline::before{content:"\F0EA5"}.mdi-file-document::before{content:"\F0219"}.mdi-file-document-edit::before{content:"\F0DC8"}.mdi-file-document-edit-outline::before{content:"\F0DC9"}.mdi-file-document-multiple::before{content:"\F1517"}.mdi-file-document-multiple-outline::before{content:"\F1518"}.mdi-file-document-outline::before{content:"\F09EE"}.mdi-file-download::before{content:"\F0965"}.mdi-file-download-outline::before{content:"\F0966"}.mdi-file-edit::before{content:"\F11E7"}.mdi-file-edit-outline::before{content:"\F11E8"}.mdi-file-excel::before{content:"\F021B"}.mdi-file-excel-box::before{content:"\F021C"}.mdi-file-excel-box-outline::before{content:"\F102C"}.mdi-file-excel-outline::before{content:"\F102D"}.mdi-file-export::before{content:"\F021D"}.mdi-file-export-outline::before{content:"\F102E"}.mdi-file-eye::before{content:"\F0DCA"}.mdi-file-eye-outline::before{content:"\F0DCB"}.mdi-file-find::before{content:"\F021E"}.mdi-file-find-outline::before{content:"\F0B97"}.mdi-file-hidden::before{content:"\F0613"}.mdi-file-image::before{content:"\F021F"}.mdi-file-image-outline::before{content:"\F0EB0"}.mdi-file-import::before{content:"\F0220"}.mdi-file-import-outline::before{content:"\F102F"}.mdi-file-key::before{content:"\F1184"}.mdi-file-key-outline::before{content:"\F1185"}.mdi-file-link::before{content:"\F1177"}.mdi-file-link-outline::before{content:"\F1178"}.mdi-file-lock::before{content:"\F0221"}.mdi-file-lock-outline::before{content:"\F1030"}.mdi-file-move::before{content:"\F0AB9"}.mdi-file-move-outline::before{content:"\F1031"}.mdi-file-multiple::before{content:"\F0222"}.mdi-file-multiple-outline::before{content:"\F1032"}.mdi-file-music::before{content:"\F0223"}.mdi-file-music-outline::before{content:"\F0E2A"}.mdi-file-outline::before{content:"\F0224"}.mdi-file-pdf::before{content:"\F0225"}.mdi-file-pdf-box::before{content:"\F0226"}.mdi-file-pdf-box-outline::before{content:"\F0FB3"}.mdi-file-pdf-outline::before{content:"\F0E2D"}.mdi-file-percent::before{content:"\F081E"}.mdi-file-percent-outline::before{content:"\F1033"}.mdi-file-phone::before{content:"\F1179"}.mdi-file-phone-outline::before{content:"\F117A"}.mdi-file-plus::before{content:"\F0752"}.mdi-file-plus-outline::before{content:"\F0EED"}.mdi-file-powerpoint::before{content:"\F0227"}.mdi-file-powerpoint-box::before{content:"\F0228"}.mdi-file-powerpoint-box-outline::before{content:"\F1034"}.mdi-file-powerpoint-outline::before{content:"\F1035"}.mdi-file-presentation-box::before{content:"\F0229"}.mdi-file-question::before{content:"\F086F"}.mdi-file-question-outline::before{content:"\F1036"}.mdi-file-refresh::before{content:"\F0918"}.mdi-file-refresh-outline::before{content:"\F0541"}.mdi-file-remove::before{content:"\F0B98"}.mdi-file-remove-outline::before{content:"\F1037"}.mdi-file-replace::before{content:"\F0B32"}.mdi-file-replace-outline::before{content:"\F0B33"}.mdi-file-restore::before{content:"\F0670"}.mdi-file-restore-outline::before{content:"\F1038"}.mdi-file-search::before{content:"\F0C7C"}.mdi-file-search-outline::before{content:"\F0C7D"}.mdi-file-send::before{content:"\F022A"}.mdi-file-send-outline::before{content:"\F1039"}.mdi-file-settings::before{content:"\F1079"}.mdi-file-settings-outline::before{content:"\F107A"}.mdi-file-star::before{content:"\F103A"}.mdi-file-star-outline::before{content:"\F103B"}.mdi-file-swap::before{content:"\F0FB4"}.mdi-file-swap-outline::before{content:"\F0FB5"}.mdi-file-sync::before{content:"\F1216"}.mdi-file-sync-outline::before{content:"\F1217"}.mdi-file-table::before{content:"\F0C7E"}.mdi-file-table-box::before{content:"\F10E1"}.mdi-file-table-box-multiple::before{content:"\F10E2"}.mdi-file-table-box-multiple-outline::before{content:"\F10E3"}.mdi-file-table-box-outline::before{content:"\F10E4"}.mdi-file-table-outline::before{content:"\F0C7F"}.mdi-file-tree::before{content:"\F0645"}.mdi-file-tree-outline::before{content:"\F13D2"}.mdi-file-undo::before{content:"\F08DC"}.mdi-file-undo-outline::before{content:"\F103C"}.mdi-file-upload::before{content:"\F0A4D"}.mdi-file-upload-outline::before{content:"\F0A4E"}.mdi-file-video::before{content:"\F022B"}.mdi-file-video-outline::before{content:"\F0E2C"}.mdi-file-word::before{content:"\F022C"}.mdi-file-word-box::before{content:"\F022D"}.mdi-file-word-box-outline::before{content:"\F103D"}.mdi-file-word-outline::before{content:"\F103E"}.mdi-film::before{content:"\F022F"}.mdi-filmstrip::before{content:"\F0230"}.mdi-filmstrip-box::before{content:"\F0332"}.mdi-filmstrip-box-multiple::before{content:"\F0D18"}.mdi-filmstrip-off::before{content:"\F0231"}.mdi-filter::before{content:"\F0232"}.mdi-filter-menu::before{content:"\F10E5"}.mdi-filter-menu-outline::before{content:"\F10E6"}.mdi-filter-minus::before{content:"\F0EEE"}.mdi-filter-minus-outline::before{content:"\F0EEF"}.mdi-filter-off::before{content:"\F14EF"}.mdi-filter-off-outline::before{content:"\F14F0"}.mdi-filter-outline::before{content:"\F0233"}.mdi-filter-plus::before{content:"\F0EF0"}.mdi-filter-plus-outline::before{content:"\F0EF1"}.mdi-filter-remove::before{content:"\F0234"}.mdi-filter-remove-outline::before{content:"\F0235"}.mdi-filter-variant::before{content:"\F0236"}.mdi-filter-variant-minus::before{content:"\F1112"}.mdi-filter-variant-plus::before{content:"\F1113"}.mdi-filter-variant-remove::before{content:"\F103F"}.mdi-finance::before{content:"\F081F"}.mdi-find-replace::before{content:"\F06D4"}.mdi-fingerprint::before{content:"\F0237"}.mdi-fingerprint-off::before{content:"\F0EB1"}.mdi-fire::before{content:"\F0238"}.mdi-fire-alert::before{content:"\F15D7"}.mdi-fire-extinguisher::before{content:"\F0EF2"}.mdi-fire-hydrant::before{content:"\F1137"}.mdi-fire-hydrant-alert::before{content:"\F1138"}.mdi-fire-hydrant-off::before{content:"\F1139"}.mdi-fire-truck::before{content:"\F08AB"}.mdi-firebase::before{content:"\F0967"}.mdi-firefox::before{content:"\F0239"}.mdi-fireplace::before{content:"\F0E2E"}.mdi-fireplace-off::before{content:"\F0E2F"}.mdi-firework::before{content:"\F0E30"}.mdi-fish::before{content:"\F023A"}.mdi-fish-off::before{content:"\F13F3"}.mdi-fishbowl::before{content:"\F0EF3"}.mdi-fishbowl-outline::before{content:"\F0EF4"}.mdi-fit-to-page::before{content:"\F0EF5"}.mdi-fit-to-page-outline::before{content:"\F0EF6"}.mdi-flag::before{content:"\F023B"}.mdi-flag-checkered::before{content:"\F023C"}.mdi-flag-minus::before{content:"\F0B99"}.mdi-flag-minus-outline::before{content:"\F10B2"}.mdi-flag-outline::before{content:"\F023D"}.mdi-flag-plus::before{content:"\F0B9A"}.mdi-flag-plus-outline::before{content:"\F10B3"}.mdi-flag-remove::before{content:"\F0B9B"}.mdi-flag-remove-outline::before{content:"\F10B4"}.mdi-flag-triangle::before{content:"\F023F"}.mdi-flag-variant::before{content:"\F0240"}.mdi-flag-variant-outline::before{content:"\F023E"}.mdi-flare::before{content:"\F0D72"}.mdi-flash::before{content:"\F0241"}.mdi-flash-alert::before{content:"\F0EF7"}.mdi-flash-alert-outline::before{content:"\F0EF8"}.mdi-flash-auto::before{content:"\F0242"}.mdi-flash-circle::before{content:"\F0820"}.mdi-flash-off::before{content:"\F0243"}.mdi-flash-outline::before{content:"\F06D5"}.mdi-flash-red-eye::before{content:"\F067B"}.mdi-flashlight::before{content:"\F0244"}.mdi-flashlight-off::before{content:"\F0245"}.mdi-flask::before{content:"\F0093"}.mdi-flask-empty::before{content:"\F0094"}.mdi-flask-empty-minus::before{content:"\F123A"}.mdi-flask-empty-minus-outline::before{content:"\F123B"}.mdi-flask-empty-off::before{content:"\F13F4"}.mdi-flask-empty-off-outline::before{content:"\F13F5"}.mdi-flask-empty-outline::before{content:"\F0095"}.mdi-flask-empty-plus::before{content:"\F123C"}.mdi-flask-empty-plus-outline::before{content:"\F123D"}.mdi-flask-empty-remove::before{content:"\F123E"}.mdi-flask-empty-remove-outline::before{content:"\F123F"}.mdi-flask-minus::before{content:"\F1240"}.mdi-flask-minus-outline::before{content:"\F1241"}.mdi-flask-off::before{content:"\F13F6"}.mdi-flask-off-outline::before{content:"\F13F7"}.mdi-flask-outline::before{content:"\F0096"}.mdi-flask-plus::before{content:"\F1242"}.mdi-flask-plus-outline::before{content:"\F1243"}.mdi-flask-remove::before{content:"\F1244"}.mdi-flask-remove-outline::before{content:"\F1245"}.mdi-flask-round-bottom::before{content:"\F124B"}.mdi-flask-round-bottom-empty::before{content:"\F124C"}.mdi-flask-round-bottom-empty-outline::before{content:"\F124D"}.mdi-flask-round-bottom-outline::before{content:"\F124E"}.mdi-fleur-de-lis::before{content:"\F1303"}.mdi-flip-horizontal::before{content:"\F10E7"}.mdi-flip-to-back::before{content:"\F0247"}.mdi-flip-to-front::before{content:"\F0248"}.mdi-flip-vertical::before{content:"\F10E8"}.mdi-floor-lamp::before{content:"\F08DD"}.mdi-floor-lamp-dual::before{content:"\F1040"}.mdi-floor-lamp-variant::before{content:"\F1041"}.mdi-floor-plan::before{content:"\F0821"}.mdi-floppy::before{content:"\F0249"}.mdi-floppy-variant::before{content:"\F09EF"}.mdi-flower::before{content:"\F024A"}.mdi-flower-outline::before{content:"\F09F0"}.mdi-flower-poppy::before{content:"\F0D08"}.mdi-flower-tulip::before{content:"\F09F1"}.mdi-flower-tulip-outline::before{content:"\F09F2"}.mdi-focus-auto::before{content:"\F0F4E"}.mdi-focus-field::before{content:"\F0F4F"}.mdi-focus-field-horizontal::before{content:"\F0F50"}.mdi-focus-field-vertical::before{content:"\F0F51"}.mdi-folder::before{content:"\F024B"}.mdi-folder-account::before{content:"\F024C"}.mdi-folder-account-outline::before{content:"\F0B9C"}.mdi-folder-alert::before{content:"\F0DCC"}.mdi-folder-alert-outline::before{content:"\F0DCD"}.mdi-folder-clock::before{content:"\F0ABA"}.mdi-folder-clock-outline::before{content:"\F0ABB"}.mdi-folder-cog::before{content:"\F107F"}.mdi-folder-cog-outline::before{content:"\F1080"}.mdi-folder-download::before{content:"\F024D"}.mdi-folder-download-outline::before{content:"\F10E9"}.mdi-folder-edit::before{content:"\F08DE"}.mdi-folder-edit-outline::before{content:"\F0DCE"}.mdi-folder-google-drive::before{content:"\F024E"}.mdi-folder-heart::before{content:"\F10EA"}.mdi-folder-heart-outline::before{content:"\F10EB"}.mdi-folder-home::before{content:"\F10B5"}.mdi-folder-home-outline::before{content:"\F10B6"}.mdi-folder-image::before{content:"\F024F"}.mdi-folder-information::before{content:"\F10B7"}.mdi-folder-information-outline::before{content:"\F10B8"}.mdi-folder-key::before{content:"\F08AC"}.mdi-folder-key-network::before{content:"\F08AD"}.mdi-folder-key-network-outline::before{content:"\F0C80"}.mdi-folder-key-outline::before{content:"\F10EC"}.mdi-folder-lock::before{content:"\F0250"}.mdi-folder-lock-open::before{content:"\F0251"}.mdi-folder-marker::before{content:"\F126D"}.mdi-folder-marker-outline::before{content:"\F126E"}.mdi-folder-move::before{content:"\F0252"}.mdi-folder-move-outline::before{content:"\F1246"}.mdi-folder-multiple::before{content:"\F0253"}.mdi-folder-multiple-image::before{content:"\F0254"}.mdi-folder-multiple-outline::before{content:"\F0255"}.mdi-folder-multiple-plus::before{content:"\F147E"}.mdi-folder-multiple-plus-outline::before{content:"\F147F"}.mdi-folder-music::before{content:"\F1359"}.mdi-folder-music-outline::before{content:"\F135A"}.mdi-folder-network::before{content:"\F0870"}.mdi-folder-network-outline::before{content:"\F0C81"}.mdi-folder-open::before{content:"\F0770"}.mdi-folder-open-outline::before{content:"\F0DCF"}.mdi-folder-outline::before{content:"\F0256"}.mdi-folder-plus::before{content:"\F0257"}.mdi-folder-plus-outline::before{content:"\F0B9D"}.mdi-folder-pound::before{content:"\F0D09"}.mdi-folder-pound-outline::before{content:"\F0D0A"}.mdi-folder-refresh::before{content:"\F0749"}.mdi-folder-refresh-outline::before{content:"\F0542"}.mdi-folder-remove::before{content:"\F0258"}.mdi-folder-remove-outline::before{content:"\F0B9E"}.mdi-folder-search::before{content:"\F0968"}.mdi-folder-search-outline::before{content:"\F0969"}.mdi-folder-settings::before{content:"\F107D"}.mdi-folder-settings-outline::before{content:"\F107E"}.mdi-folder-star::before{content:"\F069D"}.mdi-folder-star-multiple::before{content:"\F13D3"}.mdi-folder-star-multiple-outline::before{content:"\F13D4"}.mdi-folder-star-outline::before{content:"\F0B9F"}.mdi-folder-swap::before{content:"\F0FB6"}.mdi-folder-swap-outline::before{content:"\F0FB7"}.mdi-folder-sync::before{content:"\F0D0B"}.mdi-folder-sync-outline::before{content:"\F0D0C"}.mdi-folder-table::before{content:"\F12E3"}.mdi-folder-table-outline::before{content:"\F12E4"}.mdi-folder-text::before{content:"\F0C82"}.mdi-folder-text-outline::before{content:"\F0C83"}.mdi-folder-upload::before{content:"\F0259"}.mdi-folder-upload-outline::before{content:"\F10ED"}.mdi-folder-zip::before{content:"\F06EB"}.mdi-folder-zip-outline::before{content:"\F07B9"}.mdi-font-awesome::before{content:"\F003A"}.mdi-food::before{content:"\F025A"}.mdi-food-apple::before{content:"\F025B"}.mdi-food-apple-outline::before{content:"\F0C84"}.mdi-food-croissant::before{content:"\F07C8"}.mdi-food-drumstick::before{content:"\F141F"}.mdi-food-drumstick-off::before{content:"\F1468"}.mdi-food-drumstick-off-outline::before{content:"\F1469"}.mdi-food-drumstick-outline::before{content:"\F1420"}.mdi-food-fork-drink::before{content:"\F05F2"}.mdi-food-halal::before{content:"\F1572"}.mdi-food-kosher::before{content:"\F1573"}.mdi-food-off::before{content:"\F05F3"}.mdi-food-steak::before{content:"\F146A"}.mdi-food-steak-off::before{content:"\F146B"}.mdi-food-variant::before{content:"\F025C"}.mdi-food-variant-off::before{content:"\F13E5"}.mdi-foot-print::before{content:"\F0F52"}.mdi-football::before{content:"\F025D"}.mdi-football-australian::before{content:"\F025E"}.mdi-football-helmet::before{content:"\F025F"}.mdi-forklift::before{content:"\F07C9"}.mdi-form-dropdown::before{content:"\F1400"}.mdi-form-select::before{content:"\F1401"}.mdi-form-textarea::before{content:"\F1095"}.mdi-form-textbox::before{content:"\F060E"}.mdi-form-textbox-lock::before{content:"\F135D"}.mdi-form-textbox-password::before{content:"\F07F5"}.mdi-format-align-bottom::before{content:"\F0753"}.mdi-format-align-center::before{content:"\F0260"}.mdi-format-align-justify::before{content:"\F0261"}.mdi-format-align-left::before{content:"\F0262"}.mdi-format-align-middle::before{content:"\F0754"}.mdi-format-align-right::before{content:"\F0263"}.mdi-format-align-top::before{content:"\F0755"}.mdi-format-annotation-minus::before{content:"\F0ABC"}.mdi-format-annotation-plus::before{content:"\F0646"}.mdi-format-bold::before{content:"\F0264"}.mdi-format-clear::before{content:"\F0265"}.mdi-format-color-fill::before{content:"\F0266"}.mdi-format-color-highlight::before{content:"\F0E31"}.mdi-format-color-marker-cancel::before{content:"\F1313"}.mdi-format-color-text::before{content:"\F069E"}.mdi-format-columns::before{content:"\F08DF"}.mdi-format-float-center::before{content:"\F0267"}.mdi-format-float-left::before{content:"\F0268"}.mdi-format-float-none::before{content:"\F0269"}.mdi-format-float-right::before{content:"\F026A"}.mdi-format-font::before{content:"\F06D6"}.mdi-format-font-size-decrease::before{content:"\F09F3"}.mdi-format-font-size-increase::before{content:"\F09F4"}.mdi-format-header-1::before{content:"\F026B"}.mdi-format-header-2::before{content:"\F026C"}.mdi-format-header-3::before{content:"\F026D"}.mdi-format-header-4::before{content:"\F026E"}.mdi-format-header-5::before{content:"\F026F"}.mdi-format-header-6::before{content:"\F0270"}.mdi-format-header-decrease::before{content:"\F0271"}.mdi-format-header-equal::before{content:"\F0272"}.mdi-format-header-increase::before{content:"\F0273"}.mdi-format-header-pound::before{content:"\F0274"}.mdi-format-horizontal-align-center::before{content:"\F061E"}.mdi-format-horizontal-align-left::before{content:"\F061F"}.mdi-format-horizontal-align-right::before{content:"\F0620"}.mdi-format-indent-decrease::before{content:"\F0275"}.mdi-format-indent-increase::before{content:"\F0276"}.mdi-format-italic::before{content:"\F0277"}.mdi-format-letter-case::before{content:"\F0B34"}.mdi-format-letter-case-lower::before{content:"\F0B35"}.mdi-format-letter-case-upper::before{content:"\F0B36"}.mdi-format-letter-ends-with::before{content:"\F0FB8"}.mdi-format-letter-matches::before{content:"\F0FB9"}.mdi-format-letter-starts-with::before{content:"\F0FBA"}.mdi-format-line-spacing::before{content:"\F0278"}.mdi-format-line-style::before{content:"\F05C8"}.mdi-format-line-weight::before{content:"\F05C9"}.mdi-format-list-bulleted::before{content:"\F0279"}.mdi-format-list-bulleted-square::before{content:"\F0DD0"}.mdi-format-list-bulleted-triangle::before{content:"\F0EB2"}.mdi-format-list-bulleted-type::before{content:"\F027A"}.mdi-format-list-checkbox::before{content:"\F096A"}.mdi-format-list-checks::before{content:"\F0756"}.mdi-format-list-numbered::before{content:"\F027B"}.mdi-format-list-numbered-rtl::before{content:"\F0D0D"}.mdi-format-list-text::before{content:"\F126F"}.mdi-format-overline::before{content:"\F0EB3"}.mdi-format-page-break::before{content:"\F06D7"}.mdi-format-paint::before{content:"\F027C"}.mdi-format-paragraph::before{content:"\F027D"}.mdi-format-pilcrow::before{content:"\F06D8"}.mdi-format-quote-close::before{content:"\F027E"}.mdi-format-quote-close-outline::before{content:"\F11A8"}.mdi-format-quote-open::before{content:"\F0757"}.mdi-format-quote-open-outline::before{content:"\F11A7"}.mdi-format-rotate-90::before{content:"\F06AA"}.mdi-format-section::before{content:"\F069F"}.mdi-format-size::before{content:"\F027F"}.mdi-format-strikethrough::before{content:"\F0280"}.mdi-format-strikethrough-variant::before{content:"\F0281"}.mdi-format-subscript::before{content:"\F0282"}.mdi-format-superscript::before{content:"\F0283"}.mdi-format-text::before{content:"\F0284"}.mdi-format-text-rotation-angle-down::before{content:"\F0FBB"}.mdi-format-text-rotation-angle-up::before{content:"\F0FBC"}.mdi-format-text-rotation-down::before{content:"\F0D73"}.mdi-format-text-rotation-down-vertical::before{content:"\F0FBD"}.mdi-format-text-rotation-none::before{content:"\F0D74"}.mdi-format-text-rotation-up::before{content:"\F0FBE"}.mdi-format-text-rotation-vertical::before{content:"\F0FBF"}.mdi-format-text-variant::before{content:"\F0E32"}.mdi-format-text-variant-outline::before{content:"\F150F"}.mdi-format-text-wrapping-clip::before{content:"\F0D0E"}.mdi-format-text-wrapping-overflow::before{content:"\F0D0F"}.mdi-format-text-wrapping-wrap::before{content:"\F0D10"}.mdi-format-textbox::before{content:"\F0D11"}.mdi-format-textdirection-l-to-r::before{content:"\F0285"}.mdi-format-textdirection-r-to-l::before{content:"\F0286"}.mdi-format-title::before{content:"\F05F4"}.mdi-format-underline::before{content:"\F0287"}.mdi-format-vertical-align-bottom::before{content:"\F0621"}.mdi-format-vertical-align-center::before{content:"\F0622"}.mdi-format-vertical-align-top::before{content:"\F0623"}.mdi-format-wrap-inline::before{content:"\F0288"}.mdi-format-wrap-square::before{content:"\F0289"}.mdi-format-wrap-tight::before{content:"\F028A"}.mdi-format-wrap-top-bottom::before{content:"\F028B"}.mdi-forum::before{content:"\F028C"}.mdi-forum-outline::before{content:"\F0822"}.mdi-forward::before{content:"\F028D"}.mdi-forwardburger::before{content:"\F0D75"}.mdi-fountain::before{content:"\F096B"}.mdi-fountain-pen::before{content:"\F0D12"}.mdi-fountain-pen-tip::before{content:"\F0D13"}.mdi-freebsd::before{content:"\F08E0"}.mdi-frequently-asked-questions::before{content:"\F0EB4"}.mdi-fridge::before{content:"\F0290"}.mdi-fridge-alert::before{content:"\F11B1"}.mdi-fridge-alert-outline::before{content:"\F11B2"}.mdi-fridge-bottom::before{content:"\F0292"}.mdi-fridge-industrial::before{content:"\F15EE"}.mdi-fridge-industrial-alert::before{content:"\F15EF"}.mdi-fridge-industrial-alert-outline::before{content:"\F15F0"}.mdi-fridge-industrial-off::before{content:"\F15F1"}.mdi-fridge-industrial-off-outline::before{content:"\F15F2"}.mdi-fridge-industrial-outline::before{content:"\F15F3"}.mdi-fridge-off::before{content:"\F11AF"}.mdi-fridge-off-outline::before{content:"\F11B0"}.mdi-fridge-outline::before{content:"\F028F"}.mdi-fridge-top::before{content:"\F0291"}.mdi-fridge-variant::before{content:"\F15F4"}.mdi-fridge-variant-alert::before{content:"\F15F5"}.mdi-fridge-variant-alert-outline::before{content:"\F15F6"}.mdi-fridge-variant-off::before{content:"\F15F7"}.mdi-fridge-variant-off-outline::before{content:"\F15F8"}.mdi-fridge-variant-outline::before{content:"\F15F9"}.mdi-fruit-cherries::before{content:"\F1042"}.mdi-fruit-cherries-off::before{content:"\F13F8"}.mdi-fruit-citrus::before{content:"\F1043"}.mdi-fruit-citrus-off::before{content:"\F13F9"}.mdi-fruit-grapes::before{content:"\F1044"}.mdi-fruit-grapes-outline::before{content:"\F1045"}.mdi-fruit-pineapple::before{content:"\F1046"}.mdi-fruit-watermelon::before{content:"\F1047"}.mdi-fuel::before{content:"\F07CA"}.mdi-fullscreen::before{content:"\F0293"}.mdi-fullscreen-exit::before{content:"\F0294"}.mdi-function::before{content:"\F0295"}.mdi-function-variant::before{content:"\F0871"}.mdi-furigana-horizontal::before{content:"\F1081"}.mdi-furigana-vertical::before{content:"\F1082"}.mdi-fuse::before{content:"\F0C85"}.mdi-fuse-alert::before{content:"\F142D"}.mdi-fuse-blade::before{content:"\F0C86"}.mdi-fuse-off::before{content:"\F142C"}.mdi-gamepad::before{content:"\F0296"}.mdi-gamepad-circle::before{content:"\F0E33"}.mdi-gamepad-circle-down::before{content:"\F0E34"}.mdi-gamepad-circle-left::before{content:"\F0E35"}.mdi-gamepad-circle-outline::before{content:"\F0E36"}.mdi-gamepad-circle-right::before{content:"\F0E37"}.mdi-gamepad-circle-up::before{content:"\F0E38"}.mdi-gamepad-down::before{content:"\F0E39"}.mdi-gamepad-left::before{content:"\F0E3A"}.mdi-gamepad-right::before{content:"\F0E3B"}.mdi-gamepad-round::before{content:"\F0E3C"}.mdi-gamepad-round-down::before{content:"\F0E3D"}.mdi-gamepad-round-left::before{content:"\F0E3E"}.mdi-gamepad-round-outline::before{content:"\F0E3F"}.mdi-gamepad-round-right::before{content:"\F0E40"}.mdi-gamepad-round-up::before{content:"\F0E41"}.mdi-gamepad-square::before{content:"\F0EB5"}.mdi-gamepad-square-outline::before{content:"\F0EB6"}.mdi-gamepad-up::before{content:"\F0E42"}.mdi-gamepad-variant::before{content:"\F0297"}.mdi-gamepad-variant-outline::before{content:"\F0EB7"}.mdi-gamma::before{content:"\F10EE"}.mdi-gantry-crane::before{content:"\F0DD1"}.mdi-garage::before{content:"\F06D9"}.mdi-garage-alert::before{content:"\F0872"}.mdi-garage-alert-variant::before{content:"\F12D5"}.mdi-garage-open::before{content:"\F06DA"}.mdi-garage-open-variant::before{content:"\F12D4"}.mdi-garage-variant::before{content:"\F12D3"}.mdi-gas-cylinder::before{content:"\F0647"}.mdi-gas-station::before{content:"\F0298"}.mdi-gas-station-off::before{content:"\F1409"}.mdi-gas-station-off-outline::before{content:"\F140A"}.mdi-gas-station-outline::before{content:"\F0EB8"}.mdi-gate::before{content:"\F0299"}.mdi-gate-and::before{content:"\F08E1"}.mdi-gate-arrow-right::before{content:"\F1169"}.mdi-gate-nand::before{content:"\F08E2"}.mdi-gate-nor::before{content:"\F08E3"}.mdi-gate-not::before{content:"\F08E4"}.mdi-gate-open::before{content:"\F116A"}.mdi-gate-or::before{content:"\F08E5"}.mdi-gate-xnor::before{content:"\F08E6"}.mdi-gate-xor::before{content:"\F08E7"}.mdi-gatsby::before{content:"\F0E43"}.mdi-gauge::before{content:"\F029A"}.mdi-gauge-empty::before{content:"\F0873"}.mdi-gauge-full::before{content:"\F0874"}.mdi-gauge-low::before{content:"\F0875"}.mdi-gavel::before{content:"\F029B"}.mdi-gender-female::before{content:"\F029C"}.mdi-gender-male::before{content:"\F029D"}.mdi-gender-male-female::before{content:"\F029E"}.mdi-gender-male-female-variant::before{content:"\F113F"}.mdi-gender-non-binary::before{content:"\F1140"}.mdi-gender-transgender::before{content:"\F029F"}.mdi-gentoo::before{content:"\F08E8"}.mdi-gesture::before{content:"\F07CB"}.mdi-gesture-double-tap::before{content:"\F073C"}.mdi-gesture-pinch::before{content:"\F0ABD"}.mdi-gesture-spread::before{content:"\F0ABE"}.mdi-gesture-swipe::before{content:"\F0D76"}.mdi-gesture-swipe-down::before{content:"\F073D"}.mdi-gesture-swipe-horizontal::before{content:"\F0ABF"}.mdi-gesture-swipe-left::before{content:"\F073E"}.mdi-gesture-swipe-right::before{content:"\F073F"}.mdi-gesture-swipe-up::before{content:"\F0740"}.mdi-gesture-swipe-vertical::before{content:"\F0AC0"}.mdi-gesture-tap::before{content:"\F0741"}.mdi-gesture-tap-box::before{content:"\F12A9"}.mdi-gesture-tap-button::before{content:"\F12A8"}.mdi-gesture-tap-hold::before{content:"\F0D77"}.mdi-gesture-two-double-tap::before{content:"\F0742"}.mdi-gesture-two-tap::before{content:"\F0743"}.mdi-ghost::before{content:"\F02A0"}.mdi-ghost-off::before{content:"\F09F5"}.mdi-ghost-off-outline::before{content:"\F165C"}.mdi-ghost-outline::before{content:"\F165D"}.mdi-gif::before{content:"\F0D78"}.mdi-gift::before{content:"\F0E44"}.mdi-gift-outline::before{content:"\F02A1"}.mdi-git::before{content:"\F02A2"}.mdi-github::before{content:"\F02A4"}.mdi-gitlab::before{content:"\F0BA0"}.mdi-glass-cocktail::before{content:"\F0356"}.mdi-glass-cocktail-off::before{content:"\F15E6"}.mdi-glass-flute::before{content:"\F02A5"}.mdi-glass-mug::before{content:"\F02A6"}.mdi-glass-mug-off::before{content:"\F15E7"}.mdi-glass-mug-variant::before{content:"\F1116"}.mdi-glass-mug-variant-off::before{content:"\F15E8"}.mdi-glass-pint-outline::before{content:"\F130D"}.mdi-glass-stange::before{content:"\F02A7"}.mdi-glass-tulip::before{content:"\F02A8"}.mdi-glass-wine::before{content:"\F0876"}.mdi-glasses::before{content:"\F02AA"}.mdi-globe-light::before{content:"\F12D7"}.mdi-globe-model::before{content:"\F08E9"}.mdi-gmail::before{content:"\F02AB"}.mdi-gnome::before{content:"\F02AC"}.mdi-go-kart::before{content:"\F0D79"}.mdi-go-kart-track::before{content:"\F0D7A"}.mdi-gog::before{content:"\F0BA1"}.mdi-gold::before{content:"\F124F"}.mdi-golf::before{content:"\F0823"}.mdi-golf-cart::before{content:"\F11A4"}.mdi-golf-tee::before{content:"\F1083"}.mdi-gondola::before{content:"\F0686"}.mdi-goodreads::before{content:"\F0D7B"}.mdi-google::before{content:"\F02AD"}.mdi-google-ads::before{content:"\F0C87"}.mdi-google-analytics::before{content:"\F07CC"}.mdi-google-assistant::before{content:"\F07CD"}.mdi-google-cardboard::before{content:"\F02AE"}.mdi-google-chrome::before{content:"\F02AF"}.mdi-google-circles::before{content:"\F02B0"}.mdi-google-circles-communities::before{content:"\F02B1"}.mdi-google-circles-extended::before{content:"\F02B2"}.mdi-google-circles-group::before{content:"\F02B3"}.mdi-google-classroom::before{content:"\F02C0"}.mdi-google-cloud::before{content:"\F11F6"}.mdi-google-controller::before{content:"\F02B4"}.mdi-google-controller-off::before{content:"\F02B5"}.mdi-google-downasaur::before{content:"\F1362"}.mdi-google-drive::before{content:"\F02B6"}.mdi-google-earth::before{content:"\F02B7"}.mdi-google-fit::before{content:"\F096C"}.mdi-google-glass::before{content:"\F02B8"}.mdi-google-hangouts::before{content:"\F02C9"}.mdi-google-home::before{content:"\F0824"}.mdi-google-keep::before{content:"\F06DC"}.mdi-google-lens::before{content:"\F09F6"}.mdi-google-maps::before{content:"\F05F5"}.mdi-google-my-business::before{content:"\F1048"}.mdi-google-nearby::before{content:"\F02B9"}.mdi-google-photos::before{content:"\F06DD"}.mdi-google-play::before{content:"\F02BC"}.mdi-google-plus::before{content:"\F02BD"}.mdi-google-podcast::before{content:"\F0EB9"}.mdi-google-spreadsheet::before{content:"\F09F7"}.mdi-google-street-view::before{content:"\F0C88"}.mdi-google-translate::before{content:"\F02BF"}.mdi-gradient::before{content:"\F06A0"}.mdi-grain::before{content:"\F0D7C"}.mdi-graph::before{content:"\F1049"}.mdi-graph-outline::before{content:"\F104A"}.mdi-graphql::before{content:"\F0877"}.mdi-grass::before{content:"\F1510"}.mdi-grave-stone::before{content:"\F0BA2"}.mdi-grease-pencil::before{content:"\F0648"}.mdi-greater-than::before{content:"\F096D"}.mdi-greater-than-or-equal::before{content:"\F096E"}.mdi-grid::before{content:"\F02C1"}.mdi-grid-large::before{content:"\F0758"}.mdi-grid-off::before{content:"\F02C2"}.mdi-grill::before{content:"\F0E45"}.mdi-grill-outline::before{content:"\F118A"}.mdi-group::before{content:"\F02C3"}.mdi-guitar-acoustic::before{content:"\F0771"}.mdi-guitar-electric::before{content:"\F02C4"}.mdi-guitar-pick::before{content:"\F02C5"}.mdi-guitar-pick-outline::before{content:"\F02C6"}.mdi-guy-fawkes-mask::before{content:"\F0825"}.mdi-hail::before{content:"\F0AC1"}.mdi-hair-dryer::before{content:"\F10EF"}.mdi-hair-dryer-outline::before{content:"\F10F0"}.mdi-halloween::before{content:"\F0BA3"}.mdi-hamburger::before{content:"\F0685"}.mdi-hammer::before{content:"\F08EA"}.mdi-hammer-screwdriver::before{content:"\F1322"}.mdi-hammer-wrench::before{content:"\F1323"}.mdi-hand::before{content:"\F0A4F"}.mdi-hand-heart::before{content:"\F10F1"}.mdi-hand-heart-outline::before{content:"\F157E"}.mdi-hand-left::before{content:"\F0E46"}.mdi-hand-okay::before{content:"\F0A50"}.mdi-hand-peace::before{content:"\F0A51"}.mdi-hand-peace-variant::before{content:"\F0A52"}.mdi-hand-pointing-down::before{content:"\F0A53"}.mdi-hand-pointing-left::before{content:"\F0A54"}.mdi-hand-pointing-right::before{content:"\F02C7"}.mdi-hand-pointing-up::before{content:"\F0A55"}.mdi-hand-right::before{content:"\F0E47"}.mdi-hand-saw::before{content:"\F0E48"}.mdi-hand-wash::before{content:"\F157F"}.mdi-hand-wash-outline::before{content:"\F1580"}.mdi-hand-water::before{content:"\F139F"}.mdi-handball::before{content:"\F0F53"}.mdi-handcuffs::before{content:"\F113E"}.mdi-handshake::before{content:"\F1218"}.mdi-handshake-outline::before{content:"\F15A1"}.mdi-hanger::before{content:"\F02C8"}.mdi-hard-hat::before{content:"\F096F"}.mdi-harddisk::before{content:"\F02CA"}.mdi-harddisk-plus::before{content:"\F104B"}.mdi-harddisk-remove::before{content:"\F104C"}.mdi-hat-fedora::before{content:"\F0BA4"}.mdi-hazard-lights::before{content:"\F0C89"}.mdi-hdr::before{content:"\F0D7D"}.mdi-hdr-off::before{content:"\F0D7E"}.mdi-head::before{content:"\F135E"}.mdi-head-alert::before{content:"\F1338"}.mdi-head-alert-outline::before{content:"\F1339"}.mdi-head-check::before{content:"\F133A"}.mdi-head-check-outline::before{content:"\F133B"}.mdi-head-cog::before{content:"\F133C"}.mdi-head-cog-outline::before{content:"\F133D"}.mdi-head-dots-horizontal::before{content:"\F133E"}.mdi-head-dots-horizontal-outline::before{content:"\F133F"}.mdi-head-flash::before{content:"\F1340"}.mdi-head-flash-outline::before{content:"\F1341"}.mdi-head-heart::before{content:"\F1342"}.mdi-head-heart-outline::before{content:"\F1343"}.mdi-head-lightbulb::before{content:"\F1344"}.mdi-head-lightbulb-outline::before{content:"\F1345"}.mdi-head-minus::before{content:"\F1346"}.mdi-head-minus-outline::before{content:"\F1347"}.mdi-head-outline::before{content:"\F135F"}.mdi-head-plus::before{content:"\F1348"}.mdi-head-plus-outline::before{content:"\F1349"}.mdi-head-question::before{content:"\F134A"}.mdi-head-question-outline::before{content:"\F134B"}.mdi-head-remove::before{content:"\F134C"}.mdi-head-remove-outline::before{content:"\F134D"}.mdi-head-snowflake::before{content:"\F134E"}.mdi-head-snowflake-outline::before{content:"\F134F"}.mdi-head-sync::before{content:"\F1350"}.mdi-head-sync-outline::before{content:"\F1351"}.mdi-headphones::before{content:"\F02CB"}.mdi-headphones-bluetooth::before{content:"\F0970"}.mdi-headphones-box::before{content:"\F02CC"}.mdi-headphones-off::before{content:"\F07CE"}.mdi-headphones-settings::before{content:"\F02CD"}.mdi-headset::before{content:"\F02CE"}.mdi-headset-dock::before{content:"\F02CF"}.mdi-headset-off::before{content:"\F02D0"}.mdi-heart::before{content:"\F02D1"}.mdi-heart-box::before{content:"\F02D2"}.mdi-heart-box-outline::before{content:"\F02D3"}.mdi-heart-broken::before{content:"\F02D4"}.mdi-heart-broken-outline::before{content:"\F0D14"}.mdi-heart-circle::before{content:"\F0971"}.mdi-heart-circle-outline::before{content:"\F0972"}.mdi-heart-cog::before{content:"\F1663"}.mdi-heart-cog-outline::before{content:"\F1664"}.mdi-heart-flash::before{content:"\F0EF9"}.mdi-heart-half::before{content:"\F06DF"}.mdi-heart-half-full::before{content:"\F06DE"}.mdi-heart-half-outline::before{content:"\F06E0"}.mdi-heart-minus::before{content:"\F142F"}.mdi-heart-minus-outline::before{content:"\F1432"}.mdi-heart-multiple::before{content:"\F0A56"}.mdi-heart-multiple-outline::before{content:"\F0A57"}.mdi-heart-off::before{content:"\F0759"}.mdi-heart-off-outline::before{content:"\F1434"}.mdi-heart-outline::before{content:"\F02D5"}.mdi-heart-plus::before{content:"\F142E"}.mdi-heart-plus-outline::before{content:"\F1431"}.mdi-heart-pulse::before{content:"\F05F6"}.mdi-heart-remove::before{content:"\F1430"}.mdi-heart-remove-outline::before{content:"\F1433"}.mdi-heart-settings::before{content:"\F1665"}.mdi-heart-settings-outline::before{content:"\F1666"}.mdi-helicopter::before{content:"\F0AC2"}.mdi-help::before{content:"\F02D6"}.mdi-help-box::before{content:"\F078B"}.mdi-help-circle::before{content:"\F02D7"}.mdi-help-circle-outline::before{content:"\F0625"}.mdi-help-network::before{content:"\F06F5"}.mdi-help-network-outline::before{content:"\F0C8A"}.mdi-help-rhombus::before{content:"\F0BA5"}.mdi-help-rhombus-outline::before{content:"\F0BA6"}.mdi-hexadecimal::before{content:"\F12A7"}.mdi-hexagon::before{content:"\F02D8"}.mdi-hexagon-multiple::before{content:"\F06E1"}.mdi-hexagon-multiple-outline::before{content:"\F10F2"}.mdi-hexagon-outline::before{content:"\F02D9"}.mdi-hexagon-slice-1::before{content:"\F0AC3"}.mdi-hexagon-slice-2::before{content:"\F0AC4"}.mdi-hexagon-slice-3::before{content:"\F0AC5"}.mdi-hexagon-slice-4::before{content:"\F0AC6"}.mdi-hexagon-slice-5::before{content:"\F0AC7"}.mdi-hexagon-slice-6::before{content:"\F0AC8"}.mdi-hexagram::before{content:"\F0AC9"}.mdi-hexagram-outline::before{content:"\F0ACA"}.mdi-high-definition::before{content:"\F07CF"}.mdi-high-definition-box::before{content:"\F0878"}.mdi-highway::before{content:"\F05F7"}.mdi-hiking::before{content:"\F0D7F"}.mdi-hinduism::before{content:"\F0973"}.mdi-history::before{content:"\F02DA"}.mdi-hockey-puck::before{content:"\F0879"}.mdi-hockey-sticks::before{content:"\F087A"}.mdi-hololens::before{content:"\F02DB"}.mdi-home::before{content:"\F02DC"}.mdi-home-account::before{content:"\F0826"}.mdi-home-alert::before{content:"\F087B"}.mdi-home-alert-outline::before{content:"\F15D0"}.mdi-home-analytics::before{content:"\F0EBA"}.mdi-home-assistant::before{content:"\F07D0"}.mdi-home-automation::before{content:"\F07D1"}.mdi-home-circle::before{content:"\F07D2"}.mdi-home-circle-outline::before{content:"\F104D"}.mdi-home-city::before{content:"\F0D15"}.mdi-home-city-outline::before{content:"\F0D16"}.mdi-home-currency-usd::before{content:"\F08AF"}.mdi-home-edit::before{content:"\F1159"}.mdi-home-edit-outline::before{content:"\F115A"}.mdi-home-export-outline::before{content:"\F0F9B"}.mdi-home-flood::before{content:"\F0EFA"}.mdi-home-floor-0::before{content:"\F0DD2"}.mdi-home-floor-1::before{content:"\F0D80"}.mdi-home-floor-2::before{content:"\F0D81"}.mdi-home-floor-3::before{content:"\F0D82"}.mdi-home-floor-a::before{content:"\F0D83"}.mdi-home-floor-b::before{content:"\F0D84"}.mdi-home-floor-g::before{content:"\F0D85"}.mdi-home-floor-l::before{content:"\F0D86"}.mdi-home-floor-negative-1::before{content:"\F0DD3"}.mdi-home-group::before{content:"\F0DD4"}.mdi-home-heart::before{content:"\F0827"}.mdi-home-import-outline::before{content:"\F0F9C"}.mdi-home-lightbulb::before{content:"\F1251"}.mdi-home-lightbulb-outline::before{content:"\F1252"}.mdi-home-lock::before{content:"\F08EB"}.mdi-home-lock-open::before{content:"\F08EC"}.mdi-home-map-marker::before{content:"\F05F8"}.mdi-home-minus::before{content:"\F0974"}.mdi-home-minus-outline::before{content:"\F13D5"}.mdi-home-modern::before{content:"\F02DD"}.mdi-home-outline::before{content:"\F06A1"}.mdi-home-plus::before{content:"\F0975"}.mdi-home-plus-outline::before{content:"\F13D6"}.mdi-home-remove::before{content:"\F1247"}.mdi-home-remove-outline::before{content:"\F13D7"}.mdi-home-roof::before{content:"\F112B"}.mdi-home-search::before{content:"\F13B0"}.mdi-home-search-outline::before{content:"\F13B1"}.mdi-home-thermometer::before{content:"\F0F54"}.mdi-home-thermometer-outline::before{content:"\F0F55"}.mdi-home-variant::before{content:"\F02DE"}.mdi-home-variant-outline::before{content:"\F0BA7"}.mdi-hook::before{content:"\F06E2"}.mdi-hook-off::before{content:"\F06E3"}.mdi-hops::before{content:"\F02DF"}.mdi-horizontal-rotate-clockwise::before{content:"\F10F3"}.mdi-horizontal-rotate-counterclockwise::before{content:"\F10F4"}.mdi-horse::before{content:"\F15BF"}.mdi-horse-human::before{content:"\F15C0"}.mdi-horse-variant::before{content:"\F15C1"}.mdi-horseshoe::before{content:"\F0A58"}.mdi-hospital::before{content:"\F0FF6"}.mdi-hospital-box::before{content:"\F02E0"}.mdi-hospital-box-outline::before{content:"\F0FF7"}.mdi-hospital-building::before{content:"\F02E1"}.mdi-hospital-marker::before{content:"\F02E2"}.mdi-hot-tub::before{content:"\F0828"}.mdi-hours-24::before{content:"\F1478"}.mdi-hubspot::before{content:"\F0D17"}.mdi-hulu::before{content:"\F0829"}.mdi-human::before{content:"\F02E6"}.mdi-human-baby-changing-table::before{content:"\F138B"}.mdi-human-cane::before{content:"\F1581"}.mdi-human-capacity-decrease::before{content:"\F159B"}.mdi-human-capacity-increase::before{content:"\F159C"}.mdi-human-child::before{content:"\F02E7"}.mdi-human-edit::before{content:"\F14E8"}.mdi-human-female::before{content:"\F0649"}.mdi-human-female-boy::before{content:"\F0A59"}.mdi-human-female-dance::before{content:"\F15C9"}.mdi-human-female-female::before{content:"\F0A5A"}.mdi-human-female-girl::before{content:"\F0A5B"}.mdi-human-greeting::before{content:"\F064A"}.mdi-human-greeting-proximity::before{content:"\F159D"}.mdi-human-handsdown::before{content:"\F064B"}.mdi-human-handsup::before{content:"\F064C"}.mdi-human-male::before{content:"\F064D"}.mdi-human-male-boy::before{content:"\F0A5C"}.mdi-human-male-child::before{content:"\F138C"}.mdi-human-male-female::before{content:"\F02E8"}.mdi-human-male-girl::before{content:"\F0A5D"}.mdi-human-male-height::before{content:"\F0EFB"}.mdi-human-male-height-variant::before{content:"\F0EFC"}.mdi-human-male-male::before{content:"\F0A5E"}.mdi-human-pregnant::before{content:"\F05CF"}.mdi-human-queue::before{content:"\F1571"}.mdi-human-scooter::before{content:"\F11E9"}.mdi-human-wheelchair::before{content:"\F138D"}.mdi-humble-bundle::before{content:"\F0744"}.mdi-hvac::before{content:"\F1352"}.mdi-hvac-off::before{content:"\F159E"}.mdi-hydraulic-oil-level::before{content:"\F1324"}.mdi-hydraulic-oil-temperature::before{content:"\F1325"}.mdi-hydro-power::before{content:"\F12E5"}.mdi-ice-cream::before{content:"\F082A"}.mdi-ice-cream-off::before{content:"\F0E52"}.mdi-ice-pop::before{content:"\F0EFD"}.mdi-id-card::before{content:"\F0FC0"}.mdi-identifier::before{content:"\F0EFE"}.mdi-ideogram-cjk::before{content:"\F1331"}.mdi-ideogram-cjk-variant::before{content:"\F1332"}.mdi-iframe::before{content:"\F0C8B"}.mdi-iframe-array::before{content:"\F10F5"}.mdi-iframe-array-outline::before{content:"\F10F6"}.mdi-iframe-braces::before{content:"\F10F7"}.mdi-iframe-braces-outline::before{content:"\F10F8"}.mdi-iframe-outline::before{content:"\F0C8C"}.mdi-iframe-parentheses::before{content:"\F10F9"}.mdi-iframe-parentheses-outline::before{content:"\F10FA"}.mdi-iframe-variable::before{content:"\F10FB"}.mdi-iframe-variable-outline::before{content:"\F10FC"}.mdi-image::before{content:"\F02E9"}.mdi-image-album::before{content:"\F02EA"}.mdi-image-area::before{content:"\F02EB"}.mdi-image-area-close::before{content:"\F02EC"}.mdi-image-auto-adjust::before{content:"\F0FC1"}.mdi-image-broken::before{content:"\F02ED"}.mdi-image-broken-variant::before{content:"\F02EE"}.mdi-image-edit::before{content:"\F11E3"}.mdi-image-edit-outline::before{content:"\F11E4"}.mdi-image-filter-black-white::before{content:"\F02F0"}.mdi-image-filter-center-focus::before{content:"\F02F1"}.mdi-image-filter-center-focus-strong::before{content:"\F0EFF"}.mdi-image-filter-center-focus-strong-outline::before{content:"\F0F00"}.mdi-image-filter-center-focus-weak::before{content:"\F02F2"}.mdi-image-filter-drama::before{content:"\F02F3"}.mdi-image-filter-frames::before{content:"\F02F4"}.mdi-image-filter-hdr::before{content:"\F02F5"}.mdi-image-filter-none::before{content:"\F02F6"}.mdi-image-filter-tilt-shift::before{content:"\F02F7"}.mdi-image-filter-vintage::before{content:"\F02F8"}.mdi-image-frame::before{content:"\F0E49"}.mdi-image-minus::before{content:"\F1419"}.mdi-image-move::before{content:"\F09F8"}.mdi-image-multiple::before{content:"\F02F9"}.mdi-image-multiple-outline::before{content:"\F02EF"}.mdi-image-off::before{content:"\F082B"}.mdi-image-off-outline::before{content:"\F11D1"}.mdi-image-outline::before{content:"\F0976"}.mdi-image-plus::before{content:"\F087C"}.mdi-image-remove::before{content:"\F1418"}.mdi-image-search::before{content:"\F0977"}.mdi-image-search-outline::before{content:"\F0978"}.mdi-image-size-select-actual::before{content:"\F0C8D"}.mdi-image-size-select-large::before{content:"\F0C8E"}.mdi-image-size-select-small::before{content:"\F0C8F"}.mdi-image-text::before{content:"\F160D"}.mdi-import::before{content:"\F02FA"}.mdi-inbox::before{content:"\F0687"}.mdi-inbox-arrow-down::before{content:"\F02FB"}.mdi-inbox-arrow-down-outline::before{content:"\F1270"}.mdi-inbox-arrow-up::before{content:"\F03D1"}.mdi-inbox-arrow-up-outline::before{content:"\F1271"}.mdi-inbox-full::before{content:"\F1272"}.mdi-inbox-full-outline::before{content:"\F1273"}.mdi-inbox-multiple::before{content:"\F08B0"}.mdi-inbox-multiple-outline::before{content:"\F0BA8"}.mdi-inbox-outline::before{content:"\F1274"}.mdi-inbox-remove::before{content:"\F159F"}.mdi-inbox-remove-outline::before{content:"\F15A0"}.mdi-incognito::before{content:"\F05F9"}.mdi-incognito-circle::before{content:"\F1421"}.mdi-incognito-circle-off::before{content:"\F1422"}.mdi-incognito-off::before{content:"\F0075"}.mdi-infinity::before{content:"\F06E4"}.mdi-information::before{content:"\F02FC"}.mdi-information-outline::before{content:"\F02FD"}.mdi-information-variant::before{content:"\F064E"}.mdi-instagram::before{content:"\F02FE"}.mdi-instrument-triangle::before{content:"\F104E"}.mdi-invert-colors::before{content:"\F0301"}.mdi-invert-colors-off::before{content:"\F0E4A"}.mdi-iobroker::before{content:"\F12E8"}.mdi-ip::before{content:"\F0A5F"}.mdi-ip-network::before{content:"\F0A60"}.mdi-ip-network-outline::before{content:"\F0C90"}.mdi-ipod::before{content:"\F0C91"}.mdi-islam::before{content:"\F0979"}.mdi-island::before{content:"\F104F"}.mdi-iv-bag::before{content:"\F10B9"}.mdi-jabber::before{content:"\F0DD5"}.mdi-jeepney::before{content:"\F0302"}.mdi-jellyfish::before{content:"\F0F01"}.mdi-jellyfish-outline::before{content:"\F0F02"}.mdi-jira::before{content:"\F0303"}.mdi-jquery::before{content:"\F087D"}.mdi-jsfiddle::before{content:"\F0304"}.mdi-judaism::before{content:"\F097A"}.mdi-jump-rope::before{content:"\F12FF"}.mdi-kabaddi::before{content:"\F0D87"}.mdi-kangaroo::before{content:"\F1558"}.mdi-karate::before{content:"\F082C"}.mdi-keg::before{content:"\F0305"}.mdi-kettle::before{content:"\F05FA"}.mdi-kettle-alert::before{content:"\F1317"}.mdi-kettle-alert-outline::before{content:"\F1318"}.mdi-kettle-off::before{content:"\F131B"}.mdi-kettle-off-outline::before{content:"\F131C"}.mdi-kettle-outline::before{content:"\F0F56"}.mdi-kettle-steam::before{content:"\F1319"}.mdi-kettle-steam-outline::before{content:"\F131A"}.mdi-kettlebell::before{content:"\F1300"}.mdi-key::before{content:"\F0306"}.mdi-key-arrow-right::before{content:"\F1312"}.mdi-key-chain::before{content:"\F1574"}.mdi-key-chain-variant::before{content:"\F1575"}.mdi-key-change::before{content:"\F0307"}.mdi-key-link::before{content:"\F119F"}.mdi-key-minus::before{content:"\F0308"}.mdi-key-outline::before{content:"\F0DD6"}.mdi-key-plus::before{content:"\F0309"}.mdi-key-remove::before{content:"\F030A"}.mdi-key-star::before{content:"\F119E"}.mdi-key-variant::before{content:"\F030B"}.mdi-key-wireless::before{content:"\F0FC2"}.mdi-keyboard::before{content:"\F030C"}.mdi-keyboard-backspace::before{content:"\F030D"}.mdi-keyboard-caps::before{content:"\F030E"}.mdi-keyboard-close::before{content:"\F030F"}.mdi-keyboard-esc::before{content:"\F12B7"}.mdi-keyboard-f1::before{content:"\F12AB"}.mdi-keyboard-f10::before{content:"\F12B4"}.mdi-keyboard-f11::before{content:"\F12B5"}.mdi-keyboard-f12::before{content:"\F12B6"}.mdi-keyboard-f2::before{content:"\F12AC"}.mdi-keyboard-f3::before{content:"\F12AD"}.mdi-keyboard-f4::before{content:"\F12AE"}.mdi-keyboard-f5::before{content:"\F12AF"}.mdi-keyboard-f6::before{content:"\F12B0"}.mdi-keyboard-f7::before{content:"\F12B1"}.mdi-keyboard-f8::before{content:"\F12B2"}.mdi-keyboard-f9::before{content:"\F12B3"}.mdi-keyboard-off::before{content:"\F0310"}.mdi-keyboard-off-outline::before{content:"\F0E4B"}.mdi-keyboard-outline::before{content:"\F097B"}.mdi-keyboard-return::before{content:"\F0311"}.mdi-keyboard-settings::before{content:"\F09F9"}.mdi-keyboard-settings-outline::before{content:"\F09FA"}.mdi-keyboard-space::before{content:"\F1050"}.mdi-keyboard-tab::before{content:"\F0312"}.mdi-keyboard-variant::before{content:"\F0313"}.mdi-khanda::before{content:"\F10FD"}.mdi-kickstarter::before{content:"\F0745"}.mdi-klingon::before{content:"\F135B"}.mdi-knife::before{content:"\F09FB"}.mdi-knife-military::before{content:"\F09FC"}.mdi-kodi::before{content:"\F0314"}.mdi-kubernetes::before{content:"\F10FE"}.mdi-label::before{content:"\F0315"}.mdi-label-multiple::before{content:"\F1375"}.mdi-label-multiple-outline::before{content:"\F1376"}.mdi-label-off::before{content:"\F0ACB"}.mdi-label-off-outline::before{content:"\F0ACC"}.mdi-label-outline::before{content:"\F0316"}.mdi-label-percent::before{content:"\F12EA"}.mdi-label-percent-outline::before{content:"\F12EB"}.mdi-label-variant::before{content:"\F0ACD"}.mdi-label-variant-outline::before{content:"\F0ACE"}.mdi-ladder::before{content:"\F15A2"}.mdi-ladybug::before{content:"\F082D"}.mdi-lambda::before{content:"\F0627"}.mdi-lamp::before{content:"\F06B5"}.mdi-lamps::before{content:"\F1576"}.mdi-lan::before{content:"\F0317"}.mdi-lan-check::before{content:"\F12AA"}.mdi-lan-connect::before{content:"\F0318"}.mdi-lan-disconnect::before{content:"\F0319"}.mdi-lan-pending::before{content:"\F031A"}.mdi-language-c::before{content:"\F0671"}.mdi-language-cpp::before{content:"\F0672"}.mdi-language-csharp::before{content:"\F031B"}.mdi-language-css3::before{content:"\F031C"}.mdi-language-fortran::before{content:"\F121A"}.mdi-language-go::before{content:"\F07D3"}.mdi-language-haskell::before{content:"\F0C92"}.mdi-language-html5::before{content:"\F031D"}.mdi-language-java::before{content:"\F0B37"}.mdi-language-javascript::before{content:"\F031E"}.mdi-language-kotlin::before{content:"\F1219"}.mdi-language-lua::before{content:"\F08B1"}.mdi-language-markdown::before{content:"\F0354"}.mdi-language-markdown-outline::before{content:"\F0F5B"}.mdi-language-php::before{content:"\F031F"}.mdi-language-python::before{content:"\F0320"}.mdi-language-r::before{content:"\F07D4"}.mdi-language-ruby::before{content:"\F0D2D"}.mdi-language-ruby-on-rails::before{content:"\F0ACF"}.mdi-language-rust::before{content:"\F1617"}.mdi-language-swift::before{content:"\F06E5"}.mdi-language-typescript::before{content:"\F06E6"}.mdi-language-xaml::before{content:"\F0673"}.mdi-laptop::before{content:"\F0322"}.mdi-laptop-chromebook::before{content:"\F0323"}.mdi-laptop-mac::before{content:"\F0324"}.mdi-laptop-off::before{content:"\F06E7"}.mdi-laptop-windows::before{content:"\F0325"}.mdi-laravel::before{content:"\F0AD0"}.mdi-laser-pointer::before{content:"\F1484"}.mdi-lasso::before{content:"\F0F03"}.mdi-lastpass::before{content:"\F0446"}.mdi-latitude::before{content:"\F0F57"}.mdi-launch::before{content:"\F0327"}.mdi-lava-lamp::before{content:"\F07D5"}.mdi-layers::before{content:"\F0328"}.mdi-layers-minus::before{content:"\F0E4C"}.mdi-layers-off::before{content:"\F0329"}.mdi-layers-off-outline::before{content:"\F09FD"}.mdi-layers-outline::before{content:"\F09FE"}.mdi-layers-plus::before{content:"\F0E4D"}.mdi-layers-remove::before{content:"\F0E4E"}.mdi-layers-search::before{content:"\F1206"}.mdi-layers-search-outline::before{content:"\F1207"}.mdi-layers-triple::before{content:"\F0F58"}.mdi-layers-triple-outline::before{content:"\F0F59"}.mdi-lead-pencil::before{content:"\F064F"}.mdi-leaf::before{content:"\F032A"}.mdi-leaf-maple::before{content:"\F0C93"}.mdi-leaf-maple-off::before{content:"\F12DA"}.mdi-leaf-off::before{content:"\F12D9"}.mdi-leak::before{content:"\F0DD7"}.mdi-leak-off::before{content:"\F0DD8"}.mdi-led-off::before{content:"\F032B"}.mdi-led-on::before{content:"\F032C"}.mdi-led-outline::before{content:"\F032D"}.mdi-led-strip::before{content:"\F07D6"}.mdi-led-strip-variant::before{content:"\F1051"}.mdi-led-variant-off::before{content:"\F032E"}.mdi-led-variant-on::before{content:"\F032F"}.mdi-led-variant-outline::before{content:"\F0330"}.mdi-leek::before{content:"\F117D"}.mdi-less-than::before{content:"\F097C"}.mdi-less-than-or-equal::before{content:"\F097D"}.mdi-library::before{content:"\F0331"}.mdi-library-shelves::before{content:"\F0BA9"}.mdi-license::before{content:"\F0FC3"}.mdi-lifebuoy::before{content:"\F087E"}.mdi-light-switch::before{content:"\F097E"}.mdi-lightbulb::before{content:"\F0335"}.mdi-lightbulb-cfl::before{content:"\F1208"}.mdi-lightbulb-cfl-off::before{content:"\F1209"}.mdi-lightbulb-cfl-spiral::before{content:"\F1275"}.mdi-lightbulb-cfl-spiral-off::before{content:"\F12C3"}.mdi-lightbulb-group::before{content:"\F1253"}.mdi-lightbulb-group-off::before{content:"\F12CD"}.mdi-lightbulb-group-off-outline::before{content:"\F12CE"}.mdi-lightbulb-group-outline::before{content:"\F1254"}.mdi-lightbulb-multiple::before{content:"\F1255"}.mdi-lightbulb-multiple-off::before{content:"\F12CF"}.mdi-lightbulb-multiple-off-outline::before{content:"\F12D0"}.mdi-lightbulb-multiple-outline::before{content:"\F1256"}.mdi-lightbulb-off::before{content:"\F0E4F"}.mdi-lightbulb-off-outline::before{content:"\F0E50"}.mdi-lightbulb-on::before{content:"\F06E8"}.mdi-lightbulb-on-outline::before{content:"\F06E9"}.mdi-lightbulb-outline::before{content:"\F0336"}.mdi-lighthouse::before{content:"\F09FF"}.mdi-lighthouse-on::before{content:"\F0A00"}.mdi-lightning-bolt::before{content:"\F140B"}.mdi-lightning-bolt-outline::before{content:"\F140C"}.mdi-lingerie::before{content:"\F1476"}.mdi-link::before{content:"\F0337"}.mdi-link-box::before{content:"\F0D1A"}.mdi-link-box-outline::before{content:"\F0D1B"}.mdi-link-box-variant::before{content:"\F0D1C"}.mdi-link-box-variant-outline::before{content:"\F0D1D"}.mdi-link-lock::before{content:"\F10BA"}.mdi-link-off::before{content:"\F0338"}.mdi-link-plus::before{content:"\F0C94"}.mdi-link-variant::before{content:"\F0339"}.mdi-link-variant-minus::before{content:"\F10FF"}.mdi-link-variant-off::before{content:"\F033A"}.mdi-link-variant-plus::before{content:"\F1100"}.mdi-link-variant-remove::before{content:"\F1101"}.mdi-linkedin::before{content:"\F033B"}.mdi-linux::before{content:"\F033D"}.mdi-linux-mint::before{content:"\F08ED"}.mdi-lipstick::before{content:"\F13B5"}.mdi-list-status::before{content:"\F15AB"}.mdi-litecoin::before{content:"\F0A61"}.mdi-loading::before{content:"\F0772"}.mdi-location-enter::before{content:"\F0FC4"}.mdi-location-exit::before{content:"\F0FC5"}.mdi-lock::before{content:"\F033E"}.mdi-lock-alert::before{content:"\F08EE"}.mdi-lock-alert-outline::before{content:"\F15D1"}.mdi-lock-check::before{content:"\F139A"}.mdi-lock-check-outline::before{content:"\F16A8"}.mdi-lock-clock::before{content:"\F097F"}.mdi-lock-minus::before{content:"\F16A9"}.mdi-lock-minus-outline::before{content:"\F16AA"}.mdi-lock-off::before{content:"\F1671"}.mdi-lock-off-outline::before{content:"\F1672"}.mdi-lock-open::before{content:"\F033F"}.mdi-lock-open-alert::before{content:"\F139B"}.mdi-lock-open-alert-outline::before{content:"\F15D2"}.mdi-lock-open-check::before{content:"\F139C"}.mdi-lock-open-check-outline::before{content:"\F16AB"}.mdi-lock-open-minus::before{content:"\F16AC"}.mdi-lock-open-minus-outline::before{content:"\F16AD"}.mdi-lock-open-outline::before{content:"\F0340"}.mdi-lock-open-plus::before{content:"\F16AE"}.mdi-lock-open-plus-outline::before{content:"\F16AF"}.mdi-lock-open-remove::before{content:"\F16B0"}.mdi-lock-open-remove-outline::before{content:"\F16B1"}.mdi-lock-open-variant::before{content:"\F0FC6"}.mdi-lock-open-variant-outline::before{content:"\F0FC7"}.mdi-lock-outline::before{content:"\F0341"}.mdi-lock-pattern::before{content:"\F06EA"}.mdi-lock-plus::before{content:"\F05FB"}.mdi-lock-plus-outline::before{content:"\F16B2"}.mdi-lock-question::before{content:"\F08EF"}.mdi-lock-remove::before{content:"\F16B3"}.mdi-lock-remove-outline::before{content:"\F16B4"}.mdi-lock-reset::before{content:"\F0773"}.mdi-lock-smart::before{content:"\F08B2"}.mdi-locker::before{content:"\F07D7"}.mdi-locker-multiple::before{content:"\F07D8"}.mdi-login::before{content:"\F0342"}.mdi-login-variant::before{content:"\F05FC"}.mdi-logout::before{content:"\F0343"}.mdi-logout-variant::before{content:"\F05FD"}.mdi-longitude::before{content:"\F0F5A"}.mdi-looks::before{content:"\F0344"}.mdi-lotion::before{content:"\F1582"}.mdi-lotion-outline::before{content:"\F1583"}.mdi-lotion-plus::before{content:"\F1584"}.mdi-lotion-plus-outline::before{content:"\F1585"}.mdi-loupe::before{content:"\F0345"}.mdi-lumx::before{content:"\F0346"}.mdi-lungs::before{content:"\F1084"}.mdi-magnet::before{content:"\F0347"}.mdi-magnet-on::before{content:"\F0348"}.mdi-magnify::before{content:"\F0349"}.mdi-magnify-close::before{content:"\F0980"}.mdi-magnify-minus::before{content:"\F034A"}.mdi-magnify-minus-cursor::before{content:"\F0A62"}.mdi-magnify-minus-outline::before{content:"\F06EC"}.mdi-magnify-plus::before{content:"\F034B"}.mdi-magnify-plus-cursor::before{content:"\F0A63"}.mdi-magnify-plus-outline::before{content:"\F06ED"}.mdi-magnify-remove-cursor::before{content:"\F120C"}.mdi-magnify-remove-outline::before{content:"\F120D"}.mdi-magnify-scan::before{content:"\F1276"}.mdi-mail::before{content:"\F0EBB"}.mdi-mailbox::before{content:"\F06EE"}.mdi-mailbox-open::before{content:"\F0D88"}.mdi-mailbox-open-outline::before{content:"\F0D89"}.mdi-mailbox-open-up::before{content:"\F0D8A"}.mdi-mailbox-open-up-outline::before{content:"\F0D8B"}.mdi-mailbox-outline::before{content:"\F0D8C"}.mdi-mailbox-up::before{content:"\F0D8D"}.mdi-mailbox-up-outline::before{content:"\F0D8E"}.mdi-manjaro::before{content:"\F160A"}.mdi-map::before{content:"\F034D"}.mdi-map-check::before{content:"\F0EBC"}.mdi-map-check-outline::before{content:"\F0EBD"}.mdi-map-clock::before{content:"\F0D1E"}.mdi-map-clock-outline::before{content:"\F0D1F"}.mdi-map-legend::before{content:"\F0A01"}.mdi-map-marker::before{content:"\F034E"}.mdi-map-marker-alert::before{content:"\F0F05"}.mdi-map-marker-alert-outline::before{content:"\F0F06"}.mdi-map-marker-check::before{content:"\F0C95"}.mdi-map-marker-check-outline::before{content:"\F12FB"}.mdi-map-marker-circle::before{content:"\F034F"}.mdi-map-marker-distance::before{content:"\F08F0"}.mdi-map-marker-down::before{content:"\F1102"}.mdi-map-marker-left::before{content:"\F12DB"}.mdi-map-marker-left-outline::before{content:"\F12DD"}.mdi-map-marker-minus::before{content:"\F0650"}.mdi-map-marker-minus-outline::before{content:"\F12F9"}.mdi-map-marker-multiple::before{content:"\F0350"}.mdi-map-marker-multiple-outline::before{content:"\F1277"}.mdi-map-marker-off::before{content:"\F0351"}.mdi-map-marker-off-outline::before{content:"\F12FD"}.mdi-map-marker-outline::before{content:"\F07D9"}.mdi-map-marker-path::before{content:"\F0D20"}.mdi-map-marker-plus::before{content:"\F0651"}.mdi-map-marker-plus-outline::before{content:"\F12F8"}.mdi-map-marker-question::before{content:"\F0F07"}.mdi-map-marker-question-outline::before{content:"\F0F08"}.mdi-map-marker-radius::before{content:"\F0352"}.mdi-map-marker-radius-outline::before{content:"\F12FC"}.mdi-map-marker-remove::before{content:"\F0F09"}.mdi-map-marker-remove-outline::before{content:"\F12FA"}.mdi-map-marker-remove-variant::before{content:"\F0F0A"}.mdi-map-marker-right::before{content:"\F12DC"}.mdi-map-marker-right-outline::before{content:"\F12DE"}.mdi-map-marker-star::before{content:"\F1608"}.mdi-map-marker-star-outline::before{content:"\F1609"}.mdi-map-marker-up::before{content:"\F1103"}.mdi-map-minus::before{content:"\F0981"}.mdi-map-outline::before{content:"\F0982"}.mdi-map-plus::before{content:"\F0983"}.mdi-map-search::before{content:"\F0984"}.mdi-map-search-outline::before{content:"\F0985"}.mdi-mapbox::before{content:"\F0BAA"}.mdi-margin::before{content:"\F0353"}.mdi-marker::before{content:"\F0652"}.mdi-marker-cancel::before{content:"\F0DD9"}.mdi-marker-check::before{content:"\F0355"}.mdi-mastodon::before{content:"\F0AD1"}.mdi-material-design::before{content:"\F0986"}.mdi-material-ui::before{content:"\F0357"}.mdi-math-compass::before{content:"\F0358"}.mdi-math-cos::before{content:"\F0C96"}.mdi-math-integral::before{content:"\F0FC8"}.mdi-math-integral-box::before{content:"\F0FC9"}.mdi-math-log::before{content:"\F1085"}.mdi-math-norm::before{content:"\F0FCA"}.mdi-math-norm-box::before{content:"\F0FCB"}.mdi-math-sin::before{content:"\F0C97"}.mdi-math-tan::before{content:"\F0C98"}.mdi-matrix::before{content:"\F0628"}.mdi-medal::before{content:"\F0987"}.mdi-medal-outline::before{content:"\F1326"}.mdi-medical-bag::before{content:"\F06EF"}.mdi-meditation::before{content:"\F117B"}.mdi-memory::before{content:"\F035B"}.mdi-menu::before{content:"\F035C"}.mdi-menu-down::before{content:"\F035D"}.mdi-menu-down-outline::before{content:"\F06B6"}.mdi-menu-left::before{content:"\F035E"}.mdi-menu-left-outline::before{content:"\F0A02"}.mdi-menu-open::before{content:"\F0BAB"}.mdi-menu-right::before{content:"\F035F"}.mdi-menu-right-outline::before{content:"\F0A03"}.mdi-menu-swap::before{content:"\F0A64"}.mdi-menu-swap-outline::before{content:"\F0A65"}.mdi-menu-up::before{content:"\F0360"}.mdi-menu-up-outline::before{content:"\F06B7"}.mdi-merge::before{content:"\F0F5C"}.mdi-message::before{content:"\F0361"}.mdi-message-alert::before{content:"\F0362"}.mdi-message-alert-outline::before{content:"\F0A04"}.mdi-message-arrow-left::before{content:"\F12F2"}.mdi-message-arrow-left-outline::before{content:"\F12F3"}.mdi-message-arrow-right::before{content:"\F12F4"}.mdi-message-arrow-right-outline::before{content:"\F12F5"}.mdi-message-bookmark::before{content:"\F15AC"}.mdi-message-bookmark-outline::before{content:"\F15AD"}.mdi-message-bulleted::before{content:"\F06A2"}.mdi-message-bulleted-off::before{content:"\F06A3"}.mdi-message-cog::before{content:"\F06F1"}.mdi-message-cog-outline::before{content:"\F1172"}.mdi-message-draw::before{content:"\F0363"}.mdi-message-flash::before{content:"\F15A9"}.mdi-message-flash-outline::before{content:"\F15AA"}.mdi-message-image::before{content:"\F0364"}.mdi-message-image-outline::before{content:"\F116C"}.mdi-message-lock::before{content:"\F0FCC"}.mdi-message-lock-outline::before{content:"\F116D"}.mdi-message-minus::before{content:"\F116E"}.mdi-message-minus-outline::before{content:"\F116F"}.mdi-message-off::before{content:"\F164D"}.mdi-message-off-outline::before{content:"\F164E"}.mdi-message-outline::before{content:"\F0365"}.mdi-message-plus::before{content:"\F0653"}.mdi-message-plus-outline::before{content:"\F10BB"}.mdi-message-processing::before{content:"\F0366"}.mdi-message-processing-outline::before{content:"\F1170"}.mdi-message-reply::before{content:"\F0367"}.mdi-message-reply-text::before{content:"\F0368"}.mdi-message-settings::before{content:"\F06F0"}.mdi-message-settings-outline::before{content:"\F1171"}.mdi-message-text::before{content:"\F0369"}.mdi-message-text-clock::before{content:"\F1173"}.mdi-message-text-clock-outline::before{content:"\F1174"}.mdi-message-text-lock::before{content:"\F0FCD"}.mdi-message-text-lock-outline::before{content:"\F1175"}.mdi-message-text-outline::before{content:"\F036A"}.mdi-message-video::before{content:"\F036B"}.mdi-meteor::before{content:"\F0629"}.mdi-metronome::before{content:"\F07DA"}.mdi-metronome-tick::before{content:"\F07DB"}.mdi-micro-sd::before{content:"\F07DC"}.mdi-microphone::before{content:"\F036C"}.mdi-microphone-minus::before{content:"\F08B3"}.mdi-microphone-off::before{content:"\F036D"}.mdi-microphone-outline::before{content:"\F036E"}.mdi-microphone-plus::before{content:"\F08B4"}.mdi-microphone-settings::before{content:"\F036F"}.mdi-microphone-variant::before{content:"\F0370"}.mdi-microphone-variant-off::before{content:"\F0371"}.mdi-microscope::before{content:"\F0654"}.mdi-microsoft::before{content:"\F0372"}.mdi-microsoft-access::before{content:"\F138E"}.mdi-microsoft-azure::before{content:"\F0805"}.mdi-microsoft-azure-devops::before{content:"\F0FD5"}.mdi-microsoft-bing::before{content:"\F00A4"}.mdi-microsoft-dynamics-365::before{content:"\F0988"}.mdi-microsoft-edge::before{content:"\F01E9"}.mdi-microsoft-edge-legacy::before{content:"\F1250"}.mdi-microsoft-excel::before{content:"\F138F"}.mdi-microsoft-internet-explorer::before{content:"\F0300"}.mdi-microsoft-office::before{content:"\F03C6"}.mdi-microsoft-onedrive::before{content:"\F03CA"}.mdi-microsoft-onenote::before{content:"\F0747"}.mdi-microsoft-outlook::before{content:"\F0D22"}.mdi-microsoft-powerpoint::before{content:"\F1390"}.mdi-microsoft-sharepoint::before{content:"\F1391"}.mdi-microsoft-teams::before{content:"\F02BB"}.mdi-microsoft-visual-studio::before{content:"\F0610"}.mdi-microsoft-visual-studio-code::before{content:"\F0A1E"}.mdi-microsoft-windows::before{content:"\F05B3"}.mdi-microsoft-windows-classic::before{content:"\F0A21"}.mdi-microsoft-word::before{content:"\F1392"}.mdi-microsoft-xbox::before{content:"\F05B9"}.mdi-microsoft-xbox-controller::before{content:"\F05BA"}.mdi-microsoft-xbox-controller-battery-alert::before{content:"\F074B"}.mdi-microsoft-xbox-controller-battery-charging::before{content:"\F0A22"}.mdi-microsoft-xbox-controller-battery-empty::before{content:"\F074C"}.mdi-microsoft-xbox-controller-battery-full::before{content:"\F074D"}.mdi-microsoft-xbox-controller-battery-low::before{content:"\F074E"}.mdi-microsoft-xbox-controller-battery-medium::before{content:"\F074F"}.mdi-microsoft-xbox-controller-battery-unknown::before{content:"\F0750"}.mdi-microsoft-xbox-controller-menu::before{content:"\F0E6F"}.mdi-microsoft-xbox-controller-off::before{content:"\F05BB"}.mdi-microsoft-xbox-controller-view::before{content:"\F0E70"}.mdi-microsoft-yammer::before{content:"\F0789"}.mdi-microwave::before{content:"\F0C99"}.mdi-microwave-off::before{content:"\F1423"}.mdi-middleware::before{content:"\F0F5D"}.mdi-middleware-outline::before{content:"\F0F5E"}.mdi-midi::before{content:"\F08F1"}.mdi-midi-port::before{content:"\F08F2"}.mdi-mine::before{content:"\F0DDA"}.mdi-minecraft::before{content:"\F0373"}.mdi-mini-sd::before{content:"\F0A05"}.mdi-minidisc::before{content:"\F0A06"}.mdi-minus::before{content:"\F0374"}.mdi-minus-box::before{content:"\F0375"}.mdi-minus-box-multiple::before{content:"\F1141"}.mdi-minus-box-multiple-outline::before{content:"\F1142"}.mdi-minus-box-outline::before{content:"\F06F2"}.mdi-minus-circle::before{content:"\F0376"}.mdi-minus-circle-multiple::before{content:"\F035A"}.mdi-minus-circle-multiple-outline::before{content:"\F0AD3"}.mdi-minus-circle-off::before{content:"\F1459"}.mdi-minus-circle-off-outline::before{content:"\F145A"}.mdi-minus-circle-outline::before{content:"\F0377"}.mdi-minus-network::before{content:"\F0378"}.mdi-minus-network-outline::before{content:"\F0C9A"}.mdi-minus-thick::before{content:"\F1639"}.mdi-mirror::before{content:"\F11FD"}.mdi-mixed-martial-arts::before{content:"\F0D8F"}.mdi-mixed-reality::before{content:"\F087F"}.mdi-molecule::before{content:"\F0BAC"}.mdi-molecule-co::before{content:"\F12FE"}.mdi-molecule-co2::before{content:"\F07E4"}.mdi-monitor::before{content:"\F0379"}.mdi-monitor-cellphone::before{content:"\F0989"}.mdi-monitor-cellphone-star::before{content:"\F098A"}.mdi-monitor-clean::before{content:"\F1104"}.mdi-monitor-dashboard::before{content:"\F0A07"}.mdi-monitor-edit::before{content:"\F12C6"}.mdi-monitor-eye::before{content:"\F13B4"}.mdi-monitor-lock::before{content:"\F0DDB"}.mdi-monitor-multiple::before{content:"\F037A"}.mdi-monitor-off::before{content:"\F0D90"}.mdi-monitor-screenshot::before{content:"\F0E51"}.mdi-monitor-share::before{content:"\F1483"}.mdi-monitor-speaker::before{content:"\F0F5F"}.mdi-monitor-speaker-off::before{content:"\F0F60"}.mdi-monitor-star::before{content:"\F0DDC"}.mdi-moon-first-quarter::before{content:"\F0F61"}.mdi-moon-full::before{content:"\F0F62"}.mdi-moon-last-quarter::before{content:"\F0F63"}.mdi-moon-new::before{content:"\F0F64"}.mdi-moon-waning-crescent::before{content:"\F0F65"}.mdi-moon-waning-gibbous::before{content:"\F0F66"}.mdi-moon-waxing-crescent::before{content:"\F0F67"}.mdi-moon-waxing-gibbous::before{content:"\F0F68"}.mdi-moped::before{content:"\F1086"}.mdi-moped-electric::before{content:"\F15B7"}.mdi-moped-electric-outline::before{content:"\F15B8"}.mdi-moped-outline::before{content:"\F15B9"}.mdi-more::before{content:"\F037B"}.mdi-mother-heart::before{content:"\F1314"}.mdi-mother-nurse::before{content:"\F0D21"}.mdi-motion::before{content:"\F15B2"}.mdi-motion-outline::before{content:"\F15B3"}.mdi-motion-pause::before{content:"\F1590"}.mdi-motion-pause-outline::before{content:"\F1592"}.mdi-motion-play::before{content:"\F158F"}.mdi-motion-play-outline::before{content:"\F1591"}.mdi-motion-sensor::before{content:"\F0D91"}.mdi-motion-sensor-off::before{content:"\F1435"}.mdi-motorbike::before{content:"\F037C"}.mdi-motorbike-electric::before{content:"\F15BA"}.mdi-mouse::before{content:"\F037D"}.mdi-mouse-bluetooth::before{content:"\F098B"}.mdi-mouse-move-down::before{content:"\F1550"}.mdi-mouse-move-up::before{content:"\F1551"}.mdi-mouse-move-vertical::before{content:"\F1552"}.mdi-mouse-off::before{content:"\F037E"}.mdi-mouse-variant::before{content:"\F037F"}.mdi-mouse-variant-off::before{content:"\F0380"}.mdi-move-resize::before{content:"\F0655"}.mdi-move-resize-variant::before{content:"\F0656"}.mdi-movie::before{content:"\F0381"}.mdi-movie-edit::before{content:"\F1122"}.mdi-movie-edit-outline::before{content:"\F1123"}.mdi-movie-filter::before{content:"\F1124"}.mdi-movie-filter-outline::before{content:"\F1125"}.mdi-movie-open::before{content:"\F0FCE"}.mdi-movie-open-outline::before{content:"\F0FCF"}.mdi-movie-outline::before{content:"\F0DDD"}.mdi-movie-roll::before{content:"\F07DE"}.mdi-movie-search::before{content:"\F11D2"}.mdi-movie-search-outline::before{content:"\F11D3"}.mdi-mower::before{content:"\F166F"}.mdi-mower-bag::before{content:"\F1670"}.mdi-muffin::before{content:"\F098C"}.mdi-multiplication::before{content:"\F0382"}.mdi-multiplication-box::before{content:"\F0383"}.mdi-mushroom::before{content:"\F07DF"}.mdi-mushroom-off::before{content:"\F13FA"}.mdi-mushroom-off-outline::before{content:"\F13FB"}.mdi-mushroom-outline::before{content:"\F07E0"}.mdi-music::before{content:"\F075A"}.mdi-music-accidental-double-flat::before{content:"\F0F69"}.mdi-music-accidental-double-sharp::before{content:"\F0F6A"}.mdi-music-accidental-flat::before{content:"\F0F6B"}.mdi-music-accidental-natural::before{content:"\F0F6C"}.mdi-music-accidental-sharp::before{content:"\F0F6D"}.mdi-music-box::before{content:"\F0384"}.mdi-music-box-multiple::before{content:"\F0333"}.mdi-music-box-multiple-outline::before{content:"\F0F04"}.mdi-music-box-outline::before{content:"\F0385"}.mdi-music-circle::before{content:"\F0386"}.mdi-music-circle-outline::before{content:"\F0AD4"}.mdi-music-clef-alto::before{content:"\F0F6E"}.mdi-music-clef-bass::before{content:"\F0F6F"}.mdi-music-clef-treble::before{content:"\F0F70"}.mdi-music-note::before{content:"\F0387"}.mdi-music-note-bluetooth::before{content:"\F05FE"}.mdi-music-note-bluetooth-off::before{content:"\F05FF"}.mdi-music-note-eighth::before{content:"\F0388"}.mdi-music-note-eighth-dotted::before{content:"\F0F71"}.mdi-music-note-half::before{content:"\F0389"}.mdi-music-note-half-dotted::before{content:"\F0F72"}.mdi-music-note-off::before{content:"\F038A"}.mdi-music-note-off-outline::before{content:"\F0F73"}.mdi-music-note-outline::before{content:"\F0F74"}.mdi-music-note-plus::before{content:"\F0DDE"}.mdi-music-note-quarter::before{content:"\F038B"}.mdi-music-note-quarter-dotted::before{content:"\F0F75"}.mdi-music-note-sixteenth::before{content:"\F038C"}.mdi-music-note-sixteenth-dotted::before{content:"\F0F76"}.mdi-music-note-whole::before{content:"\F038D"}.mdi-music-note-whole-dotted::before{content:"\F0F77"}.mdi-music-off::before{content:"\F075B"}.mdi-music-rest-eighth::before{content:"\F0F78"}.mdi-music-rest-half::before{content:"\F0F79"}.mdi-music-rest-quarter::before{content:"\F0F7A"}.mdi-music-rest-sixteenth::before{content:"\F0F7B"}.mdi-music-rest-whole::before{content:"\F0F7C"}.mdi-mustache::before{content:"\F15DE"}.mdi-nail::before{content:"\F0DDF"}.mdi-nas::before{content:"\F08F3"}.mdi-nativescript::before{content:"\F0880"}.mdi-nature::before{content:"\F038E"}.mdi-nature-people::before{content:"\F038F"}.mdi-navigation::before{content:"\F0390"}.mdi-navigation-outline::before{content:"\F1607"}.mdi-near-me::before{content:"\F05CD"}.mdi-necklace::before{content:"\F0F0B"}.mdi-needle::before{content:"\F0391"}.mdi-netflix::before{content:"\F0746"}.mdi-network::before{content:"\F06F3"}.mdi-network-off::before{content:"\F0C9B"}.mdi-network-off-outline::before{content:"\F0C9C"}.mdi-network-outline::before{content:"\F0C9D"}.mdi-network-strength-1::before{content:"\F08F4"}.mdi-network-strength-1-alert::before{content:"\F08F5"}.mdi-network-strength-2::before{content:"\F08F6"}.mdi-network-strength-2-alert::before{content:"\F08F7"}.mdi-network-strength-3::before{content:"\F08F8"}.mdi-network-strength-3-alert::before{content:"\F08F9"}.mdi-network-strength-4::before{content:"\F08FA"}.mdi-network-strength-4-alert::before{content:"\F08FB"}.mdi-network-strength-off::before{content:"\F08FC"}.mdi-network-strength-off-outline::before{content:"\F08FD"}.mdi-network-strength-outline::before{content:"\F08FE"}.mdi-new-box::before{content:"\F0394"}.mdi-newspaper::before{content:"\F0395"}.mdi-newspaper-minus::before{content:"\F0F0C"}.mdi-newspaper-plus::before{content:"\F0F0D"}.mdi-newspaper-variant::before{content:"\F1001"}.mdi-newspaper-variant-multiple::before{content:"\F1002"}.mdi-newspaper-variant-multiple-outline::before{content:"\F1003"}.mdi-newspaper-variant-outline::before{content:"\F1004"}.mdi-nfc::before{content:"\F0396"}.mdi-nfc-search-variant::before{content:"\F0E53"}.mdi-nfc-tap::before{content:"\F0397"}.mdi-nfc-variant::before{content:"\F0398"}.mdi-nfc-variant-off::before{content:"\F0E54"}.mdi-ninja::before{content:"\F0774"}.mdi-nintendo-game-boy::before{content:"\F1393"}.mdi-nintendo-switch::before{content:"\F07E1"}.mdi-nintendo-wii::before{content:"\F05AB"}.mdi-nintendo-wiiu::before{content:"\F072D"}.mdi-nix::before{content:"\F1105"}.mdi-nodejs::before{content:"\F0399"}.mdi-noodles::before{content:"\F117E"}.mdi-not-equal::before{content:"\F098D"}.mdi-not-equal-variant::before{content:"\F098E"}.mdi-note::before{content:"\F039A"}.mdi-note-minus::before{content:"\F164F"}.mdi-note-minus-outline::before{content:"\F1650"}.mdi-note-multiple::before{content:"\F06B8"}.mdi-note-multiple-outline::before{content:"\F06B9"}.mdi-note-outline::before{content:"\F039B"}.mdi-note-plus::before{content:"\F039C"}.mdi-note-plus-outline::before{content:"\F039D"}.mdi-note-remove::before{content:"\F1651"}.mdi-note-remove-outline::before{content:"\F1652"}.mdi-note-search::before{content:"\F1653"}.mdi-note-search-outline::before{content:"\F1654"}.mdi-note-text::before{content:"\F039E"}.mdi-note-text-outline::before{content:"\F11D7"}.mdi-notebook::before{content:"\F082E"}.mdi-notebook-check::before{content:"\F14F5"}.mdi-notebook-check-outline::before{content:"\F14F6"}.mdi-notebook-edit::before{content:"\F14E7"}.mdi-notebook-edit-outline::before{content:"\F14E9"}.mdi-notebook-minus::before{content:"\F1610"}.mdi-notebook-minus-outline::before{content:"\F1611"}.mdi-notebook-multiple::before{content:"\F0E55"}.mdi-notebook-outline::before{content:"\F0EBF"}.mdi-notebook-plus::before{content:"\F1612"}.mdi-notebook-plus-outline::before{content:"\F1613"}.mdi-notebook-remove::before{content:"\F1614"}.mdi-notebook-remove-outline::before{content:"\F1615"}.mdi-notification-clear-all::before{content:"\F039F"}.mdi-npm::before{content:"\F06F7"}.mdi-nuke::before{content:"\F06A4"}.mdi-null::before{content:"\F07E2"}.mdi-numeric::before{content:"\F03A0"}.mdi-numeric-0::before{content:"\F0B39"}.mdi-numeric-0-box::before{content:"\F03A1"}.mdi-numeric-0-box-multiple::before{content:"\F0F0E"}.mdi-numeric-0-box-multiple-outline::before{content:"\F03A2"}.mdi-numeric-0-box-outline::before{content:"\F03A3"}.mdi-numeric-0-circle::before{content:"\F0C9E"}.mdi-numeric-0-circle-outline::before{content:"\F0C9F"}.mdi-numeric-1::before{content:"\F0B3A"}.mdi-numeric-1-box::before{content:"\F03A4"}.mdi-numeric-1-box-multiple::before{content:"\F0F0F"}.mdi-numeric-1-box-multiple-outline::before{content:"\F03A5"}.mdi-numeric-1-box-outline::before{content:"\F03A6"}.mdi-numeric-1-circle::before{content:"\F0CA0"}.mdi-numeric-1-circle-outline::before{content:"\F0CA1"}.mdi-numeric-10::before{content:"\F0FE9"}.mdi-numeric-10-box::before{content:"\F0F7D"}.mdi-numeric-10-box-multiple::before{content:"\F0FEA"}.mdi-numeric-10-box-multiple-outline::before{content:"\F0FEB"}.mdi-numeric-10-box-outline::before{content:"\F0F7E"}.mdi-numeric-10-circle::before{content:"\F0FEC"}.mdi-numeric-10-circle-outline::before{content:"\F0FED"}.mdi-numeric-2::before{content:"\F0B3B"}.mdi-numeric-2-box::before{content:"\F03A7"}.mdi-numeric-2-box-multiple::before{content:"\F0F10"}.mdi-numeric-2-box-multiple-outline::before{content:"\F03A8"}.mdi-numeric-2-box-outline::before{content:"\F03A9"}.mdi-numeric-2-circle::before{content:"\F0CA2"}.mdi-numeric-2-circle-outline::before{content:"\F0CA3"}.mdi-numeric-3::before{content:"\F0B3C"}.mdi-numeric-3-box::before{content:"\F03AA"}.mdi-numeric-3-box-multiple::before{content:"\F0F11"}.mdi-numeric-3-box-multiple-outline::before{content:"\F03AB"}.mdi-numeric-3-box-outline::before{content:"\F03AC"}.mdi-numeric-3-circle::before{content:"\F0CA4"}.mdi-numeric-3-circle-outline::before{content:"\F0CA5"}.mdi-numeric-4::before{content:"\F0B3D"}.mdi-numeric-4-box::before{content:"\F03AD"}.mdi-numeric-4-box-multiple::before{content:"\F0F12"}.mdi-numeric-4-box-multiple-outline::before{content:"\F03B2"}.mdi-numeric-4-box-outline::before{content:"\F03AE"}.mdi-numeric-4-circle::before{content:"\F0CA6"}.mdi-numeric-4-circle-outline::before{content:"\F0CA7"}.mdi-numeric-5::before{content:"\F0B3E"}.mdi-numeric-5-box::before{content:"\F03B1"}.mdi-numeric-5-box-multiple::before{content:"\F0F13"}.mdi-numeric-5-box-multiple-outline::before{content:"\F03AF"}.mdi-numeric-5-box-outline::before{content:"\F03B0"}.mdi-numeric-5-circle::before{content:"\F0CA8"}.mdi-numeric-5-circle-outline::before{content:"\F0CA9"}.mdi-numeric-6::before{content:"\F0B3F"}.mdi-numeric-6-box::before{content:"\F03B3"}.mdi-numeric-6-box-multiple::before{content:"\F0F14"}.mdi-numeric-6-box-multiple-outline::before{content:"\F03B4"}.mdi-numeric-6-box-outline::before{content:"\F03B5"}.mdi-numeric-6-circle::before{content:"\F0CAA"}.mdi-numeric-6-circle-outline::before{content:"\F0CAB"}.mdi-numeric-7::before{content:"\F0B40"}.mdi-numeric-7-box::before{content:"\F03B6"}.mdi-numeric-7-box-multiple::before{content:"\F0F15"}.mdi-numeric-7-box-multiple-outline::before{content:"\F03B7"}.mdi-numeric-7-box-outline::before{content:"\F03B8"}.mdi-numeric-7-circle::before{content:"\F0CAC"}.mdi-numeric-7-circle-outline::before{content:"\F0CAD"}.mdi-numeric-8::before{content:"\F0B41"}.mdi-numeric-8-box::before{content:"\F03B9"}.mdi-numeric-8-box-multiple::before{content:"\F0F16"}.mdi-numeric-8-box-multiple-outline::before{content:"\F03BA"}.mdi-numeric-8-box-outline::before{content:"\F03BB"}.mdi-numeric-8-circle::before{content:"\F0CAE"}.mdi-numeric-8-circle-outline::before{content:"\F0CAF"}.mdi-numeric-9::before{content:"\F0B42"}.mdi-numeric-9-box::before{content:"\F03BC"}.mdi-numeric-9-box-multiple::before{content:"\F0F17"}.mdi-numeric-9-box-multiple-outline::before{content:"\F03BD"}.mdi-numeric-9-box-outline::before{content:"\F03BE"}.mdi-numeric-9-circle::before{content:"\F0CB0"}.mdi-numeric-9-circle-outline::before{content:"\F0CB1"}.mdi-numeric-9-plus::before{content:"\F0FEE"}.mdi-numeric-9-plus-box::before{content:"\F03BF"}.mdi-numeric-9-plus-box-multiple::before{content:"\F0F18"}.mdi-numeric-9-plus-box-multiple-outline::before{content:"\F03C0"}.mdi-numeric-9-plus-box-outline::before{content:"\F03C1"}.mdi-numeric-9-plus-circle::before{content:"\F0CB2"}.mdi-numeric-9-plus-circle-outline::before{content:"\F0CB3"}.mdi-numeric-negative-1::before{content:"\F1052"}.mdi-numeric-positive-1::before{content:"\F15CB"}.mdi-nut::before{content:"\F06F8"}.mdi-nutrition::before{content:"\F03C2"}.mdi-nuxt::before{content:"\F1106"}.mdi-oar::before{content:"\F067C"}.mdi-ocarina::before{content:"\F0DE0"}.mdi-oci::before{content:"\F12E9"}.mdi-ocr::before{content:"\F113A"}.mdi-octagon::before{content:"\F03C3"}.mdi-octagon-outline::before{content:"\F03C4"}.mdi-octagram::before{content:"\F06F9"}.mdi-octagram-outline::before{content:"\F0775"}.mdi-odnoklassniki::before{content:"\F03C5"}.mdi-offer::before{content:"\F121B"}.mdi-office-building::before{content:"\F0991"}.mdi-office-building-marker::before{content:"\F1520"}.mdi-office-building-marker-outline::before{content:"\F1521"}.mdi-office-building-outline::before{content:"\F151F"}.mdi-oil::before{content:"\F03C7"}.mdi-oil-lamp::before{content:"\F0F19"}.mdi-oil-level::before{content:"\F1053"}.mdi-oil-temperature::before{content:"\F0FF8"}.mdi-omega::before{content:"\F03C9"}.mdi-one-up::before{content:"\F0BAD"}.mdi-onepassword::before{content:"\F0881"}.mdi-opacity::before{content:"\F05CC"}.mdi-open-in-app::before{content:"\F03CB"}.mdi-open-in-new::before{content:"\F03CC"}.mdi-open-source-initiative::before{content:"\F0BAE"}.mdi-openid::before{content:"\F03CD"}.mdi-opera::before{content:"\F03CE"}.mdi-orbit::before{content:"\F0018"}.mdi-orbit-variant::before{content:"\F15DB"}.mdi-order-alphabetical-ascending::before{content:"\F020D"}.mdi-order-alphabetical-descending::before{content:"\F0D07"}.mdi-order-bool-ascending::before{content:"\F02BE"}.mdi-order-bool-ascending-variant::before{content:"\F098F"}.mdi-order-bool-descending::before{content:"\F1384"}.mdi-order-bool-descending-variant::before{content:"\F0990"}.mdi-order-numeric-ascending::before{content:"\F0545"}.mdi-order-numeric-descending::before{content:"\F0546"}.mdi-origin::before{content:"\F0B43"}.mdi-ornament::before{content:"\F03CF"}.mdi-ornament-variant::before{content:"\F03D0"}.mdi-outdoor-lamp::before{content:"\F1054"}.mdi-overscan::before{content:"\F1005"}.mdi-owl::before{content:"\F03D2"}.mdi-pac-man::before{content:"\F0BAF"}.mdi-package::before{content:"\F03D3"}.mdi-package-down::before{content:"\F03D4"}.mdi-package-up::before{content:"\F03D5"}.mdi-package-variant::before{content:"\F03D6"}.mdi-package-variant-closed::before{content:"\F03D7"}.mdi-page-first::before{content:"\F0600"}.mdi-page-last::before{content:"\F0601"}.mdi-page-layout-body::before{content:"\F06FA"}.mdi-page-layout-footer::before{content:"\F06FB"}.mdi-page-layout-header::before{content:"\F06FC"}.mdi-page-layout-header-footer::before{content:"\F0F7F"}.mdi-page-layout-sidebar-left::before{content:"\F06FD"}.mdi-page-layout-sidebar-right::before{content:"\F06FE"}.mdi-page-next::before{content:"\F0BB0"}.mdi-page-next-outline::before{content:"\F0BB1"}.mdi-page-previous::before{content:"\F0BB2"}.mdi-page-previous-outline::before{content:"\F0BB3"}.mdi-pail::before{content:"\F1417"}.mdi-pail-minus::before{content:"\F1437"}.mdi-pail-minus-outline::before{content:"\F143C"}.mdi-pail-off::before{content:"\F1439"}.mdi-pail-off-outline::before{content:"\F143E"}.mdi-pail-outline::before{content:"\F143A"}.mdi-pail-plus::before{content:"\F1436"}.mdi-pail-plus-outline::before{content:"\F143B"}.mdi-pail-remove::before{content:"\F1438"}.mdi-pail-remove-outline::before{content:"\F143D"}.mdi-palette::before{content:"\F03D8"}.mdi-palette-advanced::before{content:"\F03D9"}.mdi-palette-outline::before{content:"\F0E0C"}.mdi-palette-swatch::before{content:"\F08B5"}.mdi-palette-swatch-outline::before{content:"\F135C"}.mdi-palm-tree::before{content:"\F1055"}.mdi-pan::before{content:"\F0BB4"}.mdi-pan-bottom-left::before{content:"\F0BB5"}.mdi-pan-bottom-right::before{content:"\F0BB6"}.mdi-pan-down::before{content:"\F0BB7"}.mdi-pan-horizontal::before{content:"\F0BB8"}.mdi-pan-left::before{content:"\F0BB9"}.mdi-pan-right::before{content:"\F0BBA"}.mdi-pan-top-left::before{content:"\F0BBB"}.mdi-pan-top-right::before{content:"\F0BBC"}.mdi-pan-up::before{content:"\F0BBD"}.mdi-pan-vertical::before{content:"\F0BBE"}.mdi-panda::before{content:"\F03DA"}.mdi-pandora::before{content:"\F03DB"}.mdi-panorama::before{content:"\F03DC"}.mdi-panorama-fisheye::before{content:"\F03DD"}.mdi-panorama-horizontal::before{content:"\F03DE"}.mdi-panorama-vertical::before{content:"\F03DF"}.mdi-panorama-wide-angle::before{content:"\F03E0"}.mdi-paper-cut-vertical::before{content:"\F03E1"}.mdi-paper-roll::before{content:"\F1157"}.mdi-paper-roll-outline::before{content:"\F1158"}.mdi-paperclip::before{content:"\F03E2"}.mdi-parachute::before{content:"\F0CB4"}.mdi-parachute-outline::before{content:"\F0CB5"}.mdi-parking::before{content:"\F03E3"}.mdi-party-popper::before{content:"\F1056"}.mdi-passport::before{content:"\F07E3"}.mdi-passport-biometric::before{content:"\F0DE1"}.mdi-pasta::before{content:"\F1160"}.mdi-patio-heater::before{content:"\F0F80"}.mdi-patreon::before{content:"\F0882"}.mdi-pause::before{content:"\F03E4"}.mdi-pause-circle::before{content:"\F03E5"}.mdi-pause-circle-outline::before{content:"\F03E6"}.mdi-pause-octagon::before{content:"\F03E7"}.mdi-pause-octagon-outline::before{content:"\F03E8"}.mdi-paw::before{content:"\F03E9"}.mdi-paw-off::before{content:"\F0657"}.mdi-paw-off-outline::before{content:"\F1676"}.mdi-paw-outline::before{content:"\F1675"}.mdi-pdf-box::before{content:"\F0E56"}.mdi-peace::before{content:"\F0884"}.mdi-peanut::before{content:"\F0FFC"}.mdi-peanut-off::before{content:"\F0FFD"}.mdi-peanut-off-outline::before{content:"\F0FFF"}.mdi-peanut-outline::before{content:"\F0FFE"}.mdi-pen::before{content:"\F03EA"}.mdi-pen-lock::before{content:"\F0DE2"}.mdi-pen-minus::before{content:"\F0DE3"}.mdi-pen-off::before{content:"\F0DE4"}.mdi-pen-plus::before{content:"\F0DE5"}.mdi-pen-remove::before{content:"\F0DE6"}.mdi-pencil::before{content:"\F03EB"}.mdi-pencil-box::before{content:"\F03EC"}.mdi-pencil-box-multiple::before{content:"\F1144"}.mdi-pencil-box-multiple-outline::before{content:"\F1145"}.mdi-pencil-box-outline::before{content:"\F03ED"}.mdi-pencil-circle::before{content:"\F06FF"}.mdi-pencil-circle-outline::before{content:"\F0776"}.mdi-pencil-lock::before{content:"\F03EE"}.mdi-pencil-lock-outline::before{content:"\F0DE7"}.mdi-pencil-minus::before{content:"\F0DE8"}.mdi-pencil-minus-outline::before{content:"\F0DE9"}.mdi-pencil-off::before{content:"\F03EF"}.mdi-pencil-off-outline::before{content:"\F0DEA"}.mdi-pencil-outline::before{content:"\F0CB6"}.mdi-pencil-plus::before{content:"\F0DEB"}.mdi-pencil-plus-outline::before{content:"\F0DEC"}.mdi-pencil-remove::before{content:"\F0DED"}.mdi-pencil-remove-outline::before{content:"\F0DEE"}.mdi-pencil-ruler::before{content:"\F1353"}.mdi-penguin::before{content:"\F0EC0"}.mdi-pentagon::before{content:"\F0701"}.mdi-pentagon-outline::before{content:"\F0700"}.mdi-pentagram::before{content:"\F1667"}.mdi-percent::before{content:"\F03F0"}.mdi-percent-outline::before{content:"\F1278"}.mdi-periodic-table::before{content:"\F08B6"}.mdi-perspective-less::before{content:"\F0D23"}.mdi-perspective-more::before{content:"\F0D24"}.mdi-pharmacy::before{content:"\F03F1"}.mdi-phone::before{content:"\F03F2"}.mdi-phone-alert::before{content:"\F0F1A"}.mdi-phone-alert-outline::before{content:"\F118E"}.mdi-phone-bluetooth::before{content:"\F03F3"}.mdi-phone-bluetooth-outline::before{content:"\F118F"}.mdi-phone-cancel::before{content:"\F10BC"}.mdi-phone-cancel-outline::before{content:"\F1190"}.mdi-phone-check::before{content:"\F11A9"}.mdi-phone-check-outline::before{content:"\F11AA"}.mdi-phone-classic::before{content:"\F0602"}.mdi-phone-classic-off::before{content:"\F1279"}.mdi-phone-dial::before{content:"\F1559"}.mdi-phone-dial-outline::before{content:"\F155A"}.mdi-phone-forward::before{content:"\F03F4"}.mdi-phone-forward-outline::before{content:"\F1191"}.mdi-phone-hangup::before{content:"\F03F5"}.mdi-phone-hangup-outline::before{content:"\F1192"}.mdi-phone-in-talk::before{content:"\F03F6"}.mdi-phone-in-talk-outline::before{content:"\F1182"}.mdi-phone-incoming::before{content:"\F03F7"}.mdi-phone-incoming-outline::before{content:"\F1193"}.mdi-phone-lock::before{content:"\F03F8"}.mdi-phone-lock-outline::before{content:"\F1194"}.mdi-phone-log::before{content:"\F03F9"}.mdi-phone-log-outline::before{content:"\F1195"}.mdi-phone-message::before{content:"\F1196"}.mdi-phone-message-outline::before{content:"\F1197"}.mdi-phone-minus::before{content:"\F0658"}.mdi-phone-minus-outline::before{content:"\F1198"}.mdi-phone-missed::before{content:"\F03FA"}.mdi-phone-missed-outline::before{content:"\F11A5"}.mdi-phone-off::before{content:"\F0DEF"}.mdi-phone-off-outline::before{content:"\F11A6"}.mdi-phone-outgoing::before{content:"\F03FB"}.mdi-phone-outgoing-outline::before{content:"\F1199"}.mdi-phone-outline::before{content:"\F0DF0"}.mdi-phone-paused::before{content:"\F03FC"}.mdi-phone-paused-outline::before{content:"\F119A"}.mdi-phone-plus::before{content:"\F0659"}.mdi-phone-plus-outline::before{content:"\F119B"}.mdi-phone-remove::before{content:"\F152F"}.mdi-phone-remove-outline::before{content:"\F1530"}.mdi-phone-return::before{content:"\F082F"}.mdi-phone-return-outline::before{content:"\F119C"}.mdi-phone-ring::before{content:"\F11AB"}.mdi-phone-ring-outline::before{content:"\F11AC"}.mdi-phone-rotate-landscape::before{content:"\F0885"}.mdi-phone-rotate-portrait::before{content:"\F0886"}.mdi-phone-settings::before{content:"\F03FD"}.mdi-phone-settings-outline::before{content:"\F119D"}.mdi-phone-voip::before{content:"\F03FE"}.mdi-pi::before{content:"\F03FF"}.mdi-pi-box::before{content:"\F0400"}.mdi-pi-hole::before{content:"\F0DF1"}.mdi-piano::before{content:"\F067D"}.mdi-pickaxe::before{content:"\F08B7"}.mdi-picture-in-picture-bottom-right::before{content:"\F0E57"}.mdi-picture-in-picture-bottom-right-outline::before{content:"\F0E58"}.mdi-picture-in-picture-top-right::before{content:"\F0E59"}.mdi-picture-in-picture-top-right-outline::before{content:"\F0E5A"}.mdi-pier::before{content:"\F0887"}.mdi-pier-crane::before{content:"\F0888"}.mdi-pig::before{content:"\F0401"}.mdi-pig-variant::before{content:"\F1006"}.mdi-pig-variant-outline::before{content:"\F1678"}.mdi-piggy-bank::before{content:"\F1007"}.mdi-piggy-bank-outline::before{content:"\F1679"}.mdi-pill::before{content:"\F0402"}.mdi-pillar::before{content:"\F0702"}.mdi-pin::before{content:"\F0403"}.mdi-pin-off::before{content:"\F0404"}.mdi-pin-off-outline::before{content:"\F0930"}.mdi-pin-outline::before{content:"\F0931"}.mdi-pine-tree::before{content:"\F0405"}.mdi-pine-tree-box::before{content:"\F0406"}.mdi-pine-tree-fire::before{content:"\F141A"}.mdi-pinterest::before{content:"\F0407"}.mdi-pinwheel::before{content:"\F0AD5"}.mdi-pinwheel-outline::before{content:"\F0AD6"}.mdi-pipe::before{content:"\F07E5"}.mdi-pipe-disconnected::before{content:"\F07E6"}.mdi-pipe-leak::before{content:"\F0889"}.mdi-pipe-wrench::before{content:"\F1354"}.mdi-pirate::before{content:"\F0A08"}.mdi-pistol::before{content:"\F0703"}.mdi-piston::before{content:"\F088A"}.mdi-pitchfork::before{content:"\F1553"}.mdi-pizza::before{content:"\F0409"}.mdi-play::before{content:"\F040A"}.mdi-play-box::before{content:"\F127A"}.mdi-play-box-multiple::before{content:"\F0D19"}.mdi-play-box-multiple-outline::before{content:"\F13E6"}.mdi-play-box-outline::before{content:"\F040B"}.mdi-play-circle::before{content:"\F040C"}.mdi-play-circle-outline::before{content:"\F040D"}.mdi-play-network::before{content:"\F088B"}.mdi-play-network-outline::before{content:"\F0CB7"}.mdi-play-outline::before{content:"\F0F1B"}.mdi-play-pause::before{content:"\F040E"}.mdi-play-protected-content::before{content:"\F040F"}.mdi-play-speed::before{content:"\F08FF"}.mdi-playlist-check::before{content:"\F05C7"}.mdi-playlist-edit::before{content:"\F0900"}.mdi-playlist-minus::before{content:"\F0410"}.mdi-playlist-music::before{content:"\F0CB8"}.mdi-playlist-music-outline::before{content:"\F0CB9"}.mdi-playlist-play::before{content:"\F0411"}.mdi-playlist-plus::before{content:"\F0412"}.mdi-playlist-remove::before{content:"\F0413"}.mdi-playlist-star::before{content:"\F0DF2"}.mdi-plex::before{content:"\F06BA"}.mdi-plus::before{content:"\F0415"}.mdi-plus-box::before{content:"\F0416"}.mdi-plus-box-multiple::before{content:"\F0334"}.mdi-plus-box-multiple-outline::before{content:"\F1143"}.mdi-plus-box-outline::before{content:"\F0704"}.mdi-plus-circle::before{content:"\F0417"}.mdi-plus-circle-multiple::before{content:"\F034C"}.mdi-plus-circle-multiple-outline::before{content:"\F0418"}.mdi-plus-circle-outline::before{content:"\F0419"}.mdi-plus-minus::before{content:"\F0992"}.mdi-plus-minus-box::before{content:"\F0993"}.mdi-plus-minus-variant::before{content:"\F14C9"}.mdi-plus-network::before{content:"\F041A"}.mdi-plus-network-outline::before{content:"\F0CBA"}.mdi-plus-one::before{content:"\F041B"}.mdi-plus-outline::before{content:"\F0705"}.mdi-plus-thick::before{content:"\F11EC"}.mdi-podcast::before{content:"\F0994"}.mdi-podium::before{content:"\F0D25"}.mdi-podium-bronze::before{content:"\F0D26"}.mdi-podium-gold::before{content:"\F0D27"}.mdi-podium-silver::before{content:"\F0D28"}.mdi-point-of-sale::before{content:"\F0D92"}.mdi-pokeball::before{content:"\F041D"}.mdi-pokemon-go::before{content:"\F0A09"}.mdi-poker-chip::before{content:"\F0830"}.mdi-polaroid::before{content:"\F041E"}.mdi-police-badge::before{content:"\F1167"}.mdi-police-badge-outline::before{content:"\F1168"}.mdi-poll::before{content:"\F041F"}.mdi-poll-box::before{content:"\F0420"}.mdi-poll-box-outline::before{content:"\F127B"}.mdi-polo::before{content:"\F14C3"}.mdi-polymer::before{content:"\F0421"}.mdi-pool::before{content:"\F0606"}.mdi-popcorn::before{content:"\F0422"}.mdi-post::before{content:"\F1008"}.mdi-post-outline::before{content:"\F1009"}.mdi-postage-stamp::before{content:"\F0CBB"}.mdi-pot::before{content:"\F02E5"}.mdi-pot-mix::before{content:"\F065B"}.mdi-pot-mix-outline::before{content:"\F0677"}.mdi-pot-outline::before{content:"\F02FF"}.mdi-pot-steam::before{content:"\F065A"}.mdi-pot-steam-outline::before{content:"\F0326"}.mdi-pound::before{content:"\F0423"}.mdi-pound-box::before{content:"\F0424"}.mdi-pound-box-outline::before{content:"\F117F"}.mdi-power::before{content:"\F0425"}.mdi-power-cycle::before{content:"\F0901"}.mdi-power-off::before{content:"\F0902"}.mdi-power-on::before{content:"\F0903"}.mdi-power-plug::before{content:"\F06A5"}.mdi-power-plug-off::before{content:"\F06A6"}.mdi-power-plug-off-outline::before{content:"\F1424"}.mdi-power-plug-outline::before{content:"\F1425"}.mdi-power-settings::before{content:"\F0426"}.mdi-power-sleep::before{content:"\F0904"}.mdi-power-socket::before{content:"\F0427"}.mdi-power-socket-au::before{content:"\F0905"}.mdi-power-socket-de::before{content:"\F1107"}.mdi-power-socket-eu::before{content:"\F07E7"}.mdi-power-socket-fr::before{content:"\F1108"}.mdi-power-socket-it::before{content:"\F14FF"}.mdi-power-socket-jp::before{content:"\F1109"}.mdi-power-socket-uk::before{content:"\F07E8"}.mdi-power-socket-us::before{content:"\F07E9"}.mdi-power-standby::before{content:"\F0906"}.mdi-powershell::before{content:"\F0A0A"}.mdi-prescription::before{content:"\F0706"}.mdi-presentation::before{content:"\F0428"}.mdi-presentation-play::before{content:"\F0429"}.mdi-pretzel::before{content:"\F1562"}.mdi-printer::before{content:"\F042A"}.mdi-printer-3d::before{content:"\F042B"}.mdi-printer-3d-nozzle::before{content:"\F0E5B"}.mdi-printer-3d-nozzle-alert::before{content:"\F11C0"}.mdi-printer-3d-nozzle-alert-outline::before{content:"\F11C1"}.mdi-printer-3d-nozzle-outline::before{content:"\F0E5C"}.mdi-printer-alert::before{content:"\F042C"}.mdi-printer-check::before{content:"\F1146"}.mdi-printer-eye::before{content:"\F1458"}.mdi-printer-off::before{content:"\F0E5D"}.mdi-printer-pos::before{content:"\F1057"}.mdi-printer-search::before{content:"\F1457"}.mdi-printer-settings::before{content:"\F0707"}.mdi-printer-wireless::before{content:"\F0A0B"}.mdi-priority-high::before{content:"\F0603"}.mdi-priority-low::before{content:"\F0604"}.mdi-professional-hexagon::before{content:"\F042D"}.mdi-progress-alert::before{content:"\F0CBC"}.mdi-progress-check::before{content:"\F0995"}.mdi-progress-clock::before{content:"\F0996"}.mdi-progress-close::before{content:"\F110A"}.mdi-progress-download::before{content:"\F0997"}.mdi-progress-question::before{content:"\F1522"}.mdi-progress-upload::before{content:"\F0998"}.mdi-progress-wrench::before{content:"\F0CBD"}.mdi-projector::before{content:"\F042E"}.mdi-projector-screen::before{content:"\F042F"}.mdi-propane-tank::before{content:"\F1357"}.mdi-propane-tank-outline::before{content:"\F1358"}.mdi-protocol::before{content:"\F0FD8"}.mdi-publish::before{content:"\F06A7"}.mdi-pulse::before{content:"\F0430"}.mdi-pump::before{content:"\F1402"}.mdi-pumpkin::before{content:"\F0BBF"}.mdi-purse::before{content:"\F0F1C"}.mdi-purse-outline::before{content:"\F0F1D"}.mdi-puzzle::before{content:"\F0431"}.mdi-puzzle-check::before{content:"\F1426"}.mdi-puzzle-check-outline::before{content:"\F1427"}.mdi-puzzle-edit::before{content:"\F14D3"}.mdi-puzzle-edit-outline::before{content:"\F14D9"}.mdi-puzzle-heart::before{content:"\F14D4"}.mdi-puzzle-heart-outline::before{content:"\F14DA"}.mdi-puzzle-minus::before{content:"\F14D1"}.mdi-puzzle-minus-outline::before{content:"\F14D7"}.mdi-puzzle-outline::before{content:"\F0A66"}.mdi-puzzle-plus::before{content:"\F14D0"}.mdi-puzzle-plus-outline::before{content:"\F14D6"}.mdi-puzzle-remove::before{content:"\F14D2"}.mdi-puzzle-remove-outline::before{content:"\F14D8"}.mdi-puzzle-star::before{content:"\F14D5"}.mdi-puzzle-star-outline::before{content:"\F14DB"}.mdi-qi::before{content:"\F0999"}.mdi-qqchat::before{content:"\F0605"}.mdi-qrcode::before{content:"\F0432"}.mdi-qrcode-edit::before{content:"\F08B8"}.mdi-qrcode-minus::before{content:"\F118C"}.mdi-qrcode-plus::before{content:"\F118B"}.mdi-qrcode-remove::before{content:"\F118D"}.mdi-qrcode-scan::before{content:"\F0433"}.mdi-quadcopter::before{content:"\F0434"}.mdi-quality-high::before{content:"\F0435"}.mdi-quality-low::before{content:"\F0A0C"}.mdi-quality-medium::before{content:"\F0A0D"}.mdi-quora::before{content:"\F0D29"}.mdi-rabbit::before{content:"\F0907"}.mdi-racing-helmet::before{content:"\F0D93"}.mdi-racquetball::before{content:"\F0D94"}.mdi-radar::before{content:"\F0437"}.mdi-radiator::before{content:"\F0438"}.mdi-radiator-disabled::before{content:"\F0AD7"}.mdi-radiator-off::before{content:"\F0AD8"}.mdi-radio::before{content:"\F0439"}.mdi-radio-am::before{content:"\F0CBE"}.mdi-radio-fm::before{content:"\F0CBF"}.mdi-radio-handheld::before{content:"\F043A"}.mdi-radio-off::before{content:"\F121C"}.mdi-radio-tower::before{content:"\F043B"}.mdi-radioactive::before{content:"\F043C"}.mdi-radioactive-off::before{content:"\F0EC1"}.mdi-radiobox-blank::before{content:"\F043D"}.mdi-radiobox-marked::before{content:"\F043E"}.mdi-radiology-box::before{content:"\F14C5"}.mdi-radiology-box-outline::before{content:"\F14C6"}.mdi-radius::before{content:"\F0CC0"}.mdi-radius-outline::before{content:"\F0CC1"}.mdi-railroad-light::before{content:"\F0F1E"}.mdi-rake::before{content:"\F1544"}.mdi-raspberry-pi::before{content:"\F043F"}.mdi-ray-end::before{content:"\F0440"}.mdi-ray-end-arrow::before{content:"\F0441"}.mdi-ray-start::before{content:"\F0442"}.mdi-ray-start-arrow::before{content:"\F0443"}.mdi-ray-start-end::before{content:"\F0444"}.mdi-ray-start-vertex-end::before{content:"\F15D8"}.mdi-ray-vertex::before{content:"\F0445"}.mdi-react::before{content:"\F0708"}.mdi-read::before{content:"\F0447"}.mdi-receipt::before{content:"\F0449"}.mdi-record::before{content:"\F044A"}.mdi-record-circle::before{content:"\F0EC2"}.mdi-record-circle-outline::before{content:"\F0EC3"}.mdi-record-player::before{content:"\F099A"}.mdi-record-rec::before{content:"\F044B"}.mdi-rectangle::before{content:"\F0E5E"}.mdi-rectangle-outline::before{content:"\F0E5F"}.mdi-recycle::before{content:"\F044C"}.mdi-recycle-variant::before{content:"\F139D"}.mdi-reddit::before{content:"\F044D"}.mdi-redhat::before{content:"\F111B"}.mdi-redo::before{content:"\F044E"}.mdi-redo-variant::before{content:"\F044F"}.mdi-reflect-horizontal::before{content:"\F0A0E"}.mdi-reflect-vertical::before{content:"\F0A0F"}.mdi-refresh::before{content:"\F0450"}.mdi-refresh-circle::before{content:"\F1377"}.mdi-regex::before{content:"\F0451"}.mdi-registered-trademark::before{content:"\F0A67"}.mdi-reiterate::before{content:"\F1588"}.mdi-relation-many-to-many::before{content:"\F1496"}.mdi-relation-many-to-one::before{content:"\F1497"}.mdi-relation-many-to-one-or-many::before{content:"\F1498"}.mdi-relation-many-to-only-one::before{content:"\F1499"}.mdi-relation-many-to-zero-or-many::before{content:"\F149A"}.mdi-relation-many-to-zero-or-one::before{content:"\F149B"}.mdi-relation-one-or-many-to-many::before{content:"\F149C"}.mdi-relation-one-or-many-to-one::before{content:"\F149D"}.mdi-relation-one-or-many-to-one-or-many::before{content:"\F149E"}.mdi-relation-one-or-many-to-only-one::before{content:"\F149F"}.mdi-relation-one-or-many-to-zero-or-many::before{content:"\F14A0"}.mdi-relation-one-or-many-to-zero-or-one::before{content:"\F14A1"}.mdi-relation-one-to-many::before{content:"\F14A2"}.mdi-relation-one-to-one::before{content:"\F14A3"}.mdi-relation-one-to-one-or-many::before{content:"\F14A4"}.mdi-relation-one-to-only-one::before{content:"\F14A5"}.mdi-relation-one-to-zero-or-many::before{content:"\F14A6"}.mdi-relation-one-to-zero-or-one::before{content:"\F14A7"}.mdi-relation-only-one-to-many::before{content:"\F14A8"}.mdi-relation-only-one-to-one::before{content:"\F14A9"}.mdi-relation-only-one-to-one-or-many::before{content:"\F14AA"}.mdi-relation-only-one-to-only-one::before{content:"\F14AB"}.mdi-relation-only-one-to-zero-or-many::before{content:"\F14AC"}.mdi-relation-only-one-to-zero-or-one::before{content:"\F14AD"}.mdi-relation-zero-or-many-to-many::before{content:"\F14AE"}.mdi-relation-zero-or-many-to-one::before{content:"\F14AF"}.mdi-relation-zero-or-many-to-one-or-many::before{content:"\F14B0"}.mdi-relation-zero-or-many-to-only-one::before{content:"\F14B1"}.mdi-relation-zero-or-many-to-zero-or-many::before{content:"\F14B2"}.mdi-relation-zero-or-many-to-zero-or-one::before{content:"\F14B3"}.mdi-relation-zero-or-one-to-many::before{content:"\F14B4"}.mdi-relation-zero-or-one-to-one::before{content:"\F14B5"}.mdi-relation-zero-or-one-to-one-or-many::before{content:"\F14B6"}.mdi-relation-zero-or-one-to-only-one::before{content:"\F14B7"}.mdi-relation-zero-or-one-to-zero-or-many::before{content:"\F14B8"}.mdi-relation-zero-or-one-to-zero-or-one::before{content:"\F14B9"}.mdi-relative-scale::before{content:"\F0452"}.mdi-reload::before{content:"\F0453"}.mdi-reload-alert::before{content:"\F110B"}.mdi-reminder::before{content:"\F088C"}.mdi-remote::before{content:"\F0454"}.mdi-remote-desktop::before{content:"\F08B9"}.mdi-remote-off::before{content:"\F0EC4"}.mdi-remote-tv::before{content:"\F0EC5"}.mdi-remote-tv-off::before{content:"\F0EC6"}.mdi-rename-box::before{content:"\F0455"}.mdi-reorder-horizontal::before{content:"\F0688"}.mdi-reorder-vertical::before{content:"\F0689"}.mdi-repeat::before{content:"\F0456"}.mdi-repeat-off::before{content:"\F0457"}.mdi-repeat-once::before{content:"\F0458"}.mdi-replay::before{content:"\F0459"}.mdi-reply::before{content:"\F045A"}.mdi-reply-all::before{content:"\F045B"}.mdi-reply-all-outline::before{content:"\F0F1F"}.mdi-reply-circle::before{content:"\F11AE"}.mdi-reply-outline::before{content:"\F0F20"}.mdi-reproduction::before{content:"\F045C"}.mdi-resistor::before{content:"\F0B44"}.mdi-resistor-nodes::before{content:"\F0B45"}.mdi-resize::before{content:"\F0A68"}.mdi-resize-bottom-right::before{content:"\F045D"}.mdi-responsive::before{content:"\F045E"}.mdi-restart::before{content:"\F0709"}.mdi-restart-alert::before{content:"\F110C"}.mdi-restart-off::before{content:"\F0D95"}.mdi-restore::before{content:"\F099B"}.mdi-restore-alert::before{content:"\F110D"}.mdi-rewind::before{content:"\F045F"}.mdi-rewind-10::before{content:"\F0D2A"}.mdi-rewind-30::before{content:"\F0D96"}.mdi-rewind-5::before{content:"\F11F9"}.mdi-rewind-60::before{content:"\F160C"}.mdi-rewind-outline::before{content:"\F070A"}.mdi-rhombus::before{content:"\F070B"}.mdi-rhombus-medium::before{content:"\F0A10"}.mdi-rhombus-medium-outline::before{content:"\F14DC"}.mdi-rhombus-outline::before{content:"\F070C"}.mdi-rhombus-split::before{content:"\F0A11"}.mdi-rhombus-split-outline::before{content:"\F14DD"}.mdi-ribbon::before{content:"\F0460"}.mdi-rice::before{content:"\F07EA"}.mdi-rickshaw::before{content:"\F15BB"}.mdi-rickshaw-electric::before{content:"\F15BC"}.mdi-ring::before{content:"\F07EB"}.mdi-rivet::before{content:"\F0E60"}.mdi-road::before{content:"\F0461"}.mdi-road-variant::before{content:"\F0462"}.mdi-robber::before{content:"\F1058"}.mdi-robot::before{content:"\F06A9"}.mdi-robot-angry::before{content:"\F169D"}.mdi-robot-angry-outline::before{content:"\F169E"}.mdi-robot-confused::before{content:"\F169F"}.mdi-robot-confused-outline::before{content:"\F16A0"}.mdi-robot-dead::before{content:"\F16A1"}.mdi-robot-dead-outline::before{content:"\F16A2"}.mdi-robot-excited::before{content:"\F16A3"}.mdi-robot-excited-outline::before{content:"\F16A4"}.mdi-robot-industrial::before{content:"\F0B46"}.mdi-robot-love::before{content:"\F16A5"}.mdi-robot-love-outline::before{content:"\F16A6"}.mdi-robot-mower::before{content:"\F11F7"}.mdi-robot-mower-outline::before{content:"\F11F3"}.mdi-robot-off::before{content:"\F16A7"}.mdi-robot-off-outline::before{content:"\F167B"}.mdi-robot-outline::before{content:"\F167A"}.mdi-robot-vacuum::before{content:"\F070D"}.mdi-robot-vacuum-variant::before{content:"\F0908"}.mdi-rocket::before{content:"\F0463"}.mdi-rocket-launch::before{content:"\F14DE"}.mdi-rocket-launch-outline::before{content:"\F14DF"}.mdi-rocket-outline::before{content:"\F13AF"}.mdi-rodent::before{content:"\F1327"}.mdi-roller-skate::before{content:"\F0D2B"}.mdi-roller-skate-off::before{content:"\F0145"}.mdi-rollerblade::before{content:"\F0D2C"}.mdi-rollerblade-off::before{content:"\F002E"}.mdi-rollupjs::before{content:"\F0BC0"}.mdi-roman-numeral-1::before{content:"\F1088"}.mdi-roman-numeral-10::before{content:"\F1091"}.mdi-roman-numeral-2::before{content:"\F1089"}.mdi-roman-numeral-3::before{content:"\F108A"}.mdi-roman-numeral-4::before{content:"\F108B"}.mdi-roman-numeral-5::before{content:"\F108C"}.mdi-roman-numeral-6::before{content:"\F108D"}.mdi-roman-numeral-7::before{content:"\F108E"}.mdi-roman-numeral-8::before{content:"\F108F"}.mdi-roman-numeral-9::before{content:"\F1090"}.mdi-room-service::before{content:"\F088D"}.mdi-room-service-outline::before{content:"\F0D97"}.mdi-rotate-3d::before{content:"\F0EC7"}.mdi-rotate-3d-variant::before{content:"\F0464"}.mdi-rotate-left::before{content:"\F0465"}.mdi-rotate-left-variant::before{content:"\F0466"}.mdi-rotate-orbit::before{content:"\F0D98"}.mdi-rotate-right::before{content:"\F0467"}.mdi-rotate-right-variant::before{content:"\F0468"}.mdi-rounded-corner::before{content:"\F0607"}.mdi-router::before{content:"\F11E2"}.mdi-router-network::before{content:"\F1087"}.mdi-router-wireless::before{content:"\F0469"}.mdi-router-wireless-off::before{content:"\F15A3"}.mdi-router-wireless-settings::before{content:"\F0A69"}.mdi-routes::before{content:"\F046A"}.mdi-routes-clock::before{content:"\F1059"}.mdi-rowing::before{content:"\F0608"}.mdi-rss::before{content:"\F046B"}.mdi-rss-box::before{content:"\F046C"}.mdi-rss-off::before{content:"\F0F21"}.mdi-rug::before{content:"\F1475"}.mdi-rugby::before{content:"\F0D99"}.mdi-ruler::before{content:"\F046D"}.mdi-ruler-square::before{content:"\F0CC2"}.mdi-ruler-square-compass::before{content:"\F0EBE"}.mdi-run::before{content:"\F070E"}.mdi-run-fast::before{content:"\F046E"}.mdi-rv-truck::before{content:"\F11D4"}.mdi-sack::before{content:"\F0D2E"}.mdi-sack-percent::before{content:"\F0D2F"}.mdi-safe::before{content:"\F0A6A"}.mdi-safe-square::before{content:"\F127C"}.mdi-safe-square-outline::before{content:"\F127D"}.mdi-safety-goggles::before{content:"\F0D30"}.mdi-sail-boat::before{content:"\F0EC8"}.mdi-sale::before{content:"\F046F"}.mdi-salesforce::before{content:"\F088E"}.mdi-sass::before{content:"\F07EC"}.mdi-satellite::before{content:"\F0470"}.mdi-satellite-uplink::before{content:"\F0909"}.mdi-satellite-variant::before{content:"\F0471"}.mdi-sausage::before{content:"\F08BA"}.mdi-saw-blade::before{content:"\F0E61"}.mdi-sawtooth-wave::before{content:"\F147A"}.mdi-saxophone::before{content:"\F0609"}.mdi-scale::before{content:"\F0472"}.mdi-scale-balance::before{content:"\F05D1"}.mdi-scale-bathroom::before{content:"\F0473"}.mdi-scale-off::before{content:"\F105A"}.mdi-scan-helper::before{content:"\F13D8"}.mdi-scanner::before{content:"\F06AB"}.mdi-scanner-off::before{content:"\F090A"}.mdi-scatter-plot::before{content:"\F0EC9"}.mdi-scatter-plot-outline::before{content:"\F0ECA"}.mdi-school::before{content:"\F0474"}.mdi-school-outline::before{content:"\F1180"}.mdi-scissors-cutting::before{content:"\F0A6B"}.mdi-scooter::before{content:"\F15BD"}.mdi-scooter-electric::before{content:"\F15BE"}.mdi-scoreboard::before{content:"\F127E"}.mdi-scoreboard-outline::before{content:"\F127F"}.mdi-screen-rotation::before{content:"\F0475"}.mdi-screen-rotation-lock::before{content:"\F0478"}.mdi-screw-flat-top::before{content:"\F0DF3"}.mdi-screw-lag::before{content:"\F0DF4"}.mdi-screw-machine-flat-top::before{content:"\F0DF5"}.mdi-screw-machine-round-top::before{content:"\F0DF6"}.mdi-screw-round-top::before{content:"\F0DF7"}.mdi-screwdriver::before{content:"\F0476"}.mdi-script::before{content:"\F0BC1"}.mdi-script-outline::before{content:"\F0477"}.mdi-script-text::before{content:"\F0BC2"}.mdi-script-text-outline::before{content:"\F0BC3"}.mdi-sd::before{content:"\F0479"}.mdi-seal::before{content:"\F047A"}.mdi-seal-variant::before{content:"\F0FD9"}.mdi-search-web::before{content:"\F070F"}.mdi-seat::before{content:"\F0CC3"}.mdi-seat-flat::before{content:"\F047B"}.mdi-seat-flat-angled::before{content:"\F047C"}.mdi-seat-individual-suite::before{content:"\F047D"}.mdi-seat-legroom-extra::before{content:"\F047E"}.mdi-seat-legroom-normal::before{content:"\F047F"}.mdi-seat-legroom-reduced::before{content:"\F0480"}.mdi-seat-outline::before{content:"\F0CC4"}.mdi-seat-passenger::before{content:"\F1249"}.mdi-seat-recline-extra::before{content:"\F0481"}.mdi-seat-recline-normal::before{content:"\F0482"}.mdi-seatbelt::before{content:"\F0CC5"}.mdi-security::before{content:"\F0483"}.mdi-security-network::before{content:"\F0484"}.mdi-seed::before{content:"\F0E62"}.mdi-seed-off::before{content:"\F13FD"}.mdi-seed-off-outline::before{content:"\F13FE"}.mdi-seed-outline::before{content:"\F0E63"}.mdi-seesaw::before{content:"\F15A4"}.mdi-segment::before{content:"\F0ECB"}.mdi-select::before{content:"\F0485"}.mdi-select-all::before{content:"\F0486"}.mdi-select-color::before{content:"\F0D31"}.mdi-select-compare::before{content:"\F0AD9"}.mdi-select-drag::before{content:"\F0A6C"}.mdi-select-group::before{content:"\F0F82"}.mdi-select-inverse::before{content:"\F0487"}.mdi-select-marker::before{content:"\F1280"}.mdi-select-multiple::before{content:"\F1281"}.mdi-select-multiple-marker::before{content:"\F1282"}.mdi-select-off::before{content:"\F0488"}.mdi-select-place::before{content:"\F0FDA"}.mdi-select-search::before{content:"\F1204"}.mdi-selection::before{content:"\F0489"}.mdi-selection-drag::before{content:"\F0A6D"}.mdi-selection-ellipse::before{content:"\F0D32"}.mdi-selection-ellipse-arrow-inside::before{content:"\F0F22"}.mdi-selection-marker::before{content:"\F1283"}.mdi-selection-multiple::before{content:"\F1285"}.mdi-selection-multiple-marker::before{content:"\F1284"}.mdi-selection-off::before{content:"\F0777"}.mdi-selection-search::before{content:"\F1205"}.mdi-semantic-web::before{content:"\F1316"}.mdi-send::before{content:"\F048A"}.mdi-send-check::before{content:"\F1161"}.mdi-send-check-outline::before{content:"\F1162"}.mdi-send-circle::before{content:"\F0DF8"}.mdi-send-circle-outline::before{content:"\F0DF9"}.mdi-send-clock::before{content:"\F1163"}.mdi-send-clock-outline::before{content:"\F1164"}.mdi-send-lock::before{content:"\F07ED"}.mdi-send-lock-outline::before{content:"\F1166"}.mdi-send-outline::before{content:"\F1165"}.mdi-serial-port::before{content:"\F065C"}.mdi-server::before{content:"\F048B"}.mdi-server-minus::before{content:"\F048C"}.mdi-server-network::before{content:"\F048D"}.mdi-server-network-off::before{content:"\F048E"}.mdi-server-off::before{content:"\F048F"}.mdi-server-plus::before{content:"\F0490"}.mdi-server-remove::before{content:"\F0491"}.mdi-server-security::before{content:"\F0492"}.mdi-set-all::before{content:"\F0778"}.mdi-set-center::before{content:"\F0779"}.mdi-set-center-right::before{content:"\F077A"}.mdi-set-left::before{content:"\F077B"}.mdi-set-left-center::before{content:"\F077C"}.mdi-set-left-right::before{content:"\F077D"}.mdi-set-merge::before{content:"\F14E0"}.mdi-set-none::before{content:"\F077E"}.mdi-set-right::before{content:"\F077F"}.mdi-set-split::before{content:"\F14E1"}.mdi-set-square::before{content:"\F145D"}.mdi-set-top-box::before{content:"\F099F"}.mdi-settings-helper::before{content:"\F0A6E"}.mdi-shaker::before{content:"\F110E"}.mdi-shaker-outline::before{content:"\F110F"}.mdi-shape::before{content:"\F0831"}.mdi-shape-circle-plus::before{content:"\F065D"}.mdi-shape-outline::before{content:"\F0832"}.mdi-shape-oval-plus::before{content:"\F11FA"}.mdi-shape-plus::before{content:"\F0495"}.mdi-shape-polygon-plus::before{content:"\F065E"}.mdi-shape-rectangle-plus::before{content:"\F065F"}.mdi-shape-square-plus::before{content:"\F0660"}.mdi-shape-square-rounded-plus::before{content:"\F14FA"}.mdi-share::before{content:"\F0496"}.mdi-share-all::before{content:"\F11F4"}.mdi-share-all-outline::before{content:"\F11F5"}.mdi-share-circle::before{content:"\F11AD"}.mdi-share-off::before{content:"\F0F23"}.mdi-share-off-outline::before{content:"\F0F24"}.mdi-share-outline::before{content:"\F0932"}.mdi-share-variant::before{content:"\F0497"}.mdi-share-variant-outline::before{content:"\F1514"}.mdi-shark-fin::before{content:"\F1673"}.mdi-shark-fin-outline::before{content:"\F1674"}.mdi-sheep::before{content:"\F0CC6"}.mdi-shield::before{content:"\F0498"}.mdi-shield-account::before{content:"\F088F"}.mdi-shield-account-outline::before{content:"\F0A12"}.mdi-shield-account-variant::before{content:"\F15A7"}.mdi-shield-account-variant-outline::before{content:"\F15A8"}.mdi-shield-airplane::before{content:"\F06BB"}.mdi-shield-airplane-outline::before{content:"\F0CC7"}.mdi-shield-alert::before{content:"\F0ECC"}.mdi-shield-alert-outline::before{content:"\F0ECD"}.mdi-shield-bug::before{content:"\F13DA"}.mdi-shield-bug-outline::before{content:"\F13DB"}.mdi-shield-car::before{content:"\F0F83"}.mdi-shield-check::before{content:"\F0565"}.mdi-shield-check-outline::before{content:"\F0CC8"}.mdi-shield-cross::before{content:"\F0CC9"}.mdi-shield-cross-outline::before{content:"\F0CCA"}.mdi-shield-edit::before{content:"\F11A0"}.mdi-shield-edit-outline::before{content:"\F11A1"}.mdi-shield-half::before{content:"\F1360"}.mdi-shield-half-full::before{content:"\F0780"}.mdi-shield-home::before{content:"\F068A"}.mdi-shield-home-outline::before{content:"\F0CCB"}.mdi-shield-key::before{content:"\F0BC4"}.mdi-shield-key-outline::before{content:"\F0BC5"}.mdi-shield-link-variant::before{content:"\F0D33"}.mdi-shield-link-variant-outline::before{content:"\F0D34"}.mdi-shield-lock::before{content:"\F099D"}.mdi-shield-lock-outline::before{content:"\F0CCC"}.mdi-shield-off::before{content:"\F099E"}.mdi-shield-off-outline::before{content:"\F099C"}.mdi-shield-outline::before{content:"\F0499"}.mdi-shield-plus::before{content:"\F0ADA"}.mdi-shield-plus-outline::before{content:"\F0ADB"}.mdi-shield-refresh::before{content:"\F00AA"}.mdi-shield-refresh-outline::before{content:"\F01E0"}.mdi-shield-remove::before{content:"\F0ADC"}.mdi-shield-remove-outline::before{content:"\F0ADD"}.mdi-shield-search::before{content:"\F0D9A"}.mdi-shield-star::before{content:"\F113B"}.mdi-shield-star-outline::before{content:"\F113C"}.mdi-shield-sun::before{content:"\F105D"}.mdi-shield-sun-outline::before{content:"\F105E"}.mdi-shield-sync::before{content:"\F11A2"}.mdi-shield-sync-outline::before{content:"\F11A3"}.mdi-ship-wheel::before{content:"\F0833"}.mdi-shoe-ballet::before{content:"\F15CA"}.mdi-shoe-cleat::before{content:"\F15C7"}.mdi-shoe-formal::before{content:"\F0B47"}.mdi-shoe-heel::before{content:"\F0B48"}.mdi-shoe-print::before{content:"\F0DFA"}.mdi-shoe-sneaker::before{content:"\F15C8"}.mdi-shopping::before{content:"\F049A"}.mdi-shopping-music::before{content:"\F049B"}.mdi-shopping-outline::before{content:"\F11D5"}.mdi-shopping-search::before{content:"\F0F84"}.mdi-shore::before{content:"\F14F9"}.mdi-shovel::before{content:"\F0710"}.mdi-shovel-off::before{content:"\F0711"}.mdi-shower::before{content:"\F09A0"}.mdi-shower-head::before{content:"\F09A1"}.mdi-shredder::before{content:"\F049C"}.mdi-shuffle::before{content:"\F049D"}.mdi-shuffle-disabled::before{content:"\F049E"}.mdi-shuffle-variant::before{content:"\F049F"}.mdi-shuriken::before{content:"\F137F"}.mdi-sigma::before{content:"\F04A0"}.mdi-sigma-lower::before{content:"\F062B"}.mdi-sign-caution::before{content:"\F04A1"}.mdi-sign-direction::before{content:"\F0781"}.mdi-sign-direction-minus::before{content:"\F1000"}.mdi-sign-direction-plus::before{content:"\F0FDC"}.mdi-sign-direction-remove::before{content:"\F0FDD"}.mdi-sign-pole::before{content:"\F14F8"}.mdi-sign-real-estate::before{content:"\F1118"}.mdi-sign-text::before{content:"\F0782"}.mdi-signal::before{content:"\F04A2"}.mdi-signal-2g::before{content:"\F0712"}.mdi-signal-3g::before{content:"\F0713"}.mdi-signal-4g::before{content:"\F0714"}.mdi-signal-5g::before{content:"\F0A6F"}.mdi-signal-cellular-1::before{content:"\F08BC"}.mdi-signal-cellular-2::before{content:"\F08BD"}.mdi-signal-cellular-3::before{content:"\F08BE"}.mdi-signal-cellular-outline::before{content:"\F08BF"}.mdi-signal-distance-variant::before{content:"\F0E64"}.mdi-signal-hspa::before{content:"\F0715"}.mdi-signal-hspa-plus::before{content:"\F0716"}.mdi-signal-off::before{content:"\F0783"}.mdi-signal-variant::before{content:"\F060A"}.mdi-signature::before{content:"\F0DFB"}.mdi-signature-freehand::before{content:"\F0DFC"}.mdi-signature-image::before{content:"\F0DFD"}.mdi-signature-text::before{content:"\F0DFE"}.mdi-silo::before{content:"\F0B49"}.mdi-silverware::before{content:"\F04A3"}.mdi-silverware-clean::before{content:"\F0FDE"}.mdi-silverware-fork::before{content:"\F04A4"}.mdi-silverware-fork-knife::before{content:"\F0A70"}.mdi-silverware-spoon::before{content:"\F04A5"}.mdi-silverware-variant::before{content:"\F04A6"}.mdi-sim::before{content:"\F04A7"}.mdi-sim-alert::before{content:"\F04A8"}.mdi-sim-alert-outline::before{content:"\F15D3"}.mdi-sim-off::before{content:"\F04A9"}.mdi-sim-off-outline::before{content:"\F15D4"}.mdi-sim-outline::before{content:"\F15D5"}.mdi-simple-icons::before{content:"\F131D"}.mdi-sina-weibo::before{content:"\F0ADF"}.mdi-sine-wave::before{content:"\F095B"}.mdi-sitemap::before{content:"\F04AA"}.mdi-size-l::before{content:"\F13A6"}.mdi-size-m::before{content:"\F13A5"}.mdi-size-s::before{content:"\F13A4"}.mdi-size-xl::before{content:"\F13A7"}.mdi-size-xs::before{content:"\F13A3"}.mdi-size-xxl::before{content:"\F13A8"}.mdi-size-xxs::before{content:"\F13A2"}.mdi-size-xxxl::before{content:"\F13A9"}.mdi-skate::before{content:"\F0D35"}.mdi-skateboard::before{content:"\F14C2"}.mdi-skew-less::before{content:"\F0D36"}.mdi-skew-more::before{content:"\F0D37"}.mdi-ski::before{content:"\F1304"}.mdi-ski-cross-country::before{content:"\F1305"}.mdi-ski-water::before{content:"\F1306"}.mdi-skip-backward::before{content:"\F04AB"}.mdi-skip-backward-outline::before{content:"\F0F25"}.mdi-skip-forward::before{content:"\F04AC"}.mdi-skip-forward-outline::before{content:"\F0F26"}.mdi-skip-next::before{content:"\F04AD"}.mdi-skip-next-circle::before{content:"\F0661"}.mdi-skip-next-circle-outline::before{content:"\F0662"}.mdi-skip-next-outline::before{content:"\F0F27"}.mdi-skip-previous::before{content:"\F04AE"}.mdi-skip-previous-circle::before{content:"\F0663"}.mdi-skip-previous-circle-outline::before{content:"\F0664"}.mdi-skip-previous-outline::before{content:"\F0F28"}.mdi-skull::before{content:"\F068C"}.mdi-skull-crossbones::before{content:"\F0BC6"}.mdi-skull-crossbones-outline::before{content:"\F0BC7"}.mdi-skull-outline::before{content:"\F0BC8"}.mdi-skull-scan::before{content:"\F14C7"}.mdi-skull-scan-outline::before{content:"\F14C8"}.mdi-skype::before{content:"\F04AF"}.mdi-skype-business::before{content:"\F04B0"}.mdi-slack::before{content:"\F04B1"}.mdi-slash-forward::before{content:"\F0FDF"}.mdi-slash-forward-box::before{content:"\F0FE0"}.mdi-sleep::before{content:"\F04B2"}.mdi-sleep-off::before{content:"\F04B3"}.mdi-slide::before{content:"\F15A5"}.mdi-slope-downhill::before{content:"\F0DFF"}.mdi-slope-uphill::before{content:"\F0E00"}.mdi-slot-machine::before{content:"\F1114"}.mdi-slot-machine-outline::before{content:"\F1115"}.mdi-smart-card::before{content:"\F10BD"}.mdi-smart-card-outline::before{content:"\F10BE"}.mdi-smart-card-reader::before{content:"\F10BF"}.mdi-smart-card-reader-outline::before{content:"\F10C0"}.mdi-smog::before{content:"\F0A71"}.mdi-smoke-detector::before{content:"\F0392"}.mdi-smoking::before{content:"\F04B4"}.mdi-smoking-off::before{content:"\F04B5"}.mdi-smoking-pipe::before{content:"\F140D"}.mdi-smoking-pipe-off::before{content:"\F1428"}.mdi-snail::before{content:"\F1677"}.mdi-snake::before{content:"\F150E"}.mdi-snapchat::before{content:"\F04B6"}.mdi-snowboard::before{content:"\F1307"}.mdi-snowflake::before{content:"\F0717"}.mdi-snowflake-alert::before{content:"\F0F29"}.mdi-snowflake-melt::before{content:"\F12CB"}.mdi-snowflake-off::before{content:"\F14E3"}.mdi-snowflake-variant::before{content:"\F0F2A"}.mdi-snowman::before{content:"\F04B7"}.mdi-soccer::before{content:"\F04B8"}.mdi-soccer-field::before{content:"\F0834"}.mdi-social-distance-2-meters::before{content:"\F1579"}.mdi-social-distance-6-feet::before{content:"\F157A"}.mdi-sofa::before{content:"\F04B9"}.mdi-sofa-outline::before{content:"\F156D"}.mdi-sofa-single::before{content:"\F156E"}.mdi-sofa-single-outline::before{content:"\F156F"}.mdi-solar-panel::before{content:"\F0D9B"}.mdi-solar-panel-large::before{content:"\F0D9C"}.mdi-solar-power::before{content:"\F0A72"}.mdi-soldering-iron::before{content:"\F1092"}.mdi-solid::before{content:"\F068D"}.mdi-sony-playstation::before{content:"\F0414"}.mdi-sort::before{content:"\F04BA"}.mdi-sort-alphabetical-ascending::before{content:"\F05BD"}.mdi-sort-alphabetical-ascending-variant::before{content:"\F1148"}.mdi-sort-alphabetical-descending::before{content:"\F05BF"}.mdi-sort-alphabetical-descending-variant::before{content:"\F1149"}.mdi-sort-alphabetical-variant::before{content:"\F04BB"}.mdi-sort-ascending::before{content:"\F04BC"}.mdi-sort-bool-ascending::before{content:"\F1385"}.mdi-sort-bool-ascending-variant::before{content:"\F1386"}.mdi-sort-bool-descending::before{content:"\F1387"}.mdi-sort-bool-descending-variant::before{content:"\F1388"}.mdi-sort-calendar-ascending::before{content:"\F1547"}.mdi-sort-calendar-descending::before{content:"\F1548"}.mdi-sort-clock-ascending::before{content:"\F1549"}.mdi-sort-clock-ascending-outline::before{content:"\F154A"}.mdi-sort-clock-descending::before{content:"\F154B"}.mdi-sort-clock-descending-outline::before{content:"\F154C"}.mdi-sort-descending::before{content:"\F04BD"}.mdi-sort-numeric-ascending::before{content:"\F1389"}.mdi-sort-numeric-ascending-variant::before{content:"\F090D"}.mdi-sort-numeric-descending::before{content:"\F138A"}.mdi-sort-numeric-descending-variant::before{content:"\F0AD2"}.mdi-sort-numeric-variant::before{content:"\F04BE"}.mdi-sort-reverse-variant::before{content:"\F033C"}.mdi-sort-variant::before{content:"\F04BF"}.mdi-sort-variant-lock::before{content:"\F0CCD"}.mdi-sort-variant-lock-open::before{content:"\F0CCE"}.mdi-sort-variant-remove::before{content:"\F1147"}.mdi-soundcloud::before{content:"\F04C0"}.mdi-source-branch::before{content:"\F062C"}.mdi-source-branch-check::before{content:"\F14CF"}.mdi-source-branch-minus::before{content:"\F14CB"}.mdi-source-branch-plus::before{content:"\F14CA"}.mdi-source-branch-refresh::before{content:"\F14CD"}.mdi-source-branch-remove::before{content:"\F14CC"}.mdi-source-branch-sync::before{content:"\F14CE"}.mdi-source-commit::before{content:"\F0718"}.mdi-source-commit-end::before{content:"\F0719"}.mdi-source-commit-end-local::before{content:"\F071A"}.mdi-source-commit-local::before{content:"\F071B"}.mdi-source-commit-next-local::before{content:"\F071C"}.mdi-source-commit-start::before{content:"\F071D"}.mdi-source-commit-start-next-local::before{content:"\F071E"}.mdi-source-fork::before{content:"\F04C1"}.mdi-source-merge::before{content:"\F062D"}.mdi-source-pull::before{content:"\F04C2"}.mdi-source-repository::before{content:"\F0CCF"}.mdi-source-repository-multiple::before{content:"\F0CD0"}.mdi-soy-sauce::before{content:"\F07EE"}.mdi-soy-sauce-off::before{content:"\F13FC"}.mdi-spa::before{content:"\F0CD1"}.mdi-spa-outline::before{content:"\F0CD2"}.mdi-space-invaders::before{content:"\F0BC9"}.mdi-space-station::before{content:"\F1383"}.mdi-spade::before{content:"\F0E65"}.mdi-sparkles::before{content:"\F1545"}.mdi-speaker::before{content:"\F04C3"}.mdi-speaker-bluetooth::before{content:"\F09A2"}.mdi-speaker-multiple::before{content:"\F0D38"}.mdi-speaker-off::before{content:"\F04C4"}.mdi-speaker-wireless::before{content:"\F071F"}.mdi-speedometer::before{content:"\F04C5"}.mdi-speedometer-medium::before{content:"\F0F85"}.mdi-speedometer-slow::before{content:"\F0F86"}.mdi-spellcheck::before{content:"\F04C6"}.mdi-spider::before{content:"\F11EA"}.mdi-spider-thread::before{content:"\F11EB"}.mdi-spider-web::before{content:"\F0BCA"}.mdi-spirit-level::before{content:"\F14F1"}.mdi-spoon-sugar::before{content:"\F1429"}.mdi-spotify::before{content:"\F04C7"}.mdi-spotlight::before{content:"\F04C8"}.mdi-spotlight-beam::before{content:"\F04C9"}.mdi-spray::before{content:"\F0665"}.mdi-spray-bottle::before{content:"\F0AE0"}.mdi-sprinkler::before{content:"\F105F"}.mdi-sprinkler-variant::before{content:"\F1060"}.mdi-sprout::before{content:"\F0E66"}.mdi-sprout-outline::before{content:"\F0E67"}.mdi-square::before{content:"\F0764"}.mdi-square-circle::before{content:"\F1500"}.mdi-square-edit-outline::before{content:"\F090C"}.mdi-square-medium::before{content:"\F0A13"}.mdi-square-medium-outline::before{content:"\F0A14"}.mdi-square-off::before{content:"\F12EE"}.mdi-square-off-outline::before{content:"\F12EF"}.mdi-square-outline::before{content:"\F0763"}.mdi-square-root::before{content:"\F0784"}.mdi-square-root-box::before{content:"\F09A3"}.mdi-square-rounded::before{content:"\F14FB"}.mdi-square-rounded-outline::before{content:"\F14FC"}.mdi-square-small::before{content:"\F0A15"}.mdi-square-wave::before{content:"\F147B"}.mdi-squeegee::before{content:"\F0AE1"}.mdi-ssh::before{content:"\F08C0"}.mdi-stack-exchange::before{content:"\F060B"}.mdi-stack-overflow::before{content:"\F04CC"}.mdi-stackpath::before{content:"\F0359"}.mdi-stadium::before{content:"\F0FF9"}.mdi-stadium-variant::before{content:"\F0720"}.mdi-stairs::before{content:"\F04CD"}.mdi-stairs-box::before{content:"\F139E"}.mdi-stairs-down::before{content:"\F12BE"}.mdi-stairs-up::before{content:"\F12BD"}.mdi-stamper::before{content:"\F0D39"}.mdi-standard-definition::before{content:"\F07EF"}.mdi-star::before{content:"\F04CE"}.mdi-star-box::before{content:"\F0A73"}.mdi-star-box-multiple::before{content:"\F1286"}.mdi-star-box-multiple-outline::before{content:"\F1287"}.mdi-star-box-outline::before{content:"\F0A74"}.mdi-star-check::before{content:"\F1566"}.mdi-star-check-outline::before{content:"\F156A"}.mdi-star-circle::before{content:"\F04CF"}.mdi-star-circle-outline::before{content:"\F09A4"}.mdi-star-cog::before{content:"\F1668"}.mdi-star-cog-outline::before{content:"\F1669"}.mdi-star-face::before{content:"\F09A5"}.mdi-star-four-points::before{content:"\F0AE2"}.mdi-star-four-points-outline::before{content:"\F0AE3"}.mdi-star-half::before{content:"\F0246"}.mdi-star-half-full::before{content:"\F04D0"}.mdi-star-minus::before{content:"\F1564"}.mdi-star-minus-outline::before{content:"\F1568"}.mdi-star-off::before{content:"\F04D1"}.mdi-star-off-outline::before{content:"\F155B"}.mdi-star-outline::before{content:"\F04D2"}.mdi-star-plus::before{content:"\F1563"}.mdi-star-plus-outline::before{content:"\F1567"}.mdi-star-remove::before{content:"\F1565"}.mdi-star-remove-outline::before{content:"\F1569"}.mdi-star-settings::before{content:"\F166A"}.mdi-star-settings-outline::before{content:"\F166B"}.mdi-star-three-points::before{content:"\F0AE4"}.mdi-star-three-points-outline::before{content:"\F0AE5"}.mdi-state-machine::before{content:"\F11EF"}.mdi-steam::before{content:"\F04D3"}.mdi-steering::before{content:"\F04D4"}.mdi-steering-off::before{content:"\F090E"}.mdi-step-backward::before{content:"\F04D5"}.mdi-step-backward-2::before{content:"\F04D6"}.mdi-step-forward::before{content:"\F04D7"}.mdi-step-forward-2::before{content:"\F04D8"}.mdi-stethoscope::before{content:"\F04D9"}.mdi-sticker::before{content:"\F1364"}.mdi-sticker-alert::before{content:"\F1365"}.mdi-sticker-alert-outline::before{content:"\F1366"}.mdi-sticker-check::before{content:"\F1367"}.mdi-sticker-check-outline::before{content:"\F1368"}.mdi-sticker-circle-outline::before{content:"\F05D0"}.mdi-sticker-emoji::before{content:"\F0785"}.mdi-sticker-minus::before{content:"\F1369"}.mdi-sticker-minus-outline::before{content:"\F136A"}.mdi-sticker-outline::before{content:"\F136B"}.mdi-sticker-plus::before{content:"\F136C"}.mdi-sticker-plus-outline::before{content:"\F136D"}.mdi-sticker-remove::before{content:"\F136E"}.mdi-sticker-remove-outline::before{content:"\F136F"}.mdi-stocking::before{content:"\F04DA"}.mdi-stomach::before{content:"\F1093"}.mdi-stop::before{content:"\F04DB"}.mdi-stop-circle::before{content:"\F0666"}.mdi-stop-circle-outline::before{content:"\F0667"}.mdi-store::before{content:"\F04DC"}.mdi-store-24-hour::before{content:"\F04DD"}.mdi-store-minus::before{content:"\F165E"}.mdi-store-outline::before{content:"\F1361"}.mdi-store-plus::before{content:"\F165F"}.mdi-store-remove::before{content:"\F1660"}.mdi-storefront::before{content:"\F07C7"}.mdi-storefront-outline::before{content:"\F10C1"}.mdi-stove::before{content:"\F04DE"}.mdi-strategy::before{content:"\F11D6"}.mdi-stretch-to-page::before{content:"\F0F2B"}.mdi-stretch-to-page-outline::before{content:"\F0F2C"}.mdi-string-lights::before{content:"\F12BA"}.mdi-string-lights-off::before{content:"\F12BB"}.mdi-subdirectory-arrow-left::before{content:"\F060C"}.mdi-subdirectory-arrow-right::before{content:"\F060D"}.mdi-submarine::before{content:"\F156C"}.mdi-subtitles::before{content:"\F0A16"}.mdi-subtitles-outline::before{content:"\F0A17"}.mdi-subway::before{content:"\F06AC"}.mdi-subway-alert-variant::before{content:"\F0D9D"}.mdi-subway-variant::before{content:"\F04DF"}.mdi-summit::before{content:"\F0786"}.mdi-sunglasses::before{content:"\F04E0"}.mdi-surround-sound::before{content:"\F05C5"}.mdi-surround-sound-2-0::before{content:"\F07F0"}.mdi-surround-sound-3-1::before{content:"\F07F1"}.mdi-surround-sound-5-1::before{content:"\F07F2"}.mdi-surround-sound-7-1::before{content:"\F07F3"}.mdi-svg::before{content:"\F0721"}.mdi-swap-horizontal::before{content:"\F04E1"}.mdi-swap-horizontal-bold::before{content:"\F0BCD"}.mdi-swap-horizontal-circle::before{content:"\F0FE1"}.mdi-swap-horizontal-circle-outline::before{content:"\F0FE2"}.mdi-swap-horizontal-variant::before{content:"\F08C1"}.mdi-swap-vertical::before{content:"\F04E2"}.mdi-swap-vertical-bold::before{content:"\F0BCE"}.mdi-swap-vertical-circle::before{content:"\F0FE3"}.mdi-swap-vertical-circle-outline::before{content:"\F0FE4"}.mdi-swap-vertical-variant::before{content:"\F08C2"}.mdi-swim::before{content:"\F04E3"}.mdi-switch::before{content:"\F04E4"}.mdi-sword::before{content:"\F04E5"}.mdi-sword-cross::before{content:"\F0787"}.mdi-syllabary-hangul::before{content:"\F1333"}.mdi-syllabary-hiragana::before{content:"\F1334"}.mdi-syllabary-katakana::before{content:"\F1335"}.mdi-syllabary-katakana-halfwidth::before{content:"\F1336"}.mdi-symbol::before{content:"\F1501"}.mdi-symfony::before{content:"\F0AE6"}.mdi-sync::before{content:"\F04E6"}.mdi-sync-alert::before{content:"\F04E7"}.mdi-sync-circle::before{content:"\F1378"}.mdi-sync-off::before{content:"\F04E8"}.mdi-tab::before{content:"\F04E9"}.mdi-tab-minus::before{content:"\F0B4B"}.mdi-tab-plus::before{content:"\F075C"}.mdi-tab-remove::before{content:"\F0B4C"}.mdi-tab-unselected::before{content:"\F04EA"}.mdi-table::before{content:"\F04EB"}.mdi-table-account::before{content:"\F13B9"}.mdi-table-alert::before{content:"\F13BA"}.mdi-table-arrow-down::before{content:"\F13BB"}.mdi-table-arrow-left::before{content:"\F13BC"}.mdi-table-arrow-right::before{content:"\F13BD"}.mdi-table-arrow-up::before{content:"\F13BE"}.mdi-table-border::before{content:"\F0A18"}.mdi-table-cancel::before{content:"\F13BF"}.mdi-table-chair::before{content:"\F1061"}.mdi-table-check::before{content:"\F13C0"}.mdi-table-clock::before{content:"\F13C1"}.mdi-table-cog::before{content:"\F13C2"}.mdi-table-column::before{content:"\F0835"}.mdi-table-column-plus-after::before{content:"\F04EC"}.mdi-table-column-plus-before::before{content:"\F04ED"}.mdi-table-column-remove::before{content:"\F04EE"}.mdi-table-column-width::before{content:"\F04EF"}.mdi-table-edit::before{content:"\F04F0"}.mdi-table-eye::before{content:"\F1094"}.mdi-table-eye-off::before{content:"\F13C3"}.mdi-table-furniture::before{content:"\F05BC"}.mdi-table-headers-eye::before{content:"\F121D"}.mdi-table-headers-eye-off::before{content:"\F121E"}.mdi-table-heart::before{content:"\F13C4"}.mdi-table-key::before{content:"\F13C5"}.mdi-table-large::before{content:"\F04F1"}.mdi-table-large-plus::before{content:"\F0F87"}.mdi-table-large-remove::before{content:"\F0F88"}.mdi-table-lock::before{content:"\F13C6"}.mdi-table-merge-cells::before{content:"\F09A6"}.mdi-table-minus::before{content:"\F13C7"}.mdi-table-multiple::before{content:"\F13C8"}.mdi-table-network::before{content:"\F13C9"}.mdi-table-of-contents::before{content:"\F0836"}.mdi-table-off::before{content:"\F13CA"}.mdi-table-plus::before{content:"\F0A75"}.mdi-table-refresh::before{content:"\F13A0"}.mdi-table-remove::before{content:"\F0A76"}.mdi-table-row::before{content:"\F0837"}.mdi-table-row-height::before{content:"\F04F2"}.mdi-table-row-plus-after::before{content:"\F04F3"}.mdi-table-row-plus-before::before{content:"\F04F4"}.mdi-table-row-remove::before{content:"\F04F5"}.mdi-table-search::before{content:"\F090F"}.mdi-table-settings::before{content:"\F0838"}.mdi-table-split-cell::before{content:"\F142A"}.mdi-table-star::before{content:"\F13CB"}.mdi-table-sync::before{content:"\F13A1"}.mdi-table-tennis::before{content:"\F0E68"}.mdi-tablet::before{content:"\F04F6"}.mdi-tablet-android::before{content:"\F04F7"}.mdi-tablet-cellphone::before{content:"\F09A7"}.mdi-tablet-dashboard::before{content:"\F0ECE"}.mdi-tablet-ipad::before{content:"\F04F8"}.mdi-taco::before{content:"\F0762"}.mdi-tag::before{content:"\F04F9"}.mdi-tag-faces::before{content:"\F04FA"}.mdi-tag-heart::before{content:"\F068B"}.mdi-tag-heart-outline::before{content:"\F0BCF"}.mdi-tag-minus::before{content:"\F0910"}.mdi-tag-minus-outline::before{content:"\F121F"}.mdi-tag-multiple::before{content:"\F04FB"}.mdi-tag-multiple-outline::before{content:"\F12F7"}.mdi-tag-off::before{content:"\F1220"}.mdi-tag-off-outline::before{content:"\F1221"}.mdi-tag-outline::before{content:"\F04FC"}.mdi-tag-plus::before{content:"\F0722"}.mdi-tag-plus-outline::before{content:"\F1222"}.mdi-tag-remove::before{content:"\F0723"}.mdi-tag-remove-outline::before{content:"\F1223"}.mdi-tag-text::before{content:"\F1224"}.mdi-tag-text-outline::before{content:"\F04FD"}.mdi-tailwind::before{content:"\F13FF"}.mdi-tank::before{content:"\F0D3A"}.mdi-tanker-truck::before{content:"\F0FE5"}.mdi-tape-drive::before{content:"\F16DF"}.mdi-tape-measure::before{content:"\F0B4D"}.mdi-target::before{content:"\F04FE"}.mdi-target-account::before{content:"\F0BD0"}.mdi-target-variant::before{content:"\F0A77"}.mdi-taxi::before{content:"\F04FF"}.mdi-tea::before{content:"\F0D9E"}.mdi-tea-outline::before{content:"\F0D9F"}.mdi-teach::before{content:"\F0890"}.mdi-teamviewer::before{content:"\F0500"}.mdi-telegram::before{content:"\F0501"}.mdi-telescope::before{content:"\F0B4E"}.mdi-television::before{content:"\F0502"}.mdi-television-ambient-light::before{content:"\F1356"}.mdi-television-box::before{content:"\F0839"}.mdi-television-classic::before{content:"\F07F4"}.mdi-television-classic-off::before{content:"\F083A"}.mdi-television-clean::before{content:"\F1110"}.mdi-television-guide::before{content:"\F0503"}.mdi-television-off::before{content:"\F083B"}.mdi-television-pause::before{content:"\F0F89"}.mdi-television-play::before{content:"\F0ECF"}.mdi-television-stop::before{content:"\F0F8A"}.mdi-temperature-celsius::before{content:"\F0504"}.mdi-temperature-fahrenheit::before{content:"\F0505"}.mdi-temperature-kelvin::before{content:"\F0506"}.mdi-tennis::before{content:"\F0DA0"}.mdi-tennis-ball::before{content:"\F0507"}.mdi-tent::before{content:"\F0508"}.mdi-terraform::before{content:"\F1062"}.mdi-terrain::before{content:"\F0509"}.mdi-test-tube::before{content:"\F0668"}.mdi-test-tube-empty::before{content:"\F0911"}.mdi-test-tube-off::before{content:"\F0912"}.mdi-text::before{content:"\F09A8"}.mdi-text-account::before{content:"\F1570"}.mdi-text-box::before{content:"\F021A"}.mdi-text-box-check::before{content:"\F0EA6"}.mdi-text-box-check-outline::before{content:"\F0EA7"}.mdi-text-box-minus::before{content:"\F0EA8"}.mdi-text-box-minus-outline::before{content:"\F0EA9"}.mdi-text-box-multiple::before{content:"\F0AB7"}.mdi-text-box-multiple-outline::before{content:"\F0AB8"}.mdi-text-box-outline::before{content:"\F09ED"}.mdi-text-box-plus::before{content:"\F0EAA"}.mdi-text-box-plus-outline::before{content:"\F0EAB"}.mdi-text-box-remove::before{content:"\F0EAC"}.mdi-text-box-remove-outline::before{content:"\F0EAD"}.mdi-text-box-search::before{content:"\F0EAE"}.mdi-text-box-search-outline::before{content:"\F0EAF"}.mdi-text-recognition::before{content:"\F113D"}.mdi-text-search::before{content:"\F13B8"}.mdi-text-shadow::before{content:"\F0669"}.mdi-text-short::before{content:"\F09A9"}.mdi-text-subject::before{content:"\F09AA"}.mdi-text-to-speech::before{content:"\F050A"}.mdi-text-to-speech-off::before{content:"\F050B"}.mdi-texture::before{content:"\F050C"}.mdi-texture-box::before{content:"\F0FE6"}.mdi-theater::before{content:"\F050D"}.mdi-theme-light-dark::before{content:"\F050E"}.mdi-thermometer::before{content:"\F050F"}.mdi-thermometer-alert::before{content:"\F0E01"}.mdi-thermometer-chevron-down::before{content:"\F0E02"}.mdi-thermometer-chevron-up::before{content:"\F0E03"}.mdi-thermometer-high::before{content:"\F10C2"}.mdi-thermometer-lines::before{content:"\F0510"}.mdi-thermometer-low::before{content:"\F10C3"}.mdi-thermometer-minus::before{content:"\F0E04"}.mdi-thermometer-off::before{content:"\F1531"}.mdi-thermometer-plus::before{content:"\F0E05"}.mdi-thermostat::before{content:"\F0393"}.mdi-thermostat-box::before{content:"\F0891"}.mdi-thought-bubble::before{content:"\F07F6"}.mdi-thought-bubble-outline::before{content:"\F07F7"}.mdi-thumb-down::before{content:"\F0511"}.mdi-thumb-down-outline::before{content:"\F0512"}.mdi-thumb-up::before{content:"\F0513"}.mdi-thumb-up-outline::before{content:"\F0514"}.mdi-thumbs-up-down::before{content:"\F0515"}.mdi-ticket::before{content:"\F0516"}.mdi-ticket-account::before{content:"\F0517"}.mdi-ticket-confirmation::before{content:"\F0518"}.mdi-ticket-confirmation-outline::before{content:"\F13AA"}.mdi-ticket-outline::before{content:"\F0913"}.mdi-ticket-percent::before{content:"\F0724"}.mdi-ticket-percent-outline::before{content:"\F142B"}.mdi-tie::before{content:"\F0519"}.mdi-tilde::before{content:"\F0725"}.mdi-timelapse::before{content:"\F051A"}.mdi-timeline::before{content:"\F0BD1"}.mdi-timeline-alert::before{content:"\F0F95"}.mdi-timeline-alert-outline::before{content:"\F0F98"}.mdi-timeline-check::before{content:"\F1532"}.mdi-timeline-check-outline::before{content:"\F1533"}.mdi-timeline-clock::before{content:"\F11FB"}.mdi-timeline-clock-outline::before{content:"\F11FC"}.mdi-timeline-help::before{content:"\F0F99"}.mdi-timeline-help-outline::before{content:"\F0F9A"}.mdi-timeline-minus::before{content:"\F1534"}.mdi-timeline-minus-outline::before{content:"\F1535"}.mdi-timeline-outline::before{content:"\F0BD2"}.mdi-timeline-plus::before{content:"\F0F96"}.mdi-timeline-plus-outline::before{content:"\F0F97"}.mdi-timeline-remove::before{content:"\F1536"}.mdi-timeline-remove-outline::before{content:"\F1537"}.mdi-timeline-text::before{content:"\F0BD3"}.mdi-timeline-text-outline::before{content:"\F0BD4"}.mdi-timer::before{content:"\F13AB"}.mdi-timer-10::before{content:"\F051C"}.mdi-timer-3::before{content:"\F051D"}.mdi-timer-off::before{content:"\F13AC"}.mdi-timer-off-outline::before{content:"\F051E"}.mdi-timer-outline::before{content:"\F051B"}.mdi-timer-sand::before{content:"\F051F"}.mdi-timer-sand-empty::before{content:"\F06AD"}.mdi-timer-sand-full::before{content:"\F078C"}.mdi-timetable::before{content:"\F0520"}.mdi-toaster::before{content:"\F1063"}.mdi-toaster-off::before{content:"\F11B7"}.mdi-toaster-oven::before{content:"\F0CD3"}.mdi-toggle-switch::before{content:"\F0521"}.mdi-toggle-switch-off::before{content:"\F0522"}.mdi-toggle-switch-off-outline::before{content:"\F0A19"}.mdi-toggle-switch-outline::before{content:"\F0A1A"}.mdi-toilet::before{content:"\F09AB"}.mdi-toolbox::before{content:"\F09AC"}.mdi-toolbox-outline::before{content:"\F09AD"}.mdi-tools::before{content:"\F1064"}.mdi-tooltip::before{content:"\F0523"}.mdi-tooltip-account::before{content:"\F000C"}.mdi-tooltip-check::before{content:"\F155C"}.mdi-tooltip-check-outline::before{content:"\F155D"}.mdi-tooltip-edit::before{content:"\F0524"}.mdi-tooltip-edit-outline::before{content:"\F12C5"}.mdi-tooltip-image::before{content:"\F0525"}.mdi-tooltip-image-outline::before{content:"\F0BD5"}.mdi-tooltip-minus::before{content:"\F155E"}.mdi-tooltip-minus-outline::before{content:"\F155F"}.mdi-tooltip-outline::before{content:"\F0526"}.mdi-tooltip-plus::before{content:"\F0BD6"}.mdi-tooltip-plus-outline::before{content:"\F0527"}.mdi-tooltip-remove::before{content:"\F1560"}.mdi-tooltip-remove-outline::before{content:"\F1561"}.mdi-tooltip-text::before{content:"\F0528"}.mdi-tooltip-text-outline::before{content:"\F0BD7"}.mdi-tooth::before{content:"\F08C3"}.mdi-tooth-outline::before{content:"\F0529"}.mdi-toothbrush::before{content:"\F1129"}.mdi-toothbrush-electric::before{content:"\F112C"}.mdi-toothbrush-paste::before{content:"\F112A"}.mdi-torch::before{content:"\F1606"}.mdi-tortoise::before{content:"\F0D3B"}.mdi-toslink::before{content:"\F12B8"}.mdi-tournament::before{content:"\F09AE"}.mdi-tow-truck::before{content:"\F083C"}.mdi-tower-beach::before{content:"\F0681"}.mdi-tower-fire::before{content:"\F0682"}.mdi-toy-brick::before{content:"\F1288"}.mdi-toy-brick-marker::before{content:"\F1289"}.mdi-toy-brick-marker-outline::before{content:"\F128A"}.mdi-toy-brick-minus::before{content:"\F128B"}.mdi-toy-brick-minus-outline::before{content:"\F128C"}.mdi-toy-brick-outline::before{content:"\F128D"}.mdi-toy-brick-plus::before{content:"\F128E"}.mdi-toy-brick-plus-outline::before{content:"\F128F"}.mdi-toy-brick-remove::before{content:"\F1290"}.mdi-toy-brick-remove-outline::before{content:"\F1291"}.mdi-toy-brick-search::before{content:"\F1292"}.mdi-toy-brick-search-outline::before{content:"\F1293"}.mdi-track-light::before{content:"\F0914"}.mdi-trackpad::before{content:"\F07F8"}.mdi-trackpad-lock::before{content:"\F0933"}.mdi-tractor::before{content:"\F0892"}.mdi-tractor-variant::before{content:"\F14C4"}.mdi-trademark::before{content:"\F0A78"}.mdi-traffic-cone::before{content:"\F137C"}.mdi-traffic-light::before{content:"\F052B"}.mdi-train::before{content:"\F052C"}.mdi-train-car::before{content:"\F0BD8"}.mdi-train-variant::before{content:"\F08C4"}.mdi-tram::before{content:"\F052D"}.mdi-tram-side::before{content:"\F0FE7"}.mdi-transcribe::before{content:"\F052E"}.mdi-transcribe-close::before{content:"\F052F"}.mdi-transfer::before{content:"\F1065"}.mdi-transfer-down::before{content:"\F0DA1"}.mdi-transfer-left::before{content:"\F0DA2"}.mdi-transfer-right::before{content:"\F0530"}.mdi-transfer-up::before{content:"\F0DA3"}.mdi-transit-connection::before{content:"\F0D3C"}.mdi-transit-connection-horizontal::before{content:"\F1546"}.mdi-transit-connection-variant::before{content:"\F0D3D"}.mdi-transit-detour::before{content:"\F0F8B"}.mdi-transit-skip::before{content:"\F1515"}.mdi-transit-transfer::before{content:"\F06AE"}.mdi-transition::before{content:"\F0915"}.mdi-transition-masked::before{content:"\F0916"}.mdi-translate::before{content:"\F05CA"}.mdi-translate-off::before{content:"\F0E06"}.mdi-transmission-tower::before{content:"\F0D3E"}.mdi-trash-can::before{content:"\F0A79"}.mdi-trash-can-outline::before{content:"\F0A7A"}.mdi-tray::before{content:"\F1294"}.mdi-tray-alert::before{content:"\F1295"}.mdi-tray-full::before{content:"\F1296"}.mdi-tray-minus::before{content:"\F1297"}.mdi-tray-plus::before{content:"\F1298"}.mdi-tray-remove::before{content:"\F1299"}.mdi-treasure-chest::before{content:"\F0726"}.mdi-tree::before{content:"\F0531"}.mdi-tree-outline::before{content:"\F0E69"}.mdi-trello::before{content:"\F0532"}.mdi-trending-down::before{content:"\F0533"}.mdi-trending-neutral::before{content:"\F0534"}.mdi-trending-up::before{content:"\F0535"}.mdi-triangle::before{content:"\F0536"}.mdi-triangle-outline::before{content:"\F0537"}.mdi-triangle-wave::before{content:"\F147C"}.mdi-triforce::before{content:"\F0BD9"}.mdi-trophy::before{content:"\F0538"}.mdi-trophy-award::before{content:"\F0539"}.mdi-trophy-broken::before{content:"\F0DA4"}.mdi-trophy-outline::before{content:"\F053A"}.mdi-trophy-variant::before{content:"\F053B"}.mdi-trophy-variant-outline::before{content:"\F053C"}.mdi-truck::before{content:"\F053D"}.mdi-truck-check::before{content:"\F0CD4"}.mdi-truck-check-outline::before{content:"\F129A"}.mdi-truck-delivery::before{content:"\F053E"}.mdi-truck-delivery-outline::before{content:"\F129B"}.mdi-truck-fast::before{content:"\F0788"}.mdi-truck-fast-outline::before{content:"\F129C"}.mdi-truck-outline::before{content:"\F129D"}.mdi-truck-trailer::before{content:"\F0727"}.mdi-trumpet::before{content:"\F1096"}.mdi-tshirt-crew::before{content:"\F0A7B"}.mdi-tshirt-crew-outline::before{content:"\F053F"}.mdi-tshirt-v::before{content:"\F0A7C"}.mdi-tshirt-v-outline::before{content:"\F0540"}.mdi-tumble-dryer::before{content:"\F0917"}.mdi-tumble-dryer-alert::before{content:"\F11BA"}.mdi-tumble-dryer-off::before{content:"\F11BB"}.mdi-tune::before{content:"\F062E"}.mdi-tune-variant::before{content:"\F1542"}.mdi-tune-vertical::before{content:"\F066A"}.mdi-tune-vertical-variant::before{content:"\F1543"}.mdi-turnstile::before{content:"\F0CD5"}.mdi-turnstile-outline::before{content:"\F0CD6"}.mdi-turtle::before{content:"\F0CD7"}.mdi-twitch::before{content:"\F0543"}.mdi-twitter::before{content:"\F0544"}.mdi-twitter-retweet::before{content:"\F0547"}.mdi-two-factor-authentication::before{content:"\F09AF"}.mdi-typewriter::before{content:"\F0F2D"}.mdi-ubisoft::before{content:"\F0BDA"}.mdi-ubuntu::before{content:"\F0548"}.mdi-ufo::before{content:"\F10C4"}.mdi-ufo-outline::before{content:"\F10C5"}.mdi-ultra-high-definition::before{content:"\F07F9"}.mdi-umbraco::before{content:"\F0549"}.mdi-umbrella::before{content:"\F054A"}.mdi-umbrella-closed::before{content:"\F09B0"}.mdi-umbrella-closed-outline::before{content:"\F13E2"}.mdi-umbrella-closed-variant::before{content:"\F13E1"}.mdi-umbrella-outline::before{content:"\F054B"}.mdi-undo::before{content:"\F054C"}.mdi-undo-variant::before{content:"\F054D"}.mdi-unfold-less-horizontal::before{content:"\F054E"}.mdi-unfold-less-vertical::before{content:"\F0760"}.mdi-unfold-more-horizontal::before{content:"\F054F"}.mdi-unfold-more-vertical::before{content:"\F0761"}.mdi-ungroup::before{content:"\F0550"}.mdi-unicode::before{content:"\F0ED0"}.mdi-unicorn::before{content:"\F15C2"}.mdi-unicorn-variant::before{content:"\F15C3"}.mdi-unicycle::before{content:"\F15E5"}.mdi-unity::before{content:"\F06AF"}.mdi-unreal::before{content:"\F09B1"}.mdi-untappd::before{content:"\F0551"}.mdi-update::before{content:"\F06B0"}.mdi-upload::before{content:"\F0552"}.mdi-upload-lock::before{content:"\F1373"}.mdi-upload-lock-outline::before{content:"\F1374"}.mdi-upload-multiple::before{content:"\F083D"}.mdi-upload-network::before{content:"\F06F6"}.mdi-upload-network-outline::before{content:"\F0CD8"}.mdi-upload-off::before{content:"\F10C6"}.mdi-upload-off-outline::before{content:"\F10C7"}.mdi-upload-outline::before{content:"\F0E07"}.mdi-usb::before{content:"\F0553"}.mdi-usb-flash-drive::before{content:"\F129E"}.mdi-usb-flash-drive-outline::before{content:"\F129F"}.mdi-usb-port::before{content:"\F11F0"}.mdi-valve::before{content:"\F1066"}.mdi-valve-closed::before{content:"\F1067"}.mdi-valve-open::before{content:"\F1068"}.mdi-van-passenger::before{content:"\F07FA"}.mdi-van-utility::before{content:"\F07FB"}.mdi-vanish::before{content:"\F07FC"}.mdi-vanish-quarter::before{content:"\F1554"}.mdi-vanity-light::before{content:"\F11E1"}.mdi-variable::before{content:"\F0AE7"}.mdi-variable-box::before{content:"\F1111"}.mdi-vector-arrange-above::before{content:"\F0554"}.mdi-vector-arrange-below::before{content:"\F0555"}.mdi-vector-bezier::before{content:"\F0AE8"}.mdi-vector-circle::before{content:"\F0556"}.mdi-vector-circle-variant::before{content:"\F0557"}.mdi-vector-combine::before{content:"\F0558"}.mdi-vector-curve::before{content:"\F0559"}.mdi-vector-difference::before{content:"\F055A"}.mdi-vector-difference-ab::before{content:"\F055B"}.mdi-vector-difference-ba::before{content:"\F055C"}.mdi-vector-ellipse::before{content:"\F0893"}.mdi-vector-intersection::before{content:"\F055D"}.mdi-vector-line::before{content:"\F055E"}.mdi-vector-link::before{content:"\F0FE8"}.mdi-vector-point::before{content:"\F055F"}.mdi-vector-polygon::before{content:"\F0560"}.mdi-vector-polyline::before{content:"\F0561"}.mdi-vector-polyline-edit::before{content:"\F1225"}.mdi-vector-polyline-minus::before{content:"\F1226"}.mdi-vector-polyline-plus::before{content:"\F1227"}.mdi-vector-polyline-remove::before{content:"\F1228"}.mdi-vector-radius::before{content:"\F074A"}.mdi-vector-rectangle::before{content:"\F05C6"}.mdi-vector-selection::before{content:"\F0562"}.mdi-vector-square::before{content:"\F0001"}.mdi-vector-triangle::before{content:"\F0563"}.mdi-vector-union::before{content:"\F0564"}.mdi-vhs::before{content:"\F0A1B"}.mdi-vibrate::before{content:"\F0566"}.mdi-vibrate-off::before{content:"\F0CD9"}.mdi-video::before{content:"\F0567"}.mdi-video-3d::before{content:"\F07FD"}.mdi-video-3d-off::before{content:"\F13D9"}.mdi-video-3d-variant::before{content:"\F0ED1"}.mdi-video-4k-box::before{content:"\F083E"}.mdi-video-account::before{content:"\F0919"}.mdi-video-box::before{content:"\F00FD"}.mdi-video-box-off::before{content:"\F00FE"}.mdi-video-check::before{content:"\F1069"}.mdi-video-check-outline::before{content:"\F106A"}.mdi-video-high-definition::before{content:"\F152E"}.mdi-video-image::before{content:"\F091A"}.mdi-video-input-antenna::before{content:"\F083F"}.mdi-video-input-component::before{content:"\F0840"}.mdi-video-input-hdmi::before{content:"\F0841"}.mdi-video-input-scart::before{content:"\F0F8C"}.mdi-video-input-svideo::before{content:"\F0842"}.mdi-video-minus::before{content:"\F09B2"}.mdi-video-minus-outline::before{content:"\F02BA"}.mdi-video-off::before{content:"\F0568"}.mdi-video-off-outline::before{content:"\F0BDB"}.mdi-video-outline::before{content:"\F0BDC"}.mdi-video-plus::before{content:"\F09B3"}.mdi-video-plus-outline::before{content:"\F01D3"}.mdi-video-stabilization::before{content:"\F091B"}.mdi-video-switch::before{content:"\F0569"}.mdi-video-switch-outline::before{content:"\F0790"}.mdi-video-vintage::before{content:"\F0A1C"}.mdi-video-wireless::before{content:"\F0ED2"}.mdi-video-wireless-outline::before{content:"\F0ED3"}.mdi-view-agenda::before{content:"\F056A"}.mdi-view-agenda-outline::before{content:"\F11D8"}.mdi-view-array::before{content:"\F056B"}.mdi-view-array-outline::before{content:"\F1485"}.mdi-view-carousel::before{content:"\F056C"}.mdi-view-carousel-outline::before{content:"\F1486"}.mdi-view-column::before{content:"\F056D"}.mdi-view-column-outline::before{content:"\F1487"}.mdi-view-comfy::before{content:"\F0E6A"}.mdi-view-comfy-outline::before{content:"\F1488"}.mdi-view-compact::before{content:"\F0E6B"}.mdi-view-compact-outline::before{content:"\F0E6C"}.mdi-view-dashboard::before{content:"\F056E"}.mdi-view-dashboard-outline::before{content:"\F0A1D"}.mdi-view-dashboard-variant::before{content:"\F0843"}.mdi-view-dashboard-variant-outline::before{content:"\F1489"}.mdi-view-day::before{content:"\F056F"}.mdi-view-day-outline::before{content:"\F148A"}.mdi-view-grid::before{content:"\F0570"}.mdi-view-grid-outline::before{content:"\F11D9"}.mdi-view-grid-plus::before{content:"\F0F8D"}.mdi-view-grid-plus-outline::before{content:"\F11DA"}.mdi-view-headline::before{content:"\F0571"}.mdi-view-list::before{content:"\F0572"}.mdi-view-list-outline::before{content:"\F148B"}.mdi-view-module::before{content:"\F0573"}.mdi-view-module-outline::before{content:"\F148C"}.mdi-view-parallel::before{content:"\F0728"}.mdi-view-parallel-outline::before{content:"\F148D"}.mdi-view-quilt::before{content:"\F0574"}.mdi-view-quilt-outline::before{content:"\F148E"}.mdi-view-sequential::before{content:"\F0729"}.mdi-view-sequential-outline::before{content:"\F148F"}.mdi-view-split-horizontal::before{content:"\F0BCB"}.mdi-view-split-vertical::before{content:"\F0BCC"}.mdi-view-stream::before{content:"\F0575"}.mdi-view-stream-outline::before{content:"\F1490"}.mdi-view-week::before{content:"\F0576"}.mdi-view-week-outline::before{content:"\F1491"}.mdi-vimeo::before{content:"\F0577"}.mdi-violin::before{content:"\F060F"}.mdi-virtual-reality::before{content:"\F0894"}.mdi-virus::before{content:"\F13B6"}.mdi-virus-outline::before{content:"\F13B7"}.mdi-vk::before{content:"\F0579"}.mdi-vlc::before{content:"\F057C"}.mdi-voice-off::before{content:"\F0ED4"}.mdi-voicemail::before{content:"\F057D"}.mdi-volleyball::before{content:"\F09B4"}.mdi-volume-high::before{content:"\F057E"}.mdi-volume-low::before{content:"\F057F"}.mdi-volume-medium::before{content:"\F0580"}.mdi-volume-minus::before{content:"\F075E"}.mdi-volume-mute::before{content:"\F075F"}.mdi-volume-off::before{content:"\F0581"}.mdi-volume-plus::before{content:"\F075D"}.mdi-volume-source::before{content:"\F1120"}.mdi-volume-variant-off::before{content:"\F0E08"}.mdi-volume-vibrate::before{content:"\F1121"}.mdi-vote::before{content:"\F0A1F"}.mdi-vote-outline::before{content:"\F0A20"}.mdi-vpn::before{content:"\F0582"}.mdi-vuejs::before{content:"\F0844"}.mdi-vuetify::before{content:"\F0E6D"}.mdi-walk::before{content:"\F0583"}.mdi-wall::before{content:"\F07FE"}.mdi-wall-sconce::before{content:"\F091C"}.mdi-wall-sconce-flat::before{content:"\F091D"}.mdi-wall-sconce-flat-variant::before{content:"\F041C"}.mdi-wall-sconce-round::before{content:"\F0748"}.mdi-wall-sconce-round-variant::before{content:"\F091E"}.mdi-wallet::before{content:"\F0584"}.mdi-wallet-giftcard::before{content:"\F0585"}.mdi-wallet-membership::before{content:"\F0586"}.mdi-wallet-outline::before{content:"\F0BDD"}.mdi-wallet-plus::before{content:"\F0F8E"}.mdi-wallet-plus-outline::before{content:"\F0F8F"}.mdi-wallet-travel::before{content:"\F0587"}.mdi-wallpaper::before{content:"\F0E09"}.mdi-wan::before{content:"\F0588"}.mdi-wardrobe::before{content:"\F0F90"}.mdi-wardrobe-outline::before{content:"\F0F91"}.mdi-warehouse::before{content:"\F0F81"}.mdi-washing-machine::before{content:"\F072A"}.mdi-washing-machine-alert::before{content:"\F11BC"}.mdi-washing-machine-off::before{content:"\F11BD"}.mdi-watch::before{content:"\F0589"}.mdi-watch-export::before{content:"\F058A"}.mdi-watch-export-variant::before{content:"\F0895"}.mdi-watch-import::before{content:"\F058B"}.mdi-watch-import-variant::before{content:"\F0896"}.mdi-watch-variant::before{content:"\F0897"}.mdi-watch-vibrate::before{content:"\F06B1"}.mdi-watch-vibrate-off::before{content:"\F0CDA"}.mdi-water::before{content:"\F058C"}.mdi-water-alert::before{content:"\F1502"}.mdi-water-alert-outline::before{content:"\F1503"}.mdi-water-boiler::before{content:"\F0F92"}.mdi-water-boiler-alert::before{content:"\F11B3"}.mdi-water-boiler-off::before{content:"\F11B4"}.mdi-water-check::before{content:"\F1504"}.mdi-water-check-outline::before{content:"\F1505"}.mdi-water-minus::before{content:"\F1506"}.mdi-water-minus-outline::before{content:"\F1507"}.mdi-water-off::before{content:"\F058D"}.mdi-water-off-outline::before{content:"\F1508"}.mdi-water-outline::before{content:"\F0E0A"}.mdi-water-percent::before{content:"\F058E"}.mdi-water-percent-alert::before{content:"\F1509"}.mdi-water-plus::before{content:"\F150A"}.mdi-water-plus-outline::before{content:"\F150B"}.mdi-water-polo::before{content:"\F12A0"}.mdi-water-pump::before{content:"\F058F"}.mdi-water-pump-off::before{content:"\F0F93"}.mdi-water-remove::before{content:"\F150C"}.mdi-water-remove-outline::before{content:"\F150D"}.mdi-water-well::before{content:"\F106B"}.mdi-water-well-outline::before{content:"\F106C"}.mdi-watering-can::before{content:"\F1481"}.mdi-watering-can-outline::before{content:"\F1482"}.mdi-watermark::before{content:"\F0612"}.mdi-wave::before{content:"\F0F2E"}.mdi-waveform::before{content:"\F147D"}.mdi-waves::before{content:"\F078D"}.mdi-waze::before{content:"\F0BDE"}.mdi-weather-cloudy::before{content:"\F0590"}.mdi-weather-cloudy-alert::before{content:"\F0F2F"}.mdi-weather-cloudy-arrow-right::before{content:"\F0E6E"}.mdi-weather-fog::before{content:"\F0591"}.mdi-weather-hail::before{content:"\F0592"}.mdi-weather-hazy::before{content:"\F0F30"}.mdi-weather-hurricane::before{content:"\F0898"}.mdi-weather-lightning::before{content:"\F0593"}.mdi-weather-lightning-rainy::before{content:"\F067E"}.mdi-weather-night::before{content:"\F0594"}.mdi-weather-night-partly-cloudy::before{content:"\F0F31"}.mdi-weather-partly-cloudy::before{content:"\F0595"}.mdi-weather-partly-lightning::before{content:"\F0F32"}.mdi-weather-partly-rainy::before{content:"\F0F33"}.mdi-weather-partly-snowy::before{content:"\F0F34"}.mdi-weather-partly-snowy-rainy::before{content:"\F0F35"}.mdi-weather-pouring::before{content:"\F0596"}.mdi-weather-rainy::before{content:"\F0597"}.mdi-weather-snowy::before{content:"\F0598"}.mdi-weather-snowy-heavy::before{content:"\F0F36"}.mdi-weather-snowy-rainy::before{content:"\F067F"}.mdi-weather-sunny::before{content:"\F0599"}.mdi-weather-sunny-alert::before{content:"\F0F37"}.mdi-weather-sunny-off::before{content:"\F14E4"}.mdi-weather-sunset::before{content:"\F059A"}.mdi-weather-sunset-down::before{content:"\F059B"}.mdi-weather-sunset-up::before{content:"\F059C"}.mdi-weather-tornado::before{content:"\F0F38"}.mdi-weather-windy::before{content:"\F059D"}.mdi-weather-windy-variant::before{content:"\F059E"}.mdi-web::before{content:"\F059F"}.mdi-web-box::before{content:"\F0F94"}.mdi-web-clock::before{content:"\F124A"}.mdi-webcam::before{content:"\F05A0"}.mdi-webhook::before{content:"\F062F"}.mdi-webpack::before{content:"\F072B"}.mdi-webrtc::before{content:"\F1248"}.mdi-wechat::before{content:"\F0611"}.mdi-weight::before{content:"\F05A1"}.mdi-weight-gram::before{content:"\F0D3F"}.mdi-weight-kilogram::before{content:"\F05A2"}.mdi-weight-lifter::before{content:"\F115D"}.mdi-weight-pound::before{content:"\F09B5"}.mdi-whatsapp::before{content:"\F05A3"}.mdi-wheel-barrow::before{content:"\F14F2"}.mdi-wheelchair-accessibility::before{content:"\F05A4"}.mdi-whistle::before{content:"\F09B6"}.mdi-whistle-outline::before{content:"\F12BC"}.mdi-white-balance-auto::before{content:"\F05A5"}.mdi-white-balance-incandescent::before{content:"\F05A6"}.mdi-white-balance-iridescent::before{content:"\F05A7"}.mdi-white-balance-sunny::before{content:"\F05A8"}.mdi-widgets::before{content:"\F072C"}.mdi-widgets-outline::before{content:"\F1355"}.mdi-wifi::before{content:"\F05A9"}.mdi-wifi-alert::before{content:"\F16B5"}.mdi-wifi-arrow-down::before{content:"\F16B6"}.mdi-wifi-arrow-left::before{content:"\F16B7"}.mdi-wifi-arrow-left-right::before{content:"\F16B8"}.mdi-wifi-arrow-right::before{content:"\F16B9"}.mdi-wifi-arrow-up::before{content:"\F16BA"}.mdi-wifi-arrow-up-down::before{content:"\F16BB"}.mdi-wifi-cancel::before{content:"\F16BC"}.mdi-wifi-check::before{content:"\F16BD"}.mdi-wifi-cog::before{content:"\F16BE"}.mdi-wifi-lock::before{content:"\F16BF"}.mdi-wifi-lock-open::before{content:"\F16C0"}.mdi-wifi-marker::before{content:"\F16C1"}.mdi-wifi-minus::before{content:"\F16C2"}.mdi-wifi-off::before{content:"\F05AA"}.mdi-wifi-plus::before{content:"\F16C3"}.mdi-wifi-refresh::before{content:"\F16C4"}.mdi-wifi-remove::before{content:"\F16C5"}.mdi-wifi-settings::before{content:"\F16C6"}.mdi-wifi-star::before{content:"\F0E0B"}.mdi-wifi-strength-1::before{content:"\F091F"}.mdi-wifi-strength-1-alert::before{content:"\F0920"}.mdi-wifi-strength-1-lock::before{content:"\F0921"}.mdi-wifi-strength-1-lock-open::before{content:"\F16CB"}.mdi-wifi-strength-2::before{content:"\F0922"}.mdi-wifi-strength-2-alert::before{content:"\F0923"}.mdi-wifi-strength-2-lock::before{content:"\F0924"}.mdi-wifi-strength-2-lock-open::before{content:"\F16CC"}.mdi-wifi-strength-3::before{content:"\F0925"}.mdi-wifi-strength-3-alert::before{content:"\F0926"}.mdi-wifi-strength-3-lock::before{content:"\F0927"}.mdi-wifi-strength-3-lock-open::before{content:"\F16CD"}.mdi-wifi-strength-4::before{content:"\F0928"}.mdi-wifi-strength-4-alert::before{content:"\F0929"}.mdi-wifi-strength-4-lock::before{content:"\F092A"}.mdi-wifi-strength-4-lock-open::before{content:"\F16CE"}.mdi-wifi-strength-alert-outline::before{content:"\F092B"}.mdi-wifi-strength-lock-open-outline::before{content:"\F16CF"}.mdi-wifi-strength-lock-outline::before{content:"\F092C"}.mdi-wifi-strength-off::before{content:"\F092D"}.mdi-wifi-strength-off-outline::before{content:"\F092E"}.mdi-wifi-strength-outline::before{content:"\F092F"}.mdi-wifi-sync::before{content:"\F16C7"}.mdi-wikipedia::before{content:"\F05AC"}.mdi-wind-turbine::before{content:"\F0DA5"}.mdi-window-close::before{content:"\F05AD"}.mdi-window-closed::before{content:"\F05AE"}.mdi-window-closed-variant::before{content:"\F11DB"}.mdi-window-maximize::before{content:"\F05AF"}.mdi-window-minimize::before{content:"\F05B0"}.mdi-window-open::before{content:"\F05B1"}.mdi-window-open-variant::before{content:"\F11DC"}.mdi-window-restore::before{content:"\F05B2"}.mdi-window-shutter::before{content:"\F111C"}.mdi-window-shutter-alert::before{content:"\F111D"}.mdi-window-shutter-open::before{content:"\F111E"}.mdi-windsock::before{content:"\F15FA"}.mdi-wiper::before{content:"\F0AE9"}.mdi-wiper-wash::before{content:"\F0DA6"}.mdi-wizard-hat::before{content:"\F1477"}.mdi-wordpress::before{content:"\F05B4"}.mdi-wrap::before{content:"\F05B6"}.mdi-wrap-disabled::before{content:"\F0BDF"}.mdi-wrench::before{content:"\F05B7"}.mdi-wrench-outline::before{content:"\F0BE0"}.mdi-xamarin::before{content:"\F0845"}.mdi-xamarin-outline::before{content:"\F0846"}.mdi-xing::before{content:"\F05BE"}.mdi-xml::before{content:"\F05C0"}.mdi-xmpp::before{content:"\F07FF"}.mdi-y-combinator::before{content:"\F0624"}.mdi-yahoo::before{content:"\F0B4F"}.mdi-yeast::before{content:"\F05C1"}.mdi-yin-yang::before{content:"\F0680"}.mdi-yoga::before{content:"\F117C"}.mdi-youtube::before{content:"\F05C3"}.mdi-youtube-gaming::before{content:"\F0848"}.mdi-youtube-studio::before{content:"\F0847"}.mdi-youtube-subscription::before{content:"\F0D40"}.mdi-youtube-tv::before{content:"\F0448"}.mdi-yurt::before{content:"\F1516"}.mdi-z-wave::before{content:"\F0AEA"}.mdi-zend::before{content:"\F0AEB"}.mdi-zigbee::before{content:"\F0D41"}.mdi-zip-box::before{content:"\F05C4"}.mdi-zip-box-outline::before{content:"\F0FFA"}.mdi-zip-disk::before{content:"\F0A23"}.mdi-zodiac-aquarius::before{content:"\F0A7D"}.mdi-zodiac-aries::before{content:"\F0A7E"}.mdi-zodiac-cancer::before{content:"\F0A7F"}.mdi-zodiac-capricorn::before{content:"\F0A80"}.mdi-zodiac-gemini::before{content:"\F0A81"}.mdi-zodiac-leo::before{content:"\F0A82"}.mdi-zodiac-libra::before{content:"\F0A83"}.mdi-zodiac-pisces::before{content:"\F0A84"}.mdi-zodiac-sagittarius::before{content:"\F0A85"}.mdi-zodiac-scorpio::before{content:"\F0A86"}.mdi-zodiac-taurus::before{content:"\F0A87"}.mdi-zodiac-virgo::before{content:"\F0A88"}.mdi-blank::before{content:"\F68C";visibility:hidden}.mdi-18px.mdi-set,.mdi-18px.mdi:before{font-size:18px}.mdi-24px.mdi-set,.mdi-24px.mdi:before{font-size:24px}.mdi-36px.mdi-set,.mdi-36px.mdi:before{font-size:36px}.mdi-48px.mdi-set,.mdi-48px.mdi:before{font-size:48px}.mdi-dark:before{color:rgba(0,0,0,0.54)}.mdi-dark.mdi-inactive:before{color:rgba(0,0,0,0.26)}.mdi-light:before{color:#fff}.mdi-light.mdi-inactive:before{color:rgba(255,255,255,0.3)}.mdi-rotate-45:before{-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.mdi-rotate-90:before{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.mdi-rotate-135:before{-webkit-transform:rotate(135deg);-ms-transform:rotate(135deg);transform:rotate(135deg)}.mdi-rotate-180:before{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.mdi-rotate-225:before{-webkit-transform:rotate(225deg);-ms-transform:rotate(225deg);transform:rotate(225deg)}.mdi-rotate-270:before{-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.mdi-rotate-315:before{-webkit-transform:rotate(315deg);-ms-transform:rotate(315deg);transform:rotate(315deg)}.mdi-flip-h:before{-webkit-transform:scaleX(-1);transform:scaleX(-1);filter:FlipH;-ms-filter:"FlipH"}.mdi-flip-v:before{-webkit-transform:scaleY(-1);transform:scaleY(-1);filter:FlipV;-ms-filter:"FlipV"}.mdi-spin:before{-webkit-animation:mdi-spin 2s infinite linear;animation:mdi-spin 2s infinite linear}@-webkit-keyframes mdi-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes mdi-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}} + +/*# sourceMappingURL=materialdesignicons.css.map */ \ No newline at end of file diff --git a/netbox/project-static/materialdesignicons-5.4.55/css/materialdesignicons.min.css.map b/netbox/project-static/materialdesignicons-5.4.55/css/materialdesignicons.min.css.map new file mode 100644 index 0000000000..b81e925340 --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/css/materialdesignicons.min.css.map @@ -0,0 +1,16 @@ +{ + "version": 3, + "file": "materialdesignicons.css", + "sources": [ + "../scss/materialdesignicons.scss", + "../scss/_variables.scss", + "../scss/_functions.scss", + "../scss/_path.scss", + "../scss/_core.scss", + "../scss/_icons.scss", + "../scss/_extras.scss", + "../scss/_animated.scss" + ], + "names": [], + "mappings": "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" +} \ No newline at end of file diff --git a/netbox/project-static/materialdesignicons-5.4.55/fonts/materialdesignicons-webfont.eot b/netbox/project-static/materialdesignicons-5.4.55/fonts/materialdesignicons-webfont.eot new file mode 100644 index 0000000000..079d5a043b Binary files /dev/null and b/netbox/project-static/materialdesignicons-5.4.55/fonts/materialdesignicons-webfont.eot differ diff --git a/netbox/project-static/materialdesignicons-5.4.55/fonts/materialdesignicons-webfont.ttf b/netbox/project-static/materialdesignicons-5.4.55/fonts/materialdesignicons-webfont.ttf new file mode 100644 index 0000000000..761dfaf8a6 Binary files /dev/null and b/netbox/project-static/materialdesignicons-5.4.55/fonts/materialdesignicons-webfont.ttf differ diff --git a/netbox/project-static/materialdesignicons-5.4.55/fonts/materialdesignicons-webfont.woff b/netbox/project-static/materialdesignicons-5.4.55/fonts/materialdesignicons-webfont.woff new file mode 100644 index 0000000000..c98a1009ca Binary files /dev/null and b/netbox/project-static/materialdesignicons-5.4.55/fonts/materialdesignicons-webfont.woff differ diff --git a/netbox/project-static/materialdesignicons-5.4.55/fonts/materialdesignicons-webfont.woff2 b/netbox/project-static/materialdesignicons-5.4.55/fonts/materialdesignicons-webfont.woff2 new file mode 100644 index 0000000000..9ef1ab3890 Binary files /dev/null and b/netbox/project-static/materialdesignicons-5.4.55/fonts/materialdesignicons-webfont.woff2 differ diff --git a/netbox/project-static/materialdesignicons-5.4.55/package.json b/netbox/project-static/materialdesignicons-5.4.55/package.json new file mode 100644 index 0000000000..4179c75038 --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/package.json @@ -0,0 +1,28 @@ +{ + "name": "@mdi/font", + "version": "5.8.55", + "description": "Dist for Material Design Webfont. This includes the Stock and Community icons in a single webfont collection.", + "style": "css/materialdesignicons.css", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/Templarian/MaterialDesign-Webfont.git" + }, + "keywords": [ + "material", + "design", + "icons", + "webfont" + ], + "author": { + "name": "Austin Andrews", + "web": "http://twitter.com/templarian" + }, + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/Templarian/MaterialDesign/issues" + }, + "homepage": "https://materialdesignicons.com" +} diff --git a/netbox/project-static/materialdesignicons-5.4.55/preview.html b/netbox/project-static/materialdesignicons-5.4.55/preview.html new file mode 100644 index 0000000000..a54569a1a2 --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/preview.html @@ -0,0 +1,717 @@ + + + + + + + Material Design Icons + + + + + +

    + + + + Material Design Icons + 5.8.55 + + + + + npm install @mdi/font + +

    + +

    Usage

    +
    <span class="mdi mdi-name"></span>
    + +
    + Click the icon, hex codepoint, or name below to copy the value to your clipboard. +
    + +

    New Icons -

    +
    + +

    All Icons -

    +
    + +

    Deprecated Icons -

    +

    + Deprecated icons will be removed in a future major release. +

    +
    + +

    Extras

    + +

    The helper CSS classes are listed below.

    + +
    +

    Size

    + +
    +
    +
    + +
    +
    + mdi-18px +
    +
    +
    +
    + +
    +
    + mdi-24px +
    +
    +
    +
    + +
    +
    + mdi-36px +
    +
    +
    +
    + +
    +
    + mdi-48px +
    +
    +
    +
    + +

    Rotate

    + +
    +
    +
    + +
    +
    +
    +
    + +
    +
    + mdi-rotate-45 +
    +
    +
    +
    + +
    +
    + mdi-rotate-90 +
    +
    +
    +
    + +
    +
    + mdi-rotate-135 +
    +
    +
    +
    + +
    +
    + mdi-rotate-180 +
    +
    +
    +
    + +
    +
    + mdi-rotate-225 +
    +
    +
    +
    + +
    +
    + mdi-rotate-270 +
    +
    +
    +
    + +
    +
    + mdi-rotate-315 +
    +
    +
    + +

    Flip

    + +
    +
    +
    + +
    +
    +
    +
    + +
    +
    + mdi-flip-h +
    +
    +
    +
    + +
    +
    + mdi-flip-v +
    +
    +
    + +

    Note: We do not include the ability to use mdi-flip-* and + mdi-rotate-* at the same time.

    + +

    Spin

    + +
    +
    +
    + +
    +
    + mdi-spin +
    +
    +
    +
    + +
    +
    + mdi-spin +
    +
    +
    + +

    Color

    + +
    +
    +
    + +
    +
    + mdi-light +
    +
    +
    +
    + +
    +
    + mdi-light mdi-inactive +
    +
    +
    +
    + +
    +
    + mdi-dark +
    +
    +
    +
    + +
    +
    + mdi-dark mdi-inactive +
    +
    +
    + + + + + + + + diff --git a/netbox/project-static/materialdesignicons-5.4.55/scss/_animated.scss b/netbox/project-static/materialdesignicons-5.4.55/scss/_animated.scss new file mode 100644 index 0000000000..a49efad3d4 --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/scss/_animated.scss @@ -0,0 +1,27 @@ +// From Font Awesome +.#{$mdi-css-prefix}-spin:before { + -webkit-animation: #{$mdi-css-prefix}-spin 2s infinite linear; + animation: #{$mdi-css-prefix}-spin 2s infinite linear; +} + +@-webkit-keyframes #{$mdi-css-prefix}-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + +@keyframes #{$mdi-css-prefix}-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} \ No newline at end of file diff --git a/netbox/project-static/font-awesome-4.7.0/less/core.less b/netbox/project-static/materialdesignicons-5.4.55/scss/_core.scss similarity index 57% rename from netbox/project-static/font-awesome-4.7.0/less/core.less rename to netbox/project-static/materialdesignicons-5.4.55/scss/_core.scss index c577ac84a6..e074cff973 100644 --- a/netbox/project-static/font-awesome-4.7.0/less/core.less +++ b/netbox/project-static/materialdesignicons-5.4.55/scss/_core.scss @@ -1,12 +1,10 @@ -// Base Class Definition -// ------------------------- - -.@{fa-css-prefix} { - display: inline-block; - font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration - font-size: inherit; // can't have font-size inherit on line above, so need to override - text-rendering: auto; // optimizelegibility throws things off #1094 - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -} +.#{$mdi-css-prefix}:before, +.#{$mdi-css-prefix}-set { + display: inline-block; + font: normal normal normal #{$mdi-font-size-base}/1 '#{$mdi-font-name}'; // shortening font declaration + font-size: inherit; // can't have font-size inherit on line above, so need to override + text-rendering: auto; // optimizelegibility throws things off #1094 + line-height: inherit; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} \ No newline at end of file diff --git a/netbox/project-static/materialdesignicons-5.4.55/scss/_extras.scss b/netbox/project-static/materialdesignicons-5.4.55/scss/_extras.scss new file mode 100644 index 0000000000..035debb452 --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/scss/_extras.scss @@ -0,0 +1,65 @@ +$mdi-sizes: 18 24 36 48 !default; +@each $mdi-size in $mdi-sizes { + .#{$mdi-css-prefix}-#{$mdi-size}px { + &.#{$mdi-css-prefix}-set, + &.#{$mdi-css-prefix}:before { + font-size: $mdi-size * 1px; + } + } +} + +.#{$mdi-css-prefix}-dark { + &:before { + color: rgba(0, 0, 0, 0.54); + } + &.#{$mdi-css-prefix}-inactive:before { + color: rgba(0, 0, 0, 0.26); + } +} +.#{$mdi-css-prefix}-light { + &:before { + color: rgba(255, 255, 255, 1); + } + &.#{$mdi-css-prefix}-inactive:before { + color: rgba(255, 255, 255, 0.3); + } +} + +$mdi-degrees: 45 90 135 180 225 270 315 !default; +@each $mdi-degree in $mdi-degrees { + .#{$mdi-css-prefix}-rotate-#{$mdi-degree}{ + &:before { + -webkit-transform: rotate(#{$mdi-degree}deg); + -ms-transform: rotate(#{$mdi-degree}deg); + transform: rotate(#{$mdi-degree}deg); + } + /* + // Not included in production + &.#{$mdi-css-prefix}-flip-h:before { + -webkit-transform: scaleX(-1) rotate(#{$mdi-degree}deg); + transform: scaleX(-1) rotate(#{$mdi-degree}deg); + filter: FlipH; + -ms-filter: "FlipH"; + } + &.#{$mdi-css-prefix}-flip-v:before { + -webkit-transform: scaleY(-1) rotate(#{$mdi-degree}deg); + -ms-transform: rotate(#{$mdi-degree}deg); + transform: scaleY(-1) rotate(#{$mdi-degree}deg); + filter: FlipV; + -ms-filter: "FlipV"; + } + */ + } +} +.#{$mdi-css-prefix}-flip-h:before { + -webkit-transform: scaleX(-1); + transform: scaleX(-1); + filter: FlipH; + -ms-filter: "FlipH"; +} +.#{$mdi-css-prefix}-flip-v:before { + -webkit-transform: scaleY(-1); + transform: scaleY(-1); + filter: FlipV; + -ms-filter: "FlipV"; +} \ No newline at end of file diff --git a/netbox/project-static/materialdesignicons-5.4.55/scss/_functions.scss b/netbox/project-static/materialdesignicons-5.4.55/scss/_functions.scss new file mode 100644 index 0000000000..43518203bd --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/scss/_functions.scss @@ -0,0 +1,20 @@ +@function char($character-code) { + @if function-exists("selector-append") { + @return unquote("\"\\#{$character-code}\""); + } + + @if "\\#{'x'}" == "\\x" { + @return str-slice("\x", 1, 1) + $character-code; + } + @else { + @return #{"\"\\"}#{$character-code + "\""}; + } +} + +@function mdi($name) { + @if map-has-key($mdi-icons, $name) == false { + @warn "Icon #{$name} not found."; + @return ""; + } + @return char(map-get($mdi-icons, $name)); +} \ No newline at end of file diff --git a/netbox/project-static/materialdesignicons-5.4.55/scss/_icons.scss b/netbox/project-static/materialdesignicons-5.4.55/scss/_icons.scss new file mode 100644 index 0000000000..1da1eb7983 --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/scss/_icons.scss @@ -0,0 +1,10 @@ +@each $key, $value in $mdi-icons { + .#{$mdi-css-prefix}-#{$key}::before { + content: char($value); + } +} + +.#{$mdi-css-prefix}-blank::before { + content: "\F68C"; + visibility: hidden; +} \ No newline at end of file diff --git a/netbox/project-static/materialdesignicons-5.4.55/scss/_path.scss b/netbox/project-static/materialdesignicons-5.4.55/scss/_path.scss new file mode 100644 index 0000000000..6dcf3aa080 --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/scss/_path.scss @@ -0,0 +1,10 @@ +@font-face { + font-family: '#{$mdi-font-name}'; + src: url('#{$mdi-font-path}/#{$mdi-filename}-webfont.eot?v=#{$mdi-version}'); + src: url('#{$mdi-font-path}/#{$mdi-filename}-webfont.eot?#iefix&v=#{$mdi-version}') format('embedded-opentype'), + url('#{$mdi-font-path}/#{$mdi-filename}-webfont.woff2?v=#{$mdi-version}') format('woff2'), + url('#{$mdi-font-path}/#{$mdi-filename}-webfont.woff?v=#{$mdi-version}') format('woff'), + url('#{$mdi-font-path}/#{$mdi-filename}-webfont.ttf?v=#{$mdi-version}') format('truetype'); + font-weight: normal; + font-style: normal; +} diff --git a/netbox/project-static/materialdesignicons-5.4.55/scss/_variables.scss b/netbox/project-static/materialdesignicons-5.4.55/scss/_variables.scss new file mode 100644 index 0000000000..2112af1d04 --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/scss/_variables.scss @@ -0,0 +1,5866 @@ +$mdi-filename: "materialdesignicons"; +$mdi-font-name: "Material Design Icons"; +$mdi-font-family: "materialdesignicons"; +$mdi-font-weight: "normal"; +$mdi-font-path: "../fonts" !default; +$mdi-font-size-base: 24px !default; +$mdi-css-prefix: mdi !default; +$mdi-version: "5.8.55" !default; + +$mdi-icons: ( + "ab-testing": F01C9, + "abjad-arabic": F1328, + "abjad-hebrew": F1329, + "abugida-devanagari": F132A, + "abugida-thai": F132B, + "access-point": F0003, + "access-point-check": F1538, + "access-point-minus": F1539, + "access-point-network": F0002, + "access-point-network-off": F0BE1, + "access-point-off": F1511, + "access-point-plus": F153A, + "access-point-remove": F153B, + "account": F0004, + "account-alert": F0005, + "account-alert-outline": F0B50, + "account-arrow-left": F0B51, + "account-arrow-left-outline": F0B52, + "account-arrow-right": F0B53, + "account-arrow-right-outline": F0B54, + "account-box": F0006, + "account-box-multiple": F0934, + "account-box-multiple-outline": F100A, + "account-box-outline": F0007, + "account-cancel": F12DF, + "account-cancel-outline": F12E0, + "account-cash": F1097, + "account-cash-outline": F1098, + "account-check": F0008, + "account-check-outline": F0BE2, + "account-child": F0A89, + "account-child-circle": F0A8A, + "account-child-outline": F10C8, + "account-circle": F0009, + "account-circle-outline": F0B55, + "account-clock": F0B56, + "account-clock-outline": F0B57, + "account-cog": F1370, + "account-cog-outline": F1371, + "account-convert": F000A, + "account-convert-outline": F1301, + "account-cowboy-hat": F0E9B, + "account-details": F0631, + "account-details-outline": F1372, + "account-edit": F06BC, + "account-edit-outline": F0FFB, + "account-group": F0849, + "account-group-outline": F0B58, + "account-hard-hat": F05B5, + "account-heart": F0899, + "account-heart-outline": F0BE3, + "account-key": F000B, + "account-key-outline": F0BE4, + "account-lock": F115E, + "account-lock-outline": F115F, + "account-minus": F000D, + "account-minus-outline": F0AEC, + "account-multiple": F000E, + "account-multiple-check": F08C5, + "account-multiple-check-outline": F11FE, + "account-multiple-minus": F05D3, + "account-multiple-minus-outline": F0BE5, + "account-multiple-outline": F000F, + "account-multiple-plus": F0010, + "account-multiple-plus-outline": F0800, + "account-multiple-remove": F120A, + "account-multiple-remove-outline": F120B, + "account-music": F0803, + "account-music-outline": F0CE9, + "account-network": F0011, + "account-network-outline": F0BE6, + "account-off": F0012, + "account-off-outline": F0BE7, + "account-outline": F0013, + "account-plus": F0014, + "account-plus-outline": F0801, + "account-question": F0B59, + "account-question-outline": F0B5A, + "account-reactivate": F152B, + "account-reactivate-outline": F152C, + "account-remove": F0015, + "account-remove-outline": F0AED, + "account-search": F0016, + "account-search-outline": F0935, + "account-settings": F0630, + "account-settings-outline": F10C9, + "account-star": F0017, + "account-star-outline": F0BE8, + "account-supervisor": F0A8B, + "account-supervisor-circle": F0A8C, + "account-supervisor-circle-outline": F14EC, + "account-supervisor-outline": F112D, + "account-switch": F0019, + "account-switch-outline": F04CB, + "account-tie": F0CE3, + "account-tie-outline": F10CA, + "account-tie-voice": F1308, + "account-tie-voice-off": F130A, + "account-tie-voice-off-outline": F130B, + "account-tie-voice-outline": F1309, + "account-voice": F05CB, + "adjust": F001A, + "adobe": F0936, + "adobe-acrobat": F0F9D, + "air-conditioner": F001B, + "air-filter": F0D43, + "air-horn": F0DAC, + "air-humidifier": F1099, + "air-humidifier-off": F1466, + "air-purifier": F0D44, + "airbag": F0BE9, + "airballoon": F001C, + "airballoon-outline": F100B, + "airplane": F001D, + "airplane-landing": F05D4, + "airplane-off": F001E, + "airplane-takeoff": F05D5, + "airport": F084B, + "alarm": F0020, + "alarm-bell": F078E, + "alarm-check": F0021, + "alarm-light": F078F, + "alarm-light-outline": F0BEA, + "alarm-multiple": F0022, + "alarm-note": F0E71, + "alarm-note-off": F0E72, + "alarm-off": F0023, + "alarm-panel": F15C4, + "alarm-panel-outline": F15C5, + "alarm-plus": F0024, + "alarm-snooze": F068E, + "album": F0025, + "alert": F0026, + "alert-box": F0027, + "alert-box-outline": F0CE4, + "alert-circle": F0028, + "alert-circle-check": F11ED, + "alert-circle-check-outline": F11EE, + "alert-circle-outline": F05D6, + "alert-decagram": F06BD, + "alert-decagram-outline": F0CE5, + "alert-minus": F14BB, + "alert-minus-outline": F14BE, + "alert-octagon": F0029, + "alert-octagon-outline": F0CE6, + "alert-octagram": F0767, + "alert-octagram-outline": F0CE7, + "alert-outline": F002A, + "alert-plus": F14BA, + "alert-plus-outline": F14BD, + "alert-remove": F14BC, + "alert-remove-outline": F14BF, + "alert-rhombus": F11CE, + "alert-rhombus-outline": F11CF, + "alien": F089A, + "alien-outline": F10CB, + "align-horizontal-center": F11C3, + "align-horizontal-left": F11C2, + "align-horizontal-right": F11C4, + "align-vertical-bottom": F11C5, + "align-vertical-center": F11C6, + "align-vertical-top": F11C7, + "all-inclusive": F06BE, + "allergy": F1258, + "alpha": F002B, + "alpha-a": F0AEE, + "alpha-a-box": F0B08, + "alpha-a-box-outline": F0BEB, + "alpha-a-circle": F0BEC, + "alpha-a-circle-outline": F0BED, + "alpha-b": F0AEF, + "alpha-b-box": F0B09, + "alpha-b-box-outline": F0BEE, + "alpha-b-circle": F0BEF, + "alpha-b-circle-outline": F0BF0, + "alpha-c": F0AF0, + "alpha-c-box": F0B0A, + "alpha-c-box-outline": F0BF1, + "alpha-c-circle": F0BF2, + "alpha-c-circle-outline": F0BF3, + "alpha-d": F0AF1, + "alpha-d-box": F0B0B, + "alpha-d-box-outline": F0BF4, + "alpha-d-circle": F0BF5, + "alpha-d-circle-outline": F0BF6, + "alpha-e": F0AF2, + "alpha-e-box": F0B0C, + "alpha-e-box-outline": F0BF7, + "alpha-e-circle": F0BF8, + "alpha-e-circle-outline": F0BF9, + "alpha-f": F0AF3, + "alpha-f-box": F0B0D, + "alpha-f-box-outline": F0BFA, + "alpha-f-circle": F0BFB, + "alpha-f-circle-outline": F0BFC, + "alpha-g": F0AF4, + "alpha-g-box": F0B0E, + "alpha-g-box-outline": F0BFD, + "alpha-g-circle": F0BFE, + "alpha-g-circle-outline": F0BFF, + "alpha-h": F0AF5, + "alpha-h-box": F0B0F, + "alpha-h-box-outline": F0C00, + "alpha-h-circle": F0C01, + "alpha-h-circle-outline": F0C02, + "alpha-i": F0AF6, + "alpha-i-box": F0B10, + "alpha-i-box-outline": F0C03, + "alpha-i-circle": F0C04, + "alpha-i-circle-outline": F0C05, + "alpha-j": F0AF7, + "alpha-j-box": F0B11, + "alpha-j-box-outline": F0C06, + "alpha-j-circle": F0C07, + "alpha-j-circle-outline": F0C08, + "alpha-k": F0AF8, + "alpha-k-box": F0B12, + "alpha-k-box-outline": F0C09, + "alpha-k-circle": F0C0A, + "alpha-k-circle-outline": F0C0B, + "alpha-l": F0AF9, + "alpha-l-box": F0B13, + "alpha-l-box-outline": F0C0C, + "alpha-l-circle": F0C0D, + "alpha-l-circle-outline": F0C0E, + "alpha-m": F0AFA, + "alpha-m-box": F0B14, + "alpha-m-box-outline": F0C0F, + "alpha-m-circle": F0C10, + "alpha-m-circle-outline": F0C11, + "alpha-n": F0AFB, + "alpha-n-box": F0B15, + "alpha-n-box-outline": F0C12, + "alpha-n-circle": F0C13, + "alpha-n-circle-outline": F0C14, + "alpha-o": F0AFC, + "alpha-o-box": F0B16, + "alpha-o-box-outline": F0C15, + "alpha-o-circle": F0C16, + "alpha-o-circle-outline": F0C17, + "alpha-p": F0AFD, + "alpha-p-box": F0B17, + "alpha-p-box-outline": F0C18, + "alpha-p-circle": F0C19, + "alpha-p-circle-outline": F0C1A, + "alpha-q": F0AFE, + "alpha-q-box": F0B18, + "alpha-q-box-outline": F0C1B, + "alpha-q-circle": F0C1C, + "alpha-q-circle-outline": F0C1D, + "alpha-r": F0AFF, + "alpha-r-box": F0B19, + "alpha-r-box-outline": F0C1E, + "alpha-r-circle": F0C1F, + "alpha-r-circle-outline": F0C20, + "alpha-s": F0B00, + "alpha-s-box": F0B1A, + "alpha-s-box-outline": F0C21, + "alpha-s-circle": F0C22, + "alpha-s-circle-outline": F0C23, + "alpha-t": F0B01, + "alpha-t-box": F0B1B, + "alpha-t-box-outline": F0C24, + "alpha-t-circle": F0C25, + "alpha-t-circle-outline": F0C26, + "alpha-u": F0B02, + "alpha-u-box": F0B1C, + "alpha-u-box-outline": F0C27, + "alpha-u-circle": F0C28, + "alpha-u-circle-outline": F0C29, + "alpha-v": F0B03, + "alpha-v-box": F0B1D, + "alpha-v-box-outline": F0C2A, + "alpha-v-circle": F0C2B, + "alpha-v-circle-outline": F0C2C, + "alpha-w": F0B04, + "alpha-w-box": F0B1E, + "alpha-w-box-outline": F0C2D, + "alpha-w-circle": F0C2E, + "alpha-w-circle-outline": F0C2F, + "alpha-x": F0B05, + "alpha-x-box": F0B1F, + "alpha-x-box-outline": F0C30, + "alpha-x-circle": F0C31, + "alpha-x-circle-outline": F0C32, + "alpha-y": F0B06, + "alpha-y-box": F0B20, + "alpha-y-box-outline": F0C33, + "alpha-y-circle": F0C34, + "alpha-y-circle-outline": F0C35, + "alpha-z": F0B07, + "alpha-z-box": F0B21, + "alpha-z-box-outline": F0C36, + "alpha-z-circle": F0C37, + "alpha-z-circle-outline": F0C38, + "alphabet-aurebesh": F132C, + "alphabet-cyrillic": F132D, + "alphabet-greek": F132E, + "alphabet-latin": F132F, + "alphabet-piqad": F1330, + "alphabet-tengwar": F1337, + "alphabetical": F002C, + "alphabetical-off": F100C, + "alphabetical-variant": F100D, + "alphabetical-variant-off": F100E, + "altimeter": F05D7, + "amazon": F002D, + "amazon-alexa": F08C6, + "ambulance": F002F, + "ammunition": F0CE8, + "ampersand": F0A8D, + "amplifier": F0030, + "amplifier-off": F11B5, + "anchor": F0031, + "android": F0032, + "android-auto": F0A8E, + "android-debug-bridge": F0033, + "android-messages": F0D45, + "android-studio": F0034, + "angle-acute": F0937, + "angle-obtuse": F0938, + "angle-right": F0939, + "angular": F06B2, + "angularjs": F06BF, + "animation": F05D8, + "animation-outline": F0A8F, + "animation-play": F093A, + "animation-play-outline": F0A90, + "ansible": F109A, + "antenna": F1119, + "anvil": F089B, + "apache-kafka": F100F, + "api": F109B, + "api-off": F1257, + "apple": F0035, + "apple-airplay": F001F, + "apple-finder": F0036, + "apple-icloud": F0038, + "apple-ios": F0037, + "apple-keyboard-caps": F0632, + "apple-keyboard-command": F0633, + "apple-keyboard-control": F0634, + "apple-keyboard-option": F0635, + "apple-keyboard-shift": F0636, + "apple-safari": F0039, + "application": F0614, + "application-cog": F1577, + "application-export": F0DAD, + "application-import": F0DAE, + "application-settings": F1555, + "approximately-equal": F0F9E, + "approximately-equal-box": F0F9F, + "apps": F003B, + "apps-box": F0D46, + "arch": F08C7, + "archive": F003C, + "archive-alert": F14FD, + "archive-alert-outline": F14FE, + "archive-arrow-down": F1259, + "archive-arrow-down-outline": F125A, + "archive-arrow-up": F125B, + "archive-arrow-up-outline": F125C, + "archive-outline": F120E, + "arm-flex": F0FD7, + "arm-flex-outline": F0FD6, + "arrange-bring-forward": F003D, + "arrange-bring-to-front": F003E, + "arrange-send-backward": F003F, + "arrange-send-to-back": F0040, + "arrow-all": F0041, + "arrow-bottom-left": F0042, + "arrow-bottom-left-bold-outline": F09B7, + "arrow-bottom-left-thick": F09B8, + "arrow-bottom-left-thin-circle-outline": F1596, + "arrow-bottom-right": F0043, + "arrow-bottom-right-bold-outline": F09B9, + "arrow-bottom-right-thick": F09BA, + "arrow-bottom-right-thin-circle-outline": F1595, + "arrow-collapse": F0615, + "arrow-collapse-all": F0044, + "arrow-collapse-down": F0792, + "arrow-collapse-horizontal": F084C, + "arrow-collapse-left": F0793, + "arrow-collapse-right": F0794, + "arrow-collapse-up": F0795, + "arrow-collapse-vertical": F084D, + "arrow-decision": F09BB, + "arrow-decision-auto": F09BC, + "arrow-decision-auto-outline": F09BD, + "arrow-decision-outline": F09BE, + "arrow-down": F0045, + "arrow-down-bold": F072E, + "arrow-down-bold-box": F072F, + "arrow-down-bold-box-outline": F0730, + "arrow-down-bold-circle": F0047, + "arrow-down-bold-circle-outline": F0048, + "arrow-down-bold-hexagon-outline": F0049, + "arrow-down-bold-outline": F09BF, + "arrow-down-box": F06C0, + "arrow-down-circle": F0CDB, + "arrow-down-circle-outline": F0CDC, + "arrow-down-drop-circle": F004A, + "arrow-down-drop-circle-outline": F004B, + "arrow-down-thick": F0046, + "arrow-down-thin-circle-outline": F1599, + "arrow-expand": F0616, + "arrow-expand-all": F004C, + "arrow-expand-down": F0796, + "arrow-expand-horizontal": F084E, + "arrow-expand-left": F0797, + "arrow-expand-right": F0798, + "arrow-expand-up": F0799, + "arrow-expand-vertical": F084F, + "arrow-horizontal-lock": F115B, + "arrow-left": F004D, + "arrow-left-bold": F0731, + "arrow-left-bold-box": F0732, + "arrow-left-bold-box-outline": F0733, + "arrow-left-bold-circle": F004F, + "arrow-left-bold-circle-outline": F0050, + "arrow-left-bold-hexagon-outline": F0051, + "arrow-left-bold-outline": F09C0, + "arrow-left-box": F06C1, + "arrow-left-circle": F0CDD, + "arrow-left-circle-outline": F0CDE, + "arrow-left-drop-circle": F0052, + "arrow-left-drop-circle-outline": F0053, + "arrow-left-right": F0E73, + "arrow-left-right-bold": F0E74, + "arrow-left-right-bold-outline": F09C1, + "arrow-left-thick": F004E, + "arrow-left-thin-circle-outline": F159A, + "arrow-right": F0054, + "arrow-right-bold": F0734, + "arrow-right-bold-box": F0735, + "arrow-right-bold-box-outline": F0736, + "arrow-right-bold-circle": F0056, + "arrow-right-bold-circle-outline": F0057, + "arrow-right-bold-hexagon-outline": F0058, + "arrow-right-bold-outline": F09C2, + "arrow-right-box": F06C2, + "arrow-right-circle": F0CDF, + "arrow-right-circle-outline": F0CE0, + "arrow-right-drop-circle": F0059, + "arrow-right-drop-circle-outline": F005A, + "arrow-right-thick": F0055, + "arrow-right-thin-circle-outline": F1598, + "arrow-split-horizontal": F093B, + "arrow-split-vertical": F093C, + "arrow-top-left": F005B, + "arrow-top-left-bold-outline": F09C3, + "arrow-top-left-bottom-right": F0E75, + "arrow-top-left-bottom-right-bold": F0E76, + "arrow-top-left-thick": F09C4, + "arrow-top-left-thin-circle-outline": F1593, + "arrow-top-right": F005C, + "arrow-top-right-bold-outline": F09C5, + "arrow-top-right-bottom-left": F0E77, + "arrow-top-right-bottom-left-bold": F0E78, + "arrow-top-right-thick": F09C6, + "arrow-top-right-thin-circle-outline": F1594, + "arrow-up": F005D, + "arrow-up-bold": F0737, + "arrow-up-bold-box": F0738, + "arrow-up-bold-box-outline": F0739, + "arrow-up-bold-circle": F005F, + "arrow-up-bold-circle-outline": F0060, + "arrow-up-bold-hexagon-outline": F0061, + "arrow-up-bold-outline": F09C7, + "arrow-up-box": F06C3, + "arrow-up-circle": F0CE1, + "arrow-up-circle-outline": F0CE2, + "arrow-up-down": F0E79, + "arrow-up-down-bold": F0E7A, + "arrow-up-down-bold-outline": F09C8, + "arrow-up-drop-circle": F0062, + "arrow-up-drop-circle-outline": F0063, + "arrow-up-thick": F005E, + "arrow-up-thin-circle-outline": F1597, + "arrow-vertical-lock": F115C, + "artstation": F0B5B, + "aspect-ratio": F0A24, + "assistant": F0064, + "asterisk": F06C4, + "at": F0065, + "atlassian": F0804, + "atm": F0D47, + "atom": F0768, + "atom-variant": F0E7B, + "attachment": F0066, + "audio-video": F093D, + "audio-video-off": F11B6, + "augmented-reality": F0850, + "auto-download": F137E, + "auto-fix": F0068, + "auto-upload": F0069, + "autorenew": F006A, + "av-timer": F006B, + "aws": F0E0F, + "axe": F08C8, + "axis": F0D48, + "axis-arrow": F0D49, + "axis-arrow-info": F140E, + "axis-arrow-lock": F0D4A, + "axis-lock": F0D4B, + "axis-x-arrow": F0D4C, + "axis-x-arrow-lock": F0D4D, + "axis-x-rotate-clockwise": F0D4E, + "axis-x-rotate-counterclockwise": F0D4F, + "axis-x-y-arrow-lock": F0D50, + "axis-y-arrow": F0D51, + "axis-y-arrow-lock": F0D52, + "axis-y-rotate-clockwise": F0D53, + "axis-y-rotate-counterclockwise": F0D54, + "axis-z-arrow": F0D55, + "axis-z-arrow-lock": F0D56, + "axis-z-rotate-clockwise": F0D57, + "axis-z-rotate-counterclockwise": F0D58, + "babel": F0A25, + "baby": F006C, + "baby-bottle": F0F39, + "baby-bottle-outline": F0F3A, + "baby-buggy": F13E0, + "baby-carriage": F068F, + "baby-carriage-off": F0FA0, + "baby-face": F0E7C, + "baby-face-outline": F0E7D, + "backburger": F006D, + "backspace": F006E, + "backspace-outline": F0B5C, + "backspace-reverse": F0E7E, + "backspace-reverse-outline": F0E7F, + "backup-restore": F006F, + "bacteria": F0ED5, + "bacteria-outline": F0ED6, + "badge-account": F0DA7, + "badge-account-alert": F0DA8, + "badge-account-alert-outline": F0DA9, + "badge-account-horizontal": F0E0D, + "badge-account-horizontal-outline": F0E0E, + "badge-account-outline": F0DAA, + "badminton": F0851, + "bag-carry-on": F0F3B, + "bag-carry-on-check": F0D65, + "bag-carry-on-off": F0F3C, + "bag-checked": F0F3D, + "bag-personal": F0E10, + "bag-personal-off": F0E11, + "bag-personal-off-outline": F0E12, + "bag-personal-outline": F0E13, + "bag-suitcase": F158B, + "bag-suitcase-off": F158D, + "bag-suitcase-off-outline": F158E, + "bag-suitcase-outline": F158C, + "baguette": F0F3E, + "balloon": F0A26, + "ballot": F09C9, + "ballot-outline": F09CA, + "ballot-recount": F0C39, + "ballot-recount-outline": F0C3A, + "bandage": F0DAF, + "bandcamp": F0675, + "bank": F0070, + "bank-check": F1655, + "bank-minus": F0DB0, + "bank-off": F1656, + "bank-off-outline": F1657, + "bank-outline": F0E80, + "bank-plus": F0DB1, + "bank-remove": F0DB2, + "bank-transfer": F0A27, + "bank-transfer-in": F0A28, + "bank-transfer-out": F0A29, + "barcode": F0071, + "barcode-off": F1236, + "barcode-scan": F0072, + "barley": F0073, + "barley-off": F0B5D, + "barn": F0B5E, + "barrel": F0074, + "baseball": F0852, + "baseball-bat": F0853, + "baseball-diamond": F15EC, + "baseball-diamond-outline": F15ED, + "bash": F1183, + "basket": F0076, + "basket-fill": F0077, + "basket-minus": F1523, + "basket-minus-outline": F1524, + "basket-off": F1525, + "basket-off-outline": F1526, + "basket-outline": F1181, + "basket-plus": F1527, + "basket-plus-outline": F1528, + "basket-remove": F1529, + "basket-remove-outline": F152A, + "basket-unfill": F0078, + "basketball": F0806, + "basketball-hoop": F0C3B, + "basketball-hoop-outline": F0C3C, + "bat": F0B5F, + "battery": F0079, + "battery-10": F007A, + "battery-10-bluetooth": F093E, + "battery-20": F007B, + "battery-20-bluetooth": F093F, + "battery-30": F007C, + "battery-30-bluetooth": F0940, + "battery-40": F007D, + "battery-40-bluetooth": F0941, + "battery-50": F007E, + "battery-50-bluetooth": F0942, + "battery-60": F007F, + "battery-60-bluetooth": F0943, + "battery-70": F0080, + "battery-70-bluetooth": F0944, + "battery-80": F0081, + "battery-80-bluetooth": F0945, + "battery-90": F0082, + "battery-90-bluetooth": F0946, + "battery-alert": F0083, + "battery-alert-bluetooth": F0947, + "battery-alert-variant": F10CC, + "battery-alert-variant-outline": F10CD, + "battery-bluetooth": F0948, + "battery-bluetooth-variant": F0949, + "battery-charging": F0084, + "battery-charging-10": F089C, + "battery-charging-100": F0085, + "battery-charging-20": F0086, + "battery-charging-30": F0087, + "battery-charging-40": F0088, + "battery-charging-50": F089D, + "battery-charging-60": F0089, + "battery-charging-70": F089E, + "battery-charging-80": F008A, + "battery-charging-90": F008B, + "battery-charging-high": F12A6, + "battery-charging-low": F12A4, + "battery-charging-medium": F12A5, + "battery-charging-outline": F089F, + "battery-charging-wireless": F0807, + "battery-charging-wireless-10": F0808, + "battery-charging-wireless-20": F0809, + "battery-charging-wireless-30": F080A, + "battery-charging-wireless-40": F080B, + "battery-charging-wireless-50": F080C, + "battery-charging-wireless-60": F080D, + "battery-charging-wireless-70": F080E, + "battery-charging-wireless-80": F080F, + "battery-charging-wireless-90": F0810, + "battery-charging-wireless-alert": F0811, + "battery-charging-wireless-outline": F0812, + "battery-heart": F120F, + "battery-heart-outline": F1210, + "battery-heart-variant": F1211, + "battery-high": F12A3, + "battery-low": F12A1, + "battery-medium": F12A2, + "battery-minus": F008C, + "battery-negative": F008D, + "battery-off": F125D, + "battery-off-outline": F125E, + "battery-outline": F008E, + "battery-plus": F008F, + "battery-positive": F0090, + "battery-unknown": F0091, + "battery-unknown-bluetooth": F094A, + "battlenet": F0B60, + "beach": F0092, + "beaker": F0CEA, + "beaker-alert": F1229, + "beaker-alert-outline": F122A, + "beaker-check": F122B, + "beaker-check-outline": F122C, + "beaker-minus": F122D, + "beaker-minus-outline": F122E, + "beaker-outline": F0690, + "beaker-plus": F122F, + "beaker-plus-outline": F1230, + "beaker-question": F1231, + "beaker-question-outline": F1232, + "beaker-remove": F1233, + "beaker-remove-outline": F1234, + "bed": F02E3, + "bed-double": F0FD4, + "bed-double-outline": F0FD3, + "bed-empty": F08A0, + "bed-king": F0FD2, + "bed-king-outline": F0FD1, + "bed-outline": F0099, + "bed-queen": F0FD0, + "bed-queen-outline": F0FDB, + "bed-single": F106D, + "bed-single-outline": F106E, + "bee": F0FA1, + "bee-flower": F0FA2, + "beehive-off-outline": F13ED, + "beehive-outline": F10CE, + "beekeeper": F14E2, + "beer": F0098, + "beer-outline": F130C, + "bell": F009A, + "bell-alert": F0D59, + "bell-alert-outline": F0E81, + "bell-cancel": F13E7, + "bell-cancel-outline": F13E8, + "bell-check": F11E5, + "bell-check-outline": F11E6, + "bell-circle": F0D5A, + "bell-circle-outline": F0D5B, + "bell-minus": F13E9, + "bell-minus-outline": F13EA, + "bell-off": F009B, + "bell-off-outline": F0A91, + "bell-outline": F009C, + "bell-plus": F009D, + "bell-plus-outline": F0A92, + "bell-remove": F13EB, + "bell-remove-outline": F13EC, + "bell-ring": F009E, + "bell-ring-outline": F009F, + "bell-sleep": F00A0, + "bell-sleep-outline": F0A93, + "beta": F00A1, + "betamax": F09CB, + "biathlon": F0E14, + "bicycle": F109C, + "bicycle-basket": F1235, + "bicycle-electric": F15B4, + "bicycle-penny-farthing": F15E9, + "bike": F00A3, + "bike-fast": F111F, + "billboard": F1010, + "billiards": F0B61, + "billiards-rack": F0B62, + "binoculars": F00A5, + "bio": F00A6, + "biohazard": F00A7, + "bird": F15C6, + "bitbucket": F00A8, + "bitcoin": F0813, + "black-mesa": F00A9, + "blender": F0CEB, + "blender-software": F00AB, + "blinds": F00AC, + "blinds-open": F1011, + "block-helper": F00AD, + "blogger": F00AE, + "blood-bag": F0CEC, + "bluetooth": F00AF, + "bluetooth-audio": F00B0, + "bluetooth-connect": F00B1, + "bluetooth-off": F00B2, + "bluetooth-settings": F00B3, + "bluetooth-transfer": F00B4, + "blur": F00B5, + "blur-linear": F00B6, + "blur-off": F00B7, + "blur-radial": F00B8, + "bolnisi-cross": F0CED, + "bolt": F0DB3, + "bomb": F0691, + "bomb-off": F06C5, + "bone": F00B9, + "book": F00BA, + "book-account": F13AD, + "book-account-outline": F13AE, + "book-alert": F167C, + "book-alert-outline": F167D, + "book-alphabet": F061D, + "book-arrow-down": F167E, + "book-arrow-down-outline": F167F, + "book-arrow-left": F1680, + "book-arrow-left-outline": F1681, + "book-arrow-right": F1682, + "book-arrow-right-outline": F1683, + "book-arrow-up": F1684, + "book-arrow-up-outline": F1685, + "book-cancel": F1686, + "book-cancel-outline": F1687, + "book-check": F14F3, + "book-check-outline": F14F4, + "book-clock": F1688, + "book-clock-outline": F1689, + "book-cog": F168A, + "book-cog-outline": F168B, + "book-cross": F00A2, + "book-edit": F168C, + "book-edit-outline": F168D, + "book-education": F16C9, + "book-education-outline": F16CA, + "book-information-variant": F106F, + "book-lock": F079A, + "book-lock-open": F079B, + "book-lock-open-outline": F168E, + "book-lock-outline": F168F, + "book-marker": F1690, + "book-marker-outline": F1691, + "book-minus": F05D9, + "book-minus-multiple": F0A94, + "book-minus-multiple-outline": F090B, + "book-minus-outline": F1692, + "book-multiple": F00BB, + "book-multiple-outline": F0436, + "book-music": F0067, + "book-music-outline": F1693, + "book-off": F1694, + "book-off-outline": F1695, + "book-open": F00BD, + "book-open-blank-variant": F00BE, + "book-open-outline": F0B63, + "book-open-page-variant": F05DA, + "book-open-page-variant-outline": F15D6, + "book-open-variant": F14F7, + "book-outline": F0B64, + "book-play": F0E82, + "book-play-outline": F0E83, + "book-plus": F05DB, + "book-plus-multiple": F0A95, + "book-plus-multiple-outline": F0ADE, + "book-plus-outline": F1696, + "book-refresh": F1697, + "book-refresh-outline": F1698, + "book-remove": F0A97, + "book-remove-multiple": F0A96, + "book-remove-multiple-outline": F04CA, + "book-remove-outline": F1699, + "book-search": F0E84, + "book-search-outline": F0E85, + "book-settings": F169A, + "book-settings-outline": F169B, + "book-sync": F169C, + "book-sync-outline": F16C8, + "book-variant": F00BF, + "book-variant-multiple": F00BC, + "bookmark": F00C0, + "bookmark-check": F00C1, + "bookmark-check-outline": F137B, + "bookmark-minus": F09CC, + "bookmark-minus-outline": F09CD, + "bookmark-multiple": F0E15, + "bookmark-multiple-outline": F0E16, + "bookmark-music": F00C2, + "bookmark-music-outline": F1379, + "bookmark-off": F09CE, + "bookmark-off-outline": F09CF, + "bookmark-outline": F00C3, + "bookmark-plus": F00C5, + "bookmark-plus-outline": F00C4, + "bookmark-remove": F00C6, + "bookmark-remove-outline": F137A, + "bookshelf": F125F, + "boom-gate": F0E86, + "boom-gate-alert": F0E87, + "boom-gate-alert-outline": F0E88, + "boom-gate-down": F0E89, + "boom-gate-down-outline": F0E8A, + "boom-gate-outline": F0E8B, + "boom-gate-up": F0E8C, + "boom-gate-up-outline": F0E8D, + "boombox": F05DC, + "boomerang": F10CF, + "bootstrap": F06C6, + "border-all": F00C7, + "border-all-variant": F08A1, + "border-bottom": F00C8, + "border-bottom-variant": F08A2, + "border-color": F00C9, + "border-horizontal": F00CA, + "border-inside": F00CB, + "border-left": F00CC, + "border-left-variant": F08A3, + "border-none": F00CD, + "border-none-variant": F08A4, + "border-outside": F00CE, + "border-right": F00CF, + "border-right-variant": F08A5, + "border-style": F00D0, + "border-top": F00D1, + "border-top-variant": F08A6, + "border-vertical": F00D2, + "bottle-soda": F1070, + "bottle-soda-classic": F1071, + "bottle-soda-classic-outline": F1363, + "bottle-soda-outline": F1072, + "bottle-tonic": F112E, + "bottle-tonic-outline": F112F, + "bottle-tonic-plus": F1130, + "bottle-tonic-plus-outline": F1131, + "bottle-tonic-skull": F1132, + "bottle-tonic-skull-outline": F1133, + "bottle-wine": F0854, + "bottle-wine-outline": F1310, + "bow-tie": F0678, + "bowl": F028E, + "bowl-mix": F0617, + "bowl-mix-outline": F02E4, + "bowl-outline": F02A9, + "bowling": F00D3, + "box": F00D4, + "box-cutter": F00D5, + "box-cutter-off": F0B4A, + "box-shadow": F0637, + "boxing-glove": F0B65, + "braille": F09D0, + "brain": F09D1, + "bread-slice": F0CEE, + "bread-slice-outline": F0CEF, + "bridge": F0618, + "briefcase": F00D6, + "briefcase-account": F0CF0, + "briefcase-account-outline": F0CF1, + "briefcase-check": F00D7, + "briefcase-check-outline": F131E, + "briefcase-clock": F10D0, + "briefcase-clock-outline": F10D1, + "briefcase-download": F00D8, + "briefcase-download-outline": F0C3D, + "briefcase-edit": F0A98, + "briefcase-edit-outline": F0C3E, + "briefcase-minus": F0A2A, + "briefcase-minus-outline": F0C3F, + "briefcase-off": F1658, + "briefcase-off-outline": F1659, + "briefcase-outline": F0814, + "briefcase-plus": F0A2B, + "briefcase-plus-outline": F0C40, + "briefcase-remove": F0A2C, + "briefcase-remove-outline": F0C41, + "briefcase-search": F0A2D, + "briefcase-search-outline": F0C42, + "briefcase-upload": F00D9, + "briefcase-upload-outline": F0C43, + "briefcase-variant": F1494, + "briefcase-variant-off": F165A, + "briefcase-variant-off-outline": F165B, + "briefcase-variant-outline": F1495, + "brightness-1": F00DA, + "brightness-2": F00DB, + "brightness-3": F00DC, + "brightness-4": F00DD, + "brightness-5": F00DE, + "brightness-6": F00DF, + "brightness-7": F00E0, + "brightness-auto": F00E1, + "brightness-percent": F0CF2, + "broom": F00E2, + "brush": F00E3, + "bucket": F1415, + "bucket-outline": F1416, + "buddhism": F094B, + "buffer": F0619, + "buffet": F0578, + "bug": F00E4, + "bug-check": F0A2E, + "bug-check-outline": F0A2F, + "bug-outline": F0A30, + "bugle": F0DB4, + "bulldozer": F0B22, + "bullet": F0CF3, + "bulletin-board": F00E5, + "bullhorn": F00E6, + "bullhorn-outline": F0B23, + "bullseye": F05DD, + "bullseye-arrow": F08C9, + "bulma": F12E7, + "bunk-bed": F1302, + "bunk-bed-outline": F0097, + "bus": F00E7, + "bus-alert": F0A99, + "bus-articulated-end": F079C, + "bus-articulated-front": F079D, + "bus-clock": F08CA, + "bus-double-decker": F079E, + "bus-marker": F1212, + "bus-multiple": F0F3F, + "bus-school": F079F, + "bus-side": F07A0, + "bus-stop": F1012, + "bus-stop-covered": F1013, + "bus-stop-uncovered": F1014, + "butterfly": F1589, + "butterfly-outline": F158A, + "cable-data": F1394, + "cached": F00E8, + "cactus": F0DB5, + "cake": F00E9, + "cake-layered": F00EA, + "cake-variant": F00EB, + "calculator": F00EC, + "calculator-variant": F0A9A, + "calculator-variant-outline": F15A6, + "calendar": F00ED, + "calendar-account": F0ED7, + "calendar-account-outline": F0ED8, + "calendar-alert": F0A31, + "calendar-arrow-left": F1134, + "calendar-arrow-right": F1135, + "calendar-blank": F00EE, + "calendar-blank-multiple": F1073, + "calendar-blank-outline": F0B66, + "calendar-check": F00EF, + "calendar-check-outline": F0C44, + "calendar-clock": F00F0, + "calendar-cursor": F157B, + "calendar-edit": F08A7, + "calendar-end": F166C, + "calendar-export": F0B24, + "calendar-heart": F09D2, + "calendar-import": F0B25, + "calendar-lock": F1641, + "calendar-lock-outline": F1642, + "calendar-minus": F0D5C, + "calendar-month": F0E17, + "calendar-month-outline": F0E18, + "calendar-multiple": F00F1, + "calendar-multiple-check": F00F2, + "calendar-multiselect": F0A32, + "calendar-outline": F0B67, + "calendar-plus": F00F3, + "calendar-question": F0692, + "calendar-range": F0679, + "calendar-range-outline": F0B68, + "calendar-refresh": F01E1, + "calendar-refresh-outline": F0203, + "calendar-remove": F00F4, + "calendar-remove-outline": F0C45, + "calendar-search": F094C, + "calendar-star": F09D3, + "calendar-start": F166D, + "calendar-sync": F0E8E, + "calendar-sync-outline": F0E8F, + "calendar-text": F00F5, + "calendar-text-outline": F0C46, + "calendar-today": F00F6, + "calendar-week": F0A33, + "calendar-week-begin": F0A34, + "calendar-weekend": F0ED9, + "calendar-weekend-outline": F0EDA, + "call-made": F00F7, + "call-merge": F00F8, + "call-missed": F00F9, + "call-received": F00FA, + "call-split": F00FB, + "camcorder": F00FC, + "camcorder-off": F00FF, + "camera": F0100, + "camera-account": F08CB, + "camera-burst": F0693, + "camera-control": F0B69, + "camera-enhance": F0101, + "camera-enhance-outline": F0B6A, + "camera-flip": F15D9, + "camera-flip-outline": F15DA, + "camera-front": F0102, + "camera-front-variant": F0103, + "camera-gopro": F07A1, + "camera-image": F08CC, + "camera-iris": F0104, + "camera-metering-center": F07A2, + "camera-metering-matrix": F07A3, + "camera-metering-partial": F07A4, + "camera-metering-spot": F07A5, + "camera-off": F05DF, + "camera-outline": F0D5D, + "camera-party-mode": F0105, + "camera-plus": F0EDB, + "camera-plus-outline": F0EDC, + "camera-rear": F0106, + "camera-rear-variant": F0107, + "camera-retake": F0E19, + "camera-retake-outline": F0E1A, + "camera-switch": F0108, + "camera-switch-outline": F084A, + "camera-timer": F0109, + "camera-wireless": F0DB6, + "camera-wireless-outline": F0DB7, + "campfire": F0EDD, + "cancel": F073A, + "candle": F05E2, + "candycane": F010A, + "cannabis": F07A6, + "cannabis-off": F166E, + "caps-lock": F0A9B, + "car": F010B, + "car-2-plus": F1015, + "car-3-plus": F1016, + "car-arrow-left": F13B2, + "car-arrow-right": F13B3, + "car-back": F0E1B, + "car-battery": F010C, + "car-brake-abs": F0C47, + "car-brake-alert": F0C48, + "car-brake-hold": F0D5E, + "car-brake-parking": F0D5F, + "car-brake-retarder": F1017, + "car-child-seat": F0FA3, + "car-clutch": F1018, + "car-cog": F13CC, + "car-connected": F010D, + "car-convertible": F07A7, + "car-coolant-level": F1019, + "car-cruise-control": F0D60, + "car-defrost-front": F0D61, + "car-defrost-rear": F0D62, + "car-door": F0B6B, + "car-door-lock": F109D, + "car-electric": F0B6C, + "car-electric-outline": F15B5, + "car-emergency": F160F, + "car-esp": F0C49, + "car-estate": F07A8, + "car-hatchback": F07A9, + "car-info": F11BE, + "car-key": F0B6D, + "car-lifted-pickup": F152D, + "car-light-dimmed": F0C4A, + "car-light-fog": F0C4B, + "car-light-high": F0C4C, + "car-limousine": F08CD, + "car-multiple": F0B6E, + "car-off": F0E1C, + "car-outline": F14ED, + "car-parking-lights": F0D63, + "car-pickup": F07AA, + "car-seat": F0FA4, + "car-seat-cooler": F0FA5, + "car-seat-heater": F0FA6, + "car-settings": F13CD, + "car-shift-pattern": F0F40, + "car-side": F07AB, + "car-sports": F07AC, + "car-tire-alert": F0C4D, + "car-traction-control": F0D64, + "car-turbocharger": F101A, + "car-wash": F010E, + "car-windshield": F101B, + "car-windshield-outline": F101C, + "carabiner": F14C0, + "caravan": F07AD, + "card": F0B6F, + "card-account-details": F05D2, + "card-account-details-outline": F0DAB, + "card-account-details-star": F02A3, + "card-account-details-star-outline": F06DB, + "card-account-mail": F018E, + "card-account-mail-outline": F0E98, + "card-account-phone": F0E99, + "card-account-phone-outline": F0E9A, + "card-bulleted": F0B70, + "card-bulleted-off": F0B71, + "card-bulleted-off-outline": F0B72, + "card-bulleted-outline": F0B73, + "card-bulleted-settings": F0B74, + "card-bulleted-settings-outline": F0B75, + "card-minus": F1600, + "card-minus-outline": F1601, + "card-off": F1602, + "card-off-outline": F1603, + "card-outline": F0B76, + "card-plus": F11FF, + "card-plus-outline": F1200, + "card-remove": F1604, + "card-remove-outline": F1605, + "card-search": F1074, + "card-search-outline": F1075, + "card-text": F0B77, + "card-text-outline": F0B78, + "cards": F0638, + "cards-club": F08CE, + "cards-diamond": F08CF, + "cards-diamond-outline": F101D, + "cards-heart": F08D0, + "cards-outline": F0639, + "cards-playing-outline": F063A, + "cards-spade": F08D1, + "cards-variant": F06C7, + "carrot": F010F, + "cart": F0110, + "cart-arrow-down": F0D66, + "cart-arrow-right": F0C4E, + "cart-arrow-up": F0D67, + "cart-check": F15EA, + "cart-minus": F0D68, + "cart-off": F066B, + "cart-outline": F0111, + "cart-plus": F0112, + "cart-remove": F0D69, + "cart-variant": F15EB, + "case-sensitive-alt": F0113, + "cash": F0114, + "cash-100": F0115, + "cash-check": F14EE, + "cash-lock": F14EA, + "cash-lock-open": F14EB, + "cash-marker": F0DB8, + "cash-minus": F1260, + "cash-multiple": F0116, + "cash-plus": F1261, + "cash-refund": F0A9C, + "cash-register": F0CF4, + "cash-remove": F1262, + "cash-usd": F1176, + "cash-usd-outline": F0117, + "cassette": F09D4, + "cast": F0118, + "cast-audio": F101E, + "cast-connected": F0119, + "cast-education": F0E1D, + "cast-off": F078A, + "castle": F011A, + "cat": F011B, + "cctv": F07AE, + "ceiling-light": F0769, + "cellphone": F011C, + "cellphone-android": F011D, + "cellphone-arrow-down": F09D5, + "cellphone-basic": F011E, + "cellphone-charging": F1397, + "cellphone-cog": F0951, + "cellphone-dock": F011F, + "cellphone-erase": F094D, + "cellphone-information": F0F41, + "cellphone-iphone": F0120, + "cellphone-key": F094E, + "cellphone-link": F0121, + "cellphone-link-off": F0122, + "cellphone-lock": F094F, + "cellphone-message": F08D3, + "cellphone-message-off": F10D2, + "cellphone-nfc": F0E90, + "cellphone-nfc-off": F12D8, + "cellphone-off": F0950, + "cellphone-play": F101F, + "cellphone-screenshot": F0A35, + "cellphone-settings": F0123, + "cellphone-sound": F0952, + "cellphone-text": F08D2, + "cellphone-wireless": F0815, + "celtic-cross": F0CF5, + "centos": F111A, + "certificate": F0124, + "certificate-outline": F1188, + "chair-rolling": F0F48, + "chair-school": F0125, + "charity": F0C4F, + "chart-arc": F0126, + "chart-areaspline": F0127, + "chart-areaspline-variant": F0E91, + "chart-bar": F0128, + "chart-bar-stacked": F076A, + "chart-bell-curve": F0C50, + "chart-bell-curve-cumulative": F0FA7, + "chart-box": F154D, + "chart-box-outline": F154E, + "chart-box-plus-outline": F154F, + "chart-bubble": F05E3, + "chart-donut": F07AF, + "chart-donut-variant": F07B0, + "chart-gantt": F066C, + "chart-histogram": F0129, + "chart-line": F012A, + "chart-line-stacked": F076B, + "chart-line-variant": F07B1, + "chart-multiline": F08D4, + "chart-multiple": F1213, + "chart-pie": F012B, + "chart-ppf": F1380, + "chart-sankey": F11DF, + "chart-sankey-variant": F11E0, + "chart-scatter-plot": F0E92, + "chart-scatter-plot-hexbin": F066D, + "chart-timeline": F066E, + "chart-timeline-variant": F0E93, + "chart-timeline-variant-shimmer": F15B6, + "chart-tree": F0E94, + "chat": F0B79, + "chat-alert": F0B7A, + "chat-alert-outline": F12C9, + "chat-minus": F1410, + "chat-minus-outline": F1413, + "chat-outline": F0EDE, + "chat-plus": F140F, + "chat-plus-outline": F1412, + "chat-processing": F0B7B, + "chat-processing-outline": F12CA, + "chat-remove": F1411, + "chat-remove-outline": F1414, + "chat-sleep": F12D1, + "chat-sleep-outline": F12D2, + "check": F012C, + "check-all": F012D, + "check-bold": F0E1E, + "check-box-multiple-outline": F0C51, + "check-box-outline": F0C52, + "check-circle": F05E0, + "check-circle-outline": F05E1, + "check-decagram": F0791, + "check-network": F0C53, + "check-network-outline": F0C54, + "check-outline": F0855, + "check-underline": F0E1F, + "check-underline-circle": F0E20, + "check-underline-circle-outline": F0E21, + "checkbook": F0A9D, + "checkbox-blank": F012E, + "checkbox-blank-circle": F012F, + "checkbox-blank-circle-outline": F0130, + "checkbox-blank-off": F12EC, + "checkbox-blank-off-outline": F12ED, + "checkbox-blank-outline": F0131, + "checkbox-intermediate": F0856, + "checkbox-marked": F0132, + "checkbox-marked-circle": F0133, + "checkbox-marked-circle-outline": F0134, + "checkbox-marked-outline": F0135, + "checkbox-multiple-blank": F0136, + "checkbox-multiple-blank-circle": F063B, + "checkbox-multiple-blank-circle-outline": F063C, + "checkbox-multiple-blank-outline": F0137, + "checkbox-multiple-marked": F0138, + "checkbox-multiple-marked-circle": F063D, + "checkbox-multiple-marked-circle-outline": F063E, + "checkbox-multiple-marked-outline": F0139, + "checkerboard": F013A, + "checkerboard-minus": F1202, + "checkerboard-plus": F1201, + "checkerboard-remove": F1203, + "cheese": F12B9, + "cheese-off": F13EE, + "chef-hat": F0B7C, + "chemical-weapon": F013B, + "chess-bishop": F085C, + "chess-king": F0857, + "chess-knight": F0858, + "chess-pawn": F0859, + "chess-queen": F085A, + "chess-rook": F085B, + "chevron-double-down": F013C, + "chevron-double-left": F013D, + "chevron-double-right": F013E, + "chevron-double-up": F013F, + "chevron-down": F0140, + "chevron-down-box": F09D6, + "chevron-down-box-outline": F09D7, + "chevron-down-circle": F0B26, + "chevron-down-circle-outline": F0B27, + "chevron-left": F0141, + "chevron-left-box": F09D8, + "chevron-left-box-outline": F09D9, + "chevron-left-circle": F0B28, + "chevron-left-circle-outline": F0B29, + "chevron-right": F0142, + "chevron-right-box": F09DA, + "chevron-right-box-outline": F09DB, + "chevron-right-circle": F0B2A, + "chevron-right-circle-outline": F0B2B, + "chevron-triple-down": F0DB9, + "chevron-triple-left": F0DBA, + "chevron-triple-right": F0DBB, + "chevron-triple-up": F0DBC, + "chevron-up": F0143, + "chevron-up-box": F09DC, + "chevron-up-box-outline": F09DD, + "chevron-up-circle": F0B2C, + "chevron-up-circle-outline": F0B2D, + "chili-hot": F07B2, + "chili-medium": F07B3, + "chili-mild": F07B4, + "chili-off": F1467, + "chip": F061A, + "christianity": F0953, + "christianity-outline": F0CF6, + "church": F0144, + "cigar": F1189, + "cigar-off": F141B, + "circle": F0765, + "circle-box": F15DC, + "circle-box-outline": F15DD, + "circle-double": F0E95, + "circle-edit-outline": F08D5, + "circle-expand": F0E96, + "circle-half": F1395, + "circle-half-full": F1396, + "circle-medium": F09DE, + "circle-multiple": F0B38, + "circle-multiple-outline": F0695, + "circle-off-outline": F10D3, + "circle-outline": F0766, + "circle-slice-1": F0A9E, + "circle-slice-2": F0A9F, + "circle-slice-3": F0AA0, + "circle-slice-4": F0AA1, + "circle-slice-5": F0AA2, + "circle-slice-6": F0AA3, + "circle-slice-7": F0AA4, + "circle-slice-8": F0AA5, + "circle-small": F09DF, + "circular-saw": F0E22, + "city": F0146, + "city-variant": F0A36, + "city-variant-outline": F0A37, + "clipboard": F0147, + "clipboard-account": F0148, + "clipboard-account-outline": F0C55, + "clipboard-alert": F0149, + "clipboard-alert-outline": F0CF7, + "clipboard-arrow-down": F014A, + "clipboard-arrow-down-outline": F0C56, + "clipboard-arrow-left": F014B, + "clipboard-arrow-left-outline": F0CF8, + "clipboard-arrow-right": F0CF9, + "clipboard-arrow-right-outline": F0CFA, + "clipboard-arrow-up": F0C57, + "clipboard-arrow-up-outline": F0C58, + "clipboard-check": F014E, + "clipboard-check-multiple": F1263, + "clipboard-check-multiple-outline": F1264, + "clipboard-check-outline": F08A8, + "clipboard-edit": F14E5, + "clipboard-edit-outline": F14E6, + "clipboard-file": F1265, + "clipboard-file-outline": F1266, + "clipboard-flow": F06C8, + "clipboard-flow-outline": F1117, + "clipboard-list": F10D4, + "clipboard-list-outline": F10D5, + "clipboard-minus": F1618, + "clipboard-minus-outline": F1619, + "clipboard-multiple": F1267, + "clipboard-multiple-outline": F1268, + "clipboard-off": F161A, + "clipboard-off-outline": F161B, + "clipboard-outline": F014C, + "clipboard-play": F0C59, + "clipboard-play-multiple": F1269, + "clipboard-play-multiple-outline": F126A, + "clipboard-play-outline": F0C5A, + "clipboard-plus": F0751, + "clipboard-plus-outline": F131F, + "clipboard-pulse": F085D, + "clipboard-pulse-outline": F085E, + "clipboard-remove": F161C, + "clipboard-remove-outline": F161D, + "clipboard-search": F161E, + "clipboard-search-outline": F161F, + "clipboard-text": F014D, + "clipboard-text-multiple": F126B, + "clipboard-text-multiple-outline": F126C, + "clipboard-text-off": F1620, + "clipboard-text-off-outline": F1621, + "clipboard-text-outline": F0A38, + "clipboard-text-play": F0C5B, + "clipboard-text-play-outline": F0C5C, + "clipboard-text-search": F1622, + "clipboard-text-search-outline": F1623, + "clippy": F014F, + "clock": F0954, + "clock-alert": F0955, + "clock-alert-outline": F05CE, + "clock-check": F0FA8, + "clock-check-outline": F0FA9, + "clock-digital": F0E97, + "clock-end": F0151, + "clock-fast": F0152, + "clock-in": F0153, + "clock-out": F0154, + "clock-outline": F0150, + "clock-start": F0155, + "clock-time-eight": F1446, + "clock-time-eight-outline": F1452, + "clock-time-eleven": F1449, + "clock-time-eleven-outline": F1455, + "clock-time-five": F1443, + "clock-time-five-outline": F144F, + "clock-time-four": F1442, + "clock-time-four-outline": F144E, + "clock-time-nine": F1447, + "clock-time-nine-outline": F1453, + "clock-time-one": F143F, + "clock-time-one-outline": F144B, + "clock-time-seven": F1445, + "clock-time-seven-outline": F1451, + "clock-time-six": F1444, + "clock-time-six-outline": F1450, + "clock-time-ten": F1448, + "clock-time-ten-outline": F1454, + "clock-time-three": F1441, + "clock-time-three-outline": F144D, + "clock-time-twelve": F144A, + "clock-time-twelve-outline": F1456, + "clock-time-two": F1440, + "clock-time-two-outline": F144C, + "close": F0156, + "close-box": F0157, + "close-box-multiple": F0C5D, + "close-box-multiple-outline": F0C5E, + "close-box-outline": F0158, + "close-circle": F0159, + "close-circle-multiple": F062A, + "close-circle-multiple-outline": F0883, + "close-circle-outline": F015A, + "close-network": F015B, + "close-network-outline": F0C5F, + "close-octagon": F015C, + "close-octagon-outline": F015D, + "close-outline": F06C9, + "close-thick": F1398, + "closed-caption": F015E, + "closed-caption-outline": F0DBD, + "cloud": F015F, + "cloud-alert": F09E0, + "cloud-braces": F07B5, + "cloud-check": F0160, + "cloud-check-outline": F12CC, + "cloud-circle": F0161, + "cloud-download": F0162, + "cloud-download-outline": F0B7D, + "cloud-lock": F11F1, + "cloud-lock-outline": F11F2, + "cloud-off-outline": F0164, + "cloud-outline": F0163, + "cloud-print": F0165, + "cloud-print-outline": F0166, + "cloud-question": F0A39, + "cloud-refresh": F052A, + "cloud-search": F0956, + "cloud-search-outline": F0957, + "cloud-sync": F063F, + "cloud-sync-outline": F12D6, + "cloud-tags": F07B6, + "cloud-upload": F0167, + "cloud-upload-outline": F0B7E, + "clover": F0816, + "coach-lamp": F1020, + "coat-rack": F109E, + "code-array": F0168, + "code-braces": F0169, + "code-braces-box": F10D6, + "code-brackets": F016A, + "code-equal": F016B, + "code-greater-than": F016C, + "code-greater-than-or-equal": F016D, + "code-json": F0626, + "code-less-than": F016E, + "code-less-than-or-equal": F016F, + "code-not-equal": F0170, + "code-not-equal-variant": F0171, + "code-parentheses": F0172, + "code-parentheses-box": F10D7, + "code-string": F0173, + "code-tags": F0174, + "code-tags-check": F0694, + "codepen": F0175, + "coffee": F0176, + "coffee-maker": F109F, + "coffee-off": F0FAA, + "coffee-off-outline": F0FAB, + "coffee-outline": F06CA, + "coffee-to-go": F0177, + "coffee-to-go-outline": F130E, + "coffin": F0B7F, + "cog": F0493, + "cog-box": F0494, + "cog-clockwise": F11DD, + "cog-counterclockwise": F11DE, + "cog-off": F13CE, + "cog-off-outline": F13CF, + "cog-outline": F08BB, + "cog-refresh": F145E, + "cog-refresh-outline": F145F, + "cog-sync": F1460, + "cog-sync-outline": F1461, + "cog-transfer": F105B, + "cog-transfer-outline": F105C, + "cogs": F08D6, + "collage": F0640, + "collapse-all": F0AA6, + "collapse-all-outline": F0AA7, + "color-helper": F0179, + "comma": F0E23, + "comma-box": F0E2B, + "comma-box-outline": F0E24, + "comma-circle": F0E25, + "comma-circle-outline": F0E26, + "comment": F017A, + "comment-account": F017B, + "comment-account-outline": F017C, + "comment-alert": F017D, + "comment-alert-outline": F017E, + "comment-arrow-left": F09E1, + "comment-arrow-left-outline": F09E2, + "comment-arrow-right": F09E3, + "comment-arrow-right-outline": F09E4, + "comment-bookmark": F15AE, + "comment-bookmark-outline": F15AF, + "comment-check": F017F, + "comment-check-outline": F0180, + "comment-edit": F11BF, + "comment-edit-outline": F12C4, + "comment-eye": F0A3A, + "comment-eye-outline": F0A3B, + "comment-flash": F15B0, + "comment-flash-outline": F15B1, + "comment-minus": F15DF, + "comment-minus-outline": F15E0, + "comment-multiple": F085F, + "comment-multiple-outline": F0181, + "comment-off": F15E1, + "comment-off-outline": F15E2, + "comment-outline": F0182, + "comment-plus": F09E5, + "comment-plus-outline": F0183, + "comment-processing": F0184, + "comment-processing-outline": F0185, + "comment-question": F0817, + "comment-question-outline": F0186, + "comment-quote": F1021, + "comment-quote-outline": F1022, + "comment-remove": F05DE, + "comment-remove-outline": F0187, + "comment-search": F0A3C, + "comment-search-outline": F0A3D, + "comment-text": F0188, + "comment-text-multiple": F0860, + "comment-text-multiple-outline": F0861, + "comment-text-outline": F0189, + "compare": F018A, + "compare-horizontal": F1492, + "compare-vertical": F1493, + "compass": F018B, + "compass-off": F0B80, + "compass-off-outline": F0B81, + "compass-outline": F018C, + "compass-rose": F1382, + "concourse-ci": F10A0, + "connection": F1616, + "console": F018D, + "console-line": F07B7, + "console-network": F08A9, + "console-network-outline": F0C60, + "consolidate": F10D8, + "contactless-payment": F0D6A, + "contactless-payment-circle": F0321, + "contactless-payment-circle-outline": F0408, + "contacts": F06CB, + "contacts-outline": F05B8, + "contain": F0A3E, + "contain-end": F0A3F, + "contain-start": F0A40, + "content-copy": F018F, + "content-cut": F0190, + "content-duplicate": F0191, + "content-paste": F0192, + "content-save": F0193, + "content-save-alert": F0F42, + "content-save-alert-outline": F0F43, + "content-save-all": F0194, + "content-save-all-outline": F0F44, + "content-save-cog": F145B, + "content-save-cog-outline": F145C, + "content-save-edit": F0CFB, + "content-save-edit-outline": F0CFC, + "content-save-move": F0E27, + "content-save-move-outline": F0E28, + "content-save-off": F1643, + "content-save-off-outline": F1644, + "content-save-outline": F0818, + "content-save-settings": F061B, + "content-save-settings-outline": F0B2E, + "contrast": F0195, + "contrast-box": F0196, + "contrast-circle": F0197, + "controller-classic": F0B82, + "controller-classic-outline": F0B83, + "cookie": F0198, + "cookie-alert": F16D0, + "cookie-alert-outline": F16D1, + "cookie-check": F16D2, + "cookie-check-outline": F16D3, + "cookie-cog": F16D4, + "cookie-cog-outline": F16D5, + "cookie-minus": F16DA, + "cookie-minus-outline": F16DB, + "cookie-outline": F16DE, + "cookie-plus": F16D6, + "cookie-plus-outline": F16D7, + "cookie-remove": F16D8, + "cookie-remove-outline": F16D9, + "cookie-settings": F16DC, + "cookie-settings-outline": F16DD, + "coolant-temperature": F03C8, + "copyright": F05E6, + "cordova": F0958, + "corn": F07B8, + "corn-off": F13EF, + "cosine-wave": F1479, + "counter": F0199, + "cow": F019A, + "cpu-32-bit": F0EDF, + "cpu-64-bit": F0EE0, + "crane": F0862, + "creation": F0674, + "creative-commons": F0D6B, + "credit-card": F0FEF, + "credit-card-check": F13D0, + "credit-card-check-outline": F13D1, + "credit-card-clock": F0EE1, + "credit-card-clock-outline": F0EE2, + "credit-card-marker": F06A8, + "credit-card-marker-outline": F0DBE, + "credit-card-minus": F0FAC, + "credit-card-minus-outline": F0FAD, + "credit-card-multiple": F0FF0, + "credit-card-multiple-outline": F019C, + "credit-card-off": F0FF1, + "credit-card-off-outline": F05E4, + "credit-card-outline": F019B, + "credit-card-plus": F0FF2, + "credit-card-plus-outline": F0676, + "credit-card-refresh": F1645, + "credit-card-refresh-outline": F1646, + "credit-card-refund": F0FF3, + "credit-card-refund-outline": F0AA8, + "credit-card-remove": F0FAE, + "credit-card-remove-outline": F0FAF, + "credit-card-scan": F0FF4, + "credit-card-scan-outline": F019D, + "credit-card-search": F1647, + "credit-card-search-outline": F1648, + "credit-card-settings": F0FF5, + "credit-card-settings-outline": F08D7, + "credit-card-sync": F1649, + "credit-card-sync-outline": F164A, + "credit-card-wireless": F0802, + "credit-card-wireless-off": F057A, + "credit-card-wireless-off-outline": F057B, + "credit-card-wireless-outline": F0D6C, + "cricket": F0D6D, + "crop": F019E, + "crop-free": F019F, + "crop-landscape": F01A0, + "crop-portrait": F01A1, + "crop-rotate": F0696, + "crop-square": F01A2, + "crosshairs": F01A3, + "crosshairs-gps": F01A4, + "crosshairs-off": F0F45, + "crosshairs-question": F1136, + "crown": F01A5, + "crown-outline": F11D0, + "cryengine": F0959, + "crystal-ball": F0B2F, + "cube": F01A6, + "cube-off": F141C, + "cube-off-outline": F141D, + "cube-outline": F01A7, + "cube-scan": F0B84, + "cube-send": F01A8, + "cube-unfolded": F01A9, + "cup": F01AA, + "cup-off": F05E5, + "cup-off-outline": F137D, + "cup-outline": F130F, + "cup-water": F01AB, + "cupboard": F0F46, + "cupboard-outline": F0F47, + "cupcake": F095A, + "curling": F0863, + "currency-bdt": F0864, + "currency-brl": F0B85, + "currency-btc": F01AC, + "currency-cny": F07BA, + "currency-eth": F07BB, + "currency-eur": F01AD, + "currency-eur-off": F1315, + "currency-gbp": F01AE, + "currency-ils": F0C61, + "currency-inr": F01AF, + "currency-jpy": F07BC, + "currency-krw": F07BD, + "currency-kzt": F0865, + "currency-mnt": F1512, + "currency-ngn": F01B0, + "currency-php": F09E6, + "currency-rial": F0E9C, + "currency-rub": F01B1, + "currency-sign": F07BE, + "currency-try": F01B2, + "currency-twd": F07BF, + "currency-usd": F01C1, + "currency-usd-circle": F116B, + "currency-usd-circle-outline": F0178, + "currency-usd-off": F067A, + "current-ac": F1480, + "current-dc": F095C, + "cursor-default": F01C0, + "cursor-default-click": F0CFD, + "cursor-default-click-outline": F0CFE, + "cursor-default-gesture": F1127, + "cursor-default-gesture-outline": F1128, + "cursor-default-outline": F01BF, + "cursor-move": F01BE, + "cursor-pointer": F01BD, + "cursor-text": F05E7, + "dance-ballroom": F15FB, + "dance-pole": F1578, + "data-matrix": F153C, + "data-matrix-edit": F153D, + "data-matrix-minus": F153E, + "data-matrix-plus": F153F, + "data-matrix-remove": F1540, + "data-matrix-scan": F1541, + "database": F01BC, + "database-alert": F163A, + "database-alert-outline": F1624, + "database-arrow-down": F163B, + "database-arrow-down-outline": F1625, + "database-arrow-left": F163C, + "database-arrow-left-outline": F1626, + "database-arrow-right": F163D, + "database-arrow-right-outline": F1627, + "database-arrow-up": F163E, + "database-arrow-up-outline": F1628, + "database-check": F0AA9, + "database-check-outline": F1629, + "database-clock": F163F, + "database-clock-outline": F162A, + "database-cog": F164B, + "database-cog-outline": F164C, + "database-edit": F0B86, + "database-edit-outline": F162B, + "database-export": F095E, + "database-export-outline": F162C, + "database-import": F095D, + "database-import-outline": F162D, + "database-lock": F0AAA, + "database-lock-outline": F162E, + "database-marker": F12F6, + "database-marker-outline": F162F, + "database-minus": F01BB, + "database-minus-outline": F1630, + "database-off": F1640, + "database-off-outline": F1631, + "database-outline": F1632, + "database-plus": F01BA, + "database-plus-outline": F1633, + "database-refresh": F05C2, + "database-refresh-outline": F1634, + "database-remove": F0D00, + "database-remove-outline": F1635, + "database-search": F0866, + "database-search-outline": F1636, + "database-settings": F0D01, + "database-settings-outline": F1637, + "database-sync": F0CFF, + "database-sync-outline": F1638, + "death-star": F08D8, + "death-star-variant": F08D9, + "deathly-hallows": F0B87, + "debian": F08DA, + "debug-step-into": F01B9, + "debug-step-out": F01B8, + "debug-step-over": F01B7, + "decagram": F076C, + "decagram-outline": F076D, + "decimal": F10A1, + "decimal-comma": F10A2, + "decimal-comma-decrease": F10A3, + "decimal-comma-increase": F10A4, + "decimal-decrease": F01B6, + "decimal-increase": F01B5, + "delete": F01B4, + "delete-alert": F10A5, + "delete-alert-outline": F10A6, + "delete-circle": F0683, + "delete-circle-outline": F0B88, + "delete-clock": F1556, + "delete-clock-outline": F1557, + "delete-empty": F06CC, + "delete-empty-outline": F0E9D, + "delete-forever": F05E8, + "delete-forever-outline": F0B89, + "delete-off": F10A7, + "delete-off-outline": F10A8, + "delete-outline": F09E7, + "delete-restore": F0819, + "delete-sweep": F05E9, + "delete-sweep-outline": F0C62, + "delete-variant": F01B3, + "delta": F01C2, + "desk": F1239, + "desk-lamp": F095F, + "deskphone": F01C3, + "desktop-classic": F07C0, + "desktop-mac": F01C4, + "desktop-mac-dashboard": F09E8, + "desktop-tower": F01C5, + "desktop-tower-monitor": F0AAB, + "details": F01C6, + "dev-to": F0D6E, + "developer-board": F0697, + "deviantart": F01C7, + "devices": F0FB0, + "diabetes": F1126, + "dialpad": F061C, + "diameter": F0C63, + "diameter-outline": F0C64, + "diameter-variant": F0C65, + "diamond": F0B8A, + "diamond-outline": F0B8B, + "diamond-stone": F01C8, + "dice-1": F01CA, + "dice-1-outline": F114A, + "dice-2": F01CB, + "dice-2-outline": F114B, + "dice-3": F01CC, + "dice-3-outline": F114C, + "dice-4": F01CD, + "dice-4-outline": F114D, + "dice-5": F01CE, + "dice-5-outline": F114E, + "dice-6": F01CF, + "dice-6-outline": F114F, + "dice-d10": F1153, + "dice-d10-outline": F076F, + "dice-d12": F1154, + "dice-d12-outline": F0867, + "dice-d20": F1155, + "dice-d20-outline": F05EA, + "dice-d4": F1150, + "dice-d4-outline": F05EB, + "dice-d6": F1151, + "dice-d6-outline": F05ED, + "dice-d8": F1152, + "dice-d8-outline": F05EC, + "dice-multiple": F076E, + "dice-multiple-outline": F1156, + "digital-ocean": F1237, + "dip-switch": F07C1, + "directions": F01D0, + "directions-fork": F0641, + "disc": F05EE, + "disc-alert": F01D1, + "disc-player": F0960, + "discord": F066F, + "dishwasher": F0AAC, + "dishwasher-alert": F11B8, + "dishwasher-off": F11B9, + "disqus": F01D2, + "distribute-horizontal-center": F11C9, + "distribute-horizontal-left": F11C8, + "distribute-horizontal-right": F11CA, + "distribute-vertical-bottom": F11CB, + "distribute-vertical-center": F11CC, + "distribute-vertical-top": F11CD, + "diving-flippers": F0DBF, + "diving-helmet": F0DC0, + "diving-scuba": F0DC1, + "diving-scuba-flag": F0DC2, + "diving-scuba-tank": F0DC3, + "diving-scuba-tank-multiple": F0DC4, + "diving-snorkel": F0DC5, + "division": F01D4, + "division-box": F01D5, + "dlna": F0A41, + "dna": F0684, + "dns": F01D6, + "dns-outline": F0B8C, + "do-not-disturb": F0698, + "do-not-disturb-off": F0699, + "dock-bottom": F10A9, + "dock-left": F10AA, + "dock-right": F10AB, + "dock-top": F1513, + "dock-window": F10AC, + "docker": F0868, + "doctor": F0A42, + "dog": F0A43, + "dog-service": F0AAD, + "dog-side": F0A44, + "dolby": F06B3, + "dolly": F0E9E, + "domain": F01D7, + "domain-off": F0D6F, + "domain-plus": F10AD, + "domain-remove": F10AE, + "dome-light": F141E, + "domino-mask": F1023, + "donkey": F07C2, + "door": F081A, + "door-closed": F081B, + "door-closed-lock": F10AF, + "door-open": F081C, + "doorbell": F12E6, + "doorbell-video": F0869, + "dot-net": F0AAE, + "dots-grid": F15FC, + "dots-hexagon": F15FF, + "dots-horizontal": F01D8, + "dots-horizontal-circle": F07C3, + "dots-horizontal-circle-outline": F0B8D, + "dots-square": F15FD, + "dots-triangle": F15FE, + "dots-vertical": F01D9, + "dots-vertical-circle": F07C4, + "dots-vertical-circle-outline": F0B8E, + "douban": F069A, + "download": F01DA, + "download-box": F1462, + "download-box-outline": F1463, + "download-circle": F1464, + "download-circle-outline": F1465, + "download-lock": F1320, + "download-lock-outline": F1321, + "download-multiple": F09E9, + "download-network": F06F4, + "download-network-outline": F0C66, + "download-off": F10B0, + "download-off-outline": F10B1, + "download-outline": F0B8F, + "drag": F01DB, + "drag-horizontal": F01DC, + "drag-horizontal-variant": F12F0, + "drag-variant": F0B90, + "drag-vertical": F01DD, + "drag-vertical-variant": F12F1, + "drama-masks": F0D02, + "draw": F0F49, + "drawing": F01DE, + "drawing-box": F01DF, + "dresser": F0F4A, + "dresser-outline": F0F4B, + "drone": F01E2, + "dropbox": F01E3, + "drupal": F01E4, + "duck": F01E5, + "dumbbell": F01E6, + "dump-truck": F0C67, + "ear-hearing": F07C5, + "ear-hearing-off": F0A45, + "earth": F01E7, + "earth-arrow-right": F1311, + "earth-box": F06CD, + "earth-box-minus": F1407, + "earth-box-off": F06CE, + "earth-box-plus": F1406, + "earth-box-remove": F1408, + "earth-minus": F1404, + "earth-off": F01E8, + "earth-plus": F1403, + "earth-remove": F1405, + "egg": F0AAF, + "egg-easter": F0AB0, + "egg-off": F13F0, + "egg-off-outline": F13F1, + "egg-outline": F13F2, + "eiffel-tower": F156B, + "eight-track": F09EA, + "eject": F01EA, + "eject-outline": F0B91, + "electric-switch": F0E9F, + "electric-switch-closed": F10D9, + "electron-framework": F1024, + "elephant": F07C6, + "elevation-decline": F01EB, + "elevation-rise": F01EC, + "elevator": F01ED, + "elevator-down": F12C2, + "elevator-passenger": F1381, + "elevator-up": F12C1, + "ellipse": F0EA0, + "ellipse-outline": F0EA1, + "email": F01EE, + "email-alert": F06CF, + "email-alert-outline": F0D42, + "email-box": F0D03, + "email-check": F0AB1, + "email-check-outline": F0AB2, + "email-edit": F0EE3, + "email-edit-outline": F0EE4, + "email-lock": F01F1, + "email-mark-as-unread": F0B92, + "email-minus": F0EE5, + "email-minus-outline": F0EE6, + "email-multiple": F0EE7, + "email-multiple-outline": F0EE8, + "email-newsletter": F0FB1, + "email-off": F13E3, + "email-off-outline": F13E4, + "email-open": F01EF, + "email-open-multiple": F0EE9, + "email-open-multiple-outline": F0EEA, + "email-open-outline": F05EF, + "email-outline": F01F0, + "email-plus": F09EB, + "email-plus-outline": F09EC, + "email-receive": F10DA, + "email-receive-outline": F10DB, + "email-remove": F1661, + "email-remove-outline": F1662, + "email-search": F0961, + "email-search-outline": F0962, + "email-send": F10DC, + "email-send-outline": F10DD, + "email-sync": F12C7, + "email-sync-outline": F12C8, + "email-variant": F05F0, + "ember": F0B30, + "emby": F06B4, + "emoticon": F0C68, + "emoticon-angry": F0C69, + "emoticon-angry-outline": F0C6A, + "emoticon-confused": F10DE, + "emoticon-confused-outline": F10DF, + "emoticon-cool": F0C6B, + "emoticon-cool-outline": F01F3, + "emoticon-cry": F0C6C, + "emoticon-cry-outline": F0C6D, + "emoticon-dead": F0C6E, + "emoticon-dead-outline": F069B, + "emoticon-devil": F0C6F, + "emoticon-devil-outline": F01F4, + "emoticon-excited": F0C70, + "emoticon-excited-outline": F069C, + "emoticon-frown": F0F4C, + "emoticon-frown-outline": F0F4D, + "emoticon-happy": F0C71, + "emoticon-happy-outline": F01F5, + "emoticon-kiss": F0C72, + "emoticon-kiss-outline": F0C73, + "emoticon-lol": F1214, + "emoticon-lol-outline": F1215, + "emoticon-neutral": F0C74, + "emoticon-neutral-outline": F01F6, + "emoticon-outline": F01F2, + "emoticon-poop": F01F7, + "emoticon-poop-outline": F0C75, + "emoticon-sad": F0C76, + "emoticon-sad-outline": F01F8, + "emoticon-sick": F157C, + "emoticon-sick-outline": F157D, + "emoticon-tongue": F01F9, + "emoticon-tongue-outline": F0C77, + "emoticon-wink": F0C78, + "emoticon-wink-outline": F0C79, + "engine": F01FA, + "engine-off": F0A46, + "engine-off-outline": F0A47, + "engine-outline": F01FB, + "epsilon": F10E0, + "equal": F01FC, + "equal-box": F01FD, + "equalizer": F0EA2, + "equalizer-outline": F0EA3, + "eraser": F01FE, + "eraser-variant": F0642, + "escalator": F01FF, + "escalator-box": F1399, + "escalator-down": F12C0, + "escalator-up": F12BF, + "eslint": F0C7A, + "et": F0AB3, + "ethereum": F086A, + "ethernet": F0200, + "ethernet-cable": F0201, + "ethernet-cable-off": F0202, + "ev-plug-ccs1": F1519, + "ev-plug-ccs2": F151A, + "ev-plug-chademo": F151B, + "ev-plug-tesla": F151C, + "ev-plug-type1": F151D, + "ev-plug-type2": F151E, + "ev-station": F05F1, + "evernote": F0204, + "excavator": F1025, + "exclamation": F0205, + "exclamation-thick": F1238, + "exit-run": F0A48, + "exit-to-app": F0206, + "expand-all": F0AB4, + "expand-all-outline": F0AB5, + "expansion-card": F08AE, + "expansion-card-variant": F0FB2, + "exponent": F0963, + "exponent-box": F0964, + "export": F0207, + "export-variant": F0B93, + "eye": F0208, + "eye-check": F0D04, + "eye-check-outline": F0D05, + "eye-circle": F0B94, + "eye-circle-outline": F0B95, + "eye-minus": F1026, + "eye-minus-outline": F1027, + "eye-off": F0209, + "eye-off-outline": F06D1, + "eye-outline": F06D0, + "eye-plus": F086B, + "eye-plus-outline": F086C, + "eye-remove": F15E3, + "eye-remove-outline": F15E4, + "eye-settings": F086D, + "eye-settings-outline": F086E, + "eyedropper": F020A, + "eyedropper-minus": F13DD, + "eyedropper-off": F13DF, + "eyedropper-plus": F13DC, + "eyedropper-remove": F13DE, + "eyedropper-variant": F020B, + "face": F0643, + "face-agent": F0D70, + "face-mask": F1586, + "face-mask-outline": F1587, + "face-outline": F0B96, + "face-profile": F0644, + "face-profile-woman": F1076, + "face-recognition": F0C7B, + "face-shimmer": F15CC, + "face-shimmer-outline": F15CD, + "face-woman": F1077, + "face-woman-outline": F1078, + "face-woman-shimmer": F15CE, + "face-woman-shimmer-outline": F15CF, + "facebook": F020C, + "facebook-gaming": F07DD, + "facebook-messenger": F020E, + "facebook-workplace": F0B31, + "factory": F020F, + "family-tree": F160E, + "fan": F0210, + "fan-alert": F146C, + "fan-chevron-down": F146D, + "fan-chevron-up": F146E, + "fan-minus": F1470, + "fan-off": F081D, + "fan-plus": F146F, + "fan-remove": F1471, + "fan-speed-1": F1472, + "fan-speed-2": F1473, + "fan-speed-3": F1474, + "fast-forward": F0211, + "fast-forward-10": F0D71, + "fast-forward-30": F0D06, + "fast-forward-5": F11F8, + "fast-forward-60": F160B, + "fast-forward-outline": F06D2, + "fax": F0212, + "feather": F06D3, + "feature-search": F0A49, + "feature-search-outline": F0A4A, + "fedora": F08DB, + "fencing": F14C1, + "ferris-wheel": F0EA4, + "ferry": F0213, + "file": F0214, + "file-account": F073B, + "file-account-outline": F1028, + "file-alert": F0A4B, + "file-alert-outline": F0A4C, + "file-cabinet": F0AB6, + "file-cad": F0EEB, + "file-cad-box": F0EEC, + "file-cancel": F0DC6, + "file-cancel-outline": F0DC7, + "file-certificate": F1186, + "file-certificate-outline": F1187, + "file-chart": F0215, + "file-chart-outline": F1029, + "file-check": F0216, + "file-check-outline": F0E29, + "file-clock": F12E1, + "file-clock-outline": F12E2, + "file-cloud": F0217, + "file-cloud-outline": F102A, + "file-code": F022E, + "file-code-outline": F102B, + "file-cog": F107B, + "file-cog-outline": F107C, + "file-compare": F08AA, + "file-delimited": F0218, + "file-delimited-outline": F0EA5, + "file-document": F0219, + "file-document-edit": F0DC8, + "file-document-edit-outline": F0DC9, + "file-document-multiple": F1517, + "file-document-multiple-outline": F1518, + "file-document-outline": F09EE, + "file-download": F0965, + "file-download-outline": F0966, + "file-edit": F11E7, + "file-edit-outline": F11E8, + "file-excel": F021B, + "file-excel-box": F021C, + "file-excel-box-outline": F102C, + "file-excel-outline": F102D, + "file-export": F021D, + "file-export-outline": F102E, + "file-eye": F0DCA, + "file-eye-outline": F0DCB, + "file-find": F021E, + "file-find-outline": F0B97, + "file-hidden": F0613, + "file-image": F021F, + "file-image-outline": F0EB0, + "file-import": F0220, + "file-import-outline": F102F, + "file-key": F1184, + "file-key-outline": F1185, + "file-link": F1177, + "file-link-outline": F1178, + "file-lock": F0221, + "file-lock-outline": F1030, + "file-move": F0AB9, + "file-move-outline": F1031, + "file-multiple": F0222, + "file-multiple-outline": F1032, + "file-music": F0223, + "file-music-outline": F0E2A, + "file-outline": F0224, + "file-pdf": F0225, + "file-pdf-box": F0226, + "file-pdf-box-outline": F0FB3, + "file-pdf-outline": F0E2D, + "file-percent": F081E, + "file-percent-outline": F1033, + "file-phone": F1179, + "file-phone-outline": F117A, + "file-plus": F0752, + "file-plus-outline": F0EED, + "file-powerpoint": F0227, + "file-powerpoint-box": F0228, + "file-powerpoint-box-outline": F1034, + "file-powerpoint-outline": F1035, + "file-presentation-box": F0229, + "file-question": F086F, + "file-question-outline": F1036, + "file-refresh": F0918, + "file-refresh-outline": F0541, + "file-remove": F0B98, + "file-remove-outline": F1037, + "file-replace": F0B32, + "file-replace-outline": F0B33, + "file-restore": F0670, + "file-restore-outline": F1038, + "file-search": F0C7C, + "file-search-outline": F0C7D, + "file-send": F022A, + "file-send-outline": F1039, + "file-settings": F1079, + "file-settings-outline": F107A, + "file-star": F103A, + "file-star-outline": F103B, + "file-swap": F0FB4, + "file-swap-outline": F0FB5, + "file-sync": F1216, + "file-sync-outline": F1217, + "file-table": F0C7E, + "file-table-box": F10E1, + "file-table-box-multiple": F10E2, + "file-table-box-multiple-outline": F10E3, + "file-table-box-outline": F10E4, + "file-table-outline": F0C7F, + "file-tree": F0645, + "file-tree-outline": F13D2, + "file-undo": F08DC, + "file-undo-outline": F103C, + "file-upload": F0A4D, + "file-upload-outline": F0A4E, + "file-video": F022B, + "file-video-outline": F0E2C, + "file-word": F022C, + "file-word-box": F022D, + "file-word-box-outline": F103D, + "file-word-outline": F103E, + "film": F022F, + "filmstrip": F0230, + "filmstrip-box": F0332, + "filmstrip-box-multiple": F0D18, + "filmstrip-off": F0231, + "filter": F0232, + "filter-menu": F10E5, + "filter-menu-outline": F10E6, + "filter-minus": F0EEE, + "filter-minus-outline": F0EEF, + "filter-off": F14EF, + "filter-off-outline": F14F0, + "filter-outline": F0233, + "filter-plus": F0EF0, + "filter-plus-outline": F0EF1, + "filter-remove": F0234, + "filter-remove-outline": F0235, + "filter-variant": F0236, + "filter-variant-minus": F1112, + "filter-variant-plus": F1113, + "filter-variant-remove": F103F, + "finance": F081F, + "find-replace": F06D4, + "fingerprint": F0237, + "fingerprint-off": F0EB1, + "fire": F0238, + "fire-alert": F15D7, + "fire-extinguisher": F0EF2, + "fire-hydrant": F1137, + "fire-hydrant-alert": F1138, + "fire-hydrant-off": F1139, + "fire-truck": F08AB, + "firebase": F0967, + "firefox": F0239, + "fireplace": F0E2E, + "fireplace-off": F0E2F, + "firework": F0E30, + "fish": F023A, + "fish-off": F13F3, + "fishbowl": F0EF3, + "fishbowl-outline": F0EF4, + "fit-to-page": F0EF5, + "fit-to-page-outline": F0EF6, + "flag": F023B, + "flag-checkered": F023C, + "flag-minus": F0B99, + "flag-minus-outline": F10B2, + "flag-outline": F023D, + "flag-plus": F0B9A, + "flag-plus-outline": F10B3, + "flag-remove": F0B9B, + "flag-remove-outline": F10B4, + "flag-triangle": F023F, + "flag-variant": F0240, + "flag-variant-outline": F023E, + "flare": F0D72, + "flash": F0241, + "flash-alert": F0EF7, + "flash-alert-outline": F0EF8, + "flash-auto": F0242, + "flash-circle": F0820, + "flash-off": F0243, + "flash-outline": F06D5, + "flash-red-eye": F067B, + "flashlight": F0244, + "flashlight-off": F0245, + "flask": F0093, + "flask-empty": F0094, + "flask-empty-minus": F123A, + "flask-empty-minus-outline": F123B, + "flask-empty-off": F13F4, + "flask-empty-off-outline": F13F5, + "flask-empty-outline": F0095, + "flask-empty-plus": F123C, + "flask-empty-plus-outline": F123D, + "flask-empty-remove": F123E, + "flask-empty-remove-outline": F123F, + "flask-minus": F1240, + "flask-minus-outline": F1241, + "flask-off": F13F6, + "flask-off-outline": F13F7, + "flask-outline": F0096, + "flask-plus": F1242, + "flask-plus-outline": F1243, + "flask-remove": F1244, + "flask-remove-outline": F1245, + "flask-round-bottom": F124B, + "flask-round-bottom-empty": F124C, + "flask-round-bottom-empty-outline": F124D, + "flask-round-bottom-outline": F124E, + "fleur-de-lis": F1303, + "flip-horizontal": F10E7, + "flip-to-back": F0247, + "flip-to-front": F0248, + "flip-vertical": F10E8, + "floor-lamp": F08DD, + "floor-lamp-dual": F1040, + "floor-lamp-variant": F1041, + "floor-plan": F0821, + "floppy": F0249, + "floppy-variant": F09EF, + "flower": F024A, + "flower-outline": F09F0, + "flower-poppy": F0D08, + "flower-tulip": F09F1, + "flower-tulip-outline": F09F2, + "focus-auto": F0F4E, + "focus-field": F0F4F, + "focus-field-horizontal": F0F50, + "focus-field-vertical": F0F51, + "folder": F024B, + "folder-account": F024C, + "folder-account-outline": F0B9C, + "folder-alert": F0DCC, + "folder-alert-outline": F0DCD, + "folder-clock": F0ABA, + "folder-clock-outline": F0ABB, + "folder-cog": F107F, + "folder-cog-outline": F1080, + "folder-download": F024D, + "folder-download-outline": F10E9, + "folder-edit": F08DE, + "folder-edit-outline": F0DCE, + "folder-google-drive": F024E, + "folder-heart": F10EA, + "folder-heart-outline": F10EB, + "folder-home": F10B5, + "folder-home-outline": F10B6, + "folder-image": F024F, + "folder-information": F10B7, + "folder-information-outline": F10B8, + "folder-key": F08AC, + "folder-key-network": F08AD, + "folder-key-network-outline": F0C80, + "folder-key-outline": F10EC, + "folder-lock": F0250, + "folder-lock-open": F0251, + "folder-marker": F126D, + "folder-marker-outline": F126E, + "folder-move": F0252, + "folder-move-outline": F1246, + "folder-multiple": F0253, + "folder-multiple-image": F0254, + "folder-multiple-outline": F0255, + "folder-multiple-plus": F147E, + "folder-multiple-plus-outline": F147F, + "folder-music": F1359, + "folder-music-outline": F135A, + "folder-network": F0870, + "folder-network-outline": F0C81, + "folder-open": F0770, + "folder-open-outline": F0DCF, + "folder-outline": F0256, + "folder-plus": F0257, + "folder-plus-outline": F0B9D, + "folder-pound": F0D09, + "folder-pound-outline": F0D0A, + "folder-refresh": F0749, + "folder-refresh-outline": F0542, + "folder-remove": F0258, + "folder-remove-outline": F0B9E, + "folder-search": F0968, + "folder-search-outline": F0969, + "folder-settings": F107D, + "folder-settings-outline": F107E, + "folder-star": F069D, + "folder-star-multiple": F13D3, + "folder-star-multiple-outline": F13D4, + "folder-star-outline": F0B9F, + "folder-swap": F0FB6, + "folder-swap-outline": F0FB7, + "folder-sync": F0D0B, + "folder-sync-outline": F0D0C, + "folder-table": F12E3, + "folder-table-outline": F12E4, + "folder-text": F0C82, + "folder-text-outline": F0C83, + "folder-upload": F0259, + "folder-upload-outline": F10ED, + "folder-zip": F06EB, + "folder-zip-outline": F07B9, + "font-awesome": F003A, + "food": F025A, + "food-apple": F025B, + "food-apple-outline": F0C84, + "food-croissant": F07C8, + "food-drumstick": F141F, + "food-drumstick-off": F1468, + "food-drumstick-off-outline": F1469, + "food-drumstick-outline": F1420, + "food-fork-drink": F05F2, + "food-halal": F1572, + "food-kosher": F1573, + "food-off": F05F3, + "food-steak": F146A, + "food-steak-off": F146B, + "food-variant": F025C, + "food-variant-off": F13E5, + "foot-print": F0F52, + "football": F025D, + "football-australian": F025E, + "football-helmet": F025F, + "forklift": F07C9, + "form-dropdown": F1400, + "form-select": F1401, + "form-textarea": F1095, + "form-textbox": F060E, + "form-textbox-lock": F135D, + "form-textbox-password": F07F5, + "format-align-bottom": F0753, + "format-align-center": F0260, + "format-align-justify": F0261, + "format-align-left": F0262, + "format-align-middle": F0754, + "format-align-right": F0263, + "format-align-top": F0755, + "format-annotation-minus": F0ABC, + "format-annotation-plus": F0646, + "format-bold": F0264, + "format-clear": F0265, + "format-color-fill": F0266, + "format-color-highlight": F0E31, + "format-color-marker-cancel": F1313, + "format-color-text": F069E, + "format-columns": F08DF, + "format-float-center": F0267, + "format-float-left": F0268, + "format-float-none": F0269, + "format-float-right": F026A, + "format-font": F06D6, + "format-font-size-decrease": F09F3, + "format-font-size-increase": F09F4, + "format-header-1": F026B, + "format-header-2": F026C, + "format-header-3": F026D, + "format-header-4": F026E, + "format-header-5": F026F, + "format-header-6": F0270, + "format-header-decrease": F0271, + "format-header-equal": F0272, + "format-header-increase": F0273, + "format-header-pound": F0274, + "format-horizontal-align-center": F061E, + "format-horizontal-align-left": F061F, + "format-horizontal-align-right": F0620, + "format-indent-decrease": F0275, + "format-indent-increase": F0276, + "format-italic": F0277, + "format-letter-case": F0B34, + "format-letter-case-lower": F0B35, + "format-letter-case-upper": F0B36, + "format-letter-ends-with": F0FB8, + "format-letter-matches": F0FB9, + "format-letter-starts-with": F0FBA, + "format-line-spacing": F0278, + "format-line-style": F05C8, + "format-line-weight": F05C9, + "format-list-bulleted": F0279, + "format-list-bulleted-square": F0DD0, + "format-list-bulleted-triangle": F0EB2, + "format-list-bulleted-type": F027A, + "format-list-checkbox": F096A, + "format-list-checks": F0756, + "format-list-numbered": F027B, + "format-list-numbered-rtl": F0D0D, + "format-list-text": F126F, + "format-overline": F0EB3, + "format-page-break": F06D7, + "format-paint": F027C, + "format-paragraph": F027D, + "format-pilcrow": F06D8, + "format-quote-close": F027E, + "format-quote-close-outline": F11A8, + "format-quote-open": F0757, + "format-quote-open-outline": F11A7, + "format-rotate-90": F06AA, + "format-section": F069F, + "format-size": F027F, + "format-strikethrough": F0280, + "format-strikethrough-variant": F0281, + "format-subscript": F0282, + "format-superscript": F0283, + "format-text": F0284, + "format-text-rotation-angle-down": F0FBB, + "format-text-rotation-angle-up": F0FBC, + "format-text-rotation-down": F0D73, + "format-text-rotation-down-vertical": F0FBD, + "format-text-rotation-none": F0D74, + "format-text-rotation-up": F0FBE, + "format-text-rotation-vertical": F0FBF, + "format-text-variant": F0E32, + "format-text-variant-outline": F150F, + "format-text-wrapping-clip": F0D0E, + "format-text-wrapping-overflow": F0D0F, + "format-text-wrapping-wrap": F0D10, + "format-textbox": F0D11, + "format-textdirection-l-to-r": F0285, + "format-textdirection-r-to-l": F0286, + "format-title": F05F4, + "format-underline": F0287, + "format-vertical-align-bottom": F0621, + "format-vertical-align-center": F0622, + "format-vertical-align-top": F0623, + "format-wrap-inline": F0288, + "format-wrap-square": F0289, + "format-wrap-tight": F028A, + "format-wrap-top-bottom": F028B, + "forum": F028C, + "forum-outline": F0822, + "forward": F028D, + "forwardburger": F0D75, + "fountain": F096B, + "fountain-pen": F0D12, + "fountain-pen-tip": F0D13, + "freebsd": F08E0, + "frequently-asked-questions": F0EB4, + "fridge": F0290, + "fridge-alert": F11B1, + "fridge-alert-outline": F11B2, + "fridge-bottom": F0292, + "fridge-industrial": F15EE, + "fridge-industrial-alert": F15EF, + "fridge-industrial-alert-outline": F15F0, + "fridge-industrial-off": F15F1, + "fridge-industrial-off-outline": F15F2, + "fridge-industrial-outline": F15F3, + "fridge-off": F11AF, + "fridge-off-outline": F11B0, + "fridge-outline": F028F, + "fridge-top": F0291, + "fridge-variant": F15F4, + "fridge-variant-alert": F15F5, + "fridge-variant-alert-outline": F15F6, + "fridge-variant-off": F15F7, + "fridge-variant-off-outline": F15F8, + "fridge-variant-outline": F15F9, + "fruit-cherries": F1042, + "fruit-cherries-off": F13F8, + "fruit-citrus": F1043, + "fruit-citrus-off": F13F9, + "fruit-grapes": F1044, + "fruit-grapes-outline": F1045, + "fruit-pineapple": F1046, + "fruit-watermelon": F1047, + "fuel": F07CA, + "fullscreen": F0293, + "fullscreen-exit": F0294, + "function": F0295, + "function-variant": F0871, + "furigana-horizontal": F1081, + "furigana-vertical": F1082, + "fuse": F0C85, + "fuse-alert": F142D, + "fuse-blade": F0C86, + "fuse-off": F142C, + "gamepad": F0296, + "gamepad-circle": F0E33, + "gamepad-circle-down": F0E34, + "gamepad-circle-left": F0E35, + "gamepad-circle-outline": F0E36, + "gamepad-circle-right": F0E37, + "gamepad-circle-up": F0E38, + "gamepad-down": F0E39, + "gamepad-left": F0E3A, + "gamepad-right": F0E3B, + "gamepad-round": F0E3C, + "gamepad-round-down": F0E3D, + "gamepad-round-left": F0E3E, + "gamepad-round-outline": F0E3F, + "gamepad-round-right": F0E40, + "gamepad-round-up": F0E41, + "gamepad-square": F0EB5, + "gamepad-square-outline": F0EB6, + "gamepad-up": F0E42, + "gamepad-variant": F0297, + "gamepad-variant-outline": F0EB7, + "gamma": F10EE, + "gantry-crane": F0DD1, + "garage": F06D9, + "garage-alert": F0872, + "garage-alert-variant": F12D5, + "garage-open": F06DA, + "garage-open-variant": F12D4, + "garage-variant": F12D3, + "gas-cylinder": F0647, + "gas-station": F0298, + "gas-station-off": F1409, + "gas-station-off-outline": F140A, + "gas-station-outline": F0EB8, + "gate": F0299, + "gate-and": F08E1, + "gate-arrow-right": F1169, + "gate-nand": F08E2, + "gate-nor": F08E3, + "gate-not": F08E4, + "gate-open": F116A, + "gate-or": F08E5, + "gate-xnor": F08E6, + "gate-xor": F08E7, + "gatsby": F0E43, + "gauge": F029A, + "gauge-empty": F0873, + "gauge-full": F0874, + "gauge-low": F0875, + "gavel": F029B, + "gender-female": F029C, + "gender-male": F029D, + "gender-male-female": F029E, + "gender-male-female-variant": F113F, + "gender-non-binary": F1140, + "gender-transgender": F029F, + "gentoo": F08E8, + "gesture": F07CB, + "gesture-double-tap": F073C, + "gesture-pinch": F0ABD, + "gesture-spread": F0ABE, + "gesture-swipe": F0D76, + "gesture-swipe-down": F073D, + "gesture-swipe-horizontal": F0ABF, + "gesture-swipe-left": F073E, + "gesture-swipe-right": F073F, + "gesture-swipe-up": F0740, + "gesture-swipe-vertical": F0AC0, + "gesture-tap": F0741, + "gesture-tap-box": F12A9, + "gesture-tap-button": F12A8, + "gesture-tap-hold": F0D77, + "gesture-two-double-tap": F0742, + "gesture-two-tap": F0743, + "ghost": F02A0, + "ghost-off": F09F5, + "ghost-off-outline": F165C, + "ghost-outline": F165D, + "gif": F0D78, + "gift": F0E44, + "gift-outline": F02A1, + "git": F02A2, + "github": F02A4, + "gitlab": F0BA0, + "glass-cocktail": F0356, + "glass-cocktail-off": F15E6, + "glass-flute": F02A5, + "glass-mug": F02A6, + "glass-mug-off": F15E7, + "glass-mug-variant": F1116, + "glass-mug-variant-off": F15E8, + "glass-pint-outline": F130D, + "glass-stange": F02A7, + "glass-tulip": F02A8, + "glass-wine": F0876, + "glasses": F02AA, + "globe-light": F12D7, + "globe-model": F08E9, + "gmail": F02AB, + "gnome": F02AC, + "go-kart": F0D79, + "go-kart-track": F0D7A, + "gog": F0BA1, + "gold": F124F, + "golf": F0823, + "golf-cart": F11A4, + "golf-tee": F1083, + "gondola": F0686, + "goodreads": F0D7B, + "google": F02AD, + "google-ads": F0C87, + "google-analytics": F07CC, + "google-assistant": F07CD, + "google-cardboard": F02AE, + "google-chrome": F02AF, + "google-circles": F02B0, + "google-circles-communities": F02B1, + "google-circles-extended": F02B2, + "google-circles-group": F02B3, + "google-classroom": F02C0, + "google-cloud": F11F6, + "google-controller": F02B4, + "google-controller-off": F02B5, + "google-downasaur": F1362, + "google-drive": F02B6, + "google-earth": F02B7, + "google-fit": F096C, + "google-glass": F02B8, + "google-hangouts": F02C9, + "google-home": F0824, + "google-keep": F06DC, + "google-lens": F09F6, + "google-maps": F05F5, + "google-my-business": F1048, + "google-nearby": F02B9, + "google-photos": F06DD, + "google-play": F02BC, + "google-plus": F02BD, + "google-podcast": F0EB9, + "google-spreadsheet": F09F7, + "google-street-view": F0C88, + "google-translate": F02BF, + "gradient": F06A0, + "grain": F0D7C, + "graph": F1049, + "graph-outline": F104A, + "graphql": F0877, + "grass": F1510, + "grave-stone": F0BA2, + "grease-pencil": F0648, + "greater-than": F096D, + "greater-than-or-equal": F096E, + "grid": F02C1, + "grid-large": F0758, + "grid-off": F02C2, + "grill": F0E45, + "grill-outline": F118A, + "group": F02C3, + "guitar-acoustic": F0771, + "guitar-electric": F02C4, + "guitar-pick": F02C5, + "guitar-pick-outline": F02C6, + "guy-fawkes-mask": F0825, + "hail": F0AC1, + "hair-dryer": F10EF, + "hair-dryer-outline": F10F0, + "halloween": F0BA3, + "hamburger": F0685, + "hammer": F08EA, + "hammer-screwdriver": F1322, + "hammer-wrench": F1323, + "hand": F0A4F, + "hand-heart": F10F1, + "hand-heart-outline": F157E, + "hand-left": F0E46, + "hand-okay": F0A50, + "hand-peace": F0A51, + "hand-peace-variant": F0A52, + "hand-pointing-down": F0A53, + "hand-pointing-left": F0A54, + "hand-pointing-right": F02C7, + "hand-pointing-up": F0A55, + "hand-right": F0E47, + "hand-saw": F0E48, + "hand-wash": F157F, + "hand-wash-outline": F1580, + "hand-water": F139F, + "handball": F0F53, + "handcuffs": F113E, + "handshake": F1218, + "handshake-outline": F15A1, + "hanger": F02C8, + "hard-hat": F096F, + "harddisk": F02CA, + "harddisk-plus": F104B, + "harddisk-remove": F104C, + "hat-fedora": F0BA4, + "hazard-lights": F0C89, + "hdr": F0D7D, + "hdr-off": F0D7E, + "head": F135E, + "head-alert": F1338, + "head-alert-outline": F1339, + "head-check": F133A, + "head-check-outline": F133B, + "head-cog": F133C, + "head-cog-outline": F133D, + "head-dots-horizontal": F133E, + "head-dots-horizontal-outline": F133F, + "head-flash": F1340, + "head-flash-outline": F1341, + "head-heart": F1342, + "head-heart-outline": F1343, + "head-lightbulb": F1344, + "head-lightbulb-outline": F1345, + "head-minus": F1346, + "head-minus-outline": F1347, + "head-outline": F135F, + "head-plus": F1348, + "head-plus-outline": F1349, + "head-question": F134A, + "head-question-outline": F134B, + "head-remove": F134C, + "head-remove-outline": F134D, + "head-snowflake": F134E, + "head-snowflake-outline": F134F, + "head-sync": F1350, + "head-sync-outline": F1351, + "headphones": F02CB, + "headphones-bluetooth": F0970, + "headphones-box": F02CC, + "headphones-off": F07CE, + "headphones-settings": F02CD, + "headset": F02CE, + "headset-dock": F02CF, + "headset-off": F02D0, + "heart": F02D1, + "heart-box": F02D2, + "heart-box-outline": F02D3, + "heart-broken": F02D4, + "heart-broken-outline": F0D14, + "heart-circle": F0971, + "heart-circle-outline": F0972, + "heart-cog": F1663, + "heart-cog-outline": F1664, + "heart-flash": F0EF9, + "heart-half": F06DF, + "heart-half-full": F06DE, + "heart-half-outline": F06E0, + "heart-minus": F142F, + "heart-minus-outline": F1432, + "heart-multiple": F0A56, + "heart-multiple-outline": F0A57, + "heart-off": F0759, + "heart-off-outline": F1434, + "heart-outline": F02D5, + "heart-plus": F142E, + "heart-plus-outline": F1431, + "heart-pulse": F05F6, + "heart-remove": F1430, + "heart-remove-outline": F1433, + "heart-settings": F1665, + "heart-settings-outline": F1666, + "helicopter": F0AC2, + "help": F02D6, + "help-box": F078B, + "help-circle": F02D7, + "help-circle-outline": F0625, + "help-network": F06F5, + "help-network-outline": F0C8A, + "help-rhombus": F0BA5, + "help-rhombus-outline": F0BA6, + "hexadecimal": F12A7, + "hexagon": F02D8, + "hexagon-multiple": F06E1, + "hexagon-multiple-outline": F10F2, + "hexagon-outline": F02D9, + "hexagon-slice-1": F0AC3, + "hexagon-slice-2": F0AC4, + "hexagon-slice-3": F0AC5, + "hexagon-slice-4": F0AC6, + "hexagon-slice-5": F0AC7, + "hexagon-slice-6": F0AC8, + "hexagram": F0AC9, + "hexagram-outline": F0ACA, + "high-definition": F07CF, + "high-definition-box": F0878, + "highway": F05F7, + "hiking": F0D7F, + "hinduism": F0973, + "history": F02DA, + "hockey-puck": F0879, + "hockey-sticks": F087A, + "hololens": F02DB, + "home": F02DC, + "home-account": F0826, + "home-alert": F087B, + "home-alert-outline": F15D0, + "home-analytics": F0EBA, + "home-assistant": F07D0, + "home-automation": F07D1, + "home-circle": F07D2, + "home-circle-outline": F104D, + "home-city": F0D15, + "home-city-outline": F0D16, + "home-currency-usd": F08AF, + "home-edit": F1159, + "home-edit-outline": F115A, + "home-export-outline": F0F9B, + "home-flood": F0EFA, + "home-floor-0": F0DD2, + "home-floor-1": F0D80, + "home-floor-2": F0D81, + "home-floor-3": F0D82, + "home-floor-a": F0D83, + "home-floor-b": F0D84, + "home-floor-g": F0D85, + "home-floor-l": F0D86, + "home-floor-negative-1": F0DD3, + "home-group": F0DD4, + "home-heart": F0827, + "home-import-outline": F0F9C, + "home-lightbulb": F1251, + "home-lightbulb-outline": F1252, + "home-lock": F08EB, + "home-lock-open": F08EC, + "home-map-marker": F05F8, + "home-minus": F0974, + "home-minus-outline": F13D5, + "home-modern": F02DD, + "home-outline": F06A1, + "home-plus": F0975, + "home-plus-outline": F13D6, + "home-remove": F1247, + "home-remove-outline": F13D7, + "home-roof": F112B, + "home-search": F13B0, + "home-search-outline": F13B1, + "home-thermometer": F0F54, + "home-thermometer-outline": F0F55, + "home-variant": F02DE, + "home-variant-outline": F0BA7, + "hook": F06E2, + "hook-off": F06E3, + "hops": F02DF, + "horizontal-rotate-clockwise": F10F3, + "horizontal-rotate-counterclockwise": F10F4, + "horse": F15BF, + "horse-human": F15C0, + "horse-variant": F15C1, + "horseshoe": F0A58, + "hospital": F0FF6, + "hospital-box": F02E0, + "hospital-box-outline": F0FF7, + "hospital-building": F02E1, + "hospital-marker": F02E2, + "hot-tub": F0828, + "hours-24": F1478, + "hubspot": F0D17, + "hulu": F0829, + "human": F02E6, + "human-baby-changing-table": F138B, + "human-cane": F1581, + "human-capacity-decrease": F159B, + "human-capacity-increase": F159C, + "human-child": F02E7, + "human-edit": F14E8, + "human-female": F0649, + "human-female-boy": F0A59, + "human-female-dance": F15C9, + "human-female-female": F0A5A, + "human-female-girl": F0A5B, + "human-greeting": F064A, + "human-greeting-proximity": F159D, + "human-handsdown": F064B, + "human-handsup": F064C, + "human-male": F064D, + "human-male-boy": F0A5C, + "human-male-child": F138C, + "human-male-female": F02E8, + "human-male-girl": F0A5D, + "human-male-height": F0EFB, + "human-male-height-variant": F0EFC, + "human-male-male": F0A5E, + "human-pregnant": F05CF, + "human-queue": F1571, + "human-scooter": F11E9, + "human-wheelchair": F138D, + "humble-bundle": F0744, + "hvac": F1352, + "hvac-off": F159E, + "hydraulic-oil-level": F1324, + "hydraulic-oil-temperature": F1325, + "hydro-power": F12E5, + "ice-cream": F082A, + "ice-cream-off": F0E52, + "ice-pop": F0EFD, + "id-card": F0FC0, + "identifier": F0EFE, + "ideogram-cjk": F1331, + "ideogram-cjk-variant": F1332, + "iframe": F0C8B, + "iframe-array": F10F5, + "iframe-array-outline": F10F6, + "iframe-braces": F10F7, + "iframe-braces-outline": F10F8, + "iframe-outline": F0C8C, + "iframe-parentheses": F10F9, + "iframe-parentheses-outline": F10FA, + "iframe-variable": F10FB, + "iframe-variable-outline": F10FC, + "image": F02E9, + "image-album": F02EA, + "image-area": F02EB, + "image-area-close": F02EC, + "image-auto-adjust": F0FC1, + "image-broken": F02ED, + "image-broken-variant": F02EE, + "image-edit": F11E3, + "image-edit-outline": F11E4, + "image-filter-black-white": F02F0, + "image-filter-center-focus": F02F1, + "image-filter-center-focus-strong": F0EFF, + "image-filter-center-focus-strong-outline": F0F00, + "image-filter-center-focus-weak": F02F2, + "image-filter-drama": F02F3, + "image-filter-frames": F02F4, + "image-filter-hdr": F02F5, + "image-filter-none": F02F6, + "image-filter-tilt-shift": F02F7, + "image-filter-vintage": F02F8, + "image-frame": F0E49, + "image-minus": F1419, + "image-move": F09F8, + "image-multiple": F02F9, + "image-multiple-outline": F02EF, + "image-off": F082B, + "image-off-outline": F11D1, + "image-outline": F0976, + "image-plus": F087C, + "image-remove": F1418, + "image-search": F0977, + "image-search-outline": F0978, + "image-size-select-actual": F0C8D, + "image-size-select-large": F0C8E, + "image-size-select-small": F0C8F, + "image-text": F160D, + "import": F02FA, + "inbox": F0687, + "inbox-arrow-down": F02FB, + "inbox-arrow-down-outline": F1270, + "inbox-arrow-up": F03D1, + "inbox-arrow-up-outline": F1271, + "inbox-full": F1272, + "inbox-full-outline": F1273, + "inbox-multiple": F08B0, + "inbox-multiple-outline": F0BA8, + "inbox-outline": F1274, + "inbox-remove": F159F, + "inbox-remove-outline": F15A0, + "incognito": F05F9, + "incognito-circle": F1421, + "incognito-circle-off": F1422, + "incognito-off": F0075, + "infinity": F06E4, + "information": F02FC, + "information-outline": F02FD, + "information-variant": F064E, + "instagram": F02FE, + "instrument-triangle": F104E, + "invert-colors": F0301, + "invert-colors-off": F0E4A, + "iobroker": F12E8, + "ip": F0A5F, + "ip-network": F0A60, + "ip-network-outline": F0C90, + "ipod": F0C91, + "islam": F0979, + "island": F104F, + "iv-bag": F10B9, + "jabber": F0DD5, + "jeepney": F0302, + "jellyfish": F0F01, + "jellyfish-outline": F0F02, + "jira": F0303, + "jquery": F087D, + "jsfiddle": F0304, + "judaism": F097A, + "jump-rope": F12FF, + "kabaddi": F0D87, + "kangaroo": F1558, + "karate": F082C, + "keg": F0305, + "kettle": F05FA, + "kettle-alert": F1317, + "kettle-alert-outline": F1318, + "kettle-off": F131B, + "kettle-off-outline": F131C, + "kettle-outline": F0F56, + "kettle-steam": F1319, + "kettle-steam-outline": F131A, + "kettlebell": F1300, + "key": F0306, + "key-arrow-right": F1312, + "key-chain": F1574, + "key-chain-variant": F1575, + "key-change": F0307, + "key-link": F119F, + "key-minus": F0308, + "key-outline": F0DD6, + "key-plus": F0309, + "key-remove": F030A, + "key-star": F119E, + "key-variant": F030B, + "key-wireless": F0FC2, + "keyboard": F030C, + "keyboard-backspace": F030D, + "keyboard-caps": F030E, + "keyboard-close": F030F, + "keyboard-esc": F12B7, + "keyboard-f1": F12AB, + "keyboard-f10": F12B4, + "keyboard-f11": F12B5, + "keyboard-f12": F12B6, + "keyboard-f2": F12AC, + "keyboard-f3": F12AD, + "keyboard-f4": F12AE, + "keyboard-f5": F12AF, + "keyboard-f6": F12B0, + "keyboard-f7": F12B1, + "keyboard-f8": F12B2, + "keyboard-f9": F12B3, + "keyboard-off": F0310, + "keyboard-off-outline": F0E4B, + "keyboard-outline": F097B, + "keyboard-return": F0311, + "keyboard-settings": F09F9, + "keyboard-settings-outline": F09FA, + "keyboard-space": F1050, + "keyboard-tab": F0312, + "keyboard-variant": F0313, + "khanda": F10FD, + "kickstarter": F0745, + "klingon": F135B, + "knife": F09FB, + "knife-military": F09FC, + "kodi": F0314, + "kubernetes": F10FE, + "label": F0315, + "label-multiple": F1375, + "label-multiple-outline": F1376, + "label-off": F0ACB, + "label-off-outline": F0ACC, + "label-outline": F0316, + "label-percent": F12EA, + "label-percent-outline": F12EB, + "label-variant": F0ACD, + "label-variant-outline": F0ACE, + "ladder": F15A2, + "ladybug": F082D, + "lambda": F0627, + "lamp": F06B5, + "lamps": F1576, + "lan": F0317, + "lan-check": F12AA, + "lan-connect": F0318, + "lan-disconnect": F0319, + "lan-pending": F031A, + "language-c": F0671, + "language-cpp": F0672, + "language-csharp": F031B, + "language-css3": F031C, + "language-fortran": F121A, + "language-go": F07D3, + "language-haskell": F0C92, + "language-html5": F031D, + "language-java": F0B37, + "language-javascript": F031E, + "language-kotlin": F1219, + "language-lua": F08B1, + "language-markdown": F0354, + "language-markdown-outline": F0F5B, + "language-php": F031F, + "language-python": F0320, + "language-r": F07D4, + "language-ruby": F0D2D, + "language-ruby-on-rails": F0ACF, + "language-rust": F1617, + "language-swift": F06E5, + "language-typescript": F06E6, + "language-xaml": F0673, + "laptop": F0322, + "laptop-chromebook": F0323, + "laptop-mac": F0324, + "laptop-off": F06E7, + "laptop-windows": F0325, + "laravel": F0AD0, + "laser-pointer": F1484, + "lasso": F0F03, + "lastpass": F0446, + "latitude": F0F57, + "launch": F0327, + "lava-lamp": F07D5, + "layers": F0328, + "layers-minus": F0E4C, + "layers-off": F0329, + "layers-off-outline": F09FD, + "layers-outline": F09FE, + "layers-plus": F0E4D, + "layers-remove": F0E4E, + "layers-search": F1206, + "layers-search-outline": F1207, + "layers-triple": F0F58, + "layers-triple-outline": F0F59, + "lead-pencil": F064F, + "leaf": F032A, + "leaf-maple": F0C93, + "leaf-maple-off": F12DA, + "leaf-off": F12D9, + "leak": F0DD7, + "leak-off": F0DD8, + "led-off": F032B, + "led-on": F032C, + "led-outline": F032D, + "led-strip": F07D6, + "led-strip-variant": F1051, + "led-variant-off": F032E, + "led-variant-on": F032F, + "led-variant-outline": F0330, + "leek": F117D, + "less-than": F097C, + "less-than-or-equal": F097D, + "library": F0331, + "library-shelves": F0BA9, + "license": F0FC3, + "lifebuoy": F087E, + "light-switch": F097E, + "lightbulb": F0335, + "lightbulb-cfl": F1208, + "lightbulb-cfl-off": F1209, + "lightbulb-cfl-spiral": F1275, + "lightbulb-cfl-spiral-off": F12C3, + "lightbulb-group": F1253, + "lightbulb-group-off": F12CD, + "lightbulb-group-off-outline": F12CE, + "lightbulb-group-outline": F1254, + "lightbulb-multiple": F1255, + "lightbulb-multiple-off": F12CF, + "lightbulb-multiple-off-outline": F12D0, + "lightbulb-multiple-outline": F1256, + "lightbulb-off": F0E4F, + "lightbulb-off-outline": F0E50, + "lightbulb-on": F06E8, + "lightbulb-on-outline": F06E9, + "lightbulb-outline": F0336, + "lighthouse": F09FF, + "lighthouse-on": F0A00, + "lightning-bolt": F140B, + "lightning-bolt-outline": F140C, + "lingerie": F1476, + "link": F0337, + "link-box": F0D1A, + "link-box-outline": F0D1B, + "link-box-variant": F0D1C, + "link-box-variant-outline": F0D1D, + "link-lock": F10BA, + "link-off": F0338, + "link-plus": F0C94, + "link-variant": F0339, + "link-variant-minus": F10FF, + "link-variant-off": F033A, + "link-variant-plus": F1100, + "link-variant-remove": F1101, + "linkedin": F033B, + "linux": F033D, + "linux-mint": F08ED, + "lipstick": F13B5, + "list-status": F15AB, + "litecoin": F0A61, + "loading": F0772, + "location-enter": F0FC4, + "location-exit": F0FC5, + "lock": F033E, + "lock-alert": F08EE, + "lock-alert-outline": F15D1, + "lock-check": F139A, + "lock-check-outline": F16A8, + "lock-clock": F097F, + "lock-minus": F16A9, + "lock-minus-outline": F16AA, + "lock-off": F1671, + "lock-off-outline": F1672, + "lock-open": F033F, + "lock-open-alert": F139B, + "lock-open-alert-outline": F15D2, + "lock-open-check": F139C, + "lock-open-check-outline": F16AB, + "lock-open-minus": F16AC, + "lock-open-minus-outline": F16AD, + "lock-open-outline": F0340, + "lock-open-plus": F16AE, + "lock-open-plus-outline": F16AF, + "lock-open-remove": F16B0, + "lock-open-remove-outline": F16B1, + "lock-open-variant": F0FC6, + "lock-open-variant-outline": F0FC7, + "lock-outline": F0341, + "lock-pattern": F06EA, + "lock-plus": F05FB, + "lock-plus-outline": F16B2, + "lock-question": F08EF, + "lock-remove": F16B3, + "lock-remove-outline": F16B4, + "lock-reset": F0773, + "lock-smart": F08B2, + "locker": F07D7, + "locker-multiple": F07D8, + "login": F0342, + "login-variant": F05FC, + "logout": F0343, + "logout-variant": F05FD, + "longitude": F0F5A, + "looks": F0344, + "lotion": F1582, + "lotion-outline": F1583, + "lotion-plus": F1584, + "lotion-plus-outline": F1585, + "loupe": F0345, + "lumx": F0346, + "lungs": F1084, + "magnet": F0347, + "magnet-on": F0348, + "magnify": F0349, + "magnify-close": F0980, + "magnify-minus": F034A, + "magnify-minus-cursor": F0A62, + "magnify-minus-outline": F06EC, + "magnify-plus": F034B, + "magnify-plus-cursor": F0A63, + "magnify-plus-outline": F06ED, + "magnify-remove-cursor": F120C, + "magnify-remove-outline": F120D, + "magnify-scan": F1276, + "mail": F0EBB, + "mailbox": F06EE, + "mailbox-open": F0D88, + "mailbox-open-outline": F0D89, + "mailbox-open-up": F0D8A, + "mailbox-open-up-outline": F0D8B, + "mailbox-outline": F0D8C, + "mailbox-up": F0D8D, + "mailbox-up-outline": F0D8E, + "manjaro": F160A, + "map": F034D, + "map-check": F0EBC, + "map-check-outline": F0EBD, + "map-clock": F0D1E, + "map-clock-outline": F0D1F, + "map-legend": F0A01, + "map-marker": F034E, + "map-marker-alert": F0F05, + "map-marker-alert-outline": F0F06, + "map-marker-check": F0C95, + "map-marker-check-outline": F12FB, + "map-marker-circle": F034F, + "map-marker-distance": F08F0, + "map-marker-down": F1102, + "map-marker-left": F12DB, + "map-marker-left-outline": F12DD, + "map-marker-minus": F0650, + "map-marker-minus-outline": F12F9, + "map-marker-multiple": F0350, + "map-marker-multiple-outline": F1277, + "map-marker-off": F0351, + "map-marker-off-outline": F12FD, + "map-marker-outline": F07D9, + "map-marker-path": F0D20, + "map-marker-plus": F0651, + "map-marker-plus-outline": F12F8, + "map-marker-question": F0F07, + "map-marker-question-outline": F0F08, + "map-marker-radius": F0352, + "map-marker-radius-outline": F12FC, + "map-marker-remove": F0F09, + "map-marker-remove-outline": F12FA, + "map-marker-remove-variant": F0F0A, + "map-marker-right": F12DC, + "map-marker-right-outline": F12DE, + "map-marker-star": F1608, + "map-marker-star-outline": F1609, + "map-marker-up": F1103, + "map-minus": F0981, + "map-outline": F0982, + "map-plus": F0983, + "map-search": F0984, + "map-search-outline": F0985, + "mapbox": F0BAA, + "margin": F0353, + "marker": F0652, + "marker-cancel": F0DD9, + "marker-check": F0355, + "mastodon": F0AD1, + "material-design": F0986, + "material-ui": F0357, + "math-compass": F0358, + "math-cos": F0C96, + "math-integral": F0FC8, + "math-integral-box": F0FC9, + "math-log": F1085, + "math-norm": F0FCA, + "math-norm-box": F0FCB, + "math-sin": F0C97, + "math-tan": F0C98, + "matrix": F0628, + "medal": F0987, + "medal-outline": F1326, + "medical-bag": F06EF, + "meditation": F117B, + "memory": F035B, + "menu": F035C, + "menu-down": F035D, + "menu-down-outline": F06B6, + "menu-left": F035E, + "menu-left-outline": F0A02, + "menu-open": F0BAB, + "menu-right": F035F, + "menu-right-outline": F0A03, + "menu-swap": F0A64, + "menu-swap-outline": F0A65, + "menu-up": F0360, + "menu-up-outline": F06B7, + "merge": F0F5C, + "message": F0361, + "message-alert": F0362, + "message-alert-outline": F0A04, + "message-arrow-left": F12F2, + "message-arrow-left-outline": F12F3, + "message-arrow-right": F12F4, + "message-arrow-right-outline": F12F5, + "message-bookmark": F15AC, + "message-bookmark-outline": F15AD, + "message-bulleted": F06A2, + "message-bulleted-off": F06A3, + "message-cog": F06F1, + "message-cog-outline": F1172, + "message-draw": F0363, + "message-flash": F15A9, + "message-flash-outline": F15AA, + "message-image": F0364, + "message-image-outline": F116C, + "message-lock": F0FCC, + "message-lock-outline": F116D, + "message-minus": F116E, + "message-minus-outline": F116F, + "message-off": F164D, + "message-off-outline": F164E, + "message-outline": F0365, + "message-plus": F0653, + "message-plus-outline": F10BB, + "message-processing": F0366, + "message-processing-outline": F1170, + "message-reply": F0367, + "message-reply-text": F0368, + "message-settings": F06F0, + "message-settings-outline": F1171, + "message-text": F0369, + "message-text-clock": F1173, + "message-text-clock-outline": F1174, + "message-text-lock": F0FCD, + "message-text-lock-outline": F1175, + "message-text-outline": F036A, + "message-video": F036B, + "meteor": F0629, + "metronome": F07DA, + "metronome-tick": F07DB, + "micro-sd": F07DC, + "microphone": F036C, + "microphone-minus": F08B3, + "microphone-off": F036D, + "microphone-outline": F036E, + "microphone-plus": F08B4, + "microphone-settings": F036F, + "microphone-variant": F0370, + "microphone-variant-off": F0371, + "microscope": F0654, + "microsoft": F0372, + "microsoft-access": F138E, + "microsoft-azure": F0805, + "microsoft-azure-devops": F0FD5, + "microsoft-bing": F00A4, + "microsoft-dynamics-365": F0988, + "microsoft-edge": F01E9, + "microsoft-edge-legacy": F1250, + "microsoft-excel": F138F, + "microsoft-internet-explorer": F0300, + "microsoft-office": F03C6, + "microsoft-onedrive": F03CA, + "microsoft-onenote": F0747, + "microsoft-outlook": F0D22, + "microsoft-powerpoint": F1390, + "microsoft-sharepoint": F1391, + "microsoft-teams": F02BB, + "microsoft-visual-studio": F0610, + "microsoft-visual-studio-code": F0A1E, + "microsoft-windows": F05B3, + "microsoft-windows-classic": F0A21, + "microsoft-word": F1392, + "microsoft-xbox": F05B9, + "microsoft-xbox-controller": F05BA, + "microsoft-xbox-controller-battery-alert": F074B, + "microsoft-xbox-controller-battery-charging": F0A22, + "microsoft-xbox-controller-battery-empty": F074C, + "microsoft-xbox-controller-battery-full": F074D, + "microsoft-xbox-controller-battery-low": F074E, + "microsoft-xbox-controller-battery-medium": F074F, + "microsoft-xbox-controller-battery-unknown": F0750, + "microsoft-xbox-controller-menu": F0E6F, + "microsoft-xbox-controller-off": F05BB, + "microsoft-xbox-controller-view": F0E70, + "microsoft-yammer": F0789, + "microwave": F0C99, + "microwave-off": F1423, + "middleware": F0F5D, + "middleware-outline": F0F5E, + "midi": F08F1, + "midi-port": F08F2, + "mine": F0DDA, + "minecraft": F0373, + "mini-sd": F0A05, + "minidisc": F0A06, + "minus": F0374, + "minus-box": F0375, + "minus-box-multiple": F1141, + "minus-box-multiple-outline": F1142, + "minus-box-outline": F06F2, + "minus-circle": F0376, + "minus-circle-multiple": F035A, + "minus-circle-multiple-outline": F0AD3, + "minus-circle-off": F1459, + "minus-circle-off-outline": F145A, + "minus-circle-outline": F0377, + "minus-network": F0378, + "minus-network-outline": F0C9A, + "minus-thick": F1639, + "mirror": F11FD, + "mixed-martial-arts": F0D8F, + "mixed-reality": F087F, + "molecule": F0BAC, + "molecule-co": F12FE, + "molecule-co2": F07E4, + "monitor": F0379, + "monitor-cellphone": F0989, + "monitor-cellphone-star": F098A, + "monitor-clean": F1104, + "monitor-dashboard": F0A07, + "monitor-edit": F12C6, + "monitor-eye": F13B4, + "monitor-lock": F0DDB, + "monitor-multiple": F037A, + "monitor-off": F0D90, + "monitor-screenshot": F0E51, + "monitor-share": F1483, + "monitor-speaker": F0F5F, + "monitor-speaker-off": F0F60, + "monitor-star": F0DDC, + "moon-first-quarter": F0F61, + "moon-full": F0F62, + "moon-last-quarter": F0F63, + "moon-new": F0F64, + "moon-waning-crescent": F0F65, + "moon-waning-gibbous": F0F66, + "moon-waxing-crescent": F0F67, + "moon-waxing-gibbous": F0F68, + "moped": F1086, + "moped-electric": F15B7, + "moped-electric-outline": F15B8, + "moped-outline": F15B9, + "more": F037B, + "mother-heart": F1314, + "mother-nurse": F0D21, + "motion": F15B2, + "motion-outline": F15B3, + "motion-pause": F1590, + "motion-pause-outline": F1592, + "motion-play": F158F, + "motion-play-outline": F1591, + "motion-sensor": F0D91, + "motion-sensor-off": F1435, + "motorbike": F037C, + "motorbike-electric": F15BA, + "mouse": F037D, + "mouse-bluetooth": F098B, + "mouse-move-down": F1550, + "mouse-move-up": F1551, + "mouse-move-vertical": F1552, + "mouse-off": F037E, + "mouse-variant": F037F, + "mouse-variant-off": F0380, + "move-resize": F0655, + "move-resize-variant": F0656, + "movie": F0381, + "movie-edit": F1122, + "movie-edit-outline": F1123, + "movie-filter": F1124, + "movie-filter-outline": F1125, + "movie-open": F0FCE, + "movie-open-outline": F0FCF, + "movie-outline": F0DDD, + "movie-roll": F07DE, + "movie-search": F11D2, + "movie-search-outline": F11D3, + "mower": F166F, + "mower-bag": F1670, + "muffin": F098C, + "multiplication": F0382, + "multiplication-box": F0383, + "mushroom": F07DF, + "mushroom-off": F13FA, + "mushroom-off-outline": F13FB, + "mushroom-outline": F07E0, + "music": F075A, + "music-accidental-double-flat": F0F69, + "music-accidental-double-sharp": F0F6A, + "music-accidental-flat": F0F6B, + "music-accidental-natural": F0F6C, + "music-accidental-sharp": F0F6D, + "music-box": F0384, + "music-box-multiple": F0333, + "music-box-multiple-outline": F0F04, + "music-box-outline": F0385, + "music-circle": F0386, + "music-circle-outline": F0AD4, + "music-clef-alto": F0F6E, + "music-clef-bass": F0F6F, + "music-clef-treble": F0F70, + "music-note": F0387, + "music-note-bluetooth": F05FE, + "music-note-bluetooth-off": F05FF, + "music-note-eighth": F0388, + "music-note-eighth-dotted": F0F71, + "music-note-half": F0389, + "music-note-half-dotted": F0F72, + "music-note-off": F038A, + "music-note-off-outline": F0F73, + "music-note-outline": F0F74, + "music-note-plus": F0DDE, + "music-note-quarter": F038B, + "music-note-quarter-dotted": F0F75, + "music-note-sixteenth": F038C, + "music-note-sixteenth-dotted": F0F76, + "music-note-whole": F038D, + "music-note-whole-dotted": F0F77, + "music-off": F075B, + "music-rest-eighth": F0F78, + "music-rest-half": F0F79, + "music-rest-quarter": F0F7A, + "music-rest-sixteenth": F0F7B, + "music-rest-whole": F0F7C, + "mustache": F15DE, + "nail": F0DDF, + "nas": F08F3, + "nativescript": F0880, + "nature": F038E, + "nature-people": F038F, + "navigation": F0390, + "navigation-outline": F1607, + "near-me": F05CD, + "necklace": F0F0B, + "needle": F0391, + "netflix": F0746, + "network": F06F3, + "network-off": F0C9B, + "network-off-outline": F0C9C, + "network-outline": F0C9D, + "network-strength-1": F08F4, + "network-strength-1-alert": F08F5, + "network-strength-2": F08F6, + "network-strength-2-alert": F08F7, + "network-strength-3": F08F8, + "network-strength-3-alert": F08F9, + "network-strength-4": F08FA, + "network-strength-4-alert": F08FB, + "network-strength-off": F08FC, + "network-strength-off-outline": F08FD, + "network-strength-outline": F08FE, + "new-box": F0394, + "newspaper": F0395, + "newspaper-minus": F0F0C, + "newspaper-plus": F0F0D, + "newspaper-variant": F1001, + "newspaper-variant-multiple": F1002, + "newspaper-variant-multiple-outline": F1003, + "newspaper-variant-outline": F1004, + "nfc": F0396, + "nfc-search-variant": F0E53, + "nfc-tap": F0397, + "nfc-variant": F0398, + "nfc-variant-off": F0E54, + "ninja": F0774, + "nintendo-game-boy": F1393, + "nintendo-switch": F07E1, + "nintendo-wii": F05AB, + "nintendo-wiiu": F072D, + "nix": F1105, + "nodejs": F0399, + "noodles": F117E, + "not-equal": F098D, + "not-equal-variant": F098E, + "note": F039A, + "note-minus": F164F, + "note-minus-outline": F1650, + "note-multiple": F06B8, + "note-multiple-outline": F06B9, + "note-outline": F039B, + "note-plus": F039C, + "note-plus-outline": F039D, + "note-remove": F1651, + "note-remove-outline": F1652, + "note-search": F1653, + "note-search-outline": F1654, + "note-text": F039E, + "note-text-outline": F11D7, + "notebook": F082E, + "notebook-check": F14F5, + "notebook-check-outline": F14F6, + "notebook-edit": F14E7, + "notebook-edit-outline": F14E9, + "notebook-minus": F1610, + "notebook-minus-outline": F1611, + "notebook-multiple": F0E55, + "notebook-outline": F0EBF, + "notebook-plus": F1612, + "notebook-plus-outline": F1613, + "notebook-remove": F1614, + "notebook-remove-outline": F1615, + "notification-clear-all": F039F, + "npm": F06F7, + "nuke": F06A4, + "null": F07E2, + "numeric": F03A0, + "numeric-0": F0B39, + "numeric-0-box": F03A1, + "numeric-0-box-multiple": F0F0E, + "numeric-0-box-multiple-outline": F03A2, + "numeric-0-box-outline": F03A3, + "numeric-0-circle": F0C9E, + "numeric-0-circle-outline": F0C9F, + "numeric-1": F0B3A, + "numeric-1-box": F03A4, + "numeric-1-box-multiple": F0F0F, + "numeric-1-box-multiple-outline": F03A5, + "numeric-1-box-outline": F03A6, + "numeric-1-circle": F0CA0, + "numeric-1-circle-outline": F0CA1, + "numeric-10": F0FE9, + "numeric-10-box": F0F7D, + "numeric-10-box-multiple": F0FEA, + "numeric-10-box-multiple-outline": F0FEB, + "numeric-10-box-outline": F0F7E, + "numeric-10-circle": F0FEC, + "numeric-10-circle-outline": F0FED, + "numeric-2": F0B3B, + "numeric-2-box": F03A7, + "numeric-2-box-multiple": F0F10, + "numeric-2-box-multiple-outline": F03A8, + "numeric-2-box-outline": F03A9, + "numeric-2-circle": F0CA2, + "numeric-2-circle-outline": F0CA3, + "numeric-3": F0B3C, + "numeric-3-box": F03AA, + "numeric-3-box-multiple": F0F11, + "numeric-3-box-multiple-outline": F03AB, + "numeric-3-box-outline": F03AC, + "numeric-3-circle": F0CA4, + "numeric-3-circle-outline": F0CA5, + "numeric-4": F0B3D, + "numeric-4-box": F03AD, + "numeric-4-box-multiple": F0F12, + "numeric-4-box-multiple-outline": F03B2, + "numeric-4-box-outline": F03AE, + "numeric-4-circle": F0CA6, + "numeric-4-circle-outline": F0CA7, + "numeric-5": F0B3E, + "numeric-5-box": F03B1, + "numeric-5-box-multiple": F0F13, + "numeric-5-box-multiple-outline": F03AF, + "numeric-5-box-outline": F03B0, + "numeric-5-circle": F0CA8, + "numeric-5-circle-outline": F0CA9, + "numeric-6": F0B3F, + "numeric-6-box": F03B3, + "numeric-6-box-multiple": F0F14, + "numeric-6-box-multiple-outline": F03B4, + "numeric-6-box-outline": F03B5, + "numeric-6-circle": F0CAA, + "numeric-6-circle-outline": F0CAB, + "numeric-7": F0B40, + "numeric-7-box": F03B6, + "numeric-7-box-multiple": F0F15, + "numeric-7-box-multiple-outline": F03B7, + "numeric-7-box-outline": F03B8, + "numeric-7-circle": F0CAC, + "numeric-7-circle-outline": F0CAD, + "numeric-8": F0B41, + "numeric-8-box": F03B9, + "numeric-8-box-multiple": F0F16, + "numeric-8-box-multiple-outline": F03BA, + "numeric-8-box-outline": F03BB, + "numeric-8-circle": F0CAE, + "numeric-8-circle-outline": F0CAF, + "numeric-9": F0B42, + "numeric-9-box": F03BC, + "numeric-9-box-multiple": F0F17, + "numeric-9-box-multiple-outline": F03BD, + "numeric-9-box-outline": F03BE, + "numeric-9-circle": F0CB0, + "numeric-9-circle-outline": F0CB1, + "numeric-9-plus": F0FEE, + "numeric-9-plus-box": F03BF, + "numeric-9-plus-box-multiple": F0F18, + "numeric-9-plus-box-multiple-outline": F03C0, + "numeric-9-plus-box-outline": F03C1, + "numeric-9-plus-circle": F0CB2, + "numeric-9-plus-circle-outline": F0CB3, + "numeric-negative-1": F1052, + "numeric-positive-1": F15CB, + "nut": F06F8, + "nutrition": F03C2, + "nuxt": F1106, + "oar": F067C, + "ocarina": F0DE0, + "oci": F12E9, + "ocr": F113A, + "octagon": F03C3, + "octagon-outline": F03C4, + "octagram": F06F9, + "octagram-outline": F0775, + "odnoklassniki": F03C5, + "offer": F121B, + "office-building": F0991, + "office-building-marker": F1520, + "office-building-marker-outline": F1521, + "office-building-outline": F151F, + "oil": F03C7, + "oil-lamp": F0F19, + "oil-level": F1053, + "oil-temperature": F0FF8, + "omega": F03C9, + "one-up": F0BAD, + "onepassword": F0881, + "opacity": F05CC, + "open-in-app": F03CB, + "open-in-new": F03CC, + "open-source-initiative": F0BAE, + "openid": F03CD, + "opera": F03CE, + "orbit": F0018, + "orbit-variant": F15DB, + "order-alphabetical-ascending": F020D, + "order-alphabetical-descending": F0D07, + "order-bool-ascending": F02BE, + "order-bool-ascending-variant": F098F, + "order-bool-descending": F1384, + "order-bool-descending-variant": F0990, + "order-numeric-ascending": F0545, + "order-numeric-descending": F0546, + "origin": F0B43, + "ornament": F03CF, + "ornament-variant": F03D0, + "outdoor-lamp": F1054, + "overscan": F1005, + "owl": F03D2, + "pac-man": F0BAF, + "package": F03D3, + "package-down": F03D4, + "package-up": F03D5, + "package-variant": F03D6, + "package-variant-closed": F03D7, + "page-first": F0600, + "page-last": F0601, + "page-layout-body": F06FA, + "page-layout-footer": F06FB, + "page-layout-header": F06FC, + "page-layout-header-footer": F0F7F, + "page-layout-sidebar-left": F06FD, + "page-layout-sidebar-right": F06FE, + "page-next": F0BB0, + "page-next-outline": F0BB1, + "page-previous": F0BB2, + "page-previous-outline": F0BB3, + "pail": F1417, + "pail-minus": F1437, + "pail-minus-outline": F143C, + "pail-off": F1439, + "pail-off-outline": F143E, + "pail-outline": F143A, + "pail-plus": F1436, + "pail-plus-outline": F143B, + "pail-remove": F1438, + "pail-remove-outline": F143D, + "palette": F03D8, + "palette-advanced": F03D9, + "palette-outline": F0E0C, + "palette-swatch": F08B5, + "palette-swatch-outline": F135C, + "palm-tree": F1055, + "pan": F0BB4, + "pan-bottom-left": F0BB5, + "pan-bottom-right": F0BB6, + "pan-down": F0BB7, + "pan-horizontal": F0BB8, + "pan-left": F0BB9, + "pan-right": F0BBA, + "pan-top-left": F0BBB, + "pan-top-right": F0BBC, + "pan-up": F0BBD, + "pan-vertical": F0BBE, + "panda": F03DA, + "pandora": F03DB, + "panorama": F03DC, + "panorama-fisheye": F03DD, + "panorama-horizontal": F03DE, + "panorama-vertical": F03DF, + "panorama-wide-angle": F03E0, + "paper-cut-vertical": F03E1, + "paper-roll": F1157, + "paper-roll-outline": F1158, + "paperclip": F03E2, + "parachute": F0CB4, + "parachute-outline": F0CB5, + "parking": F03E3, + "party-popper": F1056, + "passport": F07E3, + "passport-biometric": F0DE1, + "pasta": F1160, + "patio-heater": F0F80, + "patreon": F0882, + "pause": F03E4, + "pause-circle": F03E5, + "pause-circle-outline": F03E6, + "pause-octagon": F03E7, + "pause-octagon-outline": F03E8, + "paw": F03E9, + "paw-off": F0657, + "paw-off-outline": F1676, + "paw-outline": F1675, + "pdf-box": F0E56, + "peace": F0884, + "peanut": F0FFC, + "peanut-off": F0FFD, + "peanut-off-outline": F0FFF, + "peanut-outline": F0FFE, + "pen": F03EA, + "pen-lock": F0DE2, + "pen-minus": F0DE3, + "pen-off": F0DE4, + "pen-plus": F0DE5, + "pen-remove": F0DE6, + "pencil": F03EB, + "pencil-box": F03EC, + "pencil-box-multiple": F1144, + "pencil-box-multiple-outline": F1145, + "pencil-box-outline": F03ED, + "pencil-circle": F06FF, + "pencil-circle-outline": F0776, + "pencil-lock": F03EE, + "pencil-lock-outline": F0DE7, + "pencil-minus": F0DE8, + "pencil-minus-outline": F0DE9, + "pencil-off": F03EF, + "pencil-off-outline": F0DEA, + "pencil-outline": F0CB6, + "pencil-plus": F0DEB, + "pencil-plus-outline": F0DEC, + "pencil-remove": F0DED, + "pencil-remove-outline": F0DEE, + "pencil-ruler": F1353, + "penguin": F0EC0, + "pentagon": F0701, + "pentagon-outline": F0700, + "pentagram": F1667, + "percent": F03F0, + "percent-outline": F1278, + "periodic-table": F08B6, + "perspective-less": F0D23, + "perspective-more": F0D24, + "pharmacy": F03F1, + "phone": F03F2, + "phone-alert": F0F1A, + "phone-alert-outline": F118E, + "phone-bluetooth": F03F3, + "phone-bluetooth-outline": F118F, + "phone-cancel": F10BC, + "phone-cancel-outline": F1190, + "phone-check": F11A9, + "phone-check-outline": F11AA, + "phone-classic": F0602, + "phone-classic-off": F1279, + "phone-dial": F1559, + "phone-dial-outline": F155A, + "phone-forward": F03F4, + "phone-forward-outline": F1191, + "phone-hangup": F03F5, + "phone-hangup-outline": F1192, + "phone-in-talk": F03F6, + "phone-in-talk-outline": F1182, + "phone-incoming": F03F7, + "phone-incoming-outline": F1193, + "phone-lock": F03F8, + "phone-lock-outline": F1194, + "phone-log": F03F9, + "phone-log-outline": F1195, + "phone-message": F1196, + "phone-message-outline": F1197, + "phone-minus": F0658, + "phone-minus-outline": F1198, + "phone-missed": F03FA, + "phone-missed-outline": F11A5, + "phone-off": F0DEF, + "phone-off-outline": F11A6, + "phone-outgoing": F03FB, + "phone-outgoing-outline": F1199, + "phone-outline": F0DF0, + "phone-paused": F03FC, + "phone-paused-outline": F119A, + "phone-plus": F0659, + "phone-plus-outline": F119B, + "phone-remove": F152F, + "phone-remove-outline": F1530, + "phone-return": F082F, + "phone-return-outline": F119C, + "phone-ring": F11AB, + "phone-ring-outline": F11AC, + "phone-rotate-landscape": F0885, + "phone-rotate-portrait": F0886, + "phone-settings": F03FD, + "phone-settings-outline": F119D, + "phone-voip": F03FE, + "pi": F03FF, + "pi-box": F0400, + "pi-hole": F0DF1, + "piano": F067D, + "pickaxe": F08B7, + "picture-in-picture-bottom-right": F0E57, + "picture-in-picture-bottom-right-outline": F0E58, + "picture-in-picture-top-right": F0E59, + "picture-in-picture-top-right-outline": F0E5A, + "pier": F0887, + "pier-crane": F0888, + "pig": F0401, + "pig-variant": F1006, + "pig-variant-outline": F1678, + "piggy-bank": F1007, + "piggy-bank-outline": F1679, + "pill": F0402, + "pillar": F0702, + "pin": F0403, + "pin-off": F0404, + "pin-off-outline": F0930, + "pin-outline": F0931, + "pine-tree": F0405, + "pine-tree-box": F0406, + "pine-tree-fire": F141A, + "pinterest": F0407, + "pinwheel": F0AD5, + "pinwheel-outline": F0AD6, + "pipe": F07E5, + "pipe-disconnected": F07E6, + "pipe-leak": F0889, + "pipe-wrench": F1354, + "pirate": F0A08, + "pistol": F0703, + "piston": F088A, + "pitchfork": F1553, + "pizza": F0409, + "play": F040A, + "play-box": F127A, + "play-box-multiple": F0D19, + "play-box-multiple-outline": F13E6, + "play-box-outline": F040B, + "play-circle": F040C, + "play-circle-outline": F040D, + "play-network": F088B, + "play-network-outline": F0CB7, + "play-outline": F0F1B, + "play-pause": F040E, + "play-protected-content": F040F, + "play-speed": F08FF, + "playlist-check": F05C7, + "playlist-edit": F0900, + "playlist-minus": F0410, + "playlist-music": F0CB8, + "playlist-music-outline": F0CB9, + "playlist-play": F0411, + "playlist-plus": F0412, + "playlist-remove": F0413, + "playlist-star": F0DF2, + "plex": F06BA, + "plus": F0415, + "plus-box": F0416, + "plus-box-multiple": F0334, + "plus-box-multiple-outline": F1143, + "plus-box-outline": F0704, + "plus-circle": F0417, + "plus-circle-multiple": F034C, + "plus-circle-multiple-outline": F0418, + "plus-circle-outline": F0419, + "plus-minus": F0992, + "plus-minus-box": F0993, + "plus-minus-variant": F14C9, + "plus-network": F041A, + "plus-network-outline": F0CBA, + "plus-one": F041B, + "plus-outline": F0705, + "plus-thick": F11EC, + "podcast": F0994, + "podium": F0D25, + "podium-bronze": F0D26, + "podium-gold": F0D27, + "podium-silver": F0D28, + "point-of-sale": F0D92, + "pokeball": F041D, + "pokemon-go": F0A09, + "poker-chip": F0830, + "polaroid": F041E, + "police-badge": F1167, + "police-badge-outline": F1168, + "poll": F041F, + "poll-box": F0420, + "poll-box-outline": F127B, + "polo": F14C3, + "polymer": F0421, + "pool": F0606, + "popcorn": F0422, + "post": F1008, + "post-outline": F1009, + "postage-stamp": F0CBB, + "pot": F02E5, + "pot-mix": F065B, + "pot-mix-outline": F0677, + "pot-outline": F02FF, + "pot-steam": F065A, + "pot-steam-outline": F0326, + "pound": F0423, + "pound-box": F0424, + "pound-box-outline": F117F, + "power": F0425, + "power-cycle": F0901, + "power-off": F0902, + "power-on": F0903, + "power-plug": F06A5, + "power-plug-off": F06A6, + "power-plug-off-outline": F1424, + "power-plug-outline": F1425, + "power-settings": F0426, + "power-sleep": F0904, + "power-socket": F0427, + "power-socket-au": F0905, + "power-socket-de": F1107, + "power-socket-eu": F07E7, + "power-socket-fr": F1108, + "power-socket-it": F14FF, + "power-socket-jp": F1109, + "power-socket-uk": F07E8, + "power-socket-us": F07E9, + "power-standby": F0906, + "powershell": F0A0A, + "prescription": F0706, + "presentation": F0428, + "presentation-play": F0429, + "pretzel": F1562, + "printer": F042A, + "printer-3d": F042B, + "printer-3d-nozzle": F0E5B, + "printer-3d-nozzle-alert": F11C0, + "printer-3d-nozzle-alert-outline": F11C1, + "printer-3d-nozzle-outline": F0E5C, + "printer-alert": F042C, + "printer-check": F1146, + "printer-eye": F1458, + "printer-off": F0E5D, + "printer-pos": F1057, + "printer-search": F1457, + "printer-settings": F0707, + "printer-wireless": F0A0B, + "priority-high": F0603, + "priority-low": F0604, + "professional-hexagon": F042D, + "progress-alert": F0CBC, + "progress-check": F0995, + "progress-clock": F0996, + "progress-close": F110A, + "progress-download": F0997, + "progress-question": F1522, + "progress-upload": F0998, + "progress-wrench": F0CBD, + "projector": F042E, + "projector-screen": F042F, + "propane-tank": F1357, + "propane-tank-outline": F1358, + "protocol": F0FD8, + "publish": F06A7, + "pulse": F0430, + "pump": F1402, + "pumpkin": F0BBF, + "purse": F0F1C, + "purse-outline": F0F1D, + "puzzle": F0431, + "puzzle-check": F1426, + "puzzle-check-outline": F1427, + "puzzle-edit": F14D3, + "puzzle-edit-outline": F14D9, + "puzzle-heart": F14D4, + "puzzle-heart-outline": F14DA, + "puzzle-minus": F14D1, + "puzzle-minus-outline": F14D7, + "puzzle-outline": F0A66, + "puzzle-plus": F14D0, + "puzzle-plus-outline": F14D6, + "puzzle-remove": F14D2, + "puzzle-remove-outline": F14D8, + "puzzle-star": F14D5, + "puzzle-star-outline": F14DB, + "qi": F0999, + "qqchat": F0605, + "qrcode": F0432, + "qrcode-edit": F08B8, + "qrcode-minus": F118C, + "qrcode-plus": F118B, + "qrcode-remove": F118D, + "qrcode-scan": F0433, + "quadcopter": F0434, + "quality-high": F0435, + "quality-low": F0A0C, + "quality-medium": F0A0D, + "quora": F0D29, + "rabbit": F0907, + "racing-helmet": F0D93, + "racquetball": F0D94, + "radar": F0437, + "radiator": F0438, + "radiator-disabled": F0AD7, + "radiator-off": F0AD8, + "radio": F0439, + "radio-am": F0CBE, + "radio-fm": F0CBF, + "radio-handheld": F043A, + "radio-off": F121C, + "radio-tower": F043B, + "radioactive": F043C, + "radioactive-off": F0EC1, + "radiobox-blank": F043D, + "radiobox-marked": F043E, + "radiology-box": F14C5, + "radiology-box-outline": F14C6, + "radius": F0CC0, + "radius-outline": F0CC1, + "railroad-light": F0F1E, + "rake": F1544, + "raspberry-pi": F043F, + "ray-end": F0440, + "ray-end-arrow": F0441, + "ray-start": F0442, + "ray-start-arrow": F0443, + "ray-start-end": F0444, + "ray-start-vertex-end": F15D8, + "ray-vertex": F0445, + "react": F0708, + "read": F0447, + "receipt": F0449, + "record": F044A, + "record-circle": F0EC2, + "record-circle-outline": F0EC3, + "record-player": F099A, + "record-rec": F044B, + "rectangle": F0E5E, + "rectangle-outline": F0E5F, + "recycle": F044C, + "recycle-variant": F139D, + "reddit": F044D, + "redhat": F111B, + "redo": F044E, + "redo-variant": F044F, + "reflect-horizontal": F0A0E, + "reflect-vertical": F0A0F, + "refresh": F0450, + "refresh-circle": F1377, + "regex": F0451, + "registered-trademark": F0A67, + "reiterate": F1588, + "relation-many-to-many": F1496, + "relation-many-to-one": F1497, + "relation-many-to-one-or-many": F1498, + "relation-many-to-only-one": F1499, + "relation-many-to-zero-or-many": F149A, + "relation-many-to-zero-or-one": F149B, + "relation-one-or-many-to-many": F149C, + "relation-one-or-many-to-one": F149D, + "relation-one-or-many-to-one-or-many": F149E, + "relation-one-or-many-to-only-one": F149F, + "relation-one-or-many-to-zero-or-many": F14A0, + "relation-one-or-many-to-zero-or-one": F14A1, + "relation-one-to-many": F14A2, + "relation-one-to-one": F14A3, + "relation-one-to-one-or-many": F14A4, + "relation-one-to-only-one": F14A5, + "relation-one-to-zero-or-many": F14A6, + "relation-one-to-zero-or-one": F14A7, + "relation-only-one-to-many": F14A8, + "relation-only-one-to-one": F14A9, + "relation-only-one-to-one-or-many": F14AA, + "relation-only-one-to-only-one": F14AB, + "relation-only-one-to-zero-or-many": F14AC, + "relation-only-one-to-zero-or-one": F14AD, + "relation-zero-or-many-to-many": F14AE, + "relation-zero-or-many-to-one": F14AF, + "relation-zero-or-many-to-one-or-many": F14B0, + "relation-zero-or-many-to-only-one": F14B1, + "relation-zero-or-many-to-zero-or-many": F14B2, + "relation-zero-or-many-to-zero-or-one": F14B3, + "relation-zero-or-one-to-many": F14B4, + "relation-zero-or-one-to-one": F14B5, + "relation-zero-or-one-to-one-or-many": F14B6, + "relation-zero-or-one-to-only-one": F14B7, + "relation-zero-or-one-to-zero-or-many": F14B8, + "relation-zero-or-one-to-zero-or-one": F14B9, + "relative-scale": F0452, + "reload": F0453, + "reload-alert": F110B, + "reminder": F088C, + "remote": F0454, + "remote-desktop": F08B9, + "remote-off": F0EC4, + "remote-tv": F0EC5, + "remote-tv-off": F0EC6, + "rename-box": F0455, + "reorder-horizontal": F0688, + "reorder-vertical": F0689, + "repeat": F0456, + "repeat-off": F0457, + "repeat-once": F0458, + "replay": F0459, + "reply": F045A, + "reply-all": F045B, + "reply-all-outline": F0F1F, + "reply-circle": F11AE, + "reply-outline": F0F20, + "reproduction": F045C, + "resistor": F0B44, + "resistor-nodes": F0B45, + "resize": F0A68, + "resize-bottom-right": F045D, + "responsive": F045E, + "restart": F0709, + "restart-alert": F110C, + "restart-off": F0D95, + "restore": F099B, + "restore-alert": F110D, + "rewind": F045F, + "rewind-10": F0D2A, + "rewind-30": F0D96, + "rewind-5": F11F9, + "rewind-60": F160C, + "rewind-outline": F070A, + "rhombus": F070B, + "rhombus-medium": F0A10, + "rhombus-medium-outline": F14DC, + "rhombus-outline": F070C, + "rhombus-split": F0A11, + "rhombus-split-outline": F14DD, + "ribbon": F0460, + "rice": F07EA, + "rickshaw": F15BB, + "rickshaw-electric": F15BC, + "ring": F07EB, + "rivet": F0E60, + "road": F0461, + "road-variant": F0462, + "robber": F1058, + "robot": F06A9, + "robot-angry": F169D, + "robot-angry-outline": F169E, + "robot-confused": F169F, + "robot-confused-outline": F16A0, + "robot-dead": F16A1, + "robot-dead-outline": F16A2, + "robot-excited": F16A3, + "robot-excited-outline": F16A4, + "robot-industrial": F0B46, + "robot-love": F16A5, + "robot-love-outline": F16A6, + "robot-mower": F11F7, + "robot-mower-outline": F11F3, + "robot-off": F16A7, + "robot-off-outline": F167B, + "robot-outline": F167A, + "robot-vacuum": F070D, + "robot-vacuum-variant": F0908, + "rocket": F0463, + "rocket-launch": F14DE, + "rocket-launch-outline": F14DF, + "rocket-outline": F13AF, + "rodent": F1327, + "roller-skate": F0D2B, + "roller-skate-off": F0145, + "rollerblade": F0D2C, + "rollerblade-off": F002E, + "rollupjs": F0BC0, + "roman-numeral-1": F1088, + "roman-numeral-10": F1091, + "roman-numeral-2": F1089, + "roman-numeral-3": F108A, + "roman-numeral-4": F108B, + "roman-numeral-5": F108C, + "roman-numeral-6": F108D, + "roman-numeral-7": F108E, + "roman-numeral-8": F108F, + "roman-numeral-9": F1090, + "room-service": F088D, + "room-service-outline": F0D97, + "rotate-3d": F0EC7, + "rotate-3d-variant": F0464, + "rotate-left": F0465, + "rotate-left-variant": F0466, + "rotate-orbit": F0D98, + "rotate-right": F0467, + "rotate-right-variant": F0468, + "rounded-corner": F0607, + "router": F11E2, + "router-network": F1087, + "router-wireless": F0469, + "router-wireless-off": F15A3, + "router-wireless-settings": F0A69, + "routes": F046A, + "routes-clock": F1059, + "rowing": F0608, + "rss": F046B, + "rss-box": F046C, + "rss-off": F0F21, + "rug": F1475, + "rugby": F0D99, + "ruler": F046D, + "ruler-square": F0CC2, + "ruler-square-compass": F0EBE, + "run": F070E, + "run-fast": F046E, + "rv-truck": F11D4, + "sack": F0D2E, + "sack-percent": F0D2F, + "safe": F0A6A, + "safe-square": F127C, + "safe-square-outline": F127D, + "safety-goggles": F0D30, + "sail-boat": F0EC8, + "sale": F046F, + "salesforce": F088E, + "sass": F07EC, + "satellite": F0470, + "satellite-uplink": F0909, + "satellite-variant": F0471, + "sausage": F08BA, + "saw-blade": F0E61, + "sawtooth-wave": F147A, + "saxophone": F0609, + "scale": F0472, + "scale-balance": F05D1, + "scale-bathroom": F0473, + "scale-off": F105A, + "scan-helper": F13D8, + "scanner": F06AB, + "scanner-off": F090A, + "scatter-plot": F0EC9, + "scatter-plot-outline": F0ECA, + "school": F0474, + "school-outline": F1180, + "scissors-cutting": F0A6B, + "scooter": F15BD, + "scooter-electric": F15BE, + "scoreboard": F127E, + "scoreboard-outline": F127F, + "screen-rotation": F0475, + "screen-rotation-lock": F0478, + "screw-flat-top": F0DF3, + "screw-lag": F0DF4, + "screw-machine-flat-top": F0DF5, + "screw-machine-round-top": F0DF6, + "screw-round-top": F0DF7, + "screwdriver": F0476, + "script": F0BC1, + "script-outline": F0477, + "script-text": F0BC2, + "script-text-outline": F0BC3, + "sd": F0479, + "seal": F047A, + "seal-variant": F0FD9, + "search-web": F070F, + "seat": F0CC3, + "seat-flat": F047B, + "seat-flat-angled": F047C, + "seat-individual-suite": F047D, + "seat-legroom-extra": F047E, + "seat-legroom-normal": F047F, + "seat-legroom-reduced": F0480, + "seat-outline": F0CC4, + "seat-passenger": F1249, + "seat-recline-extra": F0481, + "seat-recline-normal": F0482, + "seatbelt": F0CC5, + "security": F0483, + "security-network": F0484, + "seed": F0E62, + "seed-off": F13FD, + "seed-off-outline": F13FE, + "seed-outline": F0E63, + "seesaw": F15A4, + "segment": F0ECB, + "select": F0485, + "select-all": F0486, + "select-color": F0D31, + "select-compare": F0AD9, + "select-drag": F0A6C, + "select-group": F0F82, + "select-inverse": F0487, + "select-marker": F1280, + "select-multiple": F1281, + "select-multiple-marker": F1282, + "select-off": F0488, + "select-place": F0FDA, + "select-search": F1204, + "selection": F0489, + "selection-drag": F0A6D, + "selection-ellipse": F0D32, + "selection-ellipse-arrow-inside": F0F22, + "selection-marker": F1283, + "selection-multiple": F1285, + "selection-multiple-marker": F1284, + "selection-off": F0777, + "selection-search": F1205, + "semantic-web": F1316, + "send": F048A, + "send-check": F1161, + "send-check-outline": F1162, + "send-circle": F0DF8, + "send-circle-outline": F0DF9, + "send-clock": F1163, + "send-clock-outline": F1164, + "send-lock": F07ED, + "send-lock-outline": F1166, + "send-outline": F1165, + "serial-port": F065C, + "server": F048B, + "server-minus": F048C, + "server-network": F048D, + "server-network-off": F048E, + "server-off": F048F, + "server-plus": F0490, + "server-remove": F0491, + "server-security": F0492, + "set-all": F0778, + "set-center": F0779, + "set-center-right": F077A, + "set-left": F077B, + "set-left-center": F077C, + "set-left-right": F077D, + "set-merge": F14E0, + "set-none": F077E, + "set-right": F077F, + "set-split": F14E1, + "set-square": F145D, + "set-top-box": F099F, + "settings-helper": F0A6E, + "shaker": F110E, + "shaker-outline": F110F, + "shape": F0831, + "shape-circle-plus": F065D, + "shape-outline": F0832, + "shape-oval-plus": F11FA, + "shape-plus": F0495, + "shape-polygon-plus": F065E, + "shape-rectangle-plus": F065F, + "shape-square-plus": F0660, + "shape-square-rounded-plus": F14FA, + "share": F0496, + "share-all": F11F4, + "share-all-outline": F11F5, + "share-circle": F11AD, + "share-off": F0F23, + "share-off-outline": F0F24, + "share-outline": F0932, + "share-variant": F0497, + "share-variant-outline": F1514, + "shark-fin": F1673, + "shark-fin-outline": F1674, + "sheep": F0CC6, + "shield": F0498, + "shield-account": F088F, + "shield-account-outline": F0A12, + "shield-account-variant": F15A7, + "shield-account-variant-outline": F15A8, + "shield-airplane": F06BB, + "shield-airplane-outline": F0CC7, + "shield-alert": F0ECC, + "shield-alert-outline": F0ECD, + "shield-bug": F13DA, + "shield-bug-outline": F13DB, + "shield-car": F0F83, + "shield-check": F0565, + "shield-check-outline": F0CC8, + "shield-cross": F0CC9, + "shield-cross-outline": F0CCA, + "shield-edit": F11A0, + "shield-edit-outline": F11A1, + "shield-half": F1360, + "shield-half-full": F0780, + "shield-home": F068A, + "shield-home-outline": F0CCB, + "shield-key": F0BC4, + "shield-key-outline": F0BC5, + "shield-link-variant": F0D33, + "shield-link-variant-outline": F0D34, + "shield-lock": F099D, + "shield-lock-outline": F0CCC, + "shield-off": F099E, + "shield-off-outline": F099C, + "shield-outline": F0499, + "shield-plus": F0ADA, + "shield-plus-outline": F0ADB, + "shield-refresh": F00AA, + "shield-refresh-outline": F01E0, + "shield-remove": F0ADC, + "shield-remove-outline": F0ADD, + "shield-search": F0D9A, + "shield-star": F113B, + "shield-star-outline": F113C, + "shield-sun": F105D, + "shield-sun-outline": F105E, + "shield-sync": F11A2, + "shield-sync-outline": F11A3, + "ship-wheel": F0833, + "shoe-ballet": F15CA, + "shoe-cleat": F15C7, + "shoe-formal": F0B47, + "shoe-heel": F0B48, + "shoe-print": F0DFA, + "shoe-sneaker": F15C8, + "shopping": F049A, + "shopping-music": F049B, + "shopping-outline": F11D5, + "shopping-search": F0F84, + "shore": F14F9, + "shovel": F0710, + "shovel-off": F0711, + "shower": F09A0, + "shower-head": F09A1, + "shredder": F049C, + "shuffle": F049D, + "shuffle-disabled": F049E, + "shuffle-variant": F049F, + "shuriken": F137F, + "sigma": F04A0, + "sigma-lower": F062B, + "sign-caution": F04A1, + "sign-direction": F0781, + "sign-direction-minus": F1000, + "sign-direction-plus": F0FDC, + "sign-direction-remove": F0FDD, + "sign-pole": F14F8, + "sign-real-estate": F1118, + "sign-text": F0782, + "signal": F04A2, + "signal-2g": F0712, + "signal-3g": F0713, + "signal-4g": F0714, + "signal-5g": F0A6F, + "signal-cellular-1": F08BC, + "signal-cellular-2": F08BD, + "signal-cellular-3": F08BE, + "signal-cellular-outline": F08BF, + "signal-distance-variant": F0E64, + "signal-hspa": F0715, + "signal-hspa-plus": F0716, + "signal-off": F0783, + "signal-variant": F060A, + "signature": F0DFB, + "signature-freehand": F0DFC, + "signature-image": F0DFD, + "signature-text": F0DFE, + "silo": F0B49, + "silverware": F04A3, + "silverware-clean": F0FDE, + "silverware-fork": F04A4, + "silverware-fork-knife": F0A70, + "silverware-spoon": F04A5, + "silverware-variant": F04A6, + "sim": F04A7, + "sim-alert": F04A8, + "sim-alert-outline": F15D3, + "sim-off": F04A9, + "sim-off-outline": F15D4, + "sim-outline": F15D5, + "simple-icons": F131D, + "sina-weibo": F0ADF, + "sine-wave": F095B, + "sitemap": F04AA, + "size-l": F13A6, + "size-m": F13A5, + "size-s": F13A4, + "size-xl": F13A7, + "size-xs": F13A3, + "size-xxl": F13A8, + "size-xxs": F13A2, + "size-xxxl": F13A9, + "skate": F0D35, + "skateboard": F14C2, + "skew-less": F0D36, + "skew-more": F0D37, + "ski": F1304, + "ski-cross-country": F1305, + "ski-water": F1306, + "skip-backward": F04AB, + "skip-backward-outline": F0F25, + "skip-forward": F04AC, + "skip-forward-outline": F0F26, + "skip-next": F04AD, + "skip-next-circle": F0661, + "skip-next-circle-outline": F0662, + "skip-next-outline": F0F27, + "skip-previous": F04AE, + "skip-previous-circle": F0663, + "skip-previous-circle-outline": F0664, + "skip-previous-outline": F0F28, + "skull": F068C, + "skull-crossbones": F0BC6, + "skull-crossbones-outline": F0BC7, + "skull-outline": F0BC8, + "skull-scan": F14C7, + "skull-scan-outline": F14C8, + "skype": F04AF, + "skype-business": F04B0, + "slack": F04B1, + "slash-forward": F0FDF, + "slash-forward-box": F0FE0, + "sleep": F04B2, + "sleep-off": F04B3, + "slide": F15A5, + "slope-downhill": F0DFF, + "slope-uphill": F0E00, + "slot-machine": F1114, + "slot-machine-outline": F1115, + "smart-card": F10BD, + "smart-card-outline": F10BE, + "smart-card-reader": F10BF, + "smart-card-reader-outline": F10C0, + "smog": F0A71, + "smoke-detector": F0392, + "smoking": F04B4, + "smoking-off": F04B5, + "smoking-pipe": F140D, + "smoking-pipe-off": F1428, + "snail": F1677, + "snake": F150E, + "snapchat": F04B6, + "snowboard": F1307, + "snowflake": F0717, + "snowflake-alert": F0F29, + "snowflake-melt": F12CB, + "snowflake-off": F14E3, + "snowflake-variant": F0F2A, + "snowman": F04B7, + "soccer": F04B8, + "soccer-field": F0834, + "social-distance-2-meters": F1579, + "social-distance-6-feet": F157A, + "sofa": F04B9, + "sofa-outline": F156D, + "sofa-single": F156E, + "sofa-single-outline": F156F, + "solar-panel": F0D9B, + "solar-panel-large": F0D9C, + "solar-power": F0A72, + "soldering-iron": F1092, + "solid": F068D, + "sony-playstation": F0414, + "sort": F04BA, + "sort-alphabetical-ascending": F05BD, + "sort-alphabetical-ascending-variant": F1148, + "sort-alphabetical-descending": F05BF, + "sort-alphabetical-descending-variant": F1149, + "sort-alphabetical-variant": F04BB, + "sort-ascending": F04BC, + "sort-bool-ascending": F1385, + "sort-bool-ascending-variant": F1386, + "sort-bool-descending": F1387, + "sort-bool-descending-variant": F1388, + "sort-calendar-ascending": F1547, + "sort-calendar-descending": F1548, + "sort-clock-ascending": F1549, + "sort-clock-ascending-outline": F154A, + "sort-clock-descending": F154B, + "sort-clock-descending-outline": F154C, + "sort-descending": F04BD, + "sort-numeric-ascending": F1389, + "sort-numeric-ascending-variant": F090D, + "sort-numeric-descending": F138A, + "sort-numeric-descending-variant": F0AD2, + "sort-numeric-variant": F04BE, + "sort-reverse-variant": F033C, + "sort-variant": F04BF, + "sort-variant-lock": F0CCD, + "sort-variant-lock-open": F0CCE, + "sort-variant-remove": F1147, + "soundcloud": F04C0, + "source-branch": F062C, + "source-branch-check": F14CF, + "source-branch-minus": F14CB, + "source-branch-plus": F14CA, + "source-branch-refresh": F14CD, + "source-branch-remove": F14CC, + "source-branch-sync": F14CE, + "source-commit": F0718, + "source-commit-end": F0719, + "source-commit-end-local": F071A, + "source-commit-local": F071B, + "source-commit-next-local": F071C, + "source-commit-start": F071D, + "source-commit-start-next-local": F071E, + "source-fork": F04C1, + "source-merge": F062D, + "source-pull": F04C2, + "source-repository": F0CCF, + "source-repository-multiple": F0CD0, + "soy-sauce": F07EE, + "soy-sauce-off": F13FC, + "spa": F0CD1, + "spa-outline": F0CD2, + "space-invaders": F0BC9, + "space-station": F1383, + "spade": F0E65, + "sparkles": F1545, + "speaker": F04C3, + "speaker-bluetooth": F09A2, + "speaker-multiple": F0D38, + "speaker-off": F04C4, + "speaker-wireless": F071F, + "speedometer": F04C5, + "speedometer-medium": F0F85, + "speedometer-slow": F0F86, + "spellcheck": F04C6, + "spider": F11EA, + "spider-thread": F11EB, + "spider-web": F0BCA, + "spirit-level": F14F1, + "spoon-sugar": F1429, + "spotify": F04C7, + "spotlight": F04C8, + "spotlight-beam": F04C9, + "spray": F0665, + "spray-bottle": F0AE0, + "sprinkler": F105F, + "sprinkler-variant": F1060, + "sprout": F0E66, + "sprout-outline": F0E67, + "square": F0764, + "square-circle": F1500, + "square-edit-outline": F090C, + "square-medium": F0A13, + "square-medium-outline": F0A14, + "square-off": F12EE, + "square-off-outline": F12EF, + "square-outline": F0763, + "square-root": F0784, + "square-root-box": F09A3, + "square-rounded": F14FB, + "square-rounded-outline": F14FC, + "square-small": F0A15, + "square-wave": F147B, + "squeegee": F0AE1, + "ssh": F08C0, + "stack-exchange": F060B, + "stack-overflow": F04CC, + "stackpath": F0359, + "stadium": F0FF9, + "stadium-variant": F0720, + "stairs": F04CD, + "stairs-box": F139E, + "stairs-down": F12BE, + "stairs-up": F12BD, + "stamper": F0D39, + "standard-definition": F07EF, + "star": F04CE, + "star-box": F0A73, + "star-box-multiple": F1286, + "star-box-multiple-outline": F1287, + "star-box-outline": F0A74, + "star-check": F1566, + "star-check-outline": F156A, + "star-circle": F04CF, + "star-circle-outline": F09A4, + "star-cog": F1668, + "star-cog-outline": F1669, + "star-face": F09A5, + "star-four-points": F0AE2, + "star-four-points-outline": F0AE3, + "star-half": F0246, + "star-half-full": F04D0, + "star-minus": F1564, + "star-minus-outline": F1568, + "star-off": F04D1, + "star-off-outline": F155B, + "star-outline": F04D2, + "star-plus": F1563, + "star-plus-outline": F1567, + "star-remove": F1565, + "star-remove-outline": F1569, + "star-settings": F166A, + "star-settings-outline": F166B, + "star-three-points": F0AE4, + "star-three-points-outline": F0AE5, + "state-machine": F11EF, + "steam": F04D3, + "steering": F04D4, + "steering-off": F090E, + "step-backward": F04D5, + "step-backward-2": F04D6, + "step-forward": F04D7, + "step-forward-2": F04D8, + "stethoscope": F04D9, + "sticker": F1364, + "sticker-alert": F1365, + "sticker-alert-outline": F1366, + "sticker-check": F1367, + "sticker-check-outline": F1368, + "sticker-circle-outline": F05D0, + "sticker-emoji": F0785, + "sticker-minus": F1369, + "sticker-minus-outline": F136A, + "sticker-outline": F136B, + "sticker-plus": F136C, + "sticker-plus-outline": F136D, + "sticker-remove": F136E, + "sticker-remove-outline": F136F, + "stocking": F04DA, + "stomach": F1093, + "stop": F04DB, + "stop-circle": F0666, + "stop-circle-outline": F0667, + "store": F04DC, + "store-24-hour": F04DD, + "store-minus": F165E, + "store-outline": F1361, + "store-plus": F165F, + "store-remove": F1660, + "storefront": F07C7, + "storefront-outline": F10C1, + "stove": F04DE, + "strategy": F11D6, + "stretch-to-page": F0F2B, + "stretch-to-page-outline": F0F2C, + "string-lights": F12BA, + "string-lights-off": F12BB, + "subdirectory-arrow-left": F060C, + "subdirectory-arrow-right": F060D, + "submarine": F156C, + "subtitles": F0A16, + "subtitles-outline": F0A17, + "subway": F06AC, + "subway-alert-variant": F0D9D, + "subway-variant": F04DF, + "summit": F0786, + "sunglasses": F04E0, + "surround-sound": F05C5, + "surround-sound-2-0": F07F0, + "surround-sound-3-1": F07F1, + "surround-sound-5-1": F07F2, + "surround-sound-7-1": F07F3, + "svg": F0721, + "swap-horizontal": F04E1, + "swap-horizontal-bold": F0BCD, + "swap-horizontal-circle": F0FE1, + "swap-horizontal-circle-outline": F0FE2, + "swap-horizontal-variant": F08C1, + "swap-vertical": F04E2, + "swap-vertical-bold": F0BCE, + "swap-vertical-circle": F0FE3, + "swap-vertical-circle-outline": F0FE4, + "swap-vertical-variant": F08C2, + "swim": F04E3, + "switch": F04E4, + "sword": F04E5, + "sword-cross": F0787, + "syllabary-hangul": F1333, + "syllabary-hiragana": F1334, + "syllabary-katakana": F1335, + "syllabary-katakana-halfwidth": F1336, + "symbol": F1501, + "symfony": F0AE6, + "sync": F04E6, + "sync-alert": F04E7, + "sync-circle": F1378, + "sync-off": F04E8, + "tab": F04E9, + "tab-minus": F0B4B, + "tab-plus": F075C, + "tab-remove": F0B4C, + "tab-unselected": F04EA, + "table": F04EB, + "table-account": F13B9, + "table-alert": F13BA, + "table-arrow-down": F13BB, + "table-arrow-left": F13BC, + "table-arrow-right": F13BD, + "table-arrow-up": F13BE, + "table-border": F0A18, + "table-cancel": F13BF, + "table-chair": F1061, + "table-check": F13C0, + "table-clock": F13C1, + "table-cog": F13C2, + "table-column": F0835, + "table-column-plus-after": F04EC, + "table-column-plus-before": F04ED, + "table-column-remove": F04EE, + "table-column-width": F04EF, + "table-edit": F04F0, + "table-eye": F1094, + "table-eye-off": F13C3, + "table-furniture": F05BC, + "table-headers-eye": F121D, + "table-headers-eye-off": F121E, + "table-heart": F13C4, + "table-key": F13C5, + "table-large": F04F1, + "table-large-plus": F0F87, + "table-large-remove": F0F88, + "table-lock": F13C6, + "table-merge-cells": F09A6, + "table-minus": F13C7, + "table-multiple": F13C8, + "table-network": F13C9, + "table-of-contents": F0836, + "table-off": F13CA, + "table-plus": F0A75, + "table-refresh": F13A0, + "table-remove": F0A76, + "table-row": F0837, + "table-row-height": F04F2, + "table-row-plus-after": F04F3, + "table-row-plus-before": F04F4, + "table-row-remove": F04F5, + "table-search": F090F, + "table-settings": F0838, + "table-split-cell": F142A, + "table-star": F13CB, + "table-sync": F13A1, + "table-tennis": F0E68, + "tablet": F04F6, + "tablet-android": F04F7, + "tablet-cellphone": F09A7, + "tablet-dashboard": F0ECE, + "tablet-ipad": F04F8, + "taco": F0762, + "tag": F04F9, + "tag-faces": F04FA, + "tag-heart": F068B, + "tag-heart-outline": F0BCF, + "tag-minus": F0910, + "tag-minus-outline": F121F, + "tag-multiple": F04FB, + "tag-multiple-outline": F12F7, + "tag-off": F1220, + "tag-off-outline": F1221, + "tag-outline": F04FC, + "tag-plus": F0722, + "tag-plus-outline": F1222, + "tag-remove": F0723, + "tag-remove-outline": F1223, + "tag-text": F1224, + "tag-text-outline": F04FD, + "tailwind": F13FF, + "tank": F0D3A, + "tanker-truck": F0FE5, + "tape-drive": F16DF, + "tape-measure": F0B4D, + "target": F04FE, + "target-account": F0BD0, + "target-variant": F0A77, + "taxi": F04FF, + "tea": F0D9E, + "tea-outline": F0D9F, + "teach": F0890, + "teamviewer": F0500, + "telegram": F0501, + "telescope": F0B4E, + "television": F0502, + "television-ambient-light": F1356, + "television-box": F0839, + "television-classic": F07F4, + "television-classic-off": F083A, + "television-clean": F1110, + "television-guide": F0503, + "television-off": F083B, + "television-pause": F0F89, + "television-play": F0ECF, + "television-stop": F0F8A, + "temperature-celsius": F0504, + "temperature-fahrenheit": F0505, + "temperature-kelvin": F0506, + "tennis": F0DA0, + "tennis-ball": F0507, + "tent": F0508, + "terraform": F1062, + "terrain": F0509, + "test-tube": F0668, + "test-tube-empty": F0911, + "test-tube-off": F0912, + "text": F09A8, + "text-account": F1570, + "text-box": F021A, + "text-box-check": F0EA6, + "text-box-check-outline": F0EA7, + "text-box-minus": F0EA8, + "text-box-minus-outline": F0EA9, + "text-box-multiple": F0AB7, + "text-box-multiple-outline": F0AB8, + "text-box-outline": F09ED, + "text-box-plus": F0EAA, + "text-box-plus-outline": F0EAB, + "text-box-remove": F0EAC, + "text-box-remove-outline": F0EAD, + "text-box-search": F0EAE, + "text-box-search-outline": F0EAF, + "text-recognition": F113D, + "text-search": F13B8, + "text-shadow": F0669, + "text-short": F09A9, + "text-subject": F09AA, + "text-to-speech": F050A, + "text-to-speech-off": F050B, + "texture": F050C, + "texture-box": F0FE6, + "theater": F050D, + "theme-light-dark": F050E, + "thermometer": F050F, + "thermometer-alert": F0E01, + "thermometer-chevron-down": F0E02, + "thermometer-chevron-up": F0E03, + "thermometer-high": F10C2, + "thermometer-lines": F0510, + "thermometer-low": F10C3, + "thermometer-minus": F0E04, + "thermometer-off": F1531, + "thermometer-plus": F0E05, + "thermostat": F0393, + "thermostat-box": F0891, + "thought-bubble": F07F6, + "thought-bubble-outline": F07F7, + "thumb-down": F0511, + "thumb-down-outline": F0512, + "thumb-up": F0513, + "thumb-up-outline": F0514, + "thumbs-up-down": F0515, + "ticket": F0516, + "ticket-account": F0517, + "ticket-confirmation": F0518, + "ticket-confirmation-outline": F13AA, + "ticket-outline": F0913, + "ticket-percent": F0724, + "ticket-percent-outline": F142B, + "tie": F0519, + "tilde": F0725, + "timelapse": F051A, + "timeline": F0BD1, + "timeline-alert": F0F95, + "timeline-alert-outline": F0F98, + "timeline-check": F1532, + "timeline-check-outline": F1533, + "timeline-clock": F11FB, + "timeline-clock-outline": F11FC, + "timeline-help": F0F99, + "timeline-help-outline": F0F9A, + "timeline-minus": F1534, + "timeline-minus-outline": F1535, + "timeline-outline": F0BD2, + "timeline-plus": F0F96, + "timeline-plus-outline": F0F97, + "timeline-remove": F1536, + "timeline-remove-outline": F1537, + "timeline-text": F0BD3, + "timeline-text-outline": F0BD4, + "timer": F13AB, + "timer-10": F051C, + "timer-3": F051D, + "timer-off": F13AC, + "timer-off-outline": F051E, + "timer-outline": F051B, + "timer-sand": F051F, + "timer-sand-empty": F06AD, + "timer-sand-full": F078C, + "timetable": F0520, + "toaster": F1063, + "toaster-off": F11B7, + "toaster-oven": F0CD3, + "toggle-switch": F0521, + "toggle-switch-off": F0522, + "toggle-switch-off-outline": F0A19, + "toggle-switch-outline": F0A1A, + "toilet": F09AB, + "toolbox": F09AC, + "toolbox-outline": F09AD, + "tools": F1064, + "tooltip": F0523, + "tooltip-account": F000C, + "tooltip-check": F155C, + "tooltip-check-outline": F155D, + "tooltip-edit": F0524, + "tooltip-edit-outline": F12C5, + "tooltip-image": F0525, + "tooltip-image-outline": F0BD5, + "tooltip-minus": F155E, + "tooltip-minus-outline": F155F, + "tooltip-outline": F0526, + "tooltip-plus": F0BD6, + "tooltip-plus-outline": F0527, + "tooltip-remove": F1560, + "tooltip-remove-outline": F1561, + "tooltip-text": F0528, + "tooltip-text-outline": F0BD7, + "tooth": F08C3, + "tooth-outline": F0529, + "toothbrush": F1129, + "toothbrush-electric": F112C, + "toothbrush-paste": F112A, + "torch": F1606, + "tortoise": F0D3B, + "toslink": F12B8, + "tournament": F09AE, + "tow-truck": F083C, + "tower-beach": F0681, + "tower-fire": F0682, + "toy-brick": F1288, + "toy-brick-marker": F1289, + "toy-brick-marker-outline": F128A, + "toy-brick-minus": F128B, + "toy-brick-minus-outline": F128C, + "toy-brick-outline": F128D, + "toy-brick-plus": F128E, + "toy-brick-plus-outline": F128F, + "toy-brick-remove": F1290, + "toy-brick-remove-outline": F1291, + "toy-brick-search": F1292, + "toy-brick-search-outline": F1293, + "track-light": F0914, + "trackpad": F07F8, + "trackpad-lock": F0933, + "tractor": F0892, + "tractor-variant": F14C4, + "trademark": F0A78, + "traffic-cone": F137C, + "traffic-light": F052B, + "train": F052C, + "train-car": F0BD8, + "train-variant": F08C4, + "tram": F052D, + "tram-side": F0FE7, + "transcribe": F052E, + "transcribe-close": F052F, + "transfer": F1065, + "transfer-down": F0DA1, + "transfer-left": F0DA2, + "transfer-right": F0530, + "transfer-up": F0DA3, + "transit-connection": F0D3C, + "transit-connection-horizontal": F1546, + "transit-connection-variant": F0D3D, + "transit-detour": F0F8B, + "transit-skip": F1515, + "transit-transfer": F06AE, + "transition": F0915, + "transition-masked": F0916, + "translate": F05CA, + "translate-off": F0E06, + "transmission-tower": F0D3E, + "trash-can": F0A79, + "trash-can-outline": F0A7A, + "tray": F1294, + "tray-alert": F1295, + "tray-full": F1296, + "tray-minus": F1297, + "tray-plus": F1298, + "tray-remove": F1299, + "treasure-chest": F0726, + "tree": F0531, + "tree-outline": F0E69, + "trello": F0532, + "trending-down": F0533, + "trending-neutral": F0534, + "trending-up": F0535, + "triangle": F0536, + "triangle-outline": F0537, + "triangle-wave": F147C, + "triforce": F0BD9, + "trophy": F0538, + "trophy-award": F0539, + "trophy-broken": F0DA4, + "trophy-outline": F053A, + "trophy-variant": F053B, + "trophy-variant-outline": F053C, + "truck": F053D, + "truck-check": F0CD4, + "truck-check-outline": F129A, + "truck-delivery": F053E, + "truck-delivery-outline": F129B, + "truck-fast": F0788, + "truck-fast-outline": F129C, + "truck-outline": F129D, + "truck-trailer": F0727, + "trumpet": F1096, + "tshirt-crew": F0A7B, + "tshirt-crew-outline": F053F, + "tshirt-v": F0A7C, + "tshirt-v-outline": F0540, + "tumble-dryer": F0917, + "tumble-dryer-alert": F11BA, + "tumble-dryer-off": F11BB, + "tune": F062E, + "tune-variant": F1542, + "tune-vertical": F066A, + "tune-vertical-variant": F1543, + "turnstile": F0CD5, + "turnstile-outline": F0CD6, + "turtle": F0CD7, + "twitch": F0543, + "twitter": F0544, + "twitter-retweet": F0547, + "two-factor-authentication": F09AF, + "typewriter": F0F2D, + "ubisoft": F0BDA, + "ubuntu": F0548, + "ufo": F10C4, + "ufo-outline": F10C5, + "ultra-high-definition": F07F9, + "umbraco": F0549, + "umbrella": F054A, + "umbrella-closed": F09B0, + "umbrella-closed-outline": F13E2, + "umbrella-closed-variant": F13E1, + "umbrella-outline": F054B, + "undo": F054C, + "undo-variant": F054D, + "unfold-less-horizontal": F054E, + "unfold-less-vertical": F0760, + "unfold-more-horizontal": F054F, + "unfold-more-vertical": F0761, + "ungroup": F0550, + "unicode": F0ED0, + "unicorn": F15C2, + "unicorn-variant": F15C3, + "unicycle": F15E5, + "unity": F06AF, + "unreal": F09B1, + "untappd": F0551, + "update": F06B0, + "upload": F0552, + "upload-lock": F1373, + "upload-lock-outline": F1374, + "upload-multiple": F083D, + "upload-network": F06F6, + "upload-network-outline": F0CD8, + "upload-off": F10C6, + "upload-off-outline": F10C7, + "upload-outline": F0E07, + "usb": F0553, + "usb-flash-drive": F129E, + "usb-flash-drive-outline": F129F, + "usb-port": F11F0, + "valve": F1066, + "valve-closed": F1067, + "valve-open": F1068, + "van-passenger": F07FA, + "van-utility": F07FB, + "vanish": F07FC, + "vanish-quarter": F1554, + "vanity-light": F11E1, + "variable": F0AE7, + "variable-box": F1111, + "vector-arrange-above": F0554, + "vector-arrange-below": F0555, + "vector-bezier": F0AE8, + "vector-circle": F0556, + "vector-circle-variant": F0557, + "vector-combine": F0558, + "vector-curve": F0559, + "vector-difference": F055A, + "vector-difference-ab": F055B, + "vector-difference-ba": F055C, + "vector-ellipse": F0893, + "vector-intersection": F055D, + "vector-line": F055E, + "vector-link": F0FE8, + "vector-point": F055F, + "vector-polygon": F0560, + "vector-polyline": F0561, + "vector-polyline-edit": F1225, + "vector-polyline-minus": F1226, + "vector-polyline-plus": F1227, + "vector-polyline-remove": F1228, + "vector-radius": F074A, + "vector-rectangle": F05C6, + "vector-selection": F0562, + "vector-square": F0001, + "vector-triangle": F0563, + "vector-union": F0564, + "vhs": F0A1B, + "vibrate": F0566, + "vibrate-off": F0CD9, + "video": F0567, + "video-3d": F07FD, + "video-3d-off": F13D9, + "video-3d-variant": F0ED1, + "video-4k-box": F083E, + "video-account": F0919, + "video-box": F00FD, + "video-box-off": F00FE, + "video-check": F1069, + "video-check-outline": F106A, + "video-high-definition": F152E, + "video-image": F091A, + "video-input-antenna": F083F, + "video-input-component": F0840, + "video-input-hdmi": F0841, + "video-input-scart": F0F8C, + "video-input-svideo": F0842, + "video-minus": F09B2, + "video-minus-outline": F02BA, + "video-off": F0568, + "video-off-outline": F0BDB, + "video-outline": F0BDC, + "video-plus": F09B3, + "video-plus-outline": F01D3, + "video-stabilization": F091B, + "video-switch": F0569, + "video-switch-outline": F0790, + "video-vintage": F0A1C, + "video-wireless": F0ED2, + "video-wireless-outline": F0ED3, + "view-agenda": F056A, + "view-agenda-outline": F11D8, + "view-array": F056B, + "view-array-outline": F1485, + "view-carousel": F056C, + "view-carousel-outline": F1486, + "view-column": F056D, + "view-column-outline": F1487, + "view-comfy": F0E6A, + "view-comfy-outline": F1488, + "view-compact": F0E6B, + "view-compact-outline": F0E6C, + "view-dashboard": F056E, + "view-dashboard-outline": F0A1D, + "view-dashboard-variant": F0843, + "view-dashboard-variant-outline": F1489, + "view-day": F056F, + "view-day-outline": F148A, + "view-grid": F0570, + "view-grid-outline": F11D9, + "view-grid-plus": F0F8D, + "view-grid-plus-outline": F11DA, + "view-headline": F0571, + "view-list": F0572, + "view-list-outline": F148B, + "view-module": F0573, + "view-module-outline": F148C, + "view-parallel": F0728, + "view-parallel-outline": F148D, + "view-quilt": F0574, + "view-quilt-outline": F148E, + "view-sequential": F0729, + "view-sequential-outline": F148F, + "view-split-horizontal": F0BCB, + "view-split-vertical": F0BCC, + "view-stream": F0575, + "view-stream-outline": F1490, + "view-week": F0576, + "view-week-outline": F1491, + "vimeo": F0577, + "violin": F060F, + "virtual-reality": F0894, + "virus": F13B6, + "virus-outline": F13B7, + "vk": F0579, + "vlc": F057C, + "voice-off": F0ED4, + "voicemail": F057D, + "volleyball": F09B4, + "volume-high": F057E, + "volume-low": F057F, + "volume-medium": F0580, + "volume-minus": F075E, + "volume-mute": F075F, + "volume-off": F0581, + "volume-plus": F075D, + "volume-source": F1120, + "volume-variant-off": F0E08, + "volume-vibrate": F1121, + "vote": F0A1F, + "vote-outline": F0A20, + "vpn": F0582, + "vuejs": F0844, + "vuetify": F0E6D, + "walk": F0583, + "wall": F07FE, + "wall-sconce": F091C, + "wall-sconce-flat": F091D, + "wall-sconce-flat-variant": F041C, + "wall-sconce-round": F0748, + "wall-sconce-round-variant": F091E, + "wallet": F0584, + "wallet-giftcard": F0585, + "wallet-membership": F0586, + "wallet-outline": F0BDD, + "wallet-plus": F0F8E, + "wallet-plus-outline": F0F8F, + "wallet-travel": F0587, + "wallpaper": F0E09, + "wan": F0588, + "wardrobe": F0F90, + "wardrobe-outline": F0F91, + "warehouse": F0F81, + "washing-machine": F072A, + "washing-machine-alert": F11BC, + "washing-machine-off": F11BD, + "watch": F0589, + "watch-export": F058A, + "watch-export-variant": F0895, + "watch-import": F058B, + "watch-import-variant": F0896, + "watch-variant": F0897, + "watch-vibrate": F06B1, + "watch-vibrate-off": F0CDA, + "water": F058C, + "water-alert": F1502, + "water-alert-outline": F1503, + "water-boiler": F0F92, + "water-boiler-alert": F11B3, + "water-boiler-off": F11B4, + "water-check": F1504, + "water-check-outline": F1505, + "water-minus": F1506, + "water-minus-outline": F1507, + "water-off": F058D, + "water-off-outline": F1508, + "water-outline": F0E0A, + "water-percent": F058E, + "water-percent-alert": F1509, + "water-plus": F150A, + "water-plus-outline": F150B, + "water-polo": F12A0, + "water-pump": F058F, + "water-pump-off": F0F93, + "water-remove": F150C, + "water-remove-outline": F150D, + "water-well": F106B, + "water-well-outline": F106C, + "watering-can": F1481, + "watering-can-outline": F1482, + "watermark": F0612, + "wave": F0F2E, + "waveform": F147D, + "waves": F078D, + "waze": F0BDE, + "weather-cloudy": F0590, + "weather-cloudy-alert": F0F2F, + "weather-cloudy-arrow-right": F0E6E, + "weather-fog": F0591, + "weather-hail": F0592, + "weather-hazy": F0F30, + "weather-hurricane": F0898, + "weather-lightning": F0593, + "weather-lightning-rainy": F067E, + "weather-night": F0594, + "weather-night-partly-cloudy": F0F31, + "weather-partly-cloudy": F0595, + "weather-partly-lightning": F0F32, + "weather-partly-rainy": F0F33, + "weather-partly-snowy": F0F34, + "weather-partly-snowy-rainy": F0F35, + "weather-pouring": F0596, + "weather-rainy": F0597, + "weather-snowy": F0598, + "weather-snowy-heavy": F0F36, + "weather-snowy-rainy": F067F, + "weather-sunny": F0599, + "weather-sunny-alert": F0F37, + "weather-sunny-off": F14E4, + "weather-sunset": F059A, + "weather-sunset-down": F059B, + "weather-sunset-up": F059C, + "weather-tornado": F0F38, + "weather-windy": F059D, + "weather-windy-variant": F059E, + "web": F059F, + "web-box": F0F94, + "web-clock": F124A, + "webcam": F05A0, + "webhook": F062F, + "webpack": F072B, + "webrtc": F1248, + "wechat": F0611, + "weight": F05A1, + "weight-gram": F0D3F, + "weight-kilogram": F05A2, + "weight-lifter": F115D, + "weight-pound": F09B5, + "whatsapp": F05A3, + "wheel-barrow": F14F2, + "wheelchair-accessibility": F05A4, + "whistle": F09B6, + "whistle-outline": F12BC, + "white-balance-auto": F05A5, + "white-balance-incandescent": F05A6, + "white-balance-iridescent": F05A7, + "white-balance-sunny": F05A8, + "widgets": F072C, + "widgets-outline": F1355, + "wifi": F05A9, + "wifi-alert": F16B5, + "wifi-arrow-down": F16B6, + "wifi-arrow-left": F16B7, + "wifi-arrow-left-right": F16B8, + "wifi-arrow-right": F16B9, + "wifi-arrow-up": F16BA, + "wifi-arrow-up-down": F16BB, + "wifi-cancel": F16BC, + "wifi-check": F16BD, + "wifi-cog": F16BE, + "wifi-lock": F16BF, + "wifi-lock-open": F16C0, + "wifi-marker": F16C1, + "wifi-minus": F16C2, + "wifi-off": F05AA, + "wifi-plus": F16C3, + "wifi-refresh": F16C4, + "wifi-remove": F16C5, + "wifi-settings": F16C6, + "wifi-star": F0E0B, + "wifi-strength-1": F091F, + "wifi-strength-1-alert": F0920, + "wifi-strength-1-lock": F0921, + "wifi-strength-1-lock-open": F16CB, + "wifi-strength-2": F0922, + "wifi-strength-2-alert": F0923, + "wifi-strength-2-lock": F0924, + "wifi-strength-2-lock-open": F16CC, + "wifi-strength-3": F0925, + "wifi-strength-3-alert": F0926, + "wifi-strength-3-lock": F0927, + "wifi-strength-3-lock-open": F16CD, + "wifi-strength-4": F0928, + "wifi-strength-4-alert": F0929, + "wifi-strength-4-lock": F092A, + "wifi-strength-4-lock-open": F16CE, + "wifi-strength-alert-outline": F092B, + "wifi-strength-lock-open-outline": F16CF, + "wifi-strength-lock-outline": F092C, + "wifi-strength-off": F092D, + "wifi-strength-off-outline": F092E, + "wifi-strength-outline": F092F, + "wifi-sync": F16C7, + "wikipedia": F05AC, + "wind-turbine": F0DA5, + "window-close": F05AD, + "window-closed": F05AE, + "window-closed-variant": F11DB, + "window-maximize": F05AF, + "window-minimize": F05B0, + "window-open": F05B1, + "window-open-variant": F11DC, + "window-restore": F05B2, + "window-shutter": F111C, + "window-shutter-alert": F111D, + "window-shutter-open": F111E, + "windsock": F15FA, + "wiper": F0AE9, + "wiper-wash": F0DA6, + "wizard-hat": F1477, + "wordpress": F05B4, + "wrap": F05B6, + "wrap-disabled": F0BDF, + "wrench": F05B7, + "wrench-outline": F0BE0, + "xamarin": F0845, + "xamarin-outline": F0846, + "xing": F05BE, + "xml": F05C0, + "xmpp": F07FF, + "y-combinator": F0624, + "yahoo": F0B4F, + "yeast": F05C1, + "yin-yang": F0680, + "yoga": F117C, + "youtube": F05C3, + "youtube-gaming": F0848, + "youtube-studio": F0847, + "youtube-subscription": F0D40, + "youtube-tv": F0448, + "yurt": F1516, + "z-wave": F0AEA, + "zend": F0AEB, + "zigbee": F0D41, + "zip-box": F05C4, + "zip-box-outline": F0FFA, + "zip-disk": F0A23, + "zodiac-aquarius": F0A7D, + "zodiac-aries": F0A7E, + "zodiac-cancer": F0A7F, + "zodiac-capricorn": F0A80, + "zodiac-gemini": F0A81, + "zodiac-leo": F0A82, + "zodiac-libra": F0A83, + "zodiac-pisces": F0A84, + "zodiac-sagittarius": F0A85, + "zodiac-scorpio": F0A86, + "zodiac-taurus": F0A87, + "zodiac-virgo": F0A88 +); \ No newline at end of file diff --git a/netbox/project-static/materialdesignicons-5.4.55/scss/materialdesignicons.scss b/netbox/project-static/materialdesignicons-5.4.55/scss/materialdesignicons.scss new file mode 100644 index 0000000000..235314591c --- /dev/null +++ b/netbox/project-static/materialdesignicons-5.4.55/scss/materialdesignicons.scss @@ -0,0 +1,8 @@ +/* MaterialDesignIcons.com */ +@import "variables"; +@import "functions"; +@import "path"; +@import "core"; +@import "icons"; +@import "extras"; +@import "animated"; \ No newline at end of file diff --git a/netbox/secrets/api/nested_serializers.py b/netbox/secrets/api/nested_serializers.py index 13c016c18e..aaec27c1f0 100644 --- a/netbox/secrets/api/nested_serializers.py +++ b/netbox/secrets/api/nested_serializers.py @@ -1,7 +1,7 @@ from rest_framework import serializers +from netbox.api import WritableNestedSerializer from secrets.models import Secret, SecretRole -from utilities.api import WritableNestedSerializer __all__ = [ 'NestedSecretRoleSerializer', diff --git a/netbox/secrets/api/serializers.py b/netbox/secrets/api/serializers.py index 2862259d87..b08b87bc51 100644 --- a/netbox/secrets/api/serializers.py +++ b/netbox/secrets/api/serializers.py @@ -1,10 +1,13 @@ +from django.contrib.contenttypes.models import ContentType +from drf_yasg.utils import swagger_serializer_method from rest_framework import serializers -from dcim.api.nested_serializers import NestedDeviceSerializer from extras.api.customfields import CustomFieldModelSerializer from extras.api.serializers import TaggedObjectSerializer +from secrets.constants import SECRET_ASSIGNMENT_MODELS from secrets.models import Secret, SecretRole -from utilities.api import ValidatedModelSerializer +from netbox.api import ContentTypeField, ValidatedModelSerializer +from utilities.api import get_serializer_for_model from .nested_serializers import * @@ -23,18 +26,27 @@ class Meta: class SecretSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='secrets-api:secret-detail') - device = NestedDeviceSerializer() + assigned_object_type = ContentTypeField( + queryset=ContentType.objects.filter(SECRET_ASSIGNMENT_MODELS) + ) + assigned_object = serializers.SerializerMethodField(read_only=True) role = NestedSecretRoleSerializer() plaintext = serializers.CharField() class Meta: model = Secret fields = [ - 'id', 'url', 'device', 'role', 'name', 'plaintext', 'hash', 'tags', 'custom_fields', 'created', - 'last_updated', + 'id', 'url', 'assigned_object_type', 'assigned_object_id', 'assigned_object', 'role', 'name', 'plaintext', + 'hash', 'tags', 'custom_fields', 'created', 'last_updated', ] validators = [] + @swagger_serializer_method(serializer_or_field=serializers.DictField) + def get_assigned_object(self, obj): + serializer = get_serializer_for_model(obj.assigned_object, prefix='Nested') + context = {'request': self.context['request']} + return serializer(obj.assigned_object, context=context).data + def validate(self, data): # Encrypt plaintext data using the master key provided from the view context diff --git a/netbox/secrets/api/urls.py b/netbox/secrets/api/urls.py index 5ad05b09ea..4000177b23 100644 --- a/netbox/secrets/api/urls.py +++ b/netbox/secrets/api/urls.py @@ -1,4 +1,4 @@ -from utilities.api import OrderedDefaultRouter +from netbox.api import OrderedDefaultRouter from . import views diff --git a/netbox/secrets/api/views.py b/netbox/secrets/api/views.py index 8147809b00..1153b0508f 100644 --- a/netbox/secrets/api/views.py +++ b/netbox/secrets/api/views.py @@ -8,10 +8,10 @@ from rest_framework.routers import APIRootView from rest_framework.viewsets import ViewSet +from netbox.api.views import ModelViewSet from secrets import filters from secrets.exceptions import InvalidKey from secrets.models import Secret, SecretRole, SessionKey, UserKey -from utilities.api import ModelViewSet from utilities.utils import get_subquery from . import serializers @@ -46,9 +46,7 @@ class SecretRoleViewSet(ModelViewSet): # class SecretViewSet(ModelViewSet): - queryset = Secret.objects.prefetch_related( - 'device__primary_ip4', 'device__primary_ip6', 'role', 'tags', - ) + queryset = Secret.objects.prefetch_related('role', 'tags') serializer_class = serializers.SecretSerializer filterset_class = filters.SecretFilterSet diff --git a/netbox/secrets/constants.py b/netbox/secrets/constants.py index a1c3cb3da4..16803820ee 100644 --- a/netbox/secrets/constants.py +++ b/netbox/secrets/constants.py @@ -1,5 +1,13 @@ +from django.db.models import Q + + # # Secrets # +SECRET_ASSIGNMENT_MODELS = Q( + Q(app_label='dcim', model='device') | + Q(app_label='virtualization', model='virtualmachine') +) + SECRET_PLAINTEXT_MAX_LENGTH = 65535 diff --git a/netbox/secrets/filters.py b/netbox/secrets/filters.py index 78f25952ae..0cf4c20451 100644 --- a/netbox/secrets/filters.py +++ b/netbox/secrets/filters.py @@ -2,8 +2,9 @@ from django.db.models import Q from dcim.models import Device -from extras.filters import CustomFieldFilterSet, CreatedUpdatedFilterSet +from extras.filters import CustomFieldModelFilterSet, CreatedUpdatedFilterSet from utilities.filters import BaseFilterSet, NameSlugSearchFilterSet, TagFilter +from virtualization.models import VirtualMachine from .models import Secret, SecretRole @@ -20,7 +21,7 @@ class Meta: fields = ['id', 'name', 'slug'] -class SecretFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet): +class SecretFilterSet(BaseFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): q = django_filters.CharFilter( method='search', label='Search', @@ -35,16 +36,28 @@ class SecretFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterS to_field_name='slug', label='Role (slug)', ) - device_id = django_filters.ModelMultipleChoiceFilter( - queryset=Device.objects.all(), - label='Device (ID)', - ) device = django_filters.ModelMultipleChoiceFilter( field_name='device__name', queryset=Device.objects.all(), to_field_name='name', label='Device (name)', ) + device_id = django_filters.ModelMultipleChoiceFilter( + field_name='device', + queryset=Device.objects.all(), + label='Device (ID)', + ) + virtual_machine = django_filters.ModelMultipleChoiceFilter( + field_name='virtual_machine__name', + queryset=VirtualMachine.objects.all(), + to_field_name='name', + label='Virtual machine (name)', + ) + virtual_machine_id = django_filters.ModelMultipleChoiceFilter( + field_name='virtual_machine', + queryset=VirtualMachine.objects.all(), + label='Virtual machine (ID)', + ) tag = TagFilter() class Meta: diff --git a/netbox/secrets/forms.py b/netbox/secrets/forms.py index 8f04edc5bd..8e976c8ead 100644 --- a/netbox/secrets/forms.py +++ b/netbox/secrets/forms.py @@ -1,6 +1,7 @@ from Crypto.Cipher import PKCS1_OAEP from Crypto.PublicKey import RSA from django import forms +from django.contrib.contenttypes.models import ContentType from dcim.models import Device from extras.forms import ( @@ -11,6 +12,7 @@ BootstrapMixin, CSVModelChoiceField, CSVModelForm, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField, TagFilterField, ) +from virtualization.models import VirtualMachine from .constants import * from .models import Secret, SecretRole, UserKey @@ -64,8 +66,13 @@ class Meta: class SecretForm(BootstrapMixin, CustomFieldModelForm): device = DynamicModelChoiceField( queryset=Device.objects.all(), + required=False, display_field='display_name' ) + virtual_machine = DynamicModelChoiceField( + queryset=VirtualMachine.objects.all(), + required=False + ) plaintext = forms.CharField( max_length=SECRET_PLAINTEXT_MAX_LENGTH, required=False, @@ -93,10 +100,21 @@ class SecretForm(BootstrapMixin, CustomFieldModelForm): class Meta: model = Secret fields = [ - 'device', 'role', 'name', 'plaintext', 'plaintext2', 'tags', + 'device', 'virtual_machine', 'role', 'name', 'plaintext', 'plaintext2', 'tags', ] def __init__(self, *args, **kwargs): + + # Initialize helper selectors + instance = kwargs.get('instance') + initial = kwargs.get('initial', {}).copy() + if instance: + if type(instance.assigned_object) is Device: + initial['device'] = instance.assigned_object + elif type(instance.assigned_object) is VirtualMachine: + initial['virtual_machine'] = instance.assigned_object + kwargs['initial'] = initial + super().__init__(*args, **kwargs) # A plaintext value is required when creating a new Secret @@ -105,33 +123,42 @@ def __init__(self, *args, **kwargs): def clean(self): + if not self.cleaned_data['device'] and not self.cleaned_data['virtual_machine']: + raise forms.ValidationError("Secrets must be assigned to a device or virtual machine.") + + if self.cleaned_data['device'] and self.cleaned_data['virtual_machine']: + raise forms.ValidationError("Cannot select both a device and virtual machine for secret assignment.") + # Verify that the provided plaintext values match if self.cleaned_data['plaintext'] != self.cleaned_data['plaintext2']: raise forms.ValidationError({ 'plaintext2': "The two given plaintext values do not match. Please check your input." }) - # Validate uniqueness - if Secret.objects.filter( - device=self.cleaned_data['device'], - role=self.cleaned_data['role'], - name=self.cleaned_data['name'] - ).exclude(pk=self.instance.pk).exists(): - raise forms.ValidationError( - "Each secret assigned to a device must have a unique combination of role and name" - ) + def save(self, *args, **kwargs): + # Set assigned object + self.instance.assigned_object = self.cleaned_data.get('device') or self.cleaned_data.get('virtual_machine') + + return super().save(*args, **kwargs) class SecretCSVForm(CustomFieldModelCSVForm): + role = CSVModelChoiceField( + queryset=SecretRole.objects.all(), + to_field_name='name', + help_text='Assigned role' + ) device = CSVModelChoiceField( queryset=Device.objects.all(), + required=False, to_field_name='name', help_text='Assigned device' ) - role = CSVModelChoiceField( - queryset=SecretRole.objects.all(), + virtual_machine = CSVModelChoiceField( + queryset=VirtualMachine.objects.all(), + required=False, to_field_name='name', - help_text='Assigned role' + help_text='Assigned VM' ) plaintext = forms.CharField( help_text='Plaintext secret data' @@ -139,14 +166,33 @@ class SecretCSVForm(CustomFieldModelCSVForm): class Meta: model = Secret - fields = Secret.csv_headers + fields = ['role', 'name', 'plaintext', 'device', 'virtual_machine'] help_texts = { 'name': 'Name or username', } + def clean(self): + super().clean() + + device = self.cleaned_data.get('device') + virtual_machine = self.cleaned_data.get('virtual_machine') + + # Validate device OR VM is assigned + if not device and not virtual_machine: + raise forms.ValidationError("Secret must be assigned to a device or a virtual machine") + if device and virtual_machine: + raise forms.ValidationError("Secret cannot be assigned to both a device and a virtual machine") + def save(self, *args, **kwargs): + + # Set device/VM assignment + self.instance.assigned_object = self.cleaned_data['device'] or self.cleaned_data['virtual_machine'] + s = super().save(*args, **kwargs) + + # Set plaintext on instance s.plaintext = str(self.cleaned_data['plaintext']) + return s diff --git a/netbox/secrets/migrations/0010_custom_field_data.py b/netbox/secrets/migrations/0010_custom_field_data.py new file mode 100644 index 0000000000..6d48e7cab7 --- /dev/null +++ b/netbox/secrets/migrations/0010_custom_field_data.py @@ -0,0 +1,17 @@ +import django.core.serializers.json +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('secrets', '0009_secretrole_drop_users_groups'), + ] + + operations = [ + migrations.AddField( + model_name='secret', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + ] diff --git a/netbox/secrets/migrations/0011_secret_generic_assignments.py b/netbox/secrets/migrations/0011_secret_generic_assignments.py new file mode 100644 index 0000000000..02a0e0e211 --- /dev/null +++ b/netbox/secrets/migrations/0011_secret_generic_assignments.py @@ -0,0 +1,67 @@ +from django.db import migrations, models +import django.db.models.deletion + + +def device_to_generic_assignment(apps, schema_editor): + ContentType = apps.get_model('contenttypes', 'ContentType') + Device = apps.get_model('dcim', 'Device') + Secret = apps.get_model('secrets', 'Secret') + + device_ct = ContentType.objects.get_for_model(Device) + Secret.objects.update(assigned_object_type=device_ct, assigned_object_id=models.F('device_id')) + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('secrets', '0010_custom_field_data'), + ] + + operations = [ + migrations.AlterModelOptions( + name='secret', + options={'ordering': ('role', 'name', 'pk')}, + ), + + # Add assigned_object type & ID fields + migrations.AddField( + model_name='secret', + name='assigned_object_id', + field=models.PositiveIntegerField(blank=True, null=True), + preserve_default=False, + ), + migrations.AddField( + model_name='secret', + name='assigned_object_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype'), + preserve_default=False, + ), + + migrations.AlterUniqueTogether( + name='secret', + unique_together={('assigned_object_type', 'assigned_object_id', 'role', 'name')}, + ), + + # Copy device assignments and delete device ForeignKey + migrations.RunPython( + code=device_to_generic_assignment, + reverse_code=migrations.RunPython.noop + ), + migrations.RemoveField( + model_name='secret', + name='device', + ), + + # Remove blank/null from assigned_object fields + migrations.AlterField( + model_name='secret', + name='assigned_object_id', + field=models.PositiveIntegerField(), + ), + migrations.AlterField( + model_name='secret', + name='assigned_object_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype'), + ), + ] diff --git a/netbox/secrets/migrations/0012_standardize_name_length.py b/netbox/secrets/migrations/0012_standardize_name_length.py new file mode 100644 index 0000000000..e41d817610 --- /dev/null +++ b/netbox/secrets/migrations/0012_standardize_name_length.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1 on 2020-10-15 19:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('secrets', '0011_secret_generic_assignments'), + ] + + operations = [ + migrations.AlterField( + model_name='secretrole', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='secretrole', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + ] diff --git a/netbox/secrets/models.py b/netbox/secrets/models.py index 6209b57002..0fa6fd04ea 100644 --- a/netbox/secrets/models.py +++ b/netbox/secrets/models.py @@ -6,14 +6,14 @@ from django.conf import settings from django.contrib.auth.hashers import make_password, check_password from django.contrib.auth.models import Group, User -from django.contrib.contenttypes.fields import GenericRelation +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError from django.db import models from django.urls import reverse from django.utils.encoding import force_bytes from taggit.managers import TaggableManager -from dcim.models import Device from extras.models import ChangeLoggedModel, CustomFieldModel, TaggedItem from extras.utils import extras_features from utilities.querysets import RestrictedQuerySet @@ -74,7 +74,8 @@ def __init__(self, *args, **kwargs): def __str__(self): return self.user.username - def clean(self, *args, **kwargs): + def clean(self): + super().clean() if self.public_key: @@ -105,8 +106,6 @@ def clean(self, *args, **kwargs): ) }) - super().clean() - def save(self, *args, **kwargs): # Check whether public_key has been modified. If so, nullify the initial master_key_cipher. @@ -241,10 +240,11 @@ class SecretRole(ChangeLoggedModel): such as "Login Credentials" or "SNMP Communities." """ name = models.CharField( - max_length=50, + max_length=100, unique=True ) slug = models.SlugField( + max_length=100, unique=True ) description = models.CharField( @@ -277,17 +277,21 @@ def to_csv(self): class Secret(ChangeLoggedModel, CustomFieldModel): """ A Secret stores an AES256-encrypted copy of sensitive data, such as passwords or secret keys. An irreversible - SHA-256 hash is stored along with the ciphertext for validation upon decryption. Each Secret is assigned to a - Device; Devices may have multiple Secrets associated with them. A name can optionally be defined along with the - ciphertext; this string is stored as plain text in the database. + SHA-256 hash is stored along with the ciphertext for validation upon decryption. Each Secret is assigned to exactly + one NetBox object, and objects may have multiple Secrets associated with them. A name can optionally be defined + along with the ciphertext; this string is stored as plain text in the database. A Secret can be up to 65,535 bytes (64KB - 1B) in length. Each secret string will be padded with random data to a minimum of 64 bytes during encryption in order to protect short strings from ciphertext analysis. """ - device = models.ForeignKey( - to='dcim.Device', - on_delete=models.CASCADE, - related_name='secrets' + assigned_object_type = models.ForeignKey( + to=ContentType, + on_delete=models.PROTECT + ) + assigned_object_id = models.PositiveIntegerField() + assigned_object = GenericForeignKey( + ct_field='assigned_object_type', + fk_field='assigned_object_id' ) role = models.ForeignKey( to='secrets.SecretRole', @@ -306,44 +310,31 @@ class Secret(ChangeLoggedModel, CustomFieldModel): max_length=128, editable=False ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) tags = TaggableManager(through=TaggedItem) objects = RestrictedQuerySet.as_manager() plaintext = None - csv_headers = ['device', 'role', 'name', 'plaintext'] + csv_headers = ['assigned_object_type', 'assigned_object_id', 'role', 'name', 'plaintext'] class Meta: - ordering = ['device', 'role', 'name'] - unique_together = ['device', 'role', 'name'] + ordering = ('role', 'name', 'pk') + unique_together = ('assigned_object_type', 'assigned_object_id', 'role', 'name') def __init__(self, *args, **kwargs): self.plaintext = kwargs.pop('plaintext', None) super().__init__(*args, **kwargs) def __str__(self): - try: - device = self.device - except Device.DoesNotExist: - device = None - if self.role and device and self.name: - return '{} for {} ({})'.format(self.role, self.device, self.name) - # Return role and device if no name is set - if self.role and device: - return '{} for {}'.format(self.role, self.device) - return 'Secret' + return self.name or 'Secret' def get_absolute_url(self): return reverse('secrets:secret', args=[self.pk]) def to_csv(self): return ( - self.device, + f'{self.assigned_object_type.app_label}.{self.assigned_object_type.model}', + self.assigned_object_id, self.role, self.name, self.plaintext or '', diff --git a/netbox/secrets/tables.py b/netbox/secrets/tables.py index 3302d0d19a..0d8559a2bb 100644 --- a/netbox/secrets/tables.py +++ b/netbox/secrets/tables.py @@ -1,6 +1,6 @@ import django_tables2 as tables -from utilities.tables import BaseTable, ButtonsColumn, TagColumn, ToggleColumn +from utilities.tables import BaseTable, ButtonsColumn, LinkedCountColumn, TagColumn, ToggleColumn from .models import SecretRole, Secret @@ -11,7 +11,9 @@ class SecretRoleTable(BaseTable): pk = ToggleColumn() name = tables.LinkColumn() - secret_count = tables.Column( + secret_count = LinkedCountColumn( + viewname='secrets:secret_list', + url_params={'role': 'slug'}, verbose_name='Secrets' ) actions = ButtonsColumn(SecretRole, pk_field='slug') @@ -28,11 +30,12 @@ class Meta(BaseTable.Meta): class SecretTable(BaseTable): pk = ToggleColumn() - id = tables.Column( + id = tables.Column( # Provides a link to the secret linkify=True ) - device = tables.Column( - linkify=True + assigned_object = tables.Column( + linkify=True, + verbose_name='Assigned object' ) role = tables.Column( linkify=True @@ -43,5 +46,5 @@ class SecretTable(BaseTable): class Meta(BaseTable.Meta): model = Secret - fields = ('pk', 'id', 'device', 'role', 'name', 'last_updated', 'hash', 'tags') - default_columns = ('pk', 'id', 'device', 'role', 'name', 'last_updated') + fields = ('pk', 'id', 'assigned_object', 'role', 'name', 'last_updated', 'hash', 'tags') + default_columns = ('pk', 'id', 'assigned_object', 'role', 'name', 'last_updated') diff --git a/netbox/secrets/tests/test_api.py b/netbox/secrets/tests/test_api.py index 89c18b7d7d..34608d68bd 100644 --- a/netbox/secrets/tests/test_api.py +++ b/netbox/secrets/tests/test_api.py @@ -36,6 +36,9 @@ class SecretRoleTest(APIViewTestCases.APIViewTestCase): 'slug': 'secret-role-6', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -80,9 +83,9 @@ def setUp(self): SecretRole.objects.bulk_create(secret_roles) secrets = ( - Secret(device=device, role=secret_roles[0], name='Secret 1', plaintext='ABC'), - Secret(device=device, role=secret_roles[0], name='Secret 2', plaintext='DEF'), - Secret(device=device, role=secret_roles[0], name='Secret 3', plaintext='GHI'), + Secret(assigned_object=device, role=secret_roles[0], name='Secret 1', plaintext='ABC'), + Secret(assigned_object=device, role=secret_roles[0], name='Secret 2', plaintext='DEF'), + Secret(assigned_object=device, role=secret_roles[0], name='Secret 3', plaintext='GHI'), ) for secret in secrets: secret.encrypt(self.master_key) @@ -90,25 +93,32 @@ def setUp(self): self.create_data = [ { - 'device': device.pk, + 'assigned_object_type': 'dcim.device', + 'assigned_object_id': device.pk, 'role': secret_roles[1].pk, 'name': 'Secret 4', 'plaintext': 'JKL', }, { - 'device': device.pk, + 'assigned_object_type': 'dcim.device', + 'assigned_object_id': device.pk, 'role': secret_roles[1].pk, 'name': 'Secret 5', 'plaintext': 'MNO', }, { - 'device': device.pk, + 'assigned_object_type': 'dcim.device', + 'assigned_object_id': device.pk, 'role': secret_roles[1].pk, 'name': 'Secret 6', 'plaintext': 'PQR', }, ] + self.bulk_update_data = { + 'role': secret_roles[1].pk, + } + def prepare_instance(self, instance): # Unlock the plaintext prior to evaluation of the instance instance.decrypt(self.master_key) diff --git a/netbox/secrets/tests/test_filters.py b/netbox/secrets/tests/test_filters.py index b7ac73f1d0..0be1ef594a 100644 --- a/netbox/secrets/tests/test_filters.py +++ b/netbox/secrets/tests/test_filters.py @@ -3,6 +3,7 @@ from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site from secrets.filters import * from secrets.models import Secret, SecretRole +from virtualization.models import Cluster, ClusterType, VirtualMachine class SecretRoleTestCase(TestCase): @@ -51,6 +52,15 @@ def setUpTestData(cls): ) Device.objects.bulk_create(devices) + cluster_type = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1') + cluster = Cluster.objects.create(name='Cluster 1', type=cluster_type) + virtual_machines = ( + VirtualMachine(name='Virtual Machine 1', cluster=cluster), + VirtualMachine(name='Virtual Machine 2', cluster=cluster), + VirtualMachine(name='Virtual Machine 3', cluster=cluster), + ) + VirtualMachine.objects.bulk_create(virtual_machines) + roles = ( SecretRole(name='Secret Role 1', slug='secret-role-1'), SecretRole(name='Secret Role 2', slug='secret-role-2'), @@ -59,9 +69,12 @@ def setUpTestData(cls): SecretRole.objects.bulk_create(roles) secrets = ( - Secret(device=devices[0], role=roles[0], name='Secret 1', plaintext='SECRET DATA'), - Secret(device=devices[1], role=roles[1], name='Secret 2', plaintext='SECRET DATA'), - Secret(device=devices[2], role=roles[2], name='Secret 3', plaintext='SECRET DATA'), + Secret(assigned_object=devices[0], role=roles[0], name='Secret 1', plaintext='SECRET DATA'), + Secret(assigned_object=devices[1], role=roles[1], name='Secret 2', plaintext='SECRET DATA'), + Secret(assigned_object=devices[2], role=roles[2], name='Secret 3', plaintext='SECRET DATA'), + Secret(assigned_object=virtual_machines[0], role=roles[0], name='Secret 4', plaintext='SECRET DATA'), + Secret(assigned_object=virtual_machines[1], role=roles[1], name='Secret 5', plaintext='SECRET DATA'), + Secret(assigned_object=virtual_machines[2], role=roles[2], name='Secret 6', plaintext='SECRET DATA'), ) # Must call save() to encrypt Secrets for s in secrets: @@ -78,9 +91,9 @@ def test_name(self): def test_role(self): roles = SecretRole.objects.all()[:2] params = {'role_id': [roles[0].pk, roles[1].pk]} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) params = {'role': [roles[0].slug, roles[1].slug]} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) def test_device(self): devices = Device.objects.all()[:2] @@ -88,3 +101,10 @@ def test_device(self): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) params = {'device': [devices[0].name, devices[1].name]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_virtual_machine(self): + virtual_machines = VirtualMachine.objects.all()[:2] + params = {'virtual_machine_id': [virtual_machines[0].pk, virtual_machines[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'virtual_machine': [virtual_machines[0].name, virtual_machines[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) diff --git a/netbox/secrets/tests/test_views.py b/netbox/secrets/tests/test_views.py index 3b7519b7bd..bff039656f 100644 --- a/netbox/secrets/tests/test_views.py +++ b/netbox/secrets/tests/test_views.py @@ -69,13 +69,14 @@ def setUpTestData(cls): # Create one secret per device to allow bulk-editing of names (which must be unique per device/role) Secret.objects.bulk_create(( - Secret(device=devices[0], role=secretroles[0], name='Secret 1', ciphertext=b'1234567890'), - Secret(device=devices[1], role=secretroles[0], name='Secret 2', ciphertext=b'1234567890'), - Secret(device=devices[2], role=secretroles[0], name='Secret 3', ciphertext=b'1234567890'), + Secret(assigned_object=devices[0], role=secretroles[0], name='Secret 1', ciphertext=b'1234567890'), + Secret(assigned_object=devices[1], role=secretroles[0], name='Secret 2', ciphertext=b'1234567890'), + Secret(assigned_object=devices[2], role=secretroles[0], name='Secret 3', ciphertext=b'1234567890'), )) cls.form_data = { - 'device': devices[1].pk, + 'assigned_object_type': 'dcim.device', + 'assigned_object_id': devices[1].pk, 'role': secretroles[1].pk, 'name': 'Secret X', } @@ -100,11 +101,12 @@ def setUp(self): def test_import_objects(self): self.add_permissions('secrets.add_secret') + device = Device.objects.get(name='Device 1') csv_data = ( "device,role,name,plaintext", - "Device 1,Secret Role 1,Secret 4,abcdefghij", - "Device 1,Secret Role 1,Secret 5,abcdefghij", - "Device 1,Secret Role 1,Secret 6,abcdefghij", + f"{device.name},Secret Role 1,Secret 4,abcdefghij", + f"{device.name},Secret Role 1,Secret 5,abcdefghij", + f"{device.name},Secret Role 1,Secret 6,abcdefghij", ) # Set the session_key cookie on the request diff --git a/netbox/secrets/views.py b/netbox/secrets/views.py index 24138e0e4d..7bfa265d65 100644 --- a/netbox/secrets/views.py +++ b/netbox/secrets/views.py @@ -6,10 +6,8 @@ from django.utils.html import escape from django.utils.safestring import mark_safe +from netbox.views import generic from utilities.utils import get_subquery -from utilities.views import ( - BulkDeleteView, BulkEditView, BulkImportView, ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView, -) from . import filters, forms, tables from .models import SecretRole, Secret, SessionKey, UserKey @@ -28,29 +26,29 @@ def get_session_key(request): # Secret roles # -class SecretRoleListView(ObjectListView): +class SecretRoleListView(generic.ObjectListView): queryset = SecretRole.objects.annotate( secret_count=get_subquery(Secret, 'role') ) table = tables.SecretRoleTable -class SecretRoleEditView(ObjectEditView): +class SecretRoleEditView(generic.ObjectEditView): queryset = SecretRole.objects.all() model_form = forms.SecretRoleForm -class SecretRoleDeleteView(ObjectDeleteView): +class SecretRoleDeleteView(generic.ObjectDeleteView): queryset = SecretRole.objects.all() -class SecretRoleBulkImportView(BulkImportView): +class SecretRoleBulkImportView(generic.BulkImportView): queryset = SecretRole.objects.all() model_form = forms.SecretRoleCSVForm table = tables.SecretRoleTable -class SecretRoleBulkDeleteView(BulkDeleteView): +class SecretRoleBulkDeleteView(generic.BulkDeleteView): queryset = SecretRole.objects.annotate( secret_count=get_subquery(Secret, 'role') ) @@ -61,27 +59,19 @@ class SecretRoleBulkDeleteView(BulkDeleteView): # Secrets # -class SecretListView(ObjectListView): - queryset = Secret.objects.prefetch_related('role', 'device') +class SecretListView(generic.ObjectListView): + queryset = Secret.objects.all() filterset = filters.SecretFilterSet filterset_form = forms.SecretFilterForm table = tables.SecretTable action_buttons = ('import', 'export') -class SecretView(ObjectView): +class SecretView(generic.ObjectView): queryset = Secret.objects.all() - def get(self, request, pk): - - secret = get_object_or_404(self.queryset, pk=pk) - - return render(request, 'secrets/secret.html', { - 'secret': secret, - }) - -class SecretEditView(ObjectEditView): +class SecretEditView(generic.ObjectEditView): queryset = Secret.objects.all() model_form = forms.SecretForm template_name = 'secrets/secret_edit.html' @@ -150,11 +140,11 @@ def post(self, request, *args, **kwargs): }) -class SecretDeleteView(ObjectDeleteView): +class SecretDeleteView(generic.ObjectDeleteView): queryset = Secret.objects.all() -class SecretBulkImportView(BulkImportView): +class SecretBulkImportView(generic.BulkImportView): queryset = Secret.objects.all() model_form = forms.SecretCSVForm table = tables.SecretTable @@ -201,14 +191,14 @@ def post(self, request): }) -class SecretBulkEditView(BulkEditView): - queryset = Secret.objects.prefetch_related('role', 'device') +class SecretBulkEditView(generic.BulkEditView): + queryset = Secret.objects.prefetch_related('role') filterset = filters.SecretFilterSet table = tables.SecretTable form = forms.SecretBulkEditForm -class SecretBulkDeleteView(BulkDeleteView): - queryset = Secret.objects.prefetch_related('role', 'device') +class SecretBulkDeleteView(generic.BulkDeleteView): + queryset = Secret.objects.prefetch_related('role') filterset = filters.SecretFilterSet table = tables.SecretTable diff --git a/netbox/templates/403.html b/netbox/templates/403.html index 6a114301f1..844697aae2 100644 --- a/netbox/templates/403.html +++ b/netbox/templates/403.html @@ -2,7 +2,7 @@ {% block title %}Access Denied{% endblock %} -{% block icon %}{% endblock %} +{% block icon %}{% endblock %} {% block message %} You do not have permission to access this page. diff --git a/netbox/templates/404.html b/netbox/templates/404.html index 22c17fed45..eec438071a 100644 --- a/netbox/templates/404.html +++ b/netbox/templates/404.html @@ -2,7 +2,7 @@ {% block title %}Page Not Found{% endblock %} -{% block icon %}{% endblock %} +{% block icon %}{% endblock %} {% block message %} The requested page does not exist. diff --git a/netbox/templates/500.html b/netbox/templates/500.html index 8e1bf410d2..8345d00c46 100644 --- a/netbox/templates/500.html +++ b/netbox/templates/500.html @@ -5,7 +5,7 @@ Server Error - + @@ -16,7 +16,7 @@
    - + Server Error
    diff --git a/netbox/templates/base.html b/netbox/templates/base.html index 20042d151c..86b582b3ef 100644 --- a/netbox/templates/base.html +++ b/netbox/templates/base.html @@ -8,8 +8,8 @@ href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}" onerror="window.location='{% url 'media_failure' %}?filename=bootstrap-3.4.1-dist/css/bootstrap.min.css'"> + href="{% static 'materialdesignicons-5.4.55/css/materialdesignicons.min.css' %}" + onerror="window.location='{% url 'media_failure' %}?filename=materialdesignicons-5.4.55/css/materialdesignicons.min.css'"> @@ -31,7 +31,7 @@ {% include 'inc/nav_menu.html' %} -
    +
    {% if settings.BANNER_TOP %}
    -
    +

    {{ settings.HOSTNAME }} (v{{ settings.VERSION }})

    @@ -71,10 +71,10 @@

    Maintenance Mode

    - Docs · - API · - Code · - Help + Docs · + API · + Code · + Help

    @@ -96,6 +96,7 @@

    Maintenance Mode

    onerror="window.location='{% url 'media_failure' %}?filename=js/forms.js'"> -{% endblock %} diff --git a/netbox/templates/circuits/provider_edit.html b/netbox/templates/circuits/provider_edit.html index 63b7f11b91..ee0a3a285c 100644 --- a/netbox/templates/circuits/provider_edit.html +++ b/netbox/templates/circuits/provider_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load form_helpers %} {% block form %} diff --git a/netbox/templates/dcim/cable.html b/netbox/templates/dcim/cable.html index 03188163dd..3bc7869fe4 100644 --- a/netbox/templates/dcim/cable.html +++ b/netbox/templates/dcim/cable.html @@ -9,31 +9,31 @@
    - {% plugin_buttons cable %} + {% plugin_buttons object %} {% if perms.dcim.change_cable %} - {% edit_button cable %} + {% edit_button object %} {% endif %} {% if perms.dcim.delete_cable %} - {% delete_button cable %} + {% delete_button object %} {% endif %}
    -

    {% block title %}Cable {{ cable }}{% endblock %}

    - {% include 'inc/created_updated.html' with obj=cable %} +

    {% block title %}Cable {{ object }}{% endblock %}

    + {% include 'inc/created_updated.html' %}
    - {% custom_links cable %} + {% custom_links object %}
    @@ -49,23 +49,23 @@

    {% block title %}Cable {{ cable }}{% endblock %}

    - + - +
    Type{{ cable.get_type_display|placeholder }}{{ object.get_type_display|placeholder }}
    Status - {{ cable.get_status_display }} + {{ object.get_status_display }}
    Label{{ cable.label|placeholder }}{{ object.label|placeholder }}
    Color - {% if cable.color %} -   + {% if object.color %} +   {% else %} {% endif %} @@ -74,8 +74,8 @@

    {% block title %}Cable {{ cable }}{% endblock %}

    Length - {% if cable.length %} - {{ cable.length }} {{ cable.get_length_unit_display }} + {% if object.length %} + {{ object.length }} {{ object.get_length_unit_display }} {% else %} {% endif %} @@ -83,28 +83,29 @@

    {% block title %}Cable {{ cable }}{% endblock %}

    - {% include 'extras/inc/tags_panel.html' with tags=cable.tags.all url='dcim:cable_list' %} - {% plugin_left_page cable %} + {% include 'inc/custom_fields_panel.html' %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='dcim:cable_list' %} + {% plugin_left_page object %}
    Termination A
    - {% include 'dcim/inc/cable_termination.html' with termination=cable.termination_a %} + {% include 'dcim/inc/cable_termination.html' with termination=object.termination_a %}
    Termination B
    - {% include 'dcim/inc/cable_termination.html' with termination=cable.termination_b %} + {% include 'dcim/inc/cable_termination.html' with termination=object.termination_b %}
    - {% plugin_right_page cable %} + {% plugin_right_page object %}
    - {% plugin_full_width_page cable %} + {% plugin_full_width_page object %}
    {% endblock %} diff --git a/netbox/templates/dcim/cable_connect.html b/netbox/templates/dcim/cable_connect.html index 05fd2de1a3..f8e07dca88 100644 --- a/netbox/templates/dcim/cable_connect.html +++ b/netbox/templates/dcim/cable_connect.html @@ -99,7 +99,7 @@

    {% block title %}Connect {{ termination_a.device }} {{ termination_a }} to {

    - +
    diff --git a/netbox/templates/dcim/cable_edit.html b/netbox/templates/dcim/cable_edit.html index 685b68206f..3bdce58a38 100644 --- a/netbox/templates/dcim/cable_edit.html +++ b/netbox/templates/dcim/cable_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% block form %} {% include 'dcim/inc/cable_form.html' %} diff --git a/netbox/templates/dcim/cable_trace.html b/netbox/templates/dcim/cable_trace.html index df484609ac..a369226121 100644 --- a/netbox/templates/dcim/cable_trace.html +++ b/netbox/templates/dcim/cable_trace.html @@ -2,106 +2,128 @@ {% load helpers %} {% block header %} -

    {% block title %}Cable Trace for {{ obj }}{% endblock %}

    +

    {% block title %}Cable Trace for {{ object|meta:"verbose_name"|bettertitle }} {{ object }}{% endblock %}

    {% endblock %} {% block content %}
    -
    -

    Near End

    -
    -
    - {% if total_length %}
    Total length: {{ total_length|floatformat:"-2" }} Meters
    {% endif %} -
    -
    -

    Far End

    -
    -
    - {% for near_end, cable, far_end in trace %} -
    -
    -

    {{ forloop.counter }}

    -
    -
    - {% include 'dcim/inc/cable_trace_end.html' with end=near_end %} -
    -
    - {% if cable %} -

    - - {% if cable.label %}{{ cable.label }}{% else %}Cable #{{ cable.pk }}{% endif %} - -

    -

    {{ cable.get_status_display }}

    -

    {{ cable.get_type_display|default:"" }}

    - {% if cable.length %}{{ cable.length }} {{ cable.get_length_unit_display }}{% endif %} - {% if cable.color %} -   - {% endif %} - {% else %} -

    No Cable

    - {% endif %} -
    -
    - {% if far_end %} - {% include 'dcim/inc/cable_trace_end.html' with end=far_end %} - {% endif %} +
    +
    + {% with traced_path=path.origin.trace %} + {% for near_end, cable, far_end in traced_path %} + + {# Near end #} + {% if near_end.device %} + {% include 'dcim/trace/device.html' with device=near_end.device %} + {% include 'dcim/trace/termination.html' with termination=near_end %} + {% elif near_end.power_panel %} + {% include 'dcim/trace/powerpanel.html' with powerpanel=near_end.power_panel %} + {% include 'dcim/trace/termination.html' with termination=far_end%} + {% elif near_end.circuit %} + {% include 'dcim/trace/circuit.html' with circuit=near_end.circuit %} + {% include 'dcim/trace/termination.html' with termination=near_end %} + {% endif %} + + {# Cable #} + {% if cable %} + {% include 'dcim/trace/cable.html' %} + {% endif %} + + {# Far end #} + {% if far_end.device %} + {% include 'dcim/trace/termination.html' with termination=far_end %} + {% if forloop.last %} + {% include 'dcim/trace/device.html' with device=far_end.device %} + {% endif %} + {% elif far_end.power_panel %} + {% include 'dcim/trace/termination.html' with termination=far_end %} + {% include 'dcim/trace/powerpanel.html' with powerpanel=far_end.power_panel %} + {% elif far_end.circuit %} + {% include 'dcim/trace/termination.html' with termination=far_end %} + {% if forloop.last %} + {% include 'dcim/trace/circuit.html' with circuit=far_end.circuit %} + {% endif %} + {% endif %} + + {% if forloop.last %} + {% if path.is_split %} +
    +

    Path split!

    +

    Select a node below to continue:

    +
      + {% for next_node in path.get_split_nodes %} + {% if next_node.cable %} +
    • + {{ next_node }} + (Cable {{ next_node.cable }}) +
    • + {% else %} +
    • {{ next_node }}
    • + {% endif %} + {% endfor %} +
    +
    + {% else %} +
    + Trace completed +
    Total segments: {{ traced_path|length }}
    +
    Total length: + {% if total_length %} + {{ total_length|floatformat:"-2" }} Meters + {% else %} + N/A + {% endif %} +
    +
    + {% endif %} + {% endif %} + + {% endfor %} + {% endwith %}
    -
    - {% endfor %} -
    - {% if split_ends %} -
    -
    -
    - Trace Split -
    -
    - There are multiple possible paths from this point. Select a port to continue. -
    +
    + +
    +
    + Related Paths
    -
    - - - - - - - - - - {% for termination in split_ends %} - - +
    PortConnectedTypeDescription
    {{ termination }}
    + + + + + + + + + {% for cablepath in related_paths %} + + - - + + {% empty %} + {% endfor %} -
    OriginDestinationSegments
    - {% if termination.cable %} - + + {{ cablepath.origin.parent }} / {{ cablepath.origin }} + + + {% if cablepath.destination %} + {{ cablepath.destination }} ({{ cablepath.destination.parent }}) {% else %} - + Incomplete {% endif %} {{ termination.get_type_display }}{{ termination.description|placeholder }} + {{ cablepath.segment_count }} +
    + None found +
    -
    -
    - {% elif position_stack %} -
    -

    - {% with last_position=position_stack|last %} - Trace completed, but there is no Front Port corresponding to - {{ last_position.device }} {{ last_position }}.
    - Therefore no end-to-end connection can be established. - {% endwith %} -

    -
    - {% else %} -
    -

    Trace completed!

    + +
    - {% endif %} + +
    {% endblock %} diff --git a/netbox/templates/dcim/console_connections_list.html b/netbox/templates/dcim/connections_list.html similarity index 60% rename from netbox/templates/dcim/console_connections_list.html rename to netbox/templates/dcim/connections_list.html index 15f7a36bb5..80d76e7d17 100644 --- a/netbox/templates/dcim/console_connections_list.html +++ b/netbox/templates/dcim/connections_list.html @@ -5,14 +5,14 @@
    {% export_button content_type %}
    -

    {% block title %}Console Connections{% endblock %}

    +

    {% block title %}{{ title }}{% endblock %}

    -
    +
    +
    + {% include 'inc/search_panel.html' %} +
    {% include 'responsive_table.html' %} {% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
    -
    - {% include 'inc/search_panel.html' %} -
    {% endblock %} diff --git a/netbox/templates/dcim/consoleport.html b/netbox/templates/dcim/consoleport.html index 3f4d7b3069..5d113c86a6 100644 --- a/netbox/templates/dcim/consoleport.html +++ b/netbox/templates/dcim/consoleport.html @@ -13,78 +13,78 @@ Device - {{ instance.device }} + {{ object.device }} Name - {{ instance.name }} + {{ object.name }} Label - {{ instance.label|placeholder }} + {{ object.label|placeholder }} Type - {{ instance.get_type_display }} + {{ object.get_type_display }} Description - {{ instance.description|placeholder }} + {{ object.description|placeholder }}
    - {% include 'extras/inc/tags_panel.html' with tags=instance.tags.all %} - {% plugin_left_page instance %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all %} + {% plugin_left_page object %}
    Connection
    - {% if instance.cable %} + {% if object.cable %} - {% if instance.connected_endpoint %} + + + + + {% if object.connected_endpoint %} - + - + + + + + {% endif %} - - - - - - - -
    Cable + {{ object.cable }} + + + +
    Device - {{ instance.connected_endpoint.device }} + {{ object.connected_endpoint.device }}
    Name - {{ instance.connected_endpoint.name }} + {{ object.connected_endpoint.name }}
    Type{{ instance.connected_endpoint.get_type_display|placeholder }}{{ object.connected_endpoint.get_type_display|placeholder }}
    Description{{ instance.connected_endpoint.description|placeholder }}{{ object.connected_endpoint.description|placeholder }}
    Path Status + {% if object.path.is_active %} + Reachable + {% else %} + Not Reachable + {% endif %} +
    Cable - {{ instance.cable }} - - - -
    Connection Status - {% if instance.connection_status %} - {{ instance.get_connection_status_display }} - {% else %} - {{ instance.get_connection_status_display }} - {% endif %} -
    {% else %}
    @@ -92,24 +92,24 @@ {% if perms.dcim.add_cable %} {% endif %}
    {% endif %}
    - {% plugin_right_page instance %} + {% plugin_right_page object %}
    - {% plugin_full_width_page instance %} + {% plugin_full_width_page object %}
    {% endblock %} diff --git a/netbox/templates/dcim/consoleserverport.html b/netbox/templates/dcim/consoleserverport.html index 77d17fe8a7..b64b4aff2c 100644 --- a/netbox/templates/dcim/consoleserverport.html +++ b/netbox/templates/dcim/consoleserverport.html @@ -13,78 +13,78 @@ Device - {{ instance.device }} + {{ object.device }} Name - {{ instance.name }} + {{ object.name }} Label - {{ instance.label|placeholder }} + {{ object.label|placeholder }} Type - {{ instance.get_type_display }} + {{ object.get_type_display }} Description - {{ instance.description|placeholder }} + {{ object.description|placeholder }}
    - {% include 'extras/inc/tags_panel.html' with tags=instance.tags.all %} - {% plugin_left_page instance %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all %} + {% plugin_left_page object %}
    Connection
    - {% if instance.cable %} + {% if object.cable %} - {% if instance.connected_endpoint %} + + + + + {% if object.connected_endpoint %} - + - + + + + + {% endif %} - - - - - - - -
    Cable + {{ object.cable }} + + + +
    Device - {{ instance.connected_endpoint.device }} + {{ object.connected_endpoint.device }}
    Name - {{ instance.connected_endpoint.name }} + {{ object.connected_endpoint.name }}
    Type{{ instance.connected_endpoint.get_type_display|placeholder }}{{ object.connected_endpoint.get_type_display|placeholder }}
    Description{{ instance.connected_endpoint.description|placeholder }}{{ object.connected_endpoint.description|placeholder }}
    Path Status + {% if object.path.is_active %} + Reachable + {% else %} + Not Reachable + {% endif %} +
    Cable - {{ instance.cable }} - - - -
    Connection Status - {% if instance.connection_status %} - {{ instance.get_connection_status_display }} - {% else %} - {{ instance.get_connection_status_display }} - {% endif %} -
    {% else %}
    @@ -92,24 +92,24 @@ {% if perms.dcim.add_cable %} {% endif %}
    {% endif %}
    - {% plugin_right_page instance %} + {% plugin_right_page object %}
    - {% plugin_full_width_page instance %} + {% plugin_full_width_page object %}
    {% endblock %} diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index c42ef828e5..97f7c89538 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -1,1026 +1,345 @@ -{% extends 'base.html' %} +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} {% load buttons %} {% load static %} {% load helpers %} -{% load custom_links %} {% load plugins %} -{% block title %}{{ device }}{% endblock %} - -{% block header %} -
    -
    - -
    -
    -
    -
    - - - - -
    -
    -
    -
    -
    - {% plugin_buttons device %} - {% if show_graphs %} - - {% endif %} - {% if perms.dcim.change_device %} -
    - - -
    - {% endif %} - {% if perms.dcim.add_device %} - {% clone_button device %} - {% endif %} - {% if perms.dcim.change_device %} - {% edit_button device %} - {% endif %} - {% if perms.dcim.delete_device %} - {% delete_button device %} - {% endif %} -
    -

    {{ device }}

    - {% include 'inc/created_updated.html' with obj=device %} -
    - {% custom_links device %} -
    - -{% endblock %} - {% block content %} -
    -
    -
    -
    - Device -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Site - {% if device.site.region %} - {{ device.site.region }} - - {% endif %} - {{ device.site }} -
    Rack - {% if device.rack %} - {% if device.rack.group %} - {% for group in device.rack.group.get_ancestors %} - {{ group }} - {% endfor %} - {{ device.rack.group }} - {% endif %} - {{ device.rack }} - {% else %} - None - {% endif %} -
    Position - {% if device.parent_bay %} - {% with device.parent_bay.device as parent %} - {{ parent }} {{ device.parent_bay }} - {% if parent.position %} - (U{{ parent.position }} / {{ parent.get_face_display }}) - {% endif %} - {% endwith %} - {% elif device.rack and device.position %} - U{{ device.position }} / {{ device.get_face_display }} - {% elif device.rack and device.device_type.u_height %} - Not racked - {% else %} - - {% endif %} -
    Tenant - {% if device.tenant %} - {% if device.tenant.group %} - {{ device.tenant.group }} - - {% endif %} - {{ device.tenant }} - {% else %} - None - {% endif %} -
    Device Type - {{ device.device_type.display_name }} ({{ device.device_type.u_height }}U) -
    Serial Number{{ device.serial|placeholder }}
    Asset Tag{{ device.asset_tag|placeholder }}
    -
    - {% if vc_members %} -
    -
    - Virtual Chassis -
    - - - - - - - - {% for vc_member in vc_members %} - - - - - - - {% endfor %} -
    DevicePositionMasterPriority
    - {{ vc_member }} - {{ vc_member.vc_position }}{% if device.virtual_chassis.master == vc_member %}{% endif %}{{ vc_member.vc_priority|default:"" }}
    - -
    - {% endif %} -
    -
    - Management -
    - - - - - - - - - - - - - - - - - - - - - - {% if device.cluster %} - - - - - {% endif %} -
    Role - {{ device.device_role }} -
    Platform - {% if device.platform %} - {{ device.platform }} - {% else %} - None - {% endif %} -
    Status - {{ device.get_status_display }} -
    Primary IPv4 - {% if device.primary_ip4 %} - {{ device.primary_ip4.address.ip }} - {% if device.primary_ip4.nat_inside %} - (NAT for {{ device.primary_ip4.nat_inside.address.ip }}) - {% elif device.primary_ip4.nat_outside %} - (NAT: {{ device.primary_ip4.nat_outside.address.ip }}) - {% endif %} - {% else %} - - {% endif %} -
    Primary IPv6 - {% if device.primary_ip6 %} - {{ device.primary_ip6.address.ip }} - {% if device.primary_ip6.nat_inside %} - (NAT for {{ device.primary_ip6.nat_inside.address.ip }}) - {% elif device.primary_ip6.nat_outside %} - (NAT: {{ device.primary_ip6.nat_outside.address.ip }}) - {% endif %} - {% else %} - - {% endif %} -
    Cluster - {% if device.cluster.group %} - {{ device.cluster.group }} - - {% endif %} - {{ device.cluster }} -
    -
    - {% include 'inc/custom_fields_panel.html' with obj=device %} - {% include 'extras/inc/tags_panel.html' with tags=device.tags.all url='dcim:device_list' %} -
    -
    - Comments -
    -
    - {% if device.comments %} - {{ device.comments|render_markdown }} - {% else %} - None - {% endif %} -
    -
    - {% plugin_left_page device %} -
    -
    - {% if powerports and poweroutlets %} -
    -
    - Power Utilization -
    - - - - - - - - - {% for pp in powerports %} - {% with utilization=pp.get_power_draw powerfeed=pp.connected_endpoint %} - - - - - {% if powerfeed.available_power %} - - - {% else %} - - - {% endif %} - - {% for leg in utilization.legs %} - - - - - - {% with phase_available=powerfeed.available_power|divide:3 %} - - {% endwith %} - - {% endfor %} - {% endwith %} - {% endfor %} -
    InputOutletsAllocatedAvailableUtilization
    {{ pp }}{{ utilization.outlet_count }}{{ utilization.allocated }}VA{{ powerfeed.available_power }}VA{% utilization_graph utilization.allocated|percentage:powerfeed.available_power %}
    Leg {{ leg.name }}{{ leg.outlet_count }}{{ leg.allocated }}{{ powerfeed.available_power|divide:3 }}VA{% utilization_graph leg.allocated|percentage:phase_available %}
    -
    - {% endif %} - {% if request.user.is_authenticated %} -
    -
    - Secrets -
    - {% if secrets %} - - {% for secret in secrets %} - {% include 'secrets/inc/secret_tr.html' %} - {% endfor %} -
    - {% else %} -
    - None found -
    - {% endif %} - {% if perms.secrets.add_secret %} -
    - {% csrf_token %} -
    - - {% endif %} -
    - {% endif %} -
    -
    - Services -
    - {% if services %} - - {% for service in services %} - {% include 'ipam/inc/service.html' %} - {% endfor %} -
    - {% else %} -
    - None -
    - {% endif %} - {% if perms.ipam.add_service %} - - {% endif %} -
    -
    -
    - Images -
    - {% include 'inc/image_attachments.html' with images=device.images.all %} - {% if perms.extras.add_imageattachment %} - - {% endif %} -
    -
    -
    - Related Devices -
    - {% if related_devices %} - - {% for rd in related_devices %} - - - - - - {% endfor %} -
    - {{ rd }} - - {% if rd.rack %} - Rack {{ rd.rack }} - {% else %} - - {% endif %} - {{ rd.device_type.display_name }}
    - {% else %} -
    None found
    - {% endif %} -
    - {% plugin_right_page device %} -
    -
    - {% plugin_full_width_page device %} -
    -
    -
    -
    -
    -
    -
    - {% csrf_token %} -
    -
    - Interfaces -
    - -
    -
    - +
    +
    +
    +
    +
    + Device
    -
    - - +
    - {% if perms.dcim.change_interface or perms.dcim.delete_interface %} - - {% endif %} - - - - - - - - + + - - - {% for iface in interfaces %} - {% include 'dcim/inc/interface.html' %} - {% endfor %} - -
    NameLAGDescriptionMTUModeCableConnectionSite + {% if object.site.region %} + {{ object.site.region }} / + {% endif %} + {{ object.site }} +
    - -
    - -
    -
    -
    - {% csrf_token %} -
    -
    - Front Ports -
    - - - {% if perms.dcim.change_frontport or perms.dcim.delete_frontport %} - - {% endif %} - - - - - - - - + + - - - {% for frontport in frontports %} - {% include 'dcim/inc/frontport.html' %} - {% endfor %} - -
    NameTypeRear PortPositionDescriptionCableConnectionRack + {% if object.rack %} + {% if object.rack.group %} + {{ object.rack.group }} / + {% endif %} + {{ object.rack }} + {% else %} + None + {% endif %} +
    - -
    -
    -
    -
    -
    - {% csrf_token %} -
    -
    - Rear Ports -
    - - - {% if perms.dcim.change_rearport or perms.dcim.delete_rearport %} - - {% endif %} - - - - - - - + + - - - {% for rearport in rearports %} - {% include 'dcim/inc/rearport.html' %} - {% endfor %} - -
    NameTypePositionsDescriptionCableConnectionPosition + {% if object.parent_bay %} + {% with object.parent_bay.device as parent %} + {{ parent }} / {{ object.parent_bay }} + {% if parent.position %} + (U{{ parent.position }} / {{ parent.get_face_display }}) + {% endif %} + {% endwith %} + {% elif object.rack and object.position %} + U{{ object.position }} / {{ object.get_face_display }} + {% elif object.rack and object.device_type.u_height %} + Not racked + {% else %} + + {% endif %} +
    - -
    -
    -
    -
    -
    - {% csrf_token %} -
    -
    - Console Ports -
    - - - {% if perms.dcim.change_consoleport or perms.dcim.delete_consoleport %} - - {% endif %} - - - - - - + + - - {% for cp in consoleports %} - {% include 'dcim/inc/consoleport.html' %} - {% endfor %} -
    NameTypeDescriptionCableConnectionTenant + {% if object.tenant %} + {% if object.tenant.group %} + {{ object.tenant.group }} / + {% endif %} + {{ object.tenant }} + {% else %} + None + {% endif %} +
    - -
    -
    -
    -
    -
    - {% csrf_token %} -
    -
    - Console Server Ports -
    - - - {% if perms.dcim.change_consoleserverport or perms.dcim.delete_consoleserverport %} - - {% endif %} - - - - - - + + - - - {% for csp in consoleserverports %} - {% include 'dcim/inc/consoleserverport.html' %} - {% endfor %} - -
    NameTypeDescriptionCableConnectionDevice Type + {{ object.device_type.display_name }} ({{ object.device_type.u_height }}U) +
    - -
    -
    -
    -
    -
    - {% csrf_token %} -
    -
    - Power Ports -
    - - - {% if perms.dcim.change_consoleport or perms.dcim.delete_consoleport %} - - {% endif %} - - - - - - - + + - - {% for pp in powerports %} - {% include 'dcim/inc/powerport.html' %} - {% endfor %} -
    NameTypeDrawDescriptionCableConnectionSerial Number{{ object.serial|placeholder }}
    - -
    -
    -
    -
    -
    - {% csrf_token %} -
    -
    - Power Outlets -
    - - - {% if perms.dcim.change_poweroutlet or perms.dcim.delete_poweroutlet %} - - {% endif %} - - - - - - - + + - - - {% for po in poweroutlets %} - {% include 'dcim/inc/poweroutlet.html' %} - {% endfor %} - -
    NameTypeInput/LegDescriptionCableConnectionAsset Tag{{ object.asset_tag|placeholder }}
    - - -
    -
    -
    - {% csrf_token %} -
    -
    - Device Bays -
    - - + + {% endif %} +
    +
    + Management +
    +
    + + + + + + + + + + + + + + + + - {% if perms.dcim.change_devicebay or perms.dcim.delete_devicebay %} - - {% endif %} - - - - - + + - - - {% for devicebay in devicebays %} - {% include 'dcim/inc/devicebay.html' %} - {% empty %} + {% if object.cluster %} + + + + + {% endif %} +
    Role + {{ object.device_role }} +
    Platform + {% if object.platform %} + {{ object.platform }} + {% else %} + None + {% endif %} +
    Status + {{ object.get_status_display }} +
    Primary IPv4 + {% if object.primary_ip4 %} + {{ object.primary_ip4.address.ip }} + {% if object.primary_ip4.nat_inside %} + (NAT for {{ object.primary_ip4.nat_inside.address.ip }}) + {% elif object.primary_ip4.nat_outside %} + (NAT: {{ object.primary_ip4.nat_outside.address.ip }}) + {% endif %} + {% else %} + + {% endif %} +
    NameStatusDescriptionInstalled DevicePrimary IPv6 + {% if object.primary_ip6 %} + {{ object.primary_ip6.address.ip }} + {% if object.primary_ip6.nat_inside %} + (NAT for {{ object.primary_ip6.nat_inside.address.ip }}) + {% elif object.primary_ip6.nat_outside %} + (NAT: {{ object.primary_ip6.nat_outside.address.ip }}) + {% endif %} + {% else %} + + {% endif %} +
    Cluster + {% if object.cluster.group %} + {{ object.cluster.group }} / + {% endif %} + {{ object.cluster }} +
    +
    + {% include 'inc/custom_fields_panel.html' %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='dcim:device_list' %} +
    +
    + Comments +
    +
    + {% if object.comments %} + {{ object.comments|render_markdown }} + {% else %} + None + {% endif %} +
    +
    + {% plugin_left_page object %} +
    +
    + {% if power_ports and poweroutlets %} +
    +
    + Power Utilization +
    + - + + + + + - {% endfor %} - -
    — No device bays defined —InputOutletsAllocatedAvailableUtilization
    - + {% endif %} + {% if perms.secrets.view_secret %} +
    +
    + Secrets +
    + {% include 'secrets/inc/assigned_secrets.html' %} + {% if perms.secrets.add_secret %} + + {% endif %} +
    + {% endif %} +
    +
    + Services +
    + {% if services %} + + {% for service in services %} + {% include 'ipam/inc/service.html' %} + {% endfor %} +
    + {% else %} +
    + None +
    {% endif %} - {% if devicebays and perms.dcim.delete_devicebay %} - + {% if perms.ipam.add_service %} + {% endif %} - {% if perms.dcim.add_devicebay %} - + +
    +
    +
    + Related Devices +
    + {% if related_devices %} + + {% for rd in related_devices %} + + + + + + {% endfor %} +
    + {{ rd }} + + {% if rd.rack %} + Rack {{ rd.rack }} + {% else %} + + {% endif %} + {{ rd.device_type.display_name }}
    + {% else %} +
    None found
    + {% endif %} +
    + {% plugin_right_page object %} +
    +
    +
    +
    + {% plugin_full_width_page object %}
    - +
    -{% include 'inc/modal.html' with name='graphs' title='Graphs' %} -{% include 'secrets/inc/private_key_modal.html' %} + {% include 'secrets/inc/private_key_modal.html' %} {% endblock %} {% block javascript %} - - - - + {% endblock %} diff --git a/netbox/templates/dcim/device/base.html b/netbox/templates/dcim/device/base.html new file mode 100644 index 0000000000..631abde891 --- /dev/null +++ b/netbox/templates/dcim/device/base.html @@ -0,0 +1,178 @@ +{% extends 'base.html' %} +{% load buttons %} +{% load static %} +{% load helpers %} +{% load custom_links %} +{% load plugins %} + +{% block title %}{{ object }}{% endblock %} + +{% block header %} +
    +
    + +
    +
    +
    +
    + + + + +
    +
    +
    +
    +
    + {% plugin_buttons object %} + {% if perms.dcim.change_device %} +
    + + +
    + {% endif %} + {% if perms.dcim.add_device %} + {% clone_button object %} + {% endif %} + {% if perms.dcim.change_device %} + {% edit_button object %} + {% endif %} + {% if perms.dcim.delete_device %} + {% delete_button object %} + {% endif %} +
    +

    {{ object }}

    + {% include 'inc/created_updated.html' %} +
    + {% custom_links object %} +
    + +{% endblock %} diff --git a/netbox/templates/dcim/device_config.html b/netbox/templates/dcim/device/config.html similarity index 92% rename from netbox/templates/dcim/device_config.html rename to netbox/templates/dcim/device/config.html index fa35f28aa6..4b73a25777 100644 --- a/netbox/templates/dcim/device_config.html +++ b/netbox/templates/dcim/device/config.html @@ -1,7 +1,7 @@ -{% extends 'dcim/device.html' %} +{% extends 'dcim/device/base.html' %} {% load static %} -{% block title %}{{ device }} - Config{% endblock %} +{% block title %}{{ object }} - Config{% endblock %} {% block content %} {% include 'inc/ajax_loader.html' %} @@ -36,7 +36,7 @@ + +{% endblock %} diff --git a/netbox/templates/dcim/device/consoleserverports.html b/netbox/templates/dcim/device/consoleserverports.html new file mode 100644 index 0000000000..61d3afd8b6 --- /dev/null +++ b/netbox/templates/dcim/device/consoleserverports.html @@ -0,0 +1,53 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load helpers %} +{% load static %} + +{% block content %} +
    + {% csrf_token %} +
    +
    + Console Server Ports +
    + {% if request.user.is_authenticated %} + + {% endif %} +
    +
    + {% render_table consoleserverport_table 'inc/table.html' %} + +
    +
    + {% table_config_form consoleserverport_table %} +{% endblock %} + +{% block javascript %} + + +{% endblock %} diff --git a/netbox/templates/dcim/device/devicebays.html b/netbox/templates/dcim/device/devicebays.html new file mode 100644 index 0000000000..d23f307e74 --- /dev/null +++ b/netbox/templates/dcim/device/devicebays.html @@ -0,0 +1,49 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load helpers %} +{% load static %} + +{% block content %} +
    + {% csrf_token %} +
    +
    + Device Bays +
    + {% if request.user.is_authenticated %} + + {% endif %} +
    +
    + {% render_table devicebay_table 'inc/table.html' %} + +
    +
    + {% table_config_form devicebay_table %} +{% endblock %} + +{% block javascript %} + +{% endblock %} diff --git a/netbox/templates/dcim/device/frontports.html b/netbox/templates/dcim/device/frontports.html new file mode 100644 index 0000000000..7084f592ef --- /dev/null +++ b/netbox/templates/dcim/device/frontports.html @@ -0,0 +1,53 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load helpers %} +{% load static %} + +{% block content %} +
    + {% csrf_token %} +
    +
    + Front Ports +
    + {% if request.user.is_authenticated %} + + {% endif %} +
    +
    + {% render_table frontport_table 'inc/table.html' %} + +
    +
    + {% table_config_form frontport_table %} +{% endblock %} + +{% block javascript %} + + +{% endblock %} diff --git a/netbox/templates/dcim/device/interfaces.html b/netbox/templates/dcim/device/interfaces.html new file mode 100644 index 0000000000..34897a6015 --- /dev/null +++ b/netbox/templates/dcim/device/interfaces.html @@ -0,0 +1,57 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load helpers %} +{% load static %} + +{% block content %} +
    + {% csrf_token %} +
    +
    + Interfaces +
    + {% if request.user.is_authenticated %} + + {% endif %} +
    +
    + +
    +
    + {% render_table interface_table 'inc/table.html' %} + +
    +
    + {% table_config_form interface_table %} +{% endblock %} + +{% block javascript %} + + + +{% endblock %} diff --git a/netbox/templates/dcim/device/inventory.html b/netbox/templates/dcim/device/inventory.html new file mode 100644 index 0000000000..5e52667cb0 --- /dev/null +++ b/netbox/templates/dcim/device/inventory.html @@ -0,0 +1,49 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load helpers %} +{% load static %} + +{% block content %} +
    + {% csrf_token %} +
    +
    + Inventory Items +
    + {% if request.user.is_authenticated %} + + {% endif %} +
    +
    + {% render_table inventoryitem_table 'inc/table.html' %} + +
    +
    + {% table_config_form inventoryitem_table %} +{% endblock %} + +{% block javascript %} + +{% endblock %} diff --git a/netbox/templates/dcim/device_lldp_neighbors.html b/netbox/templates/dcim/device/lldp_neighbors.html similarity index 94% rename from netbox/templates/dcim/device_lldp_neighbors.html rename to netbox/templates/dcim/device/lldp_neighbors.html index 221c17a52e..3216b37918 100644 --- a/netbox/templates/dcim/device_lldp_neighbors.html +++ b/netbox/templates/dcim/device/lldp_neighbors.html @@ -1,6 +1,6 @@ -{% extends 'dcim/device.html' %} +{% extends 'dcim/device/base.html' %} -{% block title %}{{ device }} - LLDP Neighbors{% endblock %} +{% block title %}{{ object }} - LLDP Neighbors{% endblock %} {% block content %} {% include 'inc/ajax_loader.html' %} @@ -32,7 +32,7 @@ {% elif iface.connected_endpoint.circuit %} {% with circuit=iface.connected_endpoint.circuit %} - + {{ circuit.provider }} {{ circuit }} {% endwith %} @@ -52,7 +52,7 @@ + +{% endblock %} diff --git a/netbox/templates/dcim/device/powerports.html b/netbox/templates/dcim/device/powerports.html new file mode 100644 index 0000000000..9b56b64a3a --- /dev/null +++ b/netbox/templates/dcim/device/powerports.html @@ -0,0 +1,53 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load helpers %} +{% load static %} + +{% block content %} +
    + {% csrf_token %} +
    +
    + Power Ports +
    + {% if request.user.is_authenticated %} + + {% endif %} +
    +
    + {% render_table powerport_table 'inc/table.html' %} + +
    +
    + {% table_config_form powerport_table %} +{% endblock %} + +{% block javascript %} + + +{% endblock %} diff --git a/netbox/templates/dcim/device/rearports.html b/netbox/templates/dcim/device/rearports.html new file mode 100644 index 0000000000..eeef667c2c --- /dev/null +++ b/netbox/templates/dcim/device/rearports.html @@ -0,0 +1,53 @@ +{% extends 'dcim/device/base.html' %} +{% load render_table from django_tables2 %} +{% load static %} +{% load helpers %} + +{% block content %} +
    + {% csrf_token %} +
    +
    + Rear Ports +
    + {% if request.user.is_authenticated %} + + {% endif %} +
    +
    + {% render_table rearport_table 'inc/table.html' %} + +
    +
    + {% table_config_form rearport_table %} +{% endblock %} + +{% block javascript %} + + +{% endblock %} diff --git a/netbox/templates/dcim/device_status.html b/netbox/templates/dcim/device/status.html similarity index 86% rename from netbox/templates/dcim/device_status.html rename to netbox/templates/dcim/device/status.html index ffb61286e0..b7f8d0eaa5 100644 --- a/netbox/templates/dcim/device_status.html +++ b/netbox/templates/dcim/device/status.html @@ -1,4 +1,4 @@ -{% extends 'dcim/device.html' %} +{% extends 'dcim/device/base.html' %} {% load static %} {% block title %}{{ device }} - Status{% endblock %} @@ -46,19 +46,19 @@
    Environment
    - + - + - + - + - +
    CPU CPU
    Memory Memory
    Temperature Temperature
    Fans Fans
    Power Power
    @@ -70,7 +70,7 @@ -{% endblock %} diff --git a/netbox/templates/dcim/site_edit.html b/netbox/templates/dcim/site_edit.html index 5819b964f6..274863fc4d 100644 --- a/netbox/templates/dcim/site_edit.html +++ b/netbox/templates/dcim/site_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load form_helpers %} {% block form %} diff --git a/netbox/templates/dcim/trace/cable.html b/netbox/templates/dcim/trace/cable.html new file mode 100644 index 0000000000..4235768a6c --- /dev/null +++ b/netbox/templates/dcim/trace/cable.html @@ -0,0 +1,19 @@ +{% load helpers %} + +
    + + + {% if cable.label %}{{ cable.label }}{% else %}Cable #{{ cable.pk }}{% endif %} + +
    + {% if cable.type %} + {{ cable.get_type_display|default:"" }}
    + {% endif %} + {% if cable.length %} + ({{ cable.length }} {{ cable.get_length_unit_display }})
    + {% endif %} + {{ cable.get_status_display }}
    + {% for tag in cable.tags.all %} + {% tag tag 'dcim:cable_list' %} + {% endfor %} +
    diff --git a/netbox/templates/dcim/trace/circuit.html b/netbox/templates/dcim/trace/circuit.html new file mode 100644 index 0000000000..70e191dd29 --- /dev/null +++ b/netbox/templates/dcim/trace/circuit.html @@ -0,0 +1,5 @@ + diff --git a/netbox/templates/dcim/trace/device.html b/netbox/templates/dcim/trace/device.html new file mode 100644 index 0000000000..c3696e786d --- /dev/null +++ b/netbox/templates/dcim/trace/device.html @@ -0,0 +1,8 @@ +
    + {{ device }}
    + {{ device.device_type.manufacturer }} {{ device.device_type }}
    + {{ device.site }} + {% if device.rack %} + / {{ device.rack }} + {% endif %} +
    diff --git a/netbox/templates/dcim/trace/powerpanel.html b/netbox/templates/dcim/trace/powerpanel.html new file mode 100644 index 0000000000..f5b6230a79 --- /dev/null +++ b/netbox/templates/dcim/trace/powerpanel.html @@ -0,0 +1,5 @@ + diff --git a/netbox/templates/dcim/trace/termination.html b/netbox/templates/dcim/trace/termination.html new file mode 100644 index 0000000000..e85bded05b --- /dev/null +++ b/netbox/templates/dcim/trace/termination.html @@ -0,0 +1,8 @@ +{% load helpers %} +
    + {{ termination }}
    + {{ termination|meta:"verbose_name"|bettertitle }} + {% if termination.type %} + ({{ termination.get_type_display }}) + {% endif %} +
    diff --git a/netbox/templates/dcim/virtualchassis.html b/netbox/templates/dcim/virtualchassis.html index 18ec8c4e7c..eb9972406c 100644 --- a/netbox/templates/dcim/virtualchassis.html +++ b/netbox/templates/dcim/virtualchassis.html @@ -9,10 +9,10 @@
    @@ -21,7 +21,7 @@
    @@ -29,26 +29,26 @@
    - {% plugin_buttons virtualchassis %} + {% plugin_buttons object %} {% if perms.dcim.change_virtualchassis %} - {% edit_button virtualchassis %} + {% edit_button object %} {% endif %} {% if perms.dcim.delete_virtualchassis %} - {% delete_button virtualchassis %} + {% delete_button object %} {% endif %}
    -

    {% block title %}{{ virtualchassis }}{% endblock %}

    - {% include 'inc/created_updated.html' with obj=virtualchassis %} +

    {% block title %}{{ object }}{% endblock %}

    + {% include 'inc/created_updated.html' %}
    - {% custom_links virtualchassis %} + {% custom_links object %}
    @@ -64,13 +64,13 @@

    {% block title %}{{ virtualchassis }}{% endblock %}

    - +
    Domain{{ virtualchassis.domain|placeholder }}{{ object.domain|placeholder }}
    Master - {% if virtualchassis.master %} - {{ virtualchassis.master }} + {% if object.master %} + {{ object.master }} {% else %} {% endif %} @@ -78,8 +78,9 @@

    {% block title %}{{ virtualchassis }}{% endblock %}

    - {% include 'extras/inc/tags_panel.html' with tags=virtualchassis.tags.all url='dcim:virtualchassis_list' %} - {% plugin_left_page virtualchassis %} + {% include 'inc/custom_fields_panel.html' %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='dcim:virtualchassis_list' %} + {% plugin_left_page object %}
    @@ -99,25 +100,25 @@

    {% block title %}{{ virtualchassis }}{% endblock %}

    {{ vc_member }} {{ vc_member.vc_position }} - {% if virtualchassis.master == vc_member %}{% endif %} + {% if object.master == vc_member %}{% endif %} {{ vc_member.vc_priority|placeholder }} {% endfor %} {% if perms.dcim.change_virtualchassis %} {% endif %}
    - {% plugin_right_page virtualchassis %} + {% plugin_right_page object %}
    - {% plugin_full_width_page virtualchassis %} + {% plugin_full_width_page object %}
    {% endblock %} diff --git a/netbox/templates/dcim/virtualchassis_add.html b/netbox/templates/dcim/virtualchassis_add.html index ac94cc7dfb..2a68cb5e4c 100644 --- a/netbox/templates/dcim/virtualchassis_add.html +++ b/netbox/templates/dcim/virtualchassis_add.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load form_helpers %} {% block form %} @@ -20,4 +20,12 @@ {% render_field form.initial_position %} + {% if form.custom_fields %} +
    +
    Custom Fields
    +
    + {% render_custom_fields form %} +
    +
    + {% endif %} {% endblock %} diff --git a/netbox/templates/dcim/virtualchassis_edit.html b/netbox/templates/dcim/virtualchassis_edit.html index 54bdc9fe84..6b3d800f15 100644 --- a/netbox/templates/dcim/virtualchassis_edit.html +++ b/netbox/templates/dcim/virtualchassis_edit.html @@ -21,9 +21,20 @@

    {% block title %}{% if vc_form.instance %}Editing {{ vc_form.instance }}{% e
    Virtual Chassis
    - {% render_form vc_form %} + {% render_field vc_form.name %} + {% render_field vc_form.domain %} + {% render_field vc_form.master %} + {% render_field vc_form.tags %}
    + {% if vc_form.custom_fields %} +
    +
    Custom Fields
    +
    + {% render_custom_fields vc_form %} +
    +
    + {% endif %}
    Members
    @@ -72,7 +83,7 @@

    {% block title %}{% if vc_form.instance %}Editing {{ vc_form.instance }}{% e

    diff --git a/netbox/templates/exceptions/import_error.html b/netbox/templates/exceptions/import_error.html index 78f4db9c03..776014e6fa 100644 --- a/netbox/templates/exceptions/import_error.html +++ b/netbox/templates/exceptions/import_error.html @@ -5,14 +5,14 @@ A module import error occurred during this request. Common causes include the following:

    - Missing required packages - This installation of NetBox might be + Missing required packages - This installation of NetBox might be missing one or more required Python packages. These packages are listed in requirements.txt and local_requirements.txt, and are normally installed as part of the installation or upgrade process. To verify installed packages, run pip freeze from the console and compare the output to the list of required packages.

    - WSGI service not restarted after upgrade - If this installation + WSGI service not restarted after upgrade - If this installation has recently been upgraded, check that the WSGI service (e.g. gunicorn or uWSGI) has been restarted. This ensures that the new code is running.

    diff --git a/netbox/templates/exceptions/permission_error.html b/netbox/templates/exceptions/permission_error.html index 9898f25dc1..d6fb3d18c9 100644 --- a/netbox/templates/exceptions/permission_error.html +++ b/netbox/templates/exceptions/permission_error.html @@ -5,7 +5,7 @@ A file permission error was detected while processing this request. Common causes include the following:

    - Insufficient write permission to the media root - The configured + Insufficient write permission to the media root - The configured media root is {{ settings.MEDIA_ROOT }}. Ensure that the user NetBox runs as has access to write files to all locations within this path.

    diff --git a/netbox/templates/exceptions/programming_error.html b/netbox/templates/exceptions/programming_error.html index 48ab707b70..d55c311ccb 100644 --- a/netbox/templates/exceptions/programming_error.html +++ b/netbox/templates/exceptions/programming_error.html @@ -5,12 +5,12 @@ A database programming error was detected while processing this request. Common causes include the following:

    - Database migrations missing - When upgrading to a new NetBox release, the upgrade script must + Database migrations missing - When upgrading to a new NetBox release, the upgrade script must be run to apply any new database migrations. You can run migrations manually by executing python3 manage.py migrate from the command line.

    - Unsupported PostgreSQL version - Ensure that PostgreSQL version 9.6 or higher is in use. You + Unsupported PostgreSQL version - Ensure that PostgreSQL version 9.6 or higher is in use. You can check this by connecting to the database using NetBox's credentials and issuing a query for SELECT VERSION().

    diff --git a/netbox/templates/extras/configcontext.html b/netbox/templates/extras/configcontext.html index 7dd8d8b0cd..408e51b751 100644 --- a/netbox/templates/extras/configcontext.html +++ b/netbox/templates/extras/configcontext.html @@ -7,7 +7,7 @@
    @@ -16,7 +16,7 @@
    @@ -25,23 +25,23 @@
    {% if perms.extras.change_configcontext %} - - + + Edit this config context {% endif %}
    -

    {% block title %}{{ configcontext }}{% endblock %}

    +

    {% block title %}{{ object }}{% endblock %}

    {% endblock %} {% block content %} @@ -55,29 +55,29 @@

    {% block title %}{{ configcontext }}{% endblock %}

    - + @@ -92,9 +92,9 @@

    {% block title %}{{ configcontext }}{% endblock %}

    {% if virtual_chassis.pk %} - + {% endif %}
    Name - {{ configcontext.name }} + {{ object.name }}
    Weight - {{ configcontext.weight }} + {{ object.weight }}
    Description{{ configcontext.description|placeholder }}{{ object.description|placeholder }}
    Active - {% if configcontext.is_active %} + {% if object.is_active %} - + {% else %} - + {% endif %}
    Regions - {% if configcontext.regions.all %} + {% if object.regions.all %}
      - {% for region in configcontext.regions.all %} + {% for region in object.regions.all %}
    • {{ region }}
    • {% endfor %}
    @@ -106,9 +106,9 @@

    {% block title %}{{ configcontext }}{% endblock %}

    Sites - {% if configcontext.sites.all %} + {% if object.sites.all %}
      - {% for site in configcontext.sites.all %} + {% for site in object.sites.all %}
    • {{ site }}
    • {% endfor %}
    @@ -120,9 +120,9 @@

    {% block title %}{{ configcontext }}{% endblock %}

    Roles - {% if configcontext.roles.all %} + {% if object.roles.all %}
      - {% for role in configcontext.roles.all %} + {% for role in object.roles.all %}
    • {{ role }}
    • {% endfor %}
    @@ -134,9 +134,9 @@

    {% block title %}{{ configcontext }}{% endblock %}

    Platforms - {% if configcontext.platforms.all %} + {% if object.platforms.all %}
      - {% for platform in configcontext.platforms.all %} + {% for platform in object.platforms.all %}
    • {{ platform }}
    • {% endfor %}
    @@ -148,9 +148,9 @@

    {% block title %}{{ configcontext }}{% endblock %}

    Cluster Groups - {% if configcontext.cluster_groups.all %} + {% if object.cluster_groups.all %}
      - {% for cluster_group in configcontext.cluster_groups.all %} + {% for cluster_group in object.cluster_groups.all %}
    • {{ cluster_group }}
    • {% endfor %}
    @@ -162,9 +162,9 @@

    {% block title %}{{ configcontext }}{% endblock %}

    Clusters - {% if configcontext.clusters.all %} + {% if object.clusters.all %}
      - {% for cluster in configcontext.clusters.all %} + {% for cluster in object.clusters.all %}
    • {{ cluster }}
    • {% endfor %}
    @@ -176,9 +176,9 @@

    {% block title %}{{ configcontext }}{% endblock %}

    Tenant Groups - {% if configcontext.tenant_groups.all %} + {% if object.tenant_groups.all %}
      - {% for tenant_group in configcontext.tenant_groups.all %} + {% for tenant_group in object.tenant_groups.all %}
    • {{ tenant_group }}
    • {% endfor %}
    @@ -190,9 +190,9 @@

    {% block title %}{{ configcontext }}{% endblock %}

    Tenants - {% if configcontext.tenants.all %} + {% if object.tenants.all %}
      - {% for tenant in configcontext.tenants.all %} + {% for tenant in object.tenants.all %}
    • {{ tenant }}
    • {% endfor %}
    @@ -204,9 +204,9 @@

    {% block title %}{{ configcontext }}{% endblock %}

    Tags - {% if configcontext.tags.all %} + {% if object.tags.all %}
      - {% for tag in configcontext.tags.all %} + {% for tag in object.tags.all %}
    • {{ tag }}
    • {% endfor %}
    @@ -225,7 +225,7 @@

    {% block title %}{{ configcontext }}{% endblock %}

    {% include 'extras/inc/configcontext_format.html' %}
    - {% include 'extras/inc/configcontext_data.html' with data=configcontext.data format=format %} + {% include 'extras/inc/configcontext_data.html' with data=object.data format=format %}
    diff --git a/netbox/templates/extras/configcontext_edit.html b/netbox/templates/extras/configcontext_edit.html index 9e922108c0..08e92d2588 100644 --- a/netbox/templates/extras/configcontext_edit.html +++ b/netbox/templates/extras/configcontext_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load form_helpers %} {% block form %} diff --git a/netbox/templates/extras/object_changelog.html b/netbox/templates/extras/object_changelog.html index 970b54d4d2..64f76fe607 100644 --- a/netbox/templates/extras/object_changelog.html +++ b/netbox/templates/extras/object_changelog.html @@ -1,9 +1,8 @@ {% extends base_template %} -{% block title %}{% if obj %}{{ obj }}{% else %}{{ block.super }}{% endif %} - Change Log{% endblock %} +{% block title %}{{ block.super }} - Change Log{% endblock %} {% block content %} - {% if obj %}

    {{ obj }}

    {% endif %} {% include 'panel_table.html' %} {% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
    diff --git a/netbox/templates/extras/object_configcontext.html b/netbox/templates/extras/object_configcontext.html index cc77def065..ca521f5663 100644 --- a/netbox/templates/extras/object_configcontext.html +++ b/netbox/templates/extras/object_configcontext.html @@ -23,15 +23,15 @@ Local Context
    - {% if obj.local_context_data %} - {% include 'extras/inc/configcontext_data.html' with data=obj.local_context_data format=format %} + {% if object.local_context_data %} + {% include 'extras/inc/configcontext_data.html' with data=object.local_context_data format=format %} {% else %} None {% endif %}
    diff --git a/netbox/templates/extras/objectchange.html b/netbox/templates/extras/objectchange.html index dcaaafdca9..15265889ea 100644 --- a/netbox/templates/extras/objectchange.html +++ b/netbox/templates/extras/objectchange.html @@ -1,21 +1,21 @@ {% extends 'base.html' %} {% load helpers %} -{% block title %}{{ objectchange }}{% endblock %} +{% block title %}{{ object }}{% endblock %} {% block header %}
    @@ -24,7 +24,7 @@
    @@ -44,41 +44,41 @@
    Time - {{ objectchange.time }} + {{ object.time }}
    User - {{ objectchange.user|default:objectchange.user_name }} + {{ object.user|default:object.user_name }}
    Action - {{ objectchange.get_action_display }} + {{ object.get_action_display }}
    Object Type - {{ objectchange.changed_object_type }} + {{ object.changed_object_type }}
    Object - {% if objectchange.changed_object.get_absolute_url %} - {{ objectchange.changed_object }} + {% if object.changed_object.get_absolute_url %} + {{ object.changed_object }} {% else %} - {{ objectchange.object_repr }} + {{ object.object_repr }} {% endif %}
    Request ID - {{ objectchange.request_id }} + {{ object.request_id }}
    @@ -88,19 +88,19 @@ Difference
    {% if diff_added == diff_removed %} - {% if objectchange.action == 'create' %} + {% if object.action == 'create' %} Object created - {% elif objectchange.action == 'delete' %} + {% elif object.action == 'delete' %} Object deleted {% else %} No changes @@ -119,7 +119,7 @@ Object Data
    -
    {{ objectchange.object_data|render_json }}
    +
    {{ object.object_data|render_json }}
    @@ -129,7 +129,7 @@ {% include 'panel_table.html' with table=related_changes_table heading='Related Changes' panel_class='default' %} {% if related_changes_count > related_changes_table.rows|length %} {% endif %} diff --git a/netbox/templates/extras/objectchange_list.html b/netbox/templates/extras/objectchange_list.html index 3672f4f041..efcac976db 100644 --- a/netbox/templates/extras/objectchange_list.html +++ b/netbox/templates/extras/objectchange_list.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_list.html' %} +{% extends 'generic/object_list.html' %} {% block title %}Change Log{% endblock %} diff --git a/netbox/templates/extras/report.html b/netbox/templates/extras/report.html index 355c21c009..76a34c0609 100644 --- a/netbox/templates/extras/report.html +++ b/netbox/templates/extras/report.html @@ -19,9 +19,9 @@ {% csrf_token %} diff --git a/netbox/templates/extras/report_list.html b/netbox/templates/extras/report_list.html index 528eb61570..7685cdacf6 100644 --- a/netbox/templates/extras/report_list.html +++ b/netbox/templates/extras/report_list.html @@ -44,9 +44,9 @@

    {{ module|bettertitle }}

    {% csrf_token %} @@ -88,7 +88,7 @@

    {{ module|bettertitle }}

      {% for report in module_reports %} - {{ report.name }} + {{ report.name }}
      {% include 'extras/inc/job_label.html' with result=report.result %}
      diff --git a/netbox/templates/extras/script.html b/netbox/templates/extras/script.html index 76a86b4354..5808f707f7 100644 --- a/netbox/templates/extras/script.html +++ b/netbox/templates/extras/script.html @@ -31,7 +31,7 @@

      {{ script }}

      {% if not perms.extras.run_script %}
      - + You do not have permission to run scripts.
      {% endif %} @@ -48,13 +48,13 @@

      {{ script }}

      {% else %}
      - + This script does not require any input to run.
      {% render_form form %} {% endif %}
      diff --git a/netbox/templates/extras/script_list.html b/netbox/templates/extras/script_list.html index caf9c34fd7..dccbba152b 100644 --- a/netbox/templates/extras/script_list.html +++ b/netbox/templates/extras/script_list.html @@ -56,7 +56,7 @@

      {{ module|bettertitle }}

        {% for class_name, script in module_scripts.items %} - {{ script.name }} + {{ script.name }}
        {% include 'extras/inc/job_label.html' with result=script.result %}
        diff --git a/netbox/templates/extras/tag.html b/netbox/templates/extras/tag.html index ff54a48004..2ad7cf814e 100644 --- a/netbox/templates/extras/tag.html +++ b/netbox/templates/extras/tag.html @@ -6,7 +6,7 @@
        @@ -15,7 +15,7 @@
        @@ -24,27 +24,27 @@
        {% if perms.taggit.change_tag %} - - + + Edit this tag {% endif %} {% if perms.taggit.delete_tag %} - - + + Delete this tag {% endif %}
        -

        {% block title %}Tag: {{ tag }}{% endblock %}

        - {% include 'inc/created_updated.html' with obj=tag %} +

        {% block title %}Tag: {{ object }}{% endblock %}

        + {% include 'inc/created_updated.html' %} @@ -61,13 +61,13 @@

        {% block title %}Tag: {{ tag }}{% endblock %}

        Name - {{ tag.name }} + {{ object.name }} Slug - {{ tag.slug }} + {{ object.slug }} @@ -79,13 +79,13 @@

        {% block title %}Tag: {{ tag }}{% endblock %}

        Color -   +   Description - {{ tag.description|placeholder }} + {{ object.description|placeholder }} diff --git a/netbox/templates/extras/tag_edit.html b/netbox/templates/extras/tag_edit.html index 87b9a2e53a..1516bde394 100644 --- a/netbox/templates/extras/tag_edit.html +++ b/netbox/templates/extras/tag_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load form_helpers %} {% block form %} diff --git a/netbox/templates/utilities/obj_bulk_add_component.html b/netbox/templates/generic/object_bulk_add_component.html similarity index 100% rename from netbox/templates/utilities/obj_bulk_add_component.html rename to netbox/templates/generic/object_bulk_add_component.html diff --git a/netbox/templates/utilities/obj_bulk_delete.html b/netbox/templates/generic/object_bulk_delete.html similarity index 100% rename from netbox/templates/utilities/obj_bulk_delete.html rename to netbox/templates/generic/object_bulk_delete.html diff --git a/netbox/templates/utilities/obj_bulk_edit.html b/netbox/templates/generic/object_bulk_edit.html similarity index 100% rename from netbox/templates/utilities/obj_bulk_edit.html rename to netbox/templates/generic/object_bulk_edit.html diff --git a/netbox/templates/utilities/obj_bulk_import.html b/netbox/templates/generic/object_bulk_import.html similarity index 83% rename from netbox/templates/utilities/obj_bulk_import.html rename to netbox/templates/generic/object_bulk_import.html index 9d63788ba9..170cf36655 100644 --- a/netbox/templates/utilities/obj_bulk_import.html +++ b/netbox/templates/generic/object_bulk_import.html @@ -53,7 +53,7 @@

        {% block title %}{{ obj_type|bettertitle }} Bulk Import{% endblock %}

        {% if field.required %} - + {% else %} {% endif %} @@ -66,9 +66,9 @@

        {% block title %}{{ obj_type|bettertitle }} Bulk Import{% endblock %}

        {% endif %} - {% if field.choice_values %} - @@ -100,11 +103,11 @@

        - Required fields must be specified for all + Required fields must be specified for all objects.

        - Related objects may be referenced by any unique attribute. + Related objects may be referenced by any unique attribute. For example, vrf.rd would identify a VRF by its route distinguisher.

        {% endif %} diff --git a/netbox/templates/utilities/obj_bulk_remove.html b/netbox/templates/generic/object_bulk_remove.html similarity index 100% rename from netbox/templates/utilities/obj_bulk_remove.html rename to netbox/templates/generic/object_bulk_remove.html diff --git a/netbox/templates/utilities/obj_bulk_rename.html b/netbox/templates/generic/object_bulk_rename.html similarity index 100% rename from netbox/templates/utilities/obj_bulk_rename.html rename to netbox/templates/generic/object_bulk_rename.html diff --git a/netbox/templates/utilities/obj_delete.html b/netbox/templates/generic/object_delete.html similarity index 100% rename from netbox/templates/utilities/obj_delete.html rename to netbox/templates/generic/object_delete.html diff --git a/netbox/templates/utilities/obj_edit.html b/netbox/templates/generic/object_edit.html similarity index 93% rename from netbox/templates/utilities/obj_edit.html rename to netbox/templates/generic/object_edit.html index 0bd051161c..965749a6dd 100644 --- a/netbox/templates/utilities/obj_edit.html +++ b/netbox/templates/generic/object_edit.html @@ -13,7 +13,9 @@

        {% if settings.DOCS_ROOT %}
        - +
        {% endif %} {% block title %}{% if obj.pk %}Editing {{ obj_type }} {{ obj }}{% else %}Add a new {{ obj_type }}{% endif %}{% endblock %} diff --git a/netbox/templates/utilities/obj_import.html b/netbox/templates/generic/object_import.html similarity index 100% rename from netbox/templates/utilities/obj_import.html rename to netbox/templates/generic/object_import.html diff --git a/netbox/templates/utilities/obj_list.html b/netbox/templates/generic/object_list.html similarity index 80% rename from netbox/templates/utilities/obj_list.html rename to netbox/templates/generic/object_list.html index 47f11e1c1d..738cbca49b 100644 --- a/netbox/templates/utilities/obj_list.html +++ b/netbox/templates/generic/object_list.html @@ -1,12 +1,13 @@ {% extends 'base.html' %} {% load buttons %} {% load helpers %} +{% load static %} {% block content %}
        {% block buttons %}{% endblock %} {% if request.user.is_authenticated and table_config_form %} - + {% endif %} {% if permissions.add and 'add' in action_buttons %} {% add_button content_type.model_class|validated_viewname:"add" %} @@ -20,7 +21,13 @@

        {% block title %}{{ content_type.model_class|meta:"verbose_name_plural"|bettertitle }}{% endblock %}

        -
        +
        + {% if filter_form %} +
        + {% include 'inc/search_panel.html' %} + {% block sidebar %}{% endblock %} +
        + {% endif %} {% with bulk_edit_url=content_type.model_class|validated_viewname:"bulk_edit" bulk_delete_url=content_type.model_class|validated_viewname:"bulk_delete" %} {% if permissions.change or permissions.delete %}
        @@ -38,12 +45,12 @@

        {% block title %}{{ content_type.model_class|meta:"verbose_name_plural"|bett
        {% if bulk_edit_url and permissions.change %} {% endif %} {% if bulk_delete_url and permissions.delete %} {% endif %}
        @@ -55,12 +62,12 @@

        {% block title %}{{ content_type.model_class|meta:"verbose_name_plural"|bett {% block bulk_buttons %}{% endblock %} {% if bulk_edit_url and permissions.change %} {% endif %} {% if bulk_delete_url and permissions.delete %} {% endif %}

        @@ -71,15 +78,11 @@

        {% block title %}{{ content_type.model_class|meta:"verbose_name_plural"|bett {% endwith %} {% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
        - {% if table_config_form %} - {% include 'inc/table_config_form.html' %} - {% endif %}

        - {% if filter_form %} -
        - {% include 'inc/search_panel.html' %} - {% block sidebar %}{% endblock %} -
        - {% endif %}
        +{% table_config_form table table_name="ObjectTable" %} +{% endblock %} + +{% block javascript %} + {% endblock %} diff --git a/netbox/templates/home.html b/netbox/templates/home.html index e06b674695..47e0e8a1ae 100644 --- a/netbox/templates/home.html +++ b/netbox/templates/home.html @@ -6,7 +6,7 @@ {% if new_release %} {# new_release is set only if the current user is a superuser or staff member #} @@ -28,7 +28,7 @@ {{ stats.site_count }}

        Sites

        {% else %} - +

        Sites

        {% endif %}

        Geographic locations

        @@ -38,7 +38,7 @@

        Sites

        {{ stats.tenant_count }}

        Tenants

        {% else %} - +

        Tenants

        {% endif %}

        Customers or departments

        @@ -55,7 +55,7 @@

        Tenants

        {{ stats.rack_count }}

        Racks

        {% else %} - +

        Racks

        {% endif %}

        Equipment racks, optionally organized by group

        @@ -65,7 +65,7 @@

        Racks

        {{ stats.devicetype_count }}

        Device Types

        {% else %} - +

        Device Types

        {% endif %}

        Physical hardware models by manufacturer

        @@ -75,7 +75,7 @@

        Device Types

        {{ stats.device_count }}

        Devices

        {% else %} - +

        Devices

        {% endif %}

        Rack-mounted network equipment, servers, and other devices

        @@ -86,28 +86,28 @@

        Connections

        {{ stats.cable_count }}

        Cables

        {% else %} - +

        Cables

        {% endif %} {% if perms.dcim.view_interface %} {{ stats.interface_connections_count }}

        Interfaces

        {% else %} - +

        Interfaces

        {% endif %} {% if perms.dcim.view_consoleport and perms.dcim.view_consoleserverport %} {{ stats.console_connections_count }}

        Console

        {% else %} - +

        Console

        {% endif %} {% if perms.dcim.view_powerport and perms.dcim.view_poweroutlet %} {{ stats.power_connections_count }}

        Power

        {% else %} - +

        Power

        {% endif %} @@ -123,7 +123,7 @@

        Connections

        {{ stats.powerfeed_count }}

        Power Feeds

        {% else %} - +

        Power Feeds

        {% endif %}

        Electrical circuits delivering power from panels

        @@ -133,7 +133,7 @@

        Power Feeds

        {{ stats.powerpanel_count }}

        Power Panels

        {% else %} - +

        Power Panels

        {% endif %}

        Electrical panels receiving utility power

        @@ -152,7 +152,7 @@

        Power Panels

        {{ stats.vrf_count }}

        VRFs

        {% else %} - +

        VRFs

        {% endif %}

        Virtual routing and forwarding tables

        @@ -162,7 +162,7 @@

        VRFs

        {{ stats.aggregate_count }}

        Aggregates

        {% else %} - +

        Aggregates

        {% endif %}

        Top-level IP allocations

        @@ -172,7 +172,7 @@

        Aggregates

        {{ stats.prefix_count }}

        Prefixes

        {% else %} - +

        Prefixes

        {% endif %}

        IPv4 and IPv6 network assignments

        @@ -182,7 +182,7 @@

        Prefixes

        {{ stats.ipaddress_count }}

        IP Addresses

        {% else %} - +

        IP Addresses

        {% endif %}

        Individual IPv4 and IPv6 addresses

        @@ -192,7 +192,7 @@

        IP Addresses

        {{ stats.vlan_count }}

        VLANs

        {% else %} - +

        VLANs

        {% endif %}

        Layer two domains, identified by VLAN ID

        @@ -209,7 +209,7 @@

        VLANs

        {{ stats.provider_count }}

        Providers

        {% else %} - +

        Providers

        {% endif %}

        Organizations which provide circuit connectivity

        @@ -219,7 +219,7 @@

        Providers

        {{ stats.circuit_count }}

        Circuits

        {% else %} - +

        Circuits

        {% endif %}

        Communication links for Internet transit, peering, and other services

        @@ -236,7 +236,7 @@

        Circuits

        {{ stats.cluster_count }}

        Clusters

        {% else %} - +

        Clusters

        {% endif %}

        Clusters of physical hosts in which VMs reside

        @@ -246,7 +246,7 @@

        Clusters

        {{ stats.virtualmachine_count }}

        Virtual Machines

        {% else %} - +

        Virtual Machines

        {% endif %}

        Virtual compute instances running inside clusters

        @@ -265,7 +265,7 @@

        Virtual Machines

        {{ stats.secret_count }}

        Secrets

        {% else %} - +

        Secrets

        {% endif %}

        Cryptographically secured secret data

        @@ -291,7 +291,7 @@

        Secrets

        {% else %}
        - No permission + No permission
        {% endif %} @@ -305,11 +305,11 @@

        Secrets

        {% with action=change.get_action_display|lower %}
        {% if action == 'created' %} - + Created {% elif action == 'updated' %} - + Modified {% elif action == 'deleted' %} - + Deleted {% endif %} {{ change.changed_object_type.name|bettertitle }} {% if change.changed_object.get_absolute_url %} @@ -337,7 +337,7 @@

        Secrets

        {% else %}
        - No permission + No permission
        {% endif %} diff --git a/netbox/templates/import_success.html b/netbox/templates/import_success.html index da9958bdb3..b427e450e4 100644 --- a/netbox/templates/import_success.html +++ b/netbox/templates/import_success.html @@ -4,7 +4,7 @@

        {% block title %}Import Completed{% endblock %}

        {% include 'responsive_table.html' %} - + Import more {% if return_url %} diff --git a/netbox/templates/inc/created_updated.html b/netbox/templates/inc/created_updated.html index 001bb6b85c..58be428c40 100644 --- a/netbox/templates/inc/created_updated.html +++ b/netbox/templates/inc/created_updated.html @@ -1,3 +1,3 @@

        - Created {{ obj.created }} · Updated {{ obj.last_updated|timesince }} ago + Created {{ object.created }} · Updated {{ object.last_updated|timesince }} ago

        diff --git a/netbox/templates/inc/custom_fields_panel.html b/netbox/templates/inc/custom_fields_panel.html index 8c1872273f..d5f858f153 100644 --- a/netbox/templates/inc/custom_fields_panel.html +++ b/netbox/templates/inc/custom_fields_panel.html @@ -1,4 +1,4 @@ -{% with custom_fields=obj.get_custom_fields %} +{% with custom_fields=object.get_custom_fields %} {% if custom_fields %}
        @@ -10,9 +10,9 @@ {{ field }} {% if field.type == 'boolean' and value == True %} - + {% elif field.type == 'boolean' and value == False %} - + {% elif field.type == 'url' and value %} {{ value|truncatechars:70 }} {% elif value is not None %} diff --git a/netbox/templates/inc/image_attachments.html b/netbox/templates/inc/image_attachments.html index 2fee4dc781..38be9924d1 100644 --- a/netbox/templates/inc/image_attachments.html +++ b/netbox/templates/inc/image_attachments.html @@ -9,7 +9,7 @@ {% for attachment in images %} - + {{ attachment }} {{ attachment.size|filesizeformat }} @@ -17,12 +17,12 @@ {% if perms.extras.change_imageattachment %} - + {% endif %} {% if perms.extras.delete_imageattachment %} - + {% endif %} diff --git a/netbox/templates/inc/nav_menu.html b/netbox/templates/inc/nav_menu.html index bf3d349cce..74a0aa35d3 100644 --- a/netbox/templates/inc/nav_menu.html +++ b/netbox/templates/inc/nav_menu.html @@ -1,7 +1,7 @@ {% load static %} {% load helpers %}
      @@ -559,7 +568,7 @@ diff --git a/netbox/templates/inc/paginator.html b/netbox/templates/inc/paginator.html index 50d7e06d3f..37c3b06df1 100644 --- a/netbox/templates/inc/paginator.html +++ b/netbox/templates/inc/paginator.html @@ -5,7 +5,7 @@ diff --git a/netbox/templates/inc/search_panel.html b/netbox/templates/inc/search_panel.html index 5302f71b92..62ea513286 100644 --- a/netbox/templates/inc/search_panel.html +++ b/netbox/templates/inc/search_panel.html @@ -2,7 +2,7 @@
      - + Search
      @@ -17,7 +17,7 @@
      @@ -31,10 +31,10 @@ {% endfor %}
      - Clear + Clear
      diff --git a/netbox/templates/ipam/aggregate.html b/netbox/templates/ipam/aggregate.html index 998eb20669..ce8cb0a196 100644 --- a/netbox/templates/ipam/aggregate.html +++ b/netbox/templates/ipam/aggregate.html @@ -9,8 +9,8 @@
      @@ -19,7 +19,7 @@
      @@ -27,30 +27,30 @@
      - {% plugin_buttons aggregate %} + {% plugin_buttons object %} {% if perms.ipam.add_aggregate %} - {% clone_button aggregate %} + {% clone_button object %} {% endif %} {% if perms.ipam.change_aggregate %} - {% edit_button aggregate %} + {% edit_button object %} {% endif %} {% if perms.ipam.delete_aggregate %} - {% delete_button aggregate %} + {% delete_button object %} {% endif %}
      -

      {% block title %}{{ aggregate }}{% endblock %}

      - {% include 'inc/created_updated.html' with obj=aggregate %} +

      {% block title %}{{ object }}{% endblock %}

      + {% include 'inc/created_updated.html' %} {% include 'ipam/inc/toggle_available.html' %}
      - {% custom_links aggregate %} + {% custom_links object %}
      @@ -66,41 +66,54 @@

      {% block title %}{{ aggregate }}{% endblock %}

      - + + + + + - + - +
      FamilyIPv{{ aggregate.family }}IPv{{ object.family }}
      RIR - {{ aggregate.rir }} + {{ object.rir }}
      Utilization - {{ aggregate.get_utilization }}% + {{ object.get_utilization }}% +
      Tenant + {% if object.tenant %} + {% if prefix.object.group %} + {{ object.tenant.group }} / + {% endif %} + {{ object.tenant }} + {% else %} + None + {% endif %}
      Date Added{{ aggregate.date_added|placeholder }}{{ object.date_added|placeholder }}
      Description{{ aggregate.description|placeholder }}{{ object.description|placeholder }}
      - {% plugin_left_page aggregate %} + {% plugin_left_page object %}
      - {% include 'inc/custom_fields_panel.html' with obj=aggregate %} - {% include 'extras/inc/tags_panel.html' with tags=aggregate.tags.all url='ipam:aggregate_list' %} - {% plugin_right_page aggregate %} + {% include 'inc/custom_fields_panel.html' %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='ipam:aggregate_list' %} + {% plugin_right_page object %}
      - {% plugin_full_width_page aggregate %} + {% plugin_full_width_page object %}
      diff --git a/netbox/templates/ipam/aggregate_edit.html b/netbox/templates/ipam/aggregate_edit.html index 3cb83ab543..f27abd6636 100644 --- a/netbox/templates/ipam/aggregate_edit.html +++ b/netbox/templates/ipam/aggregate_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load form_helpers %} {% block form %} @@ -11,6 +11,13 @@ {% render_field form.description %}
      +
      +
      Tenancy
      +
      + {% render_field form.tenant_group %} + {% render_field form.tenant %} +
      +
      {% if form.custom_fields %}
      Custom Fields
      diff --git a/netbox/templates/ipam/aggregate_list.html b/netbox/templates/ipam/aggregate_list.html index 85a2bd36d3..c60646a71d 100644 --- a/netbox/templates/ipam/aggregate_list.html +++ b/netbox/templates/ipam/aggregate_list.html @@ -1,10 +1,10 @@ -{% extends 'utilities/obj_list.html' %} +{% extends 'generic/object_list.html' %} {% load humanize %} {% block sidebar %}
      - Statistics + Statistics
      • Total IPv4 IPs {{ ipv4_total|intcomma }}
      • diff --git a/netbox/templates/ipam/inc/service.html b/netbox/templates/ipam/inc/service.html index 9611be175d..826fa99adb 100644 --- a/netbox/templates/ipam/inc/service.html +++ b/netbox/templates/ipam/inc/service.html @@ -1,13 +1,10 @@ - - {{ service.name }} - - - {{ service.get_protocol_display }}/{{ service.port }} - + {{ service.name }} + {{ service.get_protocol_display }} + {{ service.port_list }} {% for ip in service.ipaddresses.all %} - {{ ip.address.ip }}
        + {{ ip.address.ip }}
        {% empty %} All IPs {% endfor %} @@ -15,16 +12,16 @@ {{ service.description }} - + {% if perms.ipam.change_service %} - - + + {% endif %} {% if perms.ipam.delete_service %} - + {% endif %} diff --git a/netbox/templates/ipam/inc/toggle_available.html b/netbox/templates/ipam/inc/toggle_available.html index 21d734d2d8..161f6b7881 100644 --- a/netbox/templates/ipam/inc/toggle_available.html +++ b/netbox/templates/ipam/inc/toggle_available.html @@ -2,8 +2,12 @@ {% if show_available is not None %} {% endif %} diff --git a/netbox/templates/ipam/inc/vlangroup_header.html b/netbox/templates/ipam/inc/vlangroup_header.html index 221f419947..2507a749fc 100644 --- a/netbox/templates/ipam/inc/vlangroup_header.html +++ b/netbox/templates/ipam/inc/vlangroup_header.html @@ -1,14 +1,14 @@
        {% if perms.ipam.add_vlan and first_available_vlan %} - - Add a VLAN + + Add a VLAN {% endif %} {% if perms.ipam.change_vlangroup %} - - + + Edit this VLAN Group {% endif %}
        -

        {{ vlan_group }}

        +

        {{ object }}

        diff --git a/netbox/templates/ipam/ipaddress.html b/netbox/templates/ipam/ipaddress.html index f213a275af..8fe98d4da8 100644 --- a/netbox/templates/ipam/ipaddress.html +++ b/netbox/templates/ipam/ipaddress.html @@ -10,10 +10,10 @@
        @@ -22,7 +22,7 @@
        @@ -30,29 +30,29 @@
      - {% plugin_buttons ipaddress %} + {% plugin_buttons object %} {% if perms.ipam.add_ipaddress %} - {% clone_button ipaddress %} + {% clone_button object %} {% endif %} {% if perms.ipam.change_ipaddress %} - {%edit_button ipaddress %} + {%edit_button object %} {% endif %} {% if perms.ipam.delete_ipaddress %} - {% delete_button ipaddress %} + {% delete_button object %} {% endif %}
      -

      {% block title %}{{ ipaddress }}{% endblock %}

      - {% include 'inc/created_updated.html' with obj=ipaddress %} +

      {% block title %}{{ object }}{% endblock %}

      + {% include 'inc/created_updated.html' %}
      - {% custom_links ipaddress %} + {% custom_links object %}
      @@ -68,13 +68,13 @@

      {% block title %}{{ ipaddress }}{% endblock %}

      - + - + - +
      FamilyIPv{{ ipaddress.family }}IPv{{ object.family }}
      VRF - {% if ipaddress.vrf %} - {{ ipaddress.vrf }} + {% if object.vrf %} + {{ object.vrf }} {% else %} Global {% endif %} @@ -83,12 +83,11 @@

      {% block title %}{{ ipaddress }}{% endblock %}

      Tenant - {% if ipaddress.tenant %} - {% if ipaddress.tenant.group %} - {{ ipaddress.tenant.group }} - + {% if object.tenant %} + {% if object.tenant.group %} + {{ object.tenant.group }} / {% endif %} - {{ ipaddress.tenant }} + {{ object.tenant }} {% else %} None {% endif %} @@ -97,14 +96,14 @@

      {% block title %}{{ ipaddress }}{% endblock %}

      Status - {{ ipaddress.get_status_display }} + {{ object.get_status_display }}
      Role - {% if ipaddress.role %} - {{ ipaddress.get_role_display }} + {% if object.role %} + {{ object.get_role_display }} {% else %} None {% endif %} @@ -112,17 +111,17 @@

      {% block title %}{{ ipaddress }}{% endblock %}

      DNS Name{{ ipaddress.dns_name|placeholder }}{{ object.dns_name|placeholder }}
      Description{{ ipaddress.description|placeholder }}{{ object.description|placeholder }}
      Assignment - {% if ipaddress.assigned_object %} - {{ ipaddress.assigned_object.parent }} ({{ ipaddress.assigned_object }}) + {% if object.assigned_object %} + {{ object.assigned_object.parent }} ({{ object.assigned_object }}) {% else %} {% endif %} @@ -131,10 +130,10 @@

      {% block title %}{{ ipaddress }}{% endblock %}

      NAT (inside) - {% if ipaddress.nat_inside %} - {{ ipaddress.nat_inside }} - {% if ipaddress.nat_inside.assigned_object %} - ({{ ipaddress.nat_inside.assigned_object.parent }}) + {% if object.nat_inside %} + {{ object.nat_inside }} + {% if object.nat_inside.assigned_object %} + ({{ object.nat_inside.assigned_object.parent }}) {% endif %} {% else %} None @@ -144,8 +143,8 @@

      {% block title %}{{ ipaddress }}{% endblock %}

      NAT (outside) - {% if ipaddress.nat_outside %} - {{ ipaddress.nat_outside }} + {% if object.nat_outside %} + {{ object.nat_outside }} {% else %} None {% endif %} @@ -153,9 +152,9 @@

      {% block title %}{{ ipaddress }}{% endblock %}

      - {% include 'inc/custom_fields_panel.html' with obj=ipaddress %} - {% include 'extras/inc/tags_panel.html' with tags=ipaddress.tags.all url='ipam:ipaddress_list' %} - {% plugin_left_page ipaddress %} + {% include 'inc/custom_fields_panel.html' %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='ipam:ipaddress_list' %} + {% plugin_left_page object %}
      {% include 'panel_table.html' with table=parent_prefixes_table heading='Parent Prefixes' %} @@ -167,10 +166,10 @@

      {% block title %}{{ ipaddress }}{% endblock %}

      {% if more_duplicate_ips %} @@ -180,12 +179,12 @@

      {% block title %}{{ ipaddress }}{% endblock %}

      {% endif %} {% include 'utilities/obj_table.html' with table=related_ips_table table_template='panel_table.html' heading='Related IP Addresses' panel_class='default noprint' %} - {% plugin_right_page ipaddress %} + {% plugin_right_page object %}
      - {% plugin_full_width_page ipaddress %} + {% plugin_full_width_page object %}
      {% endblock %} diff --git a/netbox/templates/ipam/ipaddress_assign.html b/netbox/templates/ipam/ipaddress_assign.html index ab163533f2..913b6c4b45 100644 --- a/netbox/templates/ipam/ipaddress_assign.html +++ b/netbox/templates/ipam/ipaddress_assign.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load static %} {% load form_helpers %} {% load helpers %} diff --git a/netbox/templates/ipam/ipaddress_bulk_add.html b/netbox/templates/ipam/ipaddress_bulk_add.html index bbb179fc85..f019d48b80 100644 --- a/netbox/templates/ipam/ipaddress_bulk_add.html +++ b/netbox/templates/ipam/ipaddress_bulk_add.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load static %} {% load form_helpers %} diff --git a/netbox/templates/ipam/ipaddress_edit.html b/netbox/templates/ipam/ipaddress_edit.html index 92093dea4f..eb15a3059a 100644 --- a/netbox/templates/ipam/ipaddress_edit.html +++ b/netbox/templates/ipam/ipaddress_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load static %} {% load form_helpers %} {% load helpers %} diff --git a/netbox/templates/ipam/prefix.html b/netbox/templates/ipam/prefix.html index 241cdd9a4f..4b382636b9 100644 --- a/netbox/templates/ipam/prefix.html +++ b/netbox/templates/ipam/prefix.html @@ -9,10 +9,10 @@
      @@ -21,7 +21,7 @@
      @@ -29,49 +29,49 @@
      - {% plugin_buttons prefix %} + {% plugin_buttons object %} {% if perms.ipam.add_prefix and active_tab == 'prefixes' and first_available_prefix %} - - Add Child Prefix + + Add Child Prefix {% endif %} {% if perms.ipam.add_ipaddress and active_tab == 'ip-addresses' and first_available_ip %} - - + + Add an IP Address {% endif %} {% if perms.ipam.add_prefix %} - {% clone_button prefix %} + {% clone_button object %} {% endif %} {% if perms.ipam.change_prefix %} - {% edit_button prefix %} + {% edit_button object %} {% endif %} {% if perms.ipam.delete_prefix %} - {% delete_button prefix %} + {% delete_button object %} {% endif %}
      -

      {% block title %}{{ prefix }}{% endblock %}

      - {% include 'inc/created_updated.html' with obj=prefix %} +

      {% block title %}{{ object }}{% endblock %}

      + {% include 'inc/created_updated.html' %} {% include 'ipam/inc/toggle_available.html' %}
      - {% custom_links prefix %} + {% custom_links object %}
      @@ -87,13 +87,13 @@

      {% block title %}{{ prefix }}{% endblock %}

      - + - + - +
      FamilyIPv{{ prefix.family }}IPv{{ object.family }}
      VRF - {% if prefix.vrf %} - {{ prefix.vrf }} ({{ prefix.vrf.rd }}) + {% if object.vrf %} + {{ object.vrf }} ({{ object.vrf.rd }}) {% else %} Global {% endif %} @@ -102,12 +102,11 @@

      {% block title %}{{ prefix }}{% endblock %}

      Tenant - {% if prefix.tenant %} - {% if prefix.tenant.group %} - {{ prefix.tenant.group }} - + {% if object.tenant %} + {% if object.tenant.group %} + {{ object.tenant.group }} / {% endif %} - {{ prefix.tenant }} + {{ object.tenant }} {% else %} None {% endif %} @@ -126,12 +125,11 @@

      {% block title %}{{ prefix }}{% endblock %}

      Site - {% if prefix.site %} - {% if prefix.site.region %} - {{ prefix.site.region }} - + {% if object.site %} + {% if object.site.region %} + {{ object.site.region }} / {% endif %} - {{ prefix.site }} + {{ object.site }} {% else %} None {% endif %} @@ -140,12 +138,11 @@

      {% block title %}{{ prefix }}{% endblock %}

      VLAN - {% if prefix.vlan %} - {% if prefix.vlan.group %} - {{ prefix.vlan.group }} - + {% if object.vlan %} + {% if object.vlan.group %} + {{ object.vlan.group }} / {% endif %} - {{ prefix.vlan.display_name }} + {{ object.vlan.display_name }} {% else %} None {% endif %} @@ -154,14 +151,14 @@

      {% block title %}{{ prefix }}{% endblock %}

      Status - {{ prefix.get_status_display }} + {{ object.get_status_display }}
      Role - {% if prefix.role %} - {{ prefix.role }} + {% if object.role %} + {{ object.role }} {% else %} None {% endif %} @@ -169,39 +166,39 @@

      {% block title %}{{ prefix }}{% endblock %}

      Description{{ prefix.description|placeholder }}{{ object.description|placeholder }}
      Is a pool - {% if prefix.is_pool %} - + {% if object.is_pool %} + {% else %} - + {% endif %}
      Utilization{% utilization_graph prefix.get_utilization %}{% utilization_graph object.get_utilization %}
      - {% include 'inc/custom_fields_panel.html' with obj=prefix %} - {% include 'extras/inc/tags_panel.html' with tags=prefix.tags.all url='ipam:prefix_list' %} - {% plugin_left_page prefix %} + {% include 'inc/custom_fields_panel.html' %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='ipam:prefix_list' %} + {% plugin_left_page object %}
      {% if duplicate_prefix_table.rows %} {% include 'panel_table.html' with table=duplicate_prefix_table heading='Duplicate Prefixes' panel_class='danger' %} {% endif %} {% include 'panel_table.html' with table=parent_prefix_table heading='Parent Prefixes' panel_class='default' %} - {% plugin_right_page prefix %} + {% plugin_right_page object %}
      - {% plugin_full_width_page prefix %} + {% plugin_full_width_page object %}
      {% endblock %} diff --git a/netbox/templates/ipam/prefix_delete.html b/netbox/templates/ipam/prefix_delete.html index 5ea39dc4c9..eb7a22d3ce 100644 --- a/netbox/templates/ipam/prefix_delete.html +++ b/netbox/templates/ipam/prefix_delete.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_delete.html' %} +{% extends 'generic/object_delete.html' %} {% block message_extra %}

      Note: This will not delete any child prefixes or IP addresses.

      diff --git a/netbox/templates/ipam/prefix_edit.html b/netbox/templates/ipam/prefix_edit.html index 126593074c..3505c373b6 100644 --- a/netbox/templates/ipam/prefix_edit.html +++ b/netbox/templates/ipam/prefix_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load form_helpers %} {% block form %} diff --git a/netbox/templates/ipam/prefix_list.html b/netbox/templates/ipam/prefix_list.html index c4c6ea157a..fc3fadaee0 100644 --- a/netbox/templates/ipam/prefix_list.html +++ b/netbox/templates/ipam/prefix_list.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_list.html' %} +{% extends 'generic/object_list.html' %} {% load helpers %} {% block buttons %} @@ -11,7 +11,7 @@ diff --git a/netbox/templates/ipam/rir_list.html b/netbox/templates/ipam/rir_list.html index 02f01fc7ca..89d31ae7d0 100644 --- a/netbox/templates/ipam/rir_list.html +++ b/netbox/templates/ipam/rir_list.html @@ -1,14 +1,14 @@ -{% extends 'utilities/obj_list.html' %} +{% extends 'generic/object_list.html' %} {% block buttons %} {% if request.GET.family == '6' %} - + IPv4 Stats {% else %} - + IPv6 Stats {% endif %} @@ -17,7 +17,7 @@ {% block sidebar %} {% if request.GET.family == '6' %}
      - Numbers shown indicate /64 prefixes. + Numbers shown indicate /64 prefixes.
      {% endif %} {% endblock %} diff --git a/netbox/templates/ipam/routetarget.html b/netbox/templates/ipam/routetarget.html new file mode 100644 index 0000000000..4fa8f44240 --- /dev/null +++ b/netbox/templates/ipam/routetarget.html @@ -0,0 +1,100 @@ +{% extends 'base.html' %} +{% load buttons %} +{% load custom_links %} +{% load helpers %} +{% load plugins %} + +{% block header %} +
      +
      + +
      +
      +
      +
      + + + + +
      +
      +
      +
      +
      + {% plugin_buttons object %} + {% if perms.ipam.add_routetarget %} + {% clone_button object %} + {% endif %} + {% if perms.ipam.change_routetarget %} + {% edit_button object %} + {% endif %} + {% if perms.ipam.delete_routetarget %} + {% delete_button object %} + {% endif %} +
      +

      {% block title %}Route target {{ object }}{% endblock %}

      + {% include 'inc/created_updated.html' %} +
      + {% custom_links object %} +
      + +{% endblock %} + +{% block content %} +
      +
      +
      +
      + Route Target +
      + + + + + + + + + + + + + +
      Name{{ object.name }}
      Tenant + {% if object.tenant %} + {{ object.tenant }} + {% else %} + None + {% endif %} +
      Description{{ vrf.description|placeholder }}
      +
      + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='ipam:routetarget_list' %} + {% include 'inc/custom_fields_panel.html' %} + {% plugin_left_page object %} +
      +
      + {% include 'panel_table.html' with table=importing_vrfs_table heading="Importing VRFs" %} + {% include 'panel_table.html' with table=exporting_vrfs_table heading="Exporting VRFs" %} + {% plugin_right_page object %} +
      +
      +
      +
      + {% plugin_full_width_page object %} +
      +
      +{% endblock %} diff --git a/netbox/templates/ipam/service.html b/netbox/templates/ipam/service.html index b16e99aa3c..d3e94b90d5 100644 --- a/netbox/templates/ipam/service.html +++ b/netbox/templates/ipam/service.html @@ -9,8 +9,8 @@
      @@ -19,7 +19,7 @@
      @@ -27,18 +27,18 @@
      - {% plugin_buttons service %} + {% plugin_buttons object %} {% if perms.dcim.change_service %} - {% edit_button service %} + {% edit_button object %} {% endif %} {% if perms.dcim.delete_service %} - {% delete_button service %} + {% delete_button object %} {% endif %}
      -

      {% block title %}{{ service }}{% endblock %}

      -{% include 'inc/created_updated.html' with obj=service %} +

      {% block title %}{{ object }}{% endblock %}

      +{% include 'inc/created_updated.html' %}
      - {% custom_links service %} + {% custom_links object %}
      @@ -49,26 +49,26 @@

      {% block title %}{{ service }}{% endblock %}

      - + - + - - + + - +
      Name{{ service.name }}{{ object.name }}
      Parent - {{ service.parent }} + {{ object.parent }}
      Protocol{{ service.get_protocol_display }}{{ object.get_protocol_display }}
      Port{{ service.port }}Ports{{ object.port_list }}
      IP Addresses - {% for ipaddress in service.ipaddresses.all %} + {% for ipaddress in object.ipaddresses.all %} {{ ipaddress }}
      {% empty %} None @@ -77,21 +77,21 @@

      {% block title %}{{ service }}{% endblock %}

      Description{{ service.description|placeholder }}{{ object.description|placeholder }}
      - {% include 'inc/custom_fields_panel.html' with obj=service %} - {% include 'extras/inc/tags_panel.html' with tags=service.tags.all url='ipam:service_list' %} - {% plugin_left_page service %} + {% include 'inc/custom_fields_panel.html' %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='ipam:service_list' %} + {% plugin_left_page object %}
      - {% plugin_right_page service %} + {% plugin_right_page object %}
      - {% plugin_full_width_page service %} + {% plugin_full_width_page object %}
      {% endblock %} diff --git a/netbox/templates/ipam/service_edit.html b/netbox/templates/ipam/service_edit.html index 521aec137e..8d6fde9e94 100644 --- a/netbox/templates/ipam/service_edit.html +++ b/netbox/templates/ipam/service_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load form_helpers %} {% block form %} @@ -22,10 +22,11 @@ {% endif %} {% render_field form.name %}
      - +
      {{ form.protocol }} - {{ form.port }} + {{ form.ports }} + {{ form.ports.help_text }}
      {% render_field form.ipaddresses %} diff --git a/netbox/templates/ipam/vlan.html b/netbox/templates/ipam/vlan.html index d9cb0c66c0..d2967ca561 100644 --- a/netbox/templates/ipam/vlan.html +++ b/netbox/templates/ipam/vlan.html @@ -9,13 +9,13 @@
      @@ -24,7 +24,7 @@
      @@ -32,35 +32,35 @@
      - {% plugin_buttons vlan %} + {% plugin_buttons object %} {% if perms.ipam.add_vlan %} - {% clone_button vlan %} + {% clone_button object %} {% endif %} {% if perms.ipam.change_vlan %} - {% edit_button vlan %} + {% edit_button object %} {% endif %} {% if perms.ipam.delete_vlan %} - {% delete_button vlan %} + {% delete_button object %} {% endif %}
      -

      {% block title %}VLAN {{ vlan.display_name }}{% endblock %}

      - {% include 'inc/created_updated.html' with obj=vlan %} +

      {% block title %}VLAN {{ object.display_name }}{% endblock %}

      + {% include 'inc/created_updated.html' %}
      - {% custom_links vlan %} + {% custom_links object %}
      @@ -77,12 +77,11 @@

      {% block title %}VLAN {{ vlan.display_name }}{% endblock %}

      Site - {% if vlan.site %} - {% if vlan.site.region %} - {{ vlan.site.region }} - + {% if object.site %} + {% if object.site.region %} + {{ object.site.region }} / {% endif %} - {{ vlan.site }} + {{ object.site }} {% else %} None {% endif %} @@ -91,8 +90,8 @@

      {% block title %}VLAN {{ vlan.display_name }}{% endblock %}

      Group - {% if vlan.group %} - {{ vlan.group }} + {% if object.group %} + {{ object.group }} {% else %} None {% endif %} @@ -100,21 +99,20 @@

      {% block title %}VLAN {{ vlan.display_name }}{% endblock %}

      VLAN ID - {{ vlan.vid }} + {{ object.vid }} Name - {{ vlan.name }} + {{ object.name }} Tenant - {% if vlan.tenant %} - {% if vlan.tenant.group %} - {{ vlan.tenant.group }} - + {% if object.tenant %} + {% if object.tenant.group %} + {{ object.tenant.group }} / {% endif %} - {{ vlan.tenant }} + {{ object.tenant }} {% else %} None {% endif %} @@ -123,14 +121,14 @@

      {% block title %}VLAN {{ vlan.display_name }}{% endblock %}

      Status - {{ vlan.get_status_display }} + {{ object.get_status_display }} Role - {% if vlan.role %} - {{ vlan.role }} + {% if object.role %} + {{ object.role }} {% else %} None {% endif %} @@ -138,13 +136,13 @@

      {% block title %}VLAN {{ vlan.display_name }}{% endblock %}

      Description - {{ vlan.description|placeholder }} + {{ object.description|placeholder }} - {% include 'inc/custom_fields_panel.html' with obj=vlan %} - {% include 'extras/inc/tags_panel.html' with tags=vlan.tags.all url='ipam:vlan_list' %} - {% plugin_left_page vlan %} + {% include 'inc/custom_fields_panel.html' %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='ipam:vlan_list' %} + {% plugin_left_page object %}
      @@ -154,19 +152,19 @@

      {% block title %}VLAN {{ vlan.display_name }}{% endblock %}

      {% include 'responsive_table.html' with table=prefix_table %} {% if perms.ipam.add_prefix %} {% endif %}
      - {% plugin_right_page vlan %} + {% plugin_right_page object %}
      - {% plugin_full_width_page vlan %} + {% plugin_full_width_page object %}
      {% endblock %} diff --git a/netbox/templates/ipam/vlan_edit.html b/netbox/templates/ipam/vlan_edit.html index 9ea3cdabb2..54dcf727a8 100644 --- a/netbox/templates/ipam/vlan_edit.html +++ b/netbox/templates/ipam/vlan_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load form_helpers %} {% block form %} diff --git a/netbox/templates/ipam/vlangroup_vlans.html b/netbox/templates/ipam/vlangroup_vlans.html index 7f8ac20447..490b7ab2c9 100644 --- a/netbox/templates/ipam/vlangroup_vlans.html +++ b/netbox/templates/ipam/vlangroup_vlans.html @@ -1,16 +1,16 @@ {% extends 'base.html' %} -{% block title %}{{ vlan_group }} - VLANs{% endblock %} +{% block title %}{{ object }} - VLANs{% endblock %} {% block content %}
      diff --git a/netbox/templates/ipam/vrf.html b/netbox/templates/ipam/vrf.html index 6fb6d725fb..d17f8e9b91 100644 --- a/netbox/templates/ipam/vrf.html +++ b/netbox/templates/ipam/vrf.html @@ -9,7 +9,7 @@
      @@ -18,7 +18,7 @@
      @@ -26,29 +26,29 @@
      - {% plugin_buttons vrf %} + {% plugin_buttons object %} {% if perms.ipam.add_vrf %} - {% clone_button vrf %} + {% clone_button object %} {% endif %} {% if perms.ipam.change_vrf %} - {% edit_button vrf %} + {% edit_button object %} {% endif %} {% if perms.ipam.delete_vrf %} - {% delete_button vrf %} + {% delete_button object %} {% endif %}
      -

      {% block title %}VRF {{ vrf }}{% endblock %}

      - {% include 'inc/created_updated.html' with obj=vrf %} +

      {% block title %}VRF {{ object }}{% endblock %}

      + {% include 'inc/created_updated.html' %}
      - {% custom_links vrf %} + {% custom_links object %}
      @@ -64,13 +64,13 @@

      {% block title %}VRF {{ vrf }}{% endblock %}

      - + - +
      Route Distinguisher{{ vrf.rd }}{{ object.rd }}
      Tenant - {% if vrf.tenant %} - {{ vrf.tenant }} + {% if object.tenant %} + {{ object.tenant }} {% else %} None {% endif %} @@ -79,36 +79,38 @@

      {% block title %}VRF {{ vrf }}{% endblock %}

      Unique IP Space - {% if vrf.enforce_unique %} - + {% if object.enforce_unique %} + {% else %} - + {% endif %}
      Description{{ vrf.description|placeholder }}{{ object.description|placeholder }}
      Prefixes - {{ prefix_count }} + {{ prefix_count }}
      - {% include 'extras/inc/tags_panel.html' with tags=vrf.tags.all url='ipam:vrf_list' %} - {% plugin_left_page vrf %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='ipam:vrf_list' %} + {% include 'inc/custom_fields_panel.html' %} + {% plugin_left_page object %}
      - {% include 'inc/custom_fields_panel.html' with obj=vrf %} - {% plugin_right_page vrf %} + {% include 'panel_table.html' with table=import_targets_table heading="Import Route Targets" %} + {% include 'panel_table.html' with table=export_targets_table heading="Export Route Targets" %} + {% plugin_right_page object %}
      - {% plugin_full_width_page vrf %} + {% plugin_full_width_page object %}
      {% endblock %} diff --git a/netbox/templates/ipam/vrf_edit.html b/netbox/templates/ipam/vrf_edit.html index a2ff51d9b8..189b9c1297 100644 --- a/netbox/templates/ipam/vrf_edit.html +++ b/netbox/templates/ipam/vrf_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load form_helpers %} {% block form %} @@ -11,6 +11,13 @@ {% render_field form.description %} +
      +
      Route Targets
      +
      + {% render_field form.import_targets %} + {% render_field form.export_targets %} +
      +
      Tenancy
      diff --git a/netbox/templates/search.html b/netbox/templates/search.html index 68b69cf944..a11011ed7d 100644 --- a/netbox/templates/search.html +++ b/netbox/templates/search.html @@ -14,7 +14,7 @@

      {{ obj_type.name|bettertitle }}

      {% include 'panel_table.html' with table=obj_type.table %} - + {% if obj_type.table.page.has_next %} See all {{ obj_type.table.page.paginator.count }} results {% else %} @@ -56,7 +56,7 @@

      No results found

      diff --git a/netbox/templates/secrets/inc/assigned_secrets.html b/netbox/templates/secrets/inc/assigned_secrets.html new file mode 100644 index 0000000000..2ff3e4ea26 --- /dev/null +++ b/netbox/templates/secrets/inc/assigned_secrets.html @@ -0,0 +1,26 @@ +{% if secrets %} + + {% for secret in secrets %} + + + + + + + {% endfor %} +
      {{ secret.role }}{{ secret.name }}******** + + + +
      +{% else %} +
      + None found +
      +{% endif %} diff --git a/netbox/templates/secrets/inc/private_key_modal.html b/netbox/templates/secrets/inc/private_key_modal.html index f165df4004..5b1d4550b5 100644 --- a/netbox/templates/secrets/inc/private_key_modal.html +++ b/netbox/templates/secrets/inc/private_key_modal.html @@ -4,7 +4,7 @@ diff --git a/netbox/templates/secrets/inc/secret_tr.html b/netbox/templates/secrets/inc/secret_tr.html deleted file mode 100644 index 2af609289b..0000000000 --- a/netbox/templates/secrets/inc/secret_tr.html +++ /dev/null @@ -1,16 +0,0 @@ - -
      {{ secret.role }} - {{ secret.name }} - ******** - - - - - - diff --git a/netbox/templates/secrets/secret.html b/netbox/templates/secrets/secret.html index 841d9843a0..8921c5c65c 100644 --- a/netbox/templates/secrets/secret.html +++ b/netbox/templates/secrets/secret.html @@ -10,32 +10,33 @@
      - {% plugin_buttons secret %} + {% plugin_buttons object %} {% if perms.secrets.change_secret %} - {% edit_button secret %} + {% edit_button object %} {% endif %} {% if perms.secrets.delete_secret %} - {% delete_button secret %} + {% delete_button object %} {% endif %}
      -

      {% block title %}{{ secret }}{% endblock %}

      - {% include 'inc/created_updated.html' with obj=secret %} +

      {% block title %}{{ object }}{% endblock %}

      + {% include 'inc/created_updated.html' %}
      - {% custom_links secret %} + {% custom_links object %}
      @@ -50,23 +51,23 @@

      {% block title %}{{ secret }}{% endblock %}

      - + - + - +
      DeviceAssigned object - {{ secret.device }} + {{ object.assigned_object }}
      Role{{ secret.role }}{{ object.role }}
      Name{{ secret.name|placeholder }}{{ object.name|placeholder }}
      - {% include 'inc/custom_fields_panel.html' with obj=secret %} - {% plugin_left_page secret %} + {% include 'inc/custom_fields_panel.html' %} + {% plugin_left_page object %}
      @@ -79,28 +80,28 @@

      {% block title %}{{ secret }}{% endblock %}

      Secret
      -
      ********
      +
      ********
      - - -
      - {% include 'extras/inc/tags_panel.html' with tags=secret.tags.all url='secrets:secret_list' %} - {% plugin_right_page secret %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='secrets:secret_list' %} + {% plugin_right_page object %}
      - {% plugin_full_width_page secret %} + {% plugin_full_width_page object %}
      diff --git a/netbox/templates/secrets/secret_edit.html b/netbox/templates/secrets/secret_edit.html index 0cb1eefef1..4e2d78042e 100644 --- a/netbox/templates/secrets/secret_edit.html +++ b/netbox/templates/secrets/secret_edit.html @@ -18,9 +18,24 @@

      {% block title %}{% if obj.pk %}Editing {{ obj }}{% else %}Add a Secret{% en {% endif %}
      -
      Secret Attributes
      +
      + Secret Assignment +
      - {% render_field form.device %} + {% with vm_tab_active=form.initial.virtual_machine %} + +
      +
      + {% render_field form.device %} +
      +
      + {% render_field form.virtual_machine %} +
      +
      + {% endwith %} {% render_field form.role %} {% render_field form.name %} {% render_field form.userkeys %} @@ -37,10 +52,10 @@

      {% block title %}{% if obj.pk %}Editing {{ obj }}{% else %}Add a Secret{% en

      diff --git a/netbox/templates/secrets/secret_import.html b/netbox/templates/secrets/secret_import.html index bf2f06ae9a..0e540eb942 100644 --- a/netbox/templates/secrets/secret_import.html +++ b/netbox/templates/secrets/secret_import.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_bulk_import.html' %} +{% extends 'generic/object_bulk_import.html' %} {% load static %} {% block content %} diff --git a/netbox/templates/tenancy/tenant.html b/netbox/templates/tenancy/tenant.html index a9cf67398c..e2e66e6b26 100644 --- a/netbox/templates/tenancy/tenant.html +++ b/netbox/templates/tenancy/tenant.html @@ -9,10 +9,10 @@
      @@ -21,7 +21,7 @@
      @@ -29,29 +29,29 @@
      - {% plugin_buttons tenant %} + {% plugin_buttons object %} {% if perms.tenancy.add_tenant %} - {% clone_button tenant %} + {% clone_button object %} {% endif %} {% if perms.tenancy.change_tenant %} - {% edit_button tenant %} + {% edit_button object %} {% endif %} {% if perms.tenancy.delete_tenant %} - {% delete_button tenant %} + {% delete_button object %} {% endif %}
      -

      {% block title %}{{ tenant }}{% endblock %}

      - {% include 'inc/created_updated.html' with obj=tenant %} +

      {% block title %}{{ object }}{% endblock %}

      + {% include 'inc/created_updated.html' %}
      - {% custom_links tenant %} + {% custom_links object %}
      @@ -68,8 +68,8 @@

      {% block title %}{{ tenant }}{% endblock %}

      Group - {% if tenant.group %} - {{ tenant.group }} + {% if object.group %} + {{ object.group }} {% else %} None {% endif %} @@ -77,25 +77,25 @@

      {% block title %}{{ tenant }}{% endblock %}

      Description - {{ tenant.description|placeholder }} + {{ object.description|placeholder }} - {% include 'inc/custom_fields_panel.html' with obj=tenant %} - {% include 'extras/inc/tags_panel.html' with tags=tenant.tags.all url='tenancy:tenant_list' %} + {% include 'inc/custom_fields_panel.html' %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='tenancy:tenant_list' %}
      Comments
      - {% if tenant.comments %} - {{ tenant.comments|render_markdown }} + {% if object.comments %} + {{ object.comments|render_markdown }} {% else %} None {% endif %}
      - {% plugin_left_page tenant %} + {% plugin_left_page object %} - {% plugin_right_page tenant %} + {% plugin_right_page object %}
      - {% plugin_full_width_page tenant %} + {% plugin_full_width_page object %}
      {% endblock %} diff --git a/netbox/templates/tenancy/tenant_edit.html b/netbox/templates/tenancy/tenant_edit.html index 6f58bb4509..8a1d1d1b66 100644 --- a/netbox/templates/tenancy/tenant_edit.html +++ b/netbox/templates/tenancy/tenant_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load static %} {% load form_helpers %} diff --git a/netbox/templates/users/api_tokens.html b/netbox/templates/users/api_tokens.html index 690a966b06..04e7cb23d2 100644 --- a/netbox/templates/users/api_tokens.html +++ b/netbox/templates/users/api_tokens.html @@ -18,7 +18,7 @@ Delete {% endif %} - + {{ token.key }} {% if token.is_expired %} Expired @@ -57,7 +57,7 @@ {% endfor %} {% if perms.users.add_token %} - + Add a token {% else %} diff --git a/netbox/templates/users/preferences.html b/netbox/templates/users/preferences.html index 8b3c4bcc44..1c20e8aafe 100644 --- a/netbox/templates/users/preferences.html +++ b/netbox/templates/users/preferences.html @@ -26,7 +26,7 @@ {% else %} diff --git a/netbox/templates/users/sessionkey_delete.html b/netbox/templates/users/sessionkey_delete.html index c91956b798..e3e8a7efc3 100644 --- a/netbox/templates/users/sessionkey_delete.html +++ b/netbox/templates/users/sessionkey_delete.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_delete.html' %} +{% extends 'generic/object_delete.html' %} {% block message %}

      Are you sure you want to delete your session key?

      diff --git a/netbox/templates/users/userkey.html b/netbox/templates/users/userkey.html index 2861d187ea..09b5bde5b4 100644 --- a/netbox/templates/users/userkey.html +++ b/netbox/templates/users/userkey.html @@ -3,39 +3,39 @@ {% block title %}User Key{% endblock %} {% block usercontent %} - {% if userkey %} + {% if object %}

      Your user key is: - {% if userkey.is_active %} + {% if object.is_active %} Active {% else %} Inactive {% endif %}

      - {% include 'inc/created_updated.html' with obj=userkey %} - {% if not userkey.is_active %} + {% include 'inc/created_updated.html' %} + {% if not object.is_active %} {% endif %} -
      {{ userkey.public_key }}
      +
      {{ object.public_key }}

      - {% if userkey.session_key %} + {% if object.session_key %}

      Session key: Active

      - Created {{ userkey.session_key.created }} + Created {{ object.session_key.created }} {% else %}

      No active session key

      {% endif %} @@ -43,7 +43,7 @@

      No active session key

      You don't have a user key on file.

      - + Create a User Key

      diff --git a/netbox/templates/users/userkey_edit.html b/netbox/templates/users/userkey_edit.html index 0715f9038c..a7aaa720cf 100644 --- a/netbox/templates/users/userkey_edit.html +++ b/netbox/templates/users/userkey_edit.html @@ -5,7 +5,7 @@ {% block title %}User Key{% endblock %} {% block usercontent %} - {% if userkey.is_active %} + {% if object.is_active %} diff --git a/netbox/templates/inc/table_config_form.html b/netbox/templates/utilities/templatetags/table_config_form.html similarity index 66% rename from netbox/templates/inc/table_config_form.html rename to netbox/templates/utilities/templatetags/table_config_form.html index 66844c7ca4..c92adaee1d 100644 --- a/netbox/templates/inc/table_config_form.html +++ b/netbox/templates/utilities/templatetags/table_config_form.html @@ -1,5 +1,5 @@ {% load form_helpers %} -
      - {% plugin_full_width_page cluster %} + {% plugin_full_width_page object %}
      {% endblock %} diff --git a/netbox/templates/virtualization/cluster_edit.html b/netbox/templates/virtualization/cluster_edit.html index 5ad7c53e11..f43fc717f2 100644 --- a/netbox/templates/virtualization/cluster_edit.html +++ b/netbox/templates/virtualization/cluster_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load form_helpers %} {% block form %} diff --git a/netbox/templates/virtualization/inc/vminterface.html b/netbox/templates/virtualization/inc/vminterface.html deleted file mode 100644 index 9ee1fa3961..0000000000 --- a/netbox/templates/virtualization/inc/vminterface.html +++ /dev/null @@ -1,141 +0,0 @@ -{% load helpers %} - - - {# Checkbox #} - {% if perms.virtualization.change_vminterface or perms.virtualization.delete_vminterface %} - - - - {% endif %} - - {# Name #} - - {{ iface }} - - - {# MAC address #} - - {{ iface.mac_address|default:"—" }} - - - {# MTU #} - {{ iface.mtu|default:"—" }} - - {# 802.1Q mode #} - {{ iface.get_mode_display|default:"—" }} - - {# Description/tags #} - - {% if iface.description %} - {{ iface.description }}
      - {% endif %} - {% for tag in iface.tags.all %} - {% tag tag %} - {% empty %} - {% if not iface.description %}—{% endif %} - {% endfor %} - - - {# Buttons #} - - {% if show_interface_graphs %} - - {% endif %} - {% if perms.ipam.add_ipaddress %} - - - - {% endif %} - {% if perms.virtualization.change_vminterface %} - - - - {% endif %} - {% if perms.virtualization.delete_vminterface %} - - - - {% endif %} - - - -{% with ipaddresses=iface.ip_addresses.all %} - {% if ipaddresses %} - - {# Placeholder #} - {% if perms.virtualization.change_vminterface or perms.virtualization.delete_vminterface %} - - {% endif %} - - {# IP addresses table #} - - - - - - - - - - - - {% for ip in iface.ip_addresses.all %} - - - {# IP address #} - - - {# Primary/status/role #} - - - {# VRF #} - - - {# Description #} - - - {# Buttons #} - - - - {% endfor %} -
      IP AddressStatus/RoleVRFDescription
      - {{ ip }} - - {% if virtualmachine.primary_ip4 == ip or virtualmachine.primary_ip6 == ip %} - Primary - {% endif %} - {{ ip.get_status_display }} - {% if ip.role %} - {{ ip.get_role_display }} - {% endif %} - - {% if ip.vrf %} - {{ ip.vrf.name }} - {% else %} - Global - {% endif %} - - {% if ip.description %} - {{ ip.description }} - {% else %} - - {% endif %} - - {% if perms.ipam.change_ipaddress %} - - - - {% endif %} - {% if perms.ipam.delete_ipaddress %} - - - - {% endif %} -
      - - - {% endif %} -{% endwith %} diff --git a/netbox/templates/virtualization/virtualmachine.html b/netbox/templates/virtualization/virtualmachine.html index ea33aa4604..0f4a0416d8 100644 --- a/netbox/templates/virtualization/virtualmachine.html +++ b/netbox/templates/virtualization/virtualmachine.html @@ -9,10 +9,10 @@
      @@ -21,7 +21,7 @@
      @@ -30,38 +30,38 @@
      {% if perms.virtualization.add_vminterface %} - - Add Interfaces + + Add Interfaces {% endif %} - {% plugin_buttons virtualmachine %} + {% plugin_buttons object %} {% if perms.virtualization.add_virtualmachine %} - {% clone_button virtualmachine %} + {% clone_button object %} {% endif %} {% if perms.virtualization.change_virtualmachine %} - {% edit_button virtualmachine %} + {% edit_button object %} {% endif %} {% if perms.virtualization.delete_virtualmachine %} - {% delete_button virtualmachine %} + {% delete_button object %} {% endif %}
      -

      {% block title %}{{ virtualmachine }}{% endblock %}

      - {% include 'inc/created_updated.html' with obj=virtualmachine %} +

      {% block title %}{{ object }}{% endblock %}

      + {% include 'inc/created_updated.html' %}
      - {% custom_links virtualmachine %} + {% custom_links object %}
      @@ -77,19 +77,19 @@

      {% block title %}{{ virtualmachine }}{% endblock %}

      - +
      Name{{ virtualmachine }}{{ object }}
      Status - {{ virtualmachine.get_status_display }} + {{ object.get_status_display }}
      Role - {% if virtualmachine.role %} - {{ virtualmachine.role }} + {% if object.role %} + {{ object.role }} {% else %} None {% endif %} @@ -98,8 +98,8 @@

      {% block title %}{{ virtualmachine }}{% endblock %}

      Platform - {% if virtualmachine.platform %} - {{ virtualmachine.platform }} + {% if object.platform %} + {{ object.platform }} {% else %} None {% endif %} @@ -108,12 +108,11 @@

      {% block title %}{{ virtualmachine }}{% endblock %}

      Tenant - {% if virtualmachine.tenant %} - {% if virtualmachine.tenant.group %} - {{ virtualmachine.tenant.group }} - + {% if object.tenant %} + {% if object.tenant.group %} + {{ object.tenant.group }} / {% endif %} - {{ virtualmachine.tenant }} + {{ object.tenant }} {% else %} None {% endif %} @@ -122,12 +121,12 @@

      {% block title %}{{ virtualmachine }}{% endblock %}

      Primary IPv4 - {% if virtualmachine.primary_ip4 %} - {{ virtualmachine.primary_ip4.address.ip }} - {% if virtualmachine.primary_ip4.nat_inside %} - (NAT for {{ virtualmachine.primary_ip4.nat_inside.address.ip }}) - {% elif virtualmachine.primary_ip4.nat_outside %} - (NAT: {{ virtualmachine.primary_ip4.nat_outside.address.ip }}) + {% if object.primary_ip4 %} + {{ object.primary_ip4.address.ip }} + {% if object.primary_ip4.nat_inside %} + (NAT for {{ object.primary_ip4.nat_inside.address.ip }}) + {% elif object.primary_ip4.nat_outside %} + (NAT: {{ object.primary_ip4.nat_outside.address.ip }}) {% endif %} {% else %} @@ -137,12 +136,12 @@

      {% block title %}{{ virtualmachine }}{% endblock %}

      Primary IPv6 - {% if virtualmachine.primary_ip6 %} - {{ virtualmachine.primary_ip6.address.ip }} - {% if virtualmachine.primary_ip6.nat_inside %} - (NAT for {{ virtualmachine.primary_ip6.nat_inside.address.ip }}) - {% elif virtualmachine.primary_ip6.nat_outside %} - (NAT: {{ virtualmachine.primary_ip6.nat_outside.address.ip }}) + {% if object.primary_ip6 %} + {{ object.primary_ip6.address.ip }} + {% if object.primary_ip6.nat_inside %} + (NAT for {{ object.primary_ip6.nat_inside.address.ip }}) + {% elif object.primary_ip6.nat_outside %} + (NAT: {{ object.primary_ip6.nat_outside.address.ip }}) {% endif %} {% else %} @@ -151,21 +150,21 @@

      {% block title %}{{ virtualmachine }}{% endblock %}

      - {% include 'inc/custom_fields_panel.html' with obj=virtualmachine %} - {% include 'extras/inc/tags_panel.html' with tags=virtualmachine.tags.all url='virtualization:virtualmachine_list' %} + {% include 'inc/custom_fields_panel.html' %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='virtualization:virtualmachine_list' %}
      Comments
      - {% if virtualmachine.comments %} - {{ virtualmachine.comments|render_markdown }} + {% if object.comments %} + {{ object.comments|render_markdown }} {% else %} None {% endif %}
      - {% plugin_left_page virtualmachine %} + {% plugin_left_page object %}
      @@ -176,16 +175,15 @@

      {% block title %}{{ virtualmachine }}{% endblock %}

      Cluster - {% if virtualmachine.cluster.group %} - {{ virtualmachine.cluster.group }} - + {% if object.cluster.group %} + {{ object.cluster.group }} / {% endif %} - {{ virtualmachine.cluster }} + {{ object.cluster }} Cluster Type - {{ virtualmachine.cluster.type }} + {{ object.cluster.type }}
      @@ -195,24 +193,24 @@

      {% block title %}{{ virtualmachine }}{% endblock %}

      - - + + - + - +
      Virtual CPUs{{ virtualmachine.vcpus|placeholder }} Virtual CPUs{{ object.vcpus|placeholder }}
      Memory Memory - {% if virtualmachine.memory %} - {{ virtualmachine.memory }} MB + {% if object.memory %} + {{ object.memory }} MB {% else %} {% endif %}
      Disk Space Disk Space - {% if virtualmachine.disk %} - {{ virtualmachine.disk }} GB + {% if object.disk %} + {{ object.disk }} GB {% else %} {% endif %} @@ -220,6 +218,21 @@

      {% block title %}{{ virtualmachine }}{% endblock %}

      + {% if perms.secrets.view_secret %} +
      +
      + Secrets +
      + {% include 'secrets/inc/assigned_secrets.html' %} + {% if perms.secrets.add_secret %} + + {% endif %} +
      + {% endif %}
      Services @@ -237,96 +250,72 @@

      {% block title %}{{ virtualmachine }}{% endblock %}

      {% endif %} {% if perms.ipam.add_service %} {% endif %}
      - {% plugin_right_page virtualmachine %} + {% plugin_right_page object %}
      - {% plugin_full_width_page virtualmachine %} + {% plugin_full_width_page object %}
      - {% if perms.virtualization.change_vminterface or perms.virtualization.delete_vminterface %} -
      + {% csrf_token %} - - {% endif %} -
      -
      - Interfaces -
      - -
      -
      - + +
      +
      + Interfaces +
      + {% if request.user.is_authenticated %} + + {% endif %} +
      +
      + +
      -
      - - - - {% if perms.virtualization.change_vminterface or perms.virtualization.delete_vminterface %} - + {% include 'responsive_table.html' with table=vminterface_table %} + {% if perms.virtualization.add_vminterface or perms.virtualization.delete_vminterface %} + - - - - - - - - - {% for iface in interfaces %} - {% include 'virtualization/inc/vminterface.html' %} - {% empty %} - - - - {% endfor %} - -
      NameMAC AddressMTUModeDescription
      — No interfaces defined —
      - {% if perms.virtualization.add_vminterface or perms.virtualization.delete_vminterface %} - - {% endif %} -
      - {% if perms.virtualization.delete_vminterface %} - - {% endif %} + {% if interfaces and perms.virtualization.delete_vminterface %} + + {% endif %} + {% if perms.virtualization.add_vminterface %} + +
      + {% endif %} +
      + {% endif %} +
      + + {% table_config_form vminterface_table %}
      +{% include 'secrets/inc/private_key_modal.html' %} {% endblock %} {% block javascript %} - + + {% endblock %} diff --git a/netbox/templates/virtualization/virtualmachine_edit.html b/netbox/templates/virtualization/virtualmachine_edit.html index 3be462c4d6..6bffabaddb 100644 --- a/netbox/templates/virtualization/virtualmachine_edit.html +++ b/netbox/templates/virtualization/virtualmachine_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load form_helpers %} {% block form %} diff --git a/netbox/templates/virtualization/virtualmachine_list.html b/netbox/templates/virtualization/virtualmachine_list.html index f8ee77626c..9d8c1720fb 100644 --- a/netbox/templates/virtualization/virtualmachine_list.html +++ b/netbox/templates/virtualization/virtualmachine_list.html @@ -1,10 +1,10 @@ -{% extends 'utilities/obj_list.html' %} +{% extends 'generic/object_list.html' %} {% block bulk_buttons %} {% if perms.virtualization.change_virtualmachine %}
      - {% plugin_buttons vminterface %} + {% plugin_buttons object %} {% if perms.virtualization.change_vminterface %} - - Edit + + Edit {% endif %} {% if perms.virtualization.delete_vminterface %} - - Delete + + Delete {% endif %}
      -

      {% block title %}{{ vminterface.virtual_machine }} / {{ vminterface.name }}{% endblock %}

      +

      {% block title %}{{ object.virtual_machine }} / {{ object.name }}{% endblock %}

      @@ -49,46 +49,46 @@

      {% block title %}{{ vminterface.virtual_machine }} / {{ vminterface.name }}{ Virtual Machine - {{ vminterface.virtual_machine }} + {{ object.virtual_machine }} Name - {{ vminterface.name }} + {{ object.name }} Enabled - {% if vminterface.enabled %} - + {% if object.enabled %} + {% else %} - + {% endif %} Description - {{ vminterface.description|placeholder }} + {{ object.description|placeholder }} MTU - {{ vminterface.mtu|placeholder }} + {{ object.mtu|placeholder }} MAC Address - {{ vminterface.mac_address|placeholder }} + {{ object.mac_address|placeholder }} 802.1Q Mode - {{ vminterface.get_mode_display }} + {{ object.get_mode_display }} - {% plugin_left_page vminterface %} + {% plugin_left_page object %}
      - {% include 'extras/inc/tags_panel.html' with tags=vminterface.tags.all %} - {% plugin_right_page vminterface %} + {% include 'extras/inc/tags_panel.html' with tags=object.tags.all %} + {% plugin_right_page object %}
      @@ -103,7 +103,7 @@

      {% block title %}{{ vminterface.virtual_machine }} / {{ vminterface.name }}{

      - {% plugin_full_width_page vminterface %} + {% plugin_full_width_page object %}
      {% endblock %} diff --git a/netbox/templates/virtualization/vminterface_edit.html b/netbox/templates/virtualization/vminterface_edit.html index 12018ba5d6..d1fe6d104c 100644 --- a/netbox/templates/virtualization/vminterface_edit.html +++ b/netbox/templates/virtualization/vminterface_edit.html @@ -1,4 +1,4 @@ -{% extends 'utilities/obj_edit.html' %} +{% extends 'generic/object_edit.html' %} {% load form_helpers %} {% block form %} diff --git a/netbox/tenancy/api/nested_serializers.py b/netbox/tenancy/api/nested_serializers.py index 369d5eb1bc..7b227c1232 100644 --- a/netbox/tenancy/api/nested_serializers.py +++ b/netbox/tenancy/api/nested_serializers.py @@ -1,7 +1,7 @@ from rest_framework import serializers +from netbox.api import WritableNestedSerializer from tenancy.models import Tenant, TenantGroup -from utilities.api import WritableNestedSerializer __all__ = [ 'NestedTenantGroupSerializer', diff --git a/netbox/tenancy/api/serializers.py b/netbox/tenancy/api/serializers.py index 4467b050bd..05e83853ee 100644 --- a/netbox/tenancy/api/serializers.py +++ b/netbox/tenancy/api/serializers.py @@ -2,8 +2,8 @@ from extras.api.customfields import CustomFieldModelSerializer from extras.api.serializers import TaggedObjectSerializer +from netbox.api import ValidatedModelSerializer from tenancy.models import Tenant, TenantGroup -from utilities.api import ValidatedModelSerializer from .nested_serializers import * diff --git a/netbox/tenancy/api/urls.py b/netbox/tenancy/api/urls.py index ad4424005a..32540879d7 100644 --- a/netbox/tenancy/api/urls.py +++ b/netbox/tenancy/api/urls.py @@ -1,4 +1,4 @@ -from utilities.api import OrderedDefaultRouter +from netbox.api import OrderedDefaultRouter from . import views diff --git a/netbox/tenancy/api/views.py b/netbox/tenancy/api/views.py index 065d3a9f32..34be4991e2 100644 --- a/netbox/tenancy/api/views.py +++ b/netbox/tenancy/api/views.py @@ -4,9 +4,9 @@ from dcim.models import Device, Rack, Site from extras.api.views import CustomFieldModelViewSet from ipam.models import IPAddress, Prefix, VLAN, VRF +from netbox.api.views import ModelViewSet from tenancy import filters from tenancy.models import Tenant, TenantGroup -from utilities.api import ModelViewSet from utilities.utils import get_subquery from virtualization.models import VirtualMachine from . import serializers diff --git a/netbox/tenancy/filters.py b/netbox/tenancy/filters.py index af5ee0b2c2..d61081de44 100644 --- a/netbox/tenancy/filters.py +++ b/netbox/tenancy/filters.py @@ -1,7 +1,7 @@ import django_filters from django.db.models import Q -from extras.filters import CustomFieldFilterSet, CreatedUpdatedFilterSet +from extras.filters import CustomFieldModelFilterSet, CreatedUpdatedFilterSet from utilities.filters import BaseFilterSet, NameSlugSearchFilterSet, TagFilter, TreeNodeMultipleChoiceFilter from .models import Tenant, TenantGroup @@ -30,7 +30,7 @@ class Meta: fields = ['id', 'name', 'slug', 'description'] -class TenantFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet): +class TenantFilterSet(BaseFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): q = django_filters.CharFilter( method='search', label='Search', diff --git a/netbox/tenancy/migrations/0010_custom_field_data.py b/netbox/tenancy/migrations/0010_custom_field_data.py new file mode 100644 index 0000000000..ec05be0ff8 --- /dev/null +++ b/netbox/tenancy/migrations/0010_custom_field_data.py @@ -0,0 +1,17 @@ +import django.core.serializers.json +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tenancy', '0009_standardize_description'), + ] + + operations = [ + migrations.AddField( + model_name='tenant', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + ] diff --git a/netbox/tenancy/migrations/0011_standardize_name_length.py b/netbox/tenancy/migrations/0011_standardize_name_length.py new file mode 100644 index 0000000000..1e29a0f5e7 --- /dev/null +++ b/netbox/tenancy/migrations/0011_standardize_name_length.py @@ -0,0 +1,33 @@ +# Generated by Django 3.1 on 2020-10-15 19:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tenancy', '0010_custom_field_data'), + ] + + operations = [ + migrations.AlterField( + model_name='tenant', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='tenant', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='tenantgroup', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='tenantgroup', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + ] diff --git a/netbox/tenancy/models.py b/netbox/tenancy/models.py index cc3abf19a4..3ba644c096 100644 --- a/netbox/tenancy/models.py +++ b/netbox/tenancy/models.py @@ -1,4 +1,3 @@ -from django.contrib.contenttypes.fields import GenericRelation from django.db import models from django.urls import reverse from mptt.models import MPTTModel, TreeForeignKey @@ -22,10 +21,11 @@ class TenantGroup(MPTTModel, ChangeLoggedModel): An arbitrary collection of Tenants. """ name = models.CharField( - max_length=50, + max_length=100, unique=True ) slug = models.SlugField( + max_length=100, unique=True ) parent = TreeForeignKey( @@ -82,10 +82,11 @@ class Tenant(ChangeLoggedModel, CustomFieldModel): department. """ name = models.CharField( - max_length=30, + max_length=100, unique=True ) slug = models.SlugField( + max_length=100, unique=True ) group = models.ForeignKey( @@ -102,11 +103,6 @@ class Tenant(ChangeLoggedModel, CustomFieldModel): comments = models.TextField( blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) tags = TaggableManager(through=TaggedItem) objects = RestrictedQuerySet.as_manager() diff --git a/netbox/tenancy/tables.py b/netbox/tenancy/tables.py index dc96b839c8..8abca2bb88 100644 --- a/netbox/tenancy/tables.py +++ b/netbox/tenancy/tables.py @@ -1,11 +1,11 @@ import django_tables2 as tables -from utilities.tables import BaseTable, ButtonsColumn, TagColumn, ToggleColumn +from utilities.tables import BaseTable, ButtonsColumn, LinkedCountColumn, TagColumn, ToggleColumn from .models import Tenant, TenantGroup MPTT_LINK = """ {% if record.get_children %} - + {% else %} {% endif %} @@ -32,7 +32,9 @@ class TenantGroupTable(BaseTable): template_code=MPTT_LINK, orderable=False ) - tenant_count = tables.Column( + tenant_count = LinkedCountColumn( + viewname='tenancy:tenant_list', + url_params={'group': 'slug'}, verbose_name='Tenants' ) actions = ButtonsColumn(TenantGroup, pk_field='slug') diff --git a/netbox/tenancy/tests/test_api.py b/netbox/tenancy/tests/test_api.py index f04b2a7cef..7af3c8d790 100644 --- a/netbox/tenancy/tests/test_api.py +++ b/netbox/tenancy/tests/test_api.py @@ -17,6 +17,9 @@ def test_root(self): class TenantGroupTest(APIViewTestCases.APIViewTestCase): model = TenantGroup brief_fields = ['_depth', 'id', 'name', 'slug', 'tenant_count', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -52,6 +55,9 @@ def setUpTestData(cls): class TenantTest(APIViewTestCases.APIViewTestCase): model = Tenant brief_fields = ['id', 'name', 'slug', 'url'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): diff --git a/netbox/tenancy/views.py b/netbox/tenancy/views.py index b129177ebd..9fd77d88e3 100644 --- a/netbox/tenancy/views.py +++ b/netbox/tenancy/views.py @@ -1,12 +1,9 @@ -from django.db.models import Count from django.shortcuts import get_object_or_404, render from circuits.models import Circuit from dcim.models import Site, Rack, Device, RackReservation from ipam.models import IPAddress, Prefix, VLAN, VRF -from utilities.views import ( - BulkDeleteView, BulkEditView, BulkImportView, ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView, -) +from netbox.views import generic from virtualization.models import VirtualMachine, Cluster from . import filters, forms, tables from .models import Tenant, TenantGroup @@ -16,7 +13,7 @@ # Tenant groups # -class TenantGroupListView(ObjectListView): +class TenantGroupListView(generic.ObjectListView): queryset = TenantGroup.objects.add_related_count( TenantGroup.objects.all(), Tenant, @@ -27,22 +24,22 @@ class TenantGroupListView(ObjectListView): table = tables.TenantGroupTable -class TenantGroupEditView(ObjectEditView): +class TenantGroupEditView(generic.ObjectEditView): queryset = TenantGroup.objects.all() model_form = forms.TenantGroupForm -class TenantGroupDeleteView(ObjectDeleteView): +class TenantGroupDeleteView(generic.ObjectDeleteView): queryset = TenantGroup.objects.all() -class TenantGroupBulkImportView(BulkImportView): +class TenantGroupBulkImportView(generic.BulkImportView): queryset = TenantGroup.objects.all() model_form = forms.TenantGroupCSVForm table = tables.TenantGroupTable -class TenantGroupBulkDeleteView(BulkDeleteView): +class TenantGroupBulkDeleteView(generic.BulkDeleteView): queryset = TenantGroup.objects.add_related_count( TenantGroup.objects.all(), Tenant, @@ -57,63 +54,60 @@ class TenantGroupBulkDeleteView(BulkDeleteView): # Tenants # -class TenantListView(ObjectListView): - queryset = Tenant.objects.prefetch_related('group') +class TenantListView(generic.ObjectListView): + queryset = Tenant.objects.all() filterset = filters.TenantFilterSet filterset_form = forms.TenantFilterForm table = tables.TenantTable -class TenantView(ObjectView): +class TenantView(generic.ObjectView): queryset = Tenant.objects.prefetch_related('group') - def get(self, request, slug): - - tenant = get_object_or_404(self.queryset, slug=slug) + def get_extra_context(self, request, instance): stats = { - 'site_count': Site.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'rack_count': Rack.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'rackreservation_count': RackReservation.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'device_count': Device.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'vrf_count': VRF.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'prefix_count': Prefix.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'ipaddress_count': IPAddress.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'virtualmachine_count': VirtualMachine.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), - 'cluster_count': Cluster.objects.restrict(request.user, 'view').filter(tenant=tenant).count(), + 'site_count': Site.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'rack_count': Rack.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'rackreservation_count': RackReservation.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'device_count': Device.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'vrf_count': VRF.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'prefix_count': Prefix.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'ipaddress_count': IPAddress.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'virtualmachine_count': VirtualMachine.objects.restrict(request.user, 'view').filter(tenant=instance).count(), + 'cluster_count': Cluster.objects.restrict(request.user, 'view').filter(tenant=instance).count(), } - return render(request, 'tenancy/tenant.html', { - 'tenant': tenant, + return { 'stats': stats, - }) + } -class TenantEditView(ObjectEditView): +class TenantEditView(generic.ObjectEditView): queryset = Tenant.objects.all() model_form = forms.TenantForm template_name = 'tenancy/tenant_edit.html' -class TenantDeleteView(ObjectDeleteView): +class TenantDeleteView(generic.ObjectDeleteView): queryset = Tenant.objects.all() -class TenantBulkImportView(BulkImportView): +class TenantBulkImportView(generic.BulkImportView): queryset = Tenant.objects.all() model_form = forms.TenantCSVForm table = tables.TenantTable -class TenantBulkEditView(BulkEditView): +class TenantBulkEditView(generic.BulkEditView): queryset = Tenant.objects.prefetch_related('group') filterset = filters.TenantFilterSet table = tables.TenantTable form = forms.TenantBulkEditForm -class TenantBulkDeleteView(BulkDeleteView): +class TenantBulkDeleteView(generic.BulkDeleteView): queryset = Tenant.objects.prefetch_related('group') filterset = filters.TenantFilterSet table = tables.TenantTable diff --git a/netbox/users/api/nested_serializers.py b/netbox/users/api/nested_serializers.py index f1bcf3b37b..3b43ca7c99 100644 --- a/netbox/users/api/nested_serializers.py +++ b/netbox/users/api/nested_serializers.py @@ -2,8 +2,8 @@ from django.contrib.contenttypes.models import ContentType from rest_framework import serializers +from netbox.api import ContentTypeField, WritableNestedSerializer from users.models import ObjectPermission -from utilities.api import ContentTypeField, WritableNestedSerializer __all__ = [ 'NestedGroupSerializer', diff --git a/netbox/users/api/serializers.py b/netbox/users/api/serializers.py index a3028f3cb8..eed0bd80e2 100644 --- a/netbox/users/api/serializers.py +++ b/netbox/users/api/serializers.py @@ -2,8 +2,8 @@ from django.contrib.contenttypes.models import ContentType from rest_framework import serializers +from netbox.api import ContentTypeField, SerializedPKRelatedField, ValidatedModelSerializer from users.models import ObjectPermission -from utilities.api import ContentTypeField, SerializedPKRelatedField, ValidatedModelSerializer from .nested_serializers import * diff --git a/netbox/users/api/urls.py b/netbox/users/api/urls.py index c52c6c87fb..df2e8c25a2 100644 --- a/netbox/users/api/urls.py +++ b/netbox/users/api/urls.py @@ -1,4 +1,4 @@ -from utilities.api import OrderedDefaultRouter +from netbox.api import OrderedDefaultRouter from . import views @@ -12,5 +12,8 @@ # Permissions router.register('permissions', views.ObjectPermissionViewSet) +# User preferences +router.register('config', views.UserConfigViewSet, basename='userconfig') + app_name = 'users-api' urlpatterns = router.urls diff --git a/netbox/users/api/views.py b/netbox/users/api/views.py index a3536e960d..7773e54f4d 100644 --- a/netbox/users/api/views.py +++ b/netbox/users/api/views.py @@ -1,11 +1,15 @@ from django.contrib.auth.models import Group, User from django.db.models import Count +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response from rest_framework.routers import APIRootView +from rest_framework.viewsets import ViewSet +from netbox.api.views import ModelViewSet from users import filters -from users.models import ObjectPermission -from utilities.api import ModelViewSet +from users.models import ObjectPermission, UserConfig from utilities.querysets import RestrictedQuerySet +from utilities.utils import deepmerge from . import serializers @@ -41,3 +45,36 @@ class ObjectPermissionViewSet(ModelViewSet): queryset = ObjectPermission.objects.prefetch_related('object_types', 'groups', 'users') serializer_class = serializers.ObjectPermissionSerializer filterset_class = filters.ObjectPermissionFilterSet + + +# +# User preferences +# + +class UserConfigViewSet(ViewSet): + """ + An API endpoint via which a user can update his or her own UserConfig data (but no one else's). + """ + permission_classes = [IsAuthenticated] + + def get_queryset(self): + return UserConfig.objects.filter(user=self.request.user) + + def list(self, request): + """ + Return the UserConfig for the currently authenticated User. + """ + userconfig = self.get_queryset().first() + + return Response(userconfig.data) + + def patch(self, request): + """ + Update the UserConfig for the currently authenticated User. + """ + # TODO: How can we validate this data? + userconfig = self.get_queryset().first() + userconfig.data = deepmerge(userconfig.data, request.data) + userconfig.save() + + return Response(userconfig.data) diff --git a/netbox/users/tests/test_api.py b/netbox/users/tests/test_api.py index 2e670b5581..11d4e58cd0 100644 --- a/netbox/users/tests/test_api.py +++ b/netbox/users/tests/test_api.py @@ -1,11 +1,10 @@ from django.contrib.auth.models import Group, User from django.contrib.contenttypes.models import ContentType -from django.test import override_settings from django.urls import reverse -from rest_framework import status from users.models import ObjectPermission -from utilities.testing import APIViewTestCases, APITestCase, disable_warnings +from utilities.testing import APIViewTestCases, APITestCase +from utilities.utils import deepmerge class AppTest(APITestCase): @@ -99,7 +98,7 @@ def setUpTestData(cls): object_type = ContentType.objects.get(app_label='dcim', model='device') - for i in range(0, 3): + for i in range(3): objectpermission = ObjectPermission( name=f'Permission {i+1}', actions=['view', 'add', 'change', 'delete'], @@ -136,3 +135,60 @@ def setUpTestData(cls): 'constraints': {'name': 'TEST6'}, }, ] + + cls.bulk_update_data = { + 'description': 'New description', + } + + +class UserConfigTest(APITestCase): + + def test_get(self): + """ + Retrieve user configuration via GET request. + """ + userconfig = self.user.config + url = reverse('users-api:userconfig-list') + + response = self.client.get(url, **self.header) + self.assertEqual(response.data, {}) + + data = { + "a": 123, + "b": 456, + "c": 789, + } + userconfig.data = data + userconfig.save() + response = self.client.get(url, **self.header) + self.assertEqual(response.data, data) + + def test_patch(self): + """ + Set user config via PATCH requests. + """ + userconfig = self.user.config + url = reverse('users-api:userconfig-list') + + data = { + "a": { + "a1": "X", + "a2": "Y", + }, + "b": { + "b1": "Z", + } + } + response = self.client.patch(url, data=data, format='json', **self.header) + self.assertDictEqual(response.data, data) + userconfig.refresh_from_db() + self.assertDictEqual(userconfig.data, data) + + update_data = { + "c": 123 + } + response = self.client.patch(url, data=update_data, format='json', **self.header) + new_data = deepmerge(data, update_data) + self.assertDictEqual(response.data, new_data) + userconfig.refresh_from_db() + self.assertDictEqual(userconfig.data, new_data) diff --git a/netbox/users/views.py b/netbox/users/views.py index 46221f6499..a6d28ecd22 100644 --- a/netbox/users/views.py +++ b/netbox/users/views.py @@ -185,7 +185,7 @@ def get(self, request): userkey = None return render(request, self.template_name, { - 'userkey': userkey, + 'object': userkey, 'active_tab': 'userkey', }) @@ -205,7 +205,7 @@ def get(self, request): form = UserKeyForm(instance=self.userkey) return render(request, self.template_name, { - 'userkey': self.userkey, + 'object': self.userkey, 'form': form, 'active_tab': 'userkey', }) @@ -293,7 +293,7 @@ def get(self, request, pk=None): form = TokenForm(instance=token) - return render(request, 'utilities/obj_edit.html', { + return render(request, 'generic/object_edit.html', { 'obj': token, 'obj_type': token._meta.verbose_name, 'form': form, @@ -322,7 +322,7 @@ def post(self, request, pk=None): else: return redirect('user:token_list') - return render(request, 'utilities/obj_edit.html', { + return render(request, 'generic/object_edit.html', { 'obj': token, 'obj_type': token._meta.verbose_name, 'form': form, @@ -340,7 +340,7 @@ def get(self, request, pk): } form = ConfirmationForm(initial=initial_data) - return render(request, 'utilities/obj_delete.html', { + return render(request, 'generic/object_delete.html', { 'obj': token, 'obj_type': token._meta.verbose_name, 'form': form, @@ -356,7 +356,7 @@ def post(self, request, pk): messages.success(request, "Token deleted") return redirect('user:token_list') - return render(request, 'utilities/obj_delete.html', { + return render(request, 'generic/object_delete.html', { 'obj': token, 'obj_type': token._meta.verbose_name, 'form': form, diff --git a/netbox/utilities/api.py b/netbox/utilities/api.py index cc9789161e..09cc7004b8 100644 --- a/netbox/utilities/api.py +++ b/netbox/utilities/api.py @@ -1,41 +1,14 @@ -import logging -from collections import OrderedDict +import platform +import sys -import pytz from django.conf import settings -from django.contrib.contenttypes.models import ContentType -from django.core.exceptions import FieldError, MultipleObjectsReturned, ObjectDoesNotExist, PermissionDenied -from django.db import transaction -from django.db.models import ManyToManyField, ProtectedError +from django.http import JsonResponse from django.urls import reverse -from rest_framework import serializers -from rest_framework.exceptions import APIException, ValidationError -from rest_framework.permissions import BasePermission -from rest_framework.relations import PrimaryKeyRelatedField, RelatedField -from rest_framework.response import Response -from rest_framework.routers import DefaultRouter -from rest_framework.viewsets import ModelViewSet as _ModelViewSet +from rest_framework import status +from rest_framework.utils import formatting -from .utils import dict_to_filter_params, dynamic_import - -HTTP_ACTIONS = { - 'GET': 'view', - 'OPTIONS': None, - 'HEAD': 'view', - 'POST': 'add', - 'PUT': 'change', - 'PATCH': 'change', - 'DELETE': 'delete', -} - - -class ServiceUnavailable(APIException): - status_code = 503 - default_detail = "Service temporarily unavailable, please try again later." - - -class SerializerNotFound(Exception): - pass +from netbox.api.exceptions import SerializerNotFound +from .utils import dynamic_import def get_serializer_for_model(model, prefix=''): @@ -63,358 +36,37 @@ def is_api_request(request): return request.path_info.startswith(api_path) -# -# Authentication -# - -class IsAuthenticatedOrLoginNotRequired(BasePermission): - """ - Returns True if the user is authenticated or LOGIN_REQUIRED is False. +def get_view_name(view, suffix=None): """ - def has_permission(self, request, view): - if not settings.LOGIN_REQUIRED: - return True - return request.user.is_authenticated - - -# -# Fields -# - -class ChoiceField(serializers.Field): + Derive the view name from its associated model, if it has one. Fall back to DRF's built-in `get_view_name`. """ - Represent a ChoiceField as {'value': , 'label': }. Accepts a single value on write. - - :param choices: An iterable of choices in the form (value, key). - :param allow_blank: Allow blank values in addition to the listed choices. - """ - def __init__(self, choices, allow_blank=False, **kwargs): - self.choiceset = choices - self.allow_blank = allow_blank - self._choices = dict() - - # Unpack grouped choices - for k, v in choices: - if type(v) in [list, tuple]: - for k2, v2 in v: - self._choices[k2] = v2 - else: - self._choices[k] = v - - super().__init__(**kwargs) - - def validate_empty_values(self, data): - # Convert null to an empty string unless allow_null == True - if data is None: - if self.allow_null: - return True, None - else: - data = '' - return super().validate_empty_values(data) - - def to_representation(self, obj): - if obj is '': - return None - return OrderedDict([ - ('value', obj), - ('label', self._choices[obj]) - ]) - - def to_internal_value(self, data): - if data is '': - if self.allow_blank: - return data - raise ValidationError("This field may not be blank.") - - # Provide an explicit error message if the request is trying to write a dict or list - if isinstance(data, (dict, list)): - raise ValidationError('Value must be passed directly (e.g. "foo": 123); do not use a dictionary or list.') - - # Check for string representations of boolean/integer values - if hasattr(data, 'lower'): - if data.lower() == 'true': - data = True - elif data.lower() == 'false': - data = False - else: - try: - data = int(data) - except ValueError: - pass + if hasattr(view, 'queryset'): + # Determine the model name from the queryset. + name = view.queryset.model._meta.verbose_name + name = ' '.join([w[0].upper() + w[1:] for w in name.split()]) # Capitalize each word - try: - if data in self._choices: - return data - except TypeError: # Input is an unhashable type - pass + else: + # Replicate DRF's built-in behavior. + name = view.__class__.__name__ + name = formatting.remove_trailing_string(name, 'View') + name = formatting.remove_trailing_string(name, 'ViewSet') + name = formatting.camelcase_to_spaces(name) - raise ValidationError(f"{data} is not a valid choice.") + if suffix: + name += ' ' + suffix - @property - def choices(self): - return self._choices + return name -class ContentTypeField(RelatedField): +def rest_api_server_error(request, *args, **kwargs): """ - Represent a ContentType as '.' + Handle exceptions and return a useful error message for REST API requests. """ - default_error_messages = { - "does_not_exist": "Invalid content type: {content_type}", - "invalid": "Invalid value. Specify a content type as '.'.", + type_, error, traceback = sys.exc_info() + data = { + 'error': str(error), + 'exception': type_.__name__, + 'netbox_version': settings.VERSION, + 'python_version': platform.python_version(), } - - def to_internal_value(self, data): - try: - app_label, model = data.split('.') - return ContentType.objects.get_by_natural_key(app_label=app_label, model=model) - except ObjectDoesNotExist: - self.fail('does_not_exist', content_type=data) - except (TypeError, ValueError): - self.fail('invalid') - - def to_representation(self, obj): - return "{}.{}".format(obj.app_label, obj.model) - - -class TimeZoneField(serializers.Field): - """ - Represent a pytz time zone. - """ - def to_representation(self, obj): - return obj.zone if obj else None - - def to_internal_value(self, data): - if not data: - return "" - if data not in pytz.common_timezones: - raise ValidationError('Unknown time zone "{}" (see pytz.common_timezones for all options)'.format(data)) - return pytz.timezone(data) - - -class SerializedPKRelatedField(PrimaryKeyRelatedField): - """ - Extends PrimaryKeyRelatedField to return a serialized object on read. This is useful for representing related - objects in a ManyToManyField while still allowing a set of primary keys to be written. - """ - def __init__(self, serializer, **kwargs): - self.serializer = serializer - self.pk_field = kwargs.pop('pk_field', None) - super().__init__(**kwargs) - - def to_representation(self, value): - return self.serializer(value, context={'request': self.context['request']}).data - - -# -# Serializers -# - -# TODO: We should probably take a fresh look at exactly what we're doing with this. There might be a more elegant -# way to enforce model validation on the serializer. -class ValidatedModelSerializer(serializers.ModelSerializer): - """ - Extends the built-in ModelSerializer to enforce calling clean() on the associated model during validation. - """ - def validate(self, data): - - # Remove custom fields data and tags (if any) prior to model validation - attrs = data.copy() - attrs.pop('custom_fields', None) - attrs.pop('tags', None) - - # Skip ManyToManyFields - for field in self.Meta.model._meta.get_fields(): - if isinstance(field, ManyToManyField): - attrs.pop(field.name, None) - - # Run clean() on an instance of the model - if self.instance is None: - instance = self.Meta.model(**attrs) - else: - instance = self.instance - for k, v in attrs.items(): - setattr(instance, k, v) - instance.clean() - instance.validate_unique() - - return data - - -class WritableNestedSerializer(serializers.ModelSerializer): - """ - Returns a nested representation of an object on read, but accepts only a primary key on write. - """ - - def to_internal_value(self, data): - - if data is None: - return None - - # Dictionary of related object attributes - if isinstance(data, dict): - params = dict_to_filter_params(data) - queryset = self.Meta.model.objects - try: - return queryset.get(**params) - except ObjectDoesNotExist: - raise ValidationError( - "Related object not found using the provided attributes: {}".format(params) - ) - except MultipleObjectsReturned: - raise ValidationError( - "Multiple objects match the provided attributes: {}".format(params) - ) - except FieldError as e: - raise ValidationError(e) - - # Integer PK of related object - if isinstance(data, int): - pk = data - else: - try: - # PK might have been mistakenly passed as a string - pk = int(data) - except (TypeError, ValueError): - raise ValidationError( - "Related objects must be referenced by numeric ID or by dictionary of attributes. Received an " - "unrecognized value: {}".format(data) - ) - - # Look up object by PK - queryset = self.Meta.model.objects - try: - return queryset.get(pk=int(data)) - except ObjectDoesNotExist: - raise ValidationError( - "Related object not found using the provided numeric ID: {}".format(pk) - ) - - -# -# Viewsets -# - -class ModelViewSet(_ModelViewSet): - """ - Accept either a single object or a list of objects to create. - """ - def get_serializer(self, *args, **kwargs): - - # If a list of objects has been provided, initialize the serializer with many=True - if isinstance(kwargs.get('data', {}), list): - kwargs['many'] = True - - return super().get_serializer(*args, **kwargs) - - def get_serializer_class(self): - logger = logging.getLogger('netbox.api.views.ModelViewSet') - - # If 'brief' has been passed as a query param, find and return the nested serializer for this model, if one - # exists - request = self.get_serializer_context()['request'] - if request.query_params.get('brief'): - logger.debug("Request is for 'brief' format; initializing nested serializer") - try: - serializer = get_serializer_for_model(self.queryset.model, prefix='Nested') - logger.debug(f"Using serializer {serializer}") - return serializer - except SerializerNotFound: - pass - - # Fall back to the hard-coded serializer class - logger.debug(f"Using serializer {self.serializer_class}") - return self.serializer_class - - def initial(self, request, *args, **kwargs): - super().initial(request, *args, **kwargs) - - if not request.user.is_authenticated: - return - - # Restrict the view's QuerySet to allow only the permitted objects - action = HTTP_ACTIONS[request.method] - if action: - self.queryset = self.queryset.restrict(request.user, action) - - def dispatch(self, request, *args, **kwargs): - logger = logging.getLogger('netbox.api.views.ModelViewSet') - - try: - return super().dispatch(request, *args, **kwargs) - except ProtectedError as e: - protected_objects = list(e.protected_objects) - msg = f'Unable to delete object. {len(protected_objects)} dependent objects were found: ' - msg += ', '.join([f'{obj} ({obj.pk})' for obj in protected_objects]) - logger.warning(msg) - return self.finalize_response( - request, - Response({'detail': msg}, status=409), - *args, - **kwargs - ) - - def _validate_objects(self, instance): - """ - Check that the provided instance or list of instances are matched by the current queryset. This confirms that - any newly created or modified objects abide by the attributes granted by any applicable ObjectPermissions. - """ - if type(instance) is list: - # Check that all instances are still included in the view's queryset - conforming_count = self.queryset.filter(pk__in=[obj.pk for obj in instance]).count() - if conforming_count != len(instance): - raise ObjectDoesNotExist - else: - # Check that the instance is matched by the view's queryset - self.queryset.get(pk=instance.pk) - - def perform_create(self, serializer): - model = self.queryset.model - logger = logging.getLogger('netbox.api.views.ModelViewSet') - logger.info(f"Creating new {model._meta.verbose_name}") - - # Enforce object-level permissions on save() - try: - with transaction.atomic(): - instance = serializer.save() - self._validate_objects(instance) - except ObjectDoesNotExist: - raise PermissionDenied() - - def perform_update(self, serializer): - model = self.queryset.model - logger = logging.getLogger('netbox.api.views.ModelViewSet') - logger.info(f"Updating {model._meta.verbose_name} {serializer.instance} (PK: {serializer.instance.pk})") - - # Enforce object-level permissions on save() - try: - with transaction.atomic(): - instance = serializer.save() - self._validate_objects(instance) - except ObjectDoesNotExist: - raise PermissionDenied() - - def perform_destroy(self, instance): - model = self.queryset.model - logger = logging.getLogger('netbox.api.views.ModelViewSet') - logger.info(f"Deleting {model._meta.verbose_name} {instance} (PK: {instance.pk})") - - return super().perform_destroy(instance) - - -# -# Routers -# - -class OrderedDefaultRouter(DefaultRouter): - - def get_api_root_view(self, api_urls=None): - """ - Wrap DRF's DefaultRouter to return an alphabetized list of endpoints. - """ - api_root_dict = OrderedDict() - list_name = self.routes[0].name - for prefix, viewset, basename in sorted(self.registry, key=lambda x: x[0]): - api_root_dict[prefix] = list_name.format(basename=basename) - - return self.APIRootView.as_view(api_root_dict=api_root_dict) + return JsonResponse(data, status=status.HTTP_500_INTERNAL_SERVER_ERROR) diff --git a/netbox/utilities/custom_inspectors.py b/netbox/utilities/custom_inspectors.py index 38297838db..95c647fb85 100644 --- a/netbox/utilities/custom_inspectors.py +++ b/netbox/utilities/custom_inspectors.py @@ -5,13 +5,25 @@ from rest_framework.fields import ChoiceField from rest_framework.relations import ManyRelatedField -from extras.api.customfields import CustomFieldsSerializer -from utilities.api import ChoiceField, SerializedPKRelatedField, WritableNestedSerializer +from extras.api.customfields import CustomFieldsDataField +from netbox.api import ChoiceField, SerializedPKRelatedField, WritableNestedSerializer class NetBoxSwaggerAutoSchema(SwaggerAutoSchema): writable_serializers = {} + def get_operation_id(self, operation_keys=None): + operation_keys = operation_keys or self.operation_keys + operation_id = self.overrides.get('operation_id', '') + if not operation_id: + # Overwrite the action for bulk update/bulk delete views to ensure they get an operation ID that's + # unique from their single-object counterparts (see #3436) + if operation_keys[-1] in ('delete', 'partial_update', 'update') and not self.view.detail: + operation_keys[-1] = f'bulk_{operation_keys[-1]}' + operation_id = '_'.join(operation_keys) + + return operation_id + def get_request_serializer(self): serializer = super().get_request_serializer() @@ -49,7 +61,7 @@ def field_to_swagger_object(self, field, swagger_object_type, use_references, ** return NotHandled -class CustomChoiceFieldInspector(FieldInspector): +class ChoiceFieldInspector(FieldInspector): def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs): # this returns a callable which extracts title, description and other stuff # https://drf-yasg.readthedocs.io/en/stable/_modules/drf_yasg/inspectors/base.html#FieldInspector._get_partial_types @@ -62,8 +74,8 @@ def field_to_swagger_object(self, field, swagger_object_type, use_references, ** value_schema = openapi.Schema(type=openapi.TYPE_STRING, enum=choice_value) if set([None] + choice_value) == {None, True, False}: - # DeviceType.subdevice_role, Device.face and InterfaceConnection.connection_status all need to be - # differentiated since they each have subtly different values in their choice keys. + # DeviceType.subdevice_role and Device.face need to be differentiated since they each have + # subtly different values in their choice keys. # - subdevice_role and connection_status are booleans, although subdevice_role includes None # - face is an integer set {0, 1} which is easily confused with {False, True} schema_type = openapi.TYPE_STRING @@ -83,10 +95,6 @@ def field_to_swagger_object(self, field, swagger_object_type, use_references, ** return schema - elif isinstance(field, CustomFieldsSerializer): - schema = SwaggerType(type=openapi.TYPE_OBJECT) - return schema - return NotHandled @@ -102,6 +110,17 @@ def process_result(self, result, method_name, obj, **kwargs): return result +class CustomFieldsDataFieldInspector(FieldInspector): + + def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs): + SwaggerType, ChildSwaggerType = self._get_partial_types(field, swagger_object_type, use_references, **kwargs) + + if isinstance(field, CustomFieldsDataField) and swagger_object_type == openapi.Schema: + return SwaggerType(type=openapi.TYPE_OBJECT) + + return NotHandled + + class JSONFieldInspector(FieldInspector): """Required because by default, Swagger sees a JSONField as a string and not dict """ diff --git a/netbox/utilities/filters.py b/netbox/utilities/filters.py index 18eeab7d2a..6305c0bba9 100644 --- a/netbox/utilities/filters.py +++ b/netbox/utilities/filters.py @@ -1,4 +1,5 @@ import django_filters +from django_filters.constants import EMPTY_VALUES from copy import deepcopy from dcim.forms import MACAddressField from django import forms @@ -83,7 +84,6 @@ class NullableCharFieldFilter(django_filters.CharFilter): """ Allow matching on null field values by passing a special string used to signify NULL. """ - def filter(self, qs, value): if value != settings.FILTERS_NULL_CHOICE_VALUE: return super().filter(qs, value) @@ -106,6 +106,36 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) +class NumericArrayFilter(django_filters.NumberFilter): + """ + Filter based on the presence of an integer within an ArrayField. + """ + def filter(self, qs, value): + if value: + value = [value] + return super().filter(qs, value) + + +class ContentTypeFilter(django_filters.CharFilter): + """ + Allow specifying a ContentType by . (e.g. "dcim.site"). + """ + def filter(self, qs, value): + if value in EMPTY_VALUES: + return qs + + try: + app_label, model = value.lower().split('.') + except ValueError: + return qs.none() + return qs.filter( + **{ + f'{self.field_name}__app_label': app_label, + f'{self.field_name}__model': model + } + ) + + # # FilterSets # diff --git a/netbox/utilities/forms/fields.py b/netbox/utilities/forms/fields.py index 92e40e7bbb..a5b76fd8d2 100644 --- a/netbox/utilities/forms/fields.py +++ b/netbox/utilities/forms/fields.py @@ -6,12 +6,11 @@ import django_filters from django import forms from django.forms.fields import JSONField as _JSONField, InvalidJSONInput -from django.core.exceptions import MultipleObjectsReturned +from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist from django.db.models import Count from django.forms import BoundField from django.urls import reverse -from utilities.api import get_serializer_for_model from utilities.choices import unpack_grouped_choices from utilities.validators import EnhancedURLValidator from . import widgets @@ -21,6 +20,7 @@ __all__ = ( 'CommentField', 'CSVChoiceField', + 'CSVContentTypeField', 'CSVDataField', 'CSVModelChoiceField', 'DynamicModelChoiceField', @@ -117,18 +117,11 @@ class CSVChoiceField(forms.ChoiceField): """ Invert the provided set of choices to take the human-friendly label as input, and return the database value. """ - def __init__(self, choices, *args, **kwargs): - super().__init__(choices=choices, *args, **kwargs) - self.choices = [(label, label) for value, label in unpack_grouped_choices(choices)] - self.choice_values = {label: value for value, label in unpack_grouped_choices(choices)} + STATIC_CHOICES = True - def clean(self, value): - value = super().clean(value) - if not value: - return '' - if value not in self.choice_values: - raise forms.ValidationError("Invalid choice: {}".format(value)) - return self.choice_values[value] + def __init__(self, *, choices=(), **kwargs): + super().__init__(choices=choices, **kwargs) + self.choices = unpack_grouped_choices(choices) class CSVModelChoiceField(forms.ModelChoiceField): @@ -142,12 +135,32 @@ class CSVModelChoiceField(forms.ModelChoiceField): def to_python(self, value): try: return super().to_python(value) - except MultipleObjectsReturned as e: + except MultipleObjectsReturned: raise forms.ValidationError( f'"{value}" is not a unique value for this field; multiple objects were found' ) +class CSVContentTypeField(CSVModelChoiceField): + """ + Reference a ContentType in the form . + """ + STATIC_CHOICES = True + + def prepare_value(self, value): + return f'{value.app_label}.{value.model}' + + def to_python(self, value): + try: + app_label, model = value.split('.') + except ValueError: + raise forms.ValidationError(f'Object type must be specified as "."') + try: + return self.queryset.get(app_label=app_label, model=model) + except ObjectDoesNotExist: + raise forms.ValidationError(f'Invalid object type') + + class ExpandableNameField(forms.CharField): """ A field which allows for numeric range expansion @@ -200,7 +213,7 @@ class CommentField(forms.CharField): widget = forms.Textarea default_label = '' # TODO: Port Markdown cheat sheet to internal documentation - default_helptext = ' '\ + default_helptext = ' '\ ''\ 'Markdown syntax is supported' diff --git a/netbox/utilities/forms/forms.py b/netbox/utilities/forms/forms.py index bc68f29f69..f259f6b6d0 100644 --- a/netbox/utilities/forms/forms.py +++ b/netbox/utilities/forms/forms.py @@ -161,6 +161,7 @@ class TableConfigForm(BootstrapMixin, forms.Form): """ columns = forms.MultipleChoiceField( choices=[], + required=False, widget=forms.SelectMultiple( attrs={'size': 10} ), @@ -168,8 +169,14 @@ class TableConfigForm(BootstrapMixin, forms.Form): ) def __init__(self, table, *args, **kwargs): + self.table = table + super().__init__(*args, **kwargs) # Initialize columns field based on table attributes self.fields['columns'].choices = table.configurable_columns self.fields['columns'].initial = table.visible_columns + + @property + def table_name(self): + return self.table.__class__.__name__ diff --git a/netbox/utilities/tables.py b/netbox/utilities/tables.py index 5dddf24edd..bf087f2c9e 100644 --- a/netbox/utilities/tables.py +++ b/netbox/utilities/tables.py @@ -1,7 +1,9 @@ import django_tables2 as tables +from django.contrib.auth.models import AnonymousUser from django.contrib.contenttypes.fields import GenericForeignKey from django.core.exceptions import FieldDoesNotExist from django.db.models.fields.related import RelatedField +from django.urls import reverse from django.utils.safestring import mark_safe from django_tables2.data import TableQuerysetData @@ -10,18 +12,14 @@ class BaseTable(tables.Table): """ Default table for object lists - :param add_prefetch: By default, modify the queryset passed to the table upon initialization to automatically - prefetch related data. Set this to False if it's necessary to avoid modifying the queryset (e.g. to - accommodate PrefixQuerySet.annotate_depth()). + :param user: Personalize table display for the given user (optional). Has no effect if AnonymousUser is passed. """ - add_prefetch = True - class Meta: attrs = { 'class': 'table table-hover table-headings', } - def __init__(self, *args, columns=None, **kwargs): + def __init__(self, *args, user=None, **kwargs): super().__init__(*args, **kwargs) # Set default empty_text if none was provided @@ -35,39 +33,51 @@ def __init__(self, *args, columns=None, **kwargs): if column.name not in default_columns: self.columns.hide(column.name) - # Apply custom column ordering - if columns is not None: - pk = self.base_columns.pop('pk', None) - actions = self.base_columns.pop('actions', None) - - for name, column in self.base_columns.items(): - if name in columns: - self.columns.show(name) - else: - self.columns.hide(name) - self.sequence = [c for c in columns if c in self.base_columns] - - # Always include PK and actions column, if defined on the table - if pk: - self.base_columns['pk'] = pk - self.sequence.insert(0, 'pk') - if actions: - self.base_columns['actions'] = actions - self.sequence.append('actions') + # Apply custom column ordering for user + if user is not None and not isinstance(user, AnonymousUser): + columns = user.config.get(f"tables.{self.__class__.__name__}.columns") + if columns: + pk = self.base_columns.pop('pk', None) + actions = self.base_columns.pop('actions', None) + + for name, column in self.base_columns.items(): + if name in columns: + self.columns.show(name) + else: + self.columns.hide(name) + self.sequence = [c for c in columns if c in self.base_columns] + + # Always include PK and actions column, if defined on the table + if pk: + self.base_columns['pk'] = pk + self.sequence.insert(0, 'pk') + if actions: + self.base_columns['actions'] = actions + self.sequence.append('actions') # Dynamically update the table's QuerySet to ensure related fields are pre-fetched - if self.add_prefetch and isinstance(self.data, TableQuerysetData): - model = getattr(self.Meta, 'model') + if isinstance(self.data, TableQuerysetData): prefetch_fields = [] for column in self.columns: if column.visible: - field_path = column.accessor.split('.') - try: - model_field = model._meta.get_field(field_path[0]) - if isinstance(model_field, (RelatedField, GenericForeignKey)): - prefetch_fields.append('__'.join(field_path)) - except FieldDoesNotExist: - pass + model = getattr(self.Meta, 'model') + accessor = column.accessor + prefetch_path = [] + for field_name in accessor.split(accessor.SEPARATOR): + try: + field = model._meta.get_field(field_name) + except FieldDoesNotExist: + break + if isinstance(field, RelatedField): + # Follow ForeignKeys to the related model + prefetch_path.append(field_name) + model = field.remote_field.model + elif isinstance(field, GenericForeignKey): + # Can't prefetch beyond a GenericForeignKey + prefetch_path.append(field_name) + break + if prefetch_path: + prefetch_fields.append('__'.join(prefetch_path)) self.data.data = self.data.data.prefetch_related(None).prefetch_related(*prefetch_fields) @property @@ -116,11 +126,11 @@ class BooleanColumn(tables.Column): """ def render(self, value): if value: - rendered = '' + rendered = '' elif value is None: rendered = '' else: - rendered = '' + rendered = '' return mark_safe(rendered) @@ -138,17 +148,17 @@ class ButtonsColumn(tables.TemplateColumn): template_code = """ {{% if "changelog" in buttons %}} - + {{% endif %}} {{% if "edit" in buttons and perms.{app_label}.change_{model_name} %}} - + {{% endif %}} {{% if "delete" in buttons and perms.{app_label}.delete_{model_name} %}} - + {{% endif %}} """ @@ -178,13 +188,29 @@ def header(self): return '' +class ChoiceFieldColumn(tables.Column): + """ + Render a ChoiceField value inside a indicating a particular CSS class. This is useful for displaying colored + choices. The CSS class is derived by calling .get_FOO_class() on the row record. + """ + def render(self, record, bound_column, value): + if value: + name = bound_column.name + css_class = getattr(record, f'get_{name}_class')() + label = getattr(record, f'get_{name}_display')() + return mark_safe( + f'{label}' + ) + return self.default + + class ColorColumn(tables.Column): """ Display a color (#RRGGBB). """ def render(self, value): return mark_safe( - ' '.format(value) + f' ' ) @@ -201,6 +227,29 @@ def __init__(self, *args, **kwargs): super().__init__(template_code=self.template_code, *args, **kwargs) +class LinkedCountColumn(tables.Column): + """ + Render a count of related objects linked to a filtered URL. + + :param viewname: The view name to use for URL resolution + :param view_kwargs: Additional kwargs to pass for URL resolution (optional) + :param url_params: A dict of query parameters to append to the URL (e.g. ?foo=bar) (optional) + """ + def __init__(self, viewname, *args, view_kwargs=None, url_params=None, default=0, **kwargs): + self.viewname = viewname + self.view_kwargs = view_kwargs or {} + self.url_params = url_params + super().__init__(*args, default=default, **kwargs) + + def render(self, record, value): + if value: + url = reverse(self.viewname, kwargs=self.view_kwargs) + if self.url_params: + url += '?' + '&'.join([f'{k}={getattr(record, v)}' for k, v in self.url_params.items()]) + return mark_safe(f'{value}') + return value + + class TagColumn(tables.TemplateColumn): """ Display a list of tags assigned to the object. diff --git a/netbox/utilities/templates/buttons/add.html b/netbox/utilities/templates/buttons/add.html index 9ba2626a90..784bd05362 100644 --- a/netbox/utilities/templates/buttons/add.html +++ b/netbox/utilities/templates/buttons/add.html @@ -1,3 +1,3 @@ - Add + Add diff --git a/netbox/utilities/templates/buttons/clone.html b/netbox/utilities/templates/buttons/clone.html index b8f3638c40..b2d4c875a3 100644 --- a/netbox/utilities/templates/buttons/clone.html +++ b/netbox/utilities/templates/buttons/clone.html @@ -1,3 +1,3 @@ - Clone + Clone diff --git a/netbox/utilities/templates/buttons/delete.html b/netbox/utilities/templates/buttons/delete.html index 6d621701f4..95bf3cb617 100644 --- a/netbox/utilities/templates/buttons/delete.html +++ b/netbox/utilities/templates/buttons/delete.html @@ -1,3 +1,3 @@ - Delete + Delete diff --git a/netbox/utilities/templates/buttons/edit.html b/netbox/utilities/templates/buttons/edit.html index 14de5c86d8..7950d7ed59 100644 --- a/netbox/utilities/templates/buttons/edit.html +++ b/netbox/utilities/templates/buttons/edit.html @@ -1,3 +1,3 @@ - Edit + Edit diff --git a/netbox/utilities/templates/buttons/export.html b/netbox/utilities/templates/buttons/export.html index 15520c77b5..a6ec52d1ff 100644 --- a/netbox/utilities/templates/buttons/export.html +++ b/netbox/utilities/templates/buttons/export.html @@ -1,7 +1,7 @@ {% if export_templates %}
      {% else %} - Export + Export {% endif %} \ No newline at end of file diff --git a/netbox/utilities/templates/buttons/import.html b/netbox/utilities/templates/buttons/import.html index 67be778710..1a9ecdfce1 100644 --- a/netbox/utilities/templates/buttons/import.html +++ b/netbox/utilities/templates/buttons/import.html @@ -1,3 +1,3 @@ - Import + Import diff --git a/netbox/utilities/templates/widgets/sluginput.html b/netbox/utilities/templates/widgets/sluginput.html index 76de7f35aa..0bfe8b2018 100644 --- a/netbox/utilities/templates/widgets/sluginput.html +++ b/netbox/utilities/templates/widgets/sluginput.html @@ -2,7 +2,7 @@ {% include "django/forms/widgets/input.html" %} diff --git a/netbox/utilities/templatetags/helpers.py b/netbox/utilities/templatetags/helpers.py index 151ca99cb6..f095af58fc 100644 --- a/netbox/utilities/templatetags/helpers.py +++ b/netbox/utilities/templatetags/helpers.py @@ -10,6 +10,7 @@ from django.utils.safestring import mark_safe from markdown import markdown +from utilities.forms import TableConfigForm from utilities.utils import foreground_color register = template.Library() @@ -261,3 +262,11 @@ def badge(value, show_empty=False): 'value': value, 'show_empty': show_empty, } + + +@register.inclusion_tag('utilities/templatetags/table_config_form.html') +def table_config_form(table, table_name=None): + return { + 'table_name': table_name or table.__class__.__name__, + 'table_config_form': TableConfigForm(table=table), + } diff --git a/netbox/utilities/testing/api.py b/netbox/utilities/testing/api.py index 856af8ea1c..f81722fa85 100644 --- a/netbox/utilities/testing/api.py +++ b/netbox/utilities/testing/api.py @@ -93,6 +93,7 @@ def test_get_object(self): # Add object-level permission obj_perm = ObjectPermission( + name='Test permission', constraints={'pk': instance1.pk}, actions=['view'] ) @@ -160,6 +161,7 @@ def test_list_objects(self): # Add object-level permission obj_perm = ObjectPermission( + name='Test permission', constraints={'pk__in': [instance1.pk, instance2.pk]}, actions=['view'] ) @@ -193,6 +195,7 @@ def test_create_object(self): """ # Add object-level permission obj_perm = ObjectPermission( + name='Test permission', actions=['add'] ) obj_perm.save() @@ -216,6 +219,7 @@ def test_bulk_create_objects(self): """ # Add object-level permission obj_perm = ObjectPermission( + name='Test permission', actions=['add'] ) obj_perm.save() @@ -227,6 +231,10 @@ def test_bulk_create_objects(self): self.assertHttpStatus(response, status.HTTP_201_CREATED) self.assertEqual(len(response.data), len(self.create_data)) self.assertEqual(self._get_queryset().count(), initial_count + len(self.create_data)) + for i, obj in enumerate(response.data): + for field in self.create_data[i]: + if field not in self.validation_excluded_fields: + self.assertIn(field, obj, f"Bulk create field '{field}' missing from object {i} in response") for i, obj in enumerate(response.data): self.assertInstanceEqual( self._get_queryset().get(pk=obj['id']), @@ -237,6 +245,7 @@ def test_bulk_create_objects(self): class UpdateObjectViewTestCase(APITestCase): update_data = {} + bulk_update_data = None validation_excluded_fields = [] def test_update_object_without_permission(self): @@ -261,6 +270,7 @@ def test_update_object(self): # Add object-level permission obj_perm = ObjectPermission( + name='Test permission', actions=['change'] ) obj_perm.save() @@ -277,6 +287,36 @@ def test_update_object(self): api=True ) + def test_bulk_update_objects(self): + """ + PATCH a set of objects in a single request. + """ + if self.bulk_update_data is None: + self.skipTest("Bulk update data not set") + + # Add object-level permission + obj_perm = ObjectPermission( + name='Test permission', + actions=['change'] + ) + obj_perm.save() + obj_perm.users.add(self.user) + obj_perm.object_types.add(ContentType.objects.get_for_model(self.model)) + + id_list = self._get_queryset().values_list('id', flat=True)[:3] + self.assertEqual(len(id_list), 3, "Insufficient number of objects to test bulk update") + data = [ + {'id': id, **self.bulk_update_data} for id in id_list + ] + + response = self.client.patch(self._get_list_url(), data, format='json', **self.header) + self.assertHttpStatus(response, status.HTTP_200_OK) + for i, obj in enumerate(response.data): + for field in self.bulk_update_data: + self.assertIn(field, obj, f"Bulk update field '{field}' missing from object {i} in response") + for instance in self._get_queryset().filter(pk__in=id_list): + self.assertInstanceEqual(instance, self.bulk_update_data, api=True) + class DeleteObjectViewTestCase(APITestCase): def test_delete_object_without_permission(self): @@ -299,6 +339,7 @@ def test_delete_object(self): # Add object-level permission obj_perm = ObjectPermission( + name='Test permission', actions=['delete'] ) obj_perm.save() @@ -309,6 +350,30 @@ def test_delete_object(self): self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) self.assertFalse(self._get_queryset().filter(pk=instance.pk).exists()) + def test_bulk_delete_objects(self): + """ + DELETE a set of objects in a single request. + """ + # Add object-level permission + obj_perm = ObjectPermission( + name='Test permission', + actions=['delete'] + ) + obj_perm.save() + obj_perm.users.add(self.user) + obj_perm.object_types.add(ContentType.objects.get_for_model(self.model)) + + # Target the three most recently created objects to avoid triggering recursive deletions + # (e.g. with MPTT objects) + id_list = self._get_queryset().order_by('-id').values_list('id', flat=True)[:3] + self.assertEqual(len(id_list), 3, "Insufficient number of objects to test bulk deletion") + data = [{"id": id} for id in id_list] + + initial_count = self._get_queryset().count() + response = self.client.delete(self._get_list_url(), data, format='json', **self.header) + self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT) + self.assertEqual(self._get_queryset().count(), initial_count - 3) + class APIViewTestCase( GetObjectViewTestCase, ListObjectsViewTestCase, diff --git a/netbox/utilities/testing/views.py b/netbox/utilities/testing/views.py index d19848985a..d380996b7a 100644 --- a/netbox/utilities/testing/views.py +++ b/netbox/utilities/testing/views.py @@ -100,7 +100,7 @@ def add_permissions(self, *names): """ for name in names: ct, action = resolve_permission_ct(name) - obj_perm = ObjectPermission(actions=[action]) + obj_perm = ObjectPermission(name=name, actions=[action]) obj_perm.save() obj_perm.users.add(self.user) obj_perm.object_types.add(ct) @@ -245,6 +245,7 @@ def test_get_object_with_permission(self): # Add model-level permission obj_perm = ObjectPermission( + name='Test permission', actions=['view'] ) obj_perm.save() @@ -260,6 +261,7 @@ def test_get_object_with_constrained_permission(self): # Add object-level permission obj_perm = ObjectPermission( + name='Test permission', constraints={'pk': instance1.pk}, actions=['view'] ) @@ -312,6 +314,7 @@ def test_create_object_with_permission(self): # Assign unconstrained permission obj_perm = ObjectPermission( + name='Test permission', actions=['add'] ) obj_perm.save() @@ -336,6 +339,7 @@ def test_create_object_with_constrained_permission(self): # Assign constrained permission obj_perm = ObjectPermission( + name='Test permission', constraints={'pk': 0}, # Dummy permission to deny all actions=['add'] ) @@ -396,6 +400,7 @@ def test_edit_object_with_permission(self): # Assign model-level permission obj_perm = ObjectPermission( + name='Test permission', actions=['change'] ) obj_perm.save() @@ -419,6 +424,7 @@ def test_edit_object_with_constrained_permission(self): # Assign constrained permission obj_perm = ObjectPermission( + name='Test permission', constraints={'pk': instance1.pk}, actions=['change'] ) @@ -472,6 +478,7 @@ def test_delete_object_with_permission(self): # Assign model-level permission obj_perm = ObjectPermission( + name='Test permission', actions=['delete'] ) obj_perm.save() @@ -496,6 +503,7 @@ def test_delete_object_with_constrained_permission(self): # Assign object-level permission obj_perm = ObjectPermission( + name='Test permission', constraints={'pk': instance1.pk}, actions=['delete'] ) @@ -549,6 +557,7 @@ def test_list_objects_with_permission(self): # Add model-level permission obj_perm = ObjectPermission( + name='Test permission', actions=['view'] ) obj_perm.save() @@ -570,6 +579,7 @@ def test_list_objects_with_constrained_permission(self): # Add object-level permission obj_perm = ObjectPermission( + name='Test permission', constraints={'pk': instance1.pk}, actions=['view'] ) @@ -619,6 +629,7 @@ def test_create_multiple_objects_with_permission(self): # Assign non-constrained permission obj_perm = ObjectPermission( + name='Test permission', actions=['add'], ) obj_perm.save() @@ -642,6 +653,7 @@ def test_create_multiple_objects_with_constrained_permission(self): # Assign constrained permission obj_perm = ObjectPermission( + name='Test permission', actions=['add'], constraints={'pk': 0} # Dummy constraint to deny all ) @@ -697,6 +709,7 @@ def test_bulk_import_objects_with_permission(self): # Assign model-level permission obj_perm = ObjectPermission( + name='Test permission', actions=['add'] ) obj_perm.save() @@ -719,6 +732,7 @@ def test_bulk_import_objects_with_constrained_permission(self): # Assign constrained permission obj_perm = ObjectPermission( + name='Test permission', constraints={'pk': 0}, # Dummy permission to deny all actions=['add'] ) @@ -775,6 +789,7 @@ def test_bulk_edit_objects_with_permission(self): # Assign model-level permission obj_perm = ObjectPermission( + name='Test permission', actions=['change'] ) obj_perm.save() @@ -804,6 +819,7 @@ def test_bulk_edit_objects_with_constrained_permission(self): # Assign constrained permission obj_perm = ObjectPermission( + name='Test permission', constraints={attr_name: value}, actions=['change'] ) @@ -856,6 +872,7 @@ def test_bulk_delete_objects_with_permission(self): # Assign unconstrained permission obj_perm = ObjectPermission( + name='Test permission', actions=['delete'] ) obj_perm.save() @@ -878,6 +895,7 @@ def test_bulk_delete_objects_with_constrained_permission(self): # Assign constrained permission obj_perm = ObjectPermission( + name='Test permission', constraints={'pk': 0}, # Dummy permission to deny all actions=['delete'] ) @@ -935,6 +953,7 @@ def test_bulk_rename_objects_with_permission(self): # Assign model-level permission obj_perm = ObjectPermission( + name='Test permission', actions=['change'] ) obj_perm.save() @@ -958,6 +977,7 @@ def test_bulk_rename_objects_with_constrained_permission(self): # Assign constrained permission obj_perm = ObjectPermission( + name='Test permission', constraints={'name__regex': '[^X]$'}, actions=['change'] ) diff --git a/netbox/utilities/tests/test_api.py b/netbox/utilities/tests/test_api.py index 01d4ab8f3d..2cc9accaa5 100644 --- a/netbox/utilities/tests/test_api.py +++ b/netbox/utilities/tests/test_api.py @@ -131,7 +131,7 @@ def setUp(self): content_type = ContentType.objects.get_for_model(Site) self.cf_text = CustomField(type=CustomFieldTypeChoices.TYPE_TEXT, name='test') self.cf_text.save() - self.cf_text.obj_type.set([content_type]) + self.cf_text.content_types.set([content_type]) self.cf_text.save() def test_api_docs(self): diff --git a/netbox/utilities/utils.py b/netbox/utilities/utils.py index 81baadb7af..52a9515551 100644 --- a/netbox/utilities/utils.py +++ b/netbox/utilities/utils.py @@ -1,6 +1,7 @@ import datetime import json from collections import OrderedDict +from itertools import count, groupby from django.core.serializers import serialize from django.db.models import Count, OuterRef, Subquery @@ -91,11 +92,9 @@ def serialize_object(obj, extra=None, exclude=None): json_str = serialize('json', [obj]) data = json.loads(json_str)[0]['fields'] - # Include any custom fields - if hasattr(obj, 'get_custom_fields'): - data['custom_fields'] = { - field: str(value) for field, value in obj.cf.items() - } + # Include custom_field_data as "custom_fields" + if hasattr(obj, 'custom_field_data'): + data['custom_fields'] = data.pop('custom_field_data') # Include any tags. Check for tags cached on the instance; fall back to using the manager. if is_taggable(obj): @@ -284,6 +283,16 @@ def _curried(*moreargs, **morekwargs): return _curried +def array_to_string(array): + """ + Generate an efficient, human-friendly string from a set of integers. Intended for use with ArrayField. + For example: + [0, 1, 2, 10, 14, 15, 16] => "0-2, 10, 14-16" + """ + group = (list(x) for _, x in groupby(sorted(array), lambda x, c=count(): next(c) - x)) + return ', '.join('-'.join(map(str, (g[0], g[-1])[:len(g)])) for g in group) + + # # Fake request object # diff --git a/netbox/utilities/validators.py b/netbox/utilities/validators.py index 517a567a93..b087b08671 100644 --- a/netbox/utilities/validators.py +++ b/netbox/utilities/validators.py @@ -1,6 +1,7 @@ import re from django.conf import settings +from django.core.exceptions import ValidationError from django.core.validators import _lazy_re_compile, BaseValidator, URLValidator @@ -29,3 +30,14 @@ class ExclusionValidator(BaseValidator): def compare(self, a, b): return a in b + + +def validate_regex(value): + """ + Checks that the value is a valid regular expression. (Don't confuse this with RegexValidator, which *uses* a regex + to validate a value.) + """ + try: + re.compile(value) + except re.error: + raise ValidationError(f"{value} is not a valid regular expression.") diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index df89827558..c291a3cf23 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -1,47 +1,14 @@ -import logging -import platform -import re -import sys -from copy import deepcopy - -from django.conf import settings -from django.contrib import messages -from django.contrib.auth.decorators import login_required -from django.contrib.contenttypes.models import ContentType from django.contrib.auth.mixins import AccessMixin -from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured, ObjectDoesNotExist, ValidationError -from django.db import transaction, IntegrityError -from django.db.models import ManyToManyField, ProtectedError -from django.forms import Form, ModelMultipleChoiceField, MultipleHiddenInput, Textarea -from django.http import HttpResponse, HttpResponseServerError, JsonResponse -from django.shortcuts import get_object_or_404, redirect, render -from django.template import loader -from django.template.exceptions import TemplateDoesNotExist +from django.core.exceptions import ImproperlyConfigured from django.urls import reverse from django.urls.exceptions import NoReverseMatch -from django.utils.decorators import method_decorator -from django.utils.html import escape from django.utils.http import is_safe_url -from django.utils.safestring import mark_safe -from django.views.decorators.csrf import requires_csrf_token -from django.views.defaults import ERROR_500_TEMPLATE_NAME -from django.views.generic import View -from django_tables2 import RequestConfig -from rest_framework import status -from extras.models import CustomField, CustomFieldValue, ExportTemplate -from extras.querysets import CustomFieldQueryset -from utilities.exceptions import AbortTransaction -from utilities.forms import BootstrapMixin, BulkRenameForm, CSVDataField, TableConfigForm, restrict_form_fields -from utilities.permissions import get_permission_for_model, resolve_permission -from utilities.utils import csv_format, normalize_querydict, prepare_cloned_fields -from .error_handlers import handle_protectederror -from .forms import ConfirmationForm, ImportForm -from .paginator import EnhancedPaginator, get_paginate_count +from .permissions import resolve_permission # -# Mixins +# View Mixins # class ContentTypePermissionRequiredMixin(AccessMixin): @@ -156,1290 +123,3 @@ def get_return_url(self, request, obj=None): # If all else fails, return home. Ideally this should never happen. return reverse('home') - - -# -# Generic views -# - -class ObjectView(ObjectPermissionRequiredMixin, View): - """ - Retrieve a single object for display. - - queryset: The base queryset for retrieving the object. - """ - queryset = None - - def get_required_permission(self): - return get_permission_for_model(self.queryset.model, 'view') - - def get_template_name(self): - """ - Return self.template_name if set. Otherwise, resolve the template path by model app_label and name. - """ - if hasattr(self, 'template_name'): - return self.template_name - model_opts = self.queryset.model._meta - return f'{model_opts.app_label}/{model_opts.model_name}.html' - - def get(self, request, pk): - """ - Generic GET handler for accessing an object by PK - """ - instance = get_object_or_404(self.queryset, pk=pk) - - return render(request, self.get_template_name(), { - 'instance': instance, - }) - - -class ObjectListView(ObjectPermissionRequiredMixin, View): - """ - List a series of objects. - - queryset: The queryset of objects to display - filter: A django-filter FilterSet that is applied to the queryset - filter_form: The form used to render filter options - table: The django-tables2 Table used to render the objects list - template_name: The name of the template - """ - queryset = None - filterset = None - filterset_form = None - table = None - template_name = 'utilities/obj_list.html' - action_buttons = ('add', 'import', 'export') - - def get_required_permission(self): - return get_permission_for_model(self.queryset.model, 'view') - - def queryset_to_yaml(self): - """ - Export the queryset of objects as concatenated YAML documents. - """ - yaml_data = [obj.to_yaml() for obj in self.queryset] - - return '---\n'.join(yaml_data) - - def queryset_to_csv(self): - """ - Export the queryset of objects as comma-separated value (CSV), using the model's to_csv() method. - """ - csv_data = [] - custom_fields = [] - - # Start with the column headers - headers = self.queryset.model.csv_headers.copy() - - # Add custom field headers, if any - if hasattr(self.queryset.model, 'get_custom_fields'): - for custom_field in self.queryset.model().get_custom_fields(): - headers.append(custom_field.name) - custom_fields.append(custom_field.name) - - csv_data.append(','.join(headers)) - - # Iterate through the queryset appending each object - for obj in self.queryset: - data = obj.to_csv() - - for custom_field in custom_fields: - data += (obj.cf.get(custom_field, ''),) - - csv_data.append(csv_format(data)) - - return '\n'.join(csv_data) - - def get(self, request): - - model = self.queryset.model - content_type = ContentType.objects.get_for_model(model) - - if self.filterset: - self.queryset = self.filterset(request.GET, self.queryset).qs - - # If this type of object has one or more custom fields, prefetch any relevant custom field values - custom_fields = CustomField.objects.filter( - obj_type=ContentType.objects.get_for_model(model) - ).prefetch_related('choices') - if custom_fields: - self.queryset = self.queryset.prefetch_related('custom_field_values') - - # Check for export template rendering - if request.GET.get('export'): - et = get_object_or_404(ExportTemplate, content_type=content_type, name=request.GET.get('export')) - queryset = CustomFieldQueryset(self.queryset, custom_fields) if custom_fields else self.queryset - try: - return et.render_to_response(queryset) - except Exception as e: - messages.error( - request, - "There was an error rendering the selected export template ({}): {}".format( - et.name, e - ) - ) - - # Check for YAML export support - elif 'export' in request.GET and hasattr(model, 'to_yaml'): - response = HttpResponse(self.queryset_to_yaml(), content_type='text/yaml') - filename = 'netbox_{}.yaml'.format(self.queryset.model._meta.verbose_name_plural) - response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename) - return response - - # Fall back to built-in CSV formatting if export requested but no template specified - elif 'export' in request.GET and hasattr(model, 'to_csv'): - response = HttpResponse(self.queryset_to_csv(), content_type='text/csv') - filename = 'netbox_{}.csv'.format(self.queryset.model._meta.verbose_name_plural) - response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename) - return response - - # Provide a hook to tweak the queryset based on the request immediately prior to rendering the object list - self.queryset = self.alter_queryset(request) - - # Compile a dictionary indicating which permissions are available to the current user for this model - permissions = {} - for action in ('add', 'change', 'delete', 'view'): - perm_name = get_permission_for_model(model, action) - permissions[action] = request.user.has_perm(perm_name) - - # Construct the table based on the user's permissions - if request.user.is_authenticated: - columns = request.user.config.get(f"tables.{self.table.__name__}.columns") - else: - columns = None - table = self.table(self.queryset, columns=columns) - if 'pk' in table.base_columns and (permissions['change'] or permissions['delete']): - table.columns.show('pk') - - # Apply the request context - paginate = { - 'paginator_class': EnhancedPaginator, - 'per_page': get_paginate_count(request) - } - RequestConfig(request, paginate).configure(table) - - context = { - 'content_type': content_type, - 'table': table, - 'permissions': permissions, - 'action_buttons': self.action_buttons, - 'table_config_form': TableConfigForm(table=table), - 'filter_form': self.filterset_form(request.GET, label_suffix='') if self.filterset_form else None, - } - context.update(self.extra_context()) - - return render(request, self.template_name, context) - - @method_decorator(login_required) - def post(self, request): - - # Update the user's table configuration - table = self.table(self.queryset) - form = TableConfigForm(table=table, data=request.POST) - preference_name = f"tables.{self.table.__name__}.columns" - - if form.is_valid(): - if 'set' in request.POST: - request.user.config.set(preference_name, form.cleaned_data['columns'], commit=True) - elif 'clear' in request.POST: - request.user.config.clear(preference_name, commit=True) - messages.success(request, "Your preferences have been updated.") - - return redirect(request.get_full_path()) - - def alter_queryset(self, request): - # .all() is necessary to avoid caching queries - return self.queryset.all() - - def extra_context(self): - return {} - - -class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): - """ - Create or edit a single object. - - queryset: The base queryset for the object being modified - model_form: The form used to create or edit the object - template_name: The name of the template - """ - queryset = None - model_form = None - template_name = 'utilities/obj_edit.html' - - def get_required_permission(self): - # self._permission_action is set by dispatch() to either "add" or "change" depending on whether - # we are modifying an existing object or creating a new one. - return get_permission_for_model(self.queryset.model, self._permission_action) - - def get_object(self, kwargs): - # Look up an existing object by slug or PK, if provided. - if 'slug' in kwargs: - return get_object_or_404(self.queryset, slug=kwargs['slug']) - elif 'pk' in kwargs: - return get_object_or_404(self.queryset, pk=kwargs['pk']) - # Otherwise, return a new instance. - return self.queryset.model() - - def alter_obj(self, obj, request, url_args, url_kwargs): - # Allow views to add extra info to an object before it is processed. For example, a parent object can be defined - # given some parameter from the request URL. - return obj - - def dispatch(self, request, *args, **kwargs): - # Determine required permission based on whether we are editing an existing object - self._permission_action = 'change' if kwargs else 'add' - - return super().dispatch(request, *args, **kwargs) - - def get(self, request, *args, **kwargs): - obj = self.alter_obj(self.get_object(kwargs), request, args, kwargs) - - initial_data = normalize_querydict(request.GET) - form = self.model_form(instance=obj, initial=initial_data) - restrict_form_fields(form, request.user) - - return render(request, self.template_name, { - 'obj': obj, - 'obj_type': self.queryset.model._meta.verbose_name, - 'form': form, - 'return_url': self.get_return_url(request, obj), - }) - - def post(self, request, *args, **kwargs): - logger = logging.getLogger('netbox.views.ObjectEditView') - obj = self.alter_obj(self.get_object(kwargs), request, args, kwargs) - form = self.model_form( - data=request.POST, - files=request.FILES, - instance=obj - ) - restrict_form_fields(form, request.user) - - if form.is_valid(): - logger.debug("Form validation was successful") - - try: - with transaction.atomic(): - object_created = form.instance.pk is None - obj = form.save() - - # Check that the new object conforms with any assigned object-level permissions - self.queryset.get(pk=obj.pk) - - msg = '{} {}'.format( - 'Created' if object_created else 'Modified', - self.queryset.model._meta.verbose_name - ) - logger.info(f"{msg} {obj} (PK: {obj.pk})") - if hasattr(obj, 'get_absolute_url'): - msg = '{} {}'.format(msg, obj.get_absolute_url(), escape(obj)) - else: - msg = '{} {}'.format(msg, escape(obj)) - messages.success(request, mark_safe(msg)) - - if '_addanother' in request.POST: - - # If the object has clone_fields, pre-populate a new instance of the form - if hasattr(obj, 'clone_fields'): - url = '{}?{}'.format(request.path, prepare_cloned_fields(obj)) - return redirect(url) - - return redirect(request.get_full_path()) - - return_url = form.cleaned_data.get('return_url') - if return_url is not None and is_safe_url(url=return_url, allowed_hosts=request.get_host()): - return redirect(return_url) - else: - return redirect(self.get_return_url(request, obj)) - - except ObjectDoesNotExist: - msg = "Object save failed due to object-level permissions violation" - logger.debug(msg) - form.add_error(None, msg) - - else: - logger.debug("Form validation failed") - - return render(request, self.template_name, { - 'obj': obj, - 'obj_type': self.queryset.model._meta.verbose_name, - 'form': form, - 'return_url': self.get_return_url(request, obj), - }) - - -class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): - """ - Delete a single object. - - queryset: The base queryset for the object being deleted - template_name: The name of the template - """ - queryset = None - template_name = 'utilities/obj_delete.html' - - def get_required_permission(self): - return get_permission_for_model(self.queryset.model, 'delete') - - def get_object(self, kwargs): - # Look up object by slug if one has been provided. Otherwise, use PK. - if 'slug' in kwargs: - return get_object_or_404(self.queryset, slug=kwargs['slug']) - else: - return get_object_or_404(self.queryset, pk=kwargs['pk']) - - def get(self, request, **kwargs): - obj = self.get_object(kwargs) - form = ConfirmationForm(initial=request.GET) - - return render(request, self.template_name, { - 'obj': obj, - 'form': form, - 'obj_type': self.queryset.model._meta.verbose_name, - 'return_url': self.get_return_url(request, obj), - }) - - def post(self, request, **kwargs): - logger = logging.getLogger('netbox.views.ObjectDeleteView') - obj = self.get_object(kwargs) - form = ConfirmationForm(request.POST) - - if form.is_valid(): - logger.debug("Form validation was successful") - - try: - obj.delete() - except ProtectedError as e: - logger.info("Caught ProtectedError while attempting to delete object") - handle_protectederror([obj], request, e) - return redirect(obj.get_absolute_url()) - - msg = 'Deleted {} {}'.format(self.queryset.model._meta.verbose_name, obj) - logger.info(msg) - messages.success(request, msg) - - return_url = form.cleaned_data.get('return_url') - if return_url is not None and is_safe_url(url=return_url, allowed_hosts=request.get_host()): - return redirect(return_url) - else: - return redirect(self.get_return_url(request, obj)) - - else: - logger.debug("Form validation failed") - - return render(request, self.template_name, { - 'obj': obj, - 'form': form, - 'obj_type': self.queryset.model._meta.verbose_name, - 'return_url': self.get_return_url(request, obj), - }) - - -class BulkCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): - """ - Create new objects in bulk. - - queryset: Base queryset for the objects being created - form: Form class which provides the `pattern` field - model_form: The ModelForm used to create individual objects - pattern_target: Name of the field to be evaluated as a pattern (if any) - template_name: The name of the template - """ - queryset = None - form = None - model_form = None - pattern_target = '' - template_name = None - - def get_required_permission(self): - return get_permission_for_model(self.queryset.model, 'add') - - def get(self, request): - # Set initial values for visible form fields from query args - initial = {} - for field in getattr(self.model_form._meta, 'fields', []): - if request.GET.get(field): - initial[field] = request.GET[field] - - form = self.form() - model_form = self.model_form(initial=initial) - - return render(request, self.template_name, { - 'obj_type': self.model_form._meta.model._meta.verbose_name, - 'form': form, - 'model_form': model_form, - 'return_url': self.get_return_url(request), - }) - - def post(self, request): - logger = logging.getLogger('netbox.views.BulkCreateView') - model = self.queryset.model - form = self.form(request.POST) - model_form = self.model_form(request.POST) - - if form.is_valid(): - logger.debug("Form validation was successful") - pattern = form.cleaned_data['pattern'] - new_objs = [] - - try: - with transaction.atomic(): - - # Create objects from the expanded. Abort the transaction on the first validation error. - for value in pattern: - - # Reinstantiate the model form each time to avoid overwriting the same instance. Use a mutable - # copy of the POST QueryDict so that we can update the target field value. - model_form = self.model_form(request.POST.copy()) - model_form.data[self.pattern_target] = value - - # Validate each new object independently. - if model_form.is_valid(): - obj = model_form.save() - logger.debug(f"Created {obj} (PK: {obj.pk})") - new_objs.append(obj) - else: - # Copy any errors on the pattern target field to the pattern form. - errors = model_form.errors.as_data() - if errors.get(self.pattern_target): - form.add_error('pattern', errors[self.pattern_target]) - # Raise an IntegrityError to break the for loop and abort the transaction. - raise IntegrityError() - - # Enforce object-level permissions - if self.queryset.filter(pk__in=[obj.pk for obj in new_objs]).count() != len(new_objs): - raise ObjectDoesNotExist - - # If we make it to this point, validation has succeeded on all new objects. - msg = "Added {} {}".format(len(new_objs), model._meta.verbose_name_plural) - logger.info(msg) - messages.success(request, msg) - - if '_addanother' in request.POST: - return redirect(request.path) - return redirect(self.get_return_url(request)) - - except IntegrityError: - pass - - except ObjectDoesNotExist: - msg = "Object creation failed due to object-level permissions violation" - logger.debug(msg) - form.add_error(None, msg) - - else: - logger.debug("Form validation failed") - - return render(request, self.template_name, { - 'form': form, - 'model_form': model_form, - 'obj_type': model._meta.verbose_name, - 'return_url': self.get_return_url(request), - }) - - -class ObjectImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): - """ - Import a single object (YAML or JSON format). - - queryset: Base queryset for the objects being created - model_form: The ModelForm used to create individual objects - related_object_forms: A dictionary mapping of forms to be used for the creation of related (child) objects - template_name: The name of the template - """ - queryset = None - model_form = None - related_object_forms = dict() - template_name = 'utilities/obj_import.html' - - def get_required_permission(self): - return get_permission_for_model(self.queryset.model, 'add') - - def get(self, request): - form = ImportForm() - - return render(request, self.template_name, { - 'form': form, - 'obj_type': self.queryset.model._meta.verbose_name, - 'return_url': self.get_return_url(request), - }) - - def post(self, request): - logger = logging.getLogger('netbox.views.ObjectImportView') - form = ImportForm(request.POST) - - if form.is_valid(): - logger.debug("Import form validation was successful") - - # Initialize model form - data = form.cleaned_data['data'] - model_form = self.model_form(data) - restrict_form_fields(model_form, request.user) - - # Assign default values for any fields which were not specified. We have to do this manually because passing - # 'initial=' to the form on initialization merely sets default values for the widgets. Since widgets are not - # used for YAML/JSON import, we first bind the imported data normally, then update the form's data with the - # applicable field defaults as needed prior to form validation. - for field_name, field in model_form.fields.items(): - if field_name not in data and hasattr(field, 'initial'): - model_form.data[field_name] = field.initial - - if model_form.is_valid(): - - try: - with transaction.atomic(): - - # Save the primary object - obj = model_form.save() - - # Enforce object-level permissions - self.queryset.get(pk=obj.pk) - - logger.debug(f"Created {obj} (PK: {obj.pk})") - - # Iterate through the related object forms (if any), validating and saving each instance. - for field_name, related_object_form in self.related_object_forms.items(): - logger.debug("Processing form for related objects: {related_object_form}") - - related_obj_pks = [] - for i, rel_obj_data in enumerate(data.get(field_name, list())): - - f = related_object_form(obj, rel_obj_data) - - for subfield_name, field in f.fields.items(): - if subfield_name not in rel_obj_data and hasattr(field, 'initial'): - f.data[subfield_name] = field.initial - - if f.is_valid(): - related_obj = f.save() - related_obj_pks.append(related_obj.pk) - else: - # Replicate errors on the related object form to the primary form for display - for subfield_name, errors in f.errors.items(): - for err in errors: - err_msg = "{}[{}] {}: {}".format(field_name, i, subfield_name, err) - model_form.add_error(None, err_msg) - raise AbortTransaction() - - # Enforce object-level permissions on related objects - model = related_object_form.Meta.model - if model.objects.filter(pk__in=related_obj_pks).count() != len(related_obj_pks): - raise ObjectDoesNotExist - - except AbortTransaction: - pass - - except ObjectDoesNotExist: - msg = "Object creation failed due to object-level permissions violation" - logger.debug(msg) - form.add_error(None, msg) - - if not model_form.errors: - logger.info(f"Import object {obj} (PK: {obj.pk})") - messages.success(request, mark_safe('Imported object: {}'.format( - obj.get_absolute_url(), obj - ))) - - if '_addanother' in request.POST: - return redirect(request.get_full_path()) - - return_url = form.cleaned_data.get('return_url') - if return_url is not None and is_safe_url(url=return_url, allowed_hosts=request.get_host()): - return redirect(return_url) - else: - return redirect(self.get_return_url(request, obj)) - - else: - logger.debug("Model form validation failed") - - # Replicate model form errors for display - for field, errors in model_form.errors.items(): - for err in errors: - if field == '__all__': - form.add_error(None, err) - else: - form.add_error(None, "{}: {}".format(field, err)) - - else: - logger.debug("Import form validation failed") - - return render(request, self.template_name, { - 'form': form, - 'obj_type': self.queryset.model._meta.verbose_name, - 'return_url': self.get_return_url(request), - }) - - -class BulkImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): - """ - Import objects in bulk (CSV format). - - queryset: Base queryset for the model - model_form: The form used to create each imported object - table: The django-tables2 Table used to render the list of imported objects - template_name: The name of the template - widget_attrs: A dict of attributes to apply to the import widget (e.g. to require a session key) - """ - queryset = None - model_form = None - table = None - template_name = 'utilities/obj_bulk_import.html' - widget_attrs = {} - - def _import_form(self, *args, **kwargs): - - class ImportForm(BootstrapMixin, Form): - csv = CSVDataField( - from_form=self.model_form, - widget=Textarea(attrs=self.widget_attrs) - ) - - return ImportForm(*args, **kwargs) - - def _save_obj(self, obj_form, request): - """ - Provide a hook to modify the object immediately before saving it (e.g. to encrypt secret data). - """ - return obj_form.save() - - def get_required_permission(self): - return get_permission_for_model(self.queryset.model, 'add') - - def get(self, request): - - return render(request, self.template_name, { - 'form': self._import_form(), - 'fields': self.model_form().fields, - 'obj_type': self.model_form._meta.model._meta.verbose_name, - 'return_url': self.get_return_url(request), - }) - - def post(self, request): - logger = logging.getLogger('netbox.views.BulkImportView') - new_objs = [] - form = self._import_form(request.POST) - - if form.is_valid(): - logger.debug("Form validation was successful") - - try: - # Iterate through CSV data and bind each row to a new model form instance. - with transaction.atomic(): - headers, records = form.cleaned_data['csv'] - for row, data in enumerate(records, start=1): - obj_form = self.model_form(data, headers=headers) - restrict_form_fields(obj_form, request.user) - - if obj_form.is_valid(): - obj = self._save_obj(obj_form, request) - new_objs.append(obj) - else: - for field, err in obj_form.errors.items(): - form.add_error('csv', "Row {} {}: {}".format(row, field, err[0])) - raise ValidationError("") - - # Enforce object-level permissions - if self.queryset.filter(pk__in=[obj.pk for obj in new_objs]).count() != len(new_objs): - raise ObjectDoesNotExist - - # Compile a table containing the imported objects - obj_table = self.table(new_objs) - - if new_objs: - msg = 'Imported {} {}'.format(len(new_objs), new_objs[0]._meta.verbose_name_plural) - logger.info(msg) - messages.success(request, msg) - - return render(request, "import_success.html", { - 'table': obj_table, - 'return_url': self.get_return_url(request), - }) - - except ValidationError: - pass - - except ObjectDoesNotExist: - msg = "Object import failed due to object-level permissions violation" - logger.debug(msg) - form.add_error(None, msg) - - else: - logger.debug("Form validation failed") - - return render(request, self.template_name, { - 'form': form, - 'fields': self.model_form().fields, - 'obj_type': self.model_form._meta.model._meta.verbose_name, - 'return_url': self.get_return_url(request), - }) - - -class BulkEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): - """ - Edit objects in bulk. - - queryset: Custom queryset to use when retrieving objects (e.g. to select related objects) - filter: FilterSet to apply when deleting by QuerySet - table: The table used to display devices being edited - form: The form class used to edit objects in bulk - template_name: The name of the template - """ - queryset = None - filterset = None - table = None - form = None - template_name = 'utilities/obj_bulk_edit.html' - - def get_required_permission(self): - return get_permission_for_model(self.queryset.model, 'change') - - def get(self, request): - return redirect(self.get_return_url(request)) - - def post(self, request, **kwargs): - logger = logging.getLogger('netbox.views.BulkEditView') - model = self.queryset.model - - # If we are editing *all* objects in the queryset, replace the PK list with all matched objects. - if request.POST.get('_all') and self.filterset is not None: - pk_list = [ - obj.pk for obj in self.filterset(request.GET, self.queryset.only('pk')).qs - ] - else: - pk_list = request.POST.getlist('pk') - - if '_apply' in request.POST: - form = self.form(model, request.POST) - restrict_form_fields(form, request.user) - - if form.is_valid(): - logger.debug("Form validation was successful") - custom_fields = form.custom_fields if hasattr(form, 'custom_fields') else [] - standard_fields = [ - field for field in form.fields if field not in custom_fields + ['pk'] - ] - nullified_fields = request.POST.getlist('_nullify') - - try: - - with transaction.atomic(): - - updated_objects = [] - for obj in self.queryset.filter(pk__in=form.cleaned_data['pk']): - - # Update standard fields. If a field is listed in _nullify, delete its value. - for name in standard_fields: - - try: - model_field = model._meta.get_field(name) - except FieldDoesNotExist: - # This form field is used to modify a field rather than set its value directly - model_field = None - - # Handle nullification - if name in form.nullable_fields and name in nullified_fields: - if isinstance(model_field, ManyToManyField): - getattr(obj, name).set([]) - else: - setattr(obj, name, None if model_field.null else '') - - # ManyToManyFields - elif isinstance(model_field, ManyToManyField): - if form.cleaned_data[name]: - getattr(obj, name).set(form.cleaned_data[name]) - # Normal fields - elif form.cleaned_data[name] not in (None, ''): - setattr(obj, name, form.cleaned_data[name]) - - # Cache custom fields on instance prior to save() - if custom_fields: - obj._cf = { - name: form.cleaned_data[name] for name in custom_fields - } - - obj.full_clean() - obj.save() - updated_objects.append(obj) - logger.debug(f"Saved {obj} (PK: {obj.pk})") - - # Update custom fields - obj_type = ContentType.objects.get_for_model(model) - for name in custom_fields: - field = form.fields[name].model - if name in form.nullable_fields and name in nullified_fields: - CustomFieldValue.objects.filter( - field=field, obj_type=obj_type, obj_id=obj.pk - ).delete() - elif form.cleaned_data[name] not in [None, '']: - try: - cfv = CustomFieldValue.objects.get( - field=field, obj_type=obj_type, obj_id=obj.pk - ) - except CustomFieldValue.DoesNotExist: - cfv = CustomFieldValue( - field=field, obj_type=obj_type, obj_id=obj.pk - ) - cfv.value = form.cleaned_data[name] - cfv.save() - logger.debug(f"Saved custom fields for {obj} (PK: {obj.pk})") - - # Add/remove tags - if form.cleaned_data.get('add_tags', None): - obj.tags.add(*form.cleaned_data['add_tags']) - if form.cleaned_data.get('remove_tags', None): - obj.tags.remove(*form.cleaned_data['remove_tags']) - - # Enforce object-level permissions - if self.queryset.filter(pk__in=[obj.pk for obj in updated_objects]).count() != len(updated_objects): - raise ObjectDoesNotExist - - if updated_objects: - msg = 'Updated {} {}'.format(len(updated_objects), model._meta.verbose_name_plural) - logger.info(msg) - messages.success(self.request, msg) - - return redirect(self.get_return_url(request)) - - except ValidationError as e: - messages.error(self.request, "{} failed validation: {}".format(obj, e)) - - except ObjectDoesNotExist: - msg = "Object update failed due to object-level permissions violation" - logger.debug(msg) - form.add_error(None, msg) - - else: - logger.debug("Form validation failed") - - else: - # Include the PK list as initial data for the form - initial_data = {'pk': pk_list} - - # Check for other contextual data needed for the form. We avoid passing all of request.GET because the - # filter values will conflict with the bulk edit form fields. - # TODO: Find a better way to accomplish this - if 'device' in request.GET: - initial_data['device'] = request.GET.get('device') - elif 'device_type' in request.GET: - initial_data['device_type'] = request.GET.get('device_type') - - form = self.form(model, initial=initial_data) - restrict_form_fields(form, request.user) - - # Retrieve objects being edited - table = self.table(self.queryset.filter(pk__in=pk_list), orderable=False) - if not table.rows: - messages.warning(request, "No {} were selected.".format(model._meta.verbose_name_plural)) - return redirect(self.get_return_url(request)) - - return render(request, self.template_name, { - 'form': form, - 'table': table, - 'obj_type_plural': model._meta.verbose_name_plural, - 'return_url': self.get_return_url(request), - }) - - -class BulkRenameView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): - """ - An extendable view for renaming objects in bulk. - """ - queryset = None - template_name = 'utilities/obj_bulk_rename.html' - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # Create a new Form class from BulkRenameForm - class _Form(BulkRenameForm): - pk = ModelMultipleChoiceField( - queryset=self.queryset, - widget=MultipleHiddenInput() - ) - - self.form = _Form - - def get_required_permission(self): - return get_permission_for_model(self.queryset.model, 'change') - - def post(self, request): - logger = logging.getLogger('netbox.views.BulkRenameView') - - if '_preview' in request.POST or '_apply' in request.POST: - form = self.form(request.POST, initial={'pk': request.POST.getlist('pk')}) - selected_objects = self.queryset.filter(pk__in=form.initial['pk']) - - if form.is_valid(): - try: - with transaction.atomic(): - renamed_pks = [] - for obj in selected_objects: - find = form.cleaned_data['find'] - replace = form.cleaned_data['replace'] - if form.cleaned_data['use_regex']: - try: - obj.new_name = re.sub(find, replace, obj.name) - # Catch regex group reference errors - except re.error: - obj.new_name = obj.name - else: - obj.new_name = obj.name.replace(find, replace) - renamed_pks.append(obj.pk) - - if '_apply' in request.POST: - for obj in selected_objects: - obj.name = obj.new_name - obj.save() - - # Enforce constrained permissions - if self.queryset.filter(pk__in=renamed_pks).count() != len(selected_objects): - raise ObjectDoesNotExist - - messages.success(request, "Renamed {} {}".format( - len(selected_objects), - self.queryset.model._meta.verbose_name_plural - )) - return redirect(self.get_return_url(request)) - - except ObjectDoesNotExist: - msg = "Object update failed due to object-level permissions violation" - logger.debug(msg) - form.add_error(None, msg) - - else: - form = self.form(initial={'pk': request.POST.getlist('pk')}) - selected_objects = self.queryset.filter(pk__in=form.initial['pk']) - - return render(request, self.template_name, { - 'form': form, - 'obj_type_plural': self.queryset.model._meta.verbose_name_plural, - 'selected_objects': selected_objects, - 'return_url': self.get_return_url(request), - }) - - -class BulkDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): - """ - Delete objects in bulk. - - queryset: Custom queryset to use when retrieving objects (e.g. to select related objects) - filter: FilterSet to apply when deleting by QuerySet - table: The table used to display devices being deleted - form: The form class used to delete objects in bulk - template_name: The name of the template - """ - queryset = None - filterset = None - table = None - form = None - template_name = 'utilities/obj_bulk_delete.html' - - def get_required_permission(self): - return get_permission_for_model(self.queryset.model, 'delete') - - def get(self, request): - return redirect(self.get_return_url(request)) - - def post(self, request, **kwargs): - logger = logging.getLogger('netbox.views.BulkDeleteView') - model = self.queryset.model - - # Are we deleting *all* objects in the queryset or just a selected subset? - if request.POST.get('_all'): - if self.filterset is not None: - pk_list = [obj.pk for obj in self.filterset(request.GET, model.objects.only('pk')).qs] - else: - pk_list = model.objects.values_list('pk', flat=True) - else: - pk_list = [int(pk) for pk in request.POST.getlist('pk')] - - form_cls = self.get_form() - - if '_confirm' in request.POST: - form = form_cls(request.POST) - if form.is_valid(): - logger.debug("Form validation was successful") - - # Delete objects - queryset = self.queryset.filter(pk__in=pk_list) - try: - deleted_count = queryset.delete()[1][model._meta.label] - except ProtectedError as e: - logger.info("Caught ProtectedError while attempting to delete objects") - handle_protectederror(queryset, request, e) - return redirect(self.get_return_url(request)) - - msg = 'Deleted {} {}'.format(deleted_count, model._meta.verbose_name_plural) - logger.info(msg) - messages.success(request, msg) - return redirect(self.get_return_url(request)) - - else: - logger.debug("Form validation failed") - - else: - form = form_cls(initial={ - 'pk': pk_list, - 'return_url': self.get_return_url(request), - }) - - # Retrieve objects being deleted - table = self.table(self.queryset.filter(pk__in=pk_list), orderable=False) - if not table.rows: - messages.warning(request, "No {} were selected for deletion.".format(model._meta.verbose_name_plural)) - return redirect(self.get_return_url(request)) - - return render(request, self.template_name, { - 'form': form, - 'obj_type_plural': model._meta.verbose_name_plural, - 'table': table, - 'return_url': self.get_return_url(request), - }) - - def get_form(self): - """ - Provide a standard bulk delete form if none has been specified for the view - """ - class BulkDeleteForm(ConfirmationForm): - pk = ModelMultipleChoiceField(queryset=self.queryset, widget=MultipleHiddenInput) - - if self.form: - return self.form - - return BulkDeleteForm - - -# -# Device/VirtualMachine components -# - -# TODO: Replace with BulkCreateView -class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): - """ - Add one or more components (e.g. interfaces, console ports, etc.) to a Device or VirtualMachine. - """ - queryset = None - form = None - model_form = None - template_name = None - - def get_required_permission(self): - return get_permission_for_model(self.queryset.model, 'add') - - def get(self, request): - - form = self.form(initial=request.GET) - - return render(request, self.template_name, { - 'component_type': self.queryset.model._meta.verbose_name, - 'form': form, - 'return_url': self.get_return_url(request), - }) - - def post(self, request): - logger = logging.getLogger('netbox.views.ComponentCreateView') - form = self.form(request.POST, initial=request.GET) - - if form.is_valid(): - - new_components = [] - data = deepcopy(request.POST) - - names = form.cleaned_data['name_pattern'] - labels = form.cleaned_data.get('label_pattern') - for i, name in enumerate(names): - label = labels[i] if labels else None - # Initialize the individual component form - data['name'] = name - data['label'] = label - if hasattr(form, 'get_iterative_data'): - data.update(form.get_iterative_data(i)) - component_form = self.model_form(data) - - if component_form.is_valid(): - new_components.append(component_form) - else: - for field, errors in component_form.errors.as_data().items(): - # Assign errors on the child form's name/label field to name_pattern/label_pattern on the parent form - if field == 'name': - field = 'name_pattern' - elif field == 'label': - field = 'label_pattern' - for e in errors: - form.add_error(field, '{}: {}'.format(name, ', '.join(e))) - - if not form.errors: - - try: - - with transaction.atomic(): - - # Create the new components - new_objs = [] - for component_form in new_components: - obj = component_form.save() - new_objs.append(obj) - - # Enforce object-level permissions - if self.queryset.filter(pk__in=[obj.pk for obj in new_objs]).count() != len(new_objs): - raise ObjectDoesNotExist - - messages.success(request, "Added {} {}".format( - len(new_components), self.queryset.model._meta.verbose_name_plural - )) - if '_addanother' in request.POST: - return redirect(request.get_full_path()) - else: - return redirect(self.get_return_url(request)) - - except ObjectDoesNotExist: - msg = "Component creation failed due to object-level permissions violation" - logger.debug(msg) - form.add_error(None, msg) - - return render(request, self.template_name, { - 'component_type': self.queryset.model._meta.verbose_name, - 'form': form, - 'return_url': self.get_return_url(request), - }) - - -class BulkComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): - """ - Add one or more components (e.g. interfaces, console ports, etc.) to a set of Devices or VirtualMachines. - """ - parent_model = None - parent_field = None - form = None - queryset = None - model_form = None - filterset = None - table = None - template_name = 'utilities/obj_bulk_add_component.html' - - def get_required_permission(self): - return f'dcim.add_{self.queryset.model._meta.model_name}' - - def post(self, request): - logger = logging.getLogger('netbox.views.BulkComponentCreateView') - parent_model_name = self.parent_model._meta.verbose_name_plural - model_name = self.queryset.model._meta.verbose_name_plural - - # Are we editing *all* objects in the queryset or just a selected subset? - if request.POST.get('_all') and self.filterset is not None: - pk_list = [obj.pk for obj in self.filterset(request.GET, self.parent_model.objects.only('pk')).qs] - else: - pk_list = [int(pk) for pk in request.POST.getlist('pk')] - - selected_objects = self.parent_model.objects.filter(pk__in=pk_list) - if not selected_objects: - messages.warning(request, "No {} were selected.".format(self.parent_model._meta.verbose_name_plural)) - return redirect(self.get_return_url(request)) - table = self.table(selected_objects) - - if '_create' in request.POST: - form = self.form(request.POST) - - if form.is_valid(): - logger.debug("Form validation was successful") - - new_components = [] - data = deepcopy(form.cleaned_data) - - try: - with transaction.atomic(): - - for obj in data['pk']: - - names = data['name_pattern'] - labels = data['label_pattern'] if 'label_pattern' in data else None - for i, name in enumerate(names): - label = labels[i] if labels else None - - component_data = { - self.parent_field: obj.pk, - 'name': name, - 'label': label - } - component_data.update(data) - component_form = self.model_form(component_data) - if component_form.is_valid(): - instance = component_form.save() - logger.debug(f"Created {instance} on {instance.parent}") - new_components.append(instance) - else: - for field, errors in component_form.errors.as_data().items(): - for e in errors: - form.add_error(field, '{} {}: {}'.format(obj, name, ', '.join(e))) - - # Enforce object-level permissions - if self.queryset.filter(pk__in=[obj.pk for obj in new_components]).count() != len(new_components): - raise ObjectDoesNotExist - - except IntegrityError: - pass - - except ObjectDoesNotExist: - msg = "Component creation failed due to object-level permissions violation" - logger.debug(msg) - form.add_error(None, msg) - - if not form.errors: - msg = "Added {} {} to {} {}.".format( - len(new_components), - model_name, - len(form.cleaned_data['pk']), - parent_model_name - ) - logger.info(msg) - messages.success(request, msg) - - return redirect(self.get_return_url(request)) - - else: - logger.debug("Form validation failed") - - else: - form = self.form(initial={'pk': pk_list}) - - return render(request, self.template_name, { - 'form': form, - 'parent_model_name': parent_model_name, - 'model_name': model_name, - 'table': table, - 'return_url': self.get_return_url(request), - }) - - -@requires_csrf_token -def server_error(request, template_name=ERROR_500_TEMPLATE_NAME): - """ - Custom 500 handler to provide additional context when rendering 500.html. - """ - try: - template = loader.get_template(template_name) - except TemplateDoesNotExist: - return HttpResponseServerError('

      Server Error (500)

      ', content_type='text/html') - type_, error, traceback = sys.exc_info() - - return HttpResponseServerError(template.render({ - 'error': error, - 'exception': str(type_), - 'netbox_version': settings.VERSION, - 'python_version': platform.python_version(), - })) - - -def rest_api_server_error(request, *args, **kwargs): - """ - Handle exceptions and return a useful error message for REST API requests. - """ - type_, error, traceback = sys.exc_info() - data = { - 'error': str(error), - 'exception': type_.__name__, - 'netbox_version': settings.VERSION, - 'python_version': platform.python_version(), - } - return JsonResponse(data, status=status.HTTP_500_INTERNAL_SERVER_ERROR) diff --git a/netbox/virtualization/api/nested_serializers.py b/netbox/virtualization/api/nested_serializers.py index de56e6e6a5..7763f0ef41 100644 --- a/netbox/virtualization/api/nested_serializers.py +++ b/netbox/virtualization/api/nested_serializers.py @@ -1,7 +1,7 @@ from rest_framework import serializers from dcim.models import Interface -from utilities.api import WritableNestedSerializer +from netbox.api import WritableNestedSerializer from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine __all__ = [ diff --git a/netbox/virtualization/api/serializers.py b/netbox/virtualization/api/serializers.py index 711e1359e2..518b7086c0 100644 --- a/netbox/virtualization/api/serializers.py +++ b/netbox/virtualization/api/serializers.py @@ -7,8 +7,8 @@ from extras.api.serializers import TaggedObjectSerializer from ipam.api.nested_serializers import NestedIPAddressSerializer, NestedVLANSerializer from ipam.models import VLAN +from netbox.api import ChoiceField, SerializedPKRelatedField, ValidatedModelSerializer from tenancy.api.nested_serializers import NestedTenantSerializer -from utilities.api import ChoiceField, SerializedPKRelatedField, ValidatedModelSerializer from virtualization.choices import * from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface from .nested_serializers import * @@ -116,3 +116,16 @@ class Meta: 'id', 'url', 'virtual_machine', 'name', 'enabled', 'mtu', 'mac_address', 'description', 'mode', 'untagged_vlan', 'tagged_vlans', 'tags', ] + + def validate(self, data): + + # Validate many-to-many VLAN assignments + virtual_machine = self.instance.virtual_machine if self.instance else data.get('virtual_machine') + for vlan in data.get('tagged_vlans', []): + if vlan.site not in [virtual_machine.site, None]: + raise serializers.ValidationError({ + 'tagged_vlans': f"VLAN {vlan} must belong to the same site as the interface's parent virtual " + f"machine, or it must be global." + }) + + return super().validate(data) diff --git a/netbox/virtualization/api/urls.py b/netbox/virtualization/api/urls.py index c40202a7dd..d9df2fcfe0 100644 --- a/netbox/virtualization/api/urls.py +++ b/netbox/virtualization/api/urls.py @@ -1,4 +1,4 @@ -from utilities.api import OrderedDefaultRouter +from netbox.api import OrderedDefaultRouter from . import views diff --git a/netbox/virtualization/api/views.py b/netbox/virtualization/api/views.py index f805adb2ea..2a2a149d44 100644 --- a/netbox/virtualization/api/views.py +++ b/netbox/virtualization/api/views.py @@ -1,13 +1,7 @@ -from django.shortcuts import get_object_or_404 -from rest_framework.decorators import action -from rest_framework.response import Response from rest_framework.routers import APIRootView from dcim.models import Device -from extras.api.serializers import RenderedGraphSerializer -from extras.api.views import ConfigContextQuerySetMixin, CustomFieldModelViewSet -from extras.models import Graph -from utilities.api import ModelViewSet +from extras.api.views import ConfigContextQuerySetMixin, CustomFieldModelViewSet, ModelViewSet from utilities.utils import get_subquery from virtualization import filters from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface @@ -90,13 +84,3 @@ class VMInterfaceViewSet(ModelViewSet): ) serializer_class = serializers.VMInterfaceSerializer filterset_class = filters.VMInterfaceFilterSet - - @action(detail=True) - def graphs(self, request, pk): - """ - A convenience method for rendering graphs for a particular VM interface. - """ - vminterface = get_object_or_404(self.queryset, pk=pk) - queryset = Graph.objects.restrict(request.user).filter(type__model='vminterface') - serializer = RenderedGraphSerializer(queryset, many=True, context={'graphed_object': vminterface}) - return Response(serializer.data) diff --git a/netbox/virtualization/choices.py b/netbox/virtualization/choices.py index 083470bd9c..9c4eb6cd57 100644 --- a/netbox/virtualization/choices.py +++ b/netbox/virtualization/choices.py @@ -22,3 +22,12 @@ class VirtualMachineStatusChoices(ChoiceSet): (STATUS_FAILED, 'Failed'), (STATUS_DECOMMISSIONING, 'Decommissioning'), ) + + CSS_CLASSES = { + STATUS_OFFLINE: 'warning', + STATUS_ACTIVE: 'success', + STATUS_PLANNED: 'info', + STATUS_STAGED: 'primary', + STATUS_FAILED: 'danger', + STATUS_DECOMMISSIONING: 'warning', + } diff --git a/netbox/virtualization/filters.py b/netbox/virtualization/filters.py index 886b5484b3..af53afad5f 100644 --- a/netbox/virtualization/filters.py +++ b/netbox/virtualization/filters.py @@ -2,7 +2,7 @@ from django.db.models import Q from dcim.models import DeviceRole, Platform, Region, Site -from extras.filters import CustomFieldFilterSet, CreatedUpdatedFilterSet, LocalConfigContextFilterSet +from extras.filters import CustomFieldModelFilterSet, CreatedUpdatedFilterSet, LocalConfigContextFilterSet from tenancy.filters import TenancyFilterSet from utilities.filters import ( BaseFilterSet, MultiValueMACAddressFilter, NameSlugSearchFilterSet, TagFilter, @@ -34,7 +34,7 @@ class Meta: fields = ['id', 'name', 'slug', 'description'] -class ClusterFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet): +class ClusterFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): q = django_filters.CharFilter( method='search', label='Search', @@ -101,7 +101,7 @@ class VirtualMachineFilterSet( BaseFilterSet, LocalConfigContextFilterSet, TenancyFilterSet, - CustomFieldFilterSet, + CustomFieldModelFilterSet, CreatedUpdatedFilterSet ): q = django_filters.CharFilter( diff --git a/netbox/virtualization/forms.py b/netbox/virtualization/forms.py index ce4ca3e3c2..edacb3e073 100644 --- a/netbox/virtualization/forms.py +++ b/netbox/virtualization/forms.py @@ -4,7 +4,7 @@ from dcim.choices import InterfaceModeChoices from dcim.constants import INTERFACE_MTU_MAX, INTERFACE_MTU_MIN -from dcim.forms import INTERFACE_MODE_HELP_TEXT +from dcim.forms import InterfaceCommonForm, INTERFACE_MODE_HELP_TEXT from dcim.models import Device, DeviceRole, Platform, Rack, Region, Site from extras.forms import ( AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldModelCSVForm, CustomFieldModelForm, CustomFieldFilterForm, @@ -543,10 +543,11 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil # VM interfaces # -class VMInterfaceForm(BootstrapMixin, forms.ModelForm): +class VMInterfaceForm(BootstrapMixin, InterfaceCommonForm, forms.ModelForm): untagged_vlan = DynamicModelChoiceField( queryset=VLAN.objects.all(), required=False, + label='Untagged VLAN', display_field='display_name', brief_mode=False, query_params={ @@ -556,6 +557,7 @@ class VMInterfaceForm(BootstrapMixin, forms.ModelForm): tagged_vlans = DynamicModelMultipleChoiceField( queryset=VLAN.objects.all(), required=False, + label='Tagged VLANs', display_field='display_name', brief_mode=False, query_params={ @@ -597,24 +599,8 @@ def __init__(self, *args, **kwargs): self.fields['untagged_vlan'].widget.add_query_param('site_id', site.pk) self.fields['tagged_vlans'].widget.add_query_param('site_id', site.pk) - def clean(self): - super().clean() - - # Validate VLAN assignments - tagged_vlans = self.cleaned_data['tagged_vlans'] - - # Untagged interfaces cannot be assigned tagged VLANs - if self.cleaned_data['mode'] == InterfaceModeChoices.MODE_ACCESS and tagged_vlans: - raise forms.ValidationError({ - 'mode': "An access interface cannot have tagged VLANs assigned." - }) - - # Remove all tagged VLAN assignments from "tagged all" interfaces - elif self.cleaned_data['mode'] == InterfaceModeChoices.MODE_TAGGED_ALL: - self.cleaned_data['tagged_vlans'] = [] - -class VMInterfaceCreateForm(BootstrapMixin, forms.Form): +class VMInterfaceCreateForm(BootstrapMixin, InterfaceCommonForm): virtual_machine = DynamicModelChoiceField( queryset=VirtualMachine.objects.all() ) diff --git a/netbox/virtualization/migrations/0018_custom_field_data.py b/netbox/virtualization/migrations/0018_custom_field_data.py new file mode 100644 index 0000000000..9a120406ae --- /dev/null +++ b/netbox/virtualization/migrations/0018_custom_field_data.py @@ -0,0 +1,22 @@ +import django.core.serializers.json +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('virtualization', '0017_update_jsonfield'), + ] + + operations = [ + migrations.AddField( + model_name='cluster', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + migrations.AddField( + model_name='virtualmachine', + name='custom_field_data', + field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + ] diff --git a/netbox/virtualization/migrations/0019_standardize_name_length.py b/netbox/virtualization/migrations/0019_standardize_name_length.py new file mode 100644 index 0000000000..d6820640d0 --- /dev/null +++ b/netbox/virtualization/migrations/0019_standardize_name_length.py @@ -0,0 +1,33 @@ +# Generated by Django 3.1 on 2020-10-15 19:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('virtualization', '0018_custom_field_data'), + ] + + operations = [ + migrations.AlterField( + model_name='clustergroup', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='clustergroup', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='clustertype', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='clustertype', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + ] diff --git a/netbox/virtualization/models.py b/netbox/virtualization/models.py index 72d84a9084..cf77373407 100644 --- a/netbox/virtualization/models.py +++ b/netbox/virtualization/models.py @@ -5,7 +5,6 @@ from django.urls import reverse from taggit.managers import TaggableManager -from dcim.choices import InterfaceModeChoices from dcim.models import BaseInterface, Device from extras.models import ChangeLoggedModel, ConfigContextModel, CustomFieldModel, ObjectChange, TaggedItem from extras.querysets import ConfigContextModelQuerySet @@ -36,10 +35,11 @@ class ClusterType(ChangeLoggedModel): A type of Cluster. """ name = models.CharField( - max_length=50, + max_length=100, unique=True ) slug = models.SlugField( + max_length=100, unique=True ) description = models.CharField( @@ -77,10 +77,11 @@ class ClusterGroup(ChangeLoggedModel): An organizational group of Clusters. """ name = models.CharField( - max_length=50, + max_length=100, unique=True ) slug = models.SlugField( + max_length=100, unique=True ) description = models.CharField( @@ -151,11 +152,6 @@ class Cluster(ChangeLoggedModel, CustomFieldModel): comments = models.TextField( blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' - ) tags = TaggableManager(through=TaggedItem) objects = RestrictedQuerySet.as_manager() @@ -175,6 +171,7 @@ def get_absolute_url(self): return reverse('virtualization:cluster', args=[self.pk]) def clean(self): + super().clean() # If the Cluster is assigned to a Site, verify that all host Devices belong to that Site. if self.pk and self.site: @@ -276,10 +273,11 @@ class VirtualMachine(ChangeLoggedModel, ConfigContextModel, CustomFieldModel): comments = models.TextField( blank=True ) - custom_field_values = GenericRelation( - to='extras.CustomFieldValue', - content_type_field='obj_type', - object_id_field='obj_id' + secrets = GenericRelation( + to='secrets.Secret', + content_type_field='assigned_object_type', + object_id_field='assigned_object_id', + related_query_name='virtual_machine' ) tags = TaggableManager(through=TaggedItem) @@ -292,15 +290,6 @@ class VirtualMachine(ChangeLoggedModel, ConfigContextModel, CustomFieldModel): 'cluster', 'tenant', 'platform', 'status', 'role', 'vcpus', 'memory', 'disk', ] - STATUS_CLASS_MAP = { - VirtualMachineStatusChoices.STATUS_OFFLINE: 'warning', - VirtualMachineStatusChoices.STATUS_ACTIVE: 'success', - VirtualMachineStatusChoices.STATUS_PLANNED: 'info', - VirtualMachineStatusChoices.STATUS_STAGED: 'primary', - VirtualMachineStatusChoices.STATUS_FAILED: 'danger', - VirtualMachineStatusChoices.STATUS_DECOMMISSIONING: 'warning', - } - class Meta: ordering = ('name', 'pk') # Name may be non-unique unique_together = [ @@ -328,7 +317,6 @@ def validate_unique(self, exclude=None): super().validate_unique(exclude) def clean(self): - super().clean() # Validate primary IP addresses @@ -360,7 +348,7 @@ def to_csv(self): ) def get_status_class(self): - return self.STATUS_CLASS_MAP.get(self.status) + return VirtualMachineStatusChoices.CSS_CLASSES.get(self.status) @property def primary_ip(self): @@ -382,7 +370,7 @@ def site(self): # Interfaces # -@extras_features('graphs', 'export_templates', 'webhooks') +@extras_features('export_templates', 'webhooks') class VMInterface(BaseInterface): virtual_machine = models.ForeignKey( to='virtualization.VirtualMachine', @@ -460,8 +448,8 @@ def clean(self): # Validate untagged VLAN if self.untagged_vlan and self.untagged_vlan.site not in [self.virtual_machine.site, None]: raise ValidationError({ - 'untagged_vlan': "The untagged VLAN ({}) must belong to the same site as the interface's parent " - "virtual machine, or it must be global".format(self.untagged_vlan) + 'untagged_vlan': f"The untagged VLAN ({self.untagged_vlan}) must belong to the same site as the " + f"interface's parent virtual machine, or it must be global" }) def to_objectchange(self, action): diff --git a/netbox/virtualization/tables.py b/netbox/virtualization/tables.py index 5f5b9326de..97e1d6e36b 100644 --- a/netbox/virtualization/tables.py +++ b/netbox/virtualization/tables.py @@ -1,27 +1,28 @@ import django_tables2 as tables -from django_tables2.utils import Accessor -from dcim.tables import BaseInterfaceTable +from dcim.tables.devices import BaseInterfaceTable from tenancy.tables import COL_TENANT -from utilities.tables import BaseTable, ButtonsColumn, ColoredLabelColumn, TagColumn, ToggleColumn +from utilities.tables import ( + BaseTable, ButtonsColumn, ChoiceFieldColumn, ColoredLabelColumn, LinkedCountColumn, TagColumn, ToggleColumn, +) from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface -VIRTUALMACHINE_STATUS = """ -{{ record.get_status_display }} -""" - -VIRTUALMACHINE_PRIMARY_IP = """ -{{ record.primary_ip6.address.ip|default:"" }} -{% if record.primary_ip6 and record.primary_ip4 %}
      {% endif %} -{{ record.primary_ip4.address.ip|default:"" }} -""" - -DEVICE_COUNT = """ -{{ value|default:0 }} -""" - -VM_COUNT = """ -{{ value|default:0 }} +__all__ = ( + 'ClusterTable', + 'ClusterGroupTable', + 'ClusterTypeTable', + 'VirtualMachineDetailTable', + 'VirtualMachineTable', + 'VirtualMachineVMInterfaceTable', + 'VMInterfaceTable', +) + +VMINTERFACE_BUTTONS = """ +{% if perms.ipam.add_ipaddress %} + + + +{% endif %} """ @@ -74,12 +75,14 @@ class ClusterTable(BaseTable): site = tables.Column( linkify=True ) - device_count = tables.TemplateColumn( - template_code=DEVICE_COUNT, + device_count = LinkedCountColumn( + viewname='dcim:device_list', + url_params={'cluster_id': 'pk'}, verbose_name='Devices' ) - vm_count = tables.TemplateColumn( - template_code=VM_COUNT, + vm_count = LinkedCountColumn( + viewname='virtualization:virtualmachine_list', + url_params={'cluster_id': 'pk'}, verbose_name='VMs' ) tags = TagColumn( @@ -99,9 +102,7 @@ class Meta(BaseTable.Meta): class VirtualMachineTable(BaseTable): pk = ToggleColumn() name = tables.LinkColumn() - status = tables.TemplateColumn( - template_code=VIRTUALMACHINE_STATUS - ) + status = ChoiceFieldColumn() cluster = tables.Column( linkify=True ) @@ -124,10 +125,9 @@ class VirtualMachineDetailTable(VirtualMachineTable): linkify=True, verbose_name='IPv6 Address' ) - primary_ip = tables.TemplateColumn( - orderable=False, - verbose_name='IP Address', - template_code=VIRTUALMACHINE_PRIMARY_IP + primary_ip = tables.Column( + linkify=True, + verbose_name='IP Address' ) tags = TagColumn( url_name='virtualization:virtualmachine_list' @@ -161,7 +161,25 @@ class VMInterfaceTable(BaseInterfaceTable): class Meta(BaseTable.Meta): model = VMInterface fields = ( - 'pk', 'virtual_machine', 'name', 'enabled', 'mac_address', 'mtu', 'description', 'tags', 'ip_addresses', - 'untagged_vlan', 'tagged_vlans', + 'pk', 'virtual_machine', 'name', 'enabled', 'mac_address', 'mtu', 'mode', 'description', 'tags', + 'ip_addresses', 'untagged_vlan', 'tagged_vlans', ) default_columns = ('pk', 'virtual_machine', 'name', 'enabled', 'description') + + +class VirtualMachineVMInterfaceTable(VMInterfaceTable): + actions = ButtonsColumn( + model=VMInterface, + buttons=('edit', 'delete'), + prepend_template=VMINTERFACE_BUTTONS + ) + + class Meta(BaseTable.Meta): + model = VMInterface + fields = ( + 'pk', 'name', 'enabled', 'mac_address', 'mtu', 'mode', 'description', 'tags', 'ip_addresses', + 'untagged_vlan', 'tagged_vlans', 'actions', + ) + default_columns = ( + 'pk', 'name', 'enabled', 'mac_address', 'mtu', 'mode', 'description', 'ip_addresses', 'actions', + ) diff --git a/netbox/virtualization/tests/test_api.py b/netbox/virtualization/tests/test_api.py index 6ddcdf2ef2..716b6af4d7 100644 --- a/netbox/virtualization/tests/test_api.py +++ b/netbox/virtualization/tests/test_api.py @@ -1,10 +1,7 @@ -from django.contrib.contenttypes.models import ContentType -from django.test import override_settings from django.urls import reverse from rest_framework import status from dcim.choices import InterfaceModeChoices -from extras.models import Graph from ipam.models import VLAN from utilities.testing import APITestCase, APIViewTestCases from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface @@ -37,6 +34,9 @@ class ClusterTypeTest(APIViewTestCases.APIViewTestCase): 'slug': 'cluster-type-6', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -66,6 +66,9 @@ class ClusterGroupTest(APIViewTestCases.APIViewTestCase): 'slug': 'cluster-type-6', }, ] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -81,6 +84,9 @@ def setUpTestData(cls): class ClusterTest(APIViewTestCases.APIViewTestCase): model = Cluster brief_fields = ['id', 'name', 'url', 'virtualmachine_count'] + bulk_update_data = { + 'comments': 'New comment', + } @classmethod def setUpTestData(cls): @@ -126,6 +132,9 @@ def setUpTestData(cls): class VirtualMachineTest(APIViewTestCases.APIViewTestCase): model = VirtualMachine brief_fields = ['id', 'name', 'url'] + bulk_update_data = { + 'status': 'staged', + } @classmethod def setUpTestData(cls): @@ -199,6 +208,9 @@ def test_unique_name_per_cluster_constraint(self): class VMInterfaceTest(APIViewTestCases.APIViewTestCase): model = VMInterface brief_fields = ['id', 'name', 'url', 'virtual_machine'] + bulk_update_data = { + 'description': 'New description', + } @classmethod def setUpTestData(cls): @@ -244,25 +256,3 @@ def setUpTestData(cls): 'untagged_vlan': vlans[2].pk, }, ] - - @override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) - def test_get_vminterface_graphs(self): - """ - Test retrieval of Graphs assigned to VM interfaces. - """ - ct = ContentType.objects.get_for_model(VMInterface) - graphs = ( - Graph(type=ct, name='Graph 1', source='http://example.com/graphs.py?interface={{ obj.name }}&foo=1'), - Graph(type=ct, name='Graph 2', source='http://example.com/graphs.py?interface={{ obj.name }}&foo=2'), - Graph(type=ct, name='Graph 3', source='http://example.com/graphs.py?interface={{ obj.name }}&foo=3'), - ) - Graph.objects.bulk_create(graphs) - - self.add_permissions('virtualization.view_vminterface') - url = reverse('virtualization-api:vminterface-graphs', kwargs={ - 'pk': VMInterface.objects.first().pk - }) - response = self.client.get(url, **self.header) - - self.assertEqual(len(response.data), 3) - self.assertEqual(response.data[0]['embed_url'], 'http://example.com/graphs.py?interface=Interface 1&foo=1') diff --git a/netbox/virtualization/views.py b/netbox/virtualization/views.py index 2b7ae3a134..05fe326791 100644 --- a/netbox/virtualization/views.py +++ b/netbox/virtualization/views.py @@ -9,11 +9,9 @@ from extras.views import ObjectConfigContextView from ipam.models import IPAddress, Service from ipam.tables import InterfaceIPAddressTable, InterfaceVLANTable +from netbox.views import generic +from secrets.models import Secret from utilities.utils import get_subquery -from utilities.views import ( - BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, BulkRenameView, ComponentCreateView, - ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView, -) from . import filters, forms, tables from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface @@ -22,29 +20,29 @@ # Cluster types # -class ClusterTypeListView(ObjectListView): +class ClusterTypeListView(generic.ObjectListView): queryset = ClusterType.objects.annotate( cluster_count=get_subquery(Cluster, 'type') ) table = tables.ClusterTypeTable -class ClusterTypeEditView(ObjectEditView): +class ClusterTypeEditView(generic.ObjectEditView): queryset = ClusterType.objects.all() model_form = forms.ClusterTypeForm -class ClusterTypeDeleteView(ObjectDeleteView): +class ClusterTypeDeleteView(generic.ObjectDeleteView): queryset = ClusterType.objects.all() -class ClusterTypeBulkImportView(BulkImportView): +class ClusterTypeBulkImportView(generic.BulkImportView): queryset = ClusterType.objects.all() model_form = forms.ClusterTypeCSVForm table = tables.ClusterTypeTable -class ClusterTypeBulkDeleteView(BulkDeleteView): +class ClusterTypeBulkDeleteView(generic.BulkDeleteView): queryset = ClusterType.objects.annotate( cluster_count=get_subquery(Cluster, 'type') ) @@ -55,29 +53,29 @@ class ClusterTypeBulkDeleteView(BulkDeleteView): # Cluster groups # -class ClusterGroupListView(ObjectListView): +class ClusterGroupListView(generic.ObjectListView): queryset = ClusterGroup.objects.annotate( cluster_count=get_subquery(Cluster, 'group') ) table = tables.ClusterGroupTable -class ClusterGroupEditView(ObjectEditView): +class ClusterGroupEditView(generic.ObjectEditView): queryset = ClusterGroup.objects.all() model_form = forms.ClusterGroupForm -class ClusterGroupDeleteView(ObjectDeleteView): +class ClusterGroupDeleteView(generic.ObjectDeleteView): queryset = ClusterGroup.objects.all() -class ClusterGroupBulkImportView(BulkImportView): +class ClusterGroupBulkImportView(generic.BulkImportView): queryset = ClusterGroup.objects.all() model_form = forms.ClusterGroupCSVForm table = tables.ClusterGroupTable -class ClusterGroupBulkDeleteView(BulkDeleteView): +class ClusterGroupBulkDeleteView(generic.BulkDeleteView): queryset = ClusterGroup.objects.annotate( cluster_count=get_subquery(Cluster, 'group') ) @@ -88,9 +86,9 @@ class ClusterGroupBulkDeleteView(BulkDeleteView): # Clusters # -class ClusterListView(ObjectListView): +class ClusterListView(generic.ObjectListView): permission_required = 'virtualization.view_cluster' - queryset = Cluster.objects.prefetch_related('type', 'group', 'site', 'tenant').annotate( + queryset = Cluster.objects.annotate( device_count=get_subquery(Device, 'cluster'), vm_count=get_subquery(VirtualMachine, 'cluster') ) @@ -99,58 +97,52 @@ class ClusterListView(ObjectListView): filterset_form = forms.ClusterFilterForm -class ClusterView(ObjectView): +class ClusterView(generic.ObjectView): queryset = Cluster.objects.all() - def get(self, request, pk): - self.queryset = self.queryset.prefetch_related( - Prefetch('virtual_machines', queryset=VirtualMachine.objects.restrict(request.user)) - ) - - cluster = get_object_or_404(self.queryset, pk=pk) - devices = Device.objects.restrict(request.user, 'view').filter(cluster=cluster).prefetch_related( + def get_extra_context(self, request, instance): + devices = Device.objects.restrict(request.user, 'view').filter(cluster=instance).prefetch_related( 'site', 'rack', 'tenant', 'device_type__manufacturer' ) device_table = DeviceTable(list(devices), orderable=False) if request.user.has_perm('virtualization.change_cluster'): device_table.columns.show('pk') - return render(request, 'virtualization/cluster.html', { - 'cluster': cluster, + return { 'device_table': device_table, - }) + } -class ClusterEditView(ObjectEditView): +class ClusterEditView(generic.ObjectEditView): template_name = 'virtualization/cluster_edit.html' queryset = Cluster.objects.all() model_form = forms.ClusterForm -class ClusterDeleteView(ObjectDeleteView): +class ClusterDeleteView(generic.ObjectDeleteView): queryset = Cluster.objects.all() -class ClusterBulkImportView(BulkImportView): +class ClusterBulkImportView(generic.BulkImportView): queryset = Cluster.objects.all() model_form = forms.ClusterCSVForm table = tables.ClusterTable -class ClusterBulkEditView(BulkEditView): +class ClusterBulkEditView(generic.BulkEditView): queryset = Cluster.objects.prefetch_related('type', 'group', 'site') filterset = filters.ClusterFilterSet table = tables.ClusterTable form = forms.ClusterBulkEditForm -class ClusterBulkDeleteView(BulkDeleteView): +class ClusterBulkDeleteView(generic.BulkDeleteView): queryset = Cluster.objects.prefetch_related('type', 'group', 'site') filterset = filters.ClusterFilterSet table = tables.ClusterTable -class ClusterAddDevicesView(ObjectEditView): +class ClusterAddDevicesView(generic.ObjectEditView): queryset = Cluster.objects.all() form = forms.ClusterAddDevicesForm template_name = 'virtualization/cluster_add_devices.html' @@ -191,10 +183,10 @@ def post(self, request, pk): }) -class ClusterRemoveDevicesView(ObjectEditView): +class ClusterRemoveDevicesView(generic.ObjectEditView): queryset = Cluster.objects.all() form = forms.ClusterRemoveDevicesForm - template_name = 'utilities/obj_bulk_remove.html' + template_name = 'generic/object_bulk_remove.html' def post(self, request, pk): @@ -236,36 +228,44 @@ def post(self, request, pk): # Virtual machines # -class VirtualMachineListView(ObjectListView): - queryset = VirtualMachine.objects.prefetch_related('cluster', 'tenant', 'role', 'primary_ip4', 'primary_ip6') +class VirtualMachineListView(generic.ObjectListView): + queryset = VirtualMachine.objects.all() filterset = filters.VirtualMachineFilterSet filterset_form = forms.VirtualMachineFilterForm table = tables.VirtualMachineDetailTable template_name = 'virtualization/virtualmachine_list.html' -class VirtualMachineView(ObjectView): +class VirtualMachineView(generic.ObjectView): queryset = VirtualMachine.objects.prefetch_related('tenant__group') - def get(self, request, pk): - - virtualmachine = get_object_or_404(self.queryset, pk=pk) - interfaces = VMInterface.objects.restrict(request.user, 'view').filter( - virtual_machine=virtualmachine + def get_extra_context(self, request, instance): + # Interfaces + vminterfaces = VMInterface.objects.restrict(request.user, 'view').filter( + virtual_machine=instance ).prefetch_related( Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)) ) + vminterface_table = tables.VirtualMachineVMInterfaceTable(vminterfaces, user=request.user, orderable=False) + if request.user.has_perm('virtualization.change_vminterface') or \ + request.user.has_perm('virtualization.delete_vminterface'): + vminterface_table.columns.show('pk') + + # Services services = Service.objects.restrict(request.user, 'view').filter( - virtual_machine=virtualmachine + virtual_machine=instance ).prefetch_related( Prefetch('ipaddresses', queryset=IPAddress.objects.restrict(request.user)) ) - return render(request, 'virtualization/virtualmachine.html', { - 'virtualmachine': virtualmachine, - 'interfaces': interfaces, + # Secrets + secrets = Secret.objects.restrict(request.user, 'view').filter(virtual_machine=instance) + + return { + 'vminterface_table': vminterface_table, 'services': services, - }) + 'secrets': secrets, + } class VirtualMachineConfigContextView(ObjectConfigContextView): @@ -273,30 +273,30 @@ class VirtualMachineConfigContextView(ObjectConfigContextView): base_template = 'virtualization/virtualmachine.html' -class VirtualMachineEditView(ObjectEditView): +class VirtualMachineEditView(generic.ObjectEditView): queryset = VirtualMachine.objects.all() model_form = forms.VirtualMachineForm template_name = 'virtualization/virtualmachine_edit.html' -class VirtualMachineDeleteView(ObjectDeleteView): +class VirtualMachineDeleteView(generic.ObjectDeleteView): queryset = VirtualMachine.objects.all() -class VirtualMachineBulkImportView(BulkImportView): +class VirtualMachineBulkImportView(generic.BulkImportView): queryset = VirtualMachine.objects.all() model_form = forms.VirtualMachineCSVForm table = tables.VirtualMachineTable -class VirtualMachineBulkEditView(BulkEditView): +class VirtualMachineBulkEditView(generic.BulkEditView): queryset = VirtualMachine.objects.prefetch_related('cluster', 'tenant', 'role') filterset = filters.VirtualMachineFilterSet table = tables.VirtualMachineTable form = forms.VirtualMachineBulkEditForm -class VirtualMachineBulkDeleteView(BulkDeleteView): +class VirtualMachineBulkDeleteView(generic.BulkDeleteView): queryset = VirtualMachine.objects.prefetch_related('cluster', 'tenant', 'role') filterset = filters.VirtualMachineFilterSet table = tables.VirtualMachineTable @@ -306,84 +306,80 @@ class VirtualMachineBulkDeleteView(BulkDeleteView): # VM interfaces # -class VMInterfaceListView(ObjectListView): - queryset = VMInterface.objects.prefetch_related('virtual_machine') +class VMInterfaceListView(generic.ObjectListView): + queryset = VMInterface.objects.all() filterset = filters.VMInterfaceFilterSet filterset_form = forms.VMInterfaceFilterForm table = tables.VMInterfaceTable action_buttons = ('export',) -class VMInterfaceView(ObjectView): +class VMInterfaceView(generic.ObjectView): queryset = VMInterface.objects.all() - def get(self, request, pk): - - vminterface = get_object_or_404(self.queryset, pk=pk) - + def get_extra_context(self, request, instance): # Get assigned IP addresses ipaddress_table = InterfaceIPAddressTable( - data=vminterface.ip_addresses.restrict(request.user, 'view').prefetch_related('vrf', 'tenant'), + data=instance.ip_addresses.restrict(request.user, 'view').prefetch_related('vrf', 'tenant'), orderable=False ) # Get assigned VLANs and annotate whether each is tagged or untagged vlans = [] - if vminterface.untagged_vlan is not None: - vlans.append(vminterface.untagged_vlan) + if instance.untagged_vlan is not None: + vlans.append(instance.untagged_vlan) vlans[0].tagged = False - for vlan in vminterface.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'): + for vlan in instance.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'): vlan.tagged = True vlans.append(vlan) vlan_table = InterfaceVLANTable( - interface=vminterface, + interface=instance, data=vlans, orderable=False ) - return render(request, 'virtualization/vminterface.html', { - 'vminterface': vminterface, + return { 'ipaddress_table': ipaddress_table, 'vlan_table': vlan_table, - }) + } # TODO: This should not use ComponentCreateView -class VMInterfaceCreateView(ComponentCreateView): +class VMInterfaceCreateView(generic.ComponentCreateView): queryset = VMInterface.objects.all() form = forms.VMInterfaceCreateForm model_form = forms.VMInterfaceForm template_name = 'virtualization/virtualmachine_component_add.html' -class VMInterfaceEditView(ObjectEditView): +class VMInterfaceEditView(generic.ObjectEditView): queryset = VMInterface.objects.all() model_form = forms.VMInterfaceForm template_name = 'virtualization/vminterface_edit.html' -class VMInterfaceDeleteView(ObjectDeleteView): +class VMInterfaceDeleteView(generic.ObjectDeleteView): queryset = VMInterface.objects.all() -class VMInterfaceBulkImportView(BulkImportView): +class VMInterfaceBulkImportView(generic.BulkImportView): queryset = VMInterface.objects.all() model_form = forms.VMInterfaceCSVForm table = tables.VMInterfaceTable -class VMInterfaceBulkEditView(BulkEditView): +class VMInterfaceBulkEditView(generic.BulkEditView): queryset = VMInterface.objects.all() table = tables.VMInterfaceTable form = forms.VMInterfaceBulkEditForm -class VMInterfaceBulkRenameView(BulkRenameView): +class VMInterfaceBulkRenameView(generic.BulkRenameView): queryset = VMInterface.objects.all() form = forms.VMInterfaceBulkRenameForm -class VMInterfaceBulkDeleteView(BulkDeleteView): +class VMInterfaceBulkDeleteView(generic.BulkDeleteView): queryset = VMInterface.objects.all() table = tables.VMInterfaceTable @@ -392,7 +388,7 @@ class VMInterfaceBulkDeleteView(BulkDeleteView): # Bulk Device component creation # -class VirtualMachineBulkAddInterfaceView(BulkComponentCreateView): +class VirtualMachineBulkAddInterfaceView(generic.BulkComponentCreateView): parent_model = VirtualMachine parent_field = 'virtual_machine' form = forms.VMInterfaceBulkCreateForm diff --git a/requirements.txt b/requirements.txt index f26d444714..18ce530fd9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,23 +1,23 @@ -Django==3.1 -django-cacheops==5.1.0 -django-cors-headers==3.4.0 -django-debug-toolbar==2.2 -django-filter==2.3.0 +Django==3.1.3 +django-cacheops==5.1 +django-cors-headers==3.5.0 +django-debug-toolbar==3.1.1 +django-filter==2.4.0 django-mptt==0.11.0 django-pglocks==1.0.4 -django-prometheus==2.0.0 -django-rq==2.3.2 -django-tables2==2.3.1 +django-prometheus==2.1.0 +django-rq==2.4.0 +django-tables2==2.3.3 django-taggit==1.3.0 django-timezone-field==4.0 -djangorestframework==3.11.0 -drf-yasg[validation]==1.17.1 +djangorestframework==3.12.2 +drf-yasg[validation]==1.20.0 gunicorn==20.0.4 Jinja2==2.11.2 -Markdown==3.2.2 +Markdown==3.3.3 netaddr==0.8.0 -Pillow==7.2.0 -psycopg2-binary==2.8.5 -pycryptodome==3.9.8 +Pillow==8.0.1 +psycopg2-binary==2.8.6 +pycryptodome==3.9.9 PyYAML==5.3.1 svgwrite==1.4 diff --git a/upgrade.sh b/upgrade.sh index 66ba7b39f1..2e35a02f99 100755 --- a/upgrade.sh +++ b/upgrade.sh @@ -55,6 +55,11 @@ COMMAND="python3 netbox/manage.py migrate" echo "Applying database migrations ($COMMAND)..." eval $COMMAND || exit 1 +# Trace any missing cable paths (not typically needed) +COMMAND="python3 netbox/manage.py trace_paths --no-input" +echo "Checking for missing cable paths ($COMMAND)..." +eval $COMMAND || exit 1 + # Collect static files COMMAND="python3 netbox/manage.py collectstatic --no-input" echo "Collecting static files ($COMMAND)..." @@ -79,7 +84,8 @@ if [ -v WARN_MISSING_VENV ]; then echo "--------------------------------------------------------------------" echo "WARNING: No existing virtual environment was detected. A new one has" echo "been created. Update your systemd service files to reflect the new" - echo "Python and gunicorn executables." + echo "Python and gunicorn executables. (If this is a new installation," + echo "this warning can be ignored.)" echo "" echo "netbox.service ExecStart:" echo " ${VIRTUALENV}/bin/gunicorn"