You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by bb...@apache.org on 2022/03/02 00:47:01 UTC
[airflow] branch mapped-task-drawer updated (12b8f3e -> 2f8e444)
This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a change to branch mapped-task-drawer
in repository https://gitbox.apache.org/repos/asf/airflow.git.
discard 12b8f3e add tooltip info to details
discard 319499d switch from drawer to details section
discard e3398de fix hover and extra prop
discard 2f443e0 improve rendering and add selected dag run
discard fbd49c6 reformat grid background colors
discard d98af9a basic slide drawer
discard 911aaeb make UI and tree work with mapped tasks
discard c6da3ea Expand mapped tasks in the Scheduler
discard b7ea8f8 Create an end-to-end test for running a DAG via the scheduler.
add d87762b Don't check if `py` DAG files are zipped during parsing (#21538)
add eec873c Alembic migration filename should match revision id (#21621)
add 66c342d Support generating SQL script for upgrades (#20962)
add 6dd61c9 Delay creation of dag_run table object (#21622)
add 710d699 Support different timeout value for dag file parsing (#21501)
add 68c8de7 Chart: add envFrom to the flower deployment (#21401)
add 068e037 Update test example in CONTRIBUTORS_QUICK_START.rst (#21620)
add aab1189 Add GCSToPrestoOperator (#21084)
add ea21cb3 Adding Cover Genius to INTHEWILD.md (#21637)
add 42469f0 Fix bug in Breeze2 auto-complete setup with root files modified (#21636)
add 074b0c9 Move `confirm` script into `scripts/tools` (#21626)
add 295efd3 Dataflow Assets (#21639)
add 4ca837a Remove wrapper scripts from static_checks folder (#21643)
add 56285ee Add params dag_id, task_id etc to XCom.serialize_value (#19505)
add 5a38d15 Upgrade Postgres client in Docker images (#21631)
add 752d538 added explaining concept of logical date in DAG run docs (#21433)
add 38894e8 Adding missing login provider related methods from Flask-Appbuilder (#21294)
add f011da2 Clarify pendulum use in timezone cases (#21646)
add 366c66b Pin Markupsafe until we are able to upgrade Flask/Jinja (#21664)
add 78490f8 Deprecate helper utility `days_ago` (#21653)
add b48dc4d Update best-practices.rst (#21679)
add b28f4c5 Fix Amazon SES emailer signature (#21681)
add 61e8a5c Increase timeout for constraints (#21680)
add ecd85f8 Add celery_logging_level (#21506)
add dec05fb Update EKS sample DAGs and docs (#21523)
add 68da4d8 Update MySqlOperator example dag (#21434)
add 066ba15 Convert our internal tools to use rich_click (#21689)
add d8ae7df Add extra information about time synchronization needed (#21685)
add 9ad4de8 Refactor TriggerRule & WeightRule classes to inherit from Enum (#21264)
add a0fb0bb Log exception in local executor (#21667)
add a282329 Simply imports in dev github script (#21702)
add 62d1ef8 [de]serialize resources on task correctly (#21445)
add 6061cc4 Add Auto ML operators for Vertex AI service (#21470)
add 9f8278e Fix import in unit test example (#21703)
add 6734eb1 Fix assertion to check actual content (#21678)
add ba627f3 Run mapped tasks via the normal Scheduler (#21614)
add 35552b8 Bump upper bound version of jsonschema to 5.0 (#21712)
add 46a337c Implement mapped value unpacking (#21641)
add 4e95935 Extend documentation for states of DAGs & tasks and update trigger rules docs (#21382)
add 2807193 Replaced hql references to sql in TrinoHook and PrestoHook (#21630)
add 15a72d0 Fix failing tests on main due to merging incompatible changes (#21733)
add 2a615ab Introduce 'Callbacks Sink' classes for sending callbacks (#21301)
add b2c0a92 Fix graph autorefresh on page load (#21736)
add bb577a9 Fix stray order_by(TaskInstance.execution_date) (#21705)
add d1643d1 2.2.4 has been released (#21744)
add 6e5c9c8 Fix some migrations (#21670)
add 18fb554 Dev:`constraints-latest` needs to be force-pushed (#21746)
add 4e17528 Add support for custom command and args in jobs (#20864)
add e8afff9 Simplify chart docs for configuring Airflow (#21747)
add 2689624 Remove python 3.5 reference from README (#21749)
add 169b196 Chart: Default to Airflow 2.2.4 (#21745)
add 9076b67 Fix triggerer --capacity parameter (#21753)
add 3b4c26e Add Dataproc assets/links (#21756)
add e1fe30c Fix the triggerer capacity test (#21760)
add 3c12c2e Don't show alembic info logs at the start of every cli command (#21758)
add de41ccc Change the default auth backend to session (#21640)
add 3c4524b (AzureCosmosDBHook) Update to latest Cosmos API (#21514)
add 3bb63d4 Correct a couple grammatical errors in docs (#21750)
add e12ad53 Add Paxful to INTHEWILD.md (#21766)
add 5fbf247 Add `2.2.4` to db migrations map (#21777)
add feea143 Fix max_active_runs=1 not scheduling runs when min_file_process_interval is high (#21413)
add 919b75b Correctly handle multiple '=' in LocalFileSystem secrets. (#21694)
add 2da207d Rewrite taskflow-mapping argument validation (#21759)
add 73eb24f Fix bigquery_dts parameter docstring typo (#21786)
add f4495e2 Add --platform as parameter of image building (#21695)
add b6e141a Upgrade and record elasticsearch log_id_template changes (#21734)
add 21151fb Rename operator mapping map() to apply() (#21754)
add 272d242 Restore image rendering in AWS Secrets Manager Backend doc (#21772)
add 8ee8f2b Use Pendulum's built-in UTC object (#21732)
add a724523 Make sure emphasis in UPDATING in .md is consistent (#21804)
add 7e0c6e4 REST API: add rendered fields in task instance. (#21741)
add dade6e0 Use DB where possible for quicker ``airflow dag`` subcommands (#21793)
add 608b8c4 Fix test CreateUserJobTest::test_should_disable_default_helm_hooks (#21776)
add 5a6316f Add another way to dynamically generate DAGs to docs (#21297)
add 7e03225 Attempt to upgrede to 22.0.3 version of `pip` (#21818)
add 59c450e Make DbApiHook use get_uri from Connection (#21764)
add dc1deff Remove 8 year old screenshots (#21819)
add 6322dad fix param rendering in docs of SparkSubmitHook (#21788)
add 2e57f22 Add step to add releases to the committee report helper (#21812)
add d85781c Fix typo in chart docs (#21814)
add 43cacd8 Show Task Map Index in task instance table (#21774)
add eafbcb3 Fix doc - replace decreasing by increasing (#21805)
add 5b41e2d Update TaskFlow tutorial doc to show how to pass "operator-level" args. (#21446)
add 16f5185 Limits GitHub3.py in order to avoid backtracking (#21824)
add 9407f11 Switch to GitHub-rendered Mermaid diagrams (#21682)
add e4ead2b extends typing-extensions to be installed with python 3.8+ #21566 (#21567)
add a159ae8 Remove types from KPO docstring (#21826)
add f13f9db Describe policy about support for OS versions used. (#21697)
add 0378659 Added Hook for Amazon RDS. Added `boto3_stub` library for autocomplete. (#20642)
add c75774d Add `db clean` CLI command for purging old data (#20838)
add c8d64c9 Add Github integration steps for committers (#21834)
add b26d4d8 Fix assignment of unassigned triggers (#21770)
add 7ea0f76 Truncate stack trace to DAG user code for exceptions raised during execution (#20731)
add f0b6398 Bug Fix - S3DeleteObjectsOperator will try and delete all keys (#21458)
add 537c244 Add ALL_SKIPPED trigger rule (#21662)
add a1845c6 Databricks: add support for triggering jobs by name (#21663)
add 900bad1 Fix oracle test connection (#21699)
add df31902 Removed 'request.referrer' from views.py (#21751)
add 942f8fd Add GCSToTrinoOperator (#21704)
add 3e4fab4 Fix handling cached parameters for Breeze2 (#21849)
add cb24ee9 Add SageMakerDeleteModelOperator (#21673)
add bc1b422 Fix logging JDBC SQL error when task fails (#21540)
add 27d19e7 Databricks SQL operators (#21363)
add 43907e9 Add unit tests to infer `multiple_outputs` when invoking decorator `__call__` (#21773)
add e93820b Minor `pre-commit` config clean up (#21794)
add 03d6aaa Airflow `db downgrade` cli command (#21596)
add e782b37 Add dbt Cloud provider (#20998)
add 0c55ca2 Suppress hook warnings from the Bigquery transfers (#20119)
add 13b2c40 Add 'method' to attributes in HttpSensor. (#21831)
add 768d851 Fix DAG date range bug (#20507)
add d726579 Fix handling of empty (None) tags in `bulk_write_to_db` (#21757)
add 6442356 Quick Update GCS Presto (#21855)
add 5276ef8 Add JSON output on SqlToS3Operator (#21779)
add f0bbb9d Add 'Show record' option for variables (#21342)
add c819b4f Configurable AWS Session Factory (#21778)
add a85f00b Fix mixup up shadowed ImportError in db_cleanup (#21862)
add f5832a6 update value from database to celery workers (#21859)
add c1abd63 Allow to switch easily between Bullseye and Buster debian versions (#21546)
add 5d89dea Switch to Debian 11 (bullseye) as base for our dockerfiles (#21378)
add 8299ade Revert "Switch to Debian 11 (bullseye) as base for our dockerfiles (#21378)" (#21874)
add 2049998 Update to latest version in Dockerfile (and add instructions) (#21876)
add 4ad21f5 Log traceback in trigger excs (#21213)
add bb26f96 Make Grid and and Graph view work with task mapping (#21740)
add 82e1abf Fix UPDATING section on SqlAlchemy 1.4 scheme changes (#21887)
add d9017a0 Update databricks.rst (#21886)
add 3218cca Fix the Type Hints in ``RedshiftSQLOperator`` (#21885)
add 6ca118d Allow templates in more DataprocUpdateClusterOperator fields (#21865)
add 69f6f9e Autogenerate migration reference doc (#21601)
add 6b0ca64 Fix filesystem sensor for directories (#21729)
add 9e67692 add celery.task_timeout_error metric (#21602)
add 33edeb2 Feature: Add invoke lambda function operator (#21686)
add 2dd251d Update modules_management.rst (#21889)
add 3035d3a Switch to Debian 11 (bullseye) as base for our dockerfiles (#21378) (#21875)
add 5befc7f Fix TaskDecorator type hints (#21881)
add 08575dd Change BaseOperatorLink interface to take a ti_key, not a datetime (#21798)
add f97c25d Limits Yandexcloud to 0.145 to unblock main failing tests. (#21899)
add 351fa53 Fix Kubernetes example with wrong operator casing (#21898)
add ace8c6e EdgeModifier refactoring (#21404)
add 3aebb21 Deprecate non-JSON conn.extra (#21816)
add 5e7ad0b Limit yandexcloud to < 0.142 (#21903)
add e856aba Fix handling some None parameters in kubernetes 23 libs. (#21905)
add fb6b2d1 Make project_id argument optional in all dataproc operators (#21866)
add 1691968 Update list of non-core files/paths (#21907)
add 62bf127 Add-showing-runtime-error-feature-to-DatabricksSubmitRunOperator (#21709)
add 7689969 Refactor KubernetesPodOperator tests (#21911)
add 563ecfa Add Python 3.9 support to Hive (#21893)
new adfc609 make UI and tree work with mapped tasks
new 780d6a2 basic slide drawer
new ee86937 reformat grid background colors
new eb96150 improve rendering and add selected dag run
new ce953b3 fix hover and extra prop
new 5cb4def switch from drawer to details section
new 2192c4a add tooltip info to details
new 2f8e444 use API
This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version. This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:
* -- * -- B -- O -- O -- O (12b8f3e)
\
N -- N -- N refs/heads/mapped-task-drawer (2f8e444)
You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.
Any revisions marked "omit" are not gone; other references still
refer to them. Any revisions marked "discard" are gone forever.
The 8 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.github/ISSUE_TEMPLATE/airflow_bug_report.yml | 3 +-
.../airflow_helmchart_bug_report.yml | 3 +-
.../airflow_providers_bug_report.yml | 4 +-
.github/boring-cyborg.yml | 1 -
.github/workflows/build-images.yml | 1 +
.github/workflows/ci.yml | 3 +-
.hadolint.yaml | 1 +
.pre-commit-config.yaml | 55 +-
BREEZE.rst | 141 ++-
CHANGELOG.txt | 72 ++
CI.rst | 37 +-
CI_DIAGRAMS.md | 312 +++++
COMMITTERS.rst | 11 +
CONTRIBUTING.rst | 23 +-
CONTRIBUTORS_QUICK_START.rst | 27 +-
Dockerfile | 45 +-
Dockerfile.ci | 31 +-
IMAGES.rst | 20 +-
INSTALL | 20 +-
INTHEWILD.md | 2 +
PULL_REQUEST_WORKFLOW.rst | 107 +-
README.md | 49 +-
SELECTIVE_CHECKS.md | 144 +++
STATIC_CODE_CHECKS.rst | 61 +-
TESTING.rst | 2 +-
UPDATING.md | 100 +-
airflow/__init__.py | 1 +
.../api_connexion/endpoints/extra_link_endpoint.py | 18 +-
.../endpoints/task_instance_endpoint.py | 31 +-
airflow/api_connexion/openapi/v1.yaml | 6 +
airflow/api_connexion/schemas/common_schema.py | 15 +
.../api_connexion/schemas/task_instance_schema.py | 4 +
.../timetables => airflow/callbacks}/__init__.py | 0
.../callbacks/base_callback_sink.py | 15 +-
airflow/{utils => callbacks}/callback_requests.py | 7 +-
airflow/callbacks/pipe_callback_sink.py | 47 +
airflow/cli/cli_parser.py | 115 +-
airflow/cli/commands/celery_command.py | 6 +-
airflow/cli/commands/dag_command.py | 66 +-
airflow/cli/commands/db_command.py | 65 +-
airflow/cli/commands/task_command.py | 2 -
airflow/config_templates/config.yml | 15 +-
airflow/config_templates/default_airflow.cfg | 11 +-
airflow/config_templates/default_test.cfg | 1 +
airflow/configuration.py | 43 +-
airflow/contrib/hooks/databricks_hook.py | 1 -
airflow/dag_processing/manager.py | 34 +-
airflow/dag_processing/processor.py | 12 +-
airflow/decorators/__init__.pyi | 2 +-
airflow/decorators/base.py | 174 +--
airflow/decorators/task_group.py | 17 +-
airflow/example_dags/example_bash_operator.py | 8 +-
.../example_branch_datetime_operator.py | 14 +-
.../example_branch_day_of_week_operator.py | 4 +-
airflow/example_dags/example_branch_labels.py | 7 +-
airflow/example_dags/example_branch_operator.py | 5 +-
.../example_branch_python_dop_operator_3.py | 4 +-
airflow/example_dags/example_complex.py | 4 +-
airflow/example_dags/example_dag_decorator.py | 9 +-
.../example_external_task_marker_dag.py | 4 +-
.../example_dags/example_kubernetes_executor.py | 5 +-
.../example_latest_only_with_trigger.py | 8 +-
airflow/example_dags/example_nested_branch_dag.py | 4 +-
.../example_passing_params_via_test_command.py | 8 +-
airflow/example_dags/example_python_operator.py | 5 +-
.../example_dags/example_short_circuit_operator.py | 4 +-
airflow/example_dags/example_skip_dag.py | 9 +-
airflow/example_dags/example_sla_dag.py | 8 +-
airflow/example_dags/example_task_group.py | 7 +-
.../example_dags/example_task_group_decorator.py | 7 +-
.../example_time_delta_sensor_async.py | 8 +-
.../example_dags/example_trigger_controller_dag.py | 4 +-
airflow/example_dags/example_trigger_target_dag.py | 4 +-
airflow/example_dags/example_xcom.py | 4 +-
airflow/example_dags/example_xcomargs.py | 7 +-
airflow/example_dags/plugins/workday.py | 5 +-
airflow/example_dags/subdags/subdag.py | 4 +-
airflow/example_dags/tutorial_etl_dag.py | 5 +-
airflow/example_dags/tutorial_taskflow_api_etl.py | 10 +-
airflow/executors/base_executor.py | 14 +
airflow/executors/celery_executor.py | 24 +-
airflow/executors/debug_executor.py | 1 -
airflow/executors/local_executor.py | 4 +-
airflow/hooks/dbapi.py | 17 +-
airflow/jobs/backfill_job.py | 2 +-
airflow/jobs/scheduler_job.py | 23 +-
airflow/jobs/triggerer_job.py | 18 +-
airflow/kubernetes/pod_generator_deprecated.py | 9 +-
.../004c1210f153_increase_queue_name_size_limit.py | 3 +-
...6b6f902_increase_length_of_fab_ab_view_menu_.py | 7 +-
.../versions/03bc53e68815_add_sm_dag_index.py | 3 +-
.../versions/05f30312d566_merge_heads.py | 3 +-
..._merge_heads.py => 08364691d074_merge_heads.py} | 3 +-
...5d12_add_max_active_runs_column_to_dagmodel_.py | 7 +-
.../0a2a5b66e19d_add_task_reschedule_table.py | 3 +-
.../0e2a74e0fc9f_add_time_zone_awareness.py | 1 +
...dfa7_add_dag_id_state_index_on_dag_run_table.py | 3 +-
.../versions/13eb55f81627_for_compatibility.py | 3 +-
...ta_interval_start_end_to_dagmodel_and_dagrun.py | 1 +
.../versions/1507a7289a2f_create_is_encrypted.py | 3 +-
...cfc09e3_add_is_encrypted_column_to_variable_.py | 3 +-
.../migrations/versions/1b38cef5b76e_add_dagrun.py | 3 +-
.../versions/211e584da130_add_ti_state_index.py | 3 +-
...30d7c24_add_executor_config_to_task_instance.py | 3 +-
.../2c6edca13270_resource_based_permissions.py | 1 +
...e42bb497a22_rename_last_scheduler_run_column.py | 7 +-
.../versions/2e541a1dcfed_task_duration.py | 3 +-
.../versions/2e82aab8ef20_rename_user_table.py | 3 +-
...d44a_rename_concurrency_column_in_dag_table_.py | 14 +-
...338e90f54d61_more_logging_into_task_isntance.py | 3 +-
...7a1ff4_add_kubernetes_resource_checkpointing.py | 3 +-
.../364159666cbd_add_job_id_to_dagrun_table.py | 5 +-
.../versions/3c20cacc0044_add_dagrun_run_type.py | 7 +-
.../versions/40e67319e3a9_dagrun_config.py | 3 +-
.../versions/41f5f12752f8_add_superuser_field.py | 3 +-
.../versions/4446e08588_dagrun_start_end.py | 3 +-
...2da_increase_size_of_connection_extra_field_.py | 3 +-
...a3f1493b9_add_k8s_yaml_to_rendered_templates.py | 1 +
...236f1_add_fractional_seconds_to_mysql_tables.py | 3 +-
.../versions/502898887f84_adding_extra_to_log.py | 3 +-
...0_fix_mssql_exec_date_rendered_task_instance.py | 1 +
.../versions/52d714495f0_job_id_indices.py | 3 +-
...54bebd308c5f_add_trigger_table_and_task_info.py | 7 +-
.../561833c1c74b_add_password_column_to_user.py | 3 +-
.../587bdf053233_adding_index_for_dag_id_in_job.py | 7 +-
...27fdd3_increase_length_of_email_and_username.py | 3 +-
.../5e7d17757c7a_add_pid_field_to_taskinstance.py | 3 +-
...73d9401f_add_description_field_to_connection.py | 7 +-
...7aae_fix_description_field_in_connection_to_.py | 7 +-
.../64de9cddf6c9_add_task_fails_journal_table.py | 3 +-
...a59344a4_make_taskinstance_pool_not_nullable.py | 3 +-
...867_change_datetime_to_datetime2_6_on_mssql_.py | 1 +
...e3737b18f_added_timetable_description_column.py | 7 +-
.../versions/7939bcff74ba_add_dagtags_table.py | 7 +-
.../7b2661a43ba3_taskinstance_keyed_to_dagrun.py | 7 +-
...8c147f_remove_can_read_permission_on_config_.py | 3 +-
.../83f031fd9f1c_improve_mssql_compatibility.py | 3 +-
.../849da589634d_prefix_dag_permissions.py | 1 +
.../versions/8504051e801b_xcom_dag_task_indices.py | 3 +-
...15af_add_rendered_task_instance_fields_table.py | 5 +-
.../856955da8476_fix_sqlite_foreign_key.py | 3 +-
.../8646922c8a04_change_default_pool_slots_to_1.py | 38 +-
...0d1215c0_add_kubernetes_scheduler_uniqueness.py | 3 +-
...d48763f6d53_add_unique_constraint_to_conn_id.py | 7 +-
.../8f966b9c467a_set_conn_type_as_non_nullable.py | 7 +-
...7b86_increase_pool_name_size_in_taskinstance.py | 7 +-
.../versions/92c57b58940d_add_fab_tables.py | 1 +
...1e647c8_task_reschedule_fk_on_cascade_delete.py | 3 +-
.../versions/947454bf1dff_add_ti_job_id_index.py | 3 +-
.../versions/952da73b5eff_add_dag_code_table.py | 3 +-
.../versions/9635ae0956e7_index_taskfail.py | 3 +-
...93827b8_add_queued_at_column_to_dagrun_table.py | 7 +-
...606e2_add_scheduling_decision_to_dagrun_and_.py | 7 +-
...ad25_resource_based_permissions_for_default_.py | 3 +-
...914482_add_data_compressed_to_serialized_dag.py | 1 +
...67d16b_add_pool_slots_field_to_task_instance.py | 3 +-
.../versions/a56c9515abdc_remove_dag_stat_table.py | 3 +-
...eea_add_precision_to_execution_date_in_mysql.py | 7 +-
.../b247b1e3d1ed_add_queued_by_job_id_to_ti.py | 1 +
.../b25a55525161_increase_length_of_pool_name.py | 1 +
.../b3b105409875_add_root_dag_id_to_dag.py | 7 +-
...cfc896_add_a_column_to_track_the_encryption_.py | 1 +
...13e_add_notification_sent_column_to_sla_miss.py | 3 +-
.../bbf4a7ad0465_remove_id_column_from_xcom.py | 1 +
...3e6c56_make_xcom_value_column_a_large_binary.py | 1 +
...a23_add_has_import_errors_column_to_dagmodel.py | 1 +
.../bef4f3d11e8b_drop_kuberesourceversion_and_.py | 7 +-
.../bf00311e1990_add_index_to_taskinstance.py | 3 +-
...c306b5b5ae4a_switch_xcom_table_to_use_run_id.py | 48 +-
.../c381b21cb7e4_add_session_table_to_db.py | 7 +-
.../versions/c8ffec048a3b_add_fields_to_dag.py | 3 +-
...623dc7_add_max_tries_column_to_task_instance.py | 3 +-
...26fe78_add_index_on_state_dag_id_for_queued_.py | 7 +-
.../versions/cf5dc11e79ad_drop_user_and_chart.py | 3 +-
.../d2ae31099d61_increase_text_size_for_mysql.py | 1 +
.../d38e04c12aa2_add_serialized_dag_table.py | 3 +-
...c3a5a_add_dag_hash_column_to_serialized_dag_.py | 7 +-
.../versions/dd25f486b8ea_add_idx_log_dag.py | 3 +-
.../dd4ecb8fbee3_add_schedule_interval_to_dag.py | 1 +
...65e7455d70_add_description_field_to_variable.py | 7 +-
.../e1a11ece99cc_add_external_executor_id_to_ti.py | 1 +
.../e38be357a868_update_schema_for_smart_sensor.py | 3 +-
.../versions/e3a246e0dc1_current_schema.py | 1 +
...53f75_add_taskmap_and_map_id_on_taskinstance.py | 9 +-
...4a3141f0_make_xcom_pkey_columns_non_nullable.py | 7 +-
...ac86c_change_field_in_dagcode_to_mediumtext_.py | 3 +-
.../f23433877c24_fix_mysql_not_null_constraint.py | 3 +-
.../versions/f2ca10b85618_add_dag_stats_table.py | 3 +-
...62e7089_add_task_log_filename_template_model.py | 3 +-
...935f_increase_length_for_connection_password.py | 7 +-
airflow/models/abstractoperator.py | 193 ++-
airflow/models/baseoperator.py | 138 +--
airflow/models/connection.py | 43 +-
airflow/models/dag.py | 28 +-
airflow/models/dagbag.py | 33 +-
airflow/models/dagrun.py | 50 +-
airflow/models/mappedoperator.py | 294 +++--
airflow/models/renderedtifields.py | 2 +-
airflow/models/taskinstance.py | 138 ++-
airflow/models/taskmixin.py | 21 +-
airflow/models/trigger.py | 16 +-
airflow/models/xcom.py | 133 ++-
airflow/operators/trigger_dagrun.py | 21 +-
airflow/provider.yaml.schema.json | 1 +
.../aws/example_dags/example_eks_templated.py | 42 +-
.../example_eks_with_fargate_in_one_step.py | 14 +-
.../example_eks_with_fargate_profile.py | 21 +-
.../example_eks_with_nodegroup_in_one_step.py | 16 +-
.../example_dags/example_eks_with_nodegroups.py | 26 +-
.../amazon/aws/example_dags/example_lambda.py} | 32 +-
.../amazon/aws/example_dags/example_sagemaker.py | 177 +++
airflow/providers/amazon/aws/hooks/base_aws.py | 44 +-
.../providers/amazon/aws/hooks/lambda_function.py | 91 +-
airflow/providers/amazon/aws/hooks/rds.py | 59 +
airflow/providers/amazon/aws/hooks/sagemaker.py | 11 +
.../providers/amazon/aws/operators/aws_lambda.py | 102 ++
airflow/providers/amazon/aws/operators/emr.py | 18 +-
.../providers/amazon/aws/operators/redshift_sql.py | 4 +-
airflow/providers/amazon/aws/operators/s3.py | 14 +-
.../providers/amazon/aws/operators/sagemaker.py | 22 +
airflow/providers/amazon/aws/sensors/eks.py | 12 +
.../providers/amazon/aws/transfers/sql_to_s3.py | 36 +-
airflow/providers/amazon/aws/utils/emailer.py | 5 +-
airflow/providers/amazon/provider.yaml | 14 +
airflow/providers/apache/beam/operators/beam.py | 28 +-
airflow/providers/apache/hive/provider.yaml | 3 -
.../providers/apache/spark/hooks/spark_submit.py | 2 +-
.../kubernetes/example_dags/example_kubernetes.py | 2 +-
.../cncf/kubernetes/operators/kubernetes_pod.py | 14 +-
.../databricks/example_dags/example_databricks.py | 7 +-
.../example_dags/example_databricks_sql.py | 113 ++
airflow/providers/databricks/hooks/databricks.py | 365 +-----
.../hooks/{databricks.py => databricks_base.py} | 334 ++----
.../providers/databricks/hooks/databricks_sql.py | 189 +++
.../providers/databricks/operators/databricks.py | 24 +-
.../databricks/operators/databricks_sql.py | 267 +++++
airflow/providers/databricks/provider.yaml | 20 +-
.../providers/dbt}/__init__.py | 0
.../providers/{alibaba => dbt/cloud}/CHANGELOG.rst | 0
.../providers/dbt/cloud}/__init__.py | 0
.../providers/dbt/cloud/example_dags}/__init__.py | 0
.../dbt/cloud/example_dags/example_dbt_cloud.py | 75 ++
.../providers/dbt/cloud/hooks}/__init__.py | 0
airflow/providers/dbt/cloud/hooks/dbt.py | 499 ++++++++
.../providers/dbt/cloud/operators}/__init__.py | 0
airflow/providers/dbt/cloud/operators/dbt.py | 209 ++++
.../{databricks => dbt/cloud}/provider.yaml | 45 +-
.../providers/dbt/cloud/sensors}/__init__.py | 0
airflow/providers/dbt/cloud/sensors/dbt.py | 65 +
airflow/providers/dependencies.json | 9 +
.../tutorial_taskflow_api_etl_docker_virtualenv.py | 2 +-
.../google/cloud/example_dags/example_vertex_ai.py | 153 +++
.../google/cloud/hooks/vertex_ai/auto_ml.py | 1256 ++++++++++++++++++++
.../providers/google/cloud/links}/__init__.py | 0
airflow/providers/google/cloud/links/base.py | 51 +
airflow/providers/google/cloud/links/dataflow.py | 50 +
airflow/providers/google/cloud/links/dataproc.py | 131 ++
airflow/providers/google/cloud/links/vertex_ai.py | 119 ++
.../providers/google/cloud/operators/bigquery.py | 18 +-
.../google/cloud/operators/bigquery_dts.py | 6 +-
.../google/cloud/operators/cloud_composer.py | 34 +-
.../providers/google/cloud/operators/dataflow.py | 5 +
.../providers/google/cloud/operators/datafusion.py | 62 +-
.../providers/google/cloud/operators/dataproc.py | 180 ++-
.../google/cloud/operators/dataproc_metastore.py | 47 +-
.../google/cloud/operators/vertex_ai/auto_ml.py | 623 ++++++++++
.../google/cloud/operators/vertex_ai/custom_job.py | 90 +-
.../google/cloud/operators/vertex_ai/dataset.py | 88 +-
airflow/providers/google/cloud/sensors/dataproc.py | 6 +-
.../google/cloud/transfers/bigquery_to_bigquery.py | 21 +-
.../google/cloud/transfers/gcs_to_bigquery.py | 133 ++-
airflow/providers/google/common/links/storage.py | 23 +-
airflow/providers/google/provider.yaml | 15 +-
airflow/providers/http/sensors/http.py | 1 +
airflow/providers/microsoft/azure/hooks/cosmos.py | 88 +-
.../microsoft/azure/operators/data_factory.py | 25 +-
.../providers/mysql/example_dags/example_mysql.py | 6 +-
airflow/providers/mysql/hooks/mysql.py | 8 -
airflow/providers/oracle/hooks/oracle.py | 15 +
airflow/providers/postgres/hooks/postgres.py | 8 +-
.../providers/presto/example_dags}/__init__.py | 0
.../presto/example_dags/example_gcs_to_presto.py} | 36 +-
airflow/providers/presto/hooks/presto.py | 115 +-
airflow/providers/presto/provider.yaml | 6 +
.../providers/presto/transfers}/__init__.py | 0
.../providers/presto/transfers/gcs_to_presto.py | 122 ++
airflow/providers/qubole/operators/qubole.py | 20 +-
.../providers/trino/example_dags}/__init__.py | 0
.../trino/example_dags/example_gcs_to_trino.py} | 36 +-
airflow/providers/trino/hooks/trino.py | 121 +-
airflow/providers/trino/provider.yaml | 6 +
.../providers/trino/transfers}/__init__.py | 0
airflow/providers/trino/transfers/gcs_to_trino.py | 124 ++
airflow/secrets/local_filesystem.py | 7 +-
airflow/sensors/filesystem.py | 2 +-
airflow/serialization/serialized_objects.py | 41 +-
airflow/settings.py | 14 +-
airflow/task/task_runner/standard_task_runner.py | 18 +-
airflow/ti_deps/deps/trigger_rule_dep.py | 14 +
airflow/utils/context.py | 45 +
airflow/utils/context.pyi | 5 +-
airflow/utils/dates.py | 7 +
airflow/utils/db.py | 251 +++-
airflow/utils/db_cleanup.py | 315 +++++
airflow/utils/edgemodifier.py | 107 +-
airflow/utils/log/file_task_handler.py | 5 +-
airflow/utils/log/secrets_masker.py | 7 +-
airflow/utils/operator_resources.py | 26 +
airflow/utils/task_group.py | 19 +-
airflow/utils/trigger_rule.py | 22 +-
airflow/utils/weight_rule.py | 22 +-
airflow/www/fab_security/manager.py | 15 +
airflow/www/package.json | 2 +
airflow/www/static/js/calendar.js | 2 +-
airflow/www/static/js/connection_form.js | 2 +-
airflow/www/static/js/dag.js | 2 +-
airflow/www/static/js/dag_code.js | 2 +-
airflow/www/static/js/dags.js | 2 +-
airflow/www/static/js/graph.js | 65 +-
airflow/www/static/js/task_instances.js | 19 +
airflow/www/static/js/ti_log.js | 2 +-
airflow/www/static/js/tree/InstanceTooltip.jsx | 23 +-
airflow/www/static/js/tree/StatusBox.jsx | 6 +-
airflow/www/static/js/tree/Tree.jsx | 16 +-
.../tree/{details/content/Dag.jsx => api/index.js} | 21 +-
.../js/{meta_value.js => tree/api/useDag.js} | 14 +-
.../{details/content/Dag.jsx => api/useTasks.js} | 19 +-
airflow/www/static/js/tree/dagRuns/Bar.jsx | 2 +-
airflow/www/static/js/tree/details/Header.jsx | 5 +-
airflow/www/static/js/tree/details/content/Dag.jsx | 36 +-
.../js/tree/details/content/TaskInstance.jsx | 100 +-
airflow/www/static/js/tree/details/index.jsx | 34 +-
airflow/www/static/js/tree/index.jsx | 13 +-
airflow/www/static/js/tree/renderTaskRows.jsx | 2 +-
airflow/www/static/js/tree/useTreeData.js | 2 +-
airflow/www/static/js/{meta_value.js => utils.js} | 17 +-
airflow/www/static/screenshots/gantt.png | Bin 31140 -> 0 bytes
airflow/www/static/screenshots/graph.png | Bin 38282 -> 0 bytes
airflow/www/static/screenshots/tree.png | Bin 35259 -> 0 bytes
airflow/www/templates/airflow/dag.html | 4 +-
airflow/www/templates/airflow/dags.html | 2 +-
airflow/www/templates/airflow/variable_list.html | 4 +
.../{variable_list.html => variable_show.html} | 25 +-
.../templates/airflow/variable_show_widget.html | 70 ++
airflow/www/views.py | 137 ++-
airflow/www/widgets.py | 6 +
airflow/www/yarn.lock | 104 +-
breeze | 63 +-
breeze-complete | 12 +-
chart/Chart.yaml | 20 +-
chart/UPDATING.rst | 15 +
chart/templates/flower/flower-deployment.yaml | 2 +
chart/templates/jobs/create-user-job.yaml | 27 +-
chart/templates/jobs/migrate-database-job.yaml | 10 +-
chart/tests/test_create_user_job.py | 102 +-
chart/tests/test_extra_env_env_from.py | 4 +
chart/tests/test_migrate_database_job.py | 50 +
chart/values.schema.json | 71 +-
chart/values.yaml | 44 +-
dev/README_RELEASE_AIRFLOW.md | 11 +-
dev/README_RELEASE_HELM_CHART.md | 8 +-
dev/airflow-github | 34 +-
dev/assign_cherry_picked_prs_with_milestone.py | 2 +-
...0004-using-docker-images-as-test-environment.md | 2 +-
dev/breeze/setup.cfg | 1 +
dev/breeze/src/airflow_breeze/breeze.py | 16 +-
dev/breeze/src/airflow_breeze/cache.py | 4 +-
dev/breeze/src/airflow_breeze/ci/build_image.py | 29 +-
dev/breeze/src/airflow_breeze/ci/build_params.py | 4 +-
dev/breeze/src/airflow_breeze/pre_commit_ids.py | 3 +-
dev/breeze/src/airflow_ci/freespace.py | 2 +-
dev/breeze/tests/test_build_image.py | 60 +
dev/check_files.py | 2 +-
dev/prepare_release_issue.py | 2 +-
dev/provider_packages/prepare_provider_packages.py | 4 +-
dev/requirements.txt | 5 +-
dev/retag_docker_images.py | 2 +-
dev/send_email.py | 2 +-
...calculate_statistics_provider_testing_issues.py | 2 +-
.../connections/aws.rst | 100 ++
docs/apache-airflow-providers-amazon/index.rst | 1 +
.../operators/eks.rst | 54 +
.../operators/lambda.rst | 58 +
.../operators/sagemaker.rst | 66 +
.../secrets-backends/aws-secrets-manager.rst | 5 +-
.../connections/databricks.rst | 15 +-
docs/apache-airflow-providers-databricks/index.rst | 21 +-
.../operators/copy_into.rst | 76 ++
.../operators}/index.rst | 31 +-
.../{operators.rst => operators/run_now.rst} | 79 +-
.../operators/sql.rst | 105 ++
.../operators/submit_run.rst | 97 ++
.../commits.rst} | 31 +-
.../connections.rst | 88 ++
.../index.rst | 47 +-
.../installing-providers-from-sources.rst | 0
.../operators.rst | 108 ++
.../operators/cloud/vertex_ai.rst | 90 ++
.../connections/odbc.rst | 6 +-
docs/apache-airflow-providers-presto/index.rst | 7 +
.../operators/transfer/gcs_to_presto.rst | 52 +
docs/apache-airflow-providers-trino/index.rst | 7 +
.../operators/transfer/gcs_to_trino.rst | 52 +
docs/apache-airflow/best-practices.rst | 173 ++-
docs/apache-airflow/concepts/dags.rst | 48 +-
docs/apache-airflow/concepts/operators.rst | 2 +-
docs/apache-airflow/concepts/scheduler.rst | 2 +-
docs/apache-airflow/concepts/tasks.rst | 6 +
docs/apache-airflow/configurations-ref.rst | 5 +
docs/apache-airflow/dag-run.rst | 40 +-
docs/apache-airflow/executor/kubernetes.rst | 5 +-
docs/apache-airflow/extra-packages-ref.rst | 2 +
docs/apache-airflow/faq.rst | 60 +-
docs/apache-airflow/howto/define_extra_link.rst | 26 +-
.../howto/dynamic-dag-generation.rst | 140 +++
docs/apache-airflow/howto/email-config.rst | 5 +-
docs/apache-airflow/howto/index.rst | 1 +
docs/apache-airflow/howto/set-config.rst | 5 +
docs/apache-airflow/howto/set-up-database.rst | 2 +-
docs/apache-airflow/howto/timetable.rst | 8 +-
docs/apache-airflow/img/watcher.png | Bin 0 -> 41592 bytes
docs/apache-airflow/installation/dependencies.rst | 2 +-
docs/apache-airflow/installation/prerequisites.rst | 2 +-
.../installation/supported-versions.rst | 2 +-
docs/apache-airflow/installation/upgrading.rst | 11 +
docs/apache-airflow/lineage.rst | 7 +-
.../logging-monitoring/callbacks.rst | 8 +-
.../logging-monitoring/check-health.rst | 2 +-
docs/apache-airflow/logging-monitoring/metrics.rst | 1 +
docs/apache-airflow/migrations-ref.rst | 450 +++----
docs/apache-airflow/modules_management.rst | 1 +
docs/apache-airflow/plugins.rst | 36 +-
docs/apache-airflow/security/api.rst | 4 +-
docs/apache-airflow/start/docker.rst | 2 +-
docs/apache-airflow/timezone.rst | 19 +-
docs/apache-airflow/tutorial.rst | 15 +-
docs/apache-airflow/tutorial_taskflow_api.rst | 4 +-
docs/apache-airflow/upgrading-from-1-10/index.rst | 5 +
docs/docker-stack/build-arg-ref.rst | 7 +-
docs/docker-stack/build.rst | 16 +-
.../customizing/add-build-essential-custom.sh | 2 +-
.../docker-examples/customizing/custom-sources.sh | 2 +-
.../customizing/github-different-repository.sh | 2 +-
.../docker-examples/customizing/github-main.sh | 2 +-
.../customizing/github-v2-2-test.sh | 2 +-
.../customizing/pypi-dev-runtime-deps.sh | 2 +-
.../customizing/pypi-extras-and-deps.sh | 2 +-
.../customizing/pypi-selected-version.sh | 2 +-
.../extending/embedding-dags/test_dag.py | 10 +-
.../restricted/restricted_environments.sh | 3 +-
docs/exts/operators_and_hooks_ref.py | 2 +-
docs/helm-chart/airflow-configuration.rst | 46 +-
docs/helm-chart/production-guide.rst | 7 +-
.../aws/Amazon-RDS_light-bg@4x.png | Bin 0 -> 53014 bytes
docs/integration-logos/dbt/dbt.png | Bin 0 -> 21953 bytes
docs/spelling_wordlist.txt | 6 +
images/ci/pull_request_ci_flow.md5 | 1 -
images/ci/pull_request_ci_flow.mermaid | 116 --
images/ci/pull_request_ci_flow.png | Bin 192880 -> 0 bytes
images/ci/push_ci_flow.md5 | 1 -
images/ci/push_ci_flow.mermaid | 112 --
images/ci/push_ci_flow.png | Bin 200048 -> 0 bytes
images/ci/scheduled_ci_flow.md5 | 1 -
images/ci/scheduled_ci_flow.mermaid | 98 --
images/ci/scheduled_ci_flow.png | Bin 171588 -> 0 bytes
images/pr/selective_checks.md5 | 1 -
images/pr/selective_checks.mermaid | 35 -
images/pr/selective_checks.png | Bin 64501 -> 0 bytes
scripts/ci/docker-compose/_docker.env | 1 +
...ackend-mssql.yml => backend-mssql-bullseye.yml} | 4 +-
...{backend-mssql.yml => backend-mssql-buster.yml} | 0
scripts/ci/docker-compose/base.yml | 1 +
scripts/ci/libraries/_build_images.sh | 7 +-
scripts/ci/libraries/_initialization.sh | 11 +-
scripts/ci/pre_commit/pre_commit_check_license.sh | 49 +-
scripts/ci/pre_commit/pre_commit_flake8.sh | 25 +-
scripts/ci/pre_commit/pre_commit_helm_lint.sh | 13 +-
.../ci/pre_commit/pre_commit_lint_dockerfile.sh | 36 +-
scripts/ci/pre_commit/pre_commit_mermaid.sh | 107 --
.../pre_commit/pre_commit_migration_documented.py | 67 --
.../pre_commit/pre_commit_migration_reference.py | 134 +++
.../pre_commit_migration_reference.sh} | 11 +-
scripts/ci/pre_commit/pre_commit_mypy.sh | 26 +-
scripts/ci/pre_commit/supported_versions.py | 2 +-
scripts/ci/static_checks/check_license.sh | 63 -
scripts/ci/static_checks/helm_lint.sh | 28 -
scripts/ci/static_checks/lint_dockerfile.sh | 51 -
scripts/ci/static_checks/mypy.sh | 40 -
scripts/ci/static_checks/ui_lint.sh | 2 +-
scripts/ci/static_checks/www_lint.sh | 2 +-
.../ci_run_single_airflow_test_in_docker.sh | 6 +-
.../determine_debian_version_specific_variables.sh | 49 +
scripts/docker/install_airflow.sh | 8 +-
...install_airflow_dependencies_from_branch_tip.sh | 5 +
.../docker/install_from_docker_context_files.sh | 3 +
scripts/docker/install_mssql.sh | 35 +-
scripts/docker/install_mysql.sh | 8 +-
.../{install_mysql.sh => install_postgres.sh} | 38 +-
.../run_migration_reference.sh} | 8 +-
confirm => scripts/tools/confirm | 0
setup.cfg | 26 +-
setup.py | 32 +-
.../endpoints/test_extra_link_endpoint.py | 16 +-
.../endpoints/test_task_instance_endpoint.py | 16 +-
.../schemas/test_task_instance_schema.py | 15 +-
tests/cli/commands/test_celery_command.py | 2 +-
tests/cli/commands/test_db_command.py | 222 +++-
tests/cli/commands/test_triggerer_command.py | 2 +-
tests/core/test_configuration.py | 22 +
tests/dag_processing/test_manager.py | 2 +-
tests/dag_processing/test_processor.py | 2 +-
tests/dags/test_mapped_classic.py | 10 +-
tests/dags/test_mapped_taskflow.py | 2 +-
tests/decorators/test_python.py | 117 +-
tests/hooks/test_dbapi.py | 61 +-
tests/jobs/test_scheduler_job.py | 111 +-
tests/jobs/test_triggerer_job.py | 11 +-
tests/models/test_baseoperator.py | 21 +-
tests/models/test_connection.py | 8 +
tests/models/test_dag.py | 27 +
tests/models/test_dagbag.py | 50 +
tests/models/test_dagrun.py | 34 +-
tests/models/test_taskinstance.py | 168 ++-
tests/models/test_trigger.py | 52 +
tests/models/test_xcom.py | 88 +-
tests/operators/test_trigger_dagrun.py | 28 +-
tests/providers/amazon/aws/hooks/test_base_aws.py | 33 +-
.../amazon/aws/hooks/test_lambda_function.py | 6 +-
.../providers/amazon/aws/hooks/test_rds.py | 14 +-
tests/providers/amazon/aws/hooks/test_sagemaker.py | 22 +-
.../aws/operators/test_emr_create_job_flow.py | 8 +-
.../providers/amazon/aws/operators/test_lambda.py | 109 ++
.../amazon/aws/operators/test_s3_delete_objects.py | 96 ++
.../amazon/aws/operators/test_sagemaker_model.py | 20 +-
.../amazon/aws/transfers/test_sql_to_s3.py | 54 +
tests/providers/amazon/aws/utils/test_emailer.py | 11 +-
tests/providers/apache/beam/operators/test_beam.py | 40 +-
tests/providers/apache/hive/hooks/test_hive.py | 31 -
.../apache/hive/transfers/test_hive_to_mysql.py | 9 -
.../apache/hive/transfers/test_hive_to_samba.py | 9 -
.../apache/hive/transfers/test_mssql_to_hive.py | 8 +-
.../apache/hive/transfers/test_mysql_to_hive.py | 7 -
.../kubernetes/operators/test_kubernetes_pod.py | 289 +++--
.../providers/databricks/hooks/test_databricks.py | 231 +++-
.../databricks/hooks/test_databricks_sql.py | 84 ++
.../databricks/operators/test_databricks.py | 57 +
.../databricks/operators/test_databricks_sql.py | 170 +++
tests/{timetables => providers/dbt}/__init__.py | 0
.../dbt/cloud}/__init__.py | 0
.../dbt/cloud/hooks}/__init__.py | 0
tests/providers/dbt/cloud/hooks/test_dbt_cloud.py | 600 ++++++++++
.../dbt/cloud/operators}/__init__.py | 0
.../dbt/cloud/operators/test_dbt_cloud.py | 374 ++++++
.../dbt/cloud/sensors}/__init__.py | 0
.../providers/dbt/cloud/sensors/test_dbt_cloud.py | 71 ++
.../google/cloud/hooks/vertex_ai/test_auto_ml.py | 175 +++
.../google/cloud/operators/test_bigquery.py | 19 +-
.../google/cloud/operators/test_dataproc.py | 132 +-
.../google/cloud/operators/test_mlengine.py | 4 +-
.../google/cloud/operators/test_vertex_ai.py | 345 ++++++
.../cloud/operators/test_vertex_ai_system.py | 4 +
.../cloud/transfers/test_bigquery_to_bigquery.py | 2 +-
.../google/cloud/transfers/test_gcs_to_bigquery.py | 113 +-
.../microsoft/azure/hooks/test_azure_cosmos.py | 78 +-
.../microsoft/azure/operators/test_azure_cosmos.py | 8 +-
.../azure/operators/test_azure_data_factory.py | 2 +-
tests/providers/oracle/hooks/test_oracle.py | 6 +
.../presto/transfers}/__init__.py | 0
.../providers/presto/transfers/test_gcs_presto.py | 145 +++
tests/providers/qubole/operators/test_qubole.py | 8 +-
tests/providers/snowflake/hooks/test_snowflake.py | 1 +
.../snowflake/transfers/test_snowflake_to_slack.py | 12 +-
.../trino/transfers}/__init__.py | 0
tests/providers/trino/transfers/test_gcs_trino.py | 145 +++
tests/secrets/test_local_filesystem.py | 17 +
tests/sensors/test_external_task_sensor.py | 2 +-
tests/sensors/test_filesystem.py | 36 +-
tests/serialization/test_dag_serialization.py | 190 +--
.../task/task_runner/test_standard_task_runner.py | 24 +-
tests/test_utils/mock_executor.py | 2 +
tests/test_utils/mock_operators.py | 16 +-
.../perf/scheduler_dag_execution_timing.py | 2 +-
tests/ti_deps/deps/test_trigger_rule_dep.py | 57 +
tests/utils/test_db.py | 133 ++-
tests/utils/test_db_cleanup.py | 265 +++++
tests/utils/test_edgemodifier.py | 205 ++++
tests/utils/test_operator_resources.py | 9 +
tests/utils/test_task_group.py | 8 +-
tests/utils/test_trigger_rule.py | 8 +-
tests/utils/test_weight_rule.py | 5 +
tests/www/views/test_views_extra_links.py | 47 +-
591 files changed, 17221 insertions(+), 5164 deletions(-)
create mode 100644 CI_DIAGRAMS.md
create mode 100644 SELECTIVE_CHECKS.md
copy {tests/timetables => airflow/callbacks}/__init__.py (100%)
copy scripts/ci/pre_commit/pre_commit_helm_lint.sh => airflow/callbacks/base_callback_sink.py (74%)
mode change 100755 => 100644
rename airflow/{utils => callbacks}/callback_requests.py (95%)
create mode 100644 airflow/callbacks/pipe_callback_sink.py
rename airflow/migrations/versions/{b0125267960b_merge_heads.py => 08364691d074_merge_heads.py} (95%)
copy airflow/{example_dags/example_time_delta_sensor_async.py => providers/amazon/aws/example_dags/example_lambda.py} (56%)
create mode 100644 airflow/providers/amazon/aws/example_dags/example_sagemaker.py
create mode 100644 airflow/providers/amazon/aws/hooks/rds.py
create mode 100644 airflow/providers/amazon/aws/operators/aws_lambda.py
create mode 100644 airflow/providers/databricks/example_dags/example_databricks_sql.py
copy airflow/providers/databricks/hooks/{databricks.py => databricks_base.py} (60%)
create mode 100644 airflow/providers/databricks/hooks/databricks_sql.py
create mode 100644 airflow/providers/databricks/operators/databricks_sql.py
copy {tests/timetables => airflow/providers/dbt}/__init__.py (100%)
copy airflow/providers/{alibaba => dbt/cloud}/CHANGELOG.rst (100%)
copy {tests/timetables => airflow/providers/dbt/cloud}/__init__.py (100%)
copy {tests/timetables => airflow/providers/dbt/cloud/example_dags}/__init__.py (100%)
create mode 100644 airflow/providers/dbt/cloud/example_dags/example_dbt_cloud.py
copy {tests/timetables => airflow/providers/dbt/cloud/hooks}/__init__.py (100%)
create mode 100644 airflow/providers/dbt/cloud/hooks/dbt.py
copy {tests/timetables => airflow/providers/dbt/cloud/operators}/__init__.py (100%)
create mode 100644 airflow/providers/dbt/cloud/operators/dbt.py
copy airflow/providers/{databricks => dbt/cloud}/provider.yaml (55%)
copy {tests/www/api/experimental => airflow/providers/dbt/cloud/sensors}/__init__.py (100%)
create mode 100644 airflow/providers/dbt/cloud/sensors/dbt.py
create mode 100644 airflow/providers/google/cloud/hooks/vertex_ai/auto_ml.py
copy {tests/timetables => airflow/providers/google/cloud/links}/__init__.py (100%)
create mode 100644 airflow/providers/google/cloud/links/base.py
create mode 100644 airflow/providers/google/cloud/links/dataflow.py
create mode 100644 airflow/providers/google/cloud/links/dataproc.py
create mode 100644 airflow/providers/google/cloud/links/vertex_ai.py
create mode 100644 airflow/providers/google/cloud/operators/vertex_ai/auto_ml.py
copy {tests/timetables => airflow/providers/presto/example_dags}/__init__.py (100%)
copy airflow/{example_dags/example_trigger_controller_dag.py => providers/presto/example_dags/example_gcs_to_presto.py} (52%)
copy {tests/timetables => airflow/providers/presto/transfers}/__init__.py (100%)
create mode 100644 airflow/providers/presto/transfers/gcs_to_presto.py
copy {tests/www/api/experimental => airflow/providers/trino/example_dags}/__init__.py (100%)
copy airflow/{example_dags/example_trigger_controller_dag.py => providers/trino/example_dags/example_gcs_to_trino.py} (53%)
copy {tests/www/api/experimental => airflow/providers/trino/transfers}/__init__.py (100%)
create mode 100644 airflow/providers/trino/transfers/gcs_to_trino.py
create mode 100644 airflow/utils/db_cleanup.py
copy airflow/www/static/js/tree/{details/content/Dag.jsx => api/index.js} (72%)
copy airflow/www/static/js/{meta_value.js => tree/api/useDag.js} (79%)
copy airflow/www/static/js/tree/{details/content/Dag.jsx => api/useTasks.js} (80%)
rename airflow/www/static/js/{meta_value.js => utils.js} (74%)
delete mode 100644 airflow/www/static/screenshots/gantt.png
delete mode 100644 airflow/www/static/screenshots/graph.png
delete mode 100644 airflow/www/static/screenshots/tree.png
copy airflow/www/templates/airflow/{variable_list.html => variable_show.html} (53%)
create mode 100644 airflow/www/templates/airflow/variable_show_widget.html
create mode 100644 dev/breeze/tests/test_build_image.py
create mode 100644 docs/apache-airflow-providers-amazon/operators/lambda.rst
create mode 100644 docs/apache-airflow-providers-amazon/operators/sagemaker.rst
create mode 100644 docs/apache-airflow-providers-databricks/operators/copy_into.rst
copy docs/{apache-airflow/howto => apache-airflow-providers-databricks/operators}/index.rst (58%)
rename docs/apache-airflow-providers-databricks/{operators.rst => operators/run_now.rst} (53%)
create mode 100644 docs/apache-airflow-providers-databricks/operators/sql.rst
create mode 100644 docs/apache-airflow-providers-databricks/operators/submit_run.rst
copy docs/{apache-airflow/howto/index.rst => apache-airflow-providers-dbt-cloud/commits.rst} (57%)
create mode 100644 docs/apache-airflow-providers-dbt-cloud/connections.rst
copy docs/{apache-airflow-providers-databricks => apache-airflow-providers-dbt-cloud}/index.rst (60%)
copy docs/{apache-airflow-providers-zendesk => apache-airflow-providers-dbt-cloud}/installing-providers-from-sources.rst (100%)
create mode 100644 docs/apache-airflow-providers-dbt-cloud/operators.rst
create mode 100644 docs/apache-airflow-providers-presto/operators/transfer/gcs_to_presto.rst
create mode 100644 docs/apache-airflow-providers-trino/operators/transfer/gcs_to_trino.rst
create mode 100644 docs/apache-airflow/howto/dynamic-dag-generation.rst
create mode 100644 docs/apache-airflow/img/watcher.png
create mode 100644 docs/integration-logos/aws/Amazon-RDS_light-bg@4x.png
create mode 100644 docs/integration-logos/dbt/dbt.png
delete mode 100644 images/ci/pull_request_ci_flow.md5
delete mode 100644 images/ci/pull_request_ci_flow.mermaid
delete mode 100644 images/ci/pull_request_ci_flow.png
delete mode 100644 images/ci/push_ci_flow.md5
delete mode 100644 images/ci/push_ci_flow.mermaid
delete mode 100644 images/ci/push_ci_flow.png
delete mode 100644 images/ci/scheduled_ci_flow.md5
delete mode 100644 images/ci/scheduled_ci_flow.mermaid
delete mode 100644 images/ci/scheduled_ci_flow.png
delete mode 100644 images/pr/selective_checks.md5
delete mode 100644 images/pr/selective_checks.mermaid
delete mode 100644 images/pr/selective_checks.png
copy scripts/ci/docker-compose/{backend-mssql.yml => backend-mssql-bullseye.yml} (93%)
rename scripts/ci/docker-compose/{backend-mssql.yml => backend-mssql-buster.yml} (100%)
delete mode 100755 scripts/ci/pre_commit/pre_commit_mermaid.sh
delete mode 100755 scripts/ci/pre_commit/pre_commit_migration_documented.py
create mode 100755 scripts/ci/pre_commit/pre_commit_migration_reference.py
rename scripts/ci/{static_checks/flake8.sh => pre_commit/pre_commit_migration_reference.sh} (81%)
delete mode 100755 scripts/ci/static_checks/check_license.sh
delete mode 100755 scripts/ci/static_checks/helm_lint.sh
delete mode 100755 scripts/ci/static_checks/lint_dockerfile.sh
delete mode 100755 scripts/ci/static_checks/mypy.sh
create mode 100644 scripts/docker/determine_debian_version_specific_variables.sh
copy scripts/docker/{install_mysql.sh => install_postgres.sh} (54%)
copy scripts/{ci/pre_commit/pre_commit_mypy.sh => in_container/run_migration_reference.sh} (79%)
rename confirm => scripts/tools/confirm (100%)
copy scripts/ci/pre_commit/pre_commit_helm_lint.sh => tests/providers/amazon/aws/hooks/test_rds.py (73%)
mode change 100755 => 100644
create mode 100644 tests/providers/amazon/aws/operators/test_lambda.py
create mode 100644 tests/providers/databricks/hooks/test_databricks_sql.py
create mode 100644 tests/providers/databricks/operators/test_databricks_sql.py
copy tests/{timetables => providers/dbt}/__init__.py (100%)
copy tests/{timetables => providers/dbt/cloud}/__init__.py (100%)
copy tests/{timetables => providers/dbt/cloud/hooks}/__init__.py (100%)
create mode 100644 tests/providers/dbt/cloud/hooks/test_dbt_cloud.py
copy tests/{timetables => providers/dbt/cloud/operators}/__init__.py (100%)
create mode 100644 tests/providers/dbt/cloud/operators/test_dbt_cloud.py
copy tests/{timetables => providers/dbt/cloud/sensors}/__init__.py (100%)
create mode 100644 tests/providers/dbt/cloud/sensors/test_dbt_cloud.py
create mode 100644 tests/providers/google/cloud/hooks/vertex_ai/test_auto_ml.py
copy tests/{www/api/experimental => providers/presto/transfers}/__init__.py (100%)
create mode 100644 tests/providers/presto/transfers/test_gcs_presto.py
copy tests/{www/api/experimental => providers/trino/transfers}/__init__.py (100%)
create mode 100644 tests/providers/trino/transfers/test_gcs_trino.py
create mode 100644 tests/utils/test_db_cleanup.py
[airflow] 03/08: reformat grid background colors
Posted by bb...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch mapped-task-drawer
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit ee869372889c0f2739c09b8d48ed0431d96fd3da
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Fri Feb 25 11:58:23 2022 -0500
reformat grid background colors
---
airflow/www/static/js/tree/InstanceTooltip.jsx | 16 ++---
airflow/www/static/js/tree/SidePanel.jsx | 45 +++++++++++--
airflow/www/static/js/tree/StatusBox.jsx | 19 +++---
airflow/www/static/js/tree/Tree.jsx | 28 ++++----
airflow/www/static/js/tree/dagRuns/Bar.jsx | 9 ++-
airflow/www/static/js/tree/dagRuns/index.jsx | 3 +-
airflow/www/static/js/tree/renderTaskRows.jsx | 88 ++++++++++++++------------
7 files changed, 128 insertions(+), 80 deletions(-)
diff --git a/airflow/www/static/js/tree/InstanceTooltip.jsx b/airflow/www/static/js/tree/InstanceTooltip.jsx
index bc0d58c..b0d0584 100644
--- a/airflow/www/static/js/tree/InstanceTooltip.jsx
+++ b/airflow/www/static/js/tree/InstanceTooltip.jsx
@@ -125,29 +125,29 @@ const InstanceTooltip = ({
</>
)}
<br />
- <Text>
+ {/* <Text>
{taskIdTitle}
{taskId}
- </Text>
- <Text whiteSpace="nowrap">
+ </Text> */}
+ {/* <Text whiteSpace="nowrap">
Run Id:
{' '}
{runId}
- </Text>
- {operator && (
+ </Text> */}
+ {/* {operator && (
<Text>
Operator:
{' '}
{operator}
</Text>
- )}
+ )} */}
<Text>
Duration:
{' '}
{formatDuration(duration || getDuration(startDate, endDate))}
</Text>
<br />
- <Text as="strong">UTC</Text>
+ {/* <Text as="strong">UTC</Text>
<Text>
Started:
{' '}
@@ -173,7 +173,7 @@ const InstanceTooltip = ({
Ended:
{' '}
{endDate && formatDateTime(endDate)}
- </Text>
+ </Text> */}
</Box>
);
};
diff --git a/airflow/www/static/js/tree/SidePanel.jsx b/airflow/www/static/js/tree/SidePanel.jsx
index 3515f1c..7a21eba 100644
--- a/airflow/www/static/js/tree/SidePanel.jsx
+++ b/airflow/www/static/js/tree/SidePanel.jsx
@@ -21,29 +21,60 @@
import React from 'react';
import {
- Box,
chakra,
Flex,
Text,
+ useDisclosure,
+ CloseButton,
+ Button,
+ IconButton,
} from '@chakra-ui/react';
+import { MdKeyboardArrowLeft, MdKeyboardArrowRight } from 'react-icons/md';
import { formatDateTime } from '../datetime_utils';
-const SidePanel = ({ instance: { runId, taskId, executionDate }, isOpen }) => (
- <Box bg="gray.200" maxWidth={isOpen ? 300 : 0} minWidth={isOpen ? 300 : 0} transition="all 0.5s" position="relative" overflow="hidden">
- <Flex right={isOpen ? 0 : -300} top={0} transition="right 0.5s, max-width 0.5s" width={300} flexDirection="column" m={2}>
- <Text as="h4">
+const SidePanel = ({ instance: { runId, taskId, executionDate } }) => {
+ const { isOpen, onOpen, onClose } = useDisclosure();
+ if (!isOpen) {
+ return (
+ <IconButton
+ ml={2}
+ icon={<MdKeyboardArrowLeft size={18} />}
+ aria-label="Open Details Panel"
+ onClick={onOpen}
+ />
+ );
+ }
+ const title = runId && taskId
+ ? (
+ <>
<chakra.span>Task Instance: </chakra.span>
<chakra.b>{taskId}</chakra.b>
<chakra.span> at </chakra.span>
<chakra.b>{formatDateTime(moment.utc(executionDate))}</chakra.b>
+ </>
+ )
+ : (
+ <chakra.span>Dag Details: </chakra.span>
+ );
+
+ return (
+ <Flex bg="gray.200" maxWidth={300} minWidth={300} flexDirection="column" p={3}>
+ <IconButton
+ ml={2}
+ icon={<MdKeyboardArrowRight size={18} />}
+ aria-label="Close Details Panel"
+ onClick={onClose}
+ />
+ <Text as="h4">
+ {title}
</Text>
<Text>
{/* eslint-disable-next-line max-len */}
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Nunc vel risus commodo viverra maecenas accumsan. Ut porttitor leo a diam sollicitudin tempor id eu. Molestie at elementum eu facilisis sed odio morbi quis commodo. Facilisis leo vel fringilla est ullamcorper eget nulla facilisi etiam. Est sit amet facilisis magna etiam tempor orci eu. Id semper risus in hendrerit gravida rutrum. Ac odio tempor orci dapibus [...]
</Text>
</Flex>
- </Box>
-);
+ );
+};
export default SidePanel;
diff --git a/airflow/www/static/js/tree/StatusBox.jsx b/airflow/www/static/js/tree/StatusBox.jsx
index dce0fda..b4abc93 100644
--- a/airflow/www/static/js/tree/StatusBox.jsx
+++ b/airflow/www/static/js/tree/StatusBox.jsx
@@ -24,9 +24,10 @@ import {
Flex,
Box,
Tooltip,
+ useTheme,
} from '@chakra-ui/react';
-import { callModal } from '../dag';
+// import { callModal } from '../dag';
import InstanceTooltip from './InstanceTooltip';
const StatusBox = ({
@@ -35,21 +36,19 @@ const StatusBox = ({
const {
executionDate, taskId, tryNumber = 0, operator, runId,
} = instance;
+ const { colors } = useTheme();
+ const hoverBlue = `${colors.blue[100]}50`;
- const onOpenModal = () => executionDate && callModal(taskId, executionDate, extraLinks, tryNumber, operator === 'SubDagOperator' || undefined, runId);
- const onClick = () => {
- if (group.isMapped) {
- onSelectInstance(instance);
- } else {
- onSelectInstance({});
- onOpenModal();
- }
+ // const onOpenModal = () => executionDate && callModal(taskId, executionDate, extraLinks, tryNumber, operator === 'SubDagOperator' || undefined, runId);
+ const onClick = (e) => {
+ e.stopPropagation();
+ onSelectInstance(instance);
};
// Fetch the corresponding column element and set its background color when hovering
const onMouseOver = () => {
[...containerRef.current.getElementsByClassName(`js-${runId}`)]
- .forEach((e) => { e.style.backgroundColor = 'rgba(113, 128, 150, 0.1)'; });
+ .forEach((e) => { e.style.backgroundColor = hoverBlue; });
};
const onMouseLeave = () => {
[...containerRef.current.getElementsByClassName(`js-${runId}`)]
diff --git a/airflow/www/static/js/tree/Tree.jsx b/airflow/www/static/js/tree/Tree.jsx
index 095adbd..ff1402f 100644
--- a/airflow/www/static/js/tree/Tree.jsx
+++ b/airflow/www/static/js/tree/Tree.jsx
@@ -59,7 +59,7 @@ const Tree = () => {
return (
<Box position="relative" ref={containerRef}>
- <FormControl display="flex" alignItems="center" justifyContent="flex-end" width="100%">
+ <FormControl display="flex" alignItems="center" justifyContent="flex-end" width="100%" mb={2}>
{isRefreshOn && <Spinner color="blue.500" speed="1s" mr="4px" />}
<FormLabel htmlFor="auto-refresh" mb={0} fontSize="12px" fontWeight="normal">
Auto-refresh
@@ -68,19 +68,21 @@ const Tree = () => {
</FormControl>
<Text transform="rotate(-90deg)" position="absolute" left="-6px" top="130px">Runs</Text>
<Text transform="rotate(-90deg)" position="absolute" left="-6px" top="190px">Tasks</Text>
- <Box pl="24px">
+ <Box pl="24px" height="100%" onClick={() => setSelectedInstance({})}>
<Flex position="relative" flexDirection="row" justifyContent="space-between" overflow="hidden">
- <Table mr="24px" overflowX="auto" ref={scrollRef} height={0}>
- <Thead>
- <DagRuns containerRef={containerRef} />
- </Thead>
- <Tbody>
- {renderTaskRows({
- task: groups, containerRef, onSelectInstance,
- })}
- </Tbody>
- </Table>
- <SidePanel isOpen={!!runId} instance={selectedInstance} />
+ <Box mr="12px" pb="12px" overflowX="auto" ref={scrollRef} maxWidth="60vw">
+ <Table height={0}>
+ <Thead>
+ <DagRuns containerRef={containerRef} selectedInstance={selectedInstance} />
+ </Thead>
+ <Tbody>
+ {renderTaskRows({
+ task: groups, containerRef, onSelectInstance, selectedInstance,
+ })}
+ </Tbody>
+ </Table>
+ </Box>
+ <SidePanel instance={selectedInstance} />
</Flex>
</Box>
</Box>
diff --git a/airflow/www/static/js/tree/dagRuns/Bar.jsx b/airflow/www/static/js/tree/dagRuns/Bar.jsx
index a0fa5b1..4dbe20d 100644
--- a/airflow/www/static/js/tree/dagRuns/Bar.jsx
+++ b/airflow/www/static/js/tree/dagRuns/Bar.jsx
@@ -26,6 +26,7 @@ import {
Tooltip,
Text,
VStack,
+ useTheme,
} from '@chakra-ui/react';
import { MdPlayArrow } from 'react-icons/md';
@@ -35,13 +36,16 @@ import { callModalDag } from '../../dag';
const BAR_HEIGHT = 100;
const DagRunBar = ({
- run, max, index, totalRuns, containerRef,
+ run, max, index, totalRuns, containerRef, selectedInstance,
}) => {
+ const { colors } = useTheme();
+ const hoverBlue = `${colors.blue[100]}50`;
let highlightHeight = '100%';
if (containerRef && containerRef.current) {
const table = containerRef.current.getElementsByTagName('tbody')[0];
highlightHeight = table.offsetHeight + BAR_HEIGHT;
}
+ const isSelected = run.runId === selectedInstance.runId;
return (
<Box position="relative">
<Flex
@@ -93,7 +97,8 @@ const DagRunBar = ({
top="1px"
height={highlightHeight}
className={`js-${run.runId}`}
- _peerHover={{ backgroundColor: 'rgba(113, 128, 150, 0.1)' }}
+ bg={isSelected ? 'blue.100' : undefined}
+ _peerHover={!isSelected && { backgroundColor: hoverBlue }}
zIndex={0}
transition="background-color 0.2s"
/>
diff --git a/airflow/www/static/js/tree/dagRuns/index.jsx b/airflow/www/static/js/tree/dagRuns/index.jsx
index a0a4931..7de949f 100644
--- a/airflow/www/static/js/tree/dagRuns/index.jsx
+++ b/airflow/www/static/js/tree/dagRuns/index.jsx
@@ -36,7 +36,7 @@ const DurationTick = ({ children, ...rest }) => (
</Text>
);
-const DagRuns = ({ containerRef }) => {
+const DagRuns = ({ containerRef, selectedInstance }) => {
const { data: { dagRuns = [] } } = useTreeData();
const durations = [];
const runs = dagRuns.map((dagRun) => {
@@ -97,6 +97,7 @@ const DagRuns = ({ containerRef }) => {
index={i}
totalRuns={runs.length}
containerRef={containerRef}
+ selectedInstance={selectedInstance}
/>
))}
</Flex>
diff --git a/airflow/www/static/js/tree/renderTaskRows.jsx b/airflow/www/static/js/tree/renderTaskRows.jsx
index f5a7ba0..7eff252 100644
--- a/airflow/www/static/js/tree/renderTaskRows.jsx
+++ b/airflow/www/static/js/tree/renderTaskRows.jsx
@@ -28,6 +28,7 @@ import {
Flex,
useDisclosure,
Collapse,
+ useTheme,
} from '@chakra-ui/react';
import { FiChevronUp, FiChevronDown } from 'react-icons/fi';
@@ -40,7 +41,7 @@ import { getMetaValue } from '../utils';
const dagId = getMetaValue('dag_id');
const renderTaskRows = ({
- task, containerRef, level = 0, isParentOpen, onSelectInstance,
+ task, containerRef, level = 0, isParentOpen, onSelectInstance, selectedInstance,
}) => task.children.map((t) => (
<Row
key={t.id}
@@ -50,40 +51,37 @@ const renderTaskRows = ({
prevTaskId={task.id}
isParentOpen={isParentOpen}
onSelectInstance={onSelectInstance}
+ selectedInstance={selectedInstance}
/>
));
const TaskName = ({
isGroup = false, isMapped = false, onToggle, isOpen, level, taskName,
}) => (
- <Box _groupHover={{ backgroundColor: 'rgba(113, 128, 150, 0.1)' }} transition="background-color 0.2s">
- <Flex
- as={isGroup ? 'button' : 'div'}
- onClick={() => isGroup && onToggle()}
- color={level > 4 && 'white'}
- aria-label={taskName}
- title={taskName}
- mr={4}
- width="100%"
- backgroundColor={`rgba(203, 213, 224, ${0.25 * level})`}
- alignItems="center"
+ <Flex
+ as={isGroup ? 'button' : 'div'}
+ onClick={() => isGroup && onToggle()}
+ aria-label={taskName}
+ title={taskName}
+ mr={4}
+ width="100%"
+ alignItems="center"
+ >
+ <Text
+ display="inline"
+ fontSize="12px"
+ ml={level * 4 + 4}
+ isTruncated
>
- <Text
- display="inline"
- fontSize="12px"
- ml={level * 4 + 4}
- isTruncated
- >
- {taskName}
- {isMapped && (
- ' [ ]'
- )}
- </Text>
- {isGroup && (
- isOpen ? <FiChevronDown data-testid="open-group" /> : <FiChevronUp data-testid="closed-group" />
+ {taskName}
+ {isMapped && (
+ ' [ ]'
)}
- </Flex>
- </Box>
+ </Text>
+ {isGroup && (
+ isOpen ? <FiChevronDown data-testid="open-group" /> : <FiChevronUp data-testid="closed-group" />
+ )}
+ </Flex>
);
const TaskInstances = ({
@@ -104,16 +102,20 @@ const TaskInstances = ({
onSelectInstance={onSelectInstance}
/>
)
- : <Box key={`${run.runId}-${task.id}`} width="18px" data-testid="blank-task" />;
+ : <Box key={`${run.runId}-${task.id}`} width="16px" data-testid="blank-task" />;
})}
</Flex>
);
-const Row = ({
- task, containerRef, level, prevTaskId, isParentOpen = true, onSelectInstance,
-}) => {
+const Row = (props) => {
+ const {
+ task, containerRef, level, prevTaskId, isParentOpen = true, onSelectInstance, selectedInstance,
+ } = props;
const { data: { dagRuns = [] } } = useTreeData();
+ const { colors } = useTheme();
+ const hoverBlue = `${colors.blue[100]}50`;
const isGroup = !!task.children;
+ const isSelected = selectedInstance.taskId === task.id;
const taskName = prevTaskId ? task.id.replace(`${prevTaskId}.`, '') : task.id;
@@ -136,21 +138,23 @@ const Row = ({
return (
<>
<Tr
- backgroundColor={`rgba(203, 213, 224, ${0.25 * level})`}
+ bg={isSelected ? 'blue.100' : undefined}
borderBottomWidth={isFullyOpen ? 1 : 0}
- borderBottomColor={level > 1 ? 'white' : 'gray.200'}
+ borderBottomColor="gray.200"
role="group"
+ _hover={!isSelected && { bg: hoverBlue }}
+ transition="background-color 0.2s"
>
<Td
- _groupHover={level > 3 && {
- color: 'white',
- }}
+ bg={isSelected ? 'blue.100' : 'white'}
+ _groupHover={!isSelected && ({ bg: 'blue.50' })}
p={0}
+ transition="background-color 0.2s"
lineHeight="18px"
position="sticky"
left={0}
- backgroundColor="white"
borderBottom={0}
+ zIndex={2}
>
<Collapse in={isFullyOpen}>
<TaskName
@@ -164,7 +168,11 @@ const Row = ({
</Collapse>
</Td>
<Td width={0} p={0} borderBottom={0} />
- <Td p={0} align="right" _groupHover={{ backgroundColor: 'rgba(113, 128, 150, 0.1)' }} transition="background-color 0.2s" borderBottom={0}>
+ <Td
+ p={0}
+ align="right"
+ borderBottom={0}
+ >
<Collapse in={isFullyOpen}>
<TaskInstances
dagRuns={dagRuns}
@@ -177,7 +185,9 @@ const Row = ({
</Tr>
{isGroup && (
renderTaskRows({
- task, containerRef, level: level + 1, isParentOpen: isOpen, onSelectInstance,
+ ...props,
+ level: level + 1,
+ isParentOpen: isOpen,
})
)}
</>
[airflow] 05/08: fix hover and extra prop
Posted by bb...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch mapped-task-drawer
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit ce953b379925f3fba3ab0f0053b434f943631451
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Mon Feb 28 21:01:53 2022 -0500
fix hover and extra prop
---
airflow/www/static/js/tree/StatusBox.jsx | 5 +++--
airflow/www/static/js/tree/renderTaskRows.jsx | 1 -
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/airflow/www/static/js/tree/StatusBox.jsx b/airflow/www/static/js/tree/StatusBox.jsx
index 815e6a1..0953a79 100644
--- a/airflow/www/static/js/tree/StatusBox.jsx
+++ b/airflow/www/static/js/tree/StatusBox.jsx
@@ -37,7 +37,7 @@ const StatusBox = ({
const hoverBlue = `${colors.blue[100]}50`;
// Fetch the corresponding column element and set its background color when hovering
- const onMouseOver = () => {
+ const onMouseEnter = () => {
if (selectedInstance.runId !== runId) {
[...containerRef.current.getElementsByClassName(`js-${runId}`)]
.forEach((e) => { e.style.backgroundColor = hoverBlue; });
@@ -50,6 +50,7 @@ const StatusBox = ({
const onClick = (e) => {
e.stopPropagation();
+ onMouseLeave();
onSelectInstance(instance);
};
@@ -73,7 +74,7 @@ const StatusBox = ({
cursor={!group.children && 'pointer'}
data-testid="task-instance"
zIndex={1}
- onMouseEnter={onMouseOver}
+ onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
{...rest}
>
diff --git a/airflow/www/static/js/tree/renderTaskRows.jsx b/airflow/www/static/js/tree/renderTaskRows.jsx
index 9b454f0..7440774 100644
--- a/airflow/www/static/js/tree/renderTaskRows.jsx
+++ b/airflow/www/static/js/tree/renderTaskRows.jsx
@@ -98,7 +98,6 @@ const TaskInstances = ({
key={key}
instance={instance}
containerRef={containerRef}
- extraLinks={task.extraLinks}
group={task}
onSelectInstance={onSelectInstance}
selectedInstance={selectedInstance}
[airflow] 01/08: make UI and tree work with mapped tasks
Posted by bb...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch mapped-task-drawer
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit adfc609476992318a2068dd20ab62f1a0591b806
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Wed Feb 16 11:27:29 2022 -0500
make UI and tree work with mapped tasks
---
airflow/www/static/js/tree/InstanceTooltip.jsx | 15 +++
airflow/www/utils.py | 136 ++++++++++++-------------
2 files changed, 78 insertions(+), 73 deletions(-)
diff --git a/airflow/www/static/js/tree/InstanceTooltip.jsx b/airflow/www/static/js/tree/InstanceTooltip.jsx
index e22189d..bc0d58c 100644
--- a/airflow/www/static/js/tree/InstanceTooltip.jsx
+++ b/airflow/www/static/js/tree/InstanceTooltip.jsx
@@ -25,6 +25,21 @@ import { Box, Text } from '@chakra-ui/react';
import { formatDateTime, getDuration, formatDuration } from '../datetime_utils';
import { finalStatesMap } from '../utils';
+const STATES = [
+ ['success', 0],
+ ['failed', 0],
+ ['upstream_failed', 0],
+ ['up_for_retry', 0],
+ ['up_for_reschedule', 0],
+ ['running', 0],
+ ['deferred', 0],
+ ['sensing', 0],
+ ['queued', 0],
+ ['scheduled', 0],
+ ['skipped', 0],
+ ['no_status', 0],
+];
+
const InstanceTooltip = ({
group,
instance: {
diff --git a/airflow/www/utils.py b/airflow/www/utils.py
index b1f5e0d..ed765d4 100644
--- a/airflow/www/utils.py
+++ b/airflow/www/utils.py
@@ -43,9 +43,8 @@ from airflow.models import errors
from airflow.models.taskinstance import TaskInstance
from airflow.utils import timezone
from airflow.utils.code_utils import get_python_source
-from airflow.utils.helpers import alchemy_to_dict
from airflow.utils.json import AirflowJsonEncoder
-from airflow.utils.state import State, TaskInstanceState
+from airflow.utils.state import State
from airflow.www.forms import DateTimeWithTimezoneField
from airflow.www.widgets import AirflowDateTimePickerWidget
@@ -56,82 +55,13 @@ def datetime_to_string(value: Optional[DateTime]) -> Optional[str]:
return value.isoformat()
-def get_mapped_instances(task_instance, session):
- return (
- session.query(TaskInstance)
- .filter(
- TaskInstance.dag_id == task_instance.dag_id,
- TaskInstance.run_id == task_instance.run_id,
- TaskInstance.task_id == task_instance.task_id,
- TaskInstance.map_index >= 0,
- )
- .all()
- )
-
-
-def get_instance_with_map(task_instance, session):
- if task_instance.map_index == -1:
- return alchemy_to_dict(task_instance)
- mapped_instances = get_mapped_instances(task_instance, session)
- return get_mapped_summary(task_instance, mapped_instances)
-
-
-def get_mapped_summary(parent_instance, task_instances):
- priority = [
- TaskInstanceState.FAILED,
- TaskInstanceState.UPSTREAM_FAILED,
- TaskInstanceState.UP_FOR_RETRY,
- TaskInstanceState.UP_FOR_RESCHEDULE,
- TaskInstanceState.QUEUED,
- TaskInstanceState.SCHEDULED,
- TaskInstanceState.DEFERRED,
- TaskInstanceState.SENSING,
- TaskInstanceState.RUNNING,
- TaskInstanceState.SHUTDOWN,
- TaskInstanceState.RESTARTING,
- TaskInstanceState.REMOVED,
- TaskInstanceState.SUCCESS,
- TaskInstanceState.SKIPPED,
- ]
-
- mapped_states = [ti.state for ti in task_instances]
-
- group_state = None
- for state in priority:
- if state in mapped_states:
- group_state = state
- break
-
- group_start_date = datetime_to_string(
- min((ti.start_date for ti in task_instances if ti.start_date), default=None)
- )
- group_end_date = datetime_to_string(
- max((ti.end_date for ti in task_instances if ti.end_date), default=None)
- )
-
- return {
- 'task_id': parent_instance.task_id,
- 'run_id': parent_instance.run_id,
- 'state': group_state,
- 'start_date': group_start_date,
- 'end_date': group_end_date,
- 'mapped_states': mapped_states,
- 'operator': parent_instance.operator,
- 'execution_date': datetime_to_string(parent_instance.execution_date),
- 'try_number': parent_instance.try_number,
- }
-
-
def encode_ti(
- task_instance: Optional[TaskInstance], is_mapped: Optional[bool], session: Optional[Session]
+ task_instance: Optional[TaskInstance], is_mapped: Optional[bool], session: Session
) -> Optional[Dict[str, Any]]:
if not task_instance:
return None
- if is_mapped:
- return get_mapped_summary(task_instance, task_instances=get_mapped_instances(task_instance, session))
-
- return {
+ summary = {
'task_id': task_instance.task_id,
'dag_id': task_instance.dag_id,
'run_id': task_instance.run_id,
@@ -144,6 +74,66 @@ def encode_ti(
'try_number': task_instance.try_number,
}
+ def get_mapped_summary(task_instances):
+ priority = [
+ 'failed',
+ 'upstream_failed',
+ 'up_for_retry',
+ 'up_for_reschedule',
+ 'queued',
+ 'scheduled',
+ 'deferred',
+ 'sensing',
+ 'running',
+ 'shutdown',
+ 'restarting',
+ 'removed',
+ 'no_status',
+ 'success',
+ 'skipped',
+ ]
+
+ mapped_states = [ti.state for ti in task_instances]
+
+ group_state = None
+ for state in priority:
+ if state in mapped_states:
+ group_state = state
+ break
+
+ group_start_date = datetime_to_string(
+ min((ti.start_date for ti in task_instances if ti.start_date), default=None)
+ )
+ group_end_date = datetime_to_string(
+ max((ti.end_date for ti in task_instances if ti.end_date), default=None)
+ )
+
+ return {
+ 'task_id': task_instance.task_id,
+ 'run_id': task_instance.run_id,
+ 'state': group_state,
+ 'start_date': group_start_date,
+ 'end_date': group_end_date,
+ 'mapped_states': mapped_states,
+ 'operator': task_instance.operator,
+ 'execution_date': datetime_to_string(task_instance.execution_date),
+ 'try_number': task_instance.try_number,
+ }
+
+ if is_mapped:
+ return get_mapped_summary(
+ session.query(TaskInstance)
+ .filter(
+ TaskInstance.dag_id == task_instance.dag_id,
+ TaskInstance.run_id == task_instance.run_id,
+ TaskInstance.task_id == task_instance.task_id,
+ TaskInstance.map_index >= 0,
+ )
+ .all()
+ )
+
+ return summary
+
def encode_dag_run(dag_run: Optional[models.DagRun]) -> Optional[Dict[str, Any]]:
if not dag_run:
[airflow] 06/08: switch from drawer to details section
Posted by bb...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch mapped-task-drawer
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 5cb4defb5ebbe395f7d912561c2ffdf337f5706a
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Tue Mar 1 14:00:11 2022 -0500
switch from drawer to details section
---
airflow/www/forms.py | 4 +-
airflow/www/static/js/tree/InstanceTooltip.jsx | 83 ++------------------
airflow/www/static/js/tree/SidePanel.jsx | 90 ----------------------
airflow/www/static/js/tree/StatusBox.jsx | 6 +-
airflow/www/static/js/tree/Tree.jsx | 66 ++++++++--------
airflow/www/static/js/tree/dagRuns/Bar.jsx | 6 +-
airflow/www/static/js/tree/dagRuns/Tooltip.jsx | 51 +-----------
airflow/www/static/js/tree/dagRuns/index.jsx | 6 +-
airflow/www/static/js/tree/details/Header.jsx | 85 ++++++++++++++++++++
airflow/www/static/js/tree/details/content/Dag.jsx | 31 ++++++++
.../www/static/js/tree/details/content/DagRun.jsx | 31 ++++++++
.../js/tree/details/content/TaskInstance.jsx | 31 ++++++++
airflow/www/static/js/tree/details/index.jsx | 48 ++++++++++++
airflow/www/static/js/tree/renderTaskRows.jsx | 22 +++---
14 files changed, 291 insertions(+), 269 deletions(-)
diff --git a/airflow/www/forms.py b/airflow/www/forms.py
index 3a07cbe..3c3d0ac 100644
--- a/airflow/www/forms.py
+++ b/airflow/www/forms.py
@@ -104,13 +104,13 @@ class DateTimeWithNumRunsForm(FlaskForm):
)
num_runs = SelectField(
"Number of runs",
- default=25,
+ default=10,
choices=(
(5, "5"),
+ (10, "10"),
(25, "25"),
(50, "50"),
(100, "100"),
- (365, "365"),
),
)
diff --git a/airflow/www/static/js/tree/InstanceTooltip.jsx b/airflow/www/static/js/tree/InstanceTooltip.jsx
index b0d0584..e5c1117 100644
--- a/airflow/www/static/js/tree/InstanceTooltip.jsx
+++ b/airflow/www/static/js/tree/InstanceTooltip.jsx
@@ -17,33 +17,16 @@
* under the License.
*/
-/* global moment */
-
import React from 'react';
import { Box, Text } from '@chakra-ui/react';
-import { formatDateTime, getDuration, formatDuration } from '../datetime_utils';
import { finalStatesMap } from '../utils';
-
-const STATES = [
- ['success', 0],
- ['failed', 0],
- ['upstream_failed', 0],
- ['up_for_retry', 0],
- ['up_for_reschedule', 0],
- ['running', 0],
- ['deferred', 0],
- ['sensing', 0],
- ['queued', 0],
- ['scheduled', 0],
- ['skipped', 0],
- ['no_status', 0],
-];
+import { formatDateTime } from '../datetime_utils';
const InstanceTooltip = ({
group,
instance: {
- duration, operator, startDate, endDate, state, taskId, runId, mappedStates,
+ startDate, state, runId, mappedStates,
},
}) => {
const isGroup = !!group.children;
@@ -93,25 +76,20 @@ const InstanceTooltip = ({
});
}
- const taskIdTitle = isGroup ? 'Task Group Id: ' : 'Task Id: ';
-
return (
- <Box fontSize="12px" py="4px">
+ <Box fontSize="12px" py="2px">
{group.tooltip && (
<Text>{group.tooltip}</Text>
)}
<Text>
- <Text as="strong">Status:</Text>
+ <Text as="strong">
+ {isGroup ? 'Overall ' : ''}
+ Status:
+ </Text>
{' '}
{state || 'no status'}
</Text>
- {isGroup && (
- <>
- <br />
- <Text as="strong">Group Summary</Text>
- {groupSummary}
- </>
- )}
+ {isGroup && groupSummary}
{group.isMapped && (
<>
<br />
@@ -124,56 +102,11 @@ const InstanceTooltip = ({
{mapSummary}
</>
)}
- <br />
- {/* <Text>
- {taskIdTitle}
- {taskId}
- </Text> */}
- {/* <Text whiteSpace="nowrap">
- Run Id:
- {' '}
- {runId}
- </Text> */}
- {/* {operator && (
- <Text>
- Operator:
- {' '}
- {operator}
- </Text>
- )} */}
- <Text>
- Duration:
- {' '}
- {formatDuration(duration || getDuration(startDate, endDate))}
- </Text>
- <br />
- {/* <Text as="strong">UTC</Text>
- <Text>
- Started:
- {' '}
- {startDate && formatDateTime(moment.utc(startDate))}
- </Text>
- <Text>
- Ended:
- {' '}
- {endDate && formatDateTime(moment.utc(endDate))}
- </Text>
- <br />
- <Text as="strong">
- Local:
- {' '}
- {moment().format('Z')}
- </Text>
<Text>
Started:
{' '}
{startDate && formatDateTime(startDate)}
</Text>
- <Text>
- Ended:
- {' '}
- {endDate && formatDateTime(endDate)}
- </Text> */}
</Box>
);
};
diff --git a/airflow/www/static/js/tree/SidePanel.jsx b/airflow/www/static/js/tree/SidePanel.jsx
deleted file mode 100644
index 88439a0..0000000
--- a/airflow/www/static/js/tree/SidePanel.jsx
+++ /dev/null
@@ -1,90 +0,0 @@
-/*!
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-/* global moment */
-
-import React from 'react';
-import {
- chakra,
- Flex,
- Text,
- useDisclosure,
- IconButton,
-} from '@chakra-ui/react';
-import { MdKeyboardArrowLeft, MdKeyboardArrowRight } from 'react-icons/md';
-
-import { formatDateTime } from '../datetime_utils';
-
-const SidePanel = ({ instance: { runId, taskId, executionDate } }) => {
- const { isOpen, onOpen, onClose } = useDisclosure();
- if (!isOpen) {
- return (
- <IconButton
- m={2}
- icon={<MdKeyboardArrowLeft size={18} />}
- aria-label="Open Details Panel"
- onClick={onOpen}
- />
- );
- }
- let title = '';
- if (runId && taskId) {
- title = (
- <>
- <chakra.span>Task Instance: </chakra.span>
- <chakra.b>{taskId}</chakra.b>
- <chakra.span> at </chakra.span>
- <chakra.b>{formatDateTime(moment.utc(executionDate))}</chakra.b>
- </>
- );
- } else if (runId) {
- title = (
- <>
- <chakra.span>Dag Run: </chakra.span>
- <chakra.b>{runId}</chakra.b>
- <chakra.span> at </chakra.span>
- <chakra.b>{formatDateTime(moment.utc(executionDate))}</chakra.b>
- </>
- );
- } else {
- title = (
- <chakra.span>Dag Details: </chakra.span>
- );
- }
-
- return (
- <Flex bg="gray.200" maxWidth={isOpen ? '50%' : 0} minWidth={isOpen ? 300 : 0} flexDirection="column" p={3}>
- <IconButton
- m={2}
- icon={<MdKeyboardArrowRight size={18} />}
- aria-label="Close Details Panel"
- onClick={onClose}
- />
- <Text as="h4">
- {title}
- </Text>
- <Text>
- {/* eslint-disable-next-line max-len */}
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Nunc vel risus commodo viverra maecenas accumsan. Ut porttitor leo a diam sollicitudin tempor id eu. Molestie at elementum eu facilisis sed odio morbi quis commodo. Facilisis leo vel fringilla est ullamcorper eget nulla facilisi etiam. Est sit amet facilisis magna etiam tempor orci eu. Id semper risus in hendrerit gravida rutrum. Ac odio tempor orci dapibus [...]
- </Text>
- </Flex>
- );
-};
-
-export default SidePanel;
diff --git a/airflow/www/static/js/tree/StatusBox.jsx b/airflow/www/static/js/tree/StatusBox.jsx
index 0953a79..9609d9a 100644
--- a/airflow/www/static/js/tree/StatusBox.jsx
+++ b/airflow/www/static/js/tree/StatusBox.jsx
@@ -30,7 +30,7 @@ import {
import InstanceTooltip from './InstanceTooltip';
const StatusBox = ({
- group, instance, containerRef, onSelectInstance, selectedInstance, ...rest
+ group, instance, containerRef, onSelect, selected, ...rest
}) => {
const { runId } = instance;
const { colors } = useTheme();
@@ -38,7 +38,7 @@ const StatusBox = ({
// Fetch the corresponding column element and set its background color when hovering
const onMouseEnter = () => {
- if (selectedInstance.runId !== runId) {
+ if (selected.runId !== runId) {
[...containerRef.current.getElementsByClassName(`js-${runId}`)]
.forEach((e) => { e.style.backgroundColor = hoverBlue; });
}
@@ -51,7 +51,7 @@ const StatusBox = ({
const onClick = (e) => {
e.stopPropagation();
onMouseLeave();
- onSelectInstance(instance);
+ onSelect(instance);
};
return (
diff --git a/airflow/www/static/js/tree/Tree.jsx b/airflow/www/static/js/tree/Tree.jsx
index 199e373..1f60d03 100644
--- a/airflow/www/static/js/tree/Tree.jsx
+++ b/airflow/www/static/js/tree/Tree.jsx
@@ -34,13 +34,13 @@ import {
import useTreeData from './useTreeData';
import renderTaskRows from './renderTaskRows';
import DagRuns from './dagRuns';
-import SidePanel from './SidePanel';
+import Details from './details';
const Tree = () => {
const containerRef = useRef();
const scrollRef = useRef();
const { data: { groups = {}, dagRuns = [] }, isRefreshOn, onToggleRefresh } = useTreeData();
- const [selectedInstance, setSelectedInstance] = useState({});
+ const [selected, setSelected] = useState({});
const dagRunIds = dagRuns.map((dr) => dr.runId);
@@ -52,46 +52,42 @@ const Tree = () => {
}
}, []);
- const { runId, taskId } = selectedInstance;
- const onSelectInstance = (newInstance) => (
+ const { runId, taskId } = selected;
+ const onSelect = (newInstance) => (
(newInstance.runId === runId && newInstance.taskId === taskId)
- ? setSelectedInstance({})
- : setSelectedInstance(newInstance)
+ ? setSelected({})
+ : setSelected(newInstance)
);
return (
- <Box position="relative" ref={containerRef}>
- <FormControl display="flex" alignItems="center" justifyContent="flex-end" width="100%" mb={2}>
- {isRefreshOn && <Spinner color="blue.500" speed="1s" mr="4px" />}
- <FormLabel htmlFor="auto-refresh" mb={0} fontSize="12px" fontWeight="normal">
- Auto-refresh
- </FormLabel>
- <Switch id="auto-refresh" onChange={onToggleRefresh} isChecked={isRefreshOn} size="lg" />
- </FormControl>
+ <Flex pl="24px" position="relative" flexDirection="row" justifyContent="space-between" ref={containerRef}>
<Text transform="rotate(-90deg)" position="absolute" left="-6px" top="130px">Runs</Text>
<Text transform="rotate(-90deg)" position="absolute" left="-6px" top="190px">Tasks</Text>
- <Box pl="24px" height="100%" onClick={() => setSelectedInstance({})}>
- <Flex position="relative" flexDirection="row" justifyContent="space-between" overflow="hidden">
- <Box mr="12px" pb="12px" overflowX="auto" ref={scrollRef} maxWidth="60vw">
- <Table height={0}>
- <Thead>
- <DagRuns
- containerRef={containerRef}
- selectedInstance={selectedInstance}
- onSelectInstance={onSelectInstance}
- />
- </Thead>
- <Tbody>
- {renderTaskRows({
- task: groups, containerRef, onSelectInstance, selectedInstance, dagRunIds,
- })}
- </Tbody>
- </Table>
- </Box>
- <SidePanel instance={selectedInstance} />
- </Flex>
+ <Box mr="12px" pb="12px" overflowX="auto" ref={scrollRef} maxWidth="300px" minWidth="300px" position="relative">
+ <FormControl display="flex" alignItems="center" justifyContent="flex-end" width="100%" mb={2}>
+ {isRefreshOn && <Spinner color="blue.500" speed="1s" mr="4px" />}
+ <FormLabel htmlFor="auto-refresh" mb={0} fontSize="12px" fontWeight="normal">
+ Auto-refresh
+ </FormLabel>
+ <Switch id="auto-refresh" onChange={onToggleRefresh} isChecked={isRefreshOn} size="lg" />
+ </FormControl>
+ <Table height={0}>
+ <Thead>
+ <DagRuns
+ containerRef={containerRef}
+ selected={selected}
+ onSelect={onSelect}
+ />
+ </Thead>
+ <Tbody>
+ {renderTaskRows({
+ task: groups, containerRef, onSelect, selected, dagRunIds,
+ })}
+ </Tbody>
+ </Table>
</Box>
- </Box>
+ <Details selected={selected} onSelect={onSelect} />
+ </Flex>
);
};
diff --git a/airflow/www/static/js/tree/dagRuns/Bar.jsx b/airflow/www/static/js/tree/dagRuns/Bar.jsx
index c64abdd..1c8dd6b 100644
--- a/airflow/www/static/js/tree/dagRuns/Bar.jsx
+++ b/airflow/www/static/js/tree/dagRuns/Bar.jsx
@@ -35,7 +35,7 @@ import DagRunTooltip from './Tooltip';
const BAR_HEIGHT = 100;
const DagRunBar = ({
- run, max, index, totalRuns, containerRef, selectedInstance, onSelectInstance,
+ run, max, index, totalRuns, containerRef, selected, onSelect,
}) => {
const { colors } = useTheme();
const hoverBlue = `${colors.blue[100]}50`;
@@ -44,7 +44,7 @@ const DagRunBar = ({
const table = containerRef.current.getElementsByTagName('tbody')[0];
highlightHeight = table.offsetHeight + BAR_HEIGHT;
}
- const isSelected = run.runId === selectedInstance.runId;
+ const isSelected = run.runId === selected.runId;
return (
<Box position="relative">
<Flex
@@ -59,7 +59,7 @@ const DagRunBar = ({
zIndex={1}
onClick={(e) => {
e.stopPropagation();
- onSelectInstance(run);
+ onSelect(run);
}}
position="relative"
data-peer
diff --git a/airflow/www/static/js/tree/dagRuns/Tooltip.jsx b/airflow/www/static/js/tree/dagRuns/Tooltip.jsx
index 4e42cde..70b7f6a 100644
--- a/airflow/www/static/js/tree/dagRuns/Tooltip.jsx
+++ b/airflow/www/static/js/tree/dagRuns/Tooltip.jsx
@@ -17,8 +17,6 @@
* under the License.
*/
-/* global moment */
-
import React from 'react';
import { Box, Text } from '@chakra-ui/react';
import { MdPlayArrow } from 'react-icons/md';
@@ -27,20 +25,19 @@ import { formatDateTime, formatDuration } from '../../datetime_utils';
const DagRunTooltip = ({
dagRun: {
- state, runId, duration, dataIntervalStart, dataIntervalEnd, startDate, endDate, runType,
+ state, duration, dataIntervalEnd, runType,
},
}) => (
- <Box fontSize="12px" py="4px">
+ <Box fontSize="12px" py="2px">
<Text>
<Text as="strong">Status:</Text>
{' '}
{state || 'no status'}
</Text>
- <br />
<Text whiteSpace="nowrap">
- Run Id:
+ Run:
{' '}
- {runId}
+ {formatDateTime(dataIntervalEnd)}
</Text>
<Text>
Run Type:
@@ -53,46 +50,6 @@ const DagRunTooltip = ({
{' '}
{formatDuration(duration)}
</Text>
- <br />
- <Text as="strong">Data Interval:</Text>
- <Text>
- Start:
- {' '}
- {formatDateTime(dataIntervalStart)}
- </Text>
- <Text>
- End:
- {' '}
- {formatDateTime(dataIntervalEnd)}
- </Text>
- <br />
- <Text as="strong">UTC</Text>
- <Text>
- Started:
- {' '}
- {formatDateTime(moment.utc(startDate))}
- </Text>
- <Text>
- Ended:
- {' '}
- {endDate && formatDateTime(moment.utc(endDate))}
- </Text>
- <br />
- <Text as="strong">
- Local:
- {' '}
- {moment().format('Z')}
- </Text>
- <Text>
- Started:
- {' '}
- {formatDateTime(startDate)}
- </Text>
- <Text>
- Ended:
- {' '}
- {endDate && formatDateTime(endDate)}
- </Text>
</Box>
);
diff --git a/airflow/www/static/js/tree/dagRuns/index.jsx b/airflow/www/static/js/tree/dagRuns/index.jsx
index 7459634..7ff4e39 100644
--- a/airflow/www/static/js/tree/dagRuns/index.jsx
+++ b/airflow/www/static/js/tree/dagRuns/index.jsx
@@ -36,7 +36,7 @@ const DurationTick = ({ children, ...rest }) => (
</Text>
);
-const DagRuns = ({ containerRef, selectedInstance, onSelectInstance }) => {
+const DagRuns = ({ containerRef, selected, onSelect }) => {
const { data: { dagRuns = [] } } = useTreeData();
const durations = [];
const runs = dagRuns.map((dagRun) => {
@@ -97,8 +97,8 @@ const DagRuns = ({ containerRef, selectedInstance, onSelectInstance }) => {
index={i}
totalRuns={runs.length}
containerRef={containerRef}
- selectedInstance={selectedInstance}
- onSelectInstance={onSelectInstance}
+ selected={selected}
+ onSelect={onSelect}
/>
))}
</Flex>
diff --git a/airflow/www/static/js/tree/details/Header.jsx b/airflow/www/static/js/tree/details/Header.jsx
new file mode 100644
index 0000000..b9d3086
--- /dev/null
+++ b/airflow/www/static/js/tree/details/Header.jsx
@@ -0,0 +1,85 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 React from 'react';
+import {
+ Breadcrumb,
+ BreadcrumbItem,
+ BreadcrumbLink,
+ Box,
+ Heading,
+} from '@chakra-ui/react';
+import { MdPlayArrow } from 'react-icons/md';
+
+import useTreeData from '../useTreeData';
+import { formatDateTime } from '../../datetime_utils';
+import getMetaValue from '../../meta_value';
+
+const dagId = getMetaValue('dag_id');
+
+const LabelValue = ({ label, value }) => (
+ <Box position="relative">
+ <Heading as="h5" size="sm" color="gray.300" position="absolute" top="-12px">{label}</Heading>
+ <Heading as="h3" size="md">{value}</Heading>
+ </Box>
+);
+
+const Header = ({
+ selected: { taskId, runId },
+ onSelect,
+}) => {
+ const { data: { dagRuns = [] } } = useTreeData();
+ const dagRun = dagRuns.find((r) => r.runId === runId);
+ // console.log(dagRun);
+ let runLabel = dagRun ? formatDateTime(dagRun.dataIntervalEnd) : '';
+ if (dagRun && dagRun.runType === 'manual') {
+ runLabel = (
+ <>
+ <MdPlayArrow style={{ display: 'inline' }} />
+ {runLabel}
+ </>
+ );
+ }
+
+ return (
+ <Breadcrumb>
+ <BreadcrumbItem isCurrentPage={!runId && !taskId}>
+ <BreadcrumbLink onClick={() => onSelect({})}>
+ <LabelValue label="DAG" value={dagId} />
+ </BreadcrumbLink>
+ </BreadcrumbItem>
+ {runId && (
+ <BreadcrumbItem isCurrentPage={runId && !taskId}>
+ <BreadcrumbLink onClick={() => onSelect({ runId })}>
+ <LabelValue label="Run" value={runLabel} />
+ </BreadcrumbLink>
+ </BreadcrumbItem>
+ )}
+ {taskId && (
+ <BreadcrumbItem isCurrentPage>
+ <BreadcrumbLink>
+ <LabelValue label="Task" value={taskId} />
+ </BreadcrumbLink>
+ </BreadcrumbItem>
+ )}
+ </Breadcrumb>
+ );
+};
+
+export default Header;
diff --git a/airflow/www/static/js/tree/details/content/Dag.jsx b/airflow/www/static/js/tree/details/content/Dag.jsx
new file mode 100644
index 0000000..be460ba
--- /dev/null
+++ b/airflow/www/static/js/tree/details/content/Dag.jsx
@@ -0,0 +1,31 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 React from 'react';
+import {
+ Text,
+} from '@chakra-ui/react';
+
+const Dag = () => (
+ <>
+ <Text>dag details</Text>
+ </>
+);
+
+export default Dag;
diff --git a/airflow/www/static/js/tree/details/content/DagRun.jsx b/airflow/www/static/js/tree/details/content/DagRun.jsx
new file mode 100644
index 0000000..58e4b92
--- /dev/null
+++ b/airflow/www/static/js/tree/details/content/DagRun.jsx
@@ -0,0 +1,31 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 React from 'react';
+import {
+ Text,
+} from '@chakra-ui/react';
+
+const DagRun = () => (
+ <>
+ <Text>dag run details</Text>
+ </>
+);
+
+export default DagRun;
diff --git a/airflow/www/static/js/tree/details/content/TaskInstance.jsx b/airflow/www/static/js/tree/details/content/TaskInstance.jsx
new file mode 100644
index 0000000..4ab46e5
--- /dev/null
+++ b/airflow/www/static/js/tree/details/content/TaskInstance.jsx
@@ -0,0 +1,31 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 React from 'react';
+import {
+ Text,
+} from '@chakra-ui/react';
+
+const TaskInstance = () => (
+ <>
+ <Text>task instance details</Text>
+ </>
+);
+
+export default TaskInstance;
diff --git a/airflow/www/static/js/tree/details/index.jsx b/airflow/www/static/js/tree/details/index.jsx
new file mode 100644
index 0000000..b8f960e
--- /dev/null
+++ b/airflow/www/static/js/tree/details/index.jsx
@@ -0,0 +1,48 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 React from 'react';
+import {
+ Flex,
+ Box,
+ Divider,
+} from '@chakra-ui/react';
+
+import Header from './Header';
+import TaskInstanceContent from './content/TaskInstance';
+import DagRunContent from './content/DagRun';
+import DagContent from './content/Dag';
+
+const Details = ({
+ selected,
+ onSelect,
+}) => (
+ <Flex borderLeftWidth="1px" flexDirection="column" p={3} flexGrow={1}>
+ <Header selected={selected} onSelect={onSelect} />
+ <Divider my={2} />
+ <Box>
+ {/* TODO: get full instance data from the API */}
+ {!selected.runId && !selected.taskId && <DagContent />}
+ {selected.runId && !selected.taskId && <DagRunContent />}
+ {selected.taskId && <TaskInstanceContent instance={selected} />}
+ </Box>
+ </Flex>
+);
+
+export default Details;
diff --git a/airflow/www/static/js/tree/renderTaskRows.jsx b/airflow/www/static/js/tree/renderTaskRows.jsx
index 7440774..5e8234e 100644
--- a/airflow/www/static/js/tree/renderTaskRows.jsx
+++ b/airflow/www/static/js/tree/renderTaskRows.jsx
@@ -40,7 +40,7 @@ import { getMetaValue } from '../utils';
const dagId = getMetaValue('dag_id');
const renderTaskRows = ({
- task, containerRef, level = 0, isParentOpen, onSelectInstance, selectedInstance, dagRunIds
+ task, containerRef, level = 0, isParentOpen, onSelect, selected, dagRunIds,
}) => task.children.map((t) => (
<Row
key={t.id}
@@ -49,8 +49,8 @@ const renderTaskRows = ({
containerRef={containerRef}
prevTaskId={task.id}
isParentOpen={isParentOpen}
- onSelectInstance={onSelectInstance}
- selectedInstance={selectedInstance}
+ onSelect={onSelect}
+ selected={selected}
dagRunIds={dagRunIds}
/>
));
@@ -85,7 +85,7 @@ const TaskName = ({
);
const TaskInstances = ({
- task, containerRef, dagRunIds, onSelectInstance, selectedInstance,
+ task, containerRef, dagRunIds, onSelect, selected,
}) => (
<Flex justifyContent="flex-end">
{dagRunIds.map((runId) => {
@@ -99,8 +99,8 @@ const TaskInstances = ({
instance={instance}
containerRef={containerRef}
group={task}
- onSelectInstance={onSelectInstance}
- selectedInstance={selectedInstance}
+ onSelect={onSelect}
+ selected={selected}
/>
)
: <Box key={key} width="16px" data-testid="blank-task" />;
@@ -115,15 +115,15 @@ const Row = (props) => {
level,
prevTaskId,
isParentOpen = true,
- onSelectInstance,
- selectedInstance,
+ onSelect,
+ selected,
dagRunIds,
} = props;
// const { data: { dagRuns = [] } } = useTreeData();
const { colors } = useTheme();
const hoverBlue = `${colors.blue[100]}50`;
const isGroup = !!task.children;
- const isSelected = selectedInstance.taskId === task.id;
+ const isSelected = selected.taskId === task.id;
const taskName = prevTaskId ? task.id.replace(`${prevTaskId}.`, '') : task.id;
@@ -186,8 +186,8 @@ const Row = (props) => {
dagRunIds={dagRunIds}
task={task}
containerRef={containerRef}
- onSelectInstance={onSelectInstance}
- selectedInstance={selectedInstance}
+ onSelect={onSelect}
+ selected={selected}
/>
</Collapse>
</Td>
[airflow] 07/08: add tooltip info to details
Posted by bb...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch mapped-task-drawer
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 2192c4a318bec4958599ac79a49744884edb0482
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Tue Mar 1 18:19:27 2022 -0500
add tooltip info to details
---
.../www/static/js/tree/details/content/DagRun.jsx | 79 ++++++++++-
.../js/tree/details/content/TaskInstance.jsx | 146 ++++++++++++++++++++-
airflow/www/static/js/tree/details/index.jsx | 2 +-
3 files changed, 217 insertions(+), 10 deletions(-)
diff --git a/airflow/www/static/js/tree/details/content/DagRun.jsx b/airflow/www/static/js/tree/details/content/DagRun.jsx
index 58e4b92..abcf908 100644
--- a/airflow/www/static/js/tree/details/content/DagRun.jsx
+++ b/airflow/www/static/js/tree/details/content/DagRun.jsx
@@ -17,15 +17,86 @@
* under the License.
*/
+/* global moment */
+
import React from 'react';
import {
Text,
+ Box,
} from '@chakra-ui/react';
+import { MdPlayArrow } from 'react-icons/md';
+
+import { formatDateTime, formatDuration } from '../../../datetime_utils';
-const DagRun = () => (
- <>
- <Text>dag run details</Text>
- </>
+const DagRun = ({
+ dagRun: {
+ state, runId, duration, dataIntervalStart, dataIntervalEnd, startDate, endDate, runType,
+ },
+}) => (
+ <Box fontSize="12px" py="4px">
+ <Text>
+ <Text as="strong">Status:</Text>
+ {' '}
+ {state || 'no status'}
+ </Text>
+ <br />
+ <Text whiteSpace="nowrap">
+ Run Id:
+ {' '}
+ {runId}
+ </Text>
+ <Text>
+ Run Type:
+ {' '}
+ {runType === 'manual' && <MdPlayArrow style={{ display: 'inline' }} />}
+ {runType}
+ </Text>
+ <Text>
+ Duration:
+ {' '}
+ {formatDuration(duration)}
+ </Text>
+ <br />
+ <Text as="strong">Data Interval:</Text>
+ <Text>
+ Start:
+ {' '}
+ {formatDateTime(dataIntervalStart)}
+ </Text>
+ <Text>
+ End:
+ {' '}
+ {formatDateTime(dataIntervalEnd)}
+ </Text>
+ <br />
+ <Text as="strong">UTC</Text>
+ <Text>
+ Started:
+ {' '}
+ {formatDateTime(moment.utc(startDate))}
+ </Text>
+ <Text>
+ Ended:
+ {' '}
+ {endDate && formatDateTime(moment.utc(endDate))}
+ </Text>
+ <br />
+ <Text as="strong">
+ Local:
+ {' '}
+ {moment().format('Z')}
+ </Text>
+ <Text>
+ Started:
+ {' '}
+ {formatDateTime(startDate)}
+ </Text>
+ <Text>
+ Ended:
+ {' '}
+ {endDate && formatDateTime(endDate)}
+ </Text>
+ </Box>
);
export default DagRun;
diff --git a/airflow/www/static/js/tree/details/content/TaskInstance.jsx b/airflow/www/static/js/tree/details/content/TaskInstance.jsx
index 4ab46e5..bc60737 100644
--- a/airflow/www/static/js/tree/details/content/TaskInstance.jsx
+++ b/airflow/www/static/js/tree/details/content/TaskInstance.jsx
@@ -17,15 +17,151 @@
* under the License.
*/
+/* global moment */
+
import React from 'react';
import {
Text,
+ Box,
} from '@chakra-ui/react';
-const TaskInstance = () => (
- <>
- <Text>task instance details</Text>
- </>
-);
+import { formatDateTime, getDuration, formatDuration } from '../../../datetime_utils';
+
+const TaskInstance = ({
+ instance: {
+ duration, operator, startDate, endDate, state, taskId, runId, // mappedStates,
+ },
+}) => {
+ const isGroup = false; // !!group.children;
+ const groupSummary = [];
+ // const mapSummary = [];
+
+ // if (isGroup) {
+ // const numMap = finalStatesMap();
+ // group.children.forEach((child) => {
+ // const taskInstance = child.instances.find((ti) => ti.runId === runId);
+ // if (taskInstance) {
+ // const stateKey = taskInstance.state == null ? 'no_status' : taskInstance.state;
+ // if (numMap.has(stateKey)) numMap.set(stateKey, numMap.get(stateKey) + 1);
+ // }
+ // });
+ // numMap.forEach((key, val) => {
+ // if (key > 0) {
+ // groupSummary.push(
+ // // eslint-disable-next-line react/no-array-index-key
+ // <Text key={val} ml="10px">
+ // {val}
+ // {': '}
+ // {key}
+ // </Text>,
+ // );
+ // }
+ // });
+ // }
+
+ // if (group.isMapped && mappedStates) {
+ // const numMap = finalStatesMap();
+ // mappedStates.forEach((s) => {
+ // const stateKey = s || 'no_status';
+ // if (numMap.has(stateKey)) numMap.set(stateKey, numMap.get(stateKey) + 1);
+ // });
+ // numMap.forEach((key, val) => {
+ // if (key > 0) {
+ // mapSummary.push(
+ // // eslint-disable-next-line react/no-array-index-key
+ // <Text key={val} ml="10px">
+ // {val}
+ // {': '}
+ // {key}
+ // </Text>,
+ // );
+ // }
+ // });
+ // }
+
+ const taskIdTitle = isGroup ? 'Task Group Id: ' : 'Task Id: ';
+
+ return (
+ <Box fontSize="12px" py="4px">
+ {/* {group.tooltip && (
+ <Text>{group.tooltip}</Text>
+ )} */}
+ <Text>
+ <Text as="strong">Status:</Text>
+ {' '}
+ {state || 'no status'}
+ </Text>
+ {isGroup && (
+ <>
+ <br />
+ <Text as="strong">Group Summary</Text>
+ {groupSummary}
+ </>
+ )}
+ {/* {group.isMapped && (
+ <>
+ <br />
+ <Text as="strong">
+ {mappedStates.length}
+ {' '}
+ {mappedStates.length === 1 ? 'Task ' : 'Tasks '}
+ Mapped
+ </Text>
+ {mapSummary}
+ </>
+ )} */}
+ <br />
+ <Text>
+ {taskIdTitle}
+ {taskId}
+ </Text>
+ <Text whiteSpace="nowrap">
+ Run Id:
+ {' '}
+ {runId}
+ </Text>
+ {operator && (
+ <Text>
+ Operator:
+ {' '}
+ {operator}
+ </Text>
+ )}
+ <Text>
+ Duration:
+ {' '}
+ {formatDuration(duration || getDuration(startDate, endDate))}
+ </Text>
+ <br />
+ <Text as="strong">UTC</Text>
+ <Text>
+ Started:
+ {' '}
+ {startDate && formatDateTime(moment.utc(startDate))}
+ </Text>
+ <Text>
+ Ended:
+ {' '}
+ {endDate && formatDateTime(moment.utc(endDate))}
+ </Text>
+ <br />
+ <Text as="strong">
+ Local:
+ {' '}
+ {moment().format('Z')}
+ </Text>
+ <Text>
+ Started:
+ {' '}
+ {startDate && formatDateTime(startDate)}
+ </Text>
+ <Text>
+ Ended:
+ {' '}
+ {endDate && formatDateTime(endDate)}
+ </Text>
+ </Box>
+ );
+};
export default TaskInstance;
diff --git a/airflow/www/static/js/tree/details/index.jsx b/airflow/www/static/js/tree/details/index.jsx
index b8f960e..31610a7 100644
--- a/airflow/www/static/js/tree/details/index.jsx
+++ b/airflow/www/static/js/tree/details/index.jsx
@@ -39,7 +39,7 @@ const Details = ({
<Box>
{/* TODO: get full instance data from the API */}
{!selected.runId && !selected.taskId && <DagContent />}
- {selected.runId && !selected.taskId && <DagRunContent />}
+ {selected.runId && !selected.taskId && <DagRunContent dagRun={selected} />}
{selected.taskId && <TaskInstanceContent instance={selected} />}
</Box>
</Flex>
[airflow] 08/08: use API
Posted by bb...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch mapped-task-drawer
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 2f8e4446324ecc7ac40ef5427b4638ecc8ea1d36
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Tue Mar 1 19:44:16 2022 -0500
use API
---
airflow/www/package.json | 2 +
airflow/www/static/js/tree/StatusBox.jsx | 6 +-
airflow/www/static/js/tree/Tree.jsx | 16 ++--
.../tree/{details/content/Dag.jsx => api/index.js} | 21 +++--
.../{details/content/Dag.jsx => api/useDag.js} | 19 ++--
.../{details/content/Dag.jsx => api/useTasks.js} | 19 ++--
airflow/www/static/js/tree/dagRuns/Bar.jsx | 2 +-
airflow/www/static/js/tree/details/Header.jsx | 5 +-
airflow/www/static/js/tree/details/content/Dag.jsx | 36 ++++++-
.../js/tree/details/content/TaskInstance.jsx | 100 ++++++++++----------
airflow/www/static/js/tree/details/index.jsx | 34 ++++---
airflow/www/static/js/tree/index.jsx | 13 ++-
airflow/www/yarn.lock | 104 +++++++++++++++++++--
13 files changed, 257 insertions(+), 120 deletions(-)
diff --git a/airflow/www/package.json b/airflow/www/package.json
index 6d52987..717d5b1 100644
--- a/airflow/www/package.json
+++ b/airflow/www/package.json
@@ -74,6 +74,7 @@
"@emotion/cache": "^11.4.0",
"@emotion/react": "^11.4.1",
"@emotion/styled": "^11",
+ "axios": "^0.26.0",
"bootstrap-3-typeahead": "^4.0.2",
"camelcase-keys": "^7.0.0",
"codemirror": "^5.59.1",
@@ -92,6 +93,7 @@
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-icons": "^4.2.0",
+ "react-query": "^3.34.16",
"redoc": "^2.0.0-rc.63",
"url-search-params-polyfill": "^8.1.0"
},
diff --git a/airflow/www/static/js/tree/StatusBox.jsx b/airflow/www/static/js/tree/StatusBox.jsx
index 9609d9a..62762c5 100644
--- a/airflow/www/static/js/tree/StatusBox.jsx
+++ b/airflow/www/static/js/tree/StatusBox.jsx
@@ -32,7 +32,7 @@ import InstanceTooltip from './InstanceTooltip';
const StatusBox = ({
group, instance, containerRef, onSelect, selected, ...rest
}) => {
- const { runId } = instance;
+ const { runId, taskId } = instance;
const { colors } = useTheme();
const hoverBlue = `${colors.blue[100]}50`;
@@ -51,7 +51,9 @@ const StatusBox = ({
const onClick = (e) => {
e.stopPropagation();
onMouseLeave();
- onSelect(instance);
+ onSelect({
+ taskId, runId, instance, task: group,
+ });
};
return (
diff --git a/airflow/www/static/js/tree/Tree.jsx b/airflow/www/static/js/tree/Tree.jsx
index 1f60d03..aeeaeb5 100644
--- a/airflow/www/static/js/tree/Tree.jsx
+++ b/airflow/www/static/js/tree/Tree.jsx
@@ -63,14 +63,14 @@ const Tree = () => {
<Flex pl="24px" position="relative" flexDirection="row" justifyContent="space-between" ref={containerRef}>
<Text transform="rotate(-90deg)" position="absolute" left="-6px" top="130px">Runs</Text>
<Text transform="rotate(-90deg)" position="absolute" left="-6px" top="190px">Tasks</Text>
- <Box mr="12px" pb="12px" overflowX="auto" ref={scrollRef} maxWidth="300px" minWidth="300px" position="relative">
- <FormControl display="flex" alignItems="center" justifyContent="flex-end" width="100%" mb={2}>
- {isRefreshOn && <Spinner color="blue.500" speed="1s" mr="4px" />}
- <FormLabel htmlFor="auto-refresh" mb={0} fontSize="12px" fontWeight="normal">
- Auto-refresh
- </FormLabel>
- <Switch id="auto-refresh" onChange={onToggleRefresh} isChecked={isRefreshOn} size="lg" />
- </FormControl>
+ <FormControl display="flex" position="absolute" left="220px">
+ {isRefreshOn && <Spinner color="blue.500" speed="1s" mr="4px" />}
+ <FormLabel htmlFor="auto-refresh" mb={0} fontSize="12px" fontWeight="normal">
+ Auto-refresh
+ </FormLabel>
+ <Switch id="auto-refresh" onChange={onToggleRefresh} isChecked={isRefreshOn} size="lg" />
+ </FormControl>
+ <Box mr="12px" pb="12px" overflowX="auto" ref={scrollRef} maxWidth="300px" minWidth="300px" position="relative" mt="24px">
<Table height={0}>
<Thead>
<DagRuns
diff --git a/airflow/www/static/js/tree/details/content/Dag.jsx b/airflow/www/static/js/tree/api/index.js
similarity index 72%
copy from airflow/www/static/js/tree/details/content/Dag.jsx
copy to airflow/www/static/js/tree/api/index.js
index be460ba..58edd88 100644
--- a/airflow/www/static/js/tree/details/content/Dag.jsx
+++ b/airflow/www/static/js/tree/api/index.js
@@ -17,15 +17,18 @@
* under the License.
*/
-import React from 'react';
-import {
- Text,
-} from '@chakra-ui/react';
+import axios from 'axios';
+import camelcaseKeys from 'camelcase-keys';
-const Dag = () => (
- <>
- <Text>dag details</Text>
- </>
+import useDag from './useDag';
+import useTasks from './useTasks';
+
+axios.defaults.baseURL = '/api/v1';
+axios.interceptors.response.use(
+ (res) => (res.data ? camelcaseKeys(res.data, { deep: true }) : res),
);
-export default Dag;
+export {
+ useDag,
+ useTasks,
+};
diff --git a/airflow/www/static/js/tree/details/content/Dag.jsx b/airflow/www/static/js/tree/api/useDag.js
similarity index 80%
copy from airflow/www/static/js/tree/details/content/Dag.jsx
copy to airflow/www/static/js/tree/api/useDag.js
index be460ba..6c19ee4 100644
--- a/airflow/www/static/js/tree/details/content/Dag.jsx
+++ b/airflow/www/static/js/tree/api/useDag.js
@@ -17,15 +17,12 @@
* under the License.
*/
-import React from 'react';
-import {
- Text,
-} from '@chakra-ui/react';
+import axios from 'axios';
+import { useQuery } from 'react-query';
-const Dag = () => (
- <>
- <Text>dag details</Text>
- </>
-);
-
-export default Dag;
+export default function useDag(dagId) {
+ return useQuery(
+ ['dag', dagId],
+ () => axios.get(`/dags/${dagId}`),
+ );
+}
diff --git a/airflow/www/static/js/tree/details/content/Dag.jsx b/airflow/www/static/js/tree/api/useTasks.js
similarity index 80%
copy from airflow/www/static/js/tree/details/content/Dag.jsx
copy to airflow/www/static/js/tree/api/useTasks.js
index be460ba..3dd11e30 100644
--- a/airflow/www/static/js/tree/details/content/Dag.jsx
+++ b/airflow/www/static/js/tree/api/useTasks.js
@@ -17,15 +17,12 @@
* under the License.
*/
-import React from 'react';
-import {
- Text,
-} from '@chakra-ui/react';
+import axios from 'axios';
+import { useQuery } from 'react-query';
-const Dag = () => (
- <>
- <Text>dag details</Text>
- </>
-);
-
-export default Dag;
+export default function useTasks(dagId) {
+ return useQuery(
+ ['tasks', dagId],
+ () => axios.get(`/dags/${dagId}/tasks`),
+ );
+}
diff --git a/airflow/www/static/js/tree/dagRuns/Bar.jsx b/airflow/www/static/js/tree/dagRuns/Bar.jsx
index 1c8dd6b..94c84e7 100644
--- a/airflow/www/static/js/tree/dagRuns/Bar.jsx
+++ b/airflow/www/static/js/tree/dagRuns/Bar.jsx
@@ -59,7 +59,7 @@ const DagRunBar = ({
zIndex={1}
onClick={(e) => {
e.stopPropagation();
- onSelect(run);
+ onSelect({ runId: run.runId, dagRun: run });
}}
position="relative"
data-peer
diff --git a/airflow/www/static/js/tree/details/Header.jsx b/airflow/www/static/js/tree/details/Header.jsx
index b9d3086..c362606 100644
--- a/airflow/www/static/js/tree/details/Header.jsx
+++ b/airflow/www/static/js/tree/details/Header.jsx
@@ -27,9 +27,8 @@ import {
} from '@chakra-ui/react';
import { MdPlayArrow } from 'react-icons/md';
-import useTreeData from '../useTreeData';
import { formatDateTime } from '../../datetime_utils';
-import getMetaValue from '../../meta_value';
+import { getMetaValue } from '../../utils';
const dagId = getMetaValue('dag_id');
@@ -43,8 +42,8 @@ const LabelValue = ({ label, value }) => (
const Header = ({
selected: { taskId, runId },
onSelect,
+ dagRuns,
}) => {
- const { data: { dagRuns = [] } } = useTreeData();
const dagRun = dagRuns.find((r) => r.runId === runId);
// console.log(dagRun);
let runLabel = dagRun ? formatDateTime(dagRun.dataIntervalEnd) : '';
diff --git a/airflow/www/static/js/tree/details/content/Dag.jsx b/airflow/www/static/js/tree/details/content/Dag.jsx
index be460ba..e71d9c2 100644
--- a/airflow/www/static/js/tree/details/content/Dag.jsx
+++ b/airflow/www/static/js/tree/details/content/Dag.jsx
@@ -20,12 +20,38 @@
import React from 'react';
import {
Text,
+ Tag,
+ Code,
+ Flex,
+ HStack,
} from '@chakra-ui/react';
-const Dag = () => (
- <>
- <Text>dag details</Text>
- </>
-);
+import { getMetaValue } from '../../../utils';
+import { useDag } from '../../api';
+
+const dagId = getMetaValue('dag_id');
+
+const Dag = () => {
+ const { data: dag } = useDag(dagId);
+ if (!dag) return null;
+ const {
+ description, tags, fileloc, owners,
+ } = dag;
+ return (
+ <>
+ {description && <Text>{description}</Text>}
+ <HStack>{tags.map((tag) => <Tag key={tag.name} size="lg">{tag.name}</Tag>)}</HStack>
+ <Text>
+ Relative File Location:
+ {' '}
+ <Code colorScheme="blackAlpha">{fileloc}</Code>
+ </Text>
+ <Flex>
+ <Text mr={2}>Owner:</Text>
+ {owners.map((o) => <Text key={o}>{o}</Text>)}
+ </Flex>
+ </>
+ );
+};
export default Dag;
diff --git a/airflow/www/static/js/tree/details/content/TaskInstance.jsx b/airflow/www/static/js/tree/details/content/TaskInstance.jsx
index bc60737..0c0a21e 100644
--- a/airflow/www/static/js/tree/details/content/TaskInstance.jsx
+++ b/airflow/www/static/js/tree/details/content/TaskInstance.jsx
@@ -24,68 +24,70 @@ import {
Text,
Box,
} from '@chakra-ui/react';
+import { finalStatesMap } from '../../../utils';
import { formatDateTime, getDuration, formatDuration } from '../../../datetime_utils';
const TaskInstance = ({
instance: {
- duration, operator, startDate, endDate, state, taskId, runId, // mappedStates,
+ duration, operator, startDate, endDate, state, taskId, runId, mappedStates,
},
+ task,
}) => {
- const isGroup = false; // !!group.children;
+ const isGroup = !!task.children;
const groupSummary = [];
- // const mapSummary = [];
+ const mapSummary = [];
- // if (isGroup) {
- // const numMap = finalStatesMap();
- // group.children.forEach((child) => {
- // const taskInstance = child.instances.find((ti) => ti.runId === runId);
- // if (taskInstance) {
- // const stateKey = taskInstance.state == null ? 'no_status' : taskInstance.state;
- // if (numMap.has(stateKey)) numMap.set(stateKey, numMap.get(stateKey) + 1);
- // }
- // });
- // numMap.forEach((key, val) => {
- // if (key > 0) {
- // groupSummary.push(
- // // eslint-disable-next-line react/no-array-index-key
- // <Text key={val} ml="10px">
- // {val}
- // {': '}
- // {key}
- // </Text>,
- // );
- // }
- // });
- // }
+ if (isGroup) {
+ const numMap = finalStatesMap();
+ task.children.forEach((child) => {
+ const taskInstance = child.instances.find((ti) => ti.runId === runId);
+ if (taskInstance) {
+ const stateKey = taskInstance.state == null ? 'no_status' : taskInstance.state;
+ if (numMap.has(stateKey)) numMap.set(stateKey, numMap.get(stateKey) + 1);
+ }
+ });
+ numMap.forEach((key, val) => {
+ if (key > 0) {
+ groupSummary.push(
+ // eslint-disable-next-line react/no-array-index-key
+ <Text key={val} ml="10px">
+ {val}
+ {': '}
+ {key}
+ </Text>,
+ );
+ }
+ });
+ }
- // if (group.isMapped && mappedStates) {
- // const numMap = finalStatesMap();
- // mappedStates.forEach((s) => {
- // const stateKey = s || 'no_status';
- // if (numMap.has(stateKey)) numMap.set(stateKey, numMap.get(stateKey) + 1);
- // });
- // numMap.forEach((key, val) => {
- // if (key > 0) {
- // mapSummary.push(
- // // eslint-disable-next-line react/no-array-index-key
- // <Text key={val} ml="10px">
- // {val}
- // {': '}
- // {key}
- // </Text>,
- // );
- // }
- // });
- // }
+ if (task.isMapped && mappedStates) {
+ const numMap = finalStatesMap();
+ mappedStates.forEach((s) => {
+ const stateKey = s || 'no_status';
+ if (numMap.has(stateKey)) numMap.set(stateKey, numMap.get(stateKey) + 1);
+ });
+ numMap.forEach((key, val) => {
+ if (key > 0) {
+ mapSummary.push(
+ // eslint-disable-next-line react/no-array-index-key
+ <Text key={val} ml="10px">
+ {val}
+ {': '}
+ {key}
+ </Text>,
+ );
+ }
+ });
+ }
const taskIdTitle = isGroup ? 'Task Group Id: ' : 'Task Id: ';
return (
<Box fontSize="12px" py="4px">
- {/* {group.tooltip && (
- <Text>{group.tooltip}</Text>
- )} */}
+ {task.tooltip && (
+ <Text>{task.tooltip}</Text>
+ )}
<Text>
<Text as="strong">Status:</Text>
{' '}
@@ -98,7 +100,7 @@ const TaskInstance = ({
{groupSummary}
</>
)}
- {/* {group.isMapped && (
+ {task.isMapped && (
<>
<br />
<Text as="strong">
@@ -109,7 +111,7 @@ const TaskInstance = ({
</Text>
{mapSummary}
</>
- )} */}
+ )}
<br />
<Text>
{taskIdTitle}
diff --git a/airflow/www/static/js/tree/details/index.jsx b/airflow/www/static/js/tree/details/index.jsx
index 31610a7..ee3b044 100644
--- a/airflow/www/static/js/tree/details/index.jsx
+++ b/airflow/www/static/js/tree/details/index.jsx
@@ -28,21 +28,31 @@ import Header from './Header';
import TaskInstanceContent from './content/TaskInstance';
import DagRunContent from './content/DagRun';
import DagContent from './content/Dag';
+import useTreeData from '../useTreeData';
const Details = ({
selected,
onSelect,
-}) => (
- <Flex borderLeftWidth="1px" flexDirection="column" p={3} flexGrow={1}>
- <Header selected={selected} onSelect={onSelect} />
- <Divider my={2} />
- <Box>
- {/* TODO: get full instance data from the API */}
- {!selected.runId && !selected.taskId && <DagContent />}
- {selected.runId && !selected.taskId && <DagRunContent dagRun={selected} />}
- {selected.taskId && <TaskInstanceContent instance={selected} />}
- </Box>
- </Flex>
-);
+}) => {
+ const { data: { dagRuns = [] } } = useTreeData();
+ console.log(selected);
+ return (
+ <Flex borderLeftWidth="1px" flexDirection="column" p={3} flexGrow={1}>
+ <Header selected={selected} onSelect={onSelect} dagRuns={dagRuns} />
+ <Divider my={2} />
+ <Box>
+ {/* TODO: get full instance data from the API */}
+ {!selected.runId && !selected.taskId && <DagContent />}
+ {selected.runId && !selected.taskId && <DagRunContent dagRun={selected.dagRun} />}
+ {selected.taskId && (
+ <TaskInstanceContent
+ instance={selected.instance}
+ task={selected.task}
+ />
+ )}
+ </Box>
+ </Flex>
+ );
+};
export default Details;
diff --git a/airflow/www/static/js/tree/index.jsx b/airflow/www/static/js/tree/index.jsx
index 454f4f0..4eea821 100644
--- a/airflow/www/static/js/tree/index.jsx
+++ b/airflow/www/static/js/tree/index.jsx
@@ -24,6 +24,7 @@ import ReactDOM from 'react-dom';
import { ChakraProvider } from '@chakra-ui/react';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
+import { QueryClient, QueryClientProvider } from 'react-query';
import Tree from './Tree';
// create shadowRoot
@@ -36,12 +37,22 @@ const myCache = createCache({
const mainElement = document.getElementById('react-container');
shadowRoot.appendChild(mainElement);
+const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ refetchOnWindowFocus: false,
+ },
+ },
+});
+
function App() {
return (
<React.StrictMode>
<CacheProvider value={myCache}>
<ChakraProvider>
- <Tree />
+ <QueryClientProvider client={queryClient}>
+ <Tree />
+ </QueryClientProvider>
</ChakraProvider>
</CacheProvider>
</React.StrictMode>
diff --git a/airflow/www/yarn.lock b/airflow/www/yarn.lock
index 79c0165..0e9a1ee 100644
--- a/airflow/www/yarn.lock
+++ b/airflow/www/yarn.lock
@@ -1263,7 +1263,7 @@
core-js-pure "^3.16.0"
regenerator-runtime "^0.13.4"
-"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.13":
+"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2":
version "7.17.2"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941"
integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==
@@ -3254,6 +3254,13 @@ axe-core@^4.0.2:
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.3.3.tgz#b55cd8e8ddf659fe89b064680e1c6a4dceab0325"
integrity sha512-/lqqLAmuIPi79WYfRpy2i8z+x+vxU3zX2uAm0gs1q52qTuKwolOj1P8XbufpXcsydrpKx2yGn2wzAnxCMV86QA==
+axios@^0.26.0:
+ version "0.26.0"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.0.tgz#9a318f1c69ec108f8cd5f3c3d390366635e13928"
+ integrity sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==
+ dependencies:
+ follow-redirects "^1.14.8"
+
axobject-query@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
@@ -3594,6 +3601,11 @@ base@^0.11.1:
mixin-deep "^1.2.0"
pascalcase "^0.1.1"
+big-integer@^1.6.16:
+ version "1.6.51"
+ resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686"
+ integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==
+
big.js@^3.1.3:
version "3.2.0"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e"
@@ -3682,6 +3694,20 @@ braces@^3.0.1, braces@~3.0.2:
dependencies:
fill-range "^7.0.1"
+broadcast-channel@^3.4.1:
+ version "3.7.0"
+ resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-3.7.0.tgz#2dfa5c7b4289547ac3f6705f9c00af8723889937"
+ integrity sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==
+ dependencies:
+ "@babel/runtime" "^7.7.2"
+ detect-node "^2.1.0"
+ js-sha3 "0.8.0"
+ microseconds "0.2.0"
+ nano-time "1.0.0"
+ oblivious-set "1.0.0"
+ rimraf "3.0.2"
+ unload "2.2.0"
+
brorand@^1.0.1, brorand@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
@@ -5082,6 +5108,11 @@ detect-node-es@^1.1.0:
resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493"
integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==
+detect-node@^2.0.4, detect-node@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1"
+ integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==
+
diff-sequences@^27.0.6:
version "27.0.6"
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.0.6.tgz#3305cb2e55a033924054695cc66019fd7f8e5723"
@@ -5994,6 +6025,11 @@ focus-lock@^0.9.1:
dependencies:
tslib "^2.0.3"
+follow-redirects@^1.14.8:
+ version "1.14.9"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7"
+ integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==
+
for-in@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@@ -7621,6 +7657,11 @@ js-levenshtein@^1.1.6:
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==
+js-sha3@0.8.0:
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
+ integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
+
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@@ -8072,6 +8113,14 @@ marked@^4.0.10:
resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.12.tgz#2262a4e6fd1afd2f13557726238b69a48b982f7d"
integrity sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==
+match-sorter@^6.0.2:
+ version "6.3.1"
+ resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.3.1.tgz#98cc37fda756093424ddf3cbc62bfe9c75b92bda"
+ integrity sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+ remove-accents "0.4.2"
+
mathml-tag-names@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3"
@@ -8198,6 +8247,11 @@ micromatch@^4.0.2, micromatch@^4.0.4:
braces "^3.0.1"
picomatch "^2.2.3"
+microseconds@0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39"
+ integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==
+
miller-rabin@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
@@ -8422,6 +8476,13 @@ nan@^2.12.1:
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
+nano-time@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef"
+ integrity sha1-sFVPaa2J4i0JB/ehKwmTpdlhN+8=
+ dependencies:
+ big-integer "^1.6.16"
+
nanoid@^3.1.23:
version "3.1.23"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81"
@@ -8756,6 +8817,11 @@ object.values@^1.1.4:
define-properties "^1.1.3"
es-abstract "^1.18.2"
+oblivious-set@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/oblivious-set/-/oblivious-set-1.0.0.tgz#c8316f2c2fb6ff7b11b6158db3234c49f733c566"
+ integrity sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==
+
once@^1.3.0, once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -9735,6 +9801,15 @@ react-is@^17.0.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
+react-query@^3.34.16:
+ version "3.34.16"
+ resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.34.16.tgz#279ea180bcaeaec49c7864b29d1711ee9f152594"
+ integrity sha512-7FvBvjgEM4YQ8nPfmAr+lJfbW95uyW/TVjFoi2GwCkF33/S8ajx45tuPHPFGWs4qYwPy1mzwxD4IQfpUDrefNQ==
+ dependencies:
+ "@babel/runtime" "^7.5.5"
+ broadcast-channel "^3.4.1"
+ match-sorter "^6.0.2"
+
react-remove-scroll-bar@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.2.0.tgz#d4d545a7df024f75d67e151499a6ab5ac97c8cdd"
@@ -10007,6 +10082,11 @@ remark@^13.0.0:
remark-stringify "^9.0.0"
unified "^9.1.0"
+remove-accents@0.4.2:
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5"
+ integrity sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U=
+
remove-trailing-separator@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
@@ -10127,6 +10207,13 @@ rgba-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
+rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
+ integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
+ dependencies:
+ glob "^7.1.3"
+
rimraf@^2.5.4, rimraf@^2.6.3:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
@@ -10134,13 +10221,6 @@ rimraf@^2.5.4, rimraf@^2.6.3:
dependencies:
glob "^7.1.3"
-rimraf@^3.0.0, rimraf@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
- integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
- dependencies:
- glob "^7.1.3"
-
ripemd160@^2.0.0, ripemd160@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
@@ -11365,6 +11445,14 @@ universalify@^0.1.0, universalify@^0.1.2:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+unload@2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/unload/-/unload-2.2.0.tgz#ccc88fdcad345faa06a92039ec0f80b488880ef7"
+ integrity sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==
+ dependencies:
+ "@babel/runtime" "^7.6.2"
+ detect-node "^2.0.4"
+
unset-value@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
[airflow] 02/08: basic slide drawer
Posted by bb...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch mapped-task-drawer
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 780d6a22ebf73f153d58240ba3247ebbf050c163
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Wed Feb 16 13:57:33 2022 -0500
basic slide drawer
---
airflow/www/static/js/tree/SidePanel.jsx | 49 +++++++++++++++++
airflow/www/static/js/tree/StatusBox.jsx | 75 +++++++++++++++------------
airflow/www/static/js/tree/Tree.jsx | 25 ++++++---
airflow/www/static/js/tree/renderTaskRows.jsx | 19 +++++--
4 files changed, 125 insertions(+), 43 deletions(-)
diff --git a/airflow/www/static/js/tree/SidePanel.jsx b/airflow/www/static/js/tree/SidePanel.jsx
new file mode 100644
index 0000000..3515f1c
--- /dev/null
+++ b/airflow/www/static/js/tree/SidePanel.jsx
@@ -0,0 +1,49 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+/* global moment */
+
+import React from 'react';
+import {
+ Box,
+ chakra,
+ Flex,
+ Text,
+} from '@chakra-ui/react';
+
+import { formatDateTime } from '../datetime_utils';
+
+const SidePanel = ({ instance: { runId, taskId, executionDate }, isOpen }) => (
+ <Box bg="gray.200" maxWidth={isOpen ? 300 : 0} minWidth={isOpen ? 300 : 0} transition="all 0.5s" position="relative" overflow="hidden">
+ <Flex right={isOpen ? 0 : -300} top={0} transition="right 0.5s, max-width 0.5s" width={300} flexDirection="column" m={2}>
+ <Text as="h4">
+ <chakra.span>Task Instance: </chakra.span>
+ <chakra.b>{taskId}</chakra.b>
+ <chakra.span> at </chakra.span>
+ <chakra.b>{formatDateTime(moment.utc(executionDate))}</chakra.b>
+ </Text>
+ <Text>
+ {/* eslint-disable-next-line max-len */}
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Nunc vel risus commodo viverra maecenas accumsan. Ut porttitor leo a diam sollicitudin tempor id eu. Molestie at elementum eu facilisis sed odio morbi quis commodo. Facilisis leo vel fringilla est ullamcorper eget nulla facilisi etiam. Est sit amet facilisis magna etiam tempor orci eu. Id semper risus in hendrerit gravida rutrum. Ac odio tempor orci dapibus [...]
+ </Text>
+ </Flex>
+ </Box>
+);
+
+export default SidePanel;
diff --git a/airflow/www/static/js/tree/StatusBox.jsx b/airflow/www/static/js/tree/StatusBox.jsx
index c22f0b2..dce0fda 100644
--- a/airflow/www/static/js/tree/StatusBox.jsx
+++ b/airflow/www/static/js/tree/StatusBox.jsx
@@ -30,12 +30,21 @@ import { callModal } from '../dag';
import InstanceTooltip from './InstanceTooltip';
const StatusBox = ({
- group, instance, containerRef, extraLinks = [], ...rest
+ group, instance, containerRef, extraLinks = [], onSelectInstance, ...rest
}) => {
const {
executionDate, taskId, tryNumber = 0, operator, runId,
} = instance;
- const onClick = () => executionDate && callModal(taskId, executionDate, extraLinks, tryNumber, operator === 'SubDagOperator' || undefined, runId);
+
+ const onOpenModal = () => executionDate && callModal(taskId, executionDate, extraLinks, tryNumber, operator === 'SubDagOperator' || undefined, runId);
+ const onClick = () => {
+ if (group.isMapped) {
+ onSelectInstance(instance);
+ } else {
+ onSelectInstance({});
+ onOpenModal();
+ }
+ };
// Fetch the corresponding column element and set its background color when hovering
const onMouseOver = () => {
@@ -48,37 +57,39 @@ const StatusBox = ({
};
return (
- <Tooltip
- label={<InstanceTooltip instance={instance} group={group} />}
- fontSize="md"
- portalProps={{ containerRef }}
- hasArrow
- placement="top"
- openDelay={400}
- >
- <Flex
- p="1px"
- my="1px"
- mx="2px"
- justifyContent="center"
- alignItems="center"
- onClick={onClick}
- cursor={!group.children && 'pointer'}
- data-testid="task-instance"
- zIndex={1}
- onMouseEnter={onMouseOver}
- onMouseLeave={onMouseLeave}
- {...rest}
+ <>
+ <Tooltip
+ label={<InstanceTooltip instance={instance} group={group} />}
+ fontSize="md"
+ portalProps={{ containerRef }}
+ hasArrow
+ placement="top"
+ openDelay={400}
>
- <Box
- width="10px"
- height="10px"
- backgroundColor={stateColors[instance.state] || 'white'}
- borderRadius="2px"
- borderWidth={instance.state ? 0 : 1}
- />
- </Flex>
- </Tooltip>
+ <Flex
+ p="1px"
+ my="1px"
+ mx="2px"
+ justifyContent="center"
+ alignItems="center"
+ onClick={onClick}
+ cursor={!group.children && 'pointer'}
+ data-testid="task-instance"
+ zIndex={1}
+ onMouseEnter={onMouseOver}
+ onMouseLeave={onMouseLeave}
+ {...rest}
+ >
+ <Box
+ width="10px"
+ height="10px"
+ backgroundColor={stateColors[instance.state] || 'white'}
+ borderRadius="2px"
+ borderWidth={instance.state ? 0 : 1}
+ />
+ </Flex>
+ </Tooltip>
+ </>
);
};
diff --git a/airflow/www/static/js/tree/Tree.jsx b/airflow/www/static/js/tree/Tree.jsx
index 450e002..095adbd 100644
--- a/airflow/www/static/js/tree/Tree.jsx
+++ b/airflow/www/static/js/tree/Tree.jsx
@@ -17,7 +17,7 @@
* under the License.
*/
-import React, { useRef, useEffect } from 'react';
+import React, { useRef, useEffect, useState } from 'react';
import {
Table,
Tbody,
@@ -28,16 +28,19 @@ import {
Spinner,
Text,
Thead,
+ Flex,
} from '@chakra-ui/react';
import useTreeData from './useTreeData';
import renderTaskRows from './renderTaskRows';
import DagRuns from './dagRuns';
+import SidePanel from './SidePanel';
const Tree = () => {
const containerRef = useRef();
const scrollRef = useRef();
const { data: { groups = {} }, isRefreshOn, onToggleRefresh } = useTreeData();
+ const [selectedInstance, setSelectedInstance] = useState({});
useEffect(() => {
// Set initial scroll to far right if it is scrollable
@@ -47,6 +50,13 @@ const Tree = () => {
}
}, []);
+ const { runId, taskId } = selectedInstance;
+ const onSelectInstance = (newInstance) => (
+ (newInstance.runId === runId && newInstance.taskId === taskId)
+ ? setSelectedInstance({})
+ : setSelectedInstance(newInstance)
+ );
+
return (
<Box position="relative" ref={containerRef}>
<FormControl display="flex" alignItems="center" justifyContent="flex-end" width="100%">
@@ -58,17 +68,20 @@ const Tree = () => {
</FormControl>
<Text transform="rotate(-90deg)" position="absolute" left="-6px" top="130px">Runs</Text>
<Text transform="rotate(-90deg)" position="absolute" left="-6px" top="190px">Tasks</Text>
- <Box px="24px">
- <Box position="relative" width="100%" overflowX="auto" ref={scrollRef}>
- <Table>
+ <Box pl="24px">
+ <Flex position="relative" flexDirection="row" justifyContent="space-between" overflow="hidden">
+ <Table mr="24px" overflowX="auto" ref={scrollRef} height={0}>
<Thead>
<DagRuns containerRef={containerRef} />
</Thead>
<Tbody>
- {renderTaskRows({ task: groups, containerRef })}
+ {renderTaskRows({
+ task: groups, containerRef, onSelectInstance,
+ })}
</Tbody>
</Table>
- </Box>
+ <SidePanel isOpen={!!runId} instance={selectedInstance} />
+ </Flex>
</Box>
</Box>
);
diff --git a/airflow/www/static/js/tree/renderTaskRows.jsx b/airflow/www/static/js/tree/renderTaskRows.jsx
index afd97e6..f5a7ba0 100644
--- a/airflow/www/static/js/tree/renderTaskRows.jsx
+++ b/airflow/www/static/js/tree/renderTaskRows.jsx
@@ -40,7 +40,7 @@ import { getMetaValue } from '../utils';
const dagId = getMetaValue('dag_id');
const renderTaskRows = ({
- task, containerRef, level = 0, isParentOpen,
+ task, containerRef, level = 0, isParentOpen, onSelectInstance,
}) => task.children.map((t) => (
<Row
key={t.id}
@@ -49,6 +49,7 @@ const renderTaskRows = ({
containerRef={containerRef}
prevTaskId={task.id}
isParentOpen={isParentOpen}
+ onSelectInstance={onSelectInstance}
/>
));
@@ -85,7 +86,9 @@ const TaskName = ({
</Box>
);
-const TaskInstances = ({ task, containerRef, dagRuns }) => (
+const TaskInstances = ({
+ task, containerRef, dagRuns, onSelectInstance,
+}) => (
<Flex justifyContent="flex-end">
{dagRuns.map((run) => {
// Check if an instance exists for the run, or return an empty box
@@ -98,6 +101,7 @@ const TaskInstances = ({ task, containerRef, dagRuns }) => (
containerRef={containerRef}
extraLinks={task.extraLinks}
group={task}
+ onSelectInstance={onSelectInstance}
/>
)
: <Box key={`${run.runId}-${task.id}`} width="18px" data-testid="blank-task" />;
@@ -106,7 +110,7 @@ const TaskInstances = ({ task, containerRef, dagRuns }) => (
);
const Row = ({
- task, containerRef, level, prevTaskId, isParentOpen = true,
+ task, containerRef, level, prevTaskId, isParentOpen = true, onSelectInstance,
}) => {
const { data: { dagRuns = [] } } = useTreeData();
const isGroup = !!task.children;
@@ -162,13 +166,18 @@ const Row = ({
<Td width={0} p={0} borderBottom={0} />
<Td p={0} align="right" _groupHover={{ backgroundColor: 'rgba(113, 128, 150, 0.1)' }} transition="background-color 0.2s" borderBottom={0}>
<Collapse in={isFullyOpen}>
- <TaskInstances dagRuns={dagRuns} task={task} containerRef={containerRef} />
+ <TaskInstances
+ dagRuns={dagRuns}
+ task={task}
+ containerRef={containerRef}
+ onSelectInstance={onSelectInstance}
+ />
</Collapse>
</Td>
</Tr>
{isGroup && (
renderTaskRows({
- task, containerRef, level: level + 1, isParentOpen: isOpen,
+ task, containerRef, level: level + 1, isParentOpen: isOpen, onSelectInstance,
})
)}
</>
[airflow] 04/08: improve rendering and add selected dag run
Posted by bb...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch mapped-task-drawer
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit eb961505bac36095c84bd6c2b99e9ce49e6f37bc
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Mon Feb 28 12:24:27 2022 -0500
improve rendering and add selected dag run
---
airflow/www/static/js/tree/SidePanel.jsx | 28 +++++++++++++++++--------
airflow/www/static/js/tree/StatusBox.jsx | 24 ++++++++++-----------
airflow/www/static/js/tree/Tree.jsx | 12 ++++++++---
airflow/www/static/js/tree/dagRuns/Bar.jsx | 9 ++++----
airflow/www/static/js/tree/dagRuns/index.jsx | 3 ++-
airflow/www/static/js/tree/renderTaskRows.jsx | 30 ++++++++++++++++++---------
6 files changed, 65 insertions(+), 41 deletions(-)
diff --git a/airflow/www/static/js/tree/SidePanel.jsx b/airflow/www/static/js/tree/SidePanel.jsx
index 7a21eba..88439a0 100644
--- a/airflow/www/static/js/tree/SidePanel.jsx
+++ b/airflow/www/static/js/tree/SidePanel.jsx
@@ -25,8 +25,6 @@ import {
Flex,
Text,
useDisclosure,
- CloseButton,
- Button,
IconButton,
} from '@chakra-ui/react';
import { MdKeyboardArrowLeft, MdKeyboardArrowRight } from 'react-icons/md';
@@ -38,30 +36,42 @@ const SidePanel = ({ instance: { runId, taskId, executionDate } }) => {
if (!isOpen) {
return (
<IconButton
- ml={2}
+ m={2}
icon={<MdKeyboardArrowLeft size={18} />}
aria-label="Open Details Panel"
onClick={onOpen}
/>
);
}
- const title = runId && taskId
- ? (
+ let title = '';
+ if (runId && taskId) {
+ title = (
<>
<chakra.span>Task Instance: </chakra.span>
<chakra.b>{taskId}</chakra.b>
<chakra.span> at </chakra.span>
<chakra.b>{formatDateTime(moment.utc(executionDate))}</chakra.b>
</>
- )
- : (
+ );
+ } else if (runId) {
+ title = (
+ <>
+ <chakra.span>Dag Run: </chakra.span>
+ <chakra.b>{runId}</chakra.b>
+ <chakra.span> at </chakra.span>
+ <chakra.b>{formatDateTime(moment.utc(executionDate))}</chakra.b>
+ </>
+ );
+ } else {
+ title = (
<chakra.span>Dag Details: </chakra.span>
);
+ }
return (
- <Flex bg="gray.200" maxWidth={300} minWidth={300} flexDirection="column" p={3}>
+ <Flex bg="gray.200" maxWidth={isOpen ? '50%' : 0} minWidth={isOpen ? 300 : 0} flexDirection="column" p={3}>
<IconButton
- ml={2}
+ m={2}
icon={<MdKeyboardArrowRight size={18} />}
aria-label="Close Details Panel"
onClick={onClose}
diff --git a/airflow/www/static/js/tree/StatusBox.jsx b/airflow/www/static/js/tree/StatusBox.jsx
index b4abc93..815e6a1 100644
--- a/airflow/www/static/js/tree/StatusBox.jsx
+++ b/airflow/www/static/js/tree/StatusBox.jsx
@@ -27,34 +27,32 @@ import {
useTheme,
} from '@chakra-ui/react';
-// import { callModal } from '../dag';
import InstanceTooltip from './InstanceTooltip';
const StatusBox = ({
- group, instance, containerRef, extraLinks = [], onSelectInstance, ...rest
+ group, instance, containerRef, onSelectInstance, selectedInstance, ...rest
}) => {
- const {
- executionDate, taskId, tryNumber = 0, operator, runId,
- } = instance;
+ const { runId } = instance;
const { colors } = useTheme();
const hoverBlue = `${colors.blue[100]}50`;
- // const onOpenModal = () => executionDate && callModal(taskId, executionDate, extraLinks, tryNumber, operator === 'SubDagOperator' || undefined, runId);
- const onClick = (e) => {
- e.stopPropagation();
- onSelectInstance(instance);
- };
-
// Fetch the corresponding column element and set its background color when hovering
const onMouseOver = () => {
- [...containerRef.current.getElementsByClassName(`js-${runId}`)]
- .forEach((e) => { e.style.backgroundColor = hoverBlue; });
+ if (selectedInstance.runId !== runId) {
+ [...containerRef.current.getElementsByClassName(`js-${runId}`)]
+ .forEach((e) => { e.style.backgroundColor = hoverBlue; });
+ }
};
const onMouseLeave = () => {
[...containerRef.current.getElementsByClassName(`js-${runId}`)]
.forEach((e) => { e.style.backgroundColor = null; });
};
+ const onClick = (e) => {
+ e.stopPropagation();
+ onSelectInstance(instance);
+ };
+
return (
<>
<Tooltip
diff --git a/airflow/www/static/js/tree/Tree.jsx b/airflow/www/static/js/tree/Tree.jsx
index ff1402f..199e373 100644
--- a/airflow/www/static/js/tree/Tree.jsx
+++ b/airflow/www/static/js/tree/Tree.jsx
@@ -39,9 +39,11 @@ import SidePanel from './SidePanel';
const Tree = () => {
const containerRef = useRef();
const scrollRef = useRef();
- const { data: { groups = {} }, isRefreshOn, onToggleRefresh } = useTreeData();
+ const { data: { groups = {}, dagRuns = [] }, isRefreshOn, onToggleRefresh } = useTreeData();
const [selectedInstance, setSelectedInstance] = useState({});
+ const dagRunIds = dagRuns.map((dr) => dr.runId);
+
useEffect(() => {
// Set initial scroll to far right if it is scrollable
const runsContainer = scrollRef.current;
@@ -73,11 +75,15 @@ const Tree = () => {
<Box mr="12px" pb="12px" overflowX="auto" ref={scrollRef} maxWidth="60vw">
<Table height={0}>
<Thead>
- <DagRuns containerRef={containerRef} selectedInstance={selectedInstance} />
+ <DagRuns
+ containerRef={containerRef}
+ selectedInstance={selectedInstance}
+ onSelectInstance={onSelectInstance}
+ />
</Thead>
<Tbody>
{renderTaskRows({
- task: groups, containerRef, onSelectInstance, selectedInstance,
+ task: groups, containerRef, onSelectInstance, selectedInstance, dagRunIds,
})}
</Tbody>
</Table>
diff --git a/airflow/www/static/js/tree/dagRuns/Bar.jsx b/airflow/www/static/js/tree/dagRuns/Bar.jsx
index 4dbe20d..c64abdd 100644
--- a/airflow/www/static/js/tree/dagRuns/Bar.jsx
+++ b/airflow/www/static/js/tree/dagRuns/Bar.jsx
@@ -31,12 +31,11 @@ import {
import { MdPlayArrow } from 'react-icons/md';
import DagRunTooltip from './Tooltip';
-import { callModalDag } from '../../dag';
const BAR_HEIGHT = 100;
const DagRunBar = ({
- run, max, index, totalRuns, containerRef, selectedInstance,
+ run, max, index, totalRuns, containerRef, selectedInstance, onSelectInstance,
}) => {
const { colors } = useTheme();
const hoverBlue = `${colors.blue[100]}50`;
@@ -53,14 +52,14 @@ const DagRunBar = ({
alignItems="flex-end"
justifyContent="center"
mb="2px"
- // py="2px"
px="2px"
mx="1px"
cursor="pointer"
width="14px"
zIndex={1}
- onClick={() => {
- callModalDag({ execution_date: run.executionDate, dag_id: run.dagId, run_id: run.runId });
+ onClick={(e) => {
+ e.stopPropagation();
+ onSelectInstance(run);
}}
position="relative"
data-peer
diff --git a/airflow/www/static/js/tree/dagRuns/index.jsx b/airflow/www/static/js/tree/dagRuns/index.jsx
index 7de949f..7459634 100644
--- a/airflow/www/static/js/tree/dagRuns/index.jsx
+++ b/airflow/www/static/js/tree/dagRuns/index.jsx
@@ -36,7 +36,7 @@ const DurationTick = ({ children, ...rest }) => (
</Text>
);
-const DagRuns = ({ containerRef, selectedInstance }) => {
+const DagRuns = ({ containerRef, selectedInstance, onSelectInstance }) => {
const { data: { dagRuns = [] } } = useTreeData();
const durations = [];
const runs = dagRuns.map((dagRun) => {
@@ -98,6 +98,7 @@ const DagRuns = ({ containerRef, selectedInstance }) => {
totalRuns={runs.length}
containerRef={containerRef}
selectedInstance={selectedInstance}
+ onSelectInstance={onSelectInstance}
/>
))}
</Flex>
diff --git a/airflow/www/static/js/tree/renderTaskRows.jsx b/airflow/www/static/js/tree/renderTaskRows.jsx
index 7eff252..9b454f0 100644
--- a/airflow/www/static/js/tree/renderTaskRows.jsx
+++ b/airflow/www/static/js/tree/renderTaskRows.jsx
@@ -32,7 +32,6 @@ import {
} from '@chakra-ui/react';
import { FiChevronUp, FiChevronDown } from 'react-icons/fi';
-import useTreeData from './useTreeData';
import StatusBox from './StatusBox';
import { getMetaValue } from '../utils';
@@ -41,7 +40,7 @@ import { getMetaValue } from '../utils';
const dagId = getMetaValue('dag_id');
const renderTaskRows = ({
- task, containerRef, level = 0, isParentOpen, onSelectInstance, selectedInstance,
+ task, containerRef, level = 0, isParentOpen, onSelectInstance, selectedInstance, dagRunIds
}) => task.children.map((t) => (
<Row
key={t.id}
@@ -52,6 +51,7 @@ const renderTaskRows = ({
isParentOpen={isParentOpen}
onSelectInstance={onSelectInstance}
selectedInstance={selectedInstance}
+ dagRunIds={dagRunIds}
/>
));
@@ -85,33 +85,42 @@ const TaskName = ({
);
const TaskInstances = ({
- task, containerRef, dagRuns, onSelectInstance,
+ task, containerRef, dagRunIds, onSelectInstance, selectedInstance,
}) => (
<Flex justifyContent="flex-end">
- {dagRuns.map((run) => {
+ {dagRunIds.map((runId) => {
// Check if an instance exists for the run, or return an empty box
- const instance = task.instances.find((gi) => gi.runId === run.runId);
+ const instance = task.instances.find((gi) => gi.runId === runId);
+ const key = `${runId}-${task.id}`;
return instance
? (
<StatusBox
- key={`${run.runId}-${task.id}`}
+ key={key}
instance={instance}
containerRef={containerRef}
extraLinks={task.extraLinks}
group={task}
onSelectInstance={onSelectInstance}
+ selectedInstance={selectedInstance}
/>
)
- : <Box key={`${run.runId}-${task.id}`} width="16px" data-testid="blank-task" />;
+ : <Box key={key} width="16px" data-testid="blank-task" />;
})}
</Flex>
);
const Row = (props) => {
const {
- task, containerRef, level, prevTaskId, isParentOpen = true, onSelectInstance, selectedInstance,
+ task,
+ containerRef,
+ level,
+ prevTaskId,
+ isParentOpen = true,
+ onSelectInstance,
+ selectedInstance,
+ dagRunIds,
} = props;
- const { data: { dagRuns = [] } } = useTreeData();
+ // const { data: { dagRuns = [] } } = useTreeData();
const { colors } = useTheme();
const hoverBlue = `${colors.blue[100]}50`;
const isGroup = !!task.children;
@@ -175,10 +184,11 @@ const Row = (props) => {
>
<Collapse in={isFullyOpen}>
<TaskInstances
- dagRuns={dagRuns}
+ dagRunIds={dagRunIds}
task={task}
containerRef={containerRef}
onSelectInstance={onSelectInstance}
+ selectedInstance={selectedInstance}
/>
</Collapse>
</Td>