carte-server 1.0.8 → 1.0.9
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 +4 -4
- data/lib/carte/client/models/tag.coffee +9 -0
- data/lib/carte/client/models/tags.coffee +10 -0
- data/lib/carte/client/router.coffee +5 -0
- data/lib/carte/client/views/content.cjsx +9 -0
- data/lib/carte/client/views/edit.cjsx +1 -1
- data/lib/carte/client/views/edit_tag.cjsx +66 -0
- data/lib/carte/client/views/list.cjsx +23 -14
- data/lib/carte/client/views/tags.cjsx +65 -0
- data/lib/carte/server.rb +17 -0
- data/package.json +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd3f472fe4bb7d487fcdaed6f4ac9d6e4fcc55ae
|
4
|
+
data.tar.gz: c52db06dafe184f6a745ce5c678be0603b38e581
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14e3089137ea1bd9b1048eb573679eb85f5d5117f6de0eccabff4acf27d8c6590a6816db20877edef2e424c99e6743107ffe9294076808f74628f64ec2350b92
|
7
|
+
data.tar.gz: 3cac1e649934df4c691bc351325b0eaf3d91ed0d9305c1fba54afdcda896334472351d4a7db0da650cf1804945e9ab85bc0f53d884830cf05e8c4e0bae6d04d6
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Backbone = require('backbone')
|
2
|
+
config = require('../config')
|
3
|
+
querystring = require('querystring')
|
4
|
+
$ = require('jquery')
|
5
|
+
|
6
|
+
module.exports = class Tag extends Backbone.Model
|
7
|
+
modelName: 'Tag'
|
8
|
+
idAttribute: 'name'
|
9
|
+
url: ()-> config.root_path + config.api_path + '/tags/' + encodeURIComponent(@get('name')) + '.json'
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Backbone = require('backbone')
|
2
|
+
Tag = require('./tag')
|
3
|
+
$ = require('jquery')
|
4
|
+
config = require('../config')
|
5
|
+
|
6
|
+
module.exports = class Tags extends Backbone.Collection
|
7
|
+
collectionName: 'Tags'
|
8
|
+
model: Tag
|
9
|
+
url: config.root_path + config.api_path + '/tags.json'
|
10
|
+
parse: (response)-> response.tags
|
@@ -3,10 +3,15 @@ Backbone = require('backbone')
|
|
3
3
|
|
4
4
|
module.exports = class Router extends Backbone.Router
|
5
5
|
routes:
|
6
|
+
'tags': 'tags'
|
6
7
|
'': 'list'
|
7
8
|
':title': 'show'
|
8
9
|
':title/history': 'history'
|
9
10
|
|
11
|
+
tags: ->
|
12
|
+
console.log '[router] tags'
|
13
|
+
@current = 'tags'
|
14
|
+
|
10
15
|
list: (string)->
|
11
16
|
console.log '[router] list', string
|
12
17
|
location.hash = '/' if location.hash == ''
|
@@ -2,10 +2,12 @@
|
|
2
2
|
$ = require('jquery')
|
3
3
|
React = require('react')
|
4
4
|
List = require('./list')
|
5
|
+
Tags = require('./tags')
|
5
6
|
Slideshow = require('./slideshow')
|
6
7
|
CardCollection = require('../models/cards')
|
7
8
|
CardHistoryCollection = require('../models/card_histories')
|
8
9
|
CardModel = require('../models/card')
|
10
|
+
TagCollection = require('../models/tags')
|
9
11
|
String = require('string')
|
10
12
|
config = require('../config')
|
11
13
|
|
@@ -73,6 +75,13 @@ module.exports = React.createClass
|
|
73
75
|
cards.fetch success: ()-> cards.fetching = false
|
74
76
|
document.title = config.title + '、ヒストリー'
|
75
77
|
<List key='list' router={@props.router} cards={cards} />
|
78
|
+
when "tags"
|
79
|
+
console.log '[views/content] tags', @props
|
80
|
+
tags = new TagCollection()
|
81
|
+
tags.fetching = true
|
82
|
+
tags.fetch success: ()-> tags.fetching = false
|
83
|
+
document.title = config.title + '、タグ一覧'
|
84
|
+
<Tags tags={tags} />
|
76
85
|
else
|
77
86
|
null
|
78
87
|
}
|
@@ -53,7 +53,7 @@ module.exports = React.createClass
|
|
53
53
|
else
|
54
54
|
@props.onRequestHide()
|
55
55
|
@props.card.set 'title', @state.title
|
56
|
-
location.hash = '/' + @state.title
|
56
|
+
location.hash = '/' + encodeURIComponent(@state.title)
|
57
57
|
else
|
58
58
|
@props.onRequestHide()
|
59
59
|
@props.card = new CardModel()
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# @cjsx React.DOM
|
2
|
+
$ = require('jquery')
|
3
|
+
React = require('react/addons')
|
4
|
+
Modal = require('react-bootstrap/lib/Modal')
|
5
|
+
Button = require('react-bootstrap/lib/Button')
|
6
|
+
|
7
|
+
module.exports = React.createClass
|
8
|
+
mixins: [React.addons.LinkedStateMixin]
|
9
|
+
|
10
|
+
displayName: 'EditTag'
|
11
|
+
|
12
|
+
getInitialState: ()->
|
13
|
+
updating: false
|
14
|
+
name: @props.tag.get('name')
|
15
|
+
errors: false
|
16
|
+
shaking: false
|
17
|
+
|
18
|
+
onChangeName: (event)->
|
19
|
+
@setState name: event.target.value
|
20
|
+
|
21
|
+
onClickOk: (event)->
|
22
|
+
event.preventDefault()
|
23
|
+
@setState updating: true
|
24
|
+
attributes = {new_name: @state.name}
|
25
|
+
@props.tag.save attributes,
|
26
|
+
success: ()=>
|
27
|
+
@props.tag.set 'name', @state.name
|
28
|
+
@props.onRequestHide()
|
29
|
+
error: (model, response, options)=>
|
30
|
+
@setState errors: response.responseJSON.tag.errors
|
31
|
+
@setState updating: false
|
32
|
+
@setState shaking: true
|
33
|
+
setTimeout (=> @setState shaking: false), 300
|
34
|
+
|
35
|
+
render: ->
|
36
|
+
<Modal className={"animated infinite shake" if @state.shaking} {...@props} bsStyle='default' title={<i className="glyphicon glyphicon-edit" />} animation={false}>
|
37
|
+
<div className='modal-body'>
|
38
|
+
{
|
39
|
+
if @state.errors
|
40
|
+
<div className="alert alert-danger" role="alert">
|
41
|
+
<ul>
|
42
|
+
{
|
43
|
+
for key, errors of @state.errors
|
44
|
+
for error in errors
|
45
|
+
<li>{key + ' ' + error}</li>
|
46
|
+
}
|
47
|
+
</ul>
|
48
|
+
</div>
|
49
|
+
}
|
50
|
+
<div className="form-group">
|
51
|
+
<label className="control-label">Name</label>
|
52
|
+
<input type="text" className="form-control" value={@state.name} onChange={@onChangeName} disabled={@state.updating} id="inputError1" />
|
53
|
+
</div>
|
54
|
+
<div className="form-group">
|
55
|
+
<button className="btn btn-default pull-right" onClick={@onClickOk} disabled={@state.updating}>
|
56
|
+
|
57
|
+
OK
|
58
|
+
|
59
|
+
{
|
60
|
+
if @state.updating
|
61
|
+
<i className='glyphicon glyphicon-refresh glyphicon-refresh-animate' />
|
62
|
+
}
|
63
|
+
</button>
|
64
|
+
</div>
|
65
|
+
</div>
|
66
|
+
</Modal>
|
@@ -81,6 +81,11 @@ module.exports = React.createClass
|
|
81
81
|
</a>
|
82
82
|
</li>
|
83
83
|
}
|
84
|
+
<li>
|
85
|
+
<a href={"#/tags"}>
|
86
|
+
<i className="glyphicon glyphicon-tag" />
|
87
|
+
</a>
|
88
|
+
</li>
|
84
89
|
<li>
|
85
90
|
<a href={config.root_path + config.api_path + "/cards.xml?" + @queryParam({}, [])}>
|
86
91
|
<i className="fa fa-rss" />
|
@@ -94,16 +99,20 @@ module.exports = React.createClass
|
|
94
99
|
</ul>
|
95
100
|
</div>
|
96
101
|
<div className="col-sm-4">
|
97
|
-
<
|
98
|
-
<
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
102
|
+
<ul className="nav nav-pills nav-justified">
|
103
|
+
<li>
|
104
|
+
<a href="javascript:void(0)" className="center-block text-center">
|
105
|
+
<span className="badge">
|
106
|
+
{
|
107
|
+
if @props.cards.pagination
|
108
|
+
@props.cards.pagination.total_entries
|
109
|
+
else
|
110
|
+
<i className="glyphicon glyphicon-refresh glyphicon-refresh-animate" />
|
111
|
+
}
|
112
|
+
</span>
|
113
|
+
</a>
|
114
|
+
</li>
|
115
|
+
</ul>
|
107
116
|
</div>
|
108
117
|
<div className="col-sm-4">
|
109
118
|
{
|
@@ -136,7 +145,7 @@ module.exports = React.createClass
|
|
136
145
|
<div className="col-sm-12">
|
137
146
|
<ul className="nav nav-pills">
|
138
147
|
<li>
|
139
|
-
<a href={"#/" + title + '?context=title'}>
|
148
|
+
<a href={"#/" + encodeURIComponent(title) + '?context=title'}>
|
140
149
|
{
|
141
150
|
if @props.card && @props.card.query.context == 'title'
|
142
151
|
<strong>A to Z</strong>
|
@@ -146,7 +155,7 @@ module.exports = React.createClass
|
|
146
155
|
</a>
|
147
156
|
</li>
|
148
157
|
<li>
|
149
|
-
<a href={"#/" + title + '?context=updated_at'}>
|
158
|
+
<a href={"#/" + encodeURIComponent(title) + '?context=updated_at'}>
|
150
159
|
{
|
151
160
|
if @props.card && @props.card.query.context == 'updated_at'
|
152
161
|
<strong>Latest</strong>
|
@@ -156,7 +165,7 @@ module.exports = React.createClass
|
|
156
165
|
</a>
|
157
166
|
</li>
|
158
167
|
<li>
|
159
|
-
<a href={"#/" + title + '?context=none'}>
|
168
|
+
<a href={"#/" + encodeURIComponent(title) + '?context=none'}>
|
160
169
|
{
|
161
170
|
if @props.card && @props.card.query.context == 'none'
|
162
171
|
<strong>Detail</strong>
|
@@ -166,7 +175,7 @@ module.exports = React.createClass
|
|
166
175
|
</a>
|
167
176
|
</li>
|
168
177
|
<li>
|
169
|
-
<a href={"#/" + title + '/history'}>
|
178
|
+
<a href={"#/" + encodeURIComponent(title) + '/history'}>
|
170
179
|
{
|
171
180
|
if @props.cards.collectionName == 'CardHistories'
|
172
181
|
<strong>History</strong>
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# @cjsx React.DOM
|
2
|
+
$ = require('jquery')
|
3
|
+
Backbone = require('backbone')
|
4
|
+
React = require('react')
|
5
|
+
EditTag = require('./edit_tag')
|
6
|
+
ModalTrigger = require('react-bootstrap/lib/ModalTrigger')
|
7
|
+
|
8
|
+
module.exports = React.createClass
|
9
|
+
displayName: 'Tags'
|
10
|
+
|
11
|
+
componentDidMount: ->
|
12
|
+
console.log '[views/tags] component did mount'
|
13
|
+
@props.tags.on 'sync', @forceUpdate.bind(@, null)
|
14
|
+
|
15
|
+
componentWillReceiveProps: (nextProps)->
|
16
|
+
console.log '[views/tags] component will receive props'
|
17
|
+
nextProps.tags.on 'sync', @forceUpdate.bind(@, null)
|
18
|
+
|
19
|
+
render: ->
|
20
|
+
<div className="container carte-list">
|
21
|
+
<div className="row">
|
22
|
+
<div className="col-sm-12">
|
23
|
+
<ul className="nav nav-pills">
|
24
|
+
<li>
|
25
|
+
<a href="#/">
|
26
|
+
<i className="glyphicon glyphicon-arrow-left" />
|
27
|
+
</a>
|
28
|
+
</li>
|
29
|
+
</ul>
|
30
|
+
</div>
|
31
|
+
</div>
|
32
|
+
|
33
|
+
<div className="row">
|
34
|
+
{
|
35
|
+
if @props.tags.fetching
|
36
|
+
<div className="list-group col-sm-4">
|
37
|
+
<div className="list-group-item">
|
38
|
+
<i className="glyphicon glyphicon-refresh glyphicon-refresh-animate" />
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
else
|
42
|
+
@props.tags.map (tag)->
|
43
|
+
<div className="list-group col-sm-4">
|
44
|
+
<div className="list-group-item">
|
45
|
+
<i className="glyphicon glyphicon-tag" />
|
46
|
+
|
47
|
+
{tag.get('name')}
|
48
|
+
|
49
|
+
(
|
50
|
+
<a href={'#/?tags=' + encodeURIComponent(tag.get('name'))}>
|
51
|
+
{tag.get('count')}
|
52
|
+
</a>
|
53
|
+
)
|
54
|
+
<span className="pull-right tools">
|
55
|
+
<ModalTrigger modal={<EditTag tag={tag} />}>
|
56
|
+
<a href="javascript:void(0)">
|
57
|
+
<i className="glyphicon glyphicon-edit" />
|
58
|
+
</a>
|
59
|
+
</ModalTrigger>
|
60
|
+
</span>
|
61
|
+
</div>
|
62
|
+
</div>
|
63
|
+
}
|
64
|
+
</div>
|
65
|
+
</div>
|
data/lib/carte/server.rb
CHANGED
@@ -135,6 +135,23 @@ module Carte
|
|
135
135
|
{tags: Card.all_tags}.to_json
|
136
136
|
end
|
137
137
|
|
138
|
+
put '/tags/:name.json' do
|
139
|
+
# TODO: existence and length validation
|
140
|
+
if json_data['new_name']
|
141
|
+
cards = Card.collection.where(tags: params[:name])
|
142
|
+
cards.update(
|
143
|
+
{'$push' => {tags: json_data['new_name']}},
|
144
|
+
{:multi => true}
|
145
|
+
)
|
146
|
+
cards.update(
|
147
|
+
{'$pull' => {tags: params[:name]}},
|
148
|
+
{:multi => true}
|
149
|
+
)
|
150
|
+
end
|
151
|
+
status 201
|
152
|
+
{}.to_json
|
153
|
+
end
|
154
|
+
|
138
155
|
error(404) do
|
139
156
|
{}.to_json
|
140
157
|
end
|
data/package.json
CHANGED
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: 1.0.
|
4
|
+
version: 1.0.9
|
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-
|
11
|
+
date: 2015-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -267,6 +267,8 @@ files:
|
|
267
267
|
- lib/carte/client/models/card_histories.coffee
|
268
268
|
- lib/carte/client/models/card_history.coffee
|
269
269
|
- lib/carte/client/models/cards.coffee
|
270
|
+
- lib/carte/client/models/tag.coffee
|
271
|
+
- lib/carte/client/models/tags.coffee
|
270
272
|
- lib/carte/client/router.coffee
|
271
273
|
- lib/carte/client/tasks.coffee
|
272
274
|
- lib/carte/client/views/app.cjsx
|
@@ -274,12 +276,14 @@ files:
|
|
274
276
|
- lib/carte/client/views/cards.cjsx
|
275
277
|
- lib/carte/client/views/content.cjsx
|
276
278
|
- lib/carte/client/views/edit.cjsx
|
279
|
+
- lib/carte/client/views/edit_tag.cjsx
|
277
280
|
- lib/carte/client/views/footer.cjsx
|
278
281
|
- lib/carte/client/views/header.cjsx
|
279
282
|
- lib/carte/client/views/list.cjsx
|
280
283
|
- lib/carte/client/views/message.cjsx
|
281
284
|
- lib/carte/client/views/pagination.cjsx
|
282
285
|
- lib/carte/client/views/slideshow.cjsx
|
286
|
+
- lib/carte/client/views/tags.cjsx
|
283
287
|
- lib/carte/server.rb
|
284
288
|
- lib/carte/server/models.rb
|
285
289
|
- lib/carte/server/models/card.rb
|