Skip to content

Commit

Permalink
Add scenario builder directly to scenario module
Browse files Browse the repository at this point in the history
The builder was historically separated in its own
repository which didn't make sense anymore.
All assets have been moved to the main project.

The build process was switched to webpack.

remp/crm#2089
  • Loading branch information
Martin Brieška authored and rootpd committed Jul 9, 2024
1 parent aae358d commit 239781b
Show file tree
Hide file tree
Showing 147 changed files with 22,777 additions and 113 deletions.
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.DS_Store
node_modules
/src/assets/scenario-builder/dist
/build

# local env files
.env.local
.env.*.local
/src/env.js

# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
3 changes: 3 additions & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"esversion": 6
}
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
js:
yarn install
yarn build-prod
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,27 @@ php bin/command.php api:generate_access
php bin/command.php application:seed
```

### Building assets

Install dependencies inside module folder `yarn install`
Be sure to have scenario config filled in a global scope. It should look like this:

```js
window.Scenario = {
config: {
AUTH_TOKEN: '',
CRM_HOST: '',
CANCEL_PATH: '',
SEGMENT_ID: null
}
};
```

Run `yarn build-prod` if you want to build whole application for the deployment. Then, at the root of the project, copy assets using:
```shell
php bin/command.php application:install_assets
```

### Engine

Scenarios module requires Scenario engine worker to run separately in a background to process graph execution flows.
Expand Down
57 changes: 57 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"name": "remp-scenario-builder",
"version": "0.3.0",
"private": true,
"dependencies": {
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.56",
"@projectstorm/react-diagrams": "^5.3.2",
"axios": "^0.18.0",
"eslint-plugin-react-hooks": "^2.3.0",
"less": "^4.1.3",
"less-loader": "^11.1.3",
"lodash": "^4.17.11",
"react": "^16.6.0",
"react-dom": "^16.6.0",
"react-redux": "^7.1.3",
"react-scripts": "^3.4.3",
"react-select": "^2.1.2",
"recompose": "^0.30.0",
"redux": "^4.0.1",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0",
"storm-react-diagrams": "^5.2.1"
},
"scripts": {
"serve": "webpack serve --mode development",
"build-dev": "webpack --mode development",
"build-prod": "webpack --mode production"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"devDependencies": {
"@babel/core": "^7.24.7",
"@babel/preset-env": "^7.24.7",
"@babel/preset-react": "^7.24.7",
"babel-loader": "^9.1.3",
"cpx": "^1.5.0",
"css-loader": "^7.1.2",
"eslint-config-rallycoding": "^3.2.0",
"html-webpack-plugin": "^5.6.0",
"sass": "^1.77.6",
"sass-loader": "^14.2.1",
"style-loader": "^4.0.0",
"url-loader": "^4.1.1",
"webpack": "^5.92.1",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.0.4"
}
}
2 changes: 1 addition & 1 deletion src/ScenariosModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public function registerLazyEventHandlers(LazyEventEmitter $emitter)

public function registerAssets(AssetsManager $assetsManager)
{
$assetsManager->copyAssets(__DIR__ . '/assets/scenariobuilder', 'layouts/admin/scenariobuilder');
$assetsManager->copyAssets(__DIR__ . '/assets/scenario-builder/dist', 'layouts/admin/scenario-builder');
}

public function registerScenariosCriteria(ScenariosCriteriaStorage $scenariosCriteriaStorage)
Expand Down
63 changes: 63 additions & 0 deletions src/assets/scenario-builder/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';

import BodyWidget from './components/widgets/BodyWidget';
import { Application } from './components/Application';
import * as config from './config';
import {
fetchSegments,
fetchGoals,
fetchBanners,
fetchTriggers,
fetchBeforeTriggers,
fetchCriteria,
fetchScenario,
setScenarioName,
fetchMails,
fetchGenerics,
fetchPushNotifications,
fetchStatistics
} from './actions';

class App extends Component {
componentDidMount() {
const { dispatch } = this.props;

dispatch(fetchSegments());
dispatch(fetchCriteria());
dispatch(fetchGoals());
dispatch(fetchTriggers());
dispatch(fetchBeforeTriggers());
dispatch(fetchMails());
dispatch(fetchGenerics());

if (config.BANNER_ENABLED) {
dispatch(fetchBanners());
}

if (config.PUSH_NOTIFICATION_ENABLED) {
dispatch(fetchPushNotifications());
}

if (config.SCENARIO_ID) {
dispatch(fetchScenario(config.SCENARIO_ID));
dispatch(fetchStatistics(config.SCENARIO_ID));
} else {
dispatch(setScenarioName('Unnamed scenario'));
}
}

render() {
var app = new Application(this.props.scenarioPayload);

return <BodyWidget app={app} />;
}
}

function mapStateToProps(state) {
return {
scenarioPayload: state.scenario.payload
};
}

export default connect(mapStateToProps)(App);
35 changes: 35 additions & 0 deletions src/assets/scenario-builder/actions/BannersActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import axios from 'axios';
import * as config from '../config';
import { setScenarioLoading } from './ScenarioActions';
import { setCanvasNotification } from './CanvasActions';
import { BANNERS_CHANGED } from './types';

export function updateBanners(banners) {
return {
type: BANNERS_CHANGED,
payload: banners
};
}

export function fetchBanners() {
return dispatch => {
dispatch(setScenarioLoading(true));
return axios
.get(config.URL_BANNERS_INDEX)
.then(response => {
dispatch(updateBanners(response.data.banners));
dispatch(setScenarioLoading(false));
})
.catch(error => {
dispatch(setScenarioLoading(false));
console.log(error);
dispatch(
setCanvasNotification({
open: true,
variant: 'error',
text: 'Banners fetching failed.'
})
);
});
};
}
36 changes: 36 additions & 0 deletions src/assets/scenario-builder/actions/BeforeTriggersActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import axios from 'axios';
import * as config from './../config';
import { setScenarioLoading } from './ScenarioActions';
import { setCanvasNotification } from './CanvasActions';

import { BEFORE_TRIGGERS_CHANGED } from './types';

export function updateBeforeTriggers(beforeTriggers) {
return {
type: BEFORE_TRIGGERS_CHANGED,
payload: beforeTriggers
};
}

export function fetchBeforeTriggers() {
return dispatch => {
dispatch(setScenarioLoading(true));
return axios
.get(`${config.URL_BEFORE_TRIGGERS_INDEX}`)
.then(response => {
dispatch(updateBeforeTriggers(response.data.events));
dispatch(setScenarioLoading(false));
})
.catch(error => {
dispatch(setScenarioLoading(false));
console.log(error);
dispatch(
setCanvasNotification({
open: true,
variant: 'error',
text: 'Triggers fetching failed.'
})
);
});
};
}
34 changes: 34 additions & 0 deletions src/assets/scenario-builder/actions/CanvasActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {
CANVAS_PANNABLE,
CANVAS_ZOOMABLE,
CANVAS_ZOOMABLE_PANNABLE,
CANVAS_NOTIFICATION
} from './types';

export function setCanvasZoomable(zoomable) {
return {
type: CANVAS_ZOOMABLE,
payload: zoomable
};
}

export function setCanvasPannable(pannable) {
return {
type: CANVAS_PANNABLE,
payload: pannable
};
}

export function setCanvasZoomingAndPanning(zoomingAndPanning) {
return {
type: CANVAS_ZOOMABLE_PANNABLE,
payload: zoomingAndPanning
};
}

export function setCanvasNotification(notificationOptions) {
return {
type: CANVAS_NOTIFICATION,
payload: notificationOptions
};
}
35 changes: 35 additions & 0 deletions src/assets/scenario-builder/actions/CriteriaActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import axios from 'axios';
import * as config from '../config';
import { setScenarioLoading } from './ScenarioActions';
import { setCanvasNotification } from './CanvasActions';
import { CRITERIA_CHANGED } from './types';

export function updateCriteria(criteria) {
return {
type: CRITERIA_CHANGED,
payload: criteria
};
}

export function fetchCriteria() {
return dispatch => {
dispatch(setScenarioLoading(true));
return axios
.get(config.URL_SCENARIO_CRITERIA)
.then(response => {
dispatch(updateCriteria(response.data.blueprint));
dispatch(setScenarioLoading(false));
})
.catch(error => {
console.log(error);
dispatch(setScenarioLoading(false));
dispatch(
setCanvasNotification({
open: true,
variant: 'error',
text: 'Criteria fetching failed.'
})
);
});
};
}
36 changes: 36 additions & 0 deletions src/assets/scenario-builder/actions/GenericsActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import axios from 'axios';
import * as config from './../config';
import { setScenarioLoading } from './ScenarioActions';
import { setCanvasNotification } from './CanvasActions';

import { GENERICS_CHANGED } from './types';

export function updateGenerics(generics) {
return {
type: GENERICS_CHANGED,
payload: generics
};
}

export function fetchGenerics() {
return dispatch => {
dispatch(setScenarioLoading(true));
return axios
.get(`${config.URL_GENERICS_INDEX}`)
.then(response => {
dispatch(updateGenerics(response.data));
dispatch(setScenarioLoading(false));
})
.catch(error => {
dispatch(setScenarioLoading(false));
console.log(error);
dispatch(
setCanvasNotification({
open: true,
variant: 'error',
text: 'Generics fetching failed.'
})
);
});
};
}
Loading

0 comments on commit 239781b

Please sign in to comment.