読者です 読者をやめる 読者になる 読者になる

IT練習ノート

IT関連で調べたこと(実際は嵌ったこと)を書いています。

Learn Physics の導入

Learn Physics

learn-physics: Haskell code for learning physics

stackでインストールしてみます。

bar:graphics foo$ stack new graphics-work01
Downloading template "new-template" to create project "graphics-work01" in graphics-work01/ ...

The following parameters were needed by the template but not provided: author-email, author-name, category, copyright, github-username
You can provide them in /Users/foo/.stack/config.yaml, like this:
templates:
  params:
    author-email: value
    author-name: value
    category: value
    copyright: value
    github-username: value
Or you can pass each one as parameters like this:
stack new graphics-work01 new-template -p "author-email:value" -p "author-name:value" -p "category:value" -p "copyright:value" -p "github-username:value"

Looking for .cabal or package.yaml files to use to init the project.
Using cabal packages:
- graphics-work01/graphics-work01.cabal

Selecting the best among 10 snapshots...

Downloaded lts-8.11 build plan.
Fetching package index ...remote: Counting objects: 6105, done.
remote: Compressing objects: 100% (4824/4824), done.
remote: Total 6105 (delta 1641), reused 5005 (delta 1120), pack-reused 0
Receiving objects: 100% (6105/6105), 1.80 MiB | 2.27 MiB/s, done.
Resolving deltas: 100% (1641/1641), completed with 677 local objects.
From https://github.com/commercialhaskell/all-cabal-hashes
 + 94fd2e6...dbe78f6 hackage    -> origin/hackage  (forced update)
 - [tag update]      current-hackage -> current-hackage
Fetched package index.
Populated index cache.
Did not find .cabal file for unbounded-delays-0.1.0.10 with Git SHA of f02d37e48a454a6d91bbc9106222ea7fdd7764d2
Right Nothing
* Matches lts-8.11

Selected resolver: lts-8.11
Initialising configuration using resolver: lts-8.11
Total number of user packages considered: 1
Writing configuration to file: graphics-work01/stack.yaml
All done.

Cabalの編集

executable graphics-work01-exe
  hs-source-dirs:      app
  main-is:             Main.hs
  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
  build-depends:       base
                     , graphics-work01
                     , learn-physics

stack.yamlの編集をします。

# Dependency packages to be pulled from upstream that are not in the resolver
# (e.g., acme-missiles-0.3)
extra-deps: [
      learn-physics-0.6.0.2
    , not-gloss-0.7.7.0
    , spatial-math-0.2.7.0
]

上記のstack.yamlの設定をしないでstack buildすると、エラーとなります。

bar:graphics-work01 foo$ stack build
While constructing the BuildPlan the following exceptions were encountered:

--  Failure when adding dependencies:
      learn-physics: needed (-any), stack configuration has no specified version (latest applicable is 0.6.0.2)
    needed for package graphics-work01-0.1.0.0

--  While attempting to add dependency,
    Could not find package learn-physics in known packages

Recommended action: try adding the following to your extra-deps in /Users/foo/work03/graphics/graphics-work01/stack.yaml
- learn-physics-0.6.0.2

You may also want to try the 'stack solver' command

このエラーを解決するにはstack solverを実行します。そうすると、修正方法を教えてくれます。これが上述の設定になります。

bar:graphics-work01 foo$ stack solver
Using configuration file: stack.yaml
Using cabal packages:
- graphics-work01.cabal

Using resolver: lts-8.11
Using compiler: ghc-8.0.2
Asking cabal to calculate a build plan...
Trying with packages from lts-8.11 as hard constraints...
Successfully determined a build plan with 3 external dependencies.

The following changes will be made to stack.yaml:
* Resolver is lts-8.11
* Dependencies to be added
    extra-deps:
    - learn-physics-0.6.0.2
    - not-gloss-0.7.7.0
    - spatial-math-0.2.7.0

To automatically update stack.yaml, rerun with '--update-config'

初回のstack buildで依存関係を解決したライブラリがインストールされます。

bar:graphics-work01 foo$ stack build
graphics-work01-0.1.0.0: unregistering (missing dependencies: learn-physics)
ObjectName-1.1.0.1: download
ObjectName-1.1.0.1: configure

途中省略[f:id:naotoogawa:20170416134218p:plain]

learn-physics-0.6.0.2: build
learn-physics-0.6.0.2: copy/register
graphics-work01-0.1.0.0: configure
Configuring graphics-work01-0.1.0.0...
graphics-work01-0.1.0.0: build
Preprocessing library graphics-work01-0.1.0.0...
[1 of 1] Compiling Lib              ( src/Lib.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/Lib.o )
ld: warning: directory not found for option '-L/opt/local/lib/'
Preprocessing executable 'graphics-work01-exe' for graphics-work01-0.1.0.0...
[1 of 1] Compiling Main             ( app/Main.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/graphics-work01-exe/graphics-work01-exe-tmp/Main.o ) [Lib changed]
Linking .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/graphics-work01-exe/graphics-work01-exe ...
ld: warning: directory not found for option '-L/opt/local/lib/'
graphics-work01-0.1.0.0: copy/register
Installing library in
/Users/foo/work03/graphics/graphics-work01/.stack-work/install/x86_64-osx/lts-8.11/8.0.2/lib/x86_64-osx-ghc-8.0.2/graphics-work01-0.1.0.0-Df1PA4o0N7R3GcxbM23sV6
Installing executable(s) in
/Users/foo/work03/graphics/graphics-work01/.stack-work/install/x86_64-osx/lts-8.11/8.0.2/bin
Registering graphics-work01-0.1.0.0...
Completed 61 action(s).
bar:graphics-work01 foo$ ls

サンプルを取得します。

bar:app foo$ curl -O https://raw.githubusercontent.com/walck/learn-physics/master/examples/src/LorentzForceSimulation.hs
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1464  100  1464    0     0   4636      0 --:--:-- --:--:-- --:--:--  4647
bar:app foo$ ls
LorentzForceSimulation.hs   Main.hs             eFieldLine2D.hs
bar:app foo$

cabalファイルに、main関数があるファイルの指定と、依存関係ライブラリの指定を追加します。

executable graphics-work01-exe
  hs-source-dirs:      app
  main-is:             LorentzFoArceSimulation.hs
  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
  build-depends:       base
                     , graphics-work01
                     , learn-physics
                     , not-gloss
                     , spatial-math
                     , gloss
  default-language:    Haskell2010

ビルドします。

bar:graphics-work01 foo$ stack build
graphics-work01-0.1.0.0: build
Preprocessing library graphics-work01-0.1.0.0...
Preprocessing executable 'graphics-work01-exe' for graphics-work01-0.1.0.0...
[1 of 1] Compiling Main             ( app/LorentzForceSimulation.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/graphics-work01-exe/graphics-work01-exe-tmp/Main.o )
Linking .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/graphics-work01-exe/graphics-work01-exe ...
ld: warning: directory not found for option '-L/opt/local/lib/'
graphics-work01-0.1.0.0: copy/register
Installing library in
/Users/foo/work03/graphics/graphics-work01/.stack-work/install/x86_64-osx/lts-8.11/8.0.2/lib/x86_64-osx-ghc-8.0.2/graphics-work01-0.1.0.0-Jws64xXpAJx1AXCetAcS6y
Installing executable(s) in
/Users/foo/work03/graphics/graphics-work01/.stack-work/install/x86_64-osx/lts-8.11/8.0.2/bin
Registering graphics-work01-0.1.0.0...

実行します。

bar:graphics-work01 foo$ stack exec graphics-work01-exe
bar:graphics-work01 foo$

f:id:naotoogawa:20170416134218p:plain

Servantでipadress取得のサンプル

Servant IP Address Sample

ghcmod-vimのインストールで嵌った点

foo$ ls -al ~/.cache/dein/repos/github.com/eagletmt/ghcmod-vim/     
total 80
drwxr-xr-x  18 foo  staff   612  4  2 15:11 .
drwxr-xr-x   4 foo  staff   136  4  2 14:45 ..
drwxr-xr-x  15 foo  staff   510  4  2 19:00 .git
-rw-r--r--   1 foo  staff    49  4  2 14:45 .gitignore
-rw-r--r--   1 foo  staff   293  4  2 14:45 .travis.yml
-rw-r--r--   1 foo  staff   645  4  2 14:45 CONTRIBUTING.md
-rw-r--r--   1 foo  staff  3049  4  2 14:45 ChangeLog.md
-rw-r--r--   1 foo  staff  5207  4  2 14:45 README.md
drwxr-xr-x   3 foo  staff   102  4  2 14:45 after
drwxr-xr-x   4 foo  staff   136  4  2 14:45 autoload
-rwxr-xr-x   1 foo  staff   113  4  2 14:45 dist.sh
-rw-r--r--   1 foo  staff   180  4  2 14:45 dist.vim
drwxr-xr-x   3 foo  staff   102  4  2 14:45 doc
-rwxr-xr-x   1 foo  staff   360  4  2 14:45 install-deps.sh
drwxr-xr-x   4 foo  staff   136  4  2 17:08 plugin
drwxr-xr-x  17 foo  staff   578  4  2 14:45 test
-rwxr-xr-x   1 foo  staff   362  4  2 14:45 test.sh
-rw-r--r--   1 foo  staff     0  4  2 15:11 verbose.log
foo$ 

本来的な解決方法ではないと思いますが、afterというディレクトリにあるコードをpluginディレクトリにあるファイルにコピーしたら動きました。私の環境では、どこかfile typeの扱いがうまくいっていないようです。

neovimの導入

neovimbrewでインストールします。

https://github.com/neovim/neovim

foo$ brew install neovim/neovim/neovim
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core, homebrew/php).
==> New Formulae
alexjs                        dmtx-utils                    gtef                          httpflow                      llvm@3.9                      teleport

...

==> Renamed Formulae
bash-completion2 -> bash-completion@2                       gsl1 -> gsl@1                                               percona-server56 -> percona-server@5.6

...

==> Tapping neovim/neovim
Cloning into '/usr/local/Homebrew/Library/Taps/neovim/homebrew-neovim'...
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 7 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (7/7), done.
Checking connectivity... done.
Tapped 1 formula (32 files, 35.2KB)
==> Installing neovim from neovim/neovim
==> Installing dependencies for neovim/neovim/neovim: cmake, libtool, autoconf, automake, pkg-config, jemalloc, libuv, msgpack, unibilium, libtermkey, libvterm
==> Installing neovim/neovim/neovim dependency: cmake
==> Downloading https://homebrew.bintray.com/bottles/cmake-3.7.2.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring cmake-3.7.2.yosemite.bottle.tar.gz
==> Caveats
Emacs Lisp files have been installed to:
  /usr/local/share/emacs/site-lisp/cmake
==> Summary
🍺  /usr/local/Cellar/cmake/3.7.2: 2,143 files, 29.3MB
==> Installing neovim/neovim/neovim dependency: libtool
==> Downloading https://homebrew.bintray.com/bottles/libtool-2.4.6_1.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libtool-2.4.6_1.yosemite.bottle.tar.gz
==> Caveats
In order to prevent conflicts with Apple's own libtool we have prepended a "g"
so, you have instead: glibtool and glibtoolize.
==> Summary
🍺  /usr/local/Cellar/libtool/2.4.6_1: 70 files, 3.7MB
==> Installing neovim/neovim/neovim dependency: autoconf
==> Downloading https://homebrew.bintray.com/bottles/autoconf-2.69.yosemite.bottle.4.tar.gz
######################################################################## 100.0%
==> Pouring autoconf-2.69.yosemite.bottle.4.tar.gz
==> Caveats
Emacs Lisp files have been installed to:
  /usr/local/share/emacs/site-lisp/autoconf
==> Summary
🍺  /usr/local/Cellar/autoconf/2.69: 70 files, 3.0MB
==> Installing neovim/neovim/neovim dependency: automake
==> Downloading https://homebrew.bintray.com/bottles/automake-1.15.yosemite.bottle.2.tar.gz
######################################################################## 100.0%
==> Pouring automake-1.15.yosemite.bottle.2.tar.gz
🍺  /usr/local/Cellar/automake/1.15: 130 files, 2.9MB
==> Installing neovim/neovim/neovim dependency: pkg-config
==> Downloading https://homebrew.bintray.com/bottles/pkg-config-0.29.2.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring pkg-config-0.29.2.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/pkg-config/0.29.2: 11 files, 631KB
==> Installing neovim/neovim/neovim dependency: jemalloc
==> Downloading https://homebrew.bintray.com/bottles/jemalloc-4.5.0.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring jemalloc-4.5.0.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/jemalloc/4.5.0: 16 files, 1.4MB
==> Installing neovim/neovim/neovim dependency: libuv
==> Downloading https://homebrew.bintray.com/bottles/libuv-1.11.0.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libuv-1.11.0.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/libuv/1.11.0: 56 files, 2.3MB
==> Installing neovim/neovim/neovim dependency: msgpack
==> Downloading https://homebrew.bintray.com/bottles/msgpack-2.1.1.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring msgpack-2.1.1.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/msgpack/2.1.1: 662 files, 5MB
==> Installing neovim/neovim/neovim dependency: unibilium
==> Downloading https://homebrew.bintray.com/bottles/unibilium-1.2.0.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring unibilium-1.2.0.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/unibilium/1.2.0: 62 files, 271.3KB
==> Installing neovim/neovim/neovim dependency: libtermkey
==> Downloading https://homebrew.bintray.com/bottles/libtermkey-0.19.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libtermkey-0.19.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/libtermkey/0.19: 32 files, 103.8KB
==> Installing neovim/neovim/neovim dependency: libvterm
==> Downloading https://homebrew.bintray.com/bottles/libvterm-681.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libvterm-681.yosemite.bottle.tar.gz
🍺  /usr/local/Cellar/libvterm/681: 11 files, 167.8KB
==> Installing neovim/neovim/neovim 
==> Downloading https://github.com/neovim/neovim/archive/v0.1.7.tar.gz
==> Downloading from https://codeload.github.com/neovim/neovim/tar.gz/v0.1.7
######################################################################## 100.0%
==> Downloading https://github.com/luvit/luv/archive/146f1ce4c08c3b67f604c9ee1e124b1cf5c15cf3.tar.gz
==> Downloading from https://codeload.github.com/luvit/luv/tar.gz/146f1ce4c08c3b67f604c9ee1e124b1cf5c15cf3
######################################################################## 100.0%
==> Downloading https://raw.githubusercontent.com/neovim/deps/master/opt/LuaJIT-2.0.4.tar.gz
######################################################################## 100.0%
==> Downloading https://github.com/keplerproject/luarocks/archive/5d8a16526573b36d5b22aa74866120c998466697.tar.gz
==> Downloading from https://codeload.github.com/luarocks/luarocks/tar.gz/5d8a16526573b36d5b22aa74866120c998466697
######################################################################## 100.0%
==> Building third-party dependencies.
==> cmake ../third-party -DUSE_BUNDLED_BUSTED=OFF -DUSE_BUNDLED_GPERF=OFF -DUSE_BUNDLED_LIBUV=OFF -DUSE_BUNDLED_MSGPACK=OFF -DUSE_BUNDLED_UNIBILIUM=OFF -DUSE_BUNDLED_LIBTERMKEY=O
==> make VERBOSE=1
==> Building Neovim.
==> cmake .. -DCMAKE_C_FLAGS_RELEASE=-DNDEBUG -DCMAKE_CXX_FLAGS_RELEASE=-DNDEBUG -DCMAKE_INSTALL_PREFIX=/usr/local/Cellar/neovim/0.1.7 -DCMAKE_BUILD_TYPE=Release -DCMAKE_FIND_FRA
==> make VERBOSE=1 install
==> Caveats
To run Neovim, use the "nvim" command (not "neovim"):
    nvim

After installing or upgrading, run the "CheckHealth" command:
    :CheckHealth

To use your existing Vim configuration:
    ln -s ~/.vim ~/.config/nvim
    ln -s ~/.vimrc ~/.config/nvim/init.vim
See ':help nvim' for more information.

Breaking changes (if any) are documented at:
    https://github.com/neovim/neovim/wiki/Following-HEAD

For other questions:
    https://github.com/neovim/neovim/wiki/FAQ
==> Summary
🍺  /usr/local/Cellar/neovim/0.1.7: 1,333 files, 16.9MB, built in 2 minutes 34 seconds
foo$ nvim
foo$ brew install neovim/neovim/neovim

設定ファイルの場所

~/.config/nvim/init.vim

記載内容は下記を参考にしてdeinを導入します。

qiita.com

導入するプラグインは下記に記述します。

/Users/foo/.dein.toml

[[plugins]]
repo = 'Shougo/dein.vim'

[[plugins]]
repo = 'Shougo/vimproc.vim'
build = 'make'

[[plugins]]
repo = 'Shougo/neosnippet-snippets'

/Users/foo/.dein_lazy.toml

[[plugins]]
repo = 'Shougo/neomru.vim'
on_path = '.*'

[[plugins]]
repo = 'jiangmiao/auto-pairs'
on_i = 1

[[plugins]]
repo = 'Shougo/neoyank.vim'
on_path = '.*'
on_i = 1

[[plugins]]
repo = 'Shougo/neosnippet'
depends = ['neosnippet-snippets']
on_i = 1
on_ft = ['snippet']

[[plugins]]
repo = 'Shougo/neocomplete'
if = 'has("lua")'
on_i = 1

[[plugins]]
repo = 'Shougo/deoplete.nvim'
if = 'has("nvim")'
on_i = 1

[[plugins]]
repo = 'Shougo/unite.vim'
depends = 'neomru.vim'

# [[plugins]]
# repo  = 'begriffs/haskell-vim-now'
# on_ft = ['haskell']

# [[plugins]]
# repo = 'neovimhaskell/haskell-vim'
# on_ft = ['haskell']

[[plugins]]
repo  = 'eagletmt/neco-ghc'
on_ft = ['haskell']

[[plugins]]
repo  = 'eagletmt/ghcmod-vim'
on_ft = ['haskell']

[[plugins]]
repo = 'scrooloose/nerdtree'

nvimを起動するとプラグインがインストールされます。

foo$ nvim ./servant03/MyWebApp1.hs 
[dein] Not installed plugins: ['ghcmod-vim']
[dein] Update started: (2017/04/02 14:45:54)

[dein] Updated plugins:
[dein]   ghcmod-vim(1 change)
[dein] Done: (2017/04/02 14:45:59)
続けるにはENTERを押すかコマンドを入力してください

インストールしたプラグインcacheに取り込まれます。

foo$ ls ~/.cache/dein/repos/github.com/
Shougo/        altercation/   begriffs/      dag/           eagletmt/
jiangmiao/     morhetz/       nanotech/      neovimhaskell/ scrooloose/
vim-scripts/
foo$ ls ~/.cache/dein/repos/github.com/

react-bootstrap-tableでcolumnが動的の場合のテーブル生成

Reactのテーブルコンポーネントはどれがデファクトなのでしょうか。よくわからなかったので、目についたreact-bootstrap-tableを使ってみました。

allenfang.github.io

ライブラリの取り込み

    <script src="https://unpkg.com/react@15/dist/react.js"></script>
    <script src="https://unpkg.com/react-dom@15/dist/react-dom.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>

要素の作成

    <div id="result"></div>

以下のようなデータをAPIで取得できるとします。

{ 
  colomuns : ["col_a", "col_b", "col_c"]
 .resultSet : [
    {"id" : 1, "col_a" : "val_foo_a", "col_b" : "val_foo_b", "col_c" : "val_foo_c"}
   ,{"id" : 2, "col_a" : "val_bar_a", "col_b" : "val_bar_b", "col_c" : "val_bar_c"}
   ,{"id" : 3, "col_a" : "val_bazz_a", "col_b" : "val_bazz_b", "col_c" : "val_bazz_c"}
  ]
}

ライブラリ自体に動的にカラムを生成する機能はありませんが、下記にある通り、少しコードを書けば実現できます。

github.com

ただし、ここでの、やり取りでは述べられていませんが、Reactの仮想DOMの管理上1つのカラムのデータはユニークである必要があり、そのカラムに対してisKey属性で指定する必要があります。

下記がfetchAPIアクセスして、テーブル反映までのコードになります。id列をユニークキーとしています。

function query() {
  fetch('http://127.0.0.1:8081/query', {
    method : 'POST',
    mode   : 'cors',
    headers: new Headers({"Content-Type" : "application/x-www-form-urlencoded"}),
    body   : 'foo=bar'
  }).then(function(response) {
    response.json().then(
      (json) => {
        ReactDOM.render(
          <BootstrapTable data={json.resultSet} striped hover>
             {json.columns.map(
                (name) => <TableHeaderColumn 
                                 dataField = { name } 
                                 isKey     = { name === "id" } >
                              { name }
                          </TableHeaderColumn>
             )}
          </BootstrapTable>,
          document.getElementById('result')
        ); // render
      }); // then
  }).catch(function(err) {
    console.log(err);
  });
}

ReactでHTMLの共通化

SBAdmin2のダッシュボードページにあるカードのUI部分をReactにて共通化してみました。

startbootstrap.com

ここの部分です。

f:id:naotoogawa:20170326160605p:plain

下記が4枚あるカードのコードになります。これをReactを使って共通化します。背景色と表示内容だけが異なり、タグの構造は全く同じです。

            <div class="row">
                <div class="col-lg-3 col-md-6">
                    <div class="panel panel-primary">
                        <div class="panel-heading">
                            <div class="row">
                                <div class="col-xs-3">
                                    <i class="fa fa-comments fa-5x"></i>
                                </div>
                                <div class="col-xs-9 text-right">
                                    <div class="huge">26</div>
                                    <div>New Comments!</div>
                                </div>
                            </div>
                        </div>
                        <a href="#">
                            <div class="panel-footer">
                                <span class="pull-left">View Details</span>
                                <span class="pull-right"><i class="fa fa-arrow-circle-right"></i></span>
                                <div class="clearfix"></div>
                            </div>
                        </a>
                    </div>
                </div>
                <div class="col-lg-3 col-md-6">
                    <div class="panel panel-green">
                        <div class="panel-heading">
                            <div class="row">
                                <div class="col-xs-3">
                                    <i class="fa fa-tasks fa-5x"></i>
                                </div>
                                <div class="col-xs-9 text-right">
                                    <div class="huge">12</div>
                                    <div>New Tasks!</div>
                                </div>
                            </div>
                        </div>
                        <a href="#">
                            <div class="panel-footer">
                                <span class="pull-left">View Details</span>
                                <span class="pull-right"><i class="fa fa-arrow-circle-right"></i></span>
                                <div class="clearfix"></div>
                            </div>
                        </a>
                    </div>
                </div>
                <div class="col-lg-3 col-md-6">
                    <div class="panel panel-yellow">
                        <div class="panel-heading">
                            <div class="row">
                                <div class="col-xs-3">
                                    <i class="fa fa-shopping-cart fa-5x"></i>
                                </div>
                                <div class="col-xs-9 text-right">
                                    <div class="huge">124</div>
                                    <div>New Orders!</div>
                                </div>
                            </div>
                        </div>
                        <a href="#">
                            <div class="panel-footer">
                                <span class="pull-left">View Details</span>
                                <span class="pull-right"><i class="fa fa-arrow-circle-right"></i></span>
                                <div class="clearfix"></div>
                            </div>
                        </a>
                    </div>
                </div>
                <div class="col-lg-3 col-md-6">
                    <div class="panel panel-red">
                        <div class="panel-heading">
                            <div class="row">
                                <div class="col-xs-3">
                                    <i class="fa fa-support fa-5x"></i>
                                </div>
                                <div class="col-xs-9 text-right">
                                    <div class="huge">13</div>
                                    <div>Support Tickets!</div>
                                </div>
                            </div>
                        </div>
                        <a href="#">
                            <div class="panel-footer">
                                <span class="pull-left">View Details</span>
                                <span class="pull-right"><i class="fa fa-arrow-circle-right"></i></span>
                                <div class="clearfix"></div>
                            </div>
                        </a>
                    </div>
                </div>
            </div>

まず、ライブラリを取り込みます。

    <!-- React.js -->
    <script src="https://unpkg.com/react@15/dist/react.js"></script>
    <script src="https://unpkg.com/react-dom@15/dist/react-dom.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>

カードのHTML部分はdiv要素のみにします。

            <div class="row">
                <div id="card1"></div>
                <div id="card2"></div>
                <div id="card3"></div>
                <div id="card4"></div>
            </div>

カードのコードはJSXで書き直します。class属性はclassName属性に書き換えます。そして、カードごとに異なる部分はパラメータとします。{}で囲った部分に値を埋め込みます。

function getCard(prop) {
return <div className="col-lg-3 col-md-6">
    <div className={prop.mainStyle}>
        <div className="panel-heading">
            <div className="row">
                <div className="col-xs-3">
                    <i className="fa fa-comments fa-5x"></i>
                </div>
                <div className="col-xs-9 text-right">
                    <div className="huge">{prop.num}</div>
                    <div>{prop.text}</div>
                </div>
            </div>
        </div>
        <a href="#">
            <div className="panel-footer">
                <span className="pull-left">View Details</span>
                <span className="pull-right"><i className="fa fa-arrow-circle-right"></i></span>
                <div className="clearfix"></div>
            </div>
        </a>
    </div>
</div>;
}

共通化したコードに実引数を与えて、先ほど定義したdiv要素と関連付けさせます。

ReactDOM.render(
  getCard({num : 26, text : "New Comments!", mainStyle : "panel panel-primary"}),
  document.getElementById('card1')
)
ReactDOM.render(
  getCard({num : 12, text : "New Tasks!", mainStyle : "panel panel-green"}),
  document.getElementById('card2')
)
ReactDOM.render(
  getCard({num : 124, text : "New Orders!", mainStyle : "panel panel-yellow"}),
  document.getElementById('card3')
)
ReactDOM.render(
  getCard({num : 13, text : "Support Tickets!", mainStyle : "panel panel-red"}),
  document.getElementById('card4')
)

Fluxとしてイベントやデータバインディングの実装をしないで、単なるUIの共通化として利用するのもありかと思いました。

ServantのCSVファイルダウンロードのサンプル

Servant CSV download sample

$ curl -i http://127.0.0.1:8081/csv/UNdata_Export_pork
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Date: Mon, 20 Jun 2016 16:12:16 GMT
Server: Warp/3.2.9
Content-Type: application/csv

"Country or Area","Year","Unit","Value","Value Footnotes"
"Albania","2013","Mil. USD","3.86207176515949",""
"Albania","2013","Thousand metric tons","0.8",""
"Albania","2012","Mil. USD","3.17974879791774",""
"Albania","2012","Thousand metric tons","0.8",""