Skip to content

Commit

Permalink
Add feature page basics
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Won <dwon@lyft.com>
  • Loading branch information
Daniel Won committed Jun 2, 2021
1 parent 5a4297d commit dc59a5e
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { FeatureMetadata, FeatureSummary } from 'interfaces/Feature';

export const featureSummary: FeatureSummary = {
key: 'test key',
name: 'test feature name',
version: '1.02.0',
availability: ['source 1', 'source 2'],
entity: ['entity 1', 'entity 2'],
description: 'test feature description',
};

export const featureMetadata: FeatureMetadata = {
key: 'test key',
name: 'test feature name',
version: '1.02.0',
status: 'status',
feature_group: 'feature group',
entity: ['entity 1', 'entity 2'],
data_type: 'string',
availability: ['source 1', 'source 2'],
description: 'test feature description',
owners: [
{
display_name: 'test',
email: 'test@email.com',
profile_url: 'profile_url',
user_id: 'user_id',
},
],
badges: [],
owner_tags: [],
tags: [],
programmatic_descriptions: [],
watermarks: [],
stats: [],
last_updated_timestamp: 0,
created_timestamp: 0,
};
4 changes: 3 additions & 1 deletion frontend/amundsen_application/static/js/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ import { pageViewed } from 'ducks/ui';
import rootReducer from 'ducks/rootReducer';
import rootSaga from 'ducks/rootSaga';

import DashboardPage from './pages/DashboardPage';
import AnnouncementPage from './pages/AnnouncementPage';
import BrowsePage from './pages/BrowsePage';
import DashboardPage from './pages/DashboardPage';
import FeaturePage from './pages/FeaturePage';
import HomePage from './pages/HomePage';
import NotFoundPage from './pages/NotFoundPage';
import SearchPage from './pages/SearchPage';
Expand Down Expand Up @@ -64,6 +65,7 @@ const Routes: React.FC = () => {
<Route path="/announcements" component={AnnouncementPage} />
<Route path="/browse" component={BrowsePage} />
<Route path="/dashboard/:uri" component={DashboardPage} />
<Route path="/feature/:key" component={FeaturePage} />
<Route path="/search" component={SearchPage} />
<Route
path="/table_detail/:cluster/:database/:schema/:table"
Expand Down
6 changes: 3 additions & 3 deletions frontend/amundsen_application/static/js/interfaces/Feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ export interface FeatureMetadata {
entity?: string[];
data_type?: string;
availability: string[];
description?: string;
description: string;
owners: User[];
badges: Badge[];
owner_tags?: Tag[];
tags: Tag[];
programmatic_descriptions: ProgrammaticDescription[];
watermarks: Watermark[];
stats: FeatureStats[];
last_updated_timestamp?: number;
last_updated_timestamp: number;
created_timestamp: number;
partition_column?: TableColumn;
}
Expand All @@ -35,7 +35,7 @@ export interface FeatureSummary {
version: string;
availability: string[];
entity?: string[];
description?: string[];
description: string;
}

// TODO - Figure out if we can reuse ColumnStats
Expand Down
130 changes: 123 additions & 7 deletions frontend/amundsen_application/static/js/pages/FeaturePage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,139 @@ import * as React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { RouteComponentProps } from 'react-router';
import * as ReactMarkdown from 'react-markdown';

import { FeatureMetadata } from 'interfaces/Feature';
import { GlobalState } from 'ducks/rootReducer';
import { getFeature } from 'ducks/feature/reducer';
import { GetFeatureRequest } from 'ducks/feature/types';
import Breadcrumb from 'components/Breadcrumb';
import { getLoggingParams } from '../../utils/logUtils';
import { formatDateTimeShort } from '../../utils/dateUtils';

interface StateFromProps {
isLoading: boolean;
statusCode: number | null;
featureMetadata: FeatureMetadata;
feature: FeatureMetadata;
}

export interface DispatchFromProps {
getFeature: () => void;
getFeatureDispatch: (
key: string,
index: string,
source: string
) => GetFeatureRequest;
}

interface FeatureRouteParams {
key: string;
}

export type FeaturePageProps = StateFromProps & DispatchFromProps;
export type FeaturePageProps = RouteComponentProps<FeatureRouteParams> &
StateFromProps &
DispatchFromProps;

export function renderTabs() {
return null;
}

const FeaturePage: React.FC<FeaturePageProps> = ({
isLoading,
statusCode,
featureMetadata,
getFeature,
}: FeaturePageProps) => null;
feature,
getFeatureDispatch,
location,
match,
}: FeaturePageProps) => {
const [key, setKey] = React.useState('');
React.useEffect(() => {
if (key !== match.params.key) {
const { index, source } = getLoggingParams(location.search);
setKey(match.params.key);
getFeatureDispatch(key, index, source);
}
});

if (isLoading) {
return null;
}
// @ts-ignore
return (
<div className="resource-detail-layout dashboard-page">
<header className="resource-header">
<div className="header-section">
<Breadcrumb />
<span className="icon icon-header icon-database" />
</div>
</header>
<article className="column-layout-1">
<aside className="left-panel">
<section className="metadata-section">
<div className="section-title title-3">Description</div>
<div className="markdown-wrapper">
<ReactMarkdown>{feature.description}</ReactMarkdown>
</div>
</section>
<section className="column-layout-2">
<section className="left-panel">
<section className="metadata-section">
<div className="section-title title-3">Entity</div>
{feature.entity}
</section>
<section className="metadata-section">
<div className="section-title title-3">Data Type</div>
{feature.data_type}
</section>
<section className="metadata-section">
<div className="section-title title-3">Source</div>
{feature.availability}
</section>
<section className="metadata-section">
<div className="section-title title-3">Last Updated</div>
<time>
{formatDateTimeShort({
epochTimestamp: feature.last_updated_timestamp,
})}
</time>
</section>
</section>
<section className="right-panel">
<section className="metadata-section">
<div className="section-title title-3">Partition Key</div>
{feature.partition_column}
</section>
<section className="metadata-section">
<div className="section-title title-3">version</div>
{feature.version}
</section>
<section className="metadata-section">
<div className="section-title title-3">Owners</div>
{feature.owners.map((owner) => (
<div>{owner.email}</div>
))}
</section>
<section className="metadata-section">
<div className="section-title title-3">Feature Group</div>
{feature.feature_group}
</section>
</section>
</section>
</aside>
<main className="right-panel">{renderTabs()}</main>
</article>
</div>
);
};

export const mapStateToProps = (state: GlobalState) => ({
isLoading: state.feature.isLoading,
statusCode: state.feature.statusCode,
feature: state.feature.feature,
});

export const mapDispatchToProps = (dispatch: any) =>
bindActionCreators({ getFeatureDispatch: getFeature }, dispatch);

export default connect<StateFromProps, DispatchFromProps>(
mapStateToProps,
mapDispatchToProps
)(FeaturePage);

0 comments on commit dc59a5e

Please sign in to comment.