diff --git a/.github/ISSUE_TEMPLATE/01-feature_request.yaml b/.github/ISSUE_TEMPLATE/01-feature_request.yaml index eda44e63e..25aaa3f70 100644 --- a/.github/ISSUE_TEMPLATE/01-feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/01-feature_request.yaml @@ -15,7 +15,7 @@ body: attributes: label: NetBox version description: What version of NetBox are you currently running? - placeholder: v4.4.1 + placeholder: v4.4.2 validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/02-bug_report.yaml b/.github/ISSUE_TEMPLATE/02-bug_report.yaml index 4e62aa84e..2d654a910 100644 --- a/.github/ISSUE_TEMPLATE/02-bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/02-bug_report.yaml @@ -27,7 +27,7 @@ body: attributes: label: NetBox Version description: What version of NetBox are you currently running? - placeholder: v4.4.1 + placeholder: v4.4.2 validations: required: true - type: dropdown diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml index f763ef6df..d5453e19f 100644 --- a/.github/codeql/codeql-config.yml +++ b/.github/codeql/codeql-config.yml @@ -1,3 +1,11 @@ paths-ignore: # Ignore compiled JS - netbox/project-static/dist + +query-filters: + # Exclude py/url-redirection: NetBox uses safe_for_redirect() wrapper function + # which validates all redirects via Django's url_has_allowed_host_and_scheme(). + # CodeQL's taint tracking doesn't recognize wrapper functions without custom + # query configuration. See #20484. + - exclude: + id: py/url-redirection diff --git a/base_requirements.txt b/base_requirements.txt index 9bf8680a5..1e6f2ad29 100644 --- a/base_requirements.txt +++ b/base_requirements.txt @@ -30,7 +30,8 @@ django-htmx # Modified Preorder Tree Traversal (recursive nesting of objects) # https://github.com/django-mptt/django-mptt/blob/main/CHANGELOG.rst -django-mptt +# v0.18.0 introduces errant migrations which need to be resolved +django-mptt==0.17.0 # Context managers for PostgreSQL advisory locks # https://github.com/Xof/django-pglocks/blob/master/CHANGES.txt diff --git a/contrib/generated_schema.json b/contrib/generated_schema.json index 473e75cff..279357912 100644 --- a/contrib/generated_schema.json +++ b/contrib/generated_schema.json @@ -332,14 +332,14 @@ "100base-t1", "1000base-bx10-d", "1000base-bx10-u", - "1000base-cx", "1000base-cwdm", + "1000base-cx", "1000base-dwdm", "1000base-ex", - "1000base-sx", "1000base-lsx", "1000base-lx", "1000base-lx10", + "1000base-sx", "1000base-t", "1000base-tx", "1000base-zx", @@ -374,6 +374,7 @@ "100gbase-cr2", "100gbase-cr4", "100gbase-cr10", + "100gbase-cwdm4", "100gbase-dr", "100gbase-er4", "100gbase-fr1", @@ -387,12 +388,12 @@ "100gbase-zr", "200gbase-cr2", "200gbase-cr4", - "200gbase-sr2", - "200gbase-sr4", "200gbase-dr4", "200gbase-er4", "200gbase-fr4", "200gbase-lr4", + "200gbase-sr2", + "200gbase-sr4", "200gbase-vr2", "400gbase-cr4", "400gbase-dr4", @@ -415,34 +416,34 @@ "1000base-x-gbic", "1000base-x-sfp", "10gbase-x-sfpp", - "10gbase-x-xfp", "10gbase-x-xenpak", + "10gbase-x-xfp", "10gbase-x-x2", "25gbase-x-sfp28", - "50gbase-x-sfp56", "40gbase-x-qsfpp", "50gbase-x-sfp28", + "50gbase-x-sfp56", "100gbase-x-cfp", "100gbase-x-cfp2", - "200gbase-x-cfp2", - "400gbase-x-cfp2", "100gbase-x-cfp4", "100gbase-x-cxp", "100gbase-x-cpak", "100gbase-x-dsfp", - "100gbase-x-sfpdd", "100gbase-x-qsfp28", "100gbase-x-qsfpdd", + "100gbase-x-sfpdd", + "200gbase-x-cfp2", "200gbase-x-qsfp56", "200gbase-x-qsfpdd", "400gbase-x-qsfp112", "400gbase-x-qsfpdd", + "400gbase-x-cdfp", + "400gbase-x-cfp2", + "400gbase-x-cfp8", "400gbase-x-osfp", "400gbase-x-osfp-rhs", - "400gbase-x-cdfp", - "400gbase-x-cfp8", - "800gbase-x-qsfpdd", "800gbase-x-osfp", + "800gbase-x-qsfpdd", "1000base-kx", "2.5gbase-kx", "5gbase-kr", diff --git a/contrib/openapi.json b/contrib/openapi.json index ddbdff987..33b5092af 100644 --- a/contrib/openapi.json +++ b/contrib/openapi.json @@ -2,7 +2,7 @@ "openapi": "3.0.3", "info": { "title": "NetBox REST API", - "version": "4.4.0", + "version": "4.4.2", "license": { "name": "Apache v2 License" } @@ -16104,7 +16104,7 @@ "/api/core/background-queues/": { "get": { "operationId": "core_background_queues_retrieve", - "description": "Retrieve a list of RQ Queues.\nNote: Queue names are not URL safe so not returning a detail view.", + "description": "Retrieve a list of RQ Queues.\nNote: Queue names are not URL safe, so not returning a detail view.", "tags": [ "core" ], @@ -16133,15 +16133,14 @@ }, "/api/core/background-queues/{name}/": { "get": { - "operationId": "core_background_queues_retrieve_2", - "description": "Retrieve a list of RQ Queues.\nNote: Queue names are not URL safe so not returning a detail view.", + "operationId": "core_background_queues_retrieve_by_name", + "description": "Retrieve a list of RQ Queues.\nNote: Queue names are not URL safe, so not returning a detail view.", "parameters": [ { "in": "path", "name": "name", "schema": { - "type": "string", - "pattern": "^[\\w.@+-]+$" + "type": "string" }, "required": true } @@ -16204,7 +16203,7 @@ }, "/api/core/background-tasks/{id}/": { "get": { - "operationId": "core_background_tasks_retrieve_2", + "operationId": "core_background_tasks_retrieve_by_id", "description": "Retrieve a list of RQ Tasks.", "parameters": [ { @@ -16259,6 +16258,21 @@ "tags": [ "core" ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackgroundTaskRequest" + } + }, + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/BackgroundTaskRequest" + } + } + }, + "required": true + }, "security": [ { "cookieAuth": [] @@ -16269,7 +16283,14 @@ ], "responses": { "200": { - "description": "No response body" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackgroundTask" + } + } + }, + "description": "" } } } @@ -16291,6 +16312,21 @@ "tags": [ "core" ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackgroundTaskRequest" + } + }, + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/BackgroundTaskRequest" + } + } + }, + "required": true + }, "security": [ { "cookieAuth": [] @@ -16301,7 +16337,14 @@ ], "responses": { "200": { - "description": "No response body" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackgroundTask" + } + } + }, + "description": "" } } } @@ -16323,6 +16366,21 @@ "tags": [ "core" ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackgroundTaskRequest" + } + }, + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/BackgroundTaskRequest" + } + } + }, + "required": true + }, "security": [ { "cookieAuth": [] @@ -16333,7 +16391,14 @@ ], "responses": { "200": { - "description": "No response body" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackgroundTask" + } + } + }, + "description": "" } } } @@ -16355,6 +16420,21 @@ "tags": [ "core" ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackgroundTaskRequest" + } + }, + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/BackgroundTaskRequest" + } + } + }, + "required": true + }, "security": [ { "cookieAuth": [] @@ -16365,7 +16445,14 @@ ], "responses": { "200": { - "description": "No response body" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BackgroundTask" + } + } + }, + "description": "" } } } @@ -16402,7 +16489,7 @@ }, "/api/core/background-workers/{name}/": { "get": { - "operationId": "core_background_workers_retrieve_2", + "operationId": "core_background_workers_retrieve_by_name", "description": "Retrieve a list of RQ Workers.", "parameters": [ { @@ -16427,7 +16514,15 @@ ], "responses": { "200": { - "description": "No response body" + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": {} + } + } + }, + "description": "" } } } @@ -47839,7 +47934,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -47859,7 +47954,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -47872,7 +47967,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -47885,7 +47980,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -47898,7 +47993,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -47911,7 +48006,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -47924,7 +48019,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -47937,7 +48032,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -47950,7 +48045,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -47963,7 +48058,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -47976,7 +48071,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -47989,7 +48084,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -51766,7 +51861,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -51786,7 +51881,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -51799,7 +51894,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -51812,7 +51907,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -51825,7 +51920,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -51838,7 +51933,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -51851,7 +51946,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -51864,7 +51959,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -51877,7 +51972,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -51890,7 +51985,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -51903,7 +51998,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -51916,7 +52011,7 @@ "type": "array", "items": { "type": "string", - "x-spec-enum-id": "efa24ff9c7a39c40" + "x-spec-enum-id": "c6dfa8e84dd05942" } }, "explode": true, @@ -152933,9 +153028,8 @@ "in": "query", "name": "interface_id", "schema": { - "type": "string" - }, - "description": "Assigned interface" + "type": "integer" + } }, { "in": "query", @@ -154226,9 +154320,8 @@ "in": "query", "name": "vminterface_id", "schema": { - "type": "string" - }, - "description": "Assigned VM interface" + "type": "integer" + } } ], "tags": [ @@ -200335,6 +200428,241 @@ "vid" ] }, + "BackgroundTask": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri", + "readOnly": true + }, + "description": { + "type": "string" + }, + "origin": { + "type": "string" + }, + "func_name": { + "type": "string" + }, + "args": { + "type": "array", + "items": {}, + "readOnly": true + }, + "kwargs": { + "type": "object", + "additionalProperties": {}, + "readOnly": true + }, + "result": { + "type": "string" + }, + "timeout": { + "type": "integer" + }, + "result_ttl": { + "type": "integer" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "enqueued_at": { + "type": "string", + "format": "date-time" + }, + "started_at": { + "type": "string", + "format": "date-time" + }, + "ended_at": { + "type": "string", + "format": "date-time" + }, + "worker_name": { + "type": "string" + }, + "position": { + "type": "integer", + "readOnly": true + }, + "status": { + "type": "string", + "readOnly": true + }, + "meta": { + "type": "object", + "additionalProperties": {} + }, + "last_heartbeat": { + "type": "string" + }, + "is_finished": { + "type": "boolean" + }, + "is_queued": { + "type": "boolean" + }, + "is_failed": { + "type": "boolean" + }, + "is_started": { + "type": "boolean" + }, + "is_deferred": { + "type": "boolean" + }, + "is_canceled": { + "type": "boolean" + }, + "is_scheduled": { + "type": "boolean" + }, + "is_stopped": { + "type": "boolean" + } + }, + "required": [ + "args", + "created_at", + "description", + "ended_at", + "enqueued_at", + "func_name", + "id", + "is_canceled", + "is_deferred", + "is_failed", + "is_finished", + "is_queued", + "is_scheduled", + "is_started", + "is_stopped", + "kwargs", + "last_heartbeat", + "meta", + "origin", + "position", + "result", + "result_ttl", + "started_at", + "status", + "timeout", + "url", + "worker_name" + ] + }, + "BackgroundTaskRequest": { + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 1 + }, + "description": { + "type": "string", + "minLength": 1 + }, + "origin": { + "type": "string", + "minLength": 1 + }, + "func_name": { + "type": "string", + "minLength": 1 + }, + "result": { + "type": "string", + "minLength": 1 + }, + "timeout": { + "type": "integer" + }, + "result_ttl": { + "type": "integer" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "enqueued_at": { + "type": "string", + "format": "date-time" + }, + "started_at": { + "type": "string", + "format": "date-time" + }, + "ended_at": { + "type": "string", + "format": "date-time" + }, + "worker_name": { + "type": "string", + "minLength": 1 + }, + "meta": { + "type": "object", + "additionalProperties": {} + }, + "last_heartbeat": { + "type": "string", + "minLength": 1 + }, + "is_finished": { + "type": "boolean" + }, + "is_queued": { + "type": "boolean" + }, + "is_failed": { + "type": "boolean" + }, + "is_started": { + "type": "boolean" + }, + "is_deferred": { + "type": "boolean" + }, + "is_canceled": { + "type": "boolean" + }, + "is_scheduled": { + "type": "boolean" + }, + "is_stopped": { + "type": "boolean" + } + }, + "required": [ + "created_at", + "description", + "ended_at", + "enqueued_at", + "func_name", + "id", + "is_canceled", + "is_deferred", + "is_failed", + "is_finished", + "is_queued", + "is_scheduled", + "is_started", + "is_stopped", + "last_heartbeat", + "meta", + "origin", + "result", + "result_ttl", + "started_at", + "timeout", + "worker_name" + ] + }, "Bookmark": { "type": "object", "description": "Extends the built-in ModelSerializer to enforce calling full_clean() on a copy of the associated instance during\nvalidation. (DRF does not do this by default; see https://github.com/encode/django-rest-framework/issues/3144)", @@ -201169,7 +201497,7 @@ "maxLength": 200 }, "choices_count": { - "type": "string", + "type": "integer", "readOnly": true } }, @@ -202332,7 +202660,8 @@ "description": "Adds support for custom fields and tags.", "properties": { "mac_address": { - "type": "string" + "type": "string", + "minLength": 1 }, "description": { "type": "string", @@ -209181,7 +209510,7 @@ "description": "Choices are automatically ordered alphabetically" }, "choices_count": { - "type": "string", + "type": "integer", "readOnly": true }, "created": { @@ -214431,7 +214760,7 @@ }, "mark_utilized": { "type": "boolean", - "description": "Report space as 100% utilized" + "description": "Report space as fully utilized" } }, "required": [ @@ -214540,7 +214869,7 @@ }, "mark_utilized": { "type": "boolean", - "description": "Report space as 100% utilized" + "description": "Report space as fully utilized" } }, "required": [ @@ -215240,24 +215569,26 @@ "IntegerRange": { "type": "array", "items": { - "type": "array", - "items": { - "type": "integer" - }, - "minItems": 2, - "maxItems": 2 - } + "type": "integer" + }, + "minItems": 2, + "maxItems": 2, + "example": [ + 10, + 20 + ] }, "IntegerRangeRequest": { "type": "array", "items": { - "type": "array", - "items": { - "type": "integer" - }, - "minItems": 2, - "maxItems": 2 - } + "type": "integer" + }, + "minItems": 2, + "maxItems": 2, + "example": [ + 10, + 20 + ] }, "Interface": { "type": "object", @@ -215321,14 +215652,14 @@ "100base-t1", "1000base-bx10-d", "1000base-bx10-u", - "1000base-cx", "1000base-cwdm", + "1000base-cx", "1000base-dwdm", "1000base-ex", - "1000base-sx", "1000base-lsx", "1000base-lx", "1000base-lx10", + "1000base-sx", "1000base-t", "1000base-tx", "1000base-zx", @@ -215363,6 +215694,7 @@ "100gbase-cr2", "100gbase-cr4", "100gbase-cr10", + "100gbase-cwdm4", "100gbase-dr", "100gbase-er4", "100gbase-fr1", @@ -215376,12 +215708,12 @@ "100gbase-zr", "200gbase-cr2", "200gbase-cr4", - "200gbase-sr2", - "200gbase-sr4", "200gbase-dr4", "200gbase-er4", "200gbase-fr4", "200gbase-lr4", + "200gbase-sr2", + "200gbase-sr4", "200gbase-vr2", "400gbase-cr4", "400gbase-dr4", @@ -215404,34 +215736,34 @@ "1000base-x-gbic", "1000base-x-sfp", "10gbase-x-sfpp", - "10gbase-x-xfp", "10gbase-x-xenpak", + "10gbase-x-xfp", "10gbase-x-x2", "25gbase-x-sfp28", - "50gbase-x-sfp56", "40gbase-x-qsfpp", "50gbase-x-sfp28", + "50gbase-x-sfp56", "100gbase-x-cfp", "100gbase-x-cfp2", - "200gbase-x-cfp2", - "400gbase-x-cfp2", "100gbase-x-cfp4", "100gbase-x-cxp", "100gbase-x-cpak", "100gbase-x-dsfp", - "100gbase-x-sfpdd", "100gbase-x-qsfp28", "100gbase-x-qsfpdd", + "100gbase-x-sfpdd", + "200gbase-x-cfp2", "200gbase-x-qsfp56", "200gbase-x-qsfpdd", "400gbase-x-qsfp112", "400gbase-x-qsfpdd", + "400gbase-x-cdfp", + "400gbase-x-cfp2", + "400gbase-x-cfp8", "400gbase-x-osfp", "400gbase-x-osfp-rhs", - "400gbase-x-cdfp", - "400gbase-x-cfp8", - "800gbase-x-qsfpdd", "800gbase-x-osfp", + "800gbase-x-qsfpdd", "1000base-kx", "2.5gbase-kx", "5gbase-kr", @@ -215519,8 +215851,8 @@ "other" ], "type": "string", - "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-DR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-DR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", - "x-spec-enum-id": "efa24ff9c7a39c40" + "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-BR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-BR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-cwdm4` - 100GBASE-CWDM4 (100GE)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", + "x-spec-enum-id": "c6dfa8e84dd05942" }, "label": { "type": "string", @@ -215534,21 +215866,21 @@ "100BASE-T1 (10/100ME)", "1000BASE-BX10-D (1GE BiDi Down)", "1000BASE-BX10-U (1GE BiDi Up)", - "1000BASE-CX (1GE DAC)", "1000BASE-CWDM (1GE)", + "1000BASE-CX (1GE DAC)", "1000BASE-DWDM (1GE)", "1000BASE-EX (1GE)", - "1000BASE-SX (1GE)", "1000BASE-LSX (1GE)", "1000BASE-LX (1GE)", "1000BASE-LX10/LH (1GE)", + "1000BASE-SX (1GE)", "1000BASE-T (1GE)", "1000BASE-TX (1GE)", "1000BASE-ZX (1GE)", "2.5GBASE-T (2.5GE)", "5GBASE-T (5GE)", - "10GBASE-DR-D (10GE BiDi Down)", - "10GBASE-DR-U (10GE BiDi Up)", + "10GBASE-BR-D (10GE BiDi Down)", + "10GBASE-BR-U (10GE BiDi Up)", "10GBASE-CX4 (10GE DAC)", "10GBASE-ER (10GE)", "10GBASE-LR (10GE)", @@ -215576,6 +215908,7 @@ "100GBASE-CR2 (100GE DAC)", "100GBASE-CR4 (100GE DAC)", "100GBASE-CR10 (100GE DAC)", + "100GBASE-CWDM4 (100GE)", "100GBASE-DR (100GE)", "100GBASE-ER4 (100GE)", "100GBASE-FR1 (100GE)", @@ -215589,12 +215922,12 @@ "100GBASE-ZR (100GE)", "200GBASE-CR2 (200GE)", "200GBASE-CR4 (200GE)", - "200GBASE-SR2 (200GE)", - "200GBASE-SR4 (200GE)", "200GBASE-DR4 (200GE)", "200GBASE-ER4 (200GE)", "200GBASE-FR4 (200GE)", "200GBASE-LR4 (200GE)", + "200GBASE-SR2 (200GE)", + "200GBASE-SR4 (200GE)", "200GBASE-VR2 (200GE)", "400GBASE-CR4 (400GE)", "400GBASE-DR4 (400GE)", @@ -215617,34 +215950,34 @@ "GBIC (1GE)", "SFP (1GE)", "SFP+ (10GE)", - "XFP (10GE)", "XENPAK (10GE)", + "XFP (10GE)", "X2 (10GE)", "SFP28 (25GE)", - "SFP56 (50GE)", "QSFP+ (40GE)", "QSFP28 (50GE)", + "SFP56 (50GE)", "CFP (100GE)", "CFP2 (100GE)", - "CFP2 (200GE)", - "CFP2 (400GE)", "CFP4 (100GE)", "CXP (100GE)", "Cisco CPAK (100GE)", "DSFP (100GE)", - "SFP-DD (100GE)", "QSFP28 (100GE)", "QSFP-DD (100GE)", + "SFP-DD (100GE)", + "CFP2 (200GE)", "QSFP56 (200GE)", "QSFP-DD (200GE)", "QSFP112 (400GE)", "QSFP-DD (400GE)", + "CDFP (400GE)", + "CFP2 (400GE)", + "CPF8 (400GE)", "OSFP (400GE)", "OSFP-RHS (400GE)", - "CDFP (400GE)", - "CPF8 (400GE)", - "QSFP-DD (800GE)", "OSFP (800GE)", + "QSFP-DD (800GE)", "1000BASE-KX (1GE)", "2.5GBASE-KX (2.5GE)", "5GBASE-KR (5GE)", @@ -216603,14 +216936,14 @@ "100base-t1", "1000base-bx10-d", "1000base-bx10-u", - "1000base-cx", "1000base-cwdm", + "1000base-cx", "1000base-dwdm", "1000base-ex", - "1000base-sx", "1000base-lsx", "1000base-lx", "1000base-lx10", + "1000base-sx", "1000base-t", "1000base-tx", "1000base-zx", @@ -216645,6 +216978,7 @@ "100gbase-cr2", "100gbase-cr4", "100gbase-cr10", + "100gbase-cwdm4", "100gbase-dr", "100gbase-er4", "100gbase-fr1", @@ -216658,12 +216992,12 @@ "100gbase-zr", "200gbase-cr2", "200gbase-cr4", - "200gbase-sr2", - "200gbase-sr4", "200gbase-dr4", "200gbase-er4", "200gbase-fr4", "200gbase-lr4", + "200gbase-sr2", + "200gbase-sr4", "200gbase-vr2", "400gbase-cr4", "400gbase-dr4", @@ -216686,34 +217020,34 @@ "1000base-x-gbic", "1000base-x-sfp", "10gbase-x-sfpp", - "10gbase-x-xfp", "10gbase-x-xenpak", + "10gbase-x-xfp", "10gbase-x-x2", "25gbase-x-sfp28", - "50gbase-x-sfp56", "40gbase-x-qsfpp", "50gbase-x-sfp28", + "50gbase-x-sfp56", "100gbase-x-cfp", "100gbase-x-cfp2", - "200gbase-x-cfp2", - "400gbase-x-cfp2", "100gbase-x-cfp4", "100gbase-x-cxp", "100gbase-x-cpak", "100gbase-x-dsfp", - "100gbase-x-sfpdd", "100gbase-x-qsfp28", "100gbase-x-qsfpdd", + "100gbase-x-sfpdd", + "200gbase-x-cfp2", "200gbase-x-qsfp56", "200gbase-x-qsfpdd", "400gbase-x-qsfp112", "400gbase-x-qsfpdd", + "400gbase-x-cdfp", + "400gbase-x-cfp2", + "400gbase-x-cfp8", "400gbase-x-osfp", "400gbase-x-osfp-rhs", - "400gbase-x-cdfp", - "400gbase-x-cfp8", - "800gbase-x-qsfpdd", "800gbase-x-osfp", + "800gbase-x-qsfpdd", "1000base-kx", "2.5gbase-kx", "5gbase-kr", @@ -216801,8 +217135,8 @@ "other" ], "type": "string", - "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-DR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-DR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", - "x-spec-enum-id": "efa24ff9c7a39c40" + "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-BR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-BR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-cwdm4` - 100GBASE-CWDM4 (100GE)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", + "x-spec-enum-id": "c6dfa8e84dd05942" }, "enabled": { "type": "boolean" @@ -217322,14 +217656,14 @@ "100base-t1", "1000base-bx10-d", "1000base-bx10-u", - "1000base-cx", "1000base-cwdm", + "1000base-cx", "1000base-dwdm", "1000base-ex", - "1000base-sx", "1000base-lsx", "1000base-lx", "1000base-lx10", + "1000base-sx", "1000base-t", "1000base-tx", "1000base-zx", @@ -217364,6 +217698,7 @@ "100gbase-cr2", "100gbase-cr4", "100gbase-cr10", + "100gbase-cwdm4", "100gbase-dr", "100gbase-er4", "100gbase-fr1", @@ -217377,12 +217712,12 @@ "100gbase-zr", "200gbase-cr2", "200gbase-cr4", - "200gbase-sr2", - "200gbase-sr4", "200gbase-dr4", "200gbase-er4", "200gbase-fr4", "200gbase-lr4", + "200gbase-sr2", + "200gbase-sr4", "200gbase-vr2", "400gbase-cr4", "400gbase-dr4", @@ -217405,34 +217740,34 @@ "1000base-x-gbic", "1000base-x-sfp", "10gbase-x-sfpp", - "10gbase-x-xfp", "10gbase-x-xenpak", + "10gbase-x-xfp", "10gbase-x-x2", "25gbase-x-sfp28", - "50gbase-x-sfp56", "40gbase-x-qsfpp", "50gbase-x-sfp28", + "50gbase-x-sfp56", "100gbase-x-cfp", "100gbase-x-cfp2", - "200gbase-x-cfp2", - "400gbase-x-cfp2", "100gbase-x-cfp4", "100gbase-x-cxp", "100gbase-x-cpak", "100gbase-x-dsfp", - "100gbase-x-sfpdd", "100gbase-x-qsfp28", "100gbase-x-qsfpdd", + "100gbase-x-sfpdd", + "200gbase-x-cfp2", "200gbase-x-qsfp56", "200gbase-x-qsfpdd", "400gbase-x-qsfp112", "400gbase-x-qsfpdd", + "400gbase-x-cdfp", + "400gbase-x-cfp2", + "400gbase-x-cfp8", "400gbase-x-osfp", "400gbase-x-osfp-rhs", - "400gbase-x-cdfp", - "400gbase-x-cfp8", - "800gbase-x-qsfpdd", "800gbase-x-osfp", + "800gbase-x-qsfpdd", "1000base-kx", "2.5gbase-kx", "5gbase-kr", @@ -217520,8 +217855,8 @@ "other" ], "type": "string", - "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-DR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-DR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", - "x-spec-enum-id": "efa24ff9c7a39c40" + "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-BR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-BR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-cwdm4` - 100GBASE-CWDM4 (100GE)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", + "x-spec-enum-id": "c6dfa8e84dd05942" }, "label": { "type": "string", @@ -217535,21 +217870,21 @@ "100BASE-T1 (10/100ME)", "1000BASE-BX10-D (1GE BiDi Down)", "1000BASE-BX10-U (1GE BiDi Up)", - "1000BASE-CX (1GE DAC)", "1000BASE-CWDM (1GE)", + "1000BASE-CX (1GE DAC)", "1000BASE-DWDM (1GE)", "1000BASE-EX (1GE)", - "1000BASE-SX (1GE)", "1000BASE-LSX (1GE)", "1000BASE-LX (1GE)", "1000BASE-LX10/LH (1GE)", + "1000BASE-SX (1GE)", "1000BASE-T (1GE)", "1000BASE-TX (1GE)", "1000BASE-ZX (1GE)", "2.5GBASE-T (2.5GE)", "5GBASE-T (5GE)", - "10GBASE-DR-D (10GE BiDi Down)", - "10GBASE-DR-U (10GE BiDi Up)", + "10GBASE-BR-D (10GE BiDi Down)", + "10GBASE-BR-U (10GE BiDi Up)", "10GBASE-CX4 (10GE DAC)", "10GBASE-ER (10GE)", "10GBASE-LR (10GE)", @@ -217577,6 +217912,7 @@ "100GBASE-CR2 (100GE DAC)", "100GBASE-CR4 (100GE DAC)", "100GBASE-CR10 (100GE DAC)", + "100GBASE-CWDM4 (100GE)", "100GBASE-DR (100GE)", "100GBASE-ER4 (100GE)", "100GBASE-FR1 (100GE)", @@ -217590,12 +217926,12 @@ "100GBASE-ZR (100GE)", "200GBASE-CR2 (200GE)", "200GBASE-CR4 (200GE)", - "200GBASE-SR2 (200GE)", - "200GBASE-SR4 (200GE)", "200GBASE-DR4 (200GE)", "200GBASE-ER4 (200GE)", "200GBASE-FR4 (200GE)", "200GBASE-LR4 (200GE)", + "200GBASE-SR2 (200GE)", + "200GBASE-SR4 (200GE)", "200GBASE-VR2 (200GE)", "400GBASE-CR4 (400GE)", "400GBASE-DR4 (400GE)", @@ -217618,34 +217954,34 @@ "GBIC (1GE)", "SFP (1GE)", "SFP+ (10GE)", - "XFP (10GE)", "XENPAK (10GE)", + "XFP (10GE)", "X2 (10GE)", "SFP28 (25GE)", - "SFP56 (50GE)", "QSFP+ (40GE)", "QSFP28 (50GE)", + "SFP56 (50GE)", "CFP (100GE)", "CFP2 (100GE)", - "CFP2 (200GE)", - "CFP2 (400GE)", "CFP4 (100GE)", "CXP (100GE)", "Cisco CPAK (100GE)", "DSFP (100GE)", - "SFP-DD (100GE)", "QSFP28 (100GE)", "QSFP-DD (100GE)", + "SFP-DD (100GE)", + "CFP2 (200GE)", "QSFP56 (200GE)", "QSFP-DD (200GE)", "QSFP112 (400GE)", "QSFP-DD (400GE)", + "CDFP (400GE)", + "CFP2 (400GE)", + "CPF8 (400GE)", "OSFP (400GE)", "OSFP-RHS (400GE)", - "CDFP (400GE)", - "CPF8 (400GE)", - "QSFP-DD (800GE)", "OSFP (800GE)", + "QSFP-DD (800GE)", "1000BASE-KX (1GE)", "2.5GBASE-KX (2.5GE)", "5GBASE-KR (5GE)", @@ -217919,14 +218255,14 @@ "100base-t1", "1000base-bx10-d", "1000base-bx10-u", - "1000base-cx", "1000base-cwdm", + "1000base-cx", "1000base-dwdm", "1000base-ex", - "1000base-sx", "1000base-lsx", "1000base-lx", "1000base-lx10", + "1000base-sx", "1000base-t", "1000base-tx", "1000base-zx", @@ -217961,6 +218297,7 @@ "100gbase-cr2", "100gbase-cr4", "100gbase-cr10", + "100gbase-cwdm4", "100gbase-dr", "100gbase-er4", "100gbase-fr1", @@ -217974,12 +218311,12 @@ "100gbase-zr", "200gbase-cr2", "200gbase-cr4", - "200gbase-sr2", - "200gbase-sr4", "200gbase-dr4", "200gbase-er4", "200gbase-fr4", "200gbase-lr4", + "200gbase-sr2", + "200gbase-sr4", "200gbase-vr2", "400gbase-cr4", "400gbase-dr4", @@ -218002,34 +218339,34 @@ "1000base-x-gbic", "1000base-x-sfp", "10gbase-x-sfpp", - "10gbase-x-xfp", "10gbase-x-xenpak", + "10gbase-x-xfp", "10gbase-x-x2", "25gbase-x-sfp28", - "50gbase-x-sfp56", "40gbase-x-qsfpp", "50gbase-x-sfp28", + "50gbase-x-sfp56", "100gbase-x-cfp", "100gbase-x-cfp2", - "200gbase-x-cfp2", - "400gbase-x-cfp2", "100gbase-x-cfp4", "100gbase-x-cxp", "100gbase-x-cpak", "100gbase-x-dsfp", - "100gbase-x-sfpdd", "100gbase-x-qsfp28", "100gbase-x-qsfpdd", + "100gbase-x-sfpdd", + "200gbase-x-cfp2", "200gbase-x-qsfp56", "200gbase-x-qsfpdd", "400gbase-x-qsfp112", "400gbase-x-qsfpdd", + "400gbase-x-cdfp", + "400gbase-x-cfp2", + "400gbase-x-cfp8", "400gbase-x-osfp", "400gbase-x-osfp-rhs", - "400gbase-x-cdfp", - "400gbase-x-cfp8", - "800gbase-x-qsfpdd", "800gbase-x-osfp", + "800gbase-x-qsfpdd", "1000base-kx", "2.5gbase-kx", "5gbase-kr", @@ -218117,8 +218454,8 @@ "other" ], "type": "string", - "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-DR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-DR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", - "x-spec-enum-id": "efa24ff9c7a39c40" + "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-BR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-BR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-cwdm4` - 100GBASE-CWDM4 (100GE)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", + "x-spec-enum-id": "c6dfa8e84dd05942" }, "enabled": { "type": "boolean" @@ -219778,7 +220115,8 @@ "description": "Adds support for custom fields and tags.", "properties": { "mac_address": { - "type": "string" + "type": "string", + "minLength": 1 }, "assigned_object_type": { "type": "string", @@ -227703,7 +228041,8 @@ "description": "Adds support for custom fields and tags.", "properties": { "mac_address": { - "type": "string" + "type": "string", + "minLength": 1 }, "assigned_object_type": { "type": "string", @@ -228649,7 +228988,6 @@ }, "key": { "type": "string", - "writeOnly": true, "maxLength": 40, "minLength": 40 }, @@ -231543,7 +231881,7 @@ }, "mark_utilized": { "type": "boolean", - "description": "Report space as 100% utilized" + "description": "Report space as fully utilized" } } }, @@ -231809,14 +232147,14 @@ "100base-t1", "1000base-bx10-d", "1000base-bx10-u", - "1000base-cx", "1000base-cwdm", + "1000base-cx", "1000base-dwdm", "1000base-ex", - "1000base-sx", "1000base-lsx", "1000base-lx", "1000base-lx10", + "1000base-sx", "1000base-t", "1000base-tx", "1000base-zx", @@ -231851,6 +232189,7 @@ "100gbase-cr2", "100gbase-cr4", "100gbase-cr10", + "100gbase-cwdm4", "100gbase-dr", "100gbase-er4", "100gbase-fr1", @@ -231864,12 +232203,12 @@ "100gbase-zr", "200gbase-cr2", "200gbase-cr4", - "200gbase-sr2", - "200gbase-sr4", "200gbase-dr4", "200gbase-er4", "200gbase-fr4", "200gbase-lr4", + "200gbase-sr2", + "200gbase-sr4", "200gbase-vr2", "400gbase-cr4", "400gbase-dr4", @@ -231892,34 +232231,34 @@ "1000base-x-gbic", "1000base-x-sfp", "10gbase-x-sfpp", - "10gbase-x-xfp", "10gbase-x-xenpak", + "10gbase-x-xfp", "10gbase-x-x2", "25gbase-x-sfp28", - "50gbase-x-sfp56", "40gbase-x-qsfpp", "50gbase-x-sfp28", + "50gbase-x-sfp56", "100gbase-x-cfp", "100gbase-x-cfp2", - "200gbase-x-cfp2", - "400gbase-x-cfp2", "100gbase-x-cfp4", "100gbase-x-cxp", "100gbase-x-cpak", "100gbase-x-dsfp", - "100gbase-x-sfpdd", "100gbase-x-qsfp28", "100gbase-x-qsfpdd", + "100gbase-x-sfpdd", + "200gbase-x-cfp2", "200gbase-x-qsfp56", "200gbase-x-qsfpdd", "400gbase-x-qsfp112", "400gbase-x-qsfpdd", + "400gbase-x-cdfp", + "400gbase-x-cfp2", + "400gbase-x-cfp8", "400gbase-x-osfp", "400gbase-x-osfp-rhs", - "400gbase-x-cdfp", - "400gbase-x-cfp8", - "800gbase-x-qsfpdd", "800gbase-x-osfp", + "800gbase-x-qsfpdd", "1000base-kx", "2.5gbase-kx", "5gbase-kr", @@ -232007,8 +232346,8 @@ "other" ], "type": "string", - "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-DR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-DR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", - "x-spec-enum-id": "efa24ff9c7a39c40" + "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-BR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-BR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-cwdm4` - 100GBASE-CWDM4 (100GE)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", + "x-spec-enum-id": "c6dfa8e84dd05942" }, "enabled": { "type": "boolean" @@ -232527,14 +232866,14 @@ "100base-t1", "1000base-bx10-d", "1000base-bx10-u", - "1000base-cx", "1000base-cwdm", + "1000base-cx", "1000base-dwdm", "1000base-ex", - "1000base-sx", "1000base-lsx", "1000base-lx", "1000base-lx10", + "1000base-sx", "1000base-t", "1000base-tx", "1000base-zx", @@ -232569,6 +232908,7 @@ "100gbase-cr2", "100gbase-cr4", "100gbase-cr10", + "100gbase-cwdm4", "100gbase-dr", "100gbase-er4", "100gbase-fr1", @@ -232582,12 +232922,12 @@ "100gbase-zr", "200gbase-cr2", "200gbase-cr4", - "200gbase-sr2", - "200gbase-sr4", "200gbase-dr4", "200gbase-er4", "200gbase-fr4", "200gbase-lr4", + "200gbase-sr2", + "200gbase-sr4", "200gbase-vr2", "400gbase-cr4", "400gbase-dr4", @@ -232610,34 +232950,34 @@ "1000base-x-gbic", "1000base-x-sfp", "10gbase-x-sfpp", - "10gbase-x-xfp", "10gbase-x-xenpak", + "10gbase-x-xfp", "10gbase-x-x2", "25gbase-x-sfp28", - "50gbase-x-sfp56", "40gbase-x-qsfpp", "50gbase-x-sfp28", + "50gbase-x-sfp56", "100gbase-x-cfp", "100gbase-x-cfp2", - "200gbase-x-cfp2", - "400gbase-x-cfp2", "100gbase-x-cfp4", "100gbase-x-cxp", "100gbase-x-cpak", "100gbase-x-dsfp", - "100gbase-x-sfpdd", "100gbase-x-qsfp28", "100gbase-x-qsfpdd", + "100gbase-x-sfpdd", + "200gbase-x-cfp2", "200gbase-x-qsfp56", "200gbase-x-qsfpdd", "400gbase-x-qsfp112", "400gbase-x-qsfpdd", + "400gbase-x-cdfp", + "400gbase-x-cfp2", + "400gbase-x-cfp8", "400gbase-x-osfp", "400gbase-x-osfp-rhs", - "400gbase-x-cdfp", - "400gbase-x-cfp8", - "800gbase-x-qsfpdd", "800gbase-x-osfp", + "800gbase-x-qsfpdd", "1000base-kx", "2.5gbase-kx", "5gbase-kr", @@ -232725,8 +233065,8 @@ "other" ], "type": "string", - "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-DR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-DR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", - "x-spec-enum-id": "efa24ff9c7a39c40" + "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-BR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-BR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-cwdm4` - 100GBASE-CWDM4 (100GE)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", + "x-spec-enum-id": "c6dfa8e84dd05942" }, "enabled": { "type": "boolean" @@ -244882,6 +245222,11 @@ "format": "date-time", "nullable": true }, + "key": { + "type": "string", + "maxLength": 40, + "minLength": 40 + }, "write_enabled": { "type": "boolean", "description": "Permit create/update/delete operations using this key" @@ -245028,7 +245373,6 @@ }, "key": { "type": "string", - "writeOnly": true, "maxLength": 40, "minLength": 40 }, @@ -251864,7 +252208,7 @@ }, "mark_utilized": { "type": "boolean", - "description": "Report space as 100% utilized" + "description": "Report space as fully utilized" } }, "required": [ @@ -252146,14 +252490,14 @@ "100base-t1", "1000base-bx10-d", "1000base-bx10-u", - "1000base-cx", "1000base-cwdm", + "1000base-cx", "1000base-dwdm", "1000base-ex", - "1000base-sx", "1000base-lsx", "1000base-lx", "1000base-lx10", + "1000base-sx", "1000base-t", "1000base-tx", "1000base-zx", @@ -252188,6 +252532,7 @@ "100gbase-cr2", "100gbase-cr4", "100gbase-cr10", + "100gbase-cwdm4", "100gbase-dr", "100gbase-er4", "100gbase-fr1", @@ -252201,12 +252546,12 @@ "100gbase-zr", "200gbase-cr2", "200gbase-cr4", - "200gbase-sr2", - "200gbase-sr4", "200gbase-dr4", "200gbase-er4", "200gbase-fr4", "200gbase-lr4", + "200gbase-sr2", + "200gbase-sr4", "200gbase-vr2", "400gbase-cr4", "400gbase-dr4", @@ -252229,34 +252574,34 @@ "1000base-x-gbic", "1000base-x-sfp", "10gbase-x-sfpp", - "10gbase-x-xfp", "10gbase-x-xenpak", + "10gbase-x-xfp", "10gbase-x-x2", "25gbase-x-sfp28", - "50gbase-x-sfp56", "40gbase-x-qsfpp", "50gbase-x-sfp28", + "50gbase-x-sfp56", "100gbase-x-cfp", "100gbase-x-cfp2", - "200gbase-x-cfp2", - "400gbase-x-cfp2", "100gbase-x-cfp4", "100gbase-x-cxp", "100gbase-x-cpak", "100gbase-x-dsfp", - "100gbase-x-sfpdd", "100gbase-x-qsfp28", "100gbase-x-qsfpdd", + "100gbase-x-sfpdd", + "200gbase-x-cfp2", "200gbase-x-qsfp56", "200gbase-x-qsfpdd", "400gbase-x-qsfp112", "400gbase-x-qsfpdd", + "400gbase-x-cdfp", + "400gbase-x-cfp2", + "400gbase-x-cfp8", "400gbase-x-osfp", "400gbase-x-osfp-rhs", - "400gbase-x-cdfp", - "400gbase-x-cfp8", - "800gbase-x-qsfpdd", "800gbase-x-osfp", + "800gbase-x-qsfpdd", "1000base-kx", "2.5gbase-kx", "5gbase-kr", @@ -252344,8 +252689,8 @@ "other" ], "type": "string", - "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-DR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-DR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", - "x-spec-enum-id": "efa24ff9c7a39c40" + "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-BR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-BR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-cwdm4` - 100GBASE-CWDM4 (100GE)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", + "x-spec-enum-id": "c6dfa8e84dd05942" }, "enabled": { "type": "boolean" @@ -252869,14 +253214,14 @@ "100base-t1", "1000base-bx10-d", "1000base-bx10-u", - "1000base-cx", "1000base-cwdm", + "1000base-cx", "1000base-dwdm", "1000base-ex", - "1000base-sx", "1000base-lsx", "1000base-lx", "1000base-lx10", + "1000base-sx", "1000base-t", "1000base-tx", "1000base-zx", @@ -252911,6 +253256,7 @@ "100gbase-cr2", "100gbase-cr4", "100gbase-cr10", + "100gbase-cwdm4", "100gbase-dr", "100gbase-er4", "100gbase-fr1", @@ -252924,12 +253270,12 @@ "100gbase-zr", "200gbase-cr2", "200gbase-cr4", - "200gbase-sr2", - "200gbase-sr4", "200gbase-dr4", "200gbase-er4", "200gbase-fr4", "200gbase-lr4", + "200gbase-sr2", + "200gbase-sr4", "200gbase-vr2", "400gbase-cr4", "400gbase-dr4", @@ -252952,34 +253298,34 @@ "1000base-x-gbic", "1000base-x-sfp", "10gbase-x-sfpp", - "10gbase-x-xfp", "10gbase-x-xenpak", + "10gbase-x-xfp", "10gbase-x-x2", "25gbase-x-sfp28", - "50gbase-x-sfp56", "40gbase-x-qsfpp", "50gbase-x-sfp28", + "50gbase-x-sfp56", "100gbase-x-cfp", "100gbase-x-cfp2", - "200gbase-x-cfp2", - "400gbase-x-cfp2", "100gbase-x-cfp4", "100gbase-x-cxp", "100gbase-x-cpak", "100gbase-x-dsfp", - "100gbase-x-sfpdd", "100gbase-x-qsfp28", "100gbase-x-qsfpdd", + "100gbase-x-sfpdd", + "200gbase-x-cfp2", "200gbase-x-qsfp56", "200gbase-x-qsfpdd", "400gbase-x-qsfp112", "400gbase-x-qsfpdd", + "400gbase-x-cdfp", + "400gbase-x-cfp2", + "400gbase-x-cfp8", "400gbase-x-osfp", "400gbase-x-osfp-rhs", - "400gbase-x-cdfp", - "400gbase-x-cfp8", - "800gbase-x-qsfpdd", "800gbase-x-osfp", + "800gbase-x-qsfpdd", "1000base-kx", "2.5gbase-kx", "5gbase-kr", @@ -253067,8 +253413,8 @@ "other" ], "type": "string", - "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-DR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-DR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", - "x-spec-enum-id": "efa24ff9c7a39c40" + "description": "* `virtual` - Virtual\n* `bridge` - Bridge\n* `lag` - Link Aggregation Group (LAG)\n* `100base-fx` - 100BASE-FX (10/100ME)\n* `100base-lfx` - 100BASE-LFX (10/100ME)\n* `100base-tx` - 100BASE-TX (10/100ME)\n* `100base-t1` - 100BASE-T1 (10/100ME)\n* `1000base-bx10-d` - 1000BASE-BX10-D (1GE BiDi Down)\n* `1000base-bx10-u` - 1000BASE-BX10-U (1GE BiDi Up)\n* `1000base-cwdm` - 1000BASE-CWDM (1GE)\n* `1000base-cx` - 1000BASE-CX (1GE DAC)\n* `1000base-dwdm` - 1000BASE-DWDM (1GE)\n* `1000base-ex` - 1000BASE-EX (1GE)\n* `1000base-lsx` - 1000BASE-LSX (1GE)\n* `1000base-lx` - 1000BASE-LX (1GE)\n* `1000base-lx10` - 1000BASE-LX10/LH (1GE)\n* `1000base-sx` - 1000BASE-SX (1GE)\n* `1000base-t` - 1000BASE-T (1GE)\n* `1000base-tx` - 1000BASE-TX (1GE)\n* `1000base-zx` - 1000BASE-ZX (1GE)\n* `2.5gbase-t` - 2.5GBASE-T (2.5GE)\n* `5gbase-t` - 5GBASE-T (5GE)\n* `10gbase-br-d` - 10GBASE-BR-D (10GE BiDi Down)\n* `10gbase-br-u` - 10GBASE-BR-U (10GE BiDi Up)\n* `10gbase-cx4` - 10GBASE-CX4 (10GE DAC)\n* `10gbase-er` - 10GBASE-ER (10GE)\n* `10gbase-lr` - 10GBASE-LR (10GE)\n* `10gbase-lrm` - 10GBASE-LRM (10GE)\n* `10gbase-lx4` - 10GBASE-LX4 (10GE)\n* `10gbase-sr` - 10GBASE-SR (10GE)\n* `10gbase-t` - 10GBASE-T (10GE)\n* `10gbase-zr` - 10GBASE-ZR (10GE)\n* `25gbase-cr` - 25GBASE-CR (25GE DAC)\n* `25gbase-er` - 25GBASE-ER (25GE)\n* `25gbase-lr` - 25GBASE-LR (25GE)\n* `25gbase-sr` - 25GBASE-SR (25GE)\n* `25gbase-t` - 25GBASE-T (25GE)\n* `40gbase-cr4` - 40GBASE-CR4 (40GE DAC)\n* `40gbase-er4` - 40GBASE-ER4 (40GE)\n* `40gbase-fr4` - 40GBASE-FR4 (40GE)\n* `40gbase-lr4` - 40GBASE-LR4 (40GE)\n* `40gbase-sr4` - 40GBASE-SR4 (40GE)\n* `50gbase-cr` - 50GBASE-CR (50GE DAC)\n* `50gbase-er` - 50GBASE-ER (50GE)\n* `50gbase-fr` - 50GBASE-FR (50GE)\n* `50gbase-lr` - 50GBASE-LR (50GE)\n* `50gbase-sr` - 50GBASE-SR (50GE)\n* `100gbase-cr1` - 100GBASE-CR1 (100GE DAC)\n* `100gbase-cr2` - 100GBASE-CR2 (100GE DAC)\n* `100gbase-cr4` - 100GBASE-CR4 (100GE DAC)\n* `100gbase-cr10` - 100GBASE-CR10 (100GE DAC)\n* `100gbase-cwdm4` - 100GBASE-CWDM4 (100GE)\n* `100gbase-dr` - 100GBASE-DR (100GE)\n* `100gbase-er4` - 100GBASE-ER4 (100GE)\n* `100gbase-fr1` - 100GBASE-FR1 (100GE)\n* `100gbase-lr1` - 100GBASE-LR1 (100GE)\n* `100gbase-lr4` - 100GBASE-LR4 (100GE)\n* `100gbase-sr1` - 100GBASE-SR1 (100GE)\n* `100gbase-sr1.2` - 100GBASE-SR1.2 (100GE BiDi)\n* `100gbase-sr2` - 100GBASE-SR2 (100GE)\n* `100gbase-sr4` - 100GBASE-SR4 (100GE)\n* `100gbase-sr10` - 100GBASE-SR10 (100GE)\n* `100gbase-zr` - 100GBASE-ZR (100GE)\n* `200gbase-cr2` - 200GBASE-CR2 (200GE)\n* `200gbase-cr4` - 200GBASE-CR4 (200GE)\n* `200gbase-dr4` - 200GBASE-DR4 (200GE)\n* `200gbase-er4` - 200GBASE-ER4 (200GE)\n* `200gbase-fr4` - 200GBASE-FR4 (200GE)\n* `200gbase-lr4` - 200GBASE-LR4 (200GE)\n* `200gbase-sr2` - 200GBASE-SR2 (200GE)\n* `200gbase-sr4` - 200GBASE-SR4 (200GE)\n* `200gbase-vr2` - 200GBASE-VR2 (200GE)\n* `400gbase-cr4` - 400GBASE-CR4 (400GE)\n* `400gbase-dr4` - 400GBASE-DR4 (400GE)\n* `400gbase-er8` - 400GBASE-ER8 (400GE)\n* `400gbase-fr4` - 400GBASE-FR4 (400GE)\n* `400gbase-fr8` - 400GBASE-FR8 (400GE)\n* `400gbase-lr4` - 400GBASE-LR4 (400GE)\n* `400gbase-lr8` - 400GBASE-LR8 (400GE)\n* `400gbase-sr4` - 400GBASE-SR4 (400GE)\n* `400gbase-sr4_2` - 400GBASE-SR4.2 (400GE BiDi)\n* `400gbase-sr8` - 400GBASE-SR8 (400GE)\n* `400gbase-sr16` - 400GBASE-SR16 (400GE)\n* `400gbase-vr4` - 400GBASE-VR4 (400GE)\n* `400gbase-zr` - 400GBASE-ZR (400GE)\n* `800gbase-cr8` - 800GBASE-CR8 (800GE)\n* `800gbase-dr8` - 800GBASE-DR8 (800GE)\n* `800gbase-sr8` - 800GBASE-SR8 (800GE)\n* `800gbase-vr8` - 800GBASE-VR8 (800GE)\n* `100base-x-sfp` - SFP (100ME)\n* `1000base-x-gbic` - GBIC (1GE)\n* `1000base-x-sfp` - SFP (1GE)\n* `10gbase-x-sfpp` - SFP+ (10GE)\n* `10gbase-x-xenpak` - XENPAK (10GE)\n* `10gbase-x-xfp` - XFP (10GE)\n* `10gbase-x-x2` - X2 (10GE)\n* `25gbase-x-sfp28` - SFP28 (25GE)\n* `40gbase-x-qsfpp` - QSFP+ (40GE)\n* `50gbase-x-sfp28` - QSFP28 (50GE)\n* `50gbase-x-sfp56` - SFP56 (50GE)\n* `100gbase-x-cfp` - CFP (100GE)\n* `100gbase-x-cfp2` - CFP2 (100GE)\n* `100gbase-x-cfp4` - CFP4 (100GE)\n* `100gbase-x-cxp` - CXP (100GE)\n* `100gbase-x-cpak` - Cisco CPAK (100GE)\n* `100gbase-x-dsfp` - DSFP (100GE)\n* `100gbase-x-qsfp28` - QSFP28 (100GE)\n* `100gbase-x-qsfpdd` - QSFP-DD (100GE)\n* `100gbase-x-sfpdd` - SFP-DD (100GE)\n* `200gbase-x-cfp2` - CFP2 (200GE)\n* `200gbase-x-qsfp56` - QSFP56 (200GE)\n* `200gbase-x-qsfpdd` - QSFP-DD (200GE)\n* `400gbase-x-qsfp112` - QSFP112 (400GE)\n* `400gbase-x-qsfpdd` - QSFP-DD (400GE)\n* `400gbase-x-cdfp` - CDFP (400GE)\n* `400gbase-x-cfp2` - CFP2 (400GE)\n* `400gbase-x-cfp8` - CPF8 (400GE)\n* `400gbase-x-osfp` - OSFP (400GE)\n* `400gbase-x-osfp-rhs` - OSFP-RHS (400GE)\n* `800gbase-x-osfp` - OSFP (800GE)\n* `800gbase-x-qsfpdd` - QSFP-DD (800GE)\n* `1000base-kx` - 1000BASE-KX (1GE)\n* `2.5gbase-kx` - 2.5GBASE-KX (2.5GE)\n* `5gbase-kr` - 5GBASE-KR (5GE)\n* `10gbase-kr` - 10GBASE-KR (10GE)\n* `10gbase-kx4` - 10GBASE-KX4 (10GE)\n* `25gbase-kr` - 25GBASE-KR (25GE)\n* `40gbase-kr4` - 40GBASE-KR4 (40GE)\n* `50gbase-kr` - 50GBASE-KR (50GE)\n* `100gbase-kp4` - 100GBASE-KP4 (100GE)\n* `100gbase-kr2` - 100GBASE-KR2 (100GE)\n* `100gbase-kr4` - 100GBASE-KR4 (100GE)\n* `ieee802.11a` - IEEE 802.11a\n* `ieee802.11g` - IEEE 802.11b/g\n* `ieee802.11n` - IEEE 802.11n (Wi-Fi 4)\n* `ieee802.11ac` - IEEE 802.11ac (Wi-Fi 5)\n* `ieee802.11ad` - IEEE 802.11ad (WiGig)\n* `ieee802.11ax` - IEEE 802.11ax (Wi-Fi 6)\n* `ieee802.11ay` - IEEE 802.11ay (WiGig)\n* `ieee802.11be` - IEEE 802.11be (Wi-Fi 7)\n* `ieee802.15.1` - IEEE 802.15.1 (Bluetooth)\n* `ieee802.15.4` - IEEE 802.15.4 (LR-WPAN)\n* `other-wireless` - Other (Wireless)\n* `gsm` - GSM\n* `cdma` - CDMA\n* `lte` - LTE\n* `4g` - 4G\n* `5g` - 5G\n* `sonet-oc3` - OC-3/STM-1\n* `sonet-oc12` - OC-12/STM-4\n* `sonet-oc48` - OC-48/STM-16\n* `sonet-oc192` - OC-192/STM-64\n* `sonet-oc768` - OC-768/STM-256\n* `sonet-oc1920` - OC-1920/STM-640\n* `sonet-oc3840` - OC-3840/STM-1234\n* `1gfc-sfp` - SFP (1GFC)\n* `2gfc-sfp` - SFP (2GFC)\n* `4gfc-sfp` - SFP (4GFC)\n* `8gfc-sfpp` - SFP+ (8GFC)\n* `16gfc-sfpp` - SFP+ (16GFC)\n* `32gfc-sfp28` - SFP28 (32GFC)\n* `32gfc-sfpp` - SFP+ (32GFC)\n* `64gfc-qsfpp` - QSFP+ (64GFC)\n* `64gfc-sfpdd` - SFP-DD (64GFC)\n* `64gfc-sfpp` - SFP+ (64GFC)\n* `128gfc-qsfp28` - QSFP28 (128GFC)\n* `infiniband-sdr` - SDR (2 Gbps)\n* `infiniband-ddr` - DDR (4 Gbps)\n* `infiniband-qdr` - QDR (8 Gbps)\n* `infiniband-fdr10` - FDR10 (10 Gbps)\n* `infiniband-fdr` - FDR (13.5 Gbps)\n* `infiniband-edr` - EDR (25 Gbps)\n* `infiniband-hdr` - HDR (50 Gbps)\n* `infiniband-ndr` - NDR (100 Gbps)\n* `infiniband-xdr` - XDR (250 Gbps)\n* `t1` - T1 (1.544 Mbps)\n* `e1` - E1 (2.048 Mbps)\n* `t3` - T3 (45 Mbps)\n* `e3` - E3 (34 Mbps)\n* `xdsl` - xDSL\n* `docsis` - DOCSIS\n* `moca` - MoCA\n* `bpon` - BPON (622 Mbps / 155 Mbps)\n* `epon` - EPON (1 Gbps)\n* `10g-epon` - 10G-EPON (10 Gbps)\n* `gpon` - GPON (2.5 Gbps / 1.25 Gbps)\n* `xg-pon` - XG-PON (10 Gbps / 2.5 Gbps)\n* `xgs-pon` - XGS-PON (10 Gbps)\n* `ng-pon2` - NG-PON2 (TWDM-PON) (4x10 Gbps)\n* `25g-pon` - 25G-PON (25 Gbps)\n* `50g-pon` - 50G-PON (50 Gbps)\n* `cisco-stackwise` - Cisco StackWise\n* `cisco-stackwise-plus` - Cisco StackWise Plus\n* `cisco-flexstack` - Cisco FlexStack\n* `cisco-flexstack-plus` - Cisco FlexStack Plus\n* `cisco-stackwise-80` - Cisco StackWise-80\n* `cisco-stackwise-160` - Cisco StackWise-160\n* `cisco-stackwise-320` - Cisco StackWise-320\n* `cisco-stackwise-480` - Cisco StackWise-480\n* `cisco-stackwise-1t` - Cisco StackWise-1T\n* `juniper-vcp` - Juniper VCP\n* `extreme-summitstack` - Extreme SummitStack\n* `extreme-summitstack-128` - Extreme SummitStack-128\n* `extreme-summitstack-256` - Extreme SummitStack-256\n* `extreme-summitstack-512` - Extreme SummitStack-512\n* `other` - Other", + "x-spec-enum-id": "c6dfa8e84dd05942" }, "enabled": { "type": "boolean" diff --git a/docs/best-practices/performance-handbook.md b/docs/best-practices/performance-handbook.md index 0a212031f..5611fb14d 100644 --- a/docs/best-practices/performance-handbook.md +++ b/docs/best-practices/performance-handbook.md @@ -141,17 +141,39 @@ Complex API requests, which pull in many related objects, generate a relatively NetBox's read-only [GraphQL API](../integrations/graphql-api.md) offers an alternative to its REST API, and provides a very flexible means of retrieving data. GraphQL enables the client to request any object from a single endpoint, specifying only the desired attributes and relations. Many users prefer this to the more rigid structure of the REST API, but it's important to understand the trade-offs of crafting complex queries. +#### Request Only the Necessary Fields + +For optimal performance, craft your GraphQL queries to return only the fields needed by the client. This will reduce the overall query time, especially when omitting related objects. + #### Avoid Overly Complex Queries The primary benefit of the GraphQL API is that it allows the client to offload to the server the work of stitching together various related objects, which would require the client to make multiple requests to different endpoints if using the REST API. However, this advantage does not come for free: The more information that is requested in a single query, the more work the server needs to do to fetch the raw data from the database and render it into a GraphQL response. Very complex queries can yield dozens or hundreds of SQL queries on the backend, which increase the time it takes to render a response. While it can be tempting to pack as much data as possible into a single GraphQL query, realize that there is a balance to be struck between minimizing the number of queries needed and avoiding complexity in the interest of performance. For example, while it is possible to retrieve via a single GraphQL API request all the IP addresses and all attached cables for every device in a site, it is probably more efficient (often _much_ more efficient) to make two or three separate requests and correlate the data locally. +#### Use Filters + +You can specify filters when making a GraphQL query to limit the set of objects returned. This works a bit differently from the REST API, as filters are declared inside the query statement rather than appended to the URL, but the concept is the same. For example, to return only active sites: + +```graphql +query { + site_list( + filters: { + status: STATUS_ACTIVE + } + ) { + name + } +} +``` + +This returns only sites with a status of "active" and avoid needing to parse through all the others. For further information about filters, see the [GraphQL API documentation](../integrations/graphql-api.md). + #### Employ Pagination Like the REST API, the GraphQL API supports pagination. Queries which return a large number of objects should employ pagination to limit the size of each response. -``` +```graphql { device_list( pagination: {limit: 100} diff --git a/docs/configuration/default-values.md b/docs/configuration/default-values.md index 1d1992a8e..c1ca904e9 100644 --- a/docs/configuration/default-values.md +++ b/docs/configuration/default-values.md @@ -4,7 +4,7 @@ This parameter controls the content and layout of user's default dashboard. Once the dashboard has been created, the user is free to customize it as they please by adding, removing, and reconfiguring widgets. -This parameter must specify an iterable of dictionaries, each representing a discrete dashboard widget and its configuration. The follow widget attributes are supported: +This parameter must specify an iterable of dictionaries, each representing a discrete dashboard widget and its configuration. The following widget attributes are supported: * `widget`: Dotted path to the Python class (required) * `width`: Default widget width (between 1 and 12, inclusive) @@ -63,6 +63,8 @@ DEFAULT_USER_PREFERENCES = { For a complete list of available preferences, log into NetBox and navigate to `/user/preferences/`. A period in a preference name indicates a level of nesting in the JSON data. The example above maps to `pagination.per_page`. +See also: [Clearing table preferences](../features/user-preferences.md#clearing-table-preferences) for resolving errors caused by saved table columns or ordering. + --- ## PAGINATE_COUNT diff --git a/docs/development/user-preferences.md b/docs/development/user-preferences.md index deb469bfb..9944b5060 100644 --- a/docs/development/user-preferences.md +++ b/docs/development/user-preferences.md @@ -2,6 +2,8 @@ The `users.UserConfig` model holds individual preferences for each user in the form of JSON data. This page serves as a manifest of all recognized user preferences in NetBox. +For end‑user guidance on resetting saved table layouts, see [Features > User Preferences](../features/user-preferences.md#clearing-table-preferences). + ## Available Preferences | Name | Description | diff --git a/docs/features/customization.md b/docs/features/customization.md index 1fbace3c5..4ea39691c 100644 --- a/docs/features/customization.md +++ b/docs/features/customization.md @@ -2,6 +2,8 @@ While NetBox strives to meet the needs of every network, the needs of users to cater to their own unique environments cannot be ignored. NetBox was built with this in mind, and can be customized in many ways to better suit your particular needs. +For end‑user personalization topics (bookmarks, table preferences, language, CSV delimiter, and more), see [Features > User Preferences](../features/user-preferences.md). + ## Tags Most objects in NetBox can be assigned user-created tags to aid with organization and filtering. Tag values are completely arbitrary: They may be used to store data in key-value pairs, or they may be employed simply as labels against which objects can be filtered. Each tag can also be assigned a color for quicker differentiation in the user interface. @@ -18,10 +20,6 @@ The `tag` filter can be specified multiple times to match only objects which hav GET /api/dcim/devices/?tag=monitored&tag=deprecated ``` -## Bookmarks - -Users can bookmark their most commonly visited objects for convenient access. Bookmarks are listed under a user's profile, and can be displayed with custom filtering and ordering on the user's personal dashboard. - ## Custom Fields While NetBox provides a rather extensive data model out of the box, the need may arise to store certain additional data associated with NetBox objects. For example, you might need to record the invoice ID alongside an installed device, or record an approving authority when creating a new IP prefix. NetBox administrators can create custom fields on built-in objects to meet these needs. @@ -38,7 +36,7 @@ Custom links allow you to conveniently reference external resources related to N http://server.local/vms/?name={{ object.name }} ``` -Now, when viewing a virtual machine in NetBox, a user will see a handy button with the chosen title and link (complete with the name of the VM being viewed). Both the text and URL of custom links can be templatized in this manner, and custom links can be grouped together into dropdowns for more efficient display. +Now, when viewing a virtual machine in NetBox, a user will see a handy button with the chosen title and link (complete with the name of the VM being viewed). Both the text and URL of custom links can be templatized in this manner, and custom links can be grouped together into dropdowns for a more efficient display. To learn more about this feature, check out the [custom link documentation](../customization/custom-links.md). diff --git a/docs/features/user-preferences.md b/docs/features/user-preferences.md new file mode 100644 index 000000000..6c0a2884f --- /dev/null +++ b/docs/features/user-preferences.md @@ -0,0 +1,63 @@ +# User Preferences + +NetBox stores per‑user options that control aspects of the web interface and data display. Preferences persist across sessions and can be managed under **User → Preferences**. + +## Table configurations + +When a list view is configured using **Configure**, NetBox records the selected columns and ordering as per‑user table preferences for that table. These preferences are applied automatically on subsequent visits. + +### Clearing table preferences + +Saved table preferences may need to be reset, for example, if a table fails to render or after an upgrade that changes available columns. + +To clear saved preferences for one or more tables: + +1. Click the username in the top‑right corner. +2. Select **Preferences** from the dropdown. +3. Scroll to the **Table Configurations** section. +4. Select the tables to reset. +5. Click **Submit** to clear the selected preferences. + +After clearing preferences, reopen the list view and use **Configure** to set the desired columns and ordering. + +!!! note + Per‑user table preferences are distinct from **Table Configs**, which are named, reusable configurations managed under *Customization → Table Configs*. Clearing preferences does not delete any Table Configs. See [Table Configs](../models/extras/tableconfig.md) for details. + +## Other preferences + +### Language +Selects the user interface language from installed translations (subject to system configuration). + +### Page length +Sets the default number of rows displayed on paginated tables. + +### Paginator placement +Controls where pagination controls are rendered relative to a table. + +### HTMX navigation (experimental) +Enables partial‑page navigation for supported views. Disable this preference if unexpected behavior is observed. + +### Striped table rows +Toggles alternating row backgrounds on tables. + +### Data format (raw views) +Sets the default format (JSON or YAML) when rendering raw data blocks. + +### CSV delimiter +Overrides the delimiter used when exporting CSV data. + +## Bookmarks + +Users can bookmark frequently visited objects for convenient access. Bookmarks appear under the user menu and can be displayed on the personal dashboard using the bookmarks' widget. See [Bookmark](../models/extras/bookmark.md) for model details. + +## Notifications and subscriptions + +Users may subscribe to objects to receive notifications when changes occur. Notifications are listed under the user menu and can be marked as read or deleted. See [Features > Notifications](notifications.md) and the data‑model references for [Subscription](../models/extras/subscription.md) and [Notification](../models/extras/notification.md). + +## Admin defaults + +Administrators can define defaults for new users via [`DEFAULT_USER_PREFERENCES`](../configuration/default-values.md#default_user_preferences). Users may override these values under their own preferences. + +## See also + +- [Development > User Preferences](../development/user-preferences.md) (manifest of recognized preference keys) diff --git a/docs/models/extras/tableconfig.md b/docs/models/extras/tableconfig.md index e5484ec64..b12fc4a4c 100644 --- a/docs/models/extras/tableconfig.md +++ b/docs/models/extras/tableconfig.md @@ -4,6 +4,9 @@ This object represents the saved configuration of an object table in NetBox. Tab For example, you might wish to create a table config for the devices list to assist in inventory tasks. This view might show the device name, location, serial number, and asset tag, but omit operational details like IP addresses. Once applied, this table config can be saved for reuse in future audits. +!!! note + Per‑user table preferences (columns and ordering remembered for an individual user) are distinct from Table Configs. If a list view fails to render due to outdated saved preferences, see [Clearing table preferences](../../features/user-preferences.md#clearing-table-preferences). + ## Fields ### Name @@ -20,7 +23,7 @@ The type of NetBox object to which the table config pertains. ### Table -The name of the specific table to which the table config pertains. (Some NetBox object use multiple tables.) +The name of the specific table to which the table config pertains. (Some NetBox objects use multiple tables.) ### Weight diff --git a/docs/plugins/development/filtersets.md b/docs/plugins/development/filtersets.md index e19b3a733..a4b9e1375 100644 --- a/docs/plugins/development/filtersets.md +++ b/docs/plugins/development/filtersets.md @@ -1,6 +1,6 @@ # Filters & Filter Sets -Filter sets define the mechanisms available for filtering or searching through a set of objects in NetBox. For instance, sites can be filtered by their parent region or group, status, facility ID, and so on. The same filter set is used consistently for a model whether the request is made via the UI or REST API. (Note that the GraphQL API uses a separate filter class.) NetBox employs the [django-filters2](https://django-tables2.readthedocs.io/en/latest/) library to define filter sets. +Filter sets define the mechanisms available for filtering or searching through a set of objects in NetBox. For instance, sites can be filtered by their parent region or group, status, facility ID, and so on. The same filter set is used consistently for a model whether the request is made via the UI or REST API. (Note that the GraphQL API uses a separate filter class.) NetBox employs the [django-filter](https://django-filter.readthedocs.io/en/stable/) library to define filter sets. ## FilterSet Classes diff --git a/docs/release-notes/version-4.4.md b/docs/release-notes/version-4.4.md index 0c95e9fcf..87707c924 100644 --- a/docs/release-notes/version-4.4.md +++ b/docs/release-notes/version-4.4.md @@ -1,5 +1,34 @@ # NetBox v4.4 +## v4.4.2 (2025-09-30) + +### Enhancements + +* [#17010](https://github.com/netbox-community/netbox/issues/17010) - Show admin navigation menu items only for staff & superusers +* [#19590](https://github.com/netbox-community/netbox/issues/19590) - Add columns for device site & location to device component tables +* [#19765](https://github.com/netbox-community/netbox/issues/19765) - Linkify assigned object types under saved filter view +* [#20308](https://github.com/netbox-community/netbox/issues/20308) - Add a hotkey (`/`) for the global search field +* [#20332](https://github.com/netbox-community/netbox/issues/20332) - Add a "none" option to object tag filters +* [#20380](https://github.com/netbox-community/netbox/issues/20380) - Introduce the `SENTRY_CONFIG` configuration parameter +* [#20412](https://github.com/netbox-community/netbox/issues/20412) - Linkify cluster type on virtual machine detail view +* [#20438](https://github.com/netbox-community/netbox/issues/20438) - Add `facility` field to bulk edit forms for sites and locations + +### Bug Fixes + +* [#18878](https://github.com/netbox-community/netbox/issues/18878) - Automatically assign a designated primary MAC address upon creation of a new interface +* [#20243](https://github.com/netbox-community/netbox/issues/20243) - Prevent scheduled system jobs from re-running multiple times +* [#20253](https://github.com/netbox-community/netbox/issues/20253) - Fix support for filtering object contact assignments in GraphQL API +* [#20365](https://github.com/netbox-community/netbox/issues/20365) - Address various inaccuracies in generated OpenAPI schema +* [#20375](https://github.com/netbox-community/netbox/issues/20375) - Preserve filter parameters when performing bulk operations +* [#20390](https://github.com/netbox-community/netbox/issues/20390) - Fix styling of page size selection dropdown +* [#20392](https://github.com/netbox-community/netbox/issues/20392) - Clean up ordering of interface type options +* [#20398](https://github.com/netbox-community/netbox/issues/20398) - Fix misleading error reporting for min/max custom field values +* [#20419](https://github.com/netbox-community/netbox/issues/20419) - Correct action buttons for child object views +* [#20425](https://github.com/netbox-community/netbox/issues/20425) - Fix Markdown preview functionality within "quick add" modal +* [#20441](https://github.com/netbox-community/netbox/issues/20441) - Fix display of the "groups" column in contact assignments table + +--- + ## v4.4.1 (2025-09-16) ### Enhancements diff --git a/mkdocs.yml b/mkdocs.yml index 4df1b5d43..fd6d7e4f2 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -86,6 +86,7 @@ nav: - Change Logging: 'features/change-logging.md' - Journaling: 'features/journaling.md' - Event Rules: 'features/event-rules.md' + - User Preferences: 'features/user-preferences.md' - Notifications: 'features/notifications.md' - Background Jobs: 'features/background-jobs.md' - Auth & Permissions: 'features/authentication-permissions.md' diff --git a/netbox/circuits/apps.py b/netbox/circuits/apps.py index 4d5f177e2..7b29a1509 100644 --- a/netbox/circuits/apps.py +++ b/netbox/circuits/apps.py @@ -1,5 +1,7 @@ from django.apps import AppConfig +from netbox import denormalized + class CircuitsConfig(AppConfig): name = "circuits" @@ -8,6 +10,16 @@ class CircuitsConfig(AppConfig): def ready(self): from netbox.models.features import register_models from . import signals, search # noqa: F401 + from .models import CircuitTermination # Register models register_models(*self.get_models()) + + denormalized.register(CircuitTermination, '_site', { + '_region': 'region', + '_site_group': 'group', + }) + + denormalized.register(CircuitTermination, '_location', { + '_site': 'site', + }) diff --git a/netbox/core/api/schema.py b/netbox/core/api/schema.py index 0c59da5a1..c61675cf3 100644 --- a/netbox/core/api/schema.py +++ b/netbox/core/api/schema.py @@ -282,18 +282,18 @@ class FixSerializedPKRelatedField(OpenApiSerializerFieldExtension): class FixIntegerRangeSerializerSchema(OpenApiSerializerExtension): target_class = 'netbox.api.fields.IntegerRangeSerializer' + match_subclasses = True def map_serializer(self, auto_schema: 'AutoSchema', direction: Direction) -> _SchemaType: + # One range = two integers; many=True will wrap this in an outer array return { 'type': 'array', 'items': { - 'type': 'array', - 'items': { - 'type': 'integer', - }, - 'minItems': 2, - 'maxItems': 2, + 'type': 'integer', }, + 'minItems': 2, + 'maxItems': 2, + 'example': [10, 20], } diff --git a/netbox/core/api/serializers_/tasks.py b/netbox/core/api/serializers_/tasks.py index 85fb682c9..f5f941e61 100644 --- a/netbox/core/api/serializers_/tasks.py +++ b/netbox/core/api/serializers_/tasks.py @@ -13,7 +13,7 @@ class BackgroundTaskSerializer(serializers.Serializer): url = serializers.HyperlinkedIdentityField( view_name='core-api:rqtask-detail', lookup_field='id', - lookup_url_kwarg='pk' + lookup_url_kwarg='id' ) description = serializers.CharField() origin = serializers.CharField() diff --git a/netbox/core/api/views.py b/netbox/core/api/views.py index e9569a717..3d3462b7b 100644 --- a/netbox/core/api/views.py +++ b/netbox/core/api/views.py @@ -5,7 +5,7 @@ from django_rq.queues import get_redis_connection from django_rq.settings import QUEUES_LIST from django_rq.utils import get_statistics from drf_spectacular.types import OpenApiTypes -from drf_spectacular.utils import extend_schema +from drf_spectacular.utils import OpenApiParameter, extend_schema from rest_framework import viewsets from rest_framework.decorators import action from rest_framework.exceptions import PermissionDenied @@ -24,6 +24,7 @@ from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired from netbox.api.metadata import ContentTypeMetadata from netbox.api.pagination import LimitOffsetListPagination from netbox.api.viewsets import NetBoxModelViewSet, NetBoxReadOnlyModelViewSet + from . import serializers @@ -117,29 +118,49 @@ class BaseRQViewSet(viewsets.ViewSet): def get_serializer(self, *args, **kwargs): """ Return the serializer instance that should be used for validating and - deserializing input, and for serializing output. + deserializing input and for serializing output. """ serializer_class = self.get_serializer_class() kwargs['context'] = self.get_serializer_context() return serializer_class(*args, **kwargs) + def get_serializer_class(self): + """ + Return the class to use for the serializer. + """ + return self.serializer_class + + def get_serializer_context(self): + """ + Extra context provided to the serializer class. + """ + return { + 'request': self.request, + 'format': self.format_kwarg, + 'view': self, + } + class BackgroundQueueViewSet(BaseRQViewSet): """ Retrieve a list of RQ Queues. - Note: Queue names are not URL safe so not returning a detail view. + Note: Queue names are not URL safe, so not returning a detail view. """ serializer_class = serializers.BackgroundQueueSerializer lookup_field = 'name' lookup_value_regex = r'[\w.@+-]+' def get_view_name(self): - return "Background Queues" + return 'Background Queues' def get_data(self): - return get_statistics(run_maintenance_tasks=True)["queues"] + return get_statistics(run_maintenance_tasks=True)['queues'] - @extend_schema(responses={200: OpenApiTypes.OBJECT}) + @extend_schema( + operation_id='core_background_queues_retrieve_by_name', + parameters=[OpenApiParameter(name='name', type=OpenApiTypes.STR, location=OpenApiParameter.PATH)], + responses={200: OpenApiTypes.OBJECT}, + ) def retrieve(self, request, name): data = self.get_data() if not data: @@ -161,12 +182,17 @@ class BackgroundWorkerViewSet(BaseRQViewSet): lookup_field = 'name' def get_view_name(self): - return "Background Workers" + return 'Background Workers' def get_data(self): config = QUEUES_LIST[0] return Worker.all(get_redis_connection(config['connection_config'])) + @extend_schema( + operation_id='core_background_workers_retrieve_by_name', + parameters=[OpenApiParameter(name='name', type=OpenApiTypes.STR, location=OpenApiParameter.PATH)], + responses={200: OpenApiTypes.OBJECT}, + ) def retrieve(self, request, name): # all the RQ queues should use the same connection config = QUEUES_LIST[0] @@ -184,9 +210,10 @@ class BackgroundTaskViewSet(BaseRQViewSet): Retrieve a list of RQ Tasks. """ serializer_class = serializers.BackgroundTaskSerializer + lookup_field = 'id' def get_view_name(self): - return "Background Tasks" + return 'Background Tasks' def get_data(self): return get_rq_jobs() @@ -199,45 +226,53 @@ class BackgroundTaskViewSet(BaseRQViewSet): return task - @extend_schema(responses={200: OpenApiTypes.OBJECT}) - def retrieve(self, request, pk): + @extend_schema( + operation_id='core_background_tasks_retrieve_by_id', + parameters=[OpenApiParameter(name='id', type=OpenApiTypes.STR, location=OpenApiParameter.PATH)], + responses={200: OpenApiTypes.OBJECT}, + ) + def retrieve(self, request, id): """ Retrieve the details of the specified RQ Task. """ - task = self.get_task_from_id(pk) + task = self.get_task_from_id(id) serializer = self.serializer_class(task, context={'request': request}) return Response(serializer.data) - @action(methods=["POST"], detail=True) - def delete(self, request, pk): + @extend_schema(parameters=[OpenApiParameter(name='id', type=OpenApiTypes.STR, location=OpenApiParameter.PATH)]) + @action(methods=['POST'], detail=True) + def delete(self, request, id): """ Delete the specified RQ Task. """ - delete_rq_job(pk) + delete_rq_job(id) return HttpResponse(status=200) - @action(methods=["POST"], detail=True) - def requeue(self, request, pk): + @extend_schema(parameters=[OpenApiParameter(name='id', type=OpenApiTypes.STR, location=OpenApiParameter.PATH)]) + @action(methods=['POST'], detail=True) + def requeue(self, request, id): """ Requeues the specified RQ Task. """ - requeue_rq_job(pk) + requeue_rq_job(id) return HttpResponse(status=200) - @action(methods=["POST"], detail=True) - def enqueue(self, request, pk): + @extend_schema(parameters=[OpenApiParameter(name='id', type=OpenApiTypes.STR, location=OpenApiParameter.PATH)]) + @action(methods=['POST'], detail=True) + def enqueue(self, request, id): """ Enqueues the specified RQ Task. """ - enqueue_rq_job(pk) + enqueue_rq_job(id) return HttpResponse(status=200) - @action(methods=["POST"], detail=True) - def stop(self, request, pk): + @extend_schema(parameters=[OpenApiParameter(name='id', type=OpenApiTypes.STR, location=OpenApiParameter.PATH)]) + @action(methods=['POST'], detail=True) + def stop(self, request, id): """ Stops the specified RQ Task. """ - stopped_jobs = stop_rq_job(pk) + stopped_jobs = stop_rq_job(id) if len(stopped_jobs) == 1: return HttpResponse(status=200) else: diff --git a/netbox/core/graphql/mixins.py b/netbox/core/graphql/mixins.py index 6c9042313..bbcf1954c 100644 --- a/netbox/core/graphql/mixins.py +++ b/netbox/core/graphql/mixins.py @@ -3,12 +3,12 @@ from typing import Annotated, List, TYPE_CHECKING import strawberry import strawberry_django from django.contrib.contenttypes.models import ContentType +from strawberry.types import Info from core.models import ObjectChange if TYPE_CHECKING: - from core.graphql.types import DataFileType, DataSourceType - from netbox.core.graphql.types import ObjectChangeType + from core.graphql.types import DataFileType, DataSourceType, ObjectChangeType __all__ = ( 'ChangelogMixin', @@ -20,7 +20,7 @@ __all__ = ( class ChangelogMixin: @strawberry_django.field - def changelog(self, info) -> List[Annotated["ObjectChangeType", strawberry.lazy('.types')]]: # noqa: F821 + def changelog(self, info: Info) -> List[Annotated['ObjectChangeType', strawberry.lazy('.types')]]: # noqa: F821 content_type = ContentType.objects.get_for_model(self) object_changes = ObjectChange.objects.filter( changed_object_type=content_type, @@ -31,5 +31,5 @@ class ChangelogMixin: @strawberry.type class SyncedDataMixin: - data_source: Annotated["DataSourceType", strawberry.lazy('core.graphql.types')] | None - data_file: Annotated["DataFileType", strawberry.lazy('core.graphql.types')] | None + data_source: Annotated['DataSourceType', strawberry.lazy('core.graphql.types')] | None + data_file: Annotated['DataFileType', strawberry.lazy('core.graphql.types')] | None diff --git a/netbox/core/migrations/0019_configrevision_active.py b/netbox/core/migrations/0019_configrevision_active.py new file mode 100644 index 000000000..b911aaa53 --- /dev/null +++ b/netbox/core/migrations/0019_configrevision_active.py @@ -0,0 +1,48 @@ +# Generated by Django 5.2.5 on 2025-09-09 16:48 + +from django.db import migrations, models + + +def get_active(apps, schema_editor): + from django.core.cache import cache + ConfigRevision = apps.get_model('core', 'ConfigRevision') + version = None + revision = None + + # Try and get the latest version from cache + try: + version = cache.get('config_version') + except Exception: + pass + + # If there is a version in cache, attempt to set revision to the current version from cache + # If the version in cache does not exist or there is no version, try the lastest revision in the database + if not version or (version and not (revision := ConfigRevision.objects.filter(pk=version).first())): + revision = ConfigRevision.objects.order_by('-created').first() + + # If there is a revision set, set the active revision + if revision: + revision.active = True + revision.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0018_concrete_objecttype'), + ] + + operations = [ + migrations.AddField( + model_name='configrevision', + name='active', + field=models.BooleanField(default=False), + ), + migrations.RunPython(code=get_active, reverse_code=migrations.RunPython.noop), + migrations.AddConstraint( + model_name='configrevision', + constraint=models.UniqueConstraint( + condition=models.Q(('active', True)), fields=('active',), name='unique_active_config_revision' + ), + ), + ] diff --git a/netbox/core/models/config.py b/netbox/core/models/config.py index b2381ae40..c99521536 100644 --- a/netbox/core/models/config.py +++ b/netbox/core/models/config.py @@ -14,6 +14,9 @@ class ConfigRevision(models.Model): """ An atomic revision of NetBox's configuration. """ + active = models.BooleanField( + default=False + ) created = models.DateTimeField( verbose_name=_('created'), auto_now_add=True @@ -35,6 +38,13 @@ class ConfigRevision(models.Model): ordering = ['-created'] verbose_name = _('config revision') verbose_name_plural = _('config revisions') + constraints = [ + models.UniqueConstraint( + fields=('active',), + condition=models.Q(active=True), + name='unique_active_config_revision', + ) + ] def __str__(self): if not self.pk: @@ -59,8 +69,13 @@ class ConfigRevision(models.Model): """ cache.set('config', self.data, None) cache.set('config_version', self.pk, None) + + # Set all instances of ConfigRevision to false and set this instance to true + ConfigRevision.objects.all().update(active=False) + ConfigRevision.objects.filter(pk=self.pk).update(active=True) + activate.alters_data = True @property def is_active(self): - return cache.get('config_version') == self.pk + return self.active diff --git a/netbox/core/models/object_types.py b/netbox/core/models/object_types.py index bb031b4eb..ec9e2fef8 100644 --- a/netbox/core/models/object_types.py +++ b/netbox/core/models/object_types.py @@ -5,7 +5,7 @@ from django.contrib.contenttypes.models import ContentType from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.indexes import GinIndex from django.core.exceptions import ObjectDoesNotExist -from django.db import models +from django.db import connection, models from django.db.models import Q from django.utils.translation import gettext as _ @@ -66,6 +66,14 @@ class ObjectTypeManager(models.Manager): """ from netbox.models.features import get_model_features, model_is_public + # TODO: Remove this in NetBox v5.0 + # If the ObjectType table has not yet been provisioned (e.g. because we're in a pre-v4.4 migration), + # fall back to ContentType. + if 'core_objecttype' not in connection.introspection.table_names(): + ct = ContentType.objects.get_for_model(model, for_concrete_model=for_concrete_model) + ct.features = get_model_features(ct.model_class()) + return ct + if not inspect.isclass(model): model = model.__class__ opts = self._get_opts(model, for_concrete_model) diff --git a/netbox/core/plugins.py b/netbox/core/plugins.py index 0a5bd8fe3..15f640b86 100644 --- a/netbox/core/plugins.py +++ b/netbox/core/plugins.py @@ -1,6 +1,5 @@ import datetime import importlib -import importlib.util from dataclasses import dataclass, field from typing import Optional diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index 328b09a6c..edff95d9a 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -1163,14 +1163,14 @@ class InterfaceTypeChoices(ChoiceSet): ( (TYPE_1GE_BX10_D, '1000BASE-BX10-D (1GE BiDi Down)'), (TYPE_1GE_BX10_U, '1000BASE-BX10-U (1GE BiDi Up)'), - (TYPE_1GE_CX, '1000BASE-CX (1GE DAC)'), (TYPE_1GE_CWDM, '1000BASE-CWDM (1GE)'), + (TYPE_1GE_CX, '1000BASE-CX (1GE DAC)'), (TYPE_1GE_DWDM, '1000BASE-DWDM (1GE)'), (TYPE_1GE_EX, '1000BASE-EX (1GE)'), - (TYPE_1GE_SX_FIXED, '1000BASE-SX (1GE)'), (TYPE_1GE_LSX, '1000BASE-LSX (1GE)'), (TYPE_1GE_LX_FIXED, '1000BASE-LX (1GE)'), (TYPE_1GE_LX10, '1000BASE-LX10/LH (1GE)'), + (TYPE_1GE_SX_FIXED, '1000BASE-SX (1GE)'), (TYPE_1GE_FIXED, '1000BASE-T (1GE)'), (TYPE_1GE_TX_FIXED, '1000BASE-TX (1GE)'), (TYPE_1GE_ZX, '1000BASE-ZX (1GE)'), @@ -1186,8 +1186,8 @@ class InterfaceTypeChoices(ChoiceSet): ( _('10 Gbps Ethernet'), ( - (TYPE_10GE_BR_D, '10GBASE-DR-D (10GE BiDi Down)'), - (TYPE_10GE_BR_U, '10GBASE-DR-U (10GE BiDi Up)'), + (TYPE_10GE_BR_D, '10GBASE-BR-D (10GE BiDi Down)'), + (TYPE_10GE_BR_U, '10GBASE-BR-U (10GE BiDi Up)'), (TYPE_10GE_CX4, '10GBASE-CX4 (10GE DAC)'), (TYPE_10GE_ER, '10GBASE-ER (10GE)'), (TYPE_10GE_LR, '10GBASE-LR (10GE)'), @@ -1235,6 +1235,7 @@ class InterfaceTypeChoices(ChoiceSet): (TYPE_100GE_CR2, '100GBASE-CR2 (100GE DAC)'), (TYPE_100GE_CR4, '100GBASE-CR4 (100GE DAC)'), (TYPE_100GE_CR10, '100GBASE-CR10 (100GE DAC)'), + (TYPE_100GE_CWDM4, '100GBASE-CWDM4 (100GE)'), (TYPE_100GE_DR, '100GBASE-DR (100GE)'), (TYPE_100GE_ER4, '100GBASE-ER4 (100GE)'), (TYPE_100GE_FR1, '100GBASE-FR1 (100GE)'), @@ -1253,12 +1254,12 @@ class InterfaceTypeChoices(ChoiceSet): ( (TYPE_200GE_CR2, '200GBASE-CR2 (200GE)'), (TYPE_200GE_CR4, '200GBASE-CR4 (200GE)'), - (TYPE_200GE_SR2, '200GBASE-SR2 (200GE)'), - (TYPE_200GE_SR4, '200GBASE-SR4 (200GE)'), (TYPE_200GE_DR4, '200GBASE-DR4 (200GE)'), (TYPE_200GE_ER4, '200GBASE-ER4 (200GE)'), (TYPE_200GE_FR4, '200GBASE-FR4 (200GE)'), (TYPE_200GE_LR4, '200GBASE-LR4 (200GE)'), + (TYPE_200GE_SR2, '200GBASE-SR2 (200GE)'), + (TYPE_200GE_SR4, '200GBASE-SR4 (200GE)'), (TYPE_200GE_VR2, '200GBASE-VR2 (200GE)'), ) ), @@ -1296,34 +1297,34 @@ class InterfaceTypeChoices(ChoiceSet): (TYPE_1GE_GBIC, 'GBIC (1GE)'), (TYPE_1GE_SFP, 'SFP (1GE)'), (TYPE_10GE_SFP_PLUS, 'SFP+ (10GE)'), - (TYPE_10GE_XFP, 'XFP (10GE)'), (TYPE_10GE_XENPAK, 'XENPAK (10GE)'), + (TYPE_10GE_XFP, 'XFP (10GE)'), (TYPE_10GE_X2, 'X2 (10GE)'), (TYPE_25GE_SFP28, 'SFP28 (25GE)'), - (TYPE_50GE_SFP56, 'SFP56 (50GE)'), (TYPE_40GE_QSFP_PLUS, 'QSFP+ (40GE)'), (TYPE_50GE_QSFP28, 'QSFP28 (50GE)'), + (TYPE_50GE_SFP56, 'SFP56 (50GE)'), (TYPE_100GE_CFP, 'CFP (100GE)'), (TYPE_100GE_CFP2, 'CFP2 (100GE)'), - (TYPE_200GE_CFP2, 'CFP2 (200GE)'), - (TYPE_400GE_CFP2, 'CFP2 (400GE)'), (TYPE_100GE_CFP4, 'CFP4 (100GE)'), (TYPE_100GE_CXP, 'CXP (100GE)'), (TYPE_100GE_CPAK, 'Cisco CPAK (100GE)'), (TYPE_100GE_DSFP, 'DSFP (100GE)'), - (TYPE_100GE_SFP_DD, 'SFP-DD (100GE)'), (TYPE_100GE_QSFP28, 'QSFP28 (100GE)'), (TYPE_100GE_QSFP_DD, 'QSFP-DD (100GE)'), + (TYPE_100GE_SFP_DD, 'SFP-DD (100GE)'), + (TYPE_200GE_CFP2, 'CFP2 (200GE)'), (TYPE_200GE_QSFP56, 'QSFP56 (200GE)'), (TYPE_200GE_QSFP_DD, 'QSFP-DD (200GE)'), (TYPE_400GE_QSFP112, 'QSFP112 (400GE)'), (TYPE_400GE_QSFP_DD, 'QSFP-DD (400GE)'), + (TYPE_400GE_CDFP, 'CDFP (400GE)'), + (TYPE_400GE_CFP2, 'CFP2 (400GE)'), + (TYPE_400GE_CFP8, 'CPF8 (400GE)'), (TYPE_400GE_OSFP, 'OSFP (400GE)'), (TYPE_400GE_OSFP_RHS, 'OSFP-RHS (400GE)'), - (TYPE_400GE_CDFP, 'CDFP (400GE)'), - (TYPE_400GE_CFP8, 'CPF8 (400GE)'), - (TYPE_800GE_QSFP_DD, 'QSFP-DD (800GE)'), (TYPE_800GE_OSFP, 'OSFP (800GE)'), + (TYPE_800GE_QSFP_DD, 'QSFP-DD (800GE)'), ) ), ( diff --git a/netbox/dcim/fields.py b/netbox/dcim/fields.py index 535756bac..5985aad3c 100644 --- a/netbox/dcim/fields.py +++ b/netbox/dcim/fields.py @@ -26,7 +26,7 @@ class eui64_unix_expanded_uppercase(eui64_unix_expanded): # class MACAddressField(models.Field): - description = "PostgreSQL MAC Address field" + description = 'PostgreSQL MAC Address field' def python_type(self): return EUI @@ -34,6 +34,9 @@ class MACAddressField(models.Field): def from_db_value(self, value, expression, connection): return self.to_python(value) + def get_internal_type(self): + return 'CharField' + def to_python(self, value): if value is None: return value @@ -54,7 +57,7 @@ class MACAddressField(models.Field): class WWNField(models.Field): - description = "World Wide Name field" + description = 'World Wide Name field' def python_type(self): return EUI @@ -62,6 +65,9 @@ class WWNField(models.Field): def from_db_value(self, value, expression, connection): return self.to_python(value) + def get_internal_type(self): + return 'CharField' + def to_python(self, value): if value is None: return value diff --git a/netbox/dcim/forms/bulk_edit.py b/netbox/dcim/forms/bulk_edit.py index b7d9bcdb7..0f5550666 100644 --- a/netbox/dcim/forms/bulk_edit.py +++ b/netbox/dcim/forms/bulk_edit.py @@ -133,6 +133,11 @@ class SiteBulkEditForm(NetBoxModelBulkEditForm): queryset=Tenant.objects.all(), required=False ) + facility = forms.CharField( + label=_('Facility'), + max_length=50, + required=False + ) asns = DynamicModelMultipleChoiceField( queryset=ASN.objects.all(), label=_('ASNs'), @@ -166,10 +171,10 @@ class SiteBulkEditForm(NetBoxModelBulkEditForm): model = Site fieldsets = ( - FieldSet('status', 'region', 'group', 'tenant', 'asns', 'time_zone', 'description'), + FieldSet('status', 'region', 'group', 'tenant', 'facility', 'asns', 'time_zone', 'description'), ) nullable_fields = ( - 'region', 'group', 'tenant', 'asns', 'time_zone', 'description', 'comments', + 'region', 'group', 'tenant', 'facility', 'asns', 'time_zone', 'description', 'comments', ) @@ -198,6 +203,11 @@ class LocationBulkEditForm(NetBoxModelBulkEditForm): queryset=Tenant.objects.all(), required=False ) + facility = forms.CharField( + label=_('Facility'), + max_length=50, + required=False + ) description = forms.CharField( label=_('Description'), max_length=200, @@ -207,9 +217,9 @@ class LocationBulkEditForm(NetBoxModelBulkEditForm): model = Location fieldsets = ( - FieldSet('site', 'parent', 'status', 'tenant', 'description'), + FieldSet('site', 'parent', 'status', 'tenant', 'facility', 'description'), ) - nullable_fields = ('parent', 'tenant', 'description', 'comments') + nullable_fields = ('parent', 'tenant', 'facility', 'description', 'comments') class RackRoleBulkEditForm(NetBoxModelBulkEditForm): diff --git a/netbox/dcim/graphql/gfk_mixins.py b/netbox/dcim/graphql/gfk_mixins.py index 86ca88774..4d0948207 100644 --- a/netbox/dcim/graphql/gfk_mixins.py +++ b/netbox/dcim/graphql/gfk_mixins.py @@ -1,3 +1,5 @@ +from strawberry.types import Info + from circuits.graphql.types import CircuitTerminationType, ProviderNetworkType from circuits.models import CircuitTermination, ProviderNetwork from dcim.graphql.types import ( @@ -49,7 +51,7 @@ class InventoryItemTemplateComponentType: ) @classmethod - def resolve_type(cls, instance, info): + def resolve_type(cls, instance, info: Info): if type(instance) is ConsolePortTemplate: return ConsolePortTemplateType if type(instance) is ConsoleServerPortTemplate: @@ -79,7 +81,7 @@ class InventoryItemComponentType: ) @classmethod - def resolve_type(cls, instance, info): + def resolve_type(cls, instance, info: Info): if type(instance) is ConsolePort: return ConsolePortType if type(instance) is ConsoleServerPort: @@ -112,7 +114,7 @@ class ConnectedEndpointType: ) @classmethod - def resolve_type(cls, instance, info): + def resolve_type(cls, instance, info: Info): if type(instance) is CircuitTermination: return CircuitTerminationType if type(instance) is ConsolePortType: diff --git a/netbox/dcim/migrations/0188_racktype.py b/netbox/dcim/migrations/0188_racktype.py index 7c36e03ba..1b5fd25c8 100644 --- a/netbox/dcim/migrations/0188_racktype.py +++ b/netbox/dcim/migrations/0188_racktype.py @@ -3,9 +3,7 @@ import django.db.models.deletion import taggit.managers from django.db import migrations, models -import utilities.fields import utilities.json -import utilities.ordering class Migration(migrations.Migration): diff --git a/netbox/dcim/models/device_components.py b/netbox/dcim/models/device_components.py index 9e1d7b61e..dfc3ec689 100644 --- a/netbox/dcim/models/device_components.py +++ b/netbox/dcim/models/device_components.py @@ -632,10 +632,17 @@ class BaseInterface(models.Model): }) # Check that the primary MAC address (if any) is assigned to this interface - if self.primary_mac_address and self.primary_mac_address.assigned_object != self: + if ( + self.primary_mac_address and + self.primary_mac_address.assigned_object is not None and + self.primary_mac_address.assigned_object != self + ): raise ValidationError({ - 'primary_mac_address': _("MAC address {mac_address} is not assigned to this interface.").format( - mac_address=self.primary_mac_address + 'primary_mac_address': _( + "MAC address {mac_address} is assigned to a different interface ({interface})." + ).format( + mac_address=self.primary_mac_address, + interface=self.primary_mac_address.assigned_object, ) }) diff --git a/netbox/dcim/signals.py b/netbox/dcim/signals.py index c7d3533fb..8f7d0d2eb 100644 --- a/netbox/dcim/signals.py +++ b/netbox/dcim/signals.py @@ -4,6 +4,7 @@ from django.db.models.signals import post_save, post_delete, pre_delete from django.dispatch import receiver from dcim.choices import CableEndChoices, LinkStatusChoices +from virtualization.models import VMInterface from .models import ( Cable, CablePath, CableTermination, ConsolePort, ConsoleServerPort, Device, DeviceBay, FrontPort, Interface, InventoryItem, ModuleBay, PathEndpoint, PowerOutlet, PowerPanel, PowerPort, Rack, RearPort, Location, @@ -170,3 +171,15 @@ def extend_rearport_cable_paths(instance, created, raw, **kwargs): rearport = instance.rear_port for cablepath in CablePath.objects.filter(_nodes__contains=rearport): cablepath.retrace() + + +@receiver(post_save, sender=Interface) +@receiver(post_save, sender=VMInterface) +def update_mac_address_interface(instance, created, raw, **kwargs): + """ + When creating a new Interface or VMInterface, check whether a MACAddress has been designated as its primary. If so, + assign the MACAddress to the interface. + """ + if created and not raw and instance.primary_mac_address: + instance.primary_mac_address.assigned_object = instance + instance.primary_mac_address.save() diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py index 476c698b1..dbdfae11d 100644 --- a/netbox/dcim/tables/devices.py +++ b/netbox/dcim/tables/devices.py @@ -196,7 +196,7 @@ class DeviceTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable): verbose_name=_('Type') ) u_height = columns.TemplateColumn( - accessor=tables.A('device_type.u_height'), + accessor=tables.A('device_type__u_height'), verbose_name=_('U Height'), template_code='{{ value|floatformat }}' ) diff --git a/netbox/extras/api/serializers_/customfields.py b/netbox/extras/api/serializers_/customfields.py index f50f7a829..0d982a7e6 100644 --- a/netbox/extras/api/serializers_/customfields.py +++ b/netbox/extras/api/serializers_/customfields.py @@ -26,6 +26,7 @@ class CustomFieldChoiceSetSerializer(ChangeLogMessageSerializer, ValidatedModelS max_length=2 ) ) + choices_count = serializers.IntegerField(read_only=True) class Meta: model = CustomFieldChoiceSet diff --git a/netbox/extras/graphql/mixins.py b/netbox/extras/graphql/mixins.py index 542bbcc85..881a53aa3 100644 --- a/netbox/extras/graphql/mixins.py +++ b/netbox/extras/graphql/mixins.py @@ -2,6 +2,7 @@ from typing import TYPE_CHECKING, Annotated, List import strawberry import strawberry_django +from strawberry.types import Info __all__ = ( 'ConfigContextMixin', @@ -37,7 +38,7 @@ class CustomFieldsMixin: class ImageAttachmentsMixin: @strawberry_django.field - def image_attachments(self, info) -> List[Annotated["ImageAttachmentType", strawberry.lazy('.types')]]: + def image_attachments(self, info: Info) -> List[Annotated['ImageAttachmentType', strawberry.lazy('.types')]]: return self.images.restrict(info.context.request.user, 'view') @@ -45,17 +46,17 @@ class ImageAttachmentsMixin: class JournalEntriesMixin: @strawberry_django.field - def journal_entries(self, info) -> List[Annotated["JournalEntryType", strawberry.lazy('.types')]]: + def journal_entries(self, info: Info) -> List[Annotated['JournalEntryType', strawberry.lazy('.types')]]: return self.journal_entries.all() @strawberry.type class TagsMixin: - tags: List[Annotated["TagType", strawberry.lazy('.types')]] + tags: List[Annotated['TagType', strawberry.lazy('.types')]] @strawberry.type class ContactsMixin: - contacts: List[Annotated["ContactAssignmentType", strawberry.lazy('tenancy.graphql.types')]] + contacts: List[Annotated['ContactAssignmentType', strawberry.lazy('tenancy.graphql.types')]] diff --git a/netbox/extras/lookups.py b/netbox/extras/lookups.py index 33296340e..678239080 100644 --- a/netbox/extras/lookups.py +++ b/netbox/extras/lookups.py @@ -1,9 +1,39 @@ +from django.contrib.postgres.fields import ArrayField +from django.contrib.postgres.fields.ranges import RangeField from django.db.models import CharField, JSONField, Lookup from django.db.models.fields.json import KeyTextTransform from .fields import CachedValueField +class RangeContains(Lookup): + """ + Filter ArrayField(RangeField) columns where ANY element-range contains the scalar RHS. + + Usage (ORM): + Model.objects.filter(__range_contains=) + + Works with int4range[], int8range[], daterange[], tstzrange[], etc. + """ + + lookup_name = 'range_contains' + + def as_sql(self, compiler, connection): + # Compile LHS (the array-of-ranges column/expression) and RHS (scalar) + lhs, lhs_params = self.process_lhs(compiler, connection) + rhs, rhs_params = self.process_rhs(compiler, connection) + + # Guard: only allow ArrayField whose base_field is a PostgreSQL RangeField + field = getattr(self.lhs, 'output_field', None) + if not (isinstance(field, ArrayField) and isinstance(field.base_field, RangeField)): + raise TypeError('range_contains is only valid for ArrayField(RangeField) columns') + + # Range-contains-element using EXISTS + UNNEST keeps the range on the LHS: r @> value + sql = f"EXISTS (SELECT 1 FROM unnest({lhs}) AS r WHERE r @> {rhs})" + params = lhs_params + rhs_params + return sql, params + + class Empty(Lookup): """ Filter on whether a string is empty. @@ -25,7 +55,7 @@ class JSONEmpty(Lookup): A key is considered empty if it is "", null, or does not exist. """ - lookup_name = "empty" + lookup_name = 'empty' def as_sql(self, compiler, connection): # self.lhs.lhs is the parent expression (could be a JSONField or another KeyTransform) @@ -69,6 +99,7 @@ class NetContainsOrEquals(Lookup): return 'CAST(%s AS INET) >>= %s' % (lhs, rhs), params +ArrayField.register_lookup(RangeContains) CharField.register_lookup(Empty) JSONField.register_lookup(JSONEmpty) CachedValueField.register_lookup(NetHost) diff --git a/netbox/extras/querysets.py b/netbox/extras/querysets.py index ee2afed4c..e3f6a7dcf 100644 --- a/netbox/extras/querysets.py +++ b/netbox/extras/querysets.py @@ -90,7 +90,7 @@ class ConfigContextModelQuerySet(RestrictedQuerySet): ConfigContext.objects.filter( self._get_config_context_filters() ).annotate( - _data=EmptyGroupByJSONBAgg('data', ordering=['weight', 'name']) + _data=EmptyGroupByJSONBAgg('data', order_by=['weight', 'name']) ).values("_data").order_by() ) ) diff --git a/netbox/ipam/fields.py b/netbox/ipam/fields.py index a82976326..c5930d839 100644 --- a/netbox/ipam/fields.py +++ b/netbox/ipam/fields.py @@ -26,6 +26,9 @@ class BaseIPField(models.Field): def from_db_value(self, value, expression, connection): return self.to_python(value) + def get_internal_type(self): + return 'CharField' + def to_python(self, value): if not value: return value @@ -57,7 +60,7 @@ class IPNetworkField(BaseIPField): """ IP prefix (network and mask) """ - description = "PostgreSQL CIDR field" + description = 'PostgreSQL CIDR field' default_validators = [validators.prefix_validator] def db_type(self, connection): @@ -83,7 +86,7 @@ class IPAddressField(BaseIPField): """ IP address (host address and mask) """ - description = "PostgreSQL INET field" + description = 'PostgreSQL INET field' def db_type(self, connection): return 'inet' @@ -110,7 +113,7 @@ IPAddressField.register_lookup(lookups.Inet) class ASNField(models.BigIntegerField): - description = "32-bit ASN field" + description = '32-bit ASN field' default_validators = [ MinValueValidator(BGP_ASN_MIN), MaxValueValidator(BGP_ASN_MAX), diff --git a/netbox/ipam/filtersets.py b/netbox/ipam/filtersets.py index cf4f99d32..34bc34b48 100644 --- a/netbox/ipam/filtersets.py +++ b/netbox/ipam/filtersets.py @@ -354,13 +354,13 @@ class PrefixFilterSet(NetBoxModelFilterSet, ScopedFilterSet, TenancyFilterSet, C vlan_group_id = django_filters.ModelMultipleChoiceFilter( field_name='vlan__group', queryset=VLANGroup.objects.all(), - to_field_name="id", + to_field_name='id', label=_('VLAN Group (ID)'), ) vlan_group = django_filters.ModelMultipleChoiceFilter( field_name='vlan__group__slug', queryset=VLANGroup.objects.all(), - to_field_name="slug", + to_field_name='slug', label=_('VLAN Group (slug)'), ) vlan_id = django_filters.ModelMultipleChoiceFilter( @@ -695,12 +695,12 @@ class IPAddressFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFil return queryset.filter(q) def parse_inet_addresses(self, value): - ''' + """ Parse networks or IP addresses and cast to a format acceptable by the Postgres inet type. Skips invalid values. - ''' + """ parsed = [] for addr in value: if netaddr.valid_ipv4(addr) or netaddr.valid_ipv6(addr): @@ -718,7 +718,7 @@ class IPAddressFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFil # as argument. If they are all invalid, # we return an empty queryset value = self.parse_inet_addresses(value) - if (len(value) == 0): + if len(value) == 0: return queryset.none() try: @@ -908,7 +908,8 @@ class VLANGroupFilterSet(OrganizationalModelFilterSet, TenancyFilterSet): method='filter_scope' ) contains_vid = django_filters.NumberFilter( - method='filter_contains_vid' + field_name='vid_ranges', + lookup_expr='range_contains', ) class Meta: @@ -931,21 +932,6 @@ class VLANGroupFilterSet(OrganizationalModelFilterSet, TenancyFilterSet): scope_id=value ) - def filter_contains_vid(self, queryset, name, value): - """ - Return all VLANGroups which contain the given VLAN ID. - """ - table_name = VLANGroup._meta.db_table - # TODO: See if this can be optimized without compromising queryset integrity - # Expand VLAN ID ranges to query by integer - groups = VLANGroup.objects.raw( - f'SELECT id FROM {table_name}, unnest(vid_ranges) vid_range WHERE %s <@ vid_range', - params=(value,) - ) - return queryset.filter( - pk__in=[g.id for g in groups] - ) - class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet): region_id = TreeNodeMultipleChoiceFilter( @@ -1079,6 +1065,7 @@ class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet): def get_for_virtualmachine(self, queryset, name, value): return queryset.get_for_virtualmachine(value) + @extend_schema_field(OpenApiTypes.INT) def filter_interface_id(self, queryset, name, value): if value is None: return queryset.none() @@ -1087,6 +1074,7 @@ class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet): Q(interfaces_as_untagged=value) ).distinct() + @extend_schema_field(OpenApiTypes.INT) def filter_vminterface_id(self, queryset, name, value): if value is None: return queryset.none() diff --git a/netbox/ipam/graphql/filters.py b/netbox/ipam/graphql/filters.py index 35ddd47e4..4b2431aa2 100644 --- a/netbox/ipam/graphql/filters.py +++ b/netbox/ipam/graphql/filters.py @@ -19,7 +19,7 @@ from tenancy.graphql.filter_mixins import ContactFilterMixin, TenancyFilterMixin from virtualization.models import VMInterface if TYPE_CHECKING: - from netbox.graphql.filter_lookups import IntegerArrayLookup, IntegerLookup + from netbox.graphql.filter_lookups import IntegerLookup, IntegerRangeArrayLookup from circuits.graphql.filters import ProviderFilter from core.graphql.filters import ContentTypeFilter from dcim.graphql.filters import SiteFilter @@ -340,7 +340,7 @@ class VLANFilter(TenancyFilterMixin, PrimaryModelFilterMixin): @strawberry_django.filter_type(models.VLANGroup, lookups=True) class VLANGroupFilter(ScopedFilterMixin, OrganizationalModelFilterMixin): - vid_ranges: Annotated['IntegerArrayLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( + vid_ranges: Annotated['IntegerRangeArrayLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = ( strawberry_django.filter_field() ) diff --git a/netbox/ipam/graphql/types.py b/netbox/ipam/graphql/types.py index e8f98eabe..a07316fe4 100644 --- a/netbox/ipam/graphql/types.py +++ b/netbox/ipam/graphql/types.py @@ -74,7 +74,7 @@ class BaseIPAddressFamilyType: filters=ASNFilter, pagination=True ) -class ASNType(NetBoxObjectType): +class ASNType(NetBoxObjectType, ContactsMixin): asn: BigInt rir: Annotated["RIRType", strawberry.lazy('ipam.graphql.types')] | None tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None diff --git a/netbox/ipam/models/ip.py b/netbox/ipam/models/ip.py index cef979d3f..b31c9a14b 100644 --- a/netbox/ipam/models/ip.py +++ b/netbox/ipam/models/ip.py @@ -548,7 +548,7 @@ class IPRange(ContactsMixin, PrimaryModel): mark_utilized = models.BooleanField( verbose_name=_('mark utilized'), default=False, - help_text=_("Report space as 100% utilized") + help_text=_("Report space as fully utilized") ) clone_fields = ( diff --git a/netbox/ipam/tests/test_filtersets.py b/netbox/ipam/tests/test_filtersets.py index 54ad5df90..d2cd13dce 100644 --- a/netbox/ipam/tests/test_filtersets.py +++ b/netbox/ipam/tests/test_filtersets.py @@ -1723,6 +1723,10 @@ class VLANGroupTestCase(TestCase, ChangeLoggedFilterSetTests): self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) params = {'contains_vid': 1} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 8) + params = {'contains_vid': 12} # 11 is NOT in [1,11) + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + params = {'contains_vid': 4095} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 0) def test_region(self): params = {'region': Region.objects.first().pk} diff --git a/netbox/ipam/tests/test_lookups.py b/netbox/ipam/tests/test_lookups.py new file mode 100644 index 000000000..5c8b7a770 --- /dev/null +++ b/netbox/ipam/tests/test_lookups.py @@ -0,0 +1,66 @@ +from django.test import TestCase +from django.db.backends.postgresql.psycopg_any import NumericRange +from ipam.models import VLANGroup + + +class VLANGroupRangeContainsLookupTests(TestCase): + @classmethod + def setUpTestData(cls): + # Two ranges: [1,11) and [20,31) + cls.g1 = VLANGroup.objects.create( + name='VlanGroup-A', + slug='VlanGroup-A', + vid_ranges=[NumericRange(1, 11), NumericRange(20, 31)], + ) + # One range: [100,201) + cls.g2 = VLANGroup.objects.create( + name='VlanGroup-B', + slug='VlanGroup-B', + vid_ranges=[NumericRange(100, 201)], + ) + cls.g_empty = VLANGroup.objects.create( + name='VlanGroup-empty', + slug='VlanGroup-empty', + vid_ranges=[], + ) + + def test_contains_value_in_first_range(self): + """ + Tests whether a specific value is contained within the first range in a queried + set of VLANGroup objects. + """ + names = list( + VLANGroup.objects.filter(vid_ranges__range_contains=10).values_list('name', flat=True).order_by('name') + ) + self.assertEqual(names, ['VlanGroup-A']) + + def test_contains_value_in_second_range(self): + """ + Tests if a value exists in the second range of VLANGroup objects and + validates the result against the expected list of names. + """ + names = list( + VLANGroup.objects.filter(vid_ranges__range_contains=25).values_list('name', flat=True).order_by('name') + ) + self.assertEqual(names, ['VlanGroup-A']) + + def test_upper_bound_is_exclusive(self): + """ + Tests if the upper bound of the range is exclusive in the filter method. + """ + # 11 is NOT in [1,11) + self.assertFalse(VLANGroup.objects.filter(vid_ranges__range_contains=11).exists()) + + def test_no_match_far_outside(self): + """ + Tests that no VLANGroup contains a VID within a specified range far outside + common VID bounds and returns `False`. + """ + self.assertFalse(VLANGroup.objects.filter(vid_ranges__range_contains=4095).exists()) + + def test_empty_array_never_matches(self): + """ + Tests the behavior of VLANGroup objects when an empty array is used to match a + specific condition. + """ + self.assertFalse(VLANGroup.objects.filter(pk=self.g_empty.pk, vid_ranges__range_contains=1).exists()) diff --git a/netbox/netbox/api/fields.py b/netbox/netbox/api/fields.py index db5ec184d..7dfd7d7eb 100644 --- a/netbox/netbox/api/fields.py +++ b/netbox/netbox/api/fields.py @@ -169,7 +169,7 @@ class IntegerRangeSerializer(serializers.Serializer): if type(data[0]) is not int or type(data[1]) is not int: raise ValidationError(_("Range boundaries must be defined as integers.")) - return NumericRange(data[0], data[1], bounds='[]') + return NumericRange(data[0], data[1] + 1, bounds='[)') def to_representation(self, instance): return instance.lower, instance.upper - 1 diff --git a/netbox/netbox/api/pagination.py b/netbox/netbox/api/pagination.py index 698e0a8dd..1650628a9 100644 --- a/netbox/netbox/api/pagination.py +++ b/netbox/netbox/api/pagination.py @@ -44,22 +44,28 @@ class OptionalLimitOffsetPagination(LimitOffsetPagination): return list(queryset[self.offset:]) def get_limit(self, request): + max_limit = self.default_limit + MAX_PAGE_SIZE = get_config().MAX_PAGE_SIZE + if MAX_PAGE_SIZE: + max_limit = min(max_limit, MAX_PAGE_SIZE) + if self.limit_query_param: - MAX_PAGE_SIZE = get_config().MAX_PAGE_SIZE - if MAX_PAGE_SIZE: - MAX_PAGE_SIZE = max(MAX_PAGE_SIZE, self.default_limit) try: limit = int(request.query_params[self.limit_query_param]) if limit < 0: raise ValueError() - # Enforce maximum page size, if defined + if MAX_PAGE_SIZE: - return MAX_PAGE_SIZE if limit == 0 else min(limit, MAX_PAGE_SIZE) - return limit + if limit == 0: + max_limit = MAX_PAGE_SIZE + else: + max_limit = min(MAX_PAGE_SIZE, limit) + else: + max_limit = limit except (KeyError, ValueError): pass - return self.default_limit + return max_limit def get_queryset_count(self, queryset): return queryset.count() diff --git a/netbox/netbox/config/__init__.py b/netbox/netbox/config/__init__.py index 23108f1d2..f2fdecb33 100644 --- a/netbox/netbox/config/__init__.py +++ b/netbox/netbox/config/__init__.py @@ -78,11 +78,16 @@ class Config: from core.models import ConfigRevision try: - revision = ConfigRevision.objects.last() + # Enforce the creation date as the ordering parameter + revision = ConfigRevision.objects.get(active=True) + logger.debug(f"Loaded active configuration revision #{revision.pk}") + except (ConfigRevision.DoesNotExist, ConfigRevision.MultipleObjectsReturned): + logger.warning("No active configuration revision found - falling back to most recent") + revision = ConfigRevision.objects.order_by('-created').first() if revision is None: logger.debug("No previous configuration found in database; proceeding with default values") return - logger.debug("Loaded configuration data from database") + logger.debug(f"Using fallback configuration revision #{revision.pk}") except DatabaseError: # The database may not be available yet (e.g. when running a management command) logger.warning("Skipping config initialization (database unavailable)") diff --git a/netbox/netbox/graphql/filter_lookups.py b/netbox/netbox/graphql/filter_lookups.py index 859236e4d..ec498222d 100644 --- a/netbox/netbox/graphql/filter_lookups.py +++ b/netbox/netbox/graphql/filter_lookups.py @@ -7,6 +7,7 @@ from django.core.exceptions import FieldDoesNotExist from django.db.models import Q, QuerySet from django.db.models.fields.related import ForeignKey, ManyToManyField, ManyToManyRel, ManyToOneRel from strawberry import ID +from strawberry.directive import DirectiveValue from strawberry.types import Info from strawberry_django import ( ComparisonFilterLookup, @@ -24,6 +25,7 @@ __all__ = ( 'FloatLookup', 'IntegerArrayLookup', 'IntegerLookup', + 'IntegerRangeArrayLookup', 'JSONFilter', 'StringArrayLookup', 'TreeNodeFilter', @@ -67,7 +69,7 @@ class IntegerLookup: return None @strawberry_django.filter_field - def filter(self, info: Info, queryset: QuerySet, prefix: str = '') -> Tuple[QuerySet, Q]: + def filter(self, info: Info, queryset: QuerySet, prefix: DirectiveValue[str] = '') -> Tuple[QuerySet, Q]: filters = self.get_filter() if not filters: @@ -90,7 +92,7 @@ class FloatLookup: return None @strawberry_django.filter_field - def filter(self, info: Info, queryset: QuerySet, prefix: str = '') -> Tuple[QuerySet, Q]: + def filter(self, info: Info, queryset: QuerySet, prefix: DirectiveValue[str] = '') -> Tuple[QuerySet, Q]: filters = self.get_filter() if not filters: @@ -109,7 +111,7 @@ class JSONFilter: lookup: JSONLookup @strawberry_django.filter_field - def filter(self, info: Info, queryset: QuerySet, prefix: str = '') -> Tuple[QuerySet, Q]: + def filter(self, info: Info, queryset: QuerySet, prefix: DirectiveValue[str] = '') -> Tuple[QuerySet, Q]: filters = self.lookup.get_filter() if not filters: @@ -136,7 +138,7 @@ class TreeNodeFilter: match_type: TreeNodeMatch @strawberry_django.filter_field - def filter(self, info: Info, queryset: QuerySet, prefix: str = '') -> Tuple[QuerySet, Q]: + def filter(self, info: Info, queryset: QuerySet, prefix: DirectiveValue[str] = '') -> Tuple[QuerySet, Q]: model_field_name = prefix.removesuffix('__').removesuffix('_id') model_field = None try: @@ -217,3 +219,30 @@ class FloatArrayLookup(ArrayLookup[float]): @strawberry.input(one_of=True, description='Lookup for Array fields. Only one of the lookup fields can be set.') class StringArrayLookup(ArrayLookup[str]): pass + + +@strawberry.input(one_of=True, description='Lookups for an ArrayField(RangeField). Only one may be set.') +class RangeArrayValueLookup(Generic[T]): + """ + class for Array field of Range fields lookups + """ + + contains: T | None = strawberry.field( + default=strawberry.UNSET, description='Return rows where any stored range contains this value.' + ) + + @strawberry_django.filter_field + def filter(self, info: Info, queryset: QuerySet, prefix: str = '') -> Tuple[QuerySet, Q]: + """ + Map GraphQL: { : { contains: } } To Django ORM: __range_contains= + """ + if self.contains is strawberry.UNSET or self.contains is None: + return queryset, Q() + + # Build 'range_contains' so it works for nested paths too + return queryset, Q(**{f'{prefix}range_contains': self.contains}) + + +@strawberry.input(one_of=True, description='Lookups for an ArrayField(IntegerRangeField). Only one may be set.') +class IntegerRangeArrayLookup(RangeArrayValueLookup[int]): + pass diff --git a/netbox/netbox/graphql/types.py b/netbox/netbox/graphql/types.py index 653462630..bdc38b349 100644 --- a/netbox/netbox/graphql/types.py +++ b/netbox/netbox/graphql/types.py @@ -1,5 +1,6 @@ import strawberry import strawberry_django +from strawberry.types import Info from django.contrib.contenttypes.models import ContentType from core.graphql.mixins import ChangelogMixin @@ -26,7 +27,7 @@ class BaseObjectType: """ @classmethod - def get_queryset(cls, queryset, info, **kwargs): + def get_queryset(cls, queryset, info: Info, **kwargs): # Enforce object permissions on the queryset if hasattr(queryset, 'restrict'): return queryset.restrict(info.context.request.user, 'view') diff --git a/netbox/netbox/jobs.py b/netbox/netbox/jobs.py index 559619ac0..72dcece1f 100644 --- a/netbox/netbox/jobs.py +++ b/netbox/netbox/jobs.py @@ -4,6 +4,7 @@ from datetime import timedelta from django.core.exceptions import ImproperlyConfigured from django.utils.functional import classproperty +from django.utils import timezone from django_pglocks import advisory_lock from rq.timeouts import JobTimeoutException @@ -113,7 +114,11 @@ class JobRunner(ABC): # If the executed job is a periodic job, schedule its next execution at the specified interval. finally: if job.interval: - new_scheduled_time = (job.scheduled or job.started) + timedelta(minutes=job.interval) + # Determine the new scheduled time. Cannot be earlier than one minute in the future. + new_scheduled_time = max( + (job.scheduled or job.started) + timedelta(minutes=job.interval), + timezone.now() + timedelta(minutes=1) + ) if job.object and getattr(job.object, "python_class", None): kwargs["job_timeout"] = job.object.python_class.job_timeout cls.enqueue( diff --git a/netbox/netbox/models/features.py b/netbox/netbox/models/features.py index 09c2722ad..be58d647a 100644 --- a/netbox/netbox/models/features.py +++ b/netbox/netbox/models/features.py @@ -673,10 +673,15 @@ def has_feature(model_or_ct, feature): # If an ObjectType was passed, we can use it directly if type(model_or_ct) is ObjectType: ot = model_or_ct - # If a ContentType was passed, resolve its model class + # If a ContentType was passed, resolve its model class and run the associated feature test elif type(model_or_ct) is ContentType: - model_class = model_or_ct.model_class() - ot = ObjectType.objects.get_for_model(model_class) if model_class else None + model = model_or_ct.model_class() + try: + test_func = registry['model_features'][feature] + except KeyError: + # Unknown feature + return False + return test_func(model) # For anything else, look up the ObjectType else: ot = ObjectType.objects.get_for_model(model_or_ct) diff --git a/netbox/netbox/views/generic/object_views.py b/netbox/netbox/views/generic/object_views.py index 42407963d..4e8c3ad86 100644 --- a/netbox/netbox/views/generic/object_views.py +++ b/netbox/netbox/views/generic/object_views.py @@ -238,7 +238,8 @@ class ObjectEditView(GetReturnURLMixin, BaseObjectView): model = self.queryset.model initial_data = normalize_querydict(request.GET) - form = self.form(instance=obj, initial=initial_data) + form_prefix = 'quickadd' if request.GET.get('_quickadd') else None + form = self.form(instance=obj, initial=initial_data, prefix=form_prefix) restrict_form_fields(form, request.user) context = { diff --git a/netbox/project-static/dist/netbox.js b/netbox/project-static/dist/netbox.js index fa1a0bcd1..a84fbe7fb 100644 --- a/netbox/project-static/dist/netbox.js +++ b/netbox/project-static/dist/netbox.js @@ -1,11 +1,11 @@ -"use strict";(()=>{var tu=Object.create;var Mi=Object.defineProperty,nu=Object.defineProperties,iu=Object.getOwnPropertyDescriptor,ru=Object.getOwnPropertyDescriptors,ou=Object.getOwnPropertyNames,ps=Object.getOwnPropertySymbols,su=Object.getPrototypeOf,ms=Object.prototype.hasOwnProperty,au=Object.prototype.propertyIsEnumerable;var qr=(n,e,t)=>e in n?Mi(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,O=(n,e)=>{for(var t in e||(e={}))ms.call(e,t)&&qr(n,t,e[t]);if(ps)for(var t of ps(e))au.call(e,t)&&qr(n,t,e[t]);return n},ae=(n,e)=>nu(n,ru(e));var lu=(n,e)=>()=>(e||n((e={exports:{}}).exports,e),e.exports),gs=(n,e)=>{for(var t in e)Mi(n,t,{get:e[t],enumerable:!0})},cu=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of ou(e))!ms.call(n,r)&&r!==t&&Mi(n,r,{get:()=>e[r],enumerable:!(i=iu(e,r))||i.enumerable});return n};var uu=(n,e,t)=>(t=n!=null?tu(su(n)):{},cu(e||!n||!n.__esModule?Mi(t,"default",{value:n,enumerable:!0}):t,n));var ee=(n,e,t)=>qr(n,typeof e!="symbol"?e+"":e,t);var at=(n,e,t)=>new Promise((i,r)=>{var o=l=>{try{a(t.next(l))}catch(c){r(c)}},s=l=>{try{a(t.throw(l))}catch(c){r(c)}},a=l=>l.done?i(l.value):Promise.resolve(l.value).then(o,s);a((t=t.apply(n,e)).next())});var mc=lu((vi,ts)=>{(function(e,t){typeof vi=="object"&&typeof ts=="object"?ts.exports=t():typeof define=="function"&&define.amd?define([],t):typeof vi=="object"?vi.ClipboardJS=t():e.ClipboardJS=t()})(vi,function(){return function(){var n={686:function(i,r,o){"use strict";o.d(r,{default:function(){return Re}});var s=o(279),a=o.n(s),l=o(370),c=o.n(l),u=o(817),d=o.n(u);function p(W){try{return document.execCommand(W)}catch(M){return!1}}var y=function(M){var D=d()(M);return p("cut"),D},m=y;function v(W){var M=document.documentElement.getAttribute("dir")==="rtl",D=document.createElement("textarea");D.style.fontSize="12pt",D.style.border="0",D.style.padding="0",D.style.margin="0",D.style.position="absolute",D.style[M?"right":"left"]="-9999px";var B=window.pageYOffset||document.documentElement.scrollTop;return D.style.top="".concat(B,"px"),D.setAttribute("readonly",""),D.value=W,D}var w=function(M,D){var B=v(M);D.container.appendChild(B);var V=d()(B);return p("copy"),B.remove(),V},T=function(M){var D=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},B="";return typeof M=="string"?B=w(M,D):M instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(M==null?void 0:M.type)?B=w(M.value,D):(B=d()(M),p("copy")),B},_=T;function S(W){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?S=function(D){return typeof D}:S=function(D){return D&&typeof Symbol=="function"&&D.constructor===Symbol&&D!==Symbol.prototype?"symbol":typeof D},S(W)}var A=function(){var M=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},D=M.action,B=D===void 0?"copy":D,V=M.container,q=M.target,U=M.text;if(B!=="copy"&&B!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&S(q)==="object"&&q.nodeType===1){if(B==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(B==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(U)return _(U,{container:V});if(q)return B==="cut"?m(q):_(q,{container:V})},K=A;function z(W){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?z=function(D){return typeof D}:z=function(D){return D&&typeof Symbol=="function"&&D.constructor===Symbol&&D!==Symbol.prototype?"symbol":typeof D},z(W)}function L(W,M){if(!(W instanceof M))throw new TypeError("Cannot call a class as a function")}function H(W,M){for(var D=0;D0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof V.action=="function"?V.action:this.defaultAction,this.target=typeof V.target=="function"?V.target:this.defaultTarget,this.text=typeof V.text=="function"?V.text:this.defaultText,this.container=z(V.container)==="object"?V.container:document.body}},{key:"listenClick",value:function(V){var q=this;this.listener=c()(V,"click",function(U){return q.onClick(U)})}},{key:"onClick",value:function(V){var q=V.delegateTarget||V.currentTarget,U=this.action(q)||"copy",Z=K({action:U,container:this.container,target:this.target(q),text:this.text(q)});this.emit(Z?"success":"error",{action:U,text:Z,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(V){return ne("action",V)}},{key:"defaultTarget",value:function(V){var q=ne("target",V);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(V){return ne("text",V)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(V){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return _(V,q)}},{key:"cut",value:function(V){return m(V)}},{key:"isSupported",value:function(){var V=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof V=="string"?[V]:V,U=!!document.queryCommandSupported;return q.forEach(function(Z){U=U&&!!document.queryCommandSupported(Z)}),U}}]),D}(a()),Re=qe},828:function(i){var r=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var o=Element.prototype;o.matches=o.matchesSelector||o.mozMatchesSelector||o.msMatchesSelector||o.oMatchesSelector||o.webkitMatchesSelector}function s(a,l){for(;a&&a.nodeType!==r;){if(typeof a.matches=="function"&&a.matches(l))return a;a=a.parentNode}}i.exports=s},438:function(i,r,o){var s=o(828);function a(u,d,p,y,m){var v=c.apply(this,arguments);return u.addEventListener(p,v,m),{destroy:function(){u.removeEventListener(p,v,m)}}}function l(u,d,p,y,m){return typeof u.addEventListener=="function"?a.apply(null,arguments):typeof p=="function"?a.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return a(v,d,p,y,m)}))}function c(u,d,p,y){return function(m){m.delegateTarget=s(m.target,d),m.delegateTarget&&y.call(u,m)}}i.exports=l},879:function(i,r){r.node=function(o){return o!==void 0&&o instanceof HTMLElement&&o.nodeType===1},r.nodeList=function(o){var s=Object.prototype.toString.call(o);return o!==void 0&&(s==="[object NodeList]"||s==="[object HTMLCollection]")&&"length"in o&&(o.length===0||r.node(o[0]))},r.string=function(o){return typeof o=="string"||o instanceof String},r.fn=function(o){var s=Object.prototype.toString.call(o);return s==="[object Function]"}},370:function(i,r,o){var s=o(879),a=o(438);function l(p,y,m){if(!p&&!y&&!m)throw new Error("Missing required arguments");if(!s.string(y))throw new TypeError("Second argument must be a String");if(!s.fn(m))throw new TypeError("Third argument must be a Function");if(s.node(p))return c(p,y,m);if(s.nodeList(p))return u(p,y,m);if(s.string(p))return d(p,y,m);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(p,y,m){return p.addEventListener(y,m),{destroy:function(){p.removeEventListener(y,m)}}}function u(p,y,m){return Array.prototype.forEach.call(p,function(v){v.addEventListener(y,m)}),{destroy:function(){Array.prototype.forEach.call(p,function(v){v.removeEventListener(y,m)})}}}function d(p,y,m){return a(document.body,p,y,m)}i.exports=l},817:function(i){function r(o){var s;if(o.nodeName==="SELECT")o.focus(),s=o.value;else if(o.nodeName==="INPUT"||o.nodeName==="TEXTAREA"){var a=o.hasAttribute("readonly");a||o.setAttribute("readonly",""),o.select(),o.setSelectionRange(0,o.value.length),a||o.removeAttribute("readonly"),s=o.value}else{o.hasAttribute("contenteditable")&&o.focus();var l=window.getSelection(),c=document.createRange();c.selectNodeContents(o),l.removeAllRanges(),l.addRange(c),s=l.toString()}return s}i.exports=r},279:function(i){function r(){}r.prototype={on:function(o,s,a){var l=this.e||(this.e={});return(l[o]||(l[o]=[])).push({fn:s,ctx:a}),this},once:function(o,s,a){var l=this;function c(){l.off(o,c),s.apply(a,arguments)}return c._=s,this.on(o,c,a)},emit:function(o){var s=[].slice.call(arguments,1),a=((this.e||(this.e={}))[o]||[]).slice(),l=0,c=a.length;for(l;lws,afterRead:()=>Es,afterWrite:()=>Cs,applyStyles:()=>hn,arrow:()=>Ni,auto:()=>jn,basePlacements:()=>lt,beforeMain:()=>bs,beforeRead:()=>vs,beforeWrite:()=>xs,bottom:()=>ge,clippingParents:()=>Ur,computeStyles:()=>mn,createPopper:()=>Jn,createPopperBase:()=>Is,createPopperLite:()=>Rs,detectOverflow:()=>ke,end:()=>bt,eventListeners:()=>gn,flip:()=>Pi,hide:()=>Fi,left:()=>he,main:()=>_s,modifierPhases:()=>Gr,offset:()=>$i,placements:()=>qn,popper:()=>$t,popperGenerator:()=>Yt,popperOffsets:()=>En,preventOverflow:()=>Bi,read:()=>ys,reference:()=>Yr,right:()=>me,start:()=>rt,top:()=>de,variationPlacements:()=>ki,viewport:()=>Wn,write:()=>Ts});var de="top",ge="bottom",me="right",he="left",jn="auto",lt=[de,ge,me,he],rt="start",bt="end",Ur="clippingParents",Wn="viewport",$t="popper",Yr="reference",ki=lt.reduce(function(n,e){return n.concat([e+"-"+rt,e+"-"+bt])},[]),qn=[].concat(lt,[jn]).reduce(function(n,e){return n.concat([e,e+"-"+rt,e+"-"+bt])},[]),vs="beforeRead",ys="read",Es="afterRead",bs="beforeMain",_s="main",ws="afterMain",xs="beforeWrite",Ts="write",Cs="afterWrite",Gr=[vs,ys,Es,bs,_s,ws,xs,Ts,Cs];function we(n){return n?(n.nodeName||"").toLowerCase():null}function ce(n){if(n==null)return window;if(n.toString()!=="[object Window]"){var e=n.ownerDocument;return e&&e.defaultView||window}return n}function Ue(n){var e=ce(n).Element;return n instanceof e||n instanceof Element}function be(n){var e=ce(n).HTMLElement;return n instanceof e||n instanceof HTMLElement}function fn(n){if(typeof ShadowRoot=="undefined")return!1;var e=ce(n).ShadowRoot;return n instanceof e||n instanceof ShadowRoot}function du(n){var e=n.state;Object.keys(e.elements).forEach(function(t){var i=e.styles[t]||{},r=e.attributes[t]||{},o=e.elements[t];!be(o)||!we(o)||(Object.assign(o.style,i),Object.keys(r).forEach(function(s){var a=r[s];a===!1?o.removeAttribute(s):o.setAttribute(s,a===!0?"":a)}))})}function fu(n){var e=n.state,t={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,t.popper),e.styles=t,e.elements.arrow&&Object.assign(e.elements.arrow.style,t.arrow),function(){Object.keys(e.elements).forEach(function(i){var r=e.elements[i],o=e.attributes[i]||{},s=Object.keys(e.styles.hasOwnProperty(i)?e.styles[i]:t[i]),a=s.reduce(function(l,c){return l[c]="",l},{});!be(r)||!we(r)||(Object.assign(r.style,a),Object.keys(o).forEach(function(l){r.removeAttribute(l)}))})}}var hn={name:"applyStyles",enabled:!0,phase:"write",fn:du,effect:fu,requires:["computeStyles"]};function xe(n){return n.split("-")[0]}var Ze=Math.max,Bt=Math.min,ct=Math.round;function pn(){var n=navigator.userAgentData;return n!=null&&n.brands&&Array.isArray(n.brands)?n.brands.map(function(e){return e.brand+"/"+e.version}).join(" "):navigator.userAgent}function Un(){return!/^((?!chrome|android).)*safari/i.test(pn())}function Ye(n,e,t){e===void 0&&(e=!1),t===void 0&&(t=!1);var i=n.getBoundingClientRect(),r=1,o=1;e&&be(n)&&(r=n.offsetWidth>0&&ct(i.width)/n.offsetWidth||1,o=n.offsetHeight>0&&ct(i.height)/n.offsetHeight||1);var s=Ue(n)?ce(n):window,a=s.visualViewport,l=!Un()&&t,c=(i.left+(l&&a?a.offsetLeft:0))/r,u=(i.top+(l&&a?a.offsetTop:0))/o,d=i.width/r,p=i.height/o;return{width:d,height:p,top:u,right:c+d,bottom:u+p,left:c,x:c,y:u}}function Vt(n){var e=Ye(n),t=n.offsetWidth,i=n.offsetHeight;return Math.abs(e.width-t)<=1&&(t=e.width),Math.abs(e.height-i)<=1&&(i=e.height),{x:n.offsetLeft,y:n.offsetTop,width:t,height:i}}function Yn(n,e){var t=e.getRootNode&&e.getRootNode();if(n.contains(e))return!0;if(t&&fn(t)){var i=e;do{if(i&&n.isSameNode(i))return!0;i=i.parentNode||i.host}while(i)}return!1}function Me(n){return ce(n).getComputedStyle(n)}function Kr(n){return["table","td","th"].indexOf(we(n))>=0}function Ae(n){return((Ue(n)?n.ownerDocument:n.document)||window.document).documentElement}function ut(n){return we(n)==="html"?n:n.assignedSlot||n.parentNode||(fn(n)?n.host:null)||Ae(n)}function As(n){return!be(n)||Me(n).position==="fixed"?null:n.offsetParent}function hu(n){var e=/firefox/i.test(pn()),t=/Trident/i.test(pn());if(t&&be(n)){var i=Me(n);if(i.position==="fixed")return null}var r=ut(n);for(fn(r)&&(r=r.host);be(r)&&["html","body"].indexOf(we(r))<0;){var o=Me(r);if(o.transform!=="none"||o.perspective!=="none"||o.contain==="paint"||["transform","perspective"].indexOf(o.willChange)!==-1||e&&o.willChange==="filter"||e&&o.filter&&o.filter!=="none")return r;r=r.parentNode}return null}function et(n){for(var e=ce(n),t=As(n);t&&Kr(t)&&Me(t).position==="static";)t=As(t);return t&&(we(t)==="html"||we(t)==="body"&&Me(t).position==="static")?e:t||hu(n)||e}function zt(n){return["top","bottom"].indexOf(n)>=0?"x":"y"}function jt(n,e,t){return Ze(n,Bt(e,t))}function Ss(n,e,t){var i=jt(n,e,t);return i>t?t:i}function Gn(){return{top:0,right:0,bottom:0,left:0}}function Kn(n){return Object.assign({},Gn(),n)}function Xn(n,e){return e.reduce(function(t,i){return t[i]=n,t},{})}var pu=function(e,t){return e=typeof e=="function"?e(Object.assign({},t.rects,{placement:t.placement})):e,Kn(typeof e!="number"?e:Xn(e,lt))};function mu(n){var e,t=n.state,i=n.name,r=n.options,o=t.elements.arrow,s=t.modifiersData.popperOffsets,a=xe(t.placement),l=zt(a),c=[he,me].indexOf(a)>=0,u=c?"height":"width";if(!(!o||!s)){var d=pu(r.padding,t),p=Vt(o),y=l==="y"?de:he,m=l==="y"?ge:me,v=t.rects.reference[u]+t.rects.reference[l]-s[l]-t.rects.popper[u],w=s[l]-t.rects.reference[l],T=et(o),_=T?l==="y"?T.clientHeight||0:T.clientWidth||0:0,S=v/2-w/2,A=d[y],K=_-p[u]-d[m],z=_/2-p[u]/2+S,L=jt(A,z,K),H=l;t.modifiersData[i]=(e={},e[H]=L,e.centerOffset=L-z,e)}}function gu(n){var e=n.state,t=n.options,i=t.element,r=i===void 0?"[data-popper-arrow]":i;r!=null&&(typeof r=="string"&&(r=e.elements.popper.querySelector(r),!r)||Yn(e.elements.popper,r)&&(e.elements.arrow=r))}var Ni={name:"arrow",enabled:!0,phase:"main",fn:mu,effect:gu,requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function Ge(n){return n.split("-")[1]}var vu={top:"auto",right:"auto",bottom:"auto",left:"auto"};function yu(n,e){var t=n.x,i=n.y,r=e.devicePixelRatio||1;return{x:ct(t*r)/r||0,y:ct(i*r)/r||0}}function Ds(n){var e,t=n.popper,i=n.popperRect,r=n.placement,o=n.variation,s=n.offsets,a=n.position,l=n.gpuAcceleration,c=n.adaptive,u=n.roundOffsets,d=n.isFixed,p=s.x,y=p===void 0?0:p,m=s.y,v=m===void 0?0:m,w=typeof u=="function"?u({x:y,y:v}):{x:y,y:v};y=w.x,v=w.y;var T=s.hasOwnProperty("x"),_=s.hasOwnProperty("y"),S=he,A=de,K=window;if(c){var z=et(t),L="clientHeight",H="clientWidth";if(z===ce(t)&&(z=Ae(t),Me(z).position!=="static"&&a==="absolute"&&(L="scrollHeight",H="scrollWidth")),z=z,r===de||(r===he||r===me)&&o===bt){A=ge;var N=d&&z===K&&K.visualViewport?K.visualViewport.height:z[L];v-=N-i.height,v*=l?1:-1}if(r===he||(r===de||r===ge)&&o===bt){S=me;var Y=d&&z===K&&K.visualViewport?K.visualViewport.width:z[H];y-=Y-i.width,y*=l?1:-1}}var $=Object.assign({position:a},c&&vu),ie=u===!0?yu({x:y,y:v},ce(t)):{x:y,y:v};if(y=ie.x,v=ie.y,l){var J;return Object.assign({},$,(J={},J[A]=_?"0":"",J[S]=T?"0":"",J.transform=(K.devicePixelRatio||1)<=1?"translate("+y+"px, "+v+"px)":"translate3d("+y+"px, "+v+"px, 0)",J))}return Object.assign({},$,(e={},e[A]=_?v+"px":"",e[S]=T?y+"px":"",e.transform="",e))}function Eu(n){var e=n.state,t=n.options,i=t.gpuAcceleration,r=i===void 0?!0:i,o=t.adaptive,s=o===void 0?!0:o,a=t.roundOffsets,l=a===void 0?!0:a,c={placement:xe(e.placement),variation:Ge(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:r,isFixed:e.options.strategy==="fixed"};e.modifiersData.popperOffsets!=null&&(e.styles.popper=Object.assign({},e.styles.popper,Ds(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:s,roundOffsets:l})))),e.modifiersData.arrow!=null&&(e.styles.arrow=Object.assign({},e.styles.arrow,Ds(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})}var mn={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:Eu,data:{}};var Ii={passive:!0};function bu(n){var e=n.state,t=n.instance,i=n.options,r=i.scroll,o=r===void 0?!0:r,s=i.resize,a=s===void 0?!0:s,l=ce(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach(function(u){u.addEventListener("scroll",t.update,Ii)}),a&&l.addEventListener("resize",t.update,Ii),function(){o&&c.forEach(function(u){u.removeEventListener("scroll",t.update,Ii)}),a&&l.removeEventListener("resize",t.update,Ii)}}var gn={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:bu,data:{}};var _u={left:"right",right:"left",bottom:"top",top:"bottom"};function vn(n){return n.replace(/left|right|bottom|top/g,function(e){return _u[e]})}var wu={start:"end",end:"start"};function Ri(n){return n.replace(/start|end/g,function(e){return wu[e]})}function Wt(n){var e=ce(n),t=e.pageXOffset,i=e.pageYOffset;return{scrollLeft:t,scrollTop:i}}function qt(n){return Ye(Ae(n)).left+Wt(n).scrollLeft}function Xr(n,e){var t=ce(n),i=Ae(n),r=t.visualViewport,o=i.clientWidth,s=i.clientHeight,a=0,l=0;if(r){o=r.width,s=r.height;var c=Un();(c||!c&&e==="fixed")&&(a=r.offsetLeft,l=r.offsetTop)}return{width:o,height:s,x:a+qt(n),y:l}}function Qr(n){var e,t=Ae(n),i=Wt(n),r=(e=n.ownerDocument)==null?void 0:e.body,o=Ze(t.scrollWidth,t.clientWidth,r?r.scrollWidth:0,r?r.clientWidth:0),s=Ze(t.scrollHeight,t.clientHeight,r?r.scrollHeight:0,r?r.clientHeight:0),a=-i.scrollLeft+qt(n),l=-i.scrollTop;return Me(r||t).direction==="rtl"&&(a+=Ze(t.clientWidth,r?r.clientWidth:0)-o),{width:o,height:s,x:a,y:l}}function Ut(n){var e=Me(n),t=e.overflow,i=e.overflowX,r=e.overflowY;return/auto|scroll|overlay|hidden/.test(t+r+i)}function Hi(n){return["html","body","#document"].indexOf(we(n))>=0?n.ownerDocument.body:be(n)&&Ut(n)?n:Hi(ut(n))}function _t(n,e){var t;e===void 0&&(e=[]);var i=Hi(n),r=i===((t=n.ownerDocument)==null?void 0:t.body),o=ce(i),s=r?[o].concat(o.visualViewport||[],Ut(i)?i:[]):i,a=e.concat(s);return r?a:a.concat(_t(ut(s)))}function yn(n){return Object.assign({},n,{left:n.x,top:n.y,right:n.x+n.width,bottom:n.y+n.height})}function xu(n,e){var t=Ye(n,!1,e==="fixed");return t.top=t.top+n.clientTop,t.left=t.left+n.clientLeft,t.bottom=t.top+n.clientHeight,t.right=t.left+n.clientWidth,t.width=n.clientWidth,t.height=n.clientHeight,t.x=t.left,t.y=t.top,t}function Os(n,e,t){return e===Wn?yn(Xr(n,t)):Ue(e)?xu(e,t):yn(Qr(Ae(n)))}function Tu(n){var e=_t(ut(n)),t=["absolute","fixed"].indexOf(Me(n).position)>=0,i=t&&be(n)?et(n):n;return Ue(i)?e.filter(function(r){return Ue(r)&&Yn(r,i)&&we(r)!=="body"}):[]}function Jr(n,e,t,i){var r=e==="clippingParents"?Tu(n):[].concat(e),o=[].concat(r,[t]),s=o[0],a=o.reduce(function(l,c){var u=Os(n,c,i);return l.top=Ze(u.top,l.top),l.right=Bt(u.right,l.right),l.bottom=Bt(u.bottom,l.bottom),l.left=Ze(u.left,l.left),l},Os(n,s,i));return a.width=a.right-a.left,a.height=a.bottom-a.top,a.x=a.left,a.y=a.top,a}function Qn(n){var e=n.reference,t=n.element,i=n.placement,r=i?xe(i):null,o=i?Ge(i):null,s=e.x+e.width/2-t.width/2,a=e.y+e.height/2-t.height/2,l;switch(r){case de:l={x:s,y:e.y-t.height};break;case ge:l={x:s,y:e.y+e.height};break;case me:l={x:e.x+e.width,y:a};break;case he:l={x:e.x-t.width,y:a};break;default:l={x:e.x,y:e.y}}var c=r?zt(r):null;if(c!=null){var u=c==="y"?"height":"width";switch(o){case rt:l[c]=l[c]-(e[u]/2-t[u]/2);break;case bt:l[c]=l[c]+(e[u]/2-t[u]/2);break;default:}}return l}function ke(n,e){e===void 0&&(e={});var t=e,i=t.placement,r=i===void 0?n.placement:i,o=t.strategy,s=o===void 0?n.strategy:o,a=t.boundary,l=a===void 0?Ur:a,c=t.rootBoundary,u=c===void 0?Wn:c,d=t.elementContext,p=d===void 0?$t:d,y=t.altBoundary,m=y===void 0?!1:y,v=t.padding,w=v===void 0?0:v,T=Kn(typeof w!="number"?w:Xn(w,lt)),_=p===$t?Yr:$t,S=n.rects.popper,A=n.elements[m?_:p],K=Jr(Ue(A)?A:A.contextElement||Ae(n.elements.popper),l,u,s),z=Ye(n.elements.reference),L=Qn({reference:z,element:S,strategy:"absolute",placement:r}),H=yn(Object.assign({},S,L)),N=p===$t?H:z,Y={top:K.top-N.top+T.top,bottom:N.bottom-K.bottom+T.bottom,left:K.left-N.left+T.left,right:N.right-K.right+T.right},$=n.modifiersData.offset;if(p===$t&&$){var ie=$[r];Object.keys(Y).forEach(function(J){var Te=[me,ge].indexOf(J)>=0?1:-1,Ce=[de,ge].indexOf(J)>=0?"y":"x";Y[J]+=ie[Ce]*Te})}return Y}function Zr(n,e){e===void 0&&(e={});var t=e,i=t.placement,r=t.boundary,o=t.rootBoundary,s=t.padding,a=t.flipVariations,l=t.allowedAutoPlacements,c=l===void 0?qn:l,u=Ge(i),d=u?a?ki:ki.filter(function(m){return Ge(m)===u}):lt,p=d.filter(function(m){return c.indexOf(m)>=0});p.length===0&&(p=d);var y=p.reduce(function(m,v){return m[v]=ke(n,{placement:v,boundary:r,rootBoundary:o,padding:s})[xe(v)],m},{});return Object.keys(y).sort(function(m,v){return y[m]-y[v]})}function Cu(n){if(xe(n)===jn)return[];var e=vn(n);return[Ri(n),e,Ri(e)]}function Au(n){var e=n.state,t=n.options,i=n.name;if(!e.modifiersData[i]._skip){for(var r=t.mainAxis,o=r===void 0?!0:r,s=t.altAxis,a=s===void 0?!0:s,l=t.fallbackPlacements,c=t.padding,u=t.boundary,d=t.rootBoundary,p=t.altBoundary,y=t.flipVariations,m=y===void 0?!0:y,v=t.allowedAutoPlacements,w=e.options.placement,T=xe(w),_=T===w,S=l||(_||!m?[vn(w)]:Cu(w)),A=[w].concat(S).reduce(function(V,q){return V.concat(xe(q)===jn?Zr(e,{placement:q,boundary:u,rootBoundary:d,padding:c,flipVariations:m,allowedAutoPlacements:v}):q)},[]),K=e.rects.reference,z=e.rects.popper,L=new Map,H=!0,N=A[0],Y=0;Y=0,Ce=Te?"width":"height",se=ke(e,{placement:$,boundary:u,rootBoundary:d,altBoundary:p,padding:c}),ne=Te?J?me:he:J?ge:de;K[Ce]>z[Ce]&&(ne=vn(ne));var qe=vn(ne),Re=[];if(o&&Re.push(se[ie]<=0),a&&Re.push(se[ne]<=0,se[qe]<=0),Re.every(function(V){return V})){N=$,H=!1;break}L.set($,Re)}if(H)for(var W=m?3:1,M=function(q){var U=A.find(function(Z){var oe=L.get(Z);if(oe)return oe.slice(0,q).every(function(Et){return Et})});if(U)return N=U,"break"},D=W;D>0;D--){var B=M(D);if(B==="break")break}e.placement!==N&&(e.modifiersData[i]._skip=!0,e.placement=N,e.reset=!0)}}var Pi={name:"flip",enabled:!0,phase:"main",fn:Au,requiresIfExists:["offset"],data:{_skip:!1}};function Ls(n,e,t){return t===void 0&&(t={x:0,y:0}),{top:n.top-e.height-t.y,right:n.right-e.width+t.x,bottom:n.bottom-e.height+t.y,left:n.left-e.width-t.x}}function Ms(n){return[de,me,ge,he].some(function(e){return n[e]>=0})}function Su(n){var e=n.state,t=n.name,i=e.rects.reference,r=e.rects.popper,o=e.modifiersData.preventOverflow,s=ke(e,{elementContext:"reference"}),a=ke(e,{altBoundary:!0}),l=Ls(s,i),c=Ls(a,r,o),u=Ms(l),d=Ms(c);e.modifiersData[t]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:u,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":u,"data-popper-escaped":d})}var Fi={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:Su};function Du(n,e,t){var i=xe(n),r=[he,de].indexOf(i)>=0?-1:1,o=typeof t=="function"?t(Object.assign({},e,{placement:n})):t,s=o[0],a=o[1];return s=s||0,a=(a||0)*r,[he,me].indexOf(i)>=0?{x:a,y:s}:{x:s,y:a}}function Ou(n){var e=n.state,t=n.options,i=n.name,r=t.offset,o=r===void 0?[0,0]:r,s=qn.reduce(function(u,d){return u[d]=Du(d,e.rects,o),u},{}),a=s[e.placement],l=a.x,c=a.y;e.modifiersData.popperOffsets!=null&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[i]=s}var $i={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:Ou};function Lu(n){var e=n.state,t=n.name;e.modifiersData[t]=Qn({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})}var En={name:"popperOffsets",enabled:!0,phase:"read",fn:Lu,data:{}};function eo(n){return n==="x"?"y":"x"}function Mu(n){var e=n.state,t=n.options,i=n.name,r=t.mainAxis,o=r===void 0?!0:r,s=t.altAxis,a=s===void 0?!1:s,l=t.boundary,c=t.rootBoundary,u=t.altBoundary,d=t.padding,p=t.tether,y=p===void 0?!0:p,m=t.tetherOffset,v=m===void 0?0:m,w=ke(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:u}),T=xe(e.placement),_=Ge(e.placement),S=!_,A=zt(T),K=eo(A),z=e.modifiersData.popperOffsets,L=e.rects.reference,H=e.rects.popper,N=typeof v=="function"?v(Object.assign({},e.rects,{placement:e.placement})):v,Y=typeof N=="number"?{mainAxis:N,altAxis:N}:Object.assign({mainAxis:0,altAxis:0},N),$=e.modifiersData.offset?e.modifiersData.offset[e.placement]:null,ie={x:0,y:0};if(z){if(o){var J,Te=A==="y"?de:he,Ce=A==="y"?ge:me,se=A==="y"?"height":"width",ne=z[A],qe=ne+w[Te],Re=ne-w[Ce],W=y?-H[se]/2:0,M=_===rt?L[se]:H[se],D=_===rt?-H[se]:-L[se],B=e.elements.arrow,V=y&&B?Vt(B):{width:0,height:0},q=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:Gn(),U=q[Te],Z=q[Ce],oe=jt(0,L[se],V[se]),Et=S?L[se]/2-W-oe-U-Y.mainAxis:M-oe-U-Y.mainAxis,$r=S?-L[se]/2+W+oe+Z+Y.mainAxis:D+oe+Z+Y.mainAxis,on=e.elements.arrow&&et(e.elements.arrow),sn=on?A==="y"?on.clientTop||0:on.clientLeft||0:0,Ti=(J=$==null?void 0:$[A])!=null?J:0,Br=ne+Et-Ti-sn,Ci=ne+$r-Ti,Ai=jt(y?Bt(qe,Br):qe,ne,y?Ze(Re,Ci):Re);z[A]=Ai,ie[A]=Ai-ne}if(a){var $n,Si=A==="x"?de:he,an=A==="x"?ge:me,ot=z[K],ln=K==="y"?"height":"width",Bn=ot+w[Si],cn=ot-w[an],un=[de,he].indexOf(T)!==-1,Ft=($n=$==null?void 0:$[K])!=null?$n:0,Di=un?Bn:ot-L[ln]-H[ln]-Ft+Y.altAxis,Vn=un?ot+L[ln]+H[ln]-Ft-Y.altAxis:cn,Oi=y&&un?Ss(Di,ot,Vn):jt(y?Di:Bn,ot,y?Vn:cn);z[K]=Oi,ie[K]=Oi-ot}e.modifiersData[i]=ie}}var Bi={name:"preventOverflow",enabled:!0,phase:"main",fn:Mu,requiresIfExists:["offset"]};function to(n){return{scrollLeft:n.scrollLeft,scrollTop:n.scrollTop}}function no(n){return n===ce(n)||!be(n)?Wt(n):to(n)}function ku(n){var e=n.getBoundingClientRect(),t=ct(e.width)/n.offsetWidth||1,i=ct(e.height)/n.offsetHeight||1;return t!==1||i!==1}function io(n,e,t){t===void 0&&(t=!1);var i=be(e),r=be(e)&&ku(e),o=Ae(e),s=Ye(n,r,t),a={scrollLeft:0,scrollTop:0},l={x:0,y:0};return(i||!i&&!t)&&((we(e)!=="body"||Ut(o))&&(a=no(e)),be(e)?(l=Ye(e,!0),l.x+=e.clientLeft,l.y+=e.clientTop):o&&(l.x=qt(o))),{x:s.left+a.scrollLeft-l.x,y:s.top+a.scrollTop-l.y,width:s.width,height:s.height}}function Nu(n){var e=new Map,t=new Set,i=[];n.forEach(function(o){e.set(o.name,o)});function r(o){t.add(o.name);var s=[].concat(o.requires||[],o.requiresIfExists||[]);s.forEach(function(a){if(!t.has(a)){var l=e.get(a);l&&r(l)}}),i.push(o)}return n.forEach(function(o){t.has(o.name)||r(o)}),i}function ro(n){var e=Nu(n);return Gr.reduce(function(t,i){return t.concat(e.filter(function(r){return r.phase===i}))},[])}function oo(n){var e;return function(){return e||(e=new Promise(function(t){Promise.resolve().then(function(){e=void 0,t(n())})})),e}}function so(n){var e=n.reduce(function(t,i){var r=t[i.name];return t[i.name]=r?Object.assign({},r,i,{options:Object.assign({},r.options,i.options),data:Object.assign({},r.data,i.data)}):i,t},{});return Object.keys(e).map(function(t){return e[t]})}var ks={placement:"bottom",modifiers:[],strategy:"absolute"};function Ns(){for(var n=arguments.length,e=new Array(n),t=0;t(n&&window.CSS&&window.CSS.escape&&(n=n.replace(/#([^\s"#']+)/g,(e,t)=>`#${CSS.escape(t)}`)),n),Fu=n=>n==null?`${n}`:Object.prototype.toString.call(n).match(/\s([a-z]+)/i)[1].toLowerCase(),$u=n=>{do n+=Math.floor(Math.random()*Hu);while(document.getElementById(n));return n},Bu=n=>{if(!n)return 0;let{transitionDuration:e,transitionDelay:t}=window.getComputedStyle(n),i=Number.parseFloat(e),r=Number.parseFloat(t);return!i&&!r?0:(e=e.split(",")[0],t=t.split(",")[0],(Number.parseFloat(e)+Number.parseFloat(t))*Pu)},da=n=>{n.dispatchEvent(new Event(To))},dt=n=>!n||typeof n!="object"?!1:(typeof n.jquery!="undefined"&&(n=n[0]),typeof n.nodeType!="undefined"),xt=n=>dt(n)?n.jquery?n[0]:n:typeof n=="string"&&n.length>0?document.querySelector(ua(n)):null,An=n=>{if(!dt(n)||n.getClientRects().length===0)return!1;let e=getComputedStyle(n).getPropertyValue("visibility")==="visible",t=n.closest("details:not([open])");if(!t)return e;if(t!==n){let i=n.closest("summary");if(i&&i.parentNode!==t||i===null)return!1}return e},Tt=n=>!n||n.nodeType!==Node.ELEMENT_NODE||n.classList.contains("disabled")?!0:typeof n.disabled!="undefined"?n.disabled:n.hasAttribute("disabled")&&n.getAttribute("disabled")!=="false",fa=n=>{if(!document.documentElement.attachShadow)return null;if(typeof n.getRootNode=="function"){let e=n.getRootNode();return e instanceof ShadowRoot?e:null}return n instanceof ShadowRoot?n:n.parentNode?fa(n.parentNode):null},Xi=()=>{},ii=n=>{n.offsetHeight},ha=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,lo=[],Vu=n=>{document.readyState==="loading"?(lo.length||document.addEventListener("DOMContentLoaded",()=>{for(let e of lo)e()}),lo.push(n)):n()},Ke=()=>document.documentElement.dir==="rtl",Qe=n=>{Vu(()=>{let e=ha();if(e){let t=n.NAME,i=e.fn[t];e.fn[t]=n.jQueryInterface,e.fn[t].Constructor=n,e.fn[t].noConflict=()=>(e.fn[t]=i,n.jQueryInterface)}})},He=(n,e=[],t=n)=>typeof n=="function"?n.call(...e):t,pa=(n,e,t=!0)=>{if(!t){He(n);return}let r=Bu(e)+5,o=!1,s=({target:a})=>{a===e&&(o=!0,e.removeEventListener(To,s),He(n))};e.addEventListener(To,s),setTimeout(()=>{o||da(e)},r)},Do=(n,e,t,i)=>{let r=n.length,o=n.indexOf(e);return o===-1?!t&&i?n[r-1]:n[0]:(o+=t?1:-1,i&&(o=(o+r)%r),n[Math.max(0,Math.min(o,r-1))])},zu=/[^.]*(?=\..*)\.|.*/,ju=/\..*/,Wu=/::\d+$/,co={},Hs=1,ma={mouseenter:"mouseover",mouseleave:"mouseout"},qu=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function ga(n,e){return e&&`${e}::${Hs++}`||n.uidEvent||Hs++}function va(n){let e=ga(n);return n.uidEvent=e,co[e]=co[e]||{},co[e]}function Uu(n,e){return function t(i){return Oo(i,{delegateTarget:n}),t.oneOff&&x.off(n,i.type,e),e.apply(n,[i])}}function Yu(n,e,t){return function i(r){let o=n.querySelectorAll(e);for(let{target:s}=r;s&&s!==this;s=s.parentNode)for(let a of o)if(a===s)return Oo(r,{delegateTarget:s}),i.oneOff&&x.off(n,r.type,e,t),t.apply(s,[r])}}function ya(n,e,t=null){return Object.values(n).find(i=>i.callable===e&&i.delegationSelector===t)}function Ea(n,e,t){let i=typeof e=="string",r=i?t:e||t,o=ba(n);return qu.has(o)||(o=n),[i,r,o]}function Ps(n,e,t,i,r){if(typeof e!="string"||!n)return;let[o,s,a]=Ea(e,t,i);e in ma&&(s=(m=>function(v){if(!v.relatedTarget||v.relatedTarget!==v.delegateTarget&&!v.delegateTarget.contains(v.relatedTarget))return m.call(this,v)})(s));let l=va(n),c=l[a]||(l[a]={}),u=ya(c,s,o?t:null);if(u){u.oneOff=u.oneOff&&r;return}let d=ga(s,e.replace(zu,"")),p=o?Yu(n,t,s):Uu(n,s);p.delegationSelector=o?t:null,p.callable=s,p.oneOff=r,p.uidEvent=d,c[d]=p,n.addEventListener(a,p,o)}function Co(n,e,t,i,r){let o=ya(e[t],i,r);o&&(n.removeEventListener(t,o,!!r),delete e[t][o.uidEvent])}function Gu(n,e,t,i){let r=e[t]||{};for(let[o,s]of Object.entries(r))o.includes(i)&&Co(n,e,t,s.callable,s.delegationSelector)}function ba(n){return n=n.replace(ju,""),ma[n]||n}var x={on(n,e,t,i){Ps(n,e,t,i,!1)},one(n,e,t,i){Ps(n,e,t,i,!0)},off(n,e,t,i){if(typeof e!="string"||!n)return;let[r,o,s]=Ea(e,t,i),a=s!==e,l=va(n),c=l[s]||{},u=e.startsWith(".");if(typeof o!="undefined"){if(!Object.keys(c).length)return;Co(n,l,s,o,r?t:null);return}if(u)for(let d of Object.keys(l))Gu(n,l,d,e.slice(1));for(let[d,p]of Object.entries(c)){let y=d.replace(Wu,"");(!a||e.includes(y))&&Co(n,l,s,p.callable,p.delegationSelector)}},trigger(n,e,t){if(typeof e!="string"||!n)return null;let i=ha(),r=ba(e),o=e!==r,s=null,a=!0,l=!0,c=!1;o&&i&&(s=i.Event(e,t),i(n).trigger(s),a=!s.isPropagationStopped(),l=!s.isImmediatePropagationStopped(),c=s.isDefaultPrevented());let u=Oo(new Event(e,{bubbles:a,cancelable:!0}),t);return c&&u.preventDefault(),l&&n.dispatchEvent(u),u.defaultPrevented&&s&&s.preventDefault(),u}};function Oo(n,e={}){for(let[t,i]of Object.entries(e))try{n[t]=i}catch(r){Object.defineProperty(n,t,{configurable:!0,get(){return i}})}return n}function Fs(n){if(n==="true")return!0;if(n==="false")return!1;if(n===Number(n).toString())return Number(n);if(n===""||n==="null")return null;if(typeof n!="string")return n;try{return JSON.parse(decodeURIComponent(n))}catch(e){return n}}function uo(n){return n.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}var ft={setDataAttribute(n,e,t){n.setAttribute(`data-bs-${uo(e)}`,t)},removeDataAttribute(n,e){n.removeAttribute(`data-bs-${uo(e)}`)},getDataAttributes(n){if(!n)return{};let e={},t=Object.keys(n.dataset).filter(i=>i.startsWith("bs")&&!i.startsWith("bsConfig"));for(let i of t){let r=i.replace(/^bs/,"");r=r.charAt(0).toLowerCase()+r.slice(1),e[r]=Fs(n.dataset[i])}return e},getDataAttribute(n,e){return Fs(n.getAttribute(`data-bs-${uo(e)}`))}},Xt=class{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(e){return e=this._mergeConfigObj(e),e=this._configAfterMerge(e),this._typeCheckConfig(e),e}_configAfterMerge(e){return e}_mergeConfigObj(e,t){let i=dt(t)?ft.getDataAttribute(t,"config"):{};return O(O(O(O({},this.constructor.Default),typeof i=="object"?i:{}),dt(t)?ft.getDataAttributes(t):{}),typeof e=="object"?e:{})}_typeCheckConfig(e,t=this.constructor.DefaultType){for(let[i,r]of Object.entries(t)){let o=e[i],s=dt(o)?"element":Fu(o);if(!new RegExp(r).test(s))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${i}" provided type "${s}" but expected type "${r}".`)}}},Ku="5.3.8",je=class extends Xt{constructor(e,t){super(),e=xt(e),e&&(this._element=e,this._config=this._getConfig(t),ao.set(this._element,this.constructor.DATA_KEY,this))}dispose(){ao.remove(this._element,this.constructor.DATA_KEY),x.off(this._element,this.constructor.EVENT_KEY);for(let e of Object.getOwnPropertyNames(this))this[e]=null}_queueCallback(e,t,i=!0){pa(e,t,i)}_getConfig(e){return e=this._mergeConfigObj(e,this._element),e=this._configAfterMerge(e),this._typeCheckConfig(e),e}static getInstance(e){return ao.get(xt(e),this.DATA_KEY)}static getOrCreateInstance(e,t={}){return this.getInstance(e)||new this(e,typeof t=="object"?t:null)}static get VERSION(){return Ku}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(e){return`${e}${this.EVENT_KEY}`}},fo=n=>{let e=n.getAttribute("data-bs-target");if(!e||e==="#"){let t=n.getAttribute("href");if(!t||!t.includes("#")&&!t.startsWith("."))return null;t.includes("#")&&!t.startsWith("#")&&(t=`#${t.split("#")[1]}`),e=t&&t!=="#"?t.trim():null}return e?e.split(",").map(t=>ua(t)).join(","):null},j={find(n,e=document.documentElement){return[].concat(...Element.prototype.querySelectorAll.call(e,n))},findOne(n,e=document.documentElement){return Element.prototype.querySelector.call(e,n)},children(n,e){return[].concat(...n.children).filter(t=>t.matches(e))},parents(n,e){let t=[],i=n.parentNode.closest(e);for(;i;)t.push(i),i=i.parentNode.closest(e);return t},prev(n,e){let t=n.previousElementSibling;for(;t;){if(t.matches(e))return[t];t=t.previousElementSibling}return[]},next(n,e){let t=n.nextElementSibling;for(;t;){if(t.matches(e))return[t];t=t.nextElementSibling}return[]},focusableChildren(n){let e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map(t=>`${t}:not([tabindex^="-"])`).join(",");return this.find(e,n).filter(t=>!Tt(t)&&An(t))},getSelectorFromElement(n){let e=fo(n);return e&&j.findOne(e)?e:null},getElementFromSelector(n){let e=fo(n);return e?j.findOne(e):null},getMultipleElementsFromSelector(n){let e=fo(n);return e?j.find(e):[]}},rr=(n,e="hide")=>{let t=`click.dismiss${n.EVENT_KEY}`,i=n.NAME;x.on(document,t,`[data-bs-dismiss="${i}"]`,function(r){if(["A","AREA"].includes(this.tagName)&&r.preventDefault(),Tt(this))return;let o=j.getElementFromSelector(this)||this.closest(`.${i}`);n.getOrCreateInstance(o)[e]()})},Xu="alert",Qu="bs.alert",_a=`.${Qu}`,Ju=`close${_a}`,Zu=`closed${_a}`,ed="fade",td="show",Qi=class n extends je{static get NAME(){return Xu}close(){if(x.trigger(this._element,Ju).defaultPrevented)return;this._element.classList.remove(td);let t=this._element.classList.contains(ed);this._queueCallback(()=>this._destroyElement(),this._element,t)}_destroyElement(){this._element.remove(),x.trigger(this._element,Zu),this.dispose()}static jQueryInterface(e){return this.each(function(){let t=n.getOrCreateInstance(this);if(typeof e=="string"){if(t[e]===void 0||e.startsWith("_")||e==="constructor")throw new TypeError(`No method named "${e}"`);t[e](this)}})}};rr(Qi,"close");Qe(Qi);var nd="button",id="bs.button",rd=`.${id}`,od=".data-api",sd="active",$s='[data-bs-toggle="button"]',ad=`click${rd}${od}`,Ji=class n extends je{static get NAME(){return nd}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle(sd))}static jQueryInterface(e){return this.each(function(){let t=n.getOrCreateInstance(this);e==="toggle"&&t[e]()})}};x.on(document,ad,$s,n=>{n.preventDefault();let e=n.target.closest($s);Ji.getOrCreateInstance(e).toggle()});Qe(Ji);var ld="swipe",Sn=".bs.swipe",cd=`touchstart${Sn}`,ud=`touchmove${Sn}`,dd=`touchend${Sn}`,fd=`pointerdown${Sn}`,hd=`pointerup${Sn}`,pd="touch",md="pen",gd="pointer-event",vd=40,yd={endCallback:null,leftCallback:null,rightCallback:null},Ed={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"},Zi=class n extends Xt{constructor(e,t){super(),this._element=e,!(!e||!n.isSupported())&&(this._config=this._getConfig(t),this._deltaX=0,this._supportPointerEvents=!!window.PointerEvent,this._initEvents())}static get Default(){return yd}static get DefaultType(){return Ed}static get NAME(){return ld}dispose(){x.off(this._element,Sn)}_start(e){if(!this._supportPointerEvents){this._deltaX=e.touches[0].clientX;return}this._eventIsPointerPenTouch(e)&&(this._deltaX=e.clientX)}_end(e){this._eventIsPointerPenTouch(e)&&(this._deltaX=e.clientX-this._deltaX),this._handleSwipe(),He(this._config.endCallback)}_move(e){this._deltaX=e.touches&&e.touches.length>1?0:e.touches[0].clientX-this._deltaX}_handleSwipe(){let e=Math.abs(this._deltaX);if(e<=vd)return;let t=e/this._deltaX;this._deltaX=0,t&&He(t>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(x.on(this._element,fd,e=>this._start(e)),x.on(this._element,hd,e=>this._end(e)),this._element.classList.add(gd)):(x.on(this._element,cd,e=>this._start(e)),x.on(this._element,ud,e=>this._move(e)),x.on(this._element,dd,e=>this._end(e)))}_eventIsPointerPenTouch(e){return this._supportPointerEvents&&(e.pointerType===md||e.pointerType===pd)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}},bd="carousel",_d="bs.carousel",Dt=`.${_d}`,wa=".data-api",wd="ArrowLeft",xd="ArrowRight",Td=500,Zn="next",bn="prev",wn="left",Gi="right",Cd=`slide${Dt}`,ho=`slid${Dt}`,Ad=`keydown${Dt}`,Sd=`mouseenter${Dt}`,Dd=`mouseleave${Dt}`,Od=`dragstart${Dt}`,Ld=`load${Dt}${wa}`,Md=`click${Dt}${wa}`,xa="carousel",zi="active",kd="slide",Nd="carousel-item-end",Id="carousel-item-start",Rd="carousel-item-next",Hd="carousel-item-prev",Ta=".active",Ca=".carousel-item",Pd=Ta+Ca,Fd=".carousel-item img",$d=".carousel-indicators",Bd="[data-bs-slide], [data-bs-slide-to]",Vd='[data-bs-ride="carousel"]',zd={[wd]:Gi,[xd]:wn},jd={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},Wd={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"},ti=class n extends je{constructor(e,t){super(e,t),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=j.findOne($d,this._element),this._addEventListeners(),this._config.ride===xa&&this.cycle()}static get Default(){return jd}static get DefaultType(){return Wd}static get NAME(){return bd}next(){this._slide(Zn)}nextWhenVisible(){!document.hidden&&An(this._element)&&this.next()}prev(){this._slide(bn)}pause(){this._isSliding&&da(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval(()=>this.nextWhenVisible(),this._config.interval)}_maybeEnableCycle(){if(this._config.ride){if(this._isSliding){x.one(this._element,ho,()=>this.cycle());return}this.cycle()}}to(e){let t=this._getItems();if(e>t.length-1||e<0)return;if(this._isSliding){x.one(this._element,ho,()=>this.to(e));return}let i=this._getItemIndex(this._getActive());if(i===e)return;let r=e>i?Zn:bn;this._slide(r,t[e])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(e){return e.defaultInterval=e.interval,e}_addEventListeners(){this._config.keyboard&&x.on(this._element,Ad,e=>this._keydown(e)),this._config.pause==="hover"&&(x.on(this._element,Sd,()=>this.pause()),x.on(this._element,Dd,()=>this._maybeEnableCycle())),this._config.touch&&Zi.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(let i of j.find(Fd,this._element))x.on(i,Od,r=>r.preventDefault());let t={leftCallback:()=>this._slide(this._directionToOrder(wn)),rightCallback:()=>this._slide(this._directionToOrder(Gi)),endCallback:()=>{this._config.pause==="hover"&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout(()=>this._maybeEnableCycle(),Td+this._config.interval))}};this._swipeHelper=new Zi(this._element,t)}_keydown(e){if(/input|textarea/i.test(e.target.tagName))return;let t=zd[e.key];t&&(e.preventDefault(),this._slide(this._directionToOrder(t)))}_getItemIndex(e){return this._getItems().indexOf(e)}_setActiveIndicatorElement(e){if(!this._indicatorsElement)return;let t=j.findOne(Ta,this._indicatorsElement);t.classList.remove(zi),t.removeAttribute("aria-current");let i=j.findOne(`[data-bs-slide-to="${e}"]`,this._indicatorsElement);i&&(i.classList.add(zi),i.setAttribute("aria-current","true"))}_updateInterval(){let e=this._activeElement||this._getActive();if(!e)return;let t=Number.parseInt(e.getAttribute("data-bs-interval"),10);this._config.interval=t||this._config.defaultInterval}_slide(e,t=null){if(this._isSliding)return;let i=this._getActive(),r=e===Zn,o=t||Do(this._getItems(),i,r,this._config.wrap);if(o===i)return;let s=this._getItemIndex(o),a=y=>x.trigger(this._element,y,{relatedTarget:o,direction:this._orderToDirection(e),from:this._getItemIndex(i),to:s});if(a(Cd).defaultPrevented||!i||!o)return;let c=!!this._interval;this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(s),this._activeElement=o;let u=r?Id:Nd,d=r?Rd:Hd;o.classList.add(d),ii(o),i.classList.add(u),o.classList.add(u);let p=()=>{o.classList.remove(u,d),o.classList.add(zi),i.classList.remove(zi,d,u),this._isSliding=!1,a(ho)};this._queueCallback(p,i,this._isAnimated()),c&&this.cycle()}_isAnimated(){return this._element.classList.contains(kd)}_getActive(){return j.findOne(Pd,this._element)}_getItems(){return j.find(Ca,this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(e){return Ke()?e===wn?bn:Zn:e===wn?Zn:bn}_orderToDirection(e){return Ke()?e===bn?wn:Gi:e===bn?Gi:wn}static jQueryInterface(e){return this.each(function(){let t=n.getOrCreateInstance(this,e);if(typeof e=="number"){t.to(e);return}if(typeof e=="string"){if(t[e]===void 0||e.startsWith("_")||e==="constructor")throw new TypeError(`No method named "${e}"`);t[e]()}})}};x.on(document,Md,Bd,function(n){let e=j.getElementFromSelector(this);if(!e||!e.classList.contains(xa))return;n.preventDefault();let t=ti.getOrCreateInstance(e),i=this.getAttribute("data-bs-slide-to");if(i){t.to(i),t._maybeEnableCycle();return}if(ft.getDataAttribute(this,"slide")==="next"){t.next(),t._maybeEnableCycle();return}t.prev(),t._maybeEnableCycle()});x.on(window,Ld,()=>{let n=j.find(Vd);for(let e of n)ti.getOrCreateInstance(e)});Qe(ti);var qd="collapse",Ud="bs.collapse",ri=`.${Ud}`,Yd=".data-api",Gd=`show${ri}`,Kd=`shown${ri}`,Xd=`hide${ri}`,Qd=`hidden${ri}`,Jd=`click${ri}${Yd}`,po="show",Tn="collapse",ji="collapsing",Zd="collapsed",ef=`:scope .${Tn} .${Tn}`,tf="collapse-horizontal",nf="width",rf="height",of=".collapse.show, .collapse.collapsing",Ao='[data-bs-toggle="collapse"]',sf={parent:null,toggle:!0},af={parent:"(null|element)",toggle:"boolean"},Ct=class n extends je{constructor(e,t){super(e,t),this._isTransitioning=!1,this._triggerArray=[];let i=j.find(Ao);for(let r of i){let o=j.getSelectorFromElement(r),s=j.find(o).filter(a=>a===this._element);o!==null&&s.length&&this._triggerArray.push(r)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return sf}static get DefaultType(){return af}static get NAME(){return qd}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let e=[];if(this._config.parent&&(e=this._getFirstLevelChildren(of).filter(a=>a!==this._element).map(a=>n.getOrCreateInstance(a,{toggle:!1}))),e.length&&e[0]._isTransitioning||x.trigger(this._element,Gd).defaultPrevented)return;for(let a of e)a.hide();let i=this._getDimension();this._element.classList.remove(Tn),this._element.classList.add(ji),this._element.style[i]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;let r=()=>{this._isTransitioning=!1,this._element.classList.remove(ji),this._element.classList.add(Tn,po),this._element.style[i]="",x.trigger(this._element,Kd)},s=`scroll${i[0].toUpperCase()+i.slice(1)}`;this._queueCallback(r,this._element,!0),this._element.style[i]=`${this._element[s]}px`}hide(){if(this._isTransitioning||!this._isShown()||x.trigger(this._element,Xd).defaultPrevented)return;let t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,ii(this._element),this._element.classList.add(ji),this._element.classList.remove(Tn,po);for(let r of this._triggerArray){let o=j.getElementFromSelector(r);o&&!this._isShown(o)&&this._addAriaAndCollapsedClass([r],!1)}this._isTransitioning=!0;let i=()=>{this._isTransitioning=!1,this._element.classList.remove(ji),this._element.classList.add(Tn),x.trigger(this._element,Qd)};this._element.style[t]="",this._queueCallback(i,this._element,!0)}_isShown(e=this._element){return e.classList.contains(po)}_configAfterMerge(e){return e.toggle=!!e.toggle,e.parent=xt(e.parent),e}_getDimension(){return this._element.classList.contains(tf)?nf:rf}_initializeChildren(){if(!this._config.parent)return;let e=this._getFirstLevelChildren(Ao);for(let t of e){let i=j.getElementFromSelector(t);i&&this._addAriaAndCollapsedClass([t],this._isShown(i))}}_getFirstLevelChildren(e){let t=j.find(ef,this._config.parent);return j.find(e,this._config.parent).filter(i=>!t.includes(i))}_addAriaAndCollapsedClass(e,t){if(e.length)for(let i of e)i.classList.toggle(Zd,!t),i.setAttribute("aria-expanded",t)}static jQueryInterface(e){let t={};return typeof e=="string"&&/show|hide/.test(e)&&(t.toggle=!1),this.each(function(){let i=n.getOrCreateInstance(this,t);if(typeof e=="string"){if(typeof i[e]=="undefined")throw new TypeError(`No method named "${e}"`);i[e]()}})}};x.on(document,Jd,Ao,function(n){(n.target.tagName==="A"||n.delegateTarget&&n.delegateTarget.tagName==="A")&&n.preventDefault();for(let e of j.getMultipleElementsFromSelector(this))Ct.getOrCreateInstance(e,{toggle:!1}).toggle()});Qe(Ct);var Bs="dropdown",lf="bs.dropdown",Jt=`.${lf}`,Lo=".data-api",cf="Escape",Vs="Tab",uf="ArrowUp",zs="ArrowDown",df=2,ff=`hide${Jt}`,hf=`hidden${Jt}`,pf=`show${Jt}`,mf=`shown${Jt}`,Aa=`click${Jt}${Lo}`,Sa=`keydown${Jt}${Lo}`,gf=`keyup${Jt}${Lo}`,xn="show",vf="dropup",yf="dropend",Ef="dropstart",bf="dropup-center",_f="dropdown-center",Gt='[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)',wf=`${Gt}.${xn}`,Ki=".dropdown-menu",xf=".navbar",Tf=".navbar-nav",Cf=".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",Af=Ke()?"top-end":"top-start",Sf=Ke()?"top-start":"top-end",Df=Ke()?"bottom-end":"bottom-start",Of=Ke()?"bottom-start":"bottom-end",Lf=Ke()?"left-start":"right-start",Mf=Ke()?"right-start":"left-start",kf="top",Nf="bottom",If={autoClose:!0,boundary:"clippingParents",display:"dynamic",offset:[0,2],popperConfig:null,reference:"toggle"},Rf={autoClose:"(boolean|string)",boundary:"(string|element)",display:"string",offset:"(array|string|function)",popperConfig:"(null|object|function)",reference:"(string|element|object)"},At=class n extends je{constructor(e,t){super(e,t),this._popper=null,this._parent=this._element.parentNode,this._menu=j.next(this._element,Ki)[0]||j.prev(this._element,Ki)[0]||j.findOne(Ki,this._parent),this._inNavbar=this._detectNavbar()}static get Default(){return If}static get DefaultType(){return Rf}static get NAME(){return Bs}toggle(){return this._isShown()?this.hide():this.show()}show(){if(Tt(this._element)||this._isShown())return;let e={relatedTarget:this._element};if(!x.trigger(this._element,pf,e).defaultPrevented){if(this._createPopper(),"ontouchstart"in document.documentElement&&!this._parent.closest(Tf))for(let i of[].concat(...document.body.children))x.on(i,"mouseover",Xi);this._element.focus(),this._element.setAttribute("aria-expanded",!0),this._menu.classList.add(xn),this._element.classList.add(xn),x.trigger(this._element,mf,e)}}hide(){if(Tt(this._element)||!this._isShown())return;let e={relatedTarget:this._element};this._completeHide(e)}dispose(){this._popper&&this._popper.destroy(),super.dispose()}update(){this._inNavbar=this._detectNavbar(),this._popper&&this._popper.update()}_completeHide(e){if(!x.trigger(this._element,ff,e).defaultPrevented){if("ontouchstart"in document.documentElement)for(let i of[].concat(...document.body.children))x.off(i,"mouseover",Xi);this._popper&&this._popper.destroy(),this._menu.classList.remove(xn),this._element.classList.remove(xn),this._element.setAttribute("aria-expanded","false"),ft.removeDataAttribute(this._menu,"popper"),x.trigger(this._element,hf,e)}}_getConfig(e){if(e=super._getConfig(e),typeof e.reference=="object"&&!dt(e.reference)&&typeof e.reference.getBoundingClientRect!="function")throw new TypeError(`${Bs.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`);return e}_createPopper(){if(typeof Vi=="undefined")throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org/docs/v2/)");let e=this._element;this._config.reference==="parent"?e=this._parent:dt(this._config.reference)?e=xt(this._config.reference):typeof this._config.reference=="object"&&(e=this._config.reference);let t=this._getPopperConfig();this._popper=Jn(e,this._menu,t)}_isShown(){return this._menu.classList.contains(xn)}_getPlacement(){let e=this._parent;if(e.classList.contains(yf))return Lf;if(e.classList.contains(Ef))return Mf;if(e.classList.contains(bf))return kf;if(e.classList.contains(_f))return Nf;let t=getComputedStyle(this._menu).getPropertyValue("--bs-position").trim()==="end";return e.classList.contains(vf)?t?Sf:Af:t?Of:Df}_detectNavbar(){return this._element.closest(xf)!==null}_getOffset(){let{offset:e}=this._config;return typeof e=="string"?e.split(",").map(t=>Number.parseInt(t,10)):typeof e=="function"?t=>e(t,this._element):e}_getPopperConfig(){let e={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||this._config.display==="static")&&(ft.setDataAttribute(this._menu,"popper","static"),e.modifiers=[{name:"applyStyles",enabled:!1}]),O(O({},e),He(this._config.popperConfig,[void 0,e]))}_selectMenuItem({key:e,target:t}){let i=j.find(Cf,this._menu).filter(r=>An(r));i.length&&Do(i,t,e===zs,!i.includes(t)).focus()}static jQueryInterface(e){return this.each(function(){let t=n.getOrCreateInstance(this,e);if(typeof e=="string"){if(typeof t[e]=="undefined")throw new TypeError(`No method named "${e}"`);t[e]()}})}static clearMenus(e){if(e.button===df||e.type==="keyup"&&e.key!==Vs)return;let t=j.find(wf);for(let i of t){let r=n.getInstance(i);if(!r||r._config.autoClose===!1)continue;let o=e.composedPath(),s=o.includes(r._menu);if(o.includes(r._element)||r._config.autoClose==="inside"&&!s||r._config.autoClose==="outside"&&s||r._menu.contains(e.target)&&(e.type==="keyup"&&e.key===Vs||/input|select|option|textarea|form/i.test(e.target.tagName)))continue;let a={relatedTarget:r._element};e.type==="click"&&(a.clickEvent=e),r._completeHide(a)}}static dataApiKeydownHandler(e){let t=/input|textarea/i.test(e.target.tagName),i=e.key===cf,r=[uf,zs].includes(e.key);if(!r&&!i||t&&!i)return;e.preventDefault();let o=this.matches(Gt)?this:j.prev(this,Gt)[0]||j.next(this,Gt)[0]||j.findOne(Gt,e.delegateTarget.parentNode),s=n.getOrCreateInstance(o);if(r){e.stopPropagation(),s.show(),s._selectMenuItem(e);return}s._isShown()&&(e.stopPropagation(),s.hide(),o.focus())}};x.on(document,Sa,Gt,At.dataApiKeydownHandler);x.on(document,Sa,Ki,At.dataApiKeydownHandler);x.on(document,Aa,At.clearMenus);x.on(document,gf,At.clearMenus);x.on(document,Aa,Gt,function(n){n.preventDefault(),At.getOrCreateInstance(this).toggle()});Qe(At);var Da="backdrop",Hf="fade",js="show",Ws=`mousedown.bs.${Da}`,Pf={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},Ff={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"},er=class extends Xt{constructor(e){super(),this._config=this._getConfig(e),this._isAppended=!1,this._element=null}static get Default(){return Pf}static get DefaultType(){return Ff}static get NAME(){return Da}show(e){if(!this._config.isVisible){He(e);return}this._append();let t=this._getElement();this._config.isAnimated&&ii(t),t.classList.add(js),this._emulateAnimation(()=>{He(e)})}hide(e){if(!this._config.isVisible){He(e);return}this._getElement().classList.remove(js),this._emulateAnimation(()=>{this.dispose(),He(e)})}dispose(){this._isAppended&&(x.off(this._element,Ws),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){let e=document.createElement("div");e.className=this._config.className,this._config.isAnimated&&e.classList.add(Hf),this._element=e}return this._element}_configAfterMerge(e){return e.rootElement=xt(e.rootElement),e}_append(){if(this._isAppended)return;let e=this._getElement();this._config.rootElement.append(e),x.on(e,Ws,()=>{He(this._config.clickCallback)}),this._isAppended=!0}_emulateAnimation(e){pa(e,this._getElement(),this._config.isAnimated)}},$f="focustrap",Bf="bs.focustrap",tr=`.${Bf}`,Vf=`focusin${tr}`,zf=`keydown.tab${tr}`,jf="Tab",Wf="forward",qs="backward",qf={autofocus:!0,trapElement:null},Uf={autofocus:"boolean",trapElement:"element"},nr=class extends Xt{constructor(e){super(),this._config=this._getConfig(e),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return qf}static get DefaultType(){return Uf}static get NAME(){return $f}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),x.off(document,tr),x.on(document,Vf,e=>this._handleFocusin(e)),x.on(document,zf,e=>this._handleKeydown(e)),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,x.off(document,tr))}_handleFocusin(e){let{trapElement:t}=this._config;if(e.target===document||e.target===t||t.contains(e.target))return;let i=j.focusableChildren(t);i.length===0?t.focus():this._lastTabNavDirection===qs?i[i.length-1].focus():i[0].focus()}_handleKeydown(e){e.key===jf&&(this._lastTabNavDirection=e.shiftKey?qs:Wf)}},Us=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",Ys=".sticky-top",Wi="padding-right",Gs="margin-right",ni=class{constructor(){this._element=document.body}getWidth(){let e=document.documentElement.clientWidth;return Math.abs(window.innerWidth-e)}hide(){let e=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,Wi,t=>t+e),this._setElementAttributes(Us,Wi,t=>t+e),this._setElementAttributes(Ys,Gs,t=>t-e)}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,Wi),this._resetElementAttributes(Us,Wi),this._resetElementAttributes(Ys,Gs)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(e,t,i){let r=this.getWidth(),o=s=>{if(s!==this._element&&window.innerWidth>s.clientWidth+r)return;this._saveInitialAttribute(s,t);let a=window.getComputedStyle(s).getPropertyValue(t);s.style.setProperty(t,`${i(Number.parseFloat(a))}px`)};this._applyManipulationCallback(e,o)}_saveInitialAttribute(e,t){let i=e.style.getPropertyValue(t);i&&ft.setDataAttribute(e,t,i)}_resetElementAttributes(e,t){let i=r=>{let o=ft.getDataAttribute(r,t);if(o===null){r.style.removeProperty(t);return}ft.removeDataAttribute(r,t),r.style.setProperty(t,o)};this._applyManipulationCallback(e,i)}_applyManipulationCallback(e,t){if(dt(e)){t(e);return}for(let i of j.find(e,this._element))t(i)}},Yf="modal",Gf="bs.modal",Xe=`.${Gf}`,Kf=".data-api",Xf="Escape",Qf=`hide${Xe}`,Jf=`hidePrevented${Xe}`,Oa=`hidden${Xe}`,La=`show${Xe}`,Zf=`shown${Xe}`,eh=`resize${Xe}`,th=`click.dismiss${Xe}`,nh=`mousedown.dismiss${Xe}`,ih=`keydown.dismiss${Xe}`,rh=`click${Xe}${Kf}`,Ks="modal-open",oh="fade",Xs="show",mo="modal-static",sh=".modal.show",ah=".modal-dialog",lh=".modal-body",ch='[data-bs-toggle="modal"]',uh={backdrop:!0,focus:!0,keyboard:!0},dh={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"},tt=class n extends je{constructor(e,t){super(e,t),this._dialog=j.findOne(ah,this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new ni,this._addEventListeners()}static get Default(){return uh}static get DefaultType(){return dh}static get NAME(){return Yf}toggle(e){return this._isShown?this.hide():this.show(e)}show(e){this._isShown||this._isTransitioning||x.trigger(this._element,La,{relatedTarget:e}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(Ks),this._adjustDialog(),this._backdrop.show(()=>this._showElement(e)))}hide(){!this._isShown||this._isTransitioning||x.trigger(this._element,Qf).defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(Xs),this._queueCallback(()=>this._hideModal(),this._element,this._isAnimated()))}dispose(){x.off(window,Xe),x.off(this._dialog,Xe),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new er({isVisible:!!this._config.backdrop,isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new nr({trapElement:this._element})}_showElement(e){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;let t=j.findOne(lh,this._dialog);t&&(t.scrollTop=0),ii(this._element),this._element.classList.add(Xs);let i=()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,x.trigger(this._element,Zf,{relatedTarget:e})};this._queueCallback(i,this._dialog,this._isAnimated())}_addEventListeners(){x.on(this._element,ih,e=>{if(e.key===Xf){if(this._config.keyboard){this.hide();return}this._triggerBackdropTransition()}}),x.on(window,eh,()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()}),x.on(this._element,nh,e=>{x.one(this._element,th,t=>{if(!(this._element!==e.target||this._element!==t.target)){if(this._config.backdrop==="static"){this._triggerBackdropTransition();return}this._config.backdrop&&this.hide()}})})}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide(()=>{document.body.classList.remove(Ks),this._resetAdjustments(),this._scrollBar.reset(),x.trigger(this._element,Oa)})}_isAnimated(){return this._element.classList.contains(oh)}_triggerBackdropTransition(){if(x.trigger(this._element,Jf).defaultPrevented)return;let t=this._element.scrollHeight>document.documentElement.clientHeight,i=this._element.style.overflowY;i==="hidden"||this._element.classList.contains(mo)||(t||(this._element.style.overflowY="hidden"),this._element.classList.add(mo),this._queueCallback(()=>{this._element.classList.remove(mo),this._queueCallback(()=>{this._element.style.overflowY=i},this._dialog)},this._dialog),this._element.focus())}_adjustDialog(){let e=this._element.scrollHeight>document.documentElement.clientHeight,t=this._scrollBar.getWidth(),i=t>0;if(i&&!e){let r=Ke()?"paddingLeft":"paddingRight";this._element.style[r]=`${t}px`}if(!i&&e){let r=Ke()?"paddingRight":"paddingLeft";this._element.style[r]=`${t}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(e,t){return this.each(function(){let i=n.getOrCreateInstance(this,e);if(typeof e=="string"){if(typeof i[e]=="undefined")throw new TypeError(`No method named "${e}"`);i[e](t)}})}};x.on(document,rh,ch,function(n){let e=j.getElementFromSelector(this);["A","AREA"].includes(this.tagName)&&n.preventDefault(),x.one(e,La,r=>{r.defaultPrevented||x.one(e,Oa,()=>{An(this)&&this.focus()})});let t=j.findOne(sh);t&&tt.getInstance(t).hide(),tt.getOrCreateInstance(e).toggle(this)});rr(tt);Qe(tt);var fh="offcanvas",hh="bs.offcanvas",mt=`.${hh}`,Ma=".data-api",ph=`load${mt}${Ma}`,mh="Escape",Qs="show",Js="showing",Zs="hiding",gh="offcanvas-backdrop",ka=".offcanvas.show",vh=`show${mt}`,yh=`shown${mt}`,Eh=`hide${mt}`,ea=`hidePrevented${mt}`,Na=`hidden${mt}`,bh=`resize${mt}`,_h=`click${mt}${Ma}`,wh=`keydown.dismiss${mt}`,xh='[data-bs-toggle="offcanvas"]',Th={backdrop:!0,keyboard:!0,scroll:!1},Ch={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"},St=class n extends je{constructor(e,t){super(e,t),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return Th}static get DefaultType(){return Ch}static get NAME(){return fh}toggle(e){return this._isShown?this.hide():this.show(e)}show(e){if(this._isShown||x.trigger(this._element,vh,{relatedTarget:e}).defaultPrevented)return;this._isShown=!0,this._backdrop.show(),this._config.scroll||new ni().hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(Js);let i=()=>{(!this._config.scroll||this._config.backdrop)&&this._focustrap.activate(),this._element.classList.add(Qs),this._element.classList.remove(Js),x.trigger(this._element,yh,{relatedTarget:e})};this._queueCallback(i,this._element,!0)}hide(){if(!this._isShown||x.trigger(this._element,Eh).defaultPrevented)return;this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add(Zs),this._backdrop.hide();let t=()=>{this._element.classList.remove(Qs,Zs),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||new ni().reset(),x.trigger(this._element,Na)};this._queueCallback(t,this._element,!0)}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){let e=()=>{if(this._config.backdrop==="static"){x.trigger(this._element,ea);return}this.hide()},t=!!this._config.backdrop;return new er({className:gh,isVisible:t,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:t?e:null})}_initializeFocusTrap(){return new nr({trapElement:this._element})}_addEventListeners(){x.on(this._element,wh,e=>{if(e.key===mh){if(this._config.keyboard){this.hide();return}x.trigger(this._element,ea)}})}static jQueryInterface(e){return this.each(function(){let t=n.getOrCreateInstance(this,e);if(typeof e=="string"){if(t[e]===void 0||e.startsWith("_")||e==="constructor")throw new TypeError(`No method named "${e}"`);t[e](this)}})}};x.on(document,_h,xh,function(n){let e=j.getElementFromSelector(this);if(["A","AREA"].includes(this.tagName)&&n.preventDefault(),Tt(this))return;x.one(e,Na,()=>{An(this)&&this.focus()});let t=j.findOne(ka);t&&t!==e&&St.getInstance(t).hide(),St.getOrCreateInstance(e).toggle(this)});x.on(window,ph,()=>{for(let n of j.find(ka))St.getOrCreateInstance(n).show()});x.on(window,bh,()=>{for(let n of j.find("[aria-modal][class*=show][class*=offcanvas-]"))getComputedStyle(n).position!=="fixed"&&St.getOrCreateInstance(n).hide()});rr(St);Qe(St);var Ah=/^aria-[\w-]*$/i,Ia={"*":["class","dir","id","lang","role",Ah],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],dd:[],div:[],dl:[],dt:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Sh=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Dh=/^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i,Oh=(n,e)=>{let t=n.nodeName.toLowerCase();return e.includes(t)?Sh.has(t)?!!Dh.test(n.nodeValue):!0:e.filter(i=>i instanceof RegExp).some(i=>i.test(t))};function Lh(n,e,t){if(!n.length)return n;if(t&&typeof t=="function")return t(n);let r=new window.DOMParser().parseFromString(n,"text/html"),o=[].concat(...r.body.querySelectorAll("*"));for(let s of o){let a=s.nodeName.toLowerCase();if(!Object.keys(e).includes(a)){s.remove();continue}let l=[].concat(...s.attributes),c=[].concat(e["*"]||[],e[a]||[]);for(let u of l)Oh(u,c)||s.removeAttribute(u.nodeName)}return r.body.innerHTML}var Mh="TemplateFactory",kh={allowList:Ia,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"
"},Nh={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},Ih={entry:"(string|element|function|null)",selector:"(string|element)"},So=class extends Xt{constructor(e){super(),this._config=this._getConfig(e)}static get Default(){return kh}static get DefaultType(){return Nh}static get NAME(){return Mh}getContent(){return Object.values(this._config.content).map(e=>this._resolvePossibleFunction(e)).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(e){return this._checkContent(e),this._config.content=O(O({},this._config.content),e),this}toHtml(){let e=document.createElement("div");e.innerHTML=this._maybeSanitize(this._config.template);for(let[r,o]of Object.entries(this._config.content))this._setContent(e,o,r);let t=e.children[0],i=this._resolvePossibleFunction(this._config.extraClass);return i&&t.classList.add(...i.split(" ")),t}_typeCheckConfig(e){super._typeCheckConfig(e),this._checkContent(e.content)}_checkContent(e){for(let[t,i]of Object.entries(e))super._typeCheckConfig({selector:t,entry:i},Ih)}_setContent(e,t,i){let r=j.findOne(i,e);if(r){if(t=this._resolvePossibleFunction(t),!t){r.remove();return}if(dt(t)){this._putElementInTemplate(xt(t),r);return}if(this._config.html){r.innerHTML=this._maybeSanitize(t);return}r.textContent=t}}_maybeSanitize(e){return this._config.sanitize?Lh(e,this._config.allowList,this._config.sanitizeFn):e}_resolvePossibleFunction(e){return He(e,[void 0,this])}_putElementInTemplate(e,t){if(this._config.html){t.innerHTML="",t.append(e);return}t.textContent=e.textContent}},Rh="tooltip",Hh=new Set(["sanitize","allowList","sanitizeFn"]),go="fade",Ph="modal",qi="show",Fh=".tooltip-inner",ta=`.${Ph}`,na="hide.bs.modal",ei="hover",vo="focus",yo="click",$h="manual",Bh="hide",Vh="hidden",zh="show",jh="shown",Wh="inserted",qh="click",Uh="focusin",Yh="focusout",Gh="mouseenter",Kh="mouseleave",Xh={AUTO:"auto",TOP:"top",RIGHT:Ke()?"left":"right",BOTTOM:"bottom",LEFT:Ke()?"right":"left"},Qh={allowList:Ia,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,6],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},Jh={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"},ht=class n extends je{constructor(e,t){if(typeof Vi=="undefined")throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org/docs/v2/)");super(e,t),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return Qh}static get DefaultType(){return Jh}static get NAME(){return Rh}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){if(this._isEnabled){if(this._isShown()){this._leave();return}this._enter()}}dispose(){clearTimeout(this._timeout),x.off(this._element.closest(ta),na,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if(this._element.style.display==="none")throw new Error("Please use show on visible elements");if(!(this._isWithContent()&&this._isEnabled))return;let e=x.trigger(this._element,this.constructor.eventName(zh)),i=(fa(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(e.defaultPrevented||!i)return;this._disposePopper();let r=this._getTipElement();this._element.setAttribute("aria-describedby",r.getAttribute("id"));let{container:o}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(o.append(r),x.trigger(this._element,this.constructor.eventName(Wh))),this._popper=this._createPopper(r),r.classList.add(qi),"ontouchstart"in document.documentElement)for(let a of[].concat(...document.body.children))x.on(a,"mouseover",Xi);let s=()=>{x.trigger(this._element,this.constructor.eventName(jh)),this._isHovered===!1&&this._leave(),this._isHovered=!1};this._queueCallback(s,this.tip,this._isAnimated())}hide(){if(!this._isShown()||x.trigger(this._element,this.constructor.eventName(Bh)).defaultPrevented)return;if(this._getTipElement().classList.remove(qi),"ontouchstart"in document.documentElement)for(let r of[].concat(...document.body.children))x.off(r,"mouseover",Xi);this._activeTrigger[yo]=!1,this._activeTrigger[vo]=!1,this._activeTrigger[ei]=!1,this._isHovered=null;let i=()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),x.trigger(this._element,this.constructor.eventName(Vh)))};this._queueCallback(i,this.tip,this._isAnimated())}update(){this._popper&&this._popper.update()}_isWithContent(){return!!this._getTitle()}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(e){let t=this._getTemplateFactory(e).toHtml();if(!t)return null;t.classList.remove(go,qi),t.classList.add(`bs-${this.constructor.NAME}-auto`);let i=$u(this.constructor.NAME).toString();return t.setAttribute("id",i),this._isAnimated()&&t.classList.add(go),t}setContent(e){this._newContent=e,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(e){return this._templateFactory?this._templateFactory.changeContent(e):this._templateFactory=new So(ae(O({},this._config),{content:e,extraClass:this._resolvePossibleFunction(this._config.customClass)})),this._templateFactory}_getContentForTemplate(){return{[Fh]:this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(e){return this.constructor.getOrCreateInstance(e.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(go)}_isShown(){return this.tip&&this.tip.classList.contains(qi)}_createPopper(e){let t=He(this._config.placement,[this,e,this._element]),i=Xh[t.toUpperCase()];return Jn(this._element,e,this._getPopperConfig(i))}_getOffset(){let{offset:e}=this._config;return typeof e=="string"?e.split(",").map(t=>Number.parseInt(t,10)):typeof e=="function"?t=>e(t,this._element):e}_resolvePossibleFunction(e){return He(e,[this._element,this._element])}_getPopperConfig(e){let t={placement:e,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:i=>{this._getTipElement().setAttribute("data-popper-placement",i.state.placement)}}]};return O(O({},t),He(this._config.popperConfig,[void 0,t]))}_setListeners(){let e=this._config.trigger.split(" ");for(let t of e)if(t==="click")x.on(this._element,this.constructor.eventName(qh),this._config.selector,i=>{let r=this._initializeOnDelegatedTarget(i);r._activeTrigger[yo]=!(r._isShown()&&r._activeTrigger[yo]),r.toggle()});else if(t!==$h){let i=t===ei?this.constructor.eventName(Gh):this.constructor.eventName(Uh),r=t===ei?this.constructor.eventName(Kh):this.constructor.eventName(Yh);x.on(this._element,i,this._config.selector,o=>{let s=this._initializeOnDelegatedTarget(o);s._activeTrigger[o.type==="focusin"?vo:ei]=!0,s._enter()}),x.on(this._element,r,this._config.selector,o=>{let s=this._initializeOnDelegatedTarget(o);s._activeTrigger[o.type==="focusout"?vo:ei]=s._element.contains(o.relatedTarget),s._leave()})}this._hideModalHandler=()=>{this._element&&this.hide()},x.on(this._element.closest(ta),na,this._hideModalHandler)}_fixTitle(){let e=this._element.getAttribute("title");e&&(!this._element.getAttribute("aria-label")&&!this._element.textContent.trim()&&this._element.setAttribute("aria-label",e),this._element.setAttribute("data-bs-original-title",e),this._element.removeAttribute("title"))}_enter(){if(this._isShown()||this._isHovered){this._isHovered=!0;return}this._isHovered=!0,this._setTimeout(()=>{this._isHovered&&this.show()},this._config.delay.show)}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout(()=>{this._isHovered||this.hide()},this._config.delay.hide))}_setTimeout(e,t){clearTimeout(this._timeout),this._timeout=setTimeout(e,t)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(e){let t=ft.getDataAttributes(this._element);for(let i of Object.keys(t))Hh.has(i)&&delete t[i];return e=O(O({},t),typeof e=="object"&&e?e:{}),e=this._mergeConfigObj(e),e=this._configAfterMerge(e),this._typeCheckConfig(e),e}_configAfterMerge(e){return e.container=e.container===!1?document.body:xt(e.container),typeof e.delay=="number"&&(e.delay={show:e.delay,hide:e.delay}),typeof e.title=="number"&&(e.title=e.title.toString()),typeof e.content=="number"&&(e.content=e.content.toString()),e}_getDelegateConfig(){let e={};for(let[t,i]of Object.entries(this._config))this.constructor.Default[t]!==i&&(e[t]=i);return e.selector=!1,e.trigger="manual",e}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(e){return this.each(function(){let t=n.getOrCreateInstance(this,e);if(typeof e=="string"){if(typeof t[e]=="undefined")throw new TypeError(`No method named "${e}"`);t[e]()}})}};Qe(ht);var Zh="popover",ep=".popover-header",tp=".popover-body",np=ae(O({},ht.Default),{content:"",offset:[0,8],placement:"right",template:'',trigger:"click"}),ip=ae(O({},ht.DefaultType),{content:"(null|string|element|function)"}),Cn=class n extends ht{static get Default(){return np}static get DefaultType(){return ip}static get NAME(){return Zh}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{[ep]:this._getTitle(),[tp]:this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(e){return this.each(function(){let t=n.getOrCreateInstance(this,e);if(typeof e=="string"){if(typeof t[e]=="undefined")throw new TypeError(`No method named "${e}"`);t[e]()}})}};Qe(Cn);var rp="scrollspy",op="bs.scrollspy",Mo=`.${op}`,sp=".data-api",ap=`activate${Mo}`,ia=`click${Mo}`,lp=`load${Mo}${sp}`,cp="dropdown-item",_n="active",up='[data-bs-spy="scroll"]',Eo="[href]",dp=".nav, .list-group",ra=".nav-link",fp=".nav-item",hp=".list-group-item",pp=`${ra}, ${fp} > ${ra}, ${hp}`,mp=".dropdown",gp=".dropdown-toggle",vp={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},yp={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"},ir=class n extends je{constructor(e,t){super(e,t),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement=getComputedStyle(this._element).overflowY==="visible"?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return vp}static get DefaultType(){return yp}static get NAME(){return rp}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(let e of this._observableSections.values())this._observer.observe(e)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(e){return e.target=xt(e.target)||document.body,e.rootMargin=e.offset?`${e.offset}px 0px -30%`:e.rootMargin,typeof e.threshold=="string"&&(e.threshold=e.threshold.split(",").map(t=>Number.parseFloat(t))),e}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(x.off(this._config.target,ia),x.on(this._config.target,ia,Eo,e=>{let t=this._observableSections.get(e.target.hash);if(t){e.preventDefault();let i=this._rootElement||window,r=t.offsetTop-this._element.offsetTop;if(i.scrollTo){i.scrollTo({top:r,behavior:"smooth"});return}i.scrollTop=r}}))}_getNewObserver(){let e={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver(t=>this._observerCallback(t),e)}_observerCallback(e){let t=s=>this._targetLinks.get(`#${s.target.id}`),i=s=>{this._previousScrollData.visibleEntryTop=s.target.offsetTop,this._process(t(s))},r=(this._rootElement||document.documentElement).scrollTop,o=r>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=r;for(let s of e){if(!s.isIntersecting){this._activeTarget=null,this._clearActiveClass(t(s));continue}let a=s.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(o&&a){if(i(s),!r)return;continue}!o&&!a&&i(s)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;let e=j.find(Eo,this._config.target);for(let t of e){if(!t.hash||Tt(t))continue;let i=j.findOne(decodeURI(t.hash),this._element);An(i)&&(this._targetLinks.set(decodeURI(t.hash),t),this._observableSections.set(t.hash,i))}}_process(e){this._activeTarget!==e&&(this._clearActiveClass(this._config.target),this._activeTarget=e,e.classList.add(_n),this._activateParents(e),x.trigger(this._element,ap,{relatedTarget:e}))}_activateParents(e){if(e.classList.contains(cp)){j.findOne(gp,e.closest(mp)).classList.add(_n);return}for(let t of j.parents(e,dp))for(let i of j.prev(t,pp))i.classList.add(_n)}_clearActiveClass(e){e.classList.remove(_n);let t=j.find(`${Eo}.${_n}`,e);for(let i of t)i.classList.remove(_n)}static jQueryInterface(e){return this.each(function(){let t=n.getOrCreateInstance(this,e);if(typeof e=="string"){if(t[e]===void 0||e.startsWith("_")||e==="constructor")throw new TypeError(`No method named "${e}"`);t[e]()}})}};x.on(window,lp,()=>{for(let n of j.find(up))ir.getOrCreateInstance(n)});Qe(ir);var Ep="tab",bp="bs.tab",Zt=`.${bp}`,_p=`hide${Zt}`,wp=`hidden${Zt}`,xp=`show${Zt}`,Tp=`shown${Zt}`,Cp=`click${Zt}`,Ap=`keydown${Zt}`,Sp=`load${Zt}`,Dp="ArrowLeft",oa="ArrowRight",Op="ArrowUp",sa="ArrowDown",bo="Home",aa="End",Kt="active",la="fade",_o="show",Lp="dropdown",Ra=".dropdown-toggle",Mp=".dropdown-menu",wo=`:not(${Ra})`,kp='.list-group, .nav, [role="tablist"]',Np=".nav-item, .list-group-item",Ip=`.nav-link${wo}, .list-group-item${wo}, [role="tab"]${wo}`,Ha='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',xo=`${Ip}, ${Ha}`,Rp=`.${Kt}[data-bs-toggle="tab"], .${Kt}[data-bs-toggle="pill"], .${Kt}[data-bs-toggle="list"]`,Qt=class n extends je{constructor(e){super(e),this._parent=this._element.closest(kp),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),x.on(this._element,Ap,t=>this._keydown(t)))}static get NAME(){return Ep}show(){let e=this._element;if(this._elemIsActive(e))return;let t=this._getActiveElem(),i=t?x.trigger(t,_p,{relatedTarget:e}):null;x.trigger(e,xp,{relatedTarget:t}).defaultPrevented||i&&i.defaultPrevented||(this._deactivate(t,e),this._activate(e,t))}_activate(e,t){if(!e)return;e.classList.add(Kt),this._activate(j.getElementFromSelector(e));let i=()=>{if(e.getAttribute("role")!=="tab"){e.classList.add(_o);return}e.removeAttribute("tabindex"),e.setAttribute("aria-selected",!0),this._toggleDropDown(e,!0),x.trigger(e,Tp,{relatedTarget:t})};this._queueCallback(i,e,e.classList.contains(la))}_deactivate(e,t){if(!e)return;e.classList.remove(Kt),e.blur(),this._deactivate(j.getElementFromSelector(e));let i=()=>{if(e.getAttribute("role")!=="tab"){e.classList.remove(_o);return}e.setAttribute("aria-selected",!1),e.setAttribute("tabindex","-1"),this._toggleDropDown(e,!1),x.trigger(e,wp,{relatedTarget:t})};this._queueCallback(i,e,e.classList.contains(la))}_keydown(e){if(![Dp,oa,Op,sa,bo,aa].includes(e.key))return;e.stopPropagation(),e.preventDefault();let t=this._getChildren().filter(r=>!Tt(r)),i;if([bo,aa].includes(e.key))i=t[e.key===bo?0:t.length-1];else{let r=[oa,sa].includes(e.key);i=Do(t,e.target,r,!0)}i&&(i.focus({preventScroll:!0}),n.getOrCreateInstance(i).show())}_getChildren(){return j.find(xo,this._parent)}_getActiveElem(){return this._getChildren().find(e=>this._elemIsActive(e))||null}_setInitialAttributes(e,t){this._setAttributeIfNotExists(e,"role","tablist");for(let i of t)this._setInitialAttributesOnChild(i)}_setInitialAttributesOnChild(e){e=this._getInnerElement(e);let t=this._elemIsActive(e),i=this._getOuterElement(e);e.setAttribute("aria-selected",t),i!==e&&this._setAttributeIfNotExists(i,"role","presentation"),t||e.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(e,"role","tab"),this._setInitialAttributesOnTargetPanel(e)}_setInitialAttributesOnTargetPanel(e){let t=j.getElementFromSelector(e);t&&(this._setAttributeIfNotExists(t,"role","tabpanel"),e.id&&this._setAttributeIfNotExists(t,"aria-labelledby",`${e.id}`))}_toggleDropDown(e,t){let i=this._getOuterElement(e);if(!i.classList.contains(Lp))return;let r=(o,s)=>{let a=j.findOne(o,i);a&&a.classList.toggle(s,t)};r(Ra,Kt),r(Mp,_o),i.setAttribute("aria-expanded",t)}_setAttributeIfNotExists(e,t,i){e.hasAttribute(t)||e.setAttribute(t,i)}_elemIsActive(e){return e.classList.contains(Kt)}_getInnerElement(e){return e.matches(xo)?e:j.findOne(xo,e)}_getOuterElement(e){return e.closest(Np)||e}static jQueryInterface(e){return this.each(function(){let t=n.getOrCreateInstance(this);if(typeof e=="string"){if(t[e]===void 0||e.startsWith("_")||e==="constructor")throw new TypeError(`No method named "${e}"`);t[e]()}})}};x.on(document,Cp,Ha,function(n){["A","AREA"].includes(this.tagName)&&n.preventDefault(),!Tt(this)&&Qt.getOrCreateInstance(this).show()});x.on(window,Sp,()=>{for(let n of j.find(Rp))Qt.getOrCreateInstance(n)});Qe(Qt);var Hp="toast",Pp="bs.toast",Ot=`.${Pp}`,Fp=`mouseover${Ot}`,$p=`mouseout${Ot}`,Bp=`focusin${Ot}`,Vp=`focusout${Ot}`,zp=`hide${Ot}`,jp=`hidden${Ot}`,Wp=`show${Ot}`,qp=`shown${Ot}`,Up="fade",ca="hide",Ui="show",Yi="showing",Yp={animation:"boolean",autohide:"boolean",delay:"number"},Gp={animation:!0,autohide:!0,delay:5e3},pt=class n extends je{constructor(e,t){super(e,t),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return Gp}static get DefaultType(){return Yp}static get NAME(){return Hp}show(){if(x.trigger(this._element,Wp).defaultPrevented)return;this._clearTimeout(),this._config.animation&&this._element.classList.add(Up);let t=()=>{this._element.classList.remove(Yi),x.trigger(this._element,qp),this._maybeScheduleHide()};this._element.classList.remove(ca),ii(this._element),this._element.classList.add(Ui,Yi),this._queueCallback(t,this._element,this._config.animation)}hide(){if(!this.isShown()||x.trigger(this._element,zp).defaultPrevented)return;let t=()=>{this._element.classList.add(ca),this._element.classList.remove(Yi,Ui),x.trigger(this._element,jp)};this._element.classList.add(Yi),this._queueCallback(t,this._element,this._config.animation)}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(Ui),super.dispose()}isShown(){return this._element.classList.contains(Ui)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout(()=>{this.hide()},this._config.delay)))}_onInteraction(e,t){switch(e.type){case"mouseover":case"mouseout":{this._hasMouseInteraction=t;break}case"focusin":case"focusout":{this._hasKeyboardInteraction=t;break}}if(t){this._clearTimeout();return}let i=e.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){x.on(this._element,Fp,e=>this._onInteraction(e,!0)),x.on(this._element,$p,e=>this._onInteraction(e,!1)),x.on(this._element,Bp,e=>this._onInteraction(e,!0)),x.on(this._element,Vp,e=>this._onInteraction(e,!1))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(e){return this.each(function(){let t=n.getOrCreateInstance(this,e);if(typeof e=="string"){if(typeof t[e]=="undefined")throw new TypeError(`No method named "${e}"`);t[e](this)}})}};rr(pt);Qe(pt);var Kp=function(){"use strict";let htmx={onLoad:null,process:null,on:null,off:null,trigger:null,ajax:null,find:null,findAll:null,closest:null,values:function(n,e){return getInputValues(n,e||"post").values},remove:null,addClass:null,removeClass:null,toggleClass:null,takeClass:null,swap:null,defineExtension:null,removeExtension:null,logAll:null,logNone:null,logger:null,config:{historyEnabled:!0,historyCacheSize:10,refreshOnHistoryMiss:!1,defaultSwapStyle:"innerHTML",defaultSwapDelay:0,defaultSettleDelay:20,includeIndicatorStyles:!0,indicatorClass:"htmx-indicator",requestClass:"htmx-request",addedClass:"htmx-added",settlingClass:"htmx-settling",swappingClass:"htmx-swapping",allowEval:!0,allowScriptTags:!0,inlineScriptNonce:"",inlineStyleNonce:"",attributesToSettle:["class","style","width","height"],withCredentials:!1,timeout:0,wsReconnectDelay:"full-jitter",wsBinaryType:"blob",disableSelector:"[hx-disable], [data-hx-disable]",scrollBehavior:"instant",defaultFocusScroll:!1,getCacheBusterParam:!1,globalViewTransitions:!1,methodsThatUseUrlParams:["get","delete"],selfRequestsOnly:!0,ignoreTitle:!1,scrollIntoViewOnBoost:!0,triggerSpecsCache:null,disableInheritance:!1,responseHandling:[{code:"204",swap:!1},{code:"[23]..",swap:!0},{code:"[45]..",swap:!1,error:!0}],allowNestedOobSwaps:!0,historyRestoreAsHxRequest:!0,reportValidityOfForms:!1},parseInterval:null,location,_:null,version:"2.0.7"};htmx.onLoad=onLoadHelper,htmx.process=processNode,htmx.on=addEventListenerImpl,htmx.off=removeEventListenerImpl,htmx.trigger=triggerEvent,htmx.ajax=ajaxHelper,htmx.find=find,htmx.findAll=findAll,htmx.closest=closest,htmx.remove=removeElement,htmx.addClass=addClassToElement,htmx.removeClass=removeClassFromElement,htmx.toggleClass=toggleClassOnElement,htmx.takeClass=takeClassForElement,htmx.swap=swap,htmx.defineExtension=defineExtension,htmx.removeExtension=removeExtension,htmx.logAll=logAll,htmx.logNone=logNone,htmx.parseInterval=parseInterval,htmx._=internalEval;let internalAPI={addTriggerHandler,bodyContains,canAccessLocalStorage,findThisElement,filterValues,swap,hasAttribute,getAttributeValue,getClosestAttributeValue,getClosestMatch,getExpressionVars,getHeaders,getInputValues,getInternalData,getSwapSpecification,getTriggerSpecs,getTarget,makeFragment,mergeObjects,makeSettleInfo,oobSwap,querySelectorExt,settleImmediately,shouldCancel,triggerEvent,triggerErrorEvent,withExtensions},VERBS=["get","post","put","delete","patch"],VERB_SELECTOR=VERBS.map(function(n){return"[hx-"+n+"], [data-hx-"+n+"]"}).join(", ");function parseInterval(n){if(n==null)return;let e=NaN;return n.slice(-2)=="ms"?e=parseFloat(n.slice(0,-2)):n.slice(-1)=="s"?e=parseFloat(n.slice(0,-1))*1e3:n.slice(-1)=="m"?e=parseFloat(n.slice(0,-1))*1e3*60:e=parseFloat(n),isNaN(e)?void 0:e}function getRawAttribute(n,e){return n instanceof Element&&n.getAttribute(e)}function hasAttribute(n,e){return!!n.hasAttribute&&(n.hasAttribute(e)||n.hasAttribute("data-"+e))}function getAttributeValue(n,e){return getRawAttribute(n,e)||getRawAttribute(n,"data-"+e)}function parentElt(n){let e=n.parentElement;return!e&&n.parentNode instanceof ShadowRoot?n.parentNode:e}function getDocument(){return document}function getRootNode(n,e){return n.getRootNode?n.getRootNode({composed:e}):getDocument()}function getClosestMatch(n,e){for(;n&&!e(n);)n=parentElt(n);return n||null}function getAttributeValueWithDisinheritance(n,e,t){let i=getAttributeValue(e,t),r=getAttributeValue(e,"hx-disinherit");var o=getAttributeValue(e,"hx-inherit");if(n!==e){if(htmx.config.disableInheritance)return o&&(o==="*"||o.split(" ").indexOf(t)>=0)?i:null;if(r&&(r==="*"||r.split(" ").indexOf(t)>=0))return"unset"}return i}function getClosestAttributeValue(n,e){let t=null;if(getClosestMatch(n,function(i){return!!(t=getAttributeValueWithDisinheritance(n,asElement(i),e))}),t!=="unset")return t}function matches(n,e){return n instanceof Element&&n.matches(e)}function getStartTag(n){let t=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i.exec(n);return t?t[1].toLowerCase():""}function parseHTML(n){return new DOMParser().parseFromString(n,"text/html")}function takeChildrenFor(n,e){for(;e.childNodes.length>0;)n.append(e.childNodes[0])}function duplicateScript(n){let e=getDocument().createElement("script");return forEach(n.attributes,function(t){e.setAttribute(t.name,t.value)}),e.textContent=n.textContent,e.async=!1,htmx.config.inlineScriptNonce&&(e.nonce=htmx.config.inlineScriptNonce),e}function isJavaScriptScriptNode(n){return n.matches("script")&&(n.type==="text/javascript"||n.type==="module"||n.type==="")}function normalizeScriptTags(n){Array.from(n.querySelectorAll("script")).forEach(e=>{if(isJavaScriptScriptNode(e)){let t=duplicateScript(e),i=e.parentNode;try{i.insertBefore(t,e)}catch(r){logError(r)}finally{e.remove()}}})}function makeFragment(n){let e=n.replace(/]*)?>[\s\S]*?<\/head>/i,""),t=getStartTag(e),i;if(t==="html"){i=new DocumentFragment;let o=parseHTML(n);takeChildrenFor(i,o.body),i.title=o.title}else if(t==="body"){i=new DocumentFragment;let o=parseHTML(e);takeChildrenFor(i,o.body),i.title=o.title}else{let o=parseHTML('");i=o.querySelector("template").content,i.title=o.title;var r=i.querySelector("title");r&&r.parentNode===i&&(r.remove(),i.title=r.innerText)}return i&&(htmx.config.allowScriptTags?normalizeScriptTags(i):i.querySelectorAll("script").forEach(o=>o.remove())),i}function maybeCall(n){n&&n()}function isType(n,e){return Object.prototype.toString.call(n)==="[object "+e+"]"}function isFunction(n){return typeof n=="function"}function isRawObject(n){return isType(n,"Object")}function getInternalData(n){let e="htmx-internal-data",t=n[e];return t||(t=n[e]={}),t}function toArray(n){let e=[];if(n)for(let t=0;t=0}function bodyContains(n){return n.getRootNode({composed:!0})===document}function splitOnWhitespace(n){return n.trim().split(/\s+/)}function mergeObjects(n,e){for(let t in e)e.hasOwnProperty(t)&&(n[t]=e[t]);return n}function parseJSON(n){try{return JSON.parse(n)}catch(e){return logError(e),null}}function canAccessLocalStorage(){let n="htmx:sessionStorageTest";try{return sessionStorage.setItem(n,n),sessionStorage.removeItem(n),!0}catch(e){return!1}}function normalizePath(n){let e=new URL(n,"http://x");return e&&(n=e.pathname+e.search),n!="/"&&(n=n.replace(/\/+$/,"")),n}function internalEval(str){return maybeEval(getDocument().body,function(){return eval(str)})}function onLoadHelper(n){return htmx.on("htmx:load",function(t){n(t.detail.elt)})}function logAll(){htmx.logger=function(n,e,t){console&&console.log(e,n,t)}}function logNone(){htmx.logger=null}function find(n,e){return typeof n!="string"?n.querySelector(e):find(getDocument(),n)}function findAll(n,e){return typeof n!="string"?n.querySelectorAll(e):findAll(getDocument(),n)}function getWindow(){return window}function removeElement(n,e){n=resolveTarget(n),e?getWindow().setTimeout(function(){removeElement(n),n=null},e):parentElt(n).removeChild(n)}function asElement(n){return n instanceof Element?n:null}function asHtmlElement(n){return n instanceof HTMLElement?n:null}function asString(n){return typeof n=="string"?n:null}function asParentNode(n){return n instanceof Element||n instanceof Document||n instanceof DocumentFragment?n:null}function addClassToElement(n,e,t){n=asElement(resolveTarget(n)),n&&(t?getWindow().setTimeout(function(){addClassToElement(n,e),n=null},t):n.classList&&n.classList.add(e))}function removeClassFromElement(n,e,t){let i=asElement(resolveTarget(n));i&&(t?getWindow().setTimeout(function(){removeClassFromElement(i,e),i=null},t):i.classList&&(i.classList.remove(e),i.classList.length===0&&i.removeAttribute("class")))}function toggleClassOnElement(n,e){n=resolveTarget(n),n.classList.toggle(e)}function takeClassForElement(n,e){n=resolveTarget(n),forEach(n.parentElement.children,function(t){removeClassFromElement(t,e)}),addClassToElement(asElement(n),e)}function closest(n,e){return n=asElement(resolveTarget(n)),n?n.closest(e):null}function startsWith(n,e){return n.substring(0,e.length)===e}function endsWith(n,e){return n.substring(n.length-e.length)===e}function normalizeSelector(n){let e=n.trim();return startsWith(e,"<")&&endsWith(e,"/>")?e.substring(1,e.length-2):e}function querySelectorAllExt(n,e,t){if(e.indexOf("global ")===0)return querySelectorAllExt(n,e.slice(7),!0);n=resolveTarget(n);let i=[];{let s=0,a=0;for(let l=0;l"&&s--}a0;){let s=normalizeSelector(i.shift()),a;s.indexOf("closest ")===0?a=closest(asElement(n),normalizeSelector(s.slice(8))):s.indexOf("find ")===0?a=find(asParentNode(n),normalizeSelector(s.slice(5))):s==="next"||s==="nextElementSibling"?a=asElement(n).nextElementSibling:s.indexOf("next ")===0?a=scanForwardQuery(n,normalizeSelector(s.slice(5)),!!t):s==="previous"||s==="previousElementSibling"?a=asElement(n).previousElementSibling:s.indexOf("previous ")===0?a=scanBackwardsQuery(n,normalizeSelector(s.slice(9)),!!t):s==="document"?a=document:s==="window"?a=window:s==="body"?a=document.body:s==="root"?a=getRootNode(n,!!t):s==="host"?a=n.getRootNode().host:o.push(s),a&&r.push(a)}if(o.length>0){let s=o.join(","),a=asParentNode(getRootNode(n,!!t));r.push(...toArray(a.querySelectorAll(s)))}return r}var scanForwardQuery=function(n,e,t){let i=asParentNode(getRootNode(n,t)).querySelectorAll(e);for(let r=0;r=0;r--){let o=i[r];if(o.compareDocumentPosition(n)===Node.DOCUMENT_POSITION_FOLLOWING)return o}};function querySelectorExt(n,e){return typeof n!="string"?querySelectorAllExt(n,e)[0]:querySelectorAllExt(getDocument().body,n)[0]}function resolveTarget(n,e){return typeof n=="string"?find(asParentNode(e)||document,n):n}function processEventArgs(n,e,t,i){return isFunction(e)?{target:getDocument().body,event:asString(n),listener:e,options:t}:{target:resolveTarget(n),event:asString(e),listener:t,options:i}}function addEventListenerImpl(n,e,t,i){return ready(function(){let o=processEventArgs(n,e,t,i);o.target.addEventListener(o.event,o.listener,o.options)}),isFunction(e)?e:t}function removeEventListenerImpl(n,e,t){return ready(function(){let i=processEventArgs(n,e,t);i.target.removeEventListener(i.event,i.listener)}),isFunction(e)?e:t}let DUMMY_ELT=getDocument().createElement("output");function findAttributeTargets(n,e){let t=getClosestAttributeValue(n,e);if(t){if(t==="this")return[findThisElement(n,e)];{let i=querySelectorAllExt(n,t);if(/(^|,)(\s*)inherit(\s*)($|,)/.test(t)){let o=asElement(getClosestMatch(n,function(s){return s!==n&&hasAttribute(asElement(s),e)}));o&&i.push(...findAttributeTargets(o,e))}return i.length===0?(logError('The selector "'+t+'" on '+e+" returned no matches!"),[DUMMY_ELT]):i}}}function findThisElement(n,e){return asElement(getClosestMatch(n,function(t){return getAttributeValue(asElement(t),e)!=null}))}function getTarget(n){let e=getClosestAttributeValue(n,"hx-target");return e?e==="this"?findThisElement(n,"hx-target"):querySelectorExt(n,e):getInternalData(n).boosted?getDocument().body:n}function shouldSettleAttribute(n){return htmx.config.attributesToSettle.includes(n)}function cloneAttributes(n,e){forEach(Array.from(n.attributes),function(t){!e.hasAttribute(t.name)&&shouldSettleAttribute(t.name)&&n.removeAttribute(t.name)}),forEach(e.attributes,function(t){shouldSettleAttribute(t.name)&&n.setAttribute(t.name,t.value)})}function isInlineSwap(n,e){let t=getExtensions(e);for(let i=0;i0?(o=n.substring(0,n.indexOf(":")),r=n.substring(n.indexOf(":")+1)):o=n),e.removeAttribute("hx-swap-oob"),e.removeAttribute("data-hx-swap-oob");let s=querySelectorAllExt(i,r,!1);return s.length?(forEach(s,function(a){let l,c=e.cloneNode(!0);l=getDocument().createDocumentFragment(),l.appendChild(c),isInlineSwap(o,a)||(l=asParentNode(c));let u={shouldSwap:!0,target:a,fragment:l};triggerEvent(a,"htmx:oobBeforeSwap",u)&&(a=u.target,u.shouldSwap&&(handlePreservedElements(l),swapWithStyle(o,a,a,l,t),restorePreservedElements()),forEach(t.elts,function(d){triggerEvent(d,"htmx:oobAfterSwap",u)}))}),e.parentNode.removeChild(e)):(e.parentNode.removeChild(e),triggerErrorEvent(getDocument().body,"htmx:oobErrorNoTarget",{content:e})),n}function restorePreservedElements(){let n=find("#--htmx-preserve-pantry--");if(n){for(let e of[...n.children]){let t=find("#"+e.id);t.parentNode.moveBefore(e,t),t.remove()}n.remove()}}function handlePreservedElements(n){forEach(findAll(n,"[hx-preserve], [data-hx-preserve]"),function(e){let t=getAttributeValue(e,"id"),i=getDocument().getElementById(t);if(i!=null)if(e.moveBefore){let r=find("#--htmx-preserve-pantry--");r==null&&(getDocument().body.insertAdjacentHTML("afterend","
"),r=find("#--htmx-preserve-pantry--")),r.moveBefore(i,null)}else e.parentNode.replaceChild(i,e)})}function handleAttributes(n,e,t){forEach(e.querySelectorAll("[id]"),function(i){let r=getRawAttribute(i,"id");if(r&&r.length>0){let o=r.replace("'","\\'"),s=i.tagName.replace(":","\\:"),a=asParentNode(n),l=a&&a.querySelector(s+"[id='"+o+"']");if(l&&l!==a){let c=i.cloneNode();cloneAttributes(i,l),t.tasks.push(function(){cloneAttributes(i,c)})}}})}function makeAjaxLoadTask(n){return function(){removeClassFromElement(n,htmx.config.addedClass),processNode(asElement(n)),processFocus(asParentNode(n)),triggerEvent(n,"htmx:load")}}function processFocus(n){let e="[autofocus]",t=asHtmlElement(matches(n,e)?n:n.querySelector(e));t!=null&&t.focus()}function insertNodesBefore(n,e,t,i){for(handleAttributes(n,t,i);t.childNodes.length>0;){let r=t.firstChild;addClassToElement(asElement(r),htmx.config.addedClass),n.insertBefore(r,e),r.nodeType!==Node.TEXT_NODE&&r.nodeType!==Node.COMMENT_NODE&&i.tasks.push(makeAjaxLoadTask(r))}}function stringHash(n,e){let t=0;for(;t0}function swap(n,e,t,i){i||(i={});let r=null,o=null,s=function(){maybeCall(i.beforeSwapCallback),n=resolveTarget(n);let c=i.contextElement?getRootNode(i.contextElement,!1):getDocument(),u=document.activeElement,d={};d={elt:u,start:u?u.selectionStart:null,end:u?u.selectionEnd:null};let p=makeSettleInfo(n);if(t.swapStyle==="textContent")n.textContent=e;else{let m=makeFragment(e);if(p.title=i.title||m.title,i.historyRequest&&(m=m.querySelector("[hx-history-elt],[data-hx-history-elt]")||m),i.selectOOB){let v=i.selectOOB.split(",");for(let w=0;w0?getWindow().setTimeout(y,t.settleDelay):y()},a=htmx.config.globalViewTransitions;t.hasOwnProperty("transition")&&(a=t.transition);let l=i.contextElement||getDocument();if(a&&triggerEvent(l,"htmx:beforeTransition",i.eventInfo)&&typeof Promise!="undefined"&&document.startViewTransition){let c=new Promise(function(d,p){r=d,o=p}),u=s;s=function(){document.startViewTransition(function(){return u(),c})}}try{t!=null&&t.swapDelay&&t.swapDelay>0?getWindow().setTimeout(s,t.swapDelay):s()}catch(c){throw triggerErrorEvent(l,"htmx:swapError",i.eventInfo),maybeCall(o),c}}function handleTriggerHeader(n,e,t){let i=n.getResponseHeader(e);if(i.indexOf("{")===0){let r=parseJSON(i);for(let o in r)if(r.hasOwnProperty(o)){let s=r[o];isRawObject(s)?t=s.target!==void 0?s.target:t:s={value:s},triggerEvent(t,o,s)}}else{let r=i.split(",");for(let o=0;o0;){let s=e[0];if(s==="]"){if(i--,i===0){o===null&&(r=r+"true"),e.shift(),r+=")})";try{let a=maybeEval(n,function(){return Function(r)()},function(){return!0});return a.source=r,a}catch(a){return triggerErrorEvent(getDocument().body,"htmx:syntax:error",{error:a,source:r}),null}}}else s==="["&&i++;isPossibleRelativeReference(s,o,t)?r+="(("+t+"."+s+") ? ("+t+"."+s+") : (window."+s+"))":r=r+s,o=e.shift()}}}function consumeUntil(n,e){let t="";for(;n.length>0&&!e.test(n[0]);)t+=n.shift();return t}function consumeCSSSelector(n){let e;return n.length>0&&COMBINED_SELECTOR_START.test(n[0])?(n.shift(),e=consumeUntil(n,COMBINED_SELECTOR_END).trim(),n.shift()):e=consumeUntil(n,WHITESPACE_OR_COMMA),e}let INPUT_SELECTOR="input, textarea, select";function parseAndCacheTrigger(n,e,t){let i=[],r=tokenizeString(e);do{consumeUntil(r,NOT_WHITESPACE);let a=r.length,l=consumeUntil(r,/[,\[\s]/);if(l!=="")if(l==="every"){let c={trigger:"every"};consumeUntil(r,NOT_WHITESPACE),c.pollInterval=parseInterval(consumeUntil(r,/[,\[\s]/)),consumeUntil(r,NOT_WHITESPACE);var o=maybeGenerateConditional(n,r,"event");o&&(c.eventFilter=o),i.push(c)}else{let c={trigger:l};var o=maybeGenerateConditional(n,r,"event");for(o&&(c.eventFilter=o),consumeUntil(r,NOT_WHITESPACE);r.length>0&&r[0]!==",";){let d=r.shift();if(d==="changed")c.changed=!0;else if(d==="once")c.once=!0;else if(d==="consume")c.consume=!0;else if(d==="delay"&&r[0]===":")r.shift(),c.delay=parseInterval(consumeUntil(r,WHITESPACE_OR_COMMA));else if(d==="from"&&r[0]===":"){if(r.shift(),COMBINED_SELECTOR_START.test(r[0]))var s=consumeCSSSelector(r);else{var s=consumeUntil(r,WHITESPACE_OR_COMMA);if(s==="closest"||s==="find"||s==="next"||s==="previous"){r.shift();let y=consumeCSSSelector(r);y.length>0&&(s+=" "+y)}}c.from=s}else d==="target"&&r[0]===":"?(r.shift(),c.target=consumeCSSSelector(r)):d==="throttle"&&r[0]===":"?(r.shift(),c.throttle=parseInterval(consumeUntil(r,WHITESPACE_OR_COMMA))):d==="queue"&&r[0]===":"?(r.shift(),c.queue=consumeUntil(r,WHITESPACE_OR_COMMA)):d==="root"&&r[0]===":"?(r.shift(),c[d]=consumeCSSSelector(r)):d==="threshold"&&r[0]===":"?(r.shift(),c[d]=consumeUntil(r,WHITESPACE_OR_COMMA)):triggerErrorEvent(n,"htmx:syntax:error",{token:r.shift()});consumeUntil(r,NOT_WHITESPACE)}i.push(c)}r.length===a&&triggerErrorEvent(n,"htmx:syntax:error",{token:r.shift()}),consumeUntil(r,NOT_WHITESPACE)}while(r[0]===","&&r.shift());return t&&(t[e]=i),i}function getTriggerSpecs(n){let e=getAttributeValue(n,"hx-trigger"),t=[];if(e){let i=htmx.config.triggerSpecsCache;t=i&&i[e]||parseAndCacheTrigger(n,e,i)}return t.length>0?t:matches(n,"form")?[{trigger:"submit"}]:matches(n,'input[type="button"], input[type="submit"]')?[{trigger:"click"}]:matches(n,INPUT_SELECTOR)?[{trigger:"change"}]:[{trigger:"click"}]}function cancelPolling(n){getInternalData(n).cancelled=!0}function processPolling(n,e,t){let i=getInternalData(n);i.timeout=getWindow().setTimeout(function(){bodyContains(n)&&i.cancelled!==!0&&(maybeFilterEvent(t,n,makeEvent("hx:poll:trigger",{triggerSpec:t,target:n}))||e(n),processPolling(n,e,t))},t.pollInterval)}function isLocalLink(n){return location.hostname===n.hostname&&getRawAttribute(n,"href")&&getRawAttribute(n,"href").indexOf("#")!==0}function eltIsDisabled(n){return closest(n,htmx.config.disableSelector)}function boostElement(n,e,t){if(n instanceof HTMLAnchorElement&&isLocalLink(n)&&(n.target===""||n.target==="_self")||n.tagName==="FORM"&&String(getRawAttribute(n,"method")).toLowerCase()!=="dialog"){e.boosted=!0;let i,r;if(n.tagName==="A")i="get",r=getRawAttribute(n,"href");else{let o=getRawAttribute(n,"method");i=o?o.toLowerCase():"get",r=getRawAttribute(n,"action"),(r==null||r==="")&&(r=location.href),i==="get"&&r.includes("?")&&(r=r.replace(/\?[^#]+/,""))}t.forEach(function(o){addEventListener(n,function(s,a){let l=asElement(s);if(eltIsDisabled(l)){cleanUpElement(l);return}issueAjaxRequest(i,r,l,a)},e,o,!0)})}}function shouldCancel(n,e){if(n.type==="submit"&&e.tagName==="FORM")return!0;if(n.type==="click"){let t=e.closest('input[type="submit"], button');if(t&&t.form&&t.type==="submit")return!0;let i=e.closest("a"),r=/^#.+/;if(i&&i.href&&!r.test(i.getAttribute("href")))return!0}return!1}function ignoreBoostedAnchorCtrlClick(n,e){return getInternalData(n).boosted&&n instanceof HTMLAnchorElement&&e.type==="click"&&(e.ctrlKey||e.metaKey)}function maybeFilterEvent(n,e,t){let i=n.eventFilter;if(i)try{return i.call(e,t)!==!0}catch(r){let o=i.source;return triggerErrorEvent(getDocument().body,"htmx:eventFilter:error",{error:r,source:o}),!0}return!1}function addEventListener(n,e,t,i,r){let o=getInternalData(n),s;i.from?s=querySelectorAllExt(n,i.from):s=[n],i.changed&&("lastValue"in o||(o.lastValue=new WeakMap),s.forEach(function(a){o.lastValue.has(i)||o.lastValue.set(i,new WeakMap),o.lastValue.get(i).set(a,a.value)})),forEach(s,function(a){let l=function(c){if(!bodyContains(n)){a.removeEventListener(i.trigger,l);return}if(ignoreBoostedAnchorCtrlClick(n,c)||((r||shouldCancel(c,a))&&c.preventDefault(),maybeFilterEvent(i,n,c)))return;let u=getInternalData(c);if(u.triggerSpec=i,u.handledFor==null&&(u.handledFor=[]),u.handledFor.indexOf(n)<0){if(u.handledFor.push(n),i.consume&&c.stopPropagation(),i.target&&c.target&&!matches(asElement(c.target),i.target))return;if(i.once){if(o.triggeredOnce)return;o.triggeredOnce=!0}if(i.changed){let d=c.target,p=d.value,y=o.lastValue.get(i);if(y.has(d)&&y.get(d)===p)return;y.set(d,p)}if(o.delayed&&clearTimeout(o.delayed),o.throttle)return;i.throttle>0?o.throttle||(triggerEvent(n,"htmx:trigger"),e(n,c),o.throttle=getWindow().setTimeout(function(){o.throttle=null},i.throttle)):i.delay>0?o.delayed=getWindow().setTimeout(function(){triggerEvent(n,"htmx:trigger"),e(n,c)},i.delay):(triggerEvent(n,"htmx:trigger"),e(n,c))}};t.listenerInfos==null&&(t.listenerInfos=[]),t.listenerInfos.push({trigger:i.trigger,listener:l,on:a}),a.addEventListener(i.trigger,l)})}let windowIsScrolling=!1,scrollHandler=null;function initScrollHandler(){scrollHandler||(scrollHandler=function(){windowIsScrolling=!0},window.addEventListener("scroll",scrollHandler),window.addEventListener("resize",scrollHandler),setInterval(function(){windowIsScrolling&&(windowIsScrolling=!1,forEach(getDocument().querySelectorAll("[hx-trigger*='revealed'],[data-hx-trigger*='revealed']"),function(n){maybeReveal(n)}))},200))}function maybeReveal(n){!hasAttribute(n,"data-hx-revealed")&&isScrolledIntoView(n)&&(n.setAttribute("data-hx-revealed","true"),getInternalData(n).initHash?triggerEvent(n,"revealed"):n.addEventListener("htmx:afterProcessNode",function(){triggerEvent(n,"revealed")},{once:!0}))}function loadImmediately(n,e,t,i){let r=function(){t.loaded||(t.loaded=!0,triggerEvent(n,"htmx:trigger"),e(n))};i>0?getWindow().setTimeout(r,i):r()}function processVerbs(n,e,t){let i=!1;return forEach(VERBS,function(r){if(hasAttribute(n,"hx-"+r)){let o=getAttributeValue(n,"hx-"+r);i=!0,e.path=o,e.verb=r,t.forEach(function(s){addTriggerHandler(n,s,e,function(a,l){let c=asElement(a);if(eltIsDisabled(c)){cleanUpElement(c);return}issueAjaxRequest(r,o,c,l)})})}}),i}function addTriggerHandler(n,e,t,i){if(e.trigger==="revealed")initScrollHandler(),addEventListener(n,i,t,e),maybeReveal(asElement(n));else if(e.trigger==="intersect"){let r={};e.root&&(r.root=querySelectorExt(n,e.root)),e.threshold&&(r.threshold=parseFloat(e.threshold)),new IntersectionObserver(function(s){for(let a=0;a0?(t.polling=!0,processPolling(asElement(n),i,e)):addEventListener(n,i,t,e)}function shouldProcessHxOn(n){let e=asElement(n);if(!e)return!1;let t=e.attributes;for(let i=0;i", "+o).join(""))}else return[]}function maybeSetLastButtonClicked(n){let e=getTargetButton(n.target),t=getRelatedFormData(n);t&&(t.lastButtonClicked=e)}function maybeUnsetLastButtonClicked(n){let e=getRelatedFormData(n);e&&(e.lastButtonClicked=null)}function getTargetButton(n){return closest(asElement(n),"button, input[type='submit']")}function getRelatedForm(n){return n.form||closest(n,"form")}function getRelatedFormData(n){let e=getTargetButton(n.target);if(!e)return;let t=getRelatedForm(e);if(t)return getInternalData(t)}function initButtonTracking(n){n.addEventListener("click",maybeSetLastButtonClicked),n.addEventListener("focusin",maybeSetLastButtonClicked),n.addEventListener("focusout",maybeUnsetLastButtonClicked)}function addHxOnEventHandler(n,e,t){let i=getInternalData(n);Array.isArray(i.onHandlers)||(i.onHandlers=[]);let r,o=function(s){maybeEval(n,function(){eltIsDisabled(n)||(r||(r=new Function("event",t)),r.call(n,s))})};n.addEventListener(e,o),i.onHandlers.push({event:e,listener:o})}function processHxOnWildcard(n){deInitOnHandlers(n);for(let e=0;ehtmx.config.historyCacheSize;)o.shift();for(;o.length>0;)try{sessionStorage.setItem("htmx-history-cache",JSON.stringify(o));break}catch(a){triggerErrorEvent(getDocument().body,"htmx:historyCacheError",{cause:a,cache:o}),o.shift()}}function getCachedHistory(n){if(!canAccessLocalStorage())return null;n=normalizePath(n);let e=parseJSON(sessionStorage.getItem("htmx-history-cache"))||[];for(let t=0;t=200&&this.status<400?(i.response=this.response,triggerEvent(getDocument().body,"htmx:historyCacheMissLoad",i),swap(i.historyElt,i.response,t,{contextElement:i.historyElt,historyRequest:!0}),setCurrentPathForHistory(i.path),triggerEvent(getDocument().body,"htmx:historyRestore",{path:n,cacheMiss:!0,serverResponse:i.response})):triggerErrorEvent(getDocument().body,"htmx:historyCacheMissLoadError",i)},triggerEvent(getDocument().body,"htmx:historyCacheMiss",i)&&e.send()}function restoreHistory(n){saveCurrentPageToHistory(),n=n||location.pathname+location.search;let e=getCachedHistory(n);if(e){let t={swapStyle:"innerHTML",swapDelay:0,settleDelay:0,scroll:e.scroll},i={path:n,item:e,historyElt:getHistoryElement(),swapSpec:t};triggerEvent(getDocument().body,"htmx:historyCacheHit",i)&&(swap(i.historyElt,e.content,t,{contextElement:i.historyElt,title:e.title}),setCurrentPathForHistory(i.path),triggerEvent(getDocument().body,"htmx:historyRestore",i))}else htmx.config.refreshOnHistoryMiss?htmx.location.reload(!0):loadHistoryFromServer(n)}function addRequestIndicatorClasses(n){let e=findAttributeTargets(n,"hx-indicator");return e==null&&(e=[n]),forEach(e,function(t){let i=getInternalData(t);i.requestCount=(i.requestCount||0)+1,t.classList.add.call(t.classList,htmx.config.requestClass)}),e}function disableElements(n){let e=findAttributeTargets(n,"hx-disabled-elt");return e==null&&(e=[]),forEach(e,function(t){let i=getInternalData(t);i.requestCount=(i.requestCount||0)+1,t.setAttribute("disabled",""),t.setAttribute("data-disabled-by-htmx","")}),e}function removeRequestIndicators(n,e){forEach(n.concat(e),function(t){let i=getInternalData(t);i.requestCount=(i.requestCount||1)-1}),forEach(n,function(t){getInternalData(t).requestCount===0&&t.classList.remove.call(t.classList,htmx.config.requestClass)}),forEach(e,function(t){getInternalData(t).requestCount===0&&(t.removeAttribute("disabled"),t.removeAttribute("data-disabled-by-htmx"))})}function haveSeenNode(n,e){for(let t=0;te.indexOf(r)<0):i=i.filter(r=>r!==e),t.delete(n),forEach(i,r=>t.append(n,r))}}function getValueFromInput(n){return n instanceof HTMLSelectElement&&n.multiple?toArray(n.querySelectorAll("option:checked")).map(function(e){return e.value}):n instanceof HTMLInputElement&&n.files?toArray(n.files):n.value}function processInputValue(n,e,t,i,r){if(!(i==null||haveSeenNode(n,i))){if(n.push(i),shouldInclude(i)){let o=getRawAttribute(i,"name");addValueToFormData(o,getValueFromInput(i),e),r&&validateElement(i,t)}i instanceof HTMLFormElement&&(forEach(i.elements,function(o){n.indexOf(o)>=0?removeValueFromFormData(o.name,getValueFromInput(o),e):n.push(o),r&&validateElement(o,t)}),new FormData(i).forEach(function(o,s){o instanceof File&&o.name===""||addValueToFormData(s,o,e)}))}}function validateElement(n,e){let t=n;t.willValidate&&(triggerEvent(t,"htmx:validation:validate"),t.checkValidity()||(triggerEvent(t,"htmx:validation:failed",{message:t.validationMessage,validity:t.validity})&&!e.length&&htmx.config.reportValidityOfForms&&t.reportValidity(),e.push({elt:t,message:t.validationMessage,validity:t.validity})))}function overrideFormData(n,e){for(let t of e.keys())n.delete(t);return e.forEach(function(t,i){n.append(i,t)}),n}function getInputValues(n,e){let t=[],i=new FormData,r=new FormData,o=[],s=getInternalData(n);s.lastButtonClicked&&!bodyContains(s.lastButtonClicked)&&(s.lastButtonClicked=null);let a=n instanceof HTMLFormElement&&n.noValidate!==!0||getAttributeValue(n,"hx-validate")==="true";if(s.lastButtonClicked&&(a=a&&s.lastButtonClicked.formNoValidate!==!0),e!=="get"&&processInputValue(t,r,o,getRelatedForm(n),a),processInputValue(t,i,o,n,a),s.lastButtonClicked||n.tagName==="BUTTON"||n.tagName==="INPUT"&&getRawAttribute(n,"type")==="submit"){let c=s.lastButtonClicked||n,u=getRawAttribute(c,"name");addValueToFormData(u,c.value,r)}let l=findAttributeTargets(n,"hx-include");return forEach(l,function(c){processInputValue(t,i,o,asElement(c),a),matches(c,"form")||forEach(asParentNode(c).querySelectorAll(INPUT_SELECTOR),function(u){processInputValue(t,i,o,u,a)})}),overrideFormData(i,r),{errors:o,formData:i,values:formDataProxy(i)}}function appendParam(n,e,t){n!==""&&(n+="&"),String(t)==="[object Object]"&&(t=JSON.stringify(t));let i=encodeURIComponent(t);return n+=encodeURIComponent(e)+"="+i,n}function urlEncode(n){n=formDataFromObject(n);let e="";return n.forEach(function(t,i){e=appendParam(e,i,t)}),e}function getHeaders(n,e,t){let i={"HX-Request":"true","HX-Trigger":getRawAttribute(n,"id"),"HX-Trigger-Name":getRawAttribute(n,"name"),"HX-Target":getAttributeValue(e,"id"),"HX-Current-URL":location.href};return getValuesForElement(n,"hx-headers",!1,i),t!==void 0&&(i["HX-Prompt"]=t),getInternalData(n).boosted&&(i["HX-Boosted"]="true"),i}function filterValues(n,e){let t=getClosestAttributeValue(e,"hx-params");if(t){if(t==="none")return new FormData;if(t==="*")return n;if(t.indexOf("not ")===0)return forEach(t.slice(4).split(","),function(i){i=i.trim(),n.delete(i)}),n;{let i=new FormData;return forEach(t.split(","),function(r){r=r.trim(),n.has(r)&&n.getAll(r).forEach(function(o){i.append(r,o)})}),i}}else return n}function isAnchorLink(n){return!!getRawAttribute(n,"href")&&getRawAttribute(n,"href").indexOf("#")>=0}function getSwapSpecification(n,e){let t=e||getClosestAttributeValue(n,"hx-swap"),i={swapStyle:getInternalData(n).boosted?"innerHTML":htmx.config.defaultSwapStyle,swapDelay:htmx.config.defaultSwapDelay,settleDelay:htmx.config.defaultSettleDelay};if(htmx.config.scrollIntoViewOnBoost&&getInternalData(n).boosted&&!isAnchorLink(n)&&(i.show="top"),t){let s=splitOnWhitespace(t);if(s.length>0)for(let a=0;a0?r.join(":"):null;i.scroll=u,i.scrollTarget=o}else if(l.indexOf("show:")===0){var r=l.slice(5).split(":");let d=r.pop();var o=r.length>0?r.join(":"):null;i.show=d,i.showTarget=o}else if(l.indexOf("focus-scroll:")===0){let c=l.slice(13);i.focusScroll=c=="true"}else a==0?i.swapStyle=l:logError("Unknown modifier in hx-swap: "+l)}}return i}function usesFormData(n){return getClosestAttributeValue(n,"hx-encoding")==="multipart/form-data"||matches(n,"form")&&getRawAttribute(n,"enctype")==="multipart/form-data"}function encodeParamsForBody(n,e,t){let i=null;return withExtensions(e,function(r){i==null&&(i=r.encodeParameters(n,t,e))}),i!=null?i:usesFormData(e)?overrideFormData(new FormData,formDataFromObject(t)):urlEncode(t)}function makeSettleInfo(n){return{tasks:[],elts:[n]}}function updateScrollState(n,e){let t=n[0],i=n[n.length-1];if(e.scroll){var r=null;e.scrollTarget&&(r=asElement(querySelectorExt(t,e.scrollTarget))),e.scroll==="top"&&(t||r)&&(r=r||t,r.scrollTop=0),e.scroll==="bottom"&&(i||r)&&(r=r||i,r.scrollTop=r.scrollHeight),typeof e.scroll=="number"&&getWindow().setTimeout(function(){window.scrollTo(0,e.scroll)},0)}if(e.show){var r=null;if(e.showTarget){let s=e.showTarget;e.showTarget==="window"&&(s="body"),r=asElement(querySelectorExt(t,s))}e.show==="top"&&(t||r)&&(r=r||t,r.scrollIntoView({block:"start",behavior:htmx.config.scrollBehavior})),e.show==="bottom"&&(i||r)&&(r=r||i,r.scrollIntoView({block:"end",behavior:htmx.config.scrollBehavior}))}}function getValuesForElement(n,e,t,i,r){if(i==null&&(i={}),n==null)return i;let o=getAttributeValue(n,e);if(o){let s=o.trim(),a=t;if(s==="unset")return null;s.indexOf("javascript:")===0?(s=s.slice(11),a=!0):s.indexOf("js:")===0&&(s=s.slice(3),a=!0),s.indexOf("{")!==0&&(s="{"+s+"}");let l;a?l=maybeEval(n,function(){return r?Function("event","return ("+s+")").call(n,r):Function("return ("+s+")").call(n)},{}):l=parseJSON(s);for(let c in l)l.hasOwnProperty(c)&&i[c]==null&&(i[c]=l[c])}return getValuesForElement(asElement(parentElt(n)),e,t,i,r)}function maybeEval(n,e,t){return htmx.config.allowEval?e():(triggerErrorEvent(n,"htmx:evalDisallowedError"),t)}function getHXVarsForElement(n,e,t){return getValuesForElement(n,"hx-vars",!0,t,e)}function getHXValsForElement(n,e,t){return getValuesForElement(n,"hx-vals",!1,t,e)}function getExpressionVars(n,e){return mergeObjects(getHXVarsForElement(n,e),getHXValsForElement(n,e))}function safelySetHeaderValue(n,e,t){if(t!==null)try{n.setRequestHeader(e,t)}catch(i){n.setRequestHeader(e,encodeURIComponent(t)),n.setRequestHeader(e+"-URI-AutoEncoded","true")}}function getPathFromResponse(n){if(n.responseURL)try{let e=new URL(n.responseURL);return e.pathname+e.search}catch(e){triggerErrorEvent(getDocument().body,"htmx:badResponseUrl",{url:n.responseURL})}}function hasHeader(n,e){return e.test(n.getAllResponseHeaders())}function ajaxHelper(n,e,t){if(n=n.toLowerCase(),t){if(t instanceof Element||typeof t=="string")return issueAjaxRequest(n,e,null,null,{targetOverride:resolveTarget(t)||DUMMY_ELT,returnPromise:!0});{let i=resolveTarget(t.target);return(t.target&&!i||t.source&&!i&&!resolveTarget(t.source))&&(i=DUMMY_ELT),issueAjaxRequest(n,e,resolveTarget(t.source),t.event,{handler:t.handler,headers:t.headers,values:t.values,targetOverride:i,swapOverride:t.swap,select:t.select,returnPromise:!0})}}else return issueAjaxRequest(n,e,null,null,{returnPromise:!0})}function hierarchyForElt(n){let e=[];for(;n;)e.push(n),n=n.parentElement;return e}function verifyPath(n,e,t){let i=new URL(e,location.protocol!=="about:"?location.href:window.origin),o=(location.protocol!=="about:"?location.origin:window.origin)===i.origin;return htmx.config.selfRequestsOnly&&!o?!1:triggerEvent(n,"htmx:validateUrl",mergeObjects({url:i,sameHost:o},t))}function formDataFromObject(n){if(n instanceof FormData)return n;let e=new FormData;for(let t in n)n.hasOwnProperty(t)&&(n[t]&&typeof n[t].forEach=="function"?n[t].forEach(function(i){e.append(t,i)}):typeof n[t]=="object"&&!(n[t]instanceof Blob)?e.append(t,JSON.stringify(n[t])):e.append(t,n[t]));return e}function formDataArrayProxy(n,e,t){return new Proxy(t,{get:function(i,r){return typeof r=="number"?i[r]:r==="length"?i.length:r==="push"?function(o){i.push(o),n.append(e,o)}:typeof i[r]=="function"?function(){i[r].apply(i,arguments),n.delete(e),i.forEach(function(o){n.append(e,o)})}:i[r]&&i[r].length===1?i[r][0]:i[r]},set:function(i,r,o){return i[r]=o,n.delete(e),i.forEach(function(s){n.append(e,s)}),!0}})}function formDataProxy(n){return new Proxy(n,{get:function(e,t){if(typeof t=="symbol"){let r=Reflect.get(e,t);return typeof r=="function"?function(){return r.apply(n,arguments)}:r}if(t==="toJSON")return()=>Object.fromEntries(n);if(t in e&&typeof e[t]=="function")return function(){return n[t].apply(n,arguments)};let i=n.getAll(t);if(i.length!==0)return i.length===1?i[0]:formDataArrayProxy(e,t,i)},set:function(e,t,i){return typeof t!="string"?!1:(e.delete(t),i&&typeof i.forEach=="function"?i.forEach(function(r){e.append(t,r)}):typeof i=="object"&&!(i instanceof Blob)?e.append(t,JSON.stringify(i)):e.append(t,i),!0)},deleteProperty:function(e,t){return typeof t=="string"&&e.delete(t),!0},ownKeys:function(e){return Reflect.ownKeys(Object.fromEntries(e))},getOwnPropertyDescriptor:function(e,t){return Reflect.getOwnPropertyDescriptor(Object.fromEntries(e),t)}})}function issueAjaxRequest(n,e,t,i,r,o){let s=null,a=null;if(r=r!=null?r:{},r.returnPromise&&typeof Promise!="undefined")var l=new Promise(function(U,Z){s=U,a=Z});t==null&&(t=getDocument().body);let c=r.handler||handleAjaxResponse,u=r.select||null;if(!bodyContains(t))return maybeCall(s),l;let d=r.targetOverride||asElement(getTarget(t));if(d==null||d==DUMMY_ELT)return triggerErrorEvent(t,"htmx:targetError",{target:getClosestAttributeValue(t,"hx-target")}),maybeCall(a),l;let p=getInternalData(t),y=p.lastButtonClicked;if(y){let U=getRawAttribute(y,"formaction");U!=null&&(e=U);let Z=getRawAttribute(y,"formmethod");if(Z!=null)if(VERBS.includes(Z.toLowerCase()))n=Z;else return maybeCall(s),l}let m=getClosestAttributeValue(t,"hx-confirm");if(o===void 0&&triggerEvent(t,"htmx:confirm",{target:d,elt:t,path:e,verb:n,triggeringEvent:i,etc:r,issueRequest:function(oe){return issueAjaxRequest(n,e,t,i,r,!!oe)},question:m})===!1)return maybeCall(s),l;let v=t,w=getClosestAttributeValue(t,"hx-sync"),T=null,_=!1;if(w){let U=w.split(":"),Z=U[0].trim();if(Z==="this"?v=findThisElement(t,"hx-sync"):v=asElement(querySelectorExt(t,Z)),w=(U[1]||"drop").trim(),p=getInternalData(v),w==="drop"&&p.xhr&&p.abortable!==!0)return maybeCall(s),l;if(w==="abort"){if(p.xhr)return maybeCall(s),l;_=!0}else w==="replace"?triggerEvent(v,"htmx:abort"):w.indexOf("queue")===0&&(T=(w.split(" ")[1]||"last").trim())}if(p.xhr)if(p.abortable)triggerEvent(v,"htmx:abort");else{if(T==null){if(i){let U=getInternalData(i);U&&U.triggerSpec&&U.triggerSpec.queue&&(T=U.triggerSpec.queue)}T==null&&(T="last")}return p.queuedRequests==null&&(p.queuedRequests=[]),T==="first"&&p.queuedRequests.length===0?p.queuedRequests.push(function(){issueAjaxRequest(n,e,t,i,r)}):T==="all"?p.queuedRequests.push(function(){issueAjaxRequest(n,e,t,i,r)}):T==="last"&&(p.queuedRequests=[],p.queuedRequests.push(function(){issueAjaxRequest(n,e,t,i,r)})),maybeCall(s),l}let S=new XMLHttpRequest;p.xhr=S,p.abortable=_;let A=function(){p.xhr=null,p.abortable=!1,p.queuedRequests!=null&&p.queuedRequests.length>0&&p.queuedRequests.shift()()},K=getClosestAttributeValue(t,"hx-prompt");if(K){var z=prompt(K);if(z===null||!triggerEvent(t,"htmx:prompt",{prompt:z,target:d}))return maybeCall(s),A(),l}if(m&&!o&&!confirm(m))return maybeCall(s),A(),l;let L=getHeaders(t,d,z);n!=="get"&&!usesFormData(t)&&(L["Content-Type"]="application/x-www-form-urlencoded"),r.headers&&(L=mergeObjects(L,r.headers));let H=getInputValues(t,n),N=H.errors,Y=H.formData;r.values&&overrideFormData(Y,formDataFromObject(r.values));let $=formDataFromObject(getExpressionVars(t,i)),ie=overrideFormData(Y,$),J=filterValues(ie,t);htmx.config.getCacheBusterParam&&n==="get"&&J.set("org.htmx.cache-buster",getRawAttribute(d,"id")||"true"),(e==null||e==="")&&(e=location.href);let Te=getValuesForElement(t,"hx-request"),Ce=getInternalData(t).boosted,se=htmx.config.methodsThatUseUrlParams.indexOf(n)>=0,ne={boosted:Ce,useUrlParams:se,formData:J,parameters:formDataProxy(J),unfilteredFormData:ie,unfilteredParameters:formDataProxy(ie),headers:L,elt:t,target:d,verb:n,errors:N,withCredentials:r.credentials||Te.credentials||htmx.config.withCredentials,timeout:r.timeout||Te.timeout||htmx.config.timeout,path:e,triggeringEvent:i};if(!triggerEvent(t,"htmx:configRequest",ne))return maybeCall(s),A(),l;if(e=ne.path,n=ne.verb,L=ne.headers,J=formDataFromObject(ne.parameters),N=ne.errors,se=ne.useUrlParams,N&&N.length>0)return triggerEvent(t,"htmx:validation:halted",ne),maybeCall(s),A(),l;let qe=e.split("#"),Re=qe[0],W=qe[1],M=e;if(se&&(M=Re,!J.keys().next().done&&(M.indexOf("?")<0?M+="?":M+="&",M+=urlEncode(J),W&&(M+="#"+W))),!verifyPath(t,M,ne))return triggerErrorEvent(t,"htmx:invalidPath",ne),maybeCall(a),A(),l;if(S.open(n.toUpperCase(),M,!0),S.overrideMimeType("text/html"),S.withCredentials=ne.withCredentials,S.timeout=ne.timeout,!Te.noHeaders){for(let U in L)if(L.hasOwnProperty(U)){let Z=L[U];safelySetHeaderValue(S,U,Z)}}let D={xhr:S,target:d,requestConfig:ne,etc:r,boosted:Ce,select:u,pathInfo:{requestPath:e,finalRequestPath:M,responsePath:null,anchor:W}};if(S.onload=function(){try{let U=hierarchyForElt(t);if(D.pathInfo.responsePath=getPathFromResponse(S),c(t,D),D.keepIndicators!==!0&&removeRequestIndicators(B,V),triggerEvent(t,"htmx:afterRequest",D),triggerEvent(t,"htmx:afterOnLoad",D),!bodyContains(t)){let Z=null;for(;U.length>0&&Z==null;){let oe=U.shift();bodyContains(oe)&&(Z=oe)}Z&&(triggerEvent(Z,"htmx:afterRequest",D),triggerEvent(Z,"htmx:afterOnLoad",D))}maybeCall(s)}catch(U){throw triggerErrorEvent(t,"htmx:onLoadError",mergeObjects({error:U},D)),U}finally{A()}},S.onerror=function(){removeRequestIndicators(B,V),triggerErrorEvent(t,"htmx:afterRequest",D),triggerErrorEvent(t,"htmx:sendError",D),maybeCall(a),A()},S.onabort=function(){removeRequestIndicators(B,V),triggerErrorEvent(t,"htmx:afterRequest",D),triggerErrorEvent(t,"htmx:sendAbort",D),maybeCall(a),A()},S.ontimeout=function(){removeRequestIndicators(B,V),triggerErrorEvent(t,"htmx:afterRequest",D),triggerErrorEvent(t,"htmx:timeout",D),maybeCall(a),A()},!triggerEvent(t,"htmx:beforeRequest",D))return maybeCall(s),A(),l;var B=addRequestIndicatorClasses(t),V=disableElements(t);forEach(["loadstart","loadend","progress","abort"],function(U){forEach([S,S.upload],function(Z){Z.addEventListener(U,function(oe){triggerEvent(t,"htmx:xhr:"+U,{lengthComputable:oe.lengthComputable,loaded:oe.loaded,total:oe.total})})})}),triggerEvent(t,"htmx:beforeSend",D);let q=se?null:encodeParamsForBody(S,t,J);return S.send(q),l}function determineHistoryUpdates(n,e){let t=e.xhr,i=null,r=null;if(hasHeader(t,/HX-Push:/i)?(i=t.getResponseHeader("HX-Push"),r="push"):hasHeader(t,/HX-Push-Url:/i)?(i=t.getResponseHeader("HX-Push-Url"),r="push"):hasHeader(t,/HX-Replace-Url:/i)&&(i=t.getResponseHeader("HX-Replace-Url"),r="replace"),i)return i==="false"?{}:{type:r,path:i};let o=e.pathInfo.finalRequestPath,s=e.pathInfo.responsePath,a=getClosestAttributeValue(n,"hx-push-url"),l=getClosestAttributeValue(n,"hx-replace-url"),c=getInternalData(n).boosted,u=null,d=null;return a?(u="push",d=a):l?(u="replace",d=l):c&&(u="push",d=s||o),d?d==="false"?{}:(d==="true"&&(d=s||o),e.pathInfo.anchor&&d.indexOf("#")===-1&&(d=d+"#"+e.pathInfo.anchor),{type:u,path:d}):{}}function codeMatches(n,e){var t=new RegExp(n.code);return t.test(e.toString(10))}function resolveResponseHandling(n){for(var e=0;e.${e}{opacity:0;visibility: hidden} .${t} .${e}, .${t}.${e}{opacity:1;visibility: visible;transition: opacity 200ms ease-in}`)}}function getMetaConfig(){let n=getDocument().querySelector('meta[name="htmx-config"]');return n?parseJSON(n.content):null}function mergeMetaConfig(){let n=getMetaConfig();n&&(htmx.config=mergeObjects(htmx.config,n))}return ready(function(){mergeMetaConfig(),insertIndicatorStyles();let n=getDocument().body;processNode(n);let e=getDocument().querySelectorAll("[hx-trigger='restored'],[data-hx-trigger='restored']");n.addEventListener("htmx:abort",function(i){let r=i.target,o=getInternalData(r);o&&o.xhr&&o.xhr.abort()});let t=window.onpopstate?window.onpopstate.bind(window):null;window.onpopstate=function(i){i.state&&i.state.htmx?(restoreHistory(),forEach(e,function(r){triggerEvent(r,"htmx:restored",{document:getDocument(),triggerEvent})})):t&&t(i)},getWindow().setTimeout(function(){triggerEvent(n,"htmx:load",{}),n=null},0)}),htmx}(),x_=Kp;function ko(n,e){n.split(/\s+/).forEach(t=>{e(t)})}var oi=class{constructor(){this._events={}}on(e,t){ko(e,i=>{let r=this._events[i]||[];r.push(t),this._events[i]=r})}off(e,t){var i=arguments.length;if(i===0){this._events={};return}ko(e,r=>{if(i===1){delete this._events[r];return}let o=this._events[r];o!==void 0&&(o.splice(o.indexOf(t),1),this._events[r]=o)})}trigger(e,...t){var i=this;ko(e,r=>{let o=i._events[r];o!==void 0&&o.forEach(s=>{s.apply(i,t)})})}};function No(n){return n.plugins={},class extends n{constructor(){super(...arguments),this.plugins={names:[],settings:{},requested:{},loaded:{}}}static define(e,t){n.plugins[e]={name:e,fn:t}}initializePlugins(e){var t,i;let r=this,o=[];if(Array.isArray(e))e.forEach(s=>{typeof s=="string"?o.push(s):(r.plugins.settings[s.name]=s.options,o.push(s.name))});else if(e)for(t in e)e.hasOwnProperty(t)&&(r.plugins.settings[t]=e[t],o.push(t));for(;i=o.shift();)r.require(i)}loadPlugin(e){var t=this,i=t.plugins,r=n.plugins[e];if(!n.plugins.hasOwnProperty(e))throw new Error('Unable to find "'+e+'" plugin');i.requested[e]=!0,i.loaded[e]=r.fn.apply(t,[t.plugins.settings[e]||{}]),i.names.push(e)}require(e){var t=this,i=t.plugins;if(!t.plugins.loaded.hasOwnProperty(e)){if(i.requested[e])throw new Error('Plugin has circular dependency ("'+e+'")');t.loadPlugin(e)}return i.loaded[e]}}}var si=n=>(n=n.filter(Boolean),n.length<2?n[0]||"":Qp(n)==1?"["+n.join("")+"]":"(?:"+n.join("|")+")"),Io=n=>{if(!Xp(n))return n.join("");let e="",t=0,i=()=>{t>1&&(e+="{"+t+"}")};return n.forEach((r,o)=>{if(r===n[o-1]){t++;return}i(),e+=r,t=1}),i(),e},Ro=n=>{let e=Array.from(n);return si(e)},Xp=n=>new Set(n).size!==n.length,Lt=n=>(n+"").replace(/([\$\(\)\*\+\.\?\[\]\^\{\|\}\\])/gu,"\\$1"),Qp=n=>n.reduce((e,t)=>Math.max(e,Jp(t)),0),Jp=n=>Array.from(n).length;var Ho=n=>{if(n.length===1)return[[n]];let e=[],t=n.substring(1);return Ho(t).forEach(function(r){let o=r.slice(0);o[0]=n.charAt(0)+o[0],e.push(o),o=r.slice(0),o.unshift(n.charAt(0)),e.push(o)}),e};var Zp=[[0,65535]],em="[\u0300-\u036F\xB7\u02BE\u02BC]",or,Ba,tm=3,Po={},Pa={"/":"\u2044\u2215",0:"\u07C0",a:"\u2C65\u0250\u0251",aa:"\uA733",ae:"\xE6\u01FD\u01E3",ao:"\uA735",au:"\uA737",av:"\uA739\uA73B",ay:"\uA73D",b:"\u0180\u0253\u0183",c:"\uA73F\u0188\u023C\u2184",d:"\u0111\u0257\u0256\u1D05\u018C\uABB7\u0501\u0266",e:"\u025B\u01DD\u1D07\u0247",f:"\uA77C\u0192",g:"\u01E5\u0260\uA7A1\u1D79\uA77F\u0262",h:"\u0127\u2C68\u2C76\u0265",i:"\u0268\u0131",j:"\u0249\u0237",k:"\u0199\u2C6A\uA741\uA743\uA745\uA7A3",l:"\u0142\u019A\u026B\u2C61\uA749\uA747\uA781\u026D",m:"\u0271\u026F\u03FB",n:"\uA7A5\u019E\u0272\uA791\u1D0E\u043B\u0509",o:"\xF8\u01FF\u0254\u0275\uA74B\uA74D\u1D11",oe:"\u0153",oi:"\u01A3",oo:"\uA74F",ou:"\u0223",p:"\u01A5\u1D7D\uA751\uA753\uA755\u03C1",q:"\uA757\uA759\u024B",r:"\u024D\u027D\uA75B\uA7A7\uA783",s:"\xDF\u023F\uA7A9\uA785\u0282",t:"\u0167\u01AD\u0288\u2C66\uA787",th:"\xFE",tz:"\uA729",u:"\u0289",v:"\u028B\uA75F\u028C",vy:"\uA761",w:"\u2C73",y:"\u01B4\u024F\u1EFF",z:"\u01B6\u0225\u0240\u2C6C\uA763",hv:"\u0195"};for(let n in Pa){let e=Pa[n]||"";for(let t=0;t{or===void 0&&(or=am(n||Zp))},Fa=(n,e="NFKD")=>n.normalize(e),ai=n=>Array.from(n).reduce((e,t)=>e+rm(t),""),rm=n=>(n=Fa(n).toLowerCase().replace(nm,e=>Po[e]||""),Fa(n,"NFC"));function*om(n){for(let[e,t]of n)for(let i=e;i<=t;i++){let r=String.fromCharCode(i),o=ai(r);o!=r.toLowerCase()&&(o.length>tm||o.length!=0&&(yield{folded:o,composed:r,code_point:i}))}}var sm=n=>{let e={},t=(i,r)=>{let o=e[i]||new Set,s=new RegExp("^"+Ro(o)+"$","iu");r.match(s)||(o.add(Lt(r)),e[i]=o)};for(let i of om(n))t(i.folded,i.folded),t(i.folded,i.composed);return e},am=n=>{let e=sm(n),t={},i=[];for(let o in e){let s=e[o];s&&(t[o]=Ro(s)),o.length>1&&i.push(Lt(o))}i.sort((o,s)=>s.length-o.length);let r=si(i);return Ba=new RegExp("^"+r,"u"),t},lm=(n,e=1)=>{let t=0;return n=n.map(i=>(or[i]&&(t+=i.length),or[i]||i)),t>=e?Io(n):""},cm=(n,e=1)=>(e=Math.max(e,n.length-1),si(Ho(n).map(t=>lm(t,e)))),$a=(n,e=!0)=>{let t=n.length>1?1:0;return si(n.map(i=>{let r=[],o=e?i.length():i.length()-1;for(let s=0;s{for(let t of e){if(t.start!=n.start||t.end!=n.end||t.substrs.join("")!==n.substrs.join(""))continue;let i=n.parts,r=s=>{for(let a of i){if(a.start===s.start&&a.substr===s.substr)return!1;if(!(s.length==1||a.length==1)&&(s.starta.start||a.starts.start))return!0}return!1};if(!(t.parts.filter(r).length>0))return!0}return!1},sr=class n{constructor(){ee(this,"parts");ee(this,"substrs");ee(this,"start");ee(this,"end");this.parts=[],this.substrs=[],this.start=0,this.end=0}add(e){e&&(this.parts.push(e),this.substrs.push(e.substr),this.start=Math.min(e.start,this.start),this.end=Math.max(e.end,this.end))}last(){return this.parts[this.parts.length-1]}length(){return this.parts.length}clone(e,t){let i=new n,r=JSON.parse(JSON.stringify(this.parts)),o=r.pop();for(let l of r)i.add(l);let s=t.substr.substring(0,e-o.start),a=s.length;return i.add({start:o.start,end:o.start+a,length:a,substr:s}),i}},Va=n=>{im(),n=ai(n);let e="",t=[new sr];for(let i=0;i0){l=l.sort((u,d)=>u.length()-d.length());for(let u of l)um(u,t)||t.push(u);continue}if(i>0&&c.size==1&&!c.has("3")){e+=$a(t,!1);let u=new sr,d=t[0];d&&u.add(d.last()),t=[u]}}return e+=$a(t,!0),e};var za=(n,e)=>{if(n)return n[e]},ja=(n,e)=>{if(n){for(var t,i=e.split(".");(t=i.shift())&&(n=n[t]););return n}},ar=(n,e,t)=>{var i,r;return!n||(n=n+"",e.regex==null)||(r=n.search(e.regex),r===-1)?0:(i=e.string.length/n.length,r===0&&(i+=.5),i*t)},lr=(n,e)=>{var t=n[e];if(typeof t=="function")return t;t&&!Array.isArray(t)&&(n[e]=[t])},li=(n,e)=>{if(Array.isArray(n))n.forEach(e);else for(var t in n)n.hasOwnProperty(t)&&e(n[t],t)},Wa=(n,e)=>typeof n=="number"&&typeof e=="number"?n>e?1:ne?1:e>n?-1:0);var cr=class{constructor(e,t){ee(this,"items");ee(this,"settings");this.items=e,this.settings=t||{diacritics:!0}}tokenize(e,t,i){if(!e||!e.length)return[];let r=[],o=e.split(/\s+/);var s;return i&&(s=new RegExp("^("+Object.keys(i).map(Lt).join("|")+"):(.*)$")),o.forEach(a=>{let l,c=null,u=null;s&&(l=a.match(s))&&(c=l[1],a=l[2]),a.length>0&&(this.settings.diacritics?u=Va(a)||null:u=Lt(a),u&&t&&(u="\\b"+u)),r.push({string:a,regex:u?new RegExp(u,"iu"):null,field:c})}),r}getScoreFunction(e,t){var i=this.prepareSearch(e,t);return this._getScoreFunction(i)}_getScoreFunction(e){let t=e.tokens,i=t.length;if(!i)return function(){return 0};let r=e.options.fields,o=e.weights,s=r.length,a=e.getAttrFn;if(!s)return function(){return 1};let l=function(){return s===1?function(c,u){let d=r[0].field;return ar(a(u,d),c,o[d]||1)}:function(c,u){var d=0;if(c.field){let p=a(u,c.field);!c.regex&&p?d+=1/s:d+=ar(p,c,1)}else li(o,(p,y)=>{d+=ar(a(u,y),c,p)});return d/s}}();return i===1?function(c){return l(t[0],c)}:e.options.conjunction==="and"?function(c){var u,d=0;for(let p of t){if(u=l(p,c),u<=0)return 0;d+=u}return d/i}:function(c){var u=0;return li(t,d=>{u+=l(d,c)}),u/i}}getSortFunction(e,t){var i=this.prepareSearch(e,t);return this._getSortFunction(i)}_getSortFunction(e){var t,i=[];let r=this,o=e.options,s=!e.query&&o.sort_empty?o.sort_empty:o.sort;if(typeof s=="function")return s.bind(this);let a=function(c,u){return c==="$score"?u.score:e.getAttrFn(r.items[u.id],c)};if(s)for(let c of s)(e.query||c.field!=="$score")&&i.push(c);if(e.query){t=!0;for(let c of i)if(c.field==="$score"){t=!1;break}t&&i.unshift({field:"$score",direction:"desc"})}else i=i.filter(c=>c.field!=="$score");return i.length?function(c,u){var d,p;for(let y of i)if(p=y.field,d=(y.direction==="desc"?-1:1)*Wa(a(p,c),a(p,u)),d)return d;return 0}:null}prepareSearch(e,t){let i={};var r=Object.assign({},t);if(lr(r,"sort"),lr(r,"sort_empty"),r.fields){lr(r,"fields");let o=[];r.fields.forEach(s=>{typeof s=="string"&&(s={field:s,weight:1}),o.push(s),i[s.field]="weight"in s?s.weight:1}),r.fields=o}return{options:r,query:e.toLowerCase().trim(),tokens:this.tokenize(e,r.respect_word_boundaries,i),total:0,items:[],weights:i,getAttrFn:r.nesting?ja:za}}search(e,t){var i=this,r,o;o=this.prepareSearch(e,t),t=o.options,e=o.query;let s=t.score||i._getScoreFunction(o);e.length?li(i.items,(l,c)=>{r=s(l),(t.filter===!1||r>0)&&o.items.push({score:r,id:c})}):li(i.items,(l,c)=>{o.items.push({score:1,id:c})});let a=i._getSortFunction(o);return a&&o.items.sort(a),o.total=o.items.length,typeof t.limit=="number"&&(o.items=o.items.slice(0,t.limit)),o}};var We=n=>typeof n=="undefined"||n===null?null:ci(n),ci=n=>typeof n=="boolean"?n?"1":"0":n+"",ur=n=>(n+"").replace(/&/g,"&").replace(//g,">").replace(/"/g,"""),qa=(n,e)=>e>0?window.setTimeout(n,e):(n.call(null),null),Ua=(n,e)=>{var t;return function(i,r){var o=this;t&&(o.loading=Math.max(o.loading-1,0),clearTimeout(t)),t=setTimeout(function(){t=null,o.loadedSearches[i]=!0,n.call(o,i,r)},e)}},Fo=(n,e,t)=>{var i,r=n.trigger,o={};n.trigger=function(){var s=arguments[0];if(e.indexOf(s)!==-1)o[s]=arguments;else return r.apply(n,arguments)},t.apply(n,[]),n.trigger=r;for(i of e)i in o&&r.apply(n,o[i])},Ya=n=>({start:n.selectionStart||0,length:(n.selectionEnd||0)-(n.selectionStart||0)}),fe=(n,e=!1)=>{n&&(n.preventDefault(),e&&n.stopPropagation())},Se=(n,e,t,i)=>{n.addEventListener(e,t,i)},Mt=(n,e)=>{if(!e||!e[n])return!1;var t=(e.altKey?1:0)+(e.ctrlKey?1:0)+(e.shiftKey?1:0)+(e.metaKey?1:0);return t===1},dr=(n,e)=>{let t=n.getAttribute("id");return t||(n.setAttribute("id",e),e)},$o=n=>n.replace(/[\\"']/g,"\\$&"),kt=(n,e)=>{e&&n.append(e)},ve=(n,e)=>{if(Array.isArray(n))n.forEach(e);else for(var t in n)n.hasOwnProperty(t)&&e(n[t],t)};var nt=n=>{if(n.jquery)return n[0];if(n instanceof HTMLElement)return n;if(Bo(n)){var e=document.createElement("template");return e.innerHTML=n.trim(),e.content.firstChild}return document.querySelector(n)},Bo=n=>typeof n=="string"&&n.indexOf("<")>-1,Ga=n=>n.replace(/['"\\]/g,"\\$&"),fr=(n,e)=>{var t=document.createEvent("HTMLEvents");t.initEvent(e,!0,!1),n.dispatchEvent(t)},ui=(n,e)=>{Object.assign(n.style,e)},Pe=(n,...e)=>{var t=Ka(e);n=Xa(n),n.map(i=>{t.map(r=>{i.classList.add(r)})})},gt=(n,...e)=>{var t=Ka(e);n=Xa(n),n.map(i=>{t.map(r=>{i.classList.remove(r)})})},Ka=n=>{var e=[];return ve(n,t=>{typeof t=="string"&&(t=t.trim().split(/[\t\n\f\r\s]/)),Array.isArray(t)&&(e=e.concat(t))}),e.filter(Boolean)},Xa=n=>(Array.isArray(n)||(n=[n]),n),hr=(n,e,t)=>{if(!(t&&!t.contains(n)))for(;n&&n.matches;){if(n.matches(e))return n;n=n.parentNode}},Vo=(n,e=0)=>e>0?n[n.length-1]:n[0],Qa=n=>Object.keys(n).length===0,zo=(n,e)=>{if(!n)return-1;e=e||n.nodeName;for(var t=0;n=n.previousElementSibling;)n.matches(e)&&t++;return t},le=(n,e)=>{ve(e,(t,i)=>{t==null?n.removeAttribute(i):n.setAttribute(i,""+t)})},di=(n,e)=>{n.parentNode&&n.parentNode.replaceChild(e,n)};var Ja=(n,e)=>{if(e===null)return;if(typeof e=="string"){if(!e.length)return;e=new RegExp(e,"i")}let t=o=>{var s=o.data.match(e);if(s&&o.data.length>0){var a=document.createElement("span");a.className="highlight";var l=o.splitText(s.index);l.splitText(s[0].length);var c=l.cloneNode(!0);return a.appendChild(c),di(l,a),1}return 0},i=o=>{o.nodeType===1&&o.childNodes&&!/(script|style)/i.test(o.tagName)&&(o.className!=="highlight"||o.tagName!=="SPAN")&&Array.from(o.childNodes).forEach(s=>{r(s)})},r=o=>o.nodeType===3?t(o):(i(o),0);r(n)},Za=n=>{var e=n.querySelectorAll("span.highlight");Array.prototype.forEach.call(e,function(t){var i=t.parentNode;i.replaceChild(t.firstChild,t),i.normalize()})};var dm=typeof navigator=="undefined"?!1:/Mac/.test(navigator.userAgent),fi=dm?"metaKey":"ctrlKey";var jo={options:[],optgroups:[],plugins:[],delimiter:",",splitOn:null,persist:!0,diacritics:!0,create:null,createOnBlur:!1,createFilter:null,highlight:!0,openOnFocus:!0,shouldOpen:null,maxOptions:50,maxItems:null,hideSelected:null,duplicates:!1,addPrecedence:!1,selectOnTab:!1,preload:null,allowEmptyOption:!1,refreshThrottle:300,loadThrottle:300,loadingClass:"loading",dataAttr:null,optgroupField:"optgroup",valueField:"value",labelField:"text",disabledField:"disabled",optgroupLabelField:"label",optgroupValueField:"value",lockOptgroupOrder:!1,sortField:"$order",searchField:["text"],searchConjunction:"and",mode:null,wrapperClass:"ts-wrapper",controlClass:"ts-control",dropdownClass:"ts-dropdown",dropdownContentClass:"ts-dropdown-content",itemClass:"item",optionClass:"option",dropdownParent:null,controlInput:'',copyClassesToDropdown:!1,placeholder:null,hidePlaceholder:null,shouldLoad:function(n){return n.length>0},render:{}};function pr(n,e){var t=Object.assign({},jo,e),i=t.dataAttr,r=t.labelField,o=t.valueField,s=t.disabledField,a=t.optgroupField,l=t.optgroupLabelField,c=t.optgroupValueField,u=n.tagName.toLowerCase(),d=n.getAttribute("placeholder")||n.getAttribute("data-placeholder");if(!d&&!t.allowEmptyOption){let v=n.querySelector('option[value=""]');v&&(d=v.textContent)}var p={placeholder:d,options:[],optgroups:[],items:[],maxItems:null},y=()=>{var v,w=p.options,T={},_=1;let S=0;var A=L=>{var H=Object.assign({},L.dataset),N=i&&H[i];return typeof N=="string"&&N.length&&(H=Object.assign(H,JSON.parse(N))),H},K=(L,H)=>{var N=We(L.value);if(N!=null&&!(!N&&!t.allowEmptyOption)){if(T.hasOwnProperty(N)){if(H){var Y=T[N][a];Y?Array.isArray(Y)?Y.push(H):T[N][a]=[Y,H]:T[N][a]=H}}else{var $=A(L);$[r]=$[r]||L.textContent,$[o]=$[o]||N,$[s]=$[s]||L.disabled,$[a]=$[a]||H,$.$option=L,$.$order=$.$order||++S,T[N]=$,w.push($)}L.selected&&p.items.push(N)}},z=L=>{var H,N;N=A(L),N[l]=N[l]||L.getAttribute("label")||"",N[c]=N[c]||_++,N[s]=N[s]||L.disabled,N.$order=N.$order||++S,p.optgroups.push(N),H=N[c],ve(L.children,Y=>{K(Y,H)})};p.maxItems=n.hasAttribute("multiple")?null:1,ve(n.children,L=>{v=L.tagName.toLowerCase(),v==="optgroup"?z(L):v==="option"&&K(L)})},m=()=>{let v=n.getAttribute(i);if(v)p.options=JSON.parse(v),ve(p.options,T=>{p.items.push(T[o])});else{var w=n.value.trim()||"";if(!t.allowEmptyOption&&!w.length)return;let T=w.split(t.delimiter);ve(T,_=>{let S={};S[r]=_,S[o]=_,p.options.push(S)}),p.items=T}};return u==="select"?y():m(),Object.assign({},jo,p,e)}var nl=0,_e=class extends No(oi){constructor(e,t){super(),this.order=0,this.isOpen=!1,this.isDisabled=!1,this.isReadOnly=!1,this.isInvalid=!1,this.isValid=!0,this.isLocked=!1,this.isFocused=!1,this.isInputHidden=!1,this.isSetup=!1,this.ignoreFocus=!1,this.ignoreHover=!1,this.hasOptions=!1,this.lastValue="",this.caretPos=0,this.loading=0,this.loadedSearches={},this.activeOption=null,this.activeItems=[],this.optgroups={},this.options={},this.userOptions={},this.items=[],this.refreshTimeout=null,nl++;var i,r=nt(e);if(r.tomselect)throw new Error("Tom Select already initialized on this element");r.tomselect=this;var o=window.getComputedStyle&&window.getComputedStyle(r,null);i=o.getPropertyValue("direction");let s=pr(r,t);this.settings=s,this.input=r,this.tabIndex=r.tabIndex||0,this.is_select_tag=r.tagName.toLowerCase()==="select",this.rtl=/rtl/i.test(i),this.inputId=dr(r,"tomselect-"+nl),this.isRequired=r.required,this.sifter=new cr(this.options,{diacritics:s.diacritics}),s.mode=s.mode||(s.maxItems===1?"single":"multi"),typeof s.hideSelected!="boolean"&&(s.hideSelected=s.mode==="multi"),typeof s.hidePlaceholder!="boolean"&&(s.hidePlaceholder=s.mode!=="multi");var a=s.createFilter;typeof a!="function"&&(typeof a=="string"&&(a=new RegExp(a)),a instanceof RegExp?s.createFilter=w=>a.test(w):s.createFilter=w=>this.settings.duplicates||!this.options[w]),this.initializePlugins(s.plugins),this.setupCallbacks(),this.setupTemplates();let l=nt("
"),c=nt("
"),u=this._render("dropdown"),d=nt('
'),p=this.input.getAttribute("class")||"",y=s.mode;var m;if(Pe(l,s.wrapperClass,p,y),Pe(c,s.controlClass),kt(l,c),Pe(u,s.dropdownClass,y),s.copyClassesToDropdown&&Pe(u,p),Pe(d,s.dropdownContentClass),kt(u,d),nt(s.dropdownParent||l).appendChild(u),Bo(s.controlInput)){m=nt(s.controlInput);var v=["autocorrect","autocapitalize","autocomplete","spellcheck"];ve(v,w=>{r.getAttribute(w)&&le(m,{[w]:r.getAttribute(w)})}),m.tabIndex=-1,c.appendChild(m),this.focus_node=m}else s.controlInput?(m=nt(s.controlInput),this.focus_node=m):(m=nt(""),this.focus_node=c);this.wrapper=l,this.dropdown=u,this.dropdown_content=d,this.control=c,this.control_input=m,this.setup()}setup(){let e=this,t=e.settings,i=e.control_input,r=e.dropdown,o=e.dropdown_content,s=e.wrapper,a=e.control,l=e.input,c=e.focus_node,u={passive:!0},d=e.inputId+"-ts-dropdown";le(o,{id:d}),le(c,{role:"combobox","aria-haspopup":"listbox","aria-expanded":"false","aria-controls":d});let p=dr(c,e.inputId+"-ts-control"),y="label[for='"+Ga(e.inputId)+"']",m=document.querySelector(y),v=e.focus.bind(e);if(m){Se(m,"click",v),le(m,{for:p});let _=dr(m,e.inputId+"-ts-label");le(c,{"aria-labelledby":_}),le(o,{"aria-labelledby":_})}if(s.style.width=l.style.width,e.plugins.names.length){let _="plugin-"+e.plugins.names.join(" plugin-");Pe([s,r],_)}(t.maxItems===null||t.maxItems>1)&&e.is_select_tag&&le(l,{multiple:"multiple"}),t.placeholder&&le(i,{placeholder:t.placeholder}),!t.splitOn&&t.delimiter&&(t.splitOn=new RegExp("\\s*"+Lt(t.delimiter)+"+\\s*")),t.load&&t.loadThrottle&&(t.load=Ua(t.load,t.loadThrottle)),Se(r,"mousemove",()=>{e.ignoreHover=!1}),Se(r,"mouseenter",_=>{var S=hr(_.target,"[data-selectable]",r);S&&e.onOptionHover(_,S)},{capture:!0}),Se(r,"click",_=>{let S=hr(_.target,"[data-selectable]");S&&(e.onOptionSelect(_,S),fe(_,!0))}),Se(a,"click",_=>{var S=hr(_.target,"[data-ts-item]",a);if(S&&e.onItemSelect(_,S)){fe(_,!0);return}i.value==""&&(e.onClick(),fe(_,!0))}),Se(c,"keydown",_=>e.onKeyDown(_)),Se(i,"keypress",_=>e.onKeyPress(_)),Se(i,"input",_=>e.onInput(_)),Se(c,"blur",_=>e.onBlur(_)),Se(c,"focus",_=>e.onFocus(_)),Se(i,"paste",_=>e.onPaste(_));let w=_=>{let S=_.composedPath()[0];if(!s.contains(S)&&!r.contains(S)){e.isFocused&&e.blur(),e.inputState();return}S==i&&e.isOpen?_.stopPropagation():fe(_,!0)},T=()=>{e.isOpen&&e.positionDropdown()};Se(document,"mousedown",w),Se(window,"scroll",T,u),Se(window,"resize",T,u),this._destroy=()=>{document.removeEventListener("mousedown",w),window.removeEventListener("scroll",T),window.removeEventListener("resize",T),m&&m.removeEventListener("click",v)},this.revertSettings={innerHTML:l.innerHTML,tabIndex:l.tabIndex},l.tabIndex=-1,l.insertAdjacentElement("afterend",e.wrapper),e.sync(!1),t.items=[],delete t.optgroups,delete t.options,Se(l,"invalid",()=>{e.isValid&&(e.isValid=!1,e.isInvalid=!0,e.refreshState())}),e.updateOriginalInput(),e.refreshItems(),e.close(!1),e.inputState(),e.isSetup=!0,l.disabled?e.disable():l.readOnly?e.setReadOnly(!0):e.enable(),e.on("change",this.onChange),Pe(l,"tomselected","ts-hidden-accessible"),e.trigger("initialize"),t.preload===!0&&e.preload()}setupOptions(e=[],t=[]){this.addOptions(e),ve(t,i=>{this.registerOptionGroup(i)})}setupTemplates(){var e=this,t=e.settings.labelField,i=e.settings.optgroupLabelField,r={optgroup:o=>{let s=document.createElement("div");return s.className="optgroup",s.appendChild(o.options),s},optgroup_header:(o,s)=>'
'+s(o[i])+"
",option:(o,s)=>"
"+s(o[t])+"
",item:(o,s)=>"
"+s(o[t])+"
",option_create:(o,s)=>'
Add '+s(o.input)+"
",no_results:()=>'
No results found
',loading:()=>'
',not_loading:()=>{},dropdown:()=>"
"};e.settings.render=Object.assign({},r,e.settings.render)}setupCallbacks(){var e,t,i={initialize:"onInitialize",change:"onChange",item_add:"onItemAdd",item_remove:"onItemRemove",item_select:"onItemSelect",clear:"onClear",option_add:"onOptionAdd",option_remove:"onOptionRemove",option_clear:"onOptionClear",optgroup_add:"onOptionGroupAdd",optgroup_remove:"onOptionGroupRemove",optgroup_clear:"onOptionGroupClear",dropdown_open:"onDropdownOpen",dropdown_close:"onDropdownClose",type:"onType",load:"onLoad",focus:"onFocus",blur:"onBlur"};for(e in i)t=this.settings[i[e]],t&&this.on(e,t)}sync(e=!0){let t=this,i=e?pr(t.input,{delimiter:t.settings.delimiter}):t.settings;t.setupOptions(i.options,i.optgroups),t.setValue(i.items||[],!0),t.lastQuery=null}onClick(){var e=this;if(e.activeItems.length>0){e.clearActiveItems(),e.focus();return}e.isFocused&&e.isOpen?e.blur():e.focus()}onMouseDown(){}onChange(){fr(this.input,"input"),fr(this.input,"change")}onPaste(e){var t=this;if(t.isInputHidden||t.isLocked){fe(e);return}t.settings.splitOn&&setTimeout(()=>{var i=t.inputValue();if(i.match(t.settings.splitOn)){var r=i.trim().split(t.settings.splitOn);ve(r,o=>{We(o)&&(this.options[o]?t.addItem(o):t.createItem(o))})}},0)}onKeyPress(e){var t=this;if(t.isLocked){fe(e);return}var i=String.fromCharCode(e.keyCode||e.which);if(t.settings.create&&t.settings.mode==="multi"&&i===t.settings.delimiter){t.createItem(),fe(e);return}}onKeyDown(e){var t=this;if(t.ignoreHover=!0,t.isLocked){e.keyCode!==9&&fe(e);return}switch(e.keyCode){case 65:if(Mt(fi,e)&&t.control_input.value==""){fe(e),t.selectAll();return}break;case 27:t.isOpen&&(fe(e,!0),t.close()),t.clearActiveItems();return;case 40:if(!t.isOpen&&t.hasOptions)t.open();else if(t.activeOption){let i=t.getAdjacent(t.activeOption,1);i&&t.setActiveOption(i)}fe(e);return;case 38:if(t.activeOption){let i=t.getAdjacent(t.activeOption,-1);i&&t.setActiveOption(i)}fe(e);return;case 13:t.canSelect(t.activeOption)?(t.onOptionSelect(e,t.activeOption),fe(e)):t.settings.create&&t.createItem()?fe(e):document.activeElement==t.control_input&&t.isOpen&&fe(e);return;case 37:t.advanceSelection(-1,e);return;case 39:t.advanceSelection(1,e);return;case 9:t.settings.selectOnTab&&(t.canSelect(t.activeOption)&&(t.onOptionSelect(e,t.activeOption),fe(e)),t.settings.create&&t.createItem()&&fe(e));return;case 8:case 46:t.deleteSelection(e);return}t.isInputHidden&&!Mt(fi,e)&&fe(e)}onInput(e){if(this.isLocked)return;let t=this.inputValue();if(this.lastValue!==t){if(this.lastValue=t,t==""){this._onInput();return}this.refreshTimeout&&window.clearTimeout(this.refreshTimeout),this.refreshTimeout=qa(()=>{this.refreshTimeout=null,this._onInput()},this.settings.refreshThrottle)}}_onInput(){let e=this.lastValue;this.settings.shouldLoad.call(this,e)&&this.load(e),this.refreshOptions(),this.trigger("type",e)}onOptionHover(e,t){this.ignoreHover||this.setActiveOption(t,!1)}onFocus(e){var t=this,i=t.isFocused;if(t.isDisabled||t.isReadOnly){t.blur(),fe(e);return}t.ignoreFocus||(t.isFocused=!0,t.settings.preload==="focus"&&t.preload(),i||t.trigger("focus"),t.activeItems.length||(t.inputState(),t.refreshOptions(!!t.settings.openOnFocus)),t.refreshState())}onBlur(e){if(document.hasFocus()!==!1){var t=this;if(t.isFocused){t.isFocused=!1,t.ignoreFocus=!1;var i=()=>{t.close(),t.setActiveItem(),t.setCaret(t.items.length),t.trigger("blur")};t.settings.create&&t.settings.createOnBlur?t.createItem(null,i):i()}}}onOptionSelect(e,t){var i,r=this;t.parentElement&&t.parentElement.matches("[data-disabled]")||(t.classList.contains("create")?r.createItem(null,()=>{r.settings.closeAfterSelect&&r.close()}):(i=t.dataset.value,typeof i!="undefined"&&(r.lastQuery=null,r.addItem(i),r.settings.closeAfterSelect&&r.close(),!r.settings.hideSelected&&e.type&&/click/.test(e.type)&&r.setActiveOption(t))))}canSelect(e){return!!(this.isOpen&&e&&this.dropdown_content.contains(e))}onItemSelect(e,t){var i=this;return!i.isLocked&&i.settings.mode==="multi"?(fe(e),i.setActiveItem(t,e),!0):!1}canLoad(e){return!(!this.settings.load||this.loadedSearches.hasOwnProperty(e))}load(e){let t=this;if(!t.canLoad(e))return;Pe(t.wrapper,t.settings.loadingClass),t.loading++;let i=t.loadCallback.bind(t);t.settings.load.call(t,e,i)}loadCallback(e,t){let i=this;i.loading=Math.max(i.loading-1,0),i.lastQuery=null,i.clearActiveOption(),i.setupOptions(e,t),i.refreshOptions(i.isFocused&&!i.isInputHidden),i.loading||gt(i.wrapper,i.settings.loadingClass),i.trigger("load",e,t)}preload(){var e=this.wrapper.classList;e.contains("preloaded")||(e.add("preloaded"),this.load(""))}setTextboxValue(e=""){var t=this.control_input,i=t.value!==e;i&&(t.value=e,fr(t,"update"),this.lastValue=e)}getValue(){return this.is_select_tag&&this.input.hasAttribute("multiple")?this.items:this.items.join(this.settings.delimiter)}setValue(e,t){var i=t?[]:["change"];Fo(this,i,()=>{this.clear(t),this.addItems(e,t)})}setMaxItems(e){e===0&&(e=null),this.settings.maxItems=e,this.refreshState()}setActiveItem(e,t){var i=this,r,o,s,a,l,c;if(i.settings.mode!=="single"){if(!e){i.clearActiveItems(),i.isFocused&&i.inputState();return}if(r=t&&t.type.toLowerCase(),r==="click"&&Mt("shiftKey",t)&&i.activeItems.length){for(c=i.getLastActive(),s=Array.prototype.indexOf.call(i.control.children,c),a=Array.prototype.indexOf.call(i.control.children,e),s>a&&(l=s,s=a,a=l),o=s;o<=a;o++)e=i.control.children[o],i.activeItems.indexOf(e)===-1&&i.setActiveItemClass(e);fe(t)}else r==="click"&&Mt(fi,t)||r==="keydown"&&Mt("shiftKey",t)?e.classList.contains("active")?i.removeActiveItem(e):i.setActiveItemClass(e):(i.clearActiveItems(),i.setActiveItemClass(e));i.inputState(),i.isFocused||i.focus()}}setActiveItemClass(e){let t=this,i=t.control.querySelector(".last-active");i&>(i,"last-active"),Pe(e,"active last-active"),t.trigger("item_select",e),t.activeItems.indexOf(e)==-1&&t.activeItems.push(e)}removeActiveItem(e){var t=this.activeItems.indexOf(e);this.activeItems.splice(t,1),gt(e,"active")}clearActiveItems(){gt(this.activeItems,"active"),this.activeItems=[]}setActiveOption(e,t=!0){e!==this.activeOption&&(this.clearActiveOption(),e&&(this.activeOption=e,le(this.focus_node,{"aria-activedescendant":e.getAttribute("id")}),le(e,{"aria-selected":"true"}),Pe(e,"active"),t&&this.scrollToOption(e)))}scrollToOption(e,t){if(!e)return;let i=this.dropdown_content,r=i.clientHeight,o=i.scrollTop||0,s=e.offsetHeight,a=e.getBoundingClientRect().top-i.getBoundingClientRect().top+o;a+s>r+o?this.scroll(a-r+s,t):a{e.setActiveItemClass(i)}))}inputState(){var e=this;e.control.contains(e.control_input)&&(le(e.control_input,{placeholder:e.settings.placeholder}),e.activeItems.length>0||!e.isFocused&&e.settings.hidePlaceholder&&e.items.length>0?(e.setTextboxValue(),e.isInputHidden=!0):(e.settings.hidePlaceholder&&e.items.length>0&&le(e.control_input,{placeholder:""}),e.isInputHidden=!1),e.wrapper.classList.toggle("input-hidden",e.isInputHidden))}inputValue(){return this.control_input.value.trim()}focus(){var e=this;e.isDisabled||e.isReadOnly||(e.ignoreFocus=!0,e.control_input.offsetWidth?e.control_input.focus():e.focus_node.focus(),setTimeout(()=>{e.ignoreFocus=!1,e.onFocus()},0))}blur(){this.focus_node.blur(),this.onBlur()}getScoreFunction(e){return this.sifter.getScoreFunction(e,this.getSearchOptions())}getSearchOptions(){var e=this.settings,t=e.sortField;return typeof e.sortField=="string"&&(t=[{field:e.sortField}]),{fields:e.searchField,conjunction:e.searchConjunction,sort:t,nesting:e.nesting}}search(e){var t,i,r=this,o=this.getSearchOptions();if(r.settings.score&&(i=r.settings.score.call(r,e),typeof i!="function"))throw new Error('Tom Select "score" setting must be a function that returns a function');return e!==r.lastQuery?(r.lastQuery=e,t=r.sifter.search(e,Object.assign(o,{score:i})),r.currentResults=t):t=Object.assign({},r.currentResults),r.settings.hideSelected&&(t.items=t.items.filter(s=>{let a=We(s.id);return!(a&&r.items.indexOf(a)!==-1)})),t}refreshOptions(e=!0){var t,i,r,o,s,a,l,c,u,d;let p={},y=[];var m=this,v=m.inputValue();let w=v===m.lastQuery||v==""&&m.lastQuery==null;var T=m.search(v),_=null,S=m.settings.shouldOpen||!1,A=m.dropdown_content;w&&(_=m.activeOption,_&&(u=_.closest("[data-group]"))),o=T.items.length,typeof m.settings.maxOptions=="number"&&(o=Math.min(o,m.settings.maxOptions)),o>0&&(S=!0);let K=(L,H)=>{let N=p[L];if(N!==void 0){let $=y[N];if($!==void 0)return[N,$.fragment]}let Y=document.createDocumentFragment();return N=y.length,y.push({fragment:Y,order:H,optgroup:L}),[N,Y]};for(t=0;t0&&($=$.cloneNode(!0),le($,{id:N.$id+"-clone-"+i,"aria-selected":null}),$.classList.add("ts-cloned"),gt($,"active"),m.activeOption&&m.activeOption.dataset.value==H&&u&&u.dataset.group===s.toString()&&(_=$)),Ce.appendChild($),s!=""&&(p[s]=Te)}}m.settings.lockOptgroupOrder&&y.sort((L,H)=>L.order-H.order),l=document.createDocumentFragment(),ve(y,L=>{let H=L.fragment,N=L.optgroup;if(!H||!H.children.length)return;let Y=m.optgroups[N];if(Y!==void 0){let $=document.createDocumentFragment(),ie=m.render("optgroup_header",Y);kt($,ie),kt($,H);let J=m.render("optgroup",{group:Y,options:$});kt(l,J)}else kt(l,H)}),A.innerHTML="",kt(A,l),m.settings.highlight&&(Za(A),T.query.length&&T.tokens.length&&ve(T.tokens,L=>{Ja(A,L.regex)}));var z=L=>{let H=m.render(L,{input:v});return H&&(S=!0,A.insertBefore(H,A.firstChild)),H};if(m.loading?z("loading"):m.settings.shouldLoad.call(m,v)?T.items.length===0&&z("no_results"):z("not_loading"),c=m.canCreate(v),c&&(d=z("option_create")),m.hasOptions=T.items.length>0||c,S){if(T.items.length>0){if(!_&&m.settings.mode==="single"&&m.items[0]!=null&&(_=m.getOption(m.items[0])),!A.contains(_)){let L=0;d&&!m.settings.addPrecedence&&(L=1),_=m.selectable()[L]}}else d&&(_=d);e&&!m.isOpen&&(m.open(),m.scrollToOption(_,"auto")),m.setActiveOption(_)}else m.clearActiveOption(),e&&m.isOpen&&m.close(!1)}selectable(){return this.dropdown_content.querySelectorAll("[data-selectable]")}addOption(e,t=!1){let i=this;if(Array.isArray(e))return i.addOptions(e,t),!1;let r=We(e[i.settings.valueField]);return r===null||i.options.hasOwnProperty(r)?!1:(e.$order=e.$order||++i.order,e.$id=i.inputId+"-opt-"+e.$order,i.options[r]=e,i.lastQuery=null,t&&(i.userOptions[r]=t,i.trigger("option_add",r,e)),r)}addOptions(e,t=!1){ve(e,i=>{this.addOption(i,t)})}registerOption(e){return this.addOption(e)}registerOptionGroup(e){var t=We(e[this.settings.optgroupValueField]);return t===null?!1:(e.$order=e.$order||++this.order,this.optgroups[t]=e,t)}addOptionGroup(e,t){var i;t[this.settings.optgroupValueField]=e,(i=this.registerOptionGroup(t))&&this.trigger("optgroup_add",i,t)}removeOptionGroup(e){this.optgroups.hasOwnProperty(e)&&(delete this.optgroups[e],this.clearCache(),this.trigger("optgroup_remove",e))}clearOptionGroups(){this.optgroups={},this.clearCache(),this.trigger("optgroup_clear")}updateOption(e,t){let i=this;var r,o;let s=We(e),a=We(t[i.settings.valueField]);if(s===null)return;let l=i.options[s];if(l==null)return;if(typeof a!="string")throw new Error("Value must be set in option data");let c=i.getOption(s),u=i.getItem(s);if(t.$order=t.$order||l.$order,delete i.options[s],i.uncacheValue(a),i.options[a]=t,c){if(i.dropdown_content.contains(c)){let d=i._render("option",t);di(c,d),i.activeOption===c&&i.setActiveOption(d)}c.remove()}u&&(o=i.items.indexOf(s),o!==-1&&i.items.splice(o,1,a),r=i._render("item",t),u.classList.contains("active")&&Pe(r,"active"),di(u,r)),i.lastQuery=null}removeOption(e,t){let i=this;e=ci(e),i.uncacheValue(e),delete i.userOptions[e],delete i.options[e],i.lastQuery=null,i.trigger("option_remove",e),i.removeItem(e,t)}clearOptions(e){let t=(e||this.clearFilter).bind(this);this.loadedSearches={},this.userOptions={},this.clearCache();let i={};ve(this.options,(r,o)=>{t(r,o)&&(i[o]=r)}),this.options=this.sifter.items=i,this.lastQuery=null,this.trigger("option_clear")}clearFilter(e,t){return this.items.indexOf(t)>=0}getOption(e,t=!1){let i=We(e);if(i===null)return null;let r=this.options[i];if(r!=null){if(r.$div)return r.$div;if(t)return this._render("option",r)}return null}getAdjacent(e,t,i="option"){var r=this,o;if(!e)return null;i=="item"?o=r.controlChildren():o=r.dropdown_content.querySelectorAll("[data-selectable]");for(let s=0;s0?o[s+1]:o[s-1];return null}getItem(e){if(typeof e=="object")return e;var t=We(e);return t!==null?this.control.querySelector(`[data-value="${$o(t)}"]`):null}addItems(e,t){var i=this,r=Array.isArray(e)?e:[e];r=r.filter(s=>i.items.indexOf(s)===-1);let o=r[r.length-1];r.forEach(s=>{i.isPending=s!==o,i.addItem(s,t)})}addItem(e,t){var i=t?[]:["change","dropdown_close"];Fo(this,i,()=>{var r,o;let s=this,a=s.settings.mode,l=We(e);if(!(l&&s.items.indexOf(l)!==-1&&(a==="single"&&s.close(),a==="single"||!s.settings.duplicates))&&!(l===null||!s.options.hasOwnProperty(l))&&(a==="single"&&s.clear(t),!(a==="multi"&&s.isFull()))){if(r=s._render("item",s.options[l]),s.control.contains(r)&&(r=r.cloneNode(!0)),o=s.isFull(),s.items.splice(s.caretPos,0,l),s.insertAtCaret(r),s.isSetup){if(!s.isPending&&s.settings.hideSelected){let c=s.getOption(l),u=s.getAdjacent(c,1);u&&s.setActiveOption(u)}!s.isPending&&!s.settings.closeAfterSelect&&s.refreshOptions(s.isFocused&&a!=="single"),s.settings.closeAfterSelect!=!1&&s.isFull()?s.close():s.isPending||s.positionDropdown(),s.trigger("item_add",l,r),s.isPending||s.updateOriginalInput({silent:t})}(!s.isPending||!o&&s.isFull())&&(s.inputState(),s.refreshState())}})}removeItem(e=null,t){let i=this;if(e=i.getItem(e),!e)return;var r,o;let s=e.dataset.value;r=zo(e),e.remove(),e.classList.contains("active")&&(o=i.activeItems.indexOf(e),i.activeItems.splice(o,1),gt(e,"active")),i.items.splice(r,1),i.lastQuery=null,!i.settings.persist&&i.userOptions.hasOwnProperty(s)&&i.removeOption(s,t),r{}){arguments.length===3&&(t=arguments[2]),typeof t!="function"&&(t=()=>{});var i=this,r=i.caretPos,o;if(e=e||i.inputValue(),!i.canCreate(e))return t(),!1;i.lock();var s=!1,a=l=>{if(i.unlock(),!l||typeof l!="object")return t();var c=We(l[i.settings.valueField]);if(typeof c!="string")return t();i.setTextboxValue(),i.addOption(l,!0),i.setCaret(r),i.addItem(c),t(l),s=!0};return typeof i.settings.create=="function"?o=i.settings.create.call(this,e,a):o={[i.settings.labelField]:e,[i.settings.valueField]:e},s||a(o),!0}refreshItems(){var e=this;e.lastQuery=null,e.isSetup&&e.addItems(e.items),e.updateOriginalInput(),e.refreshState()}refreshState(){let e=this;e.refreshValidityState();let t=e.isFull(),i=e.isLocked;e.wrapper.classList.toggle("rtl",e.rtl);let r=e.wrapper.classList;r.toggle("focus",e.isFocused),r.toggle("disabled",e.isDisabled),r.toggle("readonly",e.isReadOnly),r.toggle("required",e.isRequired),r.toggle("invalid",!e.isValid),r.toggle("locked",i),r.toggle("full",t),r.toggle("input-active",e.isFocused&&!e.isInputHidden),r.toggle("dropdown-active",e.isOpen),r.toggle("has-options",Qa(e.options)),r.toggle("has-items",e.items.length>0)}refreshValidityState(){var e=this;e.input.validity&&(e.isValid=e.input.validity.valid,e.isInvalid=!e.isValid)}isFull(){return this.settings.maxItems!==null&&this.items.length>=this.settings.maxItems}updateOriginalInput(e={}){let t=this;var i,r;let o=t.input.querySelector('option[value=""]');if(t.is_select_tag){let l=function(c,u,d){return c||(c=nt('")),c!=o&&t.input.append(c),s.push(c),(c!=o||a>0)&&(c.selected=!0),c},s=[],a=t.input.querySelectorAll("option:checked").length;t.input.querySelectorAll("option:checked").forEach(c=>{c.selected=!1}),t.items.length==0&&t.settings.mode=="single"?l(o,"",""):t.items.forEach(c=>{if(i=t.options[c],r=i[t.settings.labelField]||"",s.includes(i.$option)){let u=t.input.querySelector(`option[value="${$o(c)}"]:not(:checked)`);l(u,c,r)}else i.$option=l(i.$option,c,r)})}else t.input.value=t.getValue();t.isSetup&&(e.silent||t.trigger("change",t.getValue()))}open(){var e=this;e.isLocked||e.isOpen||e.settings.mode==="multi"&&e.isFull()||(e.isOpen=!0,le(e.focus_node,{"aria-expanded":"true"}),e.refreshState(),ui(e.dropdown,{visibility:"hidden",display:"block"}),e.positionDropdown(),ui(e.dropdown,{visibility:"visible",display:"block"}),e.focus(),e.trigger("dropdown_open",e.dropdown))}close(e=!0){var t=this,i=t.isOpen;e&&(t.setTextboxValue(),t.settings.mode==="single"&&t.items.length&&t.inputState()),t.isOpen=!1,le(t.focus_node,{"aria-expanded":"false"}),ui(t.dropdown,{display:"none"}),t.settings.hideSelected&&t.clearActiveOption(),t.refreshState(),i&&t.trigger("dropdown_close",t.dropdown)}positionDropdown(){if(this.settings.dropdownParent==="body"){var e=this.control,t=e.getBoundingClientRect(),i=e.offsetHeight+t.top+window.scrollY,r=t.left+window.scrollX;ui(this.dropdown,{width:t.width+"px",top:i+"px",left:r+"px"})}}clear(e){var t=this;if(t.items.length){var i=t.controlChildren();ve(i,r=>{t.removeItem(r,!0)}),t.inputState(),e||t.updateOriginalInput(),t.trigger("clear")}}insertAtCaret(e){let t=this,i=t.caretPos,r=t.control;r.insertBefore(e,r.children[i]||null),t.setCaret(i+1)}deleteSelection(e){var t,i,r,o,s=this;t=e&&e.keyCode===8?-1:1,i=Ya(s.control_input);let a=[];if(s.activeItems.length)o=Vo(s.activeItems,t),r=zo(o),t>0&&r++,ve(s.activeItems,l=>a.push(l));else if((s.isFocused||s.settings.mode==="single")&&s.items.length){let l=s.controlChildren(),c;t<0&&i.start===0&&i.length===0?c=l[s.caretPos-1]:t>0&&i.start===s.inputValue().length&&(c=l[s.caretPos]),c!==void 0&&a.push(c)}if(!s.shouldDelete(a,e))return!1;for(fe(e,!0),typeof r!="undefined"&&s.setCaret(r);a.length;)s.removeItem(a.pop());return s.inputState(),s.positionDropdown(),s.refreshOptions(!1),!0}shouldDelete(e,t){let i=e.map(r=>r.dataset.value);return!(!i.length||typeof this.settings.onDelete=="function"&&this.settings.onDelete(i,t)===!1)}advanceSelection(e,t){var i,r,o=this;o.rtl&&(e*=-1),!o.inputValue().length&&(Mt(fi,t)||Mt("shiftKey",t)?(i=o.getLastActive(e),i?i.classList.contains("active")?r=o.getAdjacent(i,e,"item"):r=i:e>0?r=o.control_input.nextElementSibling:r=o.control_input.previousElementSibling,r&&(r.classList.contains("active")&&o.removeActiveItem(i),o.setActiveItemClass(r))):o.moveCaret(e))}moveCaret(e){}getLastActive(e){let t=this.control.querySelector(".last-active");if(t)return t;var i=this.control.querySelectorAll(".active");if(i)return Vo(i,e)}setCaret(e){this.caretPos=this.items.length}controlChildren(){return Array.from(this.control.querySelectorAll("[data-ts-item]"))}lock(){this.setLocked(!0)}unlock(){this.setLocked(!1)}setLocked(e=this.isReadOnly||this.isDisabled){this.isLocked=e,this.refreshState()}disable(){this.setDisabled(!0),this.close()}enable(){this.setDisabled(!1)}setDisabled(e){this.focus_node.tabIndex=e?-1:this.tabIndex,this.isDisabled=e,this.input.disabled=e,this.control_input.disabled=e,this.setLocked()}setReadOnly(e){this.isReadOnly=e,this.input.readOnly=e,this.control_input.readOnly=e,this.setLocked()}destroy(){var e=this,t=e.revertSettings;e.trigger("destroy"),e.off(),e.wrapper.remove(),e.dropdown.remove(),e.input.innerHTML=t.innerHTML,e.input.tabIndex=t.tabIndex,gt(e.input,"tomselected","ts-hidden-accessible"),e._destroy(),delete e.input.tomselect}render(e,t){var i,r;let o=this;if(typeof this.settings.render[e]!="function"||(r=o.settings.render[e].call(this,t,ur),!r))return null;if(r=nt(r),e==="option"||e==="option_create"?t[o.settings.disabledField]?le(r,{"aria-disabled":"true"}):le(r,{"data-selectable":""}):e==="optgroup"&&(i=t.group[o.settings.optgroupValueField],le(r,{"data-group":i}),t.group[o.settings.disabledField]&&le(r,{"data-disabled":""})),e==="option"||e==="item"){let s=ci(t[o.settings.valueField]);le(r,{"data-value":s}),e==="item"?(Pe(r,o.settings.itemClass),le(r,{"data-ts-item":""})):(Pe(r,o.settings.optionClass),le(r,{role:"option",id:t.$id}),t.$div=r,o.options[s]=t)}return r}_render(e,t){let i=this.render(e,t);if(i==null)throw"HTMLElement expected";return i}clearCache(){ve(this.options,e=>{e.$div&&(e.$div.remove(),delete e.$div)})}uncacheValue(e){let t=this.getOption(e);t&&t.remove()}canCreate(e){return this.settings.create&&e.length>0&&this.settings.createFilter.call(this,e)}hook(e,t,i){var r=this,o=r[t];r[t]=function(){var s,a;return e==="after"&&(s=o.apply(r,arguments)),a=i.apply(r,arguments),e==="instead"?a:(e==="before"&&(s=o.apply(r,arguments)),s)}}};var _m=(n,e,t,i)=>{n.addEventListener(e,t,i)};function il(){_m(this.input,"change",()=>{this.sync()})}var wm=n=>typeof n=="undefined"||n===null?null:xm(n),xm=n=>typeof n=="boolean"?n?"1":"0":n+"",rl=(n,e=!1)=>{n&&(n.preventDefault(),e&&n.stopPropagation())},Tm=n=>{if(n.jquery)return n[0];if(n instanceof HTMLElement)return n;if(Cm(n)){var e=document.createElement("template");return e.innerHTML=n.trim(),e.content.firstChild}return document.querySelector(n)},Cm=n=>typeof n=="string"&&n.indexOf("<")>-1;function ol(n){var e=this,t=e.onOptionSelect;e.settings.hideSelected=!1;let i=Object.assign({className:"tomselect-checkbox",checkedClassNames:void 0,uncheckedClassNames:void 0},n);var r=function(a,l){l?(a.checked=!0,i.uncheckedClassNames&&a.classList.remove(...i.uncheckedClassNames),i.checkedClassNames&&a.classList.add(...i.checkedClassNames)):(a.checked=!1,i.checkedClassNames&&a.classList.remove(...i.checkedClassNames),i.uncheckedClassNames&&a.classList.add(...i.uncheckedClassNames))},o=function(a){setTimeout(()=>{var l=a.querySelector("input."+i.className);l instanceof HTMLInputElement&&r(l,a.classList.contains("selected"))},1)};e.hook("after","setupTemplates",()=>{var s=e.settings.render.option;e.settings.render.option=(a,l)=>{var c=Tm(s.call(e,a,l)),u=document.createElement("input");i.className&&u.classList.add(i.className),u.addEventListener("click",function(p){rl(p)}),u.type="checkbox";let d=wm(a[e.settings.valueField]);return r(u,!!(d&&e.items.indexOf(d)>-1)),c.prepend(u),c}}),e.on("item_remove",s=>{var a=e.getOption(s);a&&(a.classList.remove("selected"),o(a))}),e.on("item_add",s=>{var a=e.getOption(s);a&&o(a)}),e.hook("instead","onOptionSelect",(s,a)=>{if(a.classList.contains("selected")){a.classList.remove("selected"),e.removeItem(a.dataset.value),e.refreshOptions(),rl(s,!0);return}t.call(e,s,a),o(a)})}var Am=n=>{if(n.jquery)return n[0];if(n instanceof HTMLElement)return n;if(Sm(n)){var e=document.createElement("template");return e.innerHTML=n.trim(),e.content.firstChild}return document.querySelector(n)},Sm=n=>typeof n=="string"&&n.indexOf("<")>-1;function sl(n){let e=this,t=Object.assign({className:"clear-button",title:"Clear All",html:i=>`
`},n);e.on("initialize",()=>{var i=Am(t.html(t));i.addEventListener("click",r=>{e.isLocked||(e.clear(),e.settings.mode==="single"&&e.settings.allowEmptyOption&&e.addItem(""),r.preventDefault(),r.stopPropagation())}),e.control.appendChild(i)})}var Dm=(n,e=!1)=>{n&&(n.preventDefault(),e&&n.stopPropagation())},Dn=(n,e,t,i)=>{n.addEventListener(e,t,i)},Om=(n,e)=>{if(Array.isArray(n))n.forEach(e);else for(var t in n)n.hasOwnProperty(t)&&e(n[t],t)},Lm=n=>{if(n.jquery)return n[0];if(n instanceof HTMLElement)return n;if(Mm(n)){var e=document.createElement("template");return e.innerHTML=n.trim(),e.content.firstChild}return document.querySelector(n)},Mm=n=>typeof n=="string"&&n.indexOf("<")>-1,km=(n,e)=>{Om(e,(t,i)=>{t==null?n.removeAttribute(i):n.setAttribute(i,""+t)})},Nm=(n,e)=>{var t;(t=n.parentNode)==null||t.insertBefore(e,n.nextSibling)},Im=(n,e)=>{var t;(t=n.parentNode)==null||t.insertBefore(e,n)},Rm=(n,e)=>{do{var t;if(e=(t=e)==null?void 0:t.previousElementSibling,n==e)return!0}while(e&&e.previousElementSibling);return!1};function al(){var n=this;if(n.settings.mode!=="multi")return;var e=n.lock,t=n.unlock;let i=!0,r;n.hook("after","setupTemplates",()=>{var o=n.settings.render.item;n.settings.render.item=(s,a)=>{let l=Lm(o.call(n,s,a));km(l,{draggable:"true"});let c=v=>{i||Dm(v),v.stopPropagation()},u=v=>{r=l,setTimeout(()=>{l.classList.add("ts-dragging")},0)},d=v=>{v.preventDefault(),l.classList.add("ts-drag-over"),y(l,r)},p=()=>{l.classList.remove("ts-drag-over")},y=(v,w)=>{w!==void 0&&(Rm(w,l)?Nm(v,w):Im(v,w))},m=()=>{var v;document.querySelectorAll(".ts-drag-over").forEach(T=>T.classList.remove("ts-drag-over")),(v=r)==null||v.classList.remove("ts-dragging"),r=void 0;var w=[];n.control.querySelectorAll("[data-value]").forEach(T=>{if(T.dataset.value){let _=T.dataset.value;_&&w.push(_)}}),n.setValue(w)};return Dn(l,"mousedown",c),Dn(l,"dragstart",u),Dn(l,"dragenter",d),Dn(l,"dragover",d),Dn(l,"dragleave",p),Dn(l,"dragend",m),l}}),n.hook("instead","lock",()=>(i=!1,e.call(n))),n.hook("instead","unlock",()=>(i=!0,t.call(n)))}var Hm=(n,e=!1)=>{n&&(n.preventDefault(),e&&n.stopPropagation())},Pm=n=>{if(n.jquery)return n[0];if(n instanceof HTMLElement)return n;if(Fm(n)){var e=document.createElement("template");return e.innerHTML=n.trim(),e.content.firstChild}return document.querySelector(n)},Fm=n=>typeof n=="string"&&n.indexOf("<")>-1;function ll(n){let e=this,t=Object.assign({title:"Untitled",headerClass:"dropdown-header",titleRowClass:"dropdown-header-title",labelClass:"dropdown-header-label",closeClass:"dropdown-header-close",html:i=>'
'+i.title+'×
'},n);e.on("initialize",()=>{var i=Pm(t.html(t)),r=i.querySelector("."+t.closeClass);r&&r.addEventListener("click",o=>{Hm(o,!0),e.close()}),e.dropdown.insertBefore(i,e.dropdown.firstChild)})}var $m=(n,e)=>{if(Array.isArray(n))n.forEach(e);else for(var t in n)n.hasOwnProperty(t)&&e(n[t],t)},Bm=(n,...e)=>{var t=Vm(e);n=zm(n),n.map(i=>{t.map(r=>{i.classList.remove(r)})})},Vm=n=>{var e=[];return $m(n,t=>{typeof t=="string"&&(t=t.trim().split(/[\t\n\f\r\s]/)),Array.isArray(t)&&(e=e.concat(t))}),e.filter(Boolean)},zm=n=>(Array.isArray(n)||(n=[n]),n),jm=(n,e)=>{if(!n)return-1;e=e||n.nodeName;for(var t=0;n=n.previousElementSibling;)n.matches(e)&&t++;return t};function cl(){var n=this;n.hook("instead","setCaret",e=>{n.settings.mode==="single"||!n.control.contains(n.control_input)?e=n.items.length:(e=Math.max(0,Math.min(n.items.length,e)),e!=n.caretPos&&!n.isPending&&n.controlChildren().forEach((t,i)=>{i{if(!n.isFocused)return;let t=n.getLastActive(e);if(t){let i=jm(t);n.setCaret(e>0?i+1:i),n.setActiveItem(),Bm(t,"last-active")}else n.setCaret(n.caretPos+e)})}var Wm=(n,e=!1)=>{n&&(n.preventDefault(),e&&n.stopPropagation())},qm=(n,e,t,i)=>{n.addEventListener(e,t,i)},Um=(n,e)=>{if(Array.isArray(n))n.forEach(e);else for(var t in n)n.hasOwnProperty(t)&&e(n[t],t)},ul=n=>{if(n.jquery)return n[0];if(n instanceof HTMLElement)return n;if(Ym(n)){var e=document.createElement("template");return e.innerHTML=n.trim(),e.content.firstChild}return document.querySelector(n)},Ym=n=>typeof n=="string"&&n.indexOf("<")>-1,Gm=(n,...e)=>{var t=Km(e);n=Xm(n),n.map(i=>{t.map(r=>{i.classList.add(r)})})},Km=n=>{var e=[];return Um(n,t=>{typeof t=="string"&&(t=t.trim().split(/[\t\n\f\r\s]/)),Array.isArray(t)&&(e=e.concat(t))}),e.filter(Boolean)},Xm=n=>(Array.isArray(n)||(n=[n]),n);function dl(){let n=this;n.settings.shouldOpen=!0,n.hook("before","setup",()=>{n.focus_node=n.control,Gm(n.control_input,"dropdown-input");let e=ul('