diff --git a/app/components/Code.tsx b/app/components/Code.tsx new file mode 100644 index 00000000..c3777767 --- /dev/null +++ b/app/components/Code.tsx @@ -0,0 +1,20 @@ +import * as React from 'react' + +interface CodeProps { + data: string | undefined +} + +const Code: React.FunctionComponent = (props: CodeProps) => { + const { data } = props + + const lines = data.split('\n') + + return ( +
+
{lines.map((_, i) => (`${i}\n`))}
+
{data}
+
+ ) +} + +export default Code diff --git a/app/components/ComponentList.tsx b/app/components/ComponentList.tsx index 1bf7bfec..6a62da41 100644 --- a/app/components/ComponentList.tsx +++ b/app/components/ComponentList.tsx @@ -6,7 +6,7 @@ import { clipboard, shell, MenuItemConstructorOptions } from 'electron' import ContextMenuArea from 'react-electron-contextmenu' import { ApiActionThunk } from '../store/api' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faTags, faArchive, faTh, IconDefinition, faExclamation } from '@fortawesome/free-solid-svg-icons' +import { faTags, faArchive, faTh, IconDefinition, faExclamation, faRobot } from '@fortawesome/free-solid-svg-icons' import { faReadme } from '@fortawesome/free-brands-svg-icons' import { DatasetStatus, SelectedComponent, ComponentType } from '../models/store' @@ -111,9 +111,26 @@ const components = [ displayName: 'Structure', tooltip: 'the structure of the dataset', icon: faTh + }, + { + name: 'transform', + displayName: 'Transform', + tooltip: 'commit automation', + icon: faRobot } ] +function removeHiddenComponents (status: DatasetStatus) { + const hideWhenMissing = { + 'transform': true + } + + return (component): boolean => { + console.log(status[component.name]) + return status[component.name] || !hideWhenMissing[component.name] + } +} + export const getComponentDisplayProps = (name: string) => { return components.filter(d => d.name === name)[0] } @@ -130,7 +147,7 @@ const ComponentList: React.FunctionComponent = (props: Compo } = props const isEnabled = (name: string): boolean => { - return (datasetSelected && selectionType === 'component' && (name === 'meta' || name === 'structure' || name === 'readme')) + return (datasetSelected && selectionType === 'component' && (name === 'meta' || name === 'structure' || name === 'readme' || name === 'transform')) } return ( @@ -145,7 +162,7 @@ const ComponentList: React.FunctionComponent = (props: Compo Dataset Components { - components.map(({ name, displayName, tooltip, icon }) => { + components.filter(removeHiddenComponents(status)).map(({ name, displayName, tooltip, icon }) => { if (status[name] && !!fsiPath) { const { filepath, status: fileStatus } = status[name] diff --git a/app/components/Dataset.tsx b/app/components/Dataset.tsx index ae29f132..7c8de551 100644 --- a/app/components/Dataset.tsx +++ b/app/components/Dataset.tsx @@ -179,7 +179,8 @@ export default class Dataset extends React.Component { if ( componentsToReset.includes('structure') || componentsToReset.includes('meta') || - componentsToReset.includes('readme') + componentsToReset.includes('readme') || + componentsToReset.includes('transform') ) fetchWorkingDataset() } diff --git a/app/components/DatasetComponent.tsx b/app/components/DatasetComponent.tsx index 33e2c62d..05c3e1f1 100644 --- a/app/components/DatasetComponent.tsx +++ b/app/components/DatasetComponent.tsx @@ -7,6 +7,7 @@ import BodyContainer from '../containers/BodyContainer' import StructureContainer from '../containers/StructureContainer' import ParseError from './ParseError' import ReadmeContainer from '../containers/ReadmeContainer' +import TransformContainer from '../containers/TransformContainer' import ReadmeHistoryContainer from '../containers/ReadmeHistoryContainer' import { CSSTransition } from 'react-transition-group' import SpinnerWithIcon from './chrome/SpinnerWithIcon' @@ -114,6 +115,19 @@ const DatasetComponent: React.FunctionComponent = (props: + +
+ +
+
diff --git a/app/components/Transform.tsx b/app/components/Transform.tsx new file mode 100644 index 00000000..72624542 --- /dev/null +++ b/app/components/Transform.tsx @@ -0,0 +1,26 @@ +import * as React from 'react' + +import { WorkingDataset } from '../models/store' +import { ApiActionThunk } from '../store/api' + +import Code from './Code' + +export interface TransformProps { + peername: string + name: string + value: string + preview: string + history: boolean + workingDataset: WorkingDataset + write: (peername: string, name: string, dataset: any) => ApiActionThunk +} + +const Transform: React.FunctionComponent = (props) => { + const { value } = props + + return ( + + ) +} + +export default Transform diff --git a/app/containers/TransformContainer.tsx b/app/containers/TransformContainer.tsx new file mode 100644 index 00000000..8bb71f78 --- /dev/null +++ b/app/containers/TransformContainer.tsx @@ -0,0 +1,31 @@ +import { connect } from 'react-redux' +import { bindActionCreators, Dispatch } from 'redux' +import Transform, { TransformProps } from '../components/Transform' +import Store from '../models/store' +import { fsiWriteAndFetch } from '../actions/api' + +const mapStateToProps = (state: Store) => { + const { workingDataset, selections } = state + const { value } = workingDataset.components.transform + + const { peername, name } = selections + + // get data for the currently selected component + return { + peername, + name, + value, + history, + workingDataset + } +} + +const mergeProps = (props: any, actions: any): TransformProps => { //eslint-disable-line + return { ...props, ...actions } +} + +const mapDispatchToProps = (dispatch: Dispatch) => { + return bindActionCreators({ write: fsiWriteAndFetch }, dispatch) +} + +export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(Transform) diff --git a/app/models/store.ts b/app/models/store.ts index eaa291dc..01706bee 100644 --- a/app/models/store.ts +++ b/app/models/store.ts @@ -68,7 +68,7 @@ export interface UI { detailsBar: Details } -export type SelectedComponent = 'readme' | 'meta' | 'body' | 'structure' | '' +export type SelectedComponent = 'readme' | 'meta' | 'body' | 'structure' | 'transform' | '' // currently selected dataset, tab, dataset component, commit, etc export interface Selections { @@ -148,6 +148,9 @@ export interface CommitDetails { structure: { value: Structure } + transform: { + value: string | undefined + } } stats: Array<{[key: string]: any}> } diff --git a/app/reducers/workingDataset.ts b/app/reducers/workingDataset.ts index 89ebf874..1f3e3dbc 100644 --- a/app/reducers/workingDataset.ts +++ b/app/reducers/workingDataset.ts @@ -33,6 +33,9 @@ const initialState: WorkingDataset = { }, structure: { value: {} + }, + transform: { + value: '' } }, history: { @@ -97,6 +100,9 @@ const workingDatasetsReducer: Reducer = (state = initialState, action: AnyAction }, structure: { value: dataset && dataset.structure ? dataset.structure : {} + }, + transform: { + value: dataset && dataset.transform ? atob(dataset.transform.scriptBytes) : '' } } } diff --git a/stories/1-CodeViewer.stories.tsx b/stories/1-CodeViewer.stories.tsx new file mode 100644 index 00000000..df7667ed --- /dev/null +++ b/stories/1-CodeViewer.stories.tsx @@ -0,0 +1,28 @@ +import React from 'react' +import Code from '../app/components/Code' + +export default { + title: 'Code' +} + +const wrap = (component) => { + return ( +
+ {component} +
+ ) +} + +const basicTransformText = ` +def transform(ds,ctx): + ds.set_body([[1,2,3,4],[5,6,7,8]]) +` + +export const basicTransform = () => wrap() + +basicTransform.story = { + name: 'Transform: Basic Starlark', + parameters: { + notes: `short code viewer` + } +} \ No newline at end of file