plotly-cloud 0.1.0rc1__tar.gz → 0.1.0rc3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/.gitignore +5 -1
- plotly_cloud-0.1.0rc1/README.md → plotly_cloud-0.1.0rc3/PKG-INFO +17 -27
- plotly_cloud-0.1.0rc1/PKG-INFO → plotly_cloud-0.1.0rc3/README.md +2 -42
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/plotly_cloud/_commands.py +8 -8
- plotly_cloud-0.1.0rc3/plotly_cloud/_devtool_hooks.py +61 -0
- plotly_cloud-0.1.0rc3/plotly_cloud/_devtool_publish_rpc.py +207 -0
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/plotly_cloud/_oauth.py +75 -23
- plotly_cloud-0.1.0rc3/plotly_cloud/cloud_devtools.css +1 -0
- plotly_cloud-0.1.0rc3/plotly_cloud/cloud_devtools.js +15 -0
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/pyproject.toml +6 -2
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/LICENSE +0 -0
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/plotly_cloud/__init__.py +0 -0
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/plotly_cloud/_api_types.py +0 -0
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/plotly_cloud/_changes.py +0 -0
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/plotly_cloud/_cloud_env.py +0 -0
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/plotly_cloud/_definitions.py +0 -0
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/plotly_cloud/_deploy.py +0 -0
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/plotly_cloud/_parser.py +0 -0
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/plotly_cloud/cli.py +0 -0
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/plotly_cloud/cloud-env.toml +0 -0
- {plotly_cloud-0.1.0rc1 → plotly_cloud-0.1.0rc3}/plotly_cloud/exceptions.py +0 -0
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: plotly-cloud
|
|
3
|
+
Version: 0.1.0rc3
|
|
4
|
+
Summary: CLI for interacting with Plotly Cloud to deploy Dash apps
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Requires-Python: >=3.9
|
|
7
|
+
Requires-Dist: dash>=2.0.0
|
|
8
|
+
Requires-Dist: httpx<1.0.0,>=0.24.0
|
|
9
|
+
Requires-Dist: nest-asyncio>=1.6.0
|
|
10
|
+
Requires-Dist: rich-argparse>=1.7.1
|
|
11
|
+
Requires-Dist: rich>=10.0.0
|
|
12
|
+
Requires-Dist: tomli-w>=1.2.0
|
|
13
|
+
Requires-Dist: tomli>=2.2.1
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
1
16
|
# Plotly Cloud CLI
|
|
2
17
|
|
|
3
18
|
A command-line interface for interacting with Plotly Cloud to publish and manage Dash applications.
|
|
@@ -11,33 +26,8 @@ A command-line interface for interacting with Plotly Cloud to publish and manage
|
|
|
11
26
|
|
|
12
27
|
## Installation
|
|
13
28
|
|
|
14
|
-
### From Source
|
|
15
|
-
|
|
16
29
|
```bash
|
|
17
|
-
|
|
18
|
-
cd plotly-cloud-cli
|
|
19
|
-
pip install -e .
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### Development Installation
|
|
23
|
-
|
|
24
|
-
For development, we recommend using UV and the provided Justfile:
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
git clone <repository-url>
|
|
28
|
-
cd plotly-cloud-cli
|
|
29
|
-
|
|
30
|
-
# Install UV if you haven't already
|
|
31
|
-
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
32
|
-
|
|
33
|
-
# Install dependencies
|
|
34
|
-
just install
|
|
35
|
-
|
|
36
|
-
# Setup cloud environment configuration
|
|
37
|
-
just setup-cloud-env "your-staging-client-id" "your-production-client-id"
|
|
38
|
-
|
|
39
|
-
# Install CLI in development mode
|
|
40
|
-
just install-cli
|
|
30
|
+
pip install plotly-cloud
|
|
41
31
|
```
|
|
42
32
|
|
|
43
33
|
## Quick Start
|
|
@@ -298,7 +288,7 @@ plotly-cloud-cli/
|
|
|
298
288
|
|
|
299
289
|
## License
|
|
300
290
|
|
|
301
|
-
|
|
291
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
302
292
|
|
|
303
293
|
## Support
|
|
304
294
|
|
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: plotly-cloud
|
|
3
|
-
Version: 0.1.0rc1
|
|
4
|
-
Summary: CLI for interacting with Plotly Cloud to deploy Dash apps
|
|
5
|
-
License-File: LICENSE
|
|
6
|
-
Requires-Python: >=3.9
|
|
7
|
-
Requires-Dist: dash>=2.0.0
|
|
8
|
-
Requires-Dist: httpx>=0.24.0
|
|
9
|
-
Requires-Dist: nest-asyncio>=1.6.0
|
|
10
|
-
Requires-Dist: rich-argparse>=1.7.1
|
|
11
|
-
Requires-Dist: rich>=10.0.0
|
|
12
|
-
Requires-Dist: tomli-w>=1.2.0
|
|
13
|
-
Requires-Dist: tomli>=2.2.1
|
|
14
|
-
Description-Content-Type: text/markdown
|
|
15
|
-
|
|
16
1
|
# Plotly Cloud CLI
|
|
17
2
|
|
|
18
3
|
A command-line interface for interacting with Plotly Cloud to publish and manage Dash applications.
|
|
@@ -26,33 +11,8 @@ A command-line interface for interacting with Plotly Cloud to publish and manage
|
|
|
26
11
|
|
|
27
12
|
## Installation
|
|
28
13
|
|
|
29
|
-
### From Source
|
|
30
|
-
|
|
31
14
|
```bash
|
|
32
|
-
|
|
33
|
-
cd plotly-cloud-cli
|
|
34
|
-
pip install -e .
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### Development Installation
|
|
38
|
-
|
|
39
|
-
For development, we recommend using UV and the provided Justfile:
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
git clone <repository-url>
|
|
43
|
-
cd plotly-cloud-cli
|
|
44
|
-
|
|
45
|
-
# Install UV if you haven't already
|
|
46
|
-
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
47
|
-
|
|
48
|
-
# Install dependencies
|
|
49
|
-
just install
|
|
50
|
-
|
|
51
|
-
# Setup cloud environment configuration
|
|
52
|
-
just setup-cloud-env "your-staging-client-id" "your-production-client-id"
|
|
53
|
-
|
|
54
|
-
# Install CLI in development mode
|
|
55
|
-
just install-cli
|
|
15
|
+
pip install plotly-cloud
|
|
56
16
|
```
|
|
57
17
|
|
|
58
18
|
## Quick Start
|
|
@@ -313,7 +273,7 @@ plotly-cloud-cli/
|
|
|
313
273
|
|
|
314
274
|
## License
|
|
315
275
|
|
|
316
|
-
|
|
276
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
317
277
|
|
|
318
278
|
## Support
|
|
319
279
|
|
|
@@ -428,43 +428,43 @@ class PublishCommand(BaseCommand):
|
|
|
428
428
|
{
|
|
429
429
|
"name": "--project-path",
|
|
430
430
|
"default": ".",
|
|
431
|
-
"help": "Path to project directory to
|
|
431
|
+
"help": "Path to project directory to publish (default: current directory)",
|
|
432
432
|
},
|
|
433
433
|
{
|
|
434
434
|
"name": "--config",
|
|
435
435
|
"default": "plotly-cloud.toml",
|
|
436
|
-
"help": "Path to configuration file
|
|
436
|
+
"help": "Path to configuration file",
|
|
437
437
|
},
|
|
438
438
|
{
|
|
439
439
|
"name": "--name",
|
|
440
|
-
"help": "Application name (will prompt if not provided
|
|
440
|
+
"help": "Application name (will prompt if not provided first time app is published)",
|
|
441
441
|
},
|
|
442
442
|
{
|
|
443
443
|
"name": "--output",
|
|
444
|
-
"help": "Output path for
|
|
444
|
+
"help": "Output path for zip file of the published app (default: temporary file)",
|
|
445
445
|
},
|
|
446
446
|
{
|
|
447
447
|
"name": "--keep-zip",
|
|
448
448
|
"action": "store_true",
|
|
449
|
-
"help": "Keep the
|
|
449
|
+
"help": "Keep the zip file of the published app after upload",
|
|
450
450
|
},
|
|
451
451
|
{
|
|
452
452
|
"name": "--poll-status",
|
|
453
453
|
"type": lambda x: x.lower() in ("true", "1", "yes", "on"), # type: ignore
|
|
454
454
|
"default": True,
|
|
455
|
-
"help": "Poll
|
|
455
|
+
"help": "Poll publishing status until completion (default: True)",
|
|
456
456
|
},
|
|
457
457
|
{
|
|
458
458
|
"name": "--poll-interval",
|
|
459
459
|
"type": float,
|
|
460
460
|
"default": 1.0,
|
|
461
|
-
"help": "Polling interval in seconds
|
|
461
|
+
"help": "Polling interval in seconds",
|
|
462
462
|
},
|
|
463
463
|
{
|
|
464
464
|
"name": "--poll-timeout",
|
|
465
465
|
"type": int,
|
|
466
466
|
"default": 180,
|
|
467
|
-
"help": "Polling timeout in seconds
|
|
467
|
+
"help": "Polling timeout in seconds",
|
|
468
468
|
},
|
|
469
469
|
]
|
|
470
470
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
import dash
|
|
4
|
+
import flask
|
|
5
|
+
from packaging.version import parse as _parse_version
|
|
6
|
+
|
|
7
|
+
from plotly_cloud._devtool_publish_rpc import PlotlyCloudPublishRPC
|
|
8
|
+
|
|
9
|
+
dash_version = _parse_version(dash.__version__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _run_sync(coro):
|
|
13
|
+
loop = asyncio.get_event_loop()
|
|
14
|
+
return loop.run_until_complete(coro)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def install_hook():
|
|
18
|
+
import nest_asyncio
|
|
19
|
+
|
|
20
|
+
# Make asyncio stuff runs smoothly.
|
|
21
|
+
# Prevent no loop and existing loop errors.
|
|
22
|
+
nest_asyncio.apply()
|
|
23
|
+
|
|
24
|
+
rpc = PlotlyCloudPublishRPC()
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
# The style only works with the position left defined.
|
|
28
|
+
dash.hooks.devtool( # type: ignore
|
|
29
|
+
"plotly_cloud_publish_component",
|
|
30
|
+
"PlotlyCloudPublishComponent",
|
|
31
|
+
{"id": "_plotly-cloud-publish"},
|
|
32
|
+
position="left",
|
|
33
|
+
)
|
|
34
|
+
except Exception:
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
dash.hooks.script(
|
|
38
|
+
[
|
|
39
|
+
{"dev_package_path": "cloud_devtools.js", "namespace": "plotly_cloud", "dev_only": True},
|
|
40
|
+
]
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
dash.hooks.stylesheet(
|
|
44
|
+
[
|
|
45
|
+
{"relative_package_path": "cloud_devtools.css", "namespace": "plotly_cloud"},
|
|
46
|
+
]
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
@dash.hooks.route("_plotly_cloud_publish", methods=["POST"])
|
|
50
|
+
def plotly_cloud_publish_rpc():
|
|
51
|
+
data = flask.request.get_json()
|
|
52
|
+
data = _run_sync(rpc.handle_operation(data))
|
|
53
|
+
return flask.jsonify(data)
|
|
54
|
+
|
|
55
|
+
@dash.hooks.setup()
|
|
56
|
+
def plotly_cloud_setup(app):
|
|
57
|
+
rpc._app_setup = app
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
if hasattr(dash.hooks, "devtool"):
|
|
61
|
+
install_hook()
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"""RPC interface for Plotly Cloud publishing in dev tools."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import importlib
|
|
5
|
+
import os
|
|
6
|
+
import tempfile
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
import dash
|
|
10
|
+
from typing_extensions import Literal, NotRequired, TypedDict
|
|
11
|
+
|
|
12
|
+
from plotly_cloud._cloud_env import cloud_config
|
|
13
|
+
from plotly_cloud._definitions import AppDeploymentConfig
|
|
14
|
+
from plotly_cloud._deploy import (
|
|
15
|
+
DeploymentClient,
|
|
16
|
+
create_deployment_zip,
|
|
17
|
+
format_app_url,
|
|
18
|
+
get_config_path,
|
|
19
|
+
load_deployment_config,
|
|
20
|
+
save_deployment_config,
|
|
21
|
+
validate_dependencies,
|
|
22
|
+
)
|
|
23
|
+
from plotly_cloud._oauth import OAuthClient
|
|
24
|
+
from plotly_cloud.exceptions import TokenError
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class PublishOperations:
|
|
28
|
+
check_auth = "initialize"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class PublishOperation(TypedDict):
|
|
32
|
+
"""RPC operation structure for dev tools publishing."""
|
|
33
|
+
|
|
34
|
+
operation: Literal["initialize", "authenticate", "auth_poll", "publish", "status"]
|
|
35
|
+
data: Any
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class RPCResponse(TypedDict):
|
|
39
|
+
"""Standard RPC response structure."""
|
|
40
|
+
|
|
41
|
+
result: NotRequired[Any]
|
|
42
|
+
error: NotRequired[str]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class PlotlyCloudPublishRPC:
|
|
46
|
+
"""RPC handler for Plotly Cloud publishing operations in dev tools."""
|
|
47
|
+
|
|
48
|
+
def __init__(self) -> None:
|
|
49
|
+
"""Initialize the RPC handler."""
|
|
50
|
+
client_id = cloud_config.get_oauth_client_id()
|
|
51
|
+
self.oauth_client = OAuthClient(client_id)
|
|
52
|
+
self._app_setup = None # Fallback incase get_app fails.
|
|
53
|
+
|
|
54
|
+
def get_project_path(self):
|
|
55
|
+
app = None
|
|
56
|
+
try:
|
|
57
|
+
app = dash.det_app() # type: ignore
|
|
58
|
+
except Exception:
|
|
59
|
+
app = self._app_setup
|
|
60
|
+
|
|
61
|
+
assert app
|
|
62
|
+
app_module = importlib.import_module(app.config.name)
|
|
63
|
+
return os.path.dirname(str(app_module.__file__))
|
|
64
|
+
|
|
65
|
+
async def handle_operation(self, publish_operation: PublishOperation) -> RPCResponse:
|
|
66
|
+
"""Handle a publish operation from dev tools.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
publish_operation: The operation to perform with its data
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
RPCResponse with data and optional error
|
|
73
|
+
|
|
74
|
+
Raises:
|
|
75
|
+
ValueError: If operation is not supported
|
|
76
|
+
"""
|
|
77
|
+
operation_name = publish_operation["operation"]
|
|
78
|
+
data = publish_operation.get("data")
|
|
79
|
+
|
|
80
|
+
# Get the method by operation name (direct match)
|
|
81
|
+
if not hasattr(self, operation_name):
|
|
82
|
+
raise ValueError(f"Unsupported operation: {operation_name}")
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
method = getattr(self, operation_name)
|
|
86
|
+
return await method(data)
|
|
87
|
+
except Exception as e:
|
|
88
|
+
return {"error": str(e)}
|
|
89
|
+
|
|
90
|
+
async def initialize(self, data: Any) -> RPCResponse:
|
|
91
|
+
is_authenticated = await self.oauth_client.is_authenticated()
|
|
92
|
+
|
|
93
|
+
try:
|
|
94
|
+
# Try to refresh the access token so it's still valid
|
|
95
|
+
await self.oauth_client.refresh_access_token()
|
|
96
|
+
except TokenError:
|
|
97
|
+
is_authenticated = False
|
|
98
|
+
self.oauth_client.clear_credentials()
|
|
99
|
+
|
|
100
|
+
project_path = self.get_project_path()
|
|
101
|
+
|
|
102
|
+
config_path = get_config_path(project_path, os.path.join(project_path, "plotly-cloud.toml"))
|
|
103
|
+
config = load_deployment_config(config_path)
|
|
104
|
+
|
|
105
|
+
app_id = config.get("app_id")
|
|
106
|
+
existing = app_id is not None
|
|
107
|
+
status = "new"
|
|
108
|
+
app_name = config.get("name", os.path.basename(project_path))
|
|
109
|
+
app_url = ""
|
|
110
|
+
|
|
111
|
+
if app_id is not None and is_authenticated:
|
|
112
|
+
async with DeploymentClient(self.oauth_client) as deploy_client:
|
|
113
|
+
status_data = await deploy_client.get_app_status(app_id)
|
|
114
|
+
status = status_data.get("status", "")
|
|
115
|
+
app_url = format_app_url(status_data.get("app_url", ""))
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
"result": {
|
|
119
|
+
"authenticated": is_authenticated,
|
|
120
|
+
"existing": existing,
|
|
121
|
+
"status": status,
|
|
122
|
+
"app_name": app_name,
|
|
123
|
+
"app_path": project_path,
|
|
124
|
+
"app_id": app_id,
|
|
125
|
+
"app_url": app_url,
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async def authenticate(self, data: Any) -> RPCResponse:
|
|
130
|
+
device_auth = await self.oauth_client.request_device_authorization()
|
|
131
|
+
return {"result": device_auth}
|
|
132
|
+
|
|
133
|
+
async def auth_poll(self, data: Any) -> RPCResponse:
|
|
134
|
+
device_code = data.get("device_code")
|
|
135
|
+
status_code, response = await self.oauth_client.check_authentication_status(device_code)
|
|
136
|
+
if status_code == 200:
|
|
137
|
+
await self.oauth_client._save_credentials(dict(response))
|
|
138
|
+
return {"result": {"success": True}}
|
|
139
|
+
else:
|
|
140
|
+
error = response.get("error", "unknown_error")
|
|
141
|
+
if error == "authorization_pending":
|
|
142
|
+
return {"result": {}}
|
|
143
|
+
elif error == "slow_down":
|
|
144
|
+
delay = 1 + data.get("delayed", 0)
|
|
145
|
+
return {"result": {"delay": delay}}
|
|
146
|
+
elif error == "expired_token":
|
|
147
|
+
return {"result": {"try_again": True}}
|
|
148
|
+
elif error == "access_denied":
|
|
149
|
+
return {"error": "Access denied by user"}
|
|
150
|
+
else:
|
|
151
|
+
return {"error": "Authentication Failed"}
|
|
152
|
+
|
|
153
|
+
async def status(self, data: Any) -> RPCResponse:
|
|
154
|
+
app_id = data.get("app_id")
|
|
155
|
+
async with DeploymentClient(self.oauth_client) as deploy_client:
|
|
156
|
+
status_data = await deploy_client.get_app_status(app_id)
|
|
157
|
+
app_url = format_app_url(status_data.get("app_url", ""))
|
|
158
|
+
return {"result": {"status": status_data.get("status", ""), "app_url": app_url}}
|
|
159
|
+
|
|
160
|
+
async def publish(self, data: Any) -> RPCResponse:
|
|
161
|
+
app_path = data.get("app_path")
|
|
162
|
+
app_id = data.get("app_id")
|
|
163
|
+
app_name = data.get("app_name")
|
|
164
|
+
|
|
165
|
+
config_path = get_config_path(app_path)
|
|
166
|
+
|
|
167
|
+
temp_file = tempfile.NamedTemporaryFile(suffix=".zip", delete=False)
|
|
168
|
+
zip_path = temp_file.name
|
|
169
|
+
temp_file.close()
|
|
170
|
+
|
|
171
|
+
validate_dependencies(app_path)
|
|
172
|
+
|
|
173
|
+
await create_deployment_zip(app_path, zip_path)
|
|
174
|
+
|
|
175
|
+
async with DeploymentClient(self.oauth_client) as deploy_client:
|
|
176
|
+
if app_id:
|
|
177
|
+
# update app
|
|
178
|
+
app_data = await deploy_client.publish_app(app_id, zip_path)
|
|
179
|
+
config = load_deployment_config(config_path)
|
|
180
|
+
|
|
181
|
+
if config.get("app_url") != app_data.get("app_url"):
|
|
182
|
+
config["app_url"] = app_data.get("app_url", "")
|
|
183
|
+
save_deployment_config(config, config_path)
|
|
184
|
+
|
|
185
|
+
return {"result": {"app_id": app_id, "app_url": format_app_url(app_data.get("app_url"))}}
|
|
186
|
+
else:
|
|
187
|
+
# create new app
|
|
188
|
+
app_data = await deploy_client.create_app(app_name, zip_path)
|
|
189
|
+
|
|
190
|
+
config: AppDeploymentConfig = {
|
|
191
|
+
"name": app_name,
|
|
192
|
+
"app_id": app_data.get("id", ""),
|
|
193
|
+
"app_url": app_data.get("app_url", ""),
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
save_deployment_config(config, config_path)
|
|
197
|
+
|
|
198
|
+
return {"result": {"app_id": app_data.get("id"), "app_url": format_app_url(app_data.get("app_url"))}}
|
|
199
|
+
|
|
200
|
+
async def wait_auth(self, data: Any):
|
|
201
|
+
# this just wait to circumvent setTimeout with window.open restriction.
|
|
202
|
+
await asyncio.sleep(2)
|
|
203
|
+
return {"result": {}}
|
|
204
|
+
|
|
205
|
+
async def logout(self, data: Any):
|
|
206
|
+
await self.oauth_client.logout()
|
|
207
|
+
return {"result": {}}
|
|
@@ -6,13 +6,14 @@ import os
|
|
|
6
6
|
import time
|
|
7
7
|
import webbrowser
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import Optional
|
|
9
|
+
from typing import Any, Dict, Optional, Tuple, Union
|
|
10
10
|
|
|
11
11
|
import httpx
|
|
12
12
|
from rich.console import Console
|
|
13
13
|
from rich.live import Live
|
|
14
14
|
from rich.panel import Panel
|
|
15
15
|
from rich.spinner import Spinner
|
|
16
|
+
from typing_extensions import TypedDict
|
|
16
17
|
|
|
17
18
|
from .exceptions import (
|
|
18
19
|
CredentialError,
|
|
@@ -36,6 +37,25 @@ WORKOS_ENDPOINTS = {
|
|
|
36
37
|
DEFAULT_AUTH_PROVIDER = "authkit"
|
|
37
38
|
|
|
38
39
|
|
|
40
|
+
class AuthTokenResponse(TypedDict):
|
|
41
|
+
"""Response from successful OAuth authentication."""
|
|
42
|
+
|
|
43
|
+
access_token: str
|
|
44
|
+
refresh_token: str
|
|
45
|
+
token_type: str
|
|
46
|
+
expires_in: int
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class AuthErrorResponse(TypedDict):
|
|
50
|
+
"""Response from failed OAuth authentication."""
|
|
51
|
+
|
|
52
|
+
error: str
|
|
53
|
+
error_description: Optional[str]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
AuthResponse = Union[AuthTokenResponse, AuthErrorResponse]
|
|
57
|
+
|
|
58
|
+
|
|
39
59
|
class OAuthClient:
|
|
40
60
|
"""OAuth client for WorkOS CLI Auth using device authorization flow."""
|
|
41
61
|
|
|
@@ -70,7 +90,45 @@ class OAuthClient:
|
|
|
70
90
|
|
|
71
91
|
return response.json()
|
|
72
92
|
|
|
73
|
-
async def
|
|
93
|
+
async def check_authentication_status(
|
|
94
|
+
self,
|
|
95
|
+
device_code: str,
|
|
96
|
+
client: Optional[httpx.AsyncClient] = None,
|
|
97
|
+
) -> Tuple[int, AuthResponse]:
|
|
98
|
+
"""Check authentication status without terminal output or polling loop.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
device_code: The device code from device authorization
|
|
102
|
+
client: Optional httpx client to use, creates new one if not provided
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
Tuple of (status_code, response_data)
|
|
106
|
+
"""
|
|
107
|
+
token_data = {
|
|
108
|
+
"client_id": self.client_id,
|
|
109
|
+
"device_code": device_code,
|
|
110
|
+
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if client:
|
|
114
|
+
response = await client.post(
|
|
115
|
+
f"{WORKOS_API_BASE_URL}{WORKOS_ENDPOINTS['AUTHENTICATE']}",
|
|
116
|
+
data=token_data,
|
|
117
|
+
headers={"Content-Type": "application/x-www-form-urlencoded", "user-agent": "PlotlyCloudCLI"},
|
|
118
|
+
)
|
|
119
|
+
else:
|
|
120
|
+
async with httpx.AsyncClient() as new_client:
|
|
121
|
+
response = await new_client.post(
|
|
122
|
+
f"{WORKOS_API_BASE_URL}{WORKOS_ENDPOINTS['AUTHENTICATE']}",
|
|
123
|
+
data=token_data,
|
|
124
|
+
headers={"Content-Type": "application/x-www-form-urlencoded", "user-agent": "PlotlyCloudCLI"},
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
return response.status_code, response.json()
|
|
128
|
+
|
|
129
|
+
async def poll_for_authentication(
|
|
130
|
+
self, device_code: str, interval: int = 5, timeout: int = 300
|
|
131
|
+
) -> AuthTokenResponse:
|
|
74
132
|
"""Poll for authentication completion with exponential backoff."""
|
|
75
133
|
start_time = time.time()
|
|
76
134
|
current_interval = interval
|
|
@@ -79,24 +137,13 @@ class OAuthClient:
|
|
|
79
137
|
spinner = Spinner("dots", text="⏳ Waiting for authorization...")
|
|
80
138
|
|
|
81
139
|
with Live(spinner, console=console, refresh_per_second=4):
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
"device_code": device_code,
|
|
86
|
-
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
|
|
87
|
-
}
|
|
140
|
+
async with httpx.AsyncClient() as client:
|
|
141
|
+
while time.time() - start_time < timeout:
|
|
142
|
+
status_code, response_data = await self.check_authentication_status(device_code, client)
|
|
88
143
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
f"{WORKOS_API_BASE_URL}{WORKOS_ENDPOINTS['AUTHENTICATE']}",
|
|
92
|
-
data=token_data,
|
|
93
|
-
headers={"Content-Type": "application/x-www-form-urlencoded", "user-agent": "PlotlyCloudCLI"},
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
if response.status_code == 200:
|
|
97
|
-
return response.json()
|
|
144
|
+
if status_code == 200:
|
|
145
|
+
return response_data # type: ignore
|
|
98
146
|
|
|
99
|
-
response_data = response.json()
|
|
100
147
|
error = response_data.get("error", "unknown_error")
|
|
101
148
|
|
|
102
149
|
if error == "authorization_pending":
|
|
@@ -121,7 +168,7 @@ class OAuthClient:
|
|
|
121
168
|
|
|
122
169
|
raise TimeoutError("Authentication timed out. Please try again.")
|
|
123
170
|
|
|
124
|
-
async def login(self, open_browser: bool = True, provider: str = DEFAULT_AUTH_PROVIDER) ->
|
|
171
|
+
async def login(self, open_browser: bool = True, provider: str = DEFAULT_AUTH_PROVIDER) -> AuthTokenResponse:
|
|
125
172
|
"""Perform CLI Auth device flow login."""
|
|
126
173
|
|
|
127
174
|
# Step 1: Request device authorization
|
|
@@ -167,11 +214,11 @@ class OAuthClient:
|
|
|
167
214
|
raise
|
|
168
215
|
|
|
169
216
|
# Step 4: Save credentials
|
|
170
|
-
await self._save_credentials(tokens)
|
|
217
|
+
await self._save_credentials(dict(tokens))
|
|
171
218
|
|
|
172
219
|
return tokens
|
|
173
220
|
|
|
174
|
-
async def _save_credentials(self, credentials:
|
|
221
|
+
async def _save_credentials(self, credentials: Dict[str, Any]):
|
|
175
222
|
"""Save credentials to file."""
|
|
176
223
|
try:
|
|
177
224
|
# Ensure parent directory exists
|
|
@@ -187,7 +234,7 @@ class OAuthClient:
|
|
|
187
234
|
except Exception as e:
|
|
188
235
|
raise CredentialError("Failed to save credentials", str(e)) from e
|
|
189
236
|
|
|
190
|
-
async def load_credentials(self) -> Optional[
|
|
237
|
+
async def load_credentials(self) -> Optional[Dict[str, Any]]:
|
|
191
238
|
"""Load saved credentials."""
|
|
192
239
|
try:
|
|
193
240
|
if not self.credentials_path.exists():
|
|
@@ -220,9 +267,14 @@ class OAuthClient:
|
|
|
220
267
|
# Continue with local cleanup even if remote logout fails
|
|
221
268
|
|
|
222
269
|
# Clear local credentials
|
|
270
|
+
if self.clear_credentials():
|
|
271
|
+
console.print("Local credentials cleared")
|
|
272
|
+
|
|
273
|
+
def clear_credentials(self):
|
|
223
274
|
if self.credentials_path.exists():
|
|
224
275
|
self.credentials_path.unlink()
|
|
225
|
-
|
|
276
|
+
return True
|
|
277
|
+
return False
|
|
226
278
|
|
|
227
279
|
async def is_authenticated(self) -> bool:
|
|
228
280
|
"""Check if user is authenticated."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.plotly-cloud-publish-container{position:relative;font-family:Verdana,Geneva,sans-serif}.plotly-cloud-publish-button{cursor:pointer}.plotly-cloud-publish-button:hover{color:#7f4bc4}.plotly-cloud-publish-modal-overlay{position:absolute;bottom:100%;left:-2px;z-index:10000;margin-bottom:2px}.plotly-cloud-publish-modal-content{width:552px;background:#fff;border:1px solid #d1d5db;border-radius:4px 4px 0 0;box-shadow:0 -4px 6px #00000014;overflow:hidden}.plotly-cloud-publish-modal-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-bottom:1px solid #e5e5e5;background:#f9fafb}.plotly-cloud-publish-modal-header h3{margin:0;color:#333}.plotly-cloud-publish-modal-close{background:none;border:none;font-size:24px;cursor:pointer;color:#666;padding:0;width:30px;height:30px;display:flex;align-items:center;justify-content:center}.plotly-cloud-publish-modal-close:hover{color:#333}.plotly-cloud-publish-modal-body{padding:20px;color:#000!important;font-weight:100}button.plotly-cloud-publish-modal-button{display:inline-flex;align-items:center;gap:6px;padding:6px 10px!important;border-radius:4px!important;font-size:12px!important;font-weight:600;cursor:pointer;border:1px solid transparent;border-top-color:transparent;border-right-color:transparent;border-bottom-color:transparent;border-left-color:transparent;background:#f3f4f6;color:#374151}.plotly-cloud-publish-modal-button:disabled{cursor:not-allowed}button.plotly-cloud-btn-primary{background:#8b5cf6!important;color:#fff;border-color:#7c3aed!important}button.plotly-cloud-btn-secondary{background:#fff;border:none;color:#8b5cf6!important;font-weight:100}.plotly-cloud-button-bar{display:flex;justify-content:flex-end;align-items:center}.plotly-cloud-publish-signin{display:flex;justify-content:space-between;align-items:center}.plotly-cloud-name-input-label{font-weight:600;color:#374151;font-size:12px;margin-bottom:6px}.plotly-cloud-name-input-field{margin-bottom:12px;width:calc(100% - 8px)}.plotly-cloud-status-info{display:flex;border-radius:5px;margin-bottom:12px;align-items:center;padding:6px;font-size:12px!important}.plotly-cloud-status-red{background:#fef2f2;color:#991b1b;border:1px solid #fecaca}.plotly-cloud-status-description{font-size:12px!important;margin-left:8px}.plotly-cloud-status-title{font-weight:700}.plotly-cloud-status-green{background:#ecfdf5;color:#065f46;border:1px solid #a7f3d0}.plotly-cloud-status-red .plotly-cloud-status-title{color:#a10}.plotly-cloud-status-green .plotly-cloud-status-title{color:#065f46}.plotly-cloud-status-gray{background:#f9fafb;color:#000;border:1px solid #dadada}.plotly-cloud-status-gray .plotly-cloud-status-title{color:#2e2e2e}.plotly-cloud-green-icon{color:#10b981!important}.plotly-cloud-red-icon{color:#ef4444}.plotly-cloud-gray-icon{color:#9ca3af}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.plotly-cloud-spin{animation:spin 2s linear infinite}.plotly-cloud-confirm-code{margin-top:1rem}.plotly-cloud-user-code{color:#8b5cf6;font-weight:700}button.plotly-cloud-logout{padding-left:0!important}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const React = window.React; const ReactDOM = window.ReactDOM;
|
|
2
|
+
"use strict";var plotly_cloud_publish_component=(()=>{var aa=Object.create;var z=Object.defineProperty;var sa=Object.getOwnPropertyDescriptor;var ra=Object.getOwnPropertyNames;var ea=Object.getPrototypeOf,na=Object.prototype.hasOwnProperty;var Io=(o,a)=>()=>(a||o((a={exports:{}}).exports,a),a.exports),ia=(o,a)=>{for(var s in a)z(o,s,{get:a[s],enumerable:!0})},yo=(o,a,s,r)=>{if(a&&typeof a=="object"||typeof a=="function")for(let n of ra(a))!na.call(o,n)&&n!==s&&z(o,n,{get:()=>a[n],enumerable:!(r=sa(a,n))||r.enumerable});return o};var e=(o,a,s)=>(s=o!=null?aa(ea(o)):{},yo(a||!o||!o.__esModule?z(s,"default",{value:o,enumerable:!0}):s,o)),ta=o=>yo(z({},"__esModule",{value:!0}),o);var l=Io((Ta,Fo)=>{Fo.exports=React});var Do=Io(Z=>{"use strict";var ca=l(),la=Symbol.for("react.element"),ma=Symbol.for("react.fragment"),pa=Object.prototype.hasOwnProperty,Ia=ca.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,fa={key:!0,ref:!0,__self:!0,__source:!0};function Bo(o,a,s){var r,n={},L=null,c=null;s!==void 0&&(L=""+s),a.key!==void 0&&(L=""+a.key),a.ref!==void 0&&(c=a.ref);for(r in a)pa.call(a,r)&&!fa.hasOwnProperty(r)&&(n[r]=a[r]);if(o&&o.defaultProps)for(r in a=o.defaultProps,a)n[r]===void 0&&(n[r]=a[r]);return{$$typeof:la,type:o,key:L,ref:c,props:n,_owner:Ia.current}}Z.Fragment=ma;Z.jsx=Bo;Z.jsxs=Bo});var h=Io((Fa,Ho)=>{"use strict";Ho.exports=Do()});var Aa={};ia(Aa,{PlotlyCloudPublishComponent:()=>uo});var t=e(l());var F=e(h()),ua=({title:o,onClose:a,children:s})=>(0,F.jsx)("div",{className:"plotly-cloud-publish-modal-overlay",children:(0,F.jsxs)("div",{className:"plotly-cloud-publish-modal-content",children:[(0,F.jsxs)("div",{className:"plotly-cloud-publish-modal-header",children:[(0,F.jsx)("h3",{children:o},"modal-title"),(0,F.jsx)("button",{className:"plotly-cloud-publish-modal-close",onClick:a,children:"\xD7"},"modal-close")]}),(0,F.jsx)("div",{className:"plotly-cloud-publish-modal-body",children:s},"modal-body")]})}),Mo=ua;var Ro=e(l()),b=e(h()),ga=o=>{let[a,s]=(0,Ro.useState)(o.waiting);return(0,b.jsx)("div",{className:"plotly-cloud-publish-signin",children:a?(0,b.jsxs)("div",{children:[(0,b.jsx)("div",{children:"Waiting for succesful sign-in on signin.cloud.plotly.com"}),o.userCode?(0,b.jsxs)("div",{className:"plotly-cloud-confirm-code",children:["Confirm your device code"," ",(0,b.jsx)("span",{className:"plotly-cloud-user-code",children:o.userCode})," ","when prompted."]}):null]}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)("span",{children:"Sign in to publish your app to Plotly Cloud."}),(0,b.jsx)("button",{className:"plotly-cloud-publish-modal-button plotly-cloud-btn-primary",onClick:()=>{s(!0),o.onSignIn()},children:"Sign In"})]})})},xo=ga;var da=o=>{let a=async r=>await(await fetch(`${o}_plotly_cloud_publish`,{method:"POST",body:JSON.stringify(r),headers:{"Content-Type":"application/json"}})).json(),s=r=>n=>a({operation:r,data:n});return{initialize:s("initialize"),authenticate:s("authenticate"),auth_poll:s("auth_poll"),publish:s("publish"),status:s("status"),wait_auth:s("wait_auth"),logout:s("logout")}},No=da;var Uo=e(l()),k=e(h()),Sa=({initialAppName:o="",onCancel:a,onPublish:s})=>{let[r,n]=(0,Uo.useState)(o);return(0,k.jsxs)("div",{className:"plotly-cloud-name-input",children:[(0,k.jsx)("div",{className:"plotly-cloud-name-input-label",children:"App Name"}),(0,k.jsxs)("form",{onSubmit:c=>{c.preventDefault(),r.trim()&&s(r.trim())},children:[(0,k.jsx)("input",{type:"text",value:r,onChange:c=>n(c.target.value),placeholder:"My Dash App",className:"plotly-cloud-name-input-field"}),(0,k.jsxs)("div",{className:"plotly-cloud-button-bar",children:[(0,k.jsx)("button",{type:"button",onClick:a,className:"plotly-cloud-publish-modal-button plotly-cloud-btn-secondary",children:"Cancel"}),(0,k.jsx)("button",{type:"submit",disabled:!r.trim(),className:"plotly-cloud-publish-modal-button plotly-cloud-btn-primary",children:"Publish App"})]})]})]})},vo=Sa;var co=e(l());var m=e(l(),1),Eo=new Map([["bold",m.createElement(m.Fragment,null,m.createElement("path",{d:"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z"}))],["duotone",m.createElement(m.Fragment,null,m.createElement("path",{d:"M184,80V208a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V80a8,8,0,0,1,8-8H176A8,8,0,0,1,184,80Z",opacity:"0.2"}),m.createElement("path",{d:"M224,104a8,8,0,0,1-16,0V59.32l-66.33,66.34a8,8,0,0,1-11.32-11.32L196.68,48H152a8,8,0,0,1,0-16h64a8,8,0,0,1,8,8Zm-40,24a8,8,0,0,0-8,8v72H48V80h72a8,8,0,0,0,0-16H48A16,16,0,0,0,32,80V208a16,16,0,0,0,16,16H176a16,16,0,0,0,16-16V136A8,8,0,0,0,184,128Z"}))],["fill",m.createElement(m.Fragment,null,m.createElement("path",{d:"M192,136v72a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V80A16,16,0,0,1,48,64h72a8,8,0,0,1,0,16H48V208H176V136a8,8,0,0,1,16,0Zm32-96a8,8,0,0,0-8-8H152a8,8,0,0,0-5.66,13.66L172.69,72l-42.35,42.34a8,8,0,0,0,11.32,11.32L184,83.31l26.34,26.35A8,8,0,0,0,224,104Z"}))],["light",m.createElement(m.Fragment,null,m.createElement("path",{d:"M222,104a6,6,0,0,1-12,0V54.49l-69.75,69.75a6,6,0,0,1-8.48-8.48L201.51,46H152a6,6,0,0,1,0-12h64a6,6,0,0,1,6,6Zm-38,26a6,6,0,0,0-6,6v72a2,2,0,0,1-2,2H48a2,2,0,0,1-2-2V80a2,2,0,0,1,2-2h72a6,6,0,0,0,0-12H48A14,14,0,0,0,34,80V208a14,14,0,0,0,14,14H176a14,14,0,0,0,14-14V136A6,6,0,0,0,184,130Z"}))],["regular",m.createElement(m.Fragment,null,m.createElement("path",{d:"M224,104a8,8,0,0,1-16,0V59.32l-66.33,66.34a8,8,0,0,1-11.32-11.32L196.68,48H152a8,8,0,0,1,0-16h64a8,8,0,0,1,8,8Zm-40,24a8,8,0,0,0-8,8v72H48V80h72a8,8,0,0,0,0-16H48A16,16,0,0,0,32,80V208a16,16,0,0,0,16,16H176a16,16,0,0,0,16-16V136A8,8,0,0,0,184,128Z"}))],["thin",m.createElement(m.Fragment,null,m.createElement("path",{d:"M220,104a4,4,0,0,1-8,0V49.66l-73.16,73.17a4,4,0,0,1-5.66-5.66L206.34,44H152a4,4,0,0,1,0-8h64a4,4,0,0,1,4,4Zm-36,28a4,4,0,0,0-4,4v72a4,4,0,0,1-4,4H48a4,4,0,0,1-4-4V80a4,4,0,0,1,4-4h72a4,4,0,0,0,0-8H48A12,12,0,0,0,36,80V208a12,12,0,0,0,12,12H176a12,12,0,0,0,12-12V136A4,4,0,0,0,184,132Z"}))]]);var p=e(l(),1),Go=new Map([["bold",p.createElement(p.Fragment,null,p.createElement("path",{d:"M236,128a108,108,0,0,1-216,0c0-42.52,24.73-81.34,63-98.9A12,12,0,1,1,93,50.91C63.24,64.57,44,94.83,44,128a84,84,0,0,0,168,0c0-33.17-19.24-63.43-49-77.09A12,12,0,1,1,173,29.1C211.27,46.66,236,85.48,236,128Z"}))],["duotone",p.createElement(p.Fragment,null,p.createElement("path",{d:"M224,128a96,96,0,1,1-96-96A96,96,0,0,1,224,128Z",opacity:"0.2"}),p.createElement("path",{d:"M232,128a104,104,0,0,1-208,0c0-41,23.81-78.36,60.66-95.27a8,8,0,0,1,6.68,14.54C60.15,61.59,40,93.27,40,128a88,88,0,0,0,176,0c0-34.73-20.15-66.41-51.34-80.73a8,8,0,0,1,6.68-14.54C208.19,49.64,232,87,232,128Z"}))],["fill",p.createElement(p.Fragment,null,p.createElement("path",{d:"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,176A72,72,0,0,1,92,65.64a8,8,0,0,1,8,13.85,56,56,0,1,0,56,0,8,8,0,0,1,8-13.85A72,72,0,0,1,128,200Z"}))],["light",p.createElement(p.Fragment,null,p.createElement("path",{d:"M230,128a102,102,0,0,1-204,0c0-40.18,23.35-76.86,59.5-93.45a6,6,0,0,1,5,10.9C58.61,60.09,38,92.49,38,128a90,90,0,0,0,180,0c0-35.51-20.61-67.91-52.5-82.55a6,6,0,0,1,5-10.9C206.65,51.14,230,87.82,230,128Z"}))],["regular",p.createElement(p.Fragment,null,p.createElement("path",{d:"M232,128a104,104,0,0,1-208,0c0-41,23.81-78.36,60.66-95.27a8,8,0,0,1,6.68,14.54C60.15,61.59,40,93.27,40,128a88,88,0,0,0,176,0c0-34.73-20.15-66.41-51.34-80.73a8,8,0,0,1,6.68-14.54C208.19,49.64,232,87,232,128Z"}))],["thin",p.createElement(p.Fragment,null,p.createElement("path",{d:"M228,128a100,100,0,0,1-200,0c0-39.4,22.9-75.37,58.33-91.63a4,4,0,1,1,3.34,7.27C57.07,58.6,36,91.71,36,128a92,92,0,0,0,184,0c0-36.29-21.07-69.4-53.67-84.36a4,4,0,1,1,3.34-7.27C205.1,52.63,228,88.6,228,128Z"}))]]);var I=e(l(),1),qo=new Map([["bold",I.createElement(I.Fragment,null,I.createElement("path",{d:"M160,36A92.09,92.09,0,0,0,79,84.36,68,68,0,1,0,72,220h88a92,92,0,0,0,0-184Zm0,160H72a44,44,0,0,1-1.82-88A91.86,91.86,0,0,0,68,128a12,12,0,0,0,24,0,68,68,0,1,1,68,68Zm40.49-92.49a12,12,0,0,1,0,17l-48,48a12,12,0,0,1-17,0l-24-24a12,12,0,1,1,17-17L144,143l39.51-39.52A12,12,0,0,1,200.49,103.51Z"}))],["duotone",I.createElement(I.Fragment,null,I.createElement("path",{d:"M240,128a80,80,0,0,1-80,80H72A56,56,0,1,1,85.92,97.74l0,.1A80,80,0,0,1,240,128Z",opacity:"0.2"}),I.createElement("path",{d:"M160,40A88.09,88.09,0,0,0,81.29,88.67,64,64,0,1,0,72,216h88a88,88,0,0,0,0-176Zm0,160H72a48,48,0,0,1,0-96c1.1,0,2.2,0,3.29.11A88,88,0,0,0,72,128a8,8,0,0,0,16,0,72,72,0,1,1,72,72Zm37.66-93.66a8,8,0,0,1,0,11.32l-48,48a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L144,148.69l42.34-42.35A8,8,0,0,1,197.66,106.34Z"}))],["fill",I.createElement(I.Fragment,null,I.createElement("path",{d:"M247.93,124.52C246.11,77.54,207.07,40,160.06,40A88.1,88.1,0,0,0,81.29,88.67h0A87.48,87.48,0,0,0,72,127.73,8.18,8.18,0,0,1,64.57,136,8,8,0,0,1,56,128a103.66,103.66,0,0,1,5.34-32.92,4,4,0,0,0-4.75-5.18A64.09,64.09,0,0,0,8,152c0,35.19,29.75,64,65,64H160A88.09,88.09,0,0,0,247.93,124.52Zm-50.27-6.86-48,48a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L144,148.69l42.34-42.35a8,8,0,0,1,11.32,11.32Z"}))],["light",I.createElement(I.Fragment,null,I.createElement("path",{d:"M160,42A86.11,86.11,0,0,0,82.43,90.88,62,62,0,1,0,72,214h88a86,86,0,0,0,0-172Zm0,160H72a50,50,0,0,1,0-100,50.67,50.67,0,0,1,5.91.35A85.61,85.61,0,0,0,74,128a6,6,0,0,0,12,0,74,74,0,1,1,74,74Zm36.24-94.24a6,6,0,0,1,0,8.48l-48,48a6,6,0,0,1-8.48,0l-24-24a6,6,0,0,1,8.48-8.48L144,151.51l43.76-43.75A6,6,0,0,1,196.24,107.76Z"}))],["regular",I.createElement(I.Fragment,null,I.createElement("path",{d:"M160,40A88.09,88.09,0,0,0,81.29,88.67,64,64,0,1,0,72,216h88a88,88,0,0,0,0-176Zm0,160H72a48,48,0,0,1,0-96c1.1,0,2.2,0,3.29.11A88,88,0,0,0,72,128a8,8,0,0,0,16,0,72,72,0,1,1,72,72Zm37.66-93.66a8,8,0,0,1,0,11.32l-48,48a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L144,148.69l42.34-42.35A8,8,0,0,1,197.66,106.34Z"}))],["thin",I.createElement(I.Fragment,null,I.createElement("path",{d:"M160,44A84.11,84.11,0,0,0,83.59,93.12,60.71,60.71,0,0,0,72,92a60,60,0,0,0,0,120h88a84,84,0,0,0,0-168Zm0,160H72a52,52,0,1,1,8.55-103.3A83.66,83.66,0,0,0,76,128a4,4,0,0,0,8,0,76,76,0,1,1,76,76Zm34.83-94.83a4,4,0,0,1,0,5.66l-48,48a4,4,0,0,1-5.66,0l-24-24a4,4,0,0,1,5.66-5.66L144,154.34l45.17-45.17A4,4,0,0,1,194.83,109.17Z"}))]]);var f=e(l(),1),Oo=new Map([["bold",f.createElement(f.Fragment,null,f.createElement("path",{d:"M56.88,31.93A12,12,0,1,0,39.12,48.07L71.79,84A68,68,0,0,0,72,220h88a91.26,91.26,0,0,0,30.66-5.24l8.46,9.31a12,12,0,0,0,17.76-16.14ZM160,196H72a44,44,0,0,1-1.8-87.95A91.91,91.91,0,0,0,68,128a12,12,0,0,0,24,0,68.22,68.22,0,0,1,2.66-18.84l77.88,85.67A68.67,68.67,0,0,1,160,196Zm92-68a91.32,91.32,0,0,1-17.53,54,12,12,0,1,1-19.41-14.11,68,68,0,0,0-89.57-98.53,12,12,0,0,1-12.2-20.66A92,92,0,0,1,252,128Z"}))],["duotone",f.createElement(f.Fragment,null,f.createElement("path",{d:"M240,128a80,80,0,0,1-80,80H72A56,56,0,1,1,85.92,97.74l0,.1A80,80,0,0,1,240,128Z",opacity:"0.2"}),f.createElement("path",{d:"M53.92,34.62A8,8,0,1,0,42.08,45.38L81.32,88.55l-.06.12A65,65,0,0,0,72,88a64,64,0,0,0,0,128h88a87.34,87.34,0,0,0,31.8-5.93l10.28,11.31a8,8,0,1,0,11.84-10.76ZM160,200H72a48,48,0,0,1,0-96c1.1,0,2.2,0,3.3.12A88.4,88.4,0,0,0,72,128a8,8,0,0,0,16,0,72.25,72.25,0,0,1,5.06-26.54l87,95.7A71.66,71.66,0,0,1,160,200Zm88-72a87.89,87.89,0,0,1-22.35,58.61A8,8,0,0,1,213.71,176,72,72,0,0,0,117.37,70a8,8,0,0,1-9.48-12.89A88,88,0,0,1,248,128Z"}))],["fill",f.createElement(f.Fragment,null,f.createElement("path",{d:"M248,128.72A87.74,87.74,0,0,1,222.41,190a4,4,0,0,1-5.77-.16L103.78,65.67a4,4,0,0,1,.39-5.76A87.82,87.82,0,0,1,160.87,40C209.15,40.47,248.38,80.43,248,128.72ZM53.92,34.62A8,8,0,1,0,42.08,45.38L81.33,88.56l-.06.11A64,64,0,0,0,8,153c.53,35.12,29.84,63,65,63h87a87.65,87.65,0,0,0,31.78-5.95l10.3,11.33a8,8,0,0,0,11.33.52,8.32,8.32,0,0,0,.29-11.52Z"}))],["light",f.createElement(f.Fragment,null,f.createElement("path",{d:"M52.44,36A6,6,0,0,0,43.56,44l40.18,44.2c-.45.87-.9,1.75-1.32,2.64A62,62,0,1,0,72,214h88a85.23,85.23,0,0,0,32.35-6.3L203.56,220a6,6,0,0,0,8.88-8.08ZM160,202H72a50,50,0,1,1,5.9-99.64A86.25,86.25,0,0,0,74,128a6,6,0,0,0,12,0,73.92,73.92,0,0,1,6.44-30.2l91.22,100.34A73.65,73.65,0,0,1,160,202Zm86-74a85.85,85.85,0,0,1-21.85,57.27,6,6,0,0,1-4.47,2,6,6,0,0,1-4.47-10,74,74,0,0,0-99-108.92,6,6,0,1,1-7.11-9.67A86,86,0,0,1,246,128Z"}))],["regular",f.createElement(f.Fragment,null,f.createElement("path",{d:"M53.92,34.62A8,8,0,1,0,42.08,45.38L81.32,88.55l-.06.12A65,65,0,0,0,72,88a64,64,0,0,0,0,128h88a87.34,87.34,0,0,0,31.8-5.93l10.28,11.31a8,8,0,1,0,11.84-10.76ZM160,200H72a48,48,0,0,1,0-96c1.1,0,2.2,0,3.3.12A88.4,88.4,0,0,0,72,128a8,8,0,0,0,16,0,72.25,72.25,0,0,1,5.06-26.54l87,95.7A71.66,71.66,0,0,1,160,200Zm88-72a87.89,87.89,0,0,1-22.35,58.61A8,8,0,0,1,213.71,176,72,72,0,0,0,117.37,70a8,8,0,0,1-9.48-12.89A88,88,0,0,1,248,128Z"}))],["thin",f.createElement(f.Fragment,null,f.createElement("path",{d:"M51,37.31A4,4,0,0,0,45,42.69L86.16,87.93q-1.38,2.55-2.59,5.19A60,60,0,1,0,72,212h88a83.19,83.19,0,0,0,32.88-6.69L205,218.69a4,4,0,1,0,5.92-5.38ZM160,204H72a52,52,0,0,1,0-104,52.92,52.92,0,0,1,8.54.72A84.21,84.21,0,0,0,76,128a4,4,0,0,0,8,0,76,76,0,0,1,7.9-33.76L187.13,199A75.37,75.37,0,0,1,160,204Zm84-76a83.86,83.86,0,0,1-21.34,55.94,4,4,0,1,1-6-5.33A76,76,0,0,0,115,66.75a4,4,0,0,1-4.74-6.45A84,84,0,0,1,244,128Z"}))]]);var u=e(l(),1),Wo=new Map([["bold",u.createElement(u.Fragment,null,u.createElement("path",{d:"M160,36A92.09,92.09,0,0,0,79,84.36,68,68,0,1,0,72,220h88a92,92,0,0,0,0-184Zm0,160H72a44,44,0,0,1-1.82-88A91.86,91.86,0,0,0,68,128a12,12,0,0,0,24,0,68,68,0,1,1,68,68Zm32.49-79.51L177,132l15.52,15.51a12,12,0,0,1-17,17L160,149l-15.51,15.52a12,12,0,1,1-17-17L143,132l-15.52-15.51a12,12,0,1,1,17-17L160,115l15.51-15.52a12,12,0,0,1,17,17Z"}))],["duotone",u.createElement(u.Fragment,null,u.createElement("path",{d:"M240,127.62a80,80,0,0,1-80,80H72A56,56,0,1,1,85.92,97.36l0,.1A80,80,0,0,1,240,127.62Z",opacity:"0.2"}),u.createElement("path",{d:"M160,40A88.09,88.09,0,0,0,81.29,88.67,64,64,0,1,0,72,216h88a88,88,0,0,0,0-176Zm0,160H72a48,48,0,0,1,0-96c1.1,0,2.2,0,3.29.11A88,88,0,0,0,72,128a8,8,0,0,0,16,0,72,72,0,1,1,72,72Zm29.66-82.34L171.31,136l18.35,18.34a8,8,0,0,1-11.32,11.32L160,147.31l-18.34,18.35a8,8,0,0,1-11.32-11.32L148.69,136l-18.35-18.34a8,8,0,0,1,11.32-11.32L160,124.69l18.34-18.35a8,8,0,0,1,11.32,11.32Z"}))],["fill",u.createElement(u.Fragment,null,u.createElement("path",{d:"M247.93,124.52C246.11,77.54,207.07,40,160.06,40A88.1,88.1,0,0,0,81.29,88.67h0A87.48,87.48,0,0,0,72,127.73,8.18,8.18,0,0,1,64.57,136,8,8,0,0,1,56,128a103.66,103.66,0,0,1,5.34-32.92,4,4,0,0,0-4.75-5.18A64.09,64.09,0,0,0,8,152c0,35.19,29.75,64,65,64H160A88.09,88.09,0,0,0,247.93,124.52Zm-58.27,29.82a8,8,0,0,1-11.32,11.32L160,147.31l-18.34,18.35a8,8,0,0,1-11.32-11.32L148.69,136l-18.35-18.34a8,8,0,0,1,11.32-11.32L160,124.69l18.34-18.35a8,8,0,0,1,11.32,11.32L171.31,136Z"}))],["light",u.createElement(u.Fragment,null,u.createElement("path",{d:"M160,42A86.11,86.11,0,0,0,82.43,90.88,62,62,0,1,0,72,214h88a86,86,0,0,0,0-172Zm0,160H72a50,50,0,0,1,0-100,50.67,50.67,0,0,1,5.91.35A85.61,85.61,0,0,0,74,128a6,6,0,0,0,12,0,74,74,0,1,1,74,74Zm28.24-85.76L168.48,136l19.76,19.76a6,6,0,1,1-8.48,8.48L160,144.48l-19.76,19.76a6,6,0,0,1-8.48-8.48L151.52,136l-19.76-19.76a6,6,0,0,1,8.48-8.48L160,127.52l19.76-19.76a6,6,0,0,1,8.48,8.48Z"}))],["regular",u.createElement(u.Fragment,null,u.createElement("path",{d:"M160,40A88.09,88.09,0,0,0,81.29,88.67,64,64,0,1,0,72,216h88a88,88,0,0,0,0-176Zm0,160H72a48,48,0,0,1,0-96c1.1,0,2.2,0,3.29.11A88,88,0,0,0,72,128a8,8,0,0,0,16,0,72,72,0,1,1,72,72Zm29.66-82.34L171.31,136l18.35,18.34a8,8,0,0,1-11.32,11.32L160,147.31l-18.34,18.35a8,8,0,0,1-11.32-11.32L148.69,136l-18.35-18.34a8,8,0,0,1,11.32-11.32L160,124.69l18.34-18.35a8,8,0,0,1,11.32,11.32Z"}))],["thin",u.createElement(u.Fragment,null,u.createElement("path",{d:"M160,44A84.11,84.11,0,0,0,83.59,93.12,60.71,60.71,0,0,0,72,92a60,60,0,0,0,0,120h88a84,84,0,0,0,0-168Zm0,160H72a52,52,0,1,1,8.55-103.3A83.66,83.66,0,0,0,76,128a4,4,0,0,0,8,0,76,76,0,1,1,76,76Zm26.83-89.17L165.66,136l21.17,21.17a4,4,0,0,1-5.66,5.66L160,141.66l-21.17,21.17a4,4,0,0,1-5.66-5.66L154.34,136l-21.17-21.17a4,4,0,0,1,5.66-5.66L160,130.34l21.17-21.17a4,4,0,1,1,5.66,5.66Z"}))]]);var g=e(l(),1),Vo=new Map([["bold",g.createElement(g.Fragment,null,g.createElement("path",{d:"M128,76a52,52,0,1,0,52,52A52.06,52.06,0,0,0,128,76Zm0,80a28,28,0,1,1,28-28A28,28,0,0,1,128,156Zm92-27.21v-1.58l14-17.51a12,12,0,0,0,2.23-10.59A111.75,111.75,0,0,0,225,71.89,12,12,0,0,0,215.89,66L193.61,63.5l-1.11-1.11L190,40.1A12,12,0,0,0,184.11,31a111.67,111.67,0,0,0-27.23-11.27A12,12,0,0,0,146.3,22L128.79,36h-1.58L109.7,22a12,12,0,0,0-10.59-2.23A111.75,111.75,0,0,0,71.89,31.05,12,12,0,0,0,66,40.11L63.5,62.39,62.39,63.5,40.1,66A12,12,0,0,0,31,71.89,111.67,111.67,0,0,0,19.77,99.12,12,12,0,0,0,22,109.7l14,17.51v1.58L22,146.3a12,12,0,0,0-2.23,10.59,111.75,111.75,0,0,0,11.29,27.22A12,12,0,0,0,40.11,190l22.28,2.48,1.11,1.11L66,215.9A12,12,0,0,0,71.89,225a111.67,111.67,0,0,0,27.23,11.27A12,12,0,0,0,109.7,234l17.51-14h1.58l17.51,14a12,12,0,0,0,10.59,2.23A111.75,111.75,0,0,0,184.11,225a12,12,0,0,0,5.91-9.06l2.48-22.28,1.11-1.11L215.9,190a12,12,0,0,0,9.06-5.91,111.67,111.67,0,0,0,11.27-27.23A12,12,0,0,0,234,146.3Zm-24.12-4.89a70.1,70.1,0,0,1,0,8.2,12,12,0,0,0,2.61,8.22l12.84,16.05A86.47,86.47,0,0,1,207,166.86l-20.43,2.27a12,12,0,0,0-7.65,4,69,69,0,0,1-5.8,5.8,12,12,0,0,0-4,7.65L166.86,207a86.47,86.47,0,0,1-10.49,4.35l-16.05-12.85a12,12,0,0,0-7.5-2.62c-.24,0-.48,0-.72,0a70.1,70.1,0,0,1-8.2,0,12.06,12.06,0,0,0-8.22,2.6L99.63,211.33A86.47,86.47,0,0,1,89.14,207l-2.27-20.43a12,12,0,0,0-4-7.65,69,69,0,0,1-5.8-5.8,12,12,0,0,0-7.65-4L49,166.86a86.47,86.47,0,0,1-4.35-10.49l12.84-16.05a12,12,0,0,0,2.61-8.22,70.1,70.1,0,0,1,0-8.2,12,12,0,0,0-2.61-8.22L44.67,99.63A86.47,86.47,0,0,1,49,89.14l20.43-2.27a12,12,0,0,0,7.65-4,69,69,0,0,1,5.8-5.8,12,12,0,0,0,4-7.65L89.14,49a86.47,86.47,0,0,1,10.49-4.35l16.05,12.85a12.06,12.06,0,0,0,8.22,2.6,70.1,70.1,0,0,1,8.2,0,12,12,0,0,0,8.22-2.6l16.05-12.85A86.47,86.47,0,0,1,166.86,49l2.27,20.43a12,12,0,0,0,4,7.65,69,69,0,0,1,5.8,5.8,12,12,0,0,0,7.65,4L207,89.14a86.47,86.47,0,0,1,4.35,10.49l-12.84,16.05A12,12,0,0,0,195.88,123.9Z"}))],["duotone",g.createElement(g.Fragment,null,g.createElement("path",{d:"M207.86,123.18l16.78-21a99.14,99.14,0,0,0-10.07-24.29l-26.7-3a81,81,0,0,0-6.81-6.81l-3-26.71a99.43,99.43,0,0,0-24.3-10l-21,16.77a81.59,81.59,0,0,0-9.64,0l-21-16.78A99.14,99.14,0,0,0,77.91,41.43l-3,26.7a81,81,0,0,0-6.81,6.81l-26.71,3a99.43,99.43,0,0,0-10,24.3l16.77,21a81.59,81.59,0,0,0,0,9.64l-16.78,21a99.14,99.14,0,0,0,10.07,24.29l26.7,3a81,81,0,0,0,6.81,6.81l3,26.71a99.43,99.43,0,0,0,24.3,10l21-16.77a81.59,81.59,0,0,0,9.64,0l21,16.78a99.14,99.14,0,0,0,24.29-10.07l3-26.7a81,81,0,0,0,6.81-6.81l26.71-3a99.43,99.43,0,0,0,10-24.3l-16.77-21A81.59,81.59,0,0,0,207.86,123.18ZM128,168a40,40,0,1,1,40-40A40,40,0,0,1,128,168Z",opacity:"0.2"}),g.createElement("path",{d:"M128,80a48,48,0,1,0,48,48A48.05,48.05,0,0,0,128,80Zm0,80a32,32,0,1,1,32-32A32,32,0,0,1,128,160Zm88-29.84q.06-2.16,0-4.32l14.92-18.64a8,8,0,0,0,1.48-7.06,107.6,107.6,0,0,0-10.88-26.25,8,8,0,0,0-6-3.93l-23.72-2.64q-1.48-1.56-3-3L186,40.54a8,8,0,0,0-3.94-6,107.29,107.29,0,0,0-26.25-10.86,8,8,0,0,0-7.06,1.48L130.16,40Q128,40,125.84,40L107.2,25.11a8,8,0,0,0-7.06-1.48A107.6,107.6,0,0,0,73.89,34.51a8,8,0,0,0-3.93,6L67.32,64.27q-1.56,1.49-3,3L40.54,70a8,8,0,0,0-6,3.94,107.71,107.71,0,0,0-10.87,26.25,8,8,0,0,0,1.49,7.06L40,125.84Q40,128,40,130.16L25.11,148.8a8,8,0,0,0-1.48,7.06,107.6,107.6,0,0,0,10.88,26.25,8,8,0,0,0,6,3.93l23.72,2.64q1.49,1.56,3,3L70,215.46a8,8,0,0,0,3.94,6,107.71,107.71,0,0,0,26.25,10.87,8,8,0,0,0,7.06-1.49L125.84,216q2.16.06,4.32,0l18.64,14.92a8,8,0,0,0,7.06,1.48,107.21,107.21,0,0,0,26.25-10.88,8,8,0,0,0,3.93-6l2.64-23.72q1.56-1.48,3-3L215.46,186a8,8,0,0,0,6-3.94,107.71,107.71,0,0,0,10.87-26.25,8,8,0,0,0-1.49-7.06Zm-16.1-6.5a73.93,73.93,0,0,1,0,8.68,8,8,0,0,0,1.74,5.48l14.19,17.73a91.57,91.57,0,0,1-6.23,15L187,173.11a8,8,0,0,0-5.1,2.64,74.11,74.11,0,0,1-6.14,6.14,8,8,0,0,0-2.64,5.1l-2.51,22.58a91.32,91.32,0,0,1-15,6.23l-17.74-14.19a8,8,0,0,0-5-1.75h-.48a73.93,73.93,0,0,1-8.68,0,8.06,8.06,0,0,0-5.48,1.74L100.45,215.8a91.57,91.57,0,0,1-15-6.23L82.89,187a8,8,0,0,0-2.64-5.1,74.11,74.11,0,0,1-6.14-6.14,8,8,0,0,0-5.1-2.64L46.43,170.6a91.32,91.32,0,0,1-6.23-15l14.19-17.74a8,8,0,0,0,1.74-5.48,73.93,73.93,0,0,1,0-8.68,8,8,0,0,0-1.74-5.48L40.2,100.45a91.57,91.57,0,0,1,6.23-15L69,82.89a8,8,0,0,0,5.1-2.64,74.11,74.11,0,0,1,6.14-6.14A8,8,0,0,0,82.89,69L85.4,46.43a91.32,91.32,0,0,1,15-6.23l17.74,14.19a8,8,0,0,0,5.48,1.74,73.93,73.93,0,0,1,8.68,0,8.06,8.06,0,0,0,5.48-1.74L155.55,40.2a91.57,91.57,0,0,1,15,6.23L173.11,69a8,8,0,0,0,2.64,5.1,74.11,74.11,0,0,1,6.14,6.14,8,8,0,0,0,5.1,2.64l22.58,2.51a91.32,91.32,0,0,1,6.23,15l-14.19,17.74A8,8,0,0,0,199.87,123.66Z"}))],["fill",g.createElement(g.Fragment,null,g.createElement("path",{d:"M216,130.16q.06-2.16,0-4.32l14.92-18.64a8,8,0,0,0,1.48-7.06,107.6,107.6,0,0,0-10.88-26.25,8,8,0,0,0-6-3.93l-23.72-2.64q-1.48-1.56-3-3L186,40.54a8,8,0,0,0-3.94-6,107.29,107.29,0,0,0-26.25-10.86,8,8,0,0,0-7.06,1.48L130.16,40Q128,40,125.84,40L107.2,25.11a8,8,0,0,0-7.06-1.48A107.6,107.6,0,0,0,73.89,34.51a8,8,0,0,0-3.93,6L67.32,64.27q-1.56,1.49-3,3L40.54,70a8,8,0,0,0-6,3.94,107.71,107.71,0,0,0-10.87,26.25,8,8,0,0,0,1.49,7.06L40,125.84Q40,128,40,130.16L25.11,148.8a8,8,0,0,0-1.48,7.06,107.6,107.6,0,0,0,10.88,26.25,8,8,0,0,0,6,3.93l23.72,2.64q1.49,1.56,3,3L70,215.46a8,8,0,0,0,3.94,6,107.71,107.71,0,0,0,26.25,10.87,8,8,0,0,0,7.06-1.49L125.84,216q2.16.06,4.32,0l18.64,14.92a8,8,0,0,0,7.06,1.48,107.21,107.21,0,0,0,26.25-10.88,8,8,0,0,0,3.93-6l2.64-23.72q1.56-1.48,3-3L215.46,186a8,8,0,0,0,6-3.94,107.71,107.71,0,0,0,10.87-26.25,8,8,0,0,0-1.49-7.06ZM128,168a40,40,0,1,1,40-40A40,40,0,0,1,128,168Z"}))],["light",g.createElement(g.Fragment,null,g.createElement("path",{d:"M128,82a46,46,0,1,0,46,46A46.06,46.06,0,0,0,128,82Zm0,80a34,34,0,1,1,34-34A34,34,0,0,1,128,162ZM214,130.84c.06-1.89.06-3.79,0-5.68L229.33,106a6,6,0,0,0,1.11-5.29A105.34,105.34,0,0,0,219.76,74.9a6,6,0,0,0-4.53-3l-24.45-2.71q-1.93-2.07-4-4l-2.72-24.46a6,6,0,0,0-3-4.53,105.65,105.65,0,0,0-25.77-10.66A6,6,0,0,0,150,26.68l-19.2,15.37c-1.89-.06-3.79-.06-5.68,0L106,26.67a6,6,0,0,0-5.29-1.11A105.34,105.34,0,0,0,74.9,36.24a6,6,0,0,0-3,4.53L69.23,65.22q-2.07,1.94-4,4L40.76,72a6,6,0,0,0-4.53,3,105.65,105.65,0,0,0-10.66,25.77A6,6,0,0,0,26.68,106l15.37,19.2c-.06,1.89-.06,3.79,0,5.68L26.67,150.05a6,6,0,0,0-1.11,5.29A105.34,105.34,0,0,0,36.24,181.1a6,6,0,0,0,4.53,3l24.45,2.71q1.94,2.07,4,4L72,215.24a6,6,0,0,0,3,4.53,105.65,105.65,0,0,0,25.77,10.66,6,6,0,0,0,5.29-1.11L125.16,214c1.89.06,3.79.06,5.68,0l19.21,15.38a6,6,0,0,0,3.75,1.31,6.2,6.2,0,0,0,1.54-.2,105.34,105.34,0,0,0,25.76-10.68,6,6,0,0,0,3-4.53l2.71-24.45q2.07-1.93,4-4l24.46-2.72a6,6,0,0,0,4.53-3,105.49,105.49,0,0,0,10.66-25.77,6,6,0,0,0-1.11-5.29Zm-3.1,41.63-23.64,2.63a6,6,0,0,0-3.82,2,75.14,75.14,0,0,1-6.31,6.31,6,6,0,0,0-2,3.82l-2.63,23.63A94.28,94.28,0,0,1,155.14,218l-18.57-14.86a6,6,0,0,0-3.75-1.31h-.36a78.07,78.07,0,0,1-8.92,0,6,6,0,0,0-4.11,1.3L100.87,218a94.13,94.13,0,0,1-17.34-7.17L80.9,187.21a6,6,0,0,0-2-3.82,75.14,75.14,0,0,1-6.31-6.31,6,6,0,0,0-3.82-2l-23.63-2.63A94.28,94.28,0,0,1,38,155.14l14.86-18.57a6,6,0,0,0,1.3-4.11,78.07,78.07,0,0,1,0-8.92,6,6,0,0,0-1.3-4.11L38,100.87a94.13,94.13,0,0,1,7.17-17.34L68.79,80.9a6,6,0,0,0,3.82-2,75.14,75.14,0,0,1,6.31-6.31,6,6,0,0,0,2-3.82l2.63-23.63A94.28,94.28,0,0,1,100.86,38l18.57,14.86a6,6,0,0,0,4.11,1.3,78.07,78.07,0,0,1,8.92,0,6,6,0,0,0,4.11-1.3L155.13,38a94.13,94.13,0,0,1,17.34,7.17l2.63,23.64a6,6,0,0,0,2,3.82,75.14,75.14,0,0,1,6.31,6.31,6,6,0,0,0,3.82,2l23.63,2.63A94.28,94.28,0,0,1,218,100.86l-14.86,18.57a6,6,0,0,0-1.3,4.11,78.07,78.07,0,0,1,0,8.92,6,6,0,0,0,1.3,4.11L218,155.13A94.13,94.13,0,0,1,210.85,172.47Z"}))],["regular",g.createElement(g.Fragment,null,g.createElement("path",{d:"M128,80a48,48,0,1,0,48,48A48.05,48.05,0,0,0,128,80Zm0,80a32,32,0,1,1,32-32A32,32,0,0,1,128,160Zm88-29.84q.06-2.16,0-4.32l14.92-18.64a8,8,0,0,0,1.48-7.06,107.21,107.21,0,0,0-10.88-26.25,8,8,0,0,0-6-3.93l-23.72-2.64q-1.48-1.56-3-3L186,40.54a8,8,0,0,0-3.94-6,107.71,107.71,0,0,0-26.25-10.87,8,8,0,0,0-7.06,1.49L130.16,40Q128,40,125.84,40L107.2,25.11a8,8,0,0,0-7.06-1.48A107.6,107.6,0,0,0,73.89,34.51a8,8,0,0,0-3.93,6L67.32,64.27q-1.56,1.49-3,3L40.54,70a8,8,0,0,0-6,3.94,107.71,107.71,0,0,0-10.87,26.25,8,8,0,0,0,1.49,7.06L40,125.84Q40,128,40,130.16L25.11,148.8a8,8,0,0,0-1.48,7.06,107.21,107.21,0,0,0,10.88,26.25,8,8,0,0,0,6,3.93l23.72,2.64q1.49,1.56,3,3L70,215.46a8,8,0,0,0,3.94,6,107.71,107.71,0,0,0,26.25,10.87,8,8,0,0,0,7.06-1.49L125.84,216q2.16.06,4.32,0l18.64,14.92a8,8,0,0,0,7.06,1.48,107.21,107.21,0,0,0,26.25-10.88,8,8,0,0,0,3.93-6l2.64-23.72q1.56-1.48,3-3L215.46,186a8,8,0,0,0,6-3.94,107.71,107.71,0,0,0,10.87-26.25,8,8,0,0,0-1.49-7.06Zm-16.1-6.5a73.93,73.93,0,0,1,0,8.68,8,8,0,0,0,1.74,5.48l14.19,17.73a91.57,91.57,0,0,1-6.23,15L187,173.11a8,8,0,0,0-5.1,2.64,74.11,74.11,0,0,1-6.14,6.14,8,8,0,0,0-2.64,5.1l-2.51,22.58a91.32,91.32,0,0,1-15,6.23l-17.74-14.19a8,8,0,0,0-5-1.75h-.48a73.93,73.93,0,0,1-8.68,0,8,8,0,0,0-5.48,1.74L100.45,215.8a91.57,91.57,0,0,1-15-6.23L82.89,187a8,8,0,0,0-2.64-5.1,74.11,74.11,0,0,1-6.14-6.14,8,8,0,0,0-5.1-2.64L46.43,170.6a91.32,91.32,0,0,1-6.23-15l14.19-17.74a8,8,0,0,0,1.74-5.48,73.93,73.93,0,0,1,0-8.68,8,8,0,0,0-1.74-5.48L40.2,100.45a91.57,91.57,0,0,1,6.23-15L69,82.89a8,8,0,0,0,5.1-2.64,74.11,74.11,0,0,1,6.14-6.14A8,8,0,0,0,82.89,69L85.4,46.43a91.32,91.32,0,0,1,15-6.23l17.74,14.19a8,8,0,0,0,5.48,1.74,73.93,73.93,0,0,1,8.68,0,8,8,0,0,0,5.48-1.74L155.55,40.2a91.57,91.57,0,0,1,15,6.23L173.11,69a8,8,0,0,0,2.64,5.1,74.11,74.11,0,0,1,6.14,6.14,8,8,0,0,0,5.1,2.64l22.58,2.51a91.32,91.32,0,0,1,6.23,15l-14.19,17.74A8,8,0,0,0,199.87,123.66Z"}))],["thin",g.createElement(g.Fragment,null,g.createElement("path",{d:"M128,84a44,44,0,1,0,44,44A44.05,44.05,0,0,0,128,84Zm0,80a36,36,0,1,1,36-36A36,36,0,0,1,128,164Zm83.93-32.49q.13-3.51,0-7l15.83-19.79a4,4,0,0,0,.75-3.53A103.64,103.64,0,0,0,218,75.9a4,4,0,0,0-3-2l-25.19-2.8c-1.58-1.71-3.24-3.37-4.95-4.95L182.07,41a4,4,0,0,0-2-3A104,104,0,0,0,154.82,27.5a4,4,0,0,0-3.53.74L131.51,44.07q-3.51-.14-7,0L104.7,28.24a4,4,0,0,0-3.53-.75A103.64,103.64,0,0,0,75.9,38a4,4,0,0,0-2,3l-2.8,25.19c-1.71,1.58-3.37,3.24-4.95,4.95L41,73.93a4,4,0,0,0-3,2A104,104,0,0,0,27.5,101.18a4,4,0,0,0,.74,3.53l15.83,19.78q-.14,3.51,0,7L28.24,151.3a4,4,0,0,0-.75,3.53A103.64,103.64,0,0,0,38,180.1a4,4,0,0,0,3,2l25.19,2.8c1.58,1.71,3.24,3.37,4.95,4.95l2.8,25.2a4,4,0,0,0,2,3,104,104,0,0,0,25.28,10.46,4,4,0,0,0,3.53-.74l19.78-15.83q3.51.13,7,0l19.79,15.83a4,4,0,0,0,2.5.88,4,4,0,0,0,1-.13A103.64,103.64,0,0,0,180.1,218a4,4,0,0,0,2-3l2.8-25.19c1.71-1.58,3.37-3.24,4.95-4.95l25.2-2.8a4,4,0,0,0,3-2,104,104,0,0,0,10.46-25.28,4,4,0,0,0-.74-3.53Zm.17,42.83-24.67,2.74a4,4,0,0,0-2.55,1.32,76.2,76.2,0,0,1-6.48,6.48,4,4,0,0,0-1.32,2.55l-2.74,24.66a95.45,95.45,0,0,1-19.64,8.15l-19.38-15.51a4,4,0,0,0-2.5-.87h-.24a73.67,73.67,0,0,1-9.16,0,4,4,0,0,0-2.74.87l-19.37,15.5a95.33,95.33,0,0,1-19.65-8.13l-2.74-24.67a4,4,0,0,0-1.32-2.55,76.2,76.2,0,0,1-6.48-6.48,4,4,0,0,0-2.55-1.32l-24.66-2.74a95.45,95.45,0,0,1-8.15-19.64l15.51-19.38a4,4,0,0,0,.87-2.74,77.76,77.76,0,0,1,0-9.16,4,4,0,0,0-.87-2.74l-15.5-19.37A95.33,95.33,0,0,1,43.9,81.66l24.67-2.74a4,4,0,0,0,2.55-1.32,76.2,76.2,0,0,1,6.48-6.48,4,4,0,0,0,1.32-2.55l2.74-24.66a95.45,95.45,0,0,1,19.64-8.15l19.38,15.51a4,4,0,0,0,2.74.87,73.67,73.67,0,0,1,9.16,0,4,4,0,0,0,2.74-.87l19.37-15.5a95.33,95.33,0,0,1,19.65,8.13l2.74,24.67a4,4,0,0,0,1.32,2.55,76.2,76.2,0,0,1,6.48,6.48,4,4,0,0,0,2.55,1.32l24.66,2.74a95.45,95.45,0,0,1,8.15,19.64l-15.51,19.38a4,4,0,0,0-.87,2.74,77.76,77.76,0,0,1,0,9.16,4,4,0,0,0,.87,2.74l15.5,19.37A95.33,95.33,0,0,1,212.1,174.34Z"}))]]);var d=e(l(),1),zo=new Map([["bold",d.createElement(d.Fragment,null,d.createElement("path",{d:"M124,216a12,12,0,0,1-12,12H48a12,12,0,0,1-12-12V40A12,12,0,0,1,48,28h64a12,12,0,0,1,0,24H60V204h52A12,12,0,0,1,124,216Zm108.49-96.49-40-40a12,12,0,0,0-17,17L195,116H112a12,12,0,0,0,0,24h83l-19.52,19.51a12,12,0,0,0,17,17l40-40A12,12,0,0,0,232.49,119.51Z"}))],["duotone",d.createElement(d.Fragment,null,d.createElement("path",{d:"M224,56V200a16,16,0,0,1-16,16H48V40H208A16,16,0,0,1,224,56Z",opacity:"0.2"}),d.createElement("path",{d:"M120,216a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V40a8,8,0,0,1,8-8h64a8,8,0,0,1,0,16H56V208h56A8,8,0,0,1,120,216Zm109.66-93.66-40-40a8,8,0,0,0-11.32,11.32L204.69,120H112a8,8,0,0,0,0,16h92.69l-26.35,26.34a8,8,0,0,0,11.32,11.32l40-40A8,8,0,0,0,229.66,122.34Z"}))],["fill",d.createElement(d.Fragment,null,d.createElement("path",{d:"M120,216a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V40a8,8,0,0,1,8-8h64a8,8,0,0,1,0,16H56V208h56A8,8,0,0,1,120,216Zm109.66-93.66-40-40A8,8,0,0,0,176,88v32H112a8,8,0,0,0,0,16h64v32a8,8,0,0,0,13.66,5.66l40-40A8,8,0,0,0,229.66,122.34Z"}))],["light",d.createElement(d.Fragment,null,d.createElement("path",{d:"M118,216a6,6,0,0,1-6,6H48a6,6,0,0,1-6-6V40a6,6,0,0,1,6-6h64a6,6,0,0,1,0,12H54V210h58A6,6,0,0,1,118,216Zm110.24-92.24-40-40a6,6,0,0,0-8.48,8.48L209.51,122H112a6,6,0,0,0,0,12h97.51l-29.75,29.76a6,6,0,1,0,8.48,8.48l40-40A6,6,0,0,0,228.24,123.76Z"}))],["regular",d.createElement(d.Fragment,null,d.createElement("path",{d:"M120,216a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V40a8,8,0,0,1,8-8h64a8,8,0,0,1,0,16H56V208h56A8,8,0,0,1,120,216Zm109.66-93.66-40-40a8,8,0,0,0-11.32,11.32L204.69,120H112a8,8,0,0,0,0,16h92.69l-26.35,26.34a8,8,0,0,0,11.32,11.32l40-40A8,8,0,0,0,229.66,122.34Z"}))],["thin",d.createElement(d.Fragment,null,d.createElement("path",{d:"M116,216a4,4,0,0,1-4,4H48a4,4,0,0,1-4-4V40a4,4,0,0,1,4-4h64a4,4,0,0,1,0,8H52V212h60A4,4,0,0,1,116,216Zm110.83-90.83-40-40a4,4,0,0,0-5.66,5.66L214.34,124H112a4,4,0,0,0,0,8H214.34l-33.17,33.17a4,4,0,0,0,5.66,5.66l40-40A4,4,0,0,0,226.83,125.17Z"}))]]);var M=e(l(),1);var Zo=e(l(),1),_o=(0,Zo.createContext)({color:"currentColor",size:"1em",weight:"regular",mirrored:!1});var C=M.forwardRef((o,a)=>{let{alt:s,color:r,size:n,weight:L,mirrored:c,children:R,weights:x,...N}=o,{color:U="currentColor",size:B,weight:T="regular",mirrored:v=!1,...D}=M.useContext(_o);return M.createElement("svg",{ref:a,xmlns:"http://www.w3.org/2000/svg",width:n??B,height:n??B,fill:r??U,viewBox:"0 0 256 256",transform:c||v?"scale(-1, 1)":void 0,...D,...N},!!s&&M.createElement("title",null,s),R,x.get(L??T))});C.displayName="IconBase";var _=e(l(),1);var X=_.forwardRef((o,a)=>_.createElement(C,{ref:a,...o,weights:Eo}));X.displayName="ArrowSquareOutIcon";var J=e(l(),1);var K=J.forwardRef((o,a)=>J.createElement(C,{ref:a,...o,weights:Go}));K.displayName="CircleNotchIcon";var Q=e(l(),1);var j=Q.forwardRef((o,a)=>Q.createElement(C,{ref:a,...o,weights:qo}));j.displayName="CloudCheckIcon";var Y=e(l(),1);var $=Y.forwardRef((o,a)=>Y.createElement(C,{ref:a,...o,weights:Oo}));$.displayName="CloudSlashIcon";var oo=e(l(),1);var ao=oo.forwardRef((o,a)=>oo.createElement(C,{ref:a,...o,weights:Wo}));ao.displayName="CloudXIcon";var so=e(l(),1);var ro=so.forwardRef((o,a)=>so.createElement(C,{ref:a,...o,weights:Vo}));ro.displayName="GearIcon";var eo=e(l(),1);var no=eo.forwardRef((o,a)=>eo.createElement(C,{ref:a,...o,weights:zo}));no.displayName="SignOutIcon";var Xo=e(h()),ha=o=>(0,Xo.jsx)(K,{size:o.size,className:"plotly-cloud-spin plotly-cloud-gray-icon",weight:"bold"}),io=ha;var E=e(h()),Ca=({status:o,size:a=16,isButtonIcon:s})=>o==="BUILDING"||o==="STARTING"||o==="unknown"?(0,E.jsx)(io,{size:a}):o==="RUNNING"?(0,E.jsx)(j,{size:a,className:"plotly-cloud-green-icon",weight:s?"fill":"duotone"}):o==="new"?(0,E.jsx)($,{size:a,className:"plotly-cloud-gray-icon",weight:s?"fill":"duotone"}):(0,E.jsx)(ao,{size:a,className:"plotly-cloud-red-icon",weight:"duotone"}),to=Ca;var S=e(h()),wa=({status:o,onPublish:a,isUpdate:s,publishing:r,onCancel:n,onLogout:L,appUrl:c})=>{let R=()=>{n&&n()},x=()=>{window.open(c,"_blank")},[N,U,B]=(0,co.useMemo)(()=>o==="BUILDING"||o==="STARTING"?["App is building","Wait for your app to finish publishing before publishing again","gray"]:o==="RUNNING"?["App is live","Your app is running in Plotly Cloud.","green"]:["App is stopped","Start your app by publishing again or starting it in the app manager","red"],[o]),[T,v]=(0,co.useMemo)(()=>r?s?["Open Settings in Plotly Cloud","Republishing",""]:["Cancel","Publishing",""]:s?[(0,S.jsxs)("span",{children:[(0,S.jsx)(ro,{}),"\xA0Open Settings in Plotly Cloud"]}),"Republish"]:["Cancel","Publish",""],[r,s]),D=(0,co.useMemo)(()=>["BUILDING","STARTING"].includes(o),[o]);return(0,S.jsxs)("div",{className:"plotly-cloud-status-banner",children:[(0,S.jsxs)("div",{className:`plotly-cloud-status-info plotly-cloud-status-${B}`,children:[(0,S.jsx)(to,{status:o,size:20}),(0,S.jsxs)("div",{className:"plotly-cloud-status-description",children:[(0,S.jsx)("div",{className:"plotly-cloud-status-title",children:N}),(0,S.jsx)("div",{className:"plotly-cloud-status-text",children:U})]})]}),(0,S.jsxs)("div",{className:"plotly-cloud-button-bar",children:[(0,S.jsx)("div",{style:{flex:1},children:(0,S.jsxs)("button",{disabled:r,className:"plotly-cloud-publish-modal-button plotly-cloud-btn-secondary plotly-cloud-logout",onClick:L,children:[(0,S.jsx)(no,{}),"\xA0Logout"]})}),(0,S.jsx)("button",{type:"button",onClick:R,disabled:s?!1:r,className:"plotly-cloud-publish-modal-button plotly-cloud-btn-secondary",children:T}),c?(0,S.jsx)("button",{onClick:x,disabled:r,className:"plotly-cloud-publish-modal-button plotly-cloud-btn-secondary",children:(0,S.jsxs)("span",{children:[(0,S.jsx)(X,{}),"\xA0View App"]})}):null,(0,S.jsxs)("button",{type:"button",onClick:a,className:"plotly-cloud-publish-modal-button plotly-cloud-btn-primary",disabled:r||D,children:[r?(0,S.jsx)(io,{size:12}):null,v]})]})]})},fo=wa;var w=e(h()),lo="cloud",La=()=>{let{popup:o,setPopup:a}=window.dash_component_api.devtool.useDevtool(),s=window.dash_component_api.devtool.useDevtoolMenuButtonClassName(lo),[r,n]=(0,t.useState)(""),[L,c]=(0,t.useState)("initialize"),[R,x]=(0,t.useState)(!1),[N,U]=(0,t.useState)(""),[B,T]=(0,t.useState)(!1),[v,D]=(0,t.useState)(!1),[go,Jo]=(0,t.useState)(""),[Ko,So]=(0,t.useState)(""),[ho,Co]=(0,t.useState)(""),[mo,H]=(0,t.useState)("unknown"),[G,q]=(0,t.useState)(-1),[Qo,jo]=(0,t.useState)(1),O=(0,t.useRef)(""),y=(0,t.useRef)(""),P=(0,t.useMemo)(()=>No("/"),[]),W=(0,t.useMemo)(()=>o===lo,[o]),po=()=>{a("")},Yo=()=>{a(o===lo?"":lo)},wo=()=>{P.logout().then(()=>{c("initialize")})},ba=(0,t.useMemo)(()=>W?"plotly-cloud-publish-container dash-debug-menu__button dash-debug-menu__button--selected":"plotly-cloud-publish-container dash-debug-menu__button",[W]),Lo=()=>{x(!0),P.authenticate().then(i=>{i.error?n(i.error):(c("auth_poll"),U(i.result.user_code),O.current=i.result.device_code,P.wait_auth().then(()=>{window.open(i.result.verification_uri_complete,"_blank"),q(setTimeout(()=>{P.auth_poll({device_code:O.current}).then(Ao)},8e3))}))})},Ao=i=>{if(i.error)n(i.error);else{if(i.result.success){O.current="",y.current?(H("unknown"),c("update_app"),P.status({app_id:y.current}).then(V=>{H(V.result.status)})):c("enter_name");return}if(i.result.try_again){Lo();return}let A=Qo||1;i.result.delay&&(A=i.result.delay,jo(A)),q(setTimeout(()=>{P.auth_poll({device_code:O.current}).then(Ao)},1e3+A*1e3))}},$o=()=>{setTimeout(Lo,2e3)};(0,t.useEffect)(()=>{L==="initialize"&&P.initialize().then(i=>{let{result:A,error:V}=i;V?n(V):(Jo(A.app_path),So(A.app_name),H(A.status),Co(A.app_url),A.app_id&&(y.current=A.app_id),A?.authenticated?A.status==="new"?c("enter_name"):c("update_app"):c("sign_in"))})},[L,W]);let bo=i=>{if(i.error){n(i.error);return}H(i.result.status),i.result.status==="RUNNING"?(T(!1),D(!0),c("update_app")):["BUILDING","STARTING"].includes(i.result.status)?q(setTimeout(()=>{P.status({app_id:y.current}).then(bo)},4e3)):(T(!1),c("update_app"))},Po=i=>{if(i.error){n(i.error);return}c("status_poll"),y.current=i.result.app_id,Co(i.result.app_url),H("BUILDING"),G>0&&clearTimeout(G),q(setTimeout(()=>{P.status({app_id:y.current}).then(bo)},2500))},oa=i=>{So(i),T(!0),D(!1),H("BUILDING"),P.publish({app_path:go,app_name:i}).then(Po)},ko=()=>{T(!0),D(!0),H("BUILDING"),P.publish({app_id:y.current,app_path:go}).then(Po)};(0,t.useEffect)(()=>()=>{G&&clearTimeout(G)});let To=()=>{window.open(`https://cloud.plotly.com/app/${y.current}/settings`,"_blank")};return(0,w.jsxs)(w.Fragment,{children:[(0,w.jsxs)("button",{className:s,onClick:Yo,children:[(0,w.jsx)(to,{status:mo,isButtonIcon:!0}),"\xA0Plotly Cloud"]}),W?(0,w.jsx)(Mo,{title:"Plotly Cloud",onClose:po,children:r||(()=>{switch(L){case"authenticate":case"auth_poll":case"sign_in":return(0,w.jsx)(xo,{onSignIn:$o,waiting:R,userCode:N});case"enter_name":return(0,w.jsx)(vo,{onPublish:oa,onCancel:po,initialAppName:Ko});case"update_app":return(0,w.jsx)(fo,{onPublish:ko,status:mo,isUpdate:!0,onCancel:To,appUrl:ho,onLogout:wo});case"status_poll":case"publish":return(0,w.jsx)(fo,{publishing:B,onPublish:ko,status:mo,onCancel:B?To:po,isUpdate:v,appUrl:ho,onLogout:wo});default:return(0,w.jsx)(w.Fragment,{})}})()},"publish-modal"):null]})},uo=La;typeof window<"u"&&(window.plotly_cloud_publish_component={PlotlyCloudPublishComponent:uo});return ta(Aa);})();
|
|
3
|
+
/*! Bundled license information:
|
|
4
|
+
|
|
5
|
+
react/cjs/react-jsx-runtime.production.min.js:
|
|
6
|
+
(**
|
|
7
|
+
* @license React
|
|
8
|
+
* react-jsx-runtime.production.min.js
|
|
9
|
+
*
|
|
10
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
11
|
+
*
|
|
12
|
+
* This source code is licensed under the MIT license found in the
|
|
13
|
+
* LICENSE file in the root directory of this source tree.
|
|
14
|
+
*)
|
|
15
|
+
*/
|
|
@@ -4,12 +4,12 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "plotly-cloud"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.0rc3"
|
|
8
8
|
description = "CLI for interacting with Plotly Cloud to deploy Dash apps"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
11
11
|
dependencies = [
|
|
12
|
-
"httpx>=0.24.0",
|
|
12
|
+
"httpx>=0.24.0,<1.0.0",
|
|
13
13
|
"dash>=2.0.0",
|
|
14
14
|
"rich>=10.0.0",
|
|
15
15
|
"rich-argparse>=1.7.1",
|
|
@@ -21,6 +21,8 @@ dependencies = [
|
|
|
21
21
|
[project.scripts]
|
|
22
22
|
plotly = "plotly_cloud.cli:main"
|
|
23
23
|
|
|
24
|
+
[project.entry-points.dash_hooks]
|
|
25
|
+
plotly_cloud_devtools = "plotly_cloud._devtool_hooks"
|
|
24
26
|
|
|
25
27
|
[tool.ruff]
|
|
26
28
|
line-length = 120
|
|
@@ -35,6 +37,8 @@ ignore-vcs = true
|
|
|
35
37
|
include = [
|
|
36
38
|
"plotly_cloud/**/*.py",
|
|
37
39
|
"plotly_cloud/cloud-env.toml",
|
|
40
|
+
"plotly_cloud/cloud_devtools.js",
|
|
41
|
+
"plotly_cloud/cloud_devtools.css",
|
|
38
42
|
]
|
|
39
43
|
|
|
40
44
|
[tool.hatch.build.targets.wheel]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|