Private
Public Access
1
0

add new websocket topic - userList - and handle it

This commit is contained in:
2017-01-22 15:21:45 +01:00
parent a91172ef7a
commit a3465f6cf9
18 changed files with 680 additions and 83 deletions

3
.gitignore vendored
View File

@@ -35,6 +35,5 @@ phpunit-report/*
/src/Mine/SeekerBundle/Resources/public/js/src/
nohup.out
src/Mine/SeekerBundle/Resources/public/js/index.js
src/Mine/SeekerBundle/Resources/public/js/index.min.js
src/Mine/SeekerBundle/Resources/public/js/build/
npm-debug.log

View File

@@ -33,14 +33,24 @@ class GameController extends Controller
// dump($response->getErrorExplanation());
// }
return $this->render('MineSeekerBundle:Game:index.html.twig');
return $this->render('MineSeekerBundle:Game:index.html.twig', array(
'env' => $this->container->getParameter('kernel.environment'),
));
}
public function playAction(Request $request)
{
return $this->render('MineSeekerBundle:Game:play.html.twig', array(
'env' => $this->container->getParameter('kernel.environment'),
'ssl' => $request->isSecure() ? 'true' : 'false'
'ssl' => $request->isSecure() ? 'true' : 'false',
));
}
public function rePlayAction(Request $request)
{
return $this->render('MineSeekerBundle:Game:play.html.twig', array(
'env' => $this->container->getParameter('kernel.environment'),
'ssl' => $request->isSecure() ? 'true' : 'false',
));
}

View File

@@ -1,4 +1,4 @@
# Topic Configuration
# MineSeeker Topic Configuration
mineseeker_topic:
channel: mineseeker/channel/{game}
handler:
@@ -7,6 +7,12 @@ mineseeker_topic:
# method:
# path: '[a-z1-9A-Z]+'
# UserList Topic Configuration
userList_topic:
channel: mineseeker/userList
handler:
callback: 'userlist.topic'
# Remote Procedure Call Configuration
mineseeker_rpc:
channel: mineseeker-rpc/{method}

View File

@@ -13,6 +13,11 @@ MineSeekerBundle_gamePlayWId:
defaults: { _controller: MineSeekerBundle:Game:play }
schemes: [https]
MineSeekerBundle_gameReplay:
path: /re-play/{gameAssoc}
defaults: { _controller: MineSeekerBundle:Game:rePlay }
schemes: [https]
MineSeekerBundle_slack:
path: /slack
defaults: { _controller: MineSeekerBundle:Game:slack }

View File

@@ -26,7 +26,7 @@ services:
arguments:
ping: '@gos_web_socket.pdo.periodic_ping'
mineseeker.topic_sample_service:
mineseeker.game_service:
class: Mine\SeekerBundle\Topic\MineseekerTopic
tags:
- { name: gos_web_socket.topic }
@@ -35,7 +35,16 @@ services:
doctrine: '@doctrine.orm.entity_manager'
requestStack: '@request_stack'
mineseeker.rpc_sample_service:
mineseeker.user_list_service:
class: Mine\SeekerBundle\Topic\UserListTopic
tags:
- { name: gos_web_socket.topic }
arguments:
clientManipulator: "@gos_web_socket.websocket.client_manipulator"
doctrine: '@doctrine.orm.entity_manager'
requestStack: '@request_stack'
mineseeker.game_rpc_service:
class: Mine\SeekerBundle\Rpc\MineseekerRpc
tags:
- { name: gos_web_socket.rpc }

View File

@@ -141,6 +141,59 @@ header section div.buttons > a.small:hover {
transition: all 250ms ease-in-out;
}
main .user-list-container {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}
main .user-list-container .user-friend {
width: 15%;
padding: 10px;
}
main .user-list-container .user-friend h1 {
display: block;
font-size: 14px;
text-align: center;
}
main .user-list-container .user-friend img {
width: 100%;
}
main .user-list-container .user-friend button {
background: #83aed9;
display: inline-block;
font: bold 22px 'Rajdhani', sans-serif;
border: 1px solid #6890ba;
color: #FFFFFF;
padding: 10px;
-webkit-box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
-webkit-transition: all 250ms ease-in-out;
-moz-transition: all 250ms ease-in-out;
-o-transition: all 250ms ease-in-out;
transition: all 250ms ease-in-out;
}
main .user-list-container .user-friend button:hover {
background: #86b5e1;
border: 1px solid #658fb8;
color: #FFFFFF;
-webkit-box-shadow: 0 7px 15px rgba(0, 0, 0, 0.2);
box-shadow: 0 7px 15px rgba(0, 0, 0, 0.2);
-webkit-transition: all 250ms ease-in-out;
-moz-transition: all 250ms ease-in-out;
-o-transition: all 250ms ease-in-out;
transition: all 250ms ease-in-out;
}
@media screen and (max-width: 1100px) {
header section {
align-items: center;
@@ -166,11 +219,6 @@ header section div.buttons > a.small:hover {
}
@media screen and (max-width: 500px) {
/*header {*/
/*min-height: 100%;*/
/*height: auto;*/
/*}*/
header section {
width: auto;
}

View File

@@ -2,9 +2,11 @@ import React from 'react';
import ReactDOM from 'react-dom';
import MineSeeker from './mine-seeker/app';
let mineWrapper = document.getElementById('mine-wrapper');
ReactDOM.render(
<MineSeeker env={document.getElementById('mine-wrapper').dataset.env}
gameId={document.getElementById('mine-wrapper').dataset.gameId}
ssl={document.getElementById('mine-wrapper').dataset.ssl}/>,
document.getElementById('mine-wrapper')
<MineSeeker env={mineWrapper.dataset.env}
gameId={mineWrapper.dataset.gameId}
ssl={mineWrapper.dataset.ssl}/>,
mineWrapper
);

View File

@@ -1,12 +1,14 @@
import React from 'react';
import Grid from './grid/grid';
import GridControl from './grid/grid-control';
import MineServices from '../mine-system/mine-services';
class MineSeeker extends React.Component {
constructor(props) {
super(props);
let gameAssoc = props.gameId !== '' ? props.gameId : this.makeGameAssoc(50);
let services = new MineServices();
let gameAssoc = props.gameId !== '' ? props.gameId : services.randomString(50);
let channel = "mineseeker/channel/" + gameAssoc;
this.state = {
@@ -19,19 +21,11 @@ class MineSeeker extends React.Component {
createGrid: false,
stepCache: [],
connectionLost: false,
end: false
end: false,
replay: false
}
}
makeGameAssoc(len) {
let text = "";
let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (let i = 0; i < len; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
currectGridSize() {
let $field = $('#mine-wrapper .grid');
$field.height($field.width());
@@ -76,8 +70,19 @@ class MineSeeker extends React.Component {
* @param payload
*/
makeGameStart(payload) {
/** every time the blue starts */
let steps = JSON.parse(Base64.decode(payload.steps));
if (steps.length) {
steps.forEach((item) => {
setTimeout(() => {
this.refs.gridControl.refs.userControl.setState({bombSelected: item.wBomb});
this.makePointsCalcAndStep([item.row, item.col]);
}, 500);
});
} else {
/** every time the blue starts when it is not a continued game */
this.refs.gridControl.refs.userControl.setState({activePlayer: 1});
}
/** Set up player names w/ server data */
this.refs.gridControl.refs.userControl.refs.red.setState({
@@ -234,6 +239,20 @@ class MineSeeker extends React.Component {
});
}
clickRestorePlayer(data) {
this.refs.gridControl.setState({
overlay: true,
overlayTitle: "We are waiting for your opponent...",
overlaySubTitle: ''
});
this.refs.gridControl.state.webPlayer = data[0];
if (data[1].userCnt === 2) {
this.makeGameStart(data[1]);
}
}
wSubscribe(payload, rpcUsers = null) {
this.state.env === 'dev' && console.info(
(typeof payload.user !== 'undefined' ? payload.user : 'user') + " has been subscribed to the channel!"
@@ -241,6 +260,21 @@ class MineSeeker extends React.Component {
let firstUser = !rpcUsers;
/** is it a REPLAY */
if (this.state.replay) {
this.refs.gridControl.setState({
overlay: true,
overlayTitle: "Which player has been you, in this game?",
overlaySubTitle: <div>
<button onClick={this.clickRestorePlayer.bind(this, ['blue', payload])}>
I was the BLUE, man!
</button>
<button onClick={this.clickRestorePlayer.bind(this, ['red', payload])} target="_blank">
I was RED, obviously!
</button>
</div>
});
} else {
this.refs.gridControl.state.webPlayer === null && this.refs.gridControl.setState({
webPlayer: payload.user === payload.users.blue ||
(
@@ -250,9 +284,6 @@ class MineSeeker extends React.Component {
? 'blue' : 'red'
});
/** rwd */
(900 > $(document).width()) && this.currectGridSize();
/** every user has been came */
if (
payload.userCnt === 2 &&
@@ -265,6 +296,10 @@ class MineSeeker extends React.Component {
}
}
/** rwd */
(900 > $(document).width()) && this.currectGridSize();
}
wUnsubscribe(payload) {
this.state.env === 'dev' && console.info(payload.msg);
@@ -400,8 +435,21 @@ class MineSeeker extends React.Component {
});
}
/**
* Unregistered
* http://mine.dev/re-play/I1Bx9UHZP5CWDnTZHpJqGTlkzehblfsbfz4A4xYaH9HFhBK2aN
*
* Registered
* http://mine.dev/re-play/km10oOgM7Xh37vJ8PFjaRRePrHpDkZFDJgxLhNc6hkTYyLyPKD
*/
/** After rendering */
componentDidMount() {
/** is it a REPLAY */
window.location.pathname.indexOf('re-play') > 0
? this.setState({replay: true})
: this.setState({replay: false});
this.connectWithWebsocket();
}

View File

@@ -0,0 +1,18 @@
import React from 'react';
class MineServices extends React.Component {
constructor() {
super();
}
randomString(len) {
let text = "";
let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (let i = 0; i < len; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
}
export default MineServices;

View File

@@ -0,0 +1,10 @@
import React from 'react';
import ReactDOM from 'react-dom';
import MineUserList from './mine-user-list/app';
let mineUserList = document.getElementById('mine-user-list');
ReactDOM.render(
<MineUserList env={mineUserList.dataset.env}/>,
mineUserList
);

View File

@@ -0,0 +1,142 @@
import React from 'react';
import MineServices from '../mine-system/mine-services';
class MineUserList extends React.Component {
constructor(props) {
super();
let services = new MineServices();
this.state = {
env: props.env,
services: services,
session: null,
users: [],
requests: new Map(),
};
}
refreshUserList(payload) {
let webUsers = JSON.parse(Base64.decode(payload.users)),
users = new Map();
webUsers.forEach((item) => {
if (!users.has(item.email)) {
users.set(item.email, item);
}
});
this.setState({users: users});
}
connectWithWebsocket() {
let websocket = WS.connect(
this.state.env === 'dev'
? "ws://mine.dev:6450"
: (this.state.ssl === 'true' ? "wss" : "ws") + "://www.mineseeker.ninja:6450/"
);
websocket.on("socket/connect", (session) => {
this.state.env === 'dev' && console.info("Successfully connected to the Server!");
this.state.session = session;
session.subscribe(
'mineseeker/userList',
(uri, payload, log) => {
/** refresh list */
if (typeof payload.users !== 'undefined') {
this.refreshUserList(payload);
}
/** communication */
if (typeof payload.gameAssoc !== 'undefined') {
switch (payload.type) {
case 'REQ':
let req = this.state.requests;
if (!req.has(payload.username)) {
req.set(payload.username, payload);
}
this.setState({reqests: req});
break;
case 'RESP':
window.location.href = window.location.origin + '/re-play/' + payload.gameAssoc;
break;
case 'GAME':
break;
}
}
});
});
websocket.on("socket/disconnect", (error) => {
this.state.env === 'dev' && console.error("Disconnected for " + error.reason + " with code " + error.code);
});
}
componentDidMount() {
this.connectWithWebsocket();
}
getProfilePicture(id) {
return <img src={"http://graph.facebook.com/" + id + "/picture?type=square&width=100&height=100"}
alt="Facebook profile"/>;
}
clickChallengeFriend(username) {
this.state.session.publish('mineseeker/userList', {
'type': 'REQ',
'username': username,
'gameAssoc': this.state.services.randomString(50)
});
}
clickChallengeAccepted(data) {
this.state.session.publish('mineseeker/userList', {
'type': 'RESP',
'username': data[0],
'gameAssoc': data[1]
});
window.location.href = window.location.origin + '/re-play/' + data[1];
}
render() {
let users = [];
let req = [];
this.state.users.size > 0
? this.state.users.forEach((item) => {
users.push(<div key={this.state.services.randomString(50)} className="user-friend">
{this.getProfilePicture(item.id)}
<h1>{item.name}</h1>
<h2>{item.online ? 'online' : 'offline'}</h2>
<button onClick={this.clickChallengeFriend.bind(this, item.username)}>Challenge</button>
</div>)
})
: '';
this.state.requests.size > 0
? this.state.requests.forEach((item) => {
req.push(<div key={this.state.services.randomString(50)} className="user-friend">
<h1>{item.username} <strong>challenged you</strong>!</h1>
<button onClick={this.clickChallengeAccepted.bind(this, [item.username, item.gameAssoc])}>Accept</button>
</div>)
})
: '';
return (
<div>
<div className="user-request-container">
{req}
</div>
<div className="user-list-container">
{users}
</div>
</div>
);
}
}
export default MineUserList;

View File

@@ -63,6 +63,9 @@
{% block body %}
<div class="txt">
{% if is_granted("IS_AUTHENTICATED_REMEMBERED") %}
<div id="mine-user-list" data-env="{{ env }}"></div>
{% endif %}
<div class="technologies">
<h1>Used technologies</h1>
<img src="{{ asset('bundles/mineseeker/images/technologies/websocket.png') }}" alt="Used Websocket"
@@ -107,6 +110,24 @@
{% block javascripts %}
{{ parent() }}
{% if is_granted("IS_AUTHENTICATED_REMEMBERED") and app.user.facebookAccessToken is defined %}
{% if env == 'dev' %}
{% javascripts filter='?uglifyjs2'
'@GosWebSocketBundle/Resources/public/js/vendor/autobahn.min.js'
'@GosWebSocketBundle/Resources/public/js/gos_web_socket_client.js'
'@MineSeekerBundle/Resources/public/js/node/js-base64/base64.min.js'
'@MineSeekerBundle/Resources/public/js/build/mine-user-list/index.js' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
{% else %}
{% javascripts filter='?uglifyjs2'
'@GosWebSocketBundle/Resources/public/js/vendor/autobahn.min.js'
'@GosWebSocketBundle/Resources/public/js/gos_web_socket_client.js'
'@MineSeekerBundle/Resources/public/js/node/js-base64/base64.min.js'
'@MineSeekerBundle/Resources/public/js/build/mine-user-list/index.min.js' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/JQuery-Snowfall/1.7.4/snowfall.jquery.min.js"
type="text/javascript"></script>
<script type="text/javascript">
@@ -114,4 +135,6 @@
$(document).snowfall({deviceorientation: true, round: true, minSize: 5, maxSize: 8});
});
</script>
{% endif %}
{% endif %}
{% endblock %}

View File

@@ -20,7 +20,8 @@
<meta property="og:type" content="website"/>
<meta property="og:title" content="Your friend challenges YOU!"/>
<meta property="og:description" content="Do you accept the challenge?"/>
<meta property="og:image" content="{{ app.request.getSchemeAndHttpHost() }}{{ asset('bundles/mineseeker/images/mine-1600x627.png') }}"/>
<meta property="og:image"
content="{{ app.request.getSchemeAndHttpHost() }}{{ asset('bundles/mineseeker/images/mine-1600x627.png') }}"/>
{% endblock %}
{% block stylesheets %}
@@ -46,7 +47,7 @@
'@GosWebSocketBundle/Resources/public/js/gos_web_socket_client.js'
'@MineSeekerBundle/Resources/public/js/node/howler/dist/howler.min.js'
'@MineSeekerBundle/Resources/public/js/node/js-base64/base64.min.js'
'@MineSeekerBundle/Resources/public/js/index.js' %}
'@MineSeekerBundle/Resources/public/js/build/mine-seeker/index.js' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
{% else %}
@@ -55,7 +56,7 @@
'@GosWebSocketBundle/Resources/public/js/gos_web_socket_client.js'
'@MineSeekerBundle/Resources/public/js/node/howler/dist/howler.min.js'
'@MineSeekerBundle/Resources/public/js/node/js-base64/base64.min.js'
'@MineSeekerBundle/Resources/public/js/index.min.js' %}
'@MineSeekerBundle/Resources/public/js/build/mine-seeker/index.min.js' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
{% endif %}

View File

@@ -1,14 +1,22 @@
<script type="text/javascript">
$(function () {
window.fbAsyncInit = function () {
FB.init({
appId: '{{ facebook_api }}',
xfbml: true,
cookie: true,
status: true,
oauth: true,
version: '{{ facebook_api_version }}'
version: '{{ facebook_api_version }}',
});
/** trigger jQuery when Facebook SKD loads */
$(document).trigger('fb-load');
// $(document).bind('fb-load', function () {
// TODO
// });
};
});
(function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];

View File

@@ -63,7 +63,8 @@ class MineseekerTopic implements TopicInterface
'channel' => $topic->getId(),
'user' => $userName,
'userCnt' => $topic->count(),
'users' => $users
'users' => $users,
'steps' => $this->getSteps($topic),
]);
}
}
@@ -180,6 +181,28 @@ class MineseekerTopic implements TopicInterface
$this->em->flush();
}
private function getSteps($topic)
{
$this->reConnect();
$gameAssoc = explode('/', $topic->getId())[2];
$playedGame = $this->em
->getRepository('MineSeekerBundle:PlayedGame')
->findOneByGameAssoc($gameAssoc);
$steps = array();
foreach ($playedGame->getStep()->toArray() as $item) {
$steps[] = array(
'row' => $item->getRow(),
'col' => $item->getCol(),
'wBomb' => $item->getWBomb(),
);
}
return base64_encode(json_encode($steps));
}
/**
* Control all users in a channel
*

View File

@@ -0,0 +1,192 @@
<?php
namespace Mine\SeekerBundle\Topic;
use Doctrine\DBAL\Driver\PDOException;
use Doctrine\ORM\EntityManager;
use Gos\Bundle\WebSocketBundle\Client\ClientManipulatorInterface;
use Gos\Bundle\WebSocketBundle\Topic\TopicInterface;
use Gos\Bundle\WebSocketBundle\Router\WampRequest;
use Ratchet\ConnectionInterface;
use Ratchet\Wamp\Topic;
use Symfony\Component\HttpFoundation\RequestStack;
class UserListTopic implements TopicInterface
{
/** @var ClientManipulatorInterface */
protected $clientManipulator;
/** @var EntityManager */
protected $em;
/** @var RequestStack */
protected $requestStack;
/**
* MineseekerTopic constructor.
*
* @param $clientManipulator ClientManipulatorInterface
* @param EntityManager $entityManager
* @param RequestStack $requestStack
*/
public function __construct(ClientManipulatorInterface $clientManipulator, EntityManager $entityManager, RequestStack $requestStack)
{
$this->clientManipulator = $clientManipulator;
$this->em = $entityManager;
$this->requestStack = $requestStack;
}
/**
* This will receive any Subscription requests for this topic.
*
* @param ConnectionInterface $connection
* @param Topic $topic
* @param WampRequest $request
* @return void
*/
public function onSubscribe(ConnectionInterface $connection, Topic $topic, WampRequest $request)
{
/** this will broadcast the message to ALL subscribers of this topic. */
$user = $this->clientManipulator->getClient($connection);
$userName = is_string($user) ? $user : $user->getUsername();
/** @var array Find all users online and offline $users */
$users = $this->findAllUsers($topic);
$topic->broadcast([
'userTopicId' => $connection->resourceId,
'channel' => $topic->getId(),
'user' => $userName,
'userCnt' => $topic->count(),
'users' => base64_encode(json_encode($users))
]);
}
/**
* This will receive any UnSubscription requests for this topic.
*
* @param ConnectionInterface $connection
* @param Topic $topic
* @param WampRequest $request
* @return void
*/
public function onUnSubscribe(ConnectionInterface $connection, Topic $topic, WampRequest $request)
{
/** this will broadcast the message to ALL subscribers of this topic. */
$topic->broadcast(['msg' => $connection->resourceId . " has left " . $topic->getId()]);
}
/**
* This will receive any Publish requests for this topic.
*
* @param ConnectionInterface $connection
* @param Topic $topic
* @param WampRequest $request
* @param $event
* @param array $exclude
* @param array $eligible
* @return mixed|void
* @internal param Topic $Topic
* @internal param array $eligibles
*/
public function onPublish(ConnectionInterface $connection, Topic $topic, WampRequest $request, $event, array $exclude, array $eligible)
{
$user = $this->clientManipulator->getClient($connection);
$userName = is_string($user) ? $user : $user->getUsername();
$reqUser = $this->clientManipulator->findByUsername($topic, $event['username']);
/** user is still online */
if (false !== $reqUser) {
$topic->broadcast(
array(
'type' => $event['type'],
'username' => $userName,
'gameAssoc' => $event['gameAssoc'],
),
array(),
array(
$reqUser['connection']->WAMP->sessionId
)
);
}
}
/**
* Like RPC is will use to prefix the channel
*
* @return string
*/
public function getName()
{
return 'userlist.topic';
}
/**
* Find all users online/offline
*
* @param $topic
* @return array
*/
private function findAllUsers($topic)
{
$usersOnline = array();
$usersOffline = array();
$this->reConnect();
$userRepo = $this->em->getRepository('JotunheimrUserBundle:User');
$usersMax = 10;
foreach ($this->clientManipulator->getAll($topic) as $item) {
if (!$usersMax) {
break;
}
$user = $userRepo->findOneByEmail(
$item['client']->getEmail()
);
$usersOnline[] = array(
'id' => $user->getFacebookId(),
'name' => $user->getRealName(),
'email' => $user->getEmail(),
'username' => $user->getUsername(),
'online' => true
);
$usersMax--;
}
foreach ($userRepo->findBy(array(), array(), 20) as $item) {
$exists = is_numeric(array_search($item->getEmail(), array_column($usersOnline, 'email')));
if (!$exists) {
$usersOffline[] = array(
'id' => $item->getFacebookId(),
'name' => $item->getRealName(),
'email' => $item->getEmail(),
'username' => $item->getUsername(),
'online' => false
);
}
}
return array_merge($usersOnline, $usersOffline);
}
/**
* Handle prod MySQL timeout
*/
private function reConnect()
{
try {
$connection = $this->em->getConnection();
if (false === $connection->ping()) {
$connection->close();
$connection->connect();
}
} catch (PDOException $ex) {
throw PDOException::class;
}
}
}

View File

@@ -1,8 +1,8 @@
'use strict';
var webpack = require("webpack");
let webpack = require("webpack");
process.env.NODE_ENV = 'production';
var isProd = (process.env.NODE_ENV === 'production');
let isProd = (process.env.NODE_ENV === 'production');
/**
* Conditionally return a list of plugins to use based on the current environment.
@@ -10,7 +10,7 @@ var isProd = (process.env.NODE_ENV === 'production');
* @returns {Array}
*/
function getPlugins() {
var plugins = [];
let plugins = [];
/**
* Always expose NODE_ENV to webpack, you can now use `process.env.NODE_ENV`
@@ -33,10 +33,14 @@ function getPlugins() {
return plugins;
}
const config = module.exports = {
const config = {
module: {}
};
let mineSeekerConfig = Object.assign({}, config, {
entry: './web/bundles/mineseeker/js/mine-seeker.js',
output: {
path: './src/Mine/SeekerBundle/Resources/public/js',
path: './src/Mine/SeekerBundle/Resources/public/js/build/mine-seeker/',
filename: 'index.min.js'
},
module: {
@@ -50,8 +54,30 @@ const config = module.exports = {
}
}
]
},
plugins: getPlugins()
};
}
});
module.exports = config;
let mineUserListConfig = Object.assign({}, config, {
entry: './web/bundles/mineseeker/js/mine-user-list.js',
output: {
path: './src/Mine/SeekerBundle/Resources/public/js/build/mine-user-list/',
filename: 'index.min.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'react']
}
}
]
}
});
module.exports = [
mineSeekerConfig,
mineUserListConfig,
];

View File

@@ -1,9 +1,13 @@
'use strict';
const config = module.exports = {
const config = {
module: {}
};
let mineSeekerConfig = Object.assign({}, config, {
entry: './web/bundles/mineseeker/js/mine-seeker.js',
output: {
path: './src/Mine/SeekerBundle/Resources/public/js',
path: './src/Mine/SeekerBundle/Resources/public/js/build/mine-seeker/',
filename: 'index.js'
},
module: {
@@ -18,6 +22,29 @@ const config = module.exports = {
}
]
}
};
});
module.exports = config;
let mineUserListConfig = Object.assign({}, config, {
entry: './web/bundles/mineseeker/js/mine-user-list.js',
output: {
path: './src/Mine/SeekerBundle/Resources/public/js/build/mine-user-list/',
filename: 'index.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'react']
}
}
]
}
});
module.exports = [
mineSeekerConfig,
mineUserListConfig,
];