mobx-react#inject TypeScript Examples
The following examples show how to use
mobx-react#inject.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx From config-generator with MIT License | 6 votes |
@inject('sourcesListStore', 'destinationsListStore')
@observer
class Destinations extends Component<IDestinationsProps> {
public render() {
return (
<Container className="Destinations">
<DestinationsCatalogue />
<ConfiguredDestinations />
</Container>
);
}
}
Example #2
Source File: banner.tsx From config-generator with MIT License | 6 votes |
@inject(
'messagesStore'
)
@observer
class Banner extends Component<{messagesStore?:IMessageStore}> {
public render() {
const { messagesStore } = this.props;
return (
<Container move={messagesStore!.isAnimating} onAnimationEnd={() => { messagesStore!.setIsAnimating(false) }}>
<Label color="#FF0000">
We highly recommend signing up for RudderStack Cloud to get access to features such as Transformations, Live Events, Warehouse Syncs, and more.
</Label>
<Flex style={{ paddingTop: '20px' }}>
<Button type="primary" shape="round" href="https://app.rudderstack.com"> Try Now </Button>
</Flex>
</Container>
);
}
}
Example #3
Source File: MainStore.ts From jmix-frontend with Apache License 2.0 | 5 votes |
export function injectMainStore<T extends IReactComponent>(target: T): T & IWrappedComponent<T> {
return inject(MainStore.NAME)(target);
}
Example #4
Source File: index.tsx From config-generator with MIT License | 5 votes |
@inject('destinationDefsListStore')
@observer
export default class DestinationsCatalogue extends React.Component<
IDestinationsCatalogueProps,
IDestinationsCatalogueState
> {
constructor(props: IDestinationsCatalogueProps) {
super(props);
this.state = {
modalVisible: false,
filteredDestinationDefs: [],
};
}
handleCancel = () => {
this.setState({ modalVisible: false });
};
onClick = (destinationDef: any) => {
// Add a modal and open it on click.
this.setState({ modalVisible: true, selected: destinationDef });
};
componentDidMount() {
const { destinationDefsListStore } = this.props;
if (destinationDefsListStore) {
const destinationDefs = destinationDefsListStore!.destinationDefs;
const destinationSettingsArr = Object.keys(formTemplatesMap);
const filteredArr = [] as Array<object>;
destinationDefs.map(def => {
if (destinationSettingsArr.includes(def.name)) {
filteredArr.push(def);
}
});
this.setState({ filteredDestinationDefs: filteredArr });
}
}
public render() {
const { destinationDefsListStore } = this.props;
const { selected, filteredDestinationDefs } = this.state;
if (destinationDefsListStore && filteredDestinationDefs) {
return (
<div>
<Drawer
visible={this.state.modalVisible}
onClose={this.handleCancel}
width={'40%'}
>
<DestinationConfigure destinationDef={selected} />
</Drawer>
<Heading>
<HeaderDiv color={theme.color.primary}>Destinations</HeaderDiv>
<LabelMedium color={theme.color.grey300}>
{destinationDefsListStore!.destinationDefs.filter(dest => !dest.config.preview).length}
Available
</LabelMedium>
</Heading>
<IconCardList
type="destination"
selectionMode="none"
icons={filteredDestinationDefs.map((destinationDef: any) => ({
id: destinationDef.id,
type: destinationDef.name,
title: destinationDef.displayName,
onClick: () => this.onClick(destinationDef),
}))}
onSelectionChange={() => {}}
/>
</div>
);
}
}
}
Example #5
Source File: index.tsx From config-generator with MIT License | 5 votes |
@inject(
'messagesStore',
)
@observer
class Sidebar extends React.Component<ISidebarProps> {
public render() {
const {messagesStore} = this.props;
return (
<Sider trigger={null} collapsible={true} collapsed={false}>
<AvatarContainer>
<SidebarAvatar icon="user" />
<UserName>RUDDERSTACK</UserName>
</AvatarContainer>
<SidebarLinksContainer>
<SidebarLink to="/home" exact>
<Svg name="connection" />
<span>Connections</span>
</SidebarLink>
<SidebarLink to="/sources">
<Svg name="source" />
<span>Sources</span>
</SidebarLink>
<SidebarLink to="/destinations">
<Svg name="destination" />
<span>Destinations</span>
</SidebarLink>
<Tooltip placement="right" title="Please try Ruderstack Control Plane for this feature">
<div onClick = {()=> {if(messagesStore) {
messagesStore.setIsAnimating(true)}}} >
<SidebarLink dim to="/transformation">
<Svg name="transformation" />
<span>Transformations</span>
</SidebarLink>
</div>
</Tooltip>
<Tooltip placement="bottom" title="Please try Ruderstack Control Plane for this feature">
<div onClick = {()=> {if(messagesStore) {
messagesStore.setIsAnimating(true)}}} >
<SidebarLink dim to="/syncs">
<Svg name="sync" />
<span> Syncs </span>
</SidebarLink>
</div>
</Tooltip>
</SidebarLinksContainer>
</Sider>
);
}
}
Example #6
Source File: index.tsx From config-generator with MIT License | 5 votes |
@inject('sourceDefinitionsListStore')
@observer
export default class SourcesCatalogue extends React.Component<
ISourcesCatalogueProps,
ISourcesCatalogueState
> {
constructor(props: ISourcesCatalogueProps) {
super(props);
this.state = {
modalVisible: false,
};
}
handleCancel = () => {
this.setState({ modalVisible: false });
};
onClick = (sourceDef: any) => {
// Add a modal and open it on click.
this.setState({ modalVisible: true, selected: sourceDef });
};
public render() {
const { sourceDefinitionsListStore } = this.props;
const { selected } = this.state;
if (sourceDefinitionsListStore)
return (
<div>
<Drawer
visible={this.state.modalVisible}
onClose={this.handleCancel}
width={'40%'}
>
<SourceConfigure sourceDef={selected} />
</Drawer>
<Heading>
<HeaderDiv color={theme.color.primary}>Sources</HeaderDiv>
<LabelMedium color={theme.color.grey300}>
{sourceDefinitionsListStore!.sourceDefinitions.length}
Available
</LabelMedium>
</Heading>
<IconCardList
type="source"
selectionMode="none"
icons={sourceDefinitionsListStore.sourceDefinitions.map(
sourceDef => ({
id: sourceDef.id,
type: sourceDef.name,
title: sourceDef.name,
onClick: () => this.onClick(sourceDef),
}),
)}
onSelectionChange={() => {}}
/>
</div>
);
}
}
Example #7
Source File: index.tsx From generator-earth with MIT License | 5 votes |
@inject('detailsStore','commonTableStore')
@observer
class Home extends React.Component<IProps> {
render() {
const { setParamsStr, paramsStr, setRequestStr, requestStr, setLoading, getPage2Data } = this.props.detailsStore;
return (
<div>
<CommonTableList
FT={FT}
type="get"
url={URL}
isShowLoading={true}
sourceId={SOURCE_ID}
pagination={{
pageNo: 1,
pageSize: 3
}}
commonTableStore={this.props.commonTableStore}
/>
<h1>下面按钮展示了,进行对表格的其他自定义操作</h1>
<ul>
<li>
<Button onClick={setParamsStr}>获取当前所有的参数列表</Button>
<p>{paramsStr}</p>
</li>
<li>
<Button onClick={setRequestStr}>获取当前请求的url和type</Button>
<p>{requestStr}</p>
</li>
<li>
<Button onClick={setLoading}>手动展示加载loading</Button>
</li>
<li>
<Button style={{ marginTop: 20 }} onClick={getPage2Data}>根据当前已有的参数请求第二页的数据</Button>
</li>
</ul>
</div>
)
}
}
Example #8
Source File: helpers.ts From companion-kit with MIT License | 5 votes |
export function injectViewModelsMulti(inner: ViewModelInjectorMulti) {
return inject(getViewModelMulti(inner));
}
Example #9
Source File: helpers.ts From companion-kit with MIT License | 5 votes |
export function injectViewModel(inner: ViewModelInjector) {
return inject(getViewModel(inner));
}
Example #10
Source File: Instance.tsx From jmix-frontend with Apache License 2.0 | 5 votes |
withDataInstance = (entityName: string, opts: DataInstanceOptions = {loadImmediately: true}) => <T extends IReactComponent>(target: T) => {
return inject(() => {
const dataInstance = new DataInstanceStore(entityName, opts.view, opts.stringIdName);
return {dataInstance}
})(target);
}
Example #11
Source File: Collection.tsx From jmix-frontend with Apache License 2.0 | 5 votes |
withDataCollection = (entityName: string, opts: DataCollectionOptions = defaultOpts) => <T extends IReactComponent>(target: T) => {
return inject(() => {
const dataCollection = createStore(entityName, opts);
return {dataCollection}
})(target);
}
Example #12
Source File: index.tsx From config-generator with MIT License | 4 votes |
@inject('sourcesListStore', 'destinationsListStore', 'messagesStore')
@observer
class SourceDetails extends Component<IConfiguredSourcesProps, any> {
constructor(props: IConfiguredSourcesProps) {
super(props);
this.state = {
sourceId: props.match && props.match.params.id,
stats: [],
overview: true,
};
}
public async componentDidMount() {
await this.getStats();
}
public getStats = async () => {
const { sourceId } = this.state;
};
public toggle = async (val: any) => {
this.setState(val);
};
deleteConnection = async (
source: ISourceStore,
destination: IDestinationStore,
) => {
const { destinationsListStore, messagesStore } = this.props;
try {
await destinationsListStore.rootStore.connectionsStore.removeConnections(
source,
destination,
);
messagesStore.showSuccessMessage('Connection deletion successful');
} catch (error) {
messagesStore.showErrorMessage('Failed to delete connection');
}
};
deleteSource = async (source: ISourceStore) => {
const { sourcesListStore, messagesStore } = this.props;
try {
const isSuccess = await sourcesListStore.deleteSource(source);
if (!isSuccess) {
throw Error('error deleting source');
}
messagesStore.showSuccessMessage('Source deletion successful');
this.props.history.push(`/home`);
} catch (error) {
messagesStore.showErrorMessage('Failed to delete source');
}
};
public renderOverView = () => {
const { sourceId, stats, overview } = this.state;
const { sourcesListStore } = this.props;
const { sources } = sourcesListStore;
const source = sources.find(source => source.id === sourceId);
if (source) {
return (
<>
<div className={'m-b-lg'}>
<SourceView source={source} deleteSource={this.deleteSource} />
</div>
<div className={'m-b-lg'}>
<DestinationView
destinations={source!.destinations}
sourceId={source!.id}
source={source}
deleteConnection={this.deleteConnection}
/>
</div>
</>
);
}
return null;
};
handleExportSourceConfig = () => {
const { sourceId } = this.state;
const { sourcesListStore } = this.props;
const { sources } = sourcesListStore;
const source = sources.find(source => source.id === sourceId);
if (source) {
const sourceConfig = {
source: {
config: source.config,
id: source.id,
name: source.name,
writeKey: source.writeKey,
enabled: source.enabled,
sourceDefinitionId: source.sourceDefinitionId,
deleted: false,
createdAt: Date(),
updatedAt: Date(),
sourceDefinition: source.sourceDef,
// Filter only useNativeSDK enabled destinations and
// includes only includeKeys (from definition) in the config
destinations: source.destinations
.filter(dest => {
return dest.config ? dest.config.useNativeSDK : false;
})
.map(dest => {
return {
id: dest.id,
name: dest.name,
enabled: dest.enabled,
config: dest.filteredConfig(), // Very Very Important to use filterConfig instead of config
destinationDefinition: dest.destinationDefinition,
};
}),
},
metadata: {
version: version,
},
};
fileDownload(
JSON.stringify(sourceConfig, null, 2),
`${source.name}_Source_Config.json`,
);
}
};
public render() {
const { sourceId, stats, overview } = this.state;
const { sourcesListStore } = this.props;
const { sources } = sourcesListStore;
const source = sources.find(source => source.id === sourceId);
return (
<Container>
<Flex flexDirection="row" spaceBetween={true}>
<PageTitle>Source {overview ? 'Details' : 'Debugger'}</PageTitle>
<div style={{ width: '260px' }}>
<ButtonSmall pink onClick={this.handleExportSourceConfig}>
Export Source config
</ButtonSmall>
</div>
</Flex>
<Flex flexDirection="column">{this.renderOverView()}</Flex>
</Container>
);
}
}
Example #13
Source File: index.tsx From config-generator with MIT License | 4 votes |
@inject('sourceDefinitionsListStore')
@observer
export default class SourceCard extends React.Component<
ISourceCardProps,
ISourceCardState
> {
constructor(props: ISourceCardProps) {
super(props);
this.state = {
copied: false,
};
}
onMouseEnter = () => {
this.props.onMouseEnter!(this.props.source);
};
onMouseLeave = () => {
this.props.onMouseLeave!(this.props.source);
};
copyText = (event: any) => {
const { source } = this.props;
event.preventDefault();
navigator.clipboard.writeText(source!.writeKey);
this.setState({ copied: true });
setTimeout(() => {
this.setState({ copied: false });
}, 1000);
};
deleteSource = (e: any) => {
e.preventDefault();
this.props.onDelete!(this.props.source);
};
public render() {
const { source } = this.props;
const { copied } = this.state;
if (source === null) {
return <EmptySourceCard />;
} else {
return (
<Link to={`/sources/${source.id}`}>
<StyledCard
id={`source-${source.id}`}
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
>
<div style={{ flexShrink: 0 }}>
<SourceIcon
source={source.sourceDef.name}
height={theme.iconSize.large}
width={theme.iconSize.large}
/>
</div>
<Content>
<Flex flexDirection="row" spaceBetween>
<LabelDiv>{source.name}</LabelDiv>
</Flex>
{source.enabled && (
<Flex flexDirection="row" spaceBetween>
<div>
<Check />
<EnabledText color={theme.color.green}>Enabled</EnabledText>
</div>
{copied ? (
<Text color={theme.color.grey300}>Write key copied</Text>
) : null}
</Flex>
)}
{!source.enabled && (
<>
<Text color={theme.color.grey300}>Disabled</Text>
</>
)}
<Flex
spaceBetween
className="m-h-sm"
onClick={this.copyText}
title="click to copy"
style={{ minWidth: '300px' }}
>
<Text color={theme.color.grey300}>
Write key {source.writeKey}
</Text>
<div className="p-l-xs">
<Icon type="copy" style={{ color: theme.color.grey300 }} />
</div>
</Flex>
</Content>
<Flex
flexDirection="row"
alignItems="flex-end"
style={{
width: '1px',
paddingRight: '35px',
backgroundColor: 'red',
}}
id={`fake-source-${source!.id}`}
/>
</StyledCard>
</Link>
);
}
}
}
Example #14
Source File: addSource.tsx From config-generator with MIT License | 4 votes |
@inject(
'sourceDefinitionsListStore',
'sourcesListStore',
'destinationsListStore',
'messagesStore',
)
@observer
class AddSource extends React.Component<IAddSourceProps, any> {
constructor(props: IAddSourceProps) {
super(props);
const parsed = queryString.parse(this.props.location.search);
this.state = {
ref: (props.match && props.match.params.id) || null,
currentStep: parsed.sourceDefId ? 1 : 0,
enableNextButton: false,
sourceName: '',
selectedSourceDefintionId: parsed.sourceDefId || null,
showNextLoader: false,
filteredSources: [],
};
}
public handleCancel = (event: React.MouseEvent<HTMLElement>) => {
if (this.props.history.length > 2) {
this.props.history.goBack();
} else {
this.props.history.push('/');
}
};
async componentDidMount() {
const filteredSources = await this.props.sourceDefinitionsListStore.getFilteredSourceDefinitions();
this.setState({ filteredSources });
}
createConnection = async (source: any) => {
const { ref } = this.state;
const { destinationsListStore } = this.props;
if (ref != null) {
const destination = destinationsListStore.destinations.find(
dest => dest.id === ref,
);
await destinationsListStore.createDestinationConnections(destination, [
source.id,
]);
}
};
public handleNext = async (event?: React.MouseEvent<HTMLElement>) => {
try {
if (this.state.currentStep === 1) {
this.setState({ showNextLoader: true });
const source = await this.props.sourcesListStore.createSource({
name: this.state.sourceName,
sourceDefinitionId: this.state.selectedSourceDefintionId,
});
this.props.messagesStore.showSuccessMessage('Added source');
if (this.state.ref != null) {
this.createConnection(source);
this.props.history.push(`/destinations/${this.state.ref}`);
} else {
this.props.history.push(`/sources/${source.id}`);
}
} else {
this.setState({
currentStep: this.state.currentStep + 1,
enableNextButton: false,
});
}
} catch (error) {
this.setState({ showNextLoader: false });
this.props.messagesStore.showErrorMessage(
'Failed to add source. Try again after sometime',
);
//throw Error(error); // ToDo how will bugsnag error-boundry know of this?
}
};
public handleSelection = (selectedMap: any) => {
const sourceDefId = Object.keys(selectedMap)[0];
if (selectedMap[sourceDefId]) {
this.setState({
enableNextButton: true,
selectedSourceDefintionId: sourceDefId,
});
} else {
this.setState({
enableNextButton: false,
selectedSourceDefintionId: null,
});
}
};
public handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
let enableNextButton = event.target.value.length > 0;
this.setState({ sourceName: event.target.value, enableNextButton });
};
public handleKeyDown = (e: any) => {
if (e.key === 'Enter' && this.state.enableNextButton) {
this.handleNext();
}
};
public render() {
const { filteredSources } = this.state;
if (filteredSources.length > 0) {
return (
<StyledContainer>
<HeaderDiv className="p-b-lg">Add Source</HeaderDiv>
<Steps
onCancel={this.handleCancel}
onNext={this.handleNext}
current={this.state.currentStep}
enableNext={this.state.enableNextButton}
showNextLoader={this.state.showNextLoader}
>
<Step>
<HeaderDiv className="text-center p-t-lg">
Choose a source
</HeaderDiv>
<IconCardListContainer>
<IconCardList
type="source"
selectionMode="single"
icons={filteredSources.map((s: any) => ({
id: s.id,
type: s.name,
title: s.name,
}))}
onSelectionChange={this.handleSelection}
/>
</IconCardListContainer>
</Step>
<Step>
<HeaderDiv className="text-center p-t-lg">
Name your source
</HeaderDiv>
<SourceNameInputContainer>
<Input
placeholder="eg. Android Dev"
onChange={this.handleNameChange}
autoFocus
onKeyDown={this.handleKeyDown}
/>
<TextDiv
color={this.props.theme.color.grey300}
className="p-t-sm"
>
Identifies this source within your workspace, and typically
includes the product area and environment.
</TextDiv>
</SourceNameInputContainer>
</Step>
</Steps>
</StyledContainer>
);
} else {
return <div></div>;
}
}
}
Example #15
Source File: home.tsx From config-generator with MIT License | 4 votes |
@inject(
'sourcesListStore',
'destinationsListStore',
'connectionsStore',
'sourceDefinitionsListStore',
'destinationDefsListStore',
'messagesStore',
)
@observer
class Home extends Component<IHomeProps> {
public async componentDidMount() {
const {
sourcesListStore,
destinationsListStore,
connectionsStore,
sourceDefinitionsListStore,
destinationDefsListStore,
} = this.props;
sourcesListStore.loadAndSave();
destinationsListStore.loadAndSave();
connectionsStore.loadAndSave();
await Promise.all([
sourceDefinitionsListStore.getSourceDefinitions(),
destinationDefsListStore.getDestinationDefs(),
]);
}
public isReadyToRender() {
return (
this.props.sourceDefinitionsListStore.sourceDefinitions.length > 0 &&
this.props.destinationDefsListStore.destinationDefs.length > 0
);
}
handleClose(type: string) {
const { messagesStore } = this.props;
if (type == 'error') {
messagesStore.setError(false);
}
if (type === 'success') {
messagesStore.setSuccess(false);
}
}
getAlertContainer(messagesStore: MessagesStore) {
if (messagesStore.isError) {
return (
<StyledNotification>
<Alert
message={messagesStore.infoString}
type="error"
showIcon
closable
afterClose={() => this.handleClose('error')}
/>
</StyledNotification>
);
}
if (messagesStore.isSuccess) {
return (
<StyledNotification>
<Alert
message={messagesStore.infoString}
type="success"
showIcon
closable
afterClose={() => this.handleClose('success')}
/>
</StyledNotification>
);
}
return null;
}
public renderError(messagesStore: IMessageStore) {
if (messagesStore.isError) {
message.error(messagesStore.infoString);
}
if (messagesStore.isSuccess) {
message.success(messagesStore.infoString);
}
}
public renderLayout() {
if (this.isReadyToRender()) {
return <RenderLayout></RenderLayout>;
} else {
return (
<Layout>
<Skeleton active />
</Layout>
);
}
}
public render() {
const { messagesStore } = this.props;
return (
<Router>
<Layout style={{ minHeight: '100vh' }}>
<Sidebar />
<Layout>
<Banner/>
{this.getAlertContainer(messagesStore)}
{this.renderLayout()}
</Layout>
</Layout>
</Router>
);
}
}
Example #16
Source File: index.tsx From config-generator with MIT License | 4 votes |
@inject('destinationsListStore', 'messagesStore')
@observer
class DestinationsList extends React.Component<
IDestinationsListProps,
IDestinationsListState
> {
linesMap: any;
constructor(props: IDestinationsListProps) {
super(props);
this.state = {};
this.linesMap = props.linesMap;
}
onMouseEnter = (destination: any) => {
Object.keys(this.linesMap).forEach(key => {
let destId = key.split('-')[1];
if (destId == destination.id) {
this.linesMap[key].setOptions({
color: this.props.theme.color.primary,
});
} else {
this.linesMap[key].setOptions({
size: 0.01,
});
}
});
};
onMouseLeave = (destination: any) => {
Object.values(this.linesMap).forEach((line: any) => {
line.setOptions({
color: this.props.theme.color.grey100,
size: 4,
});
});
};
deleteDestination = (destination: IDestinationStore) => {
const { destinationsListStore, messagesStore } = this.props;
try {
destinationsListStore!.deleteDestination(destination);
messagesStore!.showSuccessMessage('Delete destination successful');
} catch (error) {
messagesStore!.showErrorMessage('Destination deletion failed');
}
};
public render() {
const { destinationsListStore } = this.props;
const destinations =
destinationsListStore && destinationsListStore.destinations;
return (
<Container style={{ zIndex: 1 }}>
<Header color={theme.color.grey300} className="m-b-md">
Destinations
</Header>
{!destinations || destinations.length === 0 ? (
<div className="p-t-md">
<DestinationCard destination={null} key={undefined} />
</div>
) : (
<div className="p-t-md">
{destinations.map(destination => (
<DestinationCard
destination={destination}
key={destination.name}
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
onDelete={this.deleteDestination}
/>
))}
<Link to="/destinations/setup" className="d-block p-t-sm">
<Plus />
<ButtonText>ADD DESTINATION</ButtonText>
</Link>
</div>
)}
</Container>
);
}
}
Example #17
Source File: index.tsx From config-generator with MIT License | 4 votes |
@inject('sourcesListStore')
@observer
class SourcesList extends React.Component<ISourcesListProps> {
linesMap: any;
constructor(props: ISourcesListProps) {
super(props);
this.state = {};
}
componentDidMount() {
this.linesMap = this.props.linesMap;
}
/* componentWillUnmount() {
this.removeDestConnectionLines();
} */
componentDidUpdate() {
this.linesMap = this.props.linesMap;
}
/* drawDestConnectionLines = () => {
let existingCombos = Object.keys(this.linesMap);
let combos: string[] = [];
this.props.sourcesListStore!.sources.forEach(source => {
source.destinations.forEach(dest => {
if (dest.state != 'deleting') {
combos.push(`${source.id}-${dest.id}`);
}
});
});
existingCombos.forEach(c => {
if (!combos.includes(c)) {
this.linesMap[c].remove();
delete this.linesMap[c];
}
});
combos.forEach(c => {
if (!existingCombos.includes(c)) {
let line = new LeaderLine(
document.getElementById(`fake-source-${c.split('-')[0]}`),
document.getElementById(`fake-destination-${c.split('-')[1]}`),
{ endPlug: 'behind', color: this.props.theme.color.grey100, size: 4 },
);
this.linesMap[c] = line;
}
});
};
removeDestConnectionLines = () => {
Object.values(this.linesMap).forEach((l: any) => l.remove());
this.linesMap = {};
}; */
onMouseEnter = (source: any) => {
Object.keys(this.linesMap).forEach(key => {
if (key.startsWith(source.id)) {
this.linesMap[key].setOptions({
color: this.props.theme.color.primary,
});
} else {
this.linesMap[key].setOptions({
size: 0.01,
});
}
});
};
onMouseLeave = (source: any) => {
Object.values(this.linesMap).forEach((line: any) => {
line.setOptions({
color: this.props.theme.color.grey100,
size: 4,
});
});
};
deleteSource = (source: ISourceStore) => {
// useful logs
// console.log('source is to be deleted');
// console.log(source.name);
const { sourcesListStore } = this.props;
sourcesListStore!.deleteSource(source);
};
public render() {
const { sourcesListStore } = this.props;
const sources = sourcesListStore && sourcesListStore.sources;
return (
<Container id="sources-list" style={{ zIndex: 1 }}>
<Header color={theme.color.grey300} className="m-b-md">
Sources
</Header>
{!sources || sources.length === 0 ? (
<div className="p-t-md">
<SourceCard source={null} key={undefined} />
</div>
) : (
<div className="p-t-md">
{sources.map(source => (
<SourceCard
source={source}
key={source.name}
onDelete={this.deleteSource}
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
/>
))}
<Link to="/sources/setup" className="d-block p-t-sm">
<Plus />
<ButtonText> ADD SOURCE</ButtonText>
</Link>
</div>
)}
</Container>
);
}
}
Example #18
Source File: index.tsx From config-generator with MIT License | 4 votes |
@inject('sourcesListStore', 'destinationsListStore', 'messagesStore')
@observer
class DestinationDetails extends Component<IConfiguredDestinationsProps, any> {
constructor(props: IConfiguredDestinationsProps) {
super(props);
this.state = {
destinationId: props.match && props.match.params.id,
};
}
deleteConnection = async (
source: ISourceStore,
destination: IDestinationStore,
) => {
const { destinationsListStore, messagesStore } = this.props;
try {
await destinationsListStore.rootStore.connectionsStore.removeConnections(
source,
destination,
);
messagesStore.showSuccessMessage('Connection deletion successful');
} catch (error) {
messagesStore.showErrorMessage('Failed to delete connection');
}
};
deleteDestination = async (destination: IDestinationStore) => {
const { destinationsListStore, messagesStore } = this.props;
try {
const isSuccess = await destinationsListStore.deleteDestination(
destination,
);
console.log('isSuccess', isSuccess);
if (!isSuccess) {
throw Error('not successful');
}
messagesStore.showSuccessMessage('Delete destination successful');
this.props.history.push(`/home`);
} catch (error) {
messagesStore.showErrorMessage('Failed to delete destination');
}
};
public render() {
const { destinationId } = this.state;
const { destinationsListStore, messagesStore } = this.props;
const { destinations } = destinationsListStore;
const destination = destinations.find(
destination => destination.id === destinationId,
);
if (destination) {
return (
<Container>
<Flex flexDirection="row" spaceBetween>
<PageTitle>Destination Details</PageTitle>
<div onClick={() => { messagesStore.setIsAnimating(true) }}>
<Tooltip title={"Please try Rudderstack Control Plane for this feature"}>
<Button disabled >
<PlayCircleOutlined />
Live events
</Button>
</Tooltip>
</div>
</Flex>
<CardsView>
<Spacing>
<DestinationView
destination={destination}
deleteDestination={this.deleteDestination}
/>
</Spacing>
<Spacing>
<SourceView
sources={destination!.sources}
destination={destination}
deleteConnection={this.deleteConnection}
/>
</Spacing>
<Spacing></Spacing>
</CardsView>
</Container>
);
}
return null;
}
}
Example #19
Source File: addDestination.tsx From config-generator with MIT License | 4 votes |
@inject('destinationDefsListStore', 'destinationsListStore', 'sourcesListStore')
@observer
class AddDestination extends React.Component<IAddDestinationProps, any> {
constructor(props: IAddDestinationProps) {
super(props);
const parsed = queryString.parse(this.props.location.search);
let selectedSources: any = [];
if (parsed.sourceId) {
const selectedSource = props.sourcesListStore.sources.find(
source => source.id === parsed.sourceId,
);
if (selectedSource) {
selectedSources = [selectedSource];
}
}
this.state = {
currentStep: parsed.destinationDefId ? 1 : 0,
enableNextButton: selectedSources ? true : false,
destinationName: '',
selectedDestDefintionId: parsed.destinationDefId || null,
selectedDestDef:
props.destinationDefsListStore.destinationDefs.filter(
def => def.id === parsed.destinationDefId,
)[0] || null,
selectedSources,
config: {},
showNextLoader: false,
filteredDestinationDefs: [],
};
}
componentDidMount() {
const { destinationDefsListStore } = this.props;
if (destinationDefsListStore) {
const destinationDefs = destinationDefsListStore!.destinationDefs;
const destinationSettingsArr = Object.keys(formTemplatesMap);
const filteredArr = [] as Array<object>;
destinationDefs.map(def => {
if (destinationSettingsArr.includes(def.name)) {
filteredArr.push(def);
}
});
this.setState({ filteredDestinationDefs: filteredArr });
}
}
public enableConnection = async () => {
const { destinationsListStore } = this.props;
const {
destinationName,
config,
selectedDestDef,
selectedSources,
} = this.state;
const dest = await destinationsListStore.createDestination({
name: destinationName,
config: config,
destinationDefinitionId: selectedDestDef.id,
});
await destinationsListStore.createDestinationConnections(
dest,
selectedSources.map((source: any) => source.id),
);
this.setState({ destinationId: dest.id });
};
public handleNext = async (event?: React.MouseEvent<HTMLElement>) => {
const { currentStep } = this.state;
if (currentStep === 3) {
this.setState({ showNextLoader: true });
await this.enableConnection();
this.props.history.push(`/`);
} else {
this.setState({
currentStep: currentStep + 1,
enableNextButton: false,
});
}
};
public handleCancel = (event: React.MouseEvent<HTMLElement>) => {
if (this.props.history.length > 2) {
this.props.history.goBack();
} else {
this.props.history.push('/connections');
}
};
public handleSelection = (selectedMap: any) => {
const destDefId = Object.keys(selectedMap)[0];
if (selectedMap[destDefId]) {
this.setState({
enableNextButton: true,
selectedDestDefintionId: destDefId,
selectedDestDef: this.state.filteredDestinationDefs.filter(
(def: any) => def.id === destDefId,
)[0],
});
} else {
this.setState({
enableNextButton: false,
selectedDestDefintionId: null,
});
}
};
public handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
let enableNextButton = event.target.value.length > 0;
this.setState({ destinationName: event.target.value, enableNextButton });
};
public handleSourceSelection = (selectedMap: any) => {
let sourceIds = Object.keys(selectedMap).filter(k => selectedMap[k]);
if (sourceIds.length < 1) {
return this.setState({ enableNextButton: false, selectedSources: [] });
}
this.setState({
enableNextButton: true,
selectedSources: this.props.sourcesListStore.sources.filter(
source => sourceIds.indexOf(source.id) > -1,
),
});
};
public handleKeyDown = (e: any) => {
if (e.key === 'Enter' && this.state.enableNextButton) {
this.handleNext();
}
};
public handleConfigChange = (config: any) => {
this.setState({ config });
};
// public handleTransformationSelection = (
// transformation: ITransformationStore | null,
// ) => {
// this.setState({ transformation });
// };
public render() {
const {
selectedSources,
selectedDestDef,
destinationId,
filteredDestinationDefs,
} = this.state;
let icon;
if (selectedSources.length > 0) {
icon = selectedSources.map((source: any) => source.sourceDef.name);
} else {
icon = null;
}
return (
<StyledContainer>
<HeaderDiv className="p-b-lg">Add Destination</HeaderDiv>
<Steps
onCancel={this.handleCancel}
onNext={this.handleNext}
current={this.state.currentStep}
enableNext={this.state.enableNextButton}
showNextLoader={this.state.showNextLoader}
>
<Step>
<AddDestDialogBody>
<Flex justifyContentCenter className="p-t-lg" alignItems="center">
{icon != null ? (
<DottedCircle iconName={icon} />
) : (
<DottedCircle />
)}
<div className="p-l-sm p-r-sm">
<Svg name="forward-thick" />
</div>
{selectedDestDef != null ? (
<DottedCircle iconName={selectedDestDef!.name} destination />
) : (
<DottedCircle solid />
)}
</Flex>
<HeaderDiv className="text-center p-t-md">
Choose a destination
</HeaderDiv>
<IconCardListContainer>
<IconCardList
type="destination"
selectionMode="single"
icons={filteredDestinationDefs.map((def: any) => ({
id: def.id,
type: def.name,
title: def.displayName,
}))}
onSelectionChange={this.handleSelection}
/>
</IconCardListContainer>
</AddDestDialogBody>
</Step>
<Step>
<AddDestDialogBody>
<Flex justifyContentCenter className="p-t-lg" alignItems="center">
{icon ? <DottedCircle iconName={icon} /> : <DottedCircle />}
<div className="p-l-sm p-r-sm">
<Svg name="forward-thick" />
</div>
{selectedDestDef != null ? (
<DottedCircle iconName={selectedDestDef!.name} destination />
) : (
<DottedCircle solid />
)}
</Flex>
<HeaderDiv className="text-center p-t-md">
Name destination
</HeaderDiv>
<DestNameInputContainer>
<Input
placeholder="eg. Google Analytics Dev"
onChange={this.handleNameChange}
autoFocus
onKeyDown={this.handleKeyDown}
/>
<TextDiv
color={this.props.theme.color.grey300}
className="p-t-sm"
>
Pick a name to help you identify this destination.
</TextDiv>
</DestNameInputContainer>
</AddDestDialogBody>
</Step>
<Step>
{this.state.selectedDestDef && (
<AddDestDialogBody>
<Flex
justifyContentCenter
className="p-t-lg"
alignItems="center"
>
<DottedCircle solid />
<Flex className="selected-source-icons" alignItems="center">
{this.state.selectedSources.map(
(source: ISourceStore, index: number) => {
return (
<IconCircle
name={source.sourceDef.name}
listIndex={index}
/>
);
},
)}
</Flex>
<div className="p-l-sm p-r-sm">
<Svg name="forward-thick" />
</div>
<IconCircle
name={this.state.selectedDestDef!.name}
destination
/>
</Flex>
<HeaderDiv className="text-center p-t-md">
Connect Sources
</HeaderDiv>
<IconCardListContainer>
{this.props.sourcesListStore.sources.length === 0 ? (
<Flex justifyContentCenter>
<EmptySourceCard />
</Flex>
) : (
<IconCardList
type="source"
selectionMode="multi"
destinationDefConfig={
this.state.selectedDestDef.config.sourceType
}
icons={this.props.sourcesListStore.sources.map(
source => ({
id: source.id,
type: source.sourceDef.name,
title: source.name,
selected:
selectedSources.length > 0
? source.id === selectedSources[0].id
? true
: false
: false,
}),
)}
onSelectionChange={this.handleSourceSelection}
/>
)}
</IconCardListContainer>
</AddDestDialogBody>
)}
</Step>
<Step>
{this.state.selectedDestDef && (
<FormBody>
<Flex
justifyContentCenter
className="p-t-lg"
alignItems="center"
>
<DottedCircle solid />
<Flex className="selected-source-icons" alignItems="center">
{this.state.selectedSources.map(
(source: ISourceStore, index: number) => {
return (
<IconCircle
name={source.sourceDef.name}
listIndex={index}
/>
);
},
)}
</Flex>
<div className="p-l-sm p-r-sm">
<Svg name="forward-thick" />
</div>
<IconCircle
name={this.state.selectedDestDef!.name}
destination
/>
</Flex>
<FormContainer>
<DestinationSettings
destName={this.state.selectedDestDef!.name}
onSettingsChange={this.handleConfigChange}
setRequirementsState={(reqsState: any) =>
this.setState({ enableNextButton: reqsState })
}
></DestinationSettings>
</FormContainer>
</FormBody>
)}
</Step>
</Steps>
</StyledContainer>
);
}
}
Example #20
Source File: index.tsx From config-generator with MIT License | 4 votes |
@inject(
'sourcesListStore',
'destinationsListStore',
'sourceDefinitionsListStore',
'destinationDefsListStore',
'connectionsStore',
)
@observer
class Connections extends Component<IConnectionsProps, any> {
linesMap: any;
constructor(props: IConnectionsProps) {
super(props);
this.linesMap = {};
this.state = {};
}
componentDidMount() {
this.drawSourceConnectionLines();
}
componentWillUnmount() {
this.removeSourceConnectionLines();
}
drawSourceConnectionLines = () => {
let existingCombos = Object.keys(this.linesMap);
let combos: string[] = [];
this.props.sourcesListStore!.sources.forEach(source => {
source.destinations.forEach(dest =>
combos.push(`${source.id}-${dest.id}`),
);
});
existingCombos.forEach(c => {
if (!combos.includes(c)) {
this.linesMap[c].remove();
}
});
combos.forEach(c => {
if (!existingCombos.includes(c)) {
let line = new LeaderLine(
document.getElementById(`fake-source-${c.split('-')[0]}`),
document.getElementById(`fake-destination-${c.split('-')[1]}`),
{ endPlug: 'behind', color: theme.color.grey100, size: 4 },
);
this.linesMap[c] = line;
}
});
};
removeSourceConnectionLines = () => {
Object.values(this.linesMap).forEach((l: any) => l.remove());
};
buildWorkspaceConfig = () => {
const workspaceConfig = {
sources: [] as any,
metadata: {
sourceListStore: this.props.sourcesListStore.returnWithoutRootStore(),
destinationListStore: this.props.destinationsListStore.returnWithoutRootStore(),
connectionsStore: this.props.connectionsStore.returnWithoutRootStore(),
version,
},
};
this.props.sourcesListStore!.sources.forEach(source => {
let obj = {
config: source.config,
id: source.id,
name: source.name,
writeKey: source.writeKey,
enabled: source.enabled,
sourceDefinitionId: source.sourceDefinitionId,
deleted: false,
createdAt: Date(),
updatedAt: Date(),
sourceDefinition: source.sourceDef,
destinations: source.destinations.map(dest => {
return {
...dest,
isProcessorEnabled:
dest.enabled &&
source.enabled &&
!dest.config.useNativeSDK &&
!dest.destinationDefinition.config.deviceModeOnly,
rootStore: null,
};
}),
};
workspaceConfig.sources.push(obj);
});
return workspaceConfig;
};
handleExportWorkspaceConfig = () => {
const workspaceConfig = this.buildWorkspaceConfig();
fileDownload(
JSON.stringify(workspaceConfig, null, 2),
'workspaceConfig.json',
);
};
handleSaveWorkspaceConfig = () => {
const workspaceConfig = this.buildWorkspaceConfig();
apiServerCaller().post('/saveToFile', { workspaceConfig });
};
handleFileChosen = (event: any) => {
const file = event.target.files[0];
let fileReader = new FileReader();
fileReader.onloadend = e => {
const content = fileReader.result;
this.setupWorkspace(content);
};
fileReader.readAsText(file);
};
setupWorkspace = (jsonContent: any) => {
const content = JSON.parse(jsonContent);
this.props.sourcesListStore!.loadImportedFile(
content.metadata.sourceListStore.sources,
);
this.props.destinationsListStore!.loadImportedFile(
content.metadata.destinationListStore.destinations,
);
this.props.connectionsStore!.loadImportedFile(
content.metadata.connectionsStore.connections,
);
this.props.connectionsStore!.setConnections(content.sources);
};
public render() {
const isSaveToFileEnabled =
(process.env.REACT_APP_IS_SAVE_TO_FILE_ENABLED || '').toLowerCase() ===
'true';
return (
<Container>
<Flex flexDirection="column">
<Heading>
<Flex flexDirection="row" spaceBetween>
<HeaderDiv color={theme.color.primary}>Connections</HeaderDiv>
<Flex
flexDirection="row"
style={{ justifyContent: 'space-around' }}
>
<ButtonPrimary
onClick={this.handleExportWorkspaceConfig}
style={{ height: '40px', fontSize: theme.fontSize.sm }}
>
Export
</ButtonPrimary>
{isSaveToFileEnabled && (
<ButtonPrimary
className="m-l-sm"
onClick={this.handleSaveWorkspaceConfig}
style={{ height: '40px', fontSize: theme.fontSize.sm }}
>
Save
</ButtonPrimary>
)}
<ImportInputButton
type="file"
name="file"
onChange={this.handleFileChosen}
id="myuniqueid"
/>
<ImportConfigContainer htmlFor="myuniqueid">
IMPORT
</ImportConfigContainer>
</Flex>
</Flex>
</Heading>
<BodyContainer>
<SourcesList linesMap={this.linesMap} />
<DestinationsList linesMap={this.linesMap} />
</BodyContainer>
</Flex>
</Container>
);
}
}
Example #21
Source File: index.tsx From config-generator with MIT License | 4 votes |
@inject('destinationsListStore', 'sourcesListStore')
@observer
class ConnectSources extends React.Component<IConnectSourcesProps, any> {
constructor(props: IConnectSourcesProps) {
super(props);
const propsDestinationId = props.match.params.id;
let destination: any = undefined;
if (propsDestinationId) {
var selectedDestination = props.destinationsListStore.destinations.find(
destination => destination.id === propsDestinationId,
);
if (selectedDestination) {
destination = selectedDestination;
}
}
this.state = {
selectedSources: [],
destination,
refinedSourceList: [],
};
}
public componentDidMount() {
const { sourcesListStore } = this.props;
const { refinedSourceList, destination } = this.state;
const destinationId = destination.id;
const sourcesList = sourcesListStore.sources;
for (let sourceCount = 0; sourceCount < sourcesList.length; sourceCount++) {
var check = true;
for (let i = 0; i < sourcesList[sourceCount].destinations.length; i++) {
if (sourcesList[sourceCount].destinations[i].id === destinationId) {
check = false;
}
}
if (check === true) {
refinedSourceList.push(sourcesList[sourceCount]);
}
}
this.setState({ refinedSourceList });
}
public handleSourceSelection = (selectedMap: any) => {
let sourceIds = Object.keys(selectedMap).filter(k => selectedMap[k]);
if (sourceIds.length < 1) {
return this.setState({ enableNextButton: false, selectedSources: [] });
}
this.setState({
selectedSources: this.props.sourcesListStore.sources.filter(
source => sourceIds.indexOf(source.id) > -1,
),
});
};
public handleCancel = () => {
if (this.props.history.length > 2) {
this.props.history.goBack();
} else {
this.props.history.push('/connections');
}
};
public handleSubmit = async () => {
const { destination, selectedSources } = this.state;
let destinationId = destination.id;
const { destinationsListStore } = this.props;
if (selectedSources.length > 0) {
let selectedDestination = destinationsListStore.destinations.find(
destination => destination.id === destinationId,
);
if (selectedDestination) {
selectedDestination.sources.push(selectedSources);
}
await this.props.destinationsListStore.createDestinationConnections(
selectedDestination,
selectedSources.map((source: any) => source.id),
);
this.props.history.push(`/`);
}
};
renderIconCardListContainer = () => {
const { selectedSources, destination, refinedSourceList } = this.state;
if (refinedSourceList.length > 0) {
return (
<IconCardListContainer>
{this.props.sourcesListStore.sources.length === 0 ? (
<Flex justifyContentCenter>
<EmptySourceCard destinationId={destination.id} />
</Flex>
) : (
<IconCardList
type="source"
selectionMode="multi"
destinationDefConfig={
destination.destinationDefinition.config.sourceType
}
icons={refinedSourceList.map((source: any) => ({
id: source.id,
type: source.sourceDef.name,
title: source.name,
selected:
selectedSources.length > 0
? source.id === selectedSources[0].id
? true
: false
: false,
}))}
onSelectionChange={this.handleSourceSelection}
/>
)}
</IconCardListContainer>
);
}
return (
<IconCardListContainer>
<Flex justifyContentCenter>
<EmptySourceCard destinationId={destination.id} />
</Flex>
</IconCardListContainer>
);
};
renderModalFooter = () => {
const { selectedSources, destination, refinedSourceList } = this.state;
if (refinedSourceList.length > 0) {
return (
<>
<BorderLine />
<Flex flexDirection="row" spaceBetween className="p-h-md p-v-xs">
<ButtonSecondary onClick={this.handleCancel}>
Cancel
</ButtonSecondary>
<ButtonSecondary onClick={this.handleSubmit}>
Submit
</ButtonSecondary>
</Flex>
</>
);
}
};
public render() {
const { selectedSources, destination, refinedSourceList } = this.state;
return (
<StyledContainer>
<HeaderDiv className="p-b-lg"></HeaderDiv>
<AddDestDialogBody>
<Flex justifyContentCenter className="p-t-lg" alignItems="center">
<DottedCircle solid />
<Flex alignItems="center">
{this.state.selectedSources.map(
(source: ISourceStore, index: number) => {
return (
<IconCircle
name={source.sourceDef.name}
listIndex={index}
/>
);
},
)}
</Flex>
<div className="p-l-sm p-r-sm">
<Svg name="forward-thick" />
</div>
<IconCircle
name={destination.destinationDefinition.name}
destination
/>
</Flex>
<HeaderDiv className="text-center p-t-md">Connect Sources</HeaderDiv>
{this.renderIconCardListContainer()}
{this.renderModalFooter()}
</AddDestDialogBody>
</StyledContainer>
);
}
}
Example #22
Source File: index.tsx From config-generator with MIT License | 4 votes |
@inject('sourcesListStore', 'destinationsListStore')
@observer
class ConfiguredSources extends Component<
IConfiguredSourcesProps,
IConfiguredSourcesState
> {
constructor(props: IConfiguredSourcesProps) {
super(props);
this.state = {
count: 1,
active: 1,
inactive: 0,
};
}
dataSource: any = [];
columns = [
{
title: '',
dataIndex: 'icon',
key: 'icon',
},
{
title: 'Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Status',
dataIndex: 'status',
key: 'status',
},
{
title: 'Destination',
dataIndex: 'destination',
key: 'destination',
},
];
public async componentDidMount() {
const { sourcesListStore } = this.props;
await this.constructDataSource(sourcesListStore!.sources);
}
public constructDataSource = (sources: any) => {
this.dataSource = [];
let activeCount = 0;
for (let i = 0; i < sources.length; i++) {
const destinationList: any = [];
const obj: any = {};
obj.key = i;
for (let dcount = 0; dcount < sources[i].destinations.length; dcount++) {
const a = (
<IconSpacing key={`${sources[i].destinations[dcount].id}`}>
<DestinationIcon
destination={
sources[i].destinations[dcount].destinationDefinition.name
}
/>
</IconSpacing>
);
destinationList.push(a);
}
if (sources[i].enabled) {
activeCount++;
}
obj.destination = destinationList;
obj.icon = <SourceIcon source={sources[i].sourceDef.name} />;
obj.id = sources[i].id;
obj.name = sources[i].name;
obj.status = sources[i].enabled ? 'Enabled' : 'Disabled';
this.dataSource.push(obj);
}
this.setState({ count: sources.length });
this.setState({ active: activeCount });
this.setState({ inactive: this.state.count - this.state.active });
};
handleRowClick = (record: any, Index: Number) => {
const { history } = this.props;
history!.push(`/sources/${record.id}`);
};
public renderAddSource = () => {
return (
<Link to="/sources/setup">
<Flex flexDirection={'row'}>
<IconStyle>
<Svg name="plus" />
</IconStyle>
<AddSource>Add source</AddSource>
</Flex>
</Link>
);
};
public render() {
const { count, active, inactive } = this.state;
return (
<Container>
<Flex flexDirection="column">
<MainHeading>Configured Sources</MainHeading>
<HeadingTag className={'p-v-xs'}>
{count} Added {active} Active {inactive} Inactive
</HeadingTag>
</Flex>
<TableViewContainer>
<Table
dataSource={this.dataSource}
columns={this.columns}
pagination={false}
footer={this.renderAddSource}
onRow={(record, Index) => ({
onClick: () => this.handleRowClick(record, Index),
})}
/>
</TableViewContainer>
</Container>
);
}
}
Example #23
Source File: index.tsx From config-generator with MIT License | 4 votes |
@inject('sourcesListStore', 'destinationsListStore')
@observer
class ConfiguredDestinations extends Component<
IConfiguredDestinationsProps,
IConfiguredDestinationsState
> {
constructor(props: IConfiguredDestinationsProps) {
super(props);
this.state = {
count: 1,
active: 1,
inactive: 0,
};
}
public async componentDidMount() {
const { sourcesListStore, destinationsListStore } = this.props;
await this.constructDataSource(
sourcesListStore!.sources,
destinationsListStore!.destinations,
);
}
dataSource: any = [];
columns = [
{
title: '',
dataIndex: 'icon',
key: 'icon',
},
{
title: 'Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Status',
dataIndex: 'status',
key: 'status',
},
{
title: 'Sources',
dataIndex: 'sources',
key: 'sources',
},
];
public constructDataSource = (sources: any, destinations: any) => {
this.dataSource = [];
let activeCount = 0;
for (let i = 0; i < destinations.length; i++) {
const sourceList: any = [];
const obj: any = {};
obj.key = destinations[i].id;
for (let scount = 0; scount < destinations[i].sources.length; scount++) {
const a = (
<IconSpacing key={`${destinations[i].sources[scount].id}`}>
<SourceIcon
key={`${scount}`}
source={destinations[i].sources[scount].sourceDef.name}
/>
</IconSpacing>
);
sourceList.push(a);
}
if (destinations[i].enabled) {
activeCount++;
}
obj.sources = sourceList;
obj.icon = (
<DestinationIcon
destination={destinations[i].destinationDefinition.name}
/>
);
obj.id = destinations[i].id;
obj.name = destinations[i].name;
obj.status = destinations[i].enabled ? 'Enabled' : 'Disabled';
this.dataSource.push(obj);
}
this.setState({ active: activeCount });
this.setState({ count: sources.length });
this.setState({ inactive: this.state.count - this.state.active });
};
handleRowClick = (record: any, Index: Number) => {
const { history } = this.props;
history!.push(`/destinations/${record.id}`);
};
public render() {
const { count, active, inactive } = this.state;
return (
<Container className="Sources">
<HeadingContainer>
<MainHeading>Configured Destinations</MainHeading>
<HeadingTag>
{count} Added {active} Active {inactive} Inactive
</HeadingTag>
</HeadingContainer>
<TableViewContainer>
<Table
dataSource={this.dataSource}
columns={this.columns}
pagination={false}
onRow={(record, Index) => ({
onClick: () => this.handleRowClick(record, Index),
})}
/>
</TableViewContainer>
</Container>
);
}
}
Example #24
Source File: index.tsx From react-amis-admin with Apache License 2.0 | 4 votes |
@inject("store")
@observer
export default class Admin extends React.Component<AdminProps, any> {
renderHeader() {
const store = this.props.store;
return (
<div>
<div className={`cxd-Layout-brandBar`}>
<button
onClick={store.toggleOffScreen}
className="pull-right visible-xs"
>
<i className="fa fa-bars text-white"></i>
</button>
<div className={`cxd-Layout-brand`}>
<i className="fa fa-paw"></i>
<span className="hidden-folded m-l-sm">react-amis-admin</span>
</div>
</div>
<div className={`cxd-Layout-headerBar`}>
<div className="nav navbar-nav hidden-xs pull-left">
<Button
level="link"
className="no-shadow navbar-btn"
onClick={store.toggleAsideFolded}
tooltip="展开或收起侧边栏"
placement="bottom"
iconOnly
>
<i className={store.asideFolded ? 'fa fa-indent' : 'fa fa-outdent'}/>
</Button>
</div>
<div className="m-l-auto hidden-xs pull-right">
<span>{store.user.name}</span><span className={'btn btn-link'} onClick={this.logout}>[退出]</span>
</div>
</div>
</div>
);
}
state = {
pathname: '',
hasLoadMenu: false,
navigations: []
}
logout = () => {
const store = this.props.store;
store.user.logout()
const history = this.props.history;
history.replace(`/login`)
}
componentDidMount() {
const store = this.props.store;
const history = this.props.history;
console.log("componentDidMount, store.user:", store.user)
if (!store.user.isAuthenticated) {
toast['error']('用户未登陆,请先登陆!', '消息')
history.replace(`/login`)
}
this.refreshMenu()
}
componentDidUpdate() {
this.refreshMenu()
}
refreshMenu = () => {
const store = this.props.store;
let pathname = this.props.location.pathname;
console.log("location:", pathname)
console.log("store.user:", store.user)
if (pathname != 'login' && pathname != '/' &&
!this.state.hasLoadMenu &&
store.user.isAuthenticated
) {
request({
method: "get",
url: '/api/menus'
}).then((res: any) => {
console.log("res:", res);
this.setState({
"navigations": res.data.data,
"hasLoadMenu": true
}
)
})
}
}
renderAside() {
const location = this.props.location;
const store = this.props.store;
return (
<AsideNav
key={store.asideFolded ? 'folded-aside' : 'aside'}
navigations={this.state.navigations}
renderLink={({link, toggleExpand, classnames: cx, depth}: any) => {
if (link.hidden) {
return null;
}
let children = [];
if (link.children) {
children.push(
<span
key="expand-toggle"
className={cx('AsideNav-itemArrow')}
onClick={(e) => toggleExpand(link, e)}
></span>
);
}
link.badge && children.push(
<b key="badge"
className={cx(`AsideNav-itemBadge`, link.badgeClassName || 'bg-info')}>{link.badge}</b>
);
if (link.icon) {
children.push(
<i key="icon" className={cx(`AsideNav-itemIcon`, link.icon)}/>
)
} else if (store.asideFolded && depth === 1) {
children.push(
<i key="icon"
className={cx(`AsideNav-itemIcon`, link.children ? 'fa fa-folder' : 'fa fa-info')}/>
)
}
;
children.push(
<span key="label" className={cx('AsideNav-itemLabel')}>{link.label}</span>
);
return link.path
? (link.active ? <a>{children}</a> : <Link
to={link.path}>{children}</Link>)
: (
<a onClick={link.onClick ? link.onClick : link.children ? () => toggleExpand(link) : undefined}>{children}</a>);
}}
isActive={(link: any) => isActive(link.path, location)}
/>
);
}
render() {
const store = this.props.store;
let pathname = this.props.location.pathname;
console.log("location:", pathname)
if (pathname == 'login' || pathname == '/') {
return (
<Switch>
<RouterGuard/>
<Redirect to={`/404`}/>
</Switch>
)
} else {
return (
<Layout
aside={this.renderAside()}
header={this.renderHeader()}
folded={store.asideFolded}
offScreen={store.offScreen}
>
<Switch>
<RouterGuard/>
<Redirect to={`/404`}/>
</Switch>
</Layout>
);
}
}
}
Example #25
Source File: Login.tsx From react-amis-admin with Apache License 2.0 | 4 votes |
@inject("store")
// @ts-ignore
@withRouter
@observer
export default class LoginRoute extends React.Component<LoginProps, any> {
state = {
inputUsername: 'admin',
inputPassword: 'admin'
}
handleFormSaved = (value: any) => {
const history = this.props.history;
const store = this.props.store;
console.log("inputUsername:", this.state.inputUsername)
console.log("inputPassword:", this.state.inputPassword)
// 这里可以进行登陆密码验证
axios.request({
method: "post",
url: "/api/login"
}).then(res => {
console.log("login res", res);
if (res.data != null && res.data.status === 0) {
store.user.login(this.state.inputUsername);
toast['info']('登陆成功', '消息')
// 跳转到dashboard页面
console.log("replace history to dashboard, value:", value)
history.replace(`/dashboard`)
} else {
toast['error']('登陆失败', '消息')
}
})
}
handleChangeForPassword = (e: any) => {
this.setState({
inputPassword: e.target.value
})
}
componentDidMount() {
const store = this.props.store;
console.log("store.user.name", store.user.name)
console.log("store.user.isAuthenticated", store.user.isAuthenticated)
}
handleChangeForUsername = (e: any) => {
this.setState({
inputUsername: e.target.value
})
}
render() {
return (
<div className="login-page-container" >
<div className="container mt-5">
<span className="block m-b-xl text-center text-2x">React-Amis-Admin系统</span>
<span className="block m-b-xl text-center">一个开箱可用的Amis + React 低代码开发环境</span>
<div className="row d-flex justify-content-center">
<div className="col-md-6">
<div className="card px-5 py-5 bg-glass">
<div className="card-body">
<div className="form-data">
<div className="forms-inputs mb-4"><span>用户名</span>
<input autoComplete="off"
className="form-control"
placeholder="用户名"
type="text"
onChange={this.handleChangeForUsername}
defaultValue={this.state.inputUsername}
/>
<div className="invalid-feedback">A valid email is required!</div>
</div>
<div className="forms-inputs mb-4"><span>密码</span>
<input placeholder="密码"
type="password"
className="form-control"
onChange={this.handleChangeForPassword}
defaultValue={this.state.inputPassword}/>
<div className="invalid-feedback">Password must be 8 character!</div>
</div>
<div className="mb-3">
<button className="btn btn-dark w-100" onClick={this.handleFormSaved}>登陆</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
)
;
}
}
Example #26
Source File: AMisRenderer.tsx From react-amis-admin with Apache License 2.0 | 4 votes |
@inject("store")
// @ts-ignore
@withRouter
@observer
export default class AMisRenderer extends React.Component<RendererProps, any> {
env:any = null;
handleAction = (e:any, action:Action) => {
this.env.alert(`没有识别的动作:${JSON.stringify(action)}`);
}
constructor(props:RendererProps) {
super(props);
const store = props.store as IMainStore;
const fetcher = getEnv(store).fetcher;
const notify = getEnv(store).notify;
const alert = getEnv(store).alert;
const confirm = getEnv(store).confirm;
const copy = getEnv(store).copy;
const apiHost = getEnv(store).apiHost;
const getModalContainer = getEnv(store).getModalContainer;
const history = props.history;
const normalizeLink = (to:string) => {
if (/^\/api\//.test(to)) {
return to;
}
to = to || '';
const location = history.location;
if (to && to[0] === '#') {
to = location.pathname + location.search + to;
} else if (to && to[0] === '?') {
to = location.pathname + to;
}
const idx = to.indexOf('?');
const idx2 = to.indexOf('#');
let pathname = ~idx ? to.substring(0, idx) : ~idx2 ? to.substring(0, idx2) : to;
let search = ~idx ? to.substring(idx, ~idx2 ? idx2 : undefined) : '';
let hash = ~idx2 ? to.substring(idx2) : '';
if (!pathname) {
pathname = location.pathname;
}else if (pathname[0] != '/' && !/^https?\:\/\//.test(pathname)) {
let relativeBase = location.pathname;
const paths = relativeBase.split('/');
paths.pop();
let m;
while ((m = /^\.\.?\//.exec(pathname))) {
if (m[0] === '../') {
paths.pop();
}
pathname = pathname.substring(m[0].length);
}
pathname = paths.concat(pathname).join('/');
}
return pathname + search + hash;
}
// todo,这个过程可以 cache
this.env = {
session: 'global',
updateLocation: props.updateLocation || ((location:string, replace:boolean) => {
if (location === 'goBack') {
return history.goBack();
}
history[replace ? 'replace' : 'push'](normalizeLink(location));
}),
isCurrentUrl: (to:string) => {
const link = normalizeLink(to);
const location = history.location;
let pathname = link;
let search = '';
const idx = link.indexOf('?');
if (~idx) {
pathname = link.substring(0, idx);
search = link.substring(idx);
}
if (search) {
if (pathname !== location.pathname || !location.search) {
return false;
}
const query = qs.parse(search.substring(1));
const currentQuery = qs.parse(location.search.substring(1));
return Object.keys(query).every(key => query[key] === currentQuery[key]);
} else if (pathname === location.pathname) {
return true;
}
return false;
},
jumpTo: props.jumpTo || ((to:string, action?:any) => {
if (to === 'goBack') {
return history.goBack();
}
to = normalizeLink(to);
if (action && action.actionType === 'url') {
action.blank === false ? (window.location.href = to) : window.open(to);
return;
}
if (/^https?:\/\//.test(to)) {
window.location.replace(to);
} else {
history.push(to);
}
}),
fetcher,
notify,
alert,
confirm,
copy,
apiHost,
getModalContainer
};
}
render() {
const {
schema,
store,
onAction,
...rest
} = this.props;
return renderSchema(schema, {
onAction: onAction || this.handleAction,
theme: store && store.theme,
...rest
}, this.env);
}
}