carte-server 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1ad405840ee8644a09530f58b55f06d6577e7f47
4
- data.tar.gz: 02712abc98c52f3b2e84b721b6a09d921f3f0847
3
+ metadata.gz: 62e6b5113d7bafffdb2e35701cabd5a01ae26532
4
+ data.tar.gz: 8f4dd2dee37acd726a75e5c4477e5d7ec325e4ab
5
5
  SHA512:
6
- metadata.gz: 0880fb449f7b45ccd725f0d6688c9ce36eb988fdc919261e47fb57171a091701ecb47ad80f06558a190dc1d77912f8d33a3c31e77e3e43bdef56aec5f8ca1ee5
7
- data.tar.gz: 76cbdd005b7ea7b876dbf822f6e5f0c7eb27daf28e6a07316df3bb712600f2e1c18215492dcc92f8cd99216ef75d3781721ba846f1f458dd3db08076b42fc481
6
+ metadata.gz: af45cdb68b5f9de14cfc855e1199453ba0762f41bd6a781dd0e9f5db467f86713da9bd29f138d419e77b8d3bfbff7de045a30a972baf2f28b1631fdc9029853c
7
+ data.tar.gz: 015f9690877ab8a0f6ac5ca9f982b1774163ed38a9fef3fe237f02a516b1278403af5897a1d6f9e4f9113b6eb141030a84f94639b80dee25de4b13f3059fc299
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --format documentation --color
data/Rakefile CHANGED
@@ -1,49 +1,3 @@
1
1
  require "bundler/gem_tasks"
2
- require "carte/server"
2
+ require "carte/server/tasks"
3
3
  Carte::Server.configure { Mongoid.load!('mongoid.yml') }
4
- include Carte::Server::Models
5
-
6
- namespace :carte do
7
- desc 'analyze'
8
- task :analyze do
9
- title, content = {max: 0, min: 0}, {max: 0, min: 0}
10
- count = Hash.new(0)
11
- Card.all.each do |card|
12
- title[:max] = [card.title.length, title[:max]].max
13
- title[:min] = [card.title.length, title[:min]].min
14
- content[:max] = [card.content.length, content[:max]].max
15
- content[:min] = [card.content.length, content[:min]].min
16
- if card.content == ''
17
- puts "#{card.title} : content is empty"
18
- end
19
- count[card.title] += 1
20
- end
21
- puts "title: #{title}, content: #{content}"
22
- count.each do |card, count|
23
- puts "#{card}: #{count} items" if count != 1
24
- end
25
- end
26
-
27
- desc 'import fr.txt'
28
- task :import do
29
- entries = []
30
- file = File.open(ENV['FILE'])
31
- lines = file.read.split("\n")
32
- lines.each_slice(2) do |title, content|
33
- Card.create!(title: title, content: content)
34
- end
35
- end
36
-
37
- desc 'export'
38
- task :export do
39
- Card.all.each do |card|
40
- puts card.title
41
- puts card.content
42
- end
43
- end
44
-
45
- desc 'reset'
46
- task :reset do
47
- Card.delete_all
48
- end
49
- end
data/config.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "title": "carte sandbox",
3
- "description": "sandbox for carte",
2
+ "title": "Carte Sandbox",
3
+ "description": "Sandbox for Carte",
4
4
  "public_folder": "public",
5
5
  "script_path": "public/app.js",
6
- "link_color": "#2C21A6"
6
+ "link_color": "yellow"
7
7
  }
@@ -0,0 +1,4 @@
1
+
2
+ module.exports =
3
+ isMobile: ()->
4
+ /(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent)
@@ -1,4 +1,5 @@
1
1
  Backbone = require('backbone')
2
+ config = require('../../shared/config.json')
2
3
 
3
4
  module.exports = class Card extends Backbone.Model
4
5
  idAttribute: 'title'
@@ -10,10 +11,13 @@ module.exports = class Card extends Backbone.Model
10
11
  if @isNew()
11
12
  console.log @
12
13
  console.log 'url is new'
13
- '/api/cards.json'
14
+ url = '/api/cards.json'
14
15
  else
15
16
  console.log 'url is not new'
16
- '/api/cards/' + @get('title') + '.json'
17
+ url = '/api/cards/' + @get('title') + '.json'
18
+ if config.api_path
19
+ url = config.api_path + url
20
+ url
17
21
 
18
22
  parse: (response)->
19
23
  if response.card then response.card else response
@@ -1,12 +1,16 @@
1
1
  Backbone = require('backbone')
2
2
  CardModel = require('./card')
3
3
  $ = require('jquery')
4
+ config = require('../../shared/config.json')
4
5
 
5
6
  module.exports = class Cards extends Backbone.Collection
6
7
  model: CardModel
7
8
  query: {}
8
9
  url: ()->
9
- '/api/cards.json?' + $.param(@query)
10
+ url = '/api/cards.json?' + $.param(@query)
11
+ if config.api_path
12
+ url = config.api_path + url
13
+ url
10
14
  parse: (response)->
11
15
  console.log response
12
16
  @page = response.page
@@ -3,10 +3,10 @@ React = require('react')
3
3
  Edit = require('./edit')
4
4
  ModalTrigger = require('react-bootstrap/lib/ModalTrigger')
5
5
  markdownIt = require('markdown-it')(linkify: true)
6
+ helpers = require('../helpers')
6
7
 
7
8
  module.exports = React.createClass
8
9
  displayName: 'Card'
9
- isSafariOrUiWebView: /(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent)
10
10
 
11
11
  componentDidMount: ->
12
12
  @props.card.on 'change', @forceUpdate.bind(@, null)
@@ -38,7 +38,7 @@ module.exports = React.createClass
38
38
  <strong>
39
39
  {@props.card.get('title')}
40
40
  </strong>
41
- <span className='pull-right tools' style={{visibility: if @isSafariOrUiWebView || @state.showTools then 'visible' else 'hidden'}}>
41
+ <span className='pull-right tools' style={{visibility: if helpers.isMobile() || @state.showTools then 'visible' else 'hidden'}}>
42
42
  <ModalTrigger modal={<Edit card={@props.card} />}>
43
43
  <a href="javascript:void(0)">
44
44
  <i className='glyphicon glyphicon-edit' />
@@ -54,7 +54,7 @@ module.exports = React.createClass
54
54
  <div style={overflow:'hidden',width:'100%',height:'75%',wordWrap:'break-word'}>
55
55
  <div dangerouslySetInnerHTML={__html: markdownIt.render @props.card.get('content')} />
56
56
  </div>
57
- <div style={{visibility: if @isSafariOrUiWebView || @state.showTools then 'visible' else 'hidden'}}>
57
+ <div style={{visibility: if helpers.isMobile() || @state.showTools then 'visible' else 'hidden'}}>
58
58
  {
59
59
  if @props.card.get("tags")
60
60
  @props.card.get("tags").map (tag)->
@@ -3,6 +3,7 @@ React = require('react')
3
3
  List = require('./list')
4
4
  CardCollection = require('../models/cards')
5
5
  CardModel = require('../models/card')
6
+ String = require('string')
6
7
  config = require('../../shared/config.json')
7
8
 
8
9
  module.exports = React.createClass
@@ -31,7 +32,7 @@ module.exports = React.createClass
31
32
  title = []
32
33
  for k, v of cards.query
33
34
  if k != 'title'
34
- title.push(k + ': ' + v)
35
+ title.push(String(k).capitalize() + ': ' + v)
35
36
  title = title.join(', ')
36
37
  title = 'search: ' + cards.query.title + ' (' + title + ')' if cards.query.title
37
38
  title += ' - ' + config.title
@@ -36,7 +36,7 @@ module.exports = React.createClass
36
36
  <nav className="navbar navbar-default" style={{padding:"0px",backgroundColor:"white",marginBottom:"5px"}}>
37
37
  <div className="container-fluid">
38
38
  <div className="navbar-header">
39
- <a className="navbar-brand" href="#/" style={{paddingTop:"10px"}}>
39
+ <a className="navbar-brand" href={if config.icon_link then config.icon_link else "#/"} style={{paddingTop:"10px"}}>
40
40
  <img alt="Brand" src="/images/icon.png" width="30" height="30" />
41
41
  </a>
42
42
  <a className="navbar-brand" href="#/">
@@ -3,6 +3,8 @@ $ = require('jquery')
3
3
  React = require('react')
4
4
  Cards = require('./cards')
5
5
  CardCollection = require('../models/cards')
6
+ Pagination = require('./pagination')
7
+ helpers = require('../helpers')
6
8
 
7
9
  module.exports = React.createClass
8
10
  displayName: 'List'
@@ -33,11 +35,6 @@ module.exports = React.createClass
33
35
  delete query.page
34
36
  $.param(query)
35
37
 
36
- pageParam: (page)->
37
- query = $.extend {}, @props.cards.query
38
- query = $.extend query, {page: page}
39
- $.param(query)
40
-
41
38
  tagParam: (tag)->
42
39
  query = $.extend {}, @props.cards.query
43
40
  query = $.extend query, {tags: tag}
@@ -78,48 +75,7 @@ module.exports = React.createClass
78
75
  </li>
79
76
  </ul>
80
77
  else
81
- <ul className="nav nav-pills pull-right">
82
- <li>
83
- {
84
- if @props.cards.page
85
- if @props.cards.page.current > 1
86
- href = "/#/?" + @pageParam(@props.cards.page.current - 1)
87
- else
88
- href = "/#/?" + @pageParam(@props.cards.page.total)
89
- else
90
- href = "javascript:void(0)"
91
- <a href={href} aria-label="Previous" style={{padding:'6px 12px'}}>
92
- <span aria-hidden="true">&laquo;</span>
93
- </a>
94
- }
95
- </li>
96
- <li style={width:'4.0em',textAlign:'center'}>
97
- {
98
- if @props.cards.page
99
- <a href={"/#/?" + @pageParam(@props.cards.page.current)} style={{padding:'6px 12px'}}>
100
- {@props.cards.page.current} / {@props.cards.page.total}
101
- </a>
102
- else
103
- <a href="javascript:void(0)" style={{padding:'6px 12px'}}>
104
- <i className="glyphicon glyphicon-refresh glyphicon-refresh-animate" />
105
- </a>
106
- }
107
- </li>
108
- <li>
109
- {
110
- if @props.cards.page
111
- if @props.cards.page.current < @props.cards.page.total
112
- href = "/#/?" + @pageParam(@props.cards.page.current + 1)
113
- else
114
- href = "/#/?" + @pageParam(1)
115
- else
116
- href = "javascript:void(0)"
117
- <a href={href} aria-label="Next" style={{padding:'6px 12px'}}>
118
- <span aria-hidden="true">&raquo;</span>
119
- </a>
120
- }
121
- </li>
122
- </ul>
78
+ <Pagination cards={@props.cards} />
123
79
  }
124
80
  </div>
125
81
  </div>
@@ -133,4 +89,12 @@ module.exports = React.createClass
133
89
  </div>
134
90
  }
135
91
  <Cards cards={@props.cards} />
92
+ {
93
+ if !@props.card && helpers.isMobile()
94
+ <div className="row">
95
+ <div className="col-sm-12" style={{padding:"0px"}}>
96
+ <Pagination cards={@props.cards} />
97
+ </div>
98
+ </div>
99
+ }
136
100
  </div>
@@ -0,0 +1,55 @@
1
+ # @cjsx React.DOM
2
+ $ = require('jquery')
3
+ React = require('react')
4
+
5
+ module.exports = React.createClass
6
+ displayName: 'Pagination'
7
+
8
+ pageParam: (page)->
9
+ query = $.extend {}, @props.cards.query
10
+ query = $.extend query, {page: page}
11
+ $.param(query)
12
+
13
+ render: ->
14
+ <ul className="nav nav-pills pull-right">
15
+ <li>
16
+ {
17
+ if @props.cards.page
18
+ if @props.cards.page.current > 1
19
+ href = "/#/?" + @pageParam(@props.cards.page.current - 1)
20
+ else
21
+ href = "/#/?" + @pageParam(@props.cards.page.total)
22
+ else
23
+ href = "javascript:void(0)"
24
+ <a href={href} aria-label="Previous" style={{padding:'6px 12px'}}>
25
+ <span aria-hidden="true">&laquo;</span>
26
+ </a>
27
+ }
28
+ </li>
29
+ <li style={width:'4.0em',textAlign:'center'}>
30
+ {
31
+ if @props.cards.page
32
+ <a href={"/#/?" + @pageParam(@props.cards.page.current)} style={{padding:'6px 12px'}}>
33
+ {@props.cards.page.current} / {@props.cards.page.total}
34
+ </a>
35
+ else
36
+ <a href="javascript:void(0)" style={{padding:'6px 12px'}}>
37
+ <i className="glyphicon glyphicon-refresh glyphicon-refresh-animate" />
38
+ </a>
39
+ }
40
+ </li>
41
+ <li>
42
+ {
43
+ if @props.cards.page
44
+ if @props.cards.page.current < @props.cards.page.total
45
+ href = "/#/?" + @pageParam(@props.cards.page.current + 1)
46
+ else
47
+ href = "/#/?" + @pageParam(1)
48
+ else
49
+ href = "javascript:void(0)"
50
+ <a href={href} aria-label="Next" style={{padding:'6px 12px'}}>
51
+ <span aria-hidden="true">&raquo;</span>
52
+ </a>
53
+ }
54
+ </li>
55
+ </ul>
data/lib/carte/server.rb CHANGED
@@ -4,6 +4,7 @@ require 'mongoid'
4
4
  require 'mongoid_auto_increment_id'
5
5
  require 'will_paginate_mongoid'
6
6
  require 'mongoid-simple-tags'
7
+ require 'carte/server/validators'
7
8
  require 'carte/server/models'
8
9
 
9
10
  module Carte
@@ -22,6 +22,9 @@ module Carte
22
22
  validates :content,
23
23
  presence: true,
24
24
  length: {maximum: 560}
25
+ validates :tags,
26
+ length: {maximum: 3, message: 'are too many (maximum is 3 tags)'},
27
+ array: {length: {maximum: 10}}
25
28
 
26
29
  has_many :histories
27
30
 
@@ -0,0 +1,47 @@
1
+ require 'carte/server'
2
+ include Carte::Server::Models
3
+
4
+ namespace :carte do
5
+ desc 'analyze data'
6
+ task :analyze do
7
+ title, content = {max: 0, min: 0}, {max: 0, min: 0}
8
+ count = Hash.new(0)
9
+ Card.all.each do |card|
10
+ title[:max] = [card.title.length, title[:max]].max
11
+ title[:min] = [card.title.length, title[:min]].min
12
+ content[:max] = [card.content.length, content[:max]].max
13
+ content[:min] = [card.content.length, content[:min]].min
14
+ if card.content == ''
15
+ puts "#{card.title} : content is empty"
16
+ end
17
+ count[card.title] += 1
18
+ end
19
+ puts "title: #{title}, content: #{content}"
20
+ count.each do |title, count|
21
+ puts "duplicate: #{title}: #{count} items" if count != 1
22
+ end
23
+ end
24
+
25
+ desc 'import pdic one line format data'
26
+ task :import do
27
+ entries = []
28
+ file = File.open(ENV['FILE'])
29
+ lines = file.read.split("\n")
30
+ lines.each_slice(2) do |title, content|
31
+ Card.create!(title: title, content: content)
32
+ end
33
+ end
34
+
35
+ desc 'export data as pdic one line format'
36
+ task :export do
37
+ Card.all.each do |card|
38
+ puts card.title
39
+ puts card.content
40
+ end
41
+ end
42
+
43
+ desc 'reset database'
44
+ task :reset do
45
+ Card.delete_all
46
+ end
47
+ end
@@ -0,0 +1 @@
1
+ require 'carte/server/validators/array_validator'
@@ -0,0 +1,24 @@
1
+
2
+ class ArrayValidator < ActiveModel::EachValidator
3
+ def validate_each(record, attribute, values)
4
+ [values].flatten.each do |value|
5
+ options.each do |key, args|
6
+ validator_options = { attributes: attribute }
7
+ validator_options.merge!(args) if args.is_a?(Hash)
8
+
9
+ next if value.nil? && validator_options[:allow_nil]
10
+ next if value.blank? && validator_options[:allow_blank]
11
+
12
+ validator_class_name = "#{key.to_s.camelize}Validator"
13
+ validator_class = begin
14
+ validator_class_name.constantize
15
+ rescue NameError
16
+ "ActiveModel::Validations::#{validator_class_name}".constantize
17
+ end
18
+
19
+ validator = validator_class.new(validator_options)
20
+ validator.validate_each(record, attribute, value)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -2,6 +2,6 @@ require 'sinatra/base'
2
2
 
3
3
  module Carte
4
4
  class Server < Sinatra::Base
5
- VERSION = "0.0.7"
5
+ VERSION = "0.0.8"
6
6
  end
7
7
  end
data/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "carte-client",
3
3
  "description": "something like dictionary, wiki, or information card",
4
- "version": "0.0.7",
4
+ "version": "0.0.8",
5
5
  "main": "lib/carte.coffee",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -35,6 +35,7 @@
35
35
  "react": "^0.13.2",
36
36
  "react-bootstrap": "^0.21.0",
37
37
  "react-tagsinput": "^1.3.2",
38
+ "string": "^3.1.1",
38
39
  "vinyl-source-stream": "^1.1.0",
39
40
  "watchify": "^3.1.2"
40
41
  }
data/spec/server_spec.rb CHANGED
@@ -10,7 +10,7 @@ end
10
10
 
11
11
  class DictionaryClient
12
12
  include HTTParty
13
- base_uri 'http://localhost/api/'
13
+ base_uri 'http://localhost:9393/api/'
14
14
  format :json
15
15
  end
16
16
 
@@ -40,32 +40,44 @@ describe 'API' do
40
40
  it 'returns error when the title is not specified' do
41
41
  response = client.post('/cards.json', body: {content: 'content1'}.to_json)
42
42
  expect(response.code).to eq(400)
43
- expect(response['card']['errors']).to eq({'title' => ['が入力されていません']})
43
+ expect(response['card']['errors']).to eq({'title' => ["can't be blank"]})
44
44
  end
45
45
 
46
46
  it 'returns error when the content is not specified' do
47
47
  response = client.post('/cards.json', body: {title: 'card1'}.to_json)
48
48
  expect(response.code).to eq(400)
49
- expect(response['card']['errors']).to eq({'content' => ['が入力されていません']})
49
+ expect(response['card']['errors']).to eq({'content' => ["can't be blank"]})
50
50
  end
51
51
 
52
52
  it 'returns error when the title is not unique' do
53
53
  response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
54
54
  response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
55
55
  expect(response.code).to eq(400)
56
- expect(response['card']['errors']).to eq({'title' => ['は既に存在します']})
56
+ expect(response['card']['errors']).to eq({'title' => ['is already taken']})
57
57
  end
58
58
 
59
59
  it 'returns error when the title is too long' do
60
60
  response = client.post('/cards.json', body: {title: 'w' * 71, content: 'content1'}.to_json)
61
61
  expect(response.code).to eq(400)
62
- expect(response['card']['errors']).to eq({'title' => [' 70 文字以内で入力してください']})
62
+ expect(response['card']['errors']).to eq({'title' => ['is too long (maximum is 70 characters)']})
63
63
  end
64
64
 
65
65
  it 'returns error when the content is too long' do
66
66
  response = client.post('/cards.json', body: {title: 'card1', content: 'd' * 561}.to_json)
67
67
  expect(response.code).to eq(400)
68
- expect(response['card']['errors']).to eq({'content' => [' 560 文字以内で入力してください']})
68
+ expect(response['card']['errors']).to eq({'content' => ['is too long (maximum is 560 characters)']})
69
+ end
70
+
71
+ it 'returns error when the tags is too many' do
72
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1', tags: %w(tag1 tag2 tag3 tag4)}.to_json)
73
+ expect(response.code).to eq(400)
74
+ expect(response['card']['errors']).to eq({'tags' => ['are too many (maximum is 3 tags)']})
75
+ end
76
+
77
+ it 'returns error when one of the tags is too long' do
78
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1', tags: ['a' * 11]}.to_json)
79
+ expect(response.code).to eq(400)
80
+ expect(response['card']['errors']).to eq({'tags' => ['is too long (maximum is 10 characters)']})
69
81
  end
70
82
  end
71
83
  end
@@ -126,21 +138,35 @@ describe 'API' do
126
138
  response = client.post('/cards.json', body: {title: 'card2', content: 'content2'}.to_json)
127
139
  response = client.put("/cards/card2.json", body: {new_title: 'card1', content: 'content1'}.to_json)
128
140
  expect(response.code).to eq(400)
129
- expect(response['card']['errors']).to eq({'title' => ['は既に存在します']})
141
+ expect(response['card']['errors']).to eq({'title' => ['is already taken']})
130
142
  end
131
143
 
132
144
  it 'returns error when the title is too long' do
133
145
  response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
134
146
  response = client.put("/cards/card1.json", body: {new_title: 'w' * 71}.to_json)
135
147
  expect(response.code).to eq(400)
136
- expect(response['card']['errors']).to eq({'title' => [' 70 文字以内で入力してください']})
148
+ expect(response['card']['errors']).to eq({'title' => ['is too long (maximum is 70 characters)']})
137
149
  end
138
150
 
139
151
  it 'returns error when the content is too long' do
140
152
  response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
141
153
  response = client.put("/cards/card1.json", body: {content: 'd' * 561}.to_json)
142
154
  expect(response.code).to eq(400)
143
- expect(response['card']['errors']).to eq({'content' => [' 560 文字以内で入力してください']})
155
+ expect(response['card']['errors']).to eq({'content' => ['is too long (maximum is 560 characters)']})
156
+ end
157
+
158
+ it 'returns error when the tags is too many' do
159
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
160
+ response = client.put("/cards/card1.json", body: {tags: %w(tag1 tag2 tag3 tag4)}.to_json)
161
+ expect(response.code).to eq(400)
162
+ expect(response['card']['errors']).to eq({'tags' => ['are too many (maximum is 3 tags)']})
163
+ end
164
+
165
+ it 'returns error when one of the tags is too long' do
166
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
167
+ response = client.put("/cards/card1.json", body: {tags: ['a' * 11]}.to_json)
168
+ expect(response.code).to eq(400)
169
+ expect(response['card']['errors']).to eq({'tags' => ['is too long (maximum is 10 characters)']})
144
170
  end
145
171
  end
146
172
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carte-server
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - tily
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-02 00:00:00.000000000 Z
11
+ date: 2015-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -200,6 +200,7 @@ extensions: []
200
200
  extra_rdoc_files: []
201
201
  files:
202
202
  - .gitignore
203
+ - .rspec
203
204
  - Gemfile
204
205
  - LICENSE.txt
205
206
  - README.md
@@ -211,6 +212,7 @@ files:
211
212
  - lib/carte.coffee
212
213
  - lib/carte.rb
213
214
  - lib/carte/client.coffee
215
+ - lib/carte/client/helpers.coffee
214
216
  - lib/carte/client/models/card.coffee
215
217
  - lib/carte/client/models/cards.coffee
216
218
  - lib/carte/client/router.coffee
@@ -222,10 +224,14 @@ files:
222
224
  - lib/carte/client/views/footer.cjsx
223
225
  - lib/carte/client/views/header.cjsx
224
226
  - lib/carte/client/views/list.cjsx
227
+ - lib/carte/client/views/pagination.cjsx
225
228
  - lib/carte/server.rb
226
229
  - lib/carte/server/models.rb
227
230
  - lib/carte/server/models/card.rb
228
231
  - lib/carte/server/models/history.rb
232
+ - lib/carte/server/tasks.rb
233
+ - lib/carte/server/validators.rb
234
+ - lib/carte/server/validators/array_validator.rb
229
235
  - lib/carte/server/version.rb
230
236
  - lib/carte/server/views/cards.builder
231
237
  - lib/carte/server/views/index.haml