1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

9856 Replace graphene with Strawberry (#15141)

* 9856 base strawberry integration

* 9856 user and group

* 9856 user and circuits base

* 9856 extras and mixins

* 9856 fk

* 9856 update strawberry version

* 9856 update imports

* 9856 compatability fixes

* 9856 compatability fixes

* 9856 update strawberry types

* 9856 update strawberry types

* 9856 core schema

* 9856 dcim schema

* 9856 extras schema

* 9856 ipam and tenant schema

* 9856 virtualization, vpn, wireless schema

* 9856 fix old decorator

* 9856 cleanup

* 9856 cleanup

* 9856 fixes to circuits type specifiers

* 9856 fixes to circuits type specifiers

* 9856 update types

* 9856 GFK working

* 9856 GFK working

* 9856 _name

* 9856 misc fixes

* 9856 type updates

* 9856 _name to types

* 9856 update types

* 9856 update types

* 9856 update types

* 9856 update types

* 9856 update types

* 9856 update types

* 9856 update types

* 9856 update types

* 9856 update types

* 9856 GraphQLView

* 9856 GraphQLView

* 9856 fix OrganizationalObjectType

* 9856 single item query for schema

* 9856 circuits graphql tests working

* 9856 test fixes

* 9856 test fixes

* 9856 test fixes

* 9856 test fix vpn

* 9856 test fixes

* 9856 test fixes

* 9856 test fixes

* 9856 circuits test sans DjangoModelType

* 9856 core test sans DjangoModelType

* 9856 temp checkin

* 9856 fix extas FK

* 9856 fix tenancy FK

* 9856 fix virtualization FK

* 9856 fix vpn FK

* 9856 fix wireless FK

* 9856 fix ipam FK

* 9856 fix partial dcim FK

* 9856 fix dcim FK

* 9856 fix virtualization FK

* 9856 fix tests / remove debug code

* 9856 fix test imagefield

* 9856 cleanup graphene

* 9856 fix plugin schema

* 9856 fix requirements

* 9856 fix requirements

* 9856 fix docs

* 9856 fix docs

* 9856 temp fix tests

* 9856 first filterset

* 9856 first filterset

* 9856 fix tests

* 9856 fix tests

* 9856 working auto filter generation

* 9856 filter types

* 9856 filter types

* 9856 filter types

* 9856 fix graphiql test

* 9856 fix counter fields and merge feature

* 9856 temp fix tests

* 9856 fix tests

* 9856 fix tenancy, ipam filter definitions

* 9856 cleanup

* 9856 cleanup

* 9856 cleanup

* 9856 review changes

* 9856 review changes

* 9856 review changes

* 9856 fix base-requirements

* 9856 add wrapper to graphiql

* 9856 remove old graphiql debug toolbar

* 9856 review changes

* 9856 update strawberry

* 9856 remove superfluous check

---------

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
This commit is contained in:
Arthur Hanson
2024-03-22 09:56:30 -07:00
committed by GitHub
parent 423c9813a2
commit 45c99e4477
70 changed files with 97782 additions and 2290 deletions

View File

@ -14,10 +14,6 @@ django-debug-toolbar
# https://github.com/carltongibson/django-filter/blob/main/CHANGES.rst
django-filter
# Django debug toolbar extension with support for GraphiQL
# https://github.com/flavors/django-graphiql-debug-toolbar/blob/main/CHANGES.rst
django-graphiql-debug-toolbar
# HTMX utilities for Django
# https://django-htmx.readthedocs.io/en/latest/changelog.html
django-htmx
@ -75,11 +71,6 @@ drf-spectacular-sidecar
# https://github.com/kurtmckee/feedparser/blob/develop/CHANGELOG.rst
feedparser
# Django wrapper for Graphene (GraphQL support)
# https://github.com/graphql-python/graphene-django/releases
# Pinned to v3.0.0 for GraphiQL UI issue (see #12762)
graphene_django==3.0.0
# WSGI HTTP server
# https://docs.gunicorn.org/en/latest/news.html
gunicorn
@ -136,8 +127,16 @@ social-auth-core
# https://github.com/python-social-auth/social-app-django/blob/master/CHANGELOG.md
social-auth-app-django
# Strawberry GraphQL
# https://github.com/strawberry-graphql/strawberry/blob/main/CHANGELOG.md
strawberry-graphql
# Strawberry GraphQL Django extension
# https://github.com/strawberry-graphql/strawberry-django/blob/main/CHANGELOG.md
strawberry-graphql-django
# SVG image rendering (used for rack elevations)
# hhttps://github.com/mozman/svgwrite/blob/master/NEWS.rst
# https://github.com/mozman/svgwrite/blob/master/NEWS.rst
svgwrite
# Tabular dataset library (for table-based exports)

View File

@ -8,23 +8,32 @@ A plugin can extend NetBox's GraphQL API by registering its own schema class. By
```python
# graphql.py
import graphene
from netbox.graphql.types import NetBoxObjectType
from netbox.graphql.fields import ObjectField, ObjectListField
from . import filtersets, models
from typing import List
import strawberry
import strawberry_django
class MyModelType(NetBoxObjectType):
from . import models
class Meta:
model = models.MyModel
fields = '__all__'
filterset_class = filtersets.MyModelFilterSet
class MyQuery(graphene.ObjectType):
mymodel = ObjectField(MyModelType)
mymodel_list = ObjectListField(MyModelType)
@strawberry_django.type(
models.MyModel,
fields='__all__',
)
class MyModelType:
pass
schema = MyQuery
@strawberry.type
class MyQuery:
@strawberry.field
def dummymodel(self, id: int) -> DummyModelType:
return None
dummymodel_list: List[DummyModelType] = strawberry_django.field()
schema = [
MyQuery,
]
```
## GraphQL Objects
@ -38,15 +47,3 @@ NetBox provides two object type classes for use by plugins.
::: netbox.graphql.types.NetBoxObjectType
options:
members: false
## GraphQL Fields
NetBox provides two field classes for use by plugins.
::: netbox.graphql.fields.ObjectField
options:
members: false
::: netbox.graphql.fields.ObjectListField
options:
members: false

View File

@ -0,0 +1,50 @@
import strawberry
import strawberry_django
from circuits import filtersets, models
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
__all__ = (
'CircuitTerminationFilter',
'CircuitFilter',
'CircuitTypeFilter',
'ProviderFilter',
'ProviderAccountFilter',
'ProviderNetworkFilter',
)
@strawberry_django.filter(models.CircuitTermination, lookups=True)
@autotype_decorator(filtersets.CircuitTerminationFilterSet)
class CircuitTerminationFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Circuit, lookups=True)
@autotype_decorator(filtersets.CircuitFilterSet)
class CircuitFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.CircuitType, lookups=True)
@autotype_decorator(filtersets.CircuitTypeFilterSet)
class CircuitTypeFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Provider, lookups=True)
@autotype_decorator(filtersets.ProviderFilterSet)
class ProviderFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ProviderAccount, lookups=True)
@autotype_decorator(filtersets.ProviderAccountFilterSet)
class ProviderAccountFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ProviderNetwork, lookups=True)
@autotype_decorator(filtersets.ProviderNetworkFilterSet)
class ProviderNetworkFilter(BaseFilterMixin):
pass

View File

@ -1,41 +1,40 @@
import graphene
from typing import List
import strawberry
import strawberry_django
from circuits import models
from netbox.graphql.fields import ObjectField, ObjectListField
from .types import *
from utilities.graphql_optimizer import gql_query_optimizer
class CircuitsQuery(graphene.ObjectType):
circuit = ObjectField(CircuitType)
circuit_list = ObjectListField(CircuitType)
@strawberry.type
class CircuitsQuery:
@strawberry.field
def circuit(self, id: int) -> CircuitType:
return models.Circuit.objects.get(pk=id)
circuit_list: List[CircuitType] = strawberry_django.field()
def resolve_circuit_list(root, info, **kwargs):
return gql_query_optimizer(models.Circuit.objects.all(), info)
@strawberry.field
def circuit_termination(self, id: int) -> CircuitTerminationType:
return models.CircuitTermination.objects.get(pk=id)
circuit_termination_list: List[CircuitTerminationType] = strawberry_django.field()
circuit_termination = ObjectField(CircuitTerminationType)
circuit_termination_list = ObjectListField(CircuitTerminationType)
@strawberry.field
def circuit_type(self, id: int) -> CircuitTypeType:
return models.CircuitType.objects.get(pk=id)
circuit_type_list: List[CircuitTypeType] = strawberry_django.field()
def resolve_circuit_termination_list(root, info, **kwargs):
return gql_query_optimizer(models.CircuitTermination.objects.all(), info)
@strawberry.field
def provider(self, id: int) -> ProviderType:
return models.Provider.objects.get(pk=id)
provider_list: List[ProviderType] = strawberry_django.field()
circuit_type = ObjectField(CircuitTypeType)
circuit_type_list = ObjectListField(CircuitTypeType)
@strawberry.field
def provider_account(self, id: int) -> ProviderAccountType:
return models.ProviderAccount.objects.get(pk=id)
provider_account_list: List[ProviderAccountType] = strawberry_django.field()
def resolve_circuit_type_list(root, info, **kwargs):
return gql_query_optimizer(models.CircuitType.objects.all(), info)
provider = ObjectField(ProviderType)
provider_list = ObjectListField(ProviderType)
def resolve_provider_list(root, info, **kwargs):
return gql_query_optimizer(models.Provider.objects.all(), info)
provider_account = ObjectField(ProviderAccountType)
provider_account_list = ObjectListField(ProviderAccountType)
provider_network = ObjectField(ProviderNetworkType)
provider_network_list = ObjectListField(ProviderNetworkType)
def resolve_provider_network_list(root, info, **kwargs):
return gql_query_optimizer(models.ProviderNetwork.objects.all(), info)
@strawberry.field
def provider_network(self, id: int) -> ProviderNetworkType:
return models.ProviderNetwork.objects.get(pk=id)
provider_network_list: List[ProviderNetworkType] = strawberry_django.field()

View File

@ -1,9 +1,14 @@
import graphene
from typing import Annotated, List
from circuits import filtersets, models
import strawberry
import strawberry_django
from circuits import models
from dcim.graphql.mixins import CabledObjectMixin
from extras.graphql.mixins import CustomFieldsMixin, TagsMixin, ContactsMixin
from netbox.graphql.types import ObjectType, OrganizationalObjectType, NetBoxObjectType
from extras.graphql.mixins import ContactsMixin, CustomFieldsMixin, TagsMixin
from netbox.graphql.types import NetBoxObjectType, ObjectType, OrganizationalObjectType
from tenancy.graphql.types import TenantType
from .filters import *
__all__ = (
'CircuitTerminationType',
@ -15,48 +20,93 @@ __all__ = (
)
class CircuitTerminationType(CustomFieldsMixin, TagsMixin, CabledObjectMixin, ObjectType):
class Meta:
model = models.CircuitTermination
fields = '__all__'
filterset_class = filtersets.CircuitTerminationFilterSet
class CircuitType(NetBoxObjectType, ContactsMixin):
class Meta:
model = models.Circuit
fields = '__all__'
filterset_class = filtersets.CircuitFilterSet
class CircuitTypeType(OrganizationalObjectType):
class Meta:
model = models.CircuitType
fields = '__all__'
filterset_class = filtersets.CircuitTypeFilterSet
@strawberry_django.type(
models.Provider,
fields='__all__',
filters=ProviderFilter
)
class ProviderType(NetBoxObjectType, ContactsMixin):
class Meta:
model = models.Provider
fields = '__all__'
filterset_class = filtersets.ProviderFilterSet
@strawberry_django.field
def networks(self) -> List[Annotated["ProviderNetworkType", strawberry.lazy('circuits.graphql.types')]]:
return self.networks.all()
@strawberry_django.field
def circuits(self) -> List[Annotated["CircuitType", strawberry.lazy('circuits.graphql.types')]]:
return self.circuits.all()
@strawberry_django.field
def asns(self) -> List[Annotated["ASNType", strawberry.lazy('ipam.graphql.types')]]:
return self.asns.all()
@strawberry_django.field
def accounts(self) -> List[Annotated["ProviderAccountType", strawberry.lazy('circuits.graphql.types')]]:
return self.accounts.all()
@strawberry_django.type(
models.ProviderAccount,
fields='__all__',
filters=ProviderAccountFilter
)
class ProviderAccountType(NetBoxObjectType):
provider: Annotated["ProviderType", strawberry.lazy('circuits.graphql.types')]
class Meta:
model = models.ProviderAccount
fields = '__all__'
filterset_class = filtersets.ProviderAccountFilterSet
@strawberry_django.field
def circuits(self) -> List[Annotated["CircuitType", strawberry.lazy('circuits.graphql.types')]]:
return self.circuits.all()
@strawberry_django.type(
models.ProviderNetwork,
fields='__all__',
filters=ProviderNetworkFilter
)
class ProviderNetworkType(NetBoxObjectType):
provider: Annotated["ProviderType", strawberry.lazy('circuits.graphql.types')]
class Meta:
model = models.ProviderNetwork
fields = '__all__'
filterset_class = filtersets.ProviderNetworkFilterSet
@strawberry_django.field
def circuit_terminations(self) -> List[Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')]]:
return self.circuit_terminations.all()
@strawberry_django.type(
models.CircuitTermination,
fields='__all__',
filters=CircuitTerminationFilter
)
class CircuitTerminationType(CustomFieldsMixin, TagsMixin, CabledObjectMixin, ObjectType):
circuit: Annotated["CircuitType", strawberry.lazy('circuits.graphql.types')]
provider_network: Annotated["ProviderNetworkType", strawberry.lazy('circuits.graphql.types')] | None
site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')] | None
@strawberry_django.type(
models.CircuitType,
fields='__all__',
filters=CircuitTypeFilter
)
class CircuitTypeType(OrganizationalObjectType):
color: str
@strawberry_django.field
def circuits(self) -> List[Annotated["CircuitType", strawberry.lazy('circuits.graphql.types')]]:
return self.circuits.all()
@strawberry_django.type(
models.Circuit,
fields='__all__',
filters=CircuitFilter
)
class CircuitType(NetBoxObjectType, ContactsMixin):
provider: ProviderType
provider_account: ProviderAccountType | None
termination_a: CircuitTerminationType | None
termination_z: CircuitTerminationType | None
type: CircuitTypeType
tenant: TenantType | None
@strawberry_django.field
def terminations(self) -> List[CircuitTerminationType]:
return self.terminations.all()

View File

@ -0,0 +1,21 @@
import strawberry_django
from core import filtersets, models
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
__all__ = (
'DataFileFilter',
'DataSourceFilter',
)
@strawberry_django.filter(models.DataFile, lookups=True)
@autotype_decorator(filtersets.DataFileFilterSet)
class DataFileFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.DataSource, lookups=True)
@autotype_decorator(filtersets.DataSourceFilterSet)
class DataSourceFilter(BaseFilterMixin):
pass

View File

@ -1,20 +1,20 @@
import graphene
from typing import List
import strawberry
import strawberry_django
from core import models
from netbox.graphql.fields import ObjectField, ObjectListField
from .types import *
from utilities.graphql_optimizer import gql_query_optimizer
class CoreQuery(graphene.ObjectType):
data_file = ObjectField(DataFileType)
data_file_list = ObjectListField(DataFileType)
@strawberry.type
class CoreQuery:
@strawberry.field
def data_file(self, id: int) -> DataFileType:
return models.DataFile.objects.get(pk=id)
data_file_list: List[DataFileType] = strawberry_django.field()
def resolve_data_file_list(root, info, **kwargs):
return gql_query_optimizer(models.DataFile.objects.all(), info)
data_source = ObjectField(DataSourceType)
data_source_list = ObjectListField(DataSourceType)
def resolve_data_source_list(root, info, **kwargs):
return gql_query_optimizer(models.DataSource.objects.all(), info)
@strawberry.field
def data_source(self, id: int) -> DataSourceType:
return models.DataSource.objects.get(pk=id)
data_source_list: List[DataSourceType] = strawberry_django.field()

View File

@ -1,5 +1,11 @@
from core import filtersets, models
from typing import Annotated, List
import strawberry
import strawberry_django
from core import models
from netbox.graphql.types import BaseObjectType, NetBoxObjectType
from .filters import *
__all__ = (
'DataFileType',
@ -7,15 +13,22 @@ __all__ = (
)
@strawberry_django.type(
models.DataFile,
exclude=['data',],
filters=DataFileFilter
)
class DataFileType(BaseObjectType):
class Meta:
model = models.DataFile
exclude = ('data',)
filterset_class = filtersets.DataFileFilterSet
source: Annotated["DataSourceType", strawberry.lazy('core.graphql.types')]
@strawberry_django.type(
models.DataSource,
fields='__all__',
filters=DataSourceFilter
)
class DataSourceType(NetBoxObjectType):
class Meta:
model = models.DataSource
fields = '__all__'
filterset_class = filtersets.DataSourceFilterSet
@strawberry_django.field
def datafiles(self) -> List[Annotated["DataFileType", strawberry.lazy('core.graphql.types')]]:
return self.datafiles.all()

View File

@ -0,0 +1,294 @@
import strawberry_django
from dcim import filtersets, models
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
__all__ = (
'CableFilter',
'CableTerminationFilter',
'ConsolePortFilter',
'ConsolePortTemplateFilter',
'ConsoleServerPortFilter',
'ConsoleServerPortTemplateFilter',
'DeviceFilter',
'DeviceBayFilter',
'DeviceBayTemplateFilter',
'InventoryItemTemplateFilter',
'DeviceRoleFilter',
'DeviceTypeFilter',
'FrontPortFilter',
'FrontPortTemplateFilter',
'InterfaceFilter',
'InterfaceTemplateFilter',
'InventoryItemFilter',
'InventoryItemRoleFilter',
'LocationFilter',
'ManufacturerFilter',
'ModuleFilter',
'ModuleBayFilter',
'ModuleBayTemplateFilter',
'ModuleTypeFilter',
'PlatformFilter',
'PowerFeedFilter',
'PowerOutletFilter',
'PowerOutletTemplateFilter',
'PowerPanelFilter',
'PowerPortFilter',
'PowerPortTemplateFilter',
'RackFilter',
'RackReservationFilter',
'RackRoleFilter',
'RearPortFilter',
'RearPortTemplateFilter',
'RegionFilter',
'SiteFilter',
'SiteGroupFilter',
'VirtualChassisFilter',
'VirtualDeviceContextFilter',
)
@strawberry_django.filter(models.Cable, lookups=True)
@autotype_decorator(filtersets.CableFilterSet)
class CableFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.CableTermination, lookups=True)
@autotype_decorator(filtersets.CableTerminationFilterSet)
class CableTerminationFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ConsolePort, lookups=True)
@autotype_decorator(filtersets.ConsolePortFilterSet)
class ConsolePortFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ConsolePortTemplate, lookups=True)
@autotype_decorator(filtersets.ConsolePortTemplateFilterSet)
class ConsolePortTemplateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ConsoleServerPort, lookups=True)
@autotype_decorator(filtersets.ConsoleServerPortFilterSet)
class ConsoleServerPortFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ConsoleServerPortTemplate, lookups=True)
@autotype_decorator(filtersets.ConsoleServerPortTemplateFilterSet)
class ConsoleServerPortTemplateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Device, lookups=True)
@autotype_decorator(filtersets.DeviceFilterSet)
class DeviceFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.DeviceBay, lookups=True)
@autotype_decorator(filtersets.DeviceBayFilterSet)
class DeviceBayFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.DeviceBayTemplate, lookups=True)
@autotype_decorator(filtersets.DeviceBayTemplateFilterSet)
class DeviceBayTemplateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.InventoryItemTemplate, lookups=True)
@autotype_decorator(filtersets.InventoryItemTemplateFilterSet)
class InventoryItemTemplateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.DeviceRole, lookups=True)
@autotype_decorator(filtersets.DeviceRoleFilterSet)
class DeviceRoleFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.DeviceType, lookups=True)
@autotype_decorator(filtersets.DeviceTypeFilterSet)
class DeviceTypeFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.FrontPort, lookups=True)
@autotype_decorator(filtersets.FrontPortFilterSet)
class FrontPortFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.FrontPortTemplate, lookups=True)
@autotype_decorator(filtersets.FrontPortTemplateFilterSet)
class FrontPortTemplateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Interface, lookups=True)
@autotype_decorator(filtersets.InterfaceFilterSet)
class InterfaceFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.InterfaceTemplate, lookups=True)
@autotype_decorator(filtersets.InterfaceTemplateFilterSet)
class InterfaceTemplateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.InventoryItem, lookups=True)
@autotype_decorator(filtersets.InventoryItemFilterSet)
class InventoryItemFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.InventoryItemRole, lookups=True)
@autotype_decorator(filtersets.InventoryItemRoleFilterSet)
class InventoryItemRoleFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Location, lookups=True)
@autotype_decorator(filtersets.LocationFilterSet)
class LocationFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Manufacturer, lookups=True)
@autotype_decorator(filtersets.ManufacturerFilterSet)
class ManufacturerFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Module, lookups=True)
@autotype_decorator(filtersets.ModuleFilterSet)
class ModuleFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ModuleBay, lookups=True)
@autotype_decorator(filtersets.ModuleBayFilterSet)
class ModuleBayFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ModuleBayTemplate, lookups=True)
@autotype_decorator(filtersets.ModuleBayTemplateFilterSet)
class ModuleBayTemplateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ModuleType, lookups=True)
@autotype_decorator(filtersets.ModuleTypeFilterSet)
class ModuleTypeFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Platform, lookups=True)
@autotype_decorator(filtersets.PlatformFilterSet)
class PlatformFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.PowerFeed, lookups=True)
@autotype_decorator(filtersets.PowerFeedFilterSet)
class PowerFeedFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.PowerOutlet, lookups=True)
@autotype_decorator(filtersets.PowerOutletFilterSet)
class PowerOutletFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.PowerOutletTemplate, lookups=True)
@autotype_decorator(filtersets.PowerOutletTemplateFilterSet)
class PowerOutletTemplateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.PowerPanel, lookups=True)
@autotype_decorator(filtersets.PowerPanelFilterSet)
class PowerPanelFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.PowerPort, lookups=True)
@autotype_decorator(filtersets.PowerPortFilterSet)
class PowerPortFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.PowerPortTemplate, lookups=True)
@autotype_decorator(filtersets.PowerPortTemplateFilterSet)
class PowerPortTemplateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Rack, lookups=True)
@autotype_decorator(filtersets.RackFilterSet)
class RackFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.RackReservation, lookups=True)
@autotype_decorator(filtersets.RackReservationFilterSet)
class RackReservationFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.RackRole, lookups=True)
@autotype_decorator(filtersets.RackRoleFilterSet)
class RackRoleFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.RearPort, lookups=True)
@autotype_decorator(filtersets.RearPortFilterSet)
class RearPortFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.RearPortTemplate, lookups=True)
@autotype_decorator(filtersets.RearPortTemplateFilterSet)
class RearPortTemplateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Region, lookups=True)
@autotype_decorator(filtersets.RegionFilterSet)
class RegionFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Site, lookups=True)
@autotype_decorator(filtersets.SiteFilterSet)
class SiteFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.SiteGroup, lookups=True)
@autotype_decorator(filtersets.SiteGroupFilterSet)
class SiteGroupFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.VirtualChassis, lookups=True)
@autotype_decorator(filtersets.VirtualChassisFilterSet)
class VirtualChassisFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.VirtualDeviceContext, lookups=True)
@autotype_decorator(filtersets.VirtualDeviceContextFilterSet)
class VirtualDeviceContextFilter(BaseFilterMixin):
pass

View File

@ -1,4 +1,3 @@
import graphene
from circuits.graphql.types import CircuitTerminationType, ProviderNetworkType
from circuits.models import CircuitTermination, ProviderNetwork
from dcim.graphql.types import (
@ -37,79 +36,7 @@ from dcim.models import (
)
class LinkPeerType(graphene.Union):
class Meta:
types = (
CircuitTerminationType,
ConsolePortType,
ConsoleServerPortType,
FrontPortType,
InterfaceType,
PowerFeedType,
PowerOutletType,
PowerPortType,
RearPortType,
)
@classmethod
def resolve_type(cls, instance, info):
if type(instance) is CircuitTermination:
return CircuitTerminationType
if type(instance) is ConsolePortType:
return ConsolePortType
if type(instance) is ConsoleServerPort:
return ConsoleServerPortType
if type(instance) is FrontPort:
return FrontPortType
if type(instance) is Interface:
return InterfaceType
if type(instance) is PowerFeed:
return PowerFeedType
if type(instance) is PowerOutlet:
return PowerOutletType
if type(instance) is PowerPort:
return PowerPortType
if type(instance) is RearPort:
return RearPortType
class CableTerminationTerminationType(graphene.Union):
class Meta:
types = (
CircuitTerminationType,
ConsolePortType,
ConsoleServerPortType,
FrontPortType,
InterfaceType,
PowerFeedType,
PowerOutletType,
PowerPortType,
RearPortType,
)
@classmethod
def resolve_type(cls, instance, info):
if type(instance) is CircuitTermination:
return CircuitTerminationType
if type(instance) is ConsolePortType:
return ConsolePortType
if type(instance) is ConsoleServerPort:
return ConsoleServerPortType
if type(instance) is FrontPort:
return FrontPortType
if type(instance) is Interface:
return InterfaceType
if type(instance) is PowerFeed:
return PowerFeedType
if type(instance) is PowerOutlet:
return PowerOutletType
if type(instance) is PowerPort:
return PowerPortType
if type(instance) is RearPort:
return RearPortType
class InventoryItemTemplateComponentType(graphene.Union):
class InventoryItemTemplateComponentType:
class Meta:
types = (
ConsolePortTemplateType,
@ -139,7 +66,7 @@ class InventoryItemTemplateComponentType(graphene.Union):
return RearPortTemplateType
class InventoryItemComponentType(graphene.Union):
class InventoryItemComponentType:
class Meta:
types = (
ConsolePortType,
@ -169,7 +96,7 @@ class InventoryItemComponentType(graphene.Union):
return RearPortType
class ConnectedEndpointType(graphene.Union):
class ConnectedEndpointType:
class Meta:
types = (
CircuitTerminationType,

View File

@ -1,20 +1,47 @@
import graphene
from typing import Annotated, List, Union
import strawberry
import strawberry_django
__all__ = (
'CabledObjectMixin',
'PathEndpointMixin',
)
@strawberry.type
class CabledObjectMixin:
link_peers = graphene.List('dcim.graphql.gfk_mixins.LinkPeerType')
cable: Annotated["CableType", strawberry.lazy('dcim.graphql.types')] | None
def resolve_cable_end(self, info):
# Handle empty values
return self.cable_end or None
def resolve_link_peers(self, info):
@strawberry_django.field
def link_peers(self) -> List[Annotated[Union[
Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')],
Annotated["ConsolePortType", strawberry.lazy('dcim.graphql.types')],
Annotated["ConsoleServerPortType", strawberry.lazy('dcim.graphql.types')],
Annotated["FrontPortType", strawberry.lazy('dcim.graphql.types')],
Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')],
Annotated["PowerFeedType", strawberry.lazy('dcim.graphql.types')],
Annotated["PowerOutletType", strawberry.lazy('dcim.graphql.types')],
Annotated["PowerPortType", strawberry.lazy('dcim.graphql.types')],
Annotated["RearPortType", strawberry.lazy('dcim.graphql.types')],
], strawberry.union("LinkPeerType")]]:
return self.link_peers
@strawberry.type
class PathEndpointMixin:
connected_endpoints = graphene.List('dcim.graphql.gfk_mixins.ConnectedEndpointType')
def resolve_connected_endpoints(self, info):
# Handle empty values
@strawberry_django.field
def connected_endpoints(self) -> List[Annotated[Union[
Annotated["CircuitTerminationType", strawberry.lazy('circuits.graphql.types')],
Annotated["ConsolePortType", strawberry.lazy('dcim.graphql.types')],
Annotated["ConsoleServerPortType", strawberry.lazy('dcim.graphql.types')],
Annotated["FrontPortType", strawberry.lazy('dcim.graphql.types')],
Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')],
Annotated["PowerFeedType", strawberry.lazy('dcim.graphql.types')],
Annotated["PowerOutletType", strawberry.lazy('dcim.graphql.types')],
Annotated["PowerPortType", strawberry.lazy('dcim.graphql.types')],
Annotated["ProviderNetworkType", strawberry.lazy('circuits.graphql.types')],
Annotated["RearPortType", strawberry.lazy('dcim.graphql.types')],
], strawberry.union("ConnectedEndpointType")]]:
return self.connected_endpoints or None

View File

@ -1,249 +1,210 @@
import graphene
from typing import List
import strawberry
import strawberry_django
from netbox.graphql.fields import ObjectField, ObjectListField
from .types import *
from dcim import models
from .types import VirtualDeviceContextType
from utilities.graphql_optimizer import gql_query_optimizer
class DCIMQuery(graphene.ObjectType):
cable = ObjectField(CableType)
cable_list = ObjectListField(CableType)
def resolve_cable_list(root, info, **kwargs):
return gql_query_optimizer(models.Cable.objects.all(), info)
console_port = ObjectField(ConsolePortType)
console_port_list = ObjectListField(ConsolePortType)
def resolve_console_port_list(root, info, **kwargs):
return gql_query_optimizer(models.ConsolePort.objects.all(), info)
console_port_template = ObjectField(ConsolePortTemplateType)
console_port_template_list = ObjectListField(ConsolePortTemplateType)
def resolve_console_port_template_list(root, info, **kwargs):
return gql_query_optimizer(models.ConsolePortTemplate.objects.all(), info)
console_server_port = ObjectField(ConsoleServerPortType)
console_server_port_list = ObjectListField(ConsoleServerPortType)
def resolve_console_server_port_list(root, info, **kwargs):
return gql_query_optimizer(models.ConsoleServerPort.objects.all(), info)
console_server_port_template = ObjectField(ConsoleServerPortTemplateType)
console_server_port_template_list = ObjectListField(ConsoleServerPortTemplateType)
def resolve_console_server_port_template_list(root, info, **kwargs):
return gql_query_optimizer(models.ConsoleServerPortTemplate.objects.all(), info)
device = ObjectField(DeviceType)
device_list = ObjectListField(DeviceType)
def resolve_device_list(root, info, **kwargs):
return gql_query_optimizer(models.Device.objects.all(), info)
device_bay = ObjectField(DeviceBayType)
device_bay_list = ObjectListField(DeviceBayType)
def resolve_device_bay_list(root, info, **kwargs):
return gql_query_optimizer(models.DeviceBay.objects.all(), info)
device_bay_template = ObjectField(DeviceBayTemplateType)
device_bay_template_list = ObjectListField(DeviceBayTemplateType)
def resolve_device_bay_template_list(root, info, **kwargs):
return gql_query_optimizer(models.DeviceBayTemplate.objects.all(), info)
device_role = ObjectField(DeviceRoleType)
device_role_list = ObjectListField(DeviceRoleType)
def resolve_device_role_list(root, info, **kwargs):
return gql_query_optimizer(models.DeviceRole.objects.all(), info)
device_type = ObjectField(DeviceTypeType)
device_type_list = ObjectListField(DeviceTypeType)
def resolve_device_type_list(root, info, **kwargs):
return gql_query_optimizer(models.DeviceType.objects.all(), info)
front_port = ObjectField(FrontPortType)
front_port_list = ObjectListField(FrontPortType)
def resolve_front_port_list(root, info, **kwargs):
return gql_query_optimizer(models.FrontPort.objects.all(), info)
front_port_template = ObjectField(FrontPortTemplateType)
front_port_template_list = ObjectListField(FrontPortTemplateType)
def resolve_front_port_template_list(root, info, **kwargs):
return gql_query_optimizer(models.FrontPortTemplate.objects.all(), info)
interface = ObjectField(InterfaceType)
interface_list = ObjectListField(InterfaceType)
def resolve_interface_list(root, info, **kwargs):
return gql_query_optimizer(models.Interface.objects.all(), info)
interface_template = ObjectField(InterfaceTemplateType)
interface_template_list = ObjectListField(InterfaceTemplateType)
def resolve_interface_template_list(root, info, **kwargs):
return gql_query_optimizer(models.InterfaceTemplate.objects.all(), info)
inventory_item = ObjectField(InventoryItemType)
inventory_item_list = ObjectListField(InventoryItemType)
def resolve_inventory_item_list(root, info, **kwargs):
return gql_query_optimizer(models.InventoryItem.objects.all(), info)
inventory_item_role = ObjectField(InventoryItemRoleType)
inventory_item_role_list = ObjectListField(InventoryItemRoleType)
def resolve_inventory_item_role_list(root, info, **kwargs):
return gql_query_optimizer(models.InventoryItemRole.objects.all(), info)
inventory_item_template = ObjectField(InventoryItemTemplateType)
inventory_item_template_list = ObjectListField(InventoryItemTemplateType)
def resolve_inventory_item_template_list(root, info, **kwargs):
return gql_query_optimizer(models.InventoryItemTemplate.objects.all(), info)
location = ObjectField(LocationType)
location_list = ObjectListField(LocationType)
def resolve_location_list(root, info, **kwargs):
return gql_query_optimizer(models.Location.objects.all(), info)
manufacturer = ObjectField(ManufacturerType)
manufacturer_list = ObjectListField(ManufacturerType)
def resolve_manufacturer_list(root, info, **kwargs):
return gql_query_optimizer(models.Manufacturer.objects.all(), info)
module = ObjectField(ModuleType)
module_list = ObjectListField(ModuleType)
def resolve_module_list(root, info, **kwargs):
return gql_query_optimizer(models.Module.objects.all(), info)
module_bay = ObjectField(ModuleBayType)
module_bay_list = ObjectListField(ModuleBayType)
def resolve_module_bay_list(root, info, **kwargs):
return gql_query_optimizer(models.ModuleBay.objects.all(), info)
module_bay_template = ObjectField(ModuleBayTemplateType)
module_bay_template_list = ObjectListField(ModuleBayTemplateType)
def resolve_module_bay_template_list(root, info, **kwargs):
return gql_query_optimizer(models.ModuleBayTemplate.objects.all(), info)
module_type = ObjectField(ModuleTypeType)
module_type_list = ObjectListField(ModuleTypeType)
def resolve_module_type_list(root, info, **kwargs):
return gql_query_optimizer(models.ModuleType.objects.all(), info)
platform = ObjectField(PlatformType)
platform_list = ObjectListField(PlatformType)
def resolve_platform_list(root, info, **kwargs):
return gql_query_optimizer(models.Platform.objects.all(), info)
power_feed = ObjectField(PowerFeedType)
power_feed_list = ObjectListField(PowerFeedType)
def resolve_power_feed_list(root, info, **kwargs):
return gql_query_optimizer(models.PowerFeed.objects.all(), info)
power_outlet = ObjectField(PowerOutletType)
power_outlet_list = ObjectListField(PowerOutletType)
def resolve_power_outlet_list(root, info, **kwargs):
return gql_query_optimizer(models.PowerOutlet.objects.all(), info)
power_outlet_template = ObjectField(PowerOutletTemplateType)
power_outlet_template_list = ObjectListField(PowerOutletTemplateType)
def resolve_power_outlet_template_list(root, info, **kwargs):
return gql_query_optimizer(models.PowerOutletTemplate.objects.all(), info)
power_panel = ObjectField(PowerPanelType)
power_panel_list = ObjectListField(PowerPanelType)
def resolve_power_panel_list(root, info, **kwargs):
return gql_query_optimizer(models.PowerPanel.objects.all(), info)
power_port = ObjectField(PowerPortType)
power_port_list = ObjectListField(PowerPortType)
def resolve_power_port_list(root, info, **kwargs):
return gql_query_optimizer(models.PowerPort.objects.all(), info)
power_port_template = ObjectField(PowerPortTemplateType)
power_port_template_list = ObjectListField(PowerPortTemplateType)
def resolve_power_port_template_list(root, info, **kwargs):
return gql_query_optimizer(models.PowerPortTemplate.objects.all(), info)
rack = ObjectField(RackType)
rack_list = ObjectListField(RackType)
def resolve_rack_list(root, info, **kwargs):
return gql_query_optimizer(models.Rack.objects.all(), info)
rack_reservation = ObjectField(RackReservationType)
rack_reservation_list = ObjectListField(RackReservationType)
def resolve_rack_reservation_list(root, info, **kwargs):
return gql_query_optimizer(models.RackReservation.objects.all(), info)
rack_role = ObjectField(RackRoleType)
rack_role_list = ObjectListField(RackRoleType)
def resolve_rack_role_list(root, info, **kwargs):
return gql_query_optimizer(models.RackRole.objects.all(), info)
rear_port = ObjectField(RearPortType)
rear_port_list = ObjectListField(RearPortType)
def resolve_rear_port_list(root, info, **kwargs):
return gql_query_optimizer(models.RearPort.objects.all(), info)
rear_port_template = ObjectField(RearPortTemplateType)
rear_port_template_list = ObjectListField(RearPortTemplateType)
def resolve_rear_port_template_list(root, info, **kwargs):
return gql_query_optimizer(models.RearPortTemplate.objects.all(), info)
region = ObjectField(RegionType)
region_list = ObjectListField(RegionType)
def resolve_region_list(root, info, **kwargs):
return gql_query_optimizer(models.Region.objects.all(), info)
site = ObjectField(SiteType)
site_list = ObjectListField(SiteType)
def resolve_site_list(root, info, **kwargs):
return gql_query_optimizer(models.Site.objects.all(), info)
site_group = ObjectField(SiteGroupType)
site_group_list = ObjectListField(SiteGroupType)
def resolve_site_group_list(root, info, **kwargs):
return gql_query_optimizer(models.SiteGroup.objects.all(), info)
virtual_chassis = ObjectField(VirtualChassisType)
virtual_chassis_list = ObjectListField(VirtualChassisType)
def resolve_virtual_chassis_list(root, info, **kwargs):
return gql_query_optimizer(models.VirtualChassis.objects.all(), info)
virtual_device_context = ObjectField(VirtualDeviceContextType)
virtual_device_context_list = ObjectListField(VirtualDeviceContextType)
def resolve_virtual_device_context_list(root, info, **kwargs):
return gql_query_optimizer(models.VirtualDeviceContext.objects.all(), info)
from .types import *
@strawberry.type
class DCIMQuery:
@strawberry.field
def cable(self, id: int) -> CableType:
return models.Cable.objects.get(pk=id)
cable_list: List[CableType] = strawberry_django.field()
@strawberry.field
def console_port(self, id: int) -> ConsolePortType:
return models.ConsolePort.objects.get(pk=id)
console_port_list: List[ConsolePortType] = strawberry_django.field()
@strawberry.field
def console_port_template(self, id: int) -> ConsolePortTemplateType:
return models.ConsolePortTemplate.objects.get(pk=id)
console_port_template_list: List[ConsolePortTemplateType] = strawberry_django.field()
@strawberry.field
def console_server_port(self, id: int) -> ConsoleServerPortType:
return models.ConsoleServerPort.objects.get(pk=id)
console_server_port_list: List[ConsoleServerPortType] = strawberry_django.field()
@strawberry.field
def console_server_port_template(self, id: int) -> ConsoleServerPortTemplateType:
return models.ConsoleServerPortTemplate.objects.get(pk=id)
console_server_port_template_list: List[ConsoleServerPortTemplateType] = strawberry_django.field()
@strawberry.field
def device(self, id: int) -> DeviceType:
return models.Device.objects.get(pk=id)
device_list: List[DeviceType] = strawberry_django.field()
@strawberry.field
def device_bay(self, id: int) -> DeviceBayType:
return models.DeviceBay.objects.get(pk=id)
device_bay_list: List[DeviceBayType] = strawberry_django.field()
@strawberry.field
def device_bay_template(self, id: int) -> DeviceBayTemplateType:
return models.DeviceBayTemplate.objects.get(pk=id)
device_bay_template_list: List[DeviceBayTemplateType] = strawberry_django.field()
@strawberry.field
def device_role(self, id: int) -> DeviceRoleType:
return models.DeviceRole.objects.get(pk=id)
device_role_list: List[DeviceRoleType] = strawberry_django.field()
@strawberry.field
def device_type(self, id: int) -> DeviceTypeType:
return models.DeviceType.objects.get(pk=id)
device_type_list: List[DeviceTypeType] = strawberry_django.field()
@strawberry.field
def front_port(self, id: int) -> FrontPortType:
return models.FrontPort.objects.get(pk=id)
front_port_list: List[FrontPortType] = strawberry_django.field()
@strawberry.field
def front_port_template(self, id: int) -> FrontPortTemplateType:
return models.FrontPortTemplate.objects.get(pk=id)
front_port_template_list: List[FrontPortTemplateType] = strawberry_django.field()
@strawberry.field
def interface(self, id: int) -> InterfaceType:
return models.Interface.objects.get(pk=id)
interface_list: List[InterfaceType] = strawberry_django.field()
@strawberry.field
def interface_template(self, id: int) -> InterfaceTemplateType:
return models.InterfaceTemplate.objects.get(pk=id)
interface_template_list: List[InterfaceTemplateType] = strawberry_django.field()
@strawberry.field
def inventory_item(self, id: int) -> InventoryItemType:
return models.InventoryItem.objects.get(pk=id)
inventory_item_list: List[InventoryItemType] = strawberry_django.field()
@strawberry.field
def inventory_item_role(self, id: int) -> InventoryItemRoleType:
return models.InventoryItemRole.objects.get(pk=id)
inventory_item_role_list: List[InventoryItemRoleType] = strawberry_django.field()
@strawberry.field
def inventory_item_template(self, id: int) -> InventoryItemTemplateType:
return models.InventoryItemTemplate.objects.get(pk=id)
inventory_item_template_list: List[InventoryItemTemplateType] = strawberry_django.field()
@strawberry.field
def location(self, id: int) -> LocationType:
return models.Location.objects.get(pk=id)
location_list: List[LocationType] = strawberry_django.field()
@strawberry.field
def manufacturer(self, id: int) -> ManufacturerType:
return models.Manufacturer.objects.get(pk=id)
manufacturer_list: List[ManufacturerType] = strawberry_django.field()
@strawberry.field
def module(self, id: int) -> ModuleType:
return models.Module.objects.get(pk=id)
module_list: List[ModuleType] = strawberry_django.field()
@strawberry.field
def module_bay(self, id: int) -> ModuleBayType:
return models.ModuleBay.objects.get(pk=id)
module_bay_list: List[ModuleBayType] = strawberry_django.field()
@strawberry.field
def module_bay_template(self, id: int) -> ModuleBayTemplateType:
return models.ModuleBayTemplate.objects.get(pk=id)
module_bay_template_list: List[ModuleBayTemplateType] = strawberry_django.field()
@strawberry.field
def module_type(self, id: int) -> ModuleTypeType:
return models.ModuleType.objects.get(pk=id)
module_type_list: List[ModuleTypeType] = strawberry_django.field()
@strawberry.field
def platform(self, id: int) -> PlatformType:
return models.Platform.objects.get(pk=id)
platform_list: List[PlatformType] = strawberry_django.field()
@strawberry.field
def power_feed(self, id: int) -> PowerFeedType:
return models.PowerFeed.objects.get(pk=id)
power_feed_list: List[PowerFeedType] = strawberry_django.field()
@strawberry.field
def power_outlet(self, id: int) -> PowerOutletType:
return models.PowerOutlet.objects.get(pk=id)
power_outlet_list: List[PowerOutletType] = strawberry_django.field()
@strawberry.field
def power_outlet_template(self, id: int) -> PowerOutletTemplateType:
return models.PowerOutletTemplate.objects.get(pk=id)
power_outlet_template_list: List[PowerOutletTemplateType] = strawberry_django.field()
@strawberry.field
def power_panel(self, id: int) -> PowerPanelType:
return models.PowerPanel.objects.get(id=id)
power_panel_list: List[PowerPanelType] = strawberry_django.field()
@strawberry.field
def power_port(self, id: int) -> PowerPortType:
return models.PowerPort.objects.get(id=id)
power_port_list: List[PowerPortType] = strawberry_django.field()
@strawberry.field
def power_port_template(self, id: int) -> PowerPortTemplateType:
return models.PowerPortTemplate.objects.get(id=id)
power_port_template_list: List[PowerPortTemplateType] = strawberry_django.field()
@strawberry.field
def rack(self, id: int) -> RackType:
return models.Rack.objects.get(id=id)
rack_list: List[RackType] = strawberry_django.field()
@strawberry.field
def rack_reservation(self, id: int) -> RackReservationType:
return models.RackReservation.objects.get(id=id)
rack_reservation_list: List[RackReservationType] = strawberry_django.field()
@strawberry.field
def rack_role(self, id: int) -> RackRoleType:
return models.RackRole.objects.get(id=id)
rack_role_list: List[RackRoleType] = strawberry_django.field()
@strawberry.field
def rear_port(self, id: int) -> RearPortType:
return models.RearPort.objects.get(id=id)
rear_port_list: List[RearPortType] = strawberry_django.field()
@strawberry.field
def rear_port_template(self, id: int) -> RearPortTemplateType:
return models.RearPortTemplate.objects.get(id=id)
rear_port_template_list: List[RearPortTemplateType] = strawberry_django.field()
@strawberry.field
def region(self, id: int) -> RegionType:
return models.Region.objects.get(id=id)
region_list: List[RegionType] = strawberry_django.field()
@strawberry.field
def site(self, id: int) -> SiteType:
return models.Site.objects.get(id=id)
site_list: List[SiteType] = strawberry_django.field()
@strawberry.field
def site_group(self, id: int) -> SiteGroupType:
return models.SiteGroup.objects.get(id=id)
site_group_list: List[SiteGroupType] = strawberry_django.field()
@strawberry.field
def virtual_chassis(self, id: int) -> VirtualChassisType:
return models.VirtualChassis.objects.get(id=id)
virtual_chassis_list: List[VirtualChassisType] = strawberry_django.field()
@strawberry.field
def virtual_device_context(self, id: int) -> VirtualDeviceContextType:
return models.VirtualDeviceContext.objects.get(id=id)
virtual_device_context_list: List[VirtualDeviceContextType] = strawberry_django.field()

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
import strawberry_django
from extras import filtersets, models
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
__all__ = (
'ConfigContextFilter',
'ConfigTemplateFilter',
'CustomFieldFilter',
'CustomFieldChoiceSetFilter',
'CustomLinkFilter',
'EventRuleFilter',
'ExportTemplateFilter',
'ImageAttachmentFilter',
'JournalEntryFilter',
'ObjectChangeFilter',
'SavedFilterFilter',
'TagFilter',
'WebhookFilter',
)
@strawberry_django.filter(models.ConfigContext, lookups=True)
@autotype_decorator(filtersets.ConfigContextFilterSet)
class ConfigContextFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ConfigTemplate, lookups=True)
@autotype_decorator(filtersets.ConfigTemplateFilterSet)
class ConfigTemplateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.CustomField, lookups=True)
@autotype_decorator(filtersets.CustomFieldFilterSet)
class CustomFieldFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.CustomFieldChoiceSet, lookups=True)
@autotype_decorator(filtersets.CustomFieldChoiceSetFilterSet)
class CustomFieldChoiceSetFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.CustomLink, lookups=True)
@autotype_decorator(filtersets.CustomLinkFilterSet)
class CustomLinkFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ExportTemplate, lookups=True)
@autotype_decorator(filtersets.ExportTemplateFilterSet)
class ExportTemplateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ImageAttachment, lookups=True)
@autotype_decorator(filtersets.ImageAttachmentFilterSet)
class ImageAttachmentFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.JournalEntry, lookups=True)
@autotype_decorator(filtersets.JournalEntryFilterSet)
class JournalEntryFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ObjectChange, lookups=True)
@autotype_decorator(filtersets.ObjectChangeFilterSet)
class ObjectChangeFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.SavedFilter, lookups=True)
@autotype_decorator(filtersets.SavedFilterFilterSet)
class SavedFilterFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Tag, lookups=True)
@autotype_decorator(filtersets.TagFilterSet)
class TagFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Webhook, lookups=True)
@autotype_decorator(filtersets.WebhookFilterSet)
class WebhookFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.EventRule, lookups=True)
@autotype_decorator(filtersets.EventRuleFilterSet)
class EventRuleFilter(BaseFilterMixin):
pass

View File

@ -1,6 +1,8 @@
import graphene
from typing import TYPE_CHECKING, Annotated, List
import strawberry
import strawberry_django
from django.contrib.contenttypes.models import ContentType
from graphene.types.generic import GenericScalar
from extras.models import ObjectChange
@ -14,56 +16,67 @@ __all__ = (
'TagsMixin',
)
if TYPE_CHECKING:
from .types import ImageAttachmentType, JournalEntryType, ObjectChangeType, TagType
from tenancy.graphql.types import ContactAssignmentType
@strawberry.type
class ChangelogMixin:
changelog = graphene.List('extras.graphql.types.ObjectChangeType')
def resolve_changelog(self, info):
@strawberry_django.field
def changelog(self, info) -> List[Annotated["ObjectChangeType", strawberry.lazy('.types')]]:
content_type = ContentType.objects.get_for_model(self)
object_changes = ObjectChange.objects.filter(
changed_object_type=content_type,
changed_object_id=self.pk
)
return object_changes.restrict(info.context.user, 'view')
return object_changes.restrict(info.context.request.user, 'view')
@strawberry.type
class ConfigContextMixin:
config_context = GenericScalar()
def resolve_config_context(self, info):
@strawberry_django.field
def config_context(self) -> strawberry.scalars.JSON:
return self.get_config_context()
@strawberry.type
class CustomFieldsMixin:
custom_fields = GenericScalar()
def resolve_custom_fields(self, info):
@strawberry_django.field
def custom_fields(self) -> strawberry.scalars.JSON:
return self.custom_field_data
@strawberry.type
class ImageAttachmentsMixin:
image_attachments = graphene.List('extras.graphql.types.ImageAttachmentType')
def resolve_image_attachments(self, info):
return self.images.restrict(info.context.user, 'view')
@strawberry_django.field
def image_attachments(self, info) -> List[Annotated["ImageAttachmentType", strawberry.lazy('.types')]]:
return self.images.restrict(info.context.request.user, 'view')
@strawberry.type
class JournalEntriesMixin:
journal_entries = graphene.List('extras.graphql.types.JournalEntryType')
def resolve_journal_entries(self, info):
return self.journal_entries.restrict(info.context.user, 'view')
@strawberry_django.field
def journal_entries(self, info) -> List[Annotated["JournalEntryType", strawberry.lazy('.types')]]:
return self.journal_entries.all()
@strawberry.type
class TagsMixin:
tags = graphene.List('extras.graphql.types.TagType')
def resolve_tags(self, info):
@strawberry_django.field
def tags(self) -> List[Annotated["TagType", strawberry.lazy('.types')]]:
return self.tags.all()
@strawberry.type
class ContactsMixin:
contacts = graphene.List('tenancy.graphql.types.ContactAssignmentType')
def resolve_contacts(self, info):
@strawberry_django.field
def contacts(self) -> List[Annotated["ContactAssignmentType", strawberry.lazy('tenancy.graphql.types')]]:
return list(self.contacts.all())

View File

@ -1,80 +1,70 @@
import graphene
from typing import List
import strawberry
import strawberry_django
from extras import models
from netbox.graphql.fields import ObjectField, ObjectListField
from .types import *
from utilities.graphql_optimizer import gql_query_optimizer
class ExtrasQuery(graphene.ObjectType):
config_context = ObjectField(ConfigContextType)
config_context_list = ObjectListField(ConfigContextType)
@strawberry.type
class ExtrasQuery:
@strawberry.field
def config_context(self, id: int) -> ConfigContextType:
return models.ConfigContext.objects.get(pk=id)
config_context_list: List[ConfigContextType] = strawberry_django.field()
def resolve_config_context_list(root, info, **kwargs):
return gql_query_optimizer(models.ConfigContext.objects.all(), info)
@strawberry.field
def config_template(self, id: int) -> ConfigTemplateType:
return models.ConfigTemplate.objects.get(pk=id)
config_template_list: List[ConfigTemplateType] = strawberry_django.field()
config_template = ObjectField(ConfigTemplateType)
config_template_list = ObjectListField(ConfigTemplateType)
@strawberry.field
def custom_field(self, id: int) -> CustomFieldType:
return models.CustomField.objects.get(pk=id)
custom_field_list: List[CustomFieldType] = strawberry_django.field()
def resolve_config_template_list(root, info, **kwargs):
return gql_query_optimizer(models.ConfigTemplate.objects.all(), info)
@strawberry.field
def custom_field_choice_set(self, id: int) -> CustomFieldChoiceSetType:
return models.CustomFieldChoiceSet.objects.get(pk=id)
custom_field_choice_set_list: List[CustomFieldChoiceSetType] = strawberry_django.field()
custom_field = ObjectField(CustomFieldType)
custom_field_list = ObjectListField(CustomFieldType)
@strawberry.field
def custom_link(self, id: int) -> CustomLinkType:
return models.CustomLink.objects.get(pk=id)
custom_link_list: List[CustomLinkType] = strawberry_django.field()
def resolve_custom_field_list(root, info, **kwargs):
return gql_query_optimizer(models.CustomField.objects.all(), info)
@strawberry.field
def export_template(self, id: int) -> ExportTemplateType:
return models.ExportTemplate.objects.get(pk=id)
export_template_list: List[ExportTemplateType] = strawberry_django.field()
custom_field_choice_set = ObjectField(CustomFieldChoiceSetType)
custom_field_choice_set_list = ObjectListField(CustomFieldChoiceSetType)
@strawberry.field
def image_attachment(self, id: int) -> ImageAttachmentType:
return models.ImageAttachment.objects.get(pk=id)
image_attachment_list: List[ImageAttachmentType] = strawberry_django.field()
def resolve_custom_field_choices_list(root, info, **kwargs):
return gql_query_optimizer(models.CustomFieldChoiceSet.objects.all(), info)
@strawberry.field
def saved_filter(self, id: int) -> SavedFilterType:
return models.SavedFilter.objects.get(pk=id)
saved_filter_list: List[SavedFilterType] = strawberry_django.field()
custom_link = ObjectField(CustomLinkType)
custom_link_list = ObjectListField(CustomLinkType)
@strawberry.field
def journal_entry(self, id: int) -> JournalEntryType:
return models.JournalEntry.objects.get(pk=id)
journal_entry_list: List[JournalEntryType] = strawberry_django.field()
def resolve_custom_link_list(root, info, **kwargs):
return gql_query_optimizer(models.CustomLink.objects.all(), info)
@strawberry.field
def tag(self, id: int) -> TagType:
return models.Tag.objects.get(pk=id)
tag_list: List[TagType] = strawberry_django.field()
export_template = ObjectField(ExportTemplateType)
export_template_list = ObjectListField(ExportTemplateType)
@strawberry.field
def webhook(self, id: int) -> WebhookType:
return models.Webhook.objects.get(pk=id)
webhook_list: List[WebhookType] = strawberry_django.field()
def resolve_export_template_list(root, info, **kwargs):
return gql_query_optimizer(models.ExportTemplate.objects.all(), info)
image_attachment = ObjectField(ImageAttachmentType)
image_attachment_list = ObjectListField(ImageAttachmentType)
def resolve_image_attachment_list(root, info, **kwargs):
return gql_query_optimizer(models.ImageAttachment.objects.all(), info)
saved_filter = ObjectField(SavedFilterType)
saved_filter_list = ObjectListField(SavedFilterType)
def resolve_saved_filter_list(root, info, **kwargs):
return gql_query_optimizer(models.SavedFilter.objects.all(), info)
journal_entry = ObjectField(JournalEntryType)
journal_entry_list = ObjectListField(JournalEntryType)
def resolve_journal_entry_list(root, info, **kwargs):
return gql_query_optimizer(models.JournalEntry.objects.all(), info)
tag = ObjectField(TagType)
tag_list = ObjectListField(TagType)
def resolve_tag_list(root, info, **kwargs):
return gql_query_optimizer(models.Tag.objects.all(), info)
webhook = ObjectField(WebhookType)
webhook_list = ObjectListField(WebhookType)
def resolve_webhook_list(root, info, **kwargs):
return gql_query_optimizer(models.Webhook.objects.all(), info)
event_rule = ObjectField(EventRuleType)
event_rule_list = ObjectListField(EventRuleType)
def resolve_eventrule_list(root, info, **kwargs):
return gql_query_optimizer(models.EventRule.objects.all(), info)
@strawberry.field
def event_rule(self, id: int) -> EventRuleType:
return models.EventRule.objects.get(pk=id)
event_rule_list: List[EventRuleType] = strawberry_django.field()

View File

@ -1,6 +1,12 @@
from extras import filtersets, models
from typing import Annotated, List
import strawberry
import strawberry_django
from extras import models
from extras.graphql.mixins import CustomFieldsMixin, TagsMixin
from netbox.graphql.types import BaseObjectType, ObjectType, OrganizationalObjectType
from netbox.graphql.types import BaseObjectType, ContentTypeType, ObjectType, OrganizationalObjectType
from .filters import *
__all__ = (
'ConfigContextType',
@ -19,104 +25,202 @@ __all__ = (
)
@strawberry_django.type(
models.ConfigContext,
fields='__all__',
filters=ConfigContextFilter
)
class ConfigContextType(ObjectType):
data_source: Annotated["DataSourceType", strawberry.lazy('core.graphql.types')] | None
data_file: Annotated["DataFileType", strawberry.lazy('core.graphql.types')] | None
class Meta:
model = models.ConfigContext
fields = '__all__'
filterset_class = filtersets.ConfigContextFilterSet
@strawberry_django.field
def roles(self) -> List[Annotated["DeviceRoleType", strawberry.lazy('dcim.graphql.types')]]:
return self.roles.all()
@strawberry_django.field
def device_types(self) -> List[Annotated["DeviceTypeType", strawberry.lazy('dcim.graphql.types')]]:
return self.device_types.all()
@strawberry_django.field
def tags(self) -> List[Annotated["TagType", strawberry.lazy('extras.graphql.types')]]:
return self.tags.all()
@strawberry_django.field
def platforms(self) -> List[Annotated["PlatformType", strawberry.lazy('dcim.graphql.types')]]:
return self.platforms.all()
@strawberry_django.field
def regions(self) -> List[Annotated["RegionType", strawberry.lazy('dcim.graphql.types')]]:
return self.regions.all()
@strawberry_django.field
def cluster_groups(self) -> List[Annotated["ClusterGroupType", strawberry.lazy('virtualization.graphql.types')]]:
return self.cluster_groups.all()
@strawberry_django.field
def tenant_groups(self) -> List[Annotated["TenantGroupType", strawberry.lazy('tenancy.graphql.types')]]:
return self.tenant_groups.all()
@strawberry_django.field
def cluster_types(self) -> List[Annotated["ClusterTypeType", strawberry.lazy('virtualization.graphql.types')]]:
return self.cluster_types.all()
@strawberry_django.field
def clusters(self) -> List[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]:
return self.clusters.all()
@strawberry_django.field
def locations(self) -> List[Annotated["LocationType", strawberry.lazy('dcim.graphql.types')]]:
return self.locations.all()
@strawberry_django.field
def sites(self) -> List[Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]]:
return self.sites.all()
@strawberry_django.field
def tenants(self) -> List[Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')]]:
return self.tenants.all()
@strawberry_django.field
def site_groups(self) -> List[Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')]]:
return self.site_groups.all()
@strawberry_django.type(
models.ConfigTemplate,
fields='__all__',
filters=ConfigTemplateFilter
)
class ConfigTemplateType(TagsMixin, ObjectType):
data_source: Annotated["DataSourceType", strawberry.lazy('core.graphql.types')] | None
data_file: Annotated["DataFileType", strawberry.lazy('core.graphql.types')] | None
class Meta:
model = models.ConfigTemplate
fields = '__all__'
filterset_class = filtersets.ConfigTemplateFilterSet
@strawberry_django.field
def virtualmachines(self) -> List[Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')]]:
return self.virtualmachines.all()
@strawberry_django.field
def devices(self) -> List[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]]:
return self.devices.all()
@strawberry_django.field
def platforms(self) -> List[Annotated["PlatformType", strawberry.lazy('dcim.graphql.types')]]:
return self.platforms.all()
@strawberry_django.field
def device_roles(self) -> List[Annotated["DeviceRoleType", strawberry.lazy('dcim.graphql.types')]]:
return self.device_roles.all()
@strawberry_django.type(
models.CustomField,
fields='__all__',
filters=CustomFieldFilter
)
class CustomFieldType(ObjectType):
class Meta:
model = models.CustomField
fields = '__all__'
filterset_class = filtersets.CustomFieldFilterSet
related_object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
choice_set: Annotated["CustomFieldChoiceSetType", strawberry.lazy('extras.graphql.types')] | None
@strawberry_django.type(
models.CustomFieldChoiceSet,
exclude=('extra_choices', ),
filters=CustomFieldChoiceSetFilter
)
class CustomFieldChoiceSetType(ObjectType):
class Meta:
model = models.CustomFieldChoiceSet
fields = '__all__'
filterset_class = filtersets.CustomFieldChoiceSetFilterSet
@strawberry_django.field
def choices_for(self) -> List[Annotated["CustomFieldType", strawberry.lazy('extras.graphql.types')]]:
return self.choices_for.all()
@strawberry_django.field
def extra_choices(self) -> List[str] | None:
return list(self.extra_choices)
@strawberry_django.type(
models.CustomLink,
fields='__all__',
filters=CustomLinkFilter
)
class CustomLinkType(ObjectType):
class Meta:
model = models.CustomLink
fields = '__all__'
filterset_class = filtersets.CustomLinkFilterSet
class EventRuleType(OrganizationalObjectType):
class Meta:
model = models.EventRule
fields = '__all__'
filterset_class = filtersets.EventRuleFilterSet
pass
@strawberry_django.type(
models.ExportTemplate,
fields='__all__',
filters=ExportTemplateFilter
)
class ExportTemplateType(ObjectType):
class Meta:
model = models.ExportTemplate
fields = '__all__'
filterset_class = filtersets.ExportTemplateFilterSet
data_source: Annotated["DataSourceType", strawberry.lazy('core.graphql.types')] | None
data_file: Annotated["DataFileType", strawberry.lazy('core.graphql.types')] | None
@strawberry_django.type(
models.ImageAttachment,
fields='__all__',
filters=ImageAttachmentFilter
)
class ImageAttachmentType(BaseObjectType):
class Meta:
model = models.ImageAttachment
fields = '__all__'
filterset_class = filtersets.ImageAttachmentFilterSet
object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
@strawberry_django.type(
models.JournalEntry,
fields='__all__',
filters=JournalEntryFilter
)
class JournalEntryType(CustomFieldsMixin, TagsMixin, ObjectType):
class Meta:
model = models.JournalEntry
fields = '__all__'
filterset_class = filtersets.JournalEntryFilterSet
assigned_object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
created_by: Annotated["UserType", strawberry.lazy('users.graphql.types')] | None
@strawberry_django.type(
models.ObjectChange,
fields='__all__',
filters=ObjectChangeFilter
)
class ObjectChangeType(BaseObjectType):
class Meta:
model = models.ObjectChange
fields = '__all__'
filterset_class = filtersets.ObjectChangeFilterSet
pass
@strawberry_django.type(
models.SavedFilter,
exclude=['content_types',],
filters=SavedFilterFilter
)
class SavedFilterType(ObjectType):
class Meta:
model = models.SavedFilter
fields = '__all__'
filterset_class = filtersets.SavedFilterFilterSet
user: Annotated["UserType", strawberry.lazy('users.graphql.types')] | None
@strawberry_django.type(
models.Tag,
exclude=['extras_taggeditem_items', ],
filters=TagFilter
)
class TagType(ObjectType):
color: str
class Meta:
model = models.Tag
exclude = ('extras_taggeditem_items',)
filterset_class = filtersets.TagFilterSet
@strawberry_django.field
def object_types(self) -> List[ContentTypeType]:
return self.object_types.all()
@strawberry_django.type(
models.Webhook,
exclude=['content_types',],
filters=WebhookFilter
)
class WebhookType(OrganizationalObjectType):
pass
class Meta:
model = models.Webhook
filterset_class = filtersets.WebhookFilterSet
@strawberry_django.type(
models.EventRule,
exclude=['content_types',],
filters=EventRuleFilter
)
class EventRuleType(OrganizationalObjectType):
action_object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None

View File

@ -0,0 +1,119 @@
import strawberry_django
from ipam import filtersets, models
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
__all__ = (
'ASNFilter',
'ASNRangeFilter',
'AggregateFilter',
'FHRPGroupFilter',
'FHRPGroupAssignmentFilter',
'IPAddressFilter',
'IPRangeFilter',
'PrefixFilter',
'RIRFilter',
'RoleFilter',
'RouteTargetFilter',
'ServiceFilter',
'ServiceTemplateFilter',
'VLANFilter',
'VLANGroupFilter',
'VRFFilter',
)
@strawberry_django.filter(models.ASN, lookups=True)
@autotype_decorator(filtersets.ASNFilterSet)
class ASNFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ASNRange, lookups=True)
@autotype_decorator(filtersets.ASNRangeFilterSet)
class ASNRangeFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Aggregate, lookups=True)
@autotype_decorator(filtersets.AggregateFilterSet)
class AggregateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.FHRPGroup, lookups=True)
@autotype_decorator(filtersets.FHRPGroupFilterSet)
class FHRPGroupFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.FHRPGroupAssignment, lookups=True)
@autotype_decorator(filtersets.FHRPGroupAssignmentFilterSet)
class FHRPGroupAssignmentFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.IPAddress, lookups=True)
@autotype_decorator(filtersets.IPAddressFilterSet)
class IPAddressFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.IPRange, lookups=True)
@autotype_decorator(filtersets.IPRangeFilterSet)
class IPRangeFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Prefix, lookups=True)
@autotype_decorator(filtersets.PrefixFilterSet)
class PrefixFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.RIR, lookups=True)
@autotype_decorator(filtersets.RIRFilterSet)
class RIRFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Role, lookups=True)
@autotype_decorator(filtersets.RoleFilterSet)
class RoleFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.RouteTarget, lookups=True)
@autotype_decorator(filtersets.RouteTargetFilterSet)
class RouteTargetFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Service, lookups=True)
@autotype_decorator(filtersets.ServiceFilterSet)
class ServiceFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ServiceTemplate, lookups=True)
@autotype_decorator(filtersets.ServiceTemplateFilterSet)
class ServiceTemplateFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.VLAN, lookups=True)
@autotype_decorator(filtersets.VLANFilterSet)
class VLANFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.VLANGroup, lookups=True)
@autotype_decorator(filtersets.VLANGroupFilterSet)
class VLANGroupFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.VRF, lookups=True)
@autotype_decorator(filtersets.VRFFilterSet)
class VRFFilter(BaseFilterMixin):
pass

View File

@ -1,95 +0,0 @@
import graphene
from dcim.graphql.types import (
InterfaceType,
LocationType,
RackType,
RegionType,
SiteGroupType,
SiteType,
)
from dcim.models import Interface, Location, Rack, Region, Site, SiteGroup
from ipam.graphql.types import FHRPGroupType, VLANType
from ipam.models import VLAN, FHRPGroup
from virtualization.graphql.types import ClusterGroupType, ClusterType, VMInterfaceType
from virtualization.models import Cluster, ClusterGroup, VMInterface
class IPAddressAssignmentType(graphene.Union):
class Meta:
types = (
InterfaceType,
FHRPGroupType,
VMInterfaceType,
)
@classmethod
def resolve_type(cls, instance, info):
if type(instance) is Interface:
return InterfaceType
if type(instance) is FHRPGroup:
return FHRPGroupType
if type(instance) is VMInterface:
return VMInterfaceType
class L2VPNAssignmentType(graphene.Union):
class Meta:
types = (
InterfaceType,
VLANType,
VMInterfaceType,
)
@classmethod
def resolve_type(cls, instance, info):
if type(instance) is Interface:
return InterfaceType
if type(instance) is VLAN:
return VLANType
if type(instance) is VMInterface:
return VMInterfaceType
class FHRPGroupInterfaceType(graphene.Union):
class Meta:
types = (
InterfaceType,
VMInterfaceType,
)
@classmethod
def resolve_type(cls, instance, info):
if type(instance) is Interface:
return InterfaceType
if type(instance) is VMInterface:
return VMInterfaceType
class VLANGroupScopeType(graphene.Union):
class Meta:
types = (
ClusterType,
ClusterGroupType,
LocationType,
RackType,
RegionType,
SiteType,
SiteGroupType,
)
@classmethod
def resolve_type(cls, instance, info):
if type(instance) is Cluster:
return ClusterType
if type(instance) is ClusterGroup:
return ClusterGroupType
if type(instance) is Location:
return LocationType
if type(instance) is Rack:
return RackType
if type(instance) is Region:
return RegionType
if type(instance) is Site:
return SiteType
if type(instance) is SiteGroup:
return SiteGroupType

View File

@ -1,4 +1,7 @@
import graphene
from typing import Annotated, List
import strawberry
import strawberry_django
__all__ = (
'IPAddressesMixin',
@ -6,15 +9,15 @@ __all__ = (
)
@strawberry.type
class IPAddressesMixin:
ip_addresses = graphene.List('ipam.graphql.types.IPAddressType')
def resolve_ip_addresses(self, info):
return self.ip_addresses.restrict(info.context.user, 'view')
@strawberry_django.field
def ip_addresses(self) -> List[Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')]]:
return self.ip_addresses.all()
@strawberry.type
class VLANGroupsMixin:
vlan_groups = graphene.List('ipam.graphql.types.VLANGroupType')
def resolve_vlan_groups(self, info):
return self.vlan_groups.restrict(info.context.user, 'view')
@strawberry_django.field
def vlan_groups(self) -> List[Annotated["VLANGroupType", strawberry.lazy('ipam.graphql.types')]]:
return self.vlan_groups.all()

View File

@ -1,104 +1,90 @@
import graphene
from typing import List
import strawberry
import strawberry_django
from ipam import models
from netbox.graphql.fields import ObjectField, ObjectListField
from utilities.graphql_optimizer import gql_query_optimizer
from .types import *
class IPAMQuery(graphene.ObjectType):
asn = ObjectField(ASNType)
asn_list = ObjectListField(ASNType)
@strawberry.type
class IPAMQuery:
@strawberry.field
def asn(self, id: int) -> ASNType:
return models.ASN.objects.get(pk=id)
asn_list: List[ASNType] = strawberry_django.field()
def resolve_asn_list(root, info, **kwargs):
return gql_query_optimizer(models.ASN.objects.all(), info)
@strawberry.field
def asn_range(self, id: int) -> ASNRangeType:
return models.ASNRange.objects.get(pk=id)
asn_range_list: List[ASNRangeType] = strawberry_django.field()
asn_range = ObjectField(ASNRangeType)
asn_range_list = ObjectListField(ASNRangeType)
@strawberry.field
def aggregate(self, id: int) -> AggregateType:
return models.Aggregate.objects.get(pk=id)
aggregate_list: List[AggregateType] = strawberry_django.field()
def resolve_asn_range_list(root, info, **kwargs):
return gql_query_optimizer(models.ASNRange.objects.all(), info)
@strawberry.field
def ip_address(self, id: int) -> IPAddressType:
return models.IPAddress.objects.get(pk=id)
ip_address_list: List[IPAddressType] = strawberry_django.field()
aggregate = ObjectField(AggregateType)
aggregate_list = ObjectListField(AggregateType)
@strawberry.field
def ip_range(self, id: int) -> IPRangeType:
return models.IPRange.objects.get(pk=id)
ip_range_list: List[IPRangeType] = strawberry_django.field()
def resolve_aggregate_list(root, info, **kwargs):
return gql_query_optimizer(models.Aggregate.objects.all(), info)
@strawberry.field
def prefix(self, id: int) -> PrefixType:
return models.Prefix.objects.get(pk=id)
prefix_list: List[PrefixType] = strawberry_django.field()
ip_address = ObjectField(IPAddressType)
ip_address_list = ObjectListField(IPAddressType)
@strawberry.field
def rir(self, id: int) -> RIRType:
return models.RIR.objects.get(pk=id)
rir_list: List[RIRType] = strawberry_django.field()
def resolve_ip_address_list(root, info, **kwargs):
return gql_query_optimizer(models.IPAddress.objects.all(), info)
@strawberry.field
def role(self, id: int) -> RoleType:
return models.Role.objects.get(pk=id)
role_list: List[RoleType] = strawberry_django.field()
ip_range = ObjectField(IPRangeType)
ip_range_list = ObjectListField(IPRangeType)
@strawberry.field
def route_target(self, id: int) -> RouteTargetType:
return models.RouteTarget.objects.get(pk=id)
route_target_list: List[RouteTargetType] = strawberry_django.field()
def resolve_ip_range_list(root, info, **kwargs):
return gql_query_optimizer(models.IPRange.objects.all(), info)
@strawberry.field
def service(self, id: int) -> ServiceType:
return models.Service.objects.get(pk=id)
service_list: List[ServiceType] = strawberry_django.field()
prefix = ObjectField(PrefixType)
prefix_list = ObjectListField(PrefixType)
@strawberry.field
def service_template(self, id: int) -> ServiceTemplateType:
return models.ServiceTemplate.objects.get(pk=id)
service_template_list: List[ServiceTemplateType] = strawberry_django.field()
def resolve_prefix_list(root, info, **kwargs):
return gql_query_optimizer(models.Prefix.objects.all(), info)
@strawberry.field
def fhrp_group(self, id: int) -> FHRPGroupType:
return models.FHRPGroup.objects.get(pk=id)
fhrp_group_list: List[FHRPGroupType] = strawberry_django.field()
rir = ObjectField(RIRType)
rir_list = ObjectListField(RIRType)
@strawberry.field
def fhrp_group_assignment(self, id: int) -> FHRPGroupAssignmentType:
return models.FHRPGroupAssignment.objects.get(pk=id)
fhrp_group_assignment_list: List[FHRPGroupAssignmentType] = strawberry_django.field()
def resolve_rir_list(root, info, **kwargs):
return gql_query_optimizer(models.RIR.objects.all(), info)
@strawberry.field
def vlan(self, id: int) -> VLANType:
return models.VLAN.objects.get(pk=id)
vlan_list: List[VLANType] = strawberry_django.field()
role = ObjectField(RoleType)
role_list = ObjectListField(RoleType)
@strawberry.field
def vlan_group(self, id: int) -> VLANGroupType:
return models.VLANGroup.objects.get(pk=id)
vlan_group_list: List[VLANGroupType] = strawberry_django.field()
def resolve_role_list(root, info, **kwargs):
return gql_query_optimizer(models.Role.objects.all(), info)
route_target = ObjectField(RouteTargetType)
route_target_list = ObjectListField(RouteTargetType)
def resolve_route_target_list(root, info, **kwargs):
return gql_query_optimizer(models.RouteTarget.objects.all(), info)
service = ObjectField(ServiceType)
service_list = ObjectListField(ServiceType)
def resolve_service_list(root, info, **kwargs):
return gql_query_optimizer(models.Service.objects.all(), info)
service_template = ObjectField(ServiceTemplateType)
service_template_list = ObjectListField(ServiceTemplateType)
def resolve_service_template_list(root, info, **kwargs):
return gql_query_optimizer(models.ServiceTemplate.objects.all(), info)
fhrp_group = ObjectField(FHRPGroupType)
fhrp_group_list = ObjectListField(FHRPGroupType)
def resolve_fhrp_group_list(root, info, **kwargs):
return gql_query_optimizer(models.FHRPGroup.objects.all(), info)
fhrp_group_assignment = ObjectField(FHRPGroupAssignmentType)
fhrp_group_assignment_list = ObjectListField(FHRPGroupAssignmentType)
def resolve_fhrp_group_assignment_list(root, info, **kwargs):
return gql_query_optimizer(models.FHRPGroupAssignment.objects.all(), info)
vlan = ObjectField(VLANType)
vlan_list = ObjectListField(VLANType)
def resolve_vlan_list(root, info, **kwargs):
return gql_query_optimizer(models.VLAN.objects.all(), info)
vlan_group = ObjectField(VLANGroupType)
vlan_group_list = ObjectListField(VLANGroupType)
def resolve_vlan_group_list(root, info, **kwargs):
return gql_query_optimizer(models.VLANGroup.objects.all(), info)
vrf = ObjectField(VRFType)
vrf_list = ObjectListField(VRFType)
def resolve_vrf_list(root, info, **kwargs):
return gql_query_optimizer(models.VRF.objects.all(), info)
@strawberry.field
def vrf(self, id: int) -> VRFType:
return models.VRF.objects.get(pk=id)
vrf_list: List[VRFType] = strawberry_django.field()

View File

@ -1,9 +1,15 @@
import graphene
from typing import Annotated, List, Union
from ipam import filtersets, models
from .mixins import IPAddressesMixin
import strawberry
import strawberry_django
from circuits.graphql.types import ProviderType
from dcim.graphql.types import SiteType
from ipam import models
from netbox.graphql.scalars import BigInt
from netbox.graphql.types import BaseObjectType, OrganizationalObjectType, NetBoxObjectType
from netbox.graphql.types import BaseObjectType, NetBoxObjectType, OrganizationalObjectType
from .filters import *
from .mixins import IPAddressesMixin
__all__ = (
'ASNType',
@ -25,164 +31,335 @@ __all__ = (
)
class IPAddressFamilyType(graphene.ObjectType):
value = graphene.Int()
label = graphene.String()
def __init__(self, value):
self.value = value
self.label = f'IPv{value}'
@strawberry.type
class IPAddressFamilyType:
value: int
label: str
@strawberry.type
class BaseIPAddressFamilyType:
"""
Base type for models that need to expose their IPAddress family type.
"""
family = graphene.Field(IPAddressFamilyType)
def resolve_family(self, _):
@strawberry.field
def family(self) -> IPAddressFamilyType:
# Note that self, is an instance of models.IPAddress
# thus resolves to the address family value.
return IPAddressFamilyType(self.family)
return IPAddressFamilyType(value=self.family, label=f'IPv{self.family}')
@strawberry_django.type(
models.ASN,
fields='__all__',
filters=ASNFilter
)
class ASNType(NetBoxObjectType):
asn = graphene.Field(BigInt)
asn: BigInt
rir: Annotated["RIRType", strawberry.lazy('ipam.graphql.types')] | None
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
class Meta:
model = models.ASN
fields = '__all__'
filterset_class = filtersets.ASNFilterSet
@strawberry_django.field
def sites(self) -> List[SiteType]:
return self.sites.all()
@strawberry_django.field
def providers(self) -> List[ProviderType]:
return self.providers.all()
@strawberry_django.type(
models.ASNRange,
fields='__all__',
filters=ASNRangeFilter
)
class ASNRangeType(NetBoxObjectType):
class Meta:
model = models.ASNRange
fields = '__all__'
filterset_class = filtersets.ASNRangeFilterSet
start: BigInt
end: BigInt
rir: Annotated["RIRType", strawberry.lazy('ipam.graphql.types')] | None
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
@strawberry_django.type(
models.Aggregate,
fields='__all__',
filters=AggregateFilter
)
class AggregateType(NetBoxObjectType, BaseIPAddressFamilyType):
class Meta:
model = models.Aggregate
fields = '__all__'
filterset_class = filtersets.AggregateFilterSet
prefix: str
rir: Annotated["RIRType", strawberry.lazy('ipam.graphql.types')] | None
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
@strawberry_django.type(
models.FHRPGroup,
fields='__all__',
filters=FHRPGroupFilter
)
class FHRPGroupType(NetBoxObjectType, IPAddressesMixin):
class Meta:
model = models.FHRPGroup
fields = '__all__'
filterset_class = filtersets.FHRPGroupFilterSet
def resolve_auth_type(self, info):
return self.auth_type or None
@strawberry_django.field
def fhrpgroupassignment_set(self) -> List[Annotated["FHRPGroupAssignmentType", strawberry.lazy('ipam.graphql.types')]]:
return self.fhrpgroupassignment_set.all()
@strawberry_django.type(
models.FHRPGroupAssignment,
exclude=('interface_type', 'interface_id'),
filters=FHRPGroupAssignmentFilter
)
class FHRPGroupAssignmentType(BaseObjectType):
interface = graphene.Field('ipam.graphql.gfk_mixins.FHRPGroupInterfaceType')
group: Annotated["FHRPGroupType", strawberry.lazy('ipam.graphql.types')]
class Meta:
model = models.FHRPGroupAssignment
exclude = ('interface_type', 'interface_id')
filterset_class = filtersets.FHRPGroupAssignmentFilterSet
@strawberry_django.field
def interface(self) -> Annotated[Union[
Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')],
Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')],
], strawberry.union("FHRPGroupInterfaceType")]:
return self.interface
@strawberry_django.type(
models.IPAddress,
exclude=('assigned_object_type', 'assigned_object_id', 'address'),
filters=IPAddressFilter
)
class IPAddressType(NetBoxObjectType, BaseIPAddressFamilyType):
assigned_object = graphene.Field('ipam.graphql.gfk_mixins.IPAddressAssignmentType')
address: str
vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
nat_inside: Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')] | None
class Meta:
model = models.IPAddress
exclude = ('assigned_object_type', 'assigned_object_id')
filterset_class = filtersets.IPAddressFilterSet
@strawberry_django.field
def nat_outside(self) -> List[Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')]]:
return self.nat_outside.all()
def resolve_role(self, info):
return self.role or None
@strawberry_django.field
def tunnel_terminations(self) -> List[Annotated["TunnelTerminationType", strawberry.lazy('vpn.graphql.types')]]:
return self.tunnel_terminations.all()
@strawberry_django.field
def services(self) -> List[Annotated["ServiceType", strawberry.lazy('ipam.graphql.types')]]:
return self.services.all()
@strawberry_django.field
def assigned_object(self) -> Annotated[Union[
Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')],
Annotated["FHRPGroupType", strawberry.lazy('ipam.graphql.types')],
Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')],
], strawberry.union("IPAddressAssignmentType")]:
return self.assigned_object
@strawberry_django.type(
models.IPRange,
fields='__all__',
filters=IPRangeFilter
)
class IPRangeType(NetBoxObjectType):
class Meta:
model = models.IPRange
fields = '__all__'
filterset_class = filtersets.IPRangeFilterSet
def resolve_role(self, info):
return self.role or None
start_address: str
end_address: str
vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
role: Annotated["RoleType", strawberry.lazy('ipam.graphql.types')] | None
@strawberry_django.type(
models.Prefix,
fields='__all__',
filters=PrefixFilter
)
class PrefixType(NetBoxObjectType, BaseIPAddressFamilyType):
class Meta:
model = models.Prefix
fields = '__all__'
filterset_class = filtersets.PrefixFilterSet
prefix: str
site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')] | None
vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
vlan: Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None
role: Annotated["RoleType", strawberry.lazy('ipam.graphql.types')] | None
@strawberry_django.type(
models.RIR,
fields='__all__',
filters=RIRFilter
)
class RIRType(OrganizationalObjectType):
class Meta:
model = models.RIR
fields = '__all__'
filterset_class = filtersets.RIRFilterSet
@strawberry_django.field
def asn_ranges(self) -> List[Annotated["ASNRangeType", strawberry.lazy('ipam.graphql.types')]]:
return self.asn_ranges.all()
@strawberry_django.field
def asns(self) -> List[Annotated["ASNType", strawberry.lazy('ipam.graphql.types')]]:
return self.asns.all()
@strawberry_django.field
def aggregates(self) -> List[Annotated["AggregateType", strawberry.lazy('ipam.graphql.types')]]:
return self.aggregates.all()
@strawberry_django.type(
models.Role,
fields='__all__',
filters=RoleFilter
)
class RoleType(OrganizationalObjectType):
class Meta:
model = models.Role
fields = '__all__'
filterset_class = filtersets.RoleFilterSet
@strawberry_django.field
def prefixes(self) -> List[Annotated["PrefixType", strawberry.lazy('ipam.graphql.types')]]:
return self.prefixes.all()
@strawberry_django.field
def ip_ranges(self) -> List[Annotated["IPRangeType", strawberry.lazy('ipam.graphql.types')]]:
return self.ip_ranges.all()
@strawberry_django.field
def vlans(self) -> List[Annotated["VLANType", strawberry.lazy('ipam.graphql.types')]]:
return self.vlans.all()
@strawberry_django.type(
models.RouteTarget,
fields='__all__',
filters=RouteTargetFilter
)
class RouteTargetType(NetBoxObjectType):
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
class Meta:
model = models.RouteTarget
fields = '__all__'
filterset_class = filtersets.RouteTargetFilterSet
@strawberry_django.field
def exporting_l2vpns(self) -> List[Annotated["L2VPNType", strawberry.lazy('vpn.graphql.types')]]:
return self.exporting_l2vpns.all()
@strawberry_django.field
def exporting_vrfs(self) -> List[Annotated["VRFType", strawberry.lazy('ipam.graphql.types')]]:
return self.exporting_vrfs.all()
@strawberry_django.field
def importing_vrfs(self) -> List[Annotated["VRFType", strawberry.lazy('ipam.graphql.types')]]:
return self.importing_vrfs.all()
@strawberry_django.field
def importing_l2vpns(self) -> List[Annotated["L2VPNType", strawberry.lazy('vpn.graphql.types')]]:
return self.importing_l2vpns.all()
@strawberry_django.type(
models.Service,
fields='__all__',
filters=ServiceFilter
)
class ServiceType(NetBoxObjectType):
ports: List[int]
device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')] | None
virtual_machine: Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')] | None
class Meta:
model = models.Service
fields = '__all__'
filterset_class = filtersets.ServiceFilterSet
@strawberry_django.field
def ipaddresses(self) -> List[Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')]]:
return self.ipaddresses.all()
@strawberry_django.type(
models.ServiceTemplate,
fields='__all__',
filters=ServiceTemplateFilter
)
class ServiceTemplateType(NetBoxObjectType):
class Meta:
model = models.ServiceTemplate
fields = '__all__'
filterset_class = filtersets.ServiceTemplateFilterSet
ports: List[int]
@strawberry_django.type(
models.VLAN,
fields='__all__',
filters=VLANFilter
)
class VLANType(NetBoxObjectType):
site: Annotated["SiteType", strawberry.lazy('ipam.graphql.types')] | None
group: Annotated["VLANGroupType", strawberry.lazy('ipam.graphql.types')] | None
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
role: Annotated["RoleType", strawberry.lazy('ipam.graphql.types')] | None
class Meta:
model = models.VLAN
fields = '__all__'
filterset_class = filtersets.VLANFilterSet
@strawberry_django.field
def interfaces_as_untagged(self) -> List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]]:
return self.interfaces_as_untagged.all()
@strawberry_django.field
def vminterfaces_as_untagged(self) -> List[Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')]]:
return self.vminterfaces_as_untagged.all()
@strawberry_django.field
def wirelesslan_set(self) -> List[Annotated["WirelessLANType", strawberry.lazy('wireless.graphql.types')]]:
return self.wirelesslan_set.all()
@strawberry_django.field
def prefixes(self) -> List[Annotated["PrefixType", strawberry.lazy('ipam.graphql.types')]]:
return self.prefixes.all()
@strawberry_django.field
def interfaces_as_tagged(self) -> List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]]:
return self.interfaces_as_tagged.all()
@strawberry_django.field
def vminterfaces_as_tagged(self) -> List[Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')]]:
return self.vminterfaces_as_tagged.all()
@strawberry_django.type(
models.VLANGroup,
exclude=('scope_type', 'scope_id'),
filters=VLANGroupFilter
)
class VLANGroupType(OrganizationalObjectType):
scope = graphene.Field('ipam.graphql.gfk_mixins.VLANGroupScopeType')
class Meta:
model = models.VLANGroup
exclude = ('scope_type', 'scope_id')
filterset_class = filtersets.VLANGroupFilterSet
@strawberry_django.field
def vlans(self) -> List[VLANType]:
return self.vlans.all()
@strawberry_django.field
def scope(self) -> Annotated[Union[
Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')],
Annotated["ClusterGroupType", strawberry.lazy('virtualization.graphql.types')],
Annotated["LocationType", strawberry.lazy('dcim.graphql.types')],
Annotated["RackType", strawberry.lazy('dcim.graphql.types')],
Annotated["RegionType", strawberry.lazy('dcim.graphql.types')],
Annotated["SiteType", strawberry.lazy('dcim.graphql.types')],
Annotated["SiteGroupType", strawberry.lazy('dcim.graphql.types')],
], strawberry.union("VLANGroupScopeType")]:
return self.scope
@strawberry_django.type(
models.VRF,
fields='__all__',
filters=VRFFilter
)
class VRFType(NetBoxObjectType):
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
class Meta:
model = models.VRF
fields = '__all__'
filterset_class = filtersets.VRFFilterSet
@strawberry_django.field
def interfaces(self) -> List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]]:
return self.interfaces.all()
@strawberry_django.field
def ip_addresses(self) -> List[Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')]]:
return self.ip_addresses.all()
@strawberry_django.field
def vminterfaces(self) -> List[Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')]]:
return self.vminterfaces.all()
@strawberry_django.field
def ip_ranges(self) -> List[Annotated["IPRangeType", strawberry.lazy('ipam.graphql.types')]]:
return self.ip_ranges.all()
@strawberry_django.field
def export_targets(self) -> List[Annotated["RouteTargetType", strawberry.lazy('ipam.graphql.types')]]:
return self.export_targets.all()
@strawberry_django.field
def import_targets(self) -> List[Annotated["RouteTargetType", strawberry.lazy('ipam.graphql.types')]]:
return self.import_targets.all()
@strawberry_django.field
def prefixes(self) -> List[Annotated["PrefixType", strawberry.lazy('ipam.graphql.types')]]:
return self.prefixes.all()

View File

@ -1,69 +0,0 @@
import graphene
from dcim.fields import MACAddressField, WWNField
from django.db import models
from graphene import Dynamic
from graphene_django.converter import convert_django_field, get_django_field_description
from graphene_django.fields import DjangoConnectionField
from ipam.fields import IPAddressField, IPNetworkField
from taggit.managers import TaggableManager
from .fields import ObjectListField
@convert_django_field.register(TaggableManager)
def convert_field_to_tags_list(field, registry=None):
"""
Register conversion handler for django-taggit's TaggableManager
"""
return graphene.List(graphene.String)
@convert_django_field.register(IPAddressField)
@convert_django_field.register(IPNetworkField)
@convert_django_field.register(MACAddressField)
@convert_django_field.register(WWNField)
def convert_field_to_string(field, registry=None):
# TODO: Update to use get_django_field_description under django_graphene v3.0
return graphene.String(description=field.help_text, required=not field.null)
@convert_django_field.register(models.ManyToManyField)
@convert_django_field.register(models.ManyToManyRel)
@convert_django_field.register(models.ManyToOneRel)
def convert_field_to_list_or_connection(field, registry=None):
"""
From graphene_django.converter.py we need to monkey-patch this to return
our ObjectListField with filtering support instead of DjangoListField
"""
model = field.related_model
def dynamic_type():
_type = registry.get_type_for_model(model)
if not _type:
return
if isinstance(field, models.ManyToManyField):
description = get_django_field_description(field)
else:
description = get_django_field_description(field.field)
# If there is a connection, we should transform the field
# into a DjangoConnectionField
if _type._meta.connection:
# Use a DjangoFilterConnectionField if there are
# defined filter_fields or a filterset_class in the
# DjangoObjectType Meta
if _type._meta.filter_fields or _type._meta.filterset_class:
from .filter.fields import DjangoFilterConnectionField
return DjangoFilterConnectionField(_type, required=True, description=description)
return DjangoConnectionField(_type, required=True, description=description)
return ObjectListField(
_type,
required=True, # A Set is always returned, never None.
description=description,
)
return Dynamic(dynamic_type)

View File

@ -1,70 +0,0 @@
from functools import partial
import graphene
from graphene_django import DjangoListField
from .utils import get_graphene_type
__all__ = (
'ObjectField',
'ObjectListField',
)
class ObjectField(graphene.Field):
"""
Retrieve a single object, identified by its numeric ID.
"""
def __init__(self, *args, **kwargs):
if 'id' not in kwargs:
kwargs['id'] = graphene.Int(required=True)
super().__init__(*args, **kwargs)
@staticmethod
def object_resolver(django_object_type, root, info, **args):
"""
Return an object given its numeric ID.
"""
manager = django_object_type._meta.model._default_manager
queryset = django_object_type.get_queryset(manager, info)
return queryset.get(**args)
def get_resolver(self, parent_resolver):
return partial(self.object_resolver, self._type)
class ObjectListField(DjangoListField):
"""
Retrieve a list of objects, optionally filtered by one or more FilterSet filters.
"""
def __init__(self, _type, *args, **kwargs):
filter_kwargs = {}
# Get FilterSet kwargs
filterset_class = getattr(_type._meta, 'filterset_class', None)
if filterset_class:
for filter_name, filter_field in filterset_class.get_filters().items():
field_type = get_graphene_type(type(filter_field))
filter_kwargs[filter_name] = graphene.Argument(field_type)
super().__init__(_type, args=filter_kwargs, *args, **kwargs)
@staticmethod
def list_resolver(django_object_type, resolver, default_manager, root, info, **args):
queryset = super(ObjectListField, ObjectListField).list_resolver(django_object_type, resolver, default_manager, root, info, **args)
# if there are no filter params then don't need to filter
if not args:
return queryset
filterset_class = django_object_type._meta.filterset_class
if filterset_class:
filterset = filterset_class(data=args if args else None, queryset=queryset, request=info.context)
if not filterset.is_valid():
return queryset.none()
return filterset.qs
return queryset

View File

@ -0,0 +1,198 @@
from functools import partial, partialmethod, wraps
from typing import List
import django_filters
import strawberry
import strawberry_django
from strawberry import auto
from ipam.fields import ASNField
from netbox.graphql.scalars import BigInt
from utilities.fields import ColorField, CounterCacheField
from utilities.filters import *
def map_strawberry_type(field):
should_create_function = False
attr_type = None
# NetBox Filter types - put base classes after derived classes
if isinstance(field, ContentTypeFilter):
should_create_function = True
attr_type = str | None
elif isinstance(field, MultiValueArrayFilter):
pass
elif isinstance(field, MultiValueCharFilter):
should_create_function = True
attr_type = List[str] | None
elif isinstance(field, MultiValueDateFilter):
attr_type = auto
elif isinstance(field, MultiValueDateTimeFilter):
attr_type = auto
elif isinstance(field, MultiValueDecimalFilter):
pass
elif isinstance(field, MultiValueMACAddressFilter):
should_create_function = True
attr_type = List[str] | None
elif isinstance(field, MultiValueNumberFilter):
should_create_function = True
attr_type = List[str] | None
elif isinstance(field, MultiValueTimeFilter):
pass
elif isinstance(field, MultiValueWWNFilter):
should_create_function = True
attr_type = List[str] | None
elif isinstance(field, NullableCharFieldFilter):
pass
elif isinstance(field, NumericArrayFilter):
should_create_function = True
attr_type = int
elif isinstance(field, TreeNodeMultipleChoiceFilter):
should_create_function = True
attr_type = List[str] | None
# From django_filters - ordering of these matters as base classes must
# come after derived classes so the base class doesn't get matched first
# a pass for the check (no attr_type) means we don't currently handle
# or use that type
elif issubclass(type(field), django_filters.OrderingFilter):
pass
elif issubclass(type(field), django_filters.BaseRangeFilter):
pass
elif issubclass(type(field), django_filters.BaseInFilter):
pass
elif issubclass(type(field), django_filters.LookupChoiceFilter):
pass
elif issubclass(type(field), django_filters.AllValuesMultipleFilter):
pass
elif issubclass(type(field), django_filters.AllValuesFilter):
pass
elif issubclass(type(field), django_filters.TimeRangeFilter):
pass
elif issubclass(type(field), django_filters.IsoDateTimeFromToRangeFilter):
should_create_function = True
attr_type = str | None
elif issubclass(type(field), django_filters.DateTimeFromToRangeFilter):
should_create_function = True
attr_type = str | None
elif issubclass(type(field), django_filters.DateFromToRangeFilter):
should_create_function = True
attr_type = str | None
elif issubclass(type(field), django_filters.DateRangeFilter):
should_create_function = True
attr_type = str | None
elif issubclass(type(field), django_filters.RangeFilter):
pass
elif issubclass(type(field), django_filters.NumericRangeFilter):
pass
elif issubclass(type(field), django_filters.NumberFilter):
should_create_function = True
attr_type = int
elif issubclass(type(field), django_filters.ModelMultipleChoiceFilter):
should_create_function = True
attr_type = List[str] | None
elif issubclass(type(field), django_filters.ModelChoiceFilter):
should_create_function = True
attr_type = str | None
elif issubclass(type(field), django_filters.DurationFilter):
pass
elif issubclass(type(field), django_filters.IsoDateTimeFilter):
pass
elif issubclass(type(field), django_filters.DateTimeFilter):
attr_type = auto
elif issubclass(type(field), django_filters.TimeFilter):
attr_type = auto
elif issubclass(type(field), django_filters.DateFilter):
attr_type = auto
elif issubclass(type(field), django_filters.TypedMultipleChoiceFilter):
pass
elif issubclass(type(field), django_filters.MultipleChoiceFilter):
should_create_function = True
attr_type = List[str] | None
elif issubclass(type(field), django_filters.TypedChoiceFilter):
pass
elif issubclass(type(field), django_filters.ChoiceFilter):
pass
elif issubclass(type(field), django_filters.BooleanFilter):
should_create_function = True
attr_type = bool | None
elif issubclass(type(field), django_filters.UUIDFilter):
should_create_function = True
attr_type = str | None
elif issubclass(type(field), django_filters.CharFilter):
# looks like only used by 'q'
should_create_function = True
attr_type = str | None
return should_create_function, attr_type
def autotype_decorator(filterset):
"""
Decorator used to auto creates a dataclass used by Strawberry based on a filterset.
Must go after the Strawberry decorator as follows:
@strawberry_django.filter(models.Example, lookups=True)
@autotype_decorator(filtersets.ExampleFilterSet)
class ExampleFilter(BaseFilterMixin):
pass
The Filter itself must be derived from BaseFilterMixin. For items listed in meta.fields
of the filterset, usually just a type specifier is generated, so for
`fields = [created, ]` the dataclass would be:
class ExampleFilter(BaseFilterMixin):
created: auto
For other filter fields a function needs to be created for Strawberry with the
naming convention `filter_{fieldname}` which is auto detected and called by
Strawberry, this function uses the filterset to handle the query.
"""
def create_attribute_and_function(cls, fieldname, attr_type, should_create_function):
if fieldname not in cls.__annotations__ and attr_type:
cls.__annotations__[fieldname] = attr_type
filter_name = f"filter_{fieldname}"
if should_create_function and not hasattr(cls, filter_name):
filter_by_filterset = getattr(cls, 'filter_by_filterset')
setattr(cls, filter_name, partialmethod(filter_by_filterset, key=fieldname))
def wrapper(cls):
cls.filterset = filterset
fields = filterset.get_fields()
model = filterset._meta.model
for fieldname in fields.keys():
should_create_function = False
attr_type = auto
if fieldname not in cls.__annotations__:
field = model._meta.get_field(fieldname)
if isinstance(field, CounterCacheField):
should_create_function = True
attr_type = BigInt | None
elif isinstance(field, ASNField):
should_create_function = True
attr_type = List[str] | None
elif isinstance(field, ColorField):
should_create_function = True
attr_type = List[str] | None
create_attribute_and_function(cls, fieldname, attr_type, should_create_function)
declared_filters = filterset.declared_filters
for fieldname, field in declared_filters.items():
should_create_function, attr_type = map_strawberry_type(field)
if attr_type is None:
raise NotImplementedError(f"GraphQL Filter field unknown: {fieldname}: {field}")
create_attribute_and_function(cls, fieldname, attr_type, should_create_function)
return cls
return wrapper
@strawberry.input
class BaseFilterMixin:
def filter_by_filterset(self, queryset, key):
return self.filterset(data={key: getattr(self, key)}, queryset=queryset).qs

View File

@ -1,23 +1,10 @@
from graphene import Scalar
from graphql.language import ast
from graphene.types.scalars import MAX_INT, MIN_INT
from typing import Union
import strawberry
class BigInt(Scalar):
"""
Handle any BigInts
"""
@staticmethod
def to_float(value):
num = int(value)
if num > MAX_INT or num < MIN_INT:
return float(num)
return num
serialize = to_float
parse_value = to_float
@staticmethod
def parse_literal(node):
if isinstance(node, ast.IntValue):
return BigInt.to_float(node.value)
BigInt = strawberry.scalar(
Union[int, str], # type: ignore
serialize=lambda v: int(v),
parse_value=lambda v: str(v),
description="BigInt field",
)

View File

@ -1,4 +1,6 @@
import graphene
import strawberry
from strawberry_django.optimizer import DjangoOptimizerExtension
from strawberry.schema.config import StrawberryConfig
from circuits.graphql.schema import CircuitsQuery
from core.graphql.schema import CoreQuery
@ -13,6 +15,7 @@ from vpn.graphql.schema import VPNQuery
from wireless.graphql.schema import WirelessQuery
@strawberry.type
class Query(
UsersQuery,
CircuitsQuery,
@ -25,9 +28,14 @@ class Query(
VPNQuery,
WirelessQuery,
*registry['plugins']['graphql_schemas'], # Append plugin schemas
graphene.ObjectType
):
pass
schema = graphene.Schema(query=Query, auto_camelcase=False)
schema = strawberry.Schema(
query=Query,
config=StrawberryConfig(auto_camel_case=False),
extensions=[
DjangoOptimizerExtension,
]
)

View File

@ -1,4 +1,8 @@
import graphene
from typing import Annotated, List
import strawberry
from strawberry import auto
import strawberry_django
from core.models import ObjectType as ObjectType_
from django.contrib.contenttypes.models import ContentType
@ -8,13 +12,10 @@ from extras.graphql.mixins import (
JournalEntriesMixin,
TagsMixin,
)
from graphene_django import DjangoObjectType
__all__ = (
'BaseObjectType',
'ContentTypeType',
'ObjectType',
'ObjectTypeType',
'OrganizationalObjectType',
'NetBoxObjectType',
)
@ -24,26 +25,27 @@ __all__ = (
# Base types
#
class BaseObjectType(DjangoObjectType):
@strawberry.type
class BaseObjectType:
"""
Base GraphQL object type for all NetBox objects. Restricts the model queryset to enforce object permissions.
"""
display = graphene.String()
class_type = graphene.String()
class Meta:
abstract = True
@classmethod
def get_queryset(cls, queryset, info):
def get_queryset(cls, queryset, info, **kwargs):
# Enforce object permissions on the queryset
return queryset.restrict(info.context.user, 'view')
if hasattr(queryset, 'restrict'):
return queryset.restrict(info.context.request.user, 'view')
else:
return queryset
def resolve_display(parent, info, **kwargs):
return str(parent)
@strawberry_django.field
def display(self) -> str:
return str(self)
def resolve_class_type(parent, info, **kwargs):
return parent.__class__.__name__
@strawberry_django.field
def class_type(self) -> str:
return self.__class__.__name__
class ObjectType(
@ -53,8 +55,7 @@ class ObjectType(
"""
Base GraphQL object type for unclassified models which support change logging
"""
class Meta:
abstract = True
pass
class OrganizationalObjectType(
@ -66,8 +67,7 @@ class OrganizationalObjectType(
"""
Base type for organizational models
"""
class Meta:
abstract = True
pass
class NetBoxObjectType(
@ -80,23 +80,24 @@ class NetBoxObjectType(
"""
GraphQL type for most NetBox models. Includes support for custom fields, change logging, journaling, and tags.
"""
class Meta:
abstract = True
pass
#
# Miscellaneous types
#
class ContentTypeType(DjangoObjectType):
class Meta:
model = ContentType
fields = ('id', 'app_label', 'model')
@strawberry_django.type(
ContentType,
fields=['id', 'app_label', 'model'],
)
class ContentTypeType:
pass
class ObjectTypeType(DjangoObjectType):
class Meta:
model = ObjectType_
fields = ('id', 'app_label', 'model')
@strawberry_django.type(
ObjectType_,
fields=['id', 'app_label', 'model'],
)
class ObjectTypeType:
pass

View File

@ -1,25 +0,0 @@
import graphene
from django_filters import filters
def get_graphene_type(filter_cls):
"""
Return the appropriate Graphene scalar type for a django_filters Filter
"""
if issubclass(filter_cls, filters.BooleanFilter):
field_type = graphene.Boolean
elif issubclass(filter_cls, filters.NumberFilter):
# TODO: Floats? BigInts?
field_type = graphene.Int
elif issubclass(filter_cls, filters.DateFilter):
field_type = graphene.Date
elif issubclass(filter_cls, filters.DateTimeFilter):
field_type = graphene.DateTime
else:
field_type = graphene.String
# Multi-value filters should be handled as lists
if issubclass(filter_cls, filters.MultipleChoiceFilter):
return graphene.List(field_type)
return field_type

View File

@ -1,20 +1,26 @@
import json
from django.conf import settings
from django.contrib.auth.views import redirect_to_login
from django.http import HttpResponseNotFound, HttpResponseForbidden
from django.http import HttpResponse
from django.template import loader
from django.urls import reverse
from graphene_django.views import GraphQLView as GraphQLView_
from django.views.decorators.csrf import csrf_exempt
from rest_framework.exceptions import AuthenticationFailed
from strawberry.django.views import GraphQLView
from netbox.api.authentication import TokenAuthentication
from netbox.config import get_config
class GraphQLView(GraphQLView_):
class NetBoxGraphQLView(GraphQLView):
"""
Extends graphene_django's GraphQLView to support DRF's token-based authentication.
Extends strawberry's GraphQLView to support DRF's token-based authentication.
"""
graphiql_template = 'graphiql.html'
@csrf_exempt
def dispatch(self, request, *args, **kwargs):
config = get_config()
@ -34,11 +40,15 @@ class GraphQLView(GraphQLView_):
# Enforce LOGIN_REQUIRED
if settings.LOGIN_REQUIRED and not request.user.is_authenticated:
# If this is a human user, send a redirect to the login page
if self.request_wants_html(request):
if request.accepts("text/html"):
return redirect_to_login(reverse('graphql'))
else:
return HttpResponseForbidden("No credentials provided.")
return super().dispatch(request, *args, **kwargs)
def render_graphql_ide(self, request):
template = loader.get_template("graphiql.html")
context = {"SUBSCRIPTION_ENABLED": json.dumps(self.subscriptions_enabled)}
return HttpResponse(template.render(context, request))

View File

@ -73,7 +73,7 @@ def register_graphql_schema(graphql_schema):
"""
Register a GraphQL schema class for inclusion in NetBox's GraphQL API.
"""
registry['plugins']['graphql_schemas'].append(graphql_schema)
registry['plugins']['graphql_schemas'].extend(graphql_schema)
def register_user_preferences(plugin_name, preferences):

View File

@ -365,12 +365,11 @@ INSTALLED_APPS = [
'django.forms',
'corsheaders',
'debug_toolbar',
'graphiql_debug_toolbar',
'django_filters',
'django_htmx',
'django_tables2',
'django_prometheus',
'graphene_django',
'strawberry_django',
'mptt',
'rest_framework',
'social_django',
@ -398,7 +397,7 @@ if DJANGO_ADMIN_ENABLED:
# Middleware
MIDDLEWARE = [
'graphiql_debug_toolbar.middleware.DebugToolbarMiddleware',
"strawberry_django.middlewares.debug_toolbar.DebugToolbarMiddleware",
'django_prometheus.middleware.PrometheusBeforeMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
@ -674,17 +673,6 @@ SPECTACULAR_SETTINGS = {
'POSTPROCESSING_HOOKS': [],
}
#
# Graphene
#
GRAPHENE = {
# Avoids naming collision on models with 'type' field; see
# https://github.com/graphql-python/graphene-django/issues/185
'DJANGO_CHOICE_FIELD_ENUM_V3_NAMING': True,
}
#
# Django RQ (events backend)
#
@ -749,6 +737,13 @@ if not ENABLE_LOCALIZATION:
USE_I18N = False
USE_L10N = False
#
# Strawberry (GraphQL)
#
STRAWBERRY_DJANGO = {
"TYPE_DESCRIPTION_FROM_MODEL_DOCSTRING": True,
}
#
# Plugins
#

View File

@ -1,21 +1,26 @@
import graphene
from graphene_django import DjangoObjectType
from netbox.graphql.fields import ObjectField, ObjectListField
from typing import List
import strawberry
import strawberry_django
from . import models
class DummyModelType(DjangoObjectType):
class Meta:
model = models.DummyModel
fields = '__all__'
@strawberry_django.type(
models.DummyModel,
fields='__all__',
)
class DummyModelType:
pass
class DummyQuery(graphene.ObjectType):
dummymodel = ObjectField(DummyModelType)
dummymodel_list = ObjectListField(DummyModelType)
@strawberry.type
class DummyQuery:
@strawberry.field
def dummymodel(self, id: int) -> DummyModelType:
return None
dummymodel_list: List[DummyModelType] = strawberry_django.field()
schema = DummyQuery
schema = [
DummyQuery,
]

View File

@ -1,16 +1,16 @@
from django.conf import settings
from django.conf.urls import include
from django.urls import path
from django.views.decorators.csrf import csrf_exempt
from django.views.static import serve
from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView
from account.views import LoginView, LogoutView
from netbox.api.views import APIRootView, StatusView
from netbox.graphql.schema import schema
from netbox.graphql.views import GraphQLView
from netbox.graphql.views import NetBoxGraphQLView
from netbox.plugins.urls import plugin_patterns, plugin_api_patterns
from netbox.views import HomeView, StaticMediaFailureView, SearchView, htmx
from strawberry.django.views import GraphQLView
_patterns = [
@ -60,7 +60,7 @@ _patterns = [
path('api/schema/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='api_redocs'),
# GraphQL
path('graphql/', csrf_exempt(GraphQLView.as_view(graphiql=True, schema=schema)), name='graphql'),
path('graphql/', NetBoxGraphQLView.as_view(schema=schema), name='graphql'),
# Serving static media in Django to pipe it through LoginRequiredMiddleware
path('media/<path:path>', serve, {'document_root': settings.MEDIA_ROOT}),

View File

@ -1,5 +1,8 @@
const esbuild = require('esbuild');
const { sassPlugin } = require('esbuild-sass-plugin');
const util = require('util');
const fs = require('fs');
const copyFilePromise = util.promisify(fs.copyFile);
// Bundler options common to all bundle jobs.
const options = {
@ -14,24 +17,57 @@ const options = {
// Get CLI arguments for optional overrides.
const ARGS = process.argv.slice(2);
function copyFiles(files) {
return Promise.all(files.map(f => {
return copyFilePromise(f.source, f.dest);
}));
}
async function bundleGraphIQL() {
let fileMap = [
{
source: './node_modules/react/umd/react.production.min.js',
dest: './dist/graphiql/react.production.min.js'
},
{
source: './node_modules/react-dom/umd/react-dom.production.min.js',
dest: './dist/graphiql/react-dom.production.min.js'
},
{
source: './node_modules/js-cookie/dist/js.cookie.min.js',
dest: './dist/graphiql/js.cookie.min.js'
},
{
source: './node_modules/graphiql/graphiql.min.js',
dest: './dist/graphiql/graphiql.min.js'
},
{
source: './node_modules/@graphiql/plugin-explorer/dist/index.umd.js',
dest: './dist/graphiql/index.umd.js'
},
{
source: './node_modules/graphiql/graphiql.min.css',
dest: './dist/graphiql/graphiql.min.css'
},
{
source: './node_modules/@graphiql/plugin-explorer/dist/style.css',
dest: './dist/graphiql/plugin-explorer-style.css'
}
];
try {
const result = await esbuild.build({
...options,
entryPoints: {
graphiql: 'netbox-graphiql/index.ts',
},
target: 'es2016',
define: {
global: 'window',
},
});
if (result.errors.length === 0) {
console.log(`✅ Bundled source file 'netbox-graphiql/index.ts' to 'graphiql.js'`);
if (!fs.existsSync('./dist/graphiql/')) {
fs.mkdirSync('./dist/graphiql/');
}
} catch (err) {
console.error(err);
}
copyFiles(fileMap).then(() => {
console.log('✅ Copied graphiql files');
}).catch(err => {
console.error(err);
});
}
/**
@ -77,7 +113,6 @@ async function bundleStyles() {
'netbox': 'styles/netbox.scss',
rack_elevation: 'styles/svg/rack_elevation.scss',
cable_trace: 'styles/svg/cable_trace.scss',
graphiql: 'netbox-graphiql/graphiql.scss',
};
const pluginOptions = { outputStyle: 'compressed' };
// Allow cache disabling.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

83667
netbox/project-static/dist/graphiql.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
/*! js-cookie v3.0.5 | MIT */
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self,function(){var n=e.Cookies,o=e.Cookies=t();o.noConflict=function(){return e.Cookies=n,o}}())}(this,(function(){"use strict";function e(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)e[o]=n[o]}return e}var t=function t(n,o){function r(t,r,i){if("undefined"!=typeof document){"number"==typeof(i=e({},o,i)).expires&&(i.expires=new Date(Date.now()+864e5*i.expires)),i.expires&&(i.expires=i.expires.toUTCString()),t=encodeURIComponent(t).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape);var c="";for(var u in i)i[u]&&(c+="; "+u,!0!==i[u]&&(c+="="+i[u].split(";")[0]));return document.cookie=t+"="+n.write(r,t)+c}}return Object.create({set:r,get:function(e){if("undefined"!=typeof document&&(!arguments.length||e)){for(var t=document.cookie?document.cookie.split("; "):[],o={},r=0;r<t.length;r++){var i=t[r].split("="),c=i.slice(1).join("=");try{var u=decodeURIComponent(i[0]);if(o[u]=n.read(c,u),e===u)break}catch(e){}}return e?o[e]:o}},remove:function(t,n){r(t,"",e({},n,{expires:-1}))},withAttributes:function(n){return t(this.converter,e({},this.attributes,n))},withConverter:function(n){return t(e({},this.converter,n),this.attributes)}},{attributes:{value:Object.freeze(o)},converter:{value:Object.freeze(n)}})}({read:function(e){return'"'===e[0]&&(e=e.slice(1,-1)),e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)},write:function(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}},{path:"/"});return t}));

View File

@ -0,0 +1 @@
.docExplorerWrap{height:unset!important;min-width:unset!important;width:unset!important}.doc-explorer-title{font-size:var(--font-size-h2);font-weight:var(--font-weight-medium)}.doc-explorer-rhs{display:none}.graphiql-explorer-root{font-family:var(--font-family-mono)!important;font-size:var(--font-size-body)!important;padding:0!important}.graphiql-explorer-root>div:first-child{padding-left:var(--px-8);overflow:hidden!important}.graphiql-explorer-root input{background:hsl(var(--color-base))}.graphiql-explorer-root select{background-color:hsl(var(--color-base));border:1px solid hsla(var(--color-neutral),var(--alpha-secondary));border-radius:var(--border-radius-4);color:hsl(var(--color-neutral));margin:0 var(--px-4);padding:var(--px-4) var(--px-6)}

View File

@ -0,0 +1,267 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
(function(){/*
Modernizr 3.0.0pre (Custom Build) | MIT
*/
'use strict';(function(Q,mb){"object"===typeof exports&&"undefined"!==typeof module?mb(exports,require("react")):"function"===typeof define&&define.amd?define(["exports","react"],mb):(Q=Q||self,mb(Q.ReactDOM={},Q.React))})(this,function(Q,mb){function n(a){for(var b="https://reactjs.org/docs/error-decoder.html?invariant="+a,c=1;c<arguments.length;c++)b+="&args[]="+encodeURIComponent(arguments[c]);return"Minified React error #"+a+"; visit "+b+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}
function nb(a,b){Ab(a,b);Ab(a+"Capture",b)}function Ab(a,b){$b[a]=b;for(a=0;a<b.length;a++)cg.add(b[a])}function cj(a){if(Zd.call(dg,a))return!0;if(Zd.call(eg,a))return!1;if(dj.test(a))return dg[a]=!0;eg[a]=!0;return!1}function ej(a,b,c,d){if(null!==c&&0===c.type)return!1;switch(typeof b){case "function":case "symbol":return!0;case "boolean":if(d)return!1;if(null!==c)return!c.acceptsBooleans;a=a.toLowerCase().slice(0,5);return"data-"!==a&&"aria-"!==a;default:return!1}}function fj(a,b,c,d){if(null===
b||"undefined"===typeof b||ej(a,b,c,d))return!0;if(d)return!1;if(null!==c)switch(c.type){case 3:return!b;case 4:return!1===b;case 5:return isNaN(b);case 6:return isNaN(b)||1>b}return!1}function Y(a,b,c,d,e,f,g){this.acceptsBooleans=2===b||3===b||4===b;this.attributeName=d;this.attributeNamespace=e;this.mustUseProperty=c;this.propertyName=a;this.type=b;this.sanitizeURL=f;this.removeEmptyString=g}function $d(a,b,c,d){var e=R.hasOwnProperty(b)?R[b]:null;if(null!==e?0!==e.type:d||!(2<b.length)||"o"!==
b[0]&&"O"!==b[0]||"n"!==b[1]&&"N"!==b[1])fj(b,c,e,d)&&(c=null),d||null===e?cj(b)&&(null===c?a.removeAttribute(b):a.setAttribute(b,""+c)):e.mustUseProperty?a[e.propertyName]=null===c?3===e.type?!1:"":c:(b=e.attributeName,d=e.attributeNamespace,null===c?a.removeAttribute(b):(e=e.type,c=3===e||4===e&&!0===c?"":""+c,d?a.setAttributeNS(d,b,c):a.setAttribute(b,c)))}function ac(a){if(null===a||"object"!==typeof a)return null;a=fg&&a[fg]||a["@@iterator"];return"function"===typeof a?a:null}function bc(a,b,
c){if(void 0===ae)try{throw Error();}catch(d){ae=(b=d.stack.trim().match(/\n( *(at )?)/))&&b[1]||""}return"\n"+ae+a}function be(a,b){if(!a||ce)return"";ce=!0;var c=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(b)if(b=function(){throw Error();},Object.defineProperty(b.prototype,"props",{set:function(){throw Error();}}),"object"===typeof Reflect&&Reflect.construct){try{Reflect.construct(b,[])}catch(m){var d=m}Reflect.construct(a,[],b)}else{try{b.call()}catch(m){d=m}a.call(b.prototype)}else{try{throw Error();
}catch(m){d=m}a()}}catch(m){if(m&&d&&"string"===typeof m.stack){for(var e=m.stack.split("\n"),f=d.stack.split("\n"),g=e.length-1,h=f.length-1;1<=g&&0<=h&&e[g]!==f[h];)h--;for(;1<=g&&0<=h;g--,h--)if(e[g]!==f[h]){if(1!==g||1!==h){do if(g--,h--,0>h||e[g]!==f[h]){var k="\n"+e[g].replace(" at new "," at ");a.displayName&&k.includes("<anonymous>")&&(k=k.replace("<anonymous>",a.displayName));return k}while(1<=g&&0<=h)}break}}}finally{ce=!1,Error.prepareStackTrace=c}return(a=a?a.displayName||a.name:"")?bc(a):
""}function gj(a){switch(a.tag){case 5:return bc(a.type);case 16:return bc("Lazy");case 13:return bc("Suspense");case 19:return bc("SuspenseList");case 0:case 2:case 15:return a=be(a.type,!1),a;case 11:return a=be(a.type.render,!1),a;case 1:return a=be(a.type,!0),a;default:return""}}function de(a){if(null==a)return null;if("function"===typeof a)return a.displayName||a.name||null;if("string"===typeof a)return a;switch(a){case Bb:return"Fragment";case Cb:return"Portal";case ee:return"Profiler";case fe:return"StrictMode";
case ge:return"Suspense";case he:return"SuspenseList"}if("object"===typeof a)switch(a.$$typeof){case gg:return(a.displayName||"Context")+".Consumer";case hg:return(a._context.displayName||"Context")+".Provider";case ie:var b=a.render;a=a.displayName;a||(a=b.displayName||b.name||"",a=""!==a?"ForwardRef("+a+")":"ForwardRef");return a;case je:return b=a.displayName||null,null!==b?b:de(a.type)||"Memo";case Ta:b=a._payload;a=a._init;try{return de(a(b))}catch(c){}}return null}function hj(a){var b=a.type;
switch(a.tag){case 24:return"Cache";case 9:return(b.displayName||"Context")+".Consumer";case 10:return(b._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return a=b.render,a=a.displayName||a.name||"",b.displayName||(""!==a?"ForwardRef("+a+")":"ForwardRef");case 7:return"Fragment";case 5:return b;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return de(b);case 8:return b===fe?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";
case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if("function"===typeof b)return b.displayName||b.name||null;if("string"===typeof b)return b}return null}function Ua(a){switch(typeof a){case "boolean":case "number":case "string":case "undefined":return a;case "object":return a;default:return""}}function ig(a){var b=a.type;return(a=a.nodeName)&&"input"===a.toLowerCase()&&("checkbox"===b||"radio"===
b)}function ij(a){var b=ig(a)?"checked":"value",c=Object.getOwnPropertyDescriptor(a.constructor.prototype,b),d=""+a[b];if(!a.hasOwnProperty(b)&&"undefined"!==typeof c&&"function"===typeof c.get&&"function"===typeof c.set){var e=c.get,f=c.set;Object.defineProperty(a,b,{configurable:!0,get:function(){return e.call(this)},set:function(a){d=""+a;f.call(this,a)}});Object.defineProperty(a,b,{enumerable:c.enumerable});return{getValue:function(){return d},setValue:function(a){d=""+a},stopTracking:function(){a._valueTracker=
null;delete a[b]}}}}function Pc(a){a._valueTracker||(a._valueTracker=ij(a))}function jg(a){if(!a)return!1;var b=a._valueTracker;if(!b)return!0;var c=b.getValue();var d="";a&&(d=ig(a)?a.checked?"true":"false":a.value);a=d;return a!==c?(b.setValue(a),!0):!1}function Qc(a){a=a||("undefined"!==typeof document?document:void 0);if("undefined"===typeof a)return null;try{return a.activeElement||a.body}catch(b){return a.body}}function ke(a,b){var c=b.checked;return E({},b,{defaultChecked:void 0,defaultValue:void 0,
value:void 0,checked:null!=c?c:a._wrapperState.initialChecked})}function kg(a,b){var c=null==b.defaultValue?"":b.defaultValue,d=null!=b.checked?b.checked:b.defaultChecked;c=Ua(null!=b.value?b.value:c);a._wrapperState={initialChecked:d,initialValue:c,controlled:"checkbox"===b.type||"radio"===b.type?null!=b.checked:null!=b.value}}function lg(a,b){b=b.checked;null!=b&&$d(a,"checked",b,!1)}function le(a,b){lg(a,b);var c=Ua(b.value),d=b.type;if(null!=c)if("number"===d){if(0===c&&""===a.value||a.value!=
c)a.value=""+c}else a.value!==""+c&&(a.value=""+c);else if("submit"===d||"reset"===d){a.removeAttribute("value");return}b.hasOwnProperty("value")?me(a,b.type,c):b.hasOwnProperty("defaultValue")&&me(a,b.type,Ua(b.defaultValue));null==b.checked&&null!=b.defaultChecked&&(a.defaultChecked=!!b.defaultChecked)}function mg(a,b,c){if(b.hasOwnProperty("value")||b.hasOwnProperty("defaultValue")){var d=b.type;if(!("submit"!==d&&"reset"!==d||void 0!==b.value&&null!==b.value))return;b=""+a._wrapperState.initialValue;
c||b===a.value||(a.value=b);a.defaultValue=b}c=a.name;""!==c&&(a.name="");a.defaultChecked=!!a._wrapperState.initialChecked;""!==c&&(a.name=c)}function me(a,b,c){if("number"!==b||Qc(a.ownerDocument)!==a)null==c?a.defaultValue=""+a._wrapperState.initialValue:a.defaultValue!==""+c&&(a.defaultValue=""+c)}function Db(a,b,c,d){a=a.options;if(b){b={};for(var e=0;e<c.length;e++)b["$"+c[e]]=!0;for(c=0;c<a.length;c++)e=b.hasOwnProperty("$"+a[c].value),a[c].selected!==e&&(a[c].selected=e),e&&d&&(a[c].defaultSelected=
!0)}else{c=""+Ua(c);b=null;for(e=0;e<a.length;e++){if(a[e].value===c){a[e].selected=!0;d&&(a[e].defaultSelected=!0);return}null!==b||a[e].disabled||(b=a[e])}null!==b&&(b.selected=!0)}}function ne(a,b){if(null!=b.dangerouslySetInnerHTML)throw Error(n(91));return E({},b,{value:void 0,defaultValue:void 0,children:""+a._wrapperState.initialValue})}function ng(a,b){var c=b.value;if(null==c){c=b.children;b=b.defaultValue;if(null!=c){if(null!=b)throw Error(n(92));if(cc(c)){if(1<c.length)throw Error(n(93));
c=c[0]}b=c}null==b&&(b="");c=b}a._wrapperState={initialValue:Ua(c)}}function og(a,b){var c=Ua(b.value),d=Ua(b.defaultValue);null!=c&&(c=""+c,c!==a.value&&(a.value=c),null==b.defaultValue&&a.defaultValue!==c&&(a.defaultValue=c));null!=d&&(a.defaultValue=""+d)}function pg(a,b){b=a.textContent;b===a._wrapperState.initialValue&&""!==b&&null!==b&&(a.value=b)}function qg(a){switch(a){case "svg":return"http://www.w3.org/2000/svg";case "math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}
function oe(a,b){return null==a||"http://www.w3.org/1999/xhtml"===a?qg(b):"http://www.w3.org/2000/svg"===a&&"foreignObject"===b?"http://www.w3.org/1999/xhtml":a}function rg(a,b,c){return null==b||"boolean"===typeof b||""===b?"":c||"number"!==typeof b||0===b||dc.hasOwnProperty(a)&&dc[a]?(""+b).trim():b+"px"}function sg(a,b){a=a.style;for(var c in b)if(b.hasOwnProperty(c)){var d=0===c.indexOf("--"),e=rg(c,b[c],d);"float"===c&&(c="cssFloat");d?a.setProperty(c,e):a[c]=e}}function pe(a,b){if(b){if(jj[a]&&
(null!=b.children||null!=b.dangerouslySetInnerHTML))throw Error(n(137,a));if(null!=b.dangerouslySetInnerHTML){if(null!=b.children)throw Error(n(60));if("object"!==typeof b.dangerouslySetInnerHTML||!("__html"in b.dangerouslySetInnerHTML))throw Error(n(61));}if(null!=b.style&&"object"!==typeof b.style)throw Error(n(62));}}function qe(a,b){if(-1===a.indexOf("-"))return"string"===typeof b.is;switch(a){case "annotation-xml":case "color-profile":case "font-face":case "font-face-src":case "font-face-uri":case "font-face-format":case "font-face-name":case "missing-glyph":return!1;
default:return!0}}function re(a){a=a.target||a.srcElement||window;a.correspondingUseElement&&(a=a.correspondingUseElement);return 3===a.nodeType?a.parentNode:a}function tg(a){if(a=ec(a)){if("function"!==typeof se)throw Error(n(280));var b=a.stateNode;b&&(b=Rc(b),se(a.stateNode,a.type,b))}}function ug(a){Eb?Fb?Fb.push(a):Fb=[a]:Eb=a}function vg(){if(Eb){var a=Eb,b=Fb;Fb=Eb=null;tg(a);if(b)for(a=0;a<b.length;a++)tg(b[a])}}function wg(a,b,c){if(te)return a(b,c);te=!0;try{return xg(a,b,c)}finally{if(te=
!1,null!==Eb||null!==Fb)yg(),vg()}}function fc(a,b){var c=a.stateNode;if(null===c)return null;var d=Rc(c);if(null===d)return null;c=d[b];a:switch(b){case "onClick":case "onClickCapture":case "onDoubleClick":case "onDoubleClickCapture":case "onMouseDown":case "onMouseDownCapture":case "onMouseMove":case "onMouseMoveCapture":case "onMouseUp":case "onMouseUpCapture":case "onMouseEnter":(d=!d.disabled)||(a=a.type,d=!("button"===a||"input"===a||"select"===a||"textarea"===a));a=!d;break a;default:a=!1}if(a)return null;
if(c&&"function"!==typeof c)throw Error(n(231,b,typeof c));return c}function kj(a,b,c,d,e,f,g,h,k){gc=!1;Sc=null;lj.apply(mj,arguments)}function nj(a,b,c,d,e,f,g,h,k){kj.apply(this,arguments);if(gc){if(gc){var m=Sc;gc=!1;Sc=null}else throw Error(n(198));Tc||(Tc=!0,ue=m)}}function ob(a){var b=a,c=a;if(a.alternate)for(;b.return;)b=b.return;else{a=b;do b=a,0!==(b.flags&4098)&&(c=b.return),a=b.return;while(a)}return 3===b.tag?c:null}function zg(a){if(13===a.tag){var b=a.memoizedState;null===b&&(a=a.alternate,
null!==a&&(b=a.memoizedState));if(null!==b)return b.dehydrated}return null}function Ag(a){if(ob(a)!==a)throw Error(n(188));}function oj(a){var b=a.alternate;if(!b){b=ob(a);if(null===b)throw Error(n(188));return b!==a?null:a}for(var c=a,d=b;;){var e=c.return;if(null===e)break;var f=e.alternate;if(null===f){d=e.return;if(null!==d){c=d;continue}break}if(e.child===f.child){for(f=e.child;f;){if(f===c)return Ag(e),a;if(f===d)return Ag(e),b;f=f.sibling}throw Error(n(188));}if(c.return!==d.return)c=e,d=f;
else{for(var g=!1,h=e.child;h;){if(h===c){g=!0;c=e;d=f;break}if(h===d){g=!0;d=e;c=f;break}h=h.sibling}if(!g){for(h=f.child;h;){if(h===c){g=!0;c=f;d=e;break}if(h===d){g=!0;d=f;c=e;break}h=h.sibling}if(!g)throw Error(n(189));}}if(c.alternate!==d)throw Error(n(190));}if(3!==c.tag)throw Error(n(188));return c.stateNode.current===c?a:b}function Bg(a){a=oj(a);return null!==a?Cg(a):null}function Cg(a){if(5===a.tag||6===a.tag)return a;for(a=a.child;null!==a;){var b=Cg(a);if(null!==b)return b;a=a.sibling}return null}
function pj(a,b){if(Ca&&"function"===typeof Ca.onCommitFiberRoot)try{Ca.onCommitFiberRoot(Uc,a,void 0,128===(a.current.flags&128))}catch(c){}}function qj(a){a>>>=0;return 0===a?32:31-(rj(a)/sj|0)|0}function hc(a){switch(a&-a){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return a&
4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return a&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return a}}function Vc(a,b){var c=a.pendingLanes;if(0===c)return 0;var d=0,e=a.suspendedLanes,f=a.pingedLanes,g=c&268435455;if(0!==g){var h=g&~e;0!==h?d=hc(h):(f&=g,0!==f&&(d=hc(f)))}else g=c&~e,0!==g?d=hc(g):0!==f&&(d=hc(f));if(0===d)return 0;if(0!==b&&b!==d&&0===(b&e)&&
(e=d&-d,f=b&-b,e>=f||16===e&&0!==(f&4194240)))return b;0!==(d&4)&&(d|=c&16);b=a.entangledLanes;if(0!==b)for(a=a.entanglements,b&=d;0<b;)c=31-ta(b),e=1<<c,d|=a[c],b&=~e;return d}function tj(a,b){switch(a){case 1:case 2:case 4:return b+250;case 8:case 16:case 32:case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return b+5E3;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return-1;
case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function uj(a,b){for(var c=a.suspendedLanes,d=a.pingedLanes,e=a.expirationTimes,f=a.pendingLanes;0<f;){var g=31-ta(f),h=1<<g,k=e[g];if(-1===k){if(0===(h&c)||0!==(h&d))e[g]=tj(h,b)}else k<=b&&(a.expiredLanes|=h);f&=~h}}function ve(a){a=a.pendingLanes&-1073741825;return 0!==a?a:a&1073741824?1073741824:0}function Dg(){var a=Wc;Wc<<=1;0===(Wc&4194240)&&(Wc=64);return a}function we(a){for(var b=[],c=0;31>c;c++)b.push(a);
return b}function ic(a,b,c){a.pendingLanes|=b;536870912!==b&&(a.suspendedLanes=0,a.pingedLanes=0);a=a.eventTimes;b=31-ta(b);a[b]=c}function vj(a,b){var c=a.pendingLanes&~b;a.pendingLanes=b;a.suspendedLanes=0;a.pingedLanes=0;a.expiredLanes&=b;a.mutableReadLanes&=b;a.entangledLanes&=b;b=a.entanglements;var d=a.eventTimes;for(a=a.expirationTimes;0<c;){var e=31-ta(c),f=1<<e;b[e]=0;d[e]=-1;a[e]=-1;c&=~f}}function xe(a,b){var c=a.entangledLanes|=b;for(a=a.entanglements;c;){var d=31-ta(c),e=1<<d;e&b|a[d]&
b&&(a[d]|=b);c&=~e}}function Eg(a){a&=-a;return 1<a?4<a?0!==(a&268435455)?16:536870912:4:1}function Fg(a,b){switch(a){case "focusin":case "focusout":Va=null;break;case "dragenter":case "dragleave":Wa=null;break;case "mouseover":case "mouseout":Xa=null;break;case "pointerover":case "pointerout":jc.delete(b.pointerId);break;case "gotpointercapture":case "lostpointercapture":kc.delete(b.pointerId)}}function lc(a,b,c,d,e,f){if(null===a||a.nativeEvent!==f)return a={blockedOn:b,domEventName:c,eventSystemFlags:d,
nativeEvent:f,targetContainers:[e]},null!==b&&(b=ec(b),null!==b&&Gg(b)),a;a.eventSystemFlags|=d;b=a.targetContainers;null!==e&&-1===b.indexOf(e)&&b.push(e);return a}function wj(a,b,c,d,e){switch(b){case "focusin":return Va=lc(Va,a,b,c,d,e),!0;case "dragenter":return Wa=lc(Wa,a,b,c,d,e),!0;case "mouseover":return Xa=lc(Xa,a,b,c,d,e),!0;case "pointerover":var f=e.pointerId;jc.set(f,lc(jc.get(f)||null,a,b,c,d,e));return!0;case "gotpointercapture":return f=e.pointerId,kc.set(f,lc(kc.get(f)||null,a,b,
c,d,e)),!0}return!1}function Hg(a){var b=pb(a.target);if(null!==b){var c=ob(b);if(null!==c)if(b=c.tag,13===b){if(b=zg(c),null!==b){a.blockedOn=b;xj(a.priority,function(){yj(c)});return}}else if(3===b&&c.stateNode.current.memoizedState.isDehydrated){a.blockedOn=3===c.tag?c.stateNode.containerInfo:null;return}}a.blockedOn=null}function Xc(a){if(null!==a.blockedOn)return!1;for(var b=a.targetContainers;0<b.length;){var c=ye(a.domEventName,a.eventSystemFlags,b[0],a.nativeEvent);if(null===c){c=a.nativeEvent;
var d=new c.constructor(c.type,c);ze=d;c.target.dispatchEvent(d);ze=null}else return b=ec(c),null!==b&&Gg(b),a.blockedOn=c,!1;b.shift()}return!0}function Ig(a,b,c){Xc(a)&&c.delete(b)}function zj(){Ae=!1;null!==Va&&Xc(Va)&&(Va=null);null!==Wa&&Xc(Wa)&&(Wa=null);null!==Xa&&Xc(Xa)&&(Xa=null);jc.forEach(Ig);kc.forEach(Ig)}function mc(a,b){a.blockedOn===b&&(a.blockedOn=null,Ae||(Ae=!0,Jg(Kg,zj)))}function nc(a){if(0<Yc.length){mc(Yc[0],a);for(var b=1;b<Yc.length;b++){var c=Yc[b];c.blockedOn===a&&(c.blockedOn=
null)}}null!==Va&&mc(Va,a);null!==Wa&&mc(Wa,a);null!==Xa&&mc(Xa,a);b=function(b){return mc(b,a)};jc.forEach(b);kc.forEach(b);for(b=0;b<Ya.length;b++)c=Ya[b],c.blockedOn===a&&(c.blockedOn=null);for(;0<Ya.length&&(b=Ya[0],null===b.blockedOn);)Hg(b),null===b.blockedOn&&Ya.shift()}function Aj(a,b,c,d){var e=z,f=Gb.transition;Gb.transition=null;try{z=1,Be(a,b,c,d)}finally{z=e,Gb.transition=f}}function Bj(a,b,c,d){var e=z,f=Gb.transition;Gb.transition=null;try{z=4,Be(a,b,c,d)}finally{z=e,Gb.transition=
f}}function Be(a,b,c,d){if(Zc){var e=ye(a,b,c,d);if(null===e)Ce(a,b,d,$c,c),Fg(a,d);else if(wj(e,a,b,c,d))d.stopPropagation();else if(Fg(a,d),b&4&&-1<Cj.indexOf(a)){for(;null!==e;){var f=ec(e);null!==f&&Dj(f);f=ye(a,b,c,d);null===f&&Ce(a,b,d,$c,c);if(f===e)break;e=f}null!==e&&d.stopPropagation()}else Ce(a,b,d,null,c)}}function ye(a,b,c,d){$c=null;a=re(d);a=pb(a);if(null!==a)if(b=ob(a),null===b)a=null;else if(c=b.tag,13===c){a=zg(b);if(null!==a)return a;a=null}else if(3===c){if(b.stateNode.current.memoizedState.isDehydrated)return 3===
b.tag?b.stateNode.containerInfo:null;a=null}else b!==a&&(a=null);$c=a;return null}function Lg(a){switch(a){case "cancel":case "click":case "close":case "contextmenu":case "copy":case "cut":case "auxclick":case "dblclick":case "dragend":case "dragstart":case "drop":case "focusin":case "focusout":case "input":case "invalid":case "keydown":case "keypress":case "keyup":case "mousedown":case "mouseup":case "paste":case "pause":case "play":case "pointercancel":case "pointerdown":case "pointerup":case "ratechange":case "reset":case "resize":case "seeked":case "submit":case "touchcancel":case "touchend":case "touchstart":case "volumechange":case "change":case "selectionchange":case "textInput":case "compositionstart":case "compositionend":case "compositionupdate":case "beforeblur":case "afterblur":case "beforeinput":case "blur":case "fullscreenchange":case "focus":case "hashchange":case "popstate":case "select":case "selectstart":return 1;
case "drag":case "dragenter":case "dragexit":case "dragleave":case "dragover":case "mousemove":case "mouseout":case "mouseover":case "pointermove":case "pointerout":case "pointerover":case "scroll":case "toggle":case "touchmove":case "wheel":case "mouseenter":case "mouseleave":case "pointerenter":case "pointerleave":return 4;case "message":switch(Ej()){case De:return 1;case Mg:return 4;case ad:case Fj:return 16;case Ng:return 536870912;default:return 16}default:return 16}}function Og(){if(bd)return bd;
var a,b=Ee,c=b.length,d,e="value"in Za?Za.value:Za.textContent,f=e.length;for(a=0;a<c&&b[a]===e[a];a++);var g=c-a;for(d=1;d<=g&&b[c-d]===e[f-d];d++);return bd=e.slice(a,1<d?1-d:void 0)}function cd(a){var b=a.keyCode;"charCode"in a?(a=a.charCode,0===a&&13===b&&(a=13)):a=b;10===a&&(a=13);return 32<=a||13===a?a:0}function dd(){return!0}function Pg(){return!1}function ka(a){function b(b,d,e,f,g){this._reactName=b;this._targetInst=e;this.type=d;this.nativeEvent=f;this.target=g;this.currentTarget=null;
for(var c in a)a.hasOwnProperty(c)&&(b=a[c],this[c]=b?b(f):f[c]);this.isDefaultPrevented=(null!=f.defaultPrevented?f.defaultPrevented:!1===f.returnValue)?dd:Pg;this.isPropagationStopped=Pg;return this}E(b.prototype,{preventDefault:function(){this.defaultPrevented=!0;var a=this.nativeEvent;a&&(a.preventDefault?a.preventDefault():"unknown"!==typeof a.returnValue&&(a.returnValue=!1),this.isDefaultPrevented=dd)},stopPropagation:function(){var a=this.nativeEvent;a&&(a.stopPropagation?a.stopPropagation():
"unknown"!==typeof a.cancelBubble&&(a.cancelBubble=!0),this.isPropagationStopped=dd)},persist:function(){},isPersistent:dd});return b}function Gj(a){var b=this.nativeEvent;return b.getModifierState?b.getModifierState(a):(a=Hj[a])?!!b[a]:!1}function Fe(a){return Gj}function Qg(a,b){switch(a){case "keyup":return-1!==Ij.indexOf(b.keyCode);case "keydown":return 229!==b.keyCode;case "keypress":case "mousedown":case "focusout":return!0;default:return!1}}function Rg(a){a=a.detail;return"object"===typeof a&&
"data"in a?a.data:null}function Jj(a,b){switch(a){case "compositionend":return Rg(b);case "keypress":if(32!==b.which)return null;Sg=!0;return Tg;case "textInput":return a=b.data,a===Tg&&Sg?null:a;default:return null}}function Kj(a,b){if(Hb)return"compositionend"===a||!Ge&&Qg(a,b)?(a=Og(),bd=Ee=Za=null,Hb=!1,a):null;switch(a){case "paste":return null;case "keypress":if(!(b.ctrlKey||b.altKey||b.metaKey)||b.ctrlKey&&b.altKey){if(b.char&&1<b.char.length)return b.char;if(b.which)return String.fromCharCode(b.which)}return null;
case "compositionend":return Ug&&"ko"!==b.locale?null:b.data;default:return null}}function Vg(a){var b=a&&a.nodeName&&a.nodeName.toLowerCase();return"input"===b?!!Lj[a.type]:"textarea"===b?!0:!1}function Mj(a){if(!Ia)return!1;a="on"+a;var b=a in document;b||(b=document.createElement("div"),b.setAttribute(a,"return;"),b="function"===typeof b[a]);return b}function Wg(a,b,c,d){ug(d);b=ed(b,"onChange");0<b.length&&(c=new He("onChange","change",null,c,d),a.push({event:c,listeners:b}))}function Nj(a){Xg(a,
0)}function fd(a){var b=Ib(a);if(jg(b))return a}function Oj(a,b){if("change"===a)return b}function Yg(){oc&&(oc.detachEvent("onpropertychange",Zg),pc=oc=null)}function Zg(a){if("value"===a.propertyName&&fd(pc)){var b=[];Wg(b,pc,a,re(a));wg(Nj,b)}}function Pj(a,b,c){"focusin"===a?(Yg(),oc=b,pc=c,oc.attachEvent("onpropertychange",Zg)):"focusout"===a&&Yg()}function Qj(a,b){if("selectionchange"===a||"keyup"===a||"keydown"===a)return fd(pc)}function Rj(a,b){if("click"===a)return fd(b)}function Sj(a,b){if("input"===
a||"change"===a)return fd(b)}function Tj(a,b){return a===b&&(0!==a||1/a===1/b)||a!==a&&b!==b}function qc(a,b){if(ua(a,b))return!0;if("object"!==typeof a||null===a||"object"!==typeof b||null===b)return!1;var c=Object.keys(a),d=Object.keys(b);if(c.length!==d.length)return!1;for(d=0;d<c.length;d++){var e=c[d];if(!Zd.call(b,e)||!ua(a[e],b[e]))return!1}return!0}function $g(a){for(;a&&a.firstChild;)a=a.firstChild;return a}function ah(a,b){var c=$g(a);a=0;for(var d;c;){if(3===c.nodeType){d=a+c.textContent.length;
if(a<=b&&d>=b)return{node:c,offset:b-a};a=d}a:{for(;c;){if(c.nextSibling){c=c.nextSibling;break a}c=c.parentNode}c=void 0}c=$g(c)}}function bh(a,b){return a&&b?a===b?!0:a&&3===a.nodeType?!1:b&&3===b.nodeType?bh(a,b.parentNode):"contains"in a?a.contains(b):a.compareDocumentPosition?!!(a.compareDocumentPosition(b)&16):!1:!1}function ch(){for(var a=window,b=Qc();b instanceof a.HTMLIFrameElement;){try{var c="string"===typeof b.contentWindow.location.href}catch(d){c=!1}if(c)a=b.contentWindow;else break;
b=Qc(a.document)}return b}function Ie(a){var b=a&&a.nodeName&&a.nodeName.toLowerCase();return b&&("input"===b&&("text"===a.type||"search"===a.type||"tel"===a.type||"url"===a.type||"password"===a.type)||"textarea"===b||"true"===a.contentEditable)}function Uj(a){var b=ch(),c=a.focusedElem,d=a.selectionRange;if(b!==c&&c&&c.ownerDocument&&bh(c.ownerDocument.documentElement,c)){if(null!==d&&Ie(c))if(b=d.start,a=d.end,void 0===a&&(a=b),"selectionStart"in c)c.selectionStart=b,c.selectionEnd=Math.min(a,c.value.length);
else if(a=(b=c.ownerDocument||document)&&b.defaultView||window,a.getSelection){a=a.getSelection();var e=c.textContent.length,f=Math.min(d.start,e);d=void 0===d.end?f:Math.min(d.end,e);!a.extend&&f>d&&(e=d,d=f,f=e);e=ah(c,f);var g=ah(c,d);e&&g&&(1!==a.rangeCount||a.anchorNode!==e.node||a.anchorOffset!==e.offset||a.focusNode!==g.node||a.focusOffset!==g.offset)&&(b=b.createRange(),b.setStart(e.node,e.offset),a.removeAllRanges(),f>d?(a.addRange(b),a.extend(g.node,g.offset)):(b.setEnd(g.node,g.offset),
a.addRange(b)))}b=[];for(a=c;a=a.parentNode;)1===a.nodeType&&b.push({element:a,left:a.scrollLeft,top:a.scrollTop});"function"===typeof c.focus&&c.focus();for(c=0;c<b.length;c++)a=b[c],a.element.scrollLeft=a.left,a.element.scrollTop=a.top}}function dh(a,b,c){var d=c.window===c?c.document:9===c.nodeType?c:c.ownerDocument;Je||null==Jb||Jb!==Qc(d)||(d=Jb,"selectionStart"in d&&Ie(d)?d={start:d.selectionStart,end:d.selectionEnd}:(d=(d.ownerDocument&&d.ownerDocument.defaultView||window).getSelection(),d=
{anchorNode:d.anchorNode,anchorOffset:d.anchorOffset,focusNode:d.focusNode,focusOffset:d.focusOffset}),rc&&qc(rc,d)||(rc=d,d=ed(Ke,"onSelect"),0<d.length&&(b=new He("onSelect","select",null,b,c),a.push({event:b,listeners:d}),b.target=Jb)))}function gd(a,b){var c={};c[a.toLowerCase()]=b.toLowerCase();c["Webkit"+a]="webkit"+b;c["Moz"+a]="moz"+b;return c}function hd(a){if(Le[a])return Le[a];if(!Kb[a])return a;var b=Kb[a],c;for(c in b)if(b.hasOwnProperty(c)&&c in eh)return Le[a]=b[c];return a}function $a(a,
b){fh.set(a,b);nb(b,[a])}function gh(a,b,c){var d=a.type||"unknown-event";a.currentTarget=c;nj(d,b,void 0,a);a.currentTarget=null}function Xg(a,b){b=0!==(b&4);for(var c=0;c<a.length;c++){var d=a[c],e=d.event;d=d.listeners;a:{var f=void 0;if(b)for(var g=d.length-1;0<=g;g--){var h=d[g],k=h.instance,m=h.currentTarget;h=h.listener;if(k!==f&&e.isPropagationStopped())break a;gh(e,h,m);f=k}else for(g=0;g<d.length;g++){h=d[g];k=h.instance;m=h.currentTarget;h=h.listener;if(k!==f&&e.isPropagationStopped())break a;
gh(e,h,m);f=k}}}if(Tc)throw a=ue,Tc=!1,ue=null,a;}function B(a,b){var c=b[Me];void 0===c&&(c=b[Me]=new Set);var d=a+"__bubble";c.has(d)||(hh(b,a,2,!1),c.add(d))}function Ne(a,b,c){var d=0;b&&(d|=4);hh(c,a,d,b)}function sc(a){if(!a[id]){a[id]=!0;cg.forEach(function(b){"selectionchange"!==b&&(Vj.has(b)||Ne(b,!1,a),Ne(b,!0,a))});var b=9===a.nodeType?a:a.ownerDocument;null===b||b[id]||(b[id]=!0,Ne("selectionchange",!1,b))}}function hh(a,b,c,d,e){switch(Lg(b)){case 1:e=Aj;break;case 4:e=Bj;break;default:e=
Be}c=e.bind(null,b,c,a);e=void 0;!Oe||"touchstart"!==b&&"touchmove"!==b&&"wheel"!==b||(e=!0);d?void 0!==e?a.addEventListener(b,c,{capture:!0,passive:e}):a.addEventListener(b,c,!0):void 0!==e?a.addEventListener(b,c,{passive:e}):a.addEventListener(b,c,!1)}function Ce(a,b,c,d,e){var f=d;if(0===(b&1)&&0===(b&2)&&null!==d)a:for(;;){if(null===d)return;var g=d.tag;if(3===g||4===g){var h=d.stateNode.containerInfo;if(h===e||8===h.nodeType&&h.parentNode===e)break;if(4===g)for(g=d.return;null!==g;){var k=g.tag;
if(3===k||4===k)if(k=g.stateNode.containerInfo,k===e||8===k.nodeType&&k.parentNode===e)return;g=g.return}for(;null!==h;){g=pb(h);if(null===g)return;k=g.tag;if(5===k||6===k){d=f=g;continue a}h=h.parentNode}}d=d.return}wg(function(){var d=f,e=re(c),g=[];a:{var h=fh.get(a);if(void 0!==h){var k=He,n=a;switch(a){case "keypress":if(0===cd(c))break a;case "keydown":case "keyup":k=Wj;break;case "focusin":n="focus";k=Pe;break;case "focusout":n="blur";k=Pe;break;case "beforeblur":case "afterblur":k=Pe;break;
case "click":if(2===c.button)break a;case "auxclick":case "dblclick":case "mousedown":case "mousemove":case "mouseup":case "mouseout":case "mouseover":case "contextmenu":k=ih;break;case "drag":case "dragend":case "dragenter":case "dragexit":case "dragleave":case "dragover":case "dragstart":case "drop":k=Xj;break;case "touchcancel":case "touchend":case "touchmove":case "touchstart":k=Yj;break;case jh:case kh:case lh:k=Zj;break;case mh:k=ak;break;case "scroll":k=bk;break;case "wheel":k=ck;break;case "copy":case "cut":case "paste":k=
dk;break;case "gotpointercapture":case "lostpointercapture":case "pointercancel":case "pointerdown":case "pointermove":case "pointerout":case "pointerover":case "pointerup":k=nh}var l=0!==(b&4),p=!l&&"scroll"===a,A=l?null!==h?h+"Capture":null:h;l=[];for(var v=d,q;null!==v;){q=v;var M=q.stateNode;5===q.tag&&null!==M&&(q=M,null!==A&&(M=fc(v,A),null!=M&&l.push(tc(v,M,q))));if(p)break;v=v.return}0<l.length&&(h=new k(h,n,null,c,e),g.push({event:h,listeners:l}))}}if(0===(b&7)){a:{h="mouseover"===a||"pointerover"===
a;k="mouseout"===a||"pointerout"===a;if(h&&c!==ze&&(n=c.relatedTarget||c.fromElement)&&(pb(n)||n[Ja]))break a;if(k||h){h=e.window===e?e:(h=e.ownerDocument)?h.defaultView||h.parentWindow:window;if(k){if(n=c.relatedTarget||c.toElement,k=d,n=n?pb(n):null,null!==n&&(p=ob(n),n!==p||5!==n.tag&&6!==n.tag))n=null}else k=null,n=d;if(k!==n){l=ih;M="onMouseLeave";A="onMouseEnter";v="mouse";if("pointerout"===a||"pointerover"===a)l=nh,M="onPointerLeave",A="onPointerEnter",v="pointer";p=null==k?h:Ib(k);q=null==
n?h:Ib(n);h=new l(M,v+"leave",k,c,e);h.target=p;h.relatedTarget=q;M=null;pb(e)===d&&(l=new l(A,v+"enter",n,c,e),l.target=q,l.relatedTarget=p,M=l);p=M;if(k&&n)b:{l=k;A=n;v=0;for(q=l;q;q=Lb(q))v++;q=0;for(M=A;M;M=Lb(M))q++;for(;0<v-q;)l=Lb(l),v--;for(;0<q-v;)A=Lb(A),q--;for(;v--;){if(l===A||null!==A&&l===A.alternate)break b;l=Lb(l);A=Lb(A)}l=null}else l=null;null!==k&&oh(g,h,k,l,!1);null!==n&&null!==p&&oh(g,p,n,l,!0)}}}a:{h=d?Ib(d):window;k=h.nodeName&&h.nodeName.toLowerCase();if("select"===k||"input"===
k&&"file"===h.type)var ma=Oj;else if(Vg(h))if(ph)ma=Sj;else{ma=Qj;var va=Pj}else(k=h.nodeName)&&"input"===k.toLowerCase()&&("checkbox"===h.type||"radio"===h.type)&&(ma=Rj);if(ma&&(ma=ma(a,d))){Wg(g,ma,c,e);break a}va&&va(a,h,d);"focusout"===a&&(va=h._wrapperState)&&va.controlled&&"number"===h.type&&me(h,"number",h.value)}va=d?Ib(d):window;switch(a){case "focusin":if(Vg(va)||"true"===va.contentEditable)Jb=va,Ke=d,rc=null;break;case "focusout":rc=Ke=Jb=null;break;case "mousedown":Je=!0;break;case "contextmenu":case "mouseup":case "dragend":Je=
!1;dh(g,c,e);break;case "selectionchange":if(ek)break;case "keydown":case "keyup":dh(g,c,e)}var ab;if(Ge)b:{switch(a){case "compositionstart":var da="onCompositionStart";break b;case "compositionend":da="onCompositionEnd";break b;case "compositionupdate":da="onCompositionUpdate";break b}da=void 0}else Hb?Qg(a,c)&&(da="onCompositionEnd"):"keydown"===a&&229===c.keyCode&&(da="onCompositionStart");da&&(Ug&&"ko"!==c.locale&&(Hb||"onCompositionStart"!==da?"onCompositionEnd"===da&&Hb&&(ab=Og()):(Za=e,Ee=
"value"in Za?Za.value:Za.textContent,Hb=!0)),va=ed(d,da),0<va.length&&(da=new qh(da,a,null,c,e),g.push({event:da,listeners:va}),ab?da.data=ab:(ab=Rg(c),null!==ab&&(da.data=ab))));if(ab=fk?Jj(a,c):Kj(a,c))d=ed(d,"onBeforeInput"),0<d.length&&(e=new gk("onBeforeInput","beforeinput",null,c,e),g.push({event:e,listeners:d}),e.data=ab)}Xg(g,b)})}function tc(a,b,c){return{instance:a,listener:b,currentTarget:c}}function ed(a,b){for(var c=b+"Capture",d=[];null!==a;){var e=a,f=e.stateNode;5===e.tag&&null!==
f&&(e=f,f=fc(a,c),null!=f&&d.unshift(tc(a,f,e)),f=fc(a,b),null!=f&&d.push(tc(a,f,e)));a=a.return}return d}function Lb(a){if(null===a)return null;do a=a.return;while(a&&5!==a.tag);return a?a:null}function oh(a,b,c,d,e){for(var f=b._reactName,g=[];null!==c&&c!==d;){var h=c,k=h.alternate,m=h.stateNode;if(null!==k&&k===d)break;5===h.tag&&null!==m&&(h=m,e?(k=fc(c,f),null!=k&&g.unshift(tc(c,k,h))):e||(k=fc(c,f),null!=k&&g.push(tc(c,k,h))));c=c.return}0!==g.length&&a.push({event:b,listeners:g})}function rh(a){return("string"===
typeof a?a:""+a).replace(hk,"\n").replace(ik,"")}function jd(a,b,c,d){b=rh(b);if(rh(a)!==b&&c)throw Error(n(425));}function kd(){}function Qe(a,b){return"textarea"===a||"noscript"===a||"string"===typeof b.children||"number"===typeof b.children||"object"===typeof b.dangerouslySetInnerHTML&&null!==b.dangerouslySetInnerHTML&&null!=b.dangerouslySetInnerHTML.__html}function jk(a){setTimeout(function(){throw a;})}function Re(a,b){var c=b,d=0;do{var e=c.nextSibling;a.removeChild(c);if(e&&8===e.nodeType)if(c=
e.data,"/$"===c){if(0===d){a.removeChild(e);nc(b);return}d--}else"$"!==c&&"$?"!==c&&"$!"!==c||d++;c=e}while(c);nc(b)}function Ka(a){for(;null!=a;a=a.nextSibling){var b=a.nodeType;if(1===b||3===b)break;if(8===b){b=a.data;if("$"===b||"$!"===b||"$?"===b)break;if("/$"===b)return null}}return a}function sh(a){a=a.previousSibling;for(var b=0;a;){if(8===a.nodeType){var c=a.data;if("$"===c||"$!"===c||"$?"===c){if(0===b)return a;b--}else"/$"===c&&b++}a=a.previousSibling}return null}function pb(a){var b=a[Da];
if(b)return b;for(var c=a.parentNode;c;){if(b=c[Ja]||c[Da]){c=b.alternate;if(null!==b.child||null!==c&&null!==c.child)for(a=sh(a);null!==a;){if(c=a[Da])return c;a=sh(a)}return b}a=c;c=a.parentNode}return null}function ec(a){a=a[Da]||a[Ja];return!a||5!==a.tag&&6!==a.tag&&13!==a.tag&&3!==a.tag?null:a}function Ib(a){if(5===a.tag||6===a.tag)return a.stateNode;throw Error(n(33));}function Rc(a){return a[uc]||null}function bb(a){return{current:a}}function w(a,b){0>Mb||(a.current=Se[Mb],Se[Mb]=null,Mb--)}
function y(a,b,c){Mb++;Se[Mb]=a.current;a.current=b}function Nb(a,b){var c=a.type.contextTypes;if(!c)return cb;var d=a.stateNode;if(d&&d.__reactInternalMemoizedUnmaskedChildContext===b)return d.__reactInternalMemoizedMaskedChildContext;var e={},f;for(f in c)e[f]=b[f];d&&(a=a.stateNode,a.__reactInternalMemoizedUnmaskedChildContext=b,a.__reactInternalMemoizedMaskedChildContext=e);return e}function ea(a){a=a.childContextTypes;return null!==a&&void 0!==a}function th(a,b,c){if(J.current!==cb)throw Error(n(168));
y(J,b);y(S,c)}function uh(a,b,c){var d=a.stateNode;b=b.childContextTypes;if("function"!==typeof d.getChildContext)return c;d=d.getChildContext();for(var e in d)if(!(e in b))throw Error(n(108,hj(a)||"Unknown",e));return E({},c,d)}function ld(a){a=(a=a.stateNode)&&a.__reactInternalMemoizedMergedChildContext||cb;qb=J.current;y(J,a);y(S,S.current);return!0}function vh(a,b,c){var d=a.stateNode;if(!d)throw Error(n(169));c?(a=uh(a,b,qb),d.__reactInternalMemoizedMergedChildContext=a,w(S),w(J),y(J,a)):w(S);
y(S,c)}function wh(a){null===La?La=[a]:La.push(a)}function kk(a){md=!0;wh(a)}function db(){if(!Te&&null!==La){Te=!0;var a=0,b=z;try{var c=La;for(z=1;a<c.length;a++){var d=c[a];do d=d(!0);while(null!==d)}La=null;md=!1}catch(e){throw null!==La&&(La=La.slice(a+1)),xh(De,db),e;}finally{z=b,Te=!1}}return null}function rb(a,b){Ob[Pb++]=nd;Ob[Pb++]=od;od=a;nd=b}function yh(a,b,c){na[oa++]=Ma;na[oa++]=Na;na[oa++]=sb;sb=a;var d=Ma;a=Na;var e=32-ta(d)-1;d&=~(1<<e);c+=1;var f=32-ta(b)+e;if(30<f){var g=e-e%5;
f=(d&(1<<g)-1).toString(32);d>>=g;e-=g;Ma=1<<32-ta(b)+e|c<<e|d;Na=f+a}else Ma=1<<f|c<<e|d,Na=a}function Ue(a){null!==a.return&&(rb(a,1),yh(a,1,0))}function Ve(a){for(;a===od;)od=Ob[--Pb],Ob[Pb]=null,nd=Ob[--Pb],Ob[Pb]=null;for(;a===sb;)sb=na[--oa],na[oa]=null,Na=na[--oa],na[oa]=null,Ma=na[--oa],na[oa]=null}function zh(a,b){var c=pa(5,null,null,0);c.elementType="DELETED";c.stateNode=b;c.return=a;b=a.deletions;null===b?(a.deletions=[c],a.flags|=16):b.push(c)}function Ah(a,b){switch(a.tag){case 5:var c=
a.type;b=1!==b.nodeType||c.toLowerCase()!==b.nodeName.toLowerCase()?null:b;return null!==b?(a.stateNode=b,la=a,fa=Ka(b.firstChild),!0):!1;case 6:return b=""===a.pendingProps||3!==b.nodeType?null:b,null!==b?(a.stateNode=b,la=a,fa=null,!0):!1;case 13:return b=8!==b.nodeType?null:b,null!==b?(c=null!==sb?{id:Ma,overflow:Na}:null,a.memoizedState={dehydrated:b,treeContext:c,retryLane:1073741824},c=pa(18,null,null,0),c.stateNode=b,c.return=a,a.child=c,la=a,fa=null,!0):!1;default:return!1}}function We(a){return 0!==
(a.mode&1)&&0===(a.flags&128)}function Xe(a){if(D){var b=fa;if(b){var c=b;if(!Ah(a,b)){if(We(a))throw Error(n(418));b=Ka(c.nextSibling);var d=la;b&&Ah(a,b)?zh(d,c):(a.flags=a.flags&-4097|2,D=!1,la=a)}}else{if(We(a))throw Error(n(418));a.flags=a.flags&-4097|2;D=!1;la=a}}}function Bh(a){for(a=a.return;null!==a&&5!==a.tag&&3!==a.tag&&13!==a.tag;)a=a.return;la=a}function pd(a){if(a!==la)return!1;if(!D)return Bh(a),D=!0,!1;var b;(b=3!==a.tag)&&!(b=5!==a.tag)&&(b=a.type,b="head"!==b&&"body"!==b&&!Qe(a.type,
a.memoizedProps));if(b&&(b=fa)){if(We(a)){for(a=fa;a;)a=Ka(a.nextSibling);throw Error(n(418));}for(;b;)zh(a,b),b=Ka(b.nextSibling)}Bh(a);if(13===a.tag){a=a.memoizedState;a=null!==a?a.dehydrated:null;if(!a)throw Error(n(317));a:{a=a.nextSibling;for(b=0;a;){if(8===a.nodeType){var c=a.data;if("/$"===c){if(0===b){fa=Ka(a.nextSibling);break a}b--}else"$"!==c&&"$!"!==c&&"$?"!==c||b++}a=a.nextSibling}fa=null}}else fa=la?Ka(a.stateNode.nextSibling):null;return!0}function Qb(){fa=la=null;D=!1}function Ye(a){null===
wa?wa=[a]:wa.push(a)}function xa(a,b){if(a&&a.defaultProps){b=E({},b);a=a.defaultProps;for(var c in a)void 0===b[c]&&(b[c]=a[c]);return b}return b}function Ze(){$e=Rb=qd=null}function af(a,b){b=rd.current;w(rd);a._currentValue=b}function bf(a,b,c){for(;null!==a;){var d=a.alternate;(a.childLanes&b)!==b?(a.childLanes|=b,null!==d&&(d.childLanes|=b)):null!==d&&(d.childLanes&b)!==b&&(d.childLanes|=b);if(a===c)break;a=a.return}}function Sb(a,b){qd=a;$e=Rb=null;a=a.dependencies;null!==a&&null!==a.firstContext&&
(0!==(a.lanes&b)&&(ha=!0),a.firstContext=null)}function qa(a){var b=a._currentValue;if($e!==a)if(a={context:a,memoizedValue:b,next:null},null===Rb){if(null===qd)throw Error(n(308));Rb=a;qd.dependencies={lanes:0,firstContext:a}}else Rb=Rb.next=a;return b}function cf(a){null===tb?tb=[a]:tb.push(a)}function Ch(a,b,c,d){var e=b.interleaved;null===e?(c.next=c,cf(b)):(c.next=e.next,e.next=c);b.interleaved=c;return Oa(a,d)}function Oa(a,b){a.lanes|=b;var c=a.alternate;null!==c&&(c.lanes|=b);c=a;for(a=a.return;null!==
a;)a.childLanes|=b,c=a.alternate,null!==c&&(c.childLanes|=b),c=a,a=a.return;return 3===c.tag?c.stateNode:null}function df(a){a.updateQueue={baseState:a.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function Dh(a,b){a=a.updateQueue;b.updateQueue===a&&(b.updateQueue={baseState:a.baseState,firstBaseUpdate:a.firstBaseUpdate,lastBaseUpdate:a.lastBaseUpdate,shared:a.shared,effects:a.effects})}function Pa(a,b){return{eventTime:a,lane:b,
tag:0,payload:null,callback:null,next:null}}function eb(a,b,c){var d=a.updateQueue;if(null===d)return null;d=d.shared;if(0!==(p&2)){var e=d.pending;null===e?b.next=b:(b.next=e.next,e.next=b);d.pending=b;return lk(a,c)}e=d.interleaved;null===e?(b.next=b,cf(d)):(b.next=e.next,e.next=b);d.interleaved=b;return Oa(a,c)}function sd(a,b,c){b=b.updateQueue;if(null!==b&&(b=b.shared,0!==(c&4194240))){var d=b.lanes;d&=a.pendingLanes;c|=d;b.lanes=c;xe(a,c)}}function Eh(a,b){var c=a.updateQueue,d=a.alternate;
if(null!==d&&(d=d.updateQueue,c===d)){var e=null,f=null;c=c.firstBaseUpdate;if(null!==c){do{var g={eventTime:c.eventTime,lane:c.lane,tag:c.tag,payload:c.payload,callback:c.callback,next:null};null===f?e=f=g:f=f.next=g;c=c.next}while(null!==c);null===f?e=f=b:f=f.next=b}else e=f=b;c={baseState:d.baseState,firstBaseUpdate:e,lastBaseUpdate:f,shared:d.shared,effects:d.effects};a.updateQueue=c;return}a=c.lastBaseUpdate;null===a?c.firstBaseUpdate=b:a.next=b;c.lastBaseUpdate=b}function td(a,b,c,d){var e=
a.updateQueue;fb=!1;var f=e.firstBaseUpdate,g=e.lastBaseUpdate,h=e.shared.pending;if(null!==h){e.shared.pending=null;var k=h,m=k.next;k.next=null;null===g?f=m:g.next=m;g=k;var n=a.alternate;null!==n&&(n=n.updateQueue,h=n.lastBaseUpdate,h!==g&&(null===h?n.firstBaseUpdate=m:h.next=m,n.lastBaseUpdate=k))}if(null!==f){var l=e.baseState;g=0;n=m=k=null;h=f;do{var r=h.lane,p=h.eventTime;if((d&r)===r){null!==n&&(n=n.next={eventTime:p,lane:0,tag:h.tag,payload:h.payload,callback:h.callback,next:null});a:{var x=
a,F=h;r=b;p=c;switch(F.tag){case 1:x=F.payload;if("function"===typeof x){l=x.call(p,l,r);break a}l=x;break a;case 3:x.flags=x.flags&-65537|128;case 0:x=F.payload;r="function"===typeof x?x.call(p,l,r):x;if(null===r||void 0===r)break a;l=E({},l,r);break a;case 2:fb=!0}}null!==h.callback&&0!==h.lane&&(a.flags|=64,r=e.effects,null===r?e.effects=[h]:r.push(h))}else p={eventTime:p,lane:r,tag:h.tag,payload:h.payload,callback:h.callback,next:null},null===n?(m=n=p,k=l):n=n.next=p,g|=r;h=h.next;if(null===h)if(h=
e.shared.pending,null===h)break;else r=h,h=r.next,r.next=null,e.lastBaseUpdate=r,e.shared.pending=null}while(1);null===n&&(k=l);e.baseState=k;e.firstBaseUpdate=m;e.lastBaseUpdate=n;b=e.shared.interleaved;if(null!==b){e=b;do g|=e.lane,e=e.next;while(e!==b)}else null===f&&(e.shared.lanes=0);ra|=g;a.lanes=g;a.memoizedState=l}}function Fh(a,b,c){a=b.effects;b.effects=null;if(null!==a)for(b=0;b<a.length;b++){var d=a[b],e=d.callback;if(null!==e){d.callback=null;d=c;if("function"!==typeof e)throw Error(n(191,
e));e.call(d)}}}function ef(a,b,c,d){b=a.memoizedState;c=c(d,b);c=null===c||void 0===c?b:E({},b,c);a.memoizedState=c;0===a.lanes&&(a.updateQueue.baseState=c)}function Gh(a,b,c,d,e,f,g){a=a.stateNode;return"function"===typeof a.shouldComponentUpdate?a.shouldComponentUpdate(d,f,g):b.prototype&&b.prototype.isPureReactComponent?!qc(c,d)||!qc(e,f):!0}function Hh(a,b,c){var d=!1,e=cb;var f=b.contextType;"object"===typeof f&&null!==f?f=qa(f):(e=ea(b)?qb:J.current,d=b.contextTypes,f=(d=null!==d&&void 0!==
d)?Nb(a,e):cb);b=new b(c,f);a.memoizedState=null!==b.state&&void 0!==b.state?b.state:null;b.updater=ud;a.stateNode=b;b._reactInternals=a;d&&(a=a.stateNode,a.__reactInternalMemoizedUnmaskedChildContext=e,a.__reactInternalMemoizedMaskedChildContext=f);return b}function Ih(a,b,c,d){a=b.state;"function"===typeof b.componentWillReceiveProps&&b.componentWillReceiveProps(c,d);"function"===typeof b.UNSAFE_componentWillReceiveProps&&b.UNSAFE_componentWillReceiveProps(c,d);b.state!==a&&ud.enqueueReplaceState(b,
b.state,null)}function ff(a,b,c,d){var e=a.stateNode;e.props=c;e.state=a.memoizedState;e.refs=Jh;df(a);var f=b.contextType;"object"===typeof f&&null!==f?e.context=qa(f):(f=ea(b)?qb:J.current,e.context=Nb(a,f));e.state=a.memoizedState;f=b.getDerivedStateFromProps;"function"===typeof f&&(ef(a,b,f,c),e.state=a.memoizedState);"function"===typeof b.getDerivedStateFromProps||"function"===typeof e.getSnapshotBeforeUpdate||"function"!==typeof e.UNSAFE_componentWillMount&&"function"!==typeof e.componentWillMount||
(b=e.state,"function"===typeof e.componentWillMount&&e.componentWillMount(),"function"===typeof e.UNSAFE_componentWillMount&&e.UNSAFE_componentWillMount(),b!==e.state&&ud.enqueueReplaceState(e,e.state,null),td(a,c,e,d),e.state=a.memoizedState);"function"===typeof e.componentDidMount&&(a.flags|=4194308)}function vc(a,b,c){a=c.ref;if(null!==a&&"function"!==typeof a&&"object"!==typeof a){if(c._owner){c=c._owner;if(c){if(1!==c.tag)throw Error(n(309));var d=c.stateNode}if(!d)throw Error(n(147,a));var e=
d,f=""+a;if(null!==b&&null!==b.ref&&"function"===typeof b.ref&&b.ref._stringRef===f)return b.ref;b=function(a){var b=e.refs;b===Jh&&(b=e.refs={});null===a?delete b[f]:b[f]=a};b._stringRef=f;return b}if("string"!==typeof a)throw Error(n(284));if(!c._owner)throw Error(n(290,a));}return a}function vd(a,b){a=Object.prototype.toString.call(b);throw Error(n(31,"[object Object]"===a?"object with keys {"+Object.keys(b).join(", ")+"}":a));}function Kh(a){var b=a._init;return b(a._payload)}function Lh(a){function b(b,
c){if(a){var d=b.deletions;null===d?(b.deletions=[c],b.flags|=16):d.push(c)}}function c(c,d){if(!a)return null;for(;null!==d;)b(c,d),d=d.sibling;return null}function d(a,b){for(a=new Map;null!==b;)null!==b.key?a.set(b.key,b):a.set(b.index,b),b=b.sibling;return a}function e(a,b){a=gb(a,b);a.index=0;a.sibling=null;return a}function f(b,c,d){b.index=d;if(!a)return b.flags|=1048576,c;d=b.alternate;if(null!==d)return d=d.index,d<c?(b.flags|=2,c):d;b.flags|=2;return c}function g(b){a&&null===b.alternate&&
(b.flags|=2);return b}function h(a,b,c,d){if(null===b||6!==b.tag)return b=gf(c,a.mode,d),b.return=a,b;b=e(b,c);b.return=a;return b}function k(a,b,c,d){var f=c.type;if(f===Bb)return l(a,b,c.props.children,d,c.key);if(null!==b&&(b.elementType===f||"object"===typeof f&&null!==f&&f.$$typeof===Ta&&Kh(f)===b.type))return d=e(b,c.props),d.ref=vc(a,b,c),d.return=a,d;d=wd(c.type,c.key,c.props,null,a.mode,d);d.ref=vc(a,b,c);d.return=a;return d}function m(a,b,c,d){if(null===b||4!==b.tag||b.stateNode.containerInfo!==
c.containerInfo||b.stateNode.implementation!==c.implementation)return b=hf(c,a.mode,d),b.return=a,b;b=e(b,c.children||[]);b.return=a;return b}function l(a,b,c,d,f){if(null===b||7!==b.tag)return b=ub(c,a.mode,d,f),b.return=a,b;b=e(b,c);b.return=a;return b}function u(a,b,c){if("string"===typeof b&&""!==b||"number"===typeof b)return b=gf(""+b,a.mode,c),b.return=a,b;if("object"===typeof b&&null!==b){switch(b.$$typeof){case xd:return c=wd(b.type,b.key,b.props,null,a.mode,c),c.ref=vc(a,null,b),c.return=
a,c;case Cb:return b=hf(b,a.mode,c),b.return=a,b;case Ta:var d=b._init;return u(a,d(b._payload),c)}if(cc(b)||ac(b))return b=ub(b,a.mode,c,null),b.return=a,b;vd(a,b)}return null}function r(a,b,c,d){var e=null!==b?b.key:null;if("string"===typeof c&&""!==c||"number"===typeof c)return null!==e?null:h(a,b,""+c,d);if("object"===typeof c&&null!==c){switch(c.$$typeof){case xd:return c.key===e?k(a,b,c,d):null;case Cb:return c.key===e?m(a,b,c,d):null;case Ta:return e=c._init,r(a,b,e(c._payload),d)}if(cc(c)||
ac(c))return null!==e?null:l(a,b,c,d,null);vd(a,c)}return null}function p(a,b,c,d,e){if("string"===typeof d&&""!==d||"number"===typeof d)return a=a.get(c)||null,h(b,a,""+d,e);if("object"===typeof d&&null!==d){switch(d.$$typeof){case xd:return a=a.get(null===d.key?c:d.key)||null,k(b,a,d,e);case Cb:return a=a.get(null===d.key?c:d.key)||null,m(b,a,d,e);case Ta:var f=d._init;return p(a,b,c,f(d._payload),e)}if(cc(d)||ac(d))return a=a.get(c)||null,l(b,a,d,e,null);vd(b,d)}return null}function x(e,g,h,k){for(var n=
null,m=null,l=g,q=g=0,v=null;null!==l&&q<h.length;q++){l.index>q?(v=l,l=null):v=l.sibling;var A=r(e,l,h[q],k);if(null===A){null===l&&(l=v);break}a&&l&&null===A.alternate&&b(e,l);g=f(A,g,q);null===m?n=A:m.sibling=A;m=A;l=v}if(q===h.length)return c(e,l),D&&rb(e,q),n;if(null===l){for(;q<h.length;q++)l=u(e,h[q],k),null!==l&&(g=f(l,g,q),null===m?n=l:m.sibling=l,m=l);D&&rb(e,q);return n}for(l=d(e,l);q<h.length;q++)v=p(l,e,q,h[q],k),null!==v&&(a&&null!==v.alternate&&l.delete(null===v.key?q:v.key),g=f(v,
g,q),null===m?n=v:m.sibling=v,m=v);a&&l.forEach(function(a){return b(e,a)});D&&rb(e,q);return n}function F(e,g,h,k){var m=ac(h);if("function"!==typeof m)throw Error(n(150));h=m.call(h);if(null==h)throw Error(n(151));for(var l=m=null,q=g,v=g=0,A=null,t=h.next();null!==q&&!t.done;v++,t=h.next()){q.index>v?(A=q,q=null):A=q.sibling;var x=r(e,q,t.value,k);if(null===x){null===q&&(q=A);break}a&&q&&null===x.alternate&&b(e,q);g=f(x,g,v);null===l?m=x:l.sibling=x;l=x;q=A}if(t.done)return c(e,q),D&&rb(e,v),m;
if(null===q){for(;!t.done;v++,t=h.next())t=u(e,t.value,k),null!==t&&(g=f(t,g,v),null===l?m=t:l.sibling=t,l=t);D&&rb(e,v);return m}for(q=d(e,q);!t.done;v++,t=h.next())t=p(q,e,v,t.value,k),null!==t&&(a&&null!==t.alternate&&q.delete(null===t.key?v:t.key),g=f(t,g,v),null===l?m=t:l.sibling=t,l=t);a&&q.forEach(function(a){return b(e,a)});D&&rb(e,v);return m}function w(a,d,f,h){"object"===typeof f&&null!==f&&f.type===Bb&&null===f.key&&(f=f.props.children);if("object"===typeof f&&null!==f){switch(f.$$typeof){case xd:a:{for(var k=
f.key,m=d;null!==m;){if(m.key===k){k=f.type;if(k===Bb){if(7===m.tag){c(a,m.sibling);d=e(m,f.props.children);d.return=a;a=d;break a}}else if(m.elementType===k||"object"===typeof k&&null!==k&&k.$$typeof===Ta&&Kh(k)===m.type){c(a,m.sibling);d=e(m,f.props);d.ref=vc(a,m,f);d.return=a;a=d;break a}c(a,m);break}else b(a,m);m=m.sibling}f.type===Bb?(d=ub(f.props.children,a.mode,h,f.key),d.return=a,a=d):(h=wd(f.type,f.key,f.props,null,a.mode,h),h.ref=vc(a,d,f),h.return=a,a=h)}return g(a);case Cb:a:{for(m=f.key;null!==
d;){if(d.key===m)if(4===d.tag&&d.stateNode.containerInfo===f.containerInfo&&d.stateNode.implementation===f.implementation){c(a,d.sibling);d=e(d,f.children||[]);d.return=a;a=d;break a}else{c(a,d);break}else b(a,d);d=d.sibling}d=hf(f,a.mode,h);d.return=a;a=d}return g(a);case Ta:return m=f._init,w(a,d,m(f._payload),h)}if(cc(f))return x(a,d,f,h);if(ac(f))return F(a,d,f,h);vd(a,f)}return"string"===typeof f&&""!==f||"number"===typeof f?(f=""+f,null!==d&&6===d.tag?(c(a,d.sibling),d=e(d,f),d.return=a,a=d):
(c(a,d),d=gf(f,a.mode,h),d.return=a,a=d),g(a)):c(a,d)}return w}function vb(a){if(a===wc)throw Error(n(174));return a}function jf(a,b){y(xc,b);y(yc,a);y(Ea,wc);a=b.nodeType;switch(a){case 9:case 11:b=(b=b.documentElement)?b.namespaceURI:oe(null,"");break;default:a=8===a?b.parentNode:b,b=a.namespaceURI||null,a=a.tagName,b=oe(b,a)}w(Ea);y(Ea,b)}function Tb(a){w(Ea);w(yc);w(xc)}function Mh(a){vb(xc.current);var b=vb(Ea.current);var c=oe(b,a.type);b!==c&&(y(yc,a),y(Ea,c))}function kf(a){yc.current===a&&
(w(Ea),w(yc))}function yd(a){for(var b=a;null!==b;){if(13===b.tag){var c=b.memoizedState;if(null!==c&&(c=c.dehydrated,null===c||"$?"===c.data||"$!"===c.data))return b}else if(19===b.tag&&void 0!==b.memoizedProps.revealOrder){if(0!==(b.flags&128))return b}else if(null!==b.child){b.child.return=b;b=b.child;continue}if(b===a)break;for(;null===b.sibling;){if(null===b.return||b.return===a)return null;b=b.return}b.sibling.return=b.return;b=b.sibling}return null}function lf(){for(var a=0;a<mf.length;a++)mf[a]._workInProgressVersionPrimary=
null;mf.length=0}function V(){throw Error(n(321));}function nf(a,b){if(null===b)return!1;for(var c=0;c<b.length&&c<a.length;c++)if(!ua(a[c],b[c]))return!1;return!0}function of(a,b,c,d,e,f){wb=f;C=b;b.memoizedState=null;b.updateQueue=null;b.lanes=0;zd.current=null===a||null===a.memoizedState?mk:nk;a=c(d,e);if(zc){f=0;do{zc=!1;Ac=0;if(25<=f)throw Error(n(301));f+=1;N=K=null;b.updateQueue=null;zd.current=ok;a=c(d,e)}while(zc)}zd.current=Ad;b=null!==K&&null!==K.next;wb=0;N=K=C=null;Bd=!1;if(b)throw Error(n(300));
return a}function pf(){var a=0!==Ac;Ac=0;return a}function Fa(){var a={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};null===N?C.memoizedState=N=a:N=N.next=a;return N}function sa(){if(null===K){var a=C.alternate;a=null!==a?a.memoizedState:null}else a=K.next;var b=null===N?C.memoizedState:N.next;if(null!==b)N=b,K=a;else{if(null===a)throw Error(n(310));K=a;a={memoizedState:K.memoizedState,baseState:K.baseState,baseQueue:K.baseQueue,queue:K.queue,next:null};null===N?C.memoizedState=
N=a:N=N.next=a}return N}function Bc(a,b){return"function"===typeof b?b(a):b}function qf(a,b,c){b=sa();c=b.queue;if(null===c)throw Error(n(311));c.lastRenderedReducer=a;var d=K,e=d.baseQueue,f=c.pending;if(null!==f){if(null!==e){var g=e.next;e.next=f.next;f.next=g}d.baseQueue=e=f;c.pending=null}if(null!==e){f=e.next;d=d.baseState;var h=g=null,k=null,m=f;do{var l=m.lane;if((wb&l)===l)null!==k&&(k=k.next={lane:0,action:m.action,hasEagerState:m.hasEagerState,eagerState:m.eagerState,next:null}),d=m.hasEagerState?
m.eagerState:a(d,m.action);else{var u={lane:l,action:m.action,hasEagerState:m.hasEagerState,eagerState:m.eagerState,next:null};null===k?(h=k=u,g=d):k=k.next=u;C.lanes|=l;ra|=l}m=m.next}while(null!==m&&m!==f);null===k?g=d:k.next=h;ua(d,b.memoizedState)||(ha=!0);b.memoizedState=d;b.baseState=g;b.baseQueue=k;c.lastRenderedState=d}a=c.interleaved;if(null!==a){e=a;do f=e.lane,C.lanes|=f,ra|=f,e=e.next;while(e!==a)}else null===e&&(c.lanes=0);return[b.memoizedState,c.dispatch]}function rf(a,b,c){b=sa();
c=b.queue;if(null===c)throw Error(n(311));c.lastRenderedReducer=a;var d=c.dispatch,e=c.pending,f=b.memoizedState;if(null!==e){c.pending=null;var g=e=e.next;do f=a(f,g.action),g=g.next;while(g!==e);ua(f,b.memoizedState)||(ha=!0);b.memoizedState=f;null===b.baseQueue&&(b.baseState=f);c.lastRenderedState=f}return[f,d]}function Nh(a,b,c){}function Oh(a,b,c){c=C;var d=sa(),e=b(),f=!ua(d.memoizedState,e);f&&(d.memoizedState=e,ha=!0);d=d.queue;sf(Ph.bind(null,c,d,a),[a]);if(d.getSnapshot!==b||f||null!==N&&
N.memoizedState.tag&1){c.flags|=2048;Cc(9,Qh.bind(null,c,d,e,b),void 0,null);if(null===O)throw Error(n(349));0!==(wb&30)||Rh(c,b,e)}return e}function Rh(a,b,c){a.flags|=16384;a={getSnapshot:b,value:c};b=C.updateQueue;null===b?(b={lastEffect:null,stores:null},C.updateQueue=b,b.stores=[a]):(c=b.stores,null===c?b.stores=[a]:c.push(a))}function Qh(a,b,c,d){b.value=c;b.getSnapshot=d;Sh(b)&&Th(a)}function Ph(a,b,c){return c(function(){Sh(b)&&Th(a)})}function Sh(a){var b=a.getSnapshot;a=a.value;try{var c=
b();return!ua(a,c)}catch(d){return!0}}function Th(a){var b=Oa(a,1);null!==b&&ya(b,a,1,-1)}function Uh(a){var b=Fa();"function"===typeof a&&(a=a());b.memoizedState=b.baseState=a;a={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:Bc,lastRenderedState:a};b.queue=a;a=a.dispatch=pk.bind(null,C,a);return[b.memoizedState,a]}function Cc(a,b,c,d){a={tag:a,create:b,destroy:c,deps:d,next:null};b=C.updateQueue;null===b?(b={lastEffect:null,stores:null},C.updateQueue=b,b.lastEffect=a.next=
a):(c=b.lastEffect,null===c?b.lastEffect=a.next=a:(d=c.next,c.next=a,a.next=d,b.lastEffect=a));return a}function Vh(a){return sa().memoizedState}function Cd(a,b,c,d){var e=Fa();C.flags|=a;e.memoizedState=Cc(1|b,c,void 0,void 0===d?null:d)}function Dd(a,b,c,d){var e=sa();d=void 0===d?null:d;var f=void 0;if(null!==K){var g=K.memoizedState;f=g.destroy;if(null!==d&&nf(d,g.deps)){e.memoizedState=Cc(b,c,f,d);return}}C.flags|=a;e.memoizedState=Cc(1|b,c,f,d)}function Wh(a,b){return Cd(8390656,8,a,b)}function sf(a,
b){return Dd(2048,8,a,b)}function Xh(a,b){return Dd(4,2,a,b)}function Yh(a,b){return Dd(4,4,a,b)}function Zh(a,b){if("function"===typeof b)return a=a(),b(a),function(){b(null)};if(null!==b&&void 0!==b)return a=a(),b.current=a,function(){b.current=null}}function $h(a,b,c){c=null!==c&&void 0!==c?c.concat([a]):null;return Dd(4,4,Zh.bind(null,b,a),c)}function tf(a,b){}function ai(a,b){var c=sa();b=void 0===b?null:b;var d=c.memoizedState;if(null!==d&&null!==b&&nf(b,d[1]))return d[0];c.memoizedState=[a,
b];return a}function bi(a,b){var c=sa();b=void 0===b?null:b;var d=c.memoizedState;if(null!==d&&null!==b&&nf(b,d[1]))return d[0];a=a();c.memoizedState=[a,b];return a}function ci(a,b,c){if(0===(wb&21))return a.baseState&&(a.baseState=!1,ha=!0),a.memoizedState=c;ua(c,b)||(c=Dg(),C.lanes|=c,ra|=c,a.baseState=!0);return b}function qk(a,b,c){c=z;z=0!==c&&4>c?c:4;a(!0);var d=uf.transition;uf.transition={};try{a(!1),b()}finally{z=c,uf.transition=d}}function di(){return sa().memoizedState}function rk(a,b,
c){var d=hb(a);c={lane:d,action:c,hasEagerState:!1,eagerState:null,next:null};if(ei(a))fi(b,c);else if(c=Ch(a,b,c,d),null!==c){var e=Z();ya(c,a,d,e);gi(c,b,d)}}function pk(a,b,c){var d=hb(a),e={lane:d,action:c,hasEagerState:!1,eagerState:null,next:null};if(ei(a))fi(b,e);else{var f=a.alternate;if(0===a.lanes&&(null===f||0===f.lanes)&&(f=b.lastRenderedReducer,null!==f))try{var g=b.lastRenderedState,h=f(g,c);e.hasEagerState=!0;e.eagerState=h;if(ua(h,g)){var k=b.interleaved;null===k?(e.next=e,cf(b)):
(e.next=k.next,k.next=e);b.interleaved=e;return}}catch(m){}finally{}c=Ch(a,b,e,d);null!==c&&(e=Z(),ya(c,a,d,e),gi(c,b,d))}}function ei(a){var b=a.alternate;return a===C||null!==b&&b===C}function fi(a,b){zc=Bd=!0;var c=a.pending;null===c?b.next=b:(b.next=c.next,c.next=b);a.pending=b}function gi(a,b,c){if(0!==(c&4194240)){var d=b.lanes;d&=a.pendingLanes;c|=d;b.lanes=c;xe(a,c)}}function Ub(a,b){try{var c="",d=b;do c+=gj(d),d=d.return;while(d);var e=c}catch(f){e="\nError generating stack: "+f.message+
"\n"+f.stack}return{value:a,source:b,stack:e,digest:null}}function vf(a,b,c){return{value:a,source:null,stack:null!=c?c:null,digest:null!=b?b:null}}function wf(a,b){try{console.error(b.value)}catch(c){setTimeout(function(){throw c;})}}function hi(a,b,c){c=Pa(-1,c);c.tag=3;c.payload={element:null};var d=b.value;c.callback=function(){Ed||(Ed=!0,xf=d);wf(a,b)};return c}function ii(a,b,c){c=Pa(-1,c);c.tag=3;var d=a.type.getDerivedStateFromError;if("function"===typeof d){var e=b.value;c.payload=function(){return d(e)};
c.callback=function(){wf(a,b)}}var f=a.stateNode;null!==f&&"function"===typeof f.componentDidCatch&&(c.callback=function(){wf(a,b);"function"!==typeof d&&(null===ib?ib=new Set([this]):ib.add(this));var c=b.stack;this.componentDidCatch(b.value,{componentStack:null!==c?c:""})});return c}function ji(a,b,c){var d=a.pingCache;if(null===d){d=a.pingCache=new sk;var e=new Set;d.set(b,e)}else e=d.get(b),void 0===e&&(e=new Set,d.set(b,e));e.has(c)||(e.add(c),a=tk.bind(null,a,b,c),b.then(a,a))}function ki(a){do{var b;
if(b=13===a.tag)b=a.memoizedState,b=null!==b?null!==b.dehydrated?!0:!1:!0;if(b)return a;a=a.return}while(null!==a);return null}function li(a,b,c,d,e){if(0===(a.mode&1))return a===b?a.flags|=65536:(a.flags|=128,c.flags|=131072,c.flags&=-52805,1===c.tag&&(null===c.alternate?c.tag=17:(b=Pa(-1,1),b.tag=2,eb(c,b,1))),c.lanes|=1),a;a.flags|=65536;a.lanes=e;return a}function aa(a,b,c,d){b.child=null===a?mi(b,null,c,d):Vb(b,a.child,c,d)}function ni(a,b,c,d,e){c=c.render;var f=b.ref;Sb(b,e);d=of(a,b,c,d,f,
e);c=pf();if(null!==a&&!ha)return b.updateQueue=a.updateQueue,b.flags&=-2053,a.lanes&=~e,Qa(a,b,e);D&&c&&Ue(b);b.flags|=1;aa(a,b,d,e);return b.child}function oi(a,b,c,d,e){if(null===a){var f=c.type;if("function"===typeof f&&!yf(f)&&void 0===f.defaultProps&&null===c.compare&&void 0===c.defaultProps)return b.tag=15,b.type=f,pi(a,b,f,d,e);a=wd(c.type,null,d,b,b.mode,e);a.ref=b.ref;a.return=b;return b.child=a}f=a.child;if(0===(a.lanes&e)){var g=f.memoizedProps;c=c.compare;c=null!==c?c:qc;if(c(g,d)&&a.ref===
b.ref)return Qa(a,b,e)}b.flags|=1;a=gb(f,d);a.ref=b.ref;a.return=b;return b.child=a}function pi(a,b,c,d,e){if(null!==a){var f=a.memoizedProps;if(qc(f,d)&&a.ref===b.ref)if(ha=!1,b.pendingProps=d=f,0!==(a.lanes&e))0!==(a.flags&131072)&&(ha=!0);else return b.lanes=a.lanes,Qa(a,b,e)}return zf(a,b,c,d,e)}function qi(a,b,c){var d=b.pendingProps,e=d.children,f=null!==a?a.memoizedState:null;if("hidden"===d.mode)if(0===(b.mode&1))b.memoizedState={baseLanes:0,cachePool:null,transitions:null},y(Ga,ba),ba|=c;
else{if(0===(c&1073741824))return a=null!==f?f.baseLanes|c:c,b.lanes=b.childLanes=1073741824,b.memoizedState={baseLanes:a,cachePool:null,transitions:null},b.updateQueue=null,y(Ga,ba),ba|=a,null;b.memoizedState={baseLanes:0,cachePool:null,transitions:null};d=null!==f?f.baseLanes:c;y(Ga,ba);ba|=d}else null!==f?(d=f.baseLanes|c,b.memoizedState=null):d=c,y(Ga,ba),ba|=d;aa(a,b,e,c);return b.child}function ri(a,b){var c=b.ref;if(null===a&&null!==c||null!==a&&a.ref!==c)b.flags|=512,b.flags|=2097152}function zf(a,
b,c,d,e){var f=ea(c)?qb:J.current;f=Nb(b,f);Sb(b,e);c=of(a,b,c,d,f,e);d=pf();if(null!==a&&!ha)return b.updateQueue=a.updateQueue,b.flags&=-2053,a.lanes&=~e,Qa(a,b,e);D&&d&&Ue(b);b.flags|=1;aa(a,b,c,e);return b.child}function si(a,b,c,d,e){if(ea(c)){var f=!0;ld(b)}else f=!1;Sb(b,e);if(null===b.stateNode)Fd(a,b),Hh(b,c,d),ff(b,c,d,e),d=!0;else if(null===a){var g=b.stateNode,h=b.memoizedProps;g.props=h;var k=g.context,m=c.contextType;"object"===typeof m&&null!==m?m=qa(m):(m=ea(c)?qb:J.current,m=Nb(b,
m));var l=c.getDerivedStateFromProps,n="function"===typeof l||"function"===typeof g.getSnapshotBeforeUpdate;n||"function"!==typeof g.UNSAFE_componentWillReceiveProps&&"function"!==typeof g.componentWillReceiveProps||(h!==d||k!==m)&&Ih(b,g,d,m);fb=!1;var r=b.memoizedState;g.state=r;td(b,d,g,e);k=b.memoizedState;h!==d||r!==k||S.current||fb?("function"===typeof l&&(ef(b,c,l,d),k=b.memoizedState),(h=fb||Gh(b,c,h,d,r,k,m))?(n||"function"!==typeof g.UNSAFE_componentWillMount&&"function"!==typeof g.componentWillMount||
("function"===typeof g.componentWillMount&&g.componentWillMount(),"function"===typeof g.UNSAFE_componentWillMount&&g.UNSAFE_componentWillMount()),"function"===typeof g.componentDidMount&&(b.flags|=4194308)):("function"===typeof g.componentDidMount&&(b.flags|=4194308),b.memoizedProps=d,b.memoizedState=k),g.props=d,g.state=k,g.context=m,d=h):("function"===typeof g.componentDidMount&&(b.flags|=4194308),d=!1)}else{g=b.stateNode;Dh(a,b);h=b.memoizedProps;m=b.type===b.elementType?h:xa(b.type,h);g.props=
m;n=b.pendingProps;r=g.context;k=c.contextType;"object"===typeof k&&null!==k?k=qa(k):(k=ea(c)?qb:J.current,k=Nb(b,k));var p=c.getDerivedStateFromProps;(l="function"===typeof p||"function"===typeof g.getSnapshotBeforeUpdate)||"function"!==typeof g.UNSAFE_componentWillReceiveProps&&"function"!==typeof g.componentWillReceiveProps||(h!==n||r!==k)&&Ih(b,g,d,k);fb=!1;r=b.memoizedState;g.state=r;td(b,d,g,e);var x=b.memoizedState;h!==n||r!==x||S.current||fb?("function"===typeof p&&(ef(b,c,p,d),x=b.memoizedState),
(m=fb||Gh(b,c,m,d,r,x,k)||!1)?(l||"function"!==typeof g.UNSAFE_componentWillUpdate&&"function"!==typeof g.componentWillUpdate||("function"===typeof g.componentWillUpdate&&g.componentWillUpdate(d,x,k),"function"===typeof g.UNSAFE_componentWillUpdate&&g.UNSAFE_componentWillUpdate(d,x,k)),"function"===typeof g.componentDidUpdate&&(b.flags|=4),"function"===typeof g.getSnapshotBeforeUpdate&&(b.flags|=1024)):("function"!==typeof g.componentDidUpdate||h===a.memoizedProps&&r===a.memoizedState||(b.flags|=
4),"function"!==typeof g.getSnapshotBeforeUpdate||h===a.memoizedProps&&r===a.memoizedState||(b.flags|=1024),b.memoizedProps=d,b.memoizedState=x),g.props=d,g.state=x,g.context=k,d=m):("function"!==typeof g.componentDidUpdate||h===a.memoizedProps&&r===a.memoizedState||(b.flags|=4),"function"!==typeof g.getSnapshotBeforeUpdate||h===a.memoizedProps&&r===a.memoizedState||(b.flags|=1024),d=!1)}return Af(a,b,c,d,f,e)}function Af(a,b,c,d,e,f){ri(a,b);var g=0!==(b.flags&128);if(!d&&!g)return e&&vh(b,c,!1),
Qa(a,b,f);d=b.stateNode;uk.current=b;var h=g&&"function"!==typeof c.getDerivedStateFromError?null:d.render();b.flags|=1;null!==a&&g?(b.child=Vb(b,a.child,null,f),b.child=Vb(b,null,h,f)):aa(a,b,h,f);b.memoizedState=d.state;e&&vh(b,c,!0);return b.child}function ti(a){var b=a.stateNode;b.pendingContext?th(a,b.pendingContext,b.pendingContext!==b.context):b.context&&th(a,b.context,!1);jf(a,b.containerInfo)}function ui(a,b,c,d,e){Qb();Ye(e);b.flags|=256;aa(a,b,c,d);return b.child}function Bf(a){return{baseLanes:a,
cachePool:null,transitions:null}}function vi(a,b,c){var d=b.pendingProps,e=G.current,f=!1,g=0!==(b.flags&128),h;(h=g)||(h=null!==a&&null===a.memoizedState?!1:0!==(e&2));if(h)f=!0,b.flags&=-129;else if(null===a||null!==a.memoizedState)e|=1;y(G,e&1);if(null===a){Xe(b);a=b.memoizedState;if(null!==a&&(a=a.dehydrated,null!==a))return 0===(b.mode&1)?b.lanes=1:"$!"===a.data?b.lanes=8:b.lanes=1073741824,null;g=d.children;a=d.fallback;return f?(d=b.mode,f=b.child,g={mode:"hidden",children:g},0===(d&1)&&null!==
f?(f.childLanes=0,f.pendingProps=g):f=Gd(g,d,0,null),a=ub(a,d,c,null),f.return=b,a.return=b,f.sibling=a,b.child=f,b.child.memoizedState=Bf(c),b.memoizedState=Cf,a):Df(b,g)}e=a.memoizedState;if(null!==e&&(h=e.dehydrated,null!==h))return vk(a,b,g,d,h,e,c);if(f){f=d.fallback;g=b.mode;e=a.child;h=e.sibling;var k={mode:"hidden",children:d.children};0===(g&1)&&b.child!==e?(d=b.child,d.childLanes=0,d.pendingProps=k,b.deletions=null):(d=gb(e,k),d.subtreeFlags=e.subtreeFlags&14680064);null!==h?f=gb(h,f):(f=
ub(f,g,c,null),f.flags|=2);f.return=b;d.return=b;d.sibling=f;b.child=d;d=f;f=b.child;g=a.child.memoizedState;g=null===g?Bf(c):{baseLanes:g.baseLanes|c,cachePool:null,transitions:g.transitions};f.memoizedState=g;f.childLanes=a.childLanes&~c;b.memoizedState=Cf;return d}f=a.child;a=f.sibling;d=gb(f,{mode:"visible",children:d.children});0===(b.mode&1)&&(d.lanes=c);d.return=b;d.sibling=null;null!==a&&(c=b.deletions,null===c?(b.deletions=[a],b.flags|=16):c.push(a));b.child=d;b.memoizedState=null;return d}
function Df(a,b,c){b=Gd({mode:"visible",children:b},a.mode,0,null);b.return=a;return a.child=b}function Hd(a,b,c,d){null!==d&&Ye(d);Vb(b,a.child,null,c);a=Df(b,b.pendingProps.children);a.flags|=2;b.memoizedState=null;return a}function vk(a,b,c,d,e,f,g){if(c){if(b.flags&256)return b.flags&=-257,d=vf(Error(n(422))),Hd(a,b,g,d);if(null!==b.memoizedState)return b.child=a.child,b.flags|=128,null;f=d.fallback;e=b.mode;d=Gd({mode:"visible",children:d.children},e,0,null);f=ub(f,e,g,null);f.flags|=2;d.return=
b;f.return=b;d.sibling=f;b.child=d;0!==(b.mode&1)&&Vb(b,a.child,null,g);b.child.memoizedState=Bf(g);b.memoizedState=Cf;return f}if(0===(b.mode&1))return Hd(a,b,g,null);if("$!"===e.data){d=e.nextSibling&&e.nextSibling.dataset;if(d)var h=d.dgst;d=h;f=Error(n(419));d=vf(f,d,void 0);return Hd(a,b,g,d)}h=0!==(g&a.childLanes);if(ha||h){d=O;if(null!==d){switch(g&-g){case 4:e=2;break;case 16:e=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:e=
32;break;case 536870912:e=268435456;break;default:e=0}e=0!==(e&(d.suspendedLanes|g))?0:e;0!==e&&e!==f.retryLane&&(f.retryLane=e,Oa(a,e),ya(d,a,e,-1))}Ef();d=vf(Error(n(421)));return Hd(a,b,g,d)}if("$?"===e.data)return b.flags|=128,b.child=a.child,b=wk.bind(null,a),e._reactRetry=b,null;a=f.treeContext;fa=Ka(e.nextSibling);la=b;D=!0;wa=null;null!==a&&(na[oa++]=Ma,na[oa++]=Na,na[oa++]=sb,Ma=a.id,Na=a.overflow,sb=b);b=Df(b,d.children);b.flags|=4096;return b}function wi(a,b,c){a.lanes|=b;var d=a.alternate;
null!==d&&(d.lanes|=b);bf(a.return,b,c)}function Ff(a,b,c,d,e){var f=a.memoizedState;null===f?a.memoizedState={isBackwards:b,rendering:null,renderingStartTime:0,last:d,tail:c,tailMode:e}:(f.isBackwards=b,f.rendering=null,f.renderingStartTime=0,f.last=d,f.tail=c,f.tailMode=e)}function xi(a,b,c){var d=b.pendingProps,e=d.revealOrder,f=d.tail;aa(a,b,d.children,c);d=G.current;if(0!==(d&2))d=d&1|2,b.flags|=128;else{if(null!==a&&0!==(a.flags&128))a:for(a=b.child;null!==a;){if(13===a.tag)null!==a.memoizedState&&
wi(a,c,b);else if(19===a.tag)wi(a,c,b);else if(null!==a.child){a.child.return=a;a=a.child;continue}if(a===b)break a;for(;null===a.sibling;){if(null===a.return||a.return===b)break a;a=a.return}a.sibling.return=a.return;a=a.sibling}d&=1}y(G,d);if(0===(b.mode&1))b.memoizedState=null;else switch(e){case "forwards":c=b.child;for(e=null;null!==c;)a=c.alternate,null!==a&&null===yd(a)&&(e=c),c=c.sibling;c=e;null===c?(e=b.child,b.child=null):(e=c.sibling,c.sibling=null);Ff(b,!1,e,c,f);break;case "backwards":c=
null;e=b.child;for(b.child=null;null!==e;){a=e.alternate;if(null!==a&&null===yd(a)){b.child=e;break}a=e.sibling;e.sibling=c;c=e;e=a}Ff(b,!0,c,null,f);break;case "together":Ff(b,!1,null,null,void 0);break;default:b.memoizedState=null}return b.child}function Fd(a,b){0===(b.mode&1)&&null!==a&&(a.alternate=null,b.alternate=null,b.flags|=2)}function Qa(a,b,c){null!==a&&(b.dependencies=a.dependencies);ra|=b.lanes;if(0===(c&b.childLanes))return null;if(null!==a&&b.child!==a.child)throw Error(n(153));if(null!==
b.child){a=b.child;c=gb(a,a.pendingProps);b.child=c;for(c.return=b;null!==a.sibling;)a=a.sibling,c=c.sibling=gb(a,a.pendingProps),c.return=b;c.sibling=null}return b.child}function xk(a,b,c){switch(b.tag){case 3:ti(b);Qb();break;case 5:Mh(b);break;case 1:ea(b.type)&&ld(b);break;case 4:jf(b,b.stateNode.containerInfo);break;case 10:var d=b.type._context,e=b.memoizedProps.value;y(rd,d._currentValue);d._currentValue=e;break;case 13:d=b.memoizedState;if(null!==d){if(null!==d.dehydrated)return y(G,G.current&
1),b.flags|=128,null;if(0!==(c&b.child.childLanes))return vi(a,b,c);y(G,G.current&1);a=Qa(a,b,c);return null!==a?a.sibling:null}y(G,G.current&1);break;case 19:d=0!==(c&b.childLanes);if(0!==(a.flags&128)){if(d)return xi(a,b,c);b.flags|=128}e=b.memoizedState;null!==e&&(e.rendering=null,e.tail=null,e.lastEffect=null);y(G,G.current);if(d)break;else return null;case 22:case 23:return b.lanes=0,qi(a,b,c)}return Qa(a,b,c)}function Dc(a,b){if(!D)switch(a.tailMode){case "hidden":b=a.tail;for(var c=null;null!==
b;)null!==b.alternate&&(c=b),b=b.sibling;null===c?a.tail=null:c.sibling=null;break;case "collapsed":c=a.tail;for(var d=null;null!==c;)null!==c.alternate&&(d=c),c=c.sibling;null===d?b||null===a.tail?a.tail=null:a.tail.sibling=null:d.sibling=null}}function W(a){var b=null!==a.alternate&&a.alternate.child===a.child,c=0,d=0;if(b)for(var e=a.child;null!==e;)c|=e.lanes|e.childLanes,d|=e.subtreeFlags&14680064,d|=e.flags&14680064,e.return=a,e=e.sibling;else for(e=a.child;null!==e;)c|=e.lanes|e.childLanes,
d|=e.subtreeFlags,d|=e.flags,e.return=a,e=e.sibling;a.subtreeFlags|=d;a.childLanes=c;return b}function yk(a,b,c){var d=b.pendingProps;Ve(b);switch(b.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return W(b),null;case 1:return ea(b.type)&&(w(S),w(J)),W(b),null;case 3:d=b.stateNode;Tb();w(S);w(J);lf();d.pendingContext&&(d.context=d.pendingContext,d.pendingContext=null);if(null===a||null===a.child)pd(b)?b.flags|=4:null===a||a.memoizedState.isDehydrated&&0===(b.flags&
256)||(b.flags|=1024,null!==wa&&(Gf(wa),wa=null));yi(a,b);W(b);return null;case 5:kf(b);var e=vb(xc.current);c=b.type;if(null!==a&&null!=b.stateNode)zk(a,b,c,d,e),a.ref!==b.ref&&(b.flags|=512,b.flags|=2097152);else{if(!d){if(null===b.stateNode)throw Error(n(166));W(b);return null}a=vb(Ea.current);if(pd(b)){d=b.stateNode;c=b.type;var f=b.memoizedProps;d[Da]=b;d[uc]=f;a=0!==(b.mode&1);switch(c){case "dialog":B("cancel",d);B("close",d);break;case "iframe":case "object":case "embed":B("load",d);break;
case "video":case "audio":for(e=0;e<Ec.length;e++)B(Ec[e],d);break;case "source":B("error",d);break;case "img":case "image":case "link":B("error",d);B("load",d);break;case "details":B("toggle",d);break;case "input":kg(d,f);B("invalid",d);break;case "select":d._wrapperState={wasMultiple:!!f.multiple};B("invalid",d);break;case "textarea":ng(d,f),B("invalid",d)}pe(c,f);e=null;for(var g in f)if(f.hasOwnProperty(g)){var h=f[g];"children"===g?"string"===typeof h?d.textContent!==h&&(!0!==f.suppressHydrationWarning&&
jd(d.textContent,h,a),e=["children",h]):"number"===typeof h&&d.textContent!==""+h&&(!0!==f.suppressHydrationWarning&&jd(d.textContent,h,a),e=["children",""+h]):$b.hasOwnProperty(g)&&null!=h&&"onScroll"===g&&B("scroll",d)}switch(c){case "input":Pc(d);mg(d,f,!0);break;case "textarea":Pc(d);pg(d);break;case "select":case "option":break;default:"function"===typeof f.onClick&&(d.onclick=kd)}d=e;b.updateQueue=d;null!==d&&(b.flags|=4)}else{g=9===e.nodeType?e:e.ownerDocument;"http://www.w3.org/1999/xhtml"===
a&&(a=qg(c));"http://www.w3.org/1999/xhtml"===a?"script"===c?(a=g.createElement("div"),a.innerHTML="<script>\x3c/script>",a=a.removeChild(a.firstChild)):"string"===typeof d.is?a=g.createElement(c,{is:d.is}):(a=g.createElement(c),"select"===c&&(g=a,d.multiple?g.multiple=!0:d.size&&(g.size=d.size))):a=g.createElementNS(a,c);a[Da]=b;a[uc]=d;Ak(a,b,!1,!1);b.stateNode=a;a:{g=qe(c,d);switch(c){case "dialog":B("cancel",a);B("close",a);e=d;break;case "iframe":case "object":case "embed":B("load",a);e=d;break;
case "video":case "audio":for(e=0;e<Ec.length;e++)B(Ec[e],a);e=d;break;case "source":B("error",a);e=d;break;case "img":case "image":case "link":B("error",a);B("load",a);e=d;break;case "details":B("toggle",a);e=d;break;case "input":kg(a,d);e=ke(a,d);B("invalid",a);break;case "option":e=d;break;case "select":a._wrapperState={wasMultiple:!!d.multiple};e=E({},d,{value:void 0});B("invalid",a);break;case "textarea":ng(a,d);e=ne(a,d);B("invalid",a);break;default:e=d}pe(c,e);h=e;for(f in h)if(h.hasOwnProperty(f)){var k=
h[f];"style"===f?sg(a,k):"dangerouslySetInnerHTML"===f?(k=k?k.__html:void 0,null!=k&&zi(a,k)):"children"===f?"string"===typeof k?("textarea"!==c||""!==k)&&Fc(a,k):"number"===typeof k&&Fc(a,""+k):"suppressContentEditableWarning"!==f&&"suppressHydrationWarning"!==f&&"autoFocus"!==f&&($b.hasOwnProperty(f)?null!=k&&"onScroll"===f&&B("scroll",a):null!=k&&$d(a,f,k,g))}switch(c){case "input":Pc(a);mg(a,d,!1);break;case "textarea":Pc(a);pg(a);break;case "option":null!=d.value&&a.setAttribute("value",""+Ua(d.value));
break;case "select":a.multiple=!!d.multiple;f=d.value;null!=f?Db(a,!!d.multiple,f,!1):null!=d.defaultValue&&Db(a,!!d.multiple,d.defaultValue,!0);break;default:"function"===typeof e.onClick&&(a.onclick=kd)}switch(c){case "button":case "input":case "select":case "textarea":d=!!d.autoFocus;break a;case "img":d=!0;break a;default:d=!1}}d&&(b.flags|=4)}null!==b.ref&&(b.flags|=512,b.flags|=2097152)}W(b);return null;case 6:if(a&&null!=b.stateNode)Bk(a,b,a.memoizedProps,d);else{if("string"!==typeof d&&null===
b.stateNode)throw Error(n(166));c=vb(xc.current);vb(Ea.current);if(pd(b)){d=b.stateNode;c=b.memoizedProps;d[Da]=b;if(f=d.nodeValue!==c)if(a=la,null!==a)switch(a.tag){case 3:jd(d.nodeValue,c,0!==(a.mode&1));break;case 5:!0!==a.memoizedProps.suppressHydrationWarning&&jd(d.nodeValue,c,0!==(a.mode&1))}f&&(b.flags|=4)}else d=(9===c.nodeType?c:c.ownerDocument).createTextNode(d),d[Da]=b,b.stateNode=d}W(b);return null;case 13:w(G);d=b.memoizedState;if(null===a||null!==a.memoizedState&&null!==a.memoizedState.dehydrated){if(D&&
null!==fa&&0!==(b.mode&1)&&0===(b.flags&128)){for(f=fa;f;)f=Ka(f.nextSibling);Qb();b.flags|=98560;f=!1}else if(f=pd(b),null!==d&&null!==d.dehydrated){if(null===a){if(!f)throw Error(n(318));f=b.memoizedState;f=null!==f?f.dehydrated:null;if(!f)throw Error(n(317));f[Da]=b}else Qb(),0===(b.flags&128)&&(b.memoizedState=null),b.flags|=4;W(b);f=!1}else null!==wa&&(Gf(wa),wa=null),f=!0;if(!f)return b.flags&65536?b:null}if(0!==(b.flags&128))return b.lanes=c,b;d=null!==d;d!==(null!==a&&null!==a.memoizedState)&&
d&&(b.child.flags|=8192,0!==(b.mode&1)&&(null===a||0!==(G.current&1)?0===L&&(L=3):Ef()));null!==b.updateQueue&&(b.flags|=4);W(b);return null;case 4:return Tb(),yi(a,b),null===a&&sc(b.stateNode.containerInfo),W(b),null;case 10:return af(b.type._context),W(b),null;case 17:return ea(b.type)&&(w(S),w(J)),W(b),null;case 19:w(G);f=b.memoizedState;if(null===f)return W(b),null;d=0!==(b.flags&128);g=f.rendering;if(null===g)if(d)Dc(f,!1);else{if(0!==L||null!==a&&0!==(a.flags&128))for(a=b.child;null!==a;){g=
yd(a);if(null!==g){b.flags|=128;Dc(f,!1);d=g.updateQueue;null!==d&&(b.updateQueue=d,b.flags|=4);b.subtreeFlags=0;d=c;for(c=b.child;null!==c;)f=c,a=d,f.flags&=14680066,g=f.alternate,null===g?(f.childLanes=0,f.lanes=a,f.child=null,f.subtreeFlags=0,f.memoizedProps=null,f.memoizedState=null,f.updateQueue=null,f.dependencies=null,f.stateNode=null):(f.childLanes=g.childLanes,f.lanes=g.lanes,f.child=g.child,f.subtreeFlags=0,f.deletions=null,f.memoizedProps=g.memoizedProps,f.memoizedState=g.memoizedState,
f.updateQueue=g.updateQueue,f.type=g.type,a=g.dependencies,f.dependencies=null===a?null:{lanes:a.lanes,firstContext:a.firstContext}),c=c.sibling;y(G,G.current&1|2);return b.child}a=a.sibling}null!==f.tail&&P()>Hf&&(b.flags|=128,d=!0,Dc(f,!1),b.lanes=4194304)}else{if(!d)if(a=yd(g),null!==a){if(b.flags|=128,d=!0,c=a.updateQueue,null!==c&&(b.updateQueue=c,b.flags|=4),Dc(f,!0),null===f.tail&&"hidden"===f.tailMode&&!g.alternate&&!D)return W(b),null}else 2*P()-f.renderingStartTime>Hf&&1073741824!==c&&(b.flags|=
128,d=!0,Dc(f,!1),b.lanes=4194304);f.isBackwards?(g.sibling=b.child,b.child=g):(c=f.last,null!==c?c.sibling=g:b.child=g,f.last=g)}if(null!==f.tail)return b=f.tail,f.rendering=b,f.tail=b.sibling,f.renderingStartTime=P(),b.sibling=null,c=G.current,y(G,d?c&1|2:c&1),b;W(b);return null;case 22:case 23:return ba=Ga.current,w(Ga),d=null!==b.memoizedState,null!==a&&null!==a.memoizedState!==d&&(b.flags|=8192),d&&0!==(b.mode&1)?0!==(ba&1073741824)&&(W(b),b.subtreeFlags&6&&(b.flags|=8192)):W(b),null;case 24:return null;
case 25:return null}throw Error(n(156,b.tag));}function Ck(a,b,c){Ve(b);switch(b.tag){case 1:return ea(b.type)&&(w(S),w(J)),a=b.flags,a&65536?(b.flags=a&-65537|128,b):null;case 3:return Tb(),w(S),w(J),lf(),a=b.flags,0!==(a&65536)&&0===(a&128)?(b.flags=a&-65537|128,b):null;case 5:return kf(b),null;case 13:w(G);a=b.memoizedState;if(null!==a&&null!==a.dehydrated){if(null===b.alternate)throw Error(n(340));Qb()}a=b.flags;return a&65536?(b.flags=a&-65537|128,b):null;case 19:return w(G),null;case 4:return Tb(),
null;case 10:return af(b.type._context),null;case 22:case 23:return ba=Ga.current,w(Ga),null;case 24:return null;default:return null}}function Wb(a,b){var c=a.ref;if(null!==c)if("function"===typeof c)try{c(null)}catch(d){H(a,b,d)}else c.current=null}function If(a,b,c){try{c()}catch(d){H(a,b,d)}}function Dk(a,b){Jf=Zc;a=ch();if(Ie(a)){if("selectionStart"in a)var c={start:a.selectionStart,end:a.selectionEnd};else a:{c=(c=a.ownerDocument)&&c.defaultView||window;var d=c.getSelection&&c.getSelection();
if(d&&0!==d.rangeCount){c=d.anchorNode;var e=d.anchorOffset,f=d.focusNode;d=d.focusOffset;try{c.nodeType,f.nodeType}catch(M){c=null;break a}var g=0,h=-1,k=-1,m=0,t=0,u=a,r=null;b:for(;;){for(var p;;){u!==c||0!==e&&3!==u.nodeType||(h=g+e);u!==f||0!==d&&3!==u.nodeType||(k=g+d);3===u.nodeType&&(g+=u.nodeValue.length);if(null===(p=u.firstChild))break;r=u;u=p}for(;;){if(u===a)break b;r===c&&++m===e&&(h=g);r===f&&++t===d&&(k=g);if(null!==(p=u.nextSibling))break;u=r;r=u.parentNode}u=p}c=-1===h||-1===k?null:
{start:h,end:k}}else c=null}c=c||{start:0,end:0}}else c=null;Kf={focusedElem:a,selectionRange:c};Zc=!1;for(l=b;null!==l;)if(b=l,a=b.child,0!==(b.subtreeFlags&1028)&&null!==a)a.return=b,l=a;else for(;null!==l;){b=l;try{var x=b.alternate;if(0!==(b.flags&1024))switch(b.tag){case 0:case 11:case 15:break;case 1:if(null!==x){var w=x.memoizedProps,z=x.memoizedState,A=b.stateNode,v=A.getSnapshotBeforeUpdate(b.elementType===b.type?w:xa(b.type,w),z);A.__reactInternalSnapshotBeforeUpdate=v}break;case 3:var q=
b.stateNode.containerInfo;1===q.nodeType?q.textContent="":9===q.nodeType&&q.documentElement&&q.removeChild(q.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(n(163));}}catch(M){H(b,b.return,M)}a=b.sibling;if(null!==a){a.return=b.return;l=a;break}l=b.return}x=Ai;Ai=!1;return x}function Gc(a,b,c){var d=b.updateQueue;d=null!==d?d.lastEffect:null;if(null!==d){var e=d=d.next;do{if((e.tag&a)===a){var f=e.destroy;e.destroy=void 0;void 0!==f&&If(b,c,f)}e=e.next}while(e!==d)}}
function Id(a,b){b=b.updateQueue;b=null!==b?b.lastEffect:null;if(null!==b){var c=b=b.next;do{if((c.tag&a)===a){var d=c.create;c.destroy=d()}c=c.next}while(c!==b)}}function Lf(a){var b=a.ref;if(null!==b){var c=a.stateNode;switch(a.tag){case 5:a=c;break;default:a=c}"function"===typeof b?b(a):b.current=a}}function Bi(a){var b=a.alternate;null!==b&&(a.alternate=null,Bi(b));a.child=null;a.deletions=null;a.sibling=null;5===a.tag&&(b=a.stateNode,null!==b&&(delete b[Da],delete b[uc],delete b[Me],delete b[Ek],
delete b[Fk]));a.stateNode=null;a.return=null;a.dependencies=null;a.memoizedProps=null;a.memoizedState=null;a.pendingProps=null;a.stateNode=null;a.updateQueue=null}function Ci(a){return 5===a.tag||3===a.tag||4===a.tag}function Di(a){a:for(;;){for(;null===a.sibling;){if(null===a.return||Ci(a.return))return null;a=a.return}a.sibling.return=a.return;for(a=a.sibling;5!==a.tag&&6!==a.tag&&18!==a.tag;){if(a.flags&2)continue a;if(null===a.child||4===a.tag)continue a;else a.child.return=a,a=a.child}if(!(a.flags&
2))return a.stateNode}}function Mf(a,b,c){var d=a.tag;if(5===d||6===d)a=a.stateNode,b?8===c.nodeType?c.parentNode.insertBefore(a,b):c.insertBefore(a,b):(8===c.nodeType?(b=c.parentNode,b.insertBefore(a,c)):(b=c,b.appendChild(a)),c=c._reactRootContainer,null!==c&&void 0!==c||null!==b.onclick||(b.onclick=kd));else if(4!==d&&(a=a.child,null!==a))for(Mf(a,b,c),a=a.sibling;null!==a;)Mf(a,b,c),a=a.sibling}function Nf(a,b,c){var d=a.tag;if(5===d||6===d)a=a.stateNode,b?c.insertBefore(a,b):c.appendChild(a);
else if(4!==d&&(a=a.child,null!==a))for(Nf(a,b,c),a=a.sibling;null!==a;)Nf(a,b,c),a=a.sibling}function jb(a,b,c){for(c=c.child;null!==c;)Ei(a,b,c),c=c.sibling}function Ei(a,b,c){if(Ca&&"function"===typeof Ca.onCommitFiberUnmount)try{Ca.onCommitFiberUnmount(Uc,c)}catch(h){}switch(c.tag){case 5:X||Wb(c,b);case 6:var d=T,e=za;T=null;jb(a,b,c);T=d;za=e;null!==T&&(za?(a=T,c=c.stateNode,8===a.nodeType?a.parentNode.removeChild(c):a.removeChild(c)):T.removeChild(c.stateNode));break;case 18:null!==T&&(za?
(a=T,c=c.stateNode,8===a.nodeType?Re(a.parentNode,c):1===a.nodeType&&Re(a,c),nc(a)):Re(T,c.stateNode));break;case 4:d=T;e=za;T=c.stateNode.containerInfo;za=!0;jb(a,b,c);T=d;za=e;break;case 0:case 11:case 14:case 15:if(!X&&(d=c.updateQueue,null!==d&&(d=d.lastEffect,null!==d))){e=d=d.next;do{var f=e,g=f.destroy;f=f.tag;void 0!==g&&(0!==(f&2)?If(c,b,g):0!==(f&4)&&If(c,b,g));e=e.next}while(e!==d)}jb(a,b,c);break;case 1:if(!X&&(Wb(c,b),d=c.stateNode,"function"===typeof d.componentWillUnmount))try{d.props=
c.memoizedProps,d.state=c.memoizedState,d.componentWillUnmount()}catch(h){H(c,b,h)}jb(a,b,c);break;case 21:jb(a,b,c);break;case 22:c.mode&1?(X=(d=X)||null!==c.memoizedState,jb(a,b,c),X=d):jb(a,b,c);break;default:jb(a,b,c)}}function Fi(a){var b=a.updateQueue;if(null!==b){a.updateQueue=null;var c=a.stateNode;null===c&&(c=a.stateNode=new Gk);b.forEach(function(b){var d=Hk.bind(null,a,b);c.has(b)||(c.add(b),b.then(d,d))})}}function Aa(a,b,c){c=b.deletions;if(null!==c)for(var d=0;d<c.length;d++){var e=
c[d];try{var f=a,g=b,h=g;a:for(;null!==h;){switch(h.tag){case 5:T=h.stateNode;za=!1;break a;case 3:T=h.stateNode.containerInfo;za=!0;break a;case 4:T=h.stateNode.containerInfo;za=!0;break a}h=h.return}if(null===T)throw Error(n(160));Ei(f,g,e);T=null;za=!1;var k=e.alternate;null!==k&&(k.return=null);e.return=null}catch(m){H(e,b,m)}}if(b.subtreeFlags&12854)for(b=b.child;null!==b;)Gi(b,a),b=b.sibling}function Gi(a,b,c){var d=a.alternate;c=a.flags;switch(a.tag){case 0:case 11:case 14:case 15:Aa(b,a);
Ha(a);if(c&4){try{Gc(3,a,a.return),Id(3,a)}catch(F){H(a,a.return,F)}try{Gc(5,a,a.return)}catch(F){H(a,a.return,F)}}break;case 1:Aa(b,a);Ha(a);c&512&&null!==d&&Wb(d,d.return);break;case 5:Aa(b,a);Ha(a);c&512&&null!==d&&Wb(d,d.return);if(a.flags&32){var e=a.stateNode;try{Fc(e,"")}catch(F){H(a,a.return,F)}}if(c&4&&(e=a.stateNode,null!=e)){var f=a.memoizedProps,g=null!==d?d.memoizedProps:f,h=a.type,k=a.updateQueue;a.updateQueue=null;if(null!==k)try{"input"===h&&"radio"===f.type&&null!=f.name&&lg(e,f);
qe(h,g);var m=qe(h,f);for(g=0;g<k.length;g+=2){var t=k[g],u=k[g+1];"style"===t?sg(e,u):"dangerouslySetInnerHTML"===t?zi(e,u):"children"===t?Fc(e,u):$d(e,t,u,m)}switch(h){case "input":le(e,f);break;case "textarea":og(e,f);break;case "select":var r=e._wrapperState.wasMultiple;e._wrapperState.wasMultiple=!!f.multiple;var p=f.value;null!=p?Db(e,!!f.multiple,p,!1):r!==!!f.multiple&&(null!=f.defaultValue?Db(e,!!f.multiple,f.defaultValue,!0):Db(e,!!f.multiple,f.multiple?[]:"",!1))}e[uc]=f}catch(F){H(a,a.return,
F)}}break;case 6:Aa(b,a);Ha(a);if(c&4){if(null===a.stateNode)throw Error(n(162));e=a.stateNode;f=a.memoizedProps;try{e.nodeValue=f}catch(F){H(a,a.return,F)}}break;case 3:Aa(b,a);Ha(a);if(c&4&&null!==d&&d.memoizedState.isDehydrated)try{nc(b.containerInfo)}catch(F){H(a,a.return,F)}break;case 4:Aa(b,a);Ha(a);break;case 13:Aa(b,a);Ha(a);e=a.child;e.flags&8192&&(f=null!==e.memoizedState,e.stateNode.isHidden=f,!f||null!==e.alternate&&null!==e.alternate.memoizedState||(Of=P()));c&4&&Fi(a);break;case 22:t=
null!==d&&null!==d.memoizedState;a.mode&1?(X=(m=X)||t,Aa(b,a),X=m):Aa(b,a);Ha(a);if(c&8192){m=null!==a.memoizedState;if((a.stateNode.isHidden=m)&&!t&&0!==(a.mode&1))for(l=a,t=a.child;null!==t;){for(u=l=t;null!==l;){r=l;p=r.child;switch(r.tag){case 0:case 11:case 14:case 15:Gc(4,r,r.return);break;case 1:Wb(r,r.return);var x=r.stateNode;if("function"===typeof x.componentWillUnmount){c=r;b=r.return;try{d=c,x.props=d.memoizedProps,x.state=d.memoizedState,x.componentWillUnmount()}catch(F){H(c,b,F)}}break;
case 5:Wb(r,r.return);break;case 22:if(null!==r.memoizedState){Hi(u);continue}}null!==p?(p.return=r,l=p):Hi(u)}t=t.sibling}a:for(t=null,u=a;;){if(5===u.tag){if(null===t){t=u;try{e=u.stateNode,m?(f=e.style,"function"===typeof f.setProperty?f.setProperty("display","none","important"):f.display="none"):(h=u.stateNode,k=u.memoizedProps.style,g=void 0!==k&&null!==k&&k.hasOwnProperty("display")?k.display:null,h.style.display=rg("display",g))}catch(F){H(a,a.return,F)}}}else if(6===u.tag){if(null===t)try{u.stateNode.nodeValue=
m?"":u.memoizedProps}catch(F){H(a,a.return,F)}}else if((22!==u.tag&&23!==u.tag||null===u.memoizedState||u===a)&&null!==u.child){u.child.return=u;u=u.child;continue}if(u===a)break a;for(;null===u.sibling;){if(null===u.return||u.return===a)break a;t===u&&(t=null);u=u.return}t===u&&(t=null);u.sibling.return=u.return;u=u.sibling}}break;case 19:Aa(b,a);Ha(a);c&4&&Fi(a);break;case 21:break;default:Aa(b,a),Ha(a)}}function Ha(a){var b=a.flags;if(b&2){try{a:{for(var c=a.return;null!==c;){if(Ci(c)){var d=c;
break a}c=c.return}throw Error(n(160));}switch(d.tag){case 5:var e=d.stateNode;d.flags&32&&(Fc(e,""),d.flags&=-33);var f=Di(a);Nf(a,f,e);break;case 3:case 4:var g=d.stateNode.containerInfo,h=Di(a);Mf(a,h,g);break;default:throw Error(n(161));}}catch(k){H(a,a.return,k)}a.flags&=-3}b&4096&&(a.flags&=-4097)}function Ik(a,b,c){l=a;Ii(a,b,c)}function Ii(a,b,c){for(var d=0!==(a.mode&1);null!==l;){var e=l,f=e.child;if(22===e.tag&&d){var g=null!==e.memoizedState||Jd;if(!g){var h=e.alternate,k=null!==h&&null!==
h.memoizedState||X;h=Jd;var m=X;Jd=g;if((X=k)&&!m)for(l=e;null!==l;)g=l,k=g.child,22===g.tag&&null!==g.memoizedState?Ji(e):null!==k?(k.return=g,l=k):Ji(e);for(;null!==f;)l=f,Ii(f,b,c),f=f.sibling;l=e;Jd=h;X=m}Ki(a,b,c)}else 0!==(e.subtreeFlags&8772)&&null!==f?(f.return=e,l=f):Ki(a,b,c)}}function Ki(a,b,c){for(;null!==l;){b=l;if(0!==(b.flags&8772)){c=b.alternate;try{if(0!==(b.flags&8772))switch(b.tag){case 0:case 11:case 15:X||Id(5,b);break;case 1:var d=b.stateNode;if(b.flags&4&&!X)if(null===c)d.componentDidMount();
else{var e=b.elementType===b.type?c.memoizedProps:xa(b.type,c.memoizedProps);d.componentDidUpdate(e,c.memoizedState,d.__reactInternalSnapshotBeforeUpdate)}var f=b.updateQueue;null!==f&&Fh(b,f,d);break;case 3:var g=b.updateQueue;if(null!==g){c=null;if(null!==b.child)switch(b.child.tag){case 5:c=b.child.stateNode;break;case 1:c=b.child.stateNode}Fh(b,g,c)}break;case 5:var h=b.stateNode;if(null===c&&b.flags&4){c=h;var k=b.memoizedProps;switch(b.type){case "button":case "input":case "select":case "textarea":k.autoFocus&&
c.focus();break;case "img":k.src&&(c.src=k.src)}}break;case 6:break;case 4:break;case 12:break;case 13:if(null===b.memoizedState){var m=b.alternate;if(null!==m){var t=m.memoizedState;if(null!==t){var p=t.dehydrated;null!==p&&nc(p)}}}break;case 19:case 17:case 21:case 22:case 23:case 25:break;default:throw Error(n(163));}X||b.flags&512&&Lf(b)}catch(r){H(b,b.return,r)}}if(b===a){l=null;break}c=b.sibling;if(null!==c){c.return=b.return;l=c;break}l=b.return}}function Hi(a){for(;null!==l;){var b=l;if(b===
a){l=null;break}var c=b.sibling;if(null!==c){c.return=b.return;l=c;break}l=b.return}}function Ji(a){for(;null!==l;){var b=l;try{switch(b.tag){case 0:case 11:case 15:var c=b.return;try{Id(4,b)}catch(k){H(b,c,k)}break;case 1:var d=b.stateNode;if("function"===typeof d.componentDidMount){var e=b.return;try{d.componentDidMount()}catch(k){H(b,e,k)}}var f=b.return;try{Lf(b)}catch(k){H(b,f,k)}break;case 5:var g=b.return;try{Lf(b)}catch(k){H(b,g,k)}}}catch(k){H(b,b.return,k)}if(b===a){l=null;break}var h=b.sibling;
if(null!==h){h.return=b.return;l=h;break}l=b.return}}function Hc(){Hf=P()+500}function Z(){return 0!==(p&6)?P():-1!==Kd?Kd:Kd=P()}function hb(a){if(0===(a.mode&1))return 1;if(0!==(p&2)&&0!==U)return U&-U;if(null!==Jk.transition)return 0===Ld&&(Ld=Dg()),Ld;a=z;if(0!==a)return a;a=window.event;a=void 0===a?16:Lg(a.type);return a}function ya(a,b,c,d){if(50<Ic)throw Ic=0,Pf=null,Error(n(185));ic(a,c,d);if(0===(p&2)||a!==O)a===O&&(0===(p&2)&&(Md|=c),4===L&&kb(a,U)),ia(a,d),1===c&&0===p&&0===(b.mode&1)&&
(Hc(),md&&db())}function ia(a,b){var c=a.callbackNode;uj(a,b);var d=Vc(a,a===O?U:0);if(0===d)null!==c&&Li(c),a.callbackNode=null,a.callbackPriority=0;else if(b=d&-d,a.callbackPriority!==b){null!=c&&Li(c);if(1===b)0===a.tag?kk(Mi.bind(null,a)):wh(Mi.bind(null,a)),Kk(function(){0===(p&6)&&db()}),c=null;else{switch(Eg(d)){case 1:c=De;break;case 4:c=Mg;break;case 16:c=ad;break;case 536870912:c=Ng;break;default:c=ad}c=Ni(c,Oi.bind(null,a))}a.callbackPriority=b;a.callbackNode=c}}function Oi(a,b){Kd=-1;
Ld=0;if(0!==(p&6))throw Error(n(327));var c=a.callbackNode;if(Xb()&&a.callbackNode!==c)return null;var d=Vc(a,a===O?U:0);if(0===d)return null;if(0!==(d&30)||0!==(d&a.expiredLanes)||b)b=Nd(a,d);else{b=d;var e=p;p|=2;var f=Pi();if(O!==a||U!==b)Ra=null,Hc(),xb(a,b);do try{Lk();break}catch(h){Qi(a,h)}while(1);Ze();Od.current=f;p=e;null!==I?b=0:(O=null,U=0,b=L)}if(0!==b){2===b&&(e=ve(a),0!==e&&(d=e,b=Qf(a,e)));if(1===b)throw c=Jc,xb(a,0),kb(a,d),ia(a,P()),c;if(6===b)kb(a,d);else{e=a.current.alternate;
if(0===(d&30)&&!Mk(e)&&(b=Nd(a,d),2===b&&(f=ve(a),0!==f&&(d=f,b=Qf(a,f))),1===b))throw c=Jc,xb(a,0),kb(a,d),ia(a,P()),c;a.finishedWork=e;a.finishedLanes=d;switch(b){case 0:case 1:throw Error(n(345));case 2:yb(a,ja,Ra);break;case 3:kb(a,d);if((d&130023424)===d&&(b=Of+500-P(),10<b)){if(0!==Vc(a,0))break;e=a.suspendedLanes;if((e&d)!==d){Z();a.pingedLanes|=a.suspendedLanes&e;break}a.timeoutHandle=Rf(yb.bind(null,a,ja,Ra),b);break}yb(a,ja,Ra);break;case 4:kb(a,d);if((d&4194240)===d)break;b=a.eventTimes;
for(e=-1;0<d;){var g=31-ta(d);f=1<<g;g=b[g];g>e&&(e=g);d&=~f}d=e;d=P()-d;d=(120>d?120:480>d?480:1080>d?1080:1920>d?1920:3E3>d?3E3:4320>d?4320:1960*Nk(d/1960))-d;if(10<d){a.timeoutHandle=Rf(yb.bind(null,a,ja,Ra),d);break}yb(a,ja,Ra);break;case 5:yb(a,ja,Ra);break;default:throw Error(n(329));}}}ia(a,P());return a.callbackNode===c?Oi.bind(null,a):null}function Qf(a,b){var c=Kc;a.current.memoizedState.isDehydrated&&(xb(a,b).flags|=256);a=Nd(a,b);2!==a&&(b=ja,ja=c,null!==b&&Gf(b));return a}function Gf(a){null===
ja?ja=a:ja.push.apply(ja,a)}function Mk(a){for(var b=a;;){if(b.flags&16384){var c=b.updateQueue;if(null!==c&&(c=c.stores,null!==c))for(var d=0;d<c.length;d++){var e=c[d],f=e.getSnapshot;e=e.value;try{if(!ua(f(),e))return!1}catch(g){return!1}}}c=b.child;if(b.subtreeFlags&16384&&null!==c)c.return=b,b=c;else{if(b===a)break;for(;null===b.sibling;){if(null===b.return||b.return===a)return!0;b=b.return}b.sibling.return=b.return;b=b.sibling}}return!0}function kb(a,b){b&=~Sf;b&=~Md;a.suspendedLanes|=b;a.pingedLanes&=
~b;for(a=a.expirationTimes;0<b;){var c=31-ta(b),d=1<<c;a[c]=-1;b&=~d}}function Mi(a){if(0!==(p&6))throw Error(n(327));Xb();var b=Vc(a,0);if(0===(b&1))return ia(a,P()),null;var c=Nd(a,b);if(0!==a.tag&&2===c){var d=ve(a);0!==d&&(b=d,c=Qf(a,d))}if(1===c)throw c=Jc,xb(a,0),kb(a,b),ia(a,P()),c;if(6===c)throw Error(n(345));a.finishedWork=a.current.alternate;a.finishedLanes=b;yb(a,ja,Ra);ia(a,P());return null}function Tf(a,b){var c=p;p|=1;try{return a(b)}finally{p=c,0===p&&(Hc(),md&&db())}}function zb(a){null!==
lb&&0===lb.tag&&0===(p&6)&&Xb();var b=p;p|=1;var c=ca.transition,d=z;try{if(ca.transition=null,z=1,a)return a()}finally{z=d,ca.transition=c,p=b,0===(p&6)&&db()}}function xb(a,b){a.finishedWork=null;a.finishedLanes=0;var c=a.timeoutHandle;-1!==c&&(a.timeoutHandle=-1,Ok(c));if(null!==I)for(c=I.return;null!==c;){var d=c;Ve(d);switch(d.tag){case 1:d=d.type.childContextTypes;null!==d&&void 0!==d&&(w(S),w(J));break;case 3:Tb();w(S);w(J);lf();break;case 5:kf(d);break;case 4:Tb();break;case 13:w(G);break;
case 19:w(G);break;case 10:af(d.type._context);break;case 22:case 23:ba=Ga.current,w(Ga)}c=c.return}O=a;I=a=gb(a.current,null);U=ba=b;L=0;Jc=null;Sf=Md=ra=0;ja=Kc=null;if(null!==tb){for(b=0;b<tb.length;b++)if(c=tb[b],d=c.interleaved,null!==d){c.interleaved=null;var e=d.next,f=c.pending;if(null!==f){var g=f.next;f.next=e;d.next=g}c.pending=d}tb=null}return a}function Qi(a,b){do{var c=I;try{Ze();zd.current=Ad;if(Bd){for(var d=C.memoizedState;null!==d;){var e=d.queue;null!==e&&(e.pending=null);d=d.next}Bd=
!1}wb=0;N=K=C=null;zc=!1;Ac=0;Uf.current=null;if(null===c||null===c.return){L=1;Jc=b;I=null;break}a:{var f=a,g=c.return,h=c,k=b;b=U;h.flags|=32768;if(null!==k&&"object"===typeof k&&"function"===typeof k.then){var m=k,l=h,p=l.tag;if(0===(l.mode&1)&&(0===p||11===p||15===p)){var r=l.alternate;r?(l.updateQueue=r.updateQueue,l.memoizedState=r.memoizedState,l.lanes=r.lanes):(l.updateQueue=null,l.memoizedState=null)}var w=ki(g);if(null!==w){w.flags&=-257;li(w,g,h,f,b);w.mode&1&&ji(f,m,b);b=w;k=m;var x=b.updateQueue;
if(null===x){var z=new Set;z.add(k);b.updateQueue=z}else x.add(k);break a}else{if(0===(b&1)){ji(f,m,b);Ef();break a}k=Error(n(426))}}else if(D&&h.mode&1){var y=ki(g);if(null!==y){0===(y.flags&65536)&&(y.flags|=256);li(y,g,h,f,b);Ye(Ub(k,h));break a}}f=k=Ub(k,h);4!==L&&(L=2);null===Kc?Kc=[f]:Kc.push(f);f=g;do{switch(f.tag){case 3:f.flags|=65536;b&=-b;f.lanes|=b;var A=hi(f,k,b);Eh(f,A);break a;case 1:h=k;var v=f.type,q=f.stateNode;if(0===(f.flags&128)&&("function"===typeof v.getDerivedStateFromError||
null!==q&&"function"===typeof q.componentDidCatch&&(null===ib||!ib.has(q)))){f.flags|=65536;b&=-b;f.lanes|=b;var B=ii(f,h,b);Eh(f,B);break a}}f=f.return}while(null!==f)}Ri(c)}catch(ma){b=ma;I===c&&null!==c&&(I=c=c.return);continue}break}while(1)}function Pi(){var a=Od.current;Od.current=Ad;return null===a?Ad:a}function Ef(){if(0===L||3===L||2===L)L=4;null===O||0===(ra&268435455)&&0===(Md&268435455)||kb(O,U)}function Nd(a,b){var c=p;p|=2;var d=Pi();if(O!==a||U!==b)Ra=null,xb(a,b);do try{Pk();break}catch(e){Qi(a,
e)}while(1);Ze();p=c;Od.current=d;if(null!==I)throw Error(n(261));O=null;U=0;return L}function Pk(){for(;null!==I;)Si(I)}function Lk(){for(;null!==I&&!Qk();)Si(I)}function Si(a){var b=Rk(a.alternate,a,ba);a.memoizedProps=a.pendingProps;null===b?Ri(a):I=b;Uf.current=null}function Ri(a){var b=a;do{var c=b.alternate;a=b.return;if(0===(b.flags&32768)){if(c=yk(c,b,ba),null!==c){I=c;return}}else{c=Ck(c,b);if(null!==c){c.flags&=32767;I=c;return}if(null!==a)a.flags|=32768,a.subtreeFlags=0,a.deletions=null;
else{L=6;I=null;return}}b=b.sibling;if(null!==b){I=b;return}I=b=a}while(null!==b);0===L&&(L=5)}function yb(a,b,c){var d=z,e=ca.transition;try{ca.transition=null,z=1,Sk(a,b,c,d)}finally{ca.transition=e,z=d}return null}function Sk(a,b,c,d){do Xb();while(null!==lb);if(0!==(p&6))throw Error(n(327));c=a.finishedWork;var e=a.finishedLanes;if(null===c)return null;a.finishedWork=null;a.finishedLanes=0;if(c===a.current)throw Error(n(177));a.callbackNode=null;a.callbackPriority=0;var f=c.lanes|c.childLanes;
vj(a,f);a===O&&(I=O=null,U=0);0===(c.subtreeFlags&2064)&&0===(c.flags&2064)||Pd||(Pd=!0,Ni(ad,function(){Xb();return null}));f=0!==(c.flags&15990);if(0!==(c.subtreeFlags&15990)||f){f=ca.transition;ca.transition=null;var g=z;z=1;var h=p;p|=4;Uf.current=null;Dk(a,c);Gi(c,a);Uj(Kf);Zc=!!Jf;Kf=Jf=null;a.current=c;Ik(c,a,e);Tk();p=h;z=g;ca.transition=f}else a.current=c;Pd&&(Pd=!1,lb=a,Qd=e);f=a.pendingLanes;0===f&&(ib=null);pj(c.stateNode,d);ia(a,P());if(null!==b)for(d=a.onRecoverableError,c=0;c<b.length;c++)e=
b[c],d(e.value,{componentStack:e.stack,digest:e.digest});if(Ed)throw Ed=!1,a=xf,xf=null,a;0!==(Qd&1)&&0!==a.tag&&Xb();f=a.pendingLanes;0!==(f&1)?a===Pf?Ic++:(Ic=0,Pf=a):Ic=0;db();return null}function Xb(){if(null!==lb){var a=Eg(Qd),b=ca.transition,c=z;try{ca.transition=null;z=16>a?16:a;if(null===lb)var d=!1;else{a=lb;lb=null;Qd=0;if(0!==(p&6))throw Error(n(331));var e=p;p|=4;for(l=a.current;null!==l;){var f=l,g=f.child;if(0!==(l.flags&16)){var h=f.deletions;if(null!==h){for(var k=0;k<h.length;k++){var m=
h[k];for(l=m;null!==l;){var t=l;switch(t.tag){case 0:case 11:case 15:Gc(8,t,f)}var u=t.child;if(null!==u)u.return=t,l=u;else for(;null!==l;){t=l;var r=t.sibling,w=t.return;Bi(t);if(t===m){l=null;break}if(null!==r){r.return=w;l=r;break}l=w}}}var x=f.alternate;if(null!==x){var y=x.child;if(null!==y){x.child=null;do{var C=y.sibling;y.sibling=null;y=C}while(null!==y)}}l=f}}if(0!==(f.subtreeFlags&2064)&&null!==g)g.return=f,l=g;else b:for(;null!==l;){f=l;if(0!==(f.flags&2048))switch(f.tag){case 0:case 11:case 15:Gc(9,
f,f.return)}var A=f.sibling;if(null!==A){A.return=f.return;l=A;break b}l=f.return}}var v=a.current;for(l=v;null!==l;){g=l;var q=g.child;if(0!==(g.subtreeFlags&2064)&&null!==q)q.return=g,l=q;else b:for(g=v;null!==l;){h=l;if(0!==(h.flags&2048))try{switch(h.tag){case 0:case 11:case 15:Id(9,h)}}catch(ma){H(h,h.return,ma)}if(h===g){l=null;break b}var B=h.sibling;if(null!==B){B.return=h.return;l=B;break b}l=h.return}}p=e;db();if(Ca&&"function"===typeof Ca.onPostCommitFiberRoot)try{Ca.onPostCommitFiberRoot(Uc,
a)}catch(ma){}d=!0}return d}finally{z=c,ca.transition=b}}return!1}function Ti(a,b,c){b=Ub(c,b);b=hi(a,b,1);a=eb(a,b,1);b=Z();null!==a&&(ic(a,1,b),ia(a,b))}function H(a,b,c){if(3===a.tag)Ti(a,a,c);else for(;null!==b;){if(3===b.tag){Ti(b,a,c);break}else if(1===b.tag){var d=b.stateNode;if("function"===typeof b.type.getDerivedStateFromError||"function"===typeof d.componentDidCatch&&(null===ib||!ib.has(d))){a=Ub(c,a);a=ii(b,a,1);b=eb(b,a,1);a=Z();null!==b&&(ic(b,1,a),ia(b,a));break}}b=b.return}}function tk(a,
b,c){var d=a.pingCache;null!==d&&d.delete(b);b=Z();a.pingedLanes|=a.suspendedLanes&c;O===a&&(U&c)===c&&(4===L||3===L&&(U&130023424)===U&&500>P()-Of?xb(a,0):Sf|=c);ia(a,b)}function Ui(a,b){0===b&&(0===(a.mode&1)?b=1:(b=Rd,Rd<<=1,0===(Rd&130023424)&&(Rd=4194304)));var c=Z();a=Oa(a,b);null!==a&&(ic(a,b,c),ia(a,c))}function wk(a){var b=a.memoizedState,c=0;null!==b&&(c=b.retryLane);Ui(a,c)}function Hk(a,b){var c=0;switch(a.tag){case 13:var d=a.stateNode;var e=a.memoizedState;null!==e&&(c=e.retryLane);
break;case 19:d=a.stateNode;break;default:throw Error(n(314));}null!==d&&d.delete(b);Ui(a,c)}function Ni(a,b){return xh(a,b)}function Uk(a,b,c,d){this.tag=a;this.key=c;this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null;this.index=0;this.ref=null;this.pendingProps=b;this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null;this.mode=d;this.subtreeFlags=this.flags=0;this.deletions=null;this.childLanes=this.lanes=0;this.alternate=null}function yf(a){a=
a.prototype;return!(!a||!a.isReactComponent)}function Vk(a){if("function"===typeof a)return yf(a)?1:0;if(void 0!==a&&null!==a){a=a.$$typeof;if(a===ie)return 11;if(a===je)return 14}return 2}function gb(a,b){var c=a.alternate;null===c?(c=pa(a.tag,b,a.key,a.mode),c.elementType=a.elementType,c.type=a.type,c.stateNode=a.stateNode,c.alternate=a,a.alternate=c):(c.pendingProps=b,c.type=a.type,c.flags=0,c.subtreeFlags=0,c.deletions=null);c.flags=a.flags&14680064;c.childLanes=a.childLanes;c.lanes=a.lanes;c.child=
a.child;c.memoizedProps=a.memoizedProps;c.memoizedState=a.memoizedState;c.updateQueue=a.updateQueue;b=a.dependencies;c.dependencies=null===b?null:{lanes:b.lanes,firstContext:b.firstContext};c.sibling=a.sibling;c.index=a.index;c.ref=a.ref;return c}function wd(a,b,c,d,e,f){var g=2;d=a;if("function"===typeof a)yf(a)&&(g=1);else if("string"===typeof a)g=5;else a:switch(a){case Bb:return ub(c.children,e,f,b);case fe:g=8;e|=8;break;case ee:return a=pa(12,c,b,e|2),a.elementType=ee,a.lanes=f,a;case ge:return a=
pa(13,c,b,e),a.elementType=ge,a.lanes=f,a;case he:return a=pa(19,c,b,e),a.elementType=he,a.lanes=f,a;case Vi:return Gd(c,e,f,b);default:if("object"===typeof a&&null!==a)switch(a.$$typeof){case hg:g=10;break a;case gg:g=9;break a;case ie:g=11;break a;case je:g=14;break a;case Ta:g=16;d=null;break a}throw Error(n(130,null==a?a:typeof a,""));}b=pa(g,c,b,e);b.elementType=a;b.type=d;b.lanes=f;return b}function ub(a,b,c,d){a=pa(7,a,d,b);a.lanes=c;return a}function Gd(a,b,c,d){a=pa(22,a,d,b);a.elementType=
Vi;a.lanes=c;a.stateNode={isHidden:!1};return a}function gf(a,b,c){a=pa(6,a,null,b);a.lanes=c;return a}function hf(a,b,c){b=pa(4,null!==a.children?a.children:[],a.key,b);b.lanes=c;b.stateNode={containerInfo:a.containerInfo,pendingChildren:null,implementation:a.implementation};return b}function Wk(a,b,c,d,e){this.tag=b;this.containerInfo=a;this.finishedWork=this.pingCache=this.current=this.pendingChildren=null;this.timeoutHandle=-1;this.callbackNode=this.pendingContext=this.context=null;this.callbackPriority=
0;this.eventTimes=we(0);this.expirationTimes=we(-1);this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0;this.entanglements=we(0);this.identifierPrefix=d;this.onRecoverableError=e;this.mutableSourceEagerHydrationData=null}function Vf(a,b,c,d,e,f,g,h,k,m){a=new Wk(a,b,c,h,k);1===b?(b=1,!0===f&&(b|=8)):b=0;f=pa(3,null,null,b);a.current=f;f.stateNode=a;f.memoizedState={element:d,isDehydrated:c,cache:null,transitions:null,
pendingSuspenseBoundaries:null};df(f);return a}function Xk(a,b,c){var d=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null;return{$$typeof:Cb,key:null==d?null:""+d,children:a,containerInfo:b,implementation:c}}function Wi(a){if(!a)return cb;a=a._reactInternals;a:{if(ob(a)!==a||1!==a.tag)throw Error(n(170));var b=a;do{switch(b.tag){case 3:b=b.stateNode.context;break a;case 1:if(ea(b.type)){b=b.stateNode.__reactInternalMemoizedMergedChildContext;break a}}b=b.return}while(null!==b);throw Error(n(171));
}if(1===a.tag){var c=a.type;if(ea(c))return uh(a,c,b)}return b}function Xi(a,b,c,d,e,f,g,h,k,m){a=Vf(c,d,!0,a,e,f,g,h,k);a.context=Wi(null);c=a.current;d=Z();e=hb(c);f=Pa(d,e);f.callback=void 0!==b&&null!==b?b:null;eb(c,f,e);a.current.lanes=e;ic(a,e,d);ia(a,d);return a}function Sd(a,b,c,d){var e=b.current,f=Z(),g=hb(e);c=Wi(c);null===b.context?b.context=c:b.pendingContext=c;b=Pa(f,g);b.payload={element:a};d=void 0===d?null:d;null!==d&&(b.callback=d);a=eb(e,b,g);null!==a&&(ya(a,e,g,f),sd(a,e,g));return g}
function Td(a){a=a.current;if(!a.child)return null;switch(a.child.tag){case 5:return a.child.stateNode;default:return a.child.stateNode}}function Yi(a,b){a=a.memoizedState;if(null!==a&&null!==a.dehydrated){var c=a.retryLane;a.retryLane=0!==c&&c<b?c:b}}function Wf(a,b){Yi(a,b);(a=a.alternate)&&Yi(a,b)}function Yk(a){a=Bg(a);return null===a?null:a.stateNode}function Zk(a){return null}function Xf(a){this._internalRoot=a}function Ud(a){this._internalRoot=a}function Yf(a){return!(!a||1!==a.nodeType&&9!==
a.nodeType&&11!==a.nodeType)}function Vd(a){return!(!a||1!==a.nodeType&&9!==a.nodeType&&11!==a.nodeType&&(8!==a.nodeType||" react-mount-point-unstable "!==a.nodeValue))}function Zi(){}function $k(a,b,c,d,e){if(e){if("function"===typeof d){var f=d;d=function(){var a=Td(g);f.call(a)}}var g=Xi(b,d,a,0,null,!1,!1,"",Zi);a._reactRootContainer=g;a[Ja]=g.current;sc(8===a.nodeType?a.parentNode:a);zb();return g}for(;e=a.lastChild;)a.removeChild(e);if("function"===typeof d){var h=d;d=function(){var a=Td(k);
h.call(a)}}var k=Vf(a,0,!1,null,null,!1,!1,"",Zi);a._reactRootContainer=k;a[Ja]=k.current;sc(8===a.nodeType?a.parentNode:a);zb(function(){Sd(b,k,c,d)});return k}function Wd(a,b,c,d,e){var f=c._reactRootContainer;if(f){var g=f;if("function"===typeof e){var h=e;e=function(){var a=Td(g);h.call(a)}}Sd(b,g,a,e)}else g=$k(c,b,a,e,d);return Td(g)}var cg=new Set,$b={},Ia=!("undefined"===typeof window||"undefined"===typeof window.document||"undefined"===typeof window.document.createElement),Zd=Object.prototype.hasOwnProperty,
dj=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,eg={},dg={},R={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(a){R[a]=
new Y(a,0,!1,a,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(a){var b=a[0];R[b]=new Y(b,1,!1,a[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(a){R[a]=new Y(a,2,!1,a.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(a){R[a]=new Y(a,2,!1,a,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(a){R[a]=
new Y(a,3,!1,a.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(a){R[a]=new Y(a,3,!0,a,null,!1,!1)});["capture","download"].forEach(function(a){R[a]=new Y(a,4,!1,a,null,!1,!1)});["cols","rows","size","span"].forEach(function(a){R[a]=new Y(a,6,!1,a,null,!1,!1)});["rowSpan","start"].forEach(function(a){R[a]=new Y(a,5,!1,a.toLowerCase(),null,!1,!1)});var Zf=/[\-:]([a-z])/g,$f=function(a){return a[1].toUpperCase()};"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(a){var b=
a.replace(Zf,$f);R[b]=new Y(b,1,!1,a,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(a){var b=a.replace(Zf,$f);R[b]=new Y(b,1,!1,a,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(a){var b=a.replace(Zf,$f);R[b]=new Y(b,1,!1,a,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(a){R[a]=new Y(a,1,!1,a.toLowerCase(),null,!1,!1)});R.xlinkHref=new Y("xlinkHref",
1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(a){R[a]=new Y(a,1,!1,a.toLowerCase(),null,!0,!0)});var Sa=mb.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,xd=Symbol.for("react.element"),Cb=Symbol.for("react.portal"),Bb=Symbol.for("react.fragment"),fe=Symbol.for("react.strict_mode"),ee=Symbol.for("react.profiler"),hg=Symbol.for("react.provider"),gg=Symbol.for("react.context"),ie=Symbol.for("react.forward_ref"),ge=Symbol.for("react.suspense"),
he=Symbol.for("react.suspense_list"),je=Symbol.for("react.memo"),Ta=Symbol.for("react.lazy");Symbol.for("react.scope");Symbol.for("react.debug_trace_mode");var Vi=Symbol.for("react.offscreen");Symbol.for("react.legacy_hidden");Symbol.for("react.cache");Symbol.for("react.tracing_marker");var fg=Symbol.iterator,E=Object.assign,ae,ce=!1,cc=Array.isArray,Xd,zi=function(a){return"undefined"!==typeof MSApp&&MSApp.execUnsafeLocalFunction?function(b,c,d,e){MSApp.execUnsafeLocalFunction(function(){return a(b,
c,d,e)})}:a}(function(a,b){if("http://www.w3.org/2000/svg"!==a.namespaceURI||"innerHTML"in a)a.innerHTML=b;else{Xd=Xd||document.createElement("div");Xd.innerHTML="<svg>"+b.valueOf().toString()+"</svg>";for(b=Xd.firstChild;a.firstChild;)a.removeChild(a.firstChild);for(;b.firstChild;)a.appendChild(b.firstChild)}}),Fc=function(a,b){if(b){var c=a.firstChild;if(c&&c===a.lastChild&&3===c.nodeType){c.nodeValue=b;return}}a.textContent=b},dc={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,
borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,
strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},al=["Webkit","ms","Moz","O"];Object.keys(dc).forEach(function(a){al.forEach(function(b){b=b+a.charAt(0).toUpperCase()+a.substring(1);dc[b]=dc[a]})});var jj=E({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0}),ze=null,se=null,Eb=null,Fb=null,xg=function(a,b){return a(b)},yg=function(){},te=!1,Oe=!1;if(Ia)try{var Lc={};Object.defineProperty(Lc,
"passive",{get:function(){Oe=!0}});window.addEventListener("test",Lc,Lc);window.removeEventListener("test",Lc,Lc)}catch(a){Oe=!1}var lj=function(a,b,c,d,e,f,g,h,k){var m=Array.prototype.slice.call(arguments,3);try{b.apply(c,m)}catch(t){this.onError(t)}},gc=!1,Sc=null,Tc=!1,ue=null,mj={onError:function(a){gc=!0;Sc=a}},Ba=mb.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Scheduler,Jg=Ba.unstable_scheduleCallback,Kg=Ba.unstable_NormalPriority,xh=Jg,Li=Ba.unstable_cancelCallback,Qk=Ba.unstable_shouldYield,
Tk=Ba.unstable_requestPaint,P=Ba.unstable_now,Ej=Ba.unstable_getCurrentPriorityLevel,De=Ba.unstable_ImmediatePriority,Mg=Ba.unstable_UserBlockingPriority,ad=Kg,Fj=Ba.unstable_LowPriority,Ng=Ba.unstable_IdlePriority,Uc=null,Ca=null,ta=Math.clz32?Math.clz32:qj,rj=Math.log,sj=Math.LN2,Wc=64,Rd=4194304,z=0,Ae=!1,Yc=[],Va=null,Wa=null,Xa=null,jc=new Map,kc=new Map,Ya=[],Cj="mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset submit".split(" "),
Gb=Sa.ReactCurrentBatchConfig,Zc=!0,$c=null,Za=null,Ee=null,bd=null,Yb={eventPhase:0,bubbles:0,cancelable:0,timeStamp:function(a){return a.timeStamp||Date.now()},defaultPrevented:0,isTrusted:0},He=ka(Yb),Mc=E({},Yb,{view:0,detail:0}),bk=ka(Mc),ag,bg,Nc,Yd=E({},Mc,{screenX:0,screenY:0,clientX:0,clientY:0,pageX:0,pageY:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,getModifierState:Fe,button:0,buttons:0,relatedTarget:function(a){return void 0===a.relatedTarget?a.fromElement===a.srcElement?a.toElement:a.fromElement:
a.relatedTarget},movementX:function(a){if("movementX"in a)return a.movementX;a!==Nc&&(Nc&&"mousemove"===a.type?(ag=a.screenX-Nc.screenX,bg=a.screenY-Nc.screenY):bg=ag=0,Nc=a);return ag},movementY:function(a){return"movementY"in a?a.movementY:bg}}),ih=ka(Yd),bl=E({},Yd,{dataTransfer:0}),Xj=ka(bl),cl=E({},Mc,{relatedTarget:0}),Pe=ka(cl),dl=E({},Yb,{animationName:0,elapsedTime:0,pseudoElement:0}),Zj=ka(dl),el=E({},Yb,{clipboardData:function(a){return"clipboardData"in a?a.clipboardData:window.clipboardData}}),
dk=ka(el),fl=E({},Yb,{data:0}),qh=ka(fl),gk=qh,gl={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},hl={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",
112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"},Hj={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"},il=E({},Mc,{key:function(a){if(a.key){var b=gl[a.key]||a.key;if("Unidentified"!==b)return b}return"keypress"===a.type?(a=cd(a),13===a?"Enter":String.fromCharCode(a)):"keydown"===a.type||"keyup"===a.type?hl[a.keyCode]||"Unidentified":""},code:0,location:0,ctrlKey:0,shiftKey:0,altKey:0,
metaKey:0,repeat:0,locale:0,getModifierState:Fe,charCode:function(a){return"keypress"===a.type?cd(a):0},keyCode:function(a){return"keydown"===a.type||"keyup"===a.type?a.keyCode:0},which:function(a){return"keypress"===a.type?cd(a):"keydown"===a.type||"keyup"===a.type?a.keyCode:0}}),Wj=ka(il),jl=E({},Yd,{pointerId:0,width:0,height:0,pressure:0,tangentialPressure:0,tiltX:0,tiltY:0,twist:0,pointerType:0,isPrimary:0}),nh=ka(jl),kl=E({},Mc,{touches:0,targetTouches:0,changedTouches:0,altKey:0,metaKey:0,
ctrlKey:0,shiftKey:0,getModifierState:Fe}),Yj=ka(kl),ll=E({},Yb,{propertyName:0,elapsedTime:0,pseudoElement:0}),ak=ka(ll),ml=E({},Yd,{deltaX:function(a){return"deltaX"in a?a.deltaX:"wheelDeltaX"in a?-a.wheelDeltaX:0},deltaY:function(a){return"deltaY"in a?a.deltaY:"wheelDeltaY"in a?-a.wheelDeltaY:"wheelDelta"in a?-a.wheelDelta:0},deltaZ:0,deltaMode:0}),ck=ka(ml),Ij=[9,13,27,32],Ge=Ia&&"CompositionEvent"in window,Oc=null;Ia&&"documentMode"in document&&(Oc=document.documentMode);var fk=Ia&&"TextEvent"in
window&&!Oc,Ug=Ia&&(!Ge||Oc&&8<Oc&&11>=Oc),Tg=String.fromCharCode(32),Sg=!1,Hb=!1,Lj={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0},oc=null,pc=null,ph=!1;Ia&&(ph=Mj("input")&&(!document.documentMode||9<document.documentMode));var ua="function"===typeof Object.is?Object.is:Tj,ek=Ia&&"documentMode"in document&&11>=document.documentMode,Jb=null,Ke=null,rc=null,Je=!1,Kb={animationend:gd("Animation","AnimationEnd"),
animationiteration:gd("Animation","AnimationIteration"),animationstart:gd("Animation","AnimationStart"),transitionend:gd("Transition","TransitionEnd")},Le={},eh={};Ia&&(eh=document.createElement("div").style,"AnimationEvent"in window||(delete Kb.animationend.animation,delete Kb.animationiteration.animation,delete Kb.animationstart.animation),"TransitionEvent"in window||delete Kb.transitionend.transition);var jh=hd("animationend"),kh=hd("animationiteration"),lh=hd("animationstart"),mh=hd("transitionend"),
fh=new Map,$i="abort auxClick cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(" ");
(function(){for(var a=0;a<$i.length;a++){var b=$i[a],c=b.toLowerCase();b=b[0].toUpperCase()+b.slice(1);$a(c,"on"+b)}$a(jh,"onAnimationEnd");$a(kh,"onAnimationIteration");$a(lh,"onAnimationStart");$a("dblclick","onDoubleClick");$a("focusin","onFocus");$a("focusout","onBlur");$a(mh,"onTransitionEnd")})();Ab("onMouseEnter",["mouseout","mouseover"]);Ab("onMouseLeave",["mouseout","mouseover"]);Ab("onPointerEnter",["pointerout","pointerover"]);Ab("onPointerLeave",["pointerout","pointerover"]);nb("onChange",
"change click focusin focusout input keydown keyup selectionchange".split(" "));nb("onSelect","focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange".split(" "));nb("onBeforeInput",["compositionend","keypress","textInput","paste"]);nb("onCompositionEnd","compositionend focusout keydown keypress keyup mousedown".split(" "));nb("onCompositionStart","compositionstart focusout keydown keypress keyup mousedown".split(" "));nb("onCompositionUpdate","compositionupdate focusout keydown keypress keyup mousedown".split(" "));
var Ec="abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange resize seeked seeking stalled suspend timeupdate volumechange waiting".split(" "),Vj=new Set("cancel close invalid load scroll toggle".split(" ").concat(Ec)),id="_reactListening"+Math.random().toString(36).slice(2),hk=/\r\n?/g,ik=/\u0000|\uFFFD/g,Jf=null,Kf=null,Rf="function"===typeof setTimeout?setTimeout:void 0,Ok="function"===typeof clearTimeout?
clearTimeout:void 0,aj="function"===typeof Promise?Promise:void 0,Kk="function"===typeof queueMicrotask?queueMicrotask:"undefined"!==typeof aj?function(a){return aj.resolve(null).then(a).catch(jk)}:Rf,Zb=Math.random().toString(36).slice(2),Da="__reactFiber$"+Zb,uc="__reactProps$"+Zb,Ja="__reactContainer$"+Zb,Me="__reactEvents$"+Zb,Ek="__reactListeners$"+Zb,Fk="__reactHandles$"+Zb,Se=[],Mb=-1,cb={},J=bb(cb),S=bb(!1),qb=cb,La=null,md=!1,Te=!1,Ob=[],Pb=0,od=null,nd=0,na=[],oa=0,sb=null,Ma=1,Na="",la=
null,fa=null,D=!1,wa=null,Jk=Sa.ReactCurrentBatchConfig,rd=bb(null),qd=null,Rb=null,$e=null,tb=null,lk=Oa,fb=!1,Jh=(new mb.Component).refs,ud={isMounted:function(a){return(a=a._reactInternals)?ob(a)===a:!1},enqueueSetState:function(a,b,c){a=a._reactInternals;var d=Z(),e=hb(a),f=Pa(d,e);f.payload=b;void 0!==c&&null!==c&&(f.callback=c);b=eb(a,f,e);null!==b&&(ya(b,a,e,d),sd(b,a,e))},enqueueReplaceState:function(a,b,c){a=a._reactInternals;var d=Z(),e=hb(a),f=Pa(d,e);f.tag=1;f.payload=b;void 0!==c&&null!==
c&&(f.callback=c);b=eb(a,f,e);null!==b&&(ya(b,a,e,d),sd(b,a,e))},enqueueForceUpdate:function(a,b){a=a._reactInternals;var c=Z(),d=hb(a),e=Pa(c,d);e.tag=2;void 0!==b&&null!==b&&(e.callback=b);b=eb(a,e,d);null!==b&&(ya(b,a,d,c),sd(b,a,d))}},Vb=Lh(!0),mi=Lh(!1),wc={},Ea=bb(wc),yc=bb(wc),xc=bb(wc),G=bb(0),mf=[],zd=Sa.ReactCurrentDispatcher,uf=Sa.ReactCurrentBatchConfig,wb=0,C=null,K=null,N=null,Bd=!1,zc=!1,Ac=0,nl=0,Ad={readContext:qa,useCallback:V,useContext:V,useEffect:V,useImperativeHandle:V,useInsertionEffect:V,
useLayoutEffect:V,useMemo:V,useReducer:V,useRef:V,useState:V,useDebugValue:V,useDeferredValue:V,useTransition:V,useMutableSource:V,useSyncExternalStore:V,useId:V,unstable_isNewReconciler:!1},mk={readContext:qa,useCallback:function(a,b){Fa().memoizedState=[a,void 0===b?null:b];return a},useContext:qa,useEffect:Wh,useImperativeHandle:function(a,b,c){c=null!==c&&void 0!==c?c.concat([a]):null;return Cd(4194308,4,Zh.bind(null,b,a),c)},useLayoutEffect:function(a,b){return Cd(4194308,4,a,b)},useInsertionEffect:function(a,
b){return Cd(4,2,a,b)},useMemo:function(a,b){var c=Fa();b=void 0===b?null:b;a=a();c.memoizedState=[a,b];return a},useReducer:function(a,b,c){var d=Fa();b=void 0!==c?c(b):b;d.memoizedState=d.baseState=b;a={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:a,lastRenderedState:b};d.queue=a;a=a.dispatch=rk.bind(null,C,a);return[d.memoizedState,a]},useRef:function(a){var b=Fa();a={current:a};return b.memoizedState=a},useState:Uh,useDebugValue:tf,useDeferredValue:function(a){return Fa().memoizedState=
a},useTransition:function(){var a=Uh(!1),b=a[0];a=qk.bind(null,a[1]);Fa().memoizedState=a;return[b,a]},useMutableSource:function(a,b,c){},useSyncExternalStore:function(a,b,c){var d=C,e=Fa();if(D){if(void 0===c)throw Error(n(407));c=c()}else{c=b();if(null===O)throw Error(n(349));0!==(wb&30)||Rh(d,b,c)}e.memoizedState=c;var f={value:c,getSnapshot:b};e.queue=f;Wh(Ph.bind(null,d,f,a),[a]);d.flags|=2048;Cc(9,Qh.bind(null,d,f,c,b),void 0,null);return c},useId:function(){var a=Fa(),b=O.identifierPrefix;
if(D){var c=Na;var d=Ma;c=(d&~(1<<32-ta(d)-1)).toString(32)+c;b=":"+b+"R"+c;c=Ac++;0<c&&(b+="H"+c.toString(32));b+=":"}else c=nl++,b=":"+b+"r"+c.toString(32)+":";return a.memoizedState=b},unstable_isNewReconciler:!1},nk={readContext:qa,useCallback:ai,useContext:qa,useEffect:sf,useImperativeHandle:$h,useInsertionEffect:Xh,useLayoutEffect:Yh,useMemo:bi,useReducer:qf,useRef:Vh,useState:function(a){return qf(Bc)},useDebugValue:tf,useDeferredValue:function(a){var b=sa();return ci(b,K.memoizedState,a)},
useTransition:function(){var a=qf(Bc)[0],b=sa().memoizedState;return[a,b]},useMutableSource:Nh,useSyncExternalStore:Oh,useId:di,unstable_isNewReconciler:!1},ok={readContext:qa,useCallback:ai,useContext:qa,useEffect:sf,useImperativeHandle:$h,useInsertionEffect:Xh,useLayoutEffect:Yh,useMemo:bi,useReducer:rf,useRef:Vh,useState:function(a){return rf(Bc)},useDebugValue:tf,useDeferredValue:function(a){var b=sa();return null===K?b.memoizedState=a:ci(b,K.memoizedState,a)},useTransition:function(){var a=rf(Bc)[0],
b=sa().memoizedState;return[a,b]},useMutableSource:Nh,useSyncExternalStore:Oh,useId:di,unstable_isNewReconciler:!1},sk="function"===typeof WeakMap?WeakMap:Map,uk=Sa.ReactCurrentOwner,ha=!1,Cf={dehydrated:null,treeContext:null,retryLane:0};var Ak=function(a,b,c,d){for(c=b.child;null!==c;){if(5===c.tag||6===c.tag)a.appendChild(c.stateNode);else if(4!==c.tag&&null!==c.child){c.child.return=c;c=c.child;continue}if(c===b)break;for(;null===c.sibling;){if(null===c.return||c.return===b)return;c=c.return}c.sibling.return=
c.return;c=c.sibling}};var yi=function(a,b){};var zk=function(a,b,c,d,e){var f=a.memoizedProps;if(f!==d){a=b.stateNode;vb(Ea.current);e=null;switch(c){case "input":f=ke(a,f);d=ke(a,d);e=[];break;case "select":f=E({},f,{value:void 0});d=E({},d,{value:void 0});e=[];break;case "textarea":f=ne(a,f);d=ne(a,d);e=[];break;default:"function"!==typeof f.onClick&&"function"===typeof d.onClick&&(a.onclick=kd)}pe(c,d);var g;c=null;for(m in f)if(!d.hasOwnProperty(m)&&f.hasOwnProperty(m)&&null!=f[m])if("style"===
m){var h=f[m];for(g in h)h.hasOwnProperty(g)&&(c||(c={}),c[g]="")}else"dangerouslySetInnerHTML"!==m&&"children"!==m&&"suppressContentEditableWarning"!==m&&"suppressHydrationWarning"!==m&&"autoFocus"!==m&&($b.hasOwnProperty(m)?e||(e=[]):(e=e||[]).push(m,null));for(m in d){var k=d[m];h=null!=f?f[m]:void 0;if(d.hasOwnProperty(m)&&k!==h&&(null!=k||null!=h))if("style"===m)if(h){for(g in h)!h.hasOwnProperty(g)||k&&k.hasOwnProperty(g)||(c||(c={}),c[g]="");for(g in k)k.hasOwnProperty(g)&&h[g]!==k[g]&&(c||
(c={}),c[g]=k[g])}else c||(e||(e=[]),e.push(m,c)),c=k;else"dangerouslySetInnerHTML"===m?(k=k?k.__html:void 0,h=h?h.__html:void 0,null!=k&&h!==k&&(e=e||[]).push(m,k)):"children"===m?"string"!==typeof k&&"number"!==typeof k||(e=e||[]).push(m,""+k):"suppressContentEditableWarning"!==m&&"suppressHydrationWarning"!==m&&($b.hasOwnProperty(m)?(null!=k&&"onScroll"===m&&B("scroll",a),e||h===k||(e=[])):(e=e||[]).push(m,k))}c&&(e=e||[]).push("style",c);var m=e;if(b.updateQueue=m)b.flags|=4}};var Bk=function(a,
b,c,d){c!==d&&(b.flags|=4)};var Jd=!1,X=!1,Gk="function"===typeof WeakSet?WeakSet:Set,l=null,Ai=!1,T=null,za=!1,Nk=Math.ceil,Od=Sa.ReactCurrentDispatcher,Uf=Sa.ReactCurrentOwner,ca=Sa.ReactCurrentBatchConfig,p=0,O=null,I=null,U=0,ba=0,Ga=bb(0),L=0,Jc=null,ra=0,Md=0,Sf=0,Kc=null,ja=null,Of=0,Hf=Infinity,Ra=null,Ed=!1,xf=null,ib=null,Pd=!1,lb=null,Qd=0,Ic=0,Pf=null,Kd=-1,Ld=0;var Rk=function(a,b,c){if(null!==a)if(a.memoizedProps!==b.pendingProps||S.current)ha=!0;else{if(0===(a.lanes&c)&&0===(b.flags&
128))return ha=!1,xk(a,b,c);ha=0!==(a.flags&131072)?!0:!1}else ha=!1,D&&0!==(b.flags&1048576)&&yh(b,nd,b.index);b.lanes=0;switch(b.tag){case 2:var d=b.type;Fd(a,b);a=b.pendingProps;var e=Nb(b,J.current);Sb(b,c);e=of(null,b,d,a,e,c);var f=pf();b.flags|=1;"object"===typeof e&&null!==e&&"function"===typeof e.render&&void 0===e.$$typeof?(b.tag=1,b.memoizedState=null,b.updateQueue=null,ea(d)?(f=!0,ld(b)):f=!1,b.memoizedState=null!==e.state&&void 0!==e.state?e.state:null,df(b),e.updater=ud,b.stateNode=
e,e._reactInternals=b,ff(b,d,a,c),b=Af(null,b,d,!0,f,c)):(b.tag=0,D&&f&&Ue(b),aa(null,b,e,c),b=b.child);return b;case 16:d=b.elementType;a:{Fd(a,b);a=b.pendingProps;e=d._init;d=e(d._payload);b.type=d;e=b.tag=Vk(d);a=xa(d,a);switch(e){case 0:b=zf(null,b,d,a,c);break a;case 1:b=si(null,b,d,a,c);break a;case 11:b=ni(null,b,d,a,c);break a;case 14:b=oi(null,b,d,xa(d.type,a),c);break a}throw Error(n(306,d,""));}return b;case 0:return d=b.type,e=b.pendingProps,e=b.elementType===d?e:xa(d,e),zf(a,b,d,e,c);
case 1:return d=b.type,e=b.pendingProps,e=b.elementType===d?e:xa(d,e),si(a,b,d,e,c);case 3:a:{ti(b);if(null===a)throw Error(n(387));d=b.pendingProps;f=b.memoizedState;e=f.element;Dh(a,b);td(b,d,null,c);var g=b.memoizedState;d=g.element;if(f.isDehydrated)if(f={element:d,isDehydrated:!1,cache:g.cache,pendingSuspenseBoundaries:g.pendingSuspenseBoundaries,transitions:g.transitions},b.updateQueue.baseState=f,b.memoizedState=f,b.flags&256){e=Ub(Error(n(423)),b);b=ui(a,b,d,c,e);break a}else if(d!==e){e=
Ub(Error(n(424)),b);b=ui(a,b,d,c,e);break a}else for(fa=Ka(b.stateNode.containerInfo.firstChild),la=b,D=!0,wa=null,c=mi(b,null,d,c),b.child=c;c;)c.flags=c.flags&-3|4096,c=c.sibling;else{Qb();if(d===e){b=Qa(a,b,c);break a}aa(a,b,d,c)}b=b.child}return b;case 5:return Mh(b),null===a&&Xe(b),d=b.type,e=b.pendingProps,f=null!==a?a.memoizedProps:null,g=e.children,Qe(d,e)?g=null:null!==f&&Qe(d,f)&&(b.flags|=32),ri(a,b),aa(a,b,g,c),b.child;case 6:return null===a&&Xe(b),null;case 13:return vi(a,b,c);case 4:return jf(b,
b.stateNode.containerInfo),d=b.pendingProps,null===a?b.child=Vb(b,null,d,c):aa(a,b,d,c),b.child;case 11:return d=b.type,e=b.pendingProps,e=b.elementType===d?e:xa(d,e),ni(a,b,d,e,c);case 7:return aa(a,b,b.pendingProps,c),b.child;case 8:return aa(a,b,b.pendingProps.children,c),b.child;case 12:return aa(a,b,b.pendingProps.children,c),b.child;case 10:a:{d=b.type._context;e=b.pendingProps;f=b.memoizedProps;g=e.value;y(rd,d._currentValue);d._currentValue=g;if(null!==f)if(ua(f.value,g)){if(f.children===
e.children&&!S.current){b=Qa(a,b,c);break a}}else for(f=b.child,null!==f&&(f.return=b);null!==f;){var h=f.dependencies;if(null!==h){g=f.child;for(var k=h.firstContext;null!==k;){if(k.context===d){if(1===f.tag){k=Pa(-1,c&-c);k.tag=2;var m=f.updateQueue;if(null!==m){m=m.shared;var l=m.pending;null===l?k.next=k:(k.next=l.next,l.next=k);m.pending=k}}f.lanes|=c;k=f.alternate;null!==k&&(k.lanes|=c);bf(f.return,c,b);h.lanes|=c;break}k=k.next}}else if(10===f.tag)g=f.type===b.type?null:f.child;else if(18===
f.tag){g=f.return;if(null===g)throw Error(n(341));g.lanes|=c;h=g.alternate;null!==h&&(h.lanes|=c);bf(g,c,b);g=f.sibling}else g=f.child;if(null!==g)g.return=f;else for(g=f;null!==g;){if(g===b){g=null;break}f=g.sibling;if(null!==f){f.return=g.return;g=f;break}g=g.return}f=g}aa(a,b,e.children,c);b=b.child}return b;case 9:return e=b.type,d=b.pendingProps.children,Sb(b,c),e=qa(e),d=d(e),b.flags|=1,aa(a,b,d,c),b.child;case 14:return d=b.type,e=xa(d,b.pendingProps),e=xa(d.type,e),oi(a,b,d,e,c);case 15:return pi(a,
b,b.type,b.pendingProps,c);case 17:return d=b.type,e=b.pendingProps,e=b.elementType===d?e:xa(d,e),Fd(a,b),b.tag=1,ea(d)?(a=!0,ld(b)):a=!1,Sb(b,c),Hh(b,d,e),ff(b,d,e,c),Af(null,b,d,!0,a,c);case 19:return xi(a,b,c);case 22:return qi(a,b,c)}throw Error(n(156,b.tag));};var pa=function(a,b,c,d){return new Uk(a,b,c,d)},bj="function"===typeof reportError?reportError:function(a){console.error(a)};Ud.prototype.render=Xf.prototype.render=function(a){var b=this._internalRoot;if(null===b)throw Error(n(409));
Sd(a,b,null,null)};Ud.prototype.unmount=Xf.prototype.unmount=function(){var a=this._internalRoot;if(null!==a){this._internalRoot=null;var b=a.containerInfo;zb(function(){Sd(null,a,null,null)});b[Ja]=null}};Ud.prototype.unstable_scheduleHydration=function(a){if(a){var b=ol();a={blockedOn:null,target:a,priority:b};for(var c=0;c<Ya.length&&0!==b&&b<Ya[c].priority;c++);Ya.splice(c,0,a);0===c&&Hg(a)}};var Dj=function(a){switch(a.tag){case 3:var b=a.stateNode;if(b.current.memoizedState.isDehydrated){var c=
hc(b.pendingLanes);0!==c&&(xe(b,c|1),ia(b,P()),0===(p&6)&&(Hc(),db()))}break;case 13:zb(function(){var b=Oa(a,1);if(null!==b){var c=Z();ya(b,a,1,c)}}),Wf(a,1)}};var Gg=function(a){if(13===a.tag){var b=Oa(a,134217728);if(null!==b){var c=Z();ya(b,a,134217728,c)}Wf(a,134217728)}};var yj=function(a){if(13===a.tag){var b=hb(a),c=Oa(a,b);if(null!==c){var d=Z();ya(c,a,b,d)}Wf(a,b)}};var ol=function(){return z};var xj=function(a,b){var c=z;try{return z=a,b()}finally{z=c}};se=function(a,b,c){switch(b){case "input":le(a,
c);b=c.name;if("radio"===c.type&&null!=b){for(c=a;c.parentNode;)c=c.parentNode;c=c.querySelectorAll("input[name="+JSON.stringify(""+b)+'][type="radio"]');for(b=0;b<c.length;b++){var d=c[b];if(d!==a&&d.form===a.form){var e=Rc(d);if(!e)throw Error(n(90));jg(d);le(d,e)}}}break;case "textarea":og(a,c);break;case "select":b=c.value,null!=b&&Db(a,!!c.multiple,b,!1)}};(function(a,b,c){xg=a;yg=c})(Tf,function(a,b,c,d,e){var f=z,g=ca.transition;try{return ca.transition=null,z=1,a(b,c,d,e)}finally{z=f,ca.transition=
g,0===p&&Hc()}},zb);var pl={usingClientEntryPoint:!1,Events:[ec,Ib,Rc,ug,vg,Tf]};(function(a){a={bundleType:a.bundleType,version:a.version,rendererPackageName:a.rendererPackageName,rendererConfig:a.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setErrorHandler:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:Sa.ReactCurrentDispatcher,findHostInstanceByFiber:Yk,
findFiberByHostInstance:a.findFiberByHostInstance||Zk,findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null,reconcilerVersion:"18.2.0"};if("undefined"===typeof __REACT_DEVTOOLS_GLOBAL_HOOK__)a=!1;else{var b=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(b.isDisabled||!b.supportsFiber)a=!0;else{try{Uc=b.inject(a),Ca=b}catch(c){}a=b.checkDCE?!0:!1}}return a})({findFiberByHostInstance:pb,bundleType:0,version:"18.2.0-next-9e3b772b8-20220608",
rendererPackageName:"react-dom"});Q.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=pl;Q.createPortal=function(a,b){var c=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;if(!Yf(b))throw Error(n(200));return Xk(a,b,null,c)};Q.createRoot=function(a,b){if(!Yf(a))throw Error(n(299));var c=!1,d="",e=bj;null!==b&&void 0!==b&&(!0===b.unstable_strictMode&&(c=!0),void 0!==b.identifierPrefix&&(d=b.identifierPrefix),void 0!==b.onRecoverableError&&(e=b.onRecoverableError));b=Vf(a,1,!1,null,null,
c,!1,d,e);a[Ja]=b.current;sc(8===a.nodeType?a.parentNode:a);return new Xf(b)};Q.findDOMNode=function(a){if(null==a)return null;if(1===a.nodeType)return a;var b=a._reactInternals;if(void 0===b){if("function"===typeof a.render)throw Error(n(188));a=Object.keys(a).join(",");throw Error(n(268,a));}a=Bg(b);a=null===a?null:a.stateNode;return a};Q.flushSync=function(a){return zb(a)};Q.hydrate=function(a,b,c){if(!Vd(b))throw Error(n(200));return Wd(null,a,b,!0,c)};Q.hydrateRoot=function(a,b,c){if(!Yf(a))throw Error(n(405));
var d=null!=c&&c.hydratedSources||null,e=!1,f="",g=bj;null!==c&&void 0!==c&&(!0===c.unstable_strictMode&&(e=!0),void 0!==c.identifierPrefix&&(f=c.identifierPrefix),void 0!==c.onRecoverableError&&(g=c.onRecoverableError));b=Xi(b,null,a,1,null!=c?c:null,e,!1,f,g);a[Ja]=b.current;sc(a);if(d)for(a=0;a<d.length;a++)c=d[a],e=c._getVersion,e=e(c._source),null==b.mutableSourceEagerHydrationData?b.mutableSourceEagerHydrationData=[c,e]:b.mutableSourceEagerHydrationData.push(c,e);return new Ud(b)};Q.render=
function(a,b,c){if(!Vd(b))throw Error(n(200));return Wd(null,a,b,!1,c)};Q.unmountComponentAtNode=function(a){if(!Vd(a))throw Error(n(40));return a._reactRootContainer?(zb(function(){Wd(null,null,a,!1,function(){a._reactRootContainer=null;a[Ja]=null})}),!0):!1};Q.unstable_batchedUpdates=Tf;Q.unstable_renderSubtreeIntoContainer=function(a,b,c,d){if(!Vd(c))throw Error(n(200));if(null==a||void 0===a._reactInternals)throw Error(n(38));return Wd(a,b,c,!1,d)};Q.version="18.2.0-next-9e3b772b8-20220608"});
})();

View File

@ -0,0 +1,31 @@
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
(function(){'use strict';(function(c,x){"object"===typeof exports&&"undefined"!==typeof module?x(exports):"function"===typeof define&&define.amd?define(["exports"],x):(c=c||self,x(c.React={}))})(this,function(c){function x(a){if(null===a||"object"!==typeof a)return null;a=V&&a[V]||a["@@iterator"];return"function"===typeof a?a:null}function w(a,b,e){this.props=a;this.context=b;this.refs=W;this.updater=e||X}function Y(){}function K(a,b,e){this.props=a;this.context=b;this.refs=W;this.updater=e||X}function Z(a,b,
e){var m,d={},c=null,h=null;if(null!=b)for(m in void 0!==b.ref&&(h=b.ref),void 0!==b.key&&(c=""+b.key),b)aa.call(b,m)&&!ba.hasOwnProperty(m)&&(d[m]=b[m]);var l=arguments.length-2;if(1===l)d.children=e;else if(1<l){for(var f=Array(l),k=0;k<l;k++)f[k]=arguments[k+2];d.children=f}if(a&&a.defaultProps)for(m in l=a.defaultProps,l)void 0===d[m]&&(d[m]=l[m]);return{$$typeof:y,type:a,key:c,ref:h,props:d,_owner:L.current}}function na(a,b){return{$$typeof:y,type:a.type,key:b,ref:a.ref,props:a.props,_owner:a._owner}}
function M(a){return"object"===typeof a&&null!==a&&a.$$typeof===y}function oa(a){var b={"=":"=0",":":"=2"};return"$"+a.replace(/[=:]/g,function(a){return b[a]})}function N(a,b){return"object"===typeof a&&null!==a&&null!=a.key?oa(""+a.key):b.toString(36)}function B(a,b,e,m,d){var c=typeof a;if("undefined"===c||"boolean"===c)a=null;var h=!1;if(null===a)h=!0;else switch(c){case "string":case "number":h=!0;break;case "object":switch(a.$$typeof){case y:case pa:h=!0}}if(h)return h=a,d=d(h),a=""===m?"."+
N(h,0):m,ca(d)?(e="",null!=a&&(e=a.replace(da,"$&/")+"/"),B(d,b,e,"",function(a){return a})):null!=d&&(M(d)&&(d=na(d,e+(!d.key||h&&h.key===d.key?"":(""+d.key).replace(da,"$&/")+"/")+a)),b.push(d)),1;h=0;m=""===m?".":m+":";if(ca(a))for(var l=0;l<a.length;l++){c=a[l];var f=m+N(c,l);h+=B(c,b,e,f,d)}else if(f=x(a),"function"===typeof f)for(a=f.call(a),l=0;!(c=a.next()).done;)c=c.value,f=m+N(c,l++),h+=B(c,b,e,f,d);else if("object"===c)throw b=String(a),Error("Objects are not valid as a React child (found: "+
("[object Object]"===b?"object with keys {"+Object.keys(a).join(", ")+"}":b)+"). If you meant to render a collection of children, use an array instead.");return h}function C(a,b,e){if(null==a)return a;var c=[],d=0;B(a,c,"","",function(a){return b.call(e,a,d++)});return c}function qa(a){if(-1===a._status){var b=a._result;b=b();b.then(function(b){if(0===a._status||-1===a._status)a._status=1,a._result=b},function(b){if(0===a._status||-1===a._status)a._status=2,a._result=b});-1===a._status&&(a._status=
0,a._result=b)}if(1===a._status)return a._result.default;throw a._result;}function O(a,b){var e=a.length;a.push(b);a:for(;0<e;){var c=e-1>>>1,d=a[c];if(0<D(d,b))a[c]=b,a[e]=d,e=c;else break a}}function p(a){return 0===a.length?null:a[0]}function E(a){if(0===a.length)return null;var b=a[0],e=a.pop();if(e!==b){a[0]=e;a:for(var c=0,d=a.length,k=d>>>1;c<k;){var h=2*(c+1)-1,l=a[h],f=h+1,g=a[f];if(0>D(l,e))f<d&&0>D(g,l)?(a[c]=g,a[f]=e,c=f):(a[c]=l,a[h]=e,c=h);else if(f<d&&0>D(g,e))a[c]=g,a[f]=e,c=f;else break a}}return b}
function D(a,b){var c=a.sortIndex-b.sortIndex;return 0!==c?c:a.id-b.id}function P(a){for(var b=p(r);null!==b;){if(null===b.callback)E(r);else if(b.startTime<=a)E(r),b.sortIndex=b.expirationTime,O(q,b);else break;b=p(r)}}function Q(a){z=!1;P(a);if(!u)if(null!==p(q))u=!0,R(S);else{var b=p(r);null!==b&&T(Q,b.startTime-a)}}function S(a,b){u=!1;z&&(z=!1,ea(A),A=-1);F=!0;var c=k;try{P(b);for(n=p(q);null!==n&&(!(n.expirationTime>b)||a&&!fa());){var m=n.callback;if("function"===typeof m){n.callback=null;
k=n.priorityLevel;var d=m(n.expirationTime<=b);b=v();"function"===typeof d?n.callback=d:n===p(q)&&E(q);P(b)}else E(q);n=p(q)}if(null!==n)var g=!0;else{var h=p(r);null!==h&&T(Q,h.startTime-b);g=!1}return g}finally{n=null,k=c,F=!1}}function fa(){return v()-ha<ia?!1:!0}function R(a){G=a;H||(H=!0,I())}function T(a,b){A=ja(function(){a(v())},b)}var y=Symbol.for("react.element"),pa=Symbol.for("react.portal"),ra=Symbol.for("react.fragment"),sa=Symbol.for("react.strict_mode"),ta=Symbol.for("react.profiler"),
ua=Symbol.for("react.provider"),va=Symbol.for("react.context"),wa=Symbol.for("react.forward_ref"),xa=Symbol.for("react.suspense"),ya=Symbol.for("react.memo"),za=Symbol.for("react.lazy"),V=Symbol.iterator,X={isMounted:function(a){return!1},enqueueForceUpdate:function(a,b,c){},enqueueReplaceState:function(a,b,c,m){},enqueueSetState:function(a,b,c,m){}},ka=Object.assign,W={};w.prototype.isReactComponent={};w.prototype.setState=function(a,b){if("object"!==typeof a&&"function"!==typeof a&&null!=a)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");
this.updater.enqueueSetState(this,a,b,"setState")};w.prototype.forceUpdate=function(a){this.updater.enqueueForceUpdate(this,a,"forceUpdate")};Y.prototype=w.prototype;var t=K.prototype=new Y;t.constructor=K;ka(t,w.prototype);t.isPureReactComponent=!0;var ca=Array.isArray,aa=Object.prototype.hasOwnProperty,L={current:null},ba={key:!0,ref:!0,__self:!0,__source:!0},da=/\/+/g,g={current:null},J={transition:null};if("object"===typeof performance&&"function"===typeof performance.now){var Aa=performance;
var v=function(){return Aa.now()}}else{var la=Date,Ba=la.now();v=function(){return la.now()-Ba}}var q=[],r=[],Ca=1,n=null,k=3,F=!1,u=!1,z=!1,ja="function"===typeof setTimeout?setTimeout:null,ea="function"===typeof clearTimeout?clearTimeout:null,ma="undefined"!==typeof setImmediate?setImmediate:null;"undefined"!==typeof navigator&&void 0!==navigator.scheduling&&void 0!==navigator.scheduling.isInputPending&&navigator.scheduling.isInputPending.bind(navigator.scheduling);var H=!1,G=null,A=-1,ia=5,ha=
-1,U=function(){if(null!==G){var a=v();ha=a;var b=!0;try{b=G(!0,a)}finally{b?I():(H=!1,G=null)}}else H=!1};if("function"===typeof ma)var I=function(){ma(U)};else if("undefined"!==typeof MessageChannel){t=new MessageChannel;var Da=t.port2;t.port1.onmessage=U;I=function(){Da.postMessage(null)}}else I=function(){ja(U,0)};t={ReactCurrentDispatcher:g,ReactCurrentOwner:L,ReactCurrentBatchConfig:J,Scheduler:{__proto__:null,unstable_ImmediatePriority:1,unstable_UserBlockingPriority:2,unstable_NormalPriority:3,
unstable_IdlePriority:5,unstable_LowPriority:4,unstable_runWithPriority:function(a,b){switch(a){case 1:case 2:case 3:case 4:case 5:break;default:a=3}var c=k;k=a;try{return b()}finally{k=c}},unstable_next:function(a){switch(k){case 1:case 2:case 3:var b=3;break;default:b=k}var c=k;k=b;try{return a()}finally{k=c}},unstable_scheduleCallback:function(a,b,c){var e=v();"object"===typeof c&&null!==c?(c=c.delay,c="number"===typeof c&&0<c?e+c:e):c=e;switch(a){case 1:var d=-1;break;case 2:d=250;break;case 5:d=
1073741823;break;case 4:d=1E4;break;default:d=5E3}d=c+d;a={id:Ca++,callback:b,priorityLevel:a,startTime:c,expirationTime:d,sortIndex:-1};c>e?(a.sortIndex=c,O(r,a),null===p(q)&&a===p(r)&&(z?(ea(A),A=-1):z=!0,T(Q,c-e))):(a.sortIndex=d,O(q,a),u||F||(u=!0,R(S)));return a},unstable_cancelCallback:function(a){a.callback=null},unstable_wrapCallback:function(a){var b=k;return function(){var c=k;k=b;try{return a.apply(this,arguments)}finally{k=c}}},unstable_getCurrentPriorityLevel:function(){return k},unstable_shouldYield:fa,
unstable_requestPaint:function(){},unstable_continueExecution:function(){u||F||(u=!0,R(S))},unstable_pauseExecution:function(){},unstable_getFirstCallbackNode:function(){return p(q)},get unstable_now(){return v},unstable_forceFrameRate:function(a){0>a||125<a?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):ia=0<a?Math.floor(1E3/a):5},unstable_Profiling:null}};c.Children={map:C,forEach:function(a,b,c){C(a,function(){b.apply(this,
arguments)},c)},count:function(a){var b=0;C(a,function(){b++});return b},toArray:function(a){return C(a,function(a){return a})||[]},only:function(a){if(!M(a))throw Error("React.Children.only expected to receive a single React element child.");return a}};c.Component=w;c.Fragment=ra;c.Profiler=ta;c.PureComponent=K;c.StrictMode=sa;c.Suspense=xa;c.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=t;c.cloneElement=function(a,b,c){if(null===a||void 0===a)throw Error("React.cloneElement(...): The argument must be a React element, but you passed "+
a+".");var e=ka({},a.props),d=a.key,k=a.ref,h=a._owner;if(null!=b){void 0!==b.ref&&(k=b.ref,h=L.current);void 0!==b.key&&(d=""+b.key);if(a.type&&a.type.defaultProps)var l=a.type.defaultProps;for(f in b)aa.call(b,f)&&!ba.hasOwnProperty(f)&&(e[f]=void 0===b[f]&&void 0!==l?l[f]:b[f])}var f=arguments.length-2;if(1===f)e.children=c;else if(1<f){l=Array(f);for(var g=0;g<f;g++)l[g]=arguments[g+2];e.children=l}return{$$typeof:y,type:a.type,key:d,ref:k,props:e,_owner:h}};c.createContext=function(a){a={$$typeof:va,
_currentValue:a,_currentValue2:a,_threadCount:0,Provider:null,Consumer:null,_defaultValue:null,_globalName:null};a.Provider={$$typeof:ua,_context:a};return a.Consumer=a};c.createElement=Z;c.createFactory=function(a){var b=Z.bind(null,a);b.type=a;return b};c.createRef=function(){return{current:null}};c.forwardRef=function(a){return{$$typeof:wa,render:a}};c.isValidElement=M;c.lazy=function(a){return{$$typeof:za,_payload:{_status:-1,_result:a},_init:qa}};c.memo=function(a,b){return{$$typeof:ya,type:a,
compare:void 0===b?null:b}};c.startTransition=function(a,b){b=J.transition;J.transition={};try{a()}finally{J.transition=b}};c.unstable_act=function(a){throw Error("act(...) is not supported in production builds of React.");};c.useCallback=function(a,b){return g.current.useCallback(a,b)};c.useContext=function(a){return g.current.useContext(a)};c.useDebugValue=function(a,b){};c.useDeferredValue=function(a){return g.current.useDeferredValue(a)};c.useEffect=function(a,b){return g.current.useEffect(a,
b)};c.useId=function(){return g.current.useId()};c.useImperativeHandle=function(a,b,c){return g.current.useImperativeHandle(a,b,c)};c.useInsertionEffect=function(a,b){return g.current.useInsertionEffect(a,b)};c.useLayoutEffect=function(a,b){return g.current.useLayoutEffect(a,b)};c.useMemo=function(a,b){return g.current.useMemo(a,b)};c.useReducer=function(a,b,c){return g.current.useReducer(a,b,c)};c.useRef=function(a){return g.current.useRef(a)};c.useState=function(a){return g.current.useState(a)};
c.useSyncExternalStore=function(a,b,c){return g.current.useSyncExternalStore(a,b,c)};c.useTransition=function(){return g.current.useTransition()};c.version="18.2.0"});
})();

View File

@ -1,3 +0,0 @@
// Rather than use CDNs to include GraphiQL dependencies, import and bundle the dependencies so
// they can be locally served.
@import '../node_modules/graphiql/graphiql.css';

View File

@ -1,17 +0,0 @@
/**
* Rather than use CDNs to include GraphiQL dependencies, import and bundle the dependencies so
* they can be locally served.
*/
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import 'graphql';
import GraphiQL from 'graphiql';
import SubscriptionsTransportWs from 'subscriptions-transport-ws';
window.React = React;
window.ReactDOM = ReactDOM;
// @ts-expect-error Assigning to window is required for graphene-django
window.SubscriptionsTransportWs = SubscriptionsTransportWs;
// @ts-expect-error Assigning to window is required for graphene-django
window.GraphiQL = GraphiQL;

View File

@ -1,16 +1,17 @@
{
"name": "netbox-graphiql",
"version": "0.1.0",
"version": "0.2.0",
"description": "NetBox GraphiQL Custom Front End",
"main": "dist/graphiql.js",
"license": "Apache-2.0",
"private": true,
"dependencies": {
"graphiql": "1.8.9",
"graphql": ">= v14.5.0 <= 15.5.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"subscriptions-transport-ws": "0.9.18",
"whatwg-fetch": "3.6.2"
"graphiql": "3.0.9",
"graphql": "16.8.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-scripts": "5.0.1",
"js-cookie": "3.0.5",
"@graphiql/plugin-explorer": "1.0.2"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{% comment %}
This template derives from the graphene-django project:
https://github.com/graphql-python/graphene-django/blob/main/graphene_django/templates/graphene/graphiql.html
This template derives from the strawberry-graphql project:
https://github.com/strawberry-graphql/strawberry/blob/main/strawberry/static/graphiql.html
{% endcomment %}
<!--
The request to this GraphQL server provided the header "Accept: text/html"
@ -11,36 +11,130 @@ add "&raw" to the end of the URL within a browser.
-->
{% load static %}
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<title>GraphiQL | NetBox</title>
<link
rel="icon"
href="data:image/svg+xml,
<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22>
<!-- Strawberry Emoji as a HTML Entity (hex) -->
<text y=%22.9em%22 font-size=%2280%22>&#x1f353;</text>
</svg>"
/>
<style>
html, body, #editor {
body {
height: 100%;
margin: 0;
overflow: hidden;
width: 100%;
overflow: hidden;
}
#graphiql {
height: 100vh;
display: flex;
}
.docExplorerHide {
display: none;
}
.doc-explorer-contents {
overflow-y: hidden !important;
}
.docExplorerWrap {
width: unset !important;
min-width: unset !important;
}
.graphiql-explorer-actions select {
margin-left: 4px;
}
</style>
<link href="{% static 'graphiql.css'%}" rel="stylesheet" />
<link rel="icon" type="image/png" href="{% static 'graphql.ico' %}" />
<title>GraphiQL | NetBox</title>
<script src="{% static 'graphiql/react.production.min.js' %}"></script>
<script src="{% static 'graphiql/react-dom.production.min.js' %}"></script>
<script src="{% static 'graphiql/js.cookie.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'graphiql/graphiql.min.css' %}"/>
<link rel="stylesheet" href="{% static 'graphiql/plugin-explorer-style.css' %}"/>
</head>
<body>
<div id="editor"></div>
{% csrf_token %}
<script type="application/javascript">
window.GRAPHENE_SETTINGS = {
{% if subscription_path %}
subscriptionPath: "{{subscription_path}}",
{% endif %}
graphiqlHeaderEditorEnabled: {{ graphiql_header_editor_enabled|yesno:"true,false" }},
};
<div id="graphiql" class="graphiql-container">Loading...</div>
<script src="{% static 'graphiql/graphiql.min.js' %}"></script>
<script src="{% static 'graphiql/index.umd.js' %}"></script>
<script>
const EXAMPLE_QUERY = `# Welcome to GraphiQL 🍓
#
# GraphiQL is an in-browser tool for writing, validating, and
# testing GraphQL queries.
#
# Type queries into this side of the screen, and you will see intelligent
# typeaheads aware of the current GraphQL type schema and live syntax and
# validation errors highlighted within the text.
#
# GraphQL queries typically start with a "{" character. Lines that starts
# with a # are ignored.
#
# An example GraphQL query might look like:
#
# {
# field(arg: "value") {
# subField
# }
# }
#
# Keyboard shortcuts:
#
# Run Query: Ctrl-Enter (or press the play button above)
#
# Auto Complete: Ctrl-Space (or just start typing)
#
`;
const fetchURL = window.location.href;
function httpUrlToWebSockeUrl(url) {
const parsedURL = new URL(url);
const protocol = parsedURL.protocol === "http:" ? "ws:" : "wss:";
parsedURL.protocol = protocol;
parsedURL.hash = "";
return parsedURL.toString();
}
const headers = {};
const csrfToken = Cookies.get("csrftoken");
if (csrfToken) {
headers["x-csrftoken"] = csrfToken;
}
const subscriptionsEnabled = JSON.parse("{{ SUBSCRIPTION_ENABLED }}");
const subscriptionUrl = subscriptionsEnabled
? httpUrlToWebSockeUrl(fetchURL)
: null;
const fetcher = GraphiQL.createFetcher({
url: fetchURL,
headers: headers,
subscriptionUrl,
});
const explorerPlugin = GraphiQLPluginExplorer.explorerPlugin();
const root = ReactDOM.createRoot(document.getElementById("graphiql"));
root.render(
React.createElement(GraphiQL, {
fetcher: fetcher,
defaultEditorToolsVisibility: true,
plugins: [explorerPlugin],
inputValueDeprecation: true,
}),
);
</script>
<script
type="text/javascript"
src="{% static 'graphiql.js' %}"
onerror="window.location='{% url 'media_failure' %}?filename=graphiql.js'">
</script>
<script src="{% static 'graphene_django/graphiql.js' %}"></script>
</body>
</html>

View File

@ -127,11 +127,10 @@ class ContactAssignmentFilterSet(NetBoxModelFilterSet):
to_field_name='slug',
label=_('Contact role (slug)'),
)
tag = TagFilter()
class Meta:
model = ContactAssignment
fields = ('id', 'object_type_id', 'object_id', 'priority', 'tag')
fields = ('id', 'object_type_id', 'object_id', 'priority')
def search(self, queryset, name, value):
if not value.strip():

View File

@ -0,0 +1,49 @@
import strawberry_django
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
from tenancy import filtersets, models
__all__ = (
'TenantFilter',
'TenantGroupFilter',
'ContactFilter',
'ContactRoleFilter',
'ContactGroupFilter',
'ContactAssignmentFilter',
)
@strawberry_django.filter(models.Tenant, lookups=True)
@autotype_decorator(filtersets.TenantFilterSet)
class TenantFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.TenantGroup, lookups=True)
@autotype_decorator(filtersets.TenantGroupFilterSet)
class TenantGroupFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Contact, lookups=True)
@autotype_decorator(filtersets.ContactFilterSet)
class ContactFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ContactRole, lookups=True)
@autotype_decorator(filtersets.ContactRoleFilterSet)
class ContactRoleFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ContactGroup, lookups=True)
@autotype_decorator(filtersets.ContactGroupFilterSet)
class ContactGroupFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ContactAssignment, lookups=True)
@autotype_decorator(filtersets.ContactAssignmentFilterSet)
class ContactAssignmentFilter(BaseFilterMixin):
pass

View File

@ -0,0 +1,17 @@
from typing import Annotated, List
import strawberry
import strawberry_django
__all__ = (
'ContactAssignmentsMixin',
)
@strawberry.type
class ContactAssignmentsMixin:
@strawberry_django.field
def assignments(self) -> List[Annotated["ContactAssignmentType", strawberry.lazy('tenancy.graphql.types')]]:
return self.assignments.all()

View File

@ -1,44 +1,40 @@
import graphene
from typing import List
import strawberry
import strawberry_django
from netbox.graphql.fields import ObjectField, ObjectListField
from tenancy import models
from .types import *
from utilities.graphql_optimizer import gql_query_optimizer
class TenancyQuery(graphene.ObjectType):
tenant = ObjectField(TenantType)
tenant_list = ObjectListField(TenantType)
@strawberry.type
class TenancyQuery:
@strawberry.field
def tenant(self, id: int) -> TenantType:
return models.Tenant.objects.get(pk=id)
tenant_list: List[TenantType] = strawberry_django.field()
def resolve_tenant_list(root, info, **kwargs):
return gql_query_optimizer(models.Tenant.objects.all(), info)
@strawberry.field
def tenant_group(self, id: int) -> TenantGroupType:
return models.TenantGroup.objects.get(pk=id)
tenant_group_list: List[TenantGroupType] = strawberry_django.field()
tenant_group = ObjectField(TenantGroupType)
tenant_group_list = ObjectListField(TenantGroupType)
@strawberry.field
def contact(self, id: int) -> ContactType:
return models.Contact.objects.get(pk=id)
contact_list: List[ContactType] = strawberry_django.field()
def resolve_tenant_group_list(root, info, **kwargs):
return gql_query_optimizer(models.TenantGroup.objects.all(), info)
@strawberry.field
def contact_role(self, id: int) -> ContactRoleType:
return models.ContactRole.objects.get(pk=id)
contact_role_list: List[ContactRoleType] = strawberry_django.field()
contact = ObjectField(ContactType)
contact_list = ObjectListField(ContactType)
@strawberry.field
def contact_group(self, id: int) -> ContactGroupType:
return models.ContactGroup.objects.get(pk=id)
contact_group_list: List[ContactGroupType] = strawberry_django.field()
def resolve_contact_list(root, info, **kwargs):
return gql_query_optimizer(models.Contact.objects.all(), info)
contact_role = ObjectField(ContactRoleType)
contact_role_list = ObjectListField(ContactRoleType)
def resolve_contact_role_list(root, info, **kwargs):
return gql_query_optimizer(models.ContactRole.objects.all(), info)
contact_group = ObjectField(ContactGroupType)
contact_group_list = ObjectListField(ContactGroupType)
def resolve_contact_group_list(root, info, **kwargs):
return gql_query_optimizer(models.ContactGroup.objects.all(), info)
contact_assignment = ObjectField(ContactAssignmentType)
contact_assignment_list = ObjectListField(ContactAssignmentType)
def resolve_contact_assignment_list(root, info, **kwargs):
return gql_query_optimizer(models.ContactAssignment.objects.all(), info)
@strawberry.field
def contact_assignment(self, id: int) -> ContactAssignmentType:
return models.ContactAssignment.objects.get(pk=id)
contact_assignment_list: List[ContactAssignmentType] = strawberry_django.field()

View File

@ -1,8 +1,13 @@
import graphene
from typing import Annotated, List
import strawberry
import strawberry_django
from extras.graphql.mixins import CustomFieldsMixin, TagsMixin
from tenancy import filtersets, models
from netbox.graphql.types import BaseObjectType, OrganizationalObjectType, NetBoxObjectType
from tenancy import models
from .mixins import ContactAssignmentsMixin
from .filters import *
__all__ = (
'ContactAssignmentType',
@ -14,64 +19,169 @@ __all__ = (
)
class ContactAssignmentsMixin:
assignments = graphene.List('tenancy.graphql.types.ContactAssignmentType')
def resolve_assignments(self, info):
return self.assignments.restrict(info.context.user, 'view')
#
# Tenants
#
@strawberry_django.type(
models.Tenant,
fields='__all__',
filters=TenantFilter
)
class TenantType(NetBoxObjectType):
group: Annotated["TenantGroupType", strawberry.lazy('tenancy.graphql.types')] | None
class Meta:
model = models.Tenant
fields = '__all__'
filterset_class = filtersets.TenantFilterSet
@strawberry_django.field
def asns(self) -> List[Annotated["ASNType", strawberry.lazy('ipam.graphql.types')]]:
return self.asns.all()
@strawberry_django.field
def circuits(self) -> List[Annotated["CircuitType", strawberry.lazy('circuits.graphql.types')]]:
return self.circuits.all()
@strawberry_django.field
def sites(self) -> List[Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]]:
return self.sites.all()
@strawberry_django.field
def vlans(self) -> List[Annotated["VLANType", strawberry.lazy('ipam.graphql.types')]]:
return self.vlans.all()
@strawberry_django.field
def wireless_lans(self) -> List[Annotated["WirelessLANType", strawberry.lazy('wireless.graphql.types')]]:
return self.wireless_lans.all()
@strawberry_django.field
def route_targets(self) -> List[Annotated["RouteTargetType", strawberry.lazy('ipam.graphql.types')]]:
return self.route_targets.all()
@strawberry_django.field
def locations(self) -> List[Annotated["LocationType", strawberry.lazy('dcim.graphql.types')]]:
return self.locations.all()
@strawberry_django.field
def ip_ranges(self) -> List[Annotated["IPRangeType", strawberry.lazy('ipam.graphql.types')]]:
return self.ip_ranges.all()
@strawberry_django.field
def rackreservations(self) -> List[Annotated["RackReservationType", strawberry.lazy('dcim.graphql.types')]]:
return self.rackreservations.all()
@strawberry_django.field
def racks(self) -> List[Annotated["RackType", strawberry.lazy('dcim.graphql.types')]]:
return self.racks.all()
@strawberry_django.field
def vdcs(self) -> List[Annotated["VirtualDeviceContextType", strawberry.lazy('dcim.graphql.types')]]:
return self.vdcs.all()
@strawberry_django.field
def prefixes(self) -> List[Annotated["PrefixType", strawberry.lazy('ipam.graphql.types')]]:
return self.prefixes.all()
@strawberry_django.field
def cables(self) -> List[Annotated["CableType", strawberry.lazy('dcim.graphql.types')]]:
return self.cables.all()
@strawberry_django.field
def virtual_machines(self) -> List[Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')]]:
return self.virtual_machines.all()
@strawberry_django.field
def vrfs(self) -> List[Annotated["VRFType", strawberry.lazy('ipam.graphql.types')]]:
return self.vrfs.all()
@strawberry_django.field
def asn_ranges(self) -> List[Annotated["ASNRangeType", strawberry.lazy('ipam.graphql.types')]]:
return self.asn_ranges.all()
@strawberry_django.field
def wireless_links(self) -> List[Annotated["WirelessLinkType", strawberry.lazy('wireless.graphql.types')]]:
return self.wireless_links.all()
@strawberry_django.field
def aggregates(self) -> List[Annotated["AggregateType", strawberry.lazy('ipam.graphql.types')]]:
return self.aggregates.all()
@strawberry_django.field
def power_feeds(self) -> List[Annotated["PowerFeedType", strawberry.lazy('dcim.graphql.types')]]:
return self.power_feeds.all()
@strawberry_django.field
def devices(self) -> List[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]]:
return self.devices.all()
@strawberry_django.field
def tunnels(self) -> List[Annotated["TunnelType", strawberry.lazy('vpn.graphql.types')]]:
return self.tunnels.all()
@strawberry_django.field
def ip_addresses(self) -> List[Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')]]:
return self.ip_addresses.all()
@strawberry_django.field
def clusters(self) -> List[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]:
return self.clusters.all()
@strawberry_django.field
def l2vpns(self) -> List[Annotated["L2VPNType", strawberry.lazy('vpn.graphql.types')]]:
return self.l2vpns.all()
@strawberry_django.type(
models.TenantGroup,
fields='__all__',
filters=TenantGroupFilter
)
class TenantGroupType(OrganizationalObjectType):
parent: Annotated["TenantGroupType", strawberry.lazy('tenancy.graphql.types')] | None
class Meta:
model = models.TenantGroup
fields = '__all__'
filterset_class = filtersets.TenantGroupFilterSet
@strawberry_django.field
def tenants(self) -> List[TenantType]:
return self.tenants.all()
#
# Contacts
#
@strawberry_django.type(
models.Contact,
fields='__all__',
filters=ContactFilter
)
class ContactType(ContactAssignmentsMixin, NetBoxObjectType):
class Meta:
model = models.Contact
fields = '__all__'
filterset_class = filtersets.ContactFilterSet
group: Annotated["ContactGroupType", strawberry.lazy('tenancy.graphql.types')] | None
@strawberry_django.type(
models.ContactRole,
fields='__all__',
filters=ContactRoleFilter
)
class ContactRoleType(ContactAssignmentsMixin, OrganizationalObjectType):
class Meta:
model = models.ContactRole
fields = '__all__'
filterset_class = filtersets.ContactRoleFilterSet
pass
@strawberry_django.type(
models.ContactGroup,
fields='__all__',
filters=ContactGroupFilter
)
class ContactGroupType(OrganizationalObjectType):
parent: Annotated["ContactGroupType", strawberry.lazy('tenancy.graphql.types')] | None
class Meta:
model = models.ContactGroup
fields = '__all__'
filterset_class = filtersets.ContactGroupFilterSet
@strawberry_django.field
def contacts(self) -> List[ContactType]:
return self.contacts.all()
@strawberry_django.type(
models.ContactAssignment,
fields='__all__',
filters=ContactAssignmentFilter
)
class ContactAssignmentType(CustomFieldsMixin, TagsMixin, BaseObjectType):
class Meta:
model = models.ContactAssignment
fields = '__all__'
filterset_class = filtersets.ContactAssignmentFilterSet
object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
contact: Annotated["ContactType", strawberry.lazy('tenancy.graphql.types')] | None
role: Annotated["ContactRoleType", strawberry.lazy('tenancy.graphql.types')] | None

View File

@ -1,4 +1,5 @@
import django_filters
from django.contrib.auth import get_user_model
from django.db.models import Q
from django.utils.translation import gettext as _

View File

@ -0,0 +1,23 @@
import strawberry
import strawberry_django
from django.contrib.auth import get_user_model
from users import filtersets, models
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
__all__ = (
'GroupFilter',
'UserFilter',
)
@strawberry_django.filter(models.Group, lookups=True)
@autotype_decorator(filtersets.GroupFilterSet)
class GroupFilter(BaseFilterMixin):
pass
@strawberry_django.filter(get_user_model(), lookups=True)
@autotype_decorator(filtersets.UserFilterSet)
class UserFilter(BaseFilterMixin):
pass

View File

@ -1,21 +1,21 @@
import graphene
from django.contrib.auth import get_user_model
from typing import List
import strawberry
import strawberry_django
from netbox.graphql.fields import ObjectField, ObjectListField
from users.models import Group
from utilities.graphql_optimizer import gql_query_optimizer
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from users import models
from .types import *
class UsersQuery(graphene.ObjectType):
group = ObjectField(GroupType)
group_list = ObjectListField(GroupType)
@strawberry.type
class UsersQuery:
@strawberry.field
def group(self, id: int) -> GroupType:
return models.Group.objects.get(pk=id)
group_list: List[GroupType] = strawberry_django.field()
def resolve_group_list(root, info, **kwargs):
return gql_query_optimizer(Group.objects.all(), info)
user = ObjectField(UserType)
user_list = ObjectListField(UserType)
def resolve_user_list(root, info, **kwargs):
return gql_query_optimizer(get_user_model().objects.all(), info)
@strawberry.field
def user(self, id: int) -> UserType:
return models.User.objects.get(pk=id)
user_list: List[UserType] = strawberry_django.field()

View File

@ -1,9 +1,14 @@
from django.contrib.auth import get_user_model
from graphene_django import DjangoObjectType
from typing import List
import strawberry
import strawberry_django
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from strawberry import auto
from users import filtersets
from users.models import Group
from utilities.querysets import RestrictedQuerySet
from .filters import *
__all__ = (
'GroupType',
@ -11,28 +16,24 @@ __all__ = (
)
class GroupType(DjangoObjectType):
class Meta:
model = Group
fields = ('id', 'name')
filterset_class = filtersets.GroupFilterSet
@classmethod
def get_queryset(cls, queryset, info):
return RestrictedQuerySet(model=Group).restrict(info.context.user, 'view')
class UserType(DjangoObjectType):
class Meta:
model = get_user_model()
fields = (
'id', 'username', 'password', 'first_name', 'last_name', 'email', 'is_staff', 'is_active', 'date_joined',
'groups',
@strawberry_django.type(
Group,
fields=['id', 'name'],
filters=GroupFilter
)
filterset_class = filtersets.UserFilterSet
class GroupType:
pass
@classmethod
def get_queryset(cls, queryset, info):
return RestrictedQuerySet(model=get_user_model()).restrict(info.context.user, 'view')
@strawberry_django.type(
get_user_model(),
fields=[
'id', 'username', 'password', 'first_name', 'last_name', 'email', 'is_staff',
'is_active', 'date_joined', 'groups',
],
filters=UserFilter
)
class UserType:
@strawberry_django.field
def groups(self) -> List[GroupType]:
return self.groups.all()

View File

@ -1,252 +0,0 @@
import functools
from django.core.exceptions import FieldDoesNotExist
from django.db.models import ForeignKey
from django.db.models.constants import LOOKUP_SEP
from django.db.models.fields.reverse_related import ManyToOneRel
from graphene import InputObjectType
from graphene.types.generic import GenericScalar
from graphene.types.resolver import default_resolver
from graphene_django import DjangoObjectType
from graphql import GraphQLResolveInfo, GraphQLSchema
from graphql.execution.execute import get_field_def
from graphql.language.ast import FragmentSpreadNode, InlineFragmentNode, VariableNode
from graphql.pyutils import Path
from graphql.type.definition import GraphQLInterfaceType, GraphQLUnionType
__all__ = (
'gql_query_optimizer',
)
def gql_query_optimizer(queryset, info, **options):
return QueryOptimizer(info).optimize(queryset)
class QueryOptimizer(object):
def __init__(self, info, **options):
self.root_info = info
def optimize(self, queryset):
info = self.root_info
field_def = get_field_def(info.schema, info.parent_type, info.field_nodes[0])
field_names = self._optimize_gql_selections(
self._get_type(field_def),
info.field_nodes[0],
)
qs = queryset.prefetch_related(*field_names)
return qs
def _get_type(self, field_def):
a_type = field_def.type
while hasattr(a_type, "of_type"):
a_type = a_type.of_type
return a_type
def _get_graphql_schema(self, schema):
if isinstance(schema, GraphQLSchema):
return schema
else:
return schema.graphql_schema
def _get_possible_types(self, graphql_type):
if isinstance(graphql_type, (GraphQLInterfaceType, GraphQLUnionType)):
graphql_schema = self._get_graphql_schema(self.root_info.schema)
return graphql_schema.get_possible_types(graphql_type)
else:
return (graphql_type,)
def _get_base_model(self, graphql_types):
models = tuple(t.graphene_type._meta.model for t in graphql_types)
for model in models:
if all(issubclass(m, model) for m in models):
return model
return None
def handle_inline_fragment(self, selection, schema, possible_types, field_names):
fragment_type_name = selection.type_condition.name.value
graphql_schema = self._get_graphql_schema(schema)
fragment_type = graphql_schema.get_type(fragment_type_name)
fragment_possible_types = self._get_possible_types(fragment_type)
for fragment_possible_type in fragment_possible_types:
fragment_model = fragment_possible_type.graphene_type._meta.model
parent_model = self._get_base_model(possible_types)
if not parent_model:
continue
path_from_parent = fragment_model._meta.get_path_from_parent(parent_model)
select_related_name = LOOKUP_SEP.join(p.join_field.name for p in path_from_parent)
if not select_related_name:
continue
sub_field_names = self._optimize_gql_selections(
fragment_possible_type,
selection,
)
field_names.append(select_related_name)
return
def handle_fragment_spread(self, field_names, name, field_type):
fragment = self.root_info.fragments[name]
sub_field_names = self._optimize_gql_selections(
field_type,
fragment,
)
def _optimize_gql_selections(self, field_type, field_ast):
field_names = []
selection_set = field_ast.selection_set
if not selection_set:
return field_names
optimized_fields_by_model = {}
schema = self.root_info.schema
graphql_schema = self._get_graphql_schema(schema)
graphql_type = graphql_schema.get_type(field_type.name)
possible_types = self._get_possible_types(graphql_type)
for selection in selection_set.selections:
if isinstance(selection, InlineFragmentNode):
self.handle_inline_fragment(selection, schema, possible_types, field_names)
else:
name = selection.name.value
if isinstance(selection, FragmentSpreadNode):
self.handle_fragment_spread(field_names, name, field_type)
else:
for possible_type in possible_types:
selection_field_def = possible_type.fields.get(name)
if not selection_field_def:
continue
graphene_type = possible_type.graphene_type
model = getattr(graphene_type._meta, "model", None)
if model and name not in optimized_fields_by_model:
field_model = optimized_fields_by_model[name] = model
if field_model == model:
self._optimize_field(
field_names,
model,
selection,
selection_field_def,
possible_type,
)
return field_names
def _get_field_info(self, field_names, model, selection, field_def):
name = None
model_field = None
name = self._get_name_from_resolver(field_def.resolve)
if not name and callable(field_def.resolve) and not isinstance(field_def.resolve, functools.partial):
name = selection.name.value
if name:
model_field = self._get_model_field_from_name(model, name)
return (name, model_field)
def _optimize_field(self, field_names, model, selection, field_def, parent_type):
name, model_field = self._get_field_info(field_names, model, selection, field_def)
if model_field:
self._optimize_field_by_name(field_names, model, selection, field_def, name, model_field)
return
def _optimize_field_by_name(self, field_names, model, selection, field_def, name, model_field):
if model_field.many_to_one or model_field.one_to_one:
sub_field_names = self._optimize_gql_selections(
self._get_type(field_def),
selection,
)
if name not in field_names:
field_names.append(name)
for field in sub_field_names:
prefetch_key = f"{name}__{field}"
if prefetch_key not in field_names:
field_names.append(prefetch_key)
if model_field.one_to_many or model_field.many_to_many:
sub_field_names = self._optimize_gql_selections(
self._get_type(field_def),
selection,
)
if isinstance(model_field, ManyToOneRel):
sub_field_names.append(model_field.field.name)
field_names.append(name)
for field in sub_field_names:
prefetch_key = f"{name}__{field}"
if prefetch_key not in field_names:
field_names.append(prefetch_key)
return
def _get_optimization_hints(self, resolver):
return getattr(resolver, "optimization_hints", None)
def _get_value(self, info, value):
if isinstance(value, VariableNode):
var_name = value.name.value
value = info.variable_values.get(var_name)
return value
elif isinstance(value, InputObjectType):
return value.__dict__
else:
return GenericScalar.parse_literal(value)
def _get_name_from_resolver(self, resolver):
optimization_hints = self._get_optimization_hints(resolver)
if optimization_hints:
name_fn = optimization_hints.model_field
if name_fn:
return name_fn()
if self._is_resolver_for_id_field(resolver):
return "id"
elif isinstance(resolver, functools.partial):
resolver_fn = resolver
if resolver_fn.func != default_resolver:
# Some resolvers have the partial function as the second
# argument.
for arg in resolver_fn.args:
if isinstance(arg, (str, functools.partial)):
break
else:
# No suitable instances found, default to first arg
arg = resolver_fn.args[0]
resolver_fn = arg
if isinstance(resolver_fn, functools.partial) and resolver_fn.func == default_resolver:
return resolver_fn.args[0]
if self._is_resolver_for_id_field(resolver_fn):
return "id"
return resolver_fn
def _is_resolver_for_id_field(self, resolver):
resolve_id = DjangoObjectType.resolve_id
return resolver == resolve_id
def _get_model_field_from_name(self, model, name):
try:
return model._meta.get_field(name)
except FieldDoesNotExist:
descriptor = model.__dict__.get(name)
if not descriptor:
return None
return getattr(descriptor, "rel", None) or getattr(descriptor, "related", None) # Django < 1.9
def _is_foreign_key_id(self, model_field, name):
return isinstance(model_field, ForeignKey) and model_field.name != name and model_field.get_attname() == name
def _create_resolve_info(self, field_name, field_asts, return_type, parent_type):
return GraphQLResolveInfo(
field_name,
field_asts,
return_type,
parent_type,
Path(None, 0, None),
schema=self.root_info.schema,
fragments=self.root_info.fragments,
root_value=self.root_info.root_value,
operation=self.root_info.operation,
variable_values=self.root_info.variable_values,
context=self.root_info.context,
is_awaitable=self.root_info.is_awaitable,
)

View File

@ -1,12 +1,12 @@
import inspect
import json
import strawberry_django
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.urls import reverse
from django.test import override_settings
from graphene.types import Dynamic as GQLDynamic, List as GQLList, Union as GQLUnion, String as GQLString, NonNull as GQLNonNull
from rest_framework import status
from rest_framework.test import APIClient
@ -19,7 +19,10 @@ from .base import ModelTestCase
from .utils import disable_warnings
from ipam.graphql.types import IPAddressFamilyType
from strawberry.field import StrawberryField
from strawberry.lazy_type import LazyType
from strawberry.type import StrawberryList, StrawberryOptional
from strawberry.union import StrawberryUnion
__all__ = (
'APITestCase',
@ -447,34 +450,34 @@ class APIViewTestCases:
# Compile list of fields to include
fields_string = ''
for field_name, field in type_class._meta.fields.items():
is_string_array = False
if type(field.type) is GQLList:
if field.type.of_type is GQLString:
is_string_array = True
elif type(field.type.of_type) is GQLNonNull and field.type.of_type.of_type is GQLString:
is_string_array = True
if type(field) is GQLDynamic:
# Dynamic fields must specify a subselection
fields_string += f'{field_name} {{ id }}\n'
# TODO: Improve field detection logic to avoid nested ArrayFields
elif field_name == 'extra_choices':
file_fields = (strawberry_django.fields.types.DjangoFileType, strawberry_django.fields.types.DjangoImageType)
for field in type_class.__strawberry_definition__.fields:
if (
field.type in file_fields or (
type(field.type) is StrawberryOptional and field.type.of_type in file_fields
)
):
# image / file fields nullable or not...
fields_string += f'{field.name} {{ name }}\n'
elif type(field.type) is StrawberryList and type(field.type.of_type) is LazyType:
# List of related objects (queryset)
fields_string += f'{field.name} {{ id }}\n'
elif type(field.type) is StrawberryList and type(field.type.of_type) is StrawberryUnion:
# this would require a fragment query
continue
elif inspect.isclass(field.type) and issubclass(field.type, GQLUnion):
# Union types dont' have an id or consistent values
elif type(field.type) is StrawberryUnion:
# this would require a fragment query
continue
elif type(field.type) is GQLList and inspect.isclass(field.type.of_type) and issubclass(field.type.of_type, GQLUnion):
# Union types dont' have an id or consistent values
continue
elif type(field.type) is GQLList and not is_string_array:
# TODO: Come up with something more elegant
# Temporary hack to support automated testing of reverse generic relations
fields_string += f'{field_name} {{ id }}\n'
elif type(field.type) is StrawberryOptional and type(field.type.of_type) is LazyType:
fields_string += f'{field.name} {{ id }}\n'
elif hasattr(field, 'is_relation') and field.is_relation:
# Note: StrawberryField types do not have is_relation
fields_string += f'{field.name} {{ id }}\n'
elif inspect.isclass(field.type) and issubclass(field.type, IPAddressFamilyType):
fields_string += f'{field_name} {{ value, label }}\n'
fields_string += f'{field.name} {{ value, label }}\n'
else:
fields_string += f'{field_name}\n'
fields_string += f'{field.name}\n'
query = f"""
{{
@ -496,7 +499,10 @@ class APIViewTestCases:
# Non-authenticated requests should fail
with disable_warnings('django.request'):
self.assertHttpStatus(self.client.post(url, data={'query': query}), status.HTTP_403_FORBIDDEN)
header = {
'HTTP_ACCEPT': 'application/json',
}
self.assertHttpStatus(self.client.post(url, data={'query': query}, format="json", **header), status.HTTP_403_FORBIDDEN)
# Add object-level permission
obj_perm = ObjectPermission(
@ -507,7 +513,7 @@ class APIViewTestCases:
obj_perm.users.add(self.user)
obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model))
response = self.client.post(url, data={'query': query}, **self.header)
response = self.client.post(url, data={'query': query}, format="json", **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
data = json.loads(response.content)
self.assertNotIn('errors', data)
@ -521,7 +527,10 @@ class APIViewTestCases:
# Non-authenticated requests should fail
with disable_warnings('django.request'):
self.assertHttpStatus(self.client.post(url, data={'query': query}), status.HTTP_403_FORBIDDEN)
header = {
'HTTP_ACCEPT': 'application/json',
}
self.assertHttpStatus(self.client.post(url, data={'query': query}, format="json", **header), status.HTTP_403_FORBIDDEN)
# Add object-level permission
obj_perm = ObjectPermission(
@ -532,7 +541,7 @@ class APIViewTestCases:
obj_perm.users.add(self.user)
obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model))
response = self.client.post(url, data={'query': query}, **self.header)
response = self.client.post(url, data={'query': query}, format="json", **self.header)
self.assertHttpStatus(response, status.HTTP_200_OK)
data = json.loads(response.content)
self.assertNotIn('errors', data)

View File

@ -0,0 +1,49 @@
import strawberry_django
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
from virtualization import filtersets, models
__all__ = (
'ClusterFilter',
'ClusterGroupFilter',
'ClusterTypeFilter',
'VirtualMachineFilter',
'VMInterfaceFilter',
'VirtualDiskFilter',
)
@strawberry_django.filter(models.Cluster, lookups=True)
@autotype_decorator(filtersets.ClusterFilterSet)
class ClusterFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ClusterGroup, lookups=True)
@autotype_decorator(filtersets.ClusterGroupFilterSet)
class ClusterGroupFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.ClusterType, lookups=True)
@autotype_decorator(filtersets.ClusterTypeFilterSet)
class ClusterTypeFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.VirtualMachine, lookups=True)
@autotype_decorator(filtersets.VirtualMachineFilterSet)
class VirtualMachineFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.VMInterface, lookups=True)
@autotype_decorator(filtersets.VMInterfaceFilterSet)
class VMInterfaceFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.VirtualDisk, lookups=True)
@autotype_decorator(filtersets.VirtualDiskFilterSet)
class VirtualDiskFilter(BaseFilterMixin):
pass

View File

@ -1,44 +1,40 @@
import graphene
from typing import List
import strawberry
import strawberry_django
from netbox.graphql.fields import ObjectField, ObjectListField
from .types import *
from utilities.graphql_optimizer import gql_query_optimizer
from virtualization import models
from .types import *
class VirtualizationQuery(graphene.ObjectType):
cluster = ObjectField(ClusterType)
cluster_list = ObjectListField(ClusterType)
@strawberry.type
class VirtualizationQuery:
@strawberry.field
def cluster(self, id: int) -> ClusterType:
return models.Cluster.objects.get(pk=id)
cluster_list: List[ClusterType] = strawberry_django.field()
def resolve_cluster_list(root, info, **kwargs):
return gql_query_optimizer(models.Cluster.objects.all(), info)
@strawberry.field
def cluster_group(self, id: int) -> ClusterGroupType:
return models.ClusterGroup.objects.get(pk=id)
cluster_group_list: List[ClusterGroupType] = strawberry_django.field()
cluster_group = ObjectField(ClusterGroupType)
cluster_group_list = ObjectListField(ClusterGroupType)
@strawberry.field
def cluster_type(self, id: int) -> ClusterTypeType:
return models.ClusterType.objects.get(pk=id)
cluster_type_list: List[ClusterTypeType] = strawberry_django.field()
def resolve_cluster_group_list(root, info, **kwargs):
return gql_query_optimizer(models.ClusterGroup.objects.all(), info)
@strawberry.field
def virtual_machine(self, id: int) -> VirtualMachineType:
return models.VirtualMachine.objects.get(pk=id)
virtual_machine_list: List[VirtualMachineType] = strawberry_django.field()
cluster_type = ObjectField(ClusterTypeType)
cluster_type_list = ObjectListField(ClusterTypeType)
@strawberry.field
def vm_interface(self, id: int) -> VMInterfaceType:
return models.VMInterface.objects.get(pk=id)
vm_interface_list: List[VMInterfaceType] = strawberry_django.field()
def resolve_cluster_type_list(root, info, **kwargs):
return gql_query_optimizer(models.ClusterType.objects.all(), info)
virtual_machine = ObjectField(VirtualMachineType)
virtual_machine_list = ObjectListField(VirtualMachineType)
def resolve_virtual_machine_list(root, info, **kwargs):
return gql_query_optimizer(models.VirtualMachine.objects.all(), info)
vm_interface = ObjectField(VMInterfaceType)
vm_interface_list = ObjectListField(VMInterfaceType)
def resolve_vm_interface_list(root, info, **kwargs):
return gql_query_optimizer(models.VMInterface.objects.all(), info)
virtual_disk = ObjectField(VirtualDiskType)
virtual_disk_list = ObjectListField(VirtualDiskType)
def resolve_virtual_disk_list(root, info, **kwargs):
return gql_query_optimizer(models.VirtualDisk.objects.all(), info)
@strawberry.field
def virtual_disk(self, id: int) -> VirtualDiskType:
return models.VirtualDisk.objects.get(pk=id)
virtual_disk_list: List[VirtualDiskType] = strawberry_django.field()

View File

@ -1,8 +1,14 @@
from dcim.graphql.types import ComponentObjectType
from typing import Annotated, List
import strawberry
import strawberry_django
from extras.graphql.mixins import ConfigContextMixin, ContactsMixin
from ipam.graphql.mixins import IPAddressesMixin, VLANGroupsMixin
from netbox.graphql.scalars import BigInt
from netbox.graphql.types import OrganizationalObjectType, NetBoxObjectType
from virtualization import filtersets, models
from virtualization import models
from .filters import *
__all__ = (
'ClusterType',
@ -14,55 +20,121 @@ __all__ = (
)
@strawberry.type
class ComponentType(NetBoxObjectType):
"""
Base type for device/VM components
"""
_name: str
virtual_machine: Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')]
@strawberry_django.type(
models.Cluster,
fields='__all__',
filters=ClusterFilter
)
class ClusterType(VLANGroupsMixin, NetBoxObjectType):
type: Annotated["ClusterTypeType", strawberry.lazy('virtualization.graphql.types')] | None
group: Annotated["ClusterGroupType", strawberry.lazy('virtualization.graphql.types')] | None
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')] | None
class Meta:
model = models.Cluster
fields = '__all__'
filterset_class = filtersets.ClusterFilterSet
@strawberry_django.field
def virtual_machines(self) -> List[Annotated["VirtualMachineType", strawberry.lazy('virtualization.graphql.types')]]:
return self.virtual_machines.all()
@strawberry_django.field
def devices(self) -> List[Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]]:
return self.devices.all()
@strawberry_django.type(
models.ClusterGroup,
fields='__all__',
filters=ClusterGroupFilter
)
class ClusterGroupType(VLANGroupsMixin, OrganizationalObjectType):
class Meta:
model = models.ClusterGroup
fields = '__all__'
filterset_class = filtersets.ClusterGroupFilterSet
@strawberry_django.field
def clusters(self) -> List[Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')]]:
return self.clusters.all()
@strawberry_django.type(
models.ClusterType,
fields='__all__',
filters=ClusterTypeFilter
)
class ClusterTypeType(OrganizationalObjectType):
class Meta:
model = models.ClusterType
fields = '__all__'
filterset_class = filtersets.ClusterTypeFilterSet
@strawberry_django.field
def clusters(self) -> List[ClusterType]:
return self.clusters.all()
@strawberry_django.type(
models.VirtualMachine,
fields='__all__',
filters=VirtualMachineFilter
)
class VirtualMachineType(ConfigContextMixin, ContactsMixin, NetBoxObjectType):
_name: str
interface_count: BigInt
virtual_disk_count: BigInt
interface_count: BigInt
config_template: Annotated["ConfigTemplateType", strawberry.lazy('extras.graphql.types')] | None
site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')] | None
cluster: Annotated["ClusterType", strawberry.lazy('virtualization.graphql.types')] | None
device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')] | None
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
platform: Annotated["PlatformType", strawberry.lazy('dcim.graphql.types')] | None
role: Annotated["DeviceRoleType", strawberry.lazy('dcim.graphql.types')] | None
primary_ip4: Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')] | None
primary_ip6: Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')] | None
class Meta:
model = models.VirtualMachine
fields = '__all__'
filterset_class = filtersets.VirtualMachineFilterSet
@strawberry_django.field
def interfaces(self) -> List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]]:
return self.interfaces.all()
@strawberry_django.field
def services(self) -> List[Annotated["ServiceType", strawberry.lazy('ipam.graphql.types')]]:
return self.services.all()
@strawberry_django.field
def virtualdisks(self) -> List[Annotated["VirtualDiskType", strawberry.lazy('virtualization.graphql.types')]]:
return self.virtualdisks.all()
class VMInterfaceType(IPAddressesMixin, ComponentObjectType):
@strawberry_django.type(
models.VMInterface,
fields='__all__',
filters=VMInterfaceFilter
)
class VMInterfaceType(IPAddressesMixin, ComponentType):
mac_address: str | None
parent: Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')] | None
bridge: Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')] | None
untagged_vlan: Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None
vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None
class Meta:
model = models.VMInterface
fields = '__all__'
filterset_class = filtersets.VMInterfaceFilterSet
@strawberry_django.field
def tagged_vlans(self) -> List[Annotated["VLANType", strawberry.lazy('ipam.graphql.types')]]:
return self.tagged_vlans.all()
def resolve_mode(self, info):
return self.mode or None
@strawberry_django.field
def bridge_interfaces(self) -> List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]]:
return self.bridge_interfaces.all()
@strawberry_django.field
def child_interfaces(self) -> List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]]:
return self.child_interfaces.all()
class VirtualDiskType(ComponentObjectType):
class Meta:
model = models.VirtualDisk
fields = '__all__'
filterset_class = filtersets.VirtualDiskFilterSet
def resolve_mode(self, info):
return self.mode or None
@strawberry_django.type(
models.VirtualDisk,
fields='__all__',
filters=VirtualDiskFilter
)
class VirtualDiskType(ComponentType):
pass

View File

@ -0,0 +1,77 @@
import strawberry_django
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
from vpn import filtersets, models
__all__ = (
'TunnelGroupFilter',
'TunnelTerminationFilter',
'TunnelFilter',
'IKEProposalFilter',
'IKEPolicyFilter',
'IPSecProposalFilter',
'IPSecPolicyFilter',
'IPSecProfileFilter',
'L2VPNFilter',
'L2VPNTerminationFilter',
)
@strawberry_django.filter(models.TunnelGroup, lookups=True)
@autotype_decorator(filtersets.TunnelGroupFilterSet)
class TunnelGroupFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.TunnelTermination, lookups=True)
@autotype_decorator(filtersets.TunnelTerminationFilterSet)
class TunnelTerminationFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.Tunnel, lookups=True)
@autotype_decorator(filtersets.TunnelFilterSet)
class TunnelFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.IKEProposal, lookups=True)
@autotype_decorator(filtersets.IKEProposalFilterSet)
class IKEProposalFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.IKEPolicy, lookups=True)
@autotype_decorator(filtersets.IKEPolicyFilterSet)
class IKEPolicyFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.IPSecProposal, lookups=True)
@autotype_decorator(filtersets.IPSecProposalFilterSet)
class IPSecProposalFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.IPSecPolicy, lookups=True)
@autotype_decorator(filtersets.IPSecPolicyFilterSet)
class IPSecPolicyFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.IPSecProfile, lookups=True)
@autotype_decorator(filtersets.IPSecProfileFilterSet)
class IPSecProfileFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.L2VPN, lookups=True)
@autotype_decorator(filtersets.L2VPNFilterSet)
class L2VPNFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.L2VPNTermination, lookups=True)
@autotype_decorator(filtersets.L2VPNTerminationFilterSet)
class L2VPNTerminationFilter(BaseFilterMixin):
pass

View File

@ -1,30 +0,0 @@
import graphene
from dcim.graphql.types import InterfaceType
from dcim.models import Interface
from ipam.graphql.types import VLANType
from ipam.models import VLAN
from virtualization.graphql.types import VMInterfaceType
from virtualization.models import VMInterface
__all__ = (
'L2VPNAssignmentType',
)
class L2VPNAssignmentType(graphene.Union):
class Meta:
types = (
InterfaceType,
VLANType,
VMInterfaceType,
)
@classmethod
def resolve_type(cls, instance, info):
if type(instance) is Interface:
return InterfaceType
if type(instance) is VLAN:
return VLANType
if type(instance) is VMInterface:
return VMInterfaceType

View File

@ -1,69 +1,60 @@
import graphene
from typing import List
import strawberry
import strawberry_django
from netbox.graphql.fields import ObjectField, ObjectListField
from utilities.graphql_optimizer import gql_query_optimizer
from vpn import models
from .types import *
class VPNQuery(graphene.ObjectType):
@strawberry.type
class VPNQuery:
@strawberry.field
def ike_policy(self, id: int) -> IKEPolicyType:
return models.IKEPolicy.objects.get(pk=id)
ike_policy_list: List[IKEPolicyType] = strawberry_django.field()
ike_policy = ObjectField(IKEPolicyType)
ike_policy_list = ObjectListField(IKEPolicyType)
@strawberry.field
def ike_proposal(self, id: int) -> IKEProposalType:
return models.IKEProposal.objects.get(pk=id)
ike_proposal_list: List[IKEProposalType] = strawberry_django.field()
def resolve_ike_policy_list(root, info, **kwargs):
return gql_query_optimizer(models.IKEPolicy.objects.all(), info)
@strawberry.field
def ipsec_policy(self, id: int) -> IPSecPolicyType:
return models.IPSecPolicy.objects.get(pk=id)
ipsec_policy_list: List[IPSecPolicyType] = strawberry_django.field()
ike_proposal = ObjectField(IKEProposalType)
ike_proposal_list = ObjectListField(IKEProposalType)
@strawberry.field
def ipsec_profile(self, id: int) -> IPSecProfileType:
return models.IPSecProfile.objects.get(pk=id)
ipsec_profile_list: List[IPSecProfileType] = strawberry_django.field()
def resolve_ike_proposal_list(root, info, **kwargs):
return gql_query_optimizer(models.IKEProposal.objects.all(), info)
@strawberry.field
def ipsec_proposal(self, id: int) -> IPSecProposalType:
return models.IPSecProposal.objects.get(pk=id)
ipsec_proposal_list: List[IPSecProposalType] = strawberry_django.field()
ipsec_policy = ObjectField(IPSecPolicyType)
ipsec_policy_list = ObjectListField(IPSecPolicyType)
@strawberry.field
def l2vpn(self, id: int) -> L2VPNType:
return models.L2VPN.objects.get(pk=id)
l2vpn_list: List[L2VPNType] = strawberry_django.field()
def resolve_ipsec_policy_list(root, info, **kwargs):
return gql_query_optimizer(models.IPSecPolicy.objects.all(), info)
@strawberry.field
def l2vpn_termination(self, id: int) -> L2VPNTerminationType:
return models.L2VPNTermination.objects.get(pk=id)
l2vpn_termination_list: List[L2VPNTerminationType] = strawberry_django.field()
ipsec_profile = ObjectField(IPSecProfileType)
ipsec_profile_list = ObjectListField(IPSecProfileType)
@strawberry.field
def tunnel(self, id: int) -> TunnelType:
return models.Tunnel.objects.get(pk=id)
tunnel_list: List[TunnelType] = strawberry_django.field()
def resolve_ipsec_profile_list(root, info, **kwargs):
return gql_query_optimizer(models.IPSecProfile.objects.all(), info)
@strawberry.field
def tunnel_group(self, id: int) -> TunnelGroupType:
return models.TunnelGroup.objects.get(pk=id)
tunnel_group_list: List[TunnelGroupType] = strawberry_django.field()
ipsec_proposal = ObjectField(IPSecProposalType)
ipsec_proposal_list = ObjectListField(IPSecProposalType)
def resolve_ipsec_proposal_list(root, info, **kwargs):
return gql_query_optimizer(models.IPSecProposal.objects.all(), info)
l2vpn = ObjectField(L2VPNType)
l2vpn_list = ObjectListField(L2VPNType)
def resolve_l2vpn_list(root, info, **kwargs):
return gql_query_optimizer(models.L2VPN.objects.all(), info)
l2vpn_termination = ObjectField(L2VPNTerminationType)
l2vpn_termination_list = ObjectListField(L2VPNTerminationType)
def resolve_l2vpn_termination_list(root, info, **kwargs):
return gql_query_optimizer(models.L2VPNTermination.objects.all(), info)
tunnel = ObjectField(TunnelType)
tunnel_list = ObjectListField(TunnelType)
def resolve_tunnel_list(root, info, **kwargs):
return gql_query_optimizer(models.Tunnel.objects.all(), info)
tunnel_group = ObjectField(TunnelGroupType)
tunnel_group_list = ObjectListField(TunnelGroupType)
def resolve_tunnel_group_list(root, info, **kwargs):
return gql_query_optimizer(models.TunnelGroup.objects.all(), info)
tunnel_termination = ObjectField(TunnelTerminationType)
tunnel_termination_list = ObjectListField(TunnelTerminationType)
def resolve_tunnel_termination_list(root, info, **kwargs):
return gql_query_optimizer(models.TunnelTermination.objects.all(), info)
@strawberry.field
def tunnel_termination(self, id: int) -> TunnelTerminationType:
return models.TunnelTermination.objects.get(pk=id)
tunnel_termination_list: List[TunnelTerminationType] = strawberry_django.field()

View File

@ -1,8 +1,12 @@
import graphene
from typing import Annotated, List, Union
import strawberry
import strawberry_django
from extras.graphql.mixins import ContactsMixin, CustomFieldsMixin, TagsMixin
from netbox.graphql.types import ObjectType, OrganizationalObjectType, NetBoxObjectType
from vpn import filtersets, models
from vpn import models
from .filters import *
__all__ = (
'IKEPolicyType',
@ -18,81 +22,147 @@ __all__ = (
)
@strawberry_django.type(
models.TunnelGroup,
fields='__all__',
filters=TunnelGroupFilter
)
class TunnelGroupType(OrganizationalObjectType):
class Meta:
model = models.TunnelGroup
fields = '__all__'
filterset_class = filtersets.TunnelGroupFilterSet
@strawberry_django.field
def tunnels(self) -> List[Annotated["TunnelType", strawberry.lazy('vpn.graphql.types')]]:
return self.tunnels.all()
@strawberry_django.type(
models.TunnelTermination,
fields='__all__',
filters=TunnelTerminationFilter
)
class TunnelTerminationType(CustomFieldsMixin, TagsMixin, ObjectType):
class Meta:
model = models.TunnelTermination
fields = '__all__'
filterset_class = filtersets.TunnelTerminationFilterSet
tunnel: Annotated["TunnelType", strawberry.lazy('vpn.graphql.types')]
termination_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
outside_ip: Annotated["IPAddressType", strawberry.lazy('ipam.graphql.types')] | None
@strawberry_django.type(
models.Tunnel,
fields='__all__',
filters=TunnelFilter
)
class TunnelType(NetBoxObjectType):
group: Annotated["TunnelGroupType", strawberry.lazy('vpn.graphql.types')] | None
ipsec_profile: Annotated["IPSecProfileType", strawberry.lazy('vpn.graphql.types')] | None
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
class Meta:
model = models.Tunnel
fields = '__all__'
filterset_class = filtersets.TunnelFilterSet
@strawberry_django.field
def terminations(self) -> List[Annotated["TunnelTerminationType", strawberry.lazy('vpn.graphql.types')]]:
return self.terminations.all()
@strawberry_django.type(
models.IKEProposal,
fields='__all__',
filters=IKEProposalFilter
)
class IKEProposalType(OrganizationalObjectType):
class Meta:
model = models.IKEProposal
fields = '__all__'
filterset_class = filtersets.IKEProposalFilterSet
@strawberry_django.field
def ike_policies(self) -> List[Annotated["IKEPolicyType", strawberry.lazy('vpn.graphql.types')]]:
return self.ike_policies.all()
@strawberry_django.type(
models.IKEPolicy,
fields='__all__',
filters=IKEPolicyFilter
)
class IKEPolicyType(OrganizationalObjectType):
class Meta:
model = models.IKEPolicy
fields = '__all__'
filterset_class = filtersets.IKEPolicyFilterSet
@strawberry_django.field
def proposals(self) -> List[Annotated["IKEProposalType", strawberry.lazy('vpn.graphql.types')]]:
return self.proposals.all()
@strawberry_django.field
def ipsec_profiles(self) -> List[Annotated["IPSecProposalType", strawberry.lazy('vpn.graphql.types')]]:
return self.ipsec_profiles.all()
@strawberry_django.type(
models.IPSecProposal,
fields='__all__',
filters=IPSecProposalFilter
)
class IPSecProposalType(OrganizationalObjectType):
class Meta:
model = models.IPSecProposal
fields = '__all__'
filterset_class = filtersets.IPSecProposalFilterSet
@strawberry_django.field
def ipsec_policies(self) -> List[Annotated["IPSecPolicyType", strawberry.lazy('vpn.graphql.types')]]:
return self.ipsec_policies.all()
@strawberry_django.type(
models.IPSecPolicy,
fields='__all__',
filters=IPSecPolicyFilter
)
class IPSecPolicyType(OrganizationalObjectType):
class Meta:
model = models.IPSecPolicy
fields = '__all__'
filterset_class = filtersets.IPSecPolicyFilterSet
@strawberry_django.field
def proposals(self) -> List[Annotated["IPSecProposalType", strawberry.lazy('vpn.graphql.types')]]:
return self.proposals.all()
@strawberry_django.field
def ipsec_profiles(self) -> List[Annotated["IPSecProfileType", strawberry.lazy('vpn.graphql.types')]]:
return self.ipsec_profiles.all()
@strawberry_django.type(
models.IPSecProfile,
fields='__all__',
filters=IPSecProfileFilter
)
class IPSecProfileType(OrganizationalObjectType):
ike_policy: Annotated["IKEPolicyType", strawberry.lazy('vpn.graphql.types')]
ipsec_policy: Annotated["IPSecPolicyType", strawberry.lazy('vpn.graphql.types')]
class Meta:
model = models.IPSecProfile
fields = '__all__'
filterset_class = filtersets.IPSecProfileFilterSet
@strawberry_django.field
def tunnels(self) -> List[Annotated["TunnelType", strawberry.lazy('vpn.graphql.types')]]:
return self.tunnels.all()
@strawberry_django.type(
models.L2VPN,
fields='__all__',
filters=L2VPNFilter
)
class L2VPNType(ContactsMixin, NetBoxObjectType):
class Meta:
model = models.L2VPN
fields = '__all__'
filtersets_class = filtersets.L2VPNFilterSet
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
@strawberry_django.field
def export_targets(self) -> List[Annotated["RouteTargetType", strawberry.lazy('ipam.graphql.types')]]:
return self.export_targets.all()
@strawberry_django.field
def terminations(self) -> List[Annotated["L2VPNTerminationType", strawberry.lazy('vpn.graphql.types')]]:
return self.terminations.all()
@strawberry_django.field
def import_targets(self) -> List[Annotated["RouteTargetType", strawberry.lazy('ipam.graphql.types')]]:
return self.import_targets.all()
@strawberry_django.type(
models.L2VPNTermination,
exclude=('assigned_object_type', 'assigned_object_id'),
filters=L2VPNTerminationFilter
)
class L2VPNTerminationType(NetBoxObjectType):
assigned_object = graphene.Field('vpn.graphql.gfk_mixins.L2VPNAssignmentType')
l2vpn: Annotated["L2VPNType", strawberry.lazy('vpn.graphql.types')]
class Meta:
model = models.L2VPNTermination
exclude = ('assigned_object_type', 'assigned_object_id')
filtersets_class = filtersets.L2VPNTerminationFilterSet
@strawberry_django.field
def assigned_object(self) -> Annotated[Union[
Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')],
Annotated["VLANType", strawberry.lazy('ipam.graphql.types')],
Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')],
], strawberry.union("L2VPNAssignmentType")]:
return self.assigned_object

View File

@ -0,0 +1,28 @@
import strawberry_django
from netbox.graphql.filter_mixins import autotype_decorator, BaseFilterMixin
from wireless import filtersets, models
__all__ = (
'WirelessLANGroupFilter',
'WirelessLANFilter',
'WirelessLinkFilter',
)
@strawberry_django.filter(models.WirelessLANGroup, lookups=True)
@autotype_decorator(filtersets.WirelessLANGroupFilterSet)
class WirelessLANGroupFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.WirelessLAN, lookups=True)
@autotype_decorator(filtersets.WirelessLANFilterSet)
class WirelessLANFilter(BaseFilterMixin):
pass
@strawberry_django.filter(models.WirelessLink, lookups=True)
@autotype_decorator(filtersets.WirelessLinkFilterSet)
class WirelessLinkFilter(BaseFilterMixin):
pass

View File

@ -1,26 +1,25 @@
import graphene
from typing import List
import strawberry
import strawberry_django
from netbox.graphql.fields import ObjectField, ObjectListField
from .types import *
from utilities.graphql_optimizer import gql_query_optimizer
from wireless import models
from .types import *
class WirelessQuery(graphene.ObjectType):
wireless_lan = ObjectField(WirelessLANType)
wireless_lan_list = ObjectListField(WirelessLANType)
@strawberry.type
class WirelessQuery:
@strawberry.field
def wireless_lan(self, id: int) -> WirelessLANType:
return models.WirelessLAN.objects.get(pk=id)
wireless_lan_list: List[WirelessLANType] = strawberry_django.field()
def resolve_wireless_lan_list(root, info, **kwargs):
return gql_query_optimizer(models.WirelessLAN.objects.all(), info)
@strawberry.field
def wireless_lan_group(self, id: int) -> WirelessLANGroupType:
return models.WirelessLANGroup.objects.get(pk=id)
wireless_lan_group_list: List[WirelessLANGroupType] = strawberry_django.field()
wireless_lan_group = ObjectField(WirelessLANGroupType)
wireless_lan_group_list = ObjectListField(WirelessLANGroupType)
def resolve_wireless_lan_group_list(root, info, **kwargs):
return gql_query_optimizer(models.WirelessLANGroup.objects.all(), info)
wireless_link = ObjectField(WirelessLinkType)
wireless_link_list = ObjectListField(WirelessLinkType)
def resolve_wireless_link_list(root, info, **kwargs):
return gql_query_optimizer(models.WirelessLink.objects.all(), info)
@strawberry.field
def wireless_link(self, id: int) -> WirelessLinkType:
return models.WirelessLink.objects.get(pk=id)
wireless_link_list: List[WirelessLinkType] = strawberry_django.field()

View File

@ -1,5 +1,11 @@
from wireless import filtersets, models
from typing import Annotated, List
import strawberry
import strawberry_django
from netbox.graphql.types import OrganizationalObjectType, NetBoxObjectType
from wireless import models
from .filters import *
__all__ = (
'WirelessLANType',
@ -8,37 +14,42 @@ __all__ = (
)
@strawberry_django.type(
models.WirelessLANGroup,
fields='__all__',
filters=WirelessLANGroupFilter
)
class WirelessLANGroupType(OrganizationalObjectType):
parent: Annotated["WirelessLANGroupType", strawberry.lazy('wireless.graphql.types')] | None
class Meta:
model = models.WirelessLANGroup
fields = '__all__'
filterset_class = filtersets.WirelessLANGroupFilterSet
@strawberry_django.field
def wireless_lans(self) -> List[Annotated["WirelessLANType", strawberry.lazy('wireless.graphql.types')]]:
return self.wireless_lans.all()
@strawberry_django.type(
models.WirelessLAN,
fields='__all__',
filters=WirelessLANFilter
)
class WirelessLANType(NetBoxObjectType):
group: Annotated["WirelessLANGroupType", strawberry.lazy('wireless.graphql.types')] | None
vlan: Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
class Meta:
model = models.WirelessLAN
fields = '__all__'
filterset_class = filtersets.WirelessLANFilterSet
def resolve_auth_type(self, info):
return self.auth_type or None
def resolve_auth_cipher(self, info):
return self.auth_cipher or None
@strawberry_django.field
def interfaces(self) -> List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]]:
return self.interfaces.all()
@strawberry_django.type(
models.WirelessLink,
fields='__all__',
filters=WirelessLinkFilter
)
class WirelessLinkType(NetBoxObjectType):
class Meta:
model = models.WirelessLink
fields = '__all__'
filterset_class = filtersets.WirelessLinkFilterSet
def resolve_auth_type(self, info):
return self.auth_type or None
def resolve_auth_cipher(self, info):
return self.auth_cipher or None
interface_a: Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]
interface_b: Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]
tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
_interface_a_device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')] | None
_interface_b_device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')] | None

View File

@ -2,7 +2,6 @@ Django==5.0.3
django-cors-headers==4.3.1
django-debug-toolbar==4.3.0
django-filter==24.1
django-graphiql-debug-toolbar==0.2.0
django-htmx==1.17.3
django-mptt==0.14.0
django-pglocks==1.0.4
@ -17,7 +16,6 @@ djangorestframework==3.14.0
drf-spectacular==0.27.1
drf-spectacular-sidecar==2024.3.4
feedparser==6.0.11
graphene-django==3.0.0
gunicorn==21.2.0
Jinja2==3.1.3
Markdown==3.5.2
@ -31,6 +29,8 @@ PyYAML==6.0.1
requests==2.31.0
social-auth-app-django==5.4.0
social-auth-core[openidconnect]==4.5.3
strawberry-graphql==0.221.1
strawberry-graphql-django==0.35.1
svgwrite==1.4.3
tablib==3.5.0
tzdata==2024.1