almost finished new design on product page / reproduced bug with amount not updating
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
<div><%= section.delivery_destination.address %> </div>
|
||||
<div><%= section.delivery_destination.place %> <%= Place.name_from_code(section.delivery_destination.place) %></div>
|
||||
<div><%= section.delivery_destination.email %></div>
|
||||
<div><strong><%= section.delivery_destination.phone %></strong></div>
|
||||
<div><strong><%= section.delivery_destinati on.phone %></strong></div>
|
||||
|
||||
<% end %>
|
||||
|
||||
|
||||
@@ -11,166 +11,9 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20150318174814) do
|
||||
ActiveRecord::Schema.define(version: 0) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
create_table "carts", force: :cascade do |t|
|
||||
t.integer "user_id"
|
||||
t.boolean "ordered", default: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "anonymous_id_string"
|
||||
t.integer "delivery_destination_id"
|
||||
t.boolean "confirmed", default: false
|
||||
t.boolean "packed", default: false
|
||||
t.boolean "canceled_on_check", default: false
|
||||
t.boolean "canceled_on_delivery", default: false
|
||||
t.boolean "delivered", default: false
|
||||
t.text "internal_note"
|
||||
end
|
||||
|
||||
create_table "categories", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.integer "section_id"
|
||||
t.string "image_url"
|
||||
t.integer "order"
|
||||
end
|
||||
|
||||
create_table "delivery_destinations", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.string "address"
|
||||
t.string "place"
|
||||
t.string "postal_code"
|
||||
t.string "phone"
|
||||
t.string "email"
|
||||
t.text "note"
|
||||
t.boolean "email_verified"
|
||||
t.boolean "phone_verified"
|
||||
t.string "phone_verification_code"
|
||||
t.string "email_verification_code"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "user_id"
|
||||
t.string "anonymous_id_string"
|
||||
end
|
||||
|
||||
create_table "filter_criteria", force: :cascade do |t|
|
||||
t.string "title"
|
||||
t.string "field_name"
|
||||
t.integer "type"
|
||||
t.string "owner_type"
|
||||
t.integer "owner_id"
|
||||
end
|
||||
|
||||
create_table "filter_criteria_values", force: :cascade do |t|
|
||||
t.string "filter_text"
|
||||
t.string "filter_value"
|
||||
t.integer "filter_criteria_id"
|
||||
end
|
||||
|
||||
create_table "item_in_carts", force: :cascade do |t|
|
||||
t.integer "cart_id"
|
||||
t.integer "item_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "count"
|
||||
t.decimal "price"
|
||||
end
|
||||
|
||||
create_table "items", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.string "code", limit: 10
|
||||
t.decimal "current_input_price", precision: 5, scale: 2
|
||||
t.decimal "list_price", precision: 5, scale: 2
|
||||
t.integer "unit_id"
|
||||
t.decimal "units_in_pack", precision: 5, scale: 3
|
||||
t.text "description"
|
||||
t.integer "sub_category_id"
|
||||
t.integer "stock"
|
||||
t.boolean "on_display"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "tags"
|
||||
t.json "traits"
|
||||
t.decimal "weight", precision: 5, scale: 3
|
||||
t.integer "special_offer_id"
|
||||
t.integer "supplier_id"
|
||||
end
|
||||
|
||||
create_table "media_types", force: :cascade do |t|
|
||||
t.string "name"
|
||||
end
|
||||
|
||||
create_table "multi_media_descriptions", force: :cascade do |t|
|
||||
t.string "url"
|
||||
t.integer "item_id"
|
||||
t.integer "media_type_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "places", force: :cascade do |t|
|
||||
t.string "postal_code"
|
||||
t.decimal "delivery_price"
|
||||
t.string "name"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "sections", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.integer "order"
|
||||
end
|
||||
|
||||
create_table "special_offers", force: :cascade do |t|
|
||||
t.string "image_url"
|
||||
t.boolean "start_page"
|
||||
t.integer "section_id"
|
||||
t.integer "category_id"
|
||||
t.integer "sub_category_id"
|
||||
t.integer "item_id"
|
||||
t.boolean "thank_you_page"
|
||||
t.boolean "search_result_page"
|
||||
t.boolean "checkout_page"
|
||||
t.date "beginning"
|
||||
t.date "ending"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "sub_categories", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.integer "category_id"
|
||||
t.integer "order"
|
||||
end
|
||||
|
||||
create_table "suppliers", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.string "address"
|
||||
t.string "postal_code"
|
||||
t.string "town"
|
||||
t.string "phone"
|
||||
t.string "contact_person"
|
||||
t.string "email"
|
||||
t.text "note"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "units", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.string "short_name", limit: 4
|
||||
t.string "description_suffix"
|
||||
t.string "number_of_pieces_suffix"
|
||||
end
|
||||
|
||||
create_table "users", force: :cascade do |t|
|
||||
t.string "first_name"
|
||||
t.string "last_name"
|
||||
t.string "email"
|
||||
t.string "password_digest"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
4
back-office/import.log
Normal file
4
back-office/import.log
Normal file
@@ -0,0 +1,4 @@
|
||||
# Logfile created on 2015-05-13 07:02:12 +0200 by logger.rb/47272
|
||||
I, [2015-05-13T07:02:12.557157 #35872] INFO -- : Item import starting at 2015-05-13 07:02:12 +0200
|
||||
I, [2015-05-13T07:02:12.557196 #35872] INFO -- : Will be importing items from /Users/senaduka/Downloads/items_for_import.csv
|
||||
I, [2015-05-13T07:02:25.997791 #35872] INFO -- : Import done
|
||||
9
back-office/import_validate.log
Normal file
9
back-office/import_validate.log
Normal file
@@ -0,0 +1,9 @@
|
||||
# Logfile created on 2015-05-13 06:59:32 +0200 by logger.rb/47272
|
||||
I, [2015-05-13T06:59:32.650998 #35530] INFO -- : Item import starting at 2015-05-13 06:59:32 +0200
|
||||
I, [2015-05-13T06:59:32.651035 #35530] INFO -- : Will be importing items from /Users/senaduka/Downloads/items_for_import.csv
|
||||
E, [2015-05-13T06:59:40.201578 #35530] ERROR -- : Could not import item on row number 608 (Dunjica), reason: Subcategory is missing!
|
||||
I, [2015-05-13T06:59:45.758509 #35530] INFO -- : Rolling back because of errors
|
||||
I, [2015-05-13T06:59:46.065723 #35530] INFO -- : Import done
|
||||
I, [2015-05-13T07:00:24.402397 #35642] INFO -- : Item import starting at 2015-05-13 07:00:24 +0200
|
||||
I, [2015-05-13T07:00:24.402456 #35642] INFO -- : Will be importing items from /Users/senaduka/Downloads/items_for_import.csv
|
||||
I, [2015-05-13T07:00:37.829898 #35642] INFO -- : Import done
|
||||
@@ -200,11 +200,9 @@ ActiveRecord::Schema.define(version: 20150420044444) do
|
||||
end
|
||||
|
||||
create_table "sub_categories", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.integer "category_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "order"
|
||||
t.string "name"
|
||||
t.integer "category_id"
|
||||
t.integer "order"
|
||||
end
|
||||
|
||||
create_table "suppliers", force: :cascade do |t|
|
||||
|
||||
@@ -24,6 +24,14 @@ var CartActions = {
|
||||
});
|
||||
},
|
||||
|
||||
setItemCount: function(itemId, count) {
|
||||
AppDispatcher.handleAction({
|
||||
actionType: CartConstants.SET_ITEM_COUNT,
|
||||
itemId: itemId,
|
||||
count: count
|
||||
});
|
||||
},
|
||||
|
||||
dataLoaded: function() {
|
||||
AppDispatcher.handleAction({
|
||||
actionType: CartConstants.CART_DATA_LOADED
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
var React = require('react');
|
||||
var CartStore = require('../../stores/cartStore.js');
|
||||
var CartActions = require('../../actions/cartActions.js');
|
||||
var Globals = require('../../globals');
|
||||
|
||||
|
||||
|
||||
@@ -12,25 +13,23 @@ var AddToCart = React.createClass({
|
||||
|
||||
render: function() {
|
||||
|
||||
var itemCount = this.state.item.get('count');
|
||||
var itemCount = this.state.count;
|
||||
|
||||
var moreThanZeroItems = (
|
||||
var amountAndAddButton = (
|
||||
<div className="row-fluid add-to-cart">
|
||||
<div className="span12">
|
||||
<div style={buttonHolderStyle}><button className="btn btn-default" onClick={this._onDecreaseClick}>-</button></div>
|
||||
<div style={buttonHolderStyle}><button className="btn white_button" onClick={this._onDecreaseClick}>-</button></div>
|
||||
<div style={buttonHolderStyle}> <div className="add-to-cart-count">{ itemCount }</div> </div>
|
||||
<div style={buttonHolderStyle}><button className="btn btn-success" onClick={this._onIncreaseClick}>+ Dodaj</button></div>
|
||||
<div style={buttonHolderStyle}><button className="btn white_button" onClick={this._onIncreaseClick}>+</button></div>
|
||||
</div>
|
||||
<div>
|
||||
<div style={buttonHolderStyle}><button className="btn mybutton" onClick={this._addToCartClick}>Dodaj na popis za kupovinu</button></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
var zeroItems = (<div className="row-fluid add-to-cart">
|
||||
<div className="span12">
|
||||
<div style={buttonHolderStyle}><button className="btn btn-success" onClick={this._onIncreaseClick}>Kupi</button></div>
|
||||
</div>
|
||||
</div> );
|
||||
|
||||
return (itemCount <= 0) ? zeroItems : moreThanZeroItems;
|
||||
return amountAndAddButton;
|
||||
},
|
||||
|
||||
// Add change listeners to stores
|
||||
@@ -42,23 +41,38 @@ var AddToCart = React.createClass({
|
||||
|
||||
getInitialState: function() {
|
||||
var itemInCart = CartStore.getStateFor(this.props.itemId);
|
||||
return { item: itemInCart }
|
||||
return {
|
||||
item: itemInCart,
|
||||
count: 0
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
_onChange: function () {
|
||||
if (this.isMounted()) {
|
||||
var item = CartStore.getStateFor(this.props.itemId);
|
||||
this.setState({ item: item });
|
||||
this.setState({ item: item, count: 0 });
|
||||
}
|
||||
},
|
||||
|
||||
_onIncreaseClick: function () {
|
||||
CartActions.addItem(this.props.itemId);
|
||||
//CartActions.addItem(this.props.itemId);
|
||||
if (this.state.count < Globals.MaxNumberOfItemsToBeAdded ) {
|
||||
this.state.count = this.state.count + 1;
|
||||
this.setState(this.state);
|
||||
}
|
||||
},
|
||||
|
||||
_onDecreaseClick: function () {
|
||||
CartActions.takeItemOut(this.props.itemId);
|
||||
// CartActions.takeItemOut(this.props.itemId);
|
||||
if (this.state.count > 0) {
|
||||
this.state.count = this.state.count - 1;
|
||||
this.setState(this.state);
|
||||
}
|
||||
},
|
||||
|
||||
_addToCartClick: function () {
|
||||
CartActions.setItemCount(this.props.itemId, this.state.count);
|
||||
},
|
||||
|
||||
componentWillUnmount: function () {
|
||||
|
||||
@@ -16,22 +16,19 @@ var ItemWithDetailsPage = React.createClass({
|
||||
return (
|
||||
|
||||
<div className="item-with-details row-fluid center">
|
||||
<div className="col-md-5">
|
||||
<Carousel images={this.state.images}
|
||||
selected={this.state.currentImage}
|
||||
onClickLeft={this.onClickLeft}
|
||||
onClickRight={this.onClickRight}
|
||||
onSelectImage={this.onSelectImage} />
|
||||
<AddToCart itemId={this.state.item.get('id')} />
|
||||
|
||||
<div className="col-md-5 col-md-offset-2">
|
||||
<img src={this.state.firstImage} width="100%" />
|
||||
</div>
|
||||
|
||||
<div className="col-md-7">
|
||||
<h3> {this.state.item.get('name')}</h3>
|
||||
<div className="col-md-5">
|
||||
<div className='item_brand_name'> {this.state.item.get('brand').name}</div>
|
||||
<div className='item_name'> {this.state.item.get('name')}</div>
|
||||
<div>
|
||||
<div className='h4'> {this.state.item.get('brand').name}</div>
|
||||
<div className='h4'> {this.state.item.get('list_price')} KM</div>
|
||||
<div className='h5'>{this.state.item.get('pricePerUnit')}</div>
|
||||
<div className='item_price'> {this.state.item.get('list_price')} KM</div>
|
||||
|
||||
<div>Količina</div>
|
||||
|
||||
<div> <AddToCart itemId={this.state.item.get('id')} /></div>
|
||||
<div> {this.state.item.get('description')}</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ var keyMirror = require('react/lib/keyMirror');
|
||||
module.exports = keyMirror({
|
||||
LOAD_CART_CONTENTS: null,
|
||||
ADD_ITEM: null,
|
||||
// because REMOVE_ITEM could be used to completely remove item
|
||||
// and not just decrease count by 1
|
||||
TAKE_ITEM_OUT: null ,
|
||||
CART_DATA_LOADED: null,
|
||||
SAVE_CART_STATE_FOR_ITEM: null,
|
||||
CHANGE_DELIVERY_DESTINATION_PROPERTY: null,
|
||||
CONFIRM_DELIVERY: null
|
||||
CONFIRM_DELIVERY: null,
|
||||
SET_ITEM_COUNT: null,
|
||||
REMOVE_ITEM: null
|
||||
});
|
||||
|
||||
@@ -32,3 +32,22 @@
|
||||
text-align: center;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.item_name {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.item_brand_name {
|
||||
font-size: 24px;
|
||||
text-transform: uppercase;
|
||||
|
||||
}
|
||||
|
||||
.item_price {
|
||||
|
||||
font-size: 36px;
|
||||
padding-top: 36px;
|
||||
padding-bottom: 36px;
|
||||
|
||||
|
||||
}
|
||||
@@ -464,3 +464,16 @@ text-decoration: none;
|
||||
.error-message {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.white_button{
|
||||
background-color: #f9f9f9;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding-bottom: 7px;
|
||||
display: block;
|
||||
border-radius: 1px;
|
||||
margin-top: 8px;
|
||||
border: solid #cccccc 1px;
|
||||
color: #4d4d4d !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ module.exports = {
|
||||
FormatCurrency: function(amount_s) {
|
||||
var amount = parseFloat(amount_s);
|
||||
return ( amount.toFixed(2) + " KM" )
|
||||
}
|
||||
},
|
||||
MaxNumberOfItemsToBeAdded: 1000
|
||||
};
|
||||
|
||||
@@ -101,6 +101,19 @@ var takeItemOut = function(itemId) {
|
||||
saveCartStateForItem(itemId);
|
||||
};
|
||||
|
||||
var setItemCount = function(itemId, count) {
|
||||
var state = states[itemId] || new ItemInCart({
|
||||
item_id: itemId,
|
||||
count: 0
|
||||
})
|
||||
console.log("Old state", state.get('count'));
|
||||
|
||||
state.set('count', state.get('count') + count);
|
||||
console.log("New state", state.get('count'));
|
||||
states[itemId] = state;
|
||||
saveCartStateForItem(itemId);
|
||||
}
|
||||
|
||||
var changeDeliveryDestinationProperty = function(property, value) {
|
||||
_deliveryDestination.set(property, value);
|
||||
|
||||
@@ -274,6 +287,9 @@ AppDispatcher.register(function(payload) {
|
||||
case CartConstants.CONFIRM_DELIVERY:
|
||||
saveDeliveryDestination();
|
||||
break;
|
||||
case CartConstants.SET_ITEM_COUNT:
|
||||
setItemCount(action.itemId, action.count);
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -76,12 +76,13 @@ var ItemWithDetailsStore = _.extend({}, EventEmitter.prototype, {
|
||||
getState: function() {
|
||||
|
||||
|
||||
|
||||
var firstImage = _images[0] || "https://res.cloudinary.com/lfvt7ps2n/image/upload/c_fit,h_172,w_226/v1421732950/http_www.asms.ru_bitrix_templates_main_images_nophoto_irnofq.png";
|
||||
return {
|
||||
item: _itemWithDetails,
|
||||
images: _images,
|
||||
currentImage: _currentImage,
|
||||
count: _count
|
||||
count: _count,
|
||||
firstImage: firstImage
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
@@ -53,33 +53,34 @@ var fetchItemWithDetails = function() {
|
||||
}
|
||||
|
||||
var fetchItemsByCategory = function(categoryId, offset, limit, query) {
|
||||
//var items = _itemsByCategory;
|
||||
var items = new ItemCollection();
|
||||
items.clearFilter();
|
||||
items.setClassificationType(2);
|
||||
items.setClassificationId(categoryId);
|
||||
items.setLimit(limit);
|
||||
items.setOffset(offset);
|
||||
//var items = _itemsByCategory;
|
||||
var items = new ItemCollection();
|
||||
items.clearFilter();
|
||||
items.setClassificationType(2);
|
||||
items.setClassificationId(categoryId);
|
||||
items.setLimit(limit);
|
||||
items.setOffset(offset);
|
||||
|
||||
for(var key in query) {
|
||||
if (query.hasOwnProperty(key) && key != 'limit' && key !='offset') {
|
||||
items.addFilter(key, query[key]);
|
||||
for (var key in query) {
|
||||
if (query.hasOwnProperty(key) && key != 'limit' && key != 'offset') {
|
||||
items.addFilter(key, query[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
items.fetch({
|
||||
success: function(collection, response, options) {
|
||||
var total = options.xhr.getResponseHeader('x-total-count');
|
||||
items.setTotalCount(total);
|
||||
items.fetch({
|
||||
success: function(collection, response, options) {
|
||||
var total = options.xhr.getResponseHeader('x-total-count');
|
||||
items.setTotalCount(total);
|
||||
|
||||
ItemStore.emitChange();
|
||||
}});
|
||||
ItemStore.emitChange();
|
||||
}
|
||||
});
|
||||
|
||||
_itemsByCategory = items;
|
||||
_itemsByCategory = items;
|
||||
};
|
||||
|
||||
var fetchBestSellingItemsForSection = function(sectionId) {
|
||||
console.log('getting section', sectionId);
|
||||
console.log('getting section', sectionId);
|
||||
var items = _bestSellingForSection;
|
||||
items.setClassificationType(1);
|
||||
items.setClassificationId(sectionId);
|
||||
@@ -87,15 +88,15 @@ var fetchBestSellingItemsForSection = function(sectionId) {
|
||||
items.setOffset(0);
|
||||
|
||||
items.fetch({
|
||||
success: function() {
|
||||
ItemStore.emitChange();
|
||||
}
|
||||
success: function() {
|
||||
ItemStore.emitChange();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var fetchBestSellingItemsForGroup = function(groupId) {
|
||||
console.log('getting group', groupId);
|
||||
console.log('getting group', groupId);
|
||||
var items = _bestSellingForGroup;
|
||||
items.setClassificationType(4);
|
||||
items.setClassificationId(groupId);
|
||||
@@ -103,9 +104,9 @@ var fetchBestSellingItemsForGroup = function(groupId) {
|
||||
items.setOffset(0);
|
||||
|
||||
items.fetch({
|
||||
success: function() {
|
||||
ItemStore.emitChange();
|
||||
}
|
||||
success: function() {
|
||||
ItemStore.emitChange();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -113,19 +114,19 @@ var fetchBestSellingItemsForGroup = function(groupId) {
|
||||
// Extend ItemStore with EventEmitter to add eventing capabilities
|
||||
var ItemStore = _.extend({}, EventEmitter.prototype, {
|
||||
|
||||
getItemsForCategory: function() {
|
||||
return _itemsByCategory;
|
||||
},
|
||||
getItemsForCategory: function() {
|
||||
return _itemsByCategory;
|
||||
},
|
||||
getBestSellingForSection: function() {
|
||||
|
||||
return _bestSellingForSection;
|
||||
return _bestSellingForSection;
|
||||
},
|
||||
// item with details
|
||||
getLoadedItemWithDetails: function() {
|
||||
return _itemWithDetails;
|
||||
},
|
||||
|
||||
getItemsForGroup: function () {
|
||||
getItemsForGroup: function() {
|
||||
return _bestSellingForGroup;
|
||||
},
|
||||
|
||||
@@ -190,4 +191,4 @@ AppDispatcher.register(function(payload) {
|
||||
|
||||
});
|
||||
|
||||
module.exports = ItemStore;
|
||||
module.exports = ItemStore;
|
||||
@@ -9,21 +9,21 @@
|
||||
"author": "",
|
||||
"license": "BSD-2-Clause",
|
||||
"devDependencies": {
|
||||
"Backbone.Mutators": "~0.4.4",
|
||||
"browserify": "~8.1.0",
|
||||
"events": "^1.0.2",
|
||||
"flux": "^2.0.1",
|
||||
"grunt": "~0.4.5",
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-browserify": "~3.2.1",
|
||||
"grunt-cli": "~0.1.13",
|
||||
"grunt-config": "~0.2.2",
|
||||
"grunt-contrib-concat": "~0.5.0",
|
||||
"grunt-contrib-connect": "~0.9.0",
|
||||
"grunt-contrib-uglify": "~0.7.0",
|
||||
"grunt-contrib-watch": "~0.6.1",
|
||||
"grunt-replace": "~0.8.0",
|
||||
"reactify": "~0.17.1",
|
||||
"underscore": "^1.7.0",
|
||||
"Backbone.Mutators": "~0.4.4",
|
||||
"grunt-config": "~0.2.2",
|
||||
"grunt-replace": "~0.8.0"
|
||||
"underscore": "^1.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "~0.12.2",
|
||||
|
||||
Reference in New Issue
Block a user