mirror of
https://github.com/chenasraf/redar-browser.git
synced 2026-05-17 17:58:04 +00:00
Change response representation to cards instead of table
This commit is contained in:
2
scaffold/component/{{Name}}.module.d.ts
vendored
2
scaffold/component/{{Name}}.module.d.ts
vendored
@@ -1,5 +1,5 @@
|
||||
export interface IProps {
|
||||
// props
|
||||
className?: string
|
||||
}
|
||||
|
||||
export interface IState {
|
||||
|
||||
@@ -5,14 +5,13 @@ import * as I from './{{Name}}.module'
|
||||
class {{Name}} extends React.Component<I.IProps, I.IState> {
|
||||
constructor(props: I.IProps) {
|
||||
super(props)
|
||||
this.state = {
|
||||
//
|
||||
}
|
||||
this.state = {}
|
||||
}
|
||||
|
||||
render() {
|
||||
const classNames = [
|
||||
css.{{Name}},
|
||||
this.props.className
|
||||
].join(' ')
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
$font-family: "Helvetica Neue", "Calibri", "Segoe UI", "Arial", sans-serif;
|
||||
$highlight: #05a;
|
||||
$text-main: #222;
|
||||
$text-light: #555;
|
||||
$drop-shadow: drop-shadow(1.5px 1.5px 1px #0003);
|
||||
|
||||
@@ -18,20 +18,23 @@ const StoreKeys = {
|
||||
RequestType: 'REQ_TYPE'
|
||||
}
|
||||
|
||||
export interface Action<T = any> {
|
||||
name: string,
|
||||
export type TActionName =
|
||||
'UPDATE_RESPONSE' | 'UPDATE_TABLE' | 'UPDATE_COLUMNS' | 'UPDATE_VIEWKEY' | 'UPDATE_REQ_TYPE'
|
||||
|
||||
export interface IAction<T = any> {
|
||||
name: TActionName | string,
|
||||
payload?: T
|
||||
}
|
||||
|
||||
export const AppDispatcher = new Dispatcher<Action>()
|
||||
export const AppDispatcher = new Dispatcher<IAction>()
|
||||
|
||||
function innerObjFromKey<T = any>(obj: T, k: string): Immutable.OrderedMap<string, T> {
|
||||
return Immutable.OrderedMap<string, any>(obj || {}).get(k, {})
|
||||
}
|
||||
|
||||
type TState = Immutable.OrderedMap<string, any>
|
||||
export type IState = Immutable.OrderedMap<string, any>
|
||||
|
||||
class AppStore extends ReduceStore<TState, Action> {
|
||||
class AppStore extends ReduceStore<IState, IAction> {
|
||||
constructor() {
|
||||
super(AppDispatcher)
|
||||
}
|
||||
@@ -40,7 +43,7 @@ class AppStore extends ReduceStore<TState, Action> {
|
||||
return Immutable.OrderedMap<string, any>()
|
||||
}
|
||||
|
||||
reduce(state: TState, action: Action) {
|
||||
reduce(state: IState, action: IAction) {
|
||||
switch (action.name) {
|
||||
case ActionTypes.UPDATE_COLUMNS:
|
||||
return state.set(StoreKeys.Columns, action.payload)
|
||||
@@ -56,14 +59,14 @@ class AppStore extends ReduceStore<TState, Action> {
|
||||
}
|
||||
}
|
||||
|
||||
export function dispatch(name: string, payload: any) {
|
||||
export function dispatch(name: TActionName | string, payload: any) {
|
||||
AppDispatcher.dispatch({
|
||||
name, payload
|
||||
})
|
||||
}
|
||||
|
||||
export function register(name: string, callback: (payload: any) => void): string {
|
||||
return AppDispatcher.register((payload: Action) => {
|
||||
function register(name: TActionName | string, callback: (payload: any) => void): string {
|
||||
return AppDispatcher.register((payload: IAction) => {
|
||||
if (payload.name === name) {
|
||||
console.debug('Dispatching:', payload.name, payload.payload)
|
||||
callback(payload.payload)
|
||||
@@ -73,4 +76,4 @@ export function register(name: string, callback: (payload: any) => void): string
|
||||
|
||||
const Store = new AppStore()
|
||||
export default AppDispatcher
|
||||
export { Store, ActionTypes, StoreKeys }
|
||||
export { Store, ActionTypes, StoreKeys, AppDispatcher as Dispatcher, register }
|
||||
|
||||
@@ -84,23 +84,23 @@ class Header extends React.Component<I.IProps, I.IState> {
|
||||
axios.request({ method, url, data: this.requestPayload, headers: this.requestHeaders })
|
||||
.then((response: AxiosResponse) => {
|
||||
const { data } = response
|
||||
let viewKey = this.props.store.get(StoreKeys.ViewKey, null)
|
||||
let tableData
|
||||
// let viewKey = this.props.store.get(StoreKeys.ViewKey, null)
|
||||
// let tableData
|
||||
|
||||
if (viewKey && data.hasOwnProperty(viewKey)) {
|
||||
tableData = data[viewKey]
|
||||
} else {
|
||||
viewKey = ''
|
||||
}
|
||||
// if (viewKey && data.hasOwnProperty(viewKey)) {
|
||||
// tableData = data[viewKey]
|
||||
// } else {
|
||||
// viewKey = ''
|
||||
// }
|
||||
|
||||
if (viewKey === '' || !tableData) {
|
||||
tableData = [data]
|
||||
}
|
||||
// if (viewKey === '' || !tableData) {
|
||||
// tableData = [data]
|
||||
// }
|
||||
|
||||
dispatch(ActionTypes.UPDATE_RESPONSE, data)
|
||||
dispatch(ActionTypes.UPDATE_VIEWKEY, viewKey)
|
||||
dispatch(ActionTypes.UPDATE_TABLE, tableData)
|
||||
dispatch(ActionTypes.UPDATE_COLUMNS, this.getDataColumns(tableData))
|
||||
// dispatch(ActionTypes.UPDATE_VIEWKEY, viewKey)
|
||||
// dispatch(ActionTypes.UPDATE_TABLE, tableData)
|
||||
// dispatch(ActionTypes.UPDATE_COLUMNS, this.getDataColumns(tableData))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
29
src/components/RObject/RObject.css
Normal file
29
src/components/RObject/RObject.css
Normal file
@@ -0,0 +1,29 @@
|
||||
@import "../../_variables.css";
|
||||
|
||||
.RObject {
|
||||
display: inline-block;
|
||||
background: #fff;
|
||||
filter: $drop-shadow;
|
||||
// max-width: 20vw;
|
||||
padding: 7px;
|
||||
margin: 7px 5px;
|
||||
vertical-align: top;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
|
||||
& > h3 {
|
||||
font-size: 0.8rem;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
color: $text-light;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.simple {
|
||||
display: inline-block;
|
||||
max-width: 16vw;
|
||||
overflow: hidden;
|
||||
white-space: pre;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
3
src/components/RObject/RObject.css.d.ts
vendored
Normal file
3
src/components/RObject/RObject.css.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export const RObject: string;
|
||||
export const rObject: string;
|
||||
export const simple: string;
|
||||
8
src/components/RObject/RObject.module.d.ts
vendored
Normal file
8
src/components/RObject/RObject.module.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
export interface IProps {
|
||||
className?: string
|
||||
data: any
|
||||
}
|
||||
|
||||
export interface IState {
|
||||
// state
|
||||
}
|
||||
50
src/components/RObject/RObject.tsx
Normal file
50
src/components/RObject/RObject.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import * as React from 'react'
|
||||
import * as css from './RObject.css'
|
||||
import * as I from './RObject.module'
|
||||
|
||||
class RObject extends React.Component<I.IProps, I.IState> {
|
||||
constructor(props: I.IProps) {
|
||||
super(props)
|
||||
this.state = {}
|
||||
}
|
||||
|
||||
private getCorrectRepr(obj: any, cls?: string) {
|
||||
try {
|
||||
switch (typeof obj) {
|
||||
case 'number':
|
||||
case 'string':
|
||||
return <span className={css.simple}>{obj}</span>
|
||||
default:
|
||||
const keys = obj ? Object.keys(obj) : []
|
||||
const isArray = obj && obj.constructor === Array
|
||||
|
||||
if (!keys.length) {
|
||||
return <span>{JSON.stringify(obj)}</span>
|
||||
}
|
||||
|
||||
return keys.map((k: string) => {
|
||||
return (
|
||||
<div className={cls} key={'obj-' + k}>
|
||||
<h3>{!isArray ? k : typeof obj}</h3>
|
||||
<RObject data={obj[k]} />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
return <span className={css.simple}>{typeof obj}</span>
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const classNames = [
|
||||
css.RObject,
|
||||
this.props.className
|
||||
].join(' ')
|
||||
|
||||
const repr = this.getCorrectRepr(this.props.data, classNames)
|
||||
return repr
|
||||
}
|
||||
}
|
||||
|
||||
export default RObject
|
||||
9
src/components/ResponseRepr/ResponseRepr.css
Normal file
9
src/components/ResponseRepr/ResponseRepr.css
Normal file
@@ -0,0 +1,9 @@
|
||||
@import "../../_variables.css";
|
||||
|
||||
.ResponseRepr {
|
||||
/* */
|
||||
}
|
||||
|
||||
.obj {
|
||||
// max-width: 11vw;
|
||||
}
|
||||
3
src/components/ResponseRepr/ResponseRepr.css.d.ts
vendored
Normal file
3
src/components/ResponseRepr/ResponseRepr.css.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export const ResponseRepr: string;
|
||||
export const responseRepr: string;
|
||||
export const obj: string;
|
||||
8
src/components/ResponseRepr/ResponseRepr.module.d.ts
vendored
Normal file
8
src/components/ResponseRepr/ResponseRepr.module.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
export interface IProps {
|
||||
className?: string
|
||||
store: any
|
||||
}
|
||||
|
||||
export interface IState {
|
||||
response: any
|
||||
}
|
||||
61
src/components/ResponseRepr/ResponseRepr.tsx
Normal file
61
src/components/ResponseRepr/ResponseRepr.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import * as React from 'react'
|
||||
import * as css from './ResponseRepr.css'
|
||||
import * as I from './ResponseRepr.module'
|
||||
import * as D from 'common/Dispatcher'
|
||||
import RObject from 'components/RObject/RObject'
|
||||
|
||||
class ResponseRepr extends React.Component<I.IProps, I.IState> {
|
||||
private listeners: string[]
|
||||
constructor(props: I.IProps) {
|
||||
super(props)
|
||||
this.state = {
|
||||
response: props.store.get(D.ActionTypes.UPDATE_RESPONSE)
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.listeners = [
|
||||
D.register(D.ActionTypes.UPDATE_RESPONSE, (response) => {
|
||||
this.setState({ response })
|
||||
}),
|
||||
|
||||
D.register(D.ActionTypes.UPDATE_VIEWKEY, (viewKey) => {
|
||||
this.setState({ response: this.state.response[viewKey] })
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.listeners.forEach(listener => D.AppDispatcher.unregister(listener))
|
||||
}
|
||||
|
||||
private getRObjectList() {
|
||||
const { response } = this.state
|
||||
if (response && response.constructor === Array) {
|
||||
return response.map((row, i) => {
|
||||
return (<RObject key={`row-${i}`} className={css.obj} data={row} />)
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<RObject className={css.obj} data={response} />
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const classNames = [
|
||||
css.ResponseRepr,
|
||||
this.props.className
|
||||
].join(' ')
|
||||
|
||||
const repr = this.getRObjectList()
|
||||
|
||||
return (
|
||||
<div className={classNames}>
|
||||
{repr}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ResponseRepr
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react'
|
||||
import * as css from './App.css'
|
||||
import Header from 'components/Header/Header'
|
||||
import KeyList from 'components/KeyList/KeyList'
|
||||
import DataTable from 'components/DataTable/DataTable'
|
||||
import ResponseRepr from 'components/ResponseRepr/ResponseRepr'
|
||||
import axios, { AxiosResponse } from 'axios'
|
||||
import { Store } from 'common/Dispatcher'
|
||||
|
||||
@@ -42,7 +42,7 @@ class App extends React.Component<TProps> {
|
||||
<div className={css.content}>
|
||||
<KeyList className={[css.scrollable, css.keyList].join(' ')}
|
||||
{...this.props} />
|
||||
<DataTable className={[css.scrollable, css.table].join(' ')}
|
||||
<ResponseRepr className={[css.scrollable, css.table].join(' ')}
|
||||
{...this.props} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"eofline": false,
|
||||
"forin": true,
|
||||
"indent": [ true, "spaces" ],
|
||||
"interface-name": [true, "never-prefix"],
|
||||
"interface-name": [false], // true, "never-prefix"
|
||||
"jsdoc-format": true,
|
||||
"jsx-no-lambda": false,
|
||||
"jsx-no-multiline-js": false,
|
||||
|
||||
Reference in New Issue
Block a user