Compare commits

...

No commits in common. "master" and "main" have entirely different histories.
master ... main

503 changed files with 35738 additions and 1 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.DS_Store
.ipynb_checkpoints
*.ampln
*.ipynb
.jupyter_ystore.db

160
BUILDING.md Normal file
View File

@ -0,0 +1,160 @@
# Building Amphi from Source
This document explains how to build Amphi from source code. Amphi consists of two main components:
1. `jupyterlab-amphi`: The core JupyterLab extension containing the main application logic
2. `amphi-etl`: The full Amphi ETL application that builds upon the core extension
## 👉 Prerequisites 👈
Python must be installed on your machine.
Before starting the build process, we strongly recommend setting up a Python virtual environment. This helps avoid conflicts between Python packages and ensures a clean installation. You can create one using either `venv` or `conda`:
### Creating a Virtual Environment
Using venv:
#### On Windows
```bash
python -m venv venv
.\venv\Scripts\activate
```
another example
```bash
python -m venv C:\Users\yourusername\building_amphi
cd C:\Users\yourusername\building_amphi
Scripts\activate
```
on cmd, you must see the name of your virtual environment on the left.
#### On macOS/Linux
```bash
python3 -m venv venv
source venv/bin/activate
```
Using conda:
```bash
# Create a new environment
conda create -n amphi python=3.x
conda activate amphi
```
Keep this virtual environment active throughout the entire build process.
## 👷 Building jupyterlab-amphi 👷
The first step is to build the core JupyterLab extension.
1. Navigate to the jupyterlab-amphi directory: (here the cd.. is because you have to go back in the folder hierarchy)
```bash
cd ..
cd jupyterlab-amphi
```
2. Install and build the extension:
**On macOS/Linux:**
```bash
pip install jupyterlab
jlpm install
jlpm run build
python3 -m pip install .
```
**On Windows:**
```bash
pip install jupyterlab
jlpm install
jlpm run build
python -m pip install .
```
check that the extension is really installed with
```bash
python -m jupyter labextension list
```
3. To test the extension in JupyterLab:
These commands will launch jupyterlab with the extension. Please note you shouldn't get the Amphi interface here. It is highly recommanded to clear your browser cache before this step.
**On macOS/Linux:**
```bash
jupyter lab --notebook-dir=/path/to/your/workspace
```
**On Windows:**
```bash
jupyter lab --notebook-dir=C:\path\to\your\workspace
```
Replace `/path/to/your/workspace` or `C:\path\to\your\workspace` with your desired workspace directory (i.e. the directory where are your pipelines, not your building or installation directory).
Note: You can add `--ContentManager.allow_hidden=True` to the launch command if you want to show hidden files in the file browser.
to interrupt , close your browser tab and ctrl+c on cmd
## 👷 Building amphi-etl 👷
After successfully building `jupyterlab-amphi`, you can proceed with building the full Amphi ETL application.
1. Navigate to the amphi-etl directory:
```bash
cd ../amphi-etl
```
2. Modify requirements.txt to use the local jupyterlab-amphi build (save a copy somewhere):
- Open `requirements.txt`
- Find the line containing `jupyterlab-amphi==X.X.X`
- Replace it with `../jupyterlab-amphi`
3. Install the requirements:
```bash
python -m pip install -r requirements.txt
```
4. Launch Amphi ETL:
```bash
jupyter lab --notebook-dir=/path/to/your/workspace
```
(Use appropriate path format for Windows as shown above)
if ok, don't forget to replace the requirements.txt with the save you made before going further with git.
## 👓 Component Overview 👓
- **jupyterlab-amphi**: This is the core extension that contains the main application logic. It can be run independently within JupyterLab for development and testing purposes.
- **amphi-etl**: This is the complete Amphi ETL application. It incorporates the `jupyterlab-amphi` extension and adds Amphi's custom theme, styling, and additional features to create a standalone application experience.
## 🐛 Troubleshooting 🐛
If you encounter any issues:
1. Ensure your virtual environment is activated
2. Verify all prerequisites are installed correctly
3. Check that paths in commands match your system's directory structure
4. Make sure you're using compatible versions of Python and JupyterLab
## 🗈 Notes 🗈
- Always use the virtual environment when installing Python packages to maintain a clean development environment
- The build process must be completed in order: first jupyterlab-amphi, then amphi-etl
- if you use several Python releases (like 3.12 & 3.13), be sure that you're using a supported release when building and that your virtual environment is built with the same version. The easiest way is to set this version as the default. You can check with python -V before creating the virtual environment and inside the virtual environment. You can also check you're using Python from the virtual environment with the where python command (Windows) or which command (Macos/linux). The first result should be in your virtual environement.
- virtual environments are not totally isolated and, depending of your environment variables, you may have a fallback mechanism, meaning that when not finding a package in your virtual environment, it will take it from the system, causing either errors or false positive during building process.
## 📖 Additional Resources 📖
For more detailed information about:
- JupyterLab extensions: [JupyterLab Documentation](https://jupyterlab.readthedocs.io/)
- Python virtual environments: [Python venv documentation](https://docs.python.org/3/library/venv.html)
- Conda environments: [Conda documentation](https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html)
## ✚ Adding a new component ✚
1. a component is stored as a .tsx file in the amphi-etl\jupyterlab-amphi\packages\pipeline-components-core\src\components repository, within a sub-folder related to its category.
Note there is a amphi-etl\jupyterlab-amphi\packages\pipeline-components-local for components that are not packaged with amphi for snowflake (Snowpark pandas).
2. component is mainly composed of two parts : the form and the code generator. you can have some form examples in developer\FormExample.tsx
3. component must be registered in two indexes files:
amphi-etl\jupyterlab-amphi\packages\pipeline-components-core\src\index.ts
amphi-etl\jupyterlab-amphi\packages\pipeline-components-core\src\components\index.ts
4. icons are stored in amphi-etl\jupyterlab-amphi\packages\pipeline-components-core\style\icons\
it must me registered in amphi-etl\jupyterlab-amphi\packages\pipeline-components-core\src\icon.ts and the icon is a svg square of 24.
5. Component categories are created on the fly, with the super{} function, you dont need to create a category.

2
CHANGELOG.md Normal file
View File

@ -0,0 +1,2 @@
# Changelog

35
LICENSE Normal file
View File

@ -0,0 +1,35 @@
Elastic License 2.0 \(ELv2\)
**Acceptance** By using the software, you agree to all of the terms and conditions below.
**Copyright License** The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations and conditions below
**Limitations** You may not provide the software to third parties as a hosted or managed service, where the service provides users with access to any substantial set of the features or functionality of the software.
You may not move, change, disable, or circumvent the license key functionality in the software, and you may not remove or obscure any functionality in the software that is protected by the license key.
You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensors trademarks is subject to applicable law.
**Patents** The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
**Notices** You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms.
If you modify the software, you must include in any modified copies of the software prominent notices stating that you have modified the software.
**No Other Rights** These terms do not imply any licenses other than those expressly granted in these terms.
**Termination** If you use the software in violation of these terms, such use is not licensed, and your licenses will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your licenses will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your licenses to terminate automatically and permanently.
**No Liability** As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.
**Definitions** The _licensor_ is the entity offering these terms, and the _software_ is the software the licensor makes available under these terms, including any portion of it.
_you_ refers to the individual or entity agreeing to these terms.
_your company_ is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. _control_ means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
_your licenses_ are all the licenses granted to you for the software under these terms.
_use_ means anything you do with the software requiring one of your licenses.
_trademark_ means trademarks, service marks, and similar rights.

157
README.md
View File

@ -1,2 +1,157 @@
# amphi
<div align="center">
<img height="60" src="https://amphi.ai/icons/amphi_logo_paths.svg">
<p align="center">
Visual Data Transformation Powered by Python
<br/><br/>
Designed for data preparation, reporting, and ETL.
</p>
<br/>
<p align="center">
<a href="https://github.com/amphi-ai/amphi-etl/stargazers" target="_blank">
<img src="https://img.shields.io/github/stars/amphi-ai/amphi-etl?style=social&label=Star&maxAge=2592000" alt="Test">
</a>
<a href="https://join.slack.com/t/amphi-ai/shared_invite/zt-2ci2ptvoy-FENw8AW4ISDXUmz8wcd3bw" target="_blank">
<img src="https://img.shields.io/badge/slack-join-white.svg?logo=slack" alt="Slack">
</a>
<a href="https://github.com/amphi-ai/amphi-etl/blob/main/LICENSE" target="_blank">
<img src="https://img.shields.io/static/v1?label=license&message=ELv2&color=white" alt="License">
</a>
<a href="https://badge.fury.io/py/amphi-etl"><img src="https://badge.fury.io/py/amphi-etl.svg" alt="PyPI version"></a>
<a href="https://pepy.tech/projects/amphi-etl"><img src="https://static.pepy.tech/badge/amphi-etl" alt="PyPI Downloads"></a>
</p>
![amphi-github-banner](https://github.com/user-attachments/assets/e13ac7e9-4c6f-47f6-b48e-f62e098cef82)
English · [Try the demo](https://demo.amphi.ai) · [Report Bug](https://github.com/amphi-ai/amphi-etl/issues) · [Request Feature](https://github.com/amphi-ai/amphi-etl/issues)
</div>
<details>
<summary><kbd>Table of contents</kbd></summary>
#### TOC
- [📦 Installation](#-installation)
- [🔨 Usage](#-usage)
- [✨ Features](#-features)
- [🤝 Contributing](#-contributing)
- [🛣️ Ecosystem](#-ecosystem)
####
</details>
## 📦 Installation & Update
Amphi is available as both a standalone application or as a JupyterLab extension.
| Amphi ETL (standalone) | Amphi for JupyterLab (extension) |
|------------------------|----------------------|
| ![amphi-etl-home-page](https://github.com/user-attachments/assets/3a37e271-7c8d-495a-9caf-2087804305ef) | ![amphi-for-jupyterlab-homepage2](https://github.com/user-attachments/assets/52abe431-e4c3-4cfc-8ed1-71ab24eaabdf) |
| ```pip install amphi-etl``` | ```pip install jupyterlab-amphi``` |
| ```pip install --upgrade amphi-etl``` | ```pip install --upgrade jupyterlab-amphi``` |
<br/>
> \[!NOTE]
>
> If you prefer to install Amphi's **Jupyterlab extension** through the extension manager, make sure to install `jupyerlab-amphi` package
<br/>
## 🔨 Usage
To start Amphi ETL (standalone), simply run:
```bash
amphi start
```
Use the following parameters to specify your:
- workspace (where you can access files and create pipelines on your system),
- IP address to expose
- port to use
### Deploy on your local machine
```bash
amphi start -w /your/workspace/path
```
### Deploy on a server
For deploying on a server, you need to specify `-i 0.0.0.0` to expose Amphi and access it through the internet. Optionaly specify a different port.
```bash
amphi start -w /your/workspace/path -i 0.0.0.0 -p 8888
```
- 📚 [Documentation](https://docs.amphi.ai)
- 🚀 [Getting Started](https://docs.amphi.ai/getting-started/installation)
<br/>
To update Amphi ETL run the following:
```bash
pip install --upgrade amphi-etl
```
## ✨ Features
> \[!NOTE]
>
> Amphi focuses on data transformation for data preparation, reporting and ETL. It aims to empower data analysts, scientists and data engineers to easily develop pipelines with an intuitive low-code interface while generating Python code you can deploy anywhere.
**Data Transformation solution for the AI age:**
**Modern ETL for the AI age:**
- 🧑‍💻 **Visual Interface / Low-code**: Accelerate data pipeline development and reduce maintenance time.
- 🐍 **Python-code Generation**: Generate native Python code leveraging common libraries such as [pandas](https://github.com/pandas-dev/pandas), [DuckDB](https://github.com/duckdb/duckdb) that you can run anywhere.
- 🔒 **Private and Secure**: Self-host Amphi on your laptop or in the cloud for complete privacy and security over your data.
![generate-python-code-amphi](https://github.com/user-attachments/assets/67410947-caea-45b4-a8fc-4ceb7bb3dbce)
<br/>
<!--
## 👀 Showcase
TBA
<br/>
-->
## 🤝 Contributing
- **Use and Innovate**: Try Amphi and share your use case with us. Your real-world usage and feedback help us improve our product.
- **Voice Your Insights**: Encounter a glitch? Have a query? Share them by submitting [issues](https://github.com/amphi-ai/amphi-etl/issues) and help us enhance the user experience.
- **Shape the Future**: Have code enhancements or feature ideas? We invite you to propose [pull requests](https://github.com/amphi-ai/amphi-etl/pulls) and contribute directly.
Every contribution, big or small, is celebrated. Join us in our mission to refine and elevate the world of ETL for data and AI. 😃
<br/>
## 📡 Telemetry
Amphi collects **anonymous telemetry data** to help us understand users and their use-cases better to improve the product. You can of course **opt out** in the settings and disable any telemetry data collection.
<br/>
## 🛣️ Ecosystem
Amphi is available as an extension for Jupyterlab, and Amphi ETL is based on Jupyterlab. Therefore Jupyterlab extensions can be installed on Amphi ETL.
- **[Jupyterlab](https://github.com/jupyterlab/jupyterlab)** - JupyterLab computational environment.
- **[jupyterlab-git](https://github.com/jupyterlab/jupyterlab-git)** - A Git extension for JupyterLab.
---
#### 📝 License
Copyright © 2024 - present [Amphi Labs](https://amphi.ai). <br/> This project is [ELv2](./LICENSE) licensed.

94
USING_GIT_AND_GITHUB.md Normal file
View File

@ -0,0 +1,94 @@
# Using Git & Github
This document explains how to use Git and Github when contributing to Amphi Etl
## 👉 Prerequisites 👈
1. You must install the CLI (Command Line Interface) of Git on your machine.
https://git-scm.com/download/linux
https://git-scm.com/download/win
https://git-scm.com/download/mac
you can test it has been installed with the following command that should return the Git CLI version
```bash
git -v
```
2. You must have a GitHub account.
## 👷 The full dev workflow 👷
1. Using your web browser, go to Amphi ETL GitHub page
https://github.com/amphi-ai/amphi-etl
2. On the top right, click on "fork/+create a new fork". It's a necessary step since you don't have the permissions to write directly in the Amphi ETL GitHub repo.
3. On your own account, you must see an amphi repository.
e.g. : https://github.com/{your_github_username}/amphi-etl
4. Now, let's copy the repository on your machine
Go to the repository where you want to store the repository and using your cmd :
```bash
cd C:\Users\{yourusername}\amphi_dev
```
The action of copying the repository is called "cloning". On your Amphi ETL GitHub Repository, on top right, click "Code", "local" and copy the adress (https://github.com/{your_github_username}/amphi-etl.git ). The clone command is
```bash
git clone https://github.com/{your_github_username}/amphi-etl.git
```
Check that the repository is created on your machine.
Go to the amphi-etl repo on your machine :
```bash
cd amphi-etl
```
Check the git status
```bash
git status
```
5. Do your modifications and build the projet following BUILDING.md
6. Once the project is built and you're good, you will have to commit (i.e. validate your change in the Git meaning).
go the top of folder (id amphi-etl, not amphi-etl-amphi-etl with the cd command)
For that use the command (m is for the message)
```bash
git commit -m "Comment on your commit"
```
You can also do that for only 1,2,... specified files like
```bash
git commit -m "Pushing Only Single file to git" config/local.js
```
In case you're adding a file or modifying a file that wasn't tracked by git, you have to add it with the following cmd
```bash
git add {file_path}
```
e.g. :
```bash
git add jupyterlab-amphi/packages/pipeline-components-core/src/icons.ts
```
and then commit
```bash
git commit -m "Comment on your commit after adding file"
```
At this step, you have validated your modifications on your repository.
7. Now, let's update your GitHub repository
```bash
git push
```
8. Using your web browser, go to https://github.com/{your_github_username}/amphi-etl
You must see the changes
9. On the top right, click on Contribute, Open Pull request.
On the interface, explain the change.
10. If your change is approved, you will receive a notification.

61
amphi-etl/.gitignore vendored Normal file
View File

@ -0,0 +1,61 @@
MANIFEST
amphi/__pycache__
amphi/theme-light
amphi/ui-component
build
dist
lib
*_env
*_venv
*_venv3
node_modules
.cache
*.py[co]
.pytest_cache
__pycache__
*.egg-info
*~
*.bak
.ipynb_checkpoints
.DS_Store
\#*#
.#*
*.swp
*.map
coverage/
tests/**/coverage
tests/**/.cache-loader
docs/_build
docs/api
docs/source/_build
lerna-debug.log
yarn-error.log
yarn.lock
junit.xml
*.tsbuildinfo
.yarn/
# jetbrains IDE stuff
*.iml
.idea/
# ms IDE stuff
*.code-workspace
.history
.vscode
# dev
build.sh
start.sh
run.sh
install.sh
# Amphi
untitled*
testing*

1
amphi-etl/.yarnrc.yml Normal file
View File

@ -0,0 +1 @@
nodeLinker: node-modules

49
amphi-etl/Dockerfile Normal file
View File

@ -0,0 +1,49 @@
# Use the regular Python base image
FROM python:3.11-slim
# Switch to root user to install dependencies
USER root
# Create a work directory and set permissions
RUN mkdir -p /home/amphi \
&& chown -R 1000:100 /home/amphi
# Add amphi user
RUN useradd -m -s /bin/bash -N -u 1000 amphi
# Install Node.js and npm
RUN apt-get update && apt-get install -y nodejs npm && rm -rf /var/lib/apt/lists/*
# Set environment variables for Snowflake
ENV JUPYTER_ENABLE_LAB=yes \
NB_UID=1000 \
NB_GID=100
# Add .local/bin to PATH to avoid warnings
ENV PATH="/home/amphi/.local/bin:$PATH"
# Set the working directory
WORKDIR /home/amphi
# Ensure the user has full access to this directory
RUN chown -R 1000:100 /home/amphi
RUN python3 -m pip install numpy pandas==2.2.1 python-dotenv
# Install required Python packages from requirements.txt
RUN python3 -m pip install jupyterlab==4.2.5
RUN python3 -m pip install jupyterlab-amphi==0.8.1
# Provide theme and ui-component
COPY amphi/theme-light /usr/local/share/jupyter/labextensions/@amphi/theme-light
COPY amphi/ui-component /usr/local/share/jupyter/labextensions/@amphi/ui-component
# Custom Jupyterlab config files
COPY config/labconfig/page_config.json /etc/jupyter/labconfig/page_config.json
COPY config/settings/overrides.json /usr/local/share/jupyter/lab/settings/overrides.json
# Switch to amphi user
USER amphi
# Set the default command to start JupyterLab in a specific folder
ENTRYPOINT ["jupyter", "lab", "--allow-root", "--ip=0.0.0.0", "--port=8888", "--no-browser", "--NotebookApp.token=''", "--NotebookApp.password=''", "--notebook-dir=/home/amphi/data", "--ContentManager.allow_hidden=True"]

View File

@ -0,0 +1,51 @@
# Use the Jupyter Docker Stacks base image
FROM quay.io/jupyter/base-notebook:x86_64-python-3.11.10
LABEL maintainer="Amphi Labs <tgourdel@amphi.ai>"
# Switch to root user to install dependencies
USER root
# Create a work directory and set permissions
RUN mkdir -p /home/amphi \
&& chown -R $NB_UID:$NB_GID /home/amphi
# Add .local/bin to PATH to avoid warnings
ENV PATH="/home/amphi/.local/bin:$PATH"
# Set environment variables
ENV JUPYTER_ENABLE_LAB=yes
# Set the working directory
WORKDIR /home/amphi
# Ensure the user has full access to this directory
RUN chown -R $NB_UID:$NB_GID /home/amphi
# Install required Python packages
# Consolidate installations into a single RUN command
RUN apt-get update && apt-get install -y --no-install-recommends \
&& python3 -m pip install --upgrade pip setuptools wheel \
&& python3 -m pip install --no-cache-dir pandas==2.2.1 numpy \
jupyterlab==4.2.5 jupyterlab-amphi==0.8.23 \
sqlalchemy==2.0.4 python-dotenv \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# Clean up caches to reduce image size
RUN apt-get autoremove -y && apt-get clean \
&& rm -rf /var/lib/apt/lists/* /root/.cache /home/amphi/.cache
# Copy additional extensions and configurations
COPY amphi/theme-light /usr/local/share/jupyter/labextensions/@amphi/theme-light
COPY amphi/ui-component /usr/local/share/jupyter/labextensions/@amphi/ui-component
COPY config/labconfig/page_config.json /etc/jupyter/labconfig/page_config.json
COPY config/settings/overrides.json /opt/conda/share/jupyter/lab/settings/overrides.json
# Switch back to the default user
USER $NB_UID
# Set the default command to start JupyterLab
ENTRYPOINT ["jupyter", "lab", "--ip=0.0.0.0", "--port=8888", "--no-browser", "--allow-root", \
"--NotebookApp.token=''", "--NotebookApp.password=''", "--notebook-dir=/home/amphi/data", \
"--ContentManager.allow_hidden=True"]

35
amphi-etl/LICENSE Normal file
View File

@ -0,0 +1,35 @@
Elastic License 2.0 \(ELv2\)
**Acceptance** By using the software, you agree to all of the terms and conditions below.
**Copyright License** The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations and conditions below
**Limitations** You may not provide the software to third parties as a hosted or managed service, where the service provides users with access to any substantial set of the features or functionality of the software.
You may not move, change, disable, or circumvent the license key functionality in the software, and you may not remove or obscure any functionality in the software that is protected by the license key.
You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensors trademarks is subject to applicable law.
**Patents** The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
**Notices** You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms.
If you modify the software, you must include in any modified copies of the software prominent notices stating that you have modified the software.
**No Other Rights** These terms do not imply any licenses other than those expressly granted in these terms.
**Termination** If you use the software in violation of these terms, such use is not licensed, and your licenses will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your licenses will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your licenses to terminate automatically and permanently.
**No Liability** As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.
**Definitions** The _licensor_ is the entity offering these terms, and the _software_ is the software the licensor makes available under these terms, including any portion of it.
_you_ refers to the individual or entity agreeing to these terms.
_your company_ is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. _control_ means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
_your licenses_ are all the licenses granted to you for the software under these terms.
_use_ means anything you do with the software requiring one of your licenses.
_trademark_ means trademarks, service marks, and similar rights.

28
amphi-etl/MANIFEST.in Normal file
View File

@ -0,0 +1,28 @@
include LICENSE
include *.md
include pyproject.toml
include package.json
include install.json
include ts*.json
include yarn.lock
include share/jupyter/labextensions/@amphi/theme-light/*
include share/jupyter/labextensions/@amphi/ui-component/*
recursive-include share/jupyter/labextensions/@amphi/theme-light *
recursive-include share/jupyter/labextensions/@amphi/ui-component *
graft amphi/*
# Javascript files
graft packages/**
graft style
prune **/node_modules
prune lib
prune binder
# Patterns to exclude from any directory
global-exclude *~
global-exclude *.pyc
global-exclude *.pyo
global-exclude .git
global-exclude .ipynb_checkpoints

3
amphi-etl/README.md Normal file
View File

@ -0,0 +1,3 @@
# Amphi ETL
TODO

View File

@ -0,0 +1 @@
# amphi/__init__.py

View File

@ -0,0 +1,4 @@
# This file is auto-generated by Hatchling. As such, do not:
# - modify
# - track in version control e.g. be sure to add to .gitignore
__version__ = VERSION = '0.8.23'

35
amphi-etl/amphi/main.py Normal file
View File

@ -0,0 +1,35 @@
import subprocess
import sys
import argparse
import os
def main():
parser = argparse.ArgumentParser(description='Amphi ETL Command Line Interface')
parser.add_argument('command', choices=['start'], help='Command to start Amphi ETL')
parser.add_argument('-w', '--workspace', default='.', help='Workspace directory for Amphi ETL')
parser.add_argument('-p', '--port', type=int, default=8888, help='Port for Amphi ETL')
parser.add_argument('-i', '--ip', default='localhost', help='IP address for Amphi ETL')
args = parser.parse_args()
# Debugging logs
print(f"Received command: {args.command}")
print(f"Workspace directory: {args.workspace}")
print(f"Port: {args.port}")
print(f"IP: {args.ip}")
print(f"Python executable: {sys.executable}")
print(f"Environment PATH: {os.environ.get('PATH')}")
if args.command == 'start':
jupyter_command = [
sys.executable, '-m', 'jupyter', 'lab',
f'--notebook-dir={args.workspace}', f'--port={args.port}', f'--ip={args.ip}', '--ContentManager.allow_hidden=true'
]
print(f"Running JupyterLab command: {' '.join(jupyter_command)}")
try:
subprocess.check_call(jupyter_command)
except subprocess.CalledProcessError as e:
print(f"Failed to start Amphi: {e}")
if __name__ == '__main__':
main()

View File

@ -0,0 +1,25 @@
{
"disabledExtensions": {
"@jupyterlab/notebook-extension": true,
"@jupyterlab/launcher-extension": true,
"@jupyterlab/running-extension": true,
"@jupyterlab/toc-extension": true,
"@jupyterlab/help-extension": true,
"@jupyterlab/debugger-extension": true,
"@jupyterlab/application-extension:property-inspector": true,
"@jupyterlab/inspector-extension": true,
"@jupyterlab/application-extension:about": true,
"@jupyterlab/theme-dark-extension": true,
"@jupyterlab/theme-light-extension": true,
"@jupyterlab/extensionmanager-extension": true,
"@jupyterlab/application-extension:logo": true,
"@jupyterlab/metadataform-extension:metadataforms": true,
"@jupyterlab/celltags-extension:plugin": true,
"@jupyterlab/tooltip-extension:notebooks": true,
"@jupyterlab/workspaces-extension:sidebar": true,
"@jupyterlab/apputils-extension:announcements": true,
"@jupyterlab/console-extension": true,
"@jupyterlab/theme-dark-high-contrast-extension": true,
"@jupyterlab/logconsole-extension:plugin": true
}
}

View File

@ -0,0 +1,117 @@
{
"@jupyterlab/apputils-extension:themes": {
"theme": "Amphi Light",
"theme-scrollbars": true
},
"@jupyterlab/statusbar-extension:plugin": {
"visible": false
},
"@jupyterlab/mainmenu-extension:plugin": {
"menus": [
{
"id": "jp-mainmenu-run",
"disabled": true
},
{
"id": "jp-mainmenu-kernel",
"disabled": true
},
{
"id": "jp-mainmenu-file",
"items": [
{
"type": "submenu",
"submenu": {
"id": "jp-mainmenu-file-new",
"items": [
{
"command": "pipeline-editor:create-new",
"rank": 1
},
{
"command": "fileeditor:create-new",
"disabled": true
},
{
"command": "fileeditor:create-new-markdown-file",
"disabled": true
}
]
}
},
{
"command": "filebrowser:open-path",
"disabled": true
},
{
"command": "filebrowser:open-path",
"disabled": true
},
{
"command": "docmanager:reload",
"disabled": true
},
{
"command": "docmanager:restore-checkpoint",
"disabled": true
},
{
"command": "apputils:print",
"disabled": true
}
]
},
{
"id": "jp-mainmenu-view",
"items": [
{
"command": "filebrowser:open-path",
"disabled": true
}
]
},
{
"id": "jp-mainmenu-tabs",
"disabled": true
},
{
"id": "jp-mainmenu-settings",
"items": [
{
"command": "application:about",
"disabled": true
},
{
"command": "help:jupyter-forum",
"disabled": true
},
{
"command": "help:licenses",
"disabled": true
}
]
},
{
"id": "jp-mainmenu-help",
"items": [
{
"command": "help:open",
"disabled": true
},
{
"command": "fileeditor:change-font-size",
"disabled": true
},
{
"command": "fileeditor:change-font-size",
"disabled": true
},
{
"command": "settingeditor:open",
"disabled": true
}
]
}
]
}
}

View File

@ -0,0 +1,60 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
ARG REGISTRY=quay.io
ARG OWNER=amphi
ARG BASE_CONTAINER=$REGISTRY/$OWNER/docker-stacks-foundation
FROM $BASE_CONTAINER
LABEL maintainer="Amphi Labs <hello@amphi.ai>"
# Fix: https://github.com/hadolint/hadolint/wiki/DL4006
# Fix: https://github.com/koalaman/shellcheck/wiki/SC3014
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
USER root
# Install all OS dependencies for the Server that starts
# but lacks all features (e.g., download as all possible file formats)
RUN apt-get update --yes && \
apt-get install --yes --no-install-recommends \
# - `run-one` - a wrapper script that runs no more
# than one unique instance of some command with a unique set of arguments,
# we use `run-one-constantly` to support the `RESTARTABLE` option
run-one && \
apt-get clean && rm -rf /var/lib/apt/lists/*
USER ${NB_UID}
# Install JupyterLab, Jupyter Notebook, JupyterHub and NBClassic
# Generate a Jupyter Server config
# Cleanup temporary files
# Correct permissions
# Do all this in a single RUN command to avoid duplicating all of the
# files across image layers when the permissions change
WORKDIR /tmp
RUN pip install amphi-etl
ENV JUPYTER_PORT=8888
EXPOSE $JUPYTER_PORT
# Configure container startup
CMD ["amphi start"]
# Copy local files as late as possible to avoid cache busting
COPY start-notebook.py start-notebook.sh start-singleuser.py start-singleuser.sh /usr/local/bin/
COPY jupyter_server_config.py docker_healthcheck.py /etc/jupyter/
# Fix permissions on /etc/jupyter as root
USER root
RUN fix-permissions /etc/jupyter/
# HEALTHCHECK documentation: https://docs.docker.com/engine/reference/builder/#healthcheck
# This healtcheck works well for `lab`, `notebook`, `nbclassic`, `server`, and `retro` jupyter commands
# https://github.com/jupyter/docker-stacks/issues/915#issuecomment-1068528799
HEALTHCHECK --interval=3s --timeout=1s --start-period=3s --retries=3 \
CMD /etc/jupyter/docker_healthcheck.py || exit 1
# Switch back to jovyan to avoid accidental container runs as root
USER ${NB_UID}
WORKDIR "${HOME}"

4
amphi-etl/lerna.json Normal file
View File

@ -0,0 +1,4 @@
{
"npmClient": "yarn",
"version": "0.8.23"
}

1
amphi-etl/output.json Normal file

File diff suppressed because one or more lines are too long

80
amphi-etl/package.json Normal file
View File

@ -0,0 +1,80 @@
{
"name": "@amphi/amphi-etl",
"version": "0.8.23",
"keywords": [
"amphi",
"etl",
"micro etl",
"jupyterlab-extension",
"data integration",
"data pipelines"
],
"homepage": "https://amphi.ai",
"bugs": {
"url": "https://github.com/amphi-ai/amphi-etl/issues"
},
"license": "Elastic License 2.0",
"author": {
"name": "Thibaut Gourdel",
"email": "tgourdel@amphi.ai"
},
"repository": {
"type": "git",
"url": "https://github.com/amphi-ai/amphi-etl.git"
},
"workspaces": {
"packages": [
"packages/theme-light",
"packages/ui-component"
]
},
"scripts": {
"build:prod": "lerna run --sort --stream build:prod",
"build:py": "lerna run --stream build:py",
"build": "lerna run --sort --stream build",
"bump:js:version": "lerna version --no-push --force-publish --no-git-tag-version --yes",
"clean:all": "jlpm clean:build && jlpm clean:dist && lerna run --stream clean:all && jlpm clean:cache",
"clean:build": "rimraf build",
"clean:cache": "rimraf node_modules/.cache build/.lite-cache examples/.jupyterlite.doit.db",
"clean:dist": "rimraf dist",
"clean": "lerna run --stream clean",
"deduplicate": "yarn-berry-deduplicate -s fewer --fail",
"dist:npm": "lerna run --stream dist",
"dist:pypi": "pyproject-build .",
"dist": "jlpm dist:pypi && jlpm dist:npm",
"docs:lite": "cd examples && jupyter lite build",
"docs:sphinx": "sphinx-build -W -b html docs build/docs",
"docs": "jlpm docs:lite && jlpm docs:sphinx",
"eslint:check": "eslint . --cache --cache-location=./build/.cache/eslint --ext .ts,.tsx",
"eslint": "jlpm eslint:check --fix",
"lint": "jlpm lint:js && jlpm lint:py",
"lint:check": "jlpm lint:js:check && jlpm lint:py:check",
"lint:js": "jlpm prettier && jlpm eslint",
"lint:js:check": "jlpm prettier:check && jlpm eslint:check",
"lint:py": "jlpm lint:py:black && jlpm lint:py:ruff --fix-only",
"lint:py:pip": "python -m pip check",
"lint:py:check": "jlpm lint:py:pip && jlpm lint:py:black --check && jlpm lint:py:ruff",
"prettier:base": "prettier \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md,.yml,.yaml}\"",
"prettier:check": "jlpm prettier:base --check",
"prettier": "jlpm prettier:base --write --list-different",
"quickstart": "npm run setup:py && jlpm && jlpm deduplicate && jlpm clean:all && jlpm lint && jlpm build:prod && jlpm dist && jlpm docs && jlpm test",
"setup:py": "python -m pip install -e \".[dev,lint,test,docs]\"",
"test:py": "pytest",
"test": "jlpm test:py"
},
"devDependencies": {
"@jupyterlab/builder": "^4.1.5",
"lerna": "^7.2.0",
"rimraf": "^5.0.1",
"typescript": "~5.2.2",
"yarn-berry-deduplicate": "^6.1.1"
},
"publishConfig": {
"access": "public"
},
"jupyterlab": {
"title": "Amphi",
"extension": true,
"outputDir": "./amphi"
}
}

View File

@ -0,0 +1,82 @@
{
"name": "@amphi/theme-light",
"version": "0.1.0",
"description": "A Amphi Light theme for JupyterLab",
"keywords": [
"jupyter",
"jupyterlab",
"jupyterlab-extension"
],
"homepage": "https://github.com/amphi-ai/amphi",
"bugs": {
"url": "https://github.com/amphi-ai/amphi/issues"
},
"license": "ELv2",
"author": {
"name": "Thibaut Gourdel",
"email": "tgourdel@amphi.ai"
},
"files": [
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
"style/**/*.{css,eot,gif,html,jpg,json,png,svg,woff2,ttf}"
],
"main": "lib/index.js",
"types": "lib/index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/amphi-ai/amphi.git"
},
"scripts": {
"build": "jlpm run build:lib && jlpm run build:labextension:dev",
"build:prod": "jlpm run build:lib && jlpm run build:labextension",
"build:labextension": "jupyter labextension build .",
"build:labextension:dev": "jupyter labextension build --development True .",
"build:lib": "tsc --build --verbose",
"clean": "jlpm run clean:lib",
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
"clean:labextension": "rimraf ../../amphi/theme-light",
"clean:all": "jlpm run clean:lib && jlpm run clean:labextension",
"eslint": "eslint . --ext .ts,.tsx --fix",
"eslint:check": "eslint . --ext .ts,.tsx",
"install:extension": "jupyter labextension develop --overwrite .",
"prepare": "jlpm run clean && jlpm run build:prod",
"watch": "run-p watch:src watch:labextension",
"watch:src": "tsc -w",
"watch:labextension": "jupyter labextension watch ."
},
"dependencies": {
"@jupyterlab/application": "^4.0.9",
"@jupyterlab/filebrowser": "^4.0.9",
"@jupyterlab/launcher": "^4.0.9",
"@jupyterlab/mainmenu": "^4.0.9",
"@jupyterlab/ui-components": "^4.0.9"
},
"resolutions": {
"@jupyterlab/rendermime-interfaces": "^4.0.9",
"@lumino/widgets": "^2.0.0",
"@types/react": "^18.2.7"
},
"devDependencies": {
"@jupyterlab/builder": "^4.0.9",
"@typescript-eslint/eslint-plugin": "^4.8.1",
"@typescript-eslint/parser": "^4.8.1",
"eslint": "^7.14.0",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react": "^7.18.3",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.1",
"reactflow": "11.7.2",
"rimraf": "^3.0.2",
"typescript": "~5.0.4",
"yarn-deduplicate": "^6.0.2"
},
"sideEffects": [
"style/*.css"
],
"jupyterlab": {
"extension": true,
"themePath": "style/index.css",
"outputDir": "../../amphi/theme-light"
}
}

View File

@ -0,0 +1,4 @@
declare module '*.svg' {
const value: string;
export default value;
}

View File

@ -0,0 +1,111 @@
import { LabIcon } from '@jupyterlab/ui-components';
import folderIconSvgStr from '../style/icons/folder-24.svg';
import saveIconSvgStr from '../style/icons/save-24.svg';
import terminalScreenIconSvgStr from '../style/icons/terminal-screen-24.svg';
import playIconSvgStr from '../style/icons/play-24.svg';
import fileSourceIconSvgStr from '../style/icons/file-source-24.svg';
import folderPlusIconSvgStr from '../style/icons/folder-plus-24.svg';
import uploadIconSvgStr from '../style/icons/upload-24.svg';
import reloadIconSvgStr from '../style/icons/reload-24.svg';
import fileIconSvgStr from '../style/icons/file-24.svg';
import fileCsvIconSvgStr from '../style/icons/file-csv-24.svg';
import filePdfIconSvgStr from '../style/icons/file-pdf-24.svg';
import fileExcelIconSvgStr from '../style/icons/file-excel-24.svg';
import fileParquetIconSvgStr from '../style/icons/file-parquet-24.svg';
import fileJsonIconSvgStr from '../style/icons/file-json-24.svg';
import fileNotebookIconSvgStr from '../style/icons/file-ipynb-24.svg';
import terminalIconSvgStr from '../style/icons/terminal-screen-24.svg';
import homeIconSvgStr from '../style/icons/home-24.svg';
import searchIconSvgStr from '../style/icons/search-24.svg';
export const terminalIcon = new LabIcon({
name: 'amphi:terminal-amphi-icon',
svgstr: terminalIconSvgStr
});
export const folderAmphiIcon = new LabIcon({
name: 'amphi:folder-icon',
svgstr: folderIconSvgStr
});
export const saveAmphiIcon = new LabIcon({
name: 'amphi:save-icon',
svgstr: saveIconSvgStr
});
export const terminalScreenAmphiIcon = new LabIcon({
name: 'amphi:terminal-screen-icon',
svgstr: terminalScreenIconSvgStr
});
export const playAmphiIcon = new LabIcon({
name: 'amphi:play-icon',
svgstr: playIconSvgStr
});
export const fileSourceAmphiIcon = new LabIcon({
name: 'amphi:file-source-icon',
svgstr: fileSourceIconSvgStr
});
export const folderPlusAmphiIcon = new LabIcon({
name: 'amphi:folder-plus-icon',
svgstr: folderPlusIconSvgStr
});
export const uploadAmphiIcon = new LabIcon({
name: 'amphi:upload-icon',
svgstr: uploadIconSvgStr
});
export const reloadAmphiIcon = new LabIcon({
name: 'amphi:reload-icon',
svgstr: reloadIconSvgStr
});
export const fileAmphiIcon = new LabIcon({
name: 'amphi:file-icon',
svgstr: fileIconSvgStr
});
export const fileCsvAmphiIcon = new LabIcon({
name: 'amphi:file-csv-icon',
svgstr: fileCsvIconSvgStr
});
export const filePdfAmphiIcon = new LabIcon({
name: 'amphi:file-pdf-icon',
svgstr: filePdfIconSvgStr
});
export const fileJsonAmphiIcon = new LabIcon({
name: 'amphi:file-json-icon',
svgstr: fileJsonIconSvgStr
});
export const fileExcelAmphiIcon = new LabIcon({
name: 'amphi:file-excel-icon',
svgstr: fileExcelIconSvgStr
});
export const fileParquetAmphiIcon = new LabIcon({
name: 'amphi:file-parquet-icon',
svgstr: fileParquetIconSvgStr
});
export const fileNotebookIcon = new LabIcon({
name: 'amphi:file-notebook-icon',
svgstr: fileNotebookIconSvgStr
});
export const homeAmphiIcon = new LabIcon({
name: 'amphi:home-icon',
svgstr: homeIconSvgStr
});
export const searchAmphiIcon = new LabIcon({
name: 'amphi:search-icon',
svgstr: searchIconSvgStr
});

View File

@ -0,0 +1,66 @@
import {
JupyterFrontEnd,
JupyterFrontEndPlugin
} from '@jupyterlab/application';
import { folderIcon, saveIcon, runIcon, newFolderIcon, fileUploadIcon, filterIcon, refreshIcon, codeIcon, fileIcon, pdfIcon, spreadsheetIcon, jsonIcon, notebookIcon, listIcon, homeIcon } from '@jupyterlab/ui-components';
import { folderAmphiIcon, searchAmphiIcon, saveAmphiIcon, playAmphiIcon, folderPlusAmphiIcon, uploadAmphiIcon, reloadAmphiIcon, fileSourceAmphiIcon, fileAmphiIcon, filePdfAmphiIcon, fileCsvAmphiIcon, fileJsonAmphiIcon, fileNotebookIcon, terminalIcon, homeAmphiIcon, fileParquetAmphiIcon, fileExcelAmphiIcon } from './icons'
import { IThemeManager } from '@jupyterlab/apputils';
/**
* Initialization data for the @amphi/theme-light extension.
*/
const extension: JupyterFrontEndPlugin<void> = {
id: '@amphi/theme-light',
requires: [IThemeManager],
autoStart: true,
activate: (app: JupyterFrontEnd, manager: IThemeManager) => {
const style = '@amphi/theme-light/index.css';
manager.register({
name: 'Amphi Light',
isLight: true,
themeScrollbars: false,
load: () => manager.loadCSS(style),
unload: () => Promise.resolve(undefined)
});
app.docRegistry.addFileType(
{
name: 'parquet',
displayName: 'parquet',
extensions: ['.parquet'],
icon: fileParquetAmphiIcon,
fileFormat: "base64",
}
);
app.docRegistry.addFileType(
{
name: 'excel',
displayName: 'Excel',
extensions: ['.xlsx', 'xls'],
icon: fileExcelAmphiIcon,
fileFormat: "base64",
}
);
folderIcon.svgstr = folderAmphiIcon.svgstr;
saveIcon.svgstr = saveAmphiIcon.svgstr;
runIcon.svgstr = playAmphiIcon.svgstr
newFolderIcon.svgstr = folderPlusAmphiIcon.svgstr;
fileUploadIcon.svgstr = uploadAmphiIcon.svgstr;
refreshIcon.svgstr = reloadAmphiIcon.svgstr;
codeIcon.svgstr = fileSourceAmphiIcon.svgstr;
fileIcon.svgstr = fileAmphiIcon.svgstr;
pdfIcon.svgstr = filePdfAmphiIcon.svgstr;
spreadsheetIcon.svgstr = fileCsvAmphiIcon.svgstr;
jsonIcon.svgstr = fileJsonAmphiIcon.svgstr;
notebookIcon.svgstr = fileNotebookIcon.svgstr;
listIcon.svgstr = terminalIcon.svgstr;
homeIcon.svgstr = homeAmphiIcon.svgstr;
filterIcon.svgstr = searchAmphiIcon.svgstr;
}
};
export default extension;

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M5.75 1A2.75 2.75 0 003 3.75v16.5A2.75 2.75 0 005.75 23h12.5A2.75 2.75 0 0021 20.25V8.664c0-.464-.184-.909-.513-1.237l-5.914-5.914A1.75 1.75 0 0013.336 1H5.75zM4.5 3.75c0-.69.56-1.25 1.25-1.25H13v5.75c0 .414.336.75.75.75h5.75v11.25c0 .69-.56 1.25-1.25 1.25H5.75c-.69 0-1.25-.56-1.25-1.25V3.75zM18.44 7.5L14.5 3.56V7.5h3.94z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 496 B

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
fill="none"
viewBox="0 0 24 24"
version="1.1"
id="svg2"
sodipodi:docname="file-csv-24.svg"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs2" />
<sodipodi:namedview
id="namedview2"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:zoom="8.0003289"
inkscape:cx="15.124378"
inkscape:cy="22.936557"
inkscape:window-width="2560"
inkscape:window-height="1412"
inkscape:window-x="1512"
inkscape:window-y="149"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<g
fill="currentColor"
id="g2">
<path
fill-rule="evenodd"
d="M5.75 1A2.75 2.75 0 003 3.75v16.5A2.75 2.75 0 005.75 23h12.5A2.75 2.75 0 0021 20.25V8.664c0-.464-.184-.909-.513-1.237l-5.914-5.914A1.75 1.75 0 0013.336 1H5.75zM4.5 3.75c0-.69.56-1.25 1.25-1.25H13v5.75c0 .414.336.75.75.75h5.75v11.25c0 .69-.56 1.25-1.25 1.25H5.75c-.69 0-1.25-.56-1.25-1.25V3.75zM18.44 7.5L14.5 3.56V7.5h3.94z"
clip-rule="evenodd"
id="path2" />
</g>
<text
xml:space="preserve"
style="font-size:48px;line-height:0;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';fill:#f9f9f9;stroke:#7d6ec2;stroke-width:0"
x="18.610168"
y="19.525423"
id="text2"><tspan
sodipodi:role="line"
id="tspan2"></tspan></text>
<text
xml:space="preserve"
style="font-size:6.04823px;line-height:0;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';fill:#008000;stroke:#7d6ec2;stroke-width:0"
x="5.5070834"
y="19.640993"
id="text3"
transform="scale(1.0124776,0.98767617)"><tspan
sodipodi:role="line"
id="tspan3"
x="5.5070834"
y="19.640993"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;fill:#008000;stroke-width:0">CSV</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
fill="none"
viewBox="0 0 24 24"
version="1.1"
id="svg2"
sodipodi:docname="file-excel-24.svg"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs2" />
<sodipodi:namedview
id="namedview2"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:zoom="8.0003289"
inkscape:cx="15.124378"
inkscape:cy="22.936557"
inkscape:window-width="1312"
inkscape:window-height="670"
inkscape:window-x="118"
inkscape:window-y="799"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<g
fill="currentColor"
id="g2">
<path
fill-rule="evenodd"
d="M 5.75,1 A 2.75,2.75 0 0 0 3,3.75 v 16.5 A 2.75,2.75 0 0 0 5.75,23 h 12.5 A 2.75,2.75 0 0 0 21,20.25 V 8.664 C 21,8.2 20.816,7.755 20.487,7.427 L 14.573,1.513 A 1.75,1.75 0 0 0 13.336,1 Z M 4.5,3.75 C 4.5,3.06 5.06,2.5 5.75,2.5 H 13 V 8.25 C 13,8.664 13.336,9 13.75,9 h 5.75 v 11.25 c 0,0.69 -0.56,1.25 -1.25,1.25 H 5.75 C 5.06,21.5 4.5,20.94 4.5,20.25 Z M 18.44,7.5 14.5,3.56 V 7.5 Z"
clip-rule="evenodd"
id="path2" />
</g>
<text
xml:space="preserve"
style="font-size:48px;line-height:0;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';fill:#f9f9f9;stroke:#7d6ec2;stroke-width:0"
x="18.610168"
y="19.525423"
id="text2"><tspan
sodipodi:role="line"
id="tspan2"></tspan></text>
<text
xml:space="preserve"
style="font-size:4.95567px;line-height:0;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';fill:#0f7a41;stroke:#7d6ec2;stroke-width:0;fill-opacity:1"
x="7.4485302"
y="19.389633"
id="text3"
transform="scale(0.99888384,1.0011174)"
inkscape:transform-center-x="-0.74996916"><tspan
sodipodi:role="line"
id="tspan3"
x="7.4485302"
y="19.389633"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;fill:#0f7a41;stroke-width:0;fill-opacity:1">XLS</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
fill="none"
viewBox="0 0 24 24"
version="1.1"
id="svg2"
sodipodi:docname="file-ipynb-24.svg"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs2" /><sodipodi:namedview
id="namedview2"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:zoom="11.400501"
inkscape:cx="11.139861"
inkscape:cy="13.508178"
inkscape:window-width="1512"
inkscape:window-height="853"
inkscape:window-x="0"
inkscape:window-y="639"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" /><g
fill="currentColor"
id="g2"><path
fill-rule="evenodd"
d="M5.75 1A2.75 2.75 0 003 3.75v16.5A2.75 2.75 0 005.75 23h12.5A2.75 2.75 0 0021 20.25V8.664c0-.464-.184-.909-.513-1.237l-5.914-5.914A1.75 1.75 0 0013.336 1H5.75zM4.5 3.75c0-.69.56-1.25 1.25-1.25H13v5.75c0 .414.336.75.75.75h5.75v11.25c0 .69-.56 1.25-1.25 1.25H5.75c-.69 0-1.25-.56-1.25-1.25V3.75zM18.44 7.5L14.5 3.56V7.5h3.94z"
clip-rule="evenodd"
id="path2" /></g><text
xml:space="preserve"
style="font-size:48px;line-height:0;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';fill:#f9f9f9;stroke:#7d6ec2;stroke-width:0"
x="18.610168"
y="19.525423"
id="text2"><tspan
sodipodi:role="line"
id="tspan2" /></text><g
id="g1"
transform="matrix(0.39854636,0,0,0.39854636,5.4706003,9.0850278)"><path
d="M 26.233,3.588 A 1.69,1.69 0 1 1 24.473,2 a 1.67,1.67 0 0 1 1.76,1.585 z"
style="fill:#767677"
id="path1" /><path
d="m 16.375,23.111 c -4.487,0 -8.43,-1.61 -10.469,-3.988 a 11.162,11.162 0 0 0 20.938,0 C 24.81,21.5 20.882,23.111 16.375,23.111 Z"
style="fill:#f37726"
id="path2-5" /><path
d="m 16.375,7.648 c 4.487,0 8.43,1.61 10.469,3.988 a 11.162,11.162 0 0 0 -20.938,0 C 7.945,9.253 11.869,7.648 16.375,7.648 Z"
style="fill:#f37726"
id="path3" /><path
d="m 10.2,27.739 a 2.109,2.109 0 1 1 -0.2,-0.8 2.129,2.129 0 0 1 0.2,0.8 z"
style="fill:#9e9e9e"
id="path4" /><path
d="M 6.416,7.106 A 1.226,1.226 0 1 1 7.608,5.83 1.241,1.241 0 0 1 6.416,7.106 Z"
style="fill:#616262"
id="path5" /></g></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
fill="none"
viewBox="0 0 24 24"
version="1.1"
id="svg2"
sodipodi:docname="file-json-24.svg"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs2" />
<sodipodi:namedview
id="namedview2"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:zoom="8.0003289"
inkscape:cx="15.124378"
inkscape:cy="22.936557"
inkscape:window-width="2560"
inkscape:window-height="1412"
inkscape:window-x="1512"
inkscape:window-y="149"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<g
fill="currentColor"
id="g2">
<path
fill-rule="evenodd"
d="M 5.75,1 A 2.75,2.75 0 0 0 3,3.75 v 16.5 A 2.75,2.75 0 0 0 5.75,23 h 12.5 A 2.75,2.75 0 0 0 21,20.25 V 8.664 C 21,8.2 20.816,7.755 20.487,7.427 L 14.573,1.513 A 1.75,1.75 0 0 0 13.336,1 Z M 4.5,3.75 C 4.5,3.06 5.06,2.5 5.75,2.5 H 13 V 8.25 C 13,8.664 13.336,9 13.75,9 h 5.75 v 11.25 c 0,0.69 -0.56,1.25 -1.25,1.25 H 5.75 C 5.06,21.5 4.5,20.94 4.5,20.25 Z M 18.44,7.5 14.5,3.56 V 7.5 Z"
clip-rule="evenodd"
id="path2" />
</g>
<text
xml:space="preserve"
style="font-size:48px;line-height:0;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';fill:#f9f9f9;stroke:#7d6ec2;stroke-width:0"
x="18.610168"
y="19.525423"
id="text2"><tspan
sodipodi:role="line"
id="tspan2"></tspan></text>
<text
xml:space="preserve"
style="font-size:4.95567px;line-height:0;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';fill:#aa8800;stroke:#7d6ec2;stroke-width:0"
x="5.5371022"
y="19.389633"
id="text3"
transform="scale(0.99888384,1.0011174)"
inkscape:transform-center-x="-0.74996916"><tspan
sodipodi:role="line"
id="tspan3"
x="5.5371022"
y="19.389633"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;fill:#aa8800;stroke-width:0">JSON</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
fill="none"
viewBox="0 0 24 24"
version="1.1"
id="svg2"
sodipodi:docname="file-parquet-24.svg"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs2" />
<sodipodi:namedview
id="namedview2"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:zoom="8.0003289"
inkscape:cx="15.124378"
inkscape:cy="22.936557"
inkscape:window-width="1312"
inkscape:window-height="670"
inkscape:window-x="118"
inkscape:window-y="798"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<g
fill="currentColor"
id="g2">
<path
fill-rule="evenodd"
d="M 5.75,1 A 2.75,2.75 0 0 0 3,3.75 v 16.5 A 2.75,2.75 0 0 0 5.75,23 h 12.5 A 2.75,2.75 0 0 0 21,20.25 V 8.664 C 21,8.2 20.816,7.755 20.487,7.427 L 14.573,1.513 A 1.75,1.75 0 0 0 13.336,1 Z M 4.5,3.75 C 4.5,3.06 5.06,2.5 5.75,2.5 H 13 V 8.25 C 13,8.664 13.336,9 13.75,9 h 5.75 v 11.25 c 0,0.69 -0.56,1.25 -1.25,1.25 H 5.75 C 5.06,21.5 4.5,20.94 4.5,20.25 Z M 18.44,7.5 14.5,3.56 V 7.5 Z"
clip-rule="evenodd"
id="path2" />
</g>
<text
xml:space="preserve"
style="font-size:48px;line-height:0;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';fill:#f9f9f9;stroke:#7d6ec2;stroke-width:0"
x="18.610168"
y="19.525423"
id="text2"><tspan
sodipodi:role="line"
id="tspan2"></tspan></text>
<text
xml:space="preserve"
style="font-size:4.13333px;line-height:0;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';fill:#51acf1;fill-opacity:1;stroke:#7d6ec2;stroke-width:0"
x="4.8830051"
y="19.389633"
id="text3"
transform="scale(0.99888384,1.0011174)"
inkscape:transform-center-x="-0.74996916"><tspan
sodipodi:role="line"
id="tspan3"
x="4.8830051"
y="19.389633"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.13333px;font-family:Arial;-inkscape-font-specification:Arial;fill:#51acf1;fill-opacity:1;stroke-width:0">parquet</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="24"
height="24"
fill="none"
viewBox="0 0 24 24"
version="1.1"
id="svg2"
sodipodi:docname="file-pdf-24.svg"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs2" />
<sodipodi:namedview
id="namedview2"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:zoom="8.0003289"
inkscape:cx="15.124378"
inkscape:cy="22.87406"
inkscape:window-width="1512"
inkscape:window-height="853"
inkscape:window-x="0"
inkscape:window-y="639"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<g
fill="currentColor"
id="g2">
<path
fill-rule="evenodd"
d="M5.75 1A2.75 2.75 0 003 3.75v16.5A2.75 2.75 0 005.75 23h12.5A2.75 2.75 0 0021 20.25V8.664c0-.464-.184-.909-.513-1.237l-5.914-5.914A1.75 1.75 0 0013.336 1H5.75zM4.5 3.75c0-.69.56-1.25 1.25-1.25H13v5.75c0 .414.336.75.75.75h5.75v11.25c0 .69-.56 1.25-1.25 1.25H5.75c-.69 0-1.25-.56-1.25-1.25V3.75zM18.44 7.5L14.5 3.56V7.5h3.94z"
clip-rule="evenodd"
id="path2" />
</g>
<text
xml:space="preserve"
style="font-size:48px;line-height:0;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';fill:#f9f9f9;stroke:#7d6ec2;stroke-width:0"
x="18.610168"
y="19.525423"
id="text2"><tspan
sodipodi:role="line"
id="tspan2" /></text>
<text
xml:space="preserve"
style="font-size:6.04823px;line-height:0;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';fill:#d40000;stroke:#7d6ec2;stroke-width:0"
x="5.7093801"
y="19.640993"
id="text3"
transform="scale(1.0124776,0.98767617)"><tspan
sodipodi:role="line"
id="tspan3"
x="5.7093801"
y="19.640993"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial;fill:#d40000;stroke-width:0">PDF</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><g fill="currentColor"><path d="M13.15 12.3a.75.75 0 011.05-.15l3 2.25a.75.75 0 010 1.2l-3 2.25a.75.75 0 11-.9-1.2L15.5 15l-2.2-1.65a.75.75 0 01-.15-1.05zM10.7 13.35a.75.75 0 10-.9-1.2l-3 2.25a.75.75 0 000 1.2l3 2.25a.75.75 0 10.9-1.2L8.5 15l2.2-1.65z"/><path fill-rule="evenodd" d="M5.75 1A2.75 2.75 0 003 3.75v16.5A2.75 2.75 0 005.75 23h12.5A2.75 2.75 0 0021 20.25V8.664c0-.464-.184-.909-.513-1.237l-5.914-5.914A1.75 1.75 0 0013.336 1H5.75zM4.5 3.75c0-.69.56-1.25 1.25-1.25H13v5.75c0 .414.336.75.75.75h5.75v11.25c0 .69-.56 1.25-1.25 1.25H5.75c-.69 0-1.25-.56-1.25-1.25V3.75zM18.44 7.5L14.5 3.56V7.5h3.94z" clip-rule="evenodd"/></g></svg>

After

Width:  |  Height:  |  Size: 734 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M3.75 2A2.75 2.75 0 001 4.75v14.5A2.75 2.75 0 003.75 22h16.5A2.75 2.75 0 0023 19.25V6.75A2.75 2.75 0 0020.25 4h-7.172a1.25 1.25 0 01-.883-.366l-.829-.829A2.75 2.75 0 009.422 2H3.75zM2.5 4.75c0-.69.56-1.25 1.25-1.25h5.672c.331 0 .649.132.883.366l.829.829a2.75 2.75 0 001.944.805h7.172c.69 0 1.25.56 1.25 1.25v12.5c0 .69-.56 1.25-1.25 1.25H3.75c-.69 0-1.25-.56-1.25-1.25V8.5h16.75a.75.75 0 000-1.5H2.5V4.75z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 578 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><g fill="currentColor"><path d="M11.75 10.5a.75.75 0 01.75.75v2.25h2.25a.75.75 0 010 1.5H12.5v2.25a.75.75 0 01-1.5 0V15H8.75a.75.75 0 010-1.5H11v-2.25a.75.75 0 01.75-.75z"/><path fill-rule="evenodd" d="M3.75 2A2.75 2.75 0 001 4.75v14.5A2.75 2.75 0 003.75 22h16.5A2.75 2.75 0 0023 19.25V6.75A2.75 2.75 0 0020.25 4h-7.172a1.25 1.25 0 01-.883-.366l-.829-.829A2.75 2.75 0 009.422 2H3.75zM2.5 4.75c0-.69.56-1.25 1.25-1.25h5.672c.331 0 .649.132.883.366l.829.829a2.75 2.75 0 001.944.805h7.172c.69 0 1.25.56 1.25 1.25v12.5c0 .69-.56 1.25-1.25 1.25H3.75c-.69 0-1.25-.56-1.25-1.25V8.5h16.75a.75.75 0 000-1.5H2.5V4.75z" clip-rule="evenodd"/></g></svg>

After

Width:  |  Height:  |  Size: 735 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><g fill="currentColor"><path d="M11.847 2.819a.25.25 0 01.306 0l8.25 6.407a.25.25 0 01.097.198V21.25a.75.75 0 001.5 0V9.424c0-.54-.25-1.05-.677-1.382l-8.25-6.408a1.75 1.75 0 00-2.146 0l-8.25 6.408A1.75 1.75 0 002 9.424V21.25a.75.75 0 001.5 0V9.424a.25.25 0 01.097-.198l8.25-6.407z"/><path d="M9.5 15.75a.25.25 0 01.25-.25h4.5a.25.25 0 01.25.25v5.5a.75.75 0 001.5 0v-5.5A1.75 1.75 0 0014.25 14h-4.5A1.75 1.75 0 008 15.75v5.5a.75.75 0 001.5 0v-5.5z"/></g></svg>

After

Width:  |  Height:  |  Size: 554 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M4 4.814C4 3.436 5.52 2.6 6.684 3.334l11.378 7.186a1.75 1.75 0 010 2.96L6.684 20.665C5.52 21.401 4 20.564 4 19.185V4.816zm1.883-.211a.25.25 0 00-.383.211v14.372a.25.25 0 00.383.211l11.378-7.186a.25.25 0 000-.422L5.884 4.603z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 397 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" d="M11.24 1.3A.75.75 0 1112.26.2l3.5 3.25a.75.75 0 010 1.1l-3.5 3.25a.75.75 0 11-1.02-1.1l2.217-2.059a7.5 7.5 0 105.532 4.632.75.75 0 111.397-.546 9 9 0 11-7.237-5.654L11.24 1.3z"/></svg>

After

Width:  |  Height:  |  Size: 308 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M4.75 2A2.75 2.75 0 002 4.75v14.5A2.75 2.75 0 004.75 22h14.5A2.75 2.75 0 0022 19.25V9.078c0-.729-.29-1.428-.805-1.944l-4.329-4.329A2.75 2.75 0 0014.922 2H4.75zm0 1.5c-.69 0-1.25.56-1.25 1.25v14.5c0 .69.56 1.25 1.25 1.25H6v-6.75c0-.966.784-1.75 1.75-1.75h8.5c.966 0 1.75.784 1.75 1.75v6.75h1.25c.69 0 1.25-.56 1.25-1.25V9.078c0-.331-.132-.649-.366-.883l-4.329-4.329a1.25 1.25 0 00-.883-.366H7.5v3.75c0 .138.112.25.25.25h7.5a.75.75 0 010 1.5h-7.5A1.75 1.75 0 016 7.25V3.5H4.75zM7.5 13.75v6.75h9v-6.75a.25.25 0 00-.25-.25h-8.5a.25.25 0 00-.25.25z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 716 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M10.5 2a8.5 8.5 0 105.457 15.017l4.763 4.763a.75.75 0 101.06-1.06l-4.763-4.763A8.5 8.5 0 0010.5 2zm-7 8.5a7 7 0 1114 0 7 7 0 01-14 0z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 306 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><g fill="currentColor"><path d="M6.174 7.27a.75.75 0 011.056-.096l4.5 3.75a.75.75 0 010 1.152l-4.5 3.75a.75.75 0 11-.96-1.152l3.809-3.174-3.81-3.174a.75.75 0 01-.095-1.056zM11.75 16a.75.75 0 000 1.5h5.5a.75.75 0 000-1.5h-5.5z"/><path fill-rule="evenodd" d="M1 4.75A2.75 2.75 0 013.75 2h16.5A2.75 2.75 0 0123 4.75v14.5A2.75 2.75 0 0120.25 22H3.75A2.75 2.75 0 011 19.25V4.75zM3.75 3.5c-.69 0-1.25.56-1.25 1.25v14.5c0 .69.56 1.25 1.25 1.25h16.5c.69 0 1.25-.56 1.25-1.25V4.75c0-.69-.56-1.25-1.25-1.25H3.75z" clip-rule="evenodd"/></g></svg>

After

Width:  |  Height:  |  Size: 630 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><g fill="currentColor"><path d="M6.232 8.793a.75.75 0 001.06-.025l3.958-4.146V15.25a.75.75 0 001.5 0V4.622l3.957 4.146a.75.75 0 001.085-1.036l-5.25-5.5a.747.747 0 00-1.086.001l-5.249 5.5a.75.75 0 00.025 1.06z"/><path d="M2.75 14a.75.75 0 01.75.75v4.5c0 .69.56 1.25 1.25 1.25h14.5c.69 0 1.25-.56 1.25-1.25v-4.5a.75.75 0 011.5 0v4.5A2.75 2.75 0 0119.25 22H4.75A2.75 2.75 0 012 19.25v-4.5a.75.75 0 01.75-.75z"/></g></svg>

After

Width:  |  Height:  |  Size: 513 B

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,331 @@
:root {
--jp-border-width: 0px;
--jp-border-radius: 5px;
--jp-ui-font-scale-factor: 1.2;
--jp-ui-font-size0: 0.83333em;
--jp-ui-font-size1: 13px;
--jp-ui-font-size2: 1.1428em;
--jp-ui-font-size3: 1.285714em;
--jp-ui-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--jp-content-line-height: 1.6;
--jp-content-font-scale-factor: 1.2;
--jp-content-font-size0: .875em;
--jp-content-font-size1: 14px;
--jp-content-font-size2: 1.142857em;
--jp-content-font-size3: 1.25em;
--jp-content-font-size4: 1.75em;
--jp-content-font-size5: 2em;
--jp-content-presentation-font-size1: 17px;
--jp-content-heading-line-height: 1;
--jp-content-heading-margin-top: 1.2em;
--jp-content-heading-margin-bottom: .8em;
--jp-content-heading-font-weight: 500;
--jp-content-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--jp-content-font-color1: var(--amphi-text-01);
--jp-code-font-size: 12px;
--jp-code-line-height: 1.33;
--jp-code-padding: .416em;
--jp-code-font-family-default: "IBM Plex Mono", monospace;
--jp-code-font-family: var(--jp-code-font-family-default);
--jp-code-presentation-font-size: 16px;
--jp-code-cursor-width0: 1.4px;
--jp-code-cursor-width1: 2px;
--jp-code-cursor-width2: 4px;
--jp-cell-padding: 0;
--jp-cell-collapser-width: 5px;
--jp-cell-collapser-min-height: 20px;
--jp-cell-collapser-not-active-hover-opacity: .6;
--jp-cell-prompt-width: 64px;
--jp-cell-prompt-font-family: "IBM Plex Mono", monospace;
--jp-cell-prompt-letter-spacing: 0px;
--jp-cell-prompt-opacity: 1;
--jp-cell-prompt-not-active-opacity: .5;
--jp-notebook-padding: 10px;
--jp-notebook-scroll-padding: calc( 100% - var(--jp-code-font-size) * var(--jp-code-line-height) - var(--jp-code-padding) - var(--jp-cell-padding) - 1px );
--jp-console-padding: 10px;
--jp-toolbar-micro-height: 8px;
--jp-toolbar-header-margin: 4px 4px 0px 4px;
--jp-sidebar-min-width: 280px;
--jp-shadow-base-lightness: 0;
--jp-shadow-umbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .2 );
--jp-shadow-penumbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .14 );
--jp-shadow-ambient-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .12 );
--jp-elevation-z0: none;
--jp-elevation-z1: 0px 1px 1px -1px var(--jp-shadow-umbra-color), 0px 1px 1px 0px var(--jp-shadow-penumbra-color), 0px 1px 1px 0px var(--jp-shadow-ambient-color);
--jp-elevation-z2: 0px 3px 1px -2px var(--jp-shadow-umbra-color), 0px 2px 2px 0px var(--jp-shadow-penumbra-color), 0px 1px 5px 0px var(--jp-shadow-ambient-color);
--jp-elevation-z4: 0px 2px 4px -1px var(--jp-shadow-umbra-color), 0px 4px 5px 0px var(--jp-shadow-penumbra-color), 0px 1px 10px 0px var(--jp-shadow-ambient-color);
--jp-elevation-z6: 0px 3px 5px -1px var(--jp-shadow-umbra-color), 0px 6px 10px 0px var(--jp-shadow-penumbra-color), 0px 1px 18px 0px var(--jp-shadow-ambient-color);
--jp-elevation-z8: 0px 5px 5px -3px var(--jp-shadow-umbra-color), 0px 8px 10px 1px var(--jp-shadow-penumbra-color), 0px 3px 14px 2px var(--jp-shadow-ambient-color);
--jp-elevation-z12: 0px 7px 8px -4px var(--jp-shadow-umbra-color), 0px 12px 17px 2px var(--jp-shadow-penumbra-color), 0px 5px 22px 4px var(--jp-shadow-ambient-color);
--jp-elevation-z16: 0px 8px 10px -5px var(--jp-shadow-umbra-color), 0px 16px 24px 2px var(--jp-shadow-penumbra-color), 0px 6px 30px 5px var(--jp-shadow-ambient-color);
--jp-elevation-z20: 0px 10px 13px -6px var(--jp-shadow-umbra-color), 0px 20px 31px 3px var(--jp-shadow-penumbra-color), 0px 8px 38px 7px var(--jp-shadow-ambient-color);
--jp-elevation-z24: 0px 11px 15px -7px var(--jp-shadow-umbra-color), 0px 24px 38px 3px var(--jp-shadow-penumbra-color), 0px 9px 46px 8px var(--jp-shadow-ambient-color);
--jp-warn-color0: #b28600;
--jp-warn-color1: #d2a106;
--jp-warn-color2: #f1c21b;
--jp-warn-color3: #fddc69;
--jp-error-color0: #750e13;
--jp-error-color1: #da1e28;
--jp-error-color2: #ff8389;
--jp-error-color3: #ffd7d9;
--jp-success-color0: #044317;
--jp-success-color1: #198038;
--jp-success-color2: #42be65;
--jp-success-color3: #a7f0ba;
--jp-info-color0: #002d9c;
--jp-info-color1: #5A8F7B;
--jp-info-color2: #78a9ff;
--jp-info-color3: #d0e2ff;
--jp-statusbar-height: 24px;
--amphi-interactive-01: #5A8F7B;
--amphi-interactive-02: #393939;
--amphi-interactive-03: #5A8F7B;
--amphi-interactive-04: #5A8F7B;
--amphi-ui-background: #ffffff;
/* --amphi-ui-01: #f4f4f4; */
--amphi-ui-01: #ffffff;
--amphi-ui-02: #ffffff;
--amphi-ui-03: #FFFFFF;
--amphi-ui-04: #fff;
--amphi-ui-05: #161616;
--amphi-ui-06: #F2F4F7;
--amphi-text-01: #000000;
--amphi-text-02: #000000;
--amphi-text-03: #a8a8a8;
--amphi-text-04: #ffffff;
--amphi-text-05: #6f6f6f;
--amphi-text-error: #da1e28;
--amphi-icon-01: #161616;
--amphi-icon-02: #000000;
--amphi-icon-03: #ffffff;
--amphi-link-01: #5A8F7B;
--amphi-link-02: #0043ce;
--amphi-inverse-link: #78a9ff;
--amphi-field-01: #f4f4f4;
--amphi-field-02: #ffffff;
--amphi-inverse-01: #ffffff;
--amphi-inverse-02: #393939;
--amphi-support-01: #da1e28;
--amphi-support-02: #198038;
--amphi-support-03: #f1c21b;
--amphi-support-04: #0043ce;
--amphi-inverse-support-01: #fa4d56;
--amphi-inverse-support-02: #42be65;
--amphi-inverse-support-03: #f1c21b;
--amphi-inverse-support-04: #4589ff;
--amphi-overlay-01: rgba(22, 22, 22, .5);
--amphi-danger-01: #da1e28;
--amphi-danger-02: #da1e28;
--amphi-focus: #5A8F7B;
--amphi-inverse-focus-ui: #ffffff;
--amphi-hover-primary: #0353e9;
--amphi-active-primary: #002d9c;
--amphi-hover-primary-text: #0043ce;
--amphi-hover-secondary: #4c4c4c;
--amphi-active-secondary: #F2F4F7;
--amphi-hover-tertiary: #0353e9;
--amphi-active-tertiary: #002d9c;
--amphi-hover-ui: #F2F4F7;
--amphi-hover-light-ui: #F2F4F7;
--amphi-hover-selected-ui: #F2F4F7;
--amphi-active-ui: #F2F4F7;
--amphi-active-light-ui: #F2F4F7;
--amphi-selected-ui: #F2F4F7;
--amphi-selected-light-ui: #F2F4F7;
--amphi-inverse-hover-ui: #4c4c4c;
--amphi-hover-danger: #b81921;
--amphi-active-danger: #750e13;
--amphi-hover-row: #EBEBEA;
--amphi-visited-link: #5A8F7B;
--amphi-disabled-01: #f4f4f4;
--amphi-disabled-02: #c6c6c6;
--amphi-disabled-03: #8d8d8d;
--amphi-highlight: #d0e2ff;
--amphi-decorative-01: #e0e0e0;
--amphi-button-separator: #e0e0e0;
--amphi-skeleton-01: #EBEBEA;
--amphi-skeleton-02: #c6c6c6;
--amphi-background: #ffffff;
--amphi-layer: #f4f4f4;
--amphi-layer-accent: #e0e0e0;
--amphi-layer-accent-hover: #d1d1d1;
--amphi-layer-accent-active: #a8a8a8;
--amphi-field: #f4f4f4;
--amphi-background-inverse: #393939;
--amphi-background-brand: #5A8F7B;
--amphi-interactive: #5A8F7B;
--amphi-border-subtle: #e0e0e0;
--amphi-border-strong: #8d8d8d;
--amphi-border-inverse: #161616;
--amphi-border-interactive: #ffffff;
--amphi-text-primary: #000000;
--amphi-text-secondary: #000000;
--amphi-text-placeholder: #a8a8a8;
--amphi-text-helper: #6f6f6f;
--amphi-text-on-color: #ffffff;
--amphi-text-inverse: #ffffff;
--amphi-link-primary: #5A8F7B;
--amphi-link-secondary: #0043ce;
--amphi-link-visited: #5A8F7B;
--amphi-link-inverse: #78a9ff;
--amphi-icon-primary: #161616;
--amphi-icon-secondary: #525252;
--amphi-icon-on-color: #ffffff;
--amphi-icon-inverse: #ffffff;
--amphi-support-error: #da1e28;
--amphi-support-success: #198038;
--amphi-support-warning: #f1c21b;
--amphi-support-info: #0043ce;
--amphi-support-error-inverse: #fa4d56;
--amphi-support-success-inverse: #42be65;
--amphi-support-warning-inverse: #f1c21b;
--amphi-support-info-inverse: #4589ff;
--amphi-overlay: rgba(22, 22, 22, .5);
--amphi-toggle-off: #8d8d8d;
--amphi-shadow: rgba(0, 0, 0, .3);
--amphi-button-primary: #5A8F7B;
--amphi-button-secondary: #393939;
--amphi-button-tertiary: #5A8F7B;
--amphi-button-danger-primary: #da1e28;
--amphi-button-danger-secondary: #da1e28;
--amphi-background-active: #c6c6c6;
--amphi-layer-active: #c6c6c6;
--amphi-button-danger-active: #750e13;
--amphi-button-primary-active: #002d9c;
--amphi-button-secondary-active: #6f6f6f;
--amphi-button-tertiary-active: #002d9c;
--amphi-focus-inset: #ffffff;
--amphi-focus-inverse: #ffffff;
--amphi-background-hover: #EBEBEA;
--amphi-layer-hover: #EBEBEA;
--amphi-field-hover: #EBEBEA;
--amphi-background-inverse-hover: #4c4c4c;
--amphi-link-primary-hover: #0043ce;
--amphi-button-danger-hover: #b81921;
--amphi-button-primary-hover: #0353e9;
--amphi-button-secondary-hover: #4c4c4c;
--amphi-button-tertiary-hover: #0353e9;
--amphi-background-selected: #e0e0e0;
--amphi-background-selected-hover: #cacaca;
--amphi-layer-selected: #e0e0e0;
--amphi-layer-selected-hover: #cacaca;
--amphi-layer-selected-inverse: #161616;
--amphi-border-subtle-selected: #c6c6c6;
--amphi-border-disabled: #f4f4f4;
--amphi-text-disabled: #c6c6c6;
--amphi-button-disabled: #c6c6c6;
--amphi-icon-disabled: #c6c6c6;
--amphi-text-on-color-disabled: #8d8d8d;
--amphi-icon-on-color-disabled: #8d8d8d;
--amphi-layer-selected-disabled: #8d8d8d;
--amphi-skeleton-background: #EBEBEA;
--amphi-skeleton-element: #c6c6c6;
--amphi-brand-01: #5A8F7B;
--amphi-brand-02: #393939;
--amphi-brand-03: #5A8F7B;
--amphi-active-01: #c6c6c6;
--amphi-hover-field: #EBEBEA;
--amphi-danger: #da1e28;
--jp-content-link-color: var(--amphi-link-01);
--jp-border-color0: var(--amphi-ui-04);
--jp-border-color1: var(--amphi-ui-04);
--jp-border-color2: var(--amphi-ui-06);
--jp-border-color3: var(--amphi-ui-01);
--jp-border-focus: var(--amphi-focus);
--jp-ui-font-color0: var(--amphi-text-01);
--jp-ui-font-color1: var(--amphi-text-02);
--jp-ui-font-color2: var(--amphi-text-03);
--jp-ui-font-color3: var(--amphi-text-04);
--jp-ui-font-color4: var(--amphi-text-05);
--jp-ui-inverse-font-color0: var(--amphi-inverse-01);
--jp-ui-inverse-font-color1: var(--amphi-inverse-01);
--jp-ui-inverse-font-color2: var(--amphi-inverse-01);
--jp-ui-inverse-font-color3: var(--amphi-inverse-01);
--jp-layout-background: var(--amphi-ui-background);
--jp-layout-color0: var(--amphi-ui-01);
--jp-layout-color1: var(--amphi-ui-02);
--jp-layout-color2: var(--amphi-ui-06);
--jp-layout-color3: var(--amphi-ui-04);
--jp-layout-color4: var(--amphi-ui-05);
--jp-layout-hover: var(--amphi-hover-ui);
--jp-active-color: var(--amphi-active-ui);
--jp-disabled-color0: var(--amphi-disabled-01);
--jp-disabled-color1: var(--amphi-disabled-02);
--jp-disabled-color2: var(--amphi-disabled-03);
--jp-inverse-layout-color0: var(--amphi-icon-01);
--jp-inverse-layout-color1: var(--amphi-icon-01);
--jp-inverse-layout-color2: var(--amphi-icon-02);
--jp-inverse-layout-color3: var(--amphi-icon-02);
--jp-inverse-layout-color4: var(--amphi-icon-03);
--jp-brand-color0: var(--amphi-brand-02);
--jp-brand-color1: var(--amphi-brand-01);
--jp-brand-color2: var(--amphi-brand-03);
--jp-brand-color3: var(--amphi-brand-03);
--jp-accent-color0: var(--amphi-support-02);
--jp-accent-color1: var(--amphi-support-02);
--jp-accent-color2: var(--amphi-inverse-support-02);
--jp-accent-color3: var(--amphi-inverse-support-02);
--jp-cell-editor-background: var(--amphi-ui-background);
--jp-cell-editor-border-color: var(--amphi-ui-01);
--jp-cell-editor-box-shadow: inset 0 0 2px var(--amphi-active-primary);
--jp-cell-editor-active-background: var(--amphi-ui-background);
--jp-cell-editor-active-border-color: var(--amphi-brand-01);
--jp-cell-prompt-not-active-font-color: var(--amphi-text-03);
--jp-cell-inprompt-font-color: var(--amphi-text-01);
--jp-cell-outprompt-font-color: var(--amphi-text-01);
--jp-notebook-select-background: var(--amphi-ui-02);
--jp-notebook-multiselected-color: var(--amphi-interactive-04);
--jp-rendermime-error-background: var(--amphi-ui-01);
--jp-rendermime-table-row-background: var(--amphi-ui-02);
--jp-rendermime-table-row-hover-background: var(--amphi-ui-03);
--jp-dialog-background: var(--amphi-overlay-01);
--jp-toolbar-border-color: var(--amphi-ui-04);
--jp-toolbar-background: var(--amphi-ui-01);
--jp-toolbar-box-shadow: none;
--jp-toolbar-active-background: var(--amphi-ui-06);
--jp-input-box-shadow: inset 0 0 2px var(--amphi-ui-01);
--jp-input-active-background: var(--amphi-field-01);
--jp-input-hover-background: var(--amphi-hover-field);
--jp-input-background: var(--amphi-field-02);
--jp-input-border-color: var(--amphi-ui-04);
--jp-input-active-border-color: var(--amphi-brand-01);
--jp-editor-selected-background: var(--amphi-selected-light-ui);
--jp-editor-selected-focused-background: var(--amphi-selected-light-ui);
--jp-editor-cursor-color: var(--amphi-text-01);
--jp-vega-background: var(--amphi-ui-background);
--jp-private-split-panel-color: var(--amphi-skeleton-01);
--jp-scrollbar-bg: transparent;
--jp-scrollbar-color: var(--amphi-text-03);
--jp-highlight: var(--amphi-highlight);
--jp-field01: var(--amphi-field-01);
--jp-field02: var(--amphi-field-02);
/* Tab
*/
--jp-private-horizontal-tab-height: 32px;
--jp-private-toolbar-height: calc(42px + var(--jp-border-width));
--jp-private-input-height: 40px;
/* Toolbar */
--jp-private-horizontal-tab-height: 32px;
/* Menu
*/
--jp-private-menubar-height: 47px !important;
--jp-private-menu-item-height: 34px;
/* sidebar
*/
--jp-private-sidebar-tab-width: 48px;
--jp-private-sidebar-tab-height: 48px;
--neutral-fill-input-rest: var(--amphi-ui-01)
/* --accent-fill-rest: var(--jp-info-color1); */
/* search bar */
}

View File

@ -0,0 +1,8 @@
{
"extends": "../../tsconfigbase",
"compilerOptions": {
"outDir": "lib",
"rootDir": "src"
},
"include": ["src/*", "src/**/*"]
}

View File

@ -0,0 +1,86 @@
{
"name": "@amphi/ui-component",
"version": "0.1.0",
"description": "p5 notebook - lab extension",
"homepage": "https://github.com/amphi-ai/amphi",
"bugs": {
"url": "https://github.com/amphi-ai/amphi/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/amphi-ai/amphi.git"
},
"license": "ELv2",
"author": {
"name": "Thibaut Gourdel",
"email": "tgourdel@amphi.ai"
},
"sideEffects": [
"style/*.css",
"style/index.js"
],
"main": "lib/index.js",
"types": "lib/index.d.ts",
"style": "style/index.css",
"styleModule": "style/index.js",
"directories": {
"lib": "lib/"
},
"files": [
"lib/*.d.ts",
"lib/*.js.map",
"lib/*.js",
"style/*.css",
"style/index.js"
],
"scripts": {
"build": "jlpm run build:lib && jlpm run build:labextension:dev",
"build:labextension": "jupyter labextension build .",
"build:labextension:dev": "jupyter labextension build --development True .",
"build:lib": "tsc --build --verbose",
"build:prod": "jlpm run build:lib && jlpm run build:labextension && jlpm install",
"clean": "jlpm run clean:lib && jlpm run clean:labextension",
"clean:labextension": "rimraf ../../amphi/ui-component",
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
"eslint": "eslint . --ext .ts,.tsx --fix",
"eslint:check": "eslint . --ext .ts,.tsx",
"watch": "run-p watch:src watch:labextension",
"watch:labextension": "jupyter labextension watch .",
"watch:src": "tsc -w"
},
"dependencies": {
"@jupyterlab/application": "^4.0.9",
"@jupyterlab/filebrowser": "^4.0.9",
"@jupyterlab/launcher": "^4.0.9",
"@jupyterlab/mainmenu": "^4.0.9",
"@jupyterlab/ui-components": "^4.0.9",
"antd": "5.16.4"
},
"resolutions": {
"@jupyterlab/rendermime-interfaces": "^4.0.9",
"@lumino/widgets": "^2.0.0",
"@types/react": "^18.2.7"
},
"devDependencies": {
"@jupyterlab/builder": "^4.0.9",
"@typescript-eslint/eslint-plugin": "^4.8.1",
"@typescript-eslint/parser": "^4.8.1",
"eslint": "^7.14.0",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react": "^7.18.3",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.1",
"reactflow": "11.7.2",
"rimraf": "^3.0.2",
"typescript": "~5.0.4",
"yarn-deduplicate": "^6.0.2"
},
"publishConfig": {
"access": "public"
},
"jupyterlab": {
"extension": true,
"outputDir": "../../amphi/ui-component"
}
}

View File

@ -0,0 +1,246 @@
/*
* Copyright 2018-2023 Elyra Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Dialog } from '@jupyterlab/apputils';
import { IDocumentManager } from '@jupyterlab/docmanager';
import {
BreadCrumbs,
DirListing,
FilterFileBrowserModel
} from '@jupyterlab/filebrowser';
import { Widget, PanelLayout } from '@lumino/widgets';
const BROWSE_FILE_CLASS = 'elyra-browseFileDialog';
const BROWSE_FILE_OPEN_CLASS = 'elyra-browseFileDialog-open';
export interface IBrowseFileDialogOptions {
filter?: (model: any) => boolean;
multiselect?: boolean;
includeDir?: boolean;
acceptFileOnDblClick?: boolean;
rootPath?: string;
startPath?: string;
}
interface IBrowseFileBreadCrumbsOptions extends BreadCrumbs.IOptions {
rootPath?: string;
}
/**
* Breadcrumbs widget for browse file dialog body.
*/
class BrowseFileDialogBreadcrumbs extends BreadCrumbs {
model: any;
rootPath?: string;
constructor(options: IBrowseFileBreadCrumbsOptions) {
super(options);
this.model = options.model;
this.rootPath = options.rootPath;
}
protected onUpdateRequest(msg: any): void {
super.onUpdateRequest(msg);
const contents = this.model.manager.services.contents;
const localPath = contents.localPath(this.model.path);
// if 'rootPath' is defined prevent navigating to it's parent/grandparent directories
if (localPath && this.rootPath && localPath.indexOf(this.rootPath) === 0) {
const breadcrumbs = document.querySelectorAll(
'.elyra-browseFileDialog .jp-BreadCrumbs > span[title]'
);
breadcrumbs.forEach((crumb: Element): void => {
if (
(crumb as HTMLSpanElement).title.indexOf(this.rootPath ?? '') === 0
) {
crumb.className = crumb.className
.replace('elyra-BreadCrumbs-disabled', '')
.trim();
} else if (
crumb.className.indexOf('elyra-BreadCrumbs-disabled') === -1
) {
crumb.className += ' elyra-BreadCrumbs-disabled';
}
});
}
}
}
/**
* Browse file widget for dialog body
*/
class BrowseFileDialog extends Widget
implements Dialog.IBodyWidget<IBrowseFileDialogOptions> {
directoryListing: DirListing;
breadCrumbs: BreadCrumbs;
dirListingHandleEvent: (event: Event) => void;
multiselect: boolean;
includeDir: boolean;
acceptFileOnDblClick: boolean;
model: FilterFileBrowserModel;
constructor(props: any) {
super(props);
this.model = new FilterFileBrowserModel({
manager: props.manager,
filter: props.filter
});
const layout = (this.layout = new PanelLayout());
this.directoryListing = new DirListing({
model: this.model
});
this.acceptFileOnDblClick = props.acceptFileOnDblClick;
this.multiselect = props.multiselect;
this.includeDir = props.includeDir;
this.dirListingHandleEvent = this.directoryListing.handleEvent;
this.directoryListing.handleEvent = (event: Event): void => {
this.handleEvent(event);
};
this.breadCrumbs = new BrowseFileDialogBreadcrumbs({
model: this.model,
rootPath: props.rootPath
});
layout.addWidget(this.breadCrumbs);
layout.addWidget(this.directoryListing);
}
static async init(options: any): Promise<BrowseFileDialog> {
const browseFileDialog = new BrowseFileDialog(options);
if (options.startPath) {
if (
!options.rootPath ||
options.startPath.indexOf(options.rootPath) === 0
) {
await browseFileDialog.model.cd(options.startPath);
}
} else if (options.rootPath) {
await browseFileDialog.model.cd(options.rootPath);
}
return browseFileDialog;
}
getValue(): any {
const selected = [];
let item = null;
for (const item of this.directoryListing.selectedItems()) {
if (this.includeDir || item.type !== 'directory') {
selected.push(item);
}
}
return selected;
}
handleEvent(event: Event): void {
let modifierKey = false;
if (event instanceof MouseEvent) {
modifierKey =
(event as MouseEvent).shiftKey || (event as MouseEvent).metaKey;
} else if (event instanceof KeyboardEvent) {
modifierKey =
(event as KeyboardEvent).shiftKey || (event as KeyboardEvent).metaKey;
}
switch (event.type) {
case 'keydown':
case 'keyup':
case 'mousedown':
case 'mouseup':
case 'click':
if (this.multiselect || !modifierKey) {
this.dirListingHandleEvent.call(this.directoryListing, event);
}
break;
case 'dblclick': {
const clickedItem = this.directoryListing.modelForClick(
event as MouseEvent
);
if (clickedItem?.type === 'directory') {
this.dirListingHandleEvent.call(this.directoryListing, event);
} else {
event.preventDefault();
event.stopPropagation();
if (this.acceptFileOnDblClick) {
const okButton = document.querySelector(
`.${BROWSE_FILE_OPEN_CLASS} .jp-mod-accept`
);
if (okButton) {
(okButton as HTMLButtonElement).click();
}
}
}
break;
}
default:
this.dirListingHandleEvent.call(this.directoryListing, event);
break;
}
}
}
export const showBrowseFileDialog = async (
manager: IDocumentManager,
options: IBrowseFileDialogOptions
): Promise<Dialog.IResult<any>> => {
const browseFileDialogBody = await BrowseFileDialog.init({
manager: manager,
filter: options.filter,
multiselect: options.multiselect,
includeDir: options.includeDir,
rootPath: options.rootPath,
startPath: options.startPath,
acceptFileOnDblClick: Object.prototype.hasOwnProperty.call(
options,
'acceptFileOnDblClick'
)
? options.acceptFileOnDblClick
: true
});
const dialog = new Dialog({
title: 'Select a file',
body: browseFileDialogBody,
buttons: [Dialog.cancelButton(), Dialog.okButton({ label: 'Select' })]
});
dialog.addClass(BROWSE_FILE_CLASS);
document.body.className += ` ${BROWSE_FILE_OPEN_CLASS}`;
return dialog.launch().then((result: any) => {
document.body.className = document.body.className
.replace(BROWSE_FILE_OPEN_CLASS, '')
.trim();
if (options.rootPath && result.button.accept && result.value.length) {
const relativeToPath = options.rootPath.endsWith('/')
? options.rootPath
: options.rootPath + '/';
result.value.forEach((val: any) => {
val.path = val.path.replace(relativeToPath, '');
});
}
return result;
});
};

View File

@ -0,0 +1,102 @@
/*
* Copyright 2018-2023 Elyra Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Drag } from '@lumino/dragdrop';
import React, { useCallback, useEffect, useRef } from 'react';
declare global {
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
interface HTMLElementEventMap {
'lm-dragenter': Drag.Event;
'lm-dragleave': Drag.Event;
'lm-dragover': Drag.Event;
'lm-drop': Drag.Event;
}
}
interface IRootProps {
ref: React.RefObject<HTMLDivElement>;
}
interface IProps {
onDragEnter?: (e: Drag.Event) => any;
onDragLeave?: (e: Drag.Event) => any;
onDragOver?: (e: Drag.Event) => any;
onDrop?: (e: Drag.Event) => any;
children?: React.ReactNode; // add this line
}
interface IReturn {
getRootProps: () => IRootProps;
}
export const useDropzone = (props: IProps): IReturn => {
const rootRef = useRef<HTMLDivElement>(null);
const handleEvent = useCallback(
(e: Drag.Event): void => {
e.preventDefault();
e.stopPropagation();
switch (e.type) {
case 'lm-dragenter':
props.onDragEnter?.(e);
break;
case 'lm-dragleave':
props.onDragLeave?.(e);
break;
case 'lm-dragover':
e.dropAction = e.proposedAction;
props.onDragOver?.(e);
break;
case 'lm-drop':
props.onDrop?.(e);
break;
}
},
[props]
);
useEffect(() => {
const node = rootRef.current;
node?.addEventListener('lm-dragenter', handleEvent);
node?.addEventListener('lm-dragleave', handleEvent);
node?.addEventListener('lm-dragover', handleEvent);
node?.addEventListener('lm-drop', handleEvent);
return (): void => {
node?.removeEventListener('lm-dragenter', handleEvent);
node?.removeEventListener('lm-dragleave', handleEvent);
node?.removeEventListener('lm-dragover', handleEvent);
node?.removeEventListener('lm-drop', handleEvent);
};
}, [handleEvent]);
return {
getRootProps: (): IRootProps => ({
ref: rootRef
})
};
};
export const Dropzone: React.FC<IProps> = ({ children, ...rest }) => {
const { getRootProps } = useDropzone(rest);
return (
<div style={{ height: '100%' }} {...getRootProps()}>
{children}
</div>
);
};

View File

@ -0,0 +1,4 @@
declare module '*.svg' {
const value: string;
export default value;
}

View File

@ -0,0 +1,92 @@
import { LabIcon } from '@jupyterlab/ui-components';
import squareIconSvgStr from '../style/icons/amphi-square-logo.svg';
import amphiLogoSvgStr from '../style/icons/amphi.svg';
import pipelineIconSvgStr from '../style/icons/pipeline-16.svg';
import pipelineNegativeIconSvgStr from '../style/icons/pipeline-16.svg';
import shieldCheckedIconSvgStr from '../style/icons/shield-check-24.svg';
import codeIconSvgStr from '../style/icons/code-16.svg';
import docsIconSvgStr from '../style/icons/docs-16.svg';
import uploadIconSvgStr from '../style/icons/upload-16.svg';
import networkIconSvgStr from '../style/icons/network-24.svg';
import bugIconSvgStr from '../style/icons/bug-16.svg';
import githubIconSvgStr from '../style/icons/github.svg';
import discourseIconSvgStr from '../style/icons/discourse.svg';
import alertCircleFillSvgStr from '../style/icons/alert-circle-fill-24.svg';
import alertDiamondSvgStr from '../style/icons/alert-diamond-24.svg';
export const alertDiamondIcon = new LabIcon({
name: 'amphi:alertDiamond-icon',
svgstr: alertDiamondSvgStr
});
export const alertCircleFillIcon = new LabIcon({
name: 'amphi:alertCircleFill-icon',
svgstr: alertCircleFillSvgStr
});
export const asteriskIcon = new LabIcon({
name: 'amphi:asterisk-icon',
svgstr: squareIconSvgStr
});
export const squareIcon = new LabIcon({
name: 'amphi:square-icon',
svgstr: squareIconSvgStr
});
export const amphiLogo = new LabIcon({
name: 'amphi:logo',
svgstr: amphiLogoSvgStr
});
export const pipelineIcon = new LabIcon({
name: 'amphi:pipeline-icon',
svgstr: pipelineIconSvgStr
});
export const pipelineNegativeIcon = new LabIcon({
name: 'amphi:pipelinenegative-icon',
svgstr: pipelineNegativeIconSvgStr
});
export const shieldCheckedIcon = new LabIcon({
name: 'amphi:shieldchecked-icon',
svgstr: shieldCheckedIconSvgStr
});
export const codeIcon = new LabIcon({
name: 'amphi:code-icon',
svgstr: codeIconSvgStr
});
export const docsIcon = new LabIcon({
name: 'amphi:docs-icon',
svgstr: docsIconSvgStr
});
export const uploadIcon = new LabIcon({
name: 'amphi:upload-icon',
svgstr: uploadIconSvgStr
});
export const networkIcon = new LabIcon({
name: 'amphi:network-icon',
svgstr: networkIconSvgStr
});
export const bugIcon = new LabIcon({
name: 'amphi:bug-icon',
svgstr: bugIconSvgStr
});
export const githubIcon = new LabIcon({
name: 'amphi:github-icon',
svgstr: githubIconSvgStr
});
export const discourseIcon = new LabIcon({
name: 'amphi:discourse-icon',
svgstr: discourseIconSvgStr
});

View File

@ -0,0 +1,177 @@
import {
ILabShell,
JupyterFrontEnd,
JupyterFrontEndPlugin
} from '@jupyterlab/application';
import { Launcher, LauncherModel} from './launcher';
import { IThemeManager } from '@jupyterlab/apputils';
import { IMainMenu } from '@jupyterlab/mainmenu';
import { ILauncher } from '@jupyterlab/launcher';
import { ITranslator } from '@jupyterlab/translation';
import { ICommandPalette, MainAreaWidget } from '@jupyterlab/apputils';
import { toArray } from '@lumino/algorithm';
import { DockPanel, TabBar, Widget } from '@lumino/widgets';
import { pipelineIcon, asteriskIcon, squareIcon } from './icons';
import { homeIcon } from '@jupyterlab/ui-components';
export { showBrowseFileDialog } from './BrowseFileDialog';
import '../style/index.css';
/**
* The main application icon.
*/
const logo: JupyterFrontEndPlugin<void> = {
id: '@amphi/ui-component:logo',
optional: [ILabShell],
autoStart: true,
activate: (
app: JupyterFrontEnd,
labShell: ILabShell | null
) => {
let logo: Widget | null = null;
if (labShell) {
logo = new Widget();
asteriskIcon.element({
container: logo.node,
elementPosition: 'center',
margin: '2px 2px 2px 16px',
height: '16px',
width: '16px'
});
}
if (logo) {
logo.id = 'jp-MainLogo';
app.shell.add(logo, 'top', { rank: 0 });
}
}
};
/**
* The command IDs used by the launcher plugin.
*/
const CommandIDs = {
create: 'launcher:create'
};
/**
* The main launcher.
*/
const launcher: JupyterFrontEndPlugin<ILauncher> = {
id: '@amphi/ui-component:launcher',
autoStart: true,
requires: [ITranslator, ILabShell, IMainMenu],
optional: [ICommandPalette],
provides: ILauncher,
activate: (
app: JupyterFrontEnd,
translator: ITranslator,
labShell: ILabShell,
mainMenu: IMainMenu,
manager: IThemeManager,
palette: ICommandPalette | null
): ILauncher => {
console.log('Amphi - custom Launcher is activated!');
/** */
// Use custom Amphi launcher
const { commands, shell } = app;
const trans = translator.load('jupyterlab');
const model = new LauncherModel();
console.log('Amphi - theme before adding launcher:create');
commands.addCommand(CommandIDs.create, {
label: trans.__('New'),
execute: (args: any) => {
const cwd = args['cwd'] ? String(args['cwd']) : '';
const id = `launcher-${Private.id++}`;
const callback = (item: Widget): void => {
labShell.add(item, 'main', { ref: id });
};
const launcher = new Launcher({
model,
cwd,
callback,
commands,
translator
}, commands);
launcher.model = model;
launcher.title.icon = homeIcon;
launcher.title.label = trans.__('流水线主页');
const main = new MainAreaWidget({ content: launcher });
// If there are any other widgets open, remove the launcher close icon.
main.title.closable = !!toArray(labShell.widgets('main')).length;
main.id = id;
shell.add(main, 'main', {
activate: args['activate'] as boolean,
ref: args['ref'] as string
});
labShell.layoutModified.connect(() => {
// If there is only a launcher open, remove the close icon.
main.title.closable = toArray(labShell.widgets('main')).length > 1;
}, main);
return main;
}
});
if (palette) {
palette.addItem({
command: CommandIDs.create,
category: trans.__('主页')
});
}
/**
* This function seems to set up and handle the behavior of an "add" button within a JupyterLab-like environment.
* When the button is clicked (or an "add" action is requested), the function determines
* which tab or panel the action was requested from and then executes a command to handle the request,
* either by creating a main launcher or by performing another default "create" action.
*/
if (labShell) {
labShell.addButtonEnabled = true;
labShell.addRequested.connect(
(sender: DockPanel, arg: TabBar<Widget>) => {
// Get the ref for the current tab of the tabbar which the add button was clicked
const ref =
arg.currentTitle?.owner.id ||
arg.titles[arg.titles.length - 1].owner.id;
if (commands.hasCommand('filebrowser:create-main-launcher')) {
// If a file browser is defined connect the launcher to it
return commands.execute('filebrowser:create-main-launcher', {
ref
});
}
return commands.execute(CommandIDs.create, { ref });
}
);
}
return model;
}
};
/**
* The namespace for module private data.
*/
namespace Private {
/**
* The incrementing id used for launcher widgets.
*/
// eslint-disable-next-line
export let id = 0;
}
const plugins: JupyterFrontEndPlugin<any>[] = [logo, launcher];
export default plugins;
export * from './icons';

View File

@ -0,0 +1,235 @@
import {
ILauncher,
Launcher as JupyterlabLauncher,
LauncherModel as JupyterLauncherModel
} from '@jupyterlab/launcher';
import { LabIcon } from '@jupyterlab/ui-components';
import { CommandRegistry } from '@lumino/commands';
import { githubIcon, pipelineIcon, discourseIcon, alertDiamondIcon } from './icons';
import { each } from '@lumino/algorithm';
import React, { useEffect, useState } from 'react';
// Largely inspired by Elyra launcher https://github.com/elyra-ai/elyra
/**
* The known categories of launcher items and their default ordering.
*/
const AMPHI_CATEGORY = 'Data Integration';
const CommandIDs = {
newPipeline: 'pipeline-editor:create-new',
newFile: 'fileeditor:create-new',
createNewPythonEditor: 'script-editor:create-new-python-editor',
createNewREditor: 'script-editor:create-new-r-editor'
};
// LauncherModel deals with the underlying data and logic of the launcher (what items are available, their order, etc.).
export class LauncherModel extends JupyterLauncherModel {
/**
* Return an iterator of launcher items, but remove unnecessary items.
*/
items(): IterableIterator<ILauncher.IItemOptions> {
const items: ILauncher.IItemOptions[] = [];
let pyEditorInstalled = false;
let rEditorInstalled = false;
this.itemsList.forEach(item => {
if (item.command === CommandIDs.createNewPythonEditor) {
pyEditorInstalled = true;
} else if (item.command === CommandIDs.createNewREditor) {
rEditorInstalled = true;
}
});
if (!pyEditorInstalled && !rEditorInstalled) {
return this.itemsList[Symbol.iterator]();
}
// Dont add tiles for new py and r files if their script editor is installed
this.itemsList.forEach(item => {
if (
!(
item.command === CommandIDs.newFile &&
((pyEditorInstalled && item.args?.fileExt === 'py') ||
(rEditorInstalled && item.args?.fileExt === 'r'))
)
) {
items.push(item);
}
});
return items[Symbol.iterator]();
}
}
// Launcher deals with the visual representation and user interactions of the launcher
// (how items are displayed, icons, categories, etc.).
export class Launcher extends JupyterlabLauncher {
private myCommands: CommandRegistry;
/**
* Construct a new launcher widget.
*/
constructor(options: ILauncher.IOptions, commands: any) {
super(options);
this.myCommands = commands;
// this._translator = this.translator.load('jupyterlab');
}
/**
The replaceCategoryIcon function takes a category element and a new icon.
It then goes through the children of the category to find the section header.
Within the section header, it identifies the icon (by checking if it's not the section title)
and replaces it with the new icon. The function then returns a cloned version of the original
category with the icon replaced.
*/
private replaceCategoryIcon(
category: React.ReactElement,
icon: LabIcon
): React.ReactElement {
const children = React.Children.map(category.props.children, child => {
if (child.props.className === 'jp-Launcher-sectionHeader') {
const grandchildren = React.Children.map(
child.props.children,
grandchild => {
if (grandchild.props.className !== 'jp-Launcher-sectionTitle') {
return <icon.react stylesheet="launcherSection" />;
} else {
return grandchild;
}
}
);
return React.cloneElement(child, child.props, grandchildren);
} else {
return child;
}
});
return React.cloneElement(category, category.props, children);
}
/**
* Render the launcher to virtual DOM nodes.
*/
protected render(): React.ReactElement<any> | null {
if (!this.model) {
return null;
}
const launcherBody = super.render();
const launcherContent = launcherBody?.props.children;
const launcherCategories = launcherContent.props.children;
const categories: React.ReactElement<any>[] = [];
const knownCategories = [
AMPHI_CATEGORY,
// this._translator.__('Console'),
// this._translator.__('Other'),
// this._translator.__('Notebook')
];
each(knownCategories, (category, index) => {
React.Children.forEach(launcherCategories, (cat) => {
if (cat.key === category) {
if (cat.key === AMPHI_CATEGORY) {
cat = this.replaceCategoryIcon(cat, pipelineIcon);
}
categories.push(cat);
}
});
});
const handleNewPipelineClick = () => {
this.myCommands.execute('pipeline-editor:create-new');
};
const handleUploadFiles = () => {
this.myCommands.execute('ui-components:file-upload');
};
const AlertBox = () => {
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
const alertClosed = localStorage.getItem('alertClosed') === 'true';
setIsVisible(!alertClosed);
}, []);
const closeAlert = () => {
setIsVisible(false);
localStorage.setItem('alertClosed', 'true');
};
if (!isVisible) return null;
return (
<div className="alert-box">
<div className="alert-content">
<span className="alert-icon">
<alertDiamondIcon.react />
</span>
<div className="alert-text">
<h2>About</h2>
<p>
Welcome to Amphi's demo playground! Explore Amphi ETL's capabilities and user experience here. <br />
Note that <b>executing pipelines is not supported in this environment.</b> For full functionality, install Amphi it's free and open source.{' '}
<a href="https://github.com/amphi-ai/amphi-etl" target="_blank">
Learn more.
</a>
</p>
</div>
<button onClick={closeAlert} className="alert-close-btn">
<span className="sr-only">Dismiss popup</span>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
);
};
return (
<div className="launcher-body">
<div className="launcher-content">
<h1 className="launcher-title"></h1>
<div className="launcher-grid">
<div className="launcher-card">
<div className="launcher-card-header">
<h3></h3>
</div>
<ul className="launcher-card-list">
<li>
<a href="#" onClick={handleNewPipelineClick} className="launcher-card-item">
<div className="launcher-icon">
<pipelineIcon.react fill="#5A8F7B" />
</div>
<div>
<strong>线</strong>
<p>线</p>
</div>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
);
}
}

View File

@ -0,0 +1,156 @@
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.elyra-browseFileDialog .jp-Dialog-content {
height: 400px;
width: 600px;
}
.launcher-body {
padding: 20px;
width:80%;
margin: 0 auto; /* Center horizontally */
}
.launcher-content {
max-width: 1200px;
margin: auto;
width: 100%;
}
.launcher-title {
margin-top: 32px;
font-size: 36px;
font-weight: bold;
color: #1a202c;
display: flex;
align-items: center;
}
.launcher-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-top: 28px;
}
.launcher-card {
background-color: white;
padding: 16px;
border-radius: 4px;
/* border: 1px solid #e2e8f0; */
}
.launcher-card-header h3 {
font-size: 24px;
font-weight: bold;
color: #1a202c;
}
.launcher-card-links {
display: flex;
flex-wrap: wrap;
margin: -4px;
}
.launcher-card-links li {
padding: 4px;
margin-bottom: 20px;
}
.launcher-card-links a {
font-size: 12px;
font-weight: 500;
color: #3182ce;
text-decoration: none;
}
.launcher-card-list {
margin-top: 16px;
list-style: none;
padding: 0;
}
.launcher-card-list li {
margin-bottom: 20px;
}
.launcher-card-item {
display: flex;
align-items: center;
padding: 16px;
border-radius: 4px;
border: 1px solid #F2F4F7;
text-decoration: none;
color: inherit;
transition: all 0.3s;
}
.launcher-card-item:hover {
border-color: #a0aec0;
background-color: #f7fafc;
}
.launcher-icon {
display: flex;
align-items: center;
justify-content: center;
width: 64px;
height: 64px;
border-radius: 50%;
}
.alert-box {
margin-top: 20px;
padding: 16px;
border-radius: 8px;
border: 1px solid #e2e8f0;
background-color: white;
}
.alert-content {
display: flex;
align-items: start;
gap: 16px;
}
.alert-icon {
color: #4a5568;
}
.alert-text h2 {
font-size: 20px;
font-weight: bold;
color: #1a202c;
}
.alert-text p {
margin-top: 8px;
font-size: 14px;
color: #4a5568;
}
.alert-close-btn {
color: #a0aec0;
transition: color 0.3s;
background: none;
border: none;
cursor: pointer;
}
.alert-close-btn:hover {
color: #718096;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}

View File

@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="size=24">
<path id="Path" fill-rule="evenodd" clip-rule="evenodd" d="M12 1C5.92487 1 1 5.92487 1 12C1 18.0751 5.92487 23 12 23C18.0751 23 23 18.0751 23 12C23 5.92487 18.0751 1 12 1ZM11.25 7.75C11.25 7.33579 11.5858 7 12 7C12.4142 7 12.75 7.33579 12.75 7.75V12.25C12.75 12.6642 12.4142 13 12 13C11.5858 13 11.25 12.6642 11.25 12.25V7.75ZM11 16C11 15.4477 11.4477 15 12 15H12.01C12.5623 15 13.01 15.4477 13.01 16C13.01 16.5523 12.5623 17 12.01 17H12C11.4477 17 11 16.5523 11 16Z" fill="#000001"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 610 B

View File

@ -0,0 +1,9 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="size=24">
<g id="Path">
<path d="M12 7C12.4143 7 12.75 7.33579 12.75 7.75V12.25C12.75 12.6642 12.4143 13 12 13C11.5858 13 11.25 12.6642 11.25 12.25V7.75C11.25 7.33579 11.5858 7 12 7Z" fill="#000001"/>
<path d="M12 15C11.4478 15 11 15.4477 11 16C11 16.5523 11.4478 17 12 17H12.01C12.5623 17 13.01 16.5523 13.01 16C13.01 15.4477 12.5623 15 12.01 15H12Z" fill="#000001"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.88382 10.0558L10.0555 1.88415C11.1294 0.810196 12.8707 0.810205 13.9446 1.88417L22.1161 10.0558C23.19 11.1298 23.19 12.871 22.1161 13.9449L13.9446 22.1164C12.8706 23.1903 11.1295 23.1903 10.0555 22.1164L1.88385 13.9449C0.809886 12.871 0.809874 11.1298 1.88382 10.0558ZM11.1161 2.94481L2.94448 11.1165C2.45633 11.6046 2.45633 12.3961 2.9445 12.8842L11.1162 21.0557C11.6043 21.5439 12.3958 21.5439 12.8839 21.0557L21.0554 12.8842C21.5435 12.3961 21.5436 11.6046 21.0554 11.1165L12.8839 2.94482C12.3958 2.45665 11.6043 2.45665 11.1161 2.94481Z" fill="#000001"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="16"
height="16"
viewBox="0 0 4.2333334 4.2333334"
version="1.1"
id="svg1"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
sodipodi:docname="amphi-square-logo.svg"
inkscape:export-filename="../../../../../../../Desktop/ProductHunt/amphi-square-logo.png"
inkscape:export-xdpi="1462.0128"
inkscape:export-ydpi="1462.0128"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
inkscape:zoom="23.064727"
inkscape:cx="20.312401"
inkscape:cy="13.700574"
inkscape:window-width="1512"
inkscape:window-height="875"
inkscape:window-x="0"
inkscape:window-y="639"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1">
<linearGradient
id="linearGradient14"
inkscape:collect="always">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop14" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop15" />
</linearGradient>
<linearGradient
id="swatch12"
inkscape:swatch="solid">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop13" />
</linearGradient>
<rect
x="123.66742"
y="261.60416"
width="85.379112"
height="35.370846"
id="rect1" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient14"
id="linearGradient15"
x1="124.86797"
y1="278.84354"
x2="205.72131"
y2="278.84354"
gradientUnits="userSpaceOnUse" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-43.459922,-57.723277)">
<path
d="M 47.661386,61.82914 H 47.06573 v -0.5883 q -0.654488,0.720669 -1.507527,0.720669 -0.853036,0 -1.4634,-0.625072 -0.603011,-0.632423 -0.603011,-1.500169 0,-0.8751 0.610365,-1.492817 0.610362,-0.625072 1.485463,-0.625072 0.882452,0 1.47811,0.713317 v -0.610364 h 0.595656 z m -2.05906,-0.43387 q 0.610365,0 1.051591,-0.441227 0.441227,-0.441229 0.441227,-1.095714 0,-0.661842 -0.433872,-1.103068 -0.433874,-0.448581 -1.066297,-0.448581 -0.625072,0 -1.058947,0.463291 -0.433871,0.455933 -0.433871,1.081003 0,0.625072 0.441226,1.08836 0.441226,0.455936 1.058943,0.455936 z"
id="text1"
style="font-size:26.6667px;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';white-space:pre;fill:#5a8f7b;stroke-width:0.275766"
aria-label="a" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="4.000505mm"
height="4.0710607mm"
viewBox="0 0 4.000505 4.0710607"
version="1.1"
id="svg1"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
sodipodi:docname="amphi-square-logo_nonpaths.svg"
inkscape:export-filename="../../../../../../Desktop/amphi-square-logo.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
inkscape:zoom="11.428174"
inkscape:cx="19.163166"
inkscape:cy="16.231814"
inkscape:window-width="2560"
inkscape:window-height="1412"
inkscape:window-x="1512"
inkscape:window-y="149"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1">
<linearGradient
id="linearGradient14"
inkscape:collect="always">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop14" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop15" />
</linearGradient>
<linearGradient
id="swatch12"
inkscape:swatch="solid">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop13" />
</linearGradient>
<rect
x="123.66742"
y="261.60416"
width="85.379112"
height="35.370846"
id="rect1" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient14"
id="linearGradient15"
x1="124.86797"
y1="278.84354"
x2="205.72131"
y2="278.84354"
gradientUnits="userSpaceOnUse" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-43.459922,-57.723277)">
<path
d="m 139.98799,286.27021 h -2.16 v -2.13333 q -2.37334,2.61333 -5.46668,2.61333 -3.09333,0 -5.30667,-2.26667 -2.18667,-2.29333 -2.18667,-5.44 0,-3.17334 2.21334,-5.41334 2.21333,-2.26667 5.38667,-2.26667 3.2,0 5.36001,2.58667 v -2.21334 h 2.16 z m -7.46668,-1.57333 q 2.21334,0 3.81334,-1.6 1.6,-1.60001 1.6,-3.97334 0,-2.40001 -1.57333,-4.00001 -1.57334,-1.62667 -3.86667,-1.62667 -2.26667,0 -3.84001,1.68001 -1.57333,1.65333 -1.57333,3.92 0,2.26667 1.6,3.94667 1.6,1.65334 3.84,1.65334 z"
id="text1"
style="font-size:26.6667px;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';white-space:pre;fill:#5a8f7b"
transform="matrix(0.20027273,0,0,0.20138729,18.938464,3.5602989)"
aria-label="a" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="21.392445mm"
height="6.6533971mm"
viewBox="0 0 21.392445 6.6533971"
version="1.1"
id="svg1"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
sodipodi:docname="amphi.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
inkscape:zoom="6.1387102"
inkscape:cx="40.399366"
inkscape:cy="10.751444"
inkscape:window-width="1312"
inkscape:window-height="713"
inkscape:window-x="73"
inkscape:window-y="186"
inkscape:window-maximized="0"
inkscape:current-layer="layer1" />
<defs
id="defs1">
<linearGradient
id="linearGradient14"
inkscape:collect="always">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop14" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop15" />
</linearGradient>
<linearGradient
id="swatch12"
inkscape:swatch="solid">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop13" />
</linearGradient>
<rect
x="123.66742"
y="261.60416"
width="85.379112"
height="35.370846"
id="rect1" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient14"
id="linearGradient15"
x1="124.86797"
y1="278.84354"
x2="205.72131"
y2="278.84354"
gradientUnits="userSpaceOnUse" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-43.459922,-56.375664)">
<text
xml:space="preserve"
transform="matrix(0.26458333,0,0,0.26458333,10.421939,-14.074989)"
id="text1"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:26.6667px;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;white-space:pre;shape-inside:url(#rect1);fill:#5a8f7b;fill-opacity:1;fill-rule:nonzero"><tspan
x="123.66797"
y="287.87022"
id="tspan1">amphi</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="21.392445mm"
height="6.6533971mm"
viewBox="0 0 21.392445 6.6533971"
version="1.1"
id="svg1"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
sodipodi:docname="amphi_logo_paths.svg"
inkscape:export-filename="Desktop/amphi_logo_white.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
inkscape:zoom="2.1105281"
inkscape:cx="88.603416"
inkscape:cy="43.827893"
inkscape:window-width="1520"
inkscape:window-height="854"
inkscape:window-x="0"
inkscape:window-y="59"
inkscape:window-maximized="0"
inkscape:current-layer="svg1"
inkscape:export-bgcolor="#ffffff00" />
<defs
id="defs1">
<linearGradient
id="linearGradient1">
<stop
style="stop-color:#23015e;stop-opacity:1;"
offset="0.28057554"
id="stop3" />
<stop
style="stop-color:#59019e;stop-opacity:1;"
offset="0.64028776"
id="stop5" />
<stop
style="stop-color:#f8bd32;stop-opacity:1;"
offset="1"
id="stop4" />
</linearGradient>
<linearGradient
id="linearGradient1-1">
<stop
style="stop-color:#7743db;stop-opacity:1;"
offset="0.19964027"
id="stop1" />
<stop
style="stop-color:#7743db;stop-opacity:0;"
offset="1"
id="stop2" />
</linearGradient>
<linearGradient
id="linearGradient14"
inkscape:collect="always">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop14" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop15" />
</linearGradient>
<linearGradient
id="swatch12"
inkscape:swatch="solid">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop13" />
</linearGradient>
<rect
x="123.66742"
y="261.60416"
width="85.379112"
height="35.370846"
id="rect1" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient14"
id="linearGradient15"
x1="124.86797"
y1="278.84354"
x2="205.72131"
y2="278.84354"
gradientUnits="userSpaceOnUse" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-43.459922,-56.375664)" />
<path
d="m 139.98799,286.27021 h -2.16 v -2.13333 q -2.37334,2.61333 -5.46668,2.61333 -3.09333,0 -5.30667,-2.26667 -2.18667,-2.29333 -2.18667,-5.44 0,-3.17334 2.21334,-5.41334 2.21333,-2.26667 5.38667,-2.26667 3.2,0 5.36001,2.58667 v -2.21334 h 2.16 z m -7.46668,-1.57333 q 2.21334,0 3.81334,-1.6 1.6,-1.60001 1.6,-3.97334 0,-2.40001 -1.57333,-4.00001 -1.57334,-1.62667 -3.86667,-1.62667 -2.26667,0 -3.84001,1.68001 -1.57333,1.65333 -1.57333,3.92 0,2.26667 1.6,3.94667 1.6,1.65334 3.84,1.65334 z m 32.74667,1.57333 h -2.24 v -7.92001 q 0,-1.89333 -0.24,-2.77333 -0.21333,-0.88 -0.98667,-1.46667 -0.74666,-0.61334 -2,-0.61334 -1.22667,0 -2.32,0.8 -1.09334,0.80001 -1.52,2.18667 -0.42667,1.36001 -0.42667,4.05334 v 5.73334 h -2.16 v -7.44001 q 0,-2.18667 -0.24,-3.14667 -0.21334,-0.96 -0.98667,-1.57333 -0.77334,-0.61334 -1.94667,-0.61334 -1.17334,0 -2.24,0.74667 -1.04001,0.72 -1.54667,1.92 -0.50667,1.17334 -0.50667,3.92001 v 6.18667 h -2.18667 v -14.53335 h 2.18667 v 2.05334 q 1.86667,-2.42667 4.66667,-2.42667 1.52,0 2.74667,0.82667 1.25334,0.8 1.78667,2.29333 0.90667,-1.52 2.26667,-2.32 1.36,-0.8 2.88001,-0.8 2.08,0 3.54667,1.46667 1.46666,1.46666 1.46666,5.52 z m 5.68,-12.32001 q 2.16001,-2.58667 5.33334,-2.58667 3.17334,0 5.38668,2.26667 2.21333,2.24 2.21333,5.41334 0,3.17334 -2.18667,5.44 -2.18667,2.26667 -5.28,2.26667 -3.09334,0 -5.46668,-2.61333 v 7.28001 h -2.18667 v -19.68003 h 2.18667 z m 5.33334,10.74668 q 2.18667,0 3.78668,-1.62667 1.62666,-1.65334 1.62666,-3.97334 0,-2.32 -1.6,-3.94667 -1.57333,-1.65334 -3.86667,-1.65334 -2.29334,0 -3.86667,1.62667 -1.54667,1.6 -1.54667,3.97334 0,2.37334 1.6,4.00001 1.6,1.6 3.86667,1.6 z m 23.38668,1.57333 h -2.21334 v -6.93334 q 0,-2.02667 -0.13333,-2.85334 -0.10667,-0.82666 -0.53333,-1.54666 -0.42667,-0.74667 -1.17334,-1.12001 -0.72,-0.4 -1.76,-0.4 -1.01334,0 -1.94667,0.48 -0.93334,0.48001 -1.6,1.33334 -0.66667,0.85333 -0.93334,1.81334 -0.24,0.96 -0.24,3.84 v 5.38667 h -2.21333 v -20.00002 h 2.21333 v 7.65334 q 2.16001,-2.56 5.12001,-2.56 1.57333,0 2.85334,0.82667 1.28,0.8 1.92,2.24 0.64,1.41333 0.64,4.37334 z m 4.34664,-20.00002 q 0.72,0 1.2,0.50667 0.50667,0.48 0.50667,1.2 0,0.69333 -0.50667,1.2 -0.48,0.48 -1.2,0.48 -0.69334,0 -1.2,-0.50667 -0.48,-0.50667 -0.48,-1.17333 0,-0.69334 0.48,-1.2 0.50666,-0.50667 1.2,-0.50667 z m 1.12,20.00002 h -2.21334 v -14.53335 h 2.21334 z"
id="text1"
style="font-size:26.6667px;font-family:'Heiti SC';-inkscape-font-specification:'Heiti SC, Normal';white-space:pre;fill:#43766c;fill-opacity:1"
transform="matrix(0.26458333,0,0,0.26458333,-33.037984,-70.450652)"
aria-label="amphi" />
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16"><path fill="currentColor" fill-rule="evenodd" d="M10.136.803a.75.75 0 011.061 1.06l-.415.416C11.525 2.932 12 3.853 12 4.909c0 .103-.005.205-.014.306.094.016.173.03.238.045a.973.973 0 01.776.951V6.6l1.571-.629a.75.75 0 01.557 1.393L13 8.214v1.13l1.849.246a.75.75 0 11-.198 1.487l-1.659-.221a3.935 3.935 0 01-.426 1.555l2.364.887a.75.75 0 01-.527 1.404l-2.667-1a.752.752 0 01-.12-.058C10.687 14.491 9.384 15 8 15s-2.687-.509-3.616-1.356a.752.752 0 01-.12.058l-2.667 1a.75.75 0 11-.527-1.404l2.364-.887a3.935 3.935 0 01-.426-1.555l-1.659.22a.75.75 0 01-.198-1.486L3 9.343V8.174L.971 7.363a.75.75 0 01.557-1.393L3 6.56V6.21c0-.474.334-.854.776-.95.065-.015.144-.03.238-.046C4.004 5.114 4 5.012 4 4.909c0-1.056.475-1.977 1.218-2.63l-.415-.415A.75.75 0 015.863.803l.695.694a4.318 4.318 0 012.884 0l.694-.694zm-4.63 4.26C6.133 5.026 6.946 5 8 5c1.054 0 1.867.026 2.494.063.004-.051.006-.102.006-.154C10.5 3.793 9.461 2.75 8 2.75S5.5 3.793 5.5 4.91c0 .05.002.102.006.153zM4.5 7.652v-.994C5.043 6.586 6.093 6.5 8 6.5s2.957.086 3.5.158v3.949c0 1.494-1.454 2.893-3.5 2.893-2.046 0-3.5-1.4-3.5-2.893v-.59-2.335-.03z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M15.72 1.22a.75.75 0 111.06 1.06l-1.176 1.177a4.597 4.597 0 011.293 4.256c.612.071 1.008.147 1.258.208.54.133.845.61.845 1.089v1.408l2.987-1.12a.75.75 0 01.526 1.404L19 12.02v2.318l3.343.418a.75.75 0 11-.186 1.488L19 15.85v.4c0 .931-.195 1.816-.545 2.62l3.808 1.428a.75.75 0 01-.526 1.404l-4-1.5a.754.754 0 01-.046-.019C16.415 21.894 14.332 23 12 23s-4.415-1.106-5.69-2.817a.775.775 0 01-.047.02l-4 1.5a.75.75 0 11-.526-1.405l3.808-1.429A6.523 6.523 0 015 16.25v-.4l-3.157.394a.75.75 0 01-.186-1.488L5 14.338V12.02l-3.513-1.318a.75.75 0 01.526-1.404L5 10.418V9.01c0-.479.305-.956.845-1.089.25-.06.646-.137 1.258-.208a4.597 4.597 0 011.293-4.256L7.22 2.28a.75.75 0 011.06-1.06L9.63 2.568A5.196 5.196 0 0112 2c.852 0 1.661.205 2.371.568L15.72 1.22zM8.617 7.586A58.06 58.06 0 0112 7.5c1.4 0 2.508.035 3.383.086.076-.266.117-.547.117-.836 0-1.753-1.524-3.25-3.5-3.25S8.5 4.997 8.5 6.75c0 .29.04.57.117.836zM6.5 11.485v-2.17C7.198 9.188 8.772 9 12 9s4.802.187 5.5.316v6.934c0 2.87-2.433 5.25-5.5 5.25s-5.5-2.38-5.5-5.25v-1.234-3.5-.031z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16"><g fill="currentColor"><path d="M9.424 2.02a.75.75 0 00-.904.556l-2.5 10.5a.75.75 0 001.46.348l2.5-10.5a.75.75 0 00-.556-.904zM11.2 4.24a.75.75 0 011.06-.04l3.5 3.25a.75.75 0 010 1.1l-3.5 3.25a.75.75 0 11-1.02-1.1L14.148 8 11.24 5.3a.75.75 0 01-.04-1.06zM4.76 5.3a.75.75 0 00-1.02-1.1L.24 7.45a.75.75 0 000 1.1l3.5 3.25a.75.75 0 101.02-1.1L1.852 8 4.76 5.3z"/></g></svg>

After

Width:  |  Height:  |  Size: 465 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><g fill="currentColor"><path d="M14.447 3.026a.75.75 0 00-.92.527l-4.5 16.5a.75.75 0 001.447.394l4.5-16.5a.75.75 0 00-.527-.92zM16.207 6.232a.75.75 0 011.06-.025l5.5 5.25a.75.75 0 010 1.085l-5.5 5.25a.75.75 0 01-1.035-1.085L21.164 12l-4.932-4.707a.75.75 0 01-.024-1.06zM7.768 7.293a.75.75 0 00-1.036-1.086l-5.5 5.25a.75.75 0 000 1.085l5.5 5.25a.75.75 0 101.036-1.085L2.836 12l4.932-4.707z"/></g></svg>

After

Width:  |  Height:  |  Size: 496 B

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 -1 16 16"
version="1.1"
id="svg6"
sodipodi:docname="discourse.svg"
width="16"
height="16"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs6" />
<sodipodi:namedview
id="namedview6"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:zoom="11.674683"
inkscape:cx="35.41852"
inkscape:cy="17.173914"
inkscape:window-width="2560"
inkscape:window-height="1412"
inkscape:window-x="1512"
inkscape:window-y="149"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<path
fill="#231f20"
d="m 8.1664809,-0.77089887 c -4.2475396,0 -7.82385918,3.44358407 -7.82385918,7.69263207 v 7.9656448 l 7.82235048,-0.0075 c 4.2475398,0 7.6926318,-3.57632 7.6926318,-7.8238592 0,-4.2475386 -3.448109,-7.82687502 -7.6911231,-7.82687502 z"
id="path1"
style="stroke-width:0.150836" />
<path
fill="#fff9ae"
d="M 8.241899,2.2066022 A 4.7694318,4.7694318 0 0 0 4.0501685,9.2461149 L 3.1873871,12.021495 6.2855569,11.321616 A 4.7679234,4.7679234 0 1 0 8.2464244,2.2066022 Z"
id="path2"
style="stroke-width:0.150836" />
<path
fill="#00aeef"
d="M 12.024864,4.0739508 A 4.766415,4.766415 0 0 1 6.2855569,11.314075 L 3.1873871,12.023004 6.3413666,11.650439 A 4.766415,4.766415 0 0 0 12.024864,4.0739508 Z"
id="path3"
style="stroke-width:0.150836" />
<path
fill="#00a94f"
d="M 11.146999,3.1945775 A 4.766415,4.766415 0 0 1 6.1950553,10.994303 L 3.1873871,12.023004 6.2855569,11.321616 A 4.766415,4.766415 0 0 0 11.146999,3.1945775 Z"
id="path4"
style="stroke-width:0.150836" />
<path
fill="#f15d22"
d="M 4.3352485,9.3516997 A 4.7679234,4.7679234 0 0 1 12.02788,4.0724425 4.7679234,4.7679234 0 0 0 4.0501685,9.2461149 L 3.1873871,12.021495 Z"
id="path5"
style="stroke-width:0.150836" />
<path
fill="#e31b23"
d="M 4.0501685,9.2461149 A 4.7679234,4.7679234 0 0 1 11.146999,3.1945775 4.7679234,4.7679234 0 0 0 3.7560386,9.1722049 L 3.1888955,12.023004 Z"
id="path6"
style="stroke-width:0.150836" />
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16"><path fill="currentColor" fill-rule="evenodd" d="M4.25 1A2.25 2.25 0 002 3.25v9.5A2.25 2.25 0 004.25 15h8.5c.69 0 1.25-.56 1.25-1.25V2.25C14 1.56 13.44 1 12.75 1h-8.5zM3.5 12.75c0 .414.336.75.75.75h8.25v-2H4.25a.75.75 0 00-.75.75v.5zm0-2.622c.235-.083.487-.128.75-.128h8.25V2.5H4.25a.75.75 0 00-.75.75v6.878z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 432 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M5.75 1A2.75 2.75 0 003 3.75v16.5A2.75 2.75 0 005.75 23h13.5A1.75 1.75 0 0021 21.25V2.75A1.75 1.75 0 0019.25 1H5.75zM19.5 17.5V2.75a.25.25 0 00-.25-.25H5.75c-.69 0-1.25.56-1.25 1.25V17.8c.375-.192.8-.3 1.25-.3H19.5zm-15 2.75c0 .69.56 1.25 1.25 1.25h13.5a.25.25 0 00.25-.25V19H5.75c-.69 0-1.25.56-1.25 1.25z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 479 B

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
version="1.1"
id="svg1"
sodipodi:docname="github.svg"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:zoom="22.761807"
inkscape:cx="9.6653136"
inkscape:cy="3.0972937"
inkscape:window-width="1512"
inkscape:window-height="856"
inkscape:window-x="0"
inkscape:window-y="639"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M 8.012013,0.18564182 C 3.5853759,0.18564182 0,3.7710177 0,8.1976548 0,11.74297 2.2934387,14.737462 5.4782139,15.799053 c 0.4006007,0.07011 0.550826,-0.170255 0.550826,-0.380571 0,-0.190286 -0.01001,-0.821232 -0.01001,-1.492238 C 4.0060066,14.2968 3.4852256,13.435508 3.3249854,12.984833 3.2348499,12.754488 2.8442646,12.043421 2.5037541,11.853136 2.2233337,11.702911 1.8227329,11.332355 2.4937342,11.322339 c 0.630946,-0.01001 1.0816218,0.580873 1.2318471,0.821233 0.7210812,1.211817 1.872808,0.871305 2.3334988,0.660991 0.070106,-0.520782 0.2804203,-0.871307 0.5107657,-1.071607 -1.7826729,-0.200301 -3.6454659,-0.891337 -3.6454659,-3.9559319 0,-0.8713064 0.3104655,-1.5923875 0.8212313,-2.1532284 -0.08012,-0.2003004 -0.3605405,-1.0215317 0.08012,-2.1231835 0,0 0.6710061,-0.2103153 2.2033036,0.8212314 0.640961,-0.1802704 1.3219821,-0.2704055 2.0030033,-0.2704055 0.6810215,0 1.3620422,0.090136 2.0030029,0.2704055 1.532298,-1.0415618 2.203304,-0.8212314 2.203304,-0.8212314 0.440661,1.1016518 0.160241,1.9228831 0.08012,2.1231835 0.510765,0.5608409 0.82123,1.271907 0.82123,2.1532284 0,3.0746099 -1.872808,3.7556309 -3.6554799,3.9559319 0.2904354,0.250375 0.5408109,0.731096 0.5408109,1.482223 0,1.071606 -0.01002,1.932898 -0.01002,2.203303 0,0.210316 0.150226,0.460691 0.550826,0.380571 3.164749,-1.061591 5.458188,-4.066097 5.458188,-7.6013982 6e-6,-4.4266371 -3.585369,-8.01201298 -8.012007,-8.01201298 z"
fill="#1b1f23"
id="path1"
style="stroke-width:1.0015" />
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M10.25 2.5A1.75 1.75 0 008.5 4.25v3.5c0 .966.784 1.75 1.75 1.75H11V11H3a.75.75 0 000 1.5h3.5v2H5.25a1.75 1.75 0 00-1.75 1.75v3.5c0 .966.784 1.75 1.75 1.75h3.5a1.75 1.75 0 001.75-1.75v-3.5a1.75 1.75 0 00-1.75-1.75H8v-2h8v2h-.75a1.75 1.75 0 00-1.75 1.75v3.5c0 .966.784 1.75 1.75 1.75h3.5a1.75 1.75 0 001.75-1.75v-3.5a1.75 1.75 0 00-1.75-1.75H17.5v-2H21a.75.75 0 000-1.5h-8.5V9.5h1.25a1.75 1.75 0 001.75-1.75v-3.5a1.75 1.75 0 00-1.75-1.75h-3.5zM10 4.25a.25.25 0 01.25-.25h3.5a.25.25 0 01.25.25v3.5a.25.25 0 01-.25.25h-3.5a.25.25 0 01-.25-.25v-3.5zm-5 12a.25.25 0 01.25-.25h3.5a.25.25 0 01.25.25v3.5a.25.25 0 01-.25.25h-3.5a.25.25 0 01-.25-.25v-3.5zM15.25 16a.25.25 0 00-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 00.25-.25v-3.5a.25.25 0 00-.25-.25h-3.5z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 924 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 28 28"><path fill="#ED225D" stroke="#ED225D" stroke-miterlimit="10" d="M16.909 10.259l8.533-2.576 1.676 5.156-8.498 2.899 5.275 7.48-4.447 3.225-5.553-7.348-5.408 7.155-4.318-3.289 5.275-7.223L.88 12.647l1.678-5.16 8.598 2.771V1.364h5.754v8.895z"/></svg>

After

Width:  |  Height:  |  Size: 330 B

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="171.063px" height="171.06px" viewBox="0 0 191.063 191.06" enable-background="new 0 0 191.063 191.06"
xml:space="preserve">
<path fill="#ED225D" d="M58.197,108.205c-1.354-1.748-3.064-3.162-5.135-4.238c-2.07-1.074-4.496-1.611-7.281-1.611
c-2.627,0-4.977,0.557-7.045,1.672c-2.07,1.115-3.842,2.549-5.312,4.297c-1.475,1.752-2.588,3.742-3.344,5.971
c-0.758,2.229-1.133,4.459-1.133,6.686c0,2.229,0.375,4.438,1.133,6.625c0.756,2.191,1.869,4.16,3.344,5.912
c1.471,1.75,3.242,3.164,5.312,4.236c2.068,1.076,4.418,1.611,7.045,1.611c2.785,0,5.211-0.555,7.281-1.67s3.781-2.547,5.135-4.299
c1.352-1.75,2.367-3.74,3.045-5.969c0.676-2.229,1.014-4.457,1.014-6.686s-0.338-4.438-1.014-6.627
C60.564,111.927,59.549,109.957,58.197,108.205z"/>
<path fill="#ED225D" d="M0,0v191.06h191.063V0H0z M74.852,132.621c-1.312,3.701-3.184,6.924-5.611,9.67s-5.371,4.938-8.834,6.566
c-3.463,1.631-7.385,2.447-11.76,2.447c-4.061,0-7.781-0.836-11.164-2.506c-3.385-1.672-5.99-3.939-7.82-6.807h-0.238v36.295H15.098
V92.328h13.729v7.998h0.359c0.715-1.113,1.65-2.248,2.805-3.402s2.568-2.188,4.24-3.105c1.67-0.912,3.561-1.67,5.67-2.268
c2.107-0.596,4.477-0.896,7.104-0.896c4.059,0,7.799,0.777,11.223,2.328c3.422,1.555,6.367,3.684,8.836,6.389
c2.465,2.707,4.375,5.891,5.73,9.551c1.352,3.662,2.029,7.602,2.029,11.82S76.166,128.919,74.852,132.621z M136.422,134.531
c-1.633,3.701-3.842,6.826-6.627,9.371c-2.787,2.549-6.051,4.5-9.791,5.852s-7.721,2.029-11.938,2.029
c-7.086,0-13.057-1.654-17.91-4.955c-3.34-2.271-6.043-5.133-8.139-8.553l10.367-9.715l0.16-0.059
c1.193,3.344,3.182,6.029,5.969,8.059c2.785,2.029,6.09,3.045,9.91,3.045c2.148,0,4.178-0.357,6.088-1.076
c1.912-0.715,3.582-1.748,5.016-3.104c1.432-1.352,2.566-3.045,3.402-5.072c0.836-2.029,1.254-4.318,1.254-6.865
c0-3.264-0.559-5.971-1.672-8.119c-1.115-2.148-2.566-3.881-4.357-5.193s-3.803-2.229-6.029-2.746
c-2.229-0.518-4.498-0.775-6.805-0.775c-1.594,0-3.283,0.119-5.074,0.357c-1.791,0.24-3.543,0.578-5.254,1.016
c-1.713,0.438-3.383,0.936-5.014,1.49c-1.633,0.559-3.086,1.156-4.357,1.791l1.432-46.201h48.113V78h-34.504l-0.834,18.268
c1.352-0.398,2.963-0.676,4.834-0.838c1.871-0.156,3.562-0.238,5.074-0.238c4.139,0,7.979,0.598,11.521,1.791
c3.541,1.193,6.627,2.926,9.252,5.193c2.629,2.27,4.676,5.057,6.148,8.357c1.473,3.305,2.209,7.104,2.209,11.402
C138.867,126.632,138.051,130.83,136.422,134.531z M173.81,87.076l-5.243,3.802l-5.449-7.211l-5.312,7.026l-5.107-3.89l5.171-7.08
l-8.392-3.027l1.981-6.095l8.419,2.714v-8.708h6.754v8.721l8.357-2.522l1.979,6.09l-8.333,2.843L173.81,87.076z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16"><path fill="currentColor" fill-rule="evenodd" d="M2.75 2.5A1.75 1.75 0 001 4.25v1C1 6.216 1.784 7 2.75 7h1a1.75 1.75 0 001.732-1.5H6.5a.75.75 0 01.75.75v3.5A2.25 2.25 0 009.5 12h1.018c.121.848.85 1.5 1.732 1.5h1A1.75 1.75 0 0015 11.75v-1A1.75 1.75 0 0013.25 9h-1a1.75 1.75 0 00-1.732 1.5H9.5a.75.75 0 01-.75-.75v-3.5A2.25 2.25 0 006.5 4H5.482A1.75 1.75 0 003.75 2.5h-1zM2.5 4.25A.25.25 0 012.75 4h1a.25.25 0 01.25.25v1a.25.25 0 01-.25.25h-1a.25.25 0 01-.25-.25v-1zm9.75 6.25a.25.25 0 00-.25.25v1c0 .138.112.25.25.25h1a.25.25 0 00.25-.25v-1a.25.25 0 00-.25-.25h-1z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 687 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M4.75 4.5A2.25 2.25 0 002.5 6.75v1A2.25 2.25 0 004.75 10h1a2.25 2.25 0 002.236-2H9.82c.967 0 1.75.784 1.75 1.75v4.5a3.25 3.25 0 003.25 3.25h1.195a2.25 2.25 0 002.236 2h1a2.25 2.25 0 002.25-2.25v-1A2.25 2.25 0 0019.25 14h-1a2.25 2.25 0 00-2.236 2h-1.195a1.75 1.75 0 01-1.75-1.75v-4.5A3.25 3.25 0 009.82 6.5H7.986a2.25 2.25 0 00-2.236-2h-1zM4 6.75A.75.75 0 014.75 6h1a.75.75 0 01.75.75v1a.75.75 0 01-.75.75h-1A.75.75 0 014 7.75v-1zm14.25 8.75a.75.75 0 00-.75.75v1c0 .414.336.75.75.75h1a.75.75 0 00.75-.75v-1a.75.75 0 00-.75-.75h-1z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 702 B

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 3.385 3.3870001"
version="1.1"
id="svg1"
sodipodi:docname="pipeline.svg"
xml:space="preserve"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
width="3.385"
height="3.3870001"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1" /><sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:zoom="100.34401"
inkscape:cx="3.9663553"
inkscape:cy="2.9548351"
inkscape:window-width="1392"
inkscape:window-height="922"
inkscape:window-x="0"
inkscape:window-y="75"
inkscape:window-maximized="0"
inkscape:current-layer="g3" /><g
id="g3"
transform="matrix(0.15016129,0,0,0.15020517,-2.9946236,-2.9614603)"><g
class="jp-console-icon-background-color jp-icon-selectable"
fill="#0288d1"
id="g1"
style="stroke:none;fill:#f67d4e;fill-opacity:1"
transform="matrix(0.14098804,0,0,0.14120855,17.135548,16.937072)"><path
d="M 19.947973,19.721982 H 179.795 V 179.51779 H 19.947973 Z"
id="path1-3"
style="stroke:none;stroke-width:0.999197;fill:#f67d4e;fill-opacity:1" /></g><g
class="jp-console-icon-color jp-icon-selectable-inverse"
fill="#ffffff"
id="g2" /><path
d="m 26.254267,38.606198 c -1.505421,0 -2.7258,-1.206751 -2.7258,-2.695359 0,-1.488609 1.220379,-2.695359 2.7258,-2.695359 1.234552,0 2.27742,0.811533 2.612724,1.924561 l 4.396475,1.16e-4 v -1.539668 l 1.5576,-4.99e-4 v -4.432695 l -1.746849,-1.728111 h -4.483552 v 1.540699 h -4.672798 v -4.620617 h 4.672798 v 1.539712 h 4.483552 l 2.525647,-2.496673 3.304135,3.267269 -2.525334,2.496181 v 4.434237 l 1.557598,4.99e-4 v 4.620619 h -4.672797 v -1.540746 l -4.396335,6.66e-4 c -0.335156,1.113262 -1.378132,1.925102 -2.612864,1.925102 z m 0,-3.850513 c -0.645182,0 -1.1682,0.517124 -1.1682,1.155154 0,0.637953 0.523018,1.155153 1.1682,1.155153 0.64518,0 1.168198,-0.5172 1.168198,-1.155153 0,-0.63803 -0.523018,-1.155154 -1.168198,-1.155154 z m 10.124398,0.38505 h -1.557599 v 1.540205 h 1.557599 z m -0.778801,-9.560248 -1.10138,1.089087 1.10138,1.089095 1.101378,-1.089095 z m -8.566798,0.318985 h -1.5576 v 1.540205 h 1.5576 z"
id="path1"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.774439" /></g></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 3.385 3.3870001"
version="1.1"
id="svg1"
sodipodi:docname="pipeline_negative.svg"
xml:space="preserve"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
width="3.385"
height="3.3870001"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1" /><sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:zoom="100.34401"
inkscape:cx="3.9663555"
inkscape:cy="1.694172"
inkscape:window-width="1920"
inkscape:window-height="983"
inkscape:window-x="1512"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="g3" /><g
id="g3"
transform="matrix(0.15016129,0,0,0.15020517,-2.9946236,-2.9614603)"><g
class="jp-console-icon-background-color jp-icon-selectable"
fill="#0288d1"
id="g1"
style="stroke:none;fill:#7743db;fill-opacity:0"
transform="matrix(0.14098804,0,0,0.14120855,17.135548,16.937072)"><path
d="M 19.947973,19.721982 H 179.795 V 179.51779 H 19.947973 Z"
id="path1-3"
style="stroke:none;stroke-width:0.999197;fill:#7743db;fill-opacity:0" /></g><g
class="jp-console-icon-color jp-icon-selectable-inverse"
fill="#ffffff"
id="g2" /><path
d="m 26.254267,23.402305 c -1.505421,0 -2.7258,1.206751 -2.7258,2.695359 0,1.488609 1.220379,2.695359 2.7258,2.695359 1.234552,0 2.27742,-0.811533 2.612724,-1.924561 l 4.396475,-1.16e-4 v 1.539668 l 1.5576,4.99e-4 v 4.432695 l -1.746849,1.728111 H 28.590665 V 33.02862 h -4.672798 v 4.620617 h 4.672798 v -1.539712 h 4.483552 l 2.525647,2.496673 3.304135,-3.267269 -2.525334,-2.496181 v -4.434237 l 1.557598,-4.99e-4 v -4.620619 h -4.672797 v 1.540746 l -4.396335,-6.66e-4 c -0.335156,-1.113262 -1.378132,-1.925102 -2.612864,-1.925102 z m 0,3.850513 c -0.645182,0 -1.1682,-0.517124 -1.1682,-1.155154 0,-0.637953 0.523018,-1.155153 1.1682,-1.155153 0.64518,0 1.168198,0.5172 1.168198,1.155153 0,0.63803 -0.523018,1.155154 -1.168198,1.155154 z m 10.124398,-0.38505 h -1.557599 v -1.540205 h 1.557599 z m -0.778801,9.560248 -1.10138,-1.089087 1.10138,-1.089095 1.101378,1.089095 z m -8.566798,-0.318985 h -1.5576 v -1.540205 h 1.5576 z"
id="path1"
style="fill:#f67d4e;fill-opacity:1;stroke:none;stroke-width:0.774439" /></g></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><g fill="currentColor"><path d="M16.78 8.22a.75.75 0 010 1.06l-5.499 5.5a.75.75 0 01-1.061 0l-2.5-2.5a.75.75 0 111.06-1.06l1.97 1.97 4.97-4.97a.75.75 0 011.06 0z"/><path fill-rule="evenodd" d="M11.04 1.307a2.75 2.75 0 011.92 0l6.25 2.33A2.75 2.75 0 0121 6.214V12c0 2.732-1.462 5.038-3.104 6.774-1.65 1.744-3.562 3-4.65 3.642a2.437 2.437 0 01-2.493 0c-1.087-.643-3-1.898-4.65-3.642C4.463 17.038 3 14.732 3 12V6.214a2.75 2.75 0 011.79-2.577l6.25-2.33zm1.397 1.406a1.25 1.25 0 00-.874 0l-6.25 2.33a1.25 1.25 0 00-.813 1.17V12c0 2.182 1.172 4.136 2.693 5.744 1.514 1.6 3.294 2.772 4.323 3.38.304.18.664.18.968 0 1.03-.608 2.809-1.78 4.323-3.38C18.327 16.136 19.5 14.182 19.5 12V6.214a1.25 1.25 0 00-.813-1.171l-6.25-2.33z" clip-rule="evenodd"/></g></svg>

After

Width:  |  Height:  |  Size: 845 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16"><g fill="currentColor"><path d="M4.24 5.8a.75.75 0 001.06-.04l1.95-2.1v6.59a.75.75 0 001.5 0V3.66l1.95 2.1a.75.75 0 101.1-1.02l-3.25-3.5a.75.75 0 00-1.101.001L4.2 4.74a.75.75 0 00.04 1.06z"/><path d="M1.75 9a.75.75 0 01.75.75v3c0 .414.336.75.75.75h9.5a.75.75 0 00.75-.75v-3a.75.75 0 011.5 0v3A2.25 2.25 0 0112.75 15h-9.5A2.25 2.25 0 011 12.75v-3A.75.75 0 011.75 9z"/></g></svg>

After

Width:  |  Height:  |  Size: 472 B

View File

@ -0,0 +1,5 @@
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/

View File

@ -0,0 +1,8 @@
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
import './base.css';
import './output.css';

View File

@ -0,0 +1,157 @@
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.elyra-browseFileDialog .jp-Dialog-content {
height: 400px;
width: 600px;
}
.launcher-body {
padding: 20px;
width:80%;
margin: 0 auto;
/* Center horizontally */
}
.launcher-content {
max-width: 1200px;
margin: auto;
width: 100%;
}
.launcher-title {
margin-top: 32px;
font-size: 36px;
font-weight: bold;
color: #1a202c;
display: flex;
align-items: center;
}
.launcher-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-top: 28px;
}
.launcher-card {
background-color: white;
padding: 16px;
border-radius: 4px;
/* border: 1px solid #e2e8f0; */
}
.launcher-card-header h3 {
font-size: 24px;
font-weight: bold;
color: #1a202c;
}
.launcher-card-links {
display: flex;
flex-wrap: wrap;
margin: -4px;
}
.launcher-card-links li {
padding: 4px;
margin-bottom: 20px;
}
.launcher-card-links a {
font-size: 12px;
font-weight: 500;
color: #3182ce;
text-decoration: none;
}
.launcher-card-list {
margin-top: 16px;
list-style: none;
padding: 0;
}
.launcher-card-list li {
margin-bottom: 20px;
}
.launcher-card-item {
display: flex;
align-items: center;
padding: 16px;
border-radius: 4px;
border: 1px solid #F2F4F7;
text-decoration: none;
color: inherit;
transition: all 0.3s;
}
.launcher-card-item:hover {
border-color: #a0aec0;
background-color: #f7fafc;
}
.launcher-icon {
display: flex;
align-items: center;
justify-content: center;
width: 64px;
height: 64px;
border-radius: 50%;
}
.alert-box {
margin-top: 20px;
padding: 16px;
border-radius: 8px;
border: 1px solid #e2e8f0;
background-color: white;
}
.alert-content {
display: flex;
align-items: start;
gap: 16px;
}
.alert-icon {
color: #4a5568;
}
.alert-text h2 {
font-size: 20px;
font-weight: bold;
color: #1a202c;
}
.alert-text p {
margin-top: 8px;
font-size: 14px;
color: #4a5568;
}
.alert-close-btn {
color: #a0aec0;
transition: color 0.3s;
background: none;
border: none;
cursor: pointer;
}
.alert-close-btn:hover {
color: #718096;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}

View File

@ -0,0 +1,26 @@
{
"extends": "../../tsconfigbase",
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"composite": true,
"declaration": true,
"esModuleInterop": true,
"incremental": true,
"jsx": "react",
"module": "esnext",
"moduleResolution": "node",
"noEmitOnError": true,
"noImplicitAny": true,
"noUnusedLocals": false,
"preserveWatchOutput": true,
"resolveJsonModule": true,
"outDir": "lib",
"rootDir": "src",
"strict": true,
"strictNullChecks": false,
"target": "es2018",
"types": [],
"skipLibCheck": true
},
"include": ["src/**/*"]
}

88
amphi-etl/pyproject.toml Normal file
View File

@ -0,0 +1,88 @@
[build-system]
requires = ["hatchling>=1.5.0", "jupyterlab>=4.0.0,<5", "hatch-nodejs-version>=0.3.2"]
build-backend = "hatchling.build"
[project]
name = "amphi-etl"
description="Amphi is a low-code and python-based data manipulation tool"
readme = "README.md"
license = { file = "LICENSE" }
requires-python = ">=3.8"
classifiers = [
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dynamic = ["version", "authors", "keywords", "scripts", "dependencies"]
[project.urls]
Documentation = "https://docs.amphi.ai"
Homepage = "https://amphi.ai"
[tool.hatch.version]
source = "nodejs"
[tool.hatch.metadata.hooks.nodejs]
fields = ["description", "authors", "urls"]
[tool.hatch.build.targets.sdist]
artifacts = ["amphi"]
exclude = [".github", "binder"]
include = [
"amphi",
"config/labconfig/*.json",
"config/settings/*.json"
]
[tool.hatch.build.targets.wheel]
include = [
"/amphi",
]
# share/jupyter/labextensions is present in the Python environment and is the
# designated folder from wich jupterlab/lite takes its extensions
[tool.hatch.build.targets.wheel.shared-data]
amphi = "share/jupyter/labextensions/@amphi"
"config/labconfig" = "etc/jupyter/labconfig"
"config/settings" = "share/jupyter/lab/settings"
[tool.hatch.build.hooks.version]
path = "amphi/_version.py"
[tool.hatch.build.hooks.jupyter-builder]
dependencies = ["hatch-jupyter-builder>=0.5"]
build-function = "hatch_jupyter_builder.npm_builder"
ensured-targets = [
"amphi/ui-component/static/style.js",
"amphi/ui-component/package.json",
]
skip-if-exists = ["amphi/ui-component/static/style.js"]
[tool.hatch.build.hooks.jupyter-builder.build-kwargs]
build_cmd = "build:prod"
npm = ["jlpm"]
[tool.hatch.build.hooks.jupyter-builder.editable-build-kwargs]
build_cmd = "install:extension"
npm = ["jlpm"]
source_dir = "amphi"
build_dir = "amphi"
[tool.jupyter-releaser.options]
version_cmd = "hatch version"
[tool.jupyter-releaser.hooks]
before-build-npm = [
"python -m pip install 'jupyterlab>=4.0.0,<5'",
"jlpm",
"jlpm run build:prod"
]
before-build-python = ["jlpm clean:all"]
[tool.check-wheel-contents]
ignore = ["W002"]

View File

@ -0,0 +1,4 @@
jupyterlab==4.3.2
#jupyterlab-amphi==0.8.23
pandas==2.2.1
../jupyterlab-amphi

48
amphi-etl/setup.py Normal file
View File

@ -0,0 +1,48 @@
from setuptools import setup, find_packages
import os
# Collect files recursively from a directory
def collect_files(src_dir, dest_dir):
files = []
for root, dirs, filenames in os.walk(src_dir):
for dirname in dirs:
dirpath = os.path.join(root, dirname)
files.append((os.path.join(dest_dir, os.path.relpath(dirpath, src_dir)), []))
for filename in filenames:
src_file = os.path.join(root, filename)
dest_file = os.path.relpath(src_file, src_dir)
files.append((os.path.join(dest_dir, os.path.dirname(dest_file)), [src_file]))
return files
# Define the data files structure
data_files = (
collect_files('amphi', 'share/jupyter/labextensions/@amphi') +
collect_files('config/labconfig', 'etc/jupyter/labconfig') +
collect_files('config/settings', 'share/jupyter/lab/settings')
)
setup(
name='amphi-etl',
version='0.8.23',
description='Open-source and Python-based ETL',
author='Thibaut Gourdel',
author_email='tgourdel@amphi.ai',
license='ELv2',
install_requires=[
'jupyterlab==4.3.3',
'jupyterlab-amphi==0.8.23',
'pandas==2.2.1'
],
keywords=[], # Added an empty list for keywords to resolve the dynamic 'keywords' issue.
packages=find_packages(include=['amphi', 'amphi.theme-light', 'amphi.ui-component', 'config', 'packages']), # Custom package discovery.
include_package_data=True, # Include non-Python files specified in MANIFEST.in
package_data={
'amphi': ['theme-light/*', 'ui-component/*'], # Include built extensions
},
data_files=data_files,
entry_points={
'console_scripts': [
'amphi=amphi.main:main',
],
}
)

View File

@ -0,0 +1,4 @@
{
"extends": "./tsconfigbase",
"include": ["packages/**/*"]
}

View File

@ -0,0 +1,22 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"composite": true,
"declaration": true,
"esModuleInterop": true,
"incremental": true,
"jsx": "react",
"module": "esnext",
"moduleResolution": "node",
"noEmitOnError": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"preserveWatchOutput": true,
"resolveJsonModule": true,
"strict": true,
"skipLibCheck": true,
"strictNullChecks": true,
"target": "es2019",
"types": []
}
}

12
build.sh Normal file
View File

@ -0,0 +1,12 @@
# 切换到脚本所在目录
cd "$(dirname "$0")"/jupyterlab-amphi
jlpm install
jlpm run build
python -m pip install .
# 切换到脚本所在目录
cd "$(dirname "$0")"/amphi-etl
python -m pip install -r requirements.txt

54
jupyterlab-amphi/.gitignore vendored Normal file
View File

@ -0,0 +1,54 @@
MANIFEST
amphi
build
dist
lib
*_env
*_venv
node_modules
.cache
*.py[co]
.pytest_cache
__pycache__
*.egg-info
*~
*.bak
.ipynb_checkpoints
.DS_Store
\#*#
.#*
.jupyter_ystore.db
*.swp
*.map
coverage/
tests/**/coverage
tests/**/.cache-loader
docs/_build
docs/api
docs/source/_build
lerna-debug.log
yarn-error.log
yarn.lock
junit.xml
*.tsbuildinfo
.yarn/
# jetbrains IDE stuff
*.iml
.idea/
# ms IDE stuff
*.code-workspace
.history
.vscode
# dev
build.sh
start.sh
# requirements.txt

Binary file not shown.

View File

@ -0,0 +1 @@
nodeLinker: node-modules

35
jupyterlab-amphi/LICENSE Normal file
View File

@ -0,0 +1,35 @@
Elastic License 2.0 \(ELv2\)
**Acceptance** By using the software, you agree to all of the terms and conditions below.
**Copyright License** The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject to the limitations and conditions below
**Limitations** You may not provide the software to third parties as a hosted or managed service, where the service provides users with access to any substantial set of the features or functionality of the software.
You may not move, change, disable, or circumvent the license key functionality in the software, and you may not remove or obscure any functionality in the software that is protected by the license key.
You may not alter, remove, or obscure any licensing, copyright, or other notices of the licensor in the software. Any use of the licensors trademarks is subject to applicable law.
**Patents** The licensor grants you a license, under any patent claims the licensor can license, or becomes able to license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case subject to the limitations and conditions in this license. This license does not cover any patent claims that you cause to be infringed by modifications or additions to the software. If you or your company make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
**Notices** You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms.
If you modify the software, you must include in any modified copies of the software prominent notices stating that you have modified the software.
**No Other Rights** These terms do not imply any licenses other than those expressly granted in these terms.
**Termination** If you use the software in violation of these terms, such use is not licensed, and your licenses will automatically terminate. If the licensor provides you with a notice of your violation, and you cease all violation of this license no later than 30 days after you receive that notice, your licenses will be reinstated retroactively. However, if you violate these terms after such reinstatement, any additional violation of these terms will cause your licenses to terminate automatically and permanently.
**No Liability** As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.
**Definitions** The _licensor_ is the entity offering these terms, and the _software_ is the software the licensor makes available under these terms, including any portion of it.
_you_ refers to the individual or entity agreeing to these terms.
_your company_ is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. _control_ means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
_your licenses_ are all the licenses granted to you for the software under these terms.
_use_ means anything you do with the software requiring one of your licenses.
_trademark_ means trademarks, service marks, and similar rights.

View File

@ -0,0 +1,24 @@
include LICENSE
include *.md
include pyproject.toml
include package.json
include install.json
include ts*.json
include yarn.lock
graft amphi/*
# Javascript files
graft packages/**
graft style
prune **/node_modules
prune lib
prune binder
# Patterns to exclude from any directory
global-exclude *~
global-exclude *.pyc
global-exclude *.pyo
global-exclude .git
global-exclude .ipynb_checkpoints

View File

@ -0,0 +1,44 @@
# Amphi for Jupyterlab
![jupyter-lab-amph-screenshot](https://github.com/amphi-ai/jupyterlab-amphi/assets/15718239/31ce75b5-745e-4642-be4e-29e306e97b0b)
Amphi for JupyterLab is a Micro ETL designed for ingesting, cleansing, and processing data from files and databases.
Amphi addresses use cases such as data extraction from structured and unstructured data, data preparation and enrichment, and data processing for LLMs-based systems.
Use Amphi within the Jupyterlab environment to design your data pipelines with a graphical user-interface and generate native Python code you can deploy anywhere.
- 📚 [Documentation](https://docs.amphi.ai)
- 🚀 [Getting Started](https://docs.amphi.ai/getting-started/installation)
📣 **Beta release**
Amphi for Jupyterlab is currently in beta. To start with Amphi, see below for install instructions.
As Amphi is in beta version, we welcome feedback and suggestions. Join the [Slack community](https://join.slack.com/t/amphi-ai/shared_invite/zt-2ci2ptvoy-FENw8AW4ISDXUmz8wcd3bw) or reach out directly at hello@amphi.ai.
## Requirements
- JupyterLab >= 4.0
## Install Jupyterlab + Amphi
If you want to launch Jupyterlab + Amphi, you can run the following commands. It is recommended to a virtual environment (venv or conda for example).
To install perform the following steps, with _pip_:
```bash
pip install --upgrade jupyterlab jupyterlab-amphi
```
For more installation instructions, visit [the docs](https://docs.amphi.ai/getting-started/installation).
## Install Amphi on an existing Jupyterlab instance
If you already have a Jupyterlab instance, just install the amphi package:
```bash
pip install --upgrade jupyterlab-amphi
```
Alternatively, you can search in the Extension Manager for Amphi.
For more information, see [docs](https://docs.amphi.ai).

View File

@ -0,0 +1,2 @@
"""source of truth for ``amphi``` version."""
__version__ = "0.8.23"

77
jupyterlab-amphi/batch.py Normal file
View File

@ -0,0 +1,77 @@
import os
# 定义英文到中文的映射
translations = {
"S3 File Input": "S3文件输入",
"MySQL Input": "MySQL输入",
"Postgres Input": "Postgres输入",
"Oracle Input": "Oracle输入",
"SQL Server Input": "SQL服务器输入",
"Snowflake Input": "Snowflake输入",
"ODBC Input": "ODBC输入",
"System Information": "系统信息",
"Rename Columns": "重命名列",
"Select Columns": "选择列",
"Filter Rows": "筛选行",
"Sort Rows": "排序行",
"Split Column": "拆分列",
"Parse & Extract": "解析和提取",
"Formula Row": "公式行",
"Join Datasets": "合并数据集",
"Concatenate": "连接",
"Aggregate Rows": "聚合行",
"Pivot Dataset": "数据透视表",
"Transpose Dataset": "数据转置",
"Deduplicate Rows": "去重行",
"Type Converter": "类型转换器",
"DateTime Converter": "日期时间转换器",
"Data Cleansing": "数据清洗",
"Sample Datasets": "示例数据集",
"Python Transforms": "Python转换",
"CSV File Output": "CSV文件输出",
"JSON File Output": "JSON文件输出",
"Excel File Output": "Excel文件输出",
"Parquet File Output": "Parquet文件输出",
"XML File Output": "XML文件输出",
"Python Output": "Python输出",
"S3 File Output": "S3文件输出",
"MySQL Output": "MySQL输出",
"Postgres Output": "Postgres输出",
"Snowflake Output": "Snowflake输出",
"Oracle Output": "Oracle输出",
"Summary": "摘要",
"Frequency Analysis": "频率分析",
"Expand JSON List": "展开JSON列表",
"Flatten JSON": "扁平化JSON",
"OpenAI Prompt": "OpenAI提示",
"Ollama Prompt": "Ollama提示",
"Annotation": "注释",
"Form Example": "表单示例"
}
def replace_text_in_file(file_path, translations):
print(f"Processe {file_path}")
try:
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
for english, chinese in translations.items():
content = content.replace("\"" + english + "\"", "\"" + chinese + "\"")
with open(file_path, 'w', encoding='utf-8') as file:
file.write(content)
print(f"Processed {file_path}")
except Exception as e:
print(f"Error processing {file_path}: {e}")
def process_directory(directory):
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith(".tsx"):
file_path = os.path.join(root, file)
replace_text_in_file(file_path, translations)
# 指定要处理的目录
directory_to_process = "/Users/ww/trae_workspace/amphi-etl/jupyterlab-amphi/packages/pipeline-components-core/src/components"
process_directory(directory_to_process)

View File

@ -0,0 +1,5 @@
{
"packageManager": "python",
"packageName": "jupyterlab-amphi",
"uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package jupyterlab-amphi"
}

View File

@ -0,0 +1,11 @@
{
"ServerApp": {
"contents_manager_class": "jupyterfs.metamanager.MetaManager",
"jpserver_extensions": {
"jupyterfs.extension": true
}
},
"ContentsManager": {
"allow_hidden": true
}
}

View File

@ -0,0 +1,4 @@
{
"npmClient": "yarn",
"version": "0.8.23"
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,86 @@
{
"name": "@amphi/jupyterlab-amphi",
"version": "0.8.23",
"keywords": [
"amphi",
"etl",
"micro etl",
"jupyterlab-extension",
"data integration",
"data pipelines"
],
"homepage": "https://amphi.ai",
"bugs": {
"url": "https://github.com/amphi-ai/jupyterlab-amphi/issues"
},
"license": "Elastic License 2.0",
"author": {
"name": "Thibaut Gourdel",
"email": "tgourdel@amphi.ai"
},
"repository": {
"type": "git",
"url": "https://github.com/amphi-ai/jupyterlab-amphi.git"
},
"workspaces": {
"packages": [
"packages/pipeline-editor",
"packages/pipeline-components-manager",
"packages/pipeline-components-core",
"packages/pipeline-components-local",
"packages/pipeline-console",
"packages/pipeline-metadata-panel"
]
},
"scripts": {
"build:prod": "lerna run --sort --stream build:prod",
"build:py": "lerna run --stream build:py",
"build": "lerna run --sort --stream build",
"bump:js:version": "lerna version --no-push --force-publish --no-git-tag-version --yes",
"clean:all": "jlpm clean:build && jlpm clean:dist && lerna run --stream clean:all && jlpm clean:cache",
"clean:build": "rimraf build",
"clean:cache": "rimraf node_modules/.cache build/.lite-cache examples/.jupyterlite.doit.db",
"clean:dist": "rimraf dist",
"clean": "lerna run --stream clean",
"deduplicate": "yarn-berry-deduplicate -s fewer --fail",
"dist:npm": "lerna run --stream dist",
"dist:pypi": "pyproject-build .",
"dist": "jlpm dist:pypi && jlpm dist:npm",
"docs:lite": "cd examples && jupyter lite build",
"docs:sphinx": "sphinx-build -W -b html docs build/docs",
"docs": "jlpm docs:lite && jlpm docs:sphinx",
"eslint:check": "eslint . --cache --cache-location=./build/.cache/eslint --ext .ts,.tsx",
"eslint": "jlpm eslint:check --fix",
"lint": "jlpm lint:js && jlpm lint:py",
"lint:check": "jlpm lint:js:check && jlpm lint:py:check",
"lint:js": "jlpm prettier && jlpm eslint",
"lint:js:check": "jlpm prettier:check && jlpm eslint:check",
"lint:py": "jlpm lint:py:black && jlpm lint:py:ruff --fix-only",
"lint:py:pip": "python -m pip check",
"lint:py:check": "jlpm lint:py:pip && jlpm lint:py:black --check && jlpm lint:py:ruff",
"prettier:base": "prettier \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md,.yml,.yaml}\"",
"prettier:check": "jlpm prettier:base --check",
"prettier": "jlpm prettier:base --write --list-different",
"quickstart": "npm run setup:py && jlpm && jlpm deduplicate && jlpm clean:all && jlpm lint && jlpm build:prod && jlpm dist && jlpm docs && jlpm test",
"setup:py": "python -m pip install -e \".[dev,lint,test,docs]\"",
"test:py": "pytest",
"test": "jlpm test:py"
},
"devDependencies": {
"@jupyterlab/builder": "^4.1.5",
"lerna": "^7.2.0",
"npm-run-all": "^4.1.5",
"rimraf": "^5.0.1",
"typescript": "^5.8.2",
"yarn-berry-deduplicate": "^6.1.1"
},
"publishConfig": {
"access": "public"
},
"jupyterlab": {
"title": "Amphi",
"extension": true,
"outputDir": "./amphi"
},
"private": true
}

Some files were not shown because too many files have changed in this diff Show More