Skip to content

Instantly share code, notes, and snippets.

@ktec
Last active March 29, 2019 01:15
Show Gist options
  • Save ktec/58225384aa0222b496713aebb3fe0af3 to your computer and use it in GitHub Desktop.
Save ktec/58225384aa0222b496713aebb3fe0af3 to your computer and use it in GitHub Desktop.

Revisions

  1. ktec revised this gist Oct 17, 2017. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions layout_view.ex
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,8 @@ defmodule XxxWeb.LayoutView do
    use XxxWeb, :view

    def js_script_tag do
    if Application.get(:xxx, :webpack_dev_server) do
    # This assumes config is setup
    if Application.get(:xxx, :webpack_dev_server) == :enabled do
    # In development mode we'll load it from our webpack dev server
    "<script src=\"http://localhost:8080/js/app.js\"></script>"
    else
    @@ -13,7 +14,7 @@ defmodule XxxWeb.LayoutView do

    # Ditto for the css
    def css_link_tag do
    if Application.get(:xxx, :webpack_dev_server) do
    if Application.get(:xxx, :webpack_dev_server) == :enabled do
    "<link rel=\"stylesheet\" type=\"text/css\" href=\"http://localhost:8080/css/app.css\" />"
    else
    "<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/app.css\" />"
  2. ktec revised this gist Oct 17, 2017. 1 changed file with 22 additions and 0 deletions.
    22 changes: 22 additions & 0 deletions layout_view.ex
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,22 @@
    defmodule XxxWeb.LayoutView do
    use XxxWeb, :view

    def js_script_tag do
    if Application.get(:xxx, :webpack_dev_server) do
    # In development mode we'll load it from our webpack dev server
    "<script src=\"http://localhost:8080/js/app.js\"></script>"
    else
    # In production we'll just reference the file
    "<script src=\"/js/index.js\"></script>"
    end
    end

    # Ditto for the css
    def css_link_tag do
    if Application.get(:xxx, :webpack_dev_server) do
    "<link rel=\"stylesheet\" type=\"text/css\" href=\"http://localhost:8080/css/app.css\" />"
    else
    "<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/app.css\" />"
    end
    end
    end
  3. ktec created this gist Oct 17, 2017.
    33 changes: 33 additions & 0 deletions App.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,33 @@
    import React, { Component } from "react";
    import { connect } from "react-redux";

    import MessageList from "../components/MessageList";
    import MessageInput from "../components/MessageInput";
    import Actions from "../actions";

    function App(props) {
    const { messages, sendMessage } = props;
    return (
    <div>
    <MessageList messages={messages} />
    <MessageInput onClick={sendMessage} />
    </div>
    );
    }

    export const AppContainer = connect(
    function mapStateToProps(state) {
    return {
    messages: state.mainReducer.get("messages")
    };
    },
    function mapDispatchToProps(dispatch) {
    return {
    sendMessage: message => {
    dispatch(Actions.sendMessage(message));
    }
    };
    }
    )(App);

    export default AppContainer;
    17 changes: 17 additions & 0 deletions MessageInput.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,17 @@
    import React from "react";

    function MessageInput(props) {
    const { onClick } = props;
    let inputRef;

    return (
    <div>
    <input type="text" ref={node => inputRef = node} />
    <button onClick={() => onClick(inputRef.value)}>
    SEND
    </button>
    </div>
    )
    }

    export default MessageInput;
    13 changes: 13 additions & 0 deletions MessageList.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,13 @@
    import React from "react";

    function MessageList(props) {
    const { messages } = props;

    const renderMessage = (message, key) => {
    return <div key={key}>{message.text}</div>;
    }
    const renderMessages = messages.map(renderMessage);
    return <div className="message-list">{renderMessages}</div>;
    }

    export default MessageList;
    12 changes: 12 additions & 0 deletions actions.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,12 @@
    export const SEND_MESSAGE = 'SEND_MESSAGE';

    function sendMessage(message) {
    return {
    type: SEND_MESSAGE,
    payload: {
    message
    }
    };
    }

    export default { sendMessage };
    13 changes: 13 additions & 0 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,13 @@
    import React from "react";
    import { render } from "react-dom";
    import { Provider } from "react-redux";

    import App from "./containers/App";
    import MyStore from "./store";

    render(
    <Provider store={MyStore}>
    <App />
    </Provider>,
    document.getElementById("root")
    );
    37 changes: 37 additions & 0 deletions package.json
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,37 @@
    {
    "name": "xxx",
    "version": "0.1.0",
    "description": "xxx",
    "main": "js/index.js",
    "private": true,
    "dependencies": {
    "copy-webpack-plugin": "^4.1.1",
    "immutable": "^3.8.2",
    "react": "^16.0.0",
    "react-dom": "^16.0.0",
    "react-redux": "^5.0.6",
    "redux": "^3.7.2",
    "redux-immutable": "^4.0.0",
    "redux-thunk": "^2.2.0",
    "webpack": "^3.8.0",
    "webpack-dev-server": "^2.9.2"
    },
    "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-plugin-transform-object-rest-spread": "^6.26.0",
    "babel-preset-env": "^1.6.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "css-loader": "^0.28.7",
    "extract-text-webpack-plugin": "^3.0.1",
    "import-glob-loader": "^1.1.0",
    "node-sass": "^4.5.3",
    "sass-loader": "^6.0.6",
    "style-loader": "^0.19.0"
    },
    "scripts": {
    "webpack": "webpack-dev-server --watch --color"
    }
    }
    54 changes: 54 additions & 0 deletions reducers.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,54 @@
    // @flow

    import { List } from "immutable";
    import { combineReducers } from "redux";

    import { Model, MessageType } from "./types";
    import { SEND_MESSAGE } from './actions';

    const init = new Model();

    type ActionType = SEND_MESSAGE;

    function mainReducer(
    model: Model = init,
    action: { type: ActionType, payload: Object }
    ) {
    switch (action.type) {
    case SEND_MESSAGE:
    return sendMessage(model, action.payload);
    default:
    return model;
    }
    }

    function nullReducer(
    model: Model = init,
    action
    ) {
    switch (action.type) {
    default:
    return model;
    }
    }

    // private function!!
    function sendMessage(model, payload) {
    if (payload) {
    const message = new MessageType({ text: payload.message })
    const new_model = model.updateIn(
    ["messages"],
    messages => messages.push(message)
    );
    return new_model;
    } else {
    return model;
    }
    }

    const app = combineReducers({
    mainReducer,
    nullReducer
    });

    export default app;
    25 changes: 25 additions & 0 deletions store.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,25 @@
    // @flow

    import reducers from "./reducers";
    import { createStore, applyMiddleware, compose } from "redux";
    import thunk from "redux-thunk";

    function composeWithApplyMiddlewares() {
    if (window.__REDUX_DEVTOOLS_EXTENSION__) {
    return compose(
    applyMiddleware(thunk),
    window.__REDUX_DEVTOOLS_EXTENSION__()
    );
    }
    return compose(applyMiddleware(thunk));
    }

    const createMyStore = () => {
    return createStore(
    reducers,
    {},
    composeWithApplyMiddlewares()
    );
    };

    export default createMyStore();
    76 changes: 76 additions & 0 deletions webpack.config.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,76 @@
    var webpack = require("webpack");
    var path = require("path");

    // We'll be using the ExtractTextPlugin to extract any required CSS into a
    // single CSS file
    const ExtractTextPlugin = require("extract-text-webpack-plugin");
    // We'll use CopyWebpackPlugin to copy over static assets like images and
    // fonts
    const CopyWebpackPlugin = require("copy-webpack-plugin");

    var env = process.env.MIX_ENV || "dev";
    var isProduction = env === "prod";

    // We'll set up some paths for our generated files and our development server
    const staticDir = path.join(__dirname, ".");
    const destDir = path.join(__dirname, "../priv/static");
    const publicPath = "/";

    module.exports = {
    entry: [
    staticDir + "/js/index.js",
    staticDir + "/css/app.scss"
    ],
    output: {
    path: destDir,
    filename: "js/app.js",
    publicPath
    },
    module: {
    loaders: [
    {
    test: /\.jsx?$/,
    loader: 'babel-loader',
    exclude: /node_modules/,
    query: {
    presets: [
    ["es2015"],
    ["react"],
    [
    "env",
    {
    "targets": {
    "browsers": ["last 2 versions", "safari >= 7"]
    },
    "include": ["transform-es2015-arrow-functions", "es6.map"],
    "exclude": []
    }
    ]
    ],
    plugins: [
    ["transform-object-rest-spread", { "useBuiltIns": true }],
    ["transform-class-properties", { "spec": true }]
    ]
    }
    },
    // Any CSS or SCSS files will run through the css loader, the sass
    // loader, and the import-glob-loader. The last one will allow us to use
    // glob patterns to import SCSS files - for instance, a whole directory of
    // them. That isn't available by default in node-sass
    {
    test: /\.s?css$/,
    exclude: [path.resolve(__dirname, "node_modules")],
    loader: ExtractTextPlugin.extract({
    fallback: 'style-loader',
    use: ['css-loader', 'sass-loader', 'import-glob-loader']
    })
    }
    ]
    },
    // And we'll configure our ExtractTextPlugin and CopyWebpackPlugin
    plugins: [
    new ExtractTextPlugin("css/app.css"),
    // We copy our images and fonts to the output folder
    new CopyWebpackPlugin([{ from: "./static/images", to: "images" }])
    ]
    };