├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .github ├── CODEOWNERS ├── PULL_REQUEST_TEMPLATE.md ├── stale.yml ├── titleLint.yml └── workflows │ ├── license.yml │ ├── monthly_release.yml │ ├── publish_release.yml │ ├── pull_request.yml │ └── pypipublish.yml ├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── MANIFEST.in ├── Makefile ├── NOTICE ├── README.md ├── amundsen_application ├── __init__.py ├── api │ ├── __init__.py │ ├── announcements │ │ ├── __init__.py │ │ └── v0.py │ ├── exceptions.py │ ├── issue │ │ ├── __init__.py │ │ └── issue.py │ ├── log │ │ ├── __init__.py │ │ └── v0.py │ ├── mail │ │ ├── __init__.py │ │ └── v0.py │ ├── metadata │ │ ├── __init__.py │ │ └── v0.py │ ├── preview │ │ ├── __init__.py │ │ ├── dashboard │ │ │ ├── __init__.py │ │ │ ├── dashboard_preview │ │ │ │ ├── __init__.py │ │ │ │ ├── mode_preview.py │ │ │ │ └── preview_factory_method.py │ │ │ └── v0.py │ │ └── v0.py │ ├── search │ │ ├── __init__.py │ │ └── v0.py │ ├── utils │ │ ├── __init__.py │ │ ├── metadata_utils.py │ │ ├── notification_utils.py │ │ ├── request_utils.py │ │ ├── response_utils.py │ │ └── search_utils.py │ └── v0.py ├── base │ ├── __init__.py │ ├── base_announcement_client.py │ ├── base_bigquery_preview_client.py │ ├── base_issue_tracker_client.py │ ├── base_mail_client.py │ ├── base_preview.py │ ├── base_preview_client.py │ ├── base_redash_preview_client.py │ ├── base_superset_preview_client.py │ └── examples │ │ ├── __init__.py │ │ ├── example_announcement_client.py │ │ ├── example_bigquery_preview_client.py │ │ ├── example_dremio_preview_client.py │ │ ├── example_mail_client.py │ │ ├── example_redash_preview_client.py │ │ └── example_superset_preview_client.py ├── config.py ├── log │ ├── __init__.py │ ├── action_log.py │ ├── action_log_callback.py │ └── action_log_model.py ├── models │ ├── __init__.py │ ├── announcements.py │ ├── data_issue.py │ ├── issue_results.py │ ├── preview_data.py │ └── user.py ├── oidc_config.py ├── proxy │ ├── __init__.py │ └── issue_tracker_clients │ │ ├── __init__.py │ │ ├── asana_client.py │ │ ├── issue_exceptions.py │ │ └── jira_client.py ├── static │ ├── .betterer.results │ ├── .betterer.ts │ ├── .eslintignore │ ├── .nvmrc │ ├── .storybook │ │ ├── amundsenTheme.js │ │ ├── main.ts │ │ ├── manager.ts │ │ ├── preview.ts │ │ └── webpack.config.js │ ├── css │ │ ├── _animations.scss │ │ ├── _avatars.scss │ │ ├── _bootstrap-custom.scss │ │ ├── _buttons-custom.scss │ │ ├── _buttons-default.scss │ │ ├── _buttons.scss │ │ ├── _colors.scss │ │ ├── _dropdowns.scss │ │ ├── _fonts-custom.scss │ │ ├── _fonts-default.scss │ │ ├── _fonts.scss │ │ ├── _icons.scss │ │ ├── _inputs.scss │ │ ├── _labels.scss │ │ ├── _layouts.scss │ │ ├── _list-group.scss │ │ ├── _pagination.scss │ │ ├── _popovers.scss │ │ ├── _typography-custom.scss │ │ ├── _typography-default.scss │ │ ├── _typography.scss │ │ ├── _variables-custom.scss │ │ ├── _variables-default.scss │ │ ├── _variables.scss │ │ └── styles.scss │ ├── fonts │ │ ├── OpenSans-Bold.ttf │ │ ├── OpenSans-Regular.ttf │ │ ├── OpenSans-SemiBold.ttf │ │ ├── Roboto-Bold.ttf │ │ ├── Roboto-Medium.ttf │ │ └── SpaceMono-Regular.ttf │ ├── global.d.ts │ ├── images │ │ ├── airflow.jpeg │ │ ├── favicons │ │ │ ├── dev │ │ │ │ ├── android-chrome-192x192.png │ │ │ │ ├── android-chrome-256x256.png │ │ │ │ ├── apple-touch-icon.png │ │ │ │ ├── browserconfig.xml │ │ │ │ ├── favicon-16x16.png │ │ │ │ ├── favicon-32x32.png │ │ │ │ ├── favicon.ico │ │ │ │ ├── mstile-150x150.png │ │ │ │ ├── safari-pinned-tab.svg │ │ │ │ └── site.webmanifest │ │ │ ├── prod │ │ │ │ ├── android-chrome-192x192.png │ │ │ │ ├── android-chrome-256x256.png │ │ │ │ ├── apple-touch-icon.png │ │ │ │ ├── browserconfig.xml │ │ │ │ ├── favicon-16x16.png │ │ │ │ ├── favicon-32x32.png │ │ │ │ ├── favicon.ico │ │ │ │ ├── mstile-150x150.png │ │ │ │ ├── safari-pinned-tab.svg │ │ │ │ └── site.webmanifest │ │ │ └── staging │ │ │ │ ├── android-chrome-192x192.png │ │ │ │ ├── android-chrome-256x256.png │ │ │ │ ├── apple-touch-icon.png │ │ │ │ ├── browserconfig.xml │ │ │ │ ├── favicon-16x16.png │ │ │ │ ├── favicon-32x32.png │ │ │ │ ├── favicon.ico │ │ │ │ ├── mstile-150x150.png │ │ │ │ ├── safari-pinned-tab.svg │ │ │ │ └── site.webmanifest │ │ ├── github.png │ │ ├── icons │ │ │ ├── Alert-Triangle.svg │ │ │ ├── Close.svg │ │ │ ├── DataQualityWarning.svg │ │ │ ├── Database.svg │ │ │ ├── Delta-Down.svg │ │ │ ├── Delta-Up.svg │ │ │ ├── Dimension.svg │ │ │ ├── Down Arrow.svg │ │ │ ├── Down-Arrow.svg │ │ │ ├── Down.svg │ │ │ ├── Edit.svg │ │ │ ├── Edit_Inverted.svg │ │ │ ├── Expand.svg │ │ │ ├── Favorite-Filled.svg │ │ │ ├── Favorite.svg │ │ │ ├── Help-Circle.svg │ │ │ ├── Info-Filled.svg │ │ │ ├── Info.svg │ │ │ ├── Left.svg │ │ │ ├── Loader.svg │ │ │ ├── Metric.svg │ │ │ ├── Minimize.svg │ │ │ ├── More.svg │ │ │ ├── Null Value.svg │ │ │ ├── Null-Value.svg │ │ │ ├── Parameters.svg │ │ │ ├── Person.svg │ │ │ ├── Plus-Circle.svg │ │ │ ├── Preview-Fillled.svg │ │ │ ├── Preview.svg │ │ │ ├── Refresh-cw.svg │ │ │ ├── Right.svg │ │ │ ├── Search.svg │ │ │ ├── Send.svg │ │ │ ├── Speech.svg │ │ │ ├── Trash.svg │ │ │ ├── Up-Arrow.svg │ │ │ ├── Up.svg │ │ │ ├── check.svg │ │ │ ├── dashboard.svg │ │ │ ├── github.svg │ │ │ ├── logo-bigquery.svg │ │ │ ├── logo-delta.png │ │ │ ├── logo-dremio.svg │ │ │ ├── logo-druid.svg │ │ │ ├── logo-hive.svg │ │ │ ├── logo-mode.svg │ │ │ ├── logo-postgres.svg │ │ │ ├── logo-presto.svg │ │ │ ├── logo-redash.svg │ │ │ ├── logo-redshift.svg │ │ │ ├── logo-snowflake.svg │ │ │ ├── logo-tableau.svg │ │ │ ├── mail.svg │ │ │ ├── plus.svg │ │ │ ├── presto-logo.svg │ │ │ ├── slack.svg │ │ │ └── users.svg │ │ ├── loading_spinner.gif │ │ └── watermark-range.png │ ├── jest.config.js │ ├── js │ │ ├── components │ │ │ ├── Alert │ │ │ │ ├── alert.story.tsx │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── Announcements │ │ │ │ ├── AnnouncementsList │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.scss │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ └── index.tsx │ │ │ ├── AvatarLabel │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── BadgeList │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── Bookmark │ │ │ │ ├── BookmarkIcon │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.scss │ │ │ │ └── MyBookmarks │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.scss │ │ │ ├── Breadcrumb │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── Card │ │ │ │ ├── card.story.tsx │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── EditableSection │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── EditableText │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── EntityCard │ │ │ │ ├── EntityCardSection │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.scss │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── Flag │ │ │ │ ├── Flag.story.tsx │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── FlashMessage │ │ │ │ ├── constants.ts │ │ │ │ ├── flashMessage.story.tsx │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── InfoButton │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── infoButton.story.tsx │ │ │ │ └── styles.scss │ │ │ ├── Inputs │ │ │ │ ├── CheckBoxItem │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── LoadingSpinner │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── loadingSpinner.story.tsx │ │ │ │ └── styles.scss │ │ │ ├── OwnerEditor │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── PopularTables │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── Preloader │ │ │ │ ├── index.spec.tsx │ │ │ │ └── index.tsx │ │ │ ├── ResourceList │ │ │ │ ├── PaginatedApiResourceList │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── PaginatedResourceList │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── ResourceListHeader │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.scss │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── ResourceListItem │ │ │ │ ├── DashboardListItem │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── SchemaInfo │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── styles.scss │ │ │ │ │ └── tests │ │ │ │ │ │ └── index.spec.tsx │ │ │ │ ├── TableListItem │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── UserListItem │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── styles.scss │ │ │ │ └── types.ts │ │ │ ├── ResourceStatusMarker │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── SVGIcons │ │ │ │ ├── AlertIcon.tsx │ │ │ │ ├── DownIcon.tsx │ │ │ │ ├── InformationIcon.tsx │ │ │ │ ├── LeftIcon.tsx │ │ │ │ ├── RightIcon.tsx │ │ │ │ ├── UpIcon.tsx │ │ │ │ ├── constants.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── svgIcons.story.tsx │ │ │ │ └── types.ts │ │ │ ├── ScrollTracker │ │ │ │ └── index.tsx │ │ │ ├── SearchBar │ │ │ │ ├── InlineSearchResults │ │ │ │ │ ├── ResultItemList │ │ │ │ │ │ ├── ResultItem │ │ │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── tests │ │ │ │ │ │ │ └── index.spec.tsx │ │ │ │ │ ├── SearchItemList │ │ │ │ │ │ ├── SearchItem │ │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ │ └── tests │ │ │ │ │ │ │ │ └── index.spec.tsx │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── tests │ │ │ │ │ │ │ └── index.spec.tsx │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── styles.scss │ │ │ │ │ └── tests │ │ │ │ │ │ └── index.spec.tsx │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── ShimmeringResourceLoader │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── ShimmeringTagListLoader │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── StorySection │ │ │ │ └── index.tsx │ │ │ ├── Table │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── styles.scss │ │ │ │ ├── table.story.tsx │ │ │ │ └── testDataBuilder.tsx │ │ │ ├── TabsComponent │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ └── Tags │ │ │ │ ├── TagInfo │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ │ ├── TagInput │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ │ ├── TagsList │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ └── index.tsx │ │ ├── config │ │ │ ├── config-custom.ts │ │ │ ├── config-default.ts │ │ │ ├── config-types.ts │ │ │ ├── config-utils.ts │ │ │ ├── config.ts │ │ │ └── index.spec.ts │ │ ├── constants.ts │ │ ├── ducks │ │ │ ├── announcements │ │ │ │ ├── api │ │ │ │ │ ├── index.spec.ts │ │ │ │ │ └── v0.ts │ │ │ │ ├── index.spec.ts │ │ │ │ ├── index.ts │ │ │ │ ├── sagas.ts │ │ │ │ └── types.ts │ │ │ ├── bookmark │ │ │ │ ├── api │ │ │ │ │ ├── tests │ │ │ │ │ │ └── index.spec.ts │ │ │ │ │ └── v0.ts │ │ │ │ ├── index.spec.ts │ │ │ │ ├── reducer.ts │ │ │ │ ├── sagas.ts │ │ │ │ └── types.ts │ │ │ ├── dashboard │ │ │ │ ├── api │ │ │ │ │ ├── api.spec.ts │ │ │ │ │ └── v0.ts │ │ │ │ ├── reducer.spec.ts │ │ │ │ ├── reducer.ts │ │ │ │ ├── sagas.spec.ts │ │ │ │ ├── sagas.ts │ │ │ │ └── types.ts │ │ │ ├── feedback │ │ │ │ ├── api │ │ │ │ │ ├── tests │ │ │ │ │ │ └── index.spec.ts │ │ │ │ │ └── v0.ts │ │ │ │ ├── reducer.ts │ │ │ │ ├── sagas.ts │ │ │ │ ├── tests │ │ │ │ │ └── index.spec.ts │ │ │ │ └── types.ts │ │ │ ├── issue │ │ │ │ ├── api │ │ │ │ │ ├── tests │ │ │ │ │ │ └── index.spec.ts │ │ │ │ │ └── v0.ts │ │ │ │ ├── reducer.ts │ │ │ │ ├── sagas.ts │ │ │ │ ├── tests │ │ │ │ │ └── index.spec.ts │ │ │ │ └── types.ts │ │ │ ├── lastIndexed │ │ │ │ ├── api │ │ │ │ │ └── v0.ts │ │ │ │ ├── reducer.ts │ │ │ │ ├── sagas.ts │ │ │ │ ├── tests │ │ │ │ │ └── index.spec.ts │ │ │ │ └── types.ts │ │ │ ├── log │ │ │ │ └── api │ │ │ │ │ ├── tests │ │ │ │ │ └── index.spec.ts │ │ │ │ │ └── v0.ts │ │ │ ├── middlewares │ │ │ │ ├── analyticsMiddleware.ts │ │ │ │ └── index.ts │ │ │ ├── notification │ │ │ │ ├── api │ │ │ │ │ ├── tests │ │ │ │ │ │ └── index.spec.ts │ │ │ │ │ └── v0.ts │ │ │ │ ├── reducer.ts │ │ │ │ ├── sagas.ts │ │ │ │ ├── tests │ │ │ │ │ └── index.spec.ts │ │ │ │ └── types.ts │ │ │ ├── popularTables │ │ │ │ ├── api │ │ │ │ │ ├── tests │ │ │ │ │ │ └── index.spec.ts │ │ │ │ │ └── v0.ts │ │ │ │ ├── index.spec.ts │ │ │ │ ├── reducer.ts │ │ │ │ ├── sagas.ts │ │ │ │ └── types.ts │ │ │ ├── rootReducer.ts │ │ │ ├── rootSaga.ts │ │ │ ├── search │ │ │ │ ├── api │ │ │ │ │ ├── tests │ │ │ │ │ │ └── index.spec.ts │ │ │ │ │ └── v0.ts │ │ │ │ ├── filters │ │ │ │ │ ├── reducer.spec.ts │ │ │ │ │ ├── reducer.ts │ │ │ │ │ ├── sagas.spec.ts │ │ │ │ │ └── sagas.ts │ │ │ │ ├── reducer.spec.ts │ │ │ │ ├── reducer.ts │ │ │ │ ├── sagas.ts │ │ │ │ ├── tests │ │ │ │ │ ├── sagas.spec.ts │ │ │ │ │ └── utils.spec.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ │ ├── tableMetadata │ │ │ │ ├── api │ │ │ │ │ ├── helpers.spec.ts │ │ │ │ │ ├── helpers.ts │ │ │ │ │ └── v0.ts │ │ │ │ ├── index.spec.ts │ │ │ │ ├── owners │ │ │ │ │ ├── index.spec.ts │ │ │ │ │ ├── reducer.ts │ │ │ │ │ └── sagas.ts │ │ │ │ ├── reducer.ts │ │ │ │ ├── sagas.ts │ │ │ │ └── types.ts │ │ │ ├── tags │ │ │ │ ├── api │ │ │ │ │ ├── tests │ │ │ │ │ │ └── index.spec.ts │ │ │ │ │ └── v0.ts │ │ │ │ ├── reducer.ts │ │ │ │ ├── sagas.ts │ │ │ │ ├── tests │ │ │ │ │ └── index.spec.ts │ │ │ │ └── types.ts │ │ │ ├── ui │ │ │ │ ├── index.spec.ts │ │ │ │ └── index.ts │ │ │ ├── user │ │ │ │ ├── api │ │ │ │ │ ├── tests │ │ │ │ │ │ └── index.spec.ts │ │ │ │ │ └── v0.ts │ │ │ │ ├── index.spec.ts │ │ │ │ ├── reducer.ts │ │ │ │ ├── sagas.ts │ │ │ │ └── types.ts │ │ │ └── utilMethods.ts │ │ ├── features │ │ │ ├── BadgeList │ │ │ │ └── index.tsx │ │ │ ├── ColumnList │ │ │ │ ├── ColumnDescEditableText │ │ │ │ │ └── index.tsx │ │ │ │ ├── ColumnLineage │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.scss │ │ │ │ ├── ColumnLineageLoader │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.scss │ │ │ │ ├── ColumnStats │ │ │ │ │ ├── columnStats.story.tsx │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── styles.scss │ │ │ │ │ └── testDataBuilder.ts │ │ │ │ ├── ColumnType │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── parser.spec.ts │ │ │ │ │ ├── parser.ts │ │ │ │ │ └── styles.scss │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── styles.scss │ │ │ │ └── testDataBuilder.ts │ │ │ ├── ExpandableUniqueValues │ │ │ │ ├── UniqueValuesModal.spec.tsx │ │ │ │ ├── UniqueValuesModal.tsx │ │ │ │ ├── expandableUniqueValues.story.tsx │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ ├── styles.scss │ │ │ │ └── testDataBuilder.ts │ │ │ ├── Feedback │ │ │ │ ├── FeedbackForm │ │ │ │ │ ├── BugReportFeedbackForm │ │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── RatingFeedbackForm │ │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── RequestFeedbackForm │ │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── Footer │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ └── NavBar │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ ├── fixtures │ │ │ ├── globalState.ts │ │ │ ├── metadata │ │ │ │ ├── dashboard.ts │ │ │ │ ├── table.ts │ │ │ │ ├── tagsList.ts │ │ │ │ └── users.ts │ │ │ ├── mockRouter.ts │ │ │ └── search │ │ │ │ ├── filters.ts │ │ │ │ └── inlineResults.ts │ │ ├── index.tsx │ │ ├── interfaces │ │ │ ├── Analytics.ts │ │ │ ├── Announcements.ts │ │ │ ├── Badges.ts │ │ │ ├── Dashboard.ts │ │ │ ├── Enums.ts │ │ │ ├── Feedback.ts │ │ │ ├── Issue.ts │ │ │ ├── Notifications.ts │ │ │ ├── Resources.ts │ │ │ ├── TableMetadata.ts │ │ │ ├── Tags.ts │ │ │ ├── User.ts │ │ │ └── index.ts │ │ ├── pages │ │ │ ├── AnnouncementPage │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── BrowsePage │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── DashboardPage │ │ │ │ ├── ChartList │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.scss │ │ │ │ ├── DashboardOwnerEditor │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── ImagePreview │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.scss │ │ │ │ ├── QueryList │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.scss │ │ │ │ ├── QueryListItem │ │ │ │ │ ├── CodeBlock.tsx │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.scss │ │ │ │ ├── ShimmeringDashboardLoader │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.scss │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── HomePage │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── NotFoundPage │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── ProfilePage │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ ├── SearchPage │ │ │ │ ├── ResourceSelector │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── SearchFilter │ │ │ │ │ ├── CheckBoxFilter │ │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── FilterSection │ │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── InputFilter │ │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── constants.ts │ │ │ │ │ ├── index.spec.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.scss │ │ │ │ ├── SearchPanel │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── styles.scss │ │ │ │ │ └── tests │ │ │ │ │ │ └── index.spec.tsx │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ └── TableDetailPage │ │ │ │ ├── DataPreviewButton │ │ │ │ ├── constants.ts │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ │ ├── ExploreButton │ │ │ │ ├── index.spec.tsx │ │ │ │ └── index.tsx │ │ │ │ ├── FrequentUsers │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ │ ├── LineageLink │ │ │ │ └── index.tsx │ │ │ │ ├── LineageList │ │ │ │ └── index.tsx │ │ │ │ ├── ListSortingDropdown │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ │ ├── ReportTableIssue │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ │ ├── RequestDescriptionText │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ └── index.tsx │ │ │ │ ├── RequestMetadataForm │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ │ ├── ResourceReportsDropdown │ │ │ │ ├── index.spec.tsx │ │ │ │ └── index.tsx │ │ │ │ ├── SourceLink │ │ │ │ ├── index.spec.tsx │ │ │ │ └── index.tsx │ │ │ │ ├── TableDashboardResourceList │ │ │ │ ├── index.spec.tsx │ │ │ │ └── index.tsx │ │ │ │ ├── TableDescEditableText │ │ │ │ └── index.tsx │ │ │ │ ├── TableHeaderBullets │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ └── index.tsx │ │ │ │ ├── TableIssues │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ │ ├── TableOwnerEditor │ │ │ │ ├── index.spec.tsx │ │ │ │ └── index.tsx │ │ │ │ ├── WatermarkLabel │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ │ │ ├── WriterLink │ │ │ │ └── index.tsx │ │ │ │ ├── constants.ts │ │ │ │ ├── index.spec.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── styles.scss │ │ ├── stories │ │ │ ├── colors.story.tsx │ │ │ ├── typography.story.tsx │ │ │ └── welcome.story.tsx │ │ └── utils │ │ │ ├── analytics.ts │ │ │ ├── dateUtils.ts │ │ │ ├── index.spec.ts │ │ │ ├── logUtils.ts │ │ │ ├── navigationUtils.ts │ │ │ ├── numberUtils.ts │ │ │ ├── stats.ts │ │ │ └── textUtils.ts │ ├── package-lock.json │ ├── package.json │ ├── templates │ │ ├── fragments │ │ │ ├── icons-dev.html │ │ │ ├── icons-prod.html │ │ │ └── icons-staging.html │ │ └── index.html │ ├── test-setup.ts │ ├── tsconfig.json │ ├── tsconfig.webpack.json │ ├── tslint.json │ ├── webpack.common.ts │ ├── webpack.dev.ts │ └── webpack.prod.ts ├── tests │ ├── __init__.py │ ├── templates │ │ └── index.html │ └── test_utils.py └── wsgi.py ├── docs ├── application_config.md ├── authentication │ └── oidc.md ├── configuration.md ├── developer_guide.md ├── examples │ ├── announcement_client.md │ ├── redash_preview_client.md │ └── superset_preview_client.md ├── flask_config.md ├── img │ ├── announcements_feature.png │ ├── column_details.png │ ├── data_preview.png │ ├── distinct_values.png │ ├── graph_model.png │ ├── landing_page.png │ ├── notices-alert-table.png │ ├── notices-info-table.png │ ├── notices-warning-dashboard.png │ ├── programmatic_descriptions.png │ ├── search_preview.png │ └── table_detail_page.png ├── installation.md ├── react_naming_conventions.md └── recommended_practices.md ├── local.Dockerfile ├── public.Dockerfile ├── requirements.txt ├── setup.cfg ├── setup.py └── tests ├── __init__.py └── unit ├── __init__.py ├── api ├── announcements │ ├── __init__.py │ └── test_v0.py ├── issue │ └── test_issue.py ├── mail │ ├── __init__.py │ └── test_v0.py ├── metadata │ ├── __init__.py │ └── test_v0.py ├── preview │ ├── __init__.py │ ├── dashboard │ │ ├── __init__.py │ │ ├── dashboard_preview │ │ │ ├── __init__.py │ │ │ ├── test_mode_preview.py │ │ │ └── test_preview_factory_method.py │ │ └── test_v0.py │ └── test_v0.py └── search │ ├── __init__.py │ └── test_v0.py ├── base ├── __init__.py ├── test_announcement_client.py ├── test_bigquery_preview_client.py ├── test_issue_tracker_client.py ├── test_preview_client.py ├── test_redash_preview_client.py └── test_superset_preview_client.py ├── issue_tracker_clients ├── __init__.py ├── test_asana_client.py └── test_jira_client.py ├── log ├── __init__.py └── test_action_log.py ├── models ├── __init__.py ├── test_data_issue.py └── test_user.py └── utils ├── test_metadata_utils.py ├── test_notification_utils.py ├── test_response_utils.py └── test_search_utils.py /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | amundsen_application/static/node_modules 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | root = true 5 | 6 | [*] 7 | 8 | # Change these settings to your own preference 9 | indent_style = space 10 | indent_size = 2 11 | 12 | # We recommend you to keep these unchanged 13 | end_of_line = lf 14 | charset = utf-8 15 | trim_trailing_whitespace = true 16 | insert_final_newline = true 17 | 18 | [*.py] 19 | indent_size = 4 20 | 21 | [*.json] 22 | indent_size = 2 23 | 24 | [*.yaml] 25 | indent_size = 2 26 | 27 | [*.md] 28 | trim_trailing_whitespace = false 29 | 30 | [Makefile] 31 | indent_style = tab 32 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/.gitattributes -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Codeowners file by GitHub 2 | # Reference: https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners 3 | # Each line is a file pattern followed by one or more owners. 4 | # Order is important; the last matching pattern takes the most 5 | # precedence. 6 | 7 | # These owners will be the default owners for everything in 8 | # the repo. Unless a later match takes precedence, 9 | # @amundsen-io/amundsen-committerswill be requested for 10 | # review when someone opens a pull request. 11 | * @amundsen-io/amundsen-committers 12 | 13 | # Frontend Files 14 | /amundsen_application/static/ @Golodhros @ttannis @allisonsuarez @dikshathakur3119 @feng-tao @dorianj @danwon 15 | 16 | # Backend Files 17 | *.py @ttannis @feng-tao @dikshathakur3119 @allisonsuarez @dorianj @danwon 18 | /amundsen_application/api/ @ttannis @feng-tao @dikshathakur3119 @allisonsuarez @dorianj 19 | /amundsen_application/models/ @ttannis @feng-tao @dikshathakur3119 @allisonsuarez @dorianj 20 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Deprecated: please visit https://github.com/amundsen-io/amundsen/tree/main/frontend 2 | 3 | The Amundsen project [moved to a monorepo](https://github.com/amundsen-io/rfcs/pull/31). This repository will be kept up temporarily to allow users to transition gracefully, but new PRs won't be accepted. 4 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 14 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 21 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - keep fresh 8 | # Label to use when marking an issue as stale 9 | staleLabel: stale 10 | # Comment to post when marking an issue as stale. Set to `false` to disable 11 | markComment: > 12 | This issue has been automatically marked as stale because it has not had 13 | recent activity. It will be closed if no further activity occurs. 14 | # Comment to post when closing a stale issue. Set to `false` to disable 15 | closeComment: > 16 | This issue has been automatically closed for inactivity. If you still wish to 17 | make these changes, please open a new pull request or reopen this one. 18 | -------------------------------------------------------------------------------- /.github/titleLint.yml: -------------------------------------------------------------------------------- 1 | regex: (build|ci|docs|feat|fix|perf|refactor|style|test|chore|other): .* 2 | -------------------------------------------------------------------------------- /.github/workflows/license.yml: -------------------------------------------------------------------------------- 1 | name: license 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Set up Golang 18 | uses: actions/setup-go@v2 19 | - name: Install addlicense 20 | run: | 21 | export PATH=${PATH}:`go env GOPATH`/bin 22 | go get -v -u github.com/google/addlicense 23 | - name: Check license python 24 | run: | 25 | export PATH=${PATH}:`go env GOPATH`/bin 26 | addlicense -check -l mit -c "Amundsen" $(find $PWD -type f -name '*.py') 27 | - name: Check license tsx 28 | run: | 29 | export PATH=${PATH}:`go env GOPATH`/bin 30 | addlicense -check -l mit -c "Amundsen" $(find $PWD -type f -name '*.tsx') 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.log 3 | *.pyc 4 | *.pyo 5 | *.pyt 6 | *.pytc 7 | *.egg-info 8 | .*.swp 9 | .DS_Store 10 | .eggs/ 11 | venv/ 12 | venv3/ 13 | .cache/ 14 | build/ 15 | .idea/ 16 | .vscode/ 17 | .coverage 18 | .mypy_cache 19 | .pytest_cache 20 | .python-version 21 | 22 | 23 | npm-debug.log 24 | .DS_Store 25 | env 26 | 27 | amundsen_application/.*/ 28 | dist/ 29 | node_modules/ 30 | jest 31 | .coverage 32 | coverage 33 | **/coverage.xml 34 | **/htmlcov/** 35 | 36 | # IntelliJ 37 | *.iml 38 | /.idea 39 | 40 | # Auto-generated source maps from PyCharm 41 | */static/dist/webpack.* 42 | */static/dist/js/ 43 | 44 | .git 45 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | This project is governed by [Lyft's code of conduct](https://github.com/lyft/code-of-conduct). 2 | All contributors and participants agree to abide by its terms. 3 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include amundsen_application/static/dist * 2 | recursive-include amundsen_application/static/fonts * 3 | recursive-include amundsen_application/static/images * 4 | 5 | 6 | recursive-include amundsen_application/.*/static/dist * 7 | recursive-include amundsen_application/.*/static/fonts * 8 | recursive-include amundsen_application/.*/static/images * 9 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | amundsenfrontendlibrary 2 | Copyright 2018-2019 Lyft Inc. 3 | 4 | This product includes software developed at Lyft Inc. 5 | -------------------------------------------------------------------------------- /amundsen_application/api/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | from typing import Any, Tuple 5 | import logging 6 | 7 | from flask import Flask, render_template 8 | import jinja2 9 | import os 10 | 11 | 12 | ENVIRONMENT = os.getenv('APPLICATION_ENV', 'development') 13 | LOGGER = logging.getLogger(__name__) 14 | 15 | 16 | def init_routes(app: Flask) -> None: 17 | app.add_url_rule('/healthcheck', 'healthcheck', healthcheck) 18 | app.add_url_rule('/', 'index', index, defaults={'path': ''}) # also functions as catch_all 19 | app.add_url_rule('/', 'index', index) # catch_all 20 | 21 | 22 | def index(path: str) -> Any: 23 | try: 24 | return render_template("index.html", env=ENVIRONMENT) # pragma: no cover 25 | except jinja2.exceptions.TemplateNotFound as e: 26 | LOGGER.error("index.html template not found, have you built the front-end JS (npm run build in static/?") 27 | raise e 28 | 29 | 30 | def healthcheck() -> Tuple[str, int]: 31 | return '', 200 # pragma: no cover 32 | -------------------------------------------------------------------------------- /amundsen_application/api/announcements/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/api/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | 5 | class MailClientNotImplemented(Exception): 6 | """ 7 | An exception when Mail Client is not implemented 8 | """ 9 | pass 10 | -------------------------------------------------------------------------------- /amundsen_application/api/issue/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/api/log/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/api/mail/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/api/metadata/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/api/preview/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/api/preview/dashboard/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/api/preview/dashboard/dashboard_preview/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/api/search/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/api/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/api/utils/response_utils.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | import logging 5 | 6 | from typing import Dict # noqa: F401 7 | 8 | from flask import Response, jsonify, make_response 9 | 10 | 11 | def create_error_response(*, message: str, payload: Dict, status_code: int) -> Response: 12 | """ 13 | Logs and info level log with the given message, and returns a response with: 14 | 1. The given message as 'msg' in the response data 15 | 2. The given status code as thge response status code 16 | """ 17 | logging.info(message) 18 | payload['msg'] = message 19 | return make_response(jsonify(payload), status_code) 20 | -------------------------------------------------------------------------------- /amundsen_application/base/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/base/base_preview.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | from abc import ABCMeta, abstractmethod 5 | 6 | 7 | class BasePreview(metaclass=ABCMeta): 8 | """ 9 | A Preview interface for other product to implement. For example, see ModePreview. 10 | """ 11 | 12 | @abstractmethod 13 | def get_preview_image(self, *, uri: str) -> bytes: 14 | """ 15 | Returns image bytes given URI 16 | :param uri: 17 | :return: 18 | :raises: FileNotFound when either Report is not available or Preview image is not available 19 | """ 20 | pass 21 | -------------------------------------------------------------------------------- /amundsen_application/base/base_preview_client.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | import abc 5 | from typing import Dict 6 | 7 | from flask import Response 8 | 9 | 10 | class BasePreviewClient(abc.ABC): 11 | @abc.abstractmethod 12 | def __init__(self) -> None: 13 | pass # pragma: no cover 14 | 15 | @abc.abstractmethod 16 | def get_preview_data(self, params: Dict, optionalHeaders: Dict = None) -> Response: 17 | """ 18 | Returns a Response object, where the response data represents a json object 19 | with the preview data accessible on 'preview_data' key. The preview data should 20 | match amundsen_application.models.preview_data.PreviewDataSchema 21 | """ 22 | raise NotImplementedError # pragma: no cover 23 | -------------------------------------------------------------------------------- /amundsen_application/base/examples/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/log/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/models/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/models/issue_results.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | from amundsen_application.models.data_issue import DataIssue 5 | from typing import List, Dict 6 | 7 | 8 | class IssueResults: 9 | def __init__(self, 10 | issues: List[DataIssue], 11 | total: int, 12 | all_issues_url: str) -> None: 13 | """ 14 | Returns an object representing results from an issue tracker. 15 | :param issues: Issues in the issue tracker matching the requested table 16 | :param total: How many issues in all are associated with this table 17 | :param all_issues_url: url to the all issues in the issue tracker 18 | """ 19 | self.issues = issues 20 | self.total = total 21 | self.all_issues_url = all_issues_url 22 | 23 | def serialize(self) -> Dict: 24 | return {'issues': [issue.serialize() for issue in self.issues], 25 | 'total': self.total, 26 | 'all_issues_url': self.all_issues_url} 27 | -------------------------------------------------------------------------------- /amundsen_application/models/preview_data.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | from marshmallow import Schema, fields, EXCLUDE 5 | from typing import List 6 | 7 | 8 | class ColumnItem: 9 | def __init__(self, column_name: str = None, column_type: str = None) -> None: 10 | self.column_name = column_name 11 | self.column_type = column_type 12 | 13 | 14 | class ColumnItemSchema(Schema): 15 | column_name = fields.Str() 16 | column_type = fields.Str() 17 | 18 | 19 | class PreviewData: 20 | def __init__(self, columns: List = [], data: List = [], error_text: str = '') -> None: 21 | self.columns = columns 22 | self.data = data 23 | self.error_text = error_text 24 | 25 | 26 | class PreviewDataSchema(Schema): 27 | columns = fields.Nested(ColumnItemSchema, many=True, unknown=EXCLUDE) 28 | data = fields.List(fields.Dict, many=True) 29 | error_text = fields.Str() 30 | -------------------------------------------------------------------------------- /amundsen_application/proxy/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/proxy/issue_tracker_clients/issue_exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | 5 | class IssueConfigurationException(Exception): 6 | """ 7 | Raised when there are missing configuration settings 8 | """ 9 | pass 10 | -------------------------------------------------------------------------------- /amundsen_application/static/.eslintignore: -------------------------------------------------------------------------------- 1 | **/*{.,-}min.js 2 | **/*.sh 3 | coverage/** 4 | dist/* 5 | images/* 6 | node_modules/* 7 | node_modules*/* 8 | stylesheets/* 9 | vendor/* 10 | docs/* 11 | appbuilder/* 12 | .src-custom/* 13 | -------------------------------------------------------------------------------- /amundsen_application/static/.nvmrc: -------------------------------------------------------------------------------- 1 | v12 2 | -------------------------------------------------------------------------------- /amundsen_application/static/.storybook/amundsenTheme.js: -------------------------------------------------------------------------------- 1 | import { create } from '@storybook/theming/create'; 2 | 3 | export default create({ 4 | base: 'light', 5 | 6 | colorPrimary: '#9c9bff', // indigo30 7 | colorSecondary: '#665aff', // indigo60 8 | 9 | // UI 10 | appBg: '#fcfcff', // gray0 11 | appContentBg: '#cacad9', // gray20 12 | appBorderColor: '#63637b', // gray60 13 | appBorderRadius: 4, 14 | 15 | // Typography 16 | fontBase: '"Open Sans", sans-serif', 17 | fontCode: '"Menlo-Bold", monospace', 18 | 19 | // Text colors 20 | textColor: '#292936', // gray100 21 | textInverseColor: '#fcfcff', // gray0 22 | 23 | // Toolbar default and active colors 24 | barTextColor: '#dcdcff', // indigo10 25 | barSelectedColor: '#292936', // gray100 26 | barBg: '#665aff', // indigo60 27 | 28 | // Form colors 29 | inputBg: 'white', 30 | inputBorder: 'silver', 31 | inputTextColor: 'black', 32 | inputBorderRadius: 4, 33 | 34 | brandTitle: "Amundsen's Storybook", 35 | brandUrl: 'https://amundsen.lyft.net/', 36 | brandImage: 37 | 'https://raw.githubusercontent.com/lyft/amundsen/master/docs/img/logos/amundsen_logo_on_light.svg?sanitize=true', 38 | }); 39 | -------------------------------------------------------------------------------- /amundsen_application/static/.storybook/main.ts: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import customWebpackConfig from './webpack.config.js'; 5 | import MiniCssExtractPlugin from 'mini-css-extract-plugin'; 6 | 7 | module.exports = { 8 | stories: ['../js/**/*.story.tsx'], 9 | addons: [ 10 | '@storybook/addon-actions', 11 | '@storybook/addon-links', 12 | '@storybook/addon-knobs', 13 | ], 14 | webpackFinal: (config) => { 15 | return { 16 | ...config, 17 | module: { 18 | ...config.module, 19 | rules: customWebpackConfig.module.rules, 20 | }, 21 | resolve: { 22 | ...config.resolve, 23 | ...customWebpackConfig.resolve, 24 | }, 25 | plugins: [ 26 | new MiniCssExtractPlugin({ 27 | filename: '[name].[contenthash].css', 28 | }), 29 | ...config.plugins, 30 | ], 31 | }; 32 | }, 33 | }; 34 | -------------------------------------------------------------------------------- /amundsen_application/static/.storybook/manager.ts: -------------------------------------------------------------------------------- 1 | import { addons } from '@storybook/addons'; 2 | 3 | import amundsenTheme from './amundsenTheme'; 4 | 5 | addons.setConfig({ 6 | isFullscreen: false, 7 | showNav: true, 8 | showPanel: true, 9 | panelPosition: 'right', 10 | sidebarAnimations: true, 11 | enableShortcuts: true, 12 | isToolshown: true, 13 | theme: amundsenTheme, 14 | selectedPanel: undefined, 15 | initialActive: 'sidebar', 16 | showRoots: true, 17 | }); 18 | -------------------------------------------------------------------------------- /amundsen_application/static/.storybook/preview.ts: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import '../css/styles.scss'; 5 | 6 | const categoriesOrder = ['Overview', 'Attributes', 'Components']; 7 | 8 | export const parameters = { 9 | options: { 10 | storySort: { 11 | order: categoriesOrder, 12 | }, 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_animations.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | $loading-duration: 1s; 7 | $loading-curve: cubic-bezier(0.45, 0, 0.15, 1); 8 | 9 | @keyframes shimmer { 10 | 0% { 11 | background-position: 100% 0; 12 | } 13 | 14 | 100% { 15 | background-position: 0 0; 16 | } 17 | } 18 | 19 | %is-shimmer-animated { 20 | animation: $loading-duration shimmer $loading-curve infinite; 21 | background-image: linear-gradient( 22 | to right, 23 | $gray10 0%, 24 | $gray10 33%, 25 | $gray5 50%, 26 | $gray10 67%, 27 | $gray10 100% 28 | ); 29 | background-repeat: no-repeat; 30 | background-size: 300% 100%; 31 | } 32 | 33 | .is-shimmer-animated { 34 | @extend %is-shimmer-animated; 35 | } 36 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_avatars.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | .sb-avatar > img { 5 | margin: 0; 6 | } 7 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_buttons-custom.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // This file is intentionally left blank and should be overwritten by in the build process. 5 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_buttons.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'buttons-default'; 5 | @import 'buttons-custom'; 6 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_dropdowns.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .dropdown { 7 | .dropdown-toggle { 8 | box-shadow: none; 9 | } 10 | 11 | .dropdown-menu { 12 | border: 1px solid $stroke; 13 | border-radius: 4px; 14 | box-shadow: 0 4px 12px -3px rgba(17, 17, 31, 0.12); 15 | overflow: hidden; 16 | padding: 0; 17 | 18 | li { 19 | &:hover { 20 | background-color: $body-bg-tertiary; 21 | } 22 | 23 | a { 24 | padding: 8px; 25 | 26 | &:hover { 27 | background-color: inherit; 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_fonts-custom.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // This file is intentionally left blank and should be used to add new fonts or overwrite defaults from _fonts-default.scss 5 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_fonts.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // Amundsen Default Fonts 5 | @import 'fonts-default'; 6 | // Per-Client Custom Fonts 7 | @import 'fonts-custom'; 8 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_inputs.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | input { 7 | &::-webkit-input-placeholder, 8 | &::-moz-placeholder, 9 | &:-ms-input-placeholder, 10 | &:-moz-placeholder, 11 | &::placeholder { 12 | color: $text-placeholder !important; 13 | } 14 | 15 | &:-webkit-autofill, 16 | &:-webkit-autofill:hover, 17 | &:-webkit-autofill:focus, 18 | &:-webkit-autofill:active { 19 | -webkit-box-shadow: 0 0 0 1000px $white inset !important; 20 | box-shadow: 0 0 0 1000px $white inset !important; 21 | } 22 | 23 | &[type='radio'] { 24 | margin: 5px; 25 | } 26 | 27 | &[type='text'] { 28 | color: $text-secondary !important; 29 | } 30 | 31 | &:not([disabled]) { 32 | cursor: pointer; 33 | } 34 | } 35 | 36 | textarea { 37 | border: 1px solid $stroke; 38 | border-radius: 5px; 39 | color: $text-secondary !important; 40 | padding: 10px; 41 | width: 100%; 42 | } 43 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_labels.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .label-negative { 7 | background-color: $badge-negative-color; 8 | color: $badge-text-color; 9 | } 10 | 11 | .label-neutral { 12 | background-color: $badge-neutral-color; 13 | color: $badge-text-color; 14 | } 15 | 16 | .label-primary { 17 | background-color: $badge-primary-color; 18 | color: $badge-text-color; 19 | } 20 | 21 | .label-positive { 22 | background-color: $badge-positive-color; 23 | color: $badge-text-color; 24 | } 25 | 26 | .label-warning { 27 | background-color: $badge-warning-color; 28 | color: $badge-text-color; 29 | } 30 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_list-group.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .list-group { 7 | margin: 24px 0; 8 | 9 | .list-group-item { 10 | border-left: none; 11 | border-right: none; 12 | padding: 0; 13 | 14 | &.clickable:hover { 15 | box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.12), 0 2px 3px 0 rgba(0, 0, 0, 0.16); 16 | cursor: pointer; 17 | z-index: 1; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_pagination.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .pagination { 7 | display: flex; 8 | justify-content: center; 9 | 10 | li { 11 | > a, 12 | > span { 13 | border: 1px solid $stroke; 14 | color: $brand-color-4; 15 | 16 | &:focus, 17 | &:hover { 18 | background-color: $body-bg-tertiary; 19 | color: $link-hover-color; 20 | z-index: 0; 21 | } 22 | } 23 | 24 | &.active { 25 | > a, 26 | > span { 27 | &, 28 | &:active, 29 | &:hover, 30 | &:focus { 31 | background-color: $brand-color-4; 32 | border-color: $brand-color-4; 33 | color: $white; 34 | z-index: 0; 35 | } 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_typography-custom.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // This file is intentionally left blank and should be overwritten by in the build process. 5 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_typography.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // Amundsen Default Typography 5 | @import 'typography-default'; 6 | // Per-Client Custom Typography 7 | @import 'typography-custom'; 8 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_variables-custom.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // This file is intentionally left blank and should be used to add new custom variables or overwrite defaults from _variables-default.scss 5 | -------------------------------------------------------------------------------- /amundsen_application/static/css/_variables.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // Amundsen Default Values 5 | @import 'variables-default'; 6 | // Per-Client Custom Values 7 | @import 'variables-custom'; 8 | // Bootstrap Default Values 9 | @import '~bootstrap-sass/assets/stylesheets/bootstrap/variables'; 10 | -------------------------------------------------------------------------------- /amundsen_application/static/css/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'bootstrap-custom'; 5 | @import 'animations'; 6 | @import 'avatars'; 7 | @import 'buttons'; 8 | @import 'dropdowns'; 9 | @import 'fonts'; 10 | @import 'icons'; 11 | @import 'inputs'; 12 | @import 'labels'; 13 | @import 'layouts'; 14 | @import 'list-group'; 15 | @import 'pagination'; 16 | @import 'popovers'; 17 | @import 'typography'; 18 | 19 | // Misc 20 | td { 21 | overflow: hidden; 22 | text-overflow: ellipsis; 23 | white-space: nowrap; 24 | } 25 | 26 | form { 27 | margin-bottom: 0; 28 | } 29 | -------------------------------------------------------------------------------- /amundsen_application/static/fonts/OpenSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/fonts/OpenSans-Bold.ttf -------------------------------------------------------------------------------- /amundsen_application/static/fonts/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/fonts/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /amundsen_application/static/fonts/OpenSans-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/fonts/OpenSans-SemiBold.ttf -------------------------------------------------------------------------------- /amundsen_application/static/fonts/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/fonts/Roboto-Bold.ttf -------------------------------------------------------------------------------- /amundsen_application/static/fonts/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/fonts/Roboto-Medium.ttf -------------------------------------------------------------------------------- /amundsen_application/static/fonts/SpaceMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/fonts/SpaceMono-Regular.ttf -------------------------------------------------------------------------------- /amundsen_application/static/global.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | 3 | declare const require: { 4 | (path: string): T; 5 | (paths: string[], callback: (...modules: any[]) => void): void; 6 | ensure: ( 7 | paths: string[], 8 | callback: (require: (path: string) => T) => void 9 | ) => void; 10 | }; 11 | -------------------------------------------------------------------------------- /amundsen_application/static/images/airflow.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/airflow.jpeg -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/dev/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/dev/android-chrome-192x192.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/dev/android-chrome-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/dev/android-chrome-256x256.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/dev/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/dev/apple-touch-icon.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/dev/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #2d89ef 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/dev/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/dev/favicon-16x16.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/dev/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/dev/favicon-32x32.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/dev/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/dev/favicon.ico -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/dev/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/dev/mstile-150x150.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/dev/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Amundsen Dev", 3 | "short_name": "Amundsen Dev", 4 | "icons": [ 5 | { 6 | "src": "/static/images/favicons/dev/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/static/images/favicons/dev/android-chrome-256x256.png", 12 | "sizes": "256x256", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/prod/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/prod/android-chrome-192x192.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/prod/android-chrome-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/prod/android-chrome-256x256.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/prod/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/prod/apple-touch-icon.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/prod/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #2d89ef 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/prod/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/prod/favicon-16x16.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/prod/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/prod/favicon-32x32.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/prod/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/prod/favicon.ico -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/prod/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/prod/mstile-150x150.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/prod/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Amundsen", 3 | "short_name": "Amundsen", 4 | "icons": [ 5 | { 6 | "src": "/static/images/favicons/prod/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/static/images/favicons/prod/android-chrome-256x256.png", 12 | "sizes": "256x256", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/staging/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/staging/android-chrome-192x192.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/staging/android-chrome-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/staging/android-chrome-256x256.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/staging/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/staging/apple-touch-icon.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/staging/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #2b5797 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/staging/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/staging/favicon-16x16.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/staging/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/staging/favicon-32x32.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/staging/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/staging/favicon.ico -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/staging/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/favicons/staging/mstile-150x150.png -------------------------------------------------------------------------------- /amundsen_application/static/images/favicons/staging/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Amundsen", 3 | "short_name": "Amundsen", 4 | "icons": [ 5 | { 6 | "src": "/static/images/favicons/staging/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/static/images/favicons/staging/android-chrome-256x256.png", 12 | "sizes": "256x256", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /amundsen_application/static/images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/github.png -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/Alert-Triangle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/DataQualityWarning.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/Delta-Up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Delta-Up 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/Edit.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/Help-Circle.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/More.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | More 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/Null-Value.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Null-Value 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/Plus-Circle.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/Refresh-cw.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/Send.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/Trash.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/check.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/dashboard.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/github.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/logo-delta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/icons/logo-delta.png -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/logo-mode.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | mode-logo 5 | Created with Sketch. 6 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/logo-redshift.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/logo-tableau.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/mail.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/plus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/slack.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /amundsen_application/static/images/icons/users.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /amundsen_application/static/images/loading_spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/loading_spinner.gif -------------------------------------------------------------------------------- /amundsen_application/static/images/watermark-range.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/static/images/watermark-range.png -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Alert/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | @import 'typography'; 6 | 7 | $alert-border-radius: 4px; 8 | $alert-message-line-height: 24px; 9 | 10 | .alert { 11 | background-color: $body-bg; 12 | border-radius: $alert-border-radius; 13 | display: flex; 14 | padding: $spacer-1 $spacer-1 * 1.5 $spacer-1 $spacer-2; 15 | justify-content: flex-start; 16 | box-shadow: $elevation-level2; 17 | 18 | .alert-message { 19 | @extend %text-body-w2; 20 | 21 | margin: 0; 22 | display: inline; 23 | } 24 | 25 | .alert-triangle-svg-icon, 26 | .info-svg-icon { 27 | flex-shrink: 0; 28 | align-self: center; 29 | margin-right: $spacer-1; 30 | } 31 | 32 | .alert-action { 33 | margin: auto 0 auto auto; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Announcements/AnnouncementsList/styles.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | @import 'typography'; 3 | 4 | $more-link-size: 18px; 5 | $more-link-line-height: 21px; 6 | $message-size: 14px; 7 | $message-line-height: 16px; 8 | $message-border-size: 1px; 9 | 10 | .announcements-list-title { 11 | @extend %text-title-w1; 12 | } 13 | 14 | .announcements-list { 15 | list-style: none; 16 | margin: $spacer-1 0 0 0; 17 | padding: 0; 18 | 19 | .announcement { 20 | margin-bottom: -1px; 21 | } 22 | 23 | .announcement-content p { 24 | margin: 0; 25 | } 26 | } 27 | 28 | .announcements-list-more-link { 29 | font-size: $more-link-size; 30 | line-height: $more-link-line-height; 31 | margin-top: 12px; 32 | display: block; 33 | } 34 | 35 | .empty-announcement, 36 | .error-announcement { 37 | font-size: $message-size; 38 | line-height: $message-line-height; 39 | color: $text-primary; 40 | text-align: center; 41 | border-top: $message-border-size solid $gray20; 42 | padding-top: $spacer-3; 43 | } 44 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Announcements/constants.ts: -------------------------------------------------------------------------------- 1 | export const HEADER_TEXT = 'Announcements'; 2 | export const MORE_LINK_TEXT = 'See more'; 3 | export const NO_ANNOUNCEMENTS_TEXT = 'No announcements to show'; 4 | export const ANNOUNCEMENTS_ERROR_TEXT = 'Could not fetch announcements'; 5 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/AvatarLabel/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import * as Avatar from 'react-avatar'; 6 | 7 | // TODO: Use css-modules instead of 'import' 8 | import './styles.scss'; 9 | 10 | export interface AvatarLabelProps { 11 | avatarClass?: string; 12 | labelClass?: string; 13 | label?: string; 14 | round?: boolean; 15 | src?: string; 16 | } 17 | 18 | const AvatarLabel: React.FC = ({ 19 | avatarClass, 20 | labelClass = 'text-secondary', 21 | label = '', 22 | round = true, 23 | src = '', 24 | }: AvatarLabelProps) => ( 25 |
26 | 33 | {label} 34 |
35 | ); 36 | 37 | export default AvatarLabel; 38 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/AvatarLabel/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .avatar-label-component { 7 | display: inline-block; 8 | 9 | .avatar-label { 10 | cursor: inherit; 11 | margin-left: 8px; 12 | min-width: 0; 13 | vertical-align: middle; 14 | } 15 | 16 | .gray-avatar { 17 | div { 18 | background: $gray20 !important; 19 | color: $gray20 !important; 20 | } 21 | } 22 | } 23 | 24 | .avatar-overlap { 25 | margin-left: -5px; 26 | 27 | &:first-child { 28 | margin-left: 0; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Bookmark/BookmarkIcon/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .bookmark-icon { 7 | border-radius: 50%; 8 | cursor: pointer; 9 | display: inline-block; 10 | height: 32px; 11 | margin-left: 4px; 12 | padding: 4px; 13 | vertical-align: top; 14 | width: 32px; 15 | 16 | &.bookmark-large { 17 | height: 40px; 18 | width: 40px; 19 | 20 | .icon { 21 | height: 32px; 22 | -webkit-mask-size: 32px; 23 | mask-size: 32px; 24 | width: 32px; 25 | } 26 | } 27 | 28 | &:hover, 29 | &:focus { 30 | background-color: $body-bg-tertiary; 31 | } 32 | 33 | .icon { 34 | margin: 0; 35 | 36 | &.icon-bookmark { 37 | &, 38 | &:hover, 39 | &:focus { 40 | background-color: $stroke !important; 41 | } 42 | } 43 | 44 | &.icon-bookmark-filled { 45 | &, 46 | &:hover, 47 | &:focus { 48 | background-color: gold !important; 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Bookmark/MyBookmarks/constants.ts: -------------------------------------------------------------------------------- 1 | export const BOOKMARK_TITLE = 'My Bookmarks'; 2 | export const BOOKMARKS_PER_PAGE = 4; 3 | export const EMPTY_BOOKMARK_MESSAGE = 4 | "You don't have any bookmarks. Use the star icon to save a bookmark."; 5 | export const MY_BOOKMARKS_SOURCE_NAME = 'bookmarks'; 6 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Bookmark/MyBookmarks/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | @import 'typography'; 6 | 7 | .bookmark-list { 8 | margin: 32px 0; 9 | 10 | .bookmark-list-header { 11 | @extend %text-title-w1; 12 | 13 | margin-bottom: $spacer-1; 14 | } 15 | 16 | .tabs-component { 17 | .nav.nav-tabs { 18 | margin: 0; 19 | } 20 | 21 | .tab-content .list-group-item:first-child { 22 | border-top: none; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Breadcrumb/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .amundsen-breadcrumb { 7 | display: inline-block; 8 | height: 24px; 9 | 10 | img.icon-left { 11 | margin: -3px 0 -3px -8px; 12 | } 13 | 14 | span { 15 | display: inline-block; 16 | height: 24px; 17 | line-height: 24px; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/EditableSection/constants.ts: -------------------------------------------------------------------------------- 1 | export const EDIT_TEXT = 'Click to edit'; 2 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/EditableSection/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .editable-section { 7 | .editable-section-label { 8 | display: block; 9 | font-weight: 400; 10 | margin-bottom: 0; 11 | } 12 | 13 | .editable-section-label-wrapper { 14 | margin-bottom: $spacer-1; 15 | } 16 | 17 | .section-title { 18 | color: $text-tertiary; 19 | margin-bottom: $spacer-1/2; 20 | font-weight: 700; 21 | } 22 | 23 | .edit-button { 24 | margin-left: $spacer-1/2; 25 | opacity: 0; 26 | 27 | img { 28 | margin-bottom: auto; 29 | } 30 | 31 | &.active { 32 | opacity: 1; 33 | } 34 | } 35 | 36 | &:hover { 37 | .edit-button { 38 | opacity: 1; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/EditableText/constants.ts: -------------------------------------------------------------------------------- 1 | export const REFRESH_MESSAGE = 2 | 'This text is out of date, please refresh the component'; 3 | export const REFRESH_BUTTON_TEXT = 'Refresh'; 4 | export const UPDATE_BUTTON_TEXT = 'Update'; 5 | export const CANCEL_BUTTON_TEXT = 'Cancel'; 6 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/EditableText/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .editable-text { 7 | // React-Markdown 8 | .markdown-wrapper { 9 | font-size: 14px; 10 | word-break: break-word; 11 | } 12 | 13 | .edit-link { 14 | text-decoration: none; 15 | } 16 | 17 | .editable-textarea { 18 | background: $body-bg-secondary; 19 | border-color: $stroke; 20 | border-radius: 4px; 21 | max-width: 600px; 22 | min-width: 300px; 23 | outline: none; 24 | padding: 8px; 25 | resize: none; 26 | 27 | &:disabled { 28 | background: $body-bg-tertiary; 29 | } 30 | } 31 | 32 | .editable-textarea-controls { 33 | margin: 16px 0 8px; 34 | 35 | .btn { 36 | margin-right: 8px; 37 | } 38 | 39 | .label.label-danger { 40 | display: block; 41 | margin-bottom: 16px; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/EntityCard/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import EntityCardSection, { EntityCardSectionProps } from './EntityCardSection'; 6 | 7 | // TODO: Use css-modules instead of 'import' 8 | import './styles.scss'; 9 | 10 | export interface EntityCardProps { 11 | sections: EntityCardSectionProps[]; 12 | } 13 | 14 | const EntityCard: React.FC = ({ 15 | sections, 16 | }: EntityCardProps) => { 17 | const cardItems = sections.map((entry, index) => ( 18 | 25 | )); 26 | 27 | return
{cardItems}
; 28 | }; 29 | 30 | EntityCard.defaultProps = { 31 | sections: [], 32 | }; 33 | 34 | export default EntityCard; 35 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/EntityCard/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .entity-card { 7 | border-radius: 0 0 6px 6px; 8 | border-top: 4px solid $brand-color-4; 9 | box-shadow: 0 0 24px -2px rgba(0, 0, 0, 0.2); 10 | padding: 32px; 11 | } 12 | 13 | @media (max-width: $screen-sm-max) { 14 | .entity-card { 15 | border: 0; 16 | box-shadow: none; 17 | margin-bottom: 32px; 18 | padding: 0; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Flag/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | 6 | import { BadgeStyle } from 'config/config-types'; 7 | import { convertText, CaseType } from 'utils/textUtils'; 8 | 9 | import './styles.scss'; 10 | 11 | export interface FlagProps { 12 | caseType?: CaseType | null; 13 | text: string; 14 | labelStyle?: BadgeStyle; 15 | } 16 | 17 | const Flag: React.FC = ({ 18 | caseType = null, 19 | text = '', 20 | labelStyle = BadgeStyle.DEFAULT, 21 | }: FlagProps) => ( 22 | // TODO: After upgrading to Bootstrap 4, this component should leverage badges 23 | // https://getbootstrap.com/docs/4.1/components/badge/ 24 | 25 |
26 | {convertText(text, caseType)} 27 |
28 |
29 | ); 30 | export default Flag; 31 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Flag/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .flag { 7 | border-radius: 5px; 8 | display: inline-block; 9 | font-size: $font-size-base; 10 | height: $badge-height; 11 | margin: 0 0 0 $spacer-1; 12 | } 13 | 14 | .label { 15 | border-radius: 10px; 16 | font-weight: normal; 17 | } 18 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/FlashMessage/constants.ts: -------------------------------------------------------------------------------- 1 | export const CLOSE = 'Close'; 2 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/FlashMessage/flashMessage.story.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import React from 'react'; 5 | import { storiesOf } from '@storybook/react'; 6 | 7 | import { ImageIconType } from 'interfaces/Enums'; 8 | import StorySection from '../StorySection'; 9 | import FlashMessage from '.'; 10 | 11 | const stories = storiesOf('Components/Flash Message', module); 12 | 13 | stories.add('Flash Message', () => ( 14 | <> 15 | 16 | { 19 | alert('message closed!'); 20 | }} 21 | /> 22 | 23 | 24 | { 28 | alert('message closed!'); 29 | }} 30 | /> 31 | 32 | 33 | )); 34 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/FlashMessage/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import { ImageIconType } from 'interfaces/Enums'; 6 | import * as Constants from './constants'; 7 | 8 | import './styles.scss'; 9 | 10 | export interface FlashMessageProps { 11 | iconClass?: ImageIconType | null; 12 | message: string; 13 | onClose: (event: React.MouseEvent) => void; 14 | } 15 | 16 | const FlashMessage: React.FC = ({ 17 | iconClass, 18 | message, 19 | onClose, 20 | }: FlashMessageProps) => ( 21 |
22 |
23 | {iconClass && } 24 |

{message}

25 |
26 | 29 |
30 | ); 31 | 32 | FlashMessage.defaultProps = { 33 | iconClass: null, 34 | }; 35 | 36 | export default FlashMessage; 37 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/FlashMessage/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | @import 'typography'; 6 | 7 | $flash-message-height: 56px; 8 | $flash-message-border-radius: 4px; 9 | $flash-message-message-line-height: 24px; 10 | 11 | .flash-message { 12 | background-color: $body-bg-dark; 13 | border-radius: $flash-message-border-radius; 14 | color: $white; 15 | display: flex; 16 | height: $flash-message-height; 17 | padding: $spacer-2; 18 | padding-right: $spacer-1 * 1.5; 19 | justify-content: space-between; 20 | 21 | .message { 22 | @extend %text-body-w3; 23 | 24 | line-height: $flash-message-message-line-height; 25 | margin: 0; 26 | display: inline; 27 | } 28 | 29 | .icon { 30 | margin: 0 $spacer-1 0 0; 31 | } 32 | 33 | .btn-close { 34 | margin: auto 0 auto $spacer-3; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/InfoButton/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | $info-button-regular-size: 24px; 7 | $info-button-small-size: 18px; 8 | 9 | .btn.info-button { 10 | background-color: transparent; 11 | border: none; 12 | height: $info-button-regular-size; 13 | margin: 0 0 0 $spacer-1; 14 | padding: 0; 15 | width: $info-button-regular-size; 16 | 17 | &.small { 18 | height: $info-button-small-size; 19 | margin: -4px 0 0 4px; 20 | width: $info-button-small-size; 21 | } 22 | 23 | &:hover path { 24 | fill: $brand-color-4; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Inputs/CheckBoxItem/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | 6 | import 'components/Inputs/styles.scss'; 7 | 8 | export interface CheckBoxItemProps { 9 | checked?: boolean; 10 | disabled?: boolean; 11 | name: string; 12 | onChange: (e: React.FormEvent) => any; 13 | value: string; 14 | children: React.ReactNode; 15 | } 16 | 17 | const CheckBoxItem: React.FC = ({ 18 | checked = false, 19 | disabled = false, 20 | name, 21 | onChange, 22 | value, 23 | children, 24 | }: CheckBoxItemProps) => ( 25 |
26 | 37 |
38 | ); 39 | 40 | export default CheckBoxItem; 41 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Inputs/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | .checkbox, 5 | .radio { 6 | margin-bottom: 16px; 7 | margin-top: 16px; 8 | 9 | .checkbox-label, 10 | .radio-label { 11 | display: block; 12 | width: 100%; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/LoadingSpinner/index.spec.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | 6 | import { shallow } from 'enzyme'; 7 | 8 | import LoadingSpinner from '.'; 9 | 10 | describe('LoadingSpinner', () => { 11 | let subject; 12 | 13 | beforeEach(() => { 14 | subject = shallow(); 15 | }); 16 | 17 | describe('render', () => { 18 | it('renders img with props', () => { 19 | expect(subject.find('img').props()).toMatchObject({ 20 | alt: 'loading...', 21 | className: 'loading-spinner', 22 | src: '/static/images/loading_spinner.gif', 23 | }); 24 | }); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/LoadingSpinner/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | 6 | import './styles.scss'; 7 | 8 | const LoadingSpinner: React.FC = () => ( 9 | loading... 14 | ); 15 | 16 | export default LoadingSpinner; 17 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/LoadingSpinner/loadingSpinner.story.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import React from 'react'; 5 | import { storiesOf } from '@storybook/react'; 6 | 7 | import StorySection from '../StorySection'; 8 | import LoadingSpinner from '.'; 9 | 10 | const stories = storiesOf('Attributes/States', module); 11 | 12 | stories.add('Loading Spinner', () => ( 13 | <> 14 | 15 | 16 | 17 | 18 | )); 19 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/LoadingSpinner/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .loading-spinner { 7 | display: block; 8 | height: 100px; 9 | margin: auto; 10 | margin-top: 20%; 11 | width: 100px; 12 | } 13 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/OwnerEditor/constants.ts: -------------------------------------------------------------------------------- 1 | export const DEFAULT_ERROR_TEXT = 2 | 'There was a problem with the request, please reload the page.'; 3 | export const USERID_LABEL = 'email address'; 4 | export const ADD_ITEM = 'Add'; 5 | export const ADD_OWNER = 'Add Owner'; 6 | export const DELETE_ITEM = 'Delete Item'; 7 | export const NO_OWNER_TEXT = 'No owner'; 8 | export const OWNED_BY = 'Owned By'; 9 | export const CANCEL_TEXT = 'Cancel'; 10 | export const SAVE_TEXT = 'Save'; 11 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/PopularTables/constants.ts: -------------------------------------------------------------------------------- 1 | // TODO: Hard-coded text strings should be translatable/customizable 2 | export const POPULAR_TABLES_INFO_TEXT = 3 | 'These are some of the most commonly accessed tables within your organization.'; 4 | export const POPULAR_TABLES_LABEL = 'Popular Tables'; 5 | export const POPULAR_TABLES_SOURCE_NAME = 'popular_tables'; 6 | export const POPULAR_TABLES_PER_PAGE = 4; 7 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/PopularTables/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | @import 'typography'; 6 | 7 | .popular-table-list { 8 | .popular-tables-header { 9 | display: flex; 10 | flex-direction: row; 11 | margin-bottom: $spacer-2; 12 | } 13 | 14 | .popular-tables-header-text { 15 | @extend %text-title-w1; 16 | } 17 | 18 | .list-group { 19 | margin-top: 0; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Preloader/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import { bindActionCreators } from 'redux'; 6 | import { connect } from 'react-redux'; 7 | 8 | import { getBookmarks } from 'ducks/bookmark/reducer'; 9 | import { GetBookmarksRequest } from 'ducks/bookmark/types'; 10 | 11 | import { getLoggedInUser } from 'ducks/user/reducer'; 12 | import { GetLoggedInUserRequest } from 'ducks/user/types'; 13 | 14 | interface DispatchFromProps { 15 | getLoggedInUser: () => GetLoggedInUserRequest; 16 | getBookmarks: () => GetBookmarksRequest; 17 | } 18 | 19 | export type PreloaderProps = DispatchFromProps; 20 | 21 | export class Preloader extends React.Component { 22 | componentDidMount() { 23 | this.props.getLoggedInUser(); 24 | this.props.getBookmarks(); 25 | } 26 | 27 | render() { 28 | return null; 29 | } 30 | } 31 | 32 | export const mapDispatchToProps = (dispatch) => 33 | bindActionCreators({ getLoggedInUser, getBookmarks }, dispatch); 34 | 35 | export default connect<{}, DispatchFromProps>( 36 | null, 37 | mapDispatchToProps 38 | )(Preloader); 39 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/ResourceList/ResourceListHeader/constants.ts: -------------------------------------------------------------------------------- 1 | export const RESOURCE_HEADER_TITLE = 'RESOURCE'; 2 | 3 | export const SOURCE_HEADER_TITLE = 'SOURCE'; 4 | 5 | export const BADGES_HEADER_TITLE = 'BADGES'; 6 | 7 | export const LAST_UPDATED_HEADER_TITLE = 'LAST RUN'; 8 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/ResourceList/ResourceListHeader/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | @import 'typography'; 6 | 7 | .resource-list-header { 8 | @extend %text-caption-w2; 9 | 10 | display: flex; 11 | flex-direction: row; 12 | align-items: center; 13 | height: $spacer-6; 14 | padding: $spacer-1 $spacer-3 $spacer-1; 15 | 16 | .resource { 17 | flex: 7; 18 | margin-right: $spacer-2; 19 | 20 | .resource-text { 21 | margin-left: $spacer-5; 22 | } 23 | } 24 | 25 | .source { 26 | flex: 2; 27 | } 28 | 29 | .badges { 30 | display: flex; 31 | flex: 3; 32 | flex-wrap: wrap; 33 | margin-left: $spacer-3; 34 | 35 | .badges-text { 36 | margin-left: $spacer-3; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/ResourceList/constants.ts: -------------------------------------------------------------------------------- 1 | export const PAGINATION_PAGE_RANGE = 10; 2 | 3 | export const DEFAULT_EMPTY_TEXT = 'No resources to display'; 4 | 5 | export const FOOTER_TEXT_COLLAPSED = 'View all'; 6 | export const FOOTER_TEXT_EXPANDED = 'View less'; 7 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/ResourceList/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .paginated-resource-list, 7 | .resource-list { 8 | ul { 9 | margin-bottom: 0; 10 | } 11 | 12 | .resource-list-title { 13 | margin: $spacer-3 0 $spacer-1 $spacer-4; 14 | } 15 | 16 | .resource-list-footer { 17 | height: $spacer-3; 18 | margin: $spacer-1 0 $spacer-1 $spacer-4; 19 | 20 | a { 21 | cursor: pointer; 22 | font-weight: $font-weight-body-bold; 23 | } 24 | } 25 | 26 | .empty-message { 27 | display: flex; 28 | justify-content: center; 29 | margin: $spacer-4 $spacer-4 0; 30 | word-break: break-all; 31 | } 32 | } 33 | 34 | .paginated-resource-list { 35 | margin-bottom: $spacer-4; 36 | } 37 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/ResourceListItem/DashboardListItem/constants.ts: -------------------------------------------------------------------------------- 1 | export const LAST_RUN_TITLE = 'Last Successful Run'; 2 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/ResourceListItem/SchemaInfo/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import { OverlayTrigger, Popover } from 'react-bootstrap'; 6 | 7 | import './styles.scss'; 8 | 9 | export interface SchemaInfoProps { 10 | schema: string; 11 | table: string; 12 | desc: string; 13 | placement?: string; 14 | } 15 | 16 | const SchemaInfo: React.FC = ({ 17 | schema, 18 | table, 19 | desc, 20 | placement, 21 | }: SchemaInfoProps) => { 22 | const popoverHoverFocus = ( 23 | 24 | {schema}: {desc} 25 | 26 | ); 27 | 28 | return ( 29 | <> 30 | 35 | {schema} 36 | 37 | .{table} 38 | 39 | ); 40 | }; 41 | 42 | SchemaInfo.defaultProps = { 43 | placement: 'bottom', 44 | }; 45 | 46 | export default SchemaInfo; 47 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/ResourceListItem/SchemaInfo/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .underline { 7 | box-shadow: 0 1px 0 $stroke-underline; 8 | 9 | &:hover, 10 | &:focus { 11 | background: $btn-default-bg-hover; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/ResourceListItem/types.ts: -------------------------------------------------------------------------------- 1 | export interface LoggingParams { 2 | source: string; 3 | index: number; 4 | } 5 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/SVGIcons/AlertIcon.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | 6 | import { IconSizes } from 'interfaces'; 7 | import { IconProps } from './types'; 8 | 9 | const DEFAULT_STROKE_COLOR = 'currentColor'; 10 | 11 | export const AlertIcon: React.FC = ({ 12 | stroke = DEFAULT_STROKE_COLOR, 13 | size = IconSizes.REGULAR, 14 | }: IconProps) => ( 15 | 26 | 27 | 28 | ); 29 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/SVGIcons/DownIcon.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import { v4 as uuidv4 } from 'uuid'; 6 | 7 | import { IconSizes } from 'interfaces'; 8 | import { IconProps } from './types'; 9 | import { DEFAULT_FILL_COLOR } from './constants'; 10 | 11 | export const DownIcon: React.FC = ({ 12 | size = IconSizes.REGULAR, 13 | fill = DEFAULT_FILL_COLOR, 14 | }: IconProps) => { 15 | const id = `down_icon_${uuidv4()}`; 16 | 17 | return ( 18 | 19 | Down 20 | 21 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ); 34 | }; 35 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/SVGIcons/constants.ts: -------------------------------------------------------------------------------- 1 | export const DEFAULT_FILL_COLOR = '#9191A8'; // gray40 2 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/SVGIcons/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | export * from './types'; 5 | export * from './AlertIcon'; 6 | export * from './DownIcon'; 7 | export * from './UpIcon'; 8 | export * from './RightIcon'; 9 | export * from './LeftIcon'; 10 | export * from './InformationIcon'; 11 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/SVGIcons/types.ts: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | export interface IconProps { 5 | stroke?: string; 6 | size?: number; 7 | fill?: string; 8 | } 9 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/SearchBar/InlineSearchResults/ResultItemList/ResultItem/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import { Link } from 'react-router-dom'; 6 | 7 | export interface ResultItemProps { 8 | id: string; 9 | href: string; 10 | iconClass: string; 11 | onItemSelect: (event: MouseEvent) => void; 12 | subtitle: string; 13 | titleNode: React.ReactNode; 14 | type: string; 15 | } 16 | 17 | const ResultItem: React.FC = ({ 18 | href, 19 | iconClass, 20 | id, 21 | onItemSelect, 22 | subtitle, 23 | titleNode, 24 | type, 25 | }: ResultItemProps) => ( 26 |
  • 27 | 28 | 29 | 30 |
    31 |
    32 | {titleNode} 33 |
    {subtitle}
    34 |
    35 |
    36 | 37 |
    {type}
    38 | 39 |
  • 40 | ); 41 | 42 | export default ResultItem; 43 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/SearchBar/InlineSearchResults/constants.ts: -------------------------------------------------------------------------------- 1 | import { ResourceType } from 'interfaces/Resources'; 2 | import { getDisplayNameByResource } from 'config/config-utils'; 3 | 4 | export const DATASETS = getDisplayNameByResource(ResourceType.table); 5 | export const DATASETS_ITEM_TEXT = `in ${DATASETS}`; 6 | 7 | export const PEOPLE = getDisplayNameByResource(ResourceType.user); 8 | export const PEOPLE_ITEM_TEXT = `in ${PEOPLE}`; 9 | 10 | export const DASHBOARDS = getDisplayNameByResource(ResourceType.dashboard); 11 | export const DASHBOARD_ITEM_TEXT = `in ${DASHBOARDS}`; 12 | 13 | export const PEOPLE_USER_TYPE = 'User'; 14 | export const USER_ICON_CLASS = 'icon-users'; 15 | 16 | export const DASHBOARD_ICON_CLASS = 'icon-dashboard'; 17 | 18 | export const RESULT_LIST_FOOTER_PREFIX = 'See all'; 19 | export const RESULT_LIST_FOOTER_SUFFIX = 'results'; 20 | 21 | export const SEARCH_ITEM_NO_RESULTS = 'No results found'; 22 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/SearchBar/constants.ts: -------------------------------------------------------------------------------- 1 | // TODO: Hard-coded text strings should be translatable/customizable 2 | export const PLACEHOLDER_DEFAULT = 'Search for data resources...'; 3 | export const SEARCH_BUTTON_TEXT = 'Search'; 4 | export const BUTTON_CLOSE_TEXT = 'Close'; 5 | 6 | export const SIZE_SMALL = 'small'; 7 | 8 | export const INVALID_SYNTAX_MESSAGE = 9 | "Your search term contains invalid syntax ':'."; 10 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/ShimmeringResourceLoader/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | $shimmer-loader-lines: 1, 2; 7 | $shimmer-loader-text-height: 16px; 8 | $shimmer-loader-circle-size: 24px; 9 | $shimmer-loader-border-size: 1px; 10 | 11 | .shimmer-resource-loader-item { 12 | padding: $spacer-3; 13 | border-top: $shimmer-loader-border-size solid $stroke; 14 | border-bottom: $shimmer-loader-border-size solid $stroke; 15 | margin-bottom: -$shimmer-loader-border-size; 16 | margin-top: 0; 17 | 18 | & .media-left { 19 | padding-right: $spacer-2; 20 | } 21 | } 22 | 23 | .shimmer-resource-circle { 24 | height: $shimmer-loader-circle-size; 25 | width: $shimmer-loader-circle-size; 26 | border-radius: $shimmer-loader-circle-size; 27 | } 28 | 29 | .shimmer-resource-line { 30 | margin-bottom: $spacer-2; 31 | height: $shimmer-loader-text-height; 32 | 33 | &:last-child { 34 | margin-bottom: 0; 35 | } 36 | } 37 | 38 | .shimmer-resource-line--1 { 39 | width: 90%; 40 | } 41 | 42 | .shimmer-resource-line--2 { 43 | width: 75%; 44 | } 45 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/ShimmeringTagListLoader/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import * as times from 'lodash/times'; 6 | 7 | import './styles.scss'; 8 | 9 | const DEFAULT_REPETITION = 10; 10 | 11 | type ShimmeringTagItemProps = { 12 | index: number; 13 | }; 14 | 15 | export const ShimmeringTagItem: React.FC = ({ 16 | index, 17 | }: ShimmeringTagItemProps) => ( 18 | 21 | ); 22 | 23 | export interface ShimmeringTagListLoaderProps { 24 | numItems?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15; 25 | } 26 | 27 | const ShimmeringTagListLoader: React.FC = ({ 28 | numItems = DEFAULT_REPETITION, 29 | }: ShimmeringTagListLoaderProps) => ( 30 |
    31 | {times(numItems, (idx) => ( 32 | 33 | ))} 34 |
    35 | ); 36 | 37 | export default ShimmeringTagListLoader; 38 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/ShimmeringTagListLoader/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | $shimmer-loader-tag-height: 36px; 7 | $shimmer-loader-items: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14; 8 | $shimmer-loader-tag-width: 90; 9 | 10 | .shimmer-tag-loader-item { 11 | margin: 0 $spacer-1 $spacer-1 0; 12 | height: $shimmer-loader-tag-height; 13 | width: $shimmer-loader-tag-width + px; 14 | border-radius: $tag-border-radius; 15 | display: inline-block; 16 | } 17 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/StorySection/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import React, { ReactNode } from 'react'; 5 | 6 | type BlockProps = { 7 | children: ReactNode; 8 | title: string; 9 | text?: string | ReactNode; 10 | }; 11 | 12 | const StorySection: React.FC = ({ 13 | children, 14 | text, 15 | title, 16 | }: BlockProps) => ( 17 |
    18 |

    {title}

    19 | {text &&

    {text}

    } 20 |
    {children}
    21 |
    22 | ); 23 | 24 | export default StorySection; 25 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/TabsComponent/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import { Tab, Tabs } from 'react-bootstrap'; 6 | 7 | import './styles.scss'; 8 | 9 | export interface TabsProps { 10 | tabs: TabInfo[]; 11 | activeKey?: string; 12 | defaultTab?: string; 13 | onSelect?: (key: string) => void; 14 | } 15 | 16 | export interface TabInfo { 17 | content?: JSX.Element; 18 | key: string; 19 | title: string | JSX.Element; 20 | } 21 | 22 | const TabsComponent: React.FC = ({ 23 | tabs, 24 | activeKey, 25 | defaultTab, 26 | onSelect, 27 | }: TabsProps) => ( 28 | 35 | {tabs.map((tab) => ( 36 | 37 | {tab.content} 38 | 39 | ))} 40 | 41 | ); 42 | 43 | export default TabsComponent; 44 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Tags/TagInfo/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .btn.tag-button { 7 | background-color: $tag-bg; 8 | border: 0; 9 | border-radius: $tag-border-radius; 10 | color: $text-primary; 11 | margin: 0 8px 8px 0; 12 | overflow: hidden; 13 | padding: 8px; 14 | text-overflow: ellipsis; 15 | white-space: nowrap; 16 | 17 | &.compact { 18 | height: 30px; 19 | line-height: 14px; 20 | } 21 | 22 | &:hover, 23 | &:focus { 24 | background-color: $tag-bg-hover; 25 | color: $text-primary; 26 | } 27 | 28 | .tag-count { 29 | color: $text-secondary; 30 | margin-left: 8px; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Tags/TagInput/index.spec.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // TODO - Implement tests for TagInput 5 | 6 | describe('TagInput', () => { 7 | it('Placeholder test', () => {}); 8 | }); 9 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Tags/TagsList/constants.ts: -------------------------------------------------------------------------------- 1 | export const POPULAR_TAGS_TITLE = 'Popular Tags'; 2 | export const CURATED_TAGS_TITLE = 'Curated Tags'; 3 | export const OTHER_TAGS_TITLE = 'Other Tags'; 4 | export const BROWSE_TAGS_TITLE = 'Browse Tags'; 5 | export const BROWSE_MORE_TAGS_TEXT = 'Browse all tags'; 6 | export const BROWSE_PAGE_PATH = '/browse'; 7 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Tags/TagsList/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | @import 'typography'; 6 | 7 | $browse-tags-link-font-size: 16px; 8 | 9 | .header-hr { 10 | border: 2px solid $brand-color-4; 11 | } 12 | 13 | .tag-list-title { 14 | @extend %text-title-w1; 15 | 16 | margin-bottom: $spacer-2; 17 | } 18 | 19 | .tags-list { 20 | margin: 0 -4px; 21 | } 22 | 23 | .browse-tags-link { 24 | font-size: $browse-tags-link-font-size; 25 | text-decoration: none; 26 | display: block; 27 | margin-top: $spacer-1; 28 | 29 | &:link, 30 | &:visited, 31 | &:hover, 32 | &:active { 33 | text-decoration: none; 34 | } 35 | } 36 | 37 | .section-label { 38 | display: block; 39 | font-weight: $font-weight-body-regular; 40 | margin-top: $spacer-3; 41 | margin-bottom: $spacer-2; 42 | } 43 | -------------------------------------------------------------------------------- /amundsen_application/static/js/components/Tags/constants.ts: -------------------------------------------------------------------------------- 1 | export const POPULAR_TAGS_NUMBER = 20; 2 | -------------------------------------------------------------------------------- /amundsen_application/static/js/config/config-custom.ts: -------------------------------------------------------------------------------- 1 | // This file should be used to add new config variables or overwrite defaults from config-default.ts 2 | 3 | import { AppConfigCustom } from './config-types'; 4 | 5 | const configCustom: AppConfigCustom = { 6 | browse: { 7 | curatedTags: [], 8 | showAllTags: true, 9 | }, 10 | analytics: { 11 | plugins: [], 12 | }, 13 | mailClientFeatures: { 14 | feedbackEnabled: false, 15 | notificationsEnabled: false, 16 | }, 17 | indexDashboards: { 18 | enabled: false, 19 | }, 20 | indexUsers: { 21 | enabled: false, 22 | }, 23 | userIdLabel: 'email address', 24 | issueTracking: { 25 | enabled: false, 26 | }, 27 | }; 28 | 29 | export default configCustom; 30 | -------------------------------------------------------------------------------- /amundsen_application/static/js/config/config.ts: -------------------------------------------------------------------------------- 1 | import { AppConfig } from './config-types'; 2 | import configDefault from './config-default'; 3 | import configCustom from './config-custom'; 4 | 5 | // This is not a shallow merge. Any defined members of customConfig will override configDefault. 6 | const appConfig: AppConfig = { ...configDefault, ...configCustom }; 7 | 8 | export default appConfig; 9 | -------------------------------------------------------------------------------- /amundsen_application/static/js/constants.ts: -------------------------------------------------------------------------------- 1 | /* This file should contain any constants shared across multiple components */ 2 | export const NO_TIMESTAMP_TEXT = 'No timestamp available'; 3 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/announcements/api/v0.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosResponse } from 'axios'; 2 | 3 | import { AnnouncementPost } from 'interfaces'; 4 | 5 | export type AnnouncementsAPI = { 6 | msg: string; 7 | posts: AnnouncementPost[]; 8 | }; 9 | 10 | const SERVER_ERROR_CODE = 500; 11 | 12 | export function getAnnouncements() { 13 | return axios({ 14 | method: 'get', 15 | url: '/api/announcements/v0/', 16 | }) 17 | .then((response: AxiosResponse) => { 18 | const { data, status } = response; 19 | 20 | return { 21 | posts: data.posts, 22 | statusCode: status, 23 | }; 24 | }) 25 | .catch((e) => { 26 | const { response } = e; 27 | const statusCode = response 28 | ? response.status || SERVER_ERROR_CODE 29 | : SERVER_ERROR_CODE; 30 | 31 | return Promise.reject({ 32 | posts: [], 33 | statusCode, 34 | }); 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/announcements/sagas.ts: -------------------------------------------------------------------------------- 1 | import { SagaIterator } from 'redux-saga'; 2 | import { call, put, takeEvery } from 'redux-saga/effects'; 3 | 4 | import * as API from './api/v0'; 5 | import { getAnnouncementsFailure, getAnnouncementsSuccess } from '.'; 6 | import { GetAnnouncements } from './types'; 7 | 8 | export function* getAnnouncementsWorker(): SagaIterator { 9 | try { 10 | const response = yield call(API.getAnnouncements); 11 | 12 | yield put(getAnnouncementsSuccess(response)); 13 | } catch (error) { 14 | yield put(getAnnouncementsFailure(error)); 15 | } 16 | } 17 | export function* getAnnouncementsWatcher(): SagaIterator { 18 | yield takeEvery(GetAnnouncements.REQUEST, getAnnouncementsWorker); 19 | } 20 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/announcements/types.ts: -------------------------------------------------------------------------------- 1 | import { AnnouncementPost } from 'interfaces'; 2 | 3 | export enum GetAnnouncements { 4 | REQUEST = 'amundsen/announcements/GET_REQUEST', 5 | SUCCESS = 'amundsen/announcements/GET_SUCCESS', 6 | FAILURE = 'amundsen/announcements/GET_FAILURE', 7 | } 8 | 9 | export interface GetAnnouncementsRequest { 10 | type: GetAnnouncements.REQUEST; 11 | } 12 | 13 | export interface GetAnnouncementsResponse { 14 | type: GetAnnouncements.SUCCESS | GetAnnouncements.FAILURE; 15 | payload: GetAnnouncementsPayload; 16 | } 17 | 18 | export interface GetAnnouncementsPayload { 19 | posts?: AnnouncementPost[]; 20 | statusCode?: number; 21 | } 22 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/bookmark/api/v0.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosResponse } from 'axios'; 2 | 3 | import { ResourceType } from 'interfaces'; 4 | 5 | export const API_PATH = '/api/metadata/v0'; 6 | // TODO - Consider moving 'Bookmarks' under 'User' 7 | // TODO: Define types for the AxiosResponse data 8 | 9 | export function addBookmark(resourceKey: string, resourceType: ResourceType) { 10 | return axios 11 | .put(`${API_PATH}/user/bookmark`, { type: resourceType, key: resourceKey }) 12 | .then((response: AxiosResponse) => response.data); 13 | } 14 | 15 | export function removeBookmark( 16 | resourceKey: string, 17 | resourceType: ResourceType 18 | ) { 19 | return axios 20 | .delete(`${API_PATH}/user/bookmark`, { 21 | data: { type: resourceType, key: resourceKey }, 22 | }) 23 | .then((response: AxiosResponse) => response.data); 24 | } 25 | 26 | export function getBookmarks(userId?: string) { 27 | return axios 28 | .get(`${API_PATH}/user/bookmark` + (userId ? `?user_id=${userId}` : '')) 29 | .then((response: AxiosResponse) => response.data); 30 | } 31 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/dashboard/sagas.ts: -------------------------------------------------------------------------------- 1 | import { SagaIterator } from 'redux-saga'; 2 | import { call, put, takeEvery } from 'redux-saga/effects'; 3 | 4 | import * as API from './api/v0'; 5 | import { getDashboardSuccess, getDashboardFailure } from './reducer'; 6 | import { GetDashboard } from './types'; 7 | 8 | export function* getDashboardWorker(action): SagaIterator { 9 | try { 10 | const { uri, searchIndex, source } = action.payload; 11 | const response = yield call(API.getDashboard, uri, searchIndex, source); 12 | 13 | yield put(getDashboardSuccess(response)); 14 | } catch (error) { 15 | yield put(getDashboardFailure(error)); 16 | } 17 | } 18 | 19 | export function* getDashboardWatcher(): SagaIterator { 20 | yield takeEvery(GetDashboard.REQUEST, getDashboardWorker); 21 | } 22 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/dashboard/types.ts: -------------------------------------------------------------------------------- 1 | import { DashboardMetadata } from 'interfaces/Dashboard'; 2 | 3 | export enum GetDashboard { 4 | REQUEST = 'amundsen/dashboard/GET_DASHBOARD_REQUEST', 5 | SUCCESS = 'amundsen/dashboard/GET_DASHBOARD_SUCCESS', 6 | FAILURE = 'amundsen/dashboard/GET_DASHBOARD_FAILURE', 7 | } 8 | 9 | export interface GetDashboardRequest { 10 | type: GetDashboard.REQUEST; 11 | payload: { 12 | uri: string; 13 | searchIndex?: string; 14 | source?: string; 15 | }; 16 | } 17 | 18 | export interface GetDashboardResponse { 19 | type: GetDashboard.SUCCESS | GetDashboard.FAILURE; 20 | payload: GetDashboardPayload; 21 | } 22 | 23 | export interface GetDashboardPayload { 24 | dashboard?: DashboardMetadata; 25 | statusCode?: number; 26 | statusMessage?: string; 27 | } 28 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/feedback/api/tests/index.spec.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | import * as API from '../v0'; 4 | 5 | jest.mock('axios'); 6 | 7 | describe('submitFeedback', () => { 8 | let formData: FormData; 9 | beforeAll(() => { 10 | formData = new FormData(); 11 | API.submitFeedback(formData); 12 | }); 13 | 14 | it('calls axios with expected payload', () => { 15 | expect(axios).toHaveBeenCalledWith({ 16 | data: formData, 17 | method: 'post', 18 | url: '/api/mail/v0/feedback', 19 | headers: { 'Content-Type': 'multipart/form-data' }, 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/feedback/api/v0.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export function submitFeedback(data: FormData) { 4 | return axios({ 5 | data, 6 | method: 'post', 7 | url: '/api/mail/v0/feedback', 8 | headers: { 'Content-Type': 'multipart/form-data' }, 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/feedback/sagas.ts: -------------------------------------------------------------------------------- 1 | import { SagaIterator } from 'redux-saga'; 2 | import { call, delay, put, takeEvery } from 'redux-saga/effects'; 3 | 4 | import * as API from './api/v0'; 5 | import { 6 | submitFeedbackFailure, 7 | submitFeedbackSuccess, 8 | resetFeedback, 9 | } from './reducer'; 10 | import { SubmitFeedback, SubmitFeedbackRequest } from './types'; 11 | 12 | export function* submitFeedbackWorker( 13 | action: SubmitFeedbackRequest 14 | ): SagaIterator { 15 | try { 16 | yield call(API.submitFeedback, action.payload.data); 17 | yield put(submitFeedbackSuccess()); 18 | 19 | yield delay(2000); 20 | yield put(resetFeedback()); 21 | } catch (error) { 22 | yield put(submitFeedbackFailure()); 23 | 24 | yield delay(2000); 25 | yield put(resetFeedback()); 26 | } 27 | } 28 | 29 | export function* submitFeedbackWatcher(): SagaIterator { 30 | yield takeEvery(SubmitFeedback.REQUEST, submitFeedbackWorker); 31 | } 32 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/feedback/types.ts: -------------------------------------------------------------------------------- 1 | export enum SubmitFeedback { 2 | REQUEST = 'amundsen/feedback/SUBMIT_FEEDBACK_REQUEST', 3 | SUCCESS = 'amundsen/feedback/SUBMIT_FEEDBACK_SUCCESS', 4 | FAILURE = 'amundsen/feedback/SUBMIT_FEEDBACK_FAILURE', 5 | } 6 | export interface SubmitFeedbackRequest { 7 | type: SubmitFeedback.REQUEST; 8 | payload: { 9 | data: FormData; 10 | }; 11 | } 12 | export interface SubmitFeedbackResponse { 13 | type: SubmitFeedback.SUCCESS | SubmitFeedback.FAILURE; 14 | } 15 | 16 | export enum ResetFeedback { 17 | REQUEST = 'amundsen/feedback/RESET_FEEDBACK_REQUEST', 18 | } 19 | export interface ResetFeedbackRequest { 20 | type: ResetFeedback.REQUEST; 21 | } 22 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/issue/types.ts: -------------------------------------------------------------------------------- 1 | import { Issue, CreateIssuePayload, NotificationPayload } from 'interfaces'; 2 | 3 | export enum GetIssues { 4 | REQUEST = 'amundsen/issue/GET_ISSUES_REQUEST', 5 | SUCCESS = 'amundsen/issue/GET_ISSUES_SUCCESS', 6 | FAILURE = 'amundsen/issue/GET_ISSUES_FAILURE', 7 | } 8 | 9 | export enum CreateIssue { 10 | REQUEST = 'amundsen/issue/CREATE_ISSUE_REQUEST', 11 | SUCCESS = 'amundsen/issue/CREATE_ISSUE_SUCCESS', 12 | FAILURE = 'amundsen/issue/CREATE_ISSUE_FAILURE', 13 | } 14 | 15 | export interface GetIssuesRequest { 16 | type: GetIssues.REQUEST; 17 | payload: { 18 | key: string; 19 | }; 20 | } 21 | export interface CreateIssueRequest { 22 | type: CreateIssue.REQUEST; 23 | payload: { 24 | createIssuePayload: CreateIssuePayload; 25 | notificationPayload: NotificationPayload; 26 | }; 27 | } 28 | 29 | export interface GetIssuesResponse { 30 | type: GetIssues.SUCCESS | GetIssues.FAILURE; 31 | payload: { 32 | issues: Issue[]; 33 | total?: number; 34 | allIssuesUrl?: string; 35 | }; 36 | } 37 | 38 | export interface CreateIssueResponse { 39 | type: CreateIssue.SUCCESS | CreateIssue.FAILURE; 40 | payload: { 41 | issue?: Issue; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/lastIndexed/api/v0.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosResponse } from 'axios'; 2 | 3 | export const API_PATH = '/api/metadata/v0'; 4 | 5 | type MessageAPI = { msg: string }; 6 | 7 | export type LastIndexedAPI = { timestamp: string } & MessageAPI; 8 | 9 | export function getLastIndexed() { 10 | return axios 11 | .get(`${API_PATH}/get_last_indexed`) 12 | .then((response: AxiosResponse) => { 13 | const { data } = response; 14 | 15 | return data.timestamp; 16 | }) 17 | .catch(() => { 18 | const timestamp = null; 19 | return Promise.reject({ 20 | timestamp, 21 | }); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/lastIndexed/sagas.ts: -------------------------------------------------------------------------------- 1 | import { SagaIterator } from 'redux-saga'; 2 | import { call, put, takeEvery } from 'redux-saga/effects'; 3 | import * as API from 'ducks/lastIndexed/api/v0'; 4 | import { getLastIndexedFailure, getLastIndexedSuccess } from './reducer'; 5 | import { GetLastIndexed, GetLastIndexedRequest } from './types'; 6 | 7 | export function* getLastIndexedWorker( 8 | action: GetLastIndexedRequest 9 | ): SagaIterator { 10 | try { 11 | const lastIndexed = yield call(API.getLastIndexed); 12 | if (lastIndexed) { 13 | yield put(getLastIndexedSuccess(lastIndexed)); 14 | } else { 15 | yield put(getLastIndexedFailure()); 16 | } 17 | } catch (e) { 18 | yield put(getLastIndexedFailure()); 19 | } 20 | } 21 | export function* getLastIndexedWatcher(): SagaIterator { 22 | yield takeEvery(GetLastIndexed.REQUEST, getLastIndexedWorker); 23 | } 24 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/lastIndexed/types.ts: -------------------------------------------------------------------------------- 1 | export enum GetLastIndexed { 2 | REQUEST = 'amundsen/GET_LAST_UPDATED_REQUEST', 3 | SUCCESS = 'amundsen/GET_LAST_UPDATED_SUCCESS', 4 | FAILURE = 'amundsen/GET_LAST_UPDATED_FAILURE', 5 | } 6 | export interface GetLastIndexedRequest { 7 | type: GetLastIndexed.REQUEST; 8 | } 9 | export interface GetLastIndexedResponse { 10 | type: GetLastIndexed.SUCCESS | GetLastIndexed.FAILURE; 11 | payload?: GetLastIndexedPayload; 12 | } 13 | 14 | export interface GetLastIndexedPayload { 15 | lastIndexedEpoch?: number; 16 | } 17 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/log/api/tests/index.spec.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | import * as API from '../v0'; 4 | 5 | jest.mock('axios'); 6 | 7 | describe('postActionLog', () => { 8 | let axiosMock; 9 | let params: API.ActionLogParams; 10 | beforeAll(() => { 11 | axiosMock = jest 12 | .spyOn(axios, 'post') 13 | .mockImplementation(() => Promise.resolve()); 14 | params = { 15 | command: 'test', 16 | }; 17 | API.postActionLog(params); 18 | }); 19 | 20 | it('calls axios with expected parameters', () => { 21 | expect(axiosMock).toHaveBeenCalledWith(API.BASE_URL, params); 22 | }); 23 | 24 | afterAll(() => { 25 | axiosMock.mockClear(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/log/api/v0.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export interface ActionLogParams { 4 | command: string; 5 | target_id?: string; 6 | target_type?: string; 7 | label?: string; 8 | location?: string; 9 | value?: string; 10 | } 11 | 12 | export interface ClickLogParams { 13 | target_id?: string; 14 | target_type?: string; 15 | label?: string; 16 | value?: string; 17 | } 18 | 19 | export const BASE_URL = '/api/log/v0/log_event'; 20 | 21 | /* TODO: Consider what we want to do on success/failure, if anything */ 22 | export function postActionLog(params: ActionLogParams) { 23 | axios.post(BASE_URL, params); 24 | } 25 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/middlewares/analyticsMiddleware.ts: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import { Middleware } from 'redux'; 5 | 6 | import { trackEvent } from 'utils/analytics'; 7 | import { RootState } from '../rootReducer'; 8 | 9 | export const analyticsMiddleware: Middleware< 10 | {}, // legacy type parameter added to satisfy interface signature 11 | RootState 12 | > = ({ getState }) => (next) => (action) => { 13 | const result = next(action); 14 | 15 | // Intercept actions with meta analytics 16 | if (!action.meta || !action.meta.analytics) { 17 | return result; 18 | } 19 | 20 | const { name, payload } = action.meta.analytics; 21 | trackEvent(name, payload); 22 | 23 | return result; 24 | }; 25 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/middlewares/index.ts: -------------------------------------------------------------------------------- 1 | export * from './analyticsMiddleware'; 2 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/notification/api/tests/index.spec.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | import { NotificationType } from 'interfaces'; 4 | import * as API from '../v0'; 5 | 6 | jest.mock('axios'); 7 | 8 | describe('sendNotification', () => { 9 | it('calls axios with the correct params', async () => { 10 | const testRecipients = ['user1@test.com']; 11 | const testSender = 'user2@test.com'; 12 | const testNotificationType = NotificationType.OWNER_ADDED; 13 | const testOptions = { 14 | resource_name: 'testResource', 15 | resource_path: '/testResource', 16 | description_requested: false, 17 | fields_requested: false, 18 | }; 19 | API.sendNotification( 20 | testRecipients, 21 | testSender, 22 | testNotificationType, 23 | testOptions 24 | ); 25 | expect(axios).toHaveBeenCalledWith({ 26 | data: { 27 | notificationType: testNotificationType, 28 | options: testOptions, 29 | recipients: testRecipients, 30 | sender: testSender, 31 | }, 32 | method: 'post', 33 | url: `/api/mail/v0/notification`, 34 | }); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/notification/api/v0.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { NotificationType, SendNotificationOptions } from 'interfaces'; 3 | 4 | export function sendNotification( 5 | recipients: Array, 6 | sender: string, 7 | notificationType: NotificationType, 8 | options?: SendNotificationOptions 9 | ) { 10 | return axios({ 11 | data: { 12 | notificationType, 13 | options, 14 | recipients, 15 | sender, 16 | }, 17 | method: 'post', 18 | url: `/api/mail/v0/notification`, 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/notification/sagas.ts: -------------------------------------------------------------------------------- 1 | import { SagaIterator } from 'redux-saga'; 2 | import { call, put, takeEvery } from 'redux-saga/effects'; 3 | import { sendNotification } from './api/v0'; 4 | 5 | import { 6 | submitNotificationFailure, 7 | submitNotificationSuccess, 8 | } from './reducer'; 9 | import { SubmitNotification, SubmitNotificationRequest } from './types'; 10 | 11 | export function* submitNotificationWorker( 12 | action: SubmitNotificationRequest 13 | ): SagaIterator { 14 | try { 15 | const { notificationType, options, recipients, sender } = action.payload; 16 | yield call(sendNotification, recipients, sender, notificationType, options); 17 | yield put(submitNotificationSuccess()); 18 | } catch (error) { 19 | yield put(submitNotificationFailure()); 20 | } 21 | } 22 | 23 | export function* submitNotificationWatcher(): SagaIterator { 24 | yield takeEvery(SubmitNotification.REQUEST, submitNotificationWorker); 25 | } 26 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/notification/types.ts: -------------------------------------------------------------------------------- 1 | import { 2 | NotificationType, 3 | RequestMetadataType, 4 | SendNotificationOptions, 5 | } from 'interfaces'; 6 | 7 | export enum SubmitNotification { 8 | REQUEST = 'amundsen/notification/SUBMIT_NOTIFICATION_REQUEST', 9 | SUCCESS = 'amundsen/notification/SUBMIT_NOTIFICATION_SUCCESS', 10 | FAILURE = 'amundsen/notification/SUBMIT_NOTIFICATION_FAILURE', 11 | } 12 | 13 | export interface SubmitNotificationRequest { 14 | type: SubmitNotification.REQUEST; 15 | payload: { 16 | recipients: string[]; 17 | sender: string; 18 | notificationType: NotificationType; 19 | options?: SendNotificationOptions; 20 | }; 21 | } 22 | export interface SubmitNotificationResponse { 23 | type: SubmitNotification.SUCCESS | SubmitNotification.FAILURE; 24 | } 25 | 26 | export enum ToggleRequest { 27 | OPEN = 'open', 28 | CLOSE = 'close', 29 | } 30 | 31 | export interface OpenRequestAction { 32 | type: ToggleRequest.OPEN; 33 | payload: { 34 | columnName?: string; 35 | requestMetadataType: RequestMetadataType; 36 | }; 37 | } 38 | 39 | export interface CloseRequestAction { 40 | type: ToggleRequest.CLOSE; 41 | } 42 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/popularTables/api/tests/index.spec.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosResponse } from 'axios'; 2 | 3 | import globalState from 'fixtures/globalState'; 4 | 5 | import { TableResource } from 'interfaces'; 6 | 7 | import * as API from '../v0'; 8 | 9 | jest.mock('axios'); 10 | 11 | describe('getPopularTables', () => { 12 | let expectedTables: TableResource[]; 13 | let mockGetResponse: AxiosResponse; 14 | 15 | beforeAll(() => { 16 | expectedTables = globalState.popularTables.popularTables; 17 | mockGetResponse = { 18 | data: { 19 | results: expectedTables, 20 | msg: 'Success', 21 | }, 22 | status: 200, 23 | statusText: '', 24 | headers: {}, 25 | config: {}, 26 | }; 27 | jest 28 | .spyOn(axios, 'get') 29 | .mockImplementation(() => Promise.resolve(mockGetResponse)); 30 | }); 31 | 32 | it('resolves with array of table resources from response.data on success', async () => { 33 | expect.assertions(1); 34 | await API.getPopularTables().then((results) => { 35 | expect(results).toEqual(expectedTables); 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/popularTables/api/v0.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosResponse } from 'axios'; 2 | 3 | import { TableResource } from 'interfaces'; 4 | 5 | export type PopularTablesAPI = { 6 | msg: string; 7 | results: TableResource[]; 8 | }; 9 | 10 | export function getPopularTables() { 11 | return axios 12 | .get('/api/metadata/v0/popular_tables') 13 | .then((response: AxiosResponse) => response.data.results); 14 | } 15 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/popularTables/sagas.ts: -------------------------------------------------------------------------------- 1 | import { SagaIterator } from 'redux-saga'; 2 | import { call, put, takeEvery } from 'redux-saga/effects'; 3 | 4 | import * as API from './api/v0'; 5 | import { getPopularTablesFailure, getPopularTablesSuccess } from './reducer'; 6 | import { GetPopularTables } from './types'; 7 | 8 | export function* getPopularTablesWorker(): SagaIterator { 9 | try { 10 | const popularTables = yield call(API.getPopularTables); 11 | yield put(getPopularTablesSuccess(popularTables)); 12 | } catch (e) { 13 | yield put(getPopularTablesFailure()); 14 | } 15 | } 16 | 17 | export function* getPopularTablesWatcher(): SagaIterator { 18 | yield takeEvery(GetPopularTables.REQUEST, getPopularTablesWorker); 19 | } 20 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/popularTables/types.ts: -------------------------------------------------------------------------------- 1 | import { TableResource } from 'interfaces'; 2 | 3 | export enum GetPopularTables { 4 | REQUEST = 'amundsen/popularTables/GET_POPULAR_TABLES_REQUEST', 5 | SUCCESS = 'amundsen/popularTables/GET_POPULAR_TABLES_SUCCESS', 6 | FAILURE = 'amundsen/popularTables/GET_POPULAR_TABLES_FAILURE', 7 | } 8 | export interface GetPopularTablesRequest { 9 | type: GetPopularTables.REQUEST; 10 | } 11 | export interface GetPopularTablesResponse { 12 | type: GetPopularTables.SUCCESS | GetPopularTables.FAILURE; 13 | payload: { 14 | tables: TableResource[]; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/tags/api/tests/index.spec.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosResponse } from 'axios'; 2 | 3 | import { Tag } from 'interfaces'; 4 | 5 | import * as API from '../v0'; 6 | 7 | describe('getAllTags', () => { 8 | it('resolves with array of sorted result of response.data.tags on success', async () => { 9 | const rawTags: Tag[] = [ 10 | { tag_count: 2, tag_name: 'test' }, 11 | { tag_count: 1, tag_name: 'atest' }, 12 | ]; 13 | const expectedTags: Tag[] = [ 14 | { tag_count: 1, tag_name: 'atest' }, 15 | { tag_count: 2, tag_name: 'test' }, 16 | ]; 17 | const mockResponse: AxiosResponse = { 18 | data: { 19 | tags: rawTags, 20 | msg: 'Success', 21 | }, 22 | status: 200, 23 | statusText: '', 24 | headers: {}, 25 | config: {}, 26 | }; 27 | 28 | jest 29 | .spyOn(axios, 'get') 30 | .mockImplementation(() => Promise.resolve(mockResponse)); 31 | 32 | expect.assertions(1); 33 | 34 | await API.getAllTags().then((sortedTags) => { 35 | expect(sortedTags).toEqual(expectedTags); 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/tags/types.ts: -------------------------------------------------------------------------------- 1 | import { ResourceType, Tag, UpdateTagData } from 'interfaces'; 2 | 3 | export enum GetAllTags { 4 | REQUEST = 'amundsen/allTags/GET_REQUEST', 5 | SUCCESS = 'amundsen/allTags/GET_SUCCESS', 6 | FAILURE = 'amundsen/allTags/GET_FAILURE', 7 | } 8 | export interface GetAllTagsRequest { 9 | type: GetAllTags.REQUEST; 10 | } 11 | export interface GetAllTagsResponse { 12 | type: GetAllTags.SUCCESS | GetAllTags.FAILURE; 13 | payload: { 14 | allTags: Tag[]; 15 | }; 16 | } 17 | 18 | export enum UpdateTags { 19 | REQUEST = 'amundsen/tags/UPDATE_TAGS_REQUEST', 20 | SUCCESS = 'amundsen/tags/UPDATE_TAGS_SUCCESS', 21 | FAILURE = 'amundsen/tags/UPDATE_TAGS_FAILURE', 22 | } 23 | export interface UpdateTagsRequest { 24 | type: UpdateTags.REQUEST; 25 | payload: { 26 | tagArray: UpdateTagData[]; 27 | resourceType: ResourceType; 28 | uriKey: string; 29 | }; 30 | } 31 | export interface UpdateTagsResponse { 32 | type: UpdateTags.SUCCESS | UpdateTags.FAILURE; 33 | payload: { 34 | tags: Tag[]; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/ui/index.spec.ts: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import reducer, { pageViewed, pageViewActionType, UIReducerState } from '.'; 5 | 6 | describe('UI ducks', () => { 7 | describe('actions', () => { 8 | describe('pageViewed', () => { 9 | it('returns the action to track a page view', () => { 10 | const expected = '/testURL'; 11 | const action = pageViewed(expected); 12 | const { type, meta } = action; 13 | 14 | expect(type).toEqual(pageViewActionType); 15 | expect(meta.analytics.name).toEqual(pageViewActionType); 16 | expect(meta.analytics.payload.category).toEqual('pageView'); 17 | expect(meta.analytics.payload.label).toEqual(expected); 18 | }); 19 | }); 20 | }); 21 | 22 | describe('reducer', () => { 23 | const testState: UIReducerState = {}; 24 | 25 | describe('when pageViewed is triggered', () => { 26 | it('should return the existing state', () => { 27 | const expected = testState; 28 | const actual = reducer(testState, pageViewed('/testURL')); 29 | 30 | expect(actual).toEqual(expected); 31 | }); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/ui/index.ts: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | export const pageViewActionType = 'analytics/pageView'; 5 | 6 | // Actions 7 | export function pageViewed(path: string) { 8 | return { 9 | type: pageViewActionType, 10 | meta: { 11 | analytics: { 12 | name: pageViewActionType, 13 | payload: { 14 | category: 'pageView', 15 | label: `${path}`, 16 | }, 17 | }, 18 | }, 19 | }; 20 | } 21 | 22 | // Reducer 23 | export interface UIReducerState {} 24 | 25 | export const initialState: UIReducerState = {}; 26 | 27 | export default function reducer( 28 | state: UIReducerState = initialState, 29 | action 30 | ): UIReducerState { 31 | switch (action.type) { 32 | case pageViewActionType: { 33 | return state; 34 | } 35 | default: 36 | return state; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /amundsen_application/static/js/ducks/utilMethods.ts: -------------------------------------------------------------------------------- 1 | import { Tag } from 'interfaces'; 2 | 3 | export function sortTagsAlphabetical(a: Tag, b: Tag): number { 4 | return a.tag_name.localeCompare(b.tag_name); 5 | } 6 | 7 | export function extractFromObj( 8 | initialObj: object, 9 | desiredKeys: string[] 10 | ): object { 11 | return Object.keys(initialObj) 12 | .filter((key) => desiredKeys.indexOf(key) > -1) 13 | .reduce((obj, key) => { 14 | obj[key] = initialObj[key]; 15 | return obj; 16 | }, {}); 17 | } 18 | 19 | export function filterFromObj( 20 | initialObj: object, 21 | rejectedKeys: string[] 22 | ): object { 23 | return Object.keys(initialObj) 24 | .filter((key) => rejectedKeys.indexOf(key) === -1) 25 | .reduce((obj, key) => { 26 | obj[key] = initialObj[key]; 27 | return obj; 28 | }, {}); 29 | } 30 | -------------------------------------------------------------------------------- /amundsen_application/static/js/features/BadgeList/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import { bindActionCreators } from 'redux'; 6 | import { connect } from 'react-redux'; 7 | 8 | import { ResourceType, Badge } from 'interfaces'; 9 | 10 | import { updateSearchState } from 'ducks/search/reducer'; 11 | import { UpdateSearchStateRequest } from 'ducks/search/types'; 12 | 13 | import BadgeList from 'components/BadgeList'; 14 | 15 | export interface DispatchFromProps { 16 | onBadgeClick: (badgeText: string) => UpdateSearchStateRequest; 17 | } 18 | 19 | export interface BadgeListFeatureProps { 20 | badges: Badge[]; 21 | } 22 | 23 | export const mapDispatchToProps = (dispatch: any) => 24 | bindActionCreators( 25 | { 26 | onBadgeClick: (badgeText: string) => 27 | updateSearchState({ 28 | filters: { 29 | [ResourceType.table]: { badges: badgeText }, 30 | }, 31 | submitSearch: true, 32 | }), 33 | }, 34 | dispatch 35 | ); 36 | 37 | export default connect( 38 | null, 39 | mapDispatchToProps 40 | )(BadgeList); 41 | -------------------------------------------------------------------------------- /amundsen_application/static/js/features/ColumnList/ColumnLineage/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | @import 'typography'; 6 | 7 | $column-lineage-max-width: 800px; 8 | 9 | article.column-lineage-wrapper { 10 | margin-top: $spacer-3; 11 | display: flex; 12 | max-width: $column-lineage-max-width; 13 | 14 | .column-lineage-title { 15 | @extend %text-title-w3; 16 | 17 | color: $text-secondary; 18 | font-style: italic; 19 | margin-right: $spacer-2; 20 | } 21 | 22 | .column-lineage-list { 23 | flex-basis: 50%; 24 | flex-grow: 1; 25 | 26 | &:first-child { 27 | margin-right: $spacer-2; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /amundsen_application/static/js/features/ColumnList/ColumnLineageLoader/index.spec.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import { shallow } from 'enzyme'; 6 | 7 | import ColumnLineageLoader from '.'; 8 | 9 | const setup = () => { 10 | const wrapper = shallow(); 11 | 12 | return wrapper; 13 | }; 14 | 15 | describe('ColumnLineageLoader', () => { 16 | describe('render', () => { 17 | it('should render without errors', () => { 18 | expect(() => { 19 | setup(); 20 | }).not.toThrow(); 21 | }); 22 | 23 | it('should render two columns', () => { 24 | const expected = 2; 25 | const actual = setup().find('.shimmer-loader-column').length; 26 | 27 | expect(actual).toEqual(expected); 28 | }); 29 | 30 | it('should render four cells', () => { 31 | const expected = 4; 32 | const actual = setup().find('.shimmer-loader-cell').length; 33 | 34 | expect(actual).toEqual(expected); 35 | }); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /amundsen_application/static/js/features/ColumnList/ColumnLineageLoader/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | 6 | import './styles.scss'; 7 | 8 | const ColumnLineageLoader: React.FC = () => ( 9 |
    10 |
    11 |
    12 |
    13 |
    14 |
    15 |
    16 |
    17 |
    18 |
    19 | ); 20 | 21 | export default ColumnLineageLoader; 22 | -------------------------------------------------------------------------------- /amundsen_application/static/js/features/ColumnList/ColumnLineageLoader/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | $shimmer-height: 120px; 7 | $shimmer-block-spacing: $spacer-1; 8 | $shimmer-max-width: 800px; 9 | $shimmer-header-height: 24px; 10 | 11 | .column-lineage-loader { 12 | display: flex; 13 | height: $shimmer-height; 14 | margin-top: $shimmer-block-spacing; 15 | max-width: $shimmer-max-width; 16 | 17 | .shimmer-loader-column { 18 | display: flex; 19 | flex-basis: 45%; 20 | flex-direction: column; 21 | height: 100%; 22 | margin-right: $shimmer-block-spacing; 23 | 24 | &:last-child { 25 | margin-right: 0; 26 | } 27 | 28 | .shimmer-loader-cell { 29 | margin-bottom: $shimmer-block-spacing; 30 | 31 | &:last-child { 32 | margin-bottom: 0; 33 | } 34 | 35 | &.header { 36 | height: $shimmer-header-height; 37 | } 38 | 39 | &.content { 40 | height: ( 41 | $shimmer-height - $shimmer-header-height - $shimmer-block-spacing 42 | ); 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /amundsen_application/static/js/features/ColumnList/ColumnStats/columnStats.story.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import React from 'react'; 5 | import { storiesOf } from '@storybook/react'; 6 | 7 | import StorySection from 'components/StorySection'; 8 | import ColumnStats from '.'; 9 | 10 | import TestDataBuilder from './testDataBuilder'; 11 | 12 | const dataBuilder = new TestDataBuilder(); 13 | 14 | const { stats: fourStats } = dataBuilder.withFourStats().build(); 15 | const { stats: threeStats } = dataBuilder.withThreeStats().build(); 16 | const { stats: eightStats } = dataBuilder.withEightStats().build(); 17 | 18 | const stories = storiesOf('Components/ColumnStats', module); 19 | 20 | stories.add('Column Stats', () => ( 21 | <> 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | )); 33 | -------------------------------------------------------------------------------- /amundsen_application/static/js/features/ColumnList/constants.ts: -------------------------------------------------------------------------------- 1 | export const MORE_BUTTON_TEXT = 'More options'; 2 | export const REQUEST_DESCRIPTION_TEXT = 'Request Column Description'; 3 | export const EMPTY_MESSAGE = 'There are no available columns for this table'; 4 | export const EDITABLE_SECTION_TITLE = 'Description'; 5 | export const COLUMN_STATS_TITLE = 'Column Statistics'; 6 | export const COLUMN_LINEAGE_LIST_SIZE = 5; 7 | export const COLUMN_LINEAGE_DOWNSTREAM_TITLE = `Top ${COLUMN_LINEAGE_LIST_SIZE} Downstream Columns`; 8 | export const COLUMN_LINEAGE_UPSTREAM_TITLE = `Top ${COLUMN_LINEAGE_LIST_SIZE} Upstream Columns`; 9 | export const COLUMN_LINEAGE_MORE_TEXT = 'See More'; 10 | -------------------------------------------------------------------------------- /amundsen_application/static/js/features/Footer/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | $shimmer-loader-height: 20px; 7 | 8 | /* TODO: Not the greatest sticky footer implementation */ 9 | .footer { 10 | background-color: $white; 11 | border-top: 1px solid $stroke; 12 | bottom: 0; 13 | color: $text-secondary; 14 | font-size: 14px; 15 | height: $footer-height; 16 | left: 0; 17 | padding: 20px; 18 | position: fixed; 19 | text-align: center; 20 | width: 100%; 21 | z-index: 10; 22 | } 23 | 24 | .phantom-div { 25 | display: block; 26 | height: 48px; 27 | padding: 20px; 28 | width: 100%; 29 | } 30 | 31 | .shimmer-footer { 32 | height: $shimmer-loader-height; 33 | width: 100%; 34 | text-align: center; 35 | margin: 0 auto; 36 | } 37 | 38 | .shimmer-footer-row { 39 | height: $shimmer-loader-height - $spacer-1; 40 | display: inline-block; 41 | width: 33%; 42 | } 43 | -------------------------------------------------------------------------------- /amundsen_application/static/js/fixtures/metadata/users.ts: -------------------------------------------------------------------------------- 1 | import { PeopleUser } from 'interfaces/User'; 2 | 3 | export const activeUser0: PeopleUser = { 4 | manager_fullname: undefined, 5 | manager_email: undefined, 6 | profile_url: '/test0', 7 | role_name: undefined, 8 | display_name: '', 9 | github_username: '', 10 | team_name: '', 11 | last_name: '', 12 | full_name: '', 13 | slack_id: '', 14 | first_name: '', 15 | employee_type: '', 16 | is_active: true, 17 | email: 'user0@test.com', 18 | user_id: 'user0', 19 | }; 20 | 21 | export const activeUser1: PeopleUser = { 22 | manager_fullname: undefined, 23 | manager_email: undefined, 24 | profile_url: '/test1', 25 | role_name: undefined, 26 | display_name: '', 27 | github_username: '', 28 | team_name: '', 29 | last_name: '', 30 | full_name: '', 31 | slack_id: '', 32 | first_name: '', 33 | employee_type: '', 34 | is_active: true, 35 | email: 'user10@test.com', 36 | user_id: 'user1', 37 | }; 38 | -------------------------------------------------------------------------------- /amundsen_application/static/js/fixtures/mockRouter.ts: -------------------------------------------------------------------------------- 1 | import { RouteComponentProps } from 'react-router'; 2 | 3 | import * as History from 'history'; 4 | 5 | // Mock React-Router 6 | export function getMockRouterProps

    ( 7 | data: P, 8 | location: Partial = {} 9 | ): RouteComponentProps

    { 10 | const mockLocation: History.Location = { 11 | hash: '', 12 | key: '', 13 | pathname: '', 14 | search: '', 15 | state: {}, 16 | ...location, 17 | }; 18 | 19 | const props: RouteComponentProps

    = { 20 | match: { 21 | isExact: true, 22 | params: data, 23 | path: '', 24 | url: '', 25 | }, 26 | location: mockLocation, 27 | // This history object is a mock and `null`s many of the required methods. The 28 | // tests are designed not to trigger them, if they do, an error is expected. 29 | // So cast this as any. 30 | history: { 31 | length: 2, 32 | action: 'POP', 33 | location: mockLocation, 34 | push: null, 35 | replace: null, 36 | go: null, 37 | goBack: null, 38 | goForward: null, 39 | block: null, 40 | createHref: null, 41 | listen: null, 42 | }, 43 | staticContext: {}, 44 | }; 45 | 46 | return props; 47 | } 48 | -------------------------------------------------------------------------------- /amundsen_application/static/js/fixtures/search/filters.ts: -------------------------------------------------------------------------------- 1 | import { ResourceType } from 'interfaces'; 2 | 3 | export const defaultEmptyFilters = { 4 | [ResourceType.table]: {}, 5 | }; 6 | 7 | export const datasetFilterExample = { 8 | [ResourceType.table]: { 9 | schema: 'schema_name', 10 | database: { 11 | hive: true, 12 | }, 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /amundsen_application/static/js/interfaces/Analytics.ts: -------------------------------------------------------------------------------- 1 | export interface AnalyticsEvent { 2 | name: string; 3 | payload: { [prop: string]: unknown }; 4 | } 5 | -------------------------------------------------------------------------------- /amundsen_application/static/js/interfaces/Announcements.ts: -------------------------------------------------------------------------------- 1 | export interface AnnouncementPost { 2 | date: string; 3 | title: string; 4 | html_content: string; 5 | } 6 | -------------------------------------------------------------------------------- /amundsen_application/static/js/interfaces/Badges.ts: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | export interface Badge { 5 | badge_name?: string; 6 | category?: string; 7 | tag_name?: string; 8 | } 9 | -------------------------------------------------------------------------------- /amundsen_application/static/js/interfaces/Dashboard.ts: -------------------------------------------------------------------------------- 1 | import { User } from 'interfaces/User'; 2 | import { Tag } from 'interfaces/Tags'; 3 | import { Badge } from 'interfaces/Badges'; 4 | import { TableReader } from 'interfaces/TableMetadata'; 5 | import { TableResource, QueryResource } from 'interfaces/Resources'; 6 | 7 | export interface DashboardMetadata { 8 | badges: Badge[]; 9 | chart_names: string[]; 10 | cluster: string; 11 | created_timestamp: number; 12 | description: string; 13 | frequent_users: TableReader[]; 14 | group_name: string; 15 | group_url: string; 16 | last_run_state: string; 17 | last_run_timestamp: number | null; 18 | last_successful_run_timestamp: number | null; 19 | name: string; 20 | owners: User[]; 21 | product: string; 22 | queries: QueryResource[]; 23 | recent_view_count: number; 24 | tables: TableResource[]; 25 | tags: Tag[]; 26 | updated_timestamp: number; 27 | uri: string; 28 | url: string; 29 | } 30 | -------------------------------------------------------------------------------- /amundsen_application/static/js/interfaces/Feedback.ts: -------------------------------------------------------------------------------- 1 | export enum SendingState { 2 | ERROR = 'error', 3 | IDLE = 'idle', 4 | WAITING = 'waiting', 5 | COMPLETE = 'complete', 6 | } 7 | -------------------------------------------------------------------------------- /amundsen_application/static/js/interfaces/Issue.ts: -------------------------------------------------------------------------------- 1 | export interface Issue { 2 | issue_key: string; 3 | title: string; 4 | url: string; 5 | status: string; 6 | priority_name: string; 7 | priority_display_name: string; 8 | } 9 | 10 | export interface CreateIssuePayload { 11 | key: string; 12 | title: string; 13 | description: string; 14 | } 15 | -------------------------------------------------------------------------------- /amundsen_application/static/js/interfaces/Notifications.ts: -------------------------------------------------------------------------------- 1 | export enum NotificationType { 2 | OWNER_ADDED = 'owner_added', 3 | OWNER_REMOVED = 'owner_removed', 4 | METADATA_EDITED = 'metadata_edited', 5 | METADATA_REQUESTED = 'metadata_requested', 6 | DATA_ISSUE_REPORTED = 'data_issue_reported', 7 | } 8 | 9 | export enum RequestMetadataType { 10 | COLUMN_DESCRIPTION = 'columnDescriptionRequested', 11 | TABLE_DESCRIPTION = 'tableDescriptionRequested', 12 | } 13 | 14 | export interface SendNotificationOptions { 15 | resource_name: string; 16 | resource_path: string; 17 | description_requested?: boolean; 18 | fields_requested?: boolean; 19 | comment?: string; 20 | data_issue_url?: string; 21 | } 22 | 23 | export interface NotificationPayload { 24 | recipients: string[]; 25 | sender: string; 26 | notificationType: NotificationType; 27 | options: SendNotificationOptions; 28 | } 29 | -------------------------------------------------------------------------------- /amundsen_application/static/js/interfaces/Tags.ts: -------------------------------------------------------------------------------- 1 | import { UpdateMethod } from './Enums'; 2 | 3 | export interface UpdateTagData { 4 | methodName: UpdateMethod; 5 | tagName: string; 6 | } 7 | 8 | export enum TagType { 9 | TAG = 'default', 10 | } 11 | 12 | export interface Tag { 13 | tag_count?: number; 14 | tag_name: string; 15 | tag_type?: TagType.TAG; 16 | } 17 | -------------------------------------------------------------------------------- /amundsen_application/static/js/interfaces/User.ts: -------------------------------------------------------------------------------- 1 | export interface User { 2 | display_name: string; 3 | email: string; 4 | profile_url: string; 5 | user_id: string; 6 | } 7 | 8 | // Not a good name, not sure if we can consolidate yet 9 | // TODO: Change to User when ready. 10 | export interface PeopleUser { 11 | email: string; 12 | employee_type: string; 13 | display_name: string; 14 | first_name: string; 15 | full_name: string; 16 | github_username: string; 17 | is_active: boolean; 18 | last_name: string; 19 | // Inconsistent data format from search and metadata return either `manager_email` or `manager_fullname` 20 | manager_email?: string; 21 | manager_fullname?: string; 22 | profile_url: string; 23 | role_name?: string; 24 | slack_id: string; 25 | team_name: string; 26 | user_id: string; 27 | } 28 | 29 | export type LoggedInUser = PeopleUser & {}; 30 | 31 | export type OwnerDict = { [id: string]: User }; 32 | -------------------------------------------------------------------------------- /amundsen_application/static/js/interfaces/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Analytics'; 2 | export * from './Announcements'; 3 | export * from './Badges'; 4 | export * from './Enums'; 5 | export * from './Feedback'; 6 | export * from './Issue'; 7 | export * from './Notifications'; 8 | export * from './Resources'; 9 | export * from './TableMetadata'; 10 | export * from './Tags'; 11 | export * from './User'; 12 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/AnnouncementPage/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | @import 'typography'; 6 | 7 | .announcement-container hr { 8 | border: 2px solid $brand-color-4; 9 | } 10 | 11 | .announcement-header { 12 | @extend %text-title-w1; 13 | } 14 | 15 | .post-container { 16 | display: flex; 17 | flex-direction: row; 18 | margin-bottom: 32px; 19 | 20 | .post-header { 21 | border-right: 1px solid $stroke; 22 | padding-right: 16px; 23 | 24 | .post-title { 25 | width: 150px; 26 | } 27 | } 28 | 29 | .post-content { 30 | padding-left: 16px; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/BrowsePage/constants.ts: -------------------------------------------------------------------------------- 1 | export const BROWSE_PAGE_DOCUMENT_TITLE = 'Browse - Amundsen'; 2 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/BrowsePage/index.spec.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import * as DocumentTitle from 'react-document-title'; 6 | 7 | import { shallow } from 'enzyme'; 8 | 9 | import TagsListContainer from 'components/Tags'; 10 | import { BrowsePage } from '.'; 11 | 12 | describe('BrowsePage', () => { 13 | const setup = () => shallow(); 14 | let wrapper; 15 | 16 | beforeAll(() => { 17 | wrapper = setup(); 18 | }); 19 | 20 | describe('render', () => { 21 | it('renders DocumentTitle w/ correct title', () => { 22 | expect(wrapper.find(DocumentTitle).props().title).toEqual( 23 | 'Browse - Amundsen' 24 | ); 25 | }); 26 | 27 | it('renders


    ', () => { 28 | expect(wrapper.contains(
    )); 29 | }); 30 | 31 | it('contains TagsList', () => { 32 | const expected = 1; 33 | const actual = wrapper.find(TagsListContainer).length; 34 | expect(actual).toEqual(expected); 35 | }); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/BrowsePage/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import * as DocumentTitle from 'react-document-title'; 6 | 7 | import TagsListContainer from 'components/Tags'; 8 | 9 | import { BROWSE_PAGE_DOCUMENT_TITLE } from './constants'; 10 | 11 | import './styles.scss'; 12 | 13 | export class BrowsePage extends React.Component { 14 | render() { 15 | return ( 16 | /* TODO: add expand/collapse behavior */ 17 | 18 |
    19 |
    20 |
    21 | 22 |
    23 |
    24 |
    25 |
    26 | ); 27 | } 28 | } 29 | 30 | export default BrowsePage; 31 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/BrowsePage/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/DashboardPage/ChartList/index.spec.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | 6 | import { shallow } from 'enzyme'; 7 | 8 | import ChartList, { ChartListProps } from '.'; 9 | 10 | describe('ChartList', () => { 11 | const setup = (propOverrides?: Partial) => { 12 | const props = { 13 | charts: [], 14 | ...propOverrides, 15 | }; 16 | const wrapper = shallow(); 17 | return { props, wrapper }; 18 | }; 19 | 20 | describe('render', () => { 21 | it('returns null if no charts', () => { 22 | const { props, wrapper } = setup({ charts: [] }); 23 | expect(wrapper.type()).toEqual(null); 24 | }); 25 | 26 | it('returns a list item for each chart', () => { 27 | const { props, wrapper } = setup({ charts: ['chart1', 'chart2'] }); 28 | props.charts.forEach((item, index) => { 29 | expect(wrapper.find('li').at(index).text()).toBe(item); 30 | }); 31 | }); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/DashboardPage/ChartList/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | 6 | import './styles.scss'; 7 | 8 | export interface ChartListProps { 9 | charts: string[]; 10 | } 11 | 12 | class ChartList extends React.Component { 13 | render() { 14 | const { charts } = this.props; 15 | if (charts.length === 0) { 16 | return null; 17 | } 18 | 19 | return ( 20 |
      21 | {charts.map((chart, index) => ( 22 |
    • 23 |
      {chart}
      24 |
    • 25 | ))} 26 |
    27 | ); 28 | } 29 | } 30 | 31 | export default ChartList; 32 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/DashboardPage/ChartList/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | .chart-list.list-group { 5 | margin-bottom: 0; 6 | 7 | .chart-list-item.list-group-item { 8 | height: 70px; 9 | padding: 16px 24px; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/DashboardPage/ImagePreview/constants.ts: -------------------------------------------------------------------------------- 1 | export const ERROR_MESSAGE = 2 | 'Unable to load the dashboard preview image. \ 3 | Please view the dashboard at'; 4 | 5 | export const PREVIEW_BUTTON_TEXT = 'See Dashboard Preview'; 6 | export const PREVIEW_BASE = '/api/dashboard_preview/v0/dashboard'; 7 | export const PREVIEW_END = 'preview.jpg'; 8 | 9 | export const DASHBOARD_PREVIEW_MODAL_TITLE = 'Dashboard Preview'; 10 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/DashboardPage/ImagePreview/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | $max-modal-height: 87vh; 7 | 8 | .preview-button { 9 | border: none; 10 | padding: 0; 11 | 12 | &:hover img.preview { 13 | border: 1px solid $gray50; 14 | cursor: zoom-in; 15 | } 16 | } 17 | 18 | .image-preview { 19 | text-align: center; 20 | 21 | .loading-spinner { 22 | margin-top: 0; 23 | } 24 | 25 | .loading-error-text { 26 | text-align: center; 27 | } 28 | 29 | img.preview { 30 | border: 1px solid $stroke; 31 | } 32 | } 33 | 34 | .dashboard-preview-modal .modal-body { 35 | max-height: $max-modal-height; 36 | } 37 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/DashboardPage/QueryList/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import { QueryResource } from 'interfaces'; 6 | import QueryListItem from '../QueryListItem'; 7 | 8 | import './styles.scss'; 9 | 10 | export interface QueryListProps { 11 | product: string; 12 | queries: QueryResource[]; 13 | } 14 | 15 | class QueryList extends React.Component { 16 | render() { 17 | const { product, queries } = this.props; 18 | 19 | if (queries.length === 0) { 20 | return null; 21 | } 22 | 23 | const queryList = queries.map(({ name, query_text, url }) => ( 24 | 31 | )); 32 | 33 | return ( 34 |
      35 | {queryList} 36 |
    37 | ); 38 | } 39 | } 40 | 41 | export default QueryList; 42 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/DashboardPage/QueryList/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | $min-item-height: 54px; 7 | 8 | .query-list.list-group { 9 | margin-bottom: 0; 10 | } 11 | 12 | .query-list-item.list-group-item { 13 | min-height: $min-item-height; 14 | } 15 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/DashboardPage/QueryListItem/CodeBlock.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import { CopyBlock, atomOneLight } from 'react-code-blocks'; 6 | 7 | const LANGUAGE = 'sql'; 8 | 9 | type CodeBlockProps = { 10 | text: string; 11 | }; 12 | 13 | const CodeBlock: React.FC = ({ text }: CodeBlockProps) => ( 14 | 22 | ); 23 | 24 | export default CodeBlock; 25 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/DashboardPage/ShimmeringDashboardLoader/index.spec.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import { shallow } from 'enzyme'; 6 | 7 | import ShimmeringDashboardLoader from '.'; 8 | 9 | const setup = () => { 10 | const wrapper = shallow(); 11 | 12 | return wrapper; 13 | }; 14 | 15 | describe('ShimmeringDashboardLoader', () => { 16 | describe('render', () => { 17 | it('should render without errors', () => { 18 | expect(() => { 19 | setup(); 20 | }).not.toThrow(); 21 | }); 22 | 23 | it('should render three columns', () => { 24 | const expected = 3; 25 | const actual = setup().find('.shimmer-loader-column').length; 26 | 27 | expect(actual).toEqual(expected); 28 | }); 29 | 30 | it('should render six cells', () => { 31 | const expected = 6; 32 | const actual = setup().find('.shimmer-loader-cell').length; 33 | 34 | expect(actual).toEqual(expected); 35 | }); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/DashboardPage/ShimmeringDashboardLoader/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | 6 | import './styles.scss'; 7 | 8 | const ShimmeringDashboardLoader: React.FC = () => ( 9 |
    10 |
    11 |
    12 |
    13 |
    14 |
    15 |
    16 |
    17 |
    18 |
    19 |
    20 |
    21 |
    22 |
    23 | ); 24 | 25 | export default ShimmeringDashboardLoader; 26 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/DashboardPage/ShimmeringDashboardLoader/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | $shimmer-border-color: $gray20; 7 | $shimmer-height: 22vh; 8 | $shimmer-block-spacing: 16px; 9 | 10 | .dashboard-shimmer-loader { 11 | border: 1px solid $shimmer-border-color; 12 | display: flex; 13 | height: $shimmer-height; 14 | justify-content: space-around; 15 | padding: $shimmer-block-spacing; 16 | width: 100%; 17 | 18 | .shimmer-loader-column { 19 | display: flex; 20 | flex-basis: 33%; 21 | flex-direction: column; 22 | height: 100%; 23 | margin-right: $shimmer-block-spacing; 24 | 25 | &:last-child { 26 | margin-right: 0; 27 | } 28 | } 29 | 30 | .shimmer-loader-cell { 31 | margin-bottom: $shimmer-block-spacing; 32 | 33 | &:last-child { 34 | margin-bottom: 0; 35 | } 36 | 37 | &.simple { 38 | height: 40%; 39 | } 40 | 41 | &.double { 42 | height: 60%; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/DashboardPage/constants.ts: -------------------------------------------------------------------------------- 1 | export const TABLES_PER_PAGE = 10; 2 | export const DASHBOARD_SOURCE = 'dashboard_page'; 3 | 4 | export const OWNER_HEADER_TEXT = 'Owners'; 5 | 6 | export const ADD_DESC_TEXT = 'Add Description in'; 7 | export const EDIT_DESC_TEXT = 'Click to edit description in'; 8 | 9 | export const LAST_RUN_SUCCEEDED = 'succeeded'; 10 | export const STATUS_TEXT = 'Status:'; 11 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/DashboardPage/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | @import 'typography'; 6 | 7 | .dashboard-page { 8 | .left-panel .alert { 9 | margin-top: $spacer-4; 10 | margin-bottom: 0; 11 | } 12 | 13 | .header-section { 14 | .flag { 15 | margin: 0 $spacer-1; 16 | } 17 | } 18 | 19 | .header-title-text { 20 | @extend %text-headline-w2; 21 | } 22 | 23 | .edit-link { 24 | text-decoration: none; 25 | } 26 | 27 | .dashboard-group { 28 | margin-right: $spacer-3; 29 | } 30 | 31 | .last-run-state { 32 | margin-top: $spacer-1; 33 | 34 | .status { 35 | @extend %text-body-w2; 36 | 37 | display: inline-block; 38 | vertical-align: middle; 39 | } 40 | } 41 | 42 | .image-preview { 43 | margin-top: $spacer-1; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/HomePage/constants.ts: -------------------------------------------------------------------------------- 1 | export const SEARCH_BREADCRUMB_TEXT = 'Advanced Search'; 2 | export const HOMEPAGE_TITLE = 'Amundsen Homepage'; 3 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/HomePage/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .home-page { 7 | .home-element-container { 8 | margin-top: $spacer-4 * 2; 9 | } 10 | 11 | .filter-breadcrumb { 12 | margin-top: 4px; 13 | 14 | .amundsen-breadcrumb { 15 | margin-right: -$spacer-1; 16 | 17 | img.icon { 18 | margin-right: 0; 19 | } 20 | } 21 | } 22 | 23 | @media (max-width: $screen-sm-max) { 24 | .home-element-container { 25 | margin-top: 32px; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/NotFoundPage/index.spec.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import * as DocumentTitle from 'react-document-title'; 6 | 7 | import { shallow } from 'enzyme'; 8 | 9 | import Breadcrumb from 'components/Breadcrumb'; 10 | import NotFoundPage from '.'; 11 | 12 | describe('NotFoundPage', () => { 13 | let subject; 14 | beforeEach(() => { 15 | subject = shallow(); 16 | }); 17 | 18 | it('renders DocumentTitle w/ correct title', () => { 19 | expect(subject.find(DocumentTitle).props().title).toEqual( 20 | '404 Page Not Found - Amundsen' 21 | ); 22 | }); 23 | 24 | it('renders Breadcrumb to homepage', () => { 25 | expect(subject.find(Breadcrumb).props()).toMatchObject({ 26 | path: '/', 27 | text: 'Home', 28 | }); 29 | }); 30 | 31 | it('renders header correct text', () => { 32 | expect(subject.find('h1').text()).toEqual('404 Page Not Found'); 33 | }); 34 | 35 | it('renders image icon', () => { 36 | expect(subject.find('img').props()).toMatchObject({ 37 | className: 'icon icon-alert', 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/NotFoundPage/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import * as DocumentTitle from 'react-document-title'; 6 | 7 | // TODO: Use css-modules instead of 'import' 8 | import './styles.scss'; 9 | 10 | import Breadcrumb from 'components/Breadcrumb'; 11 | 12 | const NotFoundPage: React.FC = () => ( 13 | 14 |
    15 | 16 |

    404 Page Not Found

    17 | 18 |
    19 |
    20 | ); 21 | 22 | export default NotFoundPage; 23 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/NotFoundPage/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .not-found-page { 7 | h1 { 8 | text-align: center; 9 | } 10 | 11 | span { 12 | text-align: center; 13 | width: 100%; 14 | } 15 | } 16 | 17 | img.icon.icon-alert { 18 | background-color: $brand-primary; 19 | display: block; 20 | height: 200px; 21 | margin: auto; 22 | -webkit-mask-size: 100%; 23 | mask-size: 100%; 24 | width: 200px; 25 | } 26 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/ProfilePage/constants.ts: -------------------------------------------------------------------------------- 1 | export const AVATAR_SIZE = 40; 2 | 3 | export const BOOKMARKED_LABEL = 'bookmarked'; 4 | export const BOOKMARKED_SOURCE = 'profile_bookmark'; 5 | export const BOOKMARKED_TITLE_PREFIX = 'Bookmarked'; 6 | 7 | export const ITEMS_PER_PAGE = 3; 8 | 9 | export const OWNED_LABEL = 'owned'; 10 | export const OWNED_SOURCE = 'profile_own'; 11 | export const OWNED_TITLE_PREFIX = 'Owned'; 12 | 13 | export const READ_LABEL = 'frequently used'; 14 | export const READ_SOURCE = 'profile_read'; 15 | export const READ_TITLE_PREFIX = 'Frequently Used'; 16 | export const PROFILE_TEXT = 'Employee Profile'; 17 | export const GITHUB_LINK_TEXT = 'Github'; 18 | 19 | export const EMPTY_TEXT_PREFIX = 'User has no'; 20 | export const FOOTER_TEXT_PREFIX = 'View all'; 21 | 22 | export const NOT_ACTIVE_USER_TEXT = 'Alumni'; 23 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/SearchPage/SearchFilter/constants.ts: -------------------------------------------------------------------------------- 1 | export const APPLY_BTN_TEXT = 'Apply'; 2 | 3 | export const CLEAR_BTN_TEXT = 'Clear'; 4 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/SearchPage/SearchFilter/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .search-filter-section { 7 | &:not(:first-child) { 8 | margin-top: $spacer-3; 9 | } 10 | 11 | .search-filter-section-header { 12 | display: flex; 13 | } 14 | 15 | .search-filter-section-title { 16 | display: flex; 17 | flex-grow: 1; 18 | } 19 | 20 | .info-button { 21 | margin: auto 4px !important; 22 | } 23 | 24 | .search-filter-section-label { 25 | margin-bottom: 0; 26 | } 27 | 28 | .input-section-content { 29 | display: flex; 30 | 31 | button, 32 | input[type='text'] { 33 | margin-top: $spacer-1; 34 | } 35 | 36 | button { 37 | margin-left: $spacer-1; 38 | } 39 | 40 | input { 41 | min-width: 0; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/SearchPage/SearchPanel/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | 6 | import './styles.scss'; 7 | 8 | type SearchPanelProps = { 9 | children: React.ReactNode; 10 | }; 11 | 12 | const SearchPanel: React.FC = ({ children }: SearchPanelProps) => ( 13 | 20 | ); 21 | 22 | export default SearchPanel; 23 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/SearchPage/SearchPanel/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .search-control-panel { 7 | border-right: $search-panel-border-width solid $stroke; 8 | display: flex; 9 | flex: 0 0 $search-panel-width; 10 | flex-direction: column; 11 | overflow-y: auto; 12 | 13 | .section { 14 | padding: 32px 24px 32px 32px; 15 | width: $search-panel-width - $search-panel-border-width; 16 | 17 | &:not(:first-child) { 18 | border-top: 2px solid $stroke; 19 | } 20 | } 21 | 22 | .checkbox, 23 | .radio { 24 | margin-bottom: $spacer-1; 25 | margin-top: $spacer-1; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/SearchPage/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .search-page { 7 | display: flex; 8 | height: calc(100vh - #{$nav-bar-height + $footer-height}); 9 | 10 | .list-group { 11 | margin-top: 0; 12 | } 13 | 14 | .search-results { 15 | flex-grow: 1; 16 | width: 0; // Temporary hack since list-items use width % 17 | overflow-y: scroll; 18 | } 19 | 20 | @media (max-width: $screen-sm-max) { 21 | .search-error { 22 | margin-top: 16px; 23 | } 24 | } 25 | 26 | .search-error { 27 | margin-top: 32px; 28 | text-align: center; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/DataPreviewButton/constants.ts: -------------------------------------------------------------------------------- 1 | export const PREVIEW_COLUMN_MAX_LEN = 250; 2 | export const PREVIEW_COLUMN_MSG = 'Data Exceeds Render Limit'; 3 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/ExploreButton/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | 6 | import { TableMetadata } from 'interfaces'; 7 | import { exploreEnabled, generateExploreUrl } from 'config/config-utils'; 8 | import { logClick } from 'utils/analytics'; 9 | 10 | export interface ExploreButtonProps { 11 | tableData: TableMetadata; 12 | } 13 | 14 | class ExploreButton extends React.Component { 15 | render() { 16 | const url = generateExploreUrl(this.props.tableData); 17 | if (!url || !exploreEnabled()) { 18 | return null; 19 | } 20 | 21 | return ( 22 | 31 | Explore 32 | 33 | ); 34 | } 35 | } 36 | 37 | export default ExploreButton; 38 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/FrequentUsers/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .frequent-users .sb-avatar > div { 7 | border: 1px solid $btn-default-bg; 8 | } 9 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/LineageLink/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | 6 | import AvatarLabel from 'components/AvatarLabel'; 7 | import AppConfig from 'config/config'; 8 | import { TableMetadata } from 'interfaces/TableMetadata'; 9 | import { logClick } from 'utils/analytics'; 10 | 11 | export interface LineageLinkProps { 12 | tableData: TableMetadata; 13 | } 14 | 15 | const LineageLink: React.FC = ({ 16 | tableData, 17 | }: LineageLinkProps) => { 18 | const config = AppConfig.tableLineage; 19 | if (!config.isEnabled) return null; 20 | 21 | const { database, cluster, schema, name } = tableData; 22 | const href = config.urlGenerator(database, cluster, schema, name); 23 | if (!href) return null; 24 | 25 | const label = 'Lineage'; 26 | 27 | return ( 28 | 36 | 37 | 38 | ); 39 | }; 40 | 41 | export default LineageLink; 42 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/LineageList/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | 6 | import { ResourceType, TableResource } from 'interfaces/Resources'; 7 | import { LineageItem } from 'interfaces/TableMetadata'; 8 | import TableListItem from 'components/ResourceListItem/TableListItem'; 9 | 10 | export interface LineageListProps { 11 | items: LineageItem[]; 12 | } 13 | 14 | const LineageList: React.FC = ({ 15 | items, 16 | }: LineageListProps) => ( 17 |
    18 | {items.map((table, index) => { 19 | const logging = { 20 | index, 21 | source: 'table_lineage_list', 22 | }; 23 | const tableResource: TableResource = { 24 | ...table, 25 | type: ResourceType.table, 26 | description: '', 27 | }; 28 | return ; 29 | })} 30 |
    31 | ); 32 | export default LineageList; 33 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/ListSortingDropdown/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'typography'; 5 | 6 | .list-sorting-dropdown { 7 | .list-sorting-dropdown-button { 8 | border: 0; 9 | } 10 | 11 | .list-sorting-dropdown-menu { 12 | padding: $spacer-2; 13 | } 14 | 15 | .list-sorting-dropdown-menu-title { 16 | @extend %text-caption-w2; 17 | 18 | padding-bottom: $spacer-1; 19 | } 20 | 21 | .list-sorting-dropdown-menu-item { 22 | &:hover { 23 | cursor: pointer; 24 | } 25 | } 26 | 27 | .list-sorting-dropdown-menu-item-text { 28 | @extend %text-body-w3; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/ReportTableIssue/constants.ts: -------------------------------------------------------------------------------- 1 | export const REPORT_DATA_ISSUE_TEXT = 'Report an issue'; 2 | export const TABLE_OWNERS_NOTE = 3 | 'Please note: Table owners will also be notified via email when an issue is reported.'; 4 | export const CLOSE = 'Close'; 5 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/ReportTableIssue/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .report-table-issue-modal { 7 | background-color: $white; 8 | border-radius: 6px; 9 | bottom: 100px; 10 | box-shadow: 0 0 24px -2px rgba(0, 0, 0, 0.2); 11 | display: block; 12 | height: auto; 13 | left: 25px; 14 | min-height: 300px; 15 | padding: 32px; 16 | position: fixed; 17 | width: 400px; 18 | z-index: 6; 19 | 20 | .btn-close { 21 | position: absolute; 22 | right: 32px; 23 | top: 32px; 24 | } 25 | 26 | .data-owner-notification { 27 | font-size: 10px; 28 | margin: 5px 0 0; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/RequestDescriptionText/constants.ts: -------------------------------------------------------------------------------- 1 | export const REQUEST_DESCRIPTION = 'Request Description'; 2 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/RequestMetadataForm/constants.ts: -------------------------------------------------------------------------------- 1 | /* TODO: harcoded string that should be translatable/customizable */ 2 | export const TITLE_TEXT = 'Amundsen Resource Request'; 3 | export const FROM_LABEL = 'From'; 4 | export const TO_LABEL = 'To'; 5 | export const REQUEST_TYPE = 'Request Type'; 6 | export const TABLE_DESCRIPTION = 'Table Description'; 7 | export const COLUMN_DESCRIPTIONS = 'Column Descriptions'; 8 | export const ADDITIONAL_DETAILS = 'Additional Details'; 9 | export const SEND_BUTTON = 'Send Request'; 10 | 11 | export const SEND_INPROGRESS_MESSAGE = 'Your request is being sent...'; 12 | export const SEND_FAILURE_MESSAGE = 13 | 'Your request was not successfully sent, please try again'; 14 | export const SEND_SUCCESS_MESSAGE = 'Your request has been successfully sent'; 15 | 16 | export const RECIPIENT_LIST_DELIMETER = ', '; 17 | 18 | export const COMMENT_PLACEHOLDER_DEFAULT = 19 | 'Please enter more information about your request'; 20 | export const COMMENT_PLACEHOLDER_COLUMN = 21 | 'Please enter which column(s) need an improved description'; 22 | 23 | export const COLUMN_REQUESTED_COMMENT_PREFIX = 24 | 'Description requested for column: '; 25 | 26 | export const CLOSE = 'Close'; 27 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/RequestMetadataForm/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | .request-component { 7 | border-radius: 6px; 8 | bottom: 75px; 9 | box-shadow: 0 0 24px -2px rgba(0, 0, 0, 0.2); 10 | display: block; 11 | left: 25px; 12 | position: fixed; 13 | z-index: 6; 14 | 15 | &.expanded { 16 | background-color: $white; 17 | height: auto; 18 | min-height: 450px; 19 | padding: 32px; 20 | width: 400px; 21 | 22 | .title { 23 | flex-grow: 1; 24 | } 25 | 26 | .request-header { 27 | display: flex; 28 | 29 | button { 30 | margin: auto 0; 31 | } 32 | } 33 | 34 | .select-label { 35 | display: block; 36 | font-weight: $font-weight-body-regular; 37 | } 38 | 39 | .submit-request-button { 40 | img.icon { 41 | margin: 0 12px 0 0; 42 | transform: rotate(45deg); 43 | } 44 | } 45 | 46 | input, 47 | textarea { 48 | color: $text-secondary; 49 | } 50 | 51 | input[type='checkbox'] { 52 | margin-right: 8px; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/ResourceReportsDropdown/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | import { Dropdown } from 'react-bootstrap'; 6 | 7 | import { ResourceReport } from 'interfaces/index'; 8 | 9 | export interface ResourceReportProps { 10 | resourceReports: ResourceReport[]; 11 | } 12 | 13 | const TableReportsDropdown: React.FC = ({ 14 | resourceReports, 15 | }: ResourceReportProps) => { 16 | if (!resourceReports || resourceReports.length < 1) { 17 | return null; 18 | } 19 | 20 | return ( 21 | 22 | 23 | Reports 24 | 25 | 26 | {resourceReports.map((report) => ( 27 |
  • 28 | 29 | {`${report.name}`} 30 | 31 |
  • 32 | ))} 33 |
    34 |
    35 | ); 36 | }; 37 | 38 | export default TableReportsDropdown; 39 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/SourceLink/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import * as React from 'react'; 5 | 6 | import { 7 | getDescriptionSourceDisplayName, 8 | getDescriptionSourceIconPath, 9 | } from 'config/config-utils'; 10 | import AvatarLabel from 'components/AvatarLabel'; 11 | 12 | import { TableSource } from 'interfaces'; 13 | import { logClick } from 'utils/analytics'; 14 | 15 | export interface SourceLinkProps { 16 | tableSource: TableSource; 17 | } 18 | 19 | const SourceLink: React.FC = ({ 20 | tableSource, 21 | }: SourceLinkProps) => { 22 | if (tableSource === null || tableSource.source === null) return null; 23 | 24 | return ( 25 | 33 | 38 | 39 | ); 40 | }; 41 | 42 | export default SourceLink; 43 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/TableDescEditableText/index.tsx: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import { connect } from 'react-redux'; 5 | import { bindActionCreators } from 'redux'; 6 | 7 | import { GlobalState } from 'ducks/rootReducer'; 8 | import { 9 | getTableDescription, 10 | updateTableDescription, 11 | } from 'ducks/tableMetadata/reducer'; 12 | 13 | import EditableText, { 14 | ComponentProps, 15 | DispatchFromProps, 16 | StateFromProps, 17 | } from 'components/EditableText'; 18 | 19 | export const mapStateToProps = (state: GlobalState) => ({ 20 | refreshValue: state.tableMetadata.tableData.description, 21 | }); 22 | 23 | export const mapDispatchToProps = (dispatch: any) => 24 | bindActionCreators( 25 | { 26 | getLatestValue: getTableDescription, 27 | onSubmitValue: updateTableDescription, 28 | }, 29 | dispatch 30 | ); 31 | 32 | export default connect( 33 | mapStateToProps, 34 | mapDispatchToProps 35 | )(EditableText); 36 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/TableHeaderBullets/constants.ts: -------------------------------------------------------------------------------- 1 | export const TABLE_VIEW_TEXT = 'table view'; 2 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/TableIssues/constants.ts: -------------------------------------------------------------------------------- 1 | export const NO_DATA_ISSUES_TEXT = 'No associated issues'; 2 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/WatermarkLabel/constants.ts: -------------------------------------------------------------------------------- 1 | export const NO_WATERMARK_LINE_1 = 'Non-Partitioned Table'; 2 | export const NO_WATERMARK_LINE_2 = 'Data available for all dates'; 3 | export const LOW_WATERMARK_LABEL = 'From:'; 4 | export const HIGH_WATERMARK_LABEL = 'To:'; 5 | export const WATERMARK_INPUT_FORMAT = 'YYYY-MM-DD'; 6 | 7 | export enum WatermarkType { 8 | HIGH = 'high_watermark', 9 | LOW = 'low_watermark', 10 | } 11 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/WatermarkLabel/styles.scss: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'variables'; 5 | 6 | $date-range-label-width: 45px; 7 | 8 | .watermark-label { 9 | display: flex; 10 | 11 | .range-icon { 12 | flex-basis: 12px; 13 | height: 40px; 14 | margin-right: $spacer-1; 15 | width: 12px; 16 | margin-top: 2px; 17 | } 18 | 19 | .range-labels { 20 | flex-basis: 42px; 21 | } 22 | 23 | .date-range { 24 | margin-top: 0; 25 | margin-bottom: $spacer-1/2; 26 | } 27 | 28 | .date-range-label { 29 | width: $date-range-label-width; 30 | display: inline-block; 31 | } 32 | 33 | .date-range-value { 34 | margin-left: $spacer-1/2; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /amundsen_application/static/js/pages/TableDetailPage/constants.ts: -------------------------------------------------------------------------------- 1 | export const ERROR_MESSAGE = 'Something went wrong...'; 2 | export const EDIT_DESC_TEXT = 'Click to edit description in'; 3 | export const EDIT_OWNERS_TEXT = 'Click to edit owners in'; 4 | 5 | export const DATE_RANGE_TITLE = 'Date Range'; 6 | export const DESCRIPTION_TITLE = 'Description'; 7 | export const FREQ_USERS_TITLE = 'Frequent Users'; 8 | export const LAST_UPDATED_TITLE = 'Last Updated'; 9 | export const OWNERS_TITLE = 'Owners'; 10 | export const TAG_TITLE = 'Tags'; 11 | export const SORT_BY_DROPDOWN_TITLE = 'Sort by'; 12 | export const SORT_BY_MENU_TITLE_TEXT = 'Sort by'; 13 | 14 | export enum TABLE_TAB { 15 | COLUMN = 'columns', 16 | DASHBOARD = 'dashboard', 17 | DOWNSTREAM = 'downstream', 18 | UPSTREAM = 'upstream', 19 | } 20 | -------------------------------------------------------------------------------- /amundsen_application/static/js/utils/logUtils.ts: -------------------------------------------------------------------------------- 1 | import * as qs from 'simple-query-string'; 2 | 3 | export function getLoggingParams( 4 | search: string 5 | ): { index: string; source: string } { 6 | const params = qs.parse(search); 7 | const { index } = params; 8 | const { source } = params; 9 | 10 | let queryString = ''; 11 | let isInitialParam = true; 12 | Object.keys(params).forEach((key) => { 13 | if (key !== 'index' && key !== 'source') { 14 | queryString = isInitialParam 15 | ? `?${key}=${params[key]}` 16 | : `${queryString}&${key}=${params[key]}`; 17 | isInitialParam = false; 18 | } 19 | }); 20 | 21 | // Remove logging params from URL 22 | if (source !== undefined || index !== undefined) { 23 | window.history.replaceState( 24 | {}, 25 | '', 26 | `${window.location.origin}${window.location.pathname}${queryString}` 27 | ); 28 | } 29 | return { index, source }; 30 | } 31 | -------------------------------------------------------------------------------- /amundsen_application/static/js/utils/numberUtils.ts: -------------------------------------------------------------------------------- 1 | import { getNumberFormat } from 'config/config-utils'; 2 | 3 | export function formatNumber(value) { 4 | const numberformat = getNumberFormat(); 5 | if (numberformat == null) { 6 | return Intl.NumberFormat().format(value); 7 | } 8 | 9 | const numbersystem = numberformat.numberSystem || null; 10 | if (numbersystem) { 11 | return Intl.NumberFormat(numbersystem).format(value); 12 | } 13 | return Intl.NumberFormat().format(value); 14 | } 15 | 16 | export function isNumber(value): boolean { 17 | return !Number.isNaN(Number(value)); 18 | } 19 | -------------------------------------------------------------------------------- /amundsen_application/static/js/utils/textUtils.ts: -------------------------------------------------------------------------------- 1 | // Copyright Contributors to the Amundsen project. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | export enum CaseType { 5 | LOWER_CASE = 'lowerCase', 6 | SENTENCE_CASE = 'sentenceCase', 7 | UPPER_CASE = 'upperCase', 8 | TITLE_CASE = 'titleCase', 9 | } 10 | 11 | export function convertText(str = '', caseType: CaseType | null): string { 12 | switch (caseType) { 13 | case CaseType.LOWER_CASE: 14 | return str.toLowerCase(); 15 | case CaseType.SENTENCE_CASE: 16 | return `${str.charAt(0).toUpperCase()}${str.slice(1).toLowerCase()}`; 17 | case CaseType.UPPER_CASE: 18 | return str.toUpperCase(); 19 | case CaseType.TITLE_CASE: 20 | const splitStr = str.toLowerCase().split(' '); 21 | for (let i = 0; i < splitStr.length; i++) { 22 | splitStr[i] = 23 | splitStr[i].charAt(0).toUpperCase() + splitStr[i].substring(1); 24 | } 25 | return splitStr.join(' '); 26 | default: 27 | return str; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /amundsen_application/static/templates/fragments/icons-dev.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /amundsen_application/static/templates/fragments/icons-prod.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /amundsen_application/static/templates/fragments/icons-staging.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /amundsen_application/static/templates/index.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | Amundsen - Data Discovery Portal 11 | 12 | 13 | {% if env == "development" %} 14 | {% include 'fragments/icons-dev.html' %} 15 | {% elif env == "staging" %} 16 | {% include 'fragments/icons-staging.html' %} 17 | {% else %} 18 | {% include 'fragments/icons-prod.html' %} 19 | {% endif %} 20 | 21 | <%= htmlWebpackPlugin.tags.headTags %> 22 | 23 | 24 | 25 | 26 | 27 |
    28 | <%= htmlWebpackPlugin.tags.bodyTags %> 29 | 30 | 31 | -------------------------------------------------------------------------------- /amundsen_application/static/test-setup.ts: -------------------------------------------------------------------------------- 1 | import { configure } from 'enzyme'; 2 | import * as Adapter from 'enzyme-adapter-react-16'; 3 | 4 | configure({ adapter: new Adapter() }); 5 | -------------------------------------------------------------------------------- /amundsen_application/static/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["es5", "es2015", "dom", "scripthost"], 4 | "outDir": "./dist/", 5 | "sourceMap": true, 6 | "noImplicitAny": false, 7 | "module": "esnext", 8 | "target": "es2015", 9 | "strictNullChecks": true, 10 | "jsx": "react", 11 | "typeRoots": ["node_modules/@types"], 12 | "allowJs": true, 13 | "moduleResolution": "node", 14 | "noResolve": false, 15 | "removeComments": true, 16 | "allowSyntheticDefaultImports": true, 17 | "types": ["jest"], 18 | "baseUrl": "js", 19 | "paths": { 20 | "components/*": ["components/*"], 21 | "features/*": ["features/*"], 22 | "config/*": ["config/*"], 23 | "ducks/*": ["ducks/*"], 24 | "interfaces/*": ["interfaces/*"], 25 | "stories/*": ["stories/*"] 26 | } 27 | }, 28 | "exclude": ["node_modules", "**/__tests__"], 29 | "include": ["*.ts", "*.js", ".eslintrc.js", "js/"] 30 | } 31 | -------------------------------------------------------------------------------- /amundsen_application/static/tsconfig.webpack.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "esModuleInterop": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /amundsen_application/static/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [], 4 | "jsRules": { 5 | "no-empty": true 6 | }, 7 | "rules": { 8 | "variable-name": [ 9 | true, 10 | "ban-keywords", 11 | "check-format", 12 | "allow-pascal-case", 13 | "allow-leading-underscore" 14 | ], 15 | "import-name": [ 16 | false 17 | ], 18 | "no-parameter-reassignment": false, 19 | "prefer-array-literal": [ 20 | false 21 | ], 22 | "prefer-template": false 23 | }, 24 | "rulesDirectory": [] 25 | } 26 | -------------------------------------------------------------------------------- /amundsen_application/static/webpack.dev.ts: -------------------------------------------------------------------------------- 1 | import merge from 'webpack-merge'; 2 | import MiniCssExtractPlugin from 'mini-css-extract-plugin'; 3 | // import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; 4 | 5 | import commonConfig from './webpack.common'; 6 | 7 | const webpack = require('webpack'); 8 | 9 | export default merge(commonConfig, { 10 | mode: 'development', 11 | devtool: 'inline-source-map', 12 | plugins: [ 13 | new MiniCssExtractPlugin({ 14 | filename: '[name].dev.css', 15 | }), 16 | // fix "process is not defined" error: 17 | new webpack.ProvidePlugin({ 18 | process: 'process/browser', 19 | }), 20 | // new BundleAnalyzerPlugin() // Uncomment to check the bundle size on dev 21 | ], 22 | output: { 23 | filename: '[name].dev.js', 24 | }, 25 | }); 26 | -------------------------------------------------------------------------------- /amundsen_application/static/webpack.prod.ts: -------------------------------------------------------------------------------- 1 | import MiniCssExtractPlugin from 'mini-css-extract-plugin'; 2 | import merge from 'webpack-merge'; 3 | import TerserPlugin from 'terser-webpack-plugin'; 4 | import commonConfig from './webpack.common'; 5 | 6 | const webpack = require('webpack'); 7 | 8 | export default merge(commonConfig, { 9 | mode: 'production', 10 | optimization: { 11 | // minify code. also use parameters that improve build speed. 12 | minimizer: [ 13 | new TerserPlugin({ 14 | cache: true, 15 | parallel: true, 16 | sourceMap: true, 17 | }), 18 | ], 19 | }, 20 | plugins: [ 21 | new MiniCssExtractPlugin({ 22 | filename: '[name].[contenthash].css', 23 | }), 24 | // fix "process is not defined" error: 25 | new webpack.ProvidePlugin({ 26 | process: 'process/browser', 27 | }), 28 | ], 29 | }); 30 | -------------------------------------------------------------------------------- /amundsen_application/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /amundsen_application/tests/templates/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/amundsen_application/tests/templates/index.html -------------------------------------------------------------------------------- /amundsen_application/tests/test_utils.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | from flask import current_app as app 5 | from amundsen_application.models.user import load_user, User 6 | 7 | TEST_USER_ID = 'test_user_id' 8 | 9 | 10 | def get_test_user(app: app) -> User: # type: ignore 11 | user_info = { 12 | 'email': 'test@email.com', 13 | 'user_id': TEST_USER_ID, 14 | 'first_name': 'Firstname', 15 | 'last_name': 'Lastname', 16 | 'full_name': 'Firstname Lastname', 17 | } 18 | return load_user(user_info) 19 | -------------------------------------------------------------------------------- /amundsen_application/wsgi.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | import os 5 | from amundsen_application import create_app 6 | 7 | 8 | if not os.getenv('FRONTEND_SVC_CONFIG_MODULE_CLASS'): 9 | os.environ['FRONTEND_SVC_CONFIG_MODULE_CLASS'] = 'amundsen_application.config.TestConfig' 10 | 11 | application = create_app() 12 | 13 | if __name__ == '__main__': 14 | application.run(host='0.0.0.0') 15 | -------------------------------------------------------------------------------- /docs/authentication/oidc.md: -------------------------------------------------------------------------------- 1 | See [this doc](https://github.com/lyft/amundsen/blob/master/docs/authentication/oidc.md) in our main repository for information on how to set up end-to-end authentication using OIDC. 2 | 3 | -------------------------------------------------------------------------------- /docs/img/announcements_feature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/docs/img/announcements_feature.png -------------------------------------------------------------------------------- /docs/img/column_details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/docs/img/column_details.png -------------------------------------------------------------------------------- /docs/img/data_preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/docs/img/data_preview.png -------------------------------------------------------------------------------- /docs/img/distinct_values.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/docs/img/distinct_values.png -------------------------------------------------------------------------------- /docs/img/graph_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/docs/img/graph_model.png -------------------------------------------------------------------------------- /docs/img/landing_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/docs/img/landing_page.png -------------------------------------------------------------------------------- /docs/img/notices-alert-table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/docs/img/notices-alert-table.png -------------------------------------------------------------------------------- /docs/img/notices-info-table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/docs/img/notices-info-table.png -------------------------------------------------------------------------------- /docs/img/notices-warning-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/docs/img/notices-warning-dashboard.png -------------------------------------------------------------------------------- /docs/img/programmatic_descriptions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/docs/img/programmatic_descriptions.png -------------------------------------------------------------------------------- /docs/img/search_preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/docs/img/search_preview.png -------------------------------------------------------------------------------- /docs/img/table_detail_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amundsen-io/amundsenfrontendlibrary/b5b33bba886a295df2f870677341ec4c806cd6b1/docs/img/table_detail_page.png -------------------------------------------------------------------------------- /local.Dockerfile: -------------------------------------------------------------------------------- 1 | ARG METADATASERVICE_BASE 2 | ARG SEARCHSERVICE_BASE 3 | 4 | FROM node:12-slim as node-stage 5 | WORKDIR /app/amundsen_application/static 6 | 7 | COPY amundsen_application/static/package.json /app/amundsen_application/static/package.json 8 | COPY amundsen_application/static/package-lock.json /app/amundsen_application/static/package-lock.json 9 | RUN npm install 10 | 11 | COPY amundsen_application/static/ /app/amundsen_application/static/ 12 | RUN npm rebuild node-sass 13 | RUN npm run dev-build 14 | 15 | COPY . /app 16 | 17 | FROM python:3.7-slim 18 | WORKDIR /app 19 | 20 | COPY requirements.txt /app/requirements.txt 21 | RUN pip3 install -r requirements.txt 22 | 23 | COPY --from=node-stage /app /app 24 | 25 | RUN pip3 install -e . 26 | 27 | ENTRYPOINT [ "python3" ] 28 | CMD [ "amundsen_application/wsgi.py" ] 29 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | format = pylint 3 | exclude = .svc,CVS,.bzr,.hg,.git,__pycache__,venv,venv3,node_modules 4 | max-complexity = 10 5 | max-line-length = 120 6 | ignore = W503 7 | 8 | [pep8] 9 | max-line-length = 120 10 | 11 | [tool:pytest] 12 | addopts = --cov=amundsen_application --cov-fail-under=70 --cov-report=term-missing:skip-covered --cov-report=xml --cov-report=html -vvv 13 | 14 | [coverage:run] 15 | branch = True 16 | 17 | [coverage:xml] 18 | output = build/coverage.xml 19 | 20 | [coverage:html] 21 | directory = build/coverage_html 22 | 23 | [mypy] 24 | python_version = 3.6 25 | disallow_untyped_defs = True 26 | ignore_missing_imports = True 27 | strict_optional = True 28 | warn_no_return = True 29 | 30 | [semantic_release] 31 | version_variable = "./setup.py:__version__" 32 | upload_to_pypi = true 33 | upload_to_release = true 34 | commit_subject = New release for {version} 35 | commit_message = Signed-off-by: github-actions 36 | commit_author = github-actions 37 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /tests/unit/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /tests/unit/api/announcements/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /tests/unit/api/mail/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /tests/unit/api/metadata/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /tests/unit/api/preview/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /tests/unit/api/preview/dashboard/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /tests/unit/api/preview/dashboard/dashboard_preview/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /tests/unit/api/search/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /tests/unit/base/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /tests/unit/base/test_issue_tracker_client.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | import unittest 5 | import flask 6 | 7 | from amundsen_application.base.base_issue_tracker_client import BaseIssueTrackerClient 8 | 9 | 10 | app = flask.Flask(__name__) 11 | app.config.from_object('amundsen_application.config.TestConfig') 12 | 13 | 14 | class IssueTrackerClientTest(unittest.TestCase): 15 | 16 | def test_abstract_class_methods(self) -> None: 17 | abstract_methods_set = { 18 | '__init__', 19 | 'create_issue', 20 | 'get_issues' 21 | } 22 | # Use getattr to prevent mypy warning 23 | cls_abstrct_methods = getattr(BaseIssueTrackerClient, '__abstractmethods__') 24 | self.assertEquals(cls_abstrct_methods, abstract_methods_set) 25 | -------------------------------------------------------------------------------- /tests/unit/base/test_preview_client.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | import unittest 5 | import flask 6 | 7 | from amundsen_application.base.base_preview_client import BasePreviewClient 8 | 9 | app = flask.Flask(__name__) 10 | app.config.from_object('amundsen_application.config.LocalConfig') 11 | 12 | 13 | class PreviewClientTest(unittest.TestCase): 14 | 15 | def test_cover_abtract_methods(self) -> None: 16 | abstract_methods_set = { 17 | '__init__', 18 | 'get_preview_data' 19 | } 20 | # Use getattr to prevent mypy warning 21 | cls_abstrct_methods = getattr(BasePreviewClient, '__abstractmethods__') 22 | self.assertEquals(cls_abstrct_methods, abstract_methods_set) 23 | -------------------------------------------------------------------------------- /tests/unit/issue_tracker_clients/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /tests/unit/log/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /tests/unit/models/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /tests/unit/utils/test_response_utils.py: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the Amundsen project. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | import json 5 | import unittest 6 | from typing import Dict 7 | 8 | from amundsen_application import create_app 9 | from amundsen_application.api.utils.response_utils import create_error_response 10 | 11 | local_app = create_app('amundsen_application.config.TestConfig', 'tests/templates') 12 | 13 | 14 | class ResponseUtilsTest(unittest.TestCase): 15 | def setUp(self) -> None: 16 | pass 17 | 18 | def test_create_error_response(self) -> None: 19 | """ 20 | Verify that the returned response contains the given messag and status_code 21 | :return: 22 | """ 23 | test_message = 'Success' 24 | test_payload: Dict = {} 25 | status_code = 200 26 | with local_app.app_context(): 27 | response = create_error_response(message=test_message, 28 | payload=test_payload, 29 | status_code=status_code) 30 | data = json.loads(response.data) 31 | self.assertEqual(response.status_code, status_code) 32 | self.assertEqual(data.get('msg'), test_message) 33 | --------------------------------------------------------------------------------